From b19dff31e17d40f0dfacf6228a9114ab93938d6f Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Fri, 20 Jun 2025 07:58:19 +0200 Subject: [PATCH 01/36] Print gNB MAC stats in phy-test mode as well There is no PRACH, so the condition to print stats would never be reached. Fixes: 0301b239a264 ("print stats only after scheduler started") --- openair2/LAYER2/NR_MAC_gNB/gNB_scheduler.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler.c index dfe4cfeea2..09734d8215 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler.c @@ -195,7 +195,7 @@ void gNB_dlsch_ulsch_scheduler(module_id_t module_idP, frame_t frame, slot_t slo } bool wait_prach_completed = gNB->num_scheduled_prach_rx >= NUM_PRACH_RX_FOR_NOISE_ESTIMATE; - if (wait_prach_completed && (slot == 0) && (frame & 127) == 0) { + if ((wait_prach_completed || get_softmodem_params()->phy_test) && (slot == 0) && (frame & 127) == 0) { char stats_output[32656] = {0}; dump_mac_stats(gNB, stats_output, sizeof(stats_output), true); LOG_I(NR_MAC, "Frame.Slot %d.%d\n%s\n", frame, slot, stats_output); From d1541a83296bad22ab657d77ee9aefb1aab68aef Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Tue, 27 May 2025 19:24:25 +0200 Subject: [PATCH 02/36] Remove useless parameter for UE context setup response callback --- openair2/LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.c | 2 +- openair2/LAYER2/NR_MAC_gNB/mac_rrc_ul.h | 2 +- openair2/LAYER2/NR_MAC_gNB/mac_rrc_ul_direct.c | 5 +---- openair2/LAYER2/NR_MAC_gNB/mac_rrc_ul_f1ap.c | 5 +---- 4 files changed, 4 insertions(+), 10 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 5d7642c815..691a161c0a 100644 --- a/openair2/LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.c +++ b/openair2/LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.c @@ -712,7 +712,7 @@ void ue_context_setup_request(const f1ap_ue_context_setup_t *req) DevAssert(resp.du_to_cu_rrc_information != NULL); DevAssert(resp.rrc_container == NULL && resp.rrc_container_length == 0); - mac->mac_rrc.ue_context_setup_response(req, &resp); + mac->mac_rrc.ue_context_setup_response(&resp); /* free the memory we allocated above */ free(resp.srbs_to_be_setup); diff --git a/openair2/LAYER2/NR_MAC_gNB/mac_rrc_ul.h b/openair2/LAYER2/NR_MAC_gNB/mac_rrc_ul.h index 1e416f01f9..afce935185 100644 --- a/openair2/LAYER2/NR_MAC_gNB/mac_rrc_ul.h +++ b/openair2/LAYER2/NR_MAC_gNB/mac_rrc_ul.h @@ -31,7 +31,7 @@ typedef void (*f1_reset_acknowledge_cu_initiated_func_t)(const f1ap_reset_ack_t 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); -typedef void (*ue_context_setup_response_func_t)(const f1ap_ue_context_setup_t* req, const f1ap_ue_context_setup_t *resp); +typedef void (*ue_context_setup_response_func_t)(const f1ap_ue_context_setup_t *resp); typedef void (*ue_context_modification_response_func_t)(const f1ap_ue_context_modif_req_t *req, const f1ap_ue_context_modif_resp_t *resp); typedef void (*ue_context_modification_required_func_t)(const f1ap_ue_context_modif_required_t *t); 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 e687991a5e..ae672b5bfd 100644 --- a/openair2/LAYER2/NR_MAC_gNB/mac_rrc_ul_direct.c +++ b/openair2/LAYER2/NR_MAC_gNB/mac_rrc_ul_direct.c @@ -58,11 +58,8 @@ static void gnb_du_configuration_update_direct(const f1ap_gnb_du_configuration_u itti_send_msg_to_task(TASK_RRC_GNB, 0, msg); } -static void ue_context_setup_response_direct(const f1ap_ue_context_setup_t *req, const f1ap_ue_context_setup_t *resp) +static void ue_context_setup_response_direct(const f1ap_ue_context_setup_t *resp) { - DevAssert(req->drbs_to_be_setup_length == resp->drbs_to_be_setup_length); - - (void) req; /* we don't need the request -- it is to set up GTP in F1 case */ MessageDef *msg = itti_alloc_new_message (TASK_MAC_GNB, 0, F1AP_UE_CONTEXT_SETUP_RESP); msg->ittiMsgHeader.originInstance = -1; // means monolithic f1ap_ue_context_setup_t *f1ap_msg = &F1AP_UE_CONTEXT_SETUP_RESP(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 81373e0bc9..85a790b852 100644 --- a/openair2/LAYER2/NR_MAC_gNB/mac_rrc_ul_f1ap.c +++ b/openair2/LAYER2/NR_MAC_gNB/mac_rrc_ul_f1ap.c @@ -85,11 +85,8 @@ static void gnb_du_configuration_update_f1ap(const f1ap_gnb_du_configuration_upd itti_send_msg_to_task(TASK_DU_F1, 0, msg); } -static void ue_context_setup_response_f1ap(const f1ap_ue_context_setup_t *req, const f1ap_ue_context_setup_t *resp) +static void ue_context_setup_response_f1ap(const f1ap_ue_context_setup_t *resp) { - DevAssert(req->drbs_to_be_setup_length == resp->drbs_to_be_setup_length); - - DevAssert(req->srbs_to_be_setup_length == resp->srbs_to_be_setup_length); MessageDef *msg = itti_alloc_new_message (TASK_MAC_GNB, 0, F1AP_UE_CONTEXT_SETUP_RESP); f1ap_ue_context_setup_t *f1ap_msg = &F1AP_UE_CONTEXT_SETUP_RESP(msg); /* copy all fields, but reallocate rrc_containers! */ From 8a772d362f791ab617a3e064d701b02f8158e506 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Tue, 17 Jun 2025 19:13:30 +0200 Subject: [PATCH 03/36] Remove useless parameter for UE context modification response callback --- openair2/LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.c | 2 +- openair2/LAYER2/NR_MAC_gNB/mac_rrc_ul.h | 3 +-- openair2/LAYER2/NR_MAC_gNB/mac_rrc_ul_direct.c | 4 +--- openair2/LAYER2/NR_MAC_gNB/mac_rrc_ul_f1ap.c | 2 +- 4 files changed, 4 insertions(+), 7 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 691a161c0a..ed706d51f8 100644 --- a/openair2/LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.c +++ b/openair2/LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.c @@ -838,7 +838,7 @@ void ue_context_modification_request(const f1ap_ue_context_modif_req_t *req) // resp.du_to_cu_rrc_information can be either NULL or not DevAssert(resp.rrc_container == NULL && resp.rrc_container_length == 0); - mac->mac_rrc.ue_context_modification_response(req, &resp); + mac->mac_rrc.ue_context_modification_response(&resp); /* free the memory we allocated above */ free(resp.srbs_to_be_setup); diff --git a/openair2/LAYER2/NR_MAC_gNB/mac_rrc_ul.h b/openair2/LAYER2/NR_MAC_gNB/mac_rrc_ul.h index afce935185..6681b96032 100644 --- a/openair2/LAYER2/NR_MAC_gNB/mac_rrc_ul.h +++ b/openair2/LAYER2/NR_MAC_gNB/mac_rrc_ul.h @@ -32,8 +32,7 @@ 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); typedef void (*ue_context_setup_response_func_t)(const f1ap_ue_context_setup_t *resp); -typedef void (*ue_context_modification_response_func_t)(const f1ap_ue_context_modif_req_t *req, - const f1ap_ue_context_modif_resp_t *resp); +typedef void (*ue_context_modification_response_func_t)(const f1ap_ue_context_modif_resp_t *resp); typedef void (*ue_context_modification_required_func_t)(const f1ap_ue_context_modif_required_t *t); typedef void (*ue_context_release_request_func_t)(const f1ap_ue_context_release_req_t* req); typedef void (*ue_context_release_complete_func_t)(const f1ap_ue_context_release_complete_t *complete); 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 ae672b5bfd..65e56aee10 100644 --- a/openair2/LAYER2/NR_MAC_gNB/mac_rrc_ul_direct.c +++ b/openair2/LAYER2/NR_MAC_gNB/mac_rrc_ul_direct.c @@ -93,10 +93,8 @@ static void ue_context_setup_response_direct(const f1ap_ue_context_setup_t *resp itti_send_msg_to_task(TASK_RRC_GNB, 0, msg); } -static void ue_context_modification_response_direct(const f1ap_ue_context_modif_req_t *req, - const f1ap_ue_context_modif_resp_t *resp) +static void ue_context_modification_response_direct(const f1ap_ue_context_modif_resp_t *resp) { - (void)req; /* we don't need the request -- it is to set up GTP in F1 case */ MessageDef *msg = itti_alloc_new_message(TASK_MAC_GNB, 0, F1AP_UE_CONTEXT_MODIFICATION_RESP); msg->ittiMsgHeader.originInstance = -1; // means monolithic f1ap_ue_context_modif_resp_t *f1ap_msg = &F1AP_UE_CONTEXT_MODIFICATION_RESP(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 85a790b852..deb160a1a6 100644 --- a/openair2/LAYER2/NR_MAC_gNB/mac_rrc_ul_f1ap.c +++ b/openair2/LAYER2/NR_MAC_gNB/mac_rrc_ul_f1ap.c @@ -123,7 +123,7 @@ static void ue_context_setup_response_f1ap(const f1ap_ue_context_setup_t *resp) itti_send_msg_to_task(TASK_DU_F1, 0, msg); } -static void ue_context_modification_response_f1ap(const f1ap_ue_context_modif_req_t *req, const f1ap_ue_context_modif_resp_t *resp) +static void ue_context_modification_response_f1ap(const f1ap_ue_context_modif_resp_t *resp) { MessageDef *msg = itti_alloc_new_message(TASK_MAC_GNB, 0, F1AP_UE_CONTEXT_MODIFICATION_RESP); f1ap_ue_context_modif_resp_t *f1ap_msg = &F1AP_UE_CONTEXT_MODIFICATION_RESP(msg); From e4857991fc7f62097191bd3bfe8bf673825595fc Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Fri, 30 May 2025 18:14:52 +0200 Subject: [PATCH 04/36] F1 PRINT_ERROR(): show file/line no for debuggability Somewhat align with the E1 PRINT_ERROR(), but extend with information. --- openair2/F1AP/lib/f1ap_lib_common.h | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) diff --git a/openair2/F1AP/lib/f1ap_lib_common.h b/openair2/F1AP/lib/f1ap_lib_common.h index 8a3ddfba4a..162476a182 100644 --- a/openair2/F1AP/lib/f1ap_lib_common.h +++ b/openair2/F1AP/lib/f1ap_lib_common.h @@ -32,21 +32,17 @@ #include "f1ap_messages_types.h" #ifdef ENABLE_TESTS - #define PRINT_ERROR(...) fprintf(stderr, ##__VA_ARGS__) + #define PRINT_ERROR(fmt, ...) fprintf(stderr, "%s:%d: " fmt, __FILE__, __LINE__, ##__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; \ - } \ +#define _F1_EQ_CHECK_GENERIC(condition, fmt, ...) \ + do { \ + if (!(condition)) { \ + PRINT_ERROR("Equality condition '%s' failed: " fmt " != " fmt "\n", #condition, ##__VA_ARGS__); \ + return false; \ + } \ } while (0) #define _F1_EQ_CHECK_LONG(A, B) _F1_EQ_CHECK_GENERIC(A == B, "%ld", A, B); From 9f0373e051c3283f6aa85dbdd5b4830019a6dc64 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Tue, 6 May 2025 11:00:05 +0200 Subject: [PATCH 05/36] F1AP lib: introduce macros to simplify implementation Introduce generic _F1_CHECK_EXP(), which is like the macros for checking values (_F1_EQ_CHECK_INT() etc). Reuse the same for introducing _F1_EQ_CHECK_OPTIONAL_IE that will be used to write the check for optional fields more concisely. CP_OPT_BYTE_ARRAY() FREE_OPT_BYTE_ARRAY() are macros to wrap handling of optional byte arrays. _F1_MALLOC() simplifies allocations and is similar to asn1cCallocOne(), but provided to avoid confusion (since more than ASN.1 structures will use it). All will be used in the following commits. --- openair2/F1AP/lib/f1ap_lib_common.h | 39 +++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/openair2/F1AP/lib/f1ap_lib_common.h b/openair2/F1AP/lib/f1ap_lib_common.h index 162476a182..358a2d5eaf 100644 --- a/openair2/F1AP/lib/f1ap_lib_common.h +++ b/openair2/F1AP/lib/f1ap_lib_common.h @@ -27,6 +27,7 @@ #include #include "openair3/UTILS/conversions.h" #include "common/5g_platform_types.h" +#include "common/utils/ds/byte_array.h" #include "F1AP_Cause.h" #include "f1ap_messages_types.h" @@ -49,6 +50,21 @@ #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); +#define _F1_CHECK_EXP(EXP) \ + do { \ + if (!(EXP)) { \ + PRINT_ERROR("Failed at " #EXP "\n"); \ + return false; \ + } \ + } while (0) + +#define _F1_EQ_CHECK_OPTIONAL_IE(A, B, FIELD, EQ_MACRO) \ + do { \ + _F1_CHECK_EXP(((A)->FIELD && (B)->FIELD) || (!(A)->FIELD && !(B)->FIELD)); \ + if ((A)->FIELD && (B)->FIELD) \ + EQ_MACRO(*(A)->FIELD, *(B)->FIELD); \ + } while (0) + /* 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) \ @@ -68,6 +84,29 @@ } \ } while (0) +#define CP_OPT_BYTE_ARRAY(dst, src) \ + do { \ + if (src) { \ + dst = calloc_or_fail(1, sizeof(*dst)); \ + *(dst) = copy_byte_array(*(src)); \ + } \ + } while (0) + +#define FREE_OPT_BYTE_ARRAY(a) \ + do { \ + if (a) { \ + free_byte_array(*(a)); \ + } \ + free(a); \ + } while (0) + +/* similar to asn1cCallocOne(), duplicated to not confuse with asn.1 types */ +#define _F1_MALLOC(VaR, VaLue) \ + do { \ + VaR = malloc_or_fail(sizeof(*VaR)); \ + *VaR = VaLue; \ + } while (0) + bool eq_f1ap_plmn(const plmn_id_t *a, const plmn_id_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); From e991f26ff1575427b45edfb5487926efb492ea68 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Sat, 24 May 2025 12:43:42 +0200 Subject: [PATCH 06/36] Factor out NSSAI, to be used in other messages lates --- openair2/F1AP/lib/f1ap_interface_management.c | 13 ++-------- openair2/F1AP/lib/f1ap_lib_common.c | 24 ++++++++++++++++++- openair2/F1AP/lib/f1ap_lib_common.h | 4 ++++ 3 files changed, 29 insertions(+), 12 deletions(-) diff --git a/openair2/F1AP/lib/f1ap_interface_management.c b/openair2/F1AP/lib/f1ap_interface_management.c index 0ac1f8d63a..e6d863f7a3 100644 --- a/openair2/F1AP/lib/f1ap_interface_management.c +++ b/openair2/F1AP/lib/f1ap_interface_management.c @@ -394,11 +394,7 @@ static int read_slice_info(const F1AP_ServedPLMNs_Item_t *plmn, nssai_t *nssai, 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); + nssai[s] = decode_nssai(&sl->sNSSAI); } return ssl->list.count; @@ -418,12 +414,7 @@ static F1AP_ProtocolExtensionContainer_10696P34_t *write_slice_info(int num_ssi, for (int s = 0; s < num_ssi; s++) { asn1cSequenceAdd(slice_support_list->list, F1AP_SliceSupportItem_t, slice); - const nssai_t *n = &nssai[s]; - INT8_TO_OCTET_STRING(n->sst, &slice->sNSSAI.sST); - if (n->sd != 0xffffff) { - asn1cCalloc(slice->sNSSAI.sD, tmp); - INT24_TO_OCTET_STRING(n->sd, tmp); - } + slice->sNSSAI = encode_nssai(&nssai[s]); } return p; diff --git a/openair2/F1AP/lib/f1ap_lib_common.c b/openair2/F1AP/lib/f1ap_lib_common.c index e32f7e6779..0e1d07a71d 100644 --- a/openair2/F1AP/lib/f1ap_lib_common.c +++ b/openair2/F1AP/lib/f1ap_lib_common.c @@ -25,7 +25,7 @@ #include "OCTET_STRING.h" #include "common/utils/utils.h" #include "common/utils/assertions.h" -#include "common/utils/utils.h" +#include "common/utils/oai_asn1.h" bool eq_f1ap_plmn(const plmn_id_t *a, const plmn_id_t *b) { @@ -115,6 +115,28 @@ uint8_t *cp_octet_string(const OCTET_STRING_t *os, int *len) return buf; } +F1AP_SNSSAI_t encode_nssai(const nssai_t *nssai) +{ + F1AP_SNSSAI_t enc = {0}; + INT8_TO_OCTET_STRING(nssai->sst, &enc.sST); + // see 23.003 sec. 28.4.2: 0xffffff means "no SD" + if (nssai->sd != 0xffffff) { + asn1cCalloc(enc.sD, tmp); + INT24_TO_OCTET_STRING(nssai->sd, tmp); + } + return enc; +} + +nssai_t decode_nssai(const F1AP_SNSSAI_t *nssai) +{ + // see 23.003 sec. 28.4.2: 0xffffff means "no SD" + nssai_t dec = { .sd = 0xffffff, }; + OCTET_STRING_TO_INT8(&nssai->sST, dec.sst); + if (nssai->sD != NULL) + OCTET_STRING_TO_INT24(nssai->sD, dec.sd); + return dec; +} + F1AP_Cause_t encode_f1ap_cause(f1ap_Cause_t cause, long cause_value) { F1AP_Cause_t f1_cause = {0}; diff --git a/openair2/F1AP/lib/f1ap_lib_common.h b/openair2/F1AP/lib/f1ap_lib_common.h index 358a2d5eaf..6a50ba45b2 100644 --- a/openair2/F1AP/lib/f1ap_lib_common.h +++ b/openair2/F1AP/lib/f1ap_lib_common.h @@ -30,6 +30,7 @@ #include "common/utils/ds/byte_array.h" #include "F1AP_Cause.h" +#include "F1AP_SNSSAI.h" #include "f1ap_messages_types.h" #ifdef ENABLE_TESTS @@ -120,6 +121,9 @@ bool eq_f1ap_tx_bandwidth(const struct f1ap_transmission_bandwidth_t *a, const s struct OCTET_STRING; uint8_t *cp_octet_string(const struct OCTET_STRING *os, int *len); +F1AP_SNSSAI_t encode_nssai(const nssai_t *nssai); +nssai_t decode_nssai(const F1AP_SNSSAI_t *nssai); + F1AP_Cause_t encode_f1ap_cause(f1ap_Cause_t cause, long cause_value); bool decode_f1ap_cause(F1AP_Cause_t f1_cause, f1ap_Cause_t *cause, long *cause_value); From 3a4440a99cc3b79d2a505cd1c64e5148fb8f71b4 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Mon, 26 May 2025 11:10:52 +0200 Subject: [PATCH 07/36] Generalize F1AP_LIB_FIND_IE() to work with list container F1AP_LIB_FIND_IE() is used to look up elements in a list, but was hitherto hardcoded to use "protocolIEs" as an intermediate struct. A follow-up commit will use this macro where we don't have protocolIEs, but "iE_Extensions". Hence, modify to make it work for that case (and others) as well. --- openair2/F1AP/lib/f1ap_interface_management.c | 30 ++++++++-------- openair2/F1AP/lib/f1ap_lib_common.h | 6 ++-- openair2/F1AP/lib/f1ap_rrc_message_transfer.c | 35 ++++++++++--------- 3 files changed, 36 insertions(+), 35 deletions(-) diff --git a/openair2/F1AP/lib/f1ap_interface_management.c b/openair2/F1AP/lib/f1ap_interface_management.c index e6d863f7a3..cc2b5b3160 100644 --- a/openair2/F1AP/lib/f1ap_interface_management.c +++ b/openair2/F1AP/lib/f1ap_interface_management.c @@ -156,9 +156,9 @@ bool decode_f1ap_reset(const F1AP_F1AP_PDU_t *pdu, f1ap_reset_t *out) /* Check presence of mandatory IEs */ F1AP_Reset_t *in = &pdu->choice.initiatingMessage->value.choice.Reset; F1AP_ResetIEs_t *ie; - F1AP_LIB_FIND_IE(F1AP_ResetIEs_t, ie, in, F1AP_ProtocolIE_ID_id_TransactionID, true); - F1AP_LIB_FIND_IE(F1AP_ResetIEs_t, ie, in, F1AP_ProtocolIE_ID_id_Cause, true); - F1AP_LIB_FIND_IE(F1AP_ResetIEs_t, ie, in, F1AP_ProtocolIE_ID_id_ResetType, true); + F1AP_LIB_FIND_IE(F1AP_ResetIEs_t, ie, &in->protocolIEs.list, F1AP_ProtocolIE_ID_id_TransactionID, true); + F1AP_LIB_FIND_IE(F1AP_ResetIEs_t, ie, &in->protocolIEs.list, F1AP_ProtocolIE_ID_id_Cause, true); + F1AP_LIB_FIND_IE(F1AP_ResetIEs_t, ie, &in->protocolIEs.list, F1AP_ProtocolIE_ID_id_ResetType, true); /* Loop over all IEs */ for (int i = 0; i < in->protocolIEs.list.count; i++) { @@ -303,7 +303,7 @@ bool decode_f1ap_reset_ack(const struct F1AP_F1AP_PDU *pdu, f1ap_reset_ack_t *ou /* Check presence of mandatory IEs */ F1AP_ResetAcknowledge_t *in = &pdu->choice.successfulOutcome->value.choice.ResetAcknowledge; F1AP_ResetAcknowledgeIEs_t *ie; - F1AP_LIB_FIND_IE(F1AP_ResetAcknowledgeIEs_t, ie, in, F1AP_ProtocolIE_ID_id_TransactionID, true); + F1AP_LIB_FIND_IE(F1AP_ResetAcknowledgeIEs_t, ie, &in->protocolIEs.list, F1AP_ProtocolIE_ID_id_TransactionID, true); /* Loop over all IEs */ for (int i = 0; i < in->protocolIEs.list.count; i++) { @@ -813,9 +813,9 @@ bool decode_f1ap_setup_request(const F1AP_F1AP_PDU_t *pdu, f1ap_setup_req_t *out /* 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); + F1AP_LIB_FIND_IE(F1AP_F1SetupRequestIEs_t, ie, &in->protocolIEs.list, F1AP_ProtocolIE_ID_id_TransactionID, true); + F1AP_LIB_FIND_IE(F1AP_F1SetupRequestIEs_t, ie, &in->protocolIEs.list, F1AP_ProtocolIE_ID_id_gNB_DU_ID, true); + F1AP_LIB_FIND_IE(F1AP_F1SetupRequestIEs_t, ie, &in->protocolIEs.list, 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"); @@ -1086,8 +1086,8 @@ bool decode_f1ap_setup_response(const F1AP_F1AP_PDU_t *pdu, f1ap_setup_resp_t *o /* 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); + F1AP_LIB_FIND_IE(F1AP_F1SetupResponseIEs_t, ie, &in->protocolIEs.list, F1AP_ProtocolIE_ID_id_TransactionID, true); + F1AP_LIB_FIND_IE(F1AP_F1SetupResponseIEs_t, ie, &in->protocolIEs.list, 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]; @@ -1297,8 +1297,8 @@ bool decode_f1ap_setup_failure(const F1AP_F1AP_PDU_t *pdu, f1ap_setup_failure_t 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); + F1AP_LIB_FIND_IE(F1AP_F1SetupFailureIEs_t, ie, &in->protocolIEs.list, F1AP_ProtocolIE_ID_id_TransactionID, true); + F1AP_LIB_FIND_IE(F1AP_F1SetupFailureIEs_t, ie, &in->protocolIEs.list, 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]; @@ -1494,7 +1494,7 @@ bool decode_f1ap_du_configuration_update(const F1AP_F1AP_PDU_t *pdu, f1ap_gnb_du 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); + F1AP_LIB_FIND_IE(F1AP_GNBDUConfigurationUpdateIEs_t, ie, &in->protocolIEs.list, 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"); @@ -1751,7 +1751,7 @@ bool decode_f1ap_cu_configuration_update(const F1AP_F1AP_PDU_t *pdu, f1ap_gnb_cu /* 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); + F1AP_LIB_FIND_IE(F1AP_GNBCUConfigurationUpdateIEs_t, ie, &in->protocolIEs.list, 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]; @@ -1903,7 +1903,7 @@ bool decode_f1ap_cu_configuration_update_acknowledge(const F1AP_F1AP_PDU_t *pdu, 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); + F1AP_LIB_FIND_IE(F1AP_GNBCUConfigurationUpdateAcknowledgeIEs_t, ie, &in->protocolIEs.list, 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]; @@ -2079,7 +2079,7 @@ bool decode_f1ap_du_configuration_update_acknowledge(const F1AP_F1AP_PDU_t *pdu, 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); + F1AP_LIB_FIND_IE(F1AP_GNBDUConfigurationUpdateAcknowledgeIEs_t, ie, &in->protocolIEs.list, 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]; diff --git a/openair2/F1AP/lib/f1ap_lib_common.h b/openair2/F1AP/lib/f1ap_lib_common.h index 6a50ba45b2..b49fad88c1 100644 --- a/openair2/F1AP/lib/f1ap_lib_common.h +++ b/openair2/F1AP/lib/f1ap_lib_common.h @@ -68,12 +68,10 @@ /* 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) \ +#define F1AP_LIB_FIND_IE(IE_TYPE, ie, IE_LIST, IE_ID, mandatory) \ do { \ ie = NULL; \ - for (IE_TYPE **ptr = container->protocolIEs.list.array; \ - ptr < &container->protocolIEs.list.array[container->protocolIEs.list.count]; \ - ptr++) { \ + for (IE_TYPE **ptr = (IE_LIST)->array; ptr < &(IE_LIST)->array[(IE_LIST)->count]; ptr++) { \ if ((*ptr)->id == IE_ID) { \ ie = *ptr; \ break; \ diff --git a/openair2/F1AP/lib/f1ap_rrc_message_transfer.c b/openair2/F1AP/lib/f1ap_rrc_message_transfer.c index 5fc9e2d622..c2f6e780aa 100644 --- a/openair2/F1AP/lib/f1ap_rrc_message_transfer.c +++ b/openair2/F1AP/lib/f1ap_rrc_message_transfer.c @@ -114,26 +114,27 @@ bool decode_initial_ul_rrc_message_transfer(const F1AP_F1AP_PDU_t *pdu, f1ap_ini memset(out, 0, sizeof(*out)); F1AP_InitialULRRCMessageTransfer_t *container = &pdu->choice.initiatingMessage->value.choice.InitialULRRCMessageTransfer; + F1AP_ProtocolIE_Container_10659P31_t *pIEs = &container->protocolIEs; F1AP_InitialULRRCMessageTransferIEs_t *ie; - F1AP_LIB_FIND_IE(F1AP_InitialULRRCMessageTransferIEs_t, ie, container, F1AP_ProtocolIE_ID_id_gNB_DU_UE_F1AP_ID, true); + F1AP_LIB_FIND_IE(F1AP_InitialULRRCMessageTransferIEs_t, ie, &pIEs->list, 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); + F1AP_LIB_FIND_IE(F1AP_InitialULRRCMessageTransferIEs_t, ie, &pIEs->list, 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); + F1AP_LIB_FIND_IE(F1AP_InitialULRRCMessageTransferIEs_t, ie, &pIEs->list, 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); + F1AP_LIB_FIND_IE(F1AP_InitialULRRCMessageTransferIEs_t, ie, &pIEs->list, 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); + F1AP_LIB_FIND_IE(F1AP_InitialULRRCMessageTransferIEs_t, ie, &pIEs->list, 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); + F1AP_LIB_FIND_IE(F1AP_InitialULRRCMessageTransferIEs_t, ie, &pIEs->list, F1AP_ProtocolIE_ID_id_TransactionID, true); out->transaction_id = ie->value.choice.TransactionID; return true; @@ -258,19 +259,20 @@ bool decode_ul_rrc_message_transfer(const F1AP_F1AP_PDU_t *pdu, f1ap_ul_rrc_mess DevAssert(pdu != NULL); F1AP_ULRRCMessageTransfer_t *container = &pdu->choice.initiatingMessage->value.choice.ULRRCMessageTransfer; + F1AP_ProtocolIE_Container_10659P33_t *pIEs = &container->protocolIEs; 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); + F1AP_LIB_FIND_IE(F1AP_ULRRCMessageTransferIEs_t, ie, &pIEs->list, 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); + F1AP_LIB_FIND_IE(F1AP_ULRRCMessageTransferIEs_t, ie, &pIEs->list, 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); + F1AP_LIB_FIND_IE(F1AP_ULRRCMessageTransferIEs_t, ie, &pIEs->list, 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); + F1AP_LIB_FIND_IE(F1AP_ULRRCMessageTransferIEs_t, ie, &pIEs->list, F1AP_ProtocolIE_ID_id_RRCContainer, true); out->rrc_container = cp_octet_string(&ie->value.choice.RRCContainer, &out->rrc_container_length); return true; @@ -392,30 +394,31 @@ bool decode_dl_rrc_message_transfer(const F1AP_F1AP_PDU_t *pdu, f1ap_dl_rrc_mess DevAssert(pdu != NULL); F1AP_DLRRCMessageTransfer_t *container = &pdu->choice.initiatingMessage->value.choice.DLRRCMessageTransfer; + F1AP_ProtocolIE_Container_10659P32_t *pIEs = &container->protocolIEs; 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); + F1AP_LIB_FIND_IE(F1AP_DLRRCMessageTransferIEs_t, ie, &pIEs->list, 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); + F1AP_LIB_FIND_IE(F1AP_DLRRCMessageTransferIEs_t, ie, &pIEs->list, 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); + F1AP_LIB_FIND_IE(F1AP_DLRRCMessageTransferIEs_t, ie, &pIEs->list, 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); + F1AP_LIB_FIND_IE(F1AP_DLRRCMessageTransferIEs_t, ie, &pIEs->list, 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); + F1AP_LIB_FIND_IE(F1AP_DLRRCMessageTransferIEs_t, ie, &pIEs->list, 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); + F1AP_LIB_FIND_IE(F1AP_DLRRCMessageTransferIEs_t, ie, &pIEs->list, F1AP_ProtocolIE_ID_id_RRCContainer, true); out->rrc_container = cp_octet_string(&ie->value.choice.RRCContainer, &out->rrc_container_length); return true; From 8cee8ad6617776f600ae940a7b3956afd2828260 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Thu, 19 Jun 2025 19:18:13 +0200 Subject: [PATCH 08/36] Remove f1ap_lib_extern.h: use headers directly --- openair2/F1AP/lib/f1ap_interface_management.c | 2 +- openair2/F1AP/lib/f1ap_lib_extern.h | 27 ------------------- openair2/F1AP/tests/f1ap_lib_test.c | 2 +- .../LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.c | 1 + .../LAYER2/NR_MAC_gNB/mac_rrc_ul_direct.c | 2 +- openair2/LAYER2/NR_MAC_gNB/mac_rrc_ul_f1ap.c | 2 +- openair2/RRC/NR/mac_rrc_dl_f1ap.c | 4 +-- openair2/RRC/NR/rrc_gNB.c | 4 +-- 8 files changed, 9 insertions(+), 35 deletions(-) delete mode 100644 openair2/F1AP/lib/f1ap_lib_extern.h diff --git a/openair2/F1AP/lib/f1ap_interface_management.c b/openair2/F1AP/lib/f1ap_interface_management.c index cc2b5b3160..acd6859ad7 100644 --- a/openair2/F1AP/lib/f1ap_interface_management.c +++ b/openair2/F1AP/lib/f1ap_interface_management.c @@ -30,7 +30,7 @@ #include "f1ap_lib_common.h" #include "f1ap_lib_includes.h" #include "f1ap_messages_types.h" -#include "f1ap_lib_extern.h" +#include "lib/f1ap_interface_management.h" F1AP_UE_associatedLogicalF1_ConnectionItem_t encode_f1ap_ue_to_reset(const f1ap_ue_to_reset_t *to_reset) { diff --git a/openair2/F1AP/lib/f1ap_lib_extern.h b/openair2/F1AP/lib/f1ap_lib_extern.h deleted file mode 100644 index f95b685540..0000000000 --- a/openair2/F1AP/lib/f1ap_lib_extern.h +++ /dev/null @@ -1,27 +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 - */ - -#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/tests/f1ap_lib_test.c b/openair2/F1AP/tests/f1ap_lib_test.c index cbb5955fe9..57a503d8ab 100644 --- a/openair2/F1AP/tests/f1ap_lib_test.c +++ b/openair2/F1AP/tests/f1ap_lib_test.c @@ -38,7 +38,7 @@ #include "f1ap_messages_types.h" #include "F1AP_F1AP-PDU.h" -#include "f1ap_lib_extern.h" +#include "lib/f1ap_rrc_message_transfer.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) 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 ed706d51f8..ed03ba76a5 100644 --- a/openair2/LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.c +++ b/openair2/LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.c @@ -31,6 +31,7 @@ #include "NR_CG-ConfigInfo.h" #include "openair3/ocp-gtpu/gtp_itf.h" #include "openair2/LAYER2/nr_pdcp/nr_pdcp_oai_api.h" +#include "lib/f1ap_rrc_message_transfer.h" #include "lib/f1ap_interface_management.h" #include "executables/softmodem-common.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 65e56aee10..d1c9efbdfb 100644 --- a/openair2/LAYER2/NR_MAC_gNB/mac_rrc_ul_direct.c +++ b/openair2/LAYER2/NR_MAC_gNB/mac_rrc_ul_direct.c @@ -23,7 +23,7 @@ #include "intertask_interface.h" #include "mac_rrc_ul.h" -#include "f1ap_lib_extern.h" +#include "lib/f1ap_rrc_message_transfer.h" #include "lib/f1ap_interface_management.h" static void f1_reset_du_initiated_direct(const f1ap_reset_t *reset) 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 deb160a1a6..10b6206204 100644 --- a/openair2/LAYER2/NR_MAC_gNB/mac_rrc_ul_f1ap.c +++ b/openair2/LAYER2/NR_MAC_gNB/mac_rrc_ul_f1ap.c @@ -29,7 +29,7 @@ #include "mac_rrc_ul.h" -#include "f1ap_lib_extern.h" +#include "lib/f1ap_rrc_message_transfer.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) diff --git a/openair2/RRC/NR/mac_rrc_dl_f1ap.c b/openair2/RRC/NR/mac_rrc_dl_f1ap.c index 9fef2dea58..30c4f910ee 100644 --- a/openair2/RRC/NR/mac_rrc_dl_f1ap.c +++ b/openair2/RRC/NR/mac_rrc_dl_f1ap.c @@ -30,8 +30,8 @@ #include "intertask_interface.h" #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" +#include "lib/f1ap_rrc_message_transfer.h" +#include "lib/f1ap_interface_management.h" static void f1_reset_cu_initiated_f1ap(sctp_assoc_t assoc_id, const f1ap_reset_t *reset) { diff --git a/openair2/RRC/NR/rrc_gNB.c b/openair2/RRC/NR/rrc_gNB.c index 520dc469d0..e08a0a4d9e 100644 --- a/openair2/RRC/NR/rrc_gNB.c +++ b/openair2/RRC/NR/rrc_gNB.c @@ -78,8 +78,8 @@ #include "oai_asn1.h" #include "openair2/F1AP/f1ap_common.h" #include "openair2/F1AP/f1ap_ids.h" -#include "openair2/F1AP/lib/f1ap_lib_extern.h" -#include "lib/f1ap_interface_management.h" +#include "openair2/F1AP/lib/f1ap_rrc_message_transfer.h" +#include "openair2/F1AP/lib/f1ap_interface_management.h" #include "rrc_gNB_NGAP.h" #include "rrc_gNB_du.h" #include "rrc_gNB_mobility.h" From da915d21e04f8bf95a0776020348f8914d825eb7 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Wed, 2 Apr 2025 07:19:43 +0200 Subject: [PATCH 09/36] Add F1AP UE context setup request message enc/dec + test Reintroduce separate message types to simplify the encoding/decoding, including shorter names. The old types will be removed once everything has been migrated to the new encoder/decoder, which should ensure that everything is properly migrated to the unit-tested encoder/decoders. Also, for each type of F1 message (F1 UE context setup request, response, modification request, ...) introduce a separate type to avoid to mistakenly use wrong fields, which can lead to bugs. In this regard, the DL PDCP SN bit size in the DRB-ToBeSetup list of the UE context setup request is optional, as it will also be used in the UE context modification request DRB SetupMod list (which avoids quite some code duplication). The encoder checks that this IE is present, though. --- openair2/COMMON/f1ap_messages_types.h | 99 +++ openair2/F1AP/lib/CMakeLists.txt | 3 +- openair2/F1AP/lib/f1ap_lib_includes.h | 5 + openair2/F1AP/lib/f1ap_ue_context.c | 876 ++++++++++++++++++++++++++ openair2/F1AP/lib/f1ap_ue_context.h | 36 ++ openair2/F1AP/tests/CMakeLists.txt | 2 +- openair2/F1AP/tests/f1ap_lib_test.c | 170 +++++ 7 files changed, 1189 insertions(+), 2 deletions(-) create mode 100644 openair2/F1AP/lib/f1ap_ue_context.c create mode 100644 openair2/F1AP/lib/f1ap_ue_context.h diff --git a/openair2/COMMON/f1ap_messages_types.h b/openair2/COMMON/f1ap_messages_types.h index 84d887f8f9..85f2def720 100644 --- a/openair2/COMMON/f1ap_messages_types.h +++ b/openair2/COMMON/f1ap_messages_types.h @@ -26,6 +26,7 @@ #include #include "common/5g_platform_types.h" #include "common/platform_constants.h" +#include "common/utils/ds/byte_array.h" //-------------------------------------------------------------------------------------------// // Defines to access message fields. @@ -452,6 +453,13 @@ typedef struct cu_to_du_rrc_information_s { uint32_t handoverPreparationInfo_length; }cu_to_du_rrc_information_t; +typedef struct f1ap_cu_to_du_rrc_info_s { + byte_array_t *cg_configinfo; + byte_array_t *ue_cap; + byte_array_t *meas_config; + byte_array_t *ho_prep_info; +} f1ap_cu_to_du_rrc_info_t; + typedef struct du_to_cu_rrc_information_s { uint8_t * cellGroupConfig; uint32_t cellGroupConfig_length; @@ -477,6 +485,97 @@ typedef enum TransmActionInd_e { TransmActionInd_RESTART, } TransmActionInd_t; +typedef struct f1ap_srb_to_setup_t { + int id; +} f1ap_srb_to_setup_t; + +/// 9.3.1.52 Packet Error Rate +typedef struct f1ap_per_t { + uint8_t scalar; + uint8_t exponent; +} f1ap_per_t; + +// 9.3.1.49 Non-Dynamic 5QI Descriptor +typedef struct f1ap_nondynamic_5qi_t { + int fiveQI; +} f1ap_nondynamic_5qi_t; + +// 9.3.1.47 Dynamic 5QI Descriptor +typedef struct f1ap_dynamic_5qi_t { + int prio; /// QoS Priority Level + int pdb; /// Packet Delay Budget + f1ap_per_t per; /// Packet Error Rate + bool *delay_critical; /// Delay Critical + int *avg_win; /// Averaging Window +} f1ap_dynamic_5qi_t; + +typedef struct f1ap_arp_t { + uint16_t prio; + preemption_capability_t preempt_cap; + preemption_vulnerability_t preempt_vuln; +} f1ap_arp_t; + +// 9.3.1.45 QoS Flow Level QoS Parameters +typedef struct f1ap_qos_flow_param_t { + fiveQI_t qos_type; + union { + f1ap_nondynamic_5qi_t nondyn; + f1ap_dynamic_5qi_t dyn; + }; + f1ap_arp_t arp; +} f1ap_qos_flow_param_t; + +// in 9.2.2.1 Flows Mapped to DRB Item +typedef struct f1ap_drb_flows_mapped_t { + int qfi; + f1ap_qos_flow_param_t param; +} f1ap_drb_flows_mapped_t; + +/// in 9.2.2.1 DRB Info in UE Context Setup Request +typedef struct f1ap_drb_info_nr_t { + f1ap_qos_flow_param_t drb_qos; + nssai_t nssai; + int flows_len; + f1ap_drb_flows_mapped_t *flows; +} f1ap_drb_info_nr_t; + +typedef enum { F1AP_PDCP_SN_12B, F1AP_PDCP_SN_18B } f1ap_pdcp_sn_len_t; +/// in 9.2.2.1 DRB to Be Setup Item IEs +typedef struct f1ap_drb_to_setup_t { + int id; + enum { F1AP_QOS_CHOICE_EUTRAN, F1AP_QOS_CHOICE_NR } qos_choice; + union { + // eutran not implemented + f1ap_drb_info_nr_t nr; + }; + int up_ul_tnl_len; + f1ap_up_tnl_t up_ul_tnl[2]; + f1ap_rlc_mode_t rlc_mode; + f1ap_pdcp_sn_len_t *dl_pdcp_sn_len; // in setup mandatory, in setupmod optional + f1ap_pdcp_sn_len_t *ul_pdcp_sn_len; +} f1ap_drb_to_setup_t; + +typedef struct f1ap_ue_context_setup_req_s { + uint32_t gNB_CU_ue_id; + uint32_t *gNB_DU_ue_id; + + plmn_id_t plmn; + uint64_t nr_cellid; + uint8_t servCellIndex; + + f1ap_cu_to_du_rrc_info_t cu_to_du_rrc_info; + + int srbs_len; + f1ap_srb_to_setup_t *srbs; + + int drbs_len; + f1ap_drb_to_setup_t *drbs; + + byte_array_t *rrc_container; + + uint64_t *gnb_du_ue_agg_mbr_ul; // C-ifDRBSetup +} f1ap_ue_context_setup_req_t; + typedef struct f1ap_ue_context_setup_s { uint32_t gNB_CU_ue_id; uint32_t gNB_DU_ue_id; diff --git a/openair2/F1AP/lib/CMakeLists.txt b/openair2/F1AP/lib/CMakeLists.txt index 0c6137dc30..978f69fb29 100644 --- a/openair2/F1AP/lib/CMakeLists.txt +++ b/openair2/F1AP/lib/CMakeLists.txt @@ -2,8 +2,9 @@ add_library(f1ap_lib OBJECT f1ap_lib_common.c f1ap_rrc_message_transfer.c f1ap_interface_management.c + f1ap_ue_context.c ) -target_link_libraries(f1ap_lib PRIVATE asn1_f1ap) +target_link_libraries(f1ap_lib PRIVATE asn1_f1ap ds) target_include_directories(f1ap_lib PUBLIC ${CMAKE_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR} diff --git a/openair2/F1AP/lib/f1ap_lib_includes.h b/openair2/F1AP/lib/f1ap_lib_includes.h index 267e7243e7..e34ec0598d 100644 --- a/openair2/F1AP/lib/f1ap_lib_includes.h +++ b/openair2/F1AP/lib/f1ap_lib_includes.h @@ -41,5 +41,10 @@ #include "F1AP_SibtypetobeupdatedListItem.h" #include "F1AP_UnsuccessfulOutcome.h" #include "F1AP_UE-associatedLogicalF1-ConnectionListRes.h" +#include "F1AP_ULUPTNLInformation-ToBeSetup-Item.h" +#include "F1AP_GTPTunnel.h" +#include "F1AP_Flows-Mapped-To-DRB-Item.h" +#include "F1AP_NonDynamic5QIDescriptor.h" +#include "F1AP_Dynamic5QIDescriptor.h" #endif /* F1AP_LIB_INCLUDES_H_ */ diff --git a/openair2/F1AP/lib/f1ap_ue_context.c b/openair2/F1AP/lib/f1ap_ue_context.c new file mode 100644 index 0000000000..572ad3ce6a --- /dev/null +++ b/openair2/F1AP/lib/f1ap_ue_context.c @@ -0,0 +1,876 @@ +/* + * 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_ue_context.h" + +#include "f1ap_lib_common.h" +#include "f1ap_lib_includes.h" +#include "f1ap_messages_types.h" + +#include "common/utils/assertions.h" +#include "openair3/UTILS/conversions.h" +#include "common/utils/oai_asn1.h" +#include "common/utils/utils.h" +#include "common/utils/ds/byte_array.h" + +static F1AP_CUtoDURRCInformation_t encode_cu_to_du_rrc_info(const f1ap_cu_to_du_rrc_info_t *cu2du) +{ + F1AP_CUtoDURRCInformation_t enc = {0}; + + /* optional: cG_ConfigInfo */ + if (cu2du->cg_configinfo) { + asn1cCalloc(enc.cG_ConfigInfo, cG_ConfigInfo); + const byte_array_t *ba = cu2du->cg_configinfo; + OCTET_STRING_fromBuf(cG_ConfigInfo, (const char *)ba->buf, ba->len); + } + + /* optional: uE_CapabilityRAT_ContainerList */ + if (cu2du->ue_cap) { + asn1cCalloc(enc.uE_CapabilityRAT_ContainerList, uE_CapabilityRAT_ContainerList); + const byte_array_t *ba = cu2du->ue_cap; + OCTET_STRING_fromBuf(uE_CapabilityRAT_ContainerList, (const char *)ba->buf, ba->len); + } + + /* optional: measConfig */ + if (cu2du->meas_config) { + asn1cCalloc(enc.measConfig, measConfig); + const byte_array_t *ba = cu2du->meas_config; + OCTET_STRING_fromBuf(measConfig, (const char *)ba->buf, ba->len); + } + + /* optional: HandoverPreparationInformation */ + if (cu2du->ho_prep_info) { + F1AP_ProtocolExtensionContainer_10696P60_t *p = calloc_or_fail(1, sizeof(*p)); + enc.iE_Extensions = (struct F1AP_ProtocolExtensionContainer *)p; + asn1cSequenceAdd(p->list, F1AP_CUtoDURRCInformation_ExtIEs_t, ie_ext); + ie_ext->id = F1AP_ProtocolIE_ID_id_HandoverPreparationInformation; + ie_ext->criticality = F1AP_Criticality_ignore; + ie_ext->extensionValue.present = F1AP_CUtoDURRCInformation_ExtIEs__extensionValue_PR_HandoverPreparationInformation; + const byte_array_t *ba = cu2du->ho_prep_info; + F1AP_HandoverPreparationInformation_t *hpi = &ie_ext->extensionValue.choice.HandoverPreparationInformation; + OCTET_STRING_fromBuf(hpi, (const char *)ba->buf, ba->len); + } + return enc; +} + +static bool decode_cu_to_du_rrc_info(f1ap_cu_to_du_rrc_info_t *dec, const F1AP_CUtoDURRCInformation_t *cu2du) +{ + if (cu2du->cG_ConfigInfo) { + dec->cg_configinfo = calloc_or_fail(1, sizeof(*dec->cg_configinfo)); + const F1AP_CG_ConfigInfo_t *cgci = cu2du->cG_ConfigInfo; + *dec->cg_configinfo = create_byte_array(cgci->size, (uint8_t*)cgci->buf); + } + if (cu2du->uE_CapabilityRAT_ContainerList) { + dec->ue_cap = calloc_or_fail(1, sizeof(*dec->ue_cap)); + const F1AP_UE_CapabilityRAT_ContainerList_t *l = cu2du->uE_CapabilityRAT_ContainerList; + *dec->ue_cap = create_byte_array(l->size, (uint8_t*)l->buf); + } + if (cu2du->measConfig) { + dec->meas_config = calloc_or_fail(1, sizeof(*dec->meas_config)); + const F1AP_MeasConfig_t *mc = cu2du->measConfig; + *dec->meas_config = create_byte_array(mc->size, (uint8_t*)mc->buf); + } + if (cu2du->iE_Extensions) { + const F1AP_ProtocolExtensionContainer_10696P60_t *ext = (const F1AP_ProtocolExtensionContainer_10696P60_t *)cu2du->iE_Extensions; + for (int i = 0; i < ext->list.count; ++i) { + const F1AP_CUtoDURRCInformation_ExtIEs_t *cu2du_info_ext = ext->list.array[i]; + switch (cu2du_info_ext->id) { + case F1AP_ProtocolIE_ID_id_HandoverPreparationInformation: + dec->ho_prep_info = calloc_or_fail(1, sizeof(*dec->ho_prep_info)); + const F1AP_HandoverPreparationInformation_t *hopi = &cu2du_info_ext->extensionValue.choice.HandoverPreparationInformation; + *dec->ho_prep_info = create_byte_array(hopi->size, (uint8_t*) hopi->buf); + break; + default: + PRINT_ERROR("received unsupported F1AP CUtoDURRCInfo extension container %ld\n", cu2du_info_ext->id); + } + } + } + return true; +} + +static f1ap_cu_to_du_rrc_info_t cp_cu_to_du_rrc_info(const f1ap_cu_to_du_rrc_info_t *src) +{ + f1ap_cu_to_du_rrc_info_t dst = {0}; + CP_OPT_BYTE_ARRAY(dst.cg_configinfo, src->cg_configinfo); + CP_OPT_BYTE_ARRAY(dst.ue_cap, src->ue_cap); + CP_OPT_BYTE_ARRAY(dst.meas_config, src->meas_config); + CP_OPT_BYTE_ARRAY(dst.ho_prep_info, src->ho_prep_info); + return dst; +} + +static bool eq_ba(const byte_array_t a, const byte_array_t b) +{ + return eq_byte_array(&a, &b); +} + +static bool eq_cu_to_du_rrc_info(const f1ap_cu_to_du_rrc_info_t *a, const f1ap_cu_to_du_rrc_info_t *b) +{ + _F1_EQ_CHECK_OPTIONAL_IE(a, b, cg_configinfo, eq_ba); + _F1_EQ_CHECK_OPTIONAL_IE(a, b, ue_cap, eq_ba); + _F1_EQ_CHECK_OPTIONAL_IE(a, b, meas_config, eq_ba); + _F1_EQ_CHECK_OPTIONAL_IE(a, b, ho_prep_info, eq_ba); + return true; +} + +static void free_cu_to_du_rrc_info(f1ap_cu_to_du_rrc_info_t *cu2du) +{ + FREE_OPT_BYTE_ARRAY(cu2du->cg_configinfo); + FREE_OPT_BYTE_ARRAY(cu2du->ue_cap); + FREE_OPT_BYTE_ARRAY(cu2du->meas_config); + FREE_OPT_BYTE_ARRAY(cu2du->ho_prep_info); +} + +/* \brief Encode SRB-ToBeSetup List, for UE Context Setup Request, from + * f1ap_srb_to_setup_t. */ +static F1AP_SRBs_ToBeSetup_List_t encode_srbs_to_setup(int n, const f1ap_srb_to_setup_t *srbs) +{ + F1AP_SRBs_ToBeSetup_List_t list = {0}; + for (int i = 0; i < n; ++i) { + asn1cSequenceAdd(list, F1AP_SRBs_ToBeSetup_ItemIEs_t, itie); + itie->id = F1AP_ProtocolIE_ID_id_SRBs_ToBeSetup_Item; + itie->criticality = F1AP_Criticality_reject; + itie->value.present = F1AP_SRBs_ToBeSetup_ItemIEs__value_PR_SRBs_ToBeSetup_Item; + itie->value.choice.SRBs_ToBeSetup_Item.sRBID = srbs[i].id; + } + return list; +} + +/* \brief Decode SRB-ToBeSetup List, from UE Context Setup Request, into + * f1ap_srb_to_setup_t. */ +static bool decode_srbs_to_setup(const F1AP_SRBs_ToBeSetup_List_t *f1ap, int *n, f1ap_srb_to_setup_t **out) +{ + DevAssert(out != NULL); + *out = NULL; + int count = *n = f1ap->list.count; + if (count == 0) + return true; + + f1ap_srb_to_setup_t *srbs = *out = calloc_or_fail(count, sizeof(*srbs)); + for (int i = 0; i < count; ++i) { + const F1AP_SRBs_ToBeSetup_ItemIEs_t *itie = (F1AP_SRBs_ToBeSetup_ItemIEs_t *)f1ap->list.array[i]; + _F1_EQ_CHECK_LONG(itie->id, F1AP_ProtocolIE_ID_id_SRBs_ToBeSetup_Item); + _F1_EQ_CHECK_INT(itie->value.present, F1AP_SRBs_ToBeSetup_ItemIEs__value_PR_SRBs_ToBeSetup_Item); + srbs[i].id = itie->value.choice.SRBs_ToBeSetup_Item.sRBID; + } + + return true; +} + +static f1ap_srb_to_setup_t cp_srb_to_setup(const f1ap_srb_to_setup_t *orig) +{ + f1ap_srb_to_setup_t cp = { + .id = orig->id, + }; + return cp; +} + +static bool eq_srb_to_setup(const f1ap_srb_to_setup_t *a, const f1ap_srb_to_setup_t *b) +{ + _F1_EQ_CHECK_INT(a->id, b->id); + return true; +} + +static void free_srb_to_setup(f1ap_srb_to_setup_t *srbs) +{ + // nothing to free +} + +static F1AP_QoSFlowLevelQoSParameters_t encode_qos_flow_param(const f1ap_qos_flow_param_t *p) +{ + F1AP_QoSFlowLevelQoSParameters_t f1ap = {0}; + + if (p->qos_type == NON_DYNAMIC) { + f1ap.qoS_Characteristics.present = F1AP_QoS_Characteristics_PR_non_Dynamic_5QI; + asn1cCalloc(f1ap.qoS_Characteristics.choice.non_Dynamic_5QI, nd); + nd->fiveQI = p->nondyn.fiveQI; + } else { + DevAssert(p->qos_type == DYNAMIC); + f1ap.qoS_Characteristics.present = F1AP_QoS_Characteristics_PR_dynamic_5QI; + asn1cCalloc(f1ap.qoS_Characteristics.choice.dynamic_5QI, d); + + d->qoSPriorityLevel = p->dyn.prio; + d->packetDelayBudget = p->dyn.pdb; + d->packetErrorRate.pER_Scalar = p->dyn.per.scalar; + d->packetErrorRate.pER_Exponent = p->dyn.per.exponent; + + if (p->dyn.delay_critical) { + e_F1AP_Dynamic5QIDescriptor__delayCritical v = *p->dyn.delay_critical + ? F1AP_Dynamic5QIDescriptor__delayCritical_delay_critical + : F1AP_Dynamic5QIDescriptor__delayCritical_non_delay_critical; + asn1cCallocOne(d->delayCritical, v); + } + + if (p->dyn.avg_win) + asn1cCallocOne(d->averagingWindow, *p->dyn.avg_win); + } + + F1AP_NGRANAllocationAndRetentionPriority_t *arp = &f1ap.nGRANallocationRetentionPriority; + arp->priorityLevel = p->arp.prio; + arp->pre_emptionCapability = p->arp.preempt_cap; + arp->pre_emptionVulnerability = p->arp.preempt_vuln; + return f1ap; +} + +static bool decode_qos_flow_param(const F1AP_QoSFlowLevelQoSParameters_t *f1ap, f1ap_qos_flow_param_t *out) +{ + if (f1ap->qoS_Characteristics.present == F1AP_QoS_Characteristics_PR_non_Dynamic_5QI) { + out->qos_type = NON_DYNAMIC; + const F1AP_NonDynamic5QIDescriptor_t *nondyn = f1ap->qoS_Characteristics.choice.non_Dynamic_5QI; + out->nondyn.fiveQI = nondyn->fiveQI; + } else { + _F1_EQ_CHECK_INT(f1ap->qoS_Characteristics.present, F1AP_QoS_Characteristics_PR_dynamic_5QI); + const F1AP_Dynamic5QIDescriptor_t *d = f1ap->qoS_Characteristics.choice.dynamic_5QI; + out->qos_type = DYNAMIC; + out->dyn.prio = d->qoSPriorityLevel; + out->dyn.pdb = d->packetDelayBudget; + out->dyn.per.scalar = d->packetErrorRate.pER_Scalar; + out->dyn.per.exponent = d->packetErrorRate.pER_Exponent; + + if (d->delayCritical) { + bool v = *d->delayCritical == F1AP_Dynamic5QIDescriptor__delayCritical_delay_critical; + _F1_MALLOC(out->dyn.delay_critical, v); + } + + if (d->averagingWindow) + _F1_MALLOC(out->dyn.avg_win, *d->averagingWindow); + } + + const F1AP_NGRANAllocationAndRetentionPriority_t *arp = &f1ap->nGRANallocationRetentionPriority; + out->arp.prio = arp->priorityLevel; + out->arp.preempt_cap = arp->pre_emptionCapability; + out->arp.preempt_vuln = arp->pre_emptionVulnerability; + return true; +} + +static f1ap_qos_flow_param_t cp_qos_flow_param(const f1ap_qos_flow_param_t *orig) +{ + f1ap_qos_flow_param_t cp = { + .qos_type = orig->qos_type, + // dyn/nondyn below + .arp = orig->arp, + }; + if (cp.qos_type == NON_DYNAMIC) { + cp.nondyn.fiveQI = orig->nondyn.fiveQI; + } else { + DevAssert(cp.qos_type == DYNAMIC); + f1ap_dynamic_5qi_t *cpdyn = &cp.dyn; + const f1ap_dynamic_5qi_t *odyn = &orig->dyn; + cpdyn->prio = odyn->prio; + cpdyn->pdb = odyn->pdb; + cpdyn->per.scalar = odyn->per.scalar; + cpdyn->per.exponent = odyn->per.exponent; + if (odyn->delay_critical) + _F1_MALLOC(cpdyn->delay_critical, *odyn->delay_critical); + if (odyn->avg_win) + _F1_MALLOC(cpdyn->avg_win, *odyn->avg_win); + } + return cp; +} + +static bool eq_qos_flow_param(const f1ap_qos_flow_param_t *a, const f1ap_qos_flow_param_t *b) +{ + _F1_EQ_CHECK_INT(a->qos_type, b->qos_type); + if (a->qos_type == NON_DYNAMIC) { + _F1_EQ_CHECK_INT(a->nondyn.fiveQI, b->nondyn.fiveQI); + } else { + DevAssert(a->qos_type == DYNAMIC); + DevAssert(b->qos_type == DYNAMIC); + const f1ap_dynamic_5qi_t *adyn = &a->dyn, *bdyn = &b->dyn; + _F1_EQ_CHECK_INT(adyn->prio, bdyn->prio); + _F1_EQ_CHECK_INT(adyn->pdb, bdyn->pdb); + _F1_EQ_CHECK_INT(adyn->per.scalar, bdyn->per.scalar); + _F1_EQ_CHECK_INT(adyn->per.exponent, bdyn->per.exponent); + _F1_EQ_CHECK_OPTIONAL_IE(adyn, bdyn, delay_critical, _F1_EQ_CHECK_INT); + _F1_EQ_CHECK_OPTIONAL_IE(adyn, bdyn, avg_win, _F1_EQ_CHECK_INT); + } + _F1_EQ_CHECK_INT(a->arp.prio, b->arp.prio); + _F1_EQ_CHECK_INT(a->arp.preempt_cap, b->arp.preempt_cap); + _F1_EQ_CHECK_INT(a->arp.preempt_vuln, b->arp.preempt_vuln); + return true; +} + +static void free_qos_flow_param(f1ap_qos_flow_param_t *p) +{ + if (p->qos_type == NON_DYNAMIC) { + // nothing to free + } else { + DevAssert(p->qos_type == DYNAMIC); + free(p->dyn.delay_critical); + free(p->dyn.avg_win); + } + // arp: nothing to free +} + +static F1AP_DRB_Information_t encode_drb_info_nr(const f1ap_drb_info_nr_t *drb) +{ + F1AP_DRB_Information_t f1ap = {0}; + + f1ap.dRB_QoS = encode_qos_flow_param(&drb->drb_qos); + f1ap.sNSSAI = encode_nssai(&drb->nssai); + + for (int i = 0; i < drb->flows_len; ++i) { + asn1cSequenceAdd(f1ap.flows_Mapped_To_DRB_List.list, F1AP_Flows_Mapped_To_DRB_Item_t, it); + it->qoSFlowIdentifier = drb->flows[i].qfi; + it->qoSFlowLevelQoSParameters = encode_qos_flow_param(&drb->flows[i].param); + } + + return f1ap; +} + +static bool decode_drb_info_nr(const F1AP_DRB_Information_t *f1ap, f1ap_drb_info_nr_t *out) +{ + _F1_CHECK_EXP(decode_qos_flow_param(&f1ap->dRB_QoS, &out->drb_qos)); + out->nssai = decode_nssai(&f1ap->sNSSAI); + out->flows_len = f1ap->flows_Mapped_To_DRB_List.list.count; + out->flows = calloc_or_fail(out->flows_len, sizeof(*out->flows)); + for (int i = 0; i < out->flows_len; ++i) { + const F1AP_Flows_Mapped_To_DRB_Item_t *it = f1ap->flows_Mapped_To_DRB_List.list.array[i]; + out->flows[i].qfi = it->qoSFlowIdentifier; + _F1_CHECK_EXP(decode_qos_flow_param(&it->qoSFlowLevelQoSParameters, &out->flows[i].param)); + } + return true; +} + +static f1ap_drb_info_nr_t cp_drb_info_nr(const f1ap_drb_info_nr_t *orig) +{ + f1ap_drb_info_nr_t cp = { + .drb_qos = cp_qos_flow_param(&orig->drb_qos), + .nssai = orig->nssai, + .flows_len = orig->flows_len, + // flows below + }; + cp.flows = calloc_or_fail(cp.flows_len, sizeof(*cp.flows)); + for (int i = 0; i < cp.flows_len; ++i) { + cp.flows[i].qfi = orig->flows[i].qfi; + cp.flows[i].param = cp_qos_flow_param(&orig->flows[i].param); + } + return cp; +} + +static bool eq_drb_info_nr(const f1ap_drb_info_nr_t *a, const f1ap_drb_info_nr_t *b) +{ + _F1_CHECK_EXP(eq_qos_flow_param(&a->drb_qos, &b->drb_qos)); + _F1_EQ_CHECK_INT(a->nssai.sst, b->nssai.sst); + _F1_EQ_CHECK_INT(a->nssai.sd, b->nssai.sd); + _F1_EQ_CHECK_INT(a->flows_len, b->flows_len); + for (int i = 0; i < a->flows_len; ++i) { + _F1_EQ_CHECK_INT(a->flows[i].qfi, b->flows[i].qfi); + _F1_CHECK_EXP(eq_qos_flow_param(&a->flows[i].param, &b->flows[i].param)); + } + return true; +} + +static void free_drb_info_nr(f1ap_drb_info_nr_t *p) +{ + free_qos_flow_param(&p->drb_qos); + // nssai: nothing + for (int i = 0; i < p->flows_len; ++i) + free_qos_flow_param(&p->flows[i].param); + free(p->flows); +} + +static F1AP_RLCMode_t rlc_mode_to_asn1(f1ap_rlc_mode_t mode) +{ + switch (mode) { + case F1AP_RLC_MODE_AM: + return F1AP_RLCMode_rlc_am; + case F1AP_RLC_MODE_UM_BIDIR: + return F1AP_RLCMode_rlc_um_bidirectional; + default: + break; + } + AssertFatal(false, "unsupported RLC Mode %d received\n", mode); + return F1AP_RLCMode_rlc_am; // won't be reached +} + +static bool rlc_mode_from_asn1(F1AP_RLCMode_t mode, f1ap_rlc_mode_t *out) +{ + switch (mode) { + case F1AP_RLCMode_rlc_am: + *out = F1AP_RLC_MODE_AM; + return true; + case F1AP_RLCMode_rlc_um_bidirectional: + *out = F1AP_RLC_MODE_UM_BIDIR; + return true; + default: + PRINT_ERROR("unsupported RLC Mode %ld received: setting AM\n", mode); + break; + } + return false; +} + +static F1AP_UPTransportLayerInformation_t encode_up_tnl(const f1ap_up_tnl_t *tnl) +{ + F1AP_UPTransportLayerInformation_t tnl_info = { .present = F1AP_UPTransportLayerInformation_PR_gTPTunnel, }; + asn1cCalloc(tnl_info.choice.gTPTunnel, gtp_tnl); + TRANSPORT_LAYER_ADDRESS_IPv4_TO_BIT_STRING(tnl->tl_address, >p_tnl->transportLayerAddress); + INT32_TO_OCTET_STRING(tnl->teid, >p_tnl->gTP_TEID); + return tnl_info; +} + +static bool decode_up_tnl(const F1AP_UPTransportLayerInformation_t *tnl_info, f1ap_up_tnl_t *out) +{ + _F1_EQ_CHECK_INT(tnl_info->present, F1AP_UPTransportLayerInformation_PR_gTPTunnel); + const F1AP_GTPTunnel_t *gtp_tnl = tnl_info->choice.gTPTunnel; + BIT_STRING_TO_TRANSPORT_LAYER_ADDRESS_IPv4(>p_tnl->transportLayerAddress, out->tl_address); + OCTET_STRING_TO_UINT32(>p_tnl->gTP_TEID, out->teid); + return true; +} + +static f1ap_up_tnl_t cp_up_tnl(const f1ap_up_tnl_t *orig) +{ + f1ap_up_tnl_t cp = { .teid = orig->teid, }; + memcpy(&cp.tl_address, &orig->tl_address, sizeof(orig->tl_address)); + return cp; +} + +static bool eq_up_tnl(const f1ap_up_tnl_t *a, const f1ap_up_tnl_t *b) +{ + if (memcmp(&a->tl_address, &b->tl_address, sizeof(a->tl_address)) != 0) { + PRINT_ERROR("tl_address mismatch\n"); + return false; + } + _F1_EQ_CHECK_INT(a->teid, b->teid); + return true; +} + +static void free_up_tnl(const f1ap_up_tnl_t *tnl) +{ + // nothing to free +} + +/* Encode a DRBs_ToSetup list for UE Context Setup Request, from f1ap_drb_to_setup_t. */ +static F1AP_DRBs_ToBeSetup_List_t encode_drbs_to_setup(int n, const f1ap_drb_to_setup_t *drbs) +{ + F1AP_DRBs_ToBeSetup_List_t list = {0}; + for (int i = 0; i < n; ++i) { + const f1ap_drb_to_setup_t *drb = &drbs[i]; + asn1cSequenceAdd(list, F1AP_DRBs_ToBeSetup_ItemIEs_t, itie); + itie->id = F1AP_ProtocolIE_ID_id_DRBs_ToBeSetup_Item; + itie->criticality = F1AP_Criticality_reject; + itie->value.present = F1AP_DRBs_ToBeSetup_ItemIEs__value_PR_DRBs_ToBeSetup_Item; + + F1AP_DRBs_ToBeSetup_Item_t *it = &itie->value.choice.DRBs_ToBeSetup_Item; + it->dRBID = drb->id; + AssertFatal(drb->qos_choice == F1AP_QOS_CHOICE_NR, "only NR QoS choice implemented\n"); + it->qoSInformation.present = F1AP_QoSInformation_PR_choice_extension; + F1AP_QoSInformation_ExtIEs_t *qos_ext_ie = calloc_or_fail(1, sizeof(*qos_ext_ie)); + it->qoSInformation.choice.choice_extension = (struct F1AP_ProtocolIE_SingleContainer *)qos_ext_ie; + qos_ext_ie->id = F1AP_ProtocolIE_ID_id_DRB_Information; + qos_ext_ie->criticality = F1AP_Criticality_reject; + qos_ext_ie->value.present = F1AP_QoSInformation_ExtIEs__value_PR_DRB_Information; + qos_ext_ie->value.choice.DRB_Information = encode_drb_info_nr(&drb->nr); + + /* 12.1.3 uLUPTNLInformation_ToBeSetup_List */ + for (int j = 0; j < drb->up_ul_tnl_len; j++) { + DevAssert(drb->up_ul_tnl[j].teid > 0); + asn1cSequenceAdd(it->uLUPTNLInformation_ToBeSetup_List.list, F1AP_ULUPTNLInformation_ToBeSetup_Item_t, tnl_it); + tnl_it->uLUPTNLInformation = encode_up_tnl(&drb->up_ul_tnl[j]); + } + + it->rLCMode = rlc_mode_to_asn1(drb->rlc_mode); + + F1AP_ProtocolExtensionContainer_10696P82_t *ext = calloc_or_fail(1, sizeof(*ext)); + it->iE_Extensions = (struct F1AP_ProtocolExtensionContainer *)ext; + asn1cSequenceAdd(ext->list, F1AP_DRBs_ToBeSetup_ItemExtIEs_t, ext_ie); + ext_ie->id = F1AP_ProtocolIE_ID_id_DLPDCPSNLength; + ext_ie->criticality = F1AP_Criticality_ignore; + ext_ie->extensionValue.present = F1AP_DRBs_ToBeSetup_ItemExtIEs__extensionValue_PR_PDCPSNLength; + AssertFatal(drb->dl_pdcp_sn_len != NULL, "dl_pdcp_sn_len required for setup\n"); + ext_ie->extensionValue.choice.PDCPSNLength = *drb->dl_pdcp_sn_len; + + if (drb->ul_pdcp_sn_len) { + asn1cSequenceAdd(ext->list, F1AP_DRBs_ToBeSetup_ItemExtIEs_t, ext_ie); + ext_ie->id = F1AP_ProtocolIE_ID_id_ULPDCPSNLength; + ext_ie->criticality = F1AP_Criticality_ignore; + ext_ie->extensionValue.present = F1AP_DRBs_ToBeSetup_ItemExtIEs__extensionValue_PR_PDCPSNLength_1; + ext_ie->extensionValue.choice.PDCPSNLength_1 = *drb->ul_pdcp_sn_len; + } + } + return list; +} + +/* \brief Decode DRBS-ToBeSetup list from UE Context Setup request, into + * f1ap_drb_to_setup_t. */ +static bool decode_drbs_to_setup(const F1AP_DRBs_ToBeSetup_List_t *f1ap, int *n, f1ap_drb_to_setup_t **out) +{ + DevAssert(out != NULL); + *out = NULL; + int count = *n = f1ap->list.count; + if (count == 0) + return true; + + f1ap_drb_to_setup_t *drbs = *out = calloc_or_fail(count, sizeof(*drbs)); + for (int i = 0; i < count; ++i) { + const F1AP_DRBs_ToBeSetup_ItemIEs_t *itie = (const F1AP_DRBs_ToBeSetup_ItemIEs_t *)f1ap->list.array[i]; + _F1_EQ_CHECK_LONG(itie->id, F1AP_ProtocolIE_ID_id_DRBs_ToBeSetup_Item); + _F1_EQ_CHECK_INT(itie->value.present, F1AP_DRBs_ToBeSetup_ItemIEs__value_PR_DRBs_ToBeSetup_Item); + const F1AP_DRBs_ToBeSetup_Item_t *it = &itie->value.choice.DRBs_ToBeSetup_Item; + + f1ap_drb_to_setup_t *drb = &drbs[i]; + drb->id = it->dRBID; + + _F1_EQ_CHECK_INT(it->qoSInformation.present, F1AP_QoSInformation_PR_choice_extension); + const F1AP_QoSInformation_ExtIEs_t *qos_ext = (F1AP_QoSInformation_ExtIEs_t *)it->qoSInformation.choice.choice_extension; + _F1_EQ_CHECK_LONG(qos_ext->id, F1AP_ProtocolIE_ID_id_DRB_Information); + _F1_EQ_CHECK_INT(qos_ext->value.present, F1AP_QoSInformation_ExtIEs__value_PR_DRB_Information); + drb->qos_choice = F1AP_QOS_CHOICE_NR; + _F1_CHECK_EXP(decode_drb_info_nr(&qos_ext->value.choice.DRB_Information, &drb->nr)); + + drb->up_ul_tnl_len = it->uLUPTNLInformation_ToBeSetup_List.list.count; + _F1_EQ_CHECK_GENERIC(drb->up_ul_tnl_len > 0 && drb->up_ul_tnl_len <= 2, "%d", drb->up_ul_tnl_len, 1); + for (int j = 0; j < drb->up_ul_tnl_len; ++j) { + const F1AP_ULUPTNLInformation_ToBeSetup_Item_t *it_tnl = it->uLUPTNLInformation_ToBeSetup_List.list.array[j]; + _F1_CHECK_EXP(decode_up_tnl(&it_tnl->uLUPTNLInformation, &drb->up_ul_tnl[j])); + } + + _F1_CHECK_EXP(rlc_mode_from_asn1(it->rLCMode, &drb->rlc_mode)); + + _F1_CHECK_EXP(it->iE_Extensions); // PDCP SN length is under extension, is mandatory + const F1AP_ProtocolExtensionContainer_10696P82_t *ext = (const F1AP_ProtocolExtensionContainer_10696P82_t *)it->iE_Extensions; + const F1AP_DRBs_ToBeSetup_ItemExtIEs_t *ie; + F1AP_LIB_FIND_IE(F1AP_DRBs_ToBeSetup_ItemExtIEs_t, ie, &ext->list, F1AP_ProtocolIE_ID_id_DLPDCPSNLength, true); + + for (int j = 0; j < ext->list.count; ++j) { + ie = ext->list.array[j]; + AssertError(ie != NULL, return false, "ext->list.array[j] is NULL"); + switch (ie->id) { + case F1AP_ProtocolIE_ID_id_DLPDCPSNLength: + _F1_EQ_CHECK_INT(ie->extensionValue.present, F1AP_DRBs_ToBeSetup_ItemExtIEs__extensionValue_PR_PDCPSNLength); + _F1_MALLOC(drb->dl_pdcp_sn_len, ie->extensionValue.choice.PDCPSNLength); + break; + case F1AP_ProtocolIE_ID_id_ULPDCPSNLength: + _F1_EQ_CHECK_INT(ie->extensionValue.present, F1AP_DRBs_ToBeSetup_ItemExtIEs__extensionValue_PR_PDCPSNLength_1); + _F1_MALLOC(drb->ul_pdcp_sn_len, ie->extensionValue.choice.PDCPSNLength_1); + break; + default: + PRINT_ERROR("F1AP_ProtocolIE_ID_id %ld unknown, skipping\n", ie->id); + break; + } + } + } + + return true; +} + +static f1ap_drb_to_setup_t cp_drb_to_setup(const f1ap_drb_to_setup_t *orig) +{ + f1ap_drb_to_setup_t cp = { + .id = orig->id, + .qos_choice = orig->qos_choice, + // nr below + .up_ul_tnl_len = orig->up_ul_tnl_len, + .up_ul_tnl[0] = cp_up_tnl(&orig->up_ul_tnl[0]), + .up_ul_tnl[1] = cp_up_tnl(&orig->up_ul_tnl[1]), + .rlc_mode = orig->rlc_mode, + // dl_pdcp_sn_len below + // ul_pdcp_sn_len below + }; + AssertFatal(cp.qos_choice == F1AP_QOS_CHOICE_NR, "only NR QoS choice implemented\n"); + if (orig->qos_choice == F1AP_QOS_CHOICE_NR) + cp.nr = cp_drb_info_nr(&orig->nr); + if (orig->dl_pdcp_sn_len) { + _F1_MALLOC(cp.dl_pdcp_sn_len, *orig->dl_pdcp_sn_len); + } + if (orig->ul_pdcp_sn_len) { + _F1_MALLOC(cp.ul_pdcp_sn_len, *orig->ul_pdcp_sn_len); + } + return cp; +} + +static bool eq_drb_to_setup(const f1ap_drb_to_setup_t *a, const f1ap_drb_to_setup_t *b) +{ + _F1_EQ_CHECK_INT(a->id, b->id); + _F1_EQ_CHECK_INT(a->qos_choice, b->qos_choice); + AssertFatal(a->qos_choice == F1AP_QOS_CHOICE_NR, "only NR QoS choice implemented\n"); + if (a->qos_choice == F1AP_QOS_CHOICE_NR) + eq_drb_info_nr(&a->nr, &b->nr); + _F1_EQ_CHECK_INT(a->up_ul_tnl_len, b->up_ul_tnl_len); + for (int i = 0; i < a->up_ul_tnl_len; ++i) { + _F1_CHECK_EXP(eq_up_tnl(&a->up_ul_tnl[i], &b->up_ul_tnl[i])); + } + _F1_EQ_CHECK_INT(a->rlc_mode, b->rlc_mode); + _F1_EQ_CHECK_OPTIONAL_IE(a, b, dl_pdcp_sn_len, _F1_EQ_CHECK_INT); + _F1_EQ_CHECK_OPTIONAL_IE(a, b, ul_pdcp_sn_len, _F1_EQ_CHECK_INT); + return true; +} + +static void free_drb_to_setup(f1ap_drb_to_setup_t *drb) +{ + if (drb->qos_choice == F1AP_QOS_CHOICE_NR) + free_drb_info_nr(&drb->nr); + for (int i = 0; i < drb->up_ul_tnl_len; ++i) + free_up_tnl(&drb->up_ul_tnl[i]); + free(drb->dl_pdcp_sn_len); + free(drb->ul_pdcp_sn_len); +} + +/** + * @brief Encode F1 UE context setup request to ASN.1 + */ +F1AP_F1AP_PDU_t *encode_ue_context_setup_req(const f1ap_ue_context_setup_req_t *req) +{ + F1AP_F1AP_PDU_t *pdu = calloc_or_fail(1, sizeof(*pdu)); + + /* Message Type */ + pdu->present = F1AP_F1AP_PDU_PR_initiatingMessage; + asn1cCalloc(pdu->choice.initiatingMessage, tmp); + tmp->procedureCode = F1AP_ProcedureCode_id_UEContextSetup; + tmp->criticality = F1AP_Criticality_reject; + tmp->value.present = F1AP_InitiatingMessage__value_PR_UEContextSetupRequest; + F1AP_UEContextSetupRequest_t *out = &tmp->value.choice.UEContextSetupRequest; + + /* mandatory: GNB_CU_UE_F1AP_ID */ + asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextSetupRequestIEs_t, ie1); + ie1->id = F1AP_ProtocolIE_ID_id_gNB_CU_UE_F1AP_ID; + ie1->criticality = F1AP_Criticality_reject; + ie1->value.present = F1AP_UEContextSetupRequestIEs__value_PR_GNB_CU_UE_F1AP_ID; + ie1->value.choice.GNB_CU_UE_F1AP_ID = req->gNB_CU_ue_id; + + /* optional: GNB_DU_UE_F1AP_ID */ + if (req->gNB_DU_ue_id) { + asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextSetupRequestIEs_t, ie); + ie->id = F1AP_ProtocolIE_ID_id_gNB_DU_UE_F1AP_ID; + ie->criticality = F1AP_Criticality_ignore; + ie->value.present = F1AP_UEContextSetupRequestIEs__value_PR_GNB_DU_UE_F1AP_ID; + ie->value.choice.GNB_DU_UE_F1AP_ID = *req->gNB_DU_ue_id; + } + + /* mandatory: SpCell ID/NRCGI */ + asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextSetupRequestIEs_t, ie3); + ie3->id = F1AP_ProtocolIE_ID_id_SpCell_ID; + ie3->criticality = F1AP_Criticality_reject; + ie3->value.present = F1AP_UEContextSetupRequestIEs__value_PR_NRCGI; + F1AP_NRCGI_t *nrcgi = &ie3->value.choice.NRCGI; + const plmn_id_t *plmn = &req->plmn; + MCC_MNC_TO_PLMNID(plmn->mcc,plmn->mnc,plmn->mnc_digit_length, &nrcgi->pLMN_Identity); + NR_CELL_ID_TO_BIT_STRING(req->nr_cellid, &nrcgi->nRCellIdentity); + + /* mandatory: ServCellIndox */ + asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextSetupRequestIEs_t, ie4); + ie4->id = F1AP_ProtocolIE_ID_id_ServCellIndex; + ie4->criticality = F1AP_Criticality_reject; + ie4->value.present = F1AP_UEContextSetupRequestIEs__value_PR_ServCellIndex; + ie4->value.choice.ServCellIndex = req->servCellIndex; + + /* mandatory: CUtoDURRCInformation */ + asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextSetupRequestIEs_t, ie6); + ie6->id = F1AP_ProtocolIE_ID_id_CUtoDURRCInformation; + ie6->criticality = F1AP_Criticality_reject; + ie6->value.present = F1AP_UEContextSetupRequestIEs__value_PR_CUtoDURRCInformation; + ie6->value.choice.CUtoDURRCInformation = encode_cu_to_du_rrc_info(&req->cu_to_du_rrc_info); + + /* optional: SRB to be setup list */ + if (req->srbs_len > 0) { + asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextSetupRequestIEs_t, ie); + ie->id = F1AP_ProtocolIE_ID_id_SRBs_ToBeSetup_List; + ie->criticality = F1AP_Criticality_reject; + ie->value.present = F1AP_UEContextSetupRequestIEs__value_PR_SRBs_ToBeSetup_List; + ie->value.choice.SRBs_ToBeSetup_List = encode_srbs_to_setup(req->srbs_len, req->srbs); + } + + /* optional: DRB to be setup list */ + if (req->drbs_len > 0) { + asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextSetupRequestIEs_t, ie); + ie->id = F1AP_ProtocolIE_ID_id_DRBs_ToBeSetup_List; + ie->criticality = F1AP_Criticality_reject; + ie->value.present = F1AP_UEContextSetupRequestIEs__value_PR_DRBs_ToBeSetup_List; + ie->value.choice.DRBs_ToBeSetup_List = encode_drbs_to_setup(req->drbs_len, req->drbs); + } + + /* optional: RRC container */ + if (req->rrc_container) { + asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextSetupRequestIEs_t, ie); + ie->id = F1AP_ProtocolIE_ID_id_RRCContainer; + ie->criticality = F1AP_Criticality_ignore; + ie->value.present = F1AP_UEContextSetupRequestIEs__value_PR_RRCContainer; + OCTET_STRING_fromBuf(&ie->value.choice.RRCContainer, (const char *)req->rrc_container->buf, req->rrc_container->len); + } + + /* conditional if DRB setup list: gNB-DU UE Aggregate Maximum Bit Rate Uplink */ + if (req->gnb_du_ue_agg_mbr_ul) { + asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextSetupRequestIEs_t, ie); + ie->id = F1AP_ProtocolIE_ID_id_GNB_DU_UE_AMBR_UL; + ie->criticality = F1AP_Criticality_ignore; + ie->value.present = F1AP_UEContextSetupRequestIEs__value_PR_BitRate; + asn_long2INTEGER(&ie->value.choice.BitRate, *req->gnb_du_ue_agg_mbr_ul); + } + + return pdu; +} + +/** + * @brief Decode F1 UE Context Setup Request + */ +bool decode_ue_context_setup_req(const F1AP_F1AP_PDU_t *pdu, f1ap_ue_context_setup_req_t *out) +{ + DevAssert(out != NULL); + memset(out, 0, sizeof(*out)); + + F1AP_UEContextSetupRequest_t *in = &pdu->choice.initiatingMessage->value.choice.UEContextSetupRequest; + F1AP_UEContextSetupRequestIEs_t *ie; + + F1AP_LIB_FIND_IE(F1AP_UEContextSetupRequestIEs_t, ie, &in->protocolIEs.list, F1AP_ProtocolIE_ID_id_gNB_CU_UE_F1AP_ID, true); + F1AP_LIB_FIND_IE(F1AP_UEContextSetupRequestIEs_t, ie, &in->protocolIEs.list, F1AP_ProtocolIE_ID_id_SpCell_ID, true); + F1AP_LIB_FIND_IE(F1AP_UEContextSetupRequestIEs_t, ie, &in->protocolIEs.list, F1AP_ProtocolIE_ID_id_ServCellIndex, true); + F1AP_LIB_FIND_IE(F1AP_UEContextSetupRequestIEs_t, ie, &in->protocolIEs.list, F1AP_ProtocolIE_ID_id_CUtoDURRCInformation, true); + + for (int i = 0; i < in->protocolIEs.list.count; ++i) { + ie = in->protocolIEs.list.array[i]; + AssertError(ie != NULL, return false, "in->protocolIEs.list.array[i] is NULL"); + switch (ie->id) { + case F1AP_ProtocolIE_ID_id_gNB_CU_UE_F1AP_ID: + _F1_EQ_CHECK_INT(ie->value.present, F1AP_UEContextSetupRequestIEs__value_PR_GNB_CU_UE_F1AP_ID); + out->gNB_CU_ue_id = ie->value.choice.GNB_CU_UE_F1AP_ID; + break; + case F1AP_ProtocolIE_ID_id_gNB_DU_UE_F1AP_ID: + _F1_EQ_CHECK_INT(ie->value.present, F1AP_UEContextSetupRequestIEs__value_PR_GNB_DU_UE_F1AP_ID); + _F1_MALLOC(out->gNB_DU_ue_id, ie->value.choice.GNB_DU_UE_F1AP_ID); + break; + case F1AP_ProtocolIE_ID_id_SpCell_ID: { + _F1_EQ_CHECK_INT(ie->value.present, F1AP_UEContextSetupRequestIEs__value_PR_NRCGI); + const F1AP_NRCGI_t *nrcgi = &ie->value.choice.NRCGI; + PLMNID_TO_MCC_MNC(&nrcgi->pLMN_Identity, out->plmn.mcc, out->plmn.mnc, out->plmn.mnc_digit_length); + BIT_STRING_TO_NR_CELL_IDENTITY(&nrcgi->nRCellIdentity, out->nr_cellid); + } break; + case F1AP_ProtocolIE_ID_id_ServCellIndex: + _F1_EQ_CHECK_INT(ie->value.present, F1AP_UEContextSetupRequestIEs__value_PR_ServCellIndex); + out->servCellIndex = ie->value.choice.ServCellIndex; + break; + case F1AP_ProtocolIE_ID_id_CUtoDURRCInformation: + _F1_EQ_CHECK_INT(ie->value.present, F1AP_UEContextSetupRequestIEs__value_PR_CUtoDURRCInformation); + _F1_CHECK_EXP(decode_cu_to_du_rrc_info(&out->cu_to_du_rrc_info, &ie->value.choice.CUtoDURRCInformation)); + break; + case F1AP_ProtocolIE_ID_id_SRBs_ToBeSetup_List: + _F1_EQ_CHECK_INT(ie->value.present, F1AP_UEContextSetupRequestIEs__value_PR_SRBs_ToBeSetup_List); + _F1_CHECK_EXP(decode_srbs_to_setup(&ie->value.choice.SRBs_ToBeSetup_List, &out->srbs_len, &out->srbs)); + break; + case F1AP_ProtocolIE_ID_id_DRBs_ToBeSetup_List: + _F1_EQ_CHECK_INT(ie->value.present, F1AP_UEContextSetupRequestIEs__value_PR_DRBs_ToBeSetup_List); + { + // gNB-DU UE Aggregate Maximum Bit Rate Uplink is C-ifDRBSetup + // below, check that gNB-DU UE AMBR UL IE is present if we have DRB + // setup, as required by the spec, or return false otherwise (like in + // the beginning of the function) + F1AP_UEContextSetupRequestIEs_t *check_ie; + F1AP_LIB_FIND_IE(F1AP_UEContextSetupRequestIEs_t, check_ie, &in->protocolIEs.list, F1AP_ProtocolIE_ID_id_GNB_DU_UE_AMBR_UL, true); + } + _F1_CHECK_EXP(decode_drbs_to_setup(&ie->value.choice.DRBs_ToBeSetup_List, &out->drbs_len, &out->drbs)); + break; + case F1AP_ProtocolIE_ID_id_RRCContainer: + _F1_EQ_CHECK_INT(ie->value.present, F1AP_UEContextSetupRequestIEs__value_PR_RRCContainer); + out->rrc_container = malloc_or_fail(sizeof(*out->rrc_container)); + { + OCTET_STRING_t *os = &ie->value.choice.RRCContainer; + *out->rrc_container = create_byte_array(os->size, os->buf); + } + break; + case F1AP_ProtocolIE_ID_id_GNB_DU_UE_AMBR_UL: + _F1_EQ_CHECK_INT(ie->value.present, F1AP_UEContextSetupRequestIEs__value_PR_BitRate); + out->gnb_du_ue_agg_mbr_ul = malloc_or_fail(sizeof(*out->gnb_du_ue_agg_mbr_ul)); + asn_INTEGER2uint64(&ie->value.choice.BitRate, out->gnb_du_ue_agg_mbr_ul); + break; + default: + PRINT_ERROR("F1AP_ProtocolIE_ID_id %ld unknown, skipping\n", ie->id); + break; + } + } + + return true; +} + +/** + * @brief F1 UE Context Setup Request deep copy + */ +f1ap_ue_context_setup_req_t cp_ue_context_setup_req(const f1ap_ue_context_setup_req_t *orig) +{ + /* copy all mandatory fields that are not dynamic memory */ + f1ap_ue_context_setup_req_t cp = { + .gNB_CU_ue_id = orig->gNB_CU_ue_id, + .plmn = orig->plmn, + .nr_cellid = orig->nr_cellid, + .servCellIndex = orig->servCellIndex, + .cu_to_du_rrc_info = cp_cu_to_du_rrc_info(&orig->cu_to_du_rrc_info), + }; + if (orig->gNB_DU_ue_id) + _F1_MALLOC(cp.gNB_DU_ue_id, *orig->gNB_DU_ue_id); + if (orig->srbs_len > 0 && orig->srbs) { + cp.srbs = calloc_or_fail(orig->srbs_len, sizeof(*cp.srbs)); + cp.srbs_len = orig->srbs_len; + for (int i = 0; i < cp.srbs_len; ++i) + cp.srbs[i] = cp_srb_to_setup(&orig->srbs[i]); + } + if (orig->drbs_len > 0 && orig->drbs) { + cp.drbs = calloc_or_fail(orig->drbs_len, sizeof(*cp.drbs)); + cp.drbs_len = orig->drbs_len; + for (int i = 0; i < cp.drbs_len; ++i) + cp.drbs[i] = cp_drb_to_setup(&orig->drbs[i]); + } + CP_OPT_BYTE_ARRAY(cp.rrc_container, orig->rrc_container); + if (orig->gnb_du_ue_agg_mbr_ul) + _F1_MALLOC(cp.gnb_du_ue_agg_mbr_ul, *orig->gnb_du_ue_agg_mbr_ul); + return cp; +} + +/** + * @brief F1 UE Context Setup Request equality check + */ +bool eq_ue_context_setup_req(const f1ap_ue_context_setup_req_t *a, const f1ap_ue_context_setup_req_t *b) +{ + _F1_EQ_CHECK_INT(a->gNB_CU_ue_id, b->gNB_CU_ue_id); + _F1_EQ_CHECK_OPTIONAL_IE(a, b, gNB_DU_ue_id, _F1_EQ_CHECK_INT); + _F1_CHECK_EXP(eq_f1ap_plmn(&a->plmn, &b->plmn)); + _F1_EQ_CHECK_LONG(a->nr_cellid, b->nr_cellid); + _F1_EQ_CHECK_INT(a->servCellIndex, b->servCellIndex); + _F1_CHECK_EXP(eq_cu_to_du_rrc_info(&a->cu_to_du_rrc_info, &b->cu_to_du_rrc_info)); + + _F1_EQ_CHECK_INT(a->srbs_len, b->srbs_len); + _F1_CHECK_EXP(a->srbs_len == 0 || (a->srbs && b->srbs)); + for (int i = 0; i < a->srbs_len; ++i) + _F1_CHECK_EXP(eq_srb_to_setup(&a->srbs[i], &b->srbs[i])); + + _F1_EQ_CHECK_INT(a->drbs_len, b->drbs_len); + _F1_CHECK_EXP(a->drbs_len == 0 || (a->drbs && b->drbs)); + for (int i = 0; i < a->drbs_len; ++i) + _F1_CHECK_EXP(eq_drb_to_setup(&a->drbs[i], &b->drbs[i])); + + _F1_EQ_CHECK_OPTIONAL_IE(a, b, rrc_container, eq_ba); + + _F1_EQ_CHECK_OPTIONAL_IE(a, b, gnb_du_ue_agg_mbr_ul, _F1_EQ_CHECK_LONG); + return true; +} + +/** + * @brief Free Allocated F1 UE Context Setup Request + */ +void free_ue_context_setup_req(f1ap_ue_context_setup_req_t *req) +{ + free(req->gNB_DU_ue_id); + free_cu_to_du_rrc_info(&req->cu_to_du_rrc_info); + for (int i = 0; i < req->srbs_len; ++i) + free_srb_to_setup(&req->srbs[i]); + free(req->srbs); + for (int i = 0; i < req->drbs_len; ++i) + free_drb_to_setup(&req->drbs[i]); + free(req->drbs); + FREE_OPT_BYTE_ARRAY(req->rrc_container); + free(req->gnb_du_ue_agg_mbr_ul); +} diff --git a/openair2/F1AP/lib/f1ap_ue_context.h b/openair2/F1AP/lib/f1ap_ue_context.h new file mode 100644 index 0000000000..947273b7a8 --- /dev/null +++ b/openair2/F1AP/lib/f1ap_ue_context.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_UE_CONTEXT_SETUP_REQ_H_ +#define F1AP_UE_CONTEXT_SETUP_REQ_H_ + +#include +#include "f1ap_messages_types.h" + +struct F1AP_F1AP_PDU; + +struct F1AP_F1AP_PDU *encode_ue_context_setup_req(const f1ap_ue_context_setup_req_t *msg); +bool decode_ue_context_setup_req(const struct F1AP_F1AP_PDU *pdu, f1ap_ue_context_setup_req_t *out); +f1ap_ue_context_setup_req_t cp_ue_context_setup_req(const f1ap_ue_context_setup_req_t *orig); +bool eq_ue_context_setup_req(const f1ap_ue_context_setup_req_t *a, const f1ap_ue_context_setup_req_t *b); +void free_ue_context_setup_req(f1ap_ue_context_setup_req_t *req); + +#endif /* F1AP_UE_CONTEXT_SETUP_REQ_H_ */ diff --git a/openair2/F1AP/tests/CMakeLists.txt b/openair2/F1AP/tests/CMakeLists.txt index a73334051a..396e86d513 100644 --- a/openair2/F1AP/tests/CMakeLists.txt +++ b/openair2/F1AP/tests/CMakeLists.txt @@ -1,6 +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 f1ap_lib ds) 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 index 57a503d8ab..a06bd28564 100644 --- a/openair2/F1AP/tests/f1ap_lib_test.c +++ b/openair2/F1AP/tests/f1ap_lib_test.c @@ -31,6 +31,7 @@ #include #include #include +#include #include "common/utils/assertions.h" #include "common/utils/utils.h" @@ -38,8 +39,10 @@ #include "f1ap_messages_types.h" #include "F1AP_F1AP-PDU.h" +#include "lib/f1ap_lib_common.h" #include "lib/f1ap_rrc_message_transfer.h" #include "lib/f1ap_interface_management.h" +#include "lib/f1ap_ue_context.h" void exit_function(const char *file, const char *function, const int line, const char *s, const int assert) { @@ -718,6 +721,171 @@ static void test_f1ap_cu_configuration_update_acknowledge(void) // No free needed } +static byte_array_t get_test_ba(const char *s) +{ + byte_array_t ba = { + .len = strlen(s) + 1, /* binary data: needs to include null-byte of strdup() */ + .buf = (uint8_t *) strdup(s), + }; + return ba; +} + +static byte_array_t *get_malloced_test_ba(const char *s) +{ + byte_array_t *ba = calloc_or_fail(1, sizeof(*ba)); + *ba = get_test_ba(s); + return ba; +} + +static void test_f1ap_ue_context_setup_request() +{ + plmn_id_t plmn = { .mcc = 001, .mnc = 01, .mnc_digit_length = 2 }; + f1ap_ue_context_setup_req_t orig = { + .gNB_CU_ue_id = 12, + //.gNB_DU_ue_id below + .plmn = plmn, + .nr_cellid = 132, + .servCellIndex = 1, + //.cu_to_du_rrc_info below + //.srbs below + //.drbs below + //gnb_du_ue_agg_mbr_ul below + }; + _F1_MALLOC(orig.gNB_DU_ue_id, 13); + orig.cu_to_du_rrc_info.cg_configinfo = get_malloced_test_ba("CG-CONFIGINFO"); + orig.cu_to_du_rrc_info.ue_cap = get_malloced_test_ba("UE CAP"); + orig.cu_to_du_rrc_info.meas_config = get_malloced_test_ba("UE MEASUREMENT CONFIGURATION"); + orig.cu_to_du_rrc_info.ho_prep_info = get_malloced_test_ba("PREPARATION DATA FOR HANDOVER"); + orig.srbs_len = 2; + orig.srbs = calloc_or_fail(orig.srbs_len, sizeof(*orig.srbs)); + for (int i = 0; i < orig.srbs_len; ++i) + orig.srbs[i].id = 1 + i; + + orig.drbs_len = 2; + orig.drbs = calloc_or_fail(orig.drbs_len, sizeof(*orig.drbs)); + f1ap_drb_to_setup_t *drb1 = &orig.drbs[0]; + drb1->id = 4; + drb1->qos_choice = F1AP_QOS_CHOICE_NR; + f1ap_arp_t arp = { 1, MAY_TRIGGER_PREEMPTION, PREEMPTABLE, }; + drb1->nr.drb_qos.qos_type = NON_DYNAMIC; + drb1->nr.drb_qos.nondyn.fiveQI = 3; + drb1->nr.drb_qos.arp = arp; + drb1->nr.nssai = (nssai_t) {.sst = 1, .sd = 123}; + drb1->nr.flows_len = 1; + f1ap_drb_flows_mapped_t *flow = drb1->nr.flows = calloc_or_fail(drb1->nr.flows_len, sizeof(*flow)); + flow->qfi = 2; + flow->param.qos_type = NON_DYNAMIC; + flow->param.nondyn.fiveQI = 3; + flow->param.arp = arp; + drb1->up_ul_tnl_len = 1; + inet_pton(AF_INET, "192.168.40.23", &drb1->up_ul_tnl[0].tl_address); + drb1->up_ul_tnl[0].teid = 0x11223344; + drb1->rlc_mode = F1AP_RLC_MODE_UM_BIDIR; + _F1_MALLOC(drb1->dl_pdcp_sn_len, F1AP_PDCP_SN_18B); + _F1_MALLOC(drb1->ul_pdcp_sn_len, F1AP_PDCP_SN_18B); + + f1ap_drb_to_setup_t *drb2 = &orig.drbs[1]; + drb2->id = 12; + drb2->qos_choice = F1AP_QOS_CHOICE_NR; + drb2->nr.drb_qos.qos_type = DYNAMIC; + f1ap_dynamic_5qi_t *dyn = &drb2->nr.drb_qos.dyn; + dyn->prio = 4; + dyn->pdb = 1000; + dyn->per.scalar = 4; + dyn->per.exponent = 8; + _F1_MALLOC(dyn->delay_critical, true); + _F1_MALLOC(dyn->avg_win, 3000); + f1ap_arp_t arp2 = { 13, SHALL_NOT_TRIGGER_PREEMPTION, NOT_PREEMPTABLE, }; + drb2->nr.drb_qos.arp = arp2; + drb2->nr.nssai = (nssai_t) {.sst = 2, .sd = 0xffffff}; + drb2->nr.flows_len = 2; + f1ap_drb_flows_mapped_t *flow2 = drb2->nr.flows = calloc_or_fail(drb2->nr.flows_len, sizeof(*flow2)); + flow2[0].qfi = 4; + flow2[0].param.qos_type = DYNAMIC; + flow2[0].param.dyn.prio = 4; + flow2[0].param.dyn.pdb = 999; + flow2[0].param.dyn.per.scalar = 4; + flow2[0].param.dyn.per.exponent = 8; + flow2[0].param.arp = arp2; + flow2[1].qfi = 5; + flow2[1].param.qos_type = NON_DYNAMIC; + flow2[1].param.nondyn.fiveQI = 3; + flow2[1].param.arp = arp; + drb2->up_ul_tnl_len = 2; + inet_pton(AF_INET, "10.0.0.2", &drb2->up_ul_tnl[0].tl_address); + drb2->up_ul_tnl[0].teid = 0x1234; + inet_pton(AF_INET, "10.0.0.2", &drb2->up_ul_tnl[1].tl_address); + drb2->up_ul_tnl[1].teid = 0x1235; + drb2->rlc_mode = F1AP_RLC_MODE_AM; + _F1_MALLOC(drb2->dl_pdcp_sn_len, F1AP_PDCP_SN_12B); + _F1_MALLOC(drb2->ul_pdcp_sn_len, F1AP_PDCP_SN_12B); + + orig.rrc_container = get_malloced_test_ba("RRC container"); + + _F1_MALLOC(orig.gnb_du_ue_agg_mbr_ul, 5LL * 1000 * 1000 * 1000); + + F1AP_F1AP_PDU_t *f1enc = encode_ue_context_setup_req(&orig); + F1AP_F1AP_PDU_t *f1dec = f1ap_encode_decode(f1enc); + f1ap_msg_free(f1enc); + + f1ap_ue_context_setup_req_t decoded = {0}; + bool ret = decode_ue_context_setup_req(f1dec, &decoded); + AssertFatal(ret, "decode_ue_context_setup_req(): could not decode message\n"); + f1ap_msg_free(f1dec); + + ret = eq_ue_context_setup_req(&orig, &decoded); + AssertFatal(ret, "eq_ue_context_setup_req(): decoded message doesn't match\n"); + char ip_ret[100]; + inet_ntop(AF_INET, &decoded.drbs[0].up_ul_tnl[0].tl_address, ip_ret, sizeof(ip_ret)); + printf("%s\n", ip_ret); + inet_ntop(AF_INET, &decoded.drbs[1].up_ul_tnl[0].tl_address, ip_ret, sizeof(ip_ret)); + printf("%s\n", ip_ret); + free_ue_context_setup_req(&decoded); + + f1ap_ue_context_setup_req_t cp = cp_ue_context_setup_req(&orig); + ret = eq_ue_context_setup_req(&orig, &cp); + AssertFatal(ret, "eq_ue_context_setup_req(): copied message doesn't match\n"); + free_ue_context_setup_req(&orig); + free_ue_context_setup_req(&cp); + + printf("%s() successful\n", __func__); +} + +static void test_f1ap_ue_context_setup_request_simple() +{ + plmn_id_t plmn = { .mcc = 001, .mnc = 01, .mnc_digit_length = 2 }; + f1ap_ue_context_setup_req_t orig = { + .gNB_CU_ue_id = 12, + .plmn = plmn, + .nr_cellid = 132, + .servCellIndex = 1, + //.cu_to_du_rrc_info: all fields optional, intentionally left empty + // rest is optional and intentionally left empty + // .gnb_du_ue_agg_mbr_ul is C-ifDRBSetup => no DRB => no IE + }; + F1AP_F1AP_PDU_t *f1enc = encode_ue_context_setup_req(&orig); + F1AP_F1AP_PDU_t *f1dec = f1ap_encode_decode(f1enc); + f1ap_msg_free(f1enc); + + f1ap_ue_context_setup_req_t decoded = {0}; + bool ret = decode_ue_context_setup_req(f1dec, &decoded); + AssertFatal(ret, "decode_ue_context_setup_req(): could not decode message\n"); + f1ap_msg_free(f1dec); + + ret = eq_ue_context_setup_req(&orig, &decoded); + AssertFatal(ret, "eq_ue_context_setup_req(): decoded message doesn't match\n"); + free_ue_context_setup_req(&decoded); + + f1ap_ue_context_setup_req_t cp = cp_ue_context_setup_req(&orig); + ret = eq_ue_context_setup_req(&orig, &cp); + AssertFatal(ret, "eq_ue_context_setup_req(): copied message doesn't match\n"); + free_ue_context_setup_req(&orig); + free_ue_context_setup_req(&cp); + + printf("%s() successful\n", __func__); +} + + int main() { test_initial_ul_rrc_message_transfer(); @@ -733,5 +901,7 @@ int main() test_f1ap_cu_configuration_update(); test_f1ap_cu_configuration_update_acknowledge(); test_f1ap_du_configuration_update_acknowledge(); + test_f1ap_ue_context_setup_request(); + test_f1ap_ue_context_setup_request_simple(); return 0; } From 807e44d6042721d7607b6999a7e1dd8547c70b18 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Wed, 4 Jun 2025 18:23:20 +0200 Subject: [PATCH 10/36] Add F1AP UE context modification request message enc/dec + test See commit "Add F1AP UE context setup request message enc/dec + test" for more details on the approach taken. --- openair2/COMMON/f1ap_messages_types.h | 37 ++ openair2/F1AP/lib/f1ap_ue_context.c | 565 ++++++++++++++++++++++++++ openair2/F1AP/lib/f1ap_ue_context.h | 6 + openair2/F1AP/tests/f1ap_lib_test.c | 111 +++++ 4 files changed, 719 insertions(+) diff --git a/openair2/COMMON/f1ap_messages_types.h b/openair2/COMMON/f1ap_messages_types.h index 85f2def720..9992473c9e 100644 --- a/openair2/COMMON/f1ap_messages_types.h +++ b/openair2/COMMON/f1ap_messages_types.h @@ -485,6 +485,11 @@ typedef enum TransmActionInd_e { TransmActionInd_RESTART, } TransmActionInd_t; +typedef enum lower_layer_status_e { + LOWER_LAYERS_SUSPEND, + LOWER_LAYERS_RESUME, +} lower_layer_status_t; + typedef struct f1ap_srb_to_setup_t { int id; } f1ap_srb_to_setup_t; @@ -555,6 +560,10 @@ typedef struct f1ap_drb_to_setup_t { f1ap_pdcp_sn_len_t *ul_pdcp_sn_len; } f1ap_drb_to_setup_t; +typedef struct f1ap_drb_to_release_t { + int id; +} f1ap_drb_to_release_t; + typedef struct f1ap_ue_context_setup_req_s { uint32_t gNB_CU_ue_id; uint32_t *gNB_DU_ue_id; @@ -576,6 +585,34 @@ typedef struct f1ap_ue_context_setup_req_s { uint64_t *gnb_du_ue_agg_mbr_ul; // C-ifDRBSetup } f1ap_ue_context_setup_req_t; +typedef struct f1ap_ue_context_mod_req_t { + uint32_t gNB_CU_ue_id; + uint32_t gNB_DU_ue_id; + + plmn_id_t *plmn; + uint64_t *nr_cellid; + uint8_t *servCellIndex; + + f1ap_cu_to_du_rrc_info_t *cu_to_du_rrc_info; + + TransmActionInd_t *transm_action_ind; + ReconfigurationCompl_t *reconfig_compl; + + byte_array_t *rrc_container; + + int srbs_len; + f1ap_srb_to_setup_t *srbs; // reuse the same type as for setup; there is a + // list for SRB modification + + int drbs_len; + f1ap_drb_to_setup_t *drbs; // as for SRBs + + int drbs_rel_len; + f1ap_drb_to_release_t *drbs_rel; + + lower_layer_status_t *status; +} f1ap_ue_context_mod_req_t; + typedef struct f1ap_ue_context_setup_s { uint32_t gNB_CU_ue_id; uint32_t gNB_DU_ue_id; diff --git a/openair2/F1AP/lib/f1ap_ue_context.c b/openair2/F1AP/lib/f1ap_ue_context.c index 572ad3ce6a..332b0ad130 100644 --- a/openair2/F1AP/lib/f1ap_ue_context.c +++ b/openair2/F1AP/lib/f1ap_ue_context.c @@ -153,6 +153,22 @@ static F1AP_SRBs_ToBeSetup_List_t encode_srbs_to_setup(int n, const f1ap_srb_to_ return list; } +/* \brief Encode SRB-ToBeSetupMod List, for UE context Modification Request, + * from f1ap_srb_to_setup_t. The ToBeSetup/ToBeSetupMod lists are basically the + * same in both cases, but the asn1c types are different. */ +static F1AP_SRBs_ToBeSetupMod_List_t encode_srbs_to_setupmod(int n, const f1ap_srb_to_setup_t *srbs) +{ + F1AP_SRBs_ToBeSetupMod_List_t list = {0}; + for (int i = 0; i < n; ++i) { + asn1cSequenceAdd(list, F1AP_SRBs_ToBeSetupMod_ItemIEs_t, itie); + itie->id = F1AP_ProtocolIE_ID_id_SRBs_ToBeSetupMod_Item; + itie->criticality = F1AP_Criticality_reject; + itie->value.present = F1AP_SRBs_ToBeSetupMod_ItemIEs__value_PR_SRBs_ToBeSetupMod_Item; + itie->value.choice.SRBs_ToBeSetupMod_Item.sRBID = srbs[i].id; + } + return list; +} + /* \brief Decode SRB-ToBeSetup List, from UE Context Setup Request, into * f1ap_srb_to_setup_t. */ static bool decode_srbs_to_setup(const F1AP_SRBs_ToBeSetup_List_t *f1ap, int *n, f1ap_srb_to_setup_t **out) @@ -174,6 +190,28 @@ static bool decode_srbs_to_setup(const F1AP_SRBs_ToBeSetup_List_t *f1ap, int *n, return true; } +/* \brief Decode SRB-ToBeSetupMod List, from UE Context Modification Request, + * into f1ap_srb_to_setup_t. The ToBeSetup/ToBeSetupMod lists are basically the + * same, but the asn1c types are different. */ +static bool decode_srbs_to_setupmod(const F1AP_SRBs_ToBeSetupMod_List_t *f1ap, int *n, f1ap_srb_to_setup_t **out) +{ + DevAssert(out != NULL); + *out = NULL; + int count = *n = f1ap->list.count; + if (count == 0) + return true; + + f1ap_srb_to_setup_t *srbs = *out = calloc_or_fail(count, sizeof(*srbs)); + for (int i = 0; i < count; ++i) { + const F1AP_SRBs_ToBeSetupMod_ItemIEs_t *itie = (F1AP_SRBs_ToBeSetupMod_ItemIEs_t *)f1ap->list.array[i]; + _F1_EQ_CHECK_LONG(itie->id, F1AP_ProtocolIE_ID_id_SRBs_ToBeSetupMod_Item); + _F1_EQ_CHECK_INT(itie->value.present, F1AP_SRBs_ToBeSetupMod_ItemIEs__value_PR_SRBs_ToBeSetupMod_Item); + srbs[i].id = itie->value.choice.SRBs_ToBeSetupMod_Item.sRBID; + } + + return true; +} + static f1ap_srb_to_setup_t cp_srb_to_setup(const f1ap_srb_to_setup_t *orig) { f1ap_srb_to_setup_t cp = { @@ -508,6 +546,64 @@ static F1AP_DRBs_ToBeSetup_List_t encode_drbs_to_setup(int n, const f1ap_drb_to_ return list; } +/* Encode a DRBs_ToBeSetupMod list for UE Context Modification Request, from + * f1ap_drb_to_setup_t. The ToBeSetup/ToBeSetupMod lists are almost the same + * (with the exception that one field is optional in the latter), so that we + * can reuse the internal types, but the asn1c types are different. */ +static F1AP_DRBs_ToBeSetupMod_List_t encode_drbs_to_setupmod(int n, const f1ap_drb_to_setup_t *drbs) +{ + F1AP_DRBs_ToBeSetupMod_List_t list = {0}; + for (int i = 0; i < n; ++i) { + const f1ap_drb_to_setup_t *drb = &drbs[i]; + asn1cSequenceAdd(list, F1AP_DRBs_ToBeSetupMod_ItemIEs_t, itie); + itie->id = F1AP_ProtocolIE_ID_id_DRBs_ToBeSetupMod_Item; + itie->criticality = F1AP_Criticality_reject; + itie->value.present = F1AP_DRBs_ToBeSetupMod_ItemIEs__value_PR_DRBs_ToBeSetupMod_Item; + + F1AP_DRBs_ToBeSetupMod_Item_t *it = &itie->value.choice.DRBs_ToBeSetupMod_Item; + it->dRBID = drb->id; + AssertFatal(drb->qos_choice == F1AP_QOS_CHOICE_NR, "only NR QoS choice implemented\n"); + it->qoSInformation.present = F1AP_QoSInformation_PR_choice_extension; + F1AP_QoSInformation_ExtIEs_t *qos_ext_ie = calloc_or_fail(1, sizeof(*qos_ext_ie)); + it->qoSInformation.choice.choice_extension = (struct F1AP_ProtocolIE_SingleContainer *)qos_ext_ie; + qos_ext_ie->id = F1AP_ProtocolIE_ID_id_DRB_Information; + qos_ext_ie->criticality = F1AP_Criticality_reject; + qos_ext_ie->value.present = F1AP_QoSInformation_ExtIEs__value_PR_DRB_Information; + qos_ext_ie->value.choice.DRB_Information = encode_drb_info_nr(&drb->nr); + + /* 12.1.3 uLUPTNLInformation_ToBeSetupMod_List */ + for (int j = 0; j < drb->up_ul_tnl_len; j++) { + DevAssert(drb->up_ul_tnl[j].teid > 0); + asn1cSequenceAdd(it->uLUPTNLInformation_ToBeSetup_List.list, F1AP_ULUPTNLInformation_ToBeSetup_Item_t, tnl_it); + tnl_it->uLUPTNLInformation = encode_up_tnl(&drb->up_ul_tnl[j]); + } + + it->rLCMode = rlc_mode_to_asn1(drb->rlc_mode); + + if (!drb->dl_pdcp_sn_len && !drb->ul_pdcp_sn_len) + continue; + + F1AP_ProtocolExtensionContainer_10696P83_t *ext = calloc_or_fail(1, sizeof(*ext)); + it->iE_Extensions = (struct F1AP_ProtocolExtensionContainer *)ext; + if (drb->dl_pdcp_sn_len) { + asn1cSequenceAdd(ext->list, F1AP_DRBs_ToBeSetupMod_ItemExtIEs_t, ext_ie); + ext_ie->id = F1AP_ProtocolIE_ID_id_DLPDCPSNLength; + ext_ie->criticality = F1AP_Criticality_ignore; + ext_ie->extensionValue.present = F1AP_DRBs_ToBeSetupMod_ItemExtIEs__extensionValue_PR_PDCPSNLength; + ext_ie->extensionValue.choice.PDCPSNLength = *drb->dl_pdcp_sn_len; + } + + if (drb->ul_pdcp_sn_len) { + asn1cSequenceAdd(ext->list, F1AP_DRBs_ToBeSetupMod_ItemExtIEs_t, ext_ie); + ext_ie->id = F1AP_ProtocolIE_ID_id_ULPDCPSNLength; + ext_ie->criticality = F1AP_Criticality_ignore; + ext_ie->extensionValue.present = F1AP_DRBs_ToBeSetupMod_ItemExtIEs__extensionValue_PR_PDCPSNLength_1; + ext_ie->extensionValue.choice.PDCPSNLength_1 = *drb->ul_pdcp_sn_len; + } + } + return list; +} + /* \brief Decode DRBS-ToBeSetup list from UE Context Setup request, into * f1ap_drb_to_setup_t. */ static bool decode_drbs_to_setup(const F1AP_DRBs_ToBeSetup_List_t *f1ap, int *n, f1ap_drb_to_setup_t **out) @@ -571,6 +667,71 @@ static bool decode_drbs_to_setup(const F1AP_DRBs_ToBeSetup_List_t *f1ap, int *n, return true; } +/* \brief Decode DRBS-ToBeSetupMod list from UE Context Modification Request, into + * f1ap_drb_to_setup_t. The ToBeSetup/ToBeSetupMod lists are almost the same + * (except for some optional types in the latter), so we reuse the internal + * representation, but the asn1c types are different. */ +static bool decode_drbs_to_setupmod(const F1AP_DRBs_ToBeSetupMod_List_t *f1ap, int *n, f1ap_drb_to_setup_t **out) +{ + DevAssert(out != NULL); + *out = NULL; + int count = *n = f1ap->list.count; + if (count == 0) + return true; + + f1ap_drb_to_setup_t *drbs = *out = calloc_or_fail(count, sizeof(*drbs)); + for (int i = 0; i < count; ++i) { + const F1AP_DRBs_ToBeSetupMod_ItemIEs_t *itie = (const F1AP_DRBs_ToBeSetupMod_ItemIEs_t *)f1ap->list.array[i]; + _F1_EQ_CHECK_LONG(itie->id, F1AP_ProtocolIE_ID_id_DRBs_ToBeSetupMod_Item); + _F1_EQ_CHECK_INT(itie->value.present, F1AP_DRBs_ToBeSetupMod_ItemIEs__value_PR_DRBs_ToBeSetupMod_Item); + const F1AP_DRBs_ToBeSetupMod_Item_t *it = &itie->value.choice.DRBs_ToBeSetupMod_Item; + + f1ap_drb_to_setup_t *drb = &drbs[i]; + drb->id = it->dRBID; + + _F1_EQ_CHECK_INT(it->qoSInformation.present, F1AP_QoSInformation_PR_choice_extension); + const F1AP_QoSInformation_ExtIEs_t *qos_ext = (F1AP_QoSInformation_ExtIEs_t *)it->qoSInformation.choice.choice_extension; + _F1_EQ_CHECK_LONG(qos_ext->id, F1AP_ProtocolIE_ID_id_DRB_Information); + _F1_EQ_CHECK_INT(qos_ext->value.present, F1AP_QoSInformation_ExtIEs__value_PR_DRB_Information); + drb->qos_choice = F1AP_QOS_CHOICE_NR; + _F1_CHECK_EXP(decode_drb_info_nr(&qos_ext->value.choice.DRB_Information, &drb->nr)); + + drb->up_ul_tnl_len = it->uLUPTNLInformation_ToBeSetup_List.list.count; + _F1_EQ_CHECK_GENERIC(drb->up_ul_tnl_len > 0 && drb->up_ul_tnl_len <= 2, "%d", drb->up_ul_tnl_len, 1); + for (int j = 0; j < drb->up_ul_tnl_len; ++j) { + const F1AP_ULUPTNLInformation_ToBeSetup_Item_t *it_tnl = it->uLUPTNLInformation_ToBeSetup_List.list.array[j]; + _F1_CHECK_EXP(decode_up_tnl(&it_tnl->uLUPTNLInformation, &drb->up_ul_tnl[j])); + } + + _F1_CHECK_EXP(rlc_mode_from_asn1(it->rLCMode, &drb->rlc_mode)); + + if (!it->iE_Extensions) + continue; + const F1AP_ProtocolExtensionContainer_10696P83_t *ext = (const F1AP_ProtocolExtensionContainer_10696P83_t *)it->iE_Extensions; + const F1AP_DRBs_ToBeSetupMod_ItemExtIEs_t *ie; + + for (int j = 0; j < ext->list.count; ++j) { + ie = ext->list.array[j]; + AssertError(ie != NULL, return false, "ext->list.array[j] is NULL"); + switch (ie->id) { + case F1AP_ProtocolIE_ID_id_DLPDCPSNLength: + _F1_EQ_CHECK_INT(ie->extensionValue.present, F1AP_DRBs_ToBeSetupMod_ItemExtIEs__extensionValue_PR_PDCPSNLength); + _F1_MALLOC(drb->dl_pdcp_sn_len, ie->extensionValue.choice.PDCPSNLength); + break; + case F1AP_ProtocolIE_ID_id_ULPDCPSNLength: + _F1_EQ_CHECK_INT(ie->extensionValue.present, F1AP_DRBs_ToBeSetupMod_ItemExtIEs__extensionValue_PR_PDCPSNLength_1); + _F1_MALLOC(drb->ul_pdcp_sn_len, ie->extensionValue.choice.PDCPSNLength_1); + break; + default: + PRINT_ERROR("F1AP_ProtocolIE_ID_id %ld unknown, skipping\n", ie->id); + break; + } + } + } + + return true; +} + static f1ap_drb_to_setup_t cp_drb_to_setup(const f1ap_drb_to_setup_t *orig) { f1ap_drb_to_setup_t cp = { @@ -623,6 +784,57 @@ static void free_drb_to_setup(f1ap_drb_to_setup_t *drb) free(drb->ul_pdcp_sn_len); } +static F1AP_DRBs_ToBeReleased_List_t encode_drbs_to_release(int n, const f1ap_drb_to_release_t *drbs) +{ + F1AP_DRBs_ToBeReleased_List_t list = {0}; + for (int i = 0; i < n; i++) { + asn1cSequenceAdd(list, F1AP_DRBs_ToBeReleased_ItemIEs_t, itie); + itie->id = F1AP_ProtocolIE_ID_id_DRBs_ToBeReleased_Item; + itie->criticality = F1AP_Criticality_reject; + itie->value.present = F1AP_DRBs_ToBeReleased_ItemIEs__value_PR_DRBs_ToBeReleased_Item; + itie->value.choice.DRBs_ToBeReleased_Item.dRBID = drbs[i].id; + } + return list; +} + +static bool decode_drbs_to_release(const F1AP_DRBs_ToBeReleased_List_t *f1ap, int *n, f1ap_drb_to_release_t **out) +{ + DevAssert(out != NULL); + *out = NULL; + int count = *n = f1ap->list.count; + if (count == 0) + return true; + + f1ap_drb_to_release_t *drbs = *out = calloc_or_fail(count, sizeof(*drbs)); + for (int i = 0; i < count; ++i) { + const F1AP_DRBs_ToBeReleased_ItemIEs_t *itie = (F1AP_DRBs_ToBeReleased_ItemIEs_t *)f1ap->list.array[i]; + _F1_EQ_CHECK_LONG(itie->id, F1AP_ProtocolIE_ID_id_DRBs_ToBeReleased_Item); + _F1_EQ_CHECK_INT(itie->value.present, F1AP_DRBs_ToBeReleased_ItemIEs__value_PR_DRBs_ToBeReleased_Item); + drbs[i].id = itie->value.choice.DRBs_ToBeReleased_Item.dRBID; + } + + return true; +} + +static f1ap_drb_to_release_t cp_drb_to_release(const f1ap_drb_to_release_t *orig) +{ + f1ap_drb_to_release_t cp = { + .id = orig->id, + }; + return cp; +} + +static bool eq_drb_to_release(const f1ap_drb_to_release_t *a, const f1ap_drb_to_release_t *b) +{ + _F1_EQ_CHECK_INT(a->id, b->id); + return true; +} + +static void free_drb_to_release(f1ap_drb_to_release_t *drb) +{ + // nothing to free +} + /** * @brief Encode F1 UE context setup request to ASN.1 */ @@ -874,3 +1086,356 @@ void free_ue_context_setup_req(f1ap_ue_context_setup_req_t *req) FREE_OPT_BYTE_ARRAY(req->rrc_container); free(req->gnb_du_ue_agg_mbr_ul); } + +/** + * @brief Encode F1 UE context modification request to ASN.1 + */ +F1AP_F1AP_PDU_t *encode_ue_context_mod_req(const f1ap_ue_context_mod_req_t *req) +{ + F1AP_F1AP_PDU_t *pdu = calloc_or_fail(1, sizeof(*pdu)); + + /* Message Type */ + pdu->present = F1AP_F1AP_PDU_PR_initiatingMessage; + asn1cCalloc(pdu->choice.initiatingMessage, tmp); + tmp->procedureCode = F1AP_ProcedureCode_id_UEContextModification; + tmp->criticality = F1AP_Criticality_reject; + tmp->value.present = F1AP_InitiatingMessage__value_PR_UEContextModificationRequest; + F1AP_UEContextModificationRequest_t *out = &tmp->value.choice.UEContextModificationRequest; + + /* mandatory: GNB_CU_UE_F1AP_ID */ + asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextModificationRequestIEs_t, ie1); + ie1->id = F1AP_ProtocolIE_ID_id_gNB_CU_UE_F1AP_ID; + ie1->criticality = F1AP_Criticality_reject; + ie1->value.present = F1AP_UEContextModificationRequestIEs__value_PR_GNB_CU_UE_F1AP_ID; + ie1->value.choice.GNB_CU_UE_F1AP_ID = req->gNB_CU_ue_id; + + /* mandatory: GNB_DU_UE_F1AP_ID */ + asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextModificationRequestIEs_t, ie2); + ie2->id = F1AP_ProtocolIE_ID_id_gNB_DU_UE_F1AP_ID; + ie2->criticality = F1AP_Criticality_reject; + ie2->value.present = F1AP_UEContextModificationRequestIEs__value_PR_GNB_DU_UE_F1AP_ID; + ie2->value.choice.GNB_DU_UE_F1AP_ID = req->gNB_DU_ue_id; + + /* optional: SpCellID/NRCGI */ + if (req->plmn) { + DevAssert(req->nr_cellid); + asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextModificationRequestIEs_t, ie3); + ie3->id = F1AP_ProtocolIE_ID_id_SpCell_ID; + ie3->criticality = F1AP_Criticality_ignore; + ie3->value.present = F1AP_UEContextModificationRequestIEs__value_PR_NRCGI; + F1AP_NRCGI_t *nrcgi = &ie3->value.choice.NRCGI; + const plmn_id_t *plmn = req->plmn; + MCC_MNC_TO_PLMNID(plmn->mcc, plmn->mnc, plmn->mnc_digit_length, &nrcgi->pLMN_Identity); + NR_CELL_ID_TO_BIT_STRING(*req->nr_cellid, &nrcgi->nRCellIdentity); + } + + /* optional: ServCellIndex */ + if (req->servCellIndex) { + asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextModificationRequestIEs_t, ie4); + ie4->id = F1AP_ProtocolIE_ID_id_ServCellIndex; + ie4->criticality = F1AP_Criticality_reject; + ie4->value.present = F1AP_UEContextModificationRequestIEs__value_PR_ServCellIndex; + ie4->value.choice.ServCellIndex = *req->servCellIndex; + } + + /* optional: CUtoDURRCInformation */ + if (req->cu_to_du_rrc_info) { + asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextModificationRequestIEs_t, ie6); + ie6->id = F1AP_ProtocolIE_ID_id_CUtoDURRCInformation; + ie6->criticality = F1AP_Criticality_reject; + ie6->value.present = F1AP_UEContextModificationRequestIEs__value_PR_CUtoDURRCInformation; + ie6->value.choice.CUtoDURRCInformation = encode_cu_to_du_rrc_info(req->cu_to_du_rrc_info); + } + + /* optional: TransmissionActionIndicator */ + if (req->transm_action_ind) { + asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextModificationRequestIEs_t, ie7); + ie7->id = F1AP_ProtocolIE_ID_id_TransmissionActionIndicator; + ie7->criticality = F1AP_Criticality_ignore; + ie7->value.present = F1AP_UEContextModificationRequestIEs__value_PR_TransmissionActionIndicator; + ie7->value.choice.TransmissionActionIndicator = *req->transm_action_ind; + // Stop is guaranteed to be 0, by restart might be different from 1 + static_assert((int)F1AP_TransmissionActionIndicator_restart == (int)TransmActionInd_RESTART, + "mismatch of ASN.1 and internal representation\n"); + } + + /* optional: RRCRconfigurationCompleteIndicator */ + if (req->reconfig_compl) { + asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextModificationRequestIEs_t, ie71); + ie71->id = F1AP_ProtocolIE_ID_id_RRCReconfigurationCompleteIndicator; + ie71->criticality = F1AP_Criticality_ignore; + ie71->value.present = F1AP_UEContextModificationRequestIEs__value_PR_RRCReconfigurationCompleteIndicator; + ie71->value.choice.RRCReconfigurationCompleteIndicator = *req->reconfig_compl == RRCreconf_success + ? F1AP_RRCReconfigurationCompleteIndicator_true + : F1AP_RRCReconfigurationCompleteIndicator_failure; + } + + /* optional: RRC container */ + if (req->rrc_container) { + asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextModificationRequestIEs_t, ie81); + ie81->id = F1AP_ProtocolIE_ID_id_RRCContainer; + ie81->criticality = F1AP_Criticality_ignore; + ie81->value.present = F1AP_UEContextModificationRequestIEs__value_PR_RRCContainer; + OCTET_STRING_fromBuf(&ie81->value.choice.RRCContainer, (const char *)req->rrc_container->buf, req->rrc_container->len); + } + + /* optional: SRBs_ToBeSetupMod */ + if (req->srbs_len > 0) { + DevAssert(req->srbs); + asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextModificationRequestIEs_t, ie11); + ie11->id = F1AP_ProtocolIE_ID_id_SRBs_ToBeSetupMod_List; + ie11->criticality = F1AP_Criticality_reject; + ie11->value.present = F1AP_UEContextModificationRequestIEs__value_PR_SRBs_ToBeSetupMod_List; + ie11->value.choice.SRBs_ToBeSetupMod_List = encode_srbs_to_setupmod(req->srbs_len, req->srbs); + } + + /* optional: DRBs_ToBeSetupMod */ + if (req->drbs_len > 0) { + DevAssert(req->drbs); + asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextModificationRequestIEs_t, ie12); + ie12->id = F1AP_ProtocolIE_ID_id_DRBs_ToBeSetupMod_List; + ie12->criticality = F1AP_Criticality_reject; + ie12->value.present = F1AP_UEContextModificationRequestIEs__value_PR_DRBs_ToBeSetupMod_List; + ie12->value.choice.DRBs_ToBeSetupMod_List = encode_drbs_to_setupmod(req->drbs_len, req->drbs); + } + + /* optional: DRBs_ToBeReleased */ + if (req->drbs_rel_len > 0) { + asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextModificationRequestIEs_t, ie15); + ie15->id = F1AP_ProtocolIE_ID_id_DRBs_ToBeReleased_List; + ie15->criticality = F1AP_Criticality_reject; + ie15->value.present = F1AP_UEContextModificationRequestIEs__value_PR_DRBs_ToBeReleased_List; + ie15->value.choice.DRBs_ToBeReleased_List = encode_drbs_to_release(req->drbs_rel_len, req->drbs_rel); + } + + /* optional: Lower Layer Presence Status Change */ + if (req->status) { + asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextModificationRequestIEs_t, ie17); + ie17->id = F1AP_ProtocolIE_ID_id_LowerLayerPresenceStatusChange; + ie17->criticality = F1AP_Criticality_ignore; + ie17->value.present = F1AP_UEContextModificationRequestIEs__value_PR_LowerLayerPresenceStatusChange; + ie17->value.choice.LowerLayerPresenceStatusChange = *req->status == LOWER_LAYERS_SUSPEND + ? F1AP_LowerLayerPresenceStatusChange_suspend_lower_layers + : F1AP_LowerLayerPresenceStatusChange_resume_lower_layers; + } + return pdu; +} + +/** + * @brief Decode F1 UE Context Modification Request + */ +bool decode_ue_context_mod_req(const F1AP_F1AP_PDU_t *pdu, f1ap_ue_context_mod_req_t *out) +{ + DevAssert(out != NULL); + memset(out, 0, sizeof(*out)); + + F1AP_UEContextModificationRequest_t *in = &pdu->choice.initiatingMessage->value.choice.UEContextModificationRequest; + F1AP_UEContextModificationRequestIEs_t *ie; + F1AP_LIB_FIND_IE(F1AP_UEContextModificationRequestIEs_t, ie, &in->protocolIEs.list, F1AP_ProtocolIE_ID_id_gNB_CU_UE_F1AP_ID, true); + F1AP_LIB_FIND_IE(F1AP_UEContextModificationRequestIEs_t, ie, &in->protocolIEs.list, F1AP_ProtocolIE_ID_id_gNB_DU_UE_F1AP_ID, true); + + for (int i = 0; i < in->protocolIEs.list.count; ++i) { + ie = in->protocolIEs.list.array[i]; + AssertError(ie != NULL, return false, "in->protocolIEs.list.array[i] is NULL"); + switch (ie->id) { + case F1AP_ProtocolIE_ID_id_gNB_CU_UE_F1AP_ID: + _F1_EQ_CHECK_INT(ie->value.present, F1AP_UEContextModificationRequestIEs__value_PR_GNB_CU_UE_F1AP_ID); + out->gNB_CU_ue_id = ie->value.choice.GNB_CU_UE_F1AP_ID; + break; + case F1AP_ProtocolIE_ID_id_gNB_DU_UE_F1AP_ID: + _F1_EQ_CHECK_INT(ie->value.present, F1AP_UEContextModificationRequestIEs__value_PR_GNB_DU_UE_F1AP_ID); + out->gNB_DU_ue_id = ie->value.choice.GNB_DU_UE_F1AP_ID; + break; + case F1AP_ProtocolIE_ID_id_SpCell_ID: { + _F1_EQ_CHECK_INT(ie->value.present, F1AP_UEContextModificationRequestIEs__value_PR_NRCGI); + const F1AP_NRCGI_t *nrcgi = &ie->value.choice.NRCGI; + out->plmn = malloc_or_fail(sizeof(*out->plmn)); + PLMNID_TO_MCC_MNC(&nrcgi->pLMN_Identity, out->plmn->mcc, out->plmn->mnc, out->plmn->mnc_digit_length); + out->nr_cellid = malloc_or_fail(sizeof(*out->nr_cellid)); + BIT_STRING_TO_NR_CELL_IDENTITY(&nrcgi->nRCellIdentity, *out->nr_cellid); + } break; + case F1AP_ProtocolIE_ID_id_ServCellIndex: + _F1_EQ_CHECK_INT(ie->value.present, F1AP_UEContextModificationRequestIEs__value_PR_ServCellIndex); + _F1_MALLOC(out->servCellIndex, ie->value.choice.ServCellIndex); + break; + case F1AP_ProtocolIE_ID_id_CUtoDURRCInformation: + _F1_EQ_CHECK_INT(ie->value.present, F1AP_UEContextModificationRequestIEs__value_PR_CUtoDURRCInformation); + out->cu_to_du_rrc_info = calloc(1, sizeof(*out->cu_to_du_rrc_info)); + _F1_CHECK_EXP(decode_cu_to_du_rrc_info(out->cu_to_du_rrc_info, &ie->value.choice.CUtoDURRCInformation)); + break; + case F1AP_ProtocolIE_ID_id_TransmissionActionIndicator: + _F1_EQ_CHECK_INT(ie->value.present, F1AP_UEContextModificationRequestIEs__value_PR_TransmissionActionIndicator); + { + TransmActionInd_t v = ie->value.choice.TransmissionActionIndicator == F1AP_TransmissionActionIndicator_stop + ? TransmActionInd_STOP + : TransmActionInd_RESTART; + _F1_MALLOC(out->transm_action_ind, v); + } + break; + case F1AP_ProtocolIE_ID_id_RRCReconfigurationCompleteIndicator: + _F1_EQ_CHECK_INT(ie->value.present, F1AP_UEContextModificationRequestIEs__value_PR_RRCReconfigurationCompleteIndicator); + { + ReconfigurationCompl_t v = + ie->value.choice.RRCReconfigurationCompleteIndicator == F1AP_RRCReconfigurationCompleteIndicator_true + ? RRCreconf_success + : RRCreconf_failure; + _F1_MALLOC(out->reconfig_compl, v); + } + break; + case F1AP_ProtocolIE_ID_id_RRCContainer: + _F1_EQ_CHECK_INT(ie->value.present, F1AP_UEContextModificationRequestIEs__value_PR_RRCContainer); + out->rrc_container = malloc_or_fail(sizeof(*out->rrc_container)); + { + OCTET_STRING_t *os = &ie->value.choice.RRCContainer; + *out->rrc_container = create_byte_array(os->size, os->buf); + } + break; + case F1AP_ProtocolIE_ID_id_SRBs_ToBeSetupMod_List: + _F1_EQ_CHECK_INT(ie->value.present, F1AP_UEContextModificationRequestIEs__value_PR_SRBs_ToBeSetupMod_List); + _F1_CHECK_EXP(decode_srbs_to_setupmod(&ie->value.choice.SRBs_ToBeSetupMod_List, &out->srbs_len, &out->srbs)); + break; + case F1AP_ProtocolIE_ID_id_DRBs_ToBeSetupMod_List: + _F1_EQ_CHECK_INT(ie->value.present, F1AP_UEContextModificationRequestIEs__value_PR_DRBs_ToBeSetupMod_List); + _F1_CHECK_EXP(decode_drbs_to_setupmod(&ie->value.choice.DRBs_ToBeSetupMod_List, &out->drbs_len, &out->drbs)); + break; + case F1AP_ProtocolIE_ID_id_DRBs_ToBeReleased_List: + _F1_EQ_CHECK_INT(ie->value.present, F1AP_UEContextModificationRequestIEs__value_PR_DRBs_ToBeReleased_List); + _F1_CHECK_EXP(decode_drbs_to_release(&ie->value.choice.DRBs_ToBeReleased_List, &out->drbs_rel_len, &out->drbs_rel)); + break; + case F1AP_ProtocolIE_ID_id_LowerLayerPresenceStatusChange: + _F1_EQ_CHECK_INT(ie->value.present, F1AP_UEContextModificationRequestIEs__value_PR_LowerLayerPresenceStatusChange); + { + lower_layer_status_t v = ie->value.choice.LowerLayerPresenceStatusChange == F1AP_LowerLayerPresenceStatusChange_suspend_lower_layers + ? LOWER_LAYERS_SUSPEND : LOWER_LAYERS_RESUME; + _F1_MALLOC(out->status, v); + } + break; + default: + PRINT_ERROR("F1AP_ProtocolIE_ID_id %ld unknown, skipping\n", ie->id); + break; + } + } + + return true; +} + +/** + * @brief F1 UE Context Modification Request deep copy + */ +f1ap_ue_context_mod_req_t cp_ue_context_mod_req(const f1ap_ue_context_mod_req_t *orig) +{ + f1ap_ue_context_mod_req_t cp = { + .gNB_CU_ue_id = orig->gNB_CU_ue_id, + .gNB_DU_ue_id = orig->gNB_DU_ue_id, + // .plmn, .nr_cellid, .servCellIndex below + // .cu_to_du_rrc_info below + // .transm_action_ind below + // .reconfig_compl below + // .rrc_container below + .srbs_len = orig->srbs_len, + // .srbs below + .drbs_len = orig->drbs_len, + // .drbs below + // .status below + }; + + if (orig->plmn) + _F1_MALLOC(cp.plmn, *orig->plmn); + if (orig->nr_cellid) + _F1_MALLOC(cp.nr_cellid, *orig->nr_cellid); + if (orig->servCellIndex) + _F1_MALLOC(cp.servCellIndex, *orig->servCellIndex); + if (orig->cu_to_du_rrc_info) + _F1_MALLOC(cp.cu_to_du_rrc_info, cp_cu_to_du_rrc_info(orig->cu_to_du_rrc_info)); + if (orig->transm_action_ind) + _F1_MALLOC(cp.transm_action_ind, *orig->transm_action_ind); + if (orig->reconfig_compl) + _F1_MALLOC(cp.reconfig_compl, *orig->reconfig_compl); + CP_OPT_BYTE_ARRAY(cp.rrc_container, orig->rrc_container); + if (orig->srbs_len > 0) { + DevAssert(orig->srbs); + cp.srbs = calloc_or_fail(orig->srbs_len, sizeof(*cp.srbs)); + cp.srbs_len = orig->srbs_len; + for (int i = 0; i < cp.srbs_len; ++i) + cp.srbs[i] = cp_srb_to_setup(&orig->srbs[i]); + } + if (orig->drbs_len > 0) { + DevAssert(orig->drbs); + cp.drbs = calloc_or_fail(orig->drbs_len, sizeof(*cp.drbs)); + cp.drbs_len = orig->drbs_len; + for (int i = 0; i < cp.drbs_len; ++i) + cp.drbs[i] = cp_drb_to_setup(&orig->drbs[i]); + } + if (orig->drbs_rel_len > 0) { + DevAssert(orig->drbs_rel); + cp.drbs_rel = calloc_or_fail(orig->drbs_rel_len, sizeof(*cp.drbs_rel)); + cp.drbs_rel_len = orig->drbs_rel_len; + for (int i = 0; i < cp.drbs_rel_len; ++i) + cp.drbs_rel[i] = cp_drb_to_release(&orig->drbs_rel[i]); + } + if (orig->status) + _F1_MALLOC(cp.status, *orig->status); + return cp; +} + +/** + * @brief F1 UE Context Modification Request equality check + */ +bool eq_ue_context_mod_req(const f1ap_ue_context_mod_req_t *a, const f1ap_ue_context_mod_req_t *b) +{ + _F1_EQ_CHECK_INT(a->gNB_CU_ue_id, b->gNB_CU_ue_id); + _F1_EQ_CHECK_INT(a->gNB_DU_ue_id, b->gNB_DU_ue_id); + _F1_CHECK_EXP((a->plmn && b->plmn) || (!a->plmn && !b->plmn)); + _F1_CHECK_EXP(!a->plmn || eq_f1ap_plmn(a->plmn, b->plmn)); + _F1_EQ_CHECK_OPTIONAL_IE(a, b, nr_cellid, _F1_EQ_CHECK_LONG); + _F1_EQ_CHECK_OPTIONAL_IE(a, b, servCellIndex, _F1_EQ_CHECK_INT); + _F1_CHECK_EXP((a->cu_to_du_rrc_info && b->cu_to_du_rrc_info) || (!a->cu_to_du_rrc_info && !b->cu_to_du_rrc_info)); + _F1_CHECK_EXP(!a->cu_to_du_rrc_info || eq_cu_to_du_rrc_info(a->cu_to_du_rrc_info, b->cu_to_du_rrc_info)); + _F1_EQ_CHECK_OPTIONAL_IE(a, b, transm_action_ind, _F1_EQ_CHECK_INT); + _F1_EQ_CHECK_OPTIONAL_IE(a, b, reconfig_compl, _F1_EQ_CHECK_INT); + _F1_EQ_CHECK_OPTIONAL_IE(a, b, rrc_container, eq_ba); + + _F1_EQ_CHECK_INT(a->srbs_len, b->srbs_len); + _F1_CHECK_EXP(a->srbs_len == 0 || (a->srbs && b->srbs)); + for (int i = 0; i < a->srbs_len; ++i) + _F1_CHECK_EXP(eq_srb_to_setup(&a->srbs[i], &b->srbs[i])); + + _F1_EQ_CHECK_INT(a->drbs_len, b->drbs_len); + _F1_CHECK_EXP(a->drbs_len == 0 || (a->drbs && b->drbs)); + for (int i = 0; i < a->drbs_len; ++i) + _F1_CHECK_EXP(eq_drb_to_setup(&a->drbs[i], &b->drbs[i])); + + _F1_EQ_CHECK_INT(a->drbs_rel_len, b->drbs_rel_len); + _F1_CHECK_EXP(a->drbs_rel_len == 0 || (a->drbs_rel_len && b->drbs_rel_len)); + for (int i = 0; i < a->drbs_rel_len; ++i) + _F1_CHECK_EXP(eq_drb_to_release(&a->drbs_rel[i], &b->drbs_rel[i])); + + _F1_EQ_CHECK_OPTIONAL_IE(a, b, status, _F1_EQ_CHECK_INT); + return true; +} + +/** + * @brief Free Allocated F1 UE Context Modification Request + */ +void free_ue_context_mod_req(f1ap_ue_context_mod_req_t *req) +{ + free(req->plmn); + free(req->nr_cellid); + free(req->servCellIndex); + if (req->cu_to_du_rrc_info) + free_cu_to_du_rrc_info(req->cu_to_du_rrc_info); + free(req->cu_to_du_rrc_info); + free(req->transm_action_ind); + free(req->reconfig_compl); + FREE_OPT_BYTE_ARRAY(req->rrc_container); + for (int i = 0; i < req->srbs_len; ++i) + free_srb_to_setup(&req->srbs[i]); + free(req->srbs); + for (int i = 0; i < req->drbs_len; ++i) + free_drb_to_setup(&req->drbs[i]); + free(req->drbs); + for (int i = 0; i < req->drbs_rel_len; ++i) + free_drb_to_release(&req->drbs_rel[i]); + free(req->drbs_rel); + free(req->status); +} diff --git a/openair2/F1AP/lib/f1ap_ue_context.h b/openair2/F1AP/lib/f1ap_ue_context.h index 947273b7a8..6ac521085b 100644 --- a/openair2/F1AP/lib/f1ap_ue_context.h +++ b/openair2/F1AP/lib/f1ap_ue_context.h @@ -33,4 +33,10 @@ f1ap_ue_context_setup_req_t cp_ue_context_setup_req(const f1ap_ue_context_setup_ bool eq_ue_context_setup_req(const f1ap_ue_context_setup_req_t *a, const f1ap_ue_context_setup_req_t *b); void free_ue_context_setup_req(f1ap_ue_context_setup_req_t *req); +struct F1AP_F1AP_PDU *encode_ue_context_mod_req(const f1ap_ue_context_mod_req_t *msg); +bool decode_ue_context_mod_req(const struct F1AP_F1AP_PDU *pdu, f1ap_ue_context_mod_req_t *out); +f1ap_ue_context_mod_req_t cp_ue_context_mod_req(const f1ap_ue_context_mod_req_t *orig); +bool eq_ue_context_mod_req(const f1ap_ue_context_mod_req_t *a, const f1ap_ue_context_mod_req_t *b); +void free_ue_context_mod_req(f1ap_ue_context_mod_req_t *req); + #endif /* F1AP_UE_CONTEXT_SETUP_REQ_H_ */ diff --git a/openair2/F1AP/tests/f1ap_lib_test.c b/openair2/F1AP/tests/f1ap_lib_test.c index a06bd28564..159ea41470 100644 --- a/openair2/F1AP/tests/f1ap_lib_test.c +++ b/openair2/F1AP/tests/f1ap_lib_test.c @@ -886,6 +886,115 @@ static void test_f1ap_ue_context_setup_request_simple() } +static void test_f1ap_ue_context_modification_request() +{ + f1ap_ue_context_mod_req_t orig = { + .gNB_CU_ue_id = 1111, + .gNB_DU_ue_id = 2222, + // rest below + }; + plmn_id_t plmn = { .mcc = 999, .mnc = 101, .mnc_digit_length = 3 }; + _F1_MALLOC(orig.plmn, plmn); + _F1_MALLOC(orig.nr_cellid, 1532); + _F1_MALLOC(orig.servCellIndex, 3); + + f1ap_cu_to_du_rrc_info_t cu2du = { + .cg_configinfo = get_malloced_test_ba("Modified"), + .ue_cap = get_malloced_test_ba("UE forgot to send earlier"), + .meas_config = get_malloced_test_ba("with updates from another cell"), + .ho_prep_info = get_malloced_test_ba("prepare to ho soon!"), + }; + _F1_MALLOC(orig.cu_to_du_rrc_info, cu2du); + + orig.rrc_container = get_malloced_test_ba("important RRC message!!"); + + orig.srbs_len = 1; + orig.srbs = calloc_or_fail(orig.srbs_len, sizeof(*orig.srbs)); + orig.srbs[0].id = 1; + + orig.drbs_len = 1; + orig.drbs = calloc_or_fail(orig.drbs_len, sizeof(*orig.drbs)); + f1ap_drb_to_setup_t *drb1 = &orig.drbs[0]; + drb1->id = 4; + drb1->qos_choice = F1AP_QOS_CHOICE_NR; + f1ap_arp_t arp = { 2, SHALL_NOT_TRIGGER_PREEMPTION, NOT_PREEMPTABLE, }; + drb1->nr.drb_qos.qos_type = NON_DYNAMIC; + drb1->nr.drb_qos.nondyn.fiveQI = 8; + drb1->nr.drb_qos.arp = arp; + drb1->nr.nssai = (nssai_t) {.sst = 2, .sd = 0xffffff}; + drb1->nr.flows_len = 1; + f1ap_drb_flows_mapped_t *flow = drb1->nr.flows = calloc_or_fail(drb1->nr.flows_len, sizeof(*flow)); + flow->qfi = 2; + flow->param.qos_type = NON_DYNAMIC; + flow->param.nondyn.fiveQI = 9; + flow->param.arp = arp; + drb1->up_ul_tnl_len = 1; + inet_pton(AF_INET, "8.8.8.8", &drb1->up_ul_tnl[0].tl_address); + drb1->up_ul_tnl[0].teid = 0x9876541; + drb1->rlc_mode = F1AP_RLC_MODE_AM; + _F1_MALLOC(drb1->dl_pdcp_sn_len, F1AP_PDCP_SN_12B); + _F1_MALLOC(drb1->ul_pdcp_sn_len, F1AP_PDCP_SN_18B); + + orig.drbs_rel_len = 3; + orig.drbs_rel = calloc_or_fail(orig.drbs_rel_len, sizeof(*orig.drbs_rel)); + orig.drbs_rel[0].id = 13; + orig.drbs_rel[1].id = 4; + orig.drbs_rel[2].id = 19; + + _F1_MALLOC(orig.status, LOWER_LAYERS_RESUME); + + F1AP_F1AP_PDU_t *f1enc = encode_ue_context_mod_req(&orig); + F1AP_F1AP_PDU_t *f1dec = f1ap_encode_decode(f1enc); + f1ap_msg_free(f1enc); + + f1ap_ue_context_mod_req_t decoded = {0}; + bool ret = decode_ue_context_mod_req(f1dec, &decoded); + AssertFatal(ret, "decode_ue_context_mod_req(): could not decode message\n"); + f1ap_msg_free(f1dec); + + ret = eq_ue_context_mod_req(&orig, &decoded); + AssertFatal(ret, "eq_ue_context_mod_req(): decoded message doesn't match\n"); + free_ue_context_mod_req(&decoded); + + f1ap_ue_context_mod_req_t cp = cp_ue_context_mod_req(&orig); + ret = eq_ue_context_mod_req(&orig, &cp); + AssertFatal(ret, "eq_ue_context_mod_req(): copied message doesn't match\n"); + free_ue_context_mod_req(&orig); + free_ue_context_mod_req(&cp); + + printf("%s() successful\n", __func__); +} + +static void test_f1ap_ue_context_modification_request_simple() +{ + f1ap_ue_context_mod_req_t orig = { + .gNB_CU_ue_id = 1111, + .gNB_DU_ue_id = 2222, + // rest is optional and intentionally left out + }; + + F1AP_F1AP_PDU_t *f1enc = encode_ue_context_mod_req(&orig); + F1AP_F1AP_PDU_t *f1dec = f1ap_encode_decode(f1enc); + f1ap_msg_free(f1enc); + + f1ap_ue_context_mod_req_t decoded = {0}; + bool ret = decode_ue_context_mod_req(f1dec, &decoded); + AssertFatal(ret, "decode_ue_context_mod_req(): could not decode message\n"); + f1ap_msg_free(f1dec); + + ret = eq_ue_context_mod_req(&orig, &decoded); + AssertFatal(ret, "eq_ue_context_mod_req(): decoded message doesn't match\n"); + free_ue_context_mod_req(&decoded); + + f1ap_ue_context_mod_req_t cp = cp_ue_context_mod_req(&orig); + ret = eq_ue_context_mod_req(&orig, &cp); + AssertFatal(ret, "eq_ue_context_mod_req(): copied message doesn't match\n"); + free_ue_context_mod_req(&orig); + free_ue_context_mod_req(&cp); + + printf("%s() successful\n", __func__); +} + int main() { test_initial_ul_rrc_message_transfer(); @@ -903,5 +1012,7 @@ int main() test_f1ap_du_configuration_update_acknowledge(); test_f1ap_ue_context_setup_request(); test_f1ap_ue_context_setup_request_simple(); + test_f1ap_ue_context_modification_request(); + test_f1ap_ue_context_modification_request_simple(); return 0; } From 014e67fccd698120eb047ed8c2b94d3e335ddf28 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Thu, 19 Jun 2025 12:20:46 +0200 Subject: [PATCH 11/36] Use F1 UE context setup/modif Request in stack Use the new, tested F1 UE context setup request and modification requests in the stack. We have to do both at once, because there are some functions that are used by handlers for both messages, notably - handle_ue_context_drbs_setup() - handle_ue_context_srbs_setup() (+ and some functions called by those two). For instance, the first uses the (new/old) type f1ap_drb_to_be_setup_t/f1ap_drb_to_setup_t which is shared. The alternative would be to duplicate the functionality temporarily, and I want to avoid unnecessary code churn. --- openair2/COMMON/f1ap_messages_def.h | 4 +- openair2/COMMON/f1ap_messages_types.h | 4 +- openair2/F1AP/f1ap_cu_task.c | 9 +- openair2/F1AP/f1ap_cu_ue_context_management.c | 1020 +---------------- openair2/F1AP/f1ap_cu_ue_context_management.h | 5 +- openair2/F1AP/f1ap_du_task.c | 1 + openair2/F1AP/f1ap_du_ue_context_management.c | 499 +------- .../LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.c | 155 ++- .../LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.h | 4 +- openair2/RRC/NR/mac_rrc_dl.h | 4 +- openair2/RRC/NR/mac_rrc_dl_direct.c | 4 +- openair2/RRC/NR/mac_rrc_dl_f1ap.c | 106 +- openair2/RRC/NR/nr_rrc_proto.h | 8 +- openair2/RRC/NR/rrc_gNB.c | 144 ++- openair2/RRC/NR/rrc_gNB_mobility.c | 94 +- openair2/RRC/NR/rrc_gNB_nsa.c | 65 +- 16 files changed, 304 insertions(+), 1822 deletions(-) diff --git a/openair2/COMMON/f1ap_messages_def.h b/openair2/COMMON/f1ap_messages_def.h index 405ecae3d5..c713361aa5 100644 --- a/openair2/COMMON/f1ap_messages_def.h +++ b/openair2/COMMON/f1ap_messages_def.h @@ -56,9 +56,9 @@ MESSAGE_DEF(F1AP_UE_CONTEXT_MODIFICATION_REQUIRED, MESSAGE_PRIORITY_MED, f1ap_ue /* RRC -> F1AP messages */ MESSAGE_DEF(F1AP_DL_RRC_MESSAGE , MESSAGE_PRIORITY_MED, f1ap_dl_rrc_message_t , f1ap_dl_rrc_message ) //MESSAGE_DEF(F1AP_INITIAL_CONTEXT_SETUP_REQ , MESSAGE_PRIORITY_MED, f1ap_initial_context_setup_req_t , f1ap_initial_context_setup_req ) -MESSAGE_DEF(F1AP_UE_CONTEXT_SETUP_REQ, MESSAGE_PRIORITY_MED, f1ap_ue_context_setup_t, f1ap_ue_context_setup_req) +MESSAGE_DEF(F1AP_UE_CONTEXT_SETUP_REQ, MESSAGE_PRIORITY_MED, f1ap_ue_context_setup_req_t, f1ap_ue_context_setup_req) MESSAGE_DEF(F1AP_UE_CONTEXT_SETUP_RESP, MESSAGE_PRIORITY_MED, f1ap_ue_context_setup_t, f1ap_ue_context_setup_resp) -MESSAGE_DEF(F1AP_UE_CONTEXT_MODIFICATION_REQ, MESSAGE_PRIORITY_MED, f1ap_ue_context_modif_req_t, f1ap_ue_context_modification_req) +MESSAGE_DEF(F1AP_UE_CONTEXT_MODIFICATION_REQ, MESSAGE_PRIORITY_MED, f1ap_ue_context_mod_req_t, f1ap_ue_context_mod_req) MESSAGE_DEF(F1AP_UE_CONTEXT_MODIFICATION_RESP, MESSAGE_PRIORITY_MED, f1ap_ue_context_modif_resp_t, f1ap_ue_context_modification_resp) MESSAGE_DEF(F1AP_UE_CONTEXT_MODIFICATION_CONFIRM, MESSAGE_PRIORITY_MED, f1ap_ue_context_modif_confirm_t, f1ap_ue_context_modification_confirm) MESSAGE_DEF(F1AP_UE_CONTEXT_MODIFICATION_REFUSE, MESSAGE_PRIORITY_MED, f1ap_ue_context_modif_refuse_t, f1ap_ue_context_modification_refuse) diff --git a/openair2/COMMON/f1ap_messages_types.h b/openair2/COMMON/f1ap_messages_types.h index 9992473c9e..73b8162eb4 100644 --- a/openair2/COMMON/f1ap_messages_types.h +++ b/openair2/COMMON/f1ap_messages_types.h @@ -55,7 +55,7 @@ #define F1AP_UL_RRC_MESSAGE(mSGpTR) (mSGpTR)->ittiMsg.f1ap_ul_rrc_message #define F1AP_UE_CONTEXT_SETUP_REQ(mSGpTR) (mSGpTR)->ittiMsg.f1ap_ue_context_setup_req #define F1AP_UE_CONTEXT_SETUP_RESP(mSGpTR) (mSGpTR)->ittiMsg.f1ap_ue_context_setup_resp -#define F1AP_UE_CONTEXT_MODIFICATION_REQ(mSGpTR) (mSGpTR)->ittiMsg.f1ap_ue_context_modification_req +#define F1AP_UE_CONTEXT_MODIFICATION_REQ(mSGpTR) (mSGpTR)->ittiMsg.f1ap_ue_context_mod_req #define F1AP_UE_CONTEXT_MODIFICATION_RESP(mSGpTR) (mSGpTR)->ittiMsg.f1ap_ue_context_modification_resp #define F1AP_UE_CONTEXT_MODIFICATION_FAIL(mSGpTR) (mSGpTR)->ittiMsg.f1ap_ue_context_modification_fail #define F1AP_UE_CONTEXT_MODIFICATION_REQUIRED(mSGpTR) (mSGpTR)->ittiMsg.f1ap_ue_context_modification_required @@ -645,7 +645,7 @@ typedef struct f1ap_ue_context_setup_s { uint8_t *rrc_container; int rrc_container_length; TransmActionInd_t *transm_action_ind; -} f1ap_ue_context_setup_t, f1ap_ue_context_modif_req_t, f1ap_ue_context_modif_resp_t; +} f1ap_ue_context_setup_t, f1ap_ue_context_modif_resp_t; typedef enum F1ap_Cause_e { F1AP_CAUSE_NOTHING, /* No components present */ diff --git a/openair2/F1AP/f1ap_cu_task.c b/openair2/F1AP/f1ap_cu_task.c index 4528a7766f..85375e4109 100644 --- a/openair2/F1AP/f1ap_cu_task.c +++ b/openair2/F1AP/f1ap_cu_task.c @@ -36,6 +36,7 @@ #include "f1ap_cu_ue_context_management.h" #include "lib/f1ap_rrc_message_transfer.h" #include "lib/f1ap_interface_management.h" +#include "lib/f1ap_ue_context.h" #include "f1ap_cu_paging.h" #include "f1ap_cu_task.h" #include "openair2/RRC/NR/nr_rrc_defs.h" @@ -186,13 +187,13 @@ void *F1AP_CU_task(void *arg) { break; case F1AP_UE_CONTEXT_SETUP_REQ: // from rrc - CU_send_UE_CONTEXT_SETUP_REQUEST(assoc_id, - &F1AP_UE_CONTEXT_SETUP_REQ(received_msg)); + CU_send_UE_CONTEXT_SETUP_REQUEST(assoc_id, &F1AP_UE_CONTEXT_SETUP_REQ(received_msg)); + free_ue_context_setup_req(&F1AP_UE_CONTEXT_SETUP_REQ(received_msg)); break; case F1AP_UE_CONTEXT_MODIFICATION_REQ: - CU_send_UE_CONTEXT_MODIFICATION_REQUEST(assoc_id, - &F1AP_UE_CONTEXT_MODIFICATION_REQ(received_msg)); + CU_send_UE_CONTEXT_MODIFICATION_REQUEST(assoc_id, &F1AP_UE_CONTEXT_MODIFICATION_REQ(received_msg)); + free_ue_context_mod_req(&F1AP_UE_CONTEXT_MODIFICATION_REQ(received_msg)); break; case F1AP_UE_CONTEXT_RELEASE_CMD: // from rrc diff --git a/openair2/F1AP/f1ap_cu_ue_context_management.c b/openair2/F1AP/f1ap_cu_ue_context_management.c index f4bffe6144..9dc9e8c086 100644 --- a/openair2/F1AP/f1ap_cu_ue_context_management.c +++ b/openair2/F1AP/f1ap_cu_ue_context_management.c @@ -34,6 +34,7 @@ #include "f1ap_encoder.h" #include "f1ap_itti_messaging.h" #include "f1ap_cu_ue_context_management.h" +#include "lib/f1ap_ue_context.h" #include #include "rrc_extern.h" @@ -44,572 +45,25 @@ #include "openair2/E2AP/RAN_FUNCTION/O-RAN/ran_func_rc_extern.h" #endif -static void f1ap_write_drb_qos_param(const f1ap_qos_flow_level_qos_parameters_t *drb_qos_in, F1AP_QoSFlowLevelQoSParameters_t *asn1_qosparam) +int CU_send_UE_CONTEXT_SETUP_REQUEST(sctp_assoc_t assoc_id, const f1ap_ue_context_setup_req_t *req) { - int type = drb_qos_in->qos_characteristics.qos_type; + F1AP_F1AP_PDU_t *pdu = encode_ue_context_setup_req(req); - const f1ap_qos_characteristics_t *drb_qos_char_in = &drb_qos_in->qos_characteristics; - 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); - - /* 5QI */ - tmp->fiveQI = drb_qos_char_in->non_dynamic.fiveqi; - } else { - asn1_qosparam->qoS_Characteristics.present = F1AP_QoS_Characteristics_PR_dynamic_5QI; - asn1cCalloc(asn1_qosparam->qoS_Characteristics.choice.dynamic_5QI, tmp); - /* qoSPriorityLevel */ - tmp->qoSPriorityLevel = drb_qos_char_in->dynamic.qos_priority_level; - /* packetDelayBudget */ - tmp->packetDelayBudget = drb_qos_char_in->dynamic.packet_delay_budget; - /* packetErrorRate */ - tmp->packetErrorRate.pER_Scalar = drb_qos_char_in->dynamic.packet_error_rate.per_scalar; - tmp->packetErrorRate.pER_Exponent = drb_qos_char_in->dynamic.packet_error_rate.per_scalar; - - /* OPTIONAL delayCritical */ - // asn1cCallocOne(asn1_qosparam->qoS_Characteristics.choice.dynamic_5QI->delayCritical, 1L); - - /* OPTIONAL averagingWindow */ - // asn1cCallocOne(asn1_qosparam->qoS_Characteristics.choice.dynamic_5QI->averagingWindow, 1L); - - /* OPTIONAL maxDataBurstVolume */ - // asn1cCallocOne(asn1_qosparam->qoS_Characteristics.choice.dynamic_5QI->maxDataBurstVolume, 1L); - } - - { - asn1_qosparam->nGRANallocationRetentionPriority.priorityLevel = drb_qos_in->alloc_reten_priority.priority_level; - asn1_qosparam->nGRANallocationRetentionPriority.pre_emptionCapability = drb_qos_in->alloc_reten_priority.preemption_capability; - asn1_qosparam->nGRANallocationRetentionPriority.pre_emptionVulnerability = - drb_qos_in->alloc_reten_priority.preemption_vulnerability; - } // nGRANallocationRetentionPriority - - /* OPTIONAL */ - /* gBR_QoS_Flow_Information */ - if (0) { - asn1cCalloc(asn1_qosparam->gBR_QoS_Flow_Information, tmp); - asn_long2INTEGER(&tmp->maxFlowBitRateDownlink, 1L); - asn_long2INTEGER(&tmp->maxFlowBitRateUplink, 1L); - asn_long2INTEGER(&tmp->guaranteedFlowBitRateDownlink, 1L); - asn_long2INTEGER(&tmp->guaranteedFlowBitRateUplink, 1L); - - /* OPTIONAL */ - /* maxPacketLossRateDownlink */ - // asn1cCallocOne(asn1_qosparam->gBR_QoS_Flow_Information->maxPacketLossRateDownlink, 1L); - - /* OPTIONAL */ - /* maxPacketLossRateUplink */ - //asn1cCallocOne(asn1_qosparam->gBR_QoS_Flow_Information->maxPacketLossRateUplink, 1L); - } - - /* OPTIONAL */ - /* reflective_QoS_Attribute */ - if (0) { - asn1cCallocOne(asn1_qosparam->reflective_QoS_Attribute, 1L); - } -} - -static void f1ap_write_drb_nssai(const nssai_t *nssai, F1AP_SNSSAI_t *asn1_nssai) -{ - OCTET_STRING_fromBuf(&asn1_nssai->sST, (char *)&nssai->sst, 1); - - /* OPTIONAL */ - if (nssai->sd != 0xffffff) { - char sd_buffer[3]; - INT24_TO_BUFFER(nssai->sd, sd_buffer); - asn1cCalloc(asn1_nssai->sD, sD); - OCTET_STRING_fromBuf(sD, sd_buffer, 3); - } -} - -static void f1ap_write_flows_mapped(const f1ap_flows_mapped_to_drb_t *flows_mapped, F1AP_Flows_Mapped_To_DRB_List_t *asn1_flows_mapped, int n) -{ - for (int k = 0; k < n; k++) { - asn1cSequenceAdd(asn1_flows_mapped->list, F1AP_Flows_Mapped_To_DRB_Item_t, flow_item); - - const f1ap_flows_mapped_to_drb_t *qos_flow_in = flows_mapped + k; - - /* qoSFlowIndicator */ - flow_item->qoSFlowIdentifier = qos_flow_in->qfi; - - /* qoSFlowLevelQoSParameters */ - const f1ap_qos_flow_level_qos_parameters_t *flow_qos_params_in = &qos_flow_in->qos_params; - /* qoS_Characteristics */ - - F1AP_QoS_Characteristics_t *QosParams = &flow_item->qoSFlowLevelQoSParameters.qoS_Characteristics; - 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) { - QosParams->present = F1AP_QoS_Characteristics_PR_non_Dynamic_5QI; - asn1cCalloc(QosParams->choice.non_Dynamic_5QI, tmp); - - /* 5QI */ - tmp->fiveQI = flow_qos_char_in->non_dynamic.fiveqi; - } else { - QosParams->present = F1AP_QoS_Characteristics_PR_dynamic_5QI; - asn1cCalloc(QosParams->choice.dynamic_5QI, tmp); - /* qoSPriorityLevel */ - tmp->qoSPriorityLevel = flow_qos_char_in->dynamic.qos_priority_level; - /* packetDelayBudget */ - tmp->packetDelayBudget = flow_qos_char_in->dynamic.packet_delay_budget; - /* packetErrorRate */ - tmp->packetErrorRate.pER_Scalar = flow_qos_char_in->dynamic.packet_error_rate.per_scalar; - tmp->packetErrorRate.pER_Exponent = flow_qos_char_in->dynamic.packet_error_rate.per_exponent; - - /* OPTIONAL delayCritical */ - //asn1cCallocOne(QosParams->choice.dynamic_5QI->delayCritical, 1); - - /* OPTIONAL averagingWindow */ - //asn1cCallocOne(QosParams->choice.dynamic_5QI->averagingWindow, 1); - - /* OPTIONAL maxDataBurstVolume */ - //asn1cCallocOne(QosParams->choice.dynamic_5QI->maxDataBurstVolume, 1); - } - - /* nGRANallocationRetentionPriority */ - { - flow_item->qoSFlowLevelQoSParameters.nGRANallocationRetentionPriority.priorityLevel = - flow_qos_params_in->alloc_reten_priority.priority_level; - flow_item->qoSFlowLevelQoSParameters.nGRANallocationRetentionPriority.pre_emptionCapability = - flow_qos_params_in->alloc_reten_priority.preemption_capability; - flow_item->qoSFlowLevelQoSParameters.nGRANallocationRetentionPriority.pre_emptionVulnerability = - flow_qos_params_in->alloc_reten_priority.preemption_vulnerability; - } // nGRANallocationRetentionPriority - - /* OPTIONAL */ - /* gBR_QoS_Flow_Information */ - if (0) { - asn1cCalloc(flow_item->qoSFlowLevelQoSParameters.gBR_QoS_Flow_Information, tmp); - asn_long2INTEGER(&tmp->maxFlowBitRateDownlink, 1L); - asn_long2INTEGER(&tmp->maxFlowBitRateUplink, 1L); - asn_long2INTEGER(&tmp->guaranteedFlowBitRateDownlink, 1L); - asn_long2INTEGER(&tmp->guaranteedFlowBitRateUplink, 1L); - - /* OPTIONAL maxPacketLossRateDownlink */ - //asn1cCallocOne(flows_mapped_to_drb_item->qoSFlowLevelQoSParameters.gBR_QoS_Flow_Information->maxPacketLossRateDownlink, 1L); - - /* OPTIONAL maxPacketLossRateUplink */ - //asn1cCallocOne(flows_mapped_to_drb_item->qoSFlowLevelQoSParameters.gBR_QoS_Flow_Information->maxPacketLossRateUplink, 1L); - } - - /* OPTIONAL reflective_QoS_Attribute */ - //asn1cCallocOne(flows_mapped_to_drb_item->qoSFlowLevelQoSParameters.reflective_QoS_Attribute, 1L); - } -} - -int CU_send_UE_CONTEXT_SETUP_REQUEST(sctp_assoc_t assoc_id, f1ap_ue_context_setup_t *f1ap_ue_context_setup_req) -{ - F1AP_F1AP_PDU_t pdu= {0}; - /* Create */ - /* 0. Message Type */ - pdu.present = F1AP_F1AP_PDU_PR_initiatingMessage; - asn1cCalloc(pdu.choice.initiatingMessage, tmp); - tmp->procedureCode = F1AP_ProcedureCode_id_UEContextSetup; - tmp->criticality = F1AP_Criticality_reject; - tmp->value.present = F1AP_InitiatingMessage__value_PR_UEContextSetupRequest; - F1AP_UEContextSetupRequest_t *out = &pdu.choice.initiatingMessage->value.choice.UEContextSetupRequest; - /* mandatory */ - /* c1. GNB_CU_UE_F1AP_ID */ - asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextSetupRequestIEs_t, ie1); - ie1->id = F1AP_ProtocolIE_ID_id_gNB_CU_UE_F1AP_ID; - ie1->criticality = F1AP_Criticality_reject; - ie1->value.present = F1AP_UEContextSetupRequestIEs__value_PR_GNB_CU_UE_F1AP_ID; - ie1->value.choice.GNB_CU_UE_F1AP_ID = f1ap_ue_context_setup_req->gNB_CU_ue_id; - - /* optional */ - /* c2. GNB_DU_UE_F1AP_ID */ - if (f1ap_ue_context_setup_req->gNB_DU_ue_id) { - asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextSetupRequestIEs_t, ie2); - ie2->id = F1AP_ProtocolIE_ID_id_gNB_DU_UE_F1AP_ID; - ie2->criticality = F1AP_Criticality_ignore; - ie2->value.present = F1AP_UEContextSetupRequestIEs__value_PR_GNB_DU_UE_F1AP_ID; - ie2->value.choice.GNB_DU_UE_F1AP_ID = f1ap_ue_context_setup_req->gNB_DU_ue_id; - } - - /* mandatory */ - /* c3. SpCell_ID */ - asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextSetupRequestIEs_t, ie3); - ie3->id = F1AP_ProtocolIE_ID_id_SpCell_ID; - ie3->criticality = F1AP_Criticality_reject; - ie3->value.present = F1AP_UEContextSetupRequestIEs__value_PR_NRCGI; - /* - nRCGI */ - addnRCGI(ie3->value.choice.NRCGI, f1ap_ue_context_setup_req); - /* mandatory */ - /* c4. ServCellIndex */ - asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextSetupRequestIEs_t, ie4); - ie4->id = F1AP_ProtocolIE_ID_id_ServCellIndex; - ie4->criticality = F1AP_Criticality_reject; - ie4->value.present = F1AP_UEContextSetupRequestIEs__value_PR_ServCellIndex; - ie4->value.choice.ServCellIndex = 0; - - /* optional */ - /* c5. CellULConfigured */ - if (0) { - asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextSetupRequestIEs_t, ie5); - ie5->id = F1AP_ProtocolIE_ID_id_SpCellULConfigured; - ie5->criticality = F1AP_Criticality_ignore; - ie5->value.present = F1AP_UEContextSetupRequestIEs__value_PR_CellULConfigured; - ie5->value.choice.CellULConfigured = F1AP_CellULConfigured_ul; - } - - /* mandatory */ - /* c6. CUtoDURRCInformation */ - asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextSetupRequestIEs_t, ie6); - ie6->id = F1AP_ProtocolIE_ID_id_CUtoDURRCInformation; - ie6->criticality = F1AP_Criticality_reject; - ie6->value.present = F1AP_UEContextSetupRequestIEs__value_PR_CUtoDURRCInformation; - - if (f1ap_ue_context_setup_req->cu_to_du_rrc_information!=NULL) { - /* optional */ - /* 6.1 cG_ConfigInfo */ - if(f1ap_ue_context_setup_req->cu_to_du_rrc_information->cG_ConfigInfo_length > 0) { - DevAssert(f1ap_ue_context_setup_req->cu_to_du_rrc_information->cG_ConfigInfo != NULL); - asn1cCalloc(ie6->value.choice.CUtoDURRCInformation.cG_ConfigInfo, cG_ConfigInfo); - OCTET_STRING_fromBuf(cG_ConfigInfo, (const char *)f1ap_ue_context_setup_req->cu_to_du_rrc_information->cG_ConfigInfo, - f1ap_ue_context_setup_req->cu_to_du_rrc_information->cG_ConfigInfo_length); - } - - /* optional */ - /* 6.2 uE_CapabilityRAT_ContainerList */ - if(f1ap_ue_context_setup_req->cu_to_du_rrc_information->uE_CapabilityRAT_ContainerList!=NULL){ - asn1cCalloc(ie6->value.choice.CUtoDURRCInformation.uE_CapabilityRAT_ContainerList, uE_CapabilityRAT_ContainerList ); - OCTET_STRING_fromBuf(uE_CapabilityRAT_ContainerList, (const char *)f1ap_ue_context_setup_req->cu_to_du_rrc_information->uE_CapabilityRAT_ContainerList, - f1ap_ue_context_setup_req->cu_to_du_rrc_information->uE_CapabilityRAT_ContainerList_length); - } - /* optional */ - /* 6.3 measConfig */ - if(f1ap_ue_context_setup_req->cu_to_du_rrc_information->measConfig!=NULL){ - asn1cCalloc(ie6->value.choice.CUtoDURRCInformation.measConfig, measConfig); - OCTET_STRING_fromBuf(measConfig, (const char*)f1ap_ue_context_setup_req->cu_to_du_rrc_information->measConfig, - f1ap_ue_context_setup_req->cu_to_du_rrc_information->measConfig_length); - } - - /* optional */ - /* HandoverPreparationInformation */ - if (f1ap_ue_context_setup_req->cu_to_du_rrc_information->handoverPreparationInfo_length > 0) { - DevAssert(f1ap_ue_context_setup_req->cu_to_du_rrc_information->handoverPreparationInfo != NULL); - F1AP_ProtocolExtensionContainer_10696P60_t *p = calloc(1, sizeof(*p)); - ie6->value.choice.CUtoDURRCInformation.iE_Extensions = (struct F1AP_ProtocolExtensionContainer *)p; - asn1cSequenceAdd(p->list, F1AP_CUtoDURRCInformation_ExtIEs_t, ie_ext); - ie_ext->id = F1AP_ProtocolIE_ID_id_HandoverPreparationInformation; - ie_ext->criticality = F1AP_Criticality_ignore; - ie_ext->extensionValue.present = F1AP_CUtoDURRCInformation_ExtIEs__extensionValue_PR_HandoverPreparationInformation; - OCTET_STRING_fromBuf(&ie_ext->extensionValue.choice.HandoverPreparationInformation, - (const char *)f1ap_ue_context_setup_req->cu_to_du_rrc_information->handoverPreparationInfo, - f1ap_ue_context_setup_req->cu_to_du_rrc_information->handoverPreparationInfo_length); - } - } - - /* optional */ - if (0) { - /* c7. Candidate_SpCell_List */ - asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextSetupRequestIEs_t, ie7); - ie7->id = F1AP_ProtocolIE_ID_id_Candidate_SpCell_List; // 90 - ie7->criticality = F1AP_Criticality_ignore; - ie7->value.present = F1AP_UEContextSetupRequestIEs__value_PR_Candidate_SpCell_List; - - for (int i = 0; i < 1; i++) { - asn1cSequenceAdd(ie7->value.choice.Candidate_SpCell_List.list, F1AP_Candidate_SpCell_ItemIEs_t, candidate_spCell_item_ies); - candidate_spCell_item_ies->id = F1AP_ProtocolIE_ID_id_Candidate_SpCell_Item; // 91 - candidate_spCell_item_ies->criticality = F1AP_Criticality_ignore; - candidate_spCell_item_ies->value.present = F1AP_Candidate_SpCell_ItemIEs__value_PR_Candidate_SpCell_Item; - /* 7.1 Candidate_SpCell_Item */ - F1AP_Candidate_SpCell_Item_t *candidate_spCell_item = &candidate_spCell_item_ies->value.choice.Candidate_SpCell_Item; - /* - candidate_SpCell_ID */ - // FixMe: first cell ??? - addnRCGI(candidate_spCell_item->candidate_SpCell_ID, f1ap_ue_context_setup_req); - /* TODO add correct mcc/mnc */ - } - } - - /* optional */ - /* c8. DRXCycle */ - if (0) { - asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextSetupRequestIEs_t, ie8); - ie8->id = F1AP_ProtocolIE_ID_id_DRXCycle; - ie8->criticality = F1AP_Criticality_ignore; - ie8->value.present = F1AP_UEContextSetupRequestIEs__value_PR_DRXCycle; - /* 8.1 longDRXCycleLength */ - ie8->value.choice.DRXCycle.longDRXCycleLength = F1AP_LongDRXCycleLength_ms10; // enum - - /* optional */ - /* 8.2 shortDRXCycleLength */ - if (0) { - asn1cCallocOne(ie6->value.choice.DRXCycle.shortDRXCycleLength, - F1AP_ShortDRXCycleLength_ms2); // enum - } - - /* optional */ - /* 8.3 shortDRXCycleTimer */ - if (0) { - asn1cCallocOne(ie8->value.choice.DRXCycle.shortDRXCycleTimer, - 123L); - } - } - - /* optional */ - /* c9. ResourceCoordinationTransferContainer */ - if (0) { - asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextSetupRequestIEs_t, ie9); - ie9->id = F1AP_ProtocolIE_ID_id_ResourceCoordinationTransferContainer; - ie9->criticality = F1AP_Criticality_ignore; - ie9->value.present = F1AP_UEContextSetupRequestIEs__value_PR_ResourceCoordinationTransferContainer; - ie9->value.choice.ResourceCoordinationTransferContainer.buf = malloc(4); - ie9->value.choice.ResourceCoordinationTransferContainer.size = 4; - strncpy((char *)ie9->value.choice.ResourceCoordinationTransferContainer.buf, "123", 4); - OCTET_STRING_fromBuf(&ie9->value.choice.ResourceCoordinationTransferContainer, "asdsa1d32sa1d31asd31as", - strlen("asdsa1d32sa1d31asd31as")); - } - - /* optional */ - if (0) { - /* c10. SCell_ToBeSetup_List */ - asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextSetupRequestIEs_t, ie10); - ie10->id = F1AP_ProtocolIE_ID_id_SCell_ToBeSetup_List; - ie10->criticality = F1AP_Criticality_ignore; - ie10->value.present = F1AP_UEContextSetupRequestIEs__value_PR_SCell_ToBeSetup_List; - - for (int i = 0; i < 1; i++) { - asn1cSequenceAdd(ie10->value.choice.SCell_ToBeSetup_List.list, F1AP_SCell_ToBeSetup_ItemIEs_t, scell_toBeSetup_item_ies); - scell_toBeSetup_item_ies->id = F1AP_ProtocolIE_ID_id_SCell_ToBeSetup_Item; // 53 - scell_toBeSetup_item_ies->criticality = F1AP_Criticality_ignore; - scell_toBeSetup_item_ies->value.present = F1AP_SCell_ToBeSetup_ItemIEs__value_PR_SCell_ToBeSetup_Item; - /* 10.1 SCell_ToBeSetup_Item */ - F1AP_SCell_ToBeSetup_Item_t *scell_toBeSetup_item = &scell_toBeSetup_item_ies->value.choice.SCell_ToBeSetup_Item; - /* 10.1.1 sCell_ID */ - addnRCGI(scell_toBeSetup_item->sCell_ID, f1ap_ue_context_setup_req); - /* TODO correct MCC/MNC */ - /* 10.1.2 sCellIndex */ - scell_toBeSetup_item->sCellIndex = 3; // issue here - - /* OPTIONAL */ - /* 10.1.3 sCellULConfigured*/ - if (0) { - asn1cCallocOne(scell_toBeSetup_item->sCellULConfigured, - F1AP_CellULConfigured_ul_and_sul); // enum - } - } - } - - /* mandatory */ - /* c11. SRBs_ToBeSetup_List */ - if(f1ap_ue_context_setup_req->srbs_to_be_setup_length > 0){ - asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextSetupRequestIEs_t, ie11); - ie11->id = F1AP_ProtocolIE_ID_id_SRBs_ToBeSetup_List; - ie11->criticality = F1AP_Criticality_reject; // ? - ie11->value.present = F1AP_UEContextSetupRequestIEs__value_PR_SRBs_ToBeSetup_List; - - for (int i=0; isrbs_to_be_setup_length; i++) { - asn1cSequenceAdd(ie11->value.choice.SRBs_ToBeSetup_List.list, F1AP_SRBs_ToBeSetup_ItemIEs_t, srbs_toBeSetup_item_ies); - srbs_toBeSetup_item_ies->id = F1AP_ProtocolIE_ID_id_SRBs_ToBeSetup_Item; // 73 - srbs_toBeSetup_item_ies->criticality = F1AP_Criticality_reject; - srbs_toBeSetup_item_ies->value.present = F1AP_SRBs_ToBeSetup_ItemIEs__value_PR_SRBs_ToBeSetup_Item; - /* 11.1 SRBs_ToBeSetup_Item */ - F1AP_SRBs_ToBeSetup_Item_t *srbs_toBeSetup_item=&srbs_toBeSetup_item_ies->value.choice.SRBs_ToBeSetup_Item; - /* 11.1.1 sRBID */ - srbs_toBeSetup_item->sRBID = f1ap_ue_context_setup_req->srbs_to_be_setup[i].srb_id; - /* OPTIONAL */ - /* 11.1.2 duplicationIndication */ - asn1cCallocOne(srbs_toBeSetup_item->duplicationIndication, - F1AP_DuplicationIndication_true); // enum - } - } - - /* mandatory */ - /* c12. DRBs_ToBeSetup_List */ - if(f1ap_ue_context_setup_req->drbs_to_be_setup_length){ - asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextSetupRequestIEs_t, ie12); - ie12->id = F1AP_ProtocolIE_ID_id_DRBs_ToBeSetup_List; - ie12->criticality = F1AP_Criticality_reject; - ie12->value.present = F1AP_UEContextSetupRequestIEs__value_PR_DRBs_ToBeSetup_List; - - for (int i = 0; i < f1ap_ue_context_setup_req->drbs_to_be_setup_length; i++) { - const f1ap_drb_to_be_setup_t *drb = &f1ap_ue_context_setup_req->drbs_to_be_setup[i]; - asn1cSequenceAdd(ie12->value.choice.DRBs_ToBeSetup_List.list, F1AP_DRBs_ToBeSetup_ItemIEs_t, drbs_toBeSetup_item_ies); - drbs_toBeSetup_item_ies->id = F1AP_ProtocolIE_ID_id_DRBs_ToBeSetup_Item; - drbs_toBeSetup_item_ies->criticality = F1AP_Criticality_reject; - drbs_toBeSetup_item_ies->value.present = F1AP_DRBs_ToBeSetup_ItemIEs__value_PR_DRBs_ToBeSetup_Item; - /* 12.1 DRBs_ToBeSetup_Item */ - F1AP_DRBs_ToBeSetup_Item_t *drbs_toBeSetup_item=&drbs_toBeSetup_item_ies->value.choice.DRBs_ToBeSetup_Item; - /* 12.1.1 dRBID */ - drbs_toBeSetup_item->dRBID = drb->drb_id; - /* 12.1.2 qoSInformation */ - int some_decide_qos = 0; // BK: Need Check - - if (some_decide_qos) { - drbs_toBeSetup_item->qoSInformation.present = F1AP_QoSInformation_PR_eUTRANQoS; - /* 12.1.2.1 eUTRANQoS */ - asn1cCalloc(drbs_toBeSetup_item->qoSInformation.choice.eUTRANQoS, eUTRANQoS); - /* 12.1.2.1.1 qCI */ - eUTRANQoS->qCI = 254L; - /* 12.1.2.1.2 allocationAndRetentionPriority */ - { - /* 12.1.2.1.2.1 priorityLevel */ - eUTRANQoS->allocationAndRetentionPriority.priorityLevel = F1AP_PriorityLevel_highest; // enum - /* 12.1.2.1.2.2 pre_emptionCapability */ - eUTRANQoS->allocationAndRetentionPriority.pre_emptionCapability = F1AP_Pre_emptionCapability_may_trigger_pre_emption; // enum - /* 12.1.2.1.2.2 pre_emptionVulnerability */ - eUTRANQoS->allocationAndRetentionPriority.pre_emptionVulnerability = F1AP_Pre_emptionVulnerability_not_pre_emptable; // enum - } - - /* OPTIONAL */ - /* 12.1.2.1.3 gbrQosInformation */ - if (0) { - eUTRANQoS->gbrQosInformation = (F1AP_GBR_QosInformation_t *)calloc(1, sizeof(F1AP_GBR_QosInformation_t)); - asn_long2INTEGER(&eUTRANQoS->gbrQosInformation->e_RAB_MaximumBitrateDL, 1L); - asn_long2INTEGER(&eUTRANQoS->gbrQosInformation->e_RAB_MaximumBitrateUL, 1L); - asn_long2INTEGER(&eUTRANQoS->gbrQosInformation->e_RAB_GuaranteedBitrateDL, 1L); - asn_long2INTEGER(&eUTRANQoS->gbrQosInformation->e_RAB_GuaranteedBitrateUL, 1L); - } - } else { - /* 12.1.2 DRB_Information */ - const f1ap_drb_information_t *drb_info = &drb->drb_info; - drbs_toBeSetup_item->qoSInformation.present = F1AP_QoSInformation_PR_choice_extension; - F1AP_QoSInformation_ExtIEs_t *ie = (F1AP_QoSInformation_ExtIEs_t *)calloc(1, sizeof(*ie)); - ie->id = F1AP_ProtocolIE_ID_id_DRB_Information; - ie->criticality = F1AP_Criticality_reject; - ie->value.present = F1AP_QoSInformation_ExtIEs__value_PR_DRB_Information; - F1AP_DRB_Information_t *DRB_Information = &ie->value.choice.DRB_Information; - drbs_toBeSetup_item->qoSInformation.choice.choice_extension = (struct F1AP_ProtocolIE_SingleContainer *)ie; - - /* 12.1.2.1 dRB_QoS */ - f1ap_write_drb_qos_param(&drb_info->drb_qos, &DRB_Information->dRB_QoS); - - /* 12.1.2.2 sNSSAI */ - f1ap_write_drb_nssai(&drb->nssai, &DRB_Information->sNSSAI); - - /* OPTIONAL */ - /* 12.1.2.3 notificationControl */ - if (0) { - asn1cCallocOne(DRB_Information->notificationControl, - F1AP_NotificationControl_active); // enum - } - - /* 12.1.2.4 flows_Mapped_To_DRB_List */ // BK: need verifiy - f1ap_write_flows_mapped(drb_info->flows_mapped_to_drb, &DRB_Information->flows_Mapped_To_DRB_List, drb_info->flows_to_be_setup_length); - } // if some_decide_qos - - /* 12.1.3 uLUPTNLInformation_ToBeSetup_List */ - for (int j = 0; j < f1ap_ue_context_setup_req->drbs_to_be_setup[i].up_ul_tnl_length; j++) { - DevAssert(f1ap_ue_context_setup_req->drbs_to_be_setup[i].up_ul_tnl[j].teid > 0); - /* 12.3.1 ULTunnels_ToBeSetup_Item */ - asn1cSequenceAdd(drbs_toBeSetup_item->uLUPTNLInformation_ToBeSetup_List.list, - F1AP_ULUPTNLInformation_ToBeSetup_Item_t, uLUPTNLInformation_ToBeSetup_Item); - uLUPTNLInformation_ToBeSetup_Item->uLUPTNLInformation.present = F1AP_UPTransportLayerInformation_PR_gTPTunnel; - asn1cCalloc( uLUPTNLInformation_ToBeSetup_Item->uLUPTNLInformation.choice.gTPTunnel, - gTPTunnel); - /* 12.3.1.1.1 transportLayerAddress */ - TRANSPORT_LAYER_ADDRESS_IPv4_TO_BIT_STRING(f1ap_ue_context_setup_req->drbs_to_be_setup[i].up_ul_tnl[j].tl_address, - &gTPTunnel->transportLayerAddress); - /* 12.3.1.1.2 gTP_TEID */ - INT32_TO_OCTET_STRING(f1ap_ue_context_setup_req->drbs_to_be_setup[i].up_ul_tnl[j].teid, - &gTPTunnel->gTP_TEID); - } - - /* 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 F1AP_RLC_MODE_AM: - drbs_toBeSetup_item->rLCMode = F1AP_RLCMode_rlc_am; - break; - 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 */ - /* 12.1.5 ULConfiguration */ - if (0) { - asn1cCalloc(drbs_toBeSetup_item->uLConfiguration, tmp); - tmp->uLUEConfiguration = F1AP_ULUEConfiguration_no_data; - } - - /* OPTIONAL */ - /* 12.1.6 duplicationActivation */ - if (0) { - asn1cCalloc(drbs_toBeSetup_item->duplicationActivation, tmp); - *tmp = F1AP_DuplicationActivation_active; // enum - } - } - } - - /* OPTIONAL */ - /* InactivityMonitoringRequest */ - if (0) { - asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextSetupRequestIEs_t, ie12); - ie12->id = F1AP_ProtocolIE_ID_id_InactivityMonitoringRequest; - ie12->criticality = F1AP_Criticality_reject; - ie12->value.present = F1AP_UEContextSetupRequestIEs__value_PR_InactivityMonitoringRequest; - ie12->value.choice.InactivityMonitoringRequest = F1AP_InactivityMonitoringRequest_true; // 0 - } - - /* OPTIONAL */ - /* RAT_FrequencyPriorityInformation */ - if (0) { - asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextSetupRequestIEs_t, ie13); - ie13->id = F1AP_ProtocolIE_ID_id_RAT_FrequencyPriorityInformation; - ie13->criticality = F1AP_Criticality_reject; - ie13->value.present = F1AP_UEContextSetupRequestIEs__value_PR_RAT_FrequencyPriorityInformation; - int endc = 1; // RK: Get this from somewhere ... - - if (endc) { - ie13->value.choice.RAT_FrequencyPriorityInformation.present = F1AP_RAT_FrequencyPriorityInformation_PR_eNDC; - ie13->value.choice.RAT_FrequencyPriorityInformation.choice.eNDC = 11L; - } else { - ie13->value.choice.RAT_FrequencyPriorityInformation.present = F1AP_RAT_FrequencyPriorityInformation_PR_nGRAN; - ie13->value.choice.RAT_FrequencyPriorityInformation.choice.nGRAN = 11L; - } - } - - /* OPTIONAL */ - /* RRCContainer */ - if(f1ap_ue_context_setup_req->rrc_container_length > 0) { - asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextSetupRequestIEs_t, ie14); - ie14->id = F1AP_ProtocolIE_ID_id_RRCContainer; - ie14->criticality = F1AP_Criticality_ignore; - ie14->value.present = F1AP_UEContextSetupRequestIEs__value_PR_RRCContainer; - OCTET_STRING_fromBuf(&ie14->value.choice.RRCContainer, (const char *)f1ap_ue_context_setup_req->rrc_container, - f1ap_ue_context_setup_req->rrc_container_length); - } - - /* OPTIONAL */ - /* MaskedIMEISV */ - if (0) { - asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextSetupRequestIEs_t, ie15); - ie15->id = F1AP_ProtocolIE_ID_id_MaskedIMEISV; - ie15->criticality = F1AP_Criticality_reject; - ie15->value.present = F1AP_UEContextSetupRequestIEs__value_PR_MaskedIMEISV; - MaskedIMEISV_TO_BIT_STRING(12340000l, &ie15->value.choice.MaskedIMEISV); // size (64) - } - - /* encode */ - uint8_t *buffer=NULL; - uint32_t len=0; - - if (f1ap_encode_pdu(&pdu, &buffer, &len) < 0) { + uint8_t *buffer = NULL; + uint32_t len = 0; + if (f1ap_encode_pdu(pdu, &buffer, &len) < 0) { LOG_E(F1AP, "Failed to encode F1 UE CONTEXT SETUP REQUEST\n"); return -1; } + f1ap_itti_send_sctp_data_req(assoc_id, buffer, len); + ASN_STRUCT_FREE(asn_DEF_F1AP_F1AP_PDU, pdu); + #ifdef E2_AGENT - rrc_gNB_ue_context_t *ue_context_p = rrc_gNB_get_ue_context(RC.nrrrc[0], f1ap_ue_context_setup_req->gNB_CU_ue_id); + rrc_gNB_ue_context_t *ue_context_p = rrc_gNB_get_ue_context(RC.nrrrc[0], req->gNB_CU_ue_id); signal_ue_id(&ue_context_p->ue_context, F1_NETWORK_INTERFACE_TYPE, 0); #endif - // xer_fprint(stdout, &asn_DEF_F1AP_F1AP_PDU, (void *)pdu); - // asn_encode_to_new_buffer_result_t res = { NULL, {0, NULL, NULL} }; - // res = asn_encode_to_new_buffer(NULL, ATS_CANONICAL_XER, &asn_DEF_F1AP_F1AP_PDU, pdu); - // buffer = res.buffer; - // len = res.result.encoded; - // if (res.result.encoded <= 0) { - // LOG_E(F1AP, "ASN1 message encoding failed (%s, %lu)!\n", res.result.failed_type->name, res.result.encoded); - // return -1; - // } - LOG_D(F1AP,"F1AP UEContextSetupRequest Encoded %u bits\n", len); - f1ap_itti_send_sctp_data_req(assoc_id, buffer, len); return 0; } @@ -935,459 +389,19 @@ int CU_handle_UE_CONTEXT_RELEASE_COMPLETE(instance_t instance, sctp_assoc_t asso return 0; } -int CU_send_UE_CONTEXT_MODIFICATION_REQUEST(sctp_assoc_t assoc_id, f1ap_ue_context_modif_req_t *f1ap_ue_context_modification_req) +int CU_send_UE_CONTEXT_MODIFICATION_REQUEST(sctp_assoc_t assoc_id, const f1ap_ue_context_mod_req_t *req) { - F1AP_F1AP_PDU_t pdu= {0}; - F1AP_UEContextModificationRequest_t *out; + F1AP_F1AP_PDU_t *pdu = encode_ue_context_mod_req(req); + 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_UEContextModification; - tmp->criticality = F1AP_Criticality_reject; - tmp->value.present = F1AP_InitiatingMessage__value_PR_UEContextModificationRequest; - out = &tmp->value.choice.UEContextModificationRequest; - /* mandatory */ - /* c1. GNB_CU_UE_F1AP_ID */ - asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextModificationRequestIEs_t, ie1); - ie1->id = F1AP_ProtocolIE_ID_id_gNB_CU_UE_F1AP_ID; - ie1->criticality = F1AP_Criticality_reject; - ie1->value.present = F1AP_UEContextModificationRequestIEs__value_PR_GNB_CU_UE_F1AP_ID; - ie1->value.choice.GNB_CU_UE_F1AP_ID = f1ap_ue_context_modification_req->gNB_CU_ue_id; - /* mandatory */ - /* c2. GNB_DU_UE_F1AP_ID */ - asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextModificationRequestIEs_t, ie2); - ie2->id = F1AP_ProtocolIE_ID_id_gNB_DU_UE_F1AP_ID; - ie2->criticality = F1AP_Criticality_reject; - ie2->value.present = F1AP_UEContextModificationRequestIEs__value_PR_GNB_DU_UE_F1AP_ID; - ie2->value.choice.GNB_DU_UE_F1AP_ID = f1ap_ue_context_modification_req->gNB_DU_ue_id; - - /* optional */ - /* c3. NRCGI */ - if (true) { - asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextModificationRequestIEs_t, ie3); - ie3->id = F1AP_ProtocolIE_ID_id_SpCell_ID; - ie3->criticality = F1AP_Criticality_ignore; - ie3->value.present = F1AP_UEContextModificationRequestIEs__value_PR_NRCGI; - /* - nRCGI */ - - f1ap_served_cell_info_t nrcgi = { - .plmn = f1ap_ue_context_modification_req->plmn, - .nr_cellid = f1ap_ue_context_modification_req->nr_cellid, - }; - addnRCGI(ie3->value.choice.NRCGI, &nrcgi); - } - - /* optional */ - /* c4. ServCellIndex */ - if(0){ - asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextModificationRequestIEs_t, ie4); - ie4->id = F1AP_ProtocolIE_ID_id_ServCellIndex; - ie4->criticality = F1AP_Criticality_reject; - ie4->value.present = F1AP_UEContextModificationRequestIEs__value_PR_ServCellIndex; - ie4->value.choice.ServCellIndex = 5L; - } - - /* optional */ - /* c5. DRXCycle */ - if (0) { - asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextModificationRequestIEs_t, ie5); - ie5->id = F1AP_ProtocolIE_ID_id_DRXCycle; - ie5->criticality = F1AP_Criticality_ignore; - ie5->value.present = F1AP_UEContextModificationRequestIEs__value_PR_DRXCycle; - ie5->value.choice.DRXCycle.longDRXCycleLength = F1AP_LongDRXCycleLength_ms10; // enum - - if (0) { - asn1cCallocOne(ie5->value.choice.DRXCycle.shortDRXCycleLength, - F1AP_ShortDRXCycleLength_ms2); // enum - } - - if (0) { - asn1cCallocOne(ie5->value.choice.DRXCycle.shortDRXCycleTimer, 123L); - } - } - - /* optional */ - /* c6. CUtoDURRCInformation */ - if (f1ap_ue_context_modification_req->cu_to_du_rrc_information!=NULL) { - asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextModificationRequestIEs_t, ie6); - ie6->id = F1AP_ProtocolIE_ID_id_CUtoDURRCInformation; - ie6->criticality = F1AP_Criticality_reject; - ie6->value.present = F1AP_UEContextModificationRequestIEs__value_PR_CUtoDURRCInformation; - /* 6.1 cG_ConfigInfo */ - if(f1ap_ue_context_modification_req->cu_to_du_rrc_information->cG_ConfigInfo!=NULL){ - asn1cCalloc(ie6->value.choice.CUtoDURRCInformation.cG_ConfigInfo, cG_ConfigInfo); - OCTET_STRING_fromBuf(cG_ConfigInfo, (const char *)f1ap_ue_context_modification_req->cu_to_du_rrc_information->cG_ConfigInfo, - f1ap_ue_context_modification_req->cu_to_du_rrc_information->cG_ConfigInfo_length); - } - /* optional */ - /* 6.2 uE_CapabilityRAT_ContainerList */ - if(f1ap_ue_context_modification_req->cu_to_du_rrc_information->uE_CapabilityRAT_ContainerList!=NULL){ - asn1cCalloc(ie6->value.choice.CUtoDURRCInformation.uE_CapabilityRAT_ContainerList, uE_CapabilityRAT_ContainerList ); - OCTET_STRING_fromBuf(uE_CapabilityRAT_ContainerList, (const char *)f1ap_ue_context_modification_req->cu_to_du_rrc_information->uE_CapabilityRAT_ContainerList, - f1ap_ue_context_modification_req->cu_to_du_rrc_information->uE_CapabilityRAT_ContainerList_length) ; - } - /* optional */ - /* 6.3 measConfig */ - if(f1ap_ue_context_modification_req->cu_to_du_rrc_information->measConfig!=NULL){ - asn1cCalloc(ie6->value.choice.CUtoDURRCInformation.measConfig, measConfig); - OCTET_STRING_fromBuf(measConfig, (const char *)f1ap_ue_context_modification_req->cu_to_du_rrc_information->measConfig, - f1ap_ue_context_modification_req->cu_to_du_rrc_information->measConfig_length); - } - } - - /* optional */ - /* c7. TransmissionActionIndicator */ - if (f1ap_ue_context_modification_req->transm_action_ind != NULL) { - asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextModificationRequestIEs_t, ie7); - ie7->id = F1AP_ProtocolIE_ID_id_TransmissionActionIndicator; - ie7->criticality = F1AP_Criticality_ignore; - ie7->value.present = F1AP_UEContextModificationRequestIEs__value_PR_TransmissionActionIndicator; - ie7->value.choice.TransmissionActionIndicator = *f1ap_ue_context_modification_req->transm_action_ind; - // Stop is guaranteed to be 0, by restart might be different from 1 - static_assert((int)F1AP_TransmissionActionIndicator_restart == (int)TransmActionInd_RESTART, - "mismatch of ASN.1 and internal representation\n"); - } - - /* optional */ - /* c8. ResourceCoordinationTransferContainer */ - if (0) { - asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextModificationRequestIEs_t, ie8); - ie8->id = F1AP_ProtocolIE_ID_id_ResourceCoordinationTransferContainer; - ie8->criticality = F1AP_Criticality_ignore; - ie8->value.present = F1AP_UEContextModificationRequestIEs__value_PR_ResourceCoordinationTransferContainer; - OCTET_STRING_fromBuf(&ie8->value.choice.ResourceCoordinationTransferContainer, "asdsa1d32sa1d31asd31as", - strlen("asdsa1d32sa1d31asd31as")); - } - - /* optional */ - /* c7. RRCRconfigurationCompleteIndicator */ - if (f1ap_ue_context_modification_req->ReconfigComplOutcome == RRCreconf_success) { - asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextModificationRequestIEs_t, ie71); - ie71->id = F1AP_ProtocolIE_ID_id_RRCReconfigurationCompleteIndicator; - ie71->criticality = F1AP_Criticality_ignore; - ie71->value.present = F1AP_UEContextModificationRequestIEs__value_PR_RRCReconfigurationCompleteIndicator; - ie71->value.choice.RRCReconfigurationCompleteIndicator = F1AP_RRCReconfigurationCompleteIndicator_true; - } - - /* optional */ - /* c8. RRCContainer */ - if (f1ap_ue_context_modification_req->rrc_container != NULL) { - asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextModificationRequestIEs_t, ie81); - ie81->id = F1AP_ProtocolIE_ID_id_RRCContainer; - ie81->criticality = F1AP_Criticality_ignore; - ie81->value.present = F1AP_UEContextModificationRequestIEs__value_PR_RRCContainer; - OCTET_STRING_fromBuf(&ie81->value.choice.RRCContainer, (const char*)f1ap_ue_context_modification_req->rrc_container, - f1ap_ue_context_modification_req->rrc_container_length); - } - - /* optional */ - /* c9. SCell_ToBeSetupMod_List */ - if(0){ - asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextModificationRequestIEs_t, ie9); - ie9->id = F1AP_ProtocolIE_ID_id_SCell_ToBeSetupMod_List; - ie9->criticality = F1AP_Criticality_ignore; - ie9->value.present = F1AP_UEContextModificationRequestIEs__value_PR_SCell_ToBeSetupMod_List; - - for (int i=0; i<1; i++) { - // - asn1cSequenceAdd(ie9->value.choice.SCell_ToBeSetupMod_List.list, - F1AP_SCell_ToBeSetupMod_ItemIEs_t, scell_toBeSetupMod_item_ies); - scell_toBeSetupMod_item_ies->id = F1AP_ProtocolIE_ID_id_SCell_ToBeSetupMod_Item; - scell_toBeSetupMod_item_ies->criticality = F1AP_Criticality_ignore; - scell_toBeSetupMod_item_ies->value.present = F1AP_SCell_ToBeSetupMod_ItemIEs__value_PR_SCell_ToBeSetupMod_Item; - /* 8.1 SCell_ToBeSetup_Item */ - F1AP_SCell_ToBeSetupMod_Item_t *scell_toBeSetupMod_item= - &scell_toBeSetupMod_item_ies->value.choice.SCell_ToBeSetupMod_Item; - // /* - sCell_ID */ - f1ap_served_cell_info_t hardCoded = {0}; - addnRCGI(scell_toBeSetupMod_item->sCell_ID, &hardCoded); - /* sCellIndex */ - scell_toBeSetupMod_item->sCellIndex = 6; // issue here - } - } - - /* optional */ - /* c10. SCell_ToBeRemoved_List */ - if(0){ - asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextModificationRequestIEs_t, ie10); - ie10->id = F1AP_ProtocolIE_ID_id_SCell_ToBeRemoved_List; - ie10->criticality = F1AP_Criticality_ignore; - ie10->value.present = F1AP_UEContextModificationRequestIEs__value_PR_SCell_ToBeRemoved_List; - - for (int i=0; i<1; i++) { - // - asn1cSequenceAdd(ie10->value.choice.SCell_ToBeRemoved_List.list, - F1AP_SCell_ToBeRemoved_ItemIEs_t, scell_toBeRemoved_item_ies); - scell_toBeRemoved_item_ies = (F1AP_SCell_ToBeRemoved_ItemIEs_t *)calloc(1, sizeof(F1AP_SCell_ToBeRemoved_ItemIEs_t)); - //memset((void *)&scell_toBeRemoved_item_ies, 0, sizeof(F1AP_SCell_ToBeRemoved_ItemIEs_t)); - scell_toBeRemoved_item_ies->id = F1AP_ProtocolIE_ID_id_SCell_ToBeRemoved_Item; - scell_toBeRemoved_item_ies->criticality = F1AP_Criticality_ignore; - scell_toBeRemoved_item_ies->value.present = F1AP_SCell_ToBeRemoved_ItemIEs__value_PR_SCell_ToBeRemoved_Item; - /* 10.1 SCell_ToBeRemoved_Item */ - F1AP_SCell_ToBeRemoved_Item_t *scell_toBeRemoved_item= - &scell_toBeRemoved_item_ies->value.choice.SCell_ToBeRemoved_Item; - /* - sCell_ID */ - f1ap_served_cell_info_t hardCoded = {0}; - addnRCGI(scell_toBeRemoved_item->sCell_ID, &hardCoded); - } - } - - /* mandatory */ - /* c11. SRBs_ToBeSetupMod_List */ - if(f1ap_ue_context_modification_req->srbs_to_be_setup_length > 0){ - asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextModificationRequestIEs_t, ie11); - ie11->id = F1AP_ProtocolIE_ID_id_SRBs_ToBeSetupMod_List; - ie11->criticality = F1AP_Criticality_reject; - ie11->value.present = F1AP_UEContextModificationRequestIEs__value_PR_SRBs_ToBeSetupMod_List; - - for (int i=0; isrbs_to_be_setup_length; i++) { - // - asn1cSequenceAdd(ie11->value.choice.SRBs_ToBeSetupMod_List, F1AP_SRBs_ToBeSetupMod_ItemIEs_t, srbs_toBeSetupMod_item_ies); - srbs_toBeSetupMod_item_ies->id = F1AP_ProtocolIE_ID_id_SRBs_ToBeSetupMod_Item; // 73 - srbs_toBeSetupMod_item_ies->criticality = F1AP_Criticality_reject; - srbs_toBeSetupMod_item_ies->value.present = F1AP_SRBs_ToBeSetupMod_ItemIEs__value_PR_SRBs_ToBeSetupMod_Item; - /* 11.1 SRBs_ToBeSetup_Item */ - F1AP_SRBs_ToBeSetupMod_Item_t *srbs_toBeSetupMod_item=&srbs_toBeSetupMod_item_ies->value.choice.SRBs_ToBeSetupMod_Item; - /* 11.1.1 sRBID */ - srbs_toBeSetupMod_item->sRBID = f1ap_ue_context_modification_req->srbs_to_be_setup[i].srb_id; - /* OPTIONAL */ - /* 11.1.2 duplicationIndication */ - asn1cCallocOne(srbs_toBeSetupMod_item->duplicationIndication, - F1AP_DuplicationIndication_true); // enum - } - } - - /* mandatory */ - /* c12. DRBs_ToBeSetupMod_List */ - if(f1ap_ue_context_modification_req->drbs_to_be_setup_length){ - asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextModificationRequestIEs_t, ie12); - ie12->id = F1AP_ProtocolIE_ID_id_DRBs_ToBeSetupMod_List; - ie12->criticality = F1AP_Criticality_reject; - ie12->value.present = F1AP_UEContextModificationRequestIEs__value_PR_DRBs_ToBeSetupMod_List; - - for (int i = 0; i < f1ap_ue_context_modification_req->drbs_to_be_setup_length; i++) { - const f1ap_drb_to_be_setup_t *drb = &f1ap_ue_context_modification_req->drbs_to_be_setup[i]; - asn1cSequenceAdd(ie12->value.choice.DRBs_ToBeSetupMod_List.list, - F1AP_DRBs_ToBeSetupMod_ItemIEs_t, drbs_toBeSetupMod_item_ies); - drbs_toBeSetupMod_item_ies->id = F1AP_ProtocolIE_ID_id_DRBs_ToBeSetupMod_Item; - drbs_toBeSetupMod_item_ies->criticality = F1AP_Criticality_reject; - drbs_toBeSetupMod_item_ies->value.present = F1AP_DRBs_ToBeSetupMod_ItemIEs__value_PR_DRBs_ToBeSetupMod_Item; - /* 12.1 DRBs_ToBeSetupMod_Item */ - F1AP_DRBs_ToBeSetupMod_Item_t *drbs_toBeSetupMod_item= - &drbs_toBeSetupMod_item_ies->value.choice.DRBs_ToBeSetupMod_Item; - /* dRBID */ - drbs_toBeSetupMod_item->dRBID = drb->drb_id; - /* qoSInformation */ - - if(f1ap_ue_context_modification_req->QoS_information_type == EUTRAN_QoS){ - drbs_toBeSetupMod_item->qoSInformation.present = F1AP_QoSInformation_PR_eUTRANQoS; - drbs_toBeSetupMod_item->qoSInformation.choice.eUTRANQoS = (F1AP_EUTRANQoS_t *)calloc(1, sizeof(F1AP_EUTRANQoS_t)); - drbs_toBeSetupMod_item->qoSInformation.choice.eUTRANQoS->qCI = 253L; - /* uLUPTNLInformation_ToBeSetup_List */ - int maxnoofULTunnels = 1; // 2; - - for (int j=0; juLUPTNLInformation_ToBeSetup_List.list, - F1AP_ULUPTNLInformation_ToBeSetup_Item_t, uLUPTNLInformation_ToBeSetup_Item); - uLUPTNLInformation_ToBeSetup_Item->uLUPTNLInformation.present = F1AP_UPTransportLayerInformation_PR_gTPTunnel; - asn1cCalloc(uLUPTNLInformation_ToBeSetup_Item->uLUPTNLInformation.choice.gTPTunnel, - gTPTunnel); - /* transportLayerAddress */ - TRANSPORT_LAYER_ADDRESS_IPv4_TO_BIT_STRING(1234, &gTPTunnel->transportLayerAddress); - /* gTP_TEID */ - OCTET_STRING_fromBuf(&gTPTunnel->gTP_TEID, "4567", - strlen("4567")); - } - - /* rLCMode */ - drbs_toBeSetupMod_item->rLCMode = F1AP_RLCMode_rlc_um_bidirectional; // enum - - /* OPTIONAL */ - /* ULConfiguration */ - if (0) { - drbs_toBeSetupMod_item->uLConfiguration = (F1AP_ULConfiguration_t *)calloc(1, sizeof(F1AP_ULConfiguration_t)); - } - } //QoS information - - else{ - /* 12.1.2 DRB_Information */ - f1ap_drb_information_t *drb_info_in = &f1ap_ue_context_modification_req->drbs_to_be_setup[i].drb_info; - drbs_toBeSetupMod_item->qoSInformation.present = F1AP_QoSInformation_PR_choice_extension; - F1AP_QoSInformation_ExtIEs_t *ie = (F1AP_QoSInformation_ExtIEs_t *)calloc(1, sizeof(*ie)); - ie->id = F1AP_ProtocolIE_ID_id_DRB_Information; - ie->criticality = F1AP_Criticality_reject; - ie->value.present = F1AP_QoSInformation_ExtIEs__value_PR_DRB_Information; - F1AP_DRB_Information_t *DRB_Information = &ie->value.choice.DRB_Information; - drbs_toBeSetupMod_item->qoSInformation.choice.choice_extension = (struct F1AP_ProtocolIE_SingleContainer *)ie; - - /* 12.1.2.1 dRB_QoS */ - f1ap_write_drb_qos_param(&drb_info_in->drb_qos, &DRB_Information->dRB_QoS); - - /* 12.1.2.2 sNSSAI */ - f1ap_write_drb_nssai(&drb->nssai, &DRB_Information->sNSSAI); - - /* OPTIONAL */ - /* 12.1.2.3 notificationControl */ - if (0) { - asn1cCallocOne(DRB_Information->notificationControl, - F1AP_NotificationControl_active); // enum - } - - /* 12.1.2.4 flows_Mapped_To_DRB_List */ - f1ap_write_flows_mapped(drb_info_in->flows_mapped_to_drb, &DRB_Information->flows_Mapped_To_DRB_List, drb_info_in->flows_to_be_setup_length); - - } //QoS information - - /* 12.1.3 uLUPTNLInformation_ToBeSetup_List */ - for (int j = 0; j < f1ap_ue_context_modification_req->drbs_to_be_setup[i].up_ul_tnl_length; j++) { - /* Use a dummy address and teid for the outgoing GTP-U tunnel (DU) which will be updated once we get the UE context modification response from the DU */ - asn1cSequenceAdd(drbs_toBeSetupMod_item->uLUPTNLInformation_ToBeSetup_List.list, - F1AP_ULUPTNLInformation_ToBeSetup_Item_t, uLUPTNLInformation_ToBeSetup_Item); - uLUPTNLInformation_ToBeSetup_Item->uLUPTNLInformation.present = F1AP_UPTransportLayerInformation_PR_gTPTunnel; - asn1cCalloc( uLUPTNLInformation_ToBeSetup_Item->uLUPTNLInformation.choice.gTPTunnel, - gTPTunnel); - /* 12.3.1.1.1 transportLayerAddress */ - TRANSPORT_LAYER_ADDRESS_IPv4_TO_BIT_STRING(f1ap_ue_context_modification_req->drbs_to_be_setup[i].up_ul_tnl[j].tl_address, - &gTPTunnel->transportLayerAddress); - /* 12.3.1.1.2 gTP_TEID */ - INT32_TO_OCTET_STRING(f1ap_ue_context_modification_req->drbs_to_be_setup[i].up_ul_tnl[j].teid, - &gTPTunnel->gTP_TEID); - } - /* 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 F1AP_RLC_MODE_AM: - drbs_toBeSetupMod_item->rLCMode = F1AP_RLCMode_rlc_am; - break; - 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 */ - /* 12.1.5 ULConfiguration */ - if (0) { - asn1cCalloc(drbs_toBeSetupMod_item->uLConfiguration, tmp); - tmp->uLUEConfiguration = F1AP_ULUEConfiguration_no_data; - } - - /* OPTIONAL */ - /* 12.1.6 duplicationActivation */ - if (0) { - asn1cCalloc(drbs_toBeSetupMod_item->duplicationActivation, tmp); - *tmp = F1AP_DuplicationActivation_active; // enum - } - } - } - - /* optional */ - if(0){ - /* c13. DRBs_ToBeModified_List */ - asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextModificationRequestIEs_t, ie13); - ie13->id = F1AP_ProtocolIE_ID_id_DRBs_ToBeModified_List; - ie13->criticality = F1AP_Criticality_reject; - ie13->value.present = F1AP_UEContextModificationRequestIEs__value_PR_DRBs_ToBeModified_List; - - for (int i=0; i<1; i++) { - // - asn1cSequenceAdd( ie13->value.choice.DRBs_ToBeModified_List.list, - F1AP_DRBs_ToBeModified_ItemIEs_t, drbs_toBeModified_item_ies); - drbs_toBeModified_item_ies->id = F1AP_ProtocolIE_ID_id_DRBs_ToBeModified_Item; - drbs_toBeModified_item_ies->criticality = F1AP_Criticality_reject; - drbs_toBeModified_item_ies->value.present = F1AP_DRBs_ToBeModified_ItemIEs__value_PR_DRBs_ToBeModified_Item; - /* 13.1 SRBs_ToBeModified_Item */ - F1AP_DRBs_ToBeModified_Item_t *drbs_toBeModified_item= - &drbs_toBeModified_item_ies->value.choice.DRBs_ToBeModified_Item; - /* dRBID */ - drbs_toBeModified_item->dRBID = 30L; - /* qoSInformation */ - asn1cCalloc(drbs_toBeModified_item->qoSInformation, tmp); - tmp->present = F1AP_QoSInformation_PR_eUTRANQoS; - tmp->choice.eUTRANQoS = (F1AP_EUTRANQoS_t *)calloc(1, sizeof(F1AP_EUTRANQoS_t)); - tmp->choice.eUTRANQoS->qCI = 254L; - /* ULTunnels_ToBeModified_List */ - int maxnoofULTunnels = 1; // 2; - - for (int j=0; juLUPTNLInformation_ToBeSetup_List.list, - F1AP_ULUPTNLInformation_ToBeSetup_Item_t, uLUPTNLInformation_ToBeSetup_Item); - uLUPTNLInformation_ToBeSetup_Item->uLUPTNLInformation.present = F1AP_UPTransportLayerInformation_PR_gTPTunnel; - asn1cCalloc(uLUPTNLInformation_ToBeSetup_Item->uLUPTNLInformation.choice.gTPTunnel, - gTPTunnel); - TRANSPORT_LAYER_ADDRESS_IPv4_TO_BIT_STRING(1234, &gTPTunnel->transportLayerAddress); - OCTET_STRING_fromBuf(&gTPTunnel->gTP_TEID, "1204", - strlen("1204")); - } - - /* OPTIONAL */ - /* ULConfiguration */ - if (0) { - drbs_toBeModified_item->uLConfiguration = (F1AP_ULConfiguration_t *)calloc(1, sizeof(F1AP_ULConfiguration_t)); - } - } - } - - /* optional */ - if(0){ - /* c14. SRBs_ToBeReleased_List */ - asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextModificationRequestIEs_t, ie14); - ie14->id = F1AP_ProtocolIE_ID_id_SRBs_ToBeReleased_List; - ie14->criticality = F1AP_Criticality_reject; - ie14->value.present = F1AP_UEContextModificationRequestIEs__value_PR_SRBs_ToBeReleased_List; - - for (int i=0; i<1; i++) { - // - asn1cSequenceAdd(ie14->value.choice.SRBs_ToBeReleased_List.list, - F1AP_SRBs_ToBeReleased_ItemIEs_t, srbs_toBeReleased_item_ies); - srbs_toBeReleased_item_ies->id = F1AP_ProtocolIE_ID_id_SRBs_ToBeReleased_Item; - srbs_toBeReleased_item_ies->criticality = F1AP_Criticality_ignore; - srbs_toBeReleased_item_ies->value.present = F1AP_SRBs_ToBeReleased_ItemIEs__value_PR_SRBs_ToBeReleased_Item; - /* 9.1 SRBs_ToBeReleased_Item */ - F1AP_SRBs_ToBeReleased_Item_t *srbs_toBeReleased_item= - &srbs_toBeReleased_item_ies->value.choice.SRBs_ToBeReleased_Item; - /* - sRBID */ - srbs_toBeReleased_item->sRBID = 2L; - } - } - - /* optional */ - if (f1ap_ue_context_modification_req->drbs_to_be_released_length > 0) { - /* c15. DRBs_ToBeReleased_List */ - asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextModificationRequestIEs_t, ie15); - ie15->id = F1AP_ProtocolIE_ID_id_DRBs_ToBeReleased_List; - ie15->criticality = F1AP_Criticality_reject; - ie15->value.present = F1AP_UEContextModificationRequestIEs__value_PR_DRBs_ToBeReleased_List; - - for (int i = 0; i < f1ap_ue_context_modification_req->drbs_to_be_released_length; i++) { - // - asn1cSequenceAdd(ie15->value.choice.DRBs_ToBeReleased_List.list, - F1AP_DRBs_ToBeReleased_ItemIEs_t, drbs_toBeReleased_item_ies); - drbs_toBeReleased_item_ies->id = F1AP_ProtocolIE_ID_id_DRBs_ToBeReleased_Item; - drbs_toBeReleased_item_ies->criticality = F1AP_Criticality_reject; - drbs_toBeReleased_item_ies->value.present = F1AP_DRBs_ToBeReleased_ItemIEs__value_PR_DRBs_ToBeReleased_Item; - /* 14.1 SRBs_ToBeReleased_Item */ - F1AP_DRBs_ToBeReleased_Item_t *drbs_toBeReleased_item= - &drbs_toBeReleased_item_ies->value.choice.DRBs_ToBeReleased_Item; - /* dRBID */ - drbs_toBeReleased_item->dRBID = f1ap_ue_context_modification_req->drbs_to_be_released[i].rb_id; - } - } - - /* encode */ - if (f1ap_encode_pdu(&pdu, &buffer, &len) < 0) { - LOG_E(F1AP, "Failed to encode F1 UE CONTEXT_MODIFICATION REQUEST\n"); + if (f1ap_encode_pdu(pdu, &buffer, &len) < 0) { + LOG_E(F1AP, "Failed to encode F1 UE Context Modification Request\n"); return -1; } + f1ap_itti_send_sctp_data_req(assoc_id, buffer, len); + ASN_STRUCT_FREE(asn_DEF_F1AP_F1AP_PDU, pdu); return 0; } diff --git a/openair2/F1AP/f1ap_cu_ue_context_management.h b/openair2/F1AP/f1ap_cu_ue_context_management.h index 05e67930b3..ed76189c19 100644 --- a/openair2/F1AP/f1ap_cu_ue_context_management.h +++ b/openair2/F1AP/f1ap_cu_ue_context_management.h @@ -36,8 +36,7 @@ /* * UE Context Setup */ -int CU_send_UE_CONTEXT_SETUP_REQUEST(sctp_assoc_t assoc_id, - f1ap_ue_context_setup_t *f1ap_ue_context_setup_req); +int CU_send_UE_CONTEXT_SETUP_REQUEST(sctp_assoc_t assoc_id, const f1ap_ue_context_setup_req_t *req); int CU_handle_UE_CONTEXT_SETUP_RESPONSE(instance_t instance, sctp_assoc_t assoc_id, uint32_t stream, F1AP_F1AP_PDU_t *pdu); @@ -59,7 +58,7 @@ int CU_handle_UE_CONTEXT_RELEASE_COMPLETE(instance_t instance, sctp_assoc_t asso /* * UE Context Modification (gNB-CU initiated) */ -int CU_send_UE_CONTEXT_MODIFICATION_REQUEST(sctp_assoc_t assoc_id, f1ap_ue_context_modif_req_t *f1ap_ue_context_modification_req); +int CU_send_UE_CONTEXT_MODIFICATION_REQUEST(sctp_assoc_t assoc_id, const f1ap_ue_context_mod_req_t *req); int CU_handle_UE_CONTEXT_MODIFICATION_RESPONSE(instance_t instance, sctp_assoc_t assoc_id, uint32_t stream, F1AP_F1AP_PDU_t *pdu); int CU_handle_UE_CONTEXT_MODIFICATION_FAILURE(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 c231561eec..cd76933d44 100644 --- a/openair2/F1AP/f1ap_du_task.c +++ b/openair2/F1AP/f1ap_du_task.c @@ -36,6 +36,7 @@ #include "f1ap_du_rrc_message_transfer.h" #include "lib/f1ap_rrc_message_transfer.h" #include "lib/f1ap_interface_management.h" +#include "lib/f1ap_ue_context.h" #include "f1ap_du_task.h" #include diff --git a/openair2/F1AP/f1ap_du_ue_context_management.c b/openair2/F1AP/f1ap_du_ue_context_management.c index cd9b2865c9..13c9e92ec5 100644 --- a/openair2/F1AP/f1ap_du_ue_context_management.c +++ b/openair2/F1AP/f1ap_du_ue_context_management.c @@ -34,295 +34,24 @@ #include "f1ap_encoder.h" #include "f1ap_itti_messaging.h" #include "f1ap_du_ue_context_management.h" +#include "lib/f1ap_ue_context.h" #include "openair2/LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.h" #include "openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h" #include "openair2/LAYER2/nr_pdcp/nr_pdcp_oai_api.h" -static void f1ap_read_drb_qos_param(const F1AP_QoSFlowLevelQoSParameters_t *asn1_qos, f1ap_qos_flow_level_qos_parameters_t *drb_qos) -{ - f1ap_qos_characteristics_t *drb_qos_char = &drb_qos->qos_characteristics; - 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->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->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; - drb_qos_char->dynamic.packet_delay_budget = dRB_QoS_Char->choice.dynamic_5QI->packetDelayBudget; - drb_qos_char->dynamic.packet_error_rate.per_scalar = dRB_QoS_Char->choice.dynamic_5QI->packetErrorRate.pER_Scalar; - drb_qos_char->dynamic.packet_error_rate.per_exponent = dRB_QoS_Char->choice.dynamic_5QI->packetErrorRate.pER_Exponent; - } - - /* nGRANallocationRetentionPriority */ - drb_qos->alloc_reten_priority.priority_level = asn1_qos->nGRANallocationRetentionPriority.priorityLevel; - drb_qos->alloc_reten_priority.preemption_vulnerability = asn1_qos->nGRANallocationRetentionPriority.pre_emptionVulnerability; - drb_qos->alloc_reten_priority.preemption_capability = asn1_qos->nGRANallocationRetentionPriority.pre_emptionVulnerability; -} - -static void f1ap_read_flows_mapped(const F1AP_Flows_Mapped_To_DRB_List_t *asn1_flows_mapped, f1ap_flows_mapped_to_drb_t *flows_mapped, int n) -{ - for (int k = 0; k < n; k++) { - f1ap_flows_mapped_to_drb_t *flows_mapped_to_drb = flows_mapped + k; - const F1AP_Flows_Mapped_To_DRB_Item_t *flows_Mapped_To_Drb = asn1_flows_mapped->list.array[0] + k; - - flows_mapped_to_drb->qfi = flows_Mapped_To_Drb->qoSFlowIdentifier; - - /* QoS-Flow-Level-QoS-Parameters */ - { - f1ap_qos_flow_level_qos_parameters_t *flow_qos = &flows_mapped_to_drb->qos_params; - const F1AP_QoSFlowLevelQoSParameters_t *Flow_QoS = &flows_Mapped_To_Drb->qoSFlowLevelQoSParameters; - - /* QoS Characteristics*/ - f1ap_qos_characteristics_t *flow_qos_char = &flow_qos->qos_characteristics; - 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->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->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; - flow_qos_char->dynamic.packet_delay_budget = Flow_QoS_Char->choice.dynamic_5QI->packetDelayBudget; - flow_qos_char->dynamic.packet_error_rate.per_scalar = Flow_QoS_Char->choice.dynamic_5QI->packetErrorRate.pER_Scalar; - flow_qos_char->dynamic.packet_error_rate.per_exponent = Flow_QoS_Char->choice.dynamic_5QI->packetErrorRate.pER_Exponent; - } - - /* nGRANallocationRetentionPriority */ - flow_qos->alloc_reten_priority.priority_level = Flow_QoS->nGRANallocationRetentionPriority.priorityLevel; - flow_qos->alloc_reten_priority.preemption_vulnerability = Flow_QoS->nGRANallocationRetentionPriority.pre_emptionVulnerability; - flow_qos->alloc_reten_priority.preemption_capability = Flow_QoS->nGRANallocationRetentionPriority.pre_emptionVulnerability; - } - } -} - -static void f1ap_read_drb_nssai(const F1AP_SNSSAI_t *asn1_nssai, nssai_t *nssai) -{ - OCTET_STRING_TO_INT8(&asn1_nssai->sST, nssai->sst); - nssai->sd = 0xffffff; - if (asn1_nssai->sD != NULL) { - BUFFER_TO_INT24(asn1_nssai->sD->buf, nssai->sd); - } -} - int DU_handle_UE_CONTEXT_SETUP_REQUEST(instance_t instance, sctp_assoc_t assoc_id, uint32_t stream, F1AP_F1AP_PDU_t *pdu) { - F1AP_UEContextSetupRequest_t *container; - int i; - DevAssert(pdu); - f1ap_ue_context_setup_t ue_context_setup = {0}; - f1ap_ue_context_setup_t *f1ap_ue_context_setup_req = &ue_context_setup; - container = &pdu->choice.initiatingMessage->value.choice.UEContextSetupRequest; - /* GNB_CU_UE_F1AP_ID */ - F1AP_UEContextSetupRequestIEs_t *ieCU; - F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_UEContextSetupRequestIEs_t, ieCU, container, - F1AP_ProtocolIE_ID_id_gNB_CU_UE_F1AP_ID, true); - f1ap_ue_context_setup_req->gNB_CU_ue_id = ieCU->value.choice.GNB_CU_UE_F1AP_ID; - /* optional */ - /* GNB_DU_UE_F1AP_ID */ - F1AP_UEContextSetupRequestIEs_t *ieDU_UE; - F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_UEContextSetupRequestIEs_t, ieDU_UE, container, - F1AP_ProtocolIE_ID_id_gNB_DU_UE_F1AP_ID, false); - // this should be optional. At present, the DU uses the RNTI, and hence, this - // value cannot exceed 0xffff (or something below, whatever is a valid - // C-RNTI). So we use a value > 0xffff to mark optionality - f1ap_ue_context_setup_req->gNB_DU_ue_id = -1; // 0xffffffff - if (ieDU_UE != NULL) - f1ap_ue_context_setup_req->gNB_DU_ue_id = ieDU_UE->value.choice.GNB_DU_UE_F1AP_ID; - - /* SpCell_ID */ - F1AP_UEContextSetupRequestIEs_t *ieNet; - F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_UEContextSetupRequestIEs_t, ieNet, container, - F1AP_ProtocolIE_ID_id_SpCell_ID, true); - PLMNID_TO_MCC_MNC(&ieNet->value.choice.NRCGI.pLMN_Identity, - f1ap_ue_context_setup_req->plmn.mcc, - f1ap_ue_context_setup_req->plmn.mnc, - f1ap_ue_context_setup_req->plmn.mnc_digit_length); - BIT_STRING_TO_NR_CELL_IDENTITY(&ieNet->value.choice.NRCGI.nRCellIdentity, f1ap_ue_context_setup_req->nr_cellid); - /* ServCellIndex */ - F1AP_UEContextSetupRequestIEs_t *ieCell; - F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_UEContextSetupRequestIEs_t, ieCell, container, - F1AP_ProtocolIE_ID_id_ServCellIndex, true); - f1ap_ue_context_setup_req->servCellIndex = ieCell->value.choice.ServCellIndex; - /* optional */ - /* CellULConfigured */ - F1AP_UEContextSetupRequestIEs_t *ieULCell; - F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_UEContextSetupRequestIEs_t, ieULCell, container, - F1AP_ProtocolIE_ID_id_SpCellULConfigured, false); // SpCellULConfigured - - if (ieULCell) { - /* correct here */ - f1ap_ue_context_setup_req->cellULConfigured = malloc(sizeof(uint32_t)); - - if (f1ap_ue_context_setup_req->cellULConfigured) - *f1ap_ue_context_setup_req->cellULConfigured = ieULCell->value.choice.CellULConfigured; - } else { - f1ap_ue_context_setup_req->cellULConfigured = NULL; + f1ap_ue_context_setup_req_t req = {0}; + if (!decode_ue_context_setup_req(pdu, &req)) { + LOG_E(F1AP, "cannot decode F1 UE Context Setup Request\n"); + free_ue_context_setup_req(&req); + return -1; } - F1AP_UEContextSetupRequestIEs_t *ieCuRrcInfo; - F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_UEContextSetupRequestIEs_t, ieCuRrcInfo, container, - F1AP_ProtocolIE_ID_id_CUtoDURRCInformation, false); - if(ieCuRrcInfo!=NULL){ - f1ap_ue_context_setup_req->cu_to_du_rrc_information = (cu_to_du_rrc_information_t *)calloc(1,sizeof(cu_to_du_rrc_information_t)); - cu_to_du_rrc_information_t *cu2du = f1ap_ue_context_setup_req->cu_to_du_rrc_information; - const F1AP_CUtoDURRCInformation_t *cu2duie = &ieCuRrcInfo->value.choice.CUtoDURRCInformation; - if (cu2duie->cG_ConfigInfo != NULL) { - cu2du->cG_ConfigInfo = malloc_or_fail(cu2duie->cG_ConfigInfo->size); - cu2du->cG_ConfigInfo_length = cu2duie->cG_ConfigInfo->size; - memcpy(cu2du->cG_ConfigInfo, cu2duie->cG_ConfigInfo->buf, cu2du->cG_ConfigInfo_length); - } - if(cu2duie->uE_CapabilityRAT_ContainerList!=NULL){ - cu2du->uE_CapabilityRAT_ContainerList = calloc(1, cu2duie->uE_CapabilityRAT_ContainerList->size); - memcpy(cu2du->uE_CapabilityRAT_ContainerList, - cu2duie->uE_CapabilityRAT_ContainerList->buf, - cu2duie->uE_CapabilityRAT_ContainerList->size); - cu2du->uE_CapabilityRAT_ContainerList_length = cu2duie->uE_CapabilityRAT_ContainerList->size; - LOG_D(F1AP, "Size f1ap_ue_context_setup_req->cu_to_du_rrc_information->uE_CapabilityRAT_ContainerList_length: %d \n", f1ap_ue_context_setup_req->cu_to_du_rrc_information->uE_CapabilityRAT_ContainerList_length); - } - if (cu2duie->iE_Extensions != NULL) { - const F1AP_ProtocolExtensionContainer_10696P60_t *ext = (const F1AP_ProtocolExtensionContainer_10696P60_t *)cu2duie->iE_Extensions; - for (int i = 0; i < ext->list.count; ++i) { - const F1AP_CUtoDURRCInformation_ExtIEs_t *cu2du_info = ext->list.array[i]; - switch (cu2du_info->id) { - case F1AP_ProtocolIE_ID_id_HandoverPreparationInformation: - DevAssert(cu2du_info->extensionValue.present == F1AP_CUtoDURRCInformation_ExtIEs__extensionValue_PR_HandoverPreparationInformation); - const F1AP_HandoverPreparationInformation_t *hopi = &cu2du_info->extensionValue.choice.MeasurementTimingConfiguration; - cu2du->handoverPreparationInfo = calloc_or_fail(1, hopi->size); - memcpy(cu2du->handoverPreparationInfo, hopi->buf, hopi->size); - cu2du->handoverPreparationInfo_length = hopi->size; - break; - default: - LOG_W(F1AP, "unsupported CUtoDURRCInformation_ExtIE %ld encountered, ignoring\n", cu2du_info->id); - break; - } - } - } - } + ue_context_setup_request(&req); + free_ue_context_setup_req(&req); - /* DRB */ - F1AP_UEContextSetupRequestIEs_t *ieDrb; - F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_UEContextSetupRequestIEs_t, ieDrb, container, - F1AP_ProtocolIE_ID_id_DRBs_ToBeSetup_List, false); - - if(ieDrb!=NULL) { - f1ap_ue_context_setup_req->drbs_to_be_setup_length = ieDrb->value.choice.DRBs_ToBeSetup_List.list.count; - f1ap_ue_context_setup_req->drbs_to_be_setup = calloc(f1ap_ue_context_setup_req->drbs_to_be_setup_length, - sizeof(f1ap_drb_to_be_setup_t)); - AssertFatal(f1ap_ue_context_setup_req->drbs_to_be_setup, - "could not allocate memory for f1ap_ue_context_setup_req->drbs_to_be_setup\n"); - - for (i = 0; i < f1ap_ue_context_setup_req->drbs_to_be_setup_length; ++i) { - f1ap_drb_to_be_setup_t *drb_p = &f1ap_ue_context_setup_req->drbs_to_be_setup[i]; - F1AP_DRBs_ToBeSetup_Item_t *drbs_tobesetup_item_p = - &((F1AP_DRBs_ToBeSetup_ItemIEs_t *)ieDrb->value.choice.DRBs_ToBeSetup_List.list.array[i])->value.choice.DRBs_ToBeSetup_Item; - drb_p->drb_id = drbs_tobesetup_item_p->dRBID; - /* TODO in the following, assume only one UP UL TNL is present. - * this matches/assumes OAI CU implementation, can be up to 2! */ - drb_p->up_ul_tnl_length = 1; - AssertFatal(drbs_tobesetup_item_p->uLUPTNLInformation_ToBeSetup_List.list.count > 0, - "no UL UP TNL Information in DRBs to be Setup list\n"); - F1AP_ULUPTNLInformation_ToBeSetup_Item_t *ul_up_tnl_info_p = (F1AP_ULUPTNLInformation_ToBeSetup_Item_t *)drbs_tobesetup_item_p->uLUPTNLInformation_ToBeSetup_List.list.array[0]; - F1AP_GTPTunnel_t *ul_up_tnl0 = ul_up_tnl_info_p->uLUPTNLInformation.choice.gTPTunnel; - BIT_STRING_TO_TRANSPORT_LAYER_ADDRESS_IPv4(&ul_up_tnl0->transportLayerAddress, drb_p->up_ul_tnl[0].tl_address); - OCTET_STRING_TO_UINT32(&ul_up_tnl0->gTP_TEID, drb_p->up_ul_tnl[0].teid); - // 3GPP assumes GTP-U is on port 2152, but OAI is configurable - drb_p->up_ul_tnl[0].port = getCxt(instance)->net_config.CUport; - - switch (drbs_tobesetup_item_p->rLCMode) { - 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_tobesetup_item_p->rLCMode); - drb_p->rlc_mode = F1AP_RLC_MODE_UM_BIDIR; - break; - } - - if (drbs_tobesetup_item_p->qoSInformation.present == F1AP_QoSInformation_PR_eUTRANQoS) { - AssertFatal(false, "Decode of eUTRANQoS is not implemented yet"); - } // EUTRAN QoS Information - else { - /* 12.1.2 DRB_Information */ - if (drbs_tobesetup_item_p->qoSInformation.present == F1AP_QoSInformation_PR_choice_extension) { - F1AP_QoSInformation_ExtIEs_t *ie = - (F1AP_QoSInformation_ExtIEs_t *)drbs_tobesetup_item_p->qoSInformation.choice.choice_extension; - if (ie->id == F1AP_ProtocolIE_ID_id_DRB_Information && ie->criticality == F1AP_Criticality_reject - && ie->value.present == F1AP_QoSInformation_ExtIEs__value_PR_DRB_Information) { - - const F1AP_DRB_Information_t *dRB_Info = &ie->value.choice.DRB_Information; - f1ap_drb_information_t *drb_info = &drb_p->drb_info; - - /* QoS-Flow-Level-QoS-Parameters */ - /* QoS Characteristics*/ - f1ap_read_drb_qos_param(&dRB_Info->dRB_QoS, &drb_info->drb_qos); - - // 12.1.2.4 flows_Mapped_To_DRB_List - drb_info->flows_to_be_setup_length = dRB_Info->flows_Mapped_To_DRB_List.list.count; - drb_info->flows_mapped_to_drb = calloc(drb_info->flows_to_be_setup_length, sizeof(f1ap_flows_mapped_to_drb_t)); - AssertFatal(drb_info->flows_mapped_to_drb, "could not allocate memory for drb_p->drb_info.flows_mapped_to_drb\n"); - f1ap_read_flows_mapped(&dRB_Info->flows_Mapped_To_DRB_List, drb_info->flows_mapped_to_drb, drb_info->flows_to_be_setup_length); - - /* S-NSSAI */ - f1ap_read_drb_nssai(&dRB_Info->sNSSAI, &drb_p->nssai); - } - } - } - } - } - - /* SRB */ - F1AP_UEContextSetupRequestIEs_t *ieSrb; - F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_UEContextSetupRequestIEs_t, ieSrb, container, - F1AP_ProtocolIE_ID_id_SRBs_ToBeSetup_List, false); - - if(ieSrb != NULL) { - f1ap_ue_context_setup_req->srbs_to_be_setup_length = ieSrb->value.choice.SRBs_ToBeSetup_List.list.count; - f1ap_ue_context_setup_req->srbs_to_be_setup = calloc(f1ap_ue_context_setup_req->srbs_to_be_setup_length, - sizeof(f1ap_srb_to_be_setup_t)); - AssertFatal(f1ap_ue_context_setup_req->srbs_to_be_setup, - "could not allocate memory for f1ap_ue_context_setup_req->srbs_to_be_setup\n"); - - for (i = 0; i < f1ap_ue_context_setup_req->srbs_to_be_setup_length; ++i) { - f1ap_srb_to_be_setup_t *srb_p = &f1ap_ue_context_setup_req->srbs_to_be_setup[i]; - F1AP_SRBs_ToBeSetup_Item_t *srbs_tobesetup_item_p; - srbs_tobesetup_item_p = &((F1AP_SRBs_ToBeSetup_ItemIEs_t *)ieSrb->value.choice.SRBs_ToBeSetup_List.list.array[i])->value.choice.SRBs_ToBeSetup_Item; - srb_p->srb_id = srbs_tobesetup_item_p->sRBID; - } - } - - /* RRCContainer */ - F1AP_UEContextSetupRequestIEs_t *ieRRC; - F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_UEContextSetupRequestIEs_t, ieRRC, container, - F1AP_ProtocolIE_ID_id_RRCContainer, false); - - if (ieRRC) { - /* correct here */ - if ( ieRRC->value.choice.RRCContainer.size ) { - f1ap_ue_context_setup_req->rrc_container = malloc(ieRRC->value.choice.RRCContainer.size); - memcpy(f1ap_ue_context_setup_req->rrc_container, - ieRRC->value.choice.RRCContainer.buf, ieRRC->value.choice.RRCContainer.size); - f1ap_ue_context_setup_req->rrc_container_length = ieRRC->value.choice.RRCContainer.size; - } else { - LOG_E(F1AP, " RRCContainer in UEContextSetupRequestIEs size id 0\n"); - } - } - - ue_context_setup_request(f1ap_ue_context_setup_req); return 0; } @@ -893,214 +622,16 @@ int DU_send_UE_CONTEXT_RELEASE_COMPLETE(sctp_assoc_t assoc_id, f1ap_ue_context_r int DU_handle_UE_CONTEXT_MODIFICATION_REQUEST(instance_t instance, sctp_assoc_t assoc_id, uint32_t stream, F1AP_F1AP_PDU_t *pdu) { - F1AP_UEContextModificationRequest_t *container; - int i; - f1ap_ue_context_modif_req_t ue_context_modification = {0}; - f1ap_ue_context_modif_req_t *f1ap_ue_context_modification_req = &ue_context_modification; - container = &pdu->choice.initiatingMessage->value.choice.UEContextModificationRequest; - - /* mandatory */ - /* GNB_CU_UE_F1AP_ID */ - F1AP_UEContextModificationRequestIEs_t *ieCU; - F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_UEContextModificationRequestIEs_t, ieCU, container, - F1AP_ProtocolIE_ID_id_gNB_CU_UE_F1AP_ID, true); - f1ap_ue_context_modification_req->gNB_CU_ue_id = ieCU->value.choice.GNB_CU_UE_F1AP_ID; - - /* mandatory */ - /* GNB_DU_UE_F1AP_ID */ - F1AP_UEContextModificationRequestIEs_t *ieDU_UE; - F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_UEContextModificationRequestIEs_t, ieDU_UE, container, - F1AP_ProtocolIE_ID_id_gNB_DU_UE_F1AP_ID, true); - f1ap_ue_context_modification_req->gNB_DU_ue_id = ieDU_UE->value.choice.GNB_DU_UE_F1AP_ID; - - /* SRB */ - F1AP_UEContextModificationRequestIEs_t *ieSrb; - F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_UEContextModificationRequestIEs_t, ieSrb, container, - F1AP_ProtocolIE_ID_id_SRBs_ToBeSetupMod_List, false); - - F1AP_UEContextModificationRequestIEs_t *ieTxInd; - F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_UEContextModificationRequestIEs_t, - ieTxInd, - container, - F1AP_ProtocolIE_ID_id_TransmissionActionIndicator, - false); - - if (ieTxInd != NULL) { - f1ap_ue_context_modification_req->transm_action_ind = calloc_or_fail(1, sizeof(*f1ap_ue_context_modification_req->transm_action_ind)); - *f1ap_ue_context_modification_req->transm_action_ind = ieTxInd->value.choice.TransmissionActionIndicator; - // Stop is guaranteed to be 0, by restart might be different from 1 - static_assert((int)F1AP_TransmissionActionIndicator_restart == (int)TransmActionInd_RESTART, - "mismatch of ASN.1 and internal representation\n"); + f1ap_ue_context_mod_req_t req = {0}; + if (!decode_ue_context_mod_req(pdu, &req)) { + LOG_E(F1AP, "cannot decode F1 UE Context Modification Request\n"); + free_ue_context_mod_req(&req); + return -1; } - if(ieSrb != NULL) { - f1ap_ue_context_modification_req->srbs_to_be_setup_length = ieSrb->value.choice.SRBs_ToBeSetupMod_List.list.count; - f1ap_ue_context_modification_req->srbs_to_be_setup = calloc(f1ap_ue_context_modification_req->srbs_to_be_setup_length, - sizeof(f1ap_srb_to_be_setup_t)); - AssertFatal(f1ap_ue_context_modification_req->srbs_to_be_setup, - "could not allocate memory for f1ap_ue_context_setup_req->srbs_to_be_setup\n"); + ue_context_modification_request(&req); + free_ue_context_mod_req(&req); - for (i = 0; i < f1ap_ue_context_modification_req->srbs_to_be_setup_length; ++i) { - f1ap_srb_to_be_setup_t *srb_p = &f1ap_ue_context_modification_req->srbs_to_be_setup[i]; - F1AP_SRBs_ToBeSetupMod_Item_t *srbs_tobesetupmod_item_p; - srbs_tobesetupmod_item_p = &((F1AP_SRBs_ToBeSetupMod_ItemIEs_t *)ieSrb->value.choice.SRBs_ToBeSetupMod_List.list.array[i])->value.choice.SRBs_ToBeSetupMod_Item; - srb_p->srb_id = srbs_tobesetupmod_item_p->sRBID; - } - } - - /* DRB */ - F1AP_UEContextModificationRequestIEs_t *ieDrb; - F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_UEContextModificationRequestIEs_t, ieDrb, container, - F1AP_ProtocolIE_ID_id_DRBs_ToBeSetupMod_List, false); - - if(ieDrb!=NULL) { - f1ap_ue_context_modification_req->drbs_to_be_setup_length = ieDrb->value.choice.DRBs_ToBeSetupMod_List.list.count; - f1ap_ue_context_modification_req->drbs_to_be_setup = calloc(f1ap_ue_context_modification_req->drbs_to_be_setup_length, - sizeof(f1ap_drb_to_be_setup_t)); - AssertFatal(f1ap_ue_context_modification_req->drbs_to_be_setup, - "could not allocate memory for f1ap_ue_context_setup_req->drbs_to_be_setup\n"); - - for (i = 0; i < f1ap_ue_context_modification_req->drbs_to_be_setup_length; ++i) { - f1ap_drb_to_be_setup_t *drb_p = &f1ap_ue_context_modification_req->drbs_to_be_setup[i]; - F1AP_DRBs_ToBeSetupMod_Item_t *drbs_tobesetupmod_item_p = - &((F1AP_DRBs_ToBeSetupMod_ItemIEs_t *)ieDrb->value.choice.DRBs_ToBeSetupMod_List.list.array[i])->value.choice.DRBs_ToBeSetupMod_Item; - drb_p->drb_id = drbs_tobesetupmod_item_p->dRBID; - /* TODO in the following, assume only one UP UL TNL is present. - * this matches/assumes OAI CU implementation, can be up to 2! */ - drb_p->up_ul_tnl_length = 1; - AssertFatal(drbs_tobesetupmod_item_p->uLUPTNLInformation_ToBeSetup_List.list.count > 0, - "no UL UP TNL Information in DRBs to be Setup list\n"); - F1AP_ULUPTNLInformation_ToBeSetup_Item_t *ul_up_tnl_info_p = (F1AP_ULUPTNLInformation_ToBeSetup_Item_t *)drbs_tobesetupmod_item_p->uLUPTNLInformation_ToBeSetup_List.list.array[0]; - F1AP_GTPTunnel_t *ul_up_tnl0 = ul_up_tnl_info_p->uLUPTNLInformation.choice.gTPTunnel; - BIT_STRING_TO_TRANSPORT_LAYER_ADDRESS_IPv4(&ul_up_tnl0->transportLayerAddress, drb_p->up_ul_tnl[0].tl_address); - OCTET_STRING_TO_UINT32(&ul_up_tnl0->gTP_TEID, drb_p->up_ul_tnl[0].teid); - // 3GPP assumes GTP-U is on port 2152, but OAI is configurable - 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 = 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) { - AssertFatal(false, "Decode of eUTRANQoS is not implemented yet"); - } // EUTRAN QoS Information - else { - /* 12.1.2 DRB_Information */ - if (drbs_tobesetupmod_item_p->qoSInformation.present == F1AP_QoSInformation_PR_choice_extension) { - F1AP_QoSInformation_ExtIEs_t *ie = - (F1AP_QoSInformation_ExtIEs_t *)drbs_tobesetupmod_item_p->qoSInformation.choice.choice_extension; - if (ie->id == F1AP_ProtocolIE_ID_id_DRB_Information && ie->criticality == F1AP_Criticality_reject - && ie->value.present == F1AP_QoSInformation_ExtIEs__value_PR_DRB_Information) { - - const F1AP_DRB_Information_t *dRB_Info = &ie->value.choice.DRB_Information; - f1ap_drb_information_t *drb_info = &drb_p->drb_info; - - /* QoS-Flow-Level-QoS-Parameters */ - /* QoS Characteristics*/ - f1ap_read_drb_qos_param(&dRB_Info->dRB_QoS, &drb_info->drb_qos); - - // 12.1.2.4 flows_Mapped_To_DRB_List - drb_info->flows_to_be_setup_length = dRB_Info->flows_Mapped_To_DRB_List.list.count; - drb_info->flows_mapped_to_drb = calloc(drb_info->flows_to_be_setup_length, sizeof(f1ap_flows_mapped_to_drb_t)); - AssertFatal(drb_info->flows_mapped_to_drb, "could not allocate memory for drb_p->drb_info.flows_mapped_to_drb\n"); - f1ap_read_flows_mapped(&dRB_Info->flows_Mapped_To_DRB_List, drb_info->flows_mapped_to_drb, drb_info->flows_to_be_setup_length); - - /* S-NSSAI */ - f1ap_read_drb_nssai(&dRB_Info->sNSSAI, &drb_p->nssai); - } - } - } - } - } - - F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_UEContextModificationRequestIEs_t, ieDrb, container, - F1AP_ProtocolIE_ID_id_DRBs_ToBeReleased_List, false); - if (ieDrb != NULL) { - f1ap_ue_context_modification_req->drbs_to_be_released_length = ieDrb->value.choice.DRBs_ToBeReleased_List.list.count; - f1ap_ue_context_modification_req->drbs_to_be_released = - calloc(f1ap_ue_context_modification_req->drbs_to_be_released_length, sizeof(f1ap_drb_to_be_released_t)); - AssertFatal(f1ap_ue_context_modification_req->drbs_to_be_released, - "could not allocate memory for f1ap_ue_context_released_req->drbs_to_be_released\n"); - for (i = 0; i < f1ap_ue_context_modification_req->drbs_to_be_released_length; ++i) { - F1AP_DRBs_ToBeReleased_ItemIEs_t *tbrel = (F1AP_DRBs_ToBeReleased_ItemIEs_t *)ieDrb->value.choice.DRBs_ToBeReleased_List.list.array[i]; - DevAssert(tbrel->id == F1AP_ProtocolIE_ID_id_DRBs_ToBeReleased_Item); - DevAssert(tbrel->value.present == F1AP_DRBs_ToBeReleased_ItemIEs__value_PR_DRBs_ToBeReleased_Item); - f1ap_ue_context_modification_req->drbs_to_be_released[i].rb_id = tbrel->value.choice.DRBs_ToBeReleased_Item.dRBID; - } - } - - /* RRC Reconfiguration Complete indicator */ - F1AP_UEContextModificationRequestIEs_t *ieReconf; - F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_UEContextModificationRequestIEs_t, ieReconf, container, - F1AP_ProtocolIE_ID_id_RRCReconfigurationCompleteIndicator, false); - - if(ieReconf) { - switch(ieReconf->value.choice.RRCReconfigurationCompleteIndicator){ - case F1AP_RRCReconfigurationCompleteIndicator_true: - f1ap_ue_context_modification_req->ReconfigComplOutcome = RRCreconf_success; - break; - - case F1AP_RRCReconfigurationCompleteIndicator_failure: - f1ap_ue_context_modification_req->ReconfigComplOutcome = RRCreconf_failure; - break; - } - } - - /* RRCContainer */ - F1AP_UEContextModificationRequestIEs_t *ieRRC; - F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_UEContextModificationRequestIEs_t, ieRRC, container, - F1AP_ProtocolIE_ID_id_RRCContainer, false); - - if (ieRRC) { - /* correct here */ - if ( ieRRC->value.choice.RRCContainer.size ) { - f1ap_ue_context_modification_req->rrc_container = malloc(ieRRC->value.choice.RRCContainer.size); - memcpy(f1ap_ue_context_modification_req->rrc_container, - ieRRC->value.choice.RRCContainer.buf, ieRRC->value.choice.RRCContainer.size); - f1ap_ue_context_modification_req->rrc_container_length = ieRRC->value.choice.RRCContainer.size; - } else { - LOG_E(F1AP, " RRCContainer in UEContextModificationRequestIEs size id 0\n"); - } - } else { - LOG_D(F1AP, "can't find RRCContainer in UEContextModificationRequestIEs by id %ld \n", F1AP_ProtocolIE_ID_id_RRCContainer); - } - - /* CU2DU Information */ - F1AP_UEContextModificationRequestIEs_t *ieCU2DU = NULL; - F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_UEContextModificationRequestIEs_t, - ieCU2DU, - container, - F1AP_ProtocolIE_ID_id_CUtoDURRCInformation, - false); - if (ieCU2DU != NULL) { - f1ap_ue_context_modification_req->cu_to_du_rrc_information = - calloc(1, sizeof(*f1ap_ue_context_modification_req->cu_to_du_rrc_information)); - AssertFatal(f1ap_ue_context_modification_req->cu_to_du_rrc_information != NULL, "out of memory\n"); - cu_to_du_rrc_information_t *cu2du = f1ap_ue_context_modification_req->cu_to_du_rrc_information; - const F1AP_CUtoDURRCInformation_t *cu2duie = &ieCU2DU->value.choice.CUtoDURRCInformation; - if (cu2duie->cG_ConfigInfo != NULL) - LOG_W(F1AP, "UE RNTI %04x: ignoring cg_ConfigInfo, not implemented\n", f1ap_ue_context_modification_req->gNB_DU_ue_id); - if (cu2duie->measConfig != NULL) - LOG_W(F1AP, "UE RNTI %04x: ignoring measConfig, not implemented\n", f1ap_ue_context_modification_req->gNB_DU_ue_id); - if (cu2duie->uE_CapabilityRAT_ContainerList != NULL) { - F1AP_UE_CapabilityRAT_ContainerList_t *uecap = cu2duie->uE_CapabilityRAT_ContainerList; - cu2du->uE_CapabilityRAT_ContainerList = calloc(uecap->size, sizeof(*cu2du->uE_CapabilityRAT_ContainerList)); - AssertFatal(cu2du->uE_CapabilityRAT_ContainerList != NULL, "out of memory\n"); - cu2du->uE_CapabilityRAT_ContainerList_length = uecap->size; - memcpy(cu2du->uE_CapabilityRAT_ContainerList, uecap->buf, uecap->size); - } - } - - ue_context_modification_request(f1ap_ue_context_modification_req); return 0; } 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 ed03ba76a5..5f2e9b9dfa 100644 --- a/openair2/LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.c +++ b/openair2/LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.c @@ -33,6 +33,7 @@ #include "openair2/LAYER2/nr_pdcp/nr_pdcp_oai_api.h" #include "lib/f1ap_rrc_message_transfer.h" #include "lib/f1ap_interface_management.h" +#include "lib/f1ap_ue_context.h" #include "executables/softmodem-common.h" @@ -222,18 +223,18 @@ void gnb_du_configuration_update_acknowledge(const f1ap_gnb_du_configuration_upd LOG_I(MAC, "received gNB-DU configuration update acknowledge\n"); } -static NR_RLC_BearerConfig_t *get_bearerconfig_from_srb(const f1ap_srb_to_be_setup_t *srb, +static NR_RLC_BearerConfig_t *get_bearerconfig_from_srb(const f1ap_srb_to_setup_t *srb, const nr_rlc_configuration_t *rlc_config) { - long priority = srb->srb_id == 2 ? 3 : 1; // see 38.331 sec 9.2.1 + long priority = srb->id == 2 ? 3 : 1; // see 38.331 sec 9.2.1 e_NR_LogicalChannelConfig__ul_SpecificParameters__bucketSizeDuration bucket = NR_LogicalChannelConfig__ul_SpecificParameters__bucketSizeDuration_ms5; - return get_SRB_RLC_BearerConfig(get_lcid_from_srbid(srb->srb_id), priority, bucket, rlc_config); + return get_SRB_RLC_BearerConfig(get_lcid_from_srbid(srb->id), priority, bucket, rlc_config); } static int handle_ue_context_srbs_setup(NR_UE_info_t *UE, int srbs_len, - const f1ap_srb_to_be_setup_t *req_srbs, + const f1ap_srb_to_setup_t *req_srbs, f1ap_srb_to_be_setup_t **resp_srbs, NR_CellGroupConfig_t *cellGroupConfig, const nr_rlc_configuration_t *rlc_config) @@ -243,15 +244,15 @@ static int handle_ue_context_srbs_setup(NR_UE_info_t *UE, *resp_srbs = calloc(srbs_len, sizeof(**resp_srbs)); AssertFatal(*resp_srbs != NULL, "out of memory\n"); for (int i = 0; i < srbs_len; i++) { - const f1ap_srb_to_be_setup_t *srb = &req_srbs[i]; + const f1ap_srb_to_setup_t *srb = &req_srbs[i]; NR_RLC_BearerConfig_t *rlc_BearerConfig = get_bearerconfig_from_srb(srb, rlc_config); - nr_rlc_add_srb(UE->rnti, srb->srb_id, rlc_BearerConfig); + nr_rlc_add_srb(UE->rnti, srb->id, rlc_BearerConfig); int priority = rlc_BearerConfig->mac_LogicalChannelConfig->ul_SpecificParameters->priority; nr_lc_config_t c = {.lcid = rlc_BearerConfig->logicalChannelIdentity, .priority = priority}; nr_mac_add_lcid(&UE->UE_sched_ctrl, &c); - (*resp_srbs)[i].srb_id = srb->srb_id; + (*resp_srbs)[i].srb_id = srb->id; (*resp_srbs)[i].lcid = c.lcid; if (rlc_BearerConfig->logicalChannelIdentity == 1) { @@ -268,12 +269,12 @@ static int handle_ue_context_srbs_setup(NR_UE_info_t *UE, return srbs_len; } -static NR_RLC_BearerConfig_t *get_bearerconfig_from_drb(const f1ap_drb_to_be_setup_t *drb, +static NR_RLC_BearerConfig_t *get_bearerconfig_from_drb(const f1ap_drb_to_setup_t *drb, const nr_rlc_configuration_t *rlc_config) { 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, rlc_config); + return get_DRB_RLC_BearerConfig(get_lcid_from_drbid(drb->id), drb->id, rlc_conf, priority, rlc_config); } static int get_non_dynamic_priority(int fiveqi) @@ -285,20 +286,20 @@ static int get_non_dynamic_priority(int fiveqi) return 0; } -static NR_QoS_config_t get_qos_config(const f1ap_qos_characteristics_t *qos_char) +static NR_QoS_config_t get_qos_config(const f1ap_qos_flow_param_t *qos) { NR_QoS_config_t qos_c = {0}; - switch (qos_char->qos_type) { + switch (qos->qos_type) { case DYNAMIC: - qos_c.priority = qos_char->dynamic.qos_priority_level; - qos_c.fiveQI = qos_char->dynamic.fiveqi > 0 ? qos_char->dynamic.fiveqi : 0; + qos_c.priority = qos->dyn.prio; + qos_c.fiveQI = 0; // does not exist for non-dynamic break; case NON_DYNAMIC: - qos_c.fiveQI = qos_char->non_dynamic.fiveqi; - qos_c.priority = get_non_dynamic_priority(qos_char->non_dynamic.fiveqi); + qos_c.fiveQI = qos->nondyn.fiveQI; + qos_c.priority = get_non_dynamic_priority(qos_c.fiveQI); break; default: - AssertFatal(false, "illegal QoS type %d\n", qos_char->qos_type); + AssertFatal(false, "illegal QoS type %d\n", qos->qos_type); break; } return qos_c; @@ -306,7 +307,7 @@ static NR_QoS_config_t get_qos_config(const f1ap_qos_characteristics_t *qos_char static int handle_ue_context_drbs_setup(NR_UE_info_t *UE, int drbs_len, - const f1ap_drb_to_be_setup_t *req_drbs, + const f1ap_drb_to_setup_t *req_drbs, f1ap_drb_to_be_setup_t **resp_drbs, NR_CellGroupConfig_t *cellGroupConfig, const nr_rlc_configuration_t *rlc_config) @@ -319,32 +320,34 @@ static int handle_ue_context_drbs_setup(NR_UE_info_t *UE, *resp_drbs = calloc(drbs_len, sizeof(**resp_drbs)); AssertFatal(*resp_drbs != NULL, "out of memory\n"); for (int i = 0; i < drbs_len; i++) { - const f1ap_drb_to_be_setup_t *drb = &req_drbs[i]; + const f1ap_drb_to_setup_t *drb = &req_drbs[i]; + AssertFatal(drb->qos_choice == F1AP_QOS_CHOICE_NR, "only NR QoS supported\n"); f1ap_drb_to_be_setup_t *resp_drb = &(*resp_drbs)[i]; NR_RLC_BearerConfig_t *rlc_BearerConfig = get_bearerconfig_from_drb(drb, rlc_config); - nr_rlc_add_drb(UE->rnti, drb->drb_id, rlc_BearerConfig); + nr_rlc_add_drb(UE->rnti, drb->id, rlc_BearerConfig); - nr_lc_config_t c = {.lcid = rlc_BearerConfig->logicalChannelIdentity, .nssai = drb->nssai}; + nr_lc_config_t c = {.lcid = rlc_BearerConfig->logicalChannelIdentity, .nssai = drb->nr.nssai}; int prio = 100; - for (int q = 0; q < drb->drb_info.flows_to_be_setup_length; ++q) { - c.qos_config[q] = get_qos_config(&drb->drb_info.flows_mapped_to_drb[q].qos_params.qos_characteristics); + for (int q = 0; q < drb->nr.flows_len; ++q) { + c.qos_config[q] = get_qos_config(&drb->nr.flows[q].param); prio = min(prio, c.qos_config[q].priority); } c.priority = prio; nr_mac_add_lcid(&UE->UE_sched_ctrl, &c); - *resp_drb = *drb; + resp_drb->drb_id = drb->id; + // TODO lcid // just put same number of tunnels in DL as in UL - DevAssert(drb->up_ul_tnl_length == 1); - resp_drb->up_dl_tnl_length = drb->up_ul_tnl_length; + DevAssert(drb->up_ul_tnl_len == 1); + resp_drb->up_dl_tnl_length = drb->up_ul_tnl_len; if (f1inst >= 0) { // we actually use F1-U int qfi = -1; // don't put PDU session marker in GTP gtpv1u_gnb_create_tunnel_resp_t resp_f1 = {0}; int ret = drb_gtpu_create(f1inst, UE->rnti, - drb->drb_id, - drb->drb_id, + drb->id, + drb->id, qfi, drb->up_ul_tnl[0].tl_address, drb->up_ul_tnl[0].teid, @@ -366,7 +369,7 @@ static int handle_ue_context_drbs_setup(NR_UE_info_t *UE, static int handle_ue_context_drbs_release(NR_UE_info_t *UE, int drbs_len, - const f1ap_drb_to_be_released_t *req_drbs, + const f1ap_drb_to_release_t *req_drbs, NR_CellGroupConfig_t *cellGroupConfig) { DevAssert(req_drbs != NULL && cellGroupConfig != NULL); @@ -378,9 +381,9 @@ static int handle_ue_context_drbs_release(NR_UE_info_t *UE, /* Note: the actual GTP tunnels are already removed in the F1AP message * decoding */ for (int i = 0; i < drbs_len; i++) { - const f1ap_drb_to_be_released_t *drb = &req_drbs[i]; + const f1ap_drb_to_release_t *drb = &req_drbs[i]; - long lcid = get_lcid_from_drbid(drb->rb_id); + long lcid = get_lcid_from_drbid(drb->id); int idx = 0; while (idx < cellGroupConfig->rlc_BearerToAddModList->list.count) { const NR_RLC_BearerConfig_t *bc = cellGroupConfig->rlc_BearerToAddModList->list.array[idx]; @@ -392,7 +395,7 @@ static int handle_ue_context_drbs_release(NR_UE_info_t *UE, nr_mac_remove_lcid(&UE->UE_sched_ctrl, lcid); nr_rlc_release_entity(UE->rnti, lcid); if (f1inst >= 0) - newGtpuDeleteOneTunnel(f1inst, UE->rnti, drb->rb_id); + newGtpuDeleteOneTunnel(f1inst, UE->rnti, drb->id); asn_sequence_del(&cellGroupConfig->rlc_BearerToAddModList->list, idx, 1); long *plcid = malloc(sizeof(*plcid)); AssertFatal(plcid, "out of memory\n"); @@ -600,34 +603,30 @@ static NR_UE_info_t *create_new_UE(gNB_MAC_INST *mac, uint32_t cu_id, const NR_C return UE; } -void ue_context_setup_request(const f1ap_ue_context_setup_t *req) +void ue_context_setup_request(const f1ap_ue_context_setup_req_t *req) { const bool is_SA = IS_SA_MODE(get_softmodem_params()); gNB_MAC_INST *mac = RC.nrmac[0]; - /* response has same type as request... */ + + /* TODO: update response */ f1ap_ue_context_setup_t resp = { .gNB_CU_ue_id = req->gNB_CU_ue_id, - .gNB_DU_ue_id = req->gNB_DU_ue_id, }; - /* gNB-DU UE ID is optional. As of now, the F1AP module fills -1 (on uint, so - * 0xffffffff), but the DU uses the RNTI, so check if it's a legal RNTI in - * which case we consider; if not, assume no DU UE ID given */ - bool ue_id_provided = resp.gNB_DU_ue_id > 0 && resp.gNB_DU_ue_id < 0xffff; + bool ue_id_provided = req->gNB_DU_ue_id != NULL; - NR_UE_NR_Capability_t *ue_cap = NULL; + const f1ap_cu_to_du_rrc_info_t *cu2du = &req->cu_to_du_rrc_info; NR_CG_ConfigInfo_t *cg_configinfo = NULL; - if (req->cu_to_du_rrc_information != NULL) { - const cu_to_du_rrc_information_t *cu2du = req->cu_to_du_rrc_information; - if (cu2du->cG_ConfigInfo != NULL) - cg_configinfo = get_cg_config_info(cu2du->cG_ConfigInfo, cu2du->cG_ConfigInfo_length); - if (cu2du->handoverPreparationInfo != NULL) { - ue_cap = get_ue_nr_cap_from_ho_prep_info(cu2du->handoverPreparationInfo, cu2du->handoverPreparationInfo_length); - } else if (cu2du->uE_CapabilityRAT_ContainerList != NULL) { - ue_cap = get_ue_nr_cap(req->gNB_DU_ue_id, cu2du->uE_CapabilityRAT_ContainerList, cu2du->uE_CapabilityRAT_ContainerList_length); - } - AssertFatal(cu2du->measConfig == NULL, "MeasConfig not handled\n"); + if (cu2du->cg_configinfo != NULL) + cg_configinfo = get_cg_config_info(cu2du->cg_configinfo->buf, cu2du->cg_configinfo->len); + NR_UE_NR_Capability_t *ue_cap = NULL; + if (cu2du->ho_prep_info != NULL) { + ue_cap = get_ue_nr_cap_from_ho_prep_info(cu2du->ho_prep_info->buf, cu2du->ho_prep_info->len); + } else if (cu2du->ue_cap != NULL) { + ue_cap = get_ue_nr_cap(*req->gNB_DU_ue_id, cu2du->ue_cap->buf, cu2du->ue_cap->len); } + AssertFatal(cu2du->meas_config == NULL, "MeasConfig not handled\n"); + /* 38.473: "For DC operation, the CG-ConfigInfo IE shall be included in the CU * to DU RRC Information IE at the gNB acting as secondary node" As of now, * we only handle NSA => we check we have CG-ConfigInfo if not SA or have SA @@ -643,25 +642,26 @@ void ue_context_setup_request(const f1ap_ue_context_setup_t *req) resp.crnti = &UE->rnti; } else { DevAssert(is_SA); - UE = find_nr_UE(&mac->UE_info, req->gNB_DU_ue_id); + UE = find_nr_UE(&mac->UE_info, *req->gNB_DU_ue_id); } AssertFatal(UE, "no UE found or could not be created, but UE Context Setup Failed not implemented\n"); + resp.gNB_DU_ue_id = UE->rnti; NR_CellGroupConfig_t *new_CellGroup = clone_CellGroupConfig(UE->CellGroup); - if (req->srbs_to_be_setup_length > 0) { + if (req->srbs_len > 0) { resp.srbs_to_be_setup_length = handle_ue_context_srbs_setup(UE, - req->srbs_to_be_setup_length, - req->srbs_to_be_setup, + req->srbs_len, + req->srbs, &resp.srbs_to_be_setup, new_CellGroup, &mac->rlc_config); } - if (req->drbs_to_be_setup_length > 0) { + if (req->drbs_len > 0) { resp.drbs_to_be_setup_length = handle_ue_context_drbs_setup(UE, - req->drbs_to_be_setup_length, - req->drbs_to_be_setup, + req->drbs_len, + req->drbs, &resp.drbs_to_be_setup, new_CellGroup, &mac->rlc_config); @@ -669,7 +669,7 @@ void ue_context_setup_request(const f1ap_ue_context_setup_t *req) if (req->rrc_container != NULL) { logical_chan_id_t id = 1; - nr_rlc_srb_recv_sdu(req->gNB_DU_ue_id, id, req->rrc_container, req->rrc_container_length); + nr_rlc_srb_recv_sdu(UE->rnti, id, req->rrc_container->buf, req->rrc_container->len); } NR_ServingCellConfigCommon_t *scc = mac->common_channels[0].ServingCellConfigCommon; @@ -722,7 +722,7 @@ void ue_context_setup_request(const f1ap_ue_context_setup_t *req) free(resp.du_to_cu_rrc_information); } -void ue_context_modification_request(const f1ap_ue_context_modif_req_t *req) +void ue_context_modification_request(const f1ap_ue_context_mod_req_t *req) { gNB_MAC_INST *mac = RC.nrmac[0]; f1ap_ue_context_modif_resp_t resp = { @@ -731,12 +731,13 @@ void ue_context_modification_request(const f1ap_ue_context_modif_req_t *req) }; NR_UE_NR_Capability_t *ue_cap = NULL; - if (req->cu_to_du_rrc_information != NULL) { - AssertFatal(req->cu_to_du_rrc_information->cG_ConfigInfo == NULL, "CG-ConfigInfo not handled\n"); - ue_cap = get_ue_nr_cap(req->gNB_DU_ue_id, - req->cu_to_du_rrc_information->uE_CapabilityRAT_ContainerList, - req->cu_to_du_rrc_information->uE_CapabilityRAT_ContainerList_length); - AssertFatal(req->cu_to_du_rrc_information->measConfig == NULL, "MeasConfig not handled\n"); + if (req->cu_to_du_rrc_info != NULL) { + AssertFatal(req->cu_to_du_rrc_info->cg_configinfo == NULL, "CG-ConfigInfo not handled\n"); + if (req->cu_to_du_rrc_info->ue_cap) { + byte_array_t *b = req->cu_to_du_rrc_info->ue_cap; + ue_cap = get_ue_nr_cap(req->gNB_DU_ue_id, b->buf, b->len); + } + AssertFatal(req->cu_to_du_rrc_info->meas_config == NULL, "MeasConfig not handled\n"); } NR_SCHED_LOCK(&mac->sched_lock); @@ -749,39 +750,38 @@ void ue_context_modification_request(const f1ap_ue_context_modif_req_t *req) NR_CellGroupConfig_t *new_CellGroup = clone_CellGroupConfig(UE->CellGroup); - if (req->srbs_to_be_setup_length > 0) { + if (req->srbs_len > 0) { resp.srbs_to_be_setup_length = handle_ue_context_srbs_setup(UE, - req->srbs_to_be_setup_length, - req->srbs_to_be_setup, + req->srbs_len, + req->srbs, &resp.srbs_to_be_setup, new_CellGroup, &mac->rlc_config); } - if (req->drbs_to_be_setup_length > 0) { + if (req->drbs_len > 0) { resp.drbs_to_be_setup_length = handle_ue_context_drbs_setup(UE, - req->drbs_to_be_setup_length, - req->drbs_to_be_setup, + req->drbs_len, + req->drbs, &resp.drbs_to_be_setup, new_CellGroup, &mac->rlc_config); } - if (req->drbs_to_be_released_length > 0) { - resp.drbs_to_be_released_length = - handle_ue_context_drbs_release(UE, req->drbs_to_be_released_length, req->drbs_to_be_released, new_CellGroup); + if (req->drbs_rel_len > 0) { + resp.drbs_to_be_released_length = handle_ue_context_drbs_release(UE, req->drbs_rel_len, req->drbs_rel, new_CellGroup); } if (req->rrc_container != NULL) { logical_chan_id_t id = 1; - nr_rlc_srb_recv_sdu(req->gNB_DU_ue_id, id, req->rrc_container, req->rrc_container_length); + nr_rlc_srb_recv_sdu(req->gNB_DU_ue_id, id, req->rrc_container->buf, req->rrc_container->len); } NR_ServingCellConfigCommon_t *scc = mac->common_channels[0].ServingCellConfigCommon; - if (req->ReconfigComplOutcome != RRCreconf_info_not_present && req->ReconfigComplOutcome != RRCreconf_success) { + if (req->reconfig_compl && *req->reconfig_compl != RRCreconf_success) { LOG_E(NR_MAC, "RRC reconfiguration outcome unsuccessful, but no rollback mechanism implemented to come back to old configuration\n"); - } else if (req->ReconfigComplOutcome == RRCreconf_success) { + } else if (req->reconfig_compl) { LOG_I(NR_MAC, "DU received confirmation of successful RRC Reconfiguration\n"); if (UE->reconfigSpCellConfig) { // in case of reestablishment, the spCellConfig had to be released @@ -807,8 +807,7 @@ void ue_context_modification_request(const f1ap_ue_context_modif_req_t *req) update_cellGroupConfig(new_CellGroup, UE->uid, UE->capability, &mac->radio_config, scc); } - if (req->srbs_to_be_setup_length > 0 || req->drbs_to_be_setup_length > 0 || req->drbs_to_be_released_length > 0 - || ue_cap != NULL) { + if (req->srbs_len > 0 || req->drbs_len > 0 || req->drbs_rel_len > 0 || ue_cap != NULL) { resp.du_to_cu_rrc_information = calloc(1, sizeof(du_to_cu_rrc_information_t)); AssertFatal(resp.du_to_cu_rrc_information != NULL, "out of memory\n"); resp.du_to_cu_rrc_information->cellGroupConfig = calloc(1, 1024); 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 e9aceb1192..b3ecdad270 100644 --- a/openair2/LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.h +++ b/openair2/LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.h @@ -32,8 +32,8 @@ 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); NR_CellGroupConfig_t *clone_CellGroupConfig(const NR_CellGroupConfig_t *orig); -void ue_context_setup_request(const f1ap_ue_context_setup_t *req); -void ue_context_modification_request(const f1ap_ue_context_modif_req_t *req); +void ue_context_setup_request(const f1ap_ue_context_setup_req_t *req); +void ue_context_modification_request(const f1ap_ue_context_mod_req_t *req); void ue_context_modification_confirm(const f1ap_ue_context_modif_confirm_t *confirm); void ue_context_modification_refuse(const f1ap_ue_context_modif_refuse_t *refuse); void ue_context_release_command(const f1ap_ue_context_release_cmd_t *cmd); diff --git a/openair2/RRC/NR/mac_rrc_dl.h b/openair2/RRC/NR/mac_rrc_dl.h index d6937591b5..f93bc1b7fe 100644 --- a/openair2/RRC/NR/mac_rrc_dl.h +++ b/openair2/RRC/NR/mac_rrc_dl.h @@ -33,8 +33,8 @@ typedef void (*f1_setup_failure_func_t)(sctp_assoc_t assoc_id, const f1ap_setup_ typedef void (*gnb_du_configuration_update_ack_func_t)(sctp_assoc_t assoc_id, const f1ap_gnb_du_configuration_update_acknowledge_t *ack); -typedef void (*ue_context_setup_request_func_t)(sctp_assoc_t assoc_id, const f1ap_ue_context_setup_t *req); -typedef void (*ue_context_modification_request_func_t)(sctp_assoc_t assoc_id, const f1ap_ue_context_modif_req_t *req); +typedef void (*ue_context_setup_request_func_t)(sctp_assoc_t assoc_id, const f1ap_ue_context_setup_req_t *req); +typedef void (*ue_context_modification_request_func_t)(sctp_assoc_t assoc_id, const f1ap_ue_context_mod_req_t *req); typedef void (*ue_context_modification_confirm_func_t)(sctp_assoc_t assoc_id, const f1ap_ue_context_modif_confirm_t *confirm); typedef void (*ue_context_modification_refuse_func_t)(sctp_assoc_t assoc_id, const f1ap_ue_context_modif_refuse_t *refuse); typedef void (*ue_context_release_command_func_t)(sctp_assoc_t assoc_id, const f1ap_ue_context_release_cmd_t *cmd); diff --git a/openair2/RRC/NR/mac_rrc_dl_direct.c b/openair2/RRC/NR/mac_rrc_dl_direct.c index 4f8d45ac8c..29592d4e43 100644 --- a/openair2/RRC/NR/mac_rrc_dl_direct.c +++ b/openair2/RRC/NR/mac_rrc_dl_direct.c @@ -58,13 +58,13 @@ static void gnb_du_configuration_update_ack_direct(sctp_assoc_t assoc_id, const gnb_du_configuration_update_acknowledge(ack); } -static void ue_context_setup_request_direct(sctp_assoc_t assoc_id, const f1ap_ue_context_setup_t *req) +static void ue_context_setup_request_direct(sctp_assoc_t assoc_id, const f1ap_ue_context_setup_req_t *req) { AssertFatal(assoc_id == -1, "illegal assoc_id %d\n", assoc_id); ue_context_setup_request(req); } -static void ue_context_modification_request_direct(sctp_assoc_t assoc_id, const f1ap_ue_context_modif_req_t *req) +static void ue_context_modification_request_direct(sctp_assoc_t assoc_id, const f1ap_ue_context_mod_req_t *req) { AssertFatal(assoc_id == -1, "illegal assoc_id %d\n", assoc_id); ue_context_modification_request(req); diff --git a/openair2/RRC/NR/mac_rrc_dl_f1ap.c b/openair2/RRC/NR/mac_rrc_dl_f1ap.c index 30c4f910ee..47d1bc1d7e 100644 --- a/openair2/RRC/NR/mac_rrc_dl_f1ap.c +++ b/openair2/RRC/NR/mac_rrc_dl_f1ap.c @@ -32,6 +32,7 @@ #include "nr_rrc_defs.h" #include "lib/f1ap_rrc_message_transfer.h" #include "lib/f1ap_interface_management.h" +#include "lib/f1ap_ue_context.h" static void f1_reset_cu_initiated_f1ap(sctp_assoc_t assoc_id, const f1ap_reset_t *reset) { @@ -75,116 +76,19 @@ static void gnb_du_configuration_update_ack_f1ap(sctp_assoc_t assoc_id, const f1 itti_send_msg_to_task(TASK_CU_F1, 0, msg); } -static void ue_context_setup_request_f1ap(sctp_assoc_t assoc_id, const f1ap_ue_context_setup_t *req) +static void ue_context_setup_request_f1ap(sctp_assoc_t assoc_id, const f1ap_ue_context_setup_req_t *req) { MessageDef *msg = itti_alloc_new_message(TASK_RRC_GNB, 0, F1AP_UE_CONTEXT_SETUP_REQ); msg->ittiMsgHeader.originInstance = assoc_id; - f1ap_ue_context_setup_t *f1ap_msg = &F1AP_UE_CONTEXT_SETUP_REQ(msg); - *f1ap_msg = *req; - if (req->cu_to_du_rrc_information != NULL) { - f1ap_msg->cu_to_du_rrc_information = calloc(1, sizeof(*f1ap_msg->cu_to_du_rrc_information)); - AssertFatal(f1ap_msg->cu_to_du_rrc_information != NULL, "out of memory\n"); - const cu_to_du_rrc_information_t *du2cu_req = req->cu_to_du_rrc_information; - if (req->cu_to_du_rrc_information->cG_ConfigInfo != NULL) { - cu_to_du_rrc_information_t* du2cu_new = f1ap_msg->cu_to_du_rrc_information; - du2cu_new->cG_ConfigInfo_length = du2cu_req->cG_ConfigInfo_length; - du2cu_new->cG_ConfigInfo = malloc_or_fail(du2cu_new->cG_ConfigInfo_length); - memcpy(du2cu_new->cG_ConfigInfo, du2cu_req->cG_ConfigInfo, du2cu_new->cG_ConfigInfo_length); - } - AssertFatal(req->cu_to_du_rrc_information->measConfig == NULL && req->cu_to_du_rrc_information->measConfig_length == 0, "cg_ConfigInfo not implemented\n"); - if (req->cu_to_du_rrc_information->uE_CapabilityRAT_ContainerList != NULL) { - cu_to_du_rrc_information_t* du2cu_new = f1ap_msg->cu_to_du_rrc_information; - DevAssert(du2cu_req->uE_CapabilityRAT_ContainerList_length > 0); - du2cu_new->uE_CapabilityRAT_ContainerList_length = du2cu_req->uE_CapabilityRAT_ContainerList_length; - du2cu_new->uE_CapabilityRAT_ContainerList = malloc(du2cu_new->uE_CapabilityRAT_ContainerList_length); - AssertFatal(du2cu_new->uE_CapabilityRAT_ContainerList != NULL, "out of memory\n"); - memcpy(du2cu_new->uE_CapabilityRAT_ContainerList, du2cu_req->uE_CapabilityRAT_ContainerList, du2cu_new->uE_CapabilityRAT_ContainerList_length); - } - if (req->cu_to_du_rrc_information->handoverPreparationInfo != NULL) { - cu_to_du_rrc_information_t *du2cu_new = f1ap_msg->cu_to_du_rrc_information; - DevAssert(du2cu_req->handoverPreparationInfo_length > 0); - du2cu_new->handoverPreparationInfo_length = du2cu_req->handoverPreparationInfo_length; - du2cu_new->handoverPreparationInfo = malloc_or_fail(du2cu_new->handoverPreparationInfo_length); - memcpy(du2cu_new->handoverPreparationInfo, du2cu_req->handoverPreparationInfo, du2cu_new->handoverPreparationInfo_length); - } - } - if (req->drbs_to_be_setup_length > 0) { - int n = req->drbs_to_be_setup_length; - f1ap_msg->drbs_to_be_setup_length = n; - f1ap_msg->drbs_to_be_setup = calloc(n, sizeof(*f1ap_msg->drbs_to_be_setup)); - AssertFatal(f1ap_msg->drbs_to_be_setup != NULL, "out of memory\n"); - memcpy(f1ap_msg->drbs_to_be_setup, req->drbs_to_be_setup, n * sizeof(*f1ap_msg->drbs_to_be_setup)); - } - if (req->srbs_to_be_setup_length > 0) { - int n = req->srbs_to_be_setup_length; - f1ap_msg->srbs_to_be_setup_length = n; - f1ap_msg->srbs_to_be_setup = calloc(n, sizeof(*f1ap_msg->srbs_to_be_setup)); - AssertFatal(f1ap_msg->srbs_to_be_setup != NULL, "out of memory\n"); - memcpy(f1ap_msg->srbs_to_be_setup, req->srbs_to_be_setup, n * sizeof(*f1ap_msg->srbs_to_be_setup)); - } - if (req->rrc_container_length > 0) { - f1ap_msg->rrc_container = calloc(req->rrc_container_length, sizeof(*f1ap_msg->rrc_container)); - AssertFatal(f1ap_msg->rrc_container != NULL, "out of memory\n"); - f1ap_msg->rrc_container_length = req->rrc_container_length; - memcpy(f1ap_msg->rrc_container, req->rrc_container, req->rrc_container_length); - } + F1AP_UE_CONTEXT_SETUP_REQ(msg) = cp_ue_context_setup_req(req); itti_send_msg_to_task(TASK_CU_F1, 0, msg); } -static void ue_context_modification_request_f1ap(sctp_assoc_t assoc_id, const f1ap_ue_context_modif_req_t *req) +static void ue_context_modification_request_f1ap(sctp_assoc_t assoc_id, const f1ap_ue_context_mod_req_t *req) { MessageDef *msg = itti_alloc_new_message(TASK_RRC_GNB, 0, F1AP_UE_CONTEXT_MODIFICATION_REQ); msg->ittiMsgHeader.originInstance = assoc_id; - f1ap_ue_context_modif_req_t *f1ap_msg = &F1AP_UE_CONTEXT_MODIFICATION_REQ(msg); - *f1ap_msg = *req; - if (req->cu_to_du_rrc_information != NULL) { - f1ap_msg->cu_to_du_rrc_information = calloc(1, sizeof(*f1ap_msg->cu_to_du_rrc_information)); - AssertFatal(f1ap_msg->cu_to_du_rrc_information != NULL, "out of memory\n"); - AssertFatal(req->cu_to_du_rrc_information->cG_ConfigInfo == NULL && req->cu_to_du_rrc_information->cG_ConfigInfo_length == 0, "cg_ConfigInfo not implemented\n"); - AssertFatal(req->cu_to_du_rrc_information->measConfig == NULL && req->cu_to_du_rrc_information->measConfig_length == 0, "cg_ConfigInfo not implemented\n"); - if (req->cu_to_du_rrc_information->uE_CapabilityRAT_ContainerList != NULL) { - const cu_to_du_rrc_information_t *du2cu_req = req->cu_to_du_rrc_information; - cu_to_du_rrc_information_t* du2cu_new = f1ap_msg->cu_to_du_rrc_information; - DevAssert(du2cu_req->uE_CapabilityRAT_ContainerList_length > 0); - du2cu_new->uE_CapabilityRAT_ContainerList_length = du2cu_req->uE_CapabilityRAT_ContainerList_length; - du2cu_new->uE_CapabilityRAT_ContainerList = malloc(du2cu_new->uE_CapabilityRAT_ContainerList_length); - AssertFatal(du2cu_new->uE_CapabilityRAT_ContainerList != NULL, "out of memory\n"); - memcpy(du2cu_new->uE_CapabilityRAT_ContainerList, du2cu_req->uE_CapabilityRAT_ContainerList, du2cu_new->uE_CapabilityRAT_ContainerList_length); - } - } - AssertFatal(req->drbs_to_be_modified_length == 0, "drbs_to_be_modified not supported yet\n"); - if (req->drbs_to_be_setup_length > 0) { - int n = req->drbs_to_be_setup_length; - f1ap_msg->drbs_to_be_setup_length = n; - f1ap_msg->drbs_to_be_setup = calloc(n, sizeof(*f1ap_msg->drbs_to_be_setup)); - AssertFatal(f1ap_msg->drbs_to_be_setup != NULL, "out of memory\n"); - memcpy(f1ap_msg->drbs_to_be_setup, req->drbs_to_be_setup, n * sizeof(*f1ap_msg->drbs_to_be_setup)); - } - if (req->srbs_to_be_setup_length > 0) { - int n = req->srbs_to_be_setup_length; - f1ap_msg->srbs_to_be_setup_length = n; - f1ap_msg->srbs_to_be_setup = calloc(n, sizeof(*f1ap_msg->srbs_to_be_setup)); - AssertFatal(f1ap_msg->srbs_to_be_setup != NULL, "out of memory\n"); - memcpy(f1ap_msg->srbs_to_be_setup, req->srbs_to_be_setup, n * sizeof(*f1ap_msg->srbs_to_be_setup)); - } - if (req->drbs_to_be_released_length > 0) { - int n = req->drbs_to_be_released_length; - f1ap_msg->drbs_to_be_released_length = n; - f1ap_msg->drbs_to_be_released = calloc(n, sizeof(*f1ap_msg->drbs_to_be_released)); - AssertFatal(f1ap_msg->drbs_to_be_released != NULL, "out of memory\n"); - memcpy(f1ap_msg->drbs_to_be_released, req->drbs_to_be_released, n * sizeof(*f1ap_msg->drbs_to_be_released)); - } - if (req->rrc_container_length > 0) { - f1ap_msg->rrc_container = calloc(req->rrc_container_length, sizeof(*f1ap_msg->rrc_container)); - AssertFatal(f1ap_msg->rrc_container != NULL, "out of memory\n"); - f1ap_msg->rrc_container_length = req->rrc_container_length; - memcpy(f1ap_msg->rrc_container, req->rrc_container, req->rrc_container_length); - } - if (req->transm_action_ind != NULL) { - f1ap_msg->transm_action_ind = malloc(sizeof *f1ap_msg->transm_action_ind); - AssertFatal(f1ap_msg->transm_action_ind != NULL, "out of memory\n"); - *f1ap_msg->transm_action_ind = *req->transm_action_ind; - } + F1AP_UE_CONTEXT_MODIFICATION_REQ(msg) = cp_ue_context_mod_req(req); itti_send_msg_to_task(TASK_CU_F1, 0, msg); } diff --git a/openair2/RRC/NR/nr_rrc_proto.h b/openair2/RRC/NR/nr_rrc_proto.h index 3a4fed6411..3ac774c69f 100644 --- a/openair2/RRC/NR/nr_rrc_proto.h +++ b/openair2/RRC/NR/nr_rrc_proto.h @@ -107,14 +107,14 @@ int rrc_gNB_generate_pcch_msg(sctp_assoc_t assoc_id, const NR_SIB1_t *sib, uint3 void rrc_gNB_generate_UeContextSetupRequest(const gNB_RRC_INST *rrc, rrc_gNB_ue_context_t *const ue_context_pP, int n_drbs, - const f1ap_drb_to_be_setup_t *drbs); + const f1ap_drb_to_setup_t *drbs); void rrc_gNB_generate_UeContextModificationRequest(const gNB_RRC_INST *rrc, rrc_gNB_ue_context_t *const ue_context_pP, int n_drbs, - const f1ap_drb_to_be_setup_t *drbs, + const f1ap_drb_to_setup_t *drbs, int n_rel_drbs, - const f1ap_drb_to_be_released_t *rel_drbs); + const f1ap_drb_to_release_t *rel_drbs); void free_RRCReconfiguration_params(nr_rrc_reconfig_param_t params); @@ -123,6 +123,6 @@ byte_array_t rrc_gNB_encode_RRCReconfiguration(gNB_RRC_INST *rrc, gNB_RRC_UE_t * nr_rrc_reconfig_param_t get_RRCReconfiguration_params(gNB_RRC_INST *rrc, gNB_RRC_UE_t *UE, uint8_t srb_reest_bitmap, bool drb_reestablish); pdusession_level_qos_parameter_t *get_qos_characteristics(const int qfi, rrc_pdu_session_param_t *pduSession); -f1ap_qos_characteristics_t get_qos_char_from_qos_flow_param(const pdusession_level_qos_parameter_t *qos_param); +f1ap_qos_flow_param_t get_qos_char_from_qos_flow_param(const pdusession_level_qos_parameter_t *qos_param); void openair_rrc_gNB_configuration(gNB_RRC_INST *rrc, gNB_RrcConfigurationReq *configuration); #endif diff --git a/openair2/RRC/NR/rrc_gNB.c b/openair2/RRC/NR/rrc_gNB.c index e08a0a4d9e..6e53de1c10 100644 --- a/openair2/RRC/NR/rrc_gNB.c +++ b/openair2/RRC/NR/rrc_gNB.c @@ -80,6 +80,7 @@ #include "openair2/F1AP/f1ap_ids.h" #include "openair2/F1AP/lib/f1ap_rrc_message_transfer.h" #include "openair2/F1AP/lib/f1ap_interface_management.h" +#include "openair2/F1AP/lib/f1ap_ue_context.h" #include "rrc_gNB_NGAP.h" #include "rrc_gNB_du.h" #include "rrc_gNB_mobility.h" @@ -1774,12 +1775,14 @@ static void handle_rrcReconfigurationComplete(gNB_RRC_INST *rrc, gNB_RRC_UE_t *U f1_ue_data_t ue_data = cu_get_f1_ue_data(UE->rrc_ue_id); RETURN_IF_INVALID_ASSOC_ID(ue_data.du_assoc_id); - f1ap_ue_context_modif_req_t ue_context_modif_req = { + ReconfigurationCompl_t rc = RRCreconf_success; + f1ap_ue_context_mod_req_t req = { .gNB_CU_ue_id = UE->rrc_ue_id, .gNB_DU_ue_id = ue_data.secondary_ue, - .ReconfigComplOutcome = RRCreconf_success, + .reconfig_compl = &rc, }; - rrc->mac_rrc.ue_context_modification_request(ue_data.du_assoc_id, &ue_context_modif_req); + rrc->mac_rrc.ue_context_modification_request(ue_data.du_assoc_id, &req); + /* nothing to be freed */ } static void rrc_gNB_generate_UECapabilityEnquiry(gNB_RRC_INST *rrc, gNB_RRC_UE_t *ue) @@ -2364,18 +2367,26 @@ pdusession_level_qos_parameter_t *get_qos_characteristics(const int qfi, rrc_pdu } /* \bref return F1AP QoS characteristics based on Qos flow parameters */ -f1ap_qos_characteristics_t get_qos_char_from_qos_flow_param(const pdusession_level_qos_parameter_t *qos_param) +f1ap_qos_flow_param_t get_qos_char_from_qos_flow_param(const pdusession_level_qos_parameter_t *qos_param) { - f1ap_qos_characteristics_t qos_char = {0}; + f1ap_qos_flow_param_t qos_char = {0}; 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; + qos_char.dyn.prio = qos_param->qos_priority; + qos_char.dyn.pdb = 100; // TODO + qos_char.dyn.per.scalar = 10; // TODO + qos_char.dyn.per.exponent = 100; // TODO } else { 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; + qos_char.nondyn.fiveQI = qos_param->fiveQI; } + const ngap_allocation_retention_priority_t *a = &qos_param->allocation_retention_priority; + qos_char.arp.prio = a->priority_level; + qos_char.arp.preempt_cap = a->pre_emp_capability == NGAP_PRE_EMPTION_CAPABILITY_MAY_TRIGGER_PREEMPTION + ? MAY_TRIGGER_PREEMPTION + : SHALL_NOT_TRIGGER_PREEMPTION; + qos_char.arp.preempt_vuln = + a->pre_emp_vulnerability == NGAP_PRE_EMPTION_VULNERABILITY_PREEMPTABLE ? PREEMPTABLE : NOT_PREEMPTABLE; return qos_char; } @@ -2385,38 +2396,52 @@ static int fill_drb_to_be_setup_from_e1_resp(const gNB_RRC_INST *rrc, gNB_RRC_UE_t *UE, const pdu_session_setup_t *pduSession, int numPduSession, - f1ap_drb_to_be_setup_t drbs[32]) + f1ap_drb_to_setup_t drbs[32]) { int nb_drb = 0; for (int p = 0; p < numPduSession; ++p) { - rrc_pdu_session_param_t *RRC_pduSession = find_pduSession(UE, pduSession[p].id, false); - DevAssert(RRC_pduSession); + rrc_pdu_session_param_t *pdu = find_pduSession(UE, pduSession[p].id, false); + DevAssert(pdu); for (int i = 0; i < pduSession[p].numDRBSetup; i++) { 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 ? F1AP_RLC_MODE_UM_BIDIR : F1AP_RLC_MODE_AM; - drb->up_ul_tnl[0].tl_address = drb_config->UpParamList[0].tl_info.tlAddress; - drb->up_ul_tnl[0].port = rrc->eth_params_s.my_portd; - drb->up_ul_tnl[0].teid = drb_config->UpParamList[0].tl_info.teId; - drb->up_ul_tnl_length = 1; + drb_t *rrc_drb = get_drb(UE, pduSession[p].DRBnGRanList[i].id); + DevAssert(rrc_drb); + + f1ap_drb_to_setup_t *drb = &drbs[nb_drb]; + drb->id = rrc_drb->drb_id; + + drb->qos_choice = F1AP_QOS_CHOICE_NR; /* pass QoS info to MAC */ int nb_qos_flows = drb_config->numQosFlowSetup; AssertFatal(nb_qos_flows > 0, "must map at least one flow to a DRB\n"); - drb->drb_info.flows_to_be_setup_length = nb_qos_flows; - drb->drb_info.flows_mapped_to_drb = calloc(nb_qos_flows, sizeof(f1ap_flows_mapped_to_drb_t)); - AssertFatal(drb->drb_info.flows_mapped_to_drb, "could not allocate memory\n"); + drb->nr.flows_len = nb_qos_flows; + drb->nr.flows = calloc_or_fail(nb_qos_flows, sizeof(*drb->nr.flows)); for (int j = 0; j < nb_qos_flows; j++) { - drb->drb_info.flows_mapped_to_drb[j].qfi = drb_config->qosFlows[j].qfi; - pdusession_level_qos_parameter_t *in_qos_char = get_qos_characteristics(drb_config->qosFlows[j].qfi, RRC_pduSession); - drb->drb_info.flows_mapped_to_drb[j].qos_params.qos_characteristics = get_qos_char_from_qos_flow_param(in_qos_char); + int qfi = drb_config->qosFlows[j].qfi; + /* find the QoS characteristics stored at RRC based on QFI returned + * from E1. We expect this to correspond to a QFI we passed to E1 + * previously, so we expect it to exist. */ + pdusession_level_qos_parameter_t *qos_param = get_qos_characteristics(qfi, pdu); + DevAssert(qos_param); + f1ap_drb_flows_mapped_t *flow = &drb->nr.flows[j]; + flow->qfi = qfi; + flow->param = get_qos_char_from_qos_flow_param(qos_param); } /* the DRB QoS parameters: we just reuse the ones from the first flow */ - drb->drb_info.drb_qos = drb->drb_info.flows_mapped_to_drb[0].qos_params; + drb->nr.drb_qos = drb->nr.flows[0].param; /* pass NSSAI info to MAC */ - drb->nssai = RRC_pduSession->param.nssai; + drb->nr.nssai = pdu->param.nssai; + + drb->up_ul_tnl[0].tl_address = drb_config->UpParamList[0].tl_info.tlAddress; + drb->up_ul_tnl[0].teid = drb_config->UpParamList[0].tl_info.teId; + drb->up_ul_tnl_len = 1; + drb->rlc_mode = rrc->configuration.um_on_default_drb ? F1AP_RLC_MODE_UM_BIDIR : F1AP_RLC_MODE_AM; + drb->dl_pdcp_sn_len = malloc_or_fail(sizeof(*drb->dl_pdcp_sn_len)); + *drb->dl_pdcp_sn_len = rrc_drb->pdcp_config.pdcp_SN_SizeDL == 1 ? F1AP_PDCP_SN_18B : F1AP_PDCP_SN_12B; + drb->ul_pdcp_sn_len = malloc_or_fail(sizeof(*drb->ul_pdcp_sn_len)); + *drb->ul_pdcp_sn_len = rrc_drb->pdcp_config.pdcp_SN_SizeUL == 1 ? F1AP_PDCP_SN_18B : F1AP_PDCP_SN_12B; nb_drb++; } @@ -2463,7 +2488,7 @@ void rrc_gNB_process_e1_bearer_context_setup_resp(e1ap_bearer_setup_resp_t *resp } /* Instruction towards the DU for DRB configuration and tunnel creation */ - f1ap_drb_to_be_setup_t drbs[32]; // maximum DRB can be 32 + f1ap_drb_to_setup_t drbs[32]; // maximum DRB can be 32 int nb_drb = fill_drb_to_be_setup_from_e1_resp(rrc, UE, resp->pduSession, resp->numPDUSessions, drbs); if (!UE->f1_ue_context_active) @@ -3001,7 +3026,7 @@ int rrc_gNB_generate_pcch_msg(sctp_assoc_t assoc_id, const NR_SIB1_t *sib1, uint void rrc_gNB_generate_UeContextSetupRequest(const gNB_RRC_INST *rrc, rrc_gNB_ue_context_t *const ue_context_pP, int n_drbs, - const f1ap_drb_to_be_setup_t *drbs) + const f1ap_drb_to_setup_t *drbs) //----------------------------------------------------------------------------- { gNB_RRC_UE_t *ue_p = &ue_context_pP->ue_context; @@ -3009,47 +3034,51 @@ void rrc_gNB_generate_UeContextSetupRequest(const gNB_RRC_INST *rrc, AssertFatal(!NODE_IS_DU(rrc->node_type), "illegal node type DU!\n"); - cu_to_du_rrc_information_t cu2du = {0}; - cu_to_du_rrc_information_t *cu2du_p = NULL; + f1ap_cu_to_du_rrc_info_t cu2du = {0}; if (ue_p->ue_cap_buffer.len > 0 && ue_p->ue_cap_buffer.buf != NULL) { - cu2du_p = &cu2du; - cu2du.uE_CapabilityRAT_ContainerList = ue_p->ue_cap_buffer.buf; - cu2du.uE_CapabilityRAT_ContainerList_length = ue_p->ue_cap_buffer.len; + cu2du.ue_cap = &ue_p->ue_cap_buffer; } int nb_srb = 1; - f1ap_srb_to_be_setup_t srbs[1] = {{.srb_id = 2, .lcid = 2}}; + f1ap_srb_to_setup_t srbs[1] = {{.id = 2, }}; activate_srb(ue_p, 2); + /* gNB-DU UE Aggregate Maximum Bit Rate Uplink is C- ifDRBSetup */ + uint64_t agg_mbr = 1000000000 /* bps */, *agg_mbr_p = NULL; + if (n_drbs > 0) + agg_mbr_p = &agg_mbr; + /* the callback will fill the UE context setup request and forward it */ f1_ue_data_t ue_data = cu_get_f1_ue_data(ue_p->rrc_ue_id); RETURN_IF_INVALID_ASSOC_ID(ue_data.du_assoc_id); - f1ap_ue_context_setup_t ue_context_setup_req = { + f1ap_ue_context_setup_req_t ue_context_setup_req = { .gNB_CU_ue_id = ue_p->rrc_ue_id, - .gNB_DU_ue_id = ue_data.secondary_ue, + .gNB_DU_ue_id = &ue_data.secondary_ue, .plmn.mcc = rrc->configuration.plmn[0].mcc, .plmn.mnc = rrc->configuration.plmn[0].mnc, .plmn.mnc_digit_length = rrc->configuration.plmn[0].mnc_digit_length, .nr_cellid = rrc->nr_cellid, - .servCellId = 0, /* TODO: correct value? */ - .srbs_to_be_setup_length = nb_srb, - .srbs_to_be_setup = srbs, - .drbs_to_be_setup_length = n_drbs, - .drbs_to_be_setup = (f1ap_drb_to_be_setup_t *)drbs, - .cu_to_du_rrc_information = cu2du_p, + .servCellIndex = 0, /* TODO: correct value? */ + .srbs_len = nb_srb, + .srbs = srbs, + .drbs_len = n_drbs, + .drbs = (f1ap_drb_to_setup_t *) drbs, // cast to avoid warning on const + .cu_to_du_rrc_info = cu2du, + .gnb_du_ue_agg_mbr_ul = agg_mbr_p, }; rrc->mac_rrc.ue_context_setup_request(ue_data.du_assoc_id, &ue_context_setup_req); LOG_I(RRC, "UE %d trigger UE context setup request with %d DRBs\n", ue_p->rrc_ue_id, n_drbs); + // nothing to free for ue_context_setup_req } //----------------------------------------------------------------------------- void rrc_gNB_generate_UeContextModificationRequest(const gNB_RRC_INST *rrc, rrc_gNB_ue_context_t *const ue_context_pP, int n_drbs, - const f1ap_drb_to_be_setup_t *drbs, + const f1ap_drb_to_setup_t *drbs, int n_rel_drbs, - const f1ap_drb_to_be_released_t *rel_drbs) + const f1ap_drb_to_release_t *rel_drbs) //----------------------------------------------------------------------------- { gNB_RRC_UE_t *ue_p = &ue_context_pP->ue_context; @@ -3058,30 +3087,23 @@ void rrc_gNB_generate_UeContextModificationRequest(const gNB_RRC_INST *rrc, AssertFatal(!NODE_IS_DU(rrc->node_type), "illegal node type DU!\n"); - cu_to_du_rrc_information_t cu2du = {0}; - cu_to_du_rrc_information_t *cu2du_p = NULL; + f1ap_cu_to_du_rrc_info_t cu2du = {0}; if (ue_p->ue_cap_buffer.len > 0 && ue_p->ue_cap_buffer.buf != NULL) { - cu2du_p = &cu2du; - cu2du.uE_CapabilityRAT_ContainerList = ue_p->ue_cap_buffer.buf; - cu2du.uE_CapabilityRAT_ContainerList_length = ue_p->ue_cap_buffer.len; + cu2du.ue_cap = &ue_p->ue_cap_buffer; } f1_ue_data_t ue_data = cu_get_f1_ue_data(ue_p->rrc_ue_id); RETURN_IF_INVALID_ASSOC_ID(ue_data.du_assoc_id); - f1ap_ue_context_modif_req_t ue_context_modif_req = { + f1ap_ue_context_mod_req_t ue_context_modif_req = { .gNB_CU_ue_id = ue_p->rrc_ue_id, .gNB_DU_ue_id = ue_data.secondary_ue, - .plmn.mcc = rrc->configuration.plmn[0].mcc, - .plmn.mnc = rrc->configuration.plmn[0].mnc, - .plmn.mnc_digit_length = rrc->configuration.plmn[0].mnc_digit_length, - .nr_cellid = rrc->nr_cellid, - .servCellId = 0, /* TODO: correct value? */ - .drbs_to_be_setup_length = n_drbs, - .drbs_to_be_setup = (f1ap_drb_to_be_setup_t *)drbs, - .drbs_to_be_released_length = n_rel_drbs, - .drbs_to_be_released = (f1ap_drb_to_be_released_t *)rel_drbs, - .cu_to_du_rrc_information = cu2du_p, + .drbs_len = n_drbs, + .drbs = (f1ap_drb_to_setup_t *)drbs, + .drbs_rel_len = n_rel_drbs, + .drbs_rel = (f1ap_drb_to_release_t *)rel_drbs, + .cu_to_du_rrc_info = &cu2du, }; rrc->mac_rrc.ue_context_modification_request(ue_data.du_assoc_id, &ue_context_modif_req); LOG_I(RRC, "UE %d trigger UE context modification request with %d DRBs\n", ue_p->rrc_ue_id, n_drbs); + // nothing to free } diff --git a/openair2/RRC/NR/rrc_gNB_mobility.c b/openair2/RRC/NR/rrc_gNB_mobility.c index 647f253989..a08e446ef1 100644 --- a/openair2/RRC/NR/rrc_gNB_mobility.c +++ b/openair2/RRC/NR/rrc_gNB_mobility.c @@ -31,6 +31,7 @@ #include "rrc_gNB_UE_context.h" #include "openair2/LAYER2/NR_MAC_COMMON/nr_mac.h" #include "openair2/F1AP/f1ap_ids.h" +#include "openair2/F1AP/lib/f1ap_ue_context.h" #include "MESSAGES/asn1_msg.h" #include "nr_pdcp/nr_pdcp_oai_api.h" #include "openair3/SECU/key_nas_deriver.h" @@ -61,7 +62,7 @@ static void free_ho_ctx(nr_handover_context_t *ho_ctx) free(ho_ctx); } -static int fill_drb_to_be_setup(const gNB_RRC_INST *rrc, gNB_RRC_UE_t *ue, f1ap_drb_to_be_setup_t drbs[MAX_DRBS_PER_UE]) +static int fill_drb_to_be_setup(const gNB_RRC_INST *rrc, gNB_RRC_UE_t *ue, f1ap_drb_to_setup_t drbs[MAX_DRBS_PER_UE]) { int nb_drb = 0; for (int i = 0; i < MAX_DRBS_PER_UE; ++i) { @@ -69,34 +70,38 @@ static int fill_drb_to_be_setup(const gNB_RRC_INST *rrc, gNB_RRC_UE_t *ue, f1ap_ if (rrc_drb->status == DRB_INACTIVE) continue; - f1ap_drb_to_be_setup_t *drb = &drbs[nb_drb]; + f1ap_drb_to_setup_t *drb = &drbs[nb_drb]; nb_drb++; - drb->drb_id = rrc_drb->drb_id; - drb->rlc_mode = rrc->configuration.um_on_default_drb ? F1AP_RLC_MODE_UM_BIDIR : F1AP_RLC_MODE_AM; - memcpy(&drb->up_ul_tnl[0].tl_address, &rrc_drb->cuup_tunnel_config.addr.buffer, sizeof(uint8_t) * 4); - drb->up_ul_tnl[0].port = rrc->eth_params_s.my_portd; - drb->up_ul_tnl[0].teid = rrc_drb->cuup_tunnel_config.teid; - drb->up_ul_tnl_length = 1; - /* fetch an existing PDU session for this DRB */ - rrc_pdu_session_param_t *pdu = find_pduSession_from_drbId(ue, drb->drb_id); - AssertFatal(pdu != NULL, "no PDU session for DRB ID %ld\n", drb->drb_id); - drb->nssai = pdu->param.nssai; - + rrc_pdu_session_param_t *pdu = find_pduSession_from_drbId(ue, rrc_drb->drb_id); + AssertFatal(pdu != NULL, "no PDU session for DRB ID %d\n", rrc_drb->drb_id); // for the moment, we only support one QoS flow. Put a reminder in case // this changes AssertFatal(pdu->param.nb_qos == 1, "only 1 Qos flow supported\n"); - drb->drb_info.flows_to_be_setup_length = 1; - drb->drb_info.flows_mapped_to_drb = calloc_or_fail(1, sizeof(drb->drb_info.flows_mapped_to_drb[0])); - AssertFatal(drb->drb_info.flows_mapped_to_drb, "could not allocate memory\n"); int qfi = rrc_drb->cnAssociation.sdap_config.mappedQoS_FlowsToAdd[0]; - DevAssert(qfi > 0); - drb->drb_info.flows_mapped_to_drb[0].qfi = qfi; - pdusession_level_qos_parameter_t *in_qos_char = get_qos_characteristics(qfi, pdu); - drb->drb_info.flows_mapped_to_drb[0].qos_params.qos_characteristics = get_qos_char_from_qos_flow_param(in_qos_char); + pdusession_level_qos_parameter_t *qos_param = get_qos_characteristics(qfi, pdu); + drb->id = rrc_drb->drb_id; + + drb->qos_choice = F1AP_QOS_CHOICE_NR; + drb->nr.nssai = pdu->param.nssai; + drb->nr.flows_len = 1; + drb->nr.flows = calloc_or_fail(1, sizeof(*drb->nr.flows)); + DevAssert(qfi > 0); + drb->nr.flows[0].qfi = qfi; + drb->nr.flows[0].param = get_qos_char_from_qos_flow_param(qos_param); /* the DRB QoS parameters: we just reuse the ones from the first flow */ - drb->drb_info.drb_qos = drb->drb_info.flows_mapped_to_drb[0].qos_params; + drb->nr.drb_qos = drb->nr.flows[0].param; + + memcpy(&drb->up_ul_tnl[0].tl_address, &rrc_drb->cuup_tunnel_config.addr.buffer, sizeof(uint8_t) * 4); + drb->up_ul_tnl[0].teid = rrc_drb->cuup_tunnel_config.teid; + drb->up_ul_tnl_len = 1; + + drb->rlc_mode = rrc->configuration.um_on_default_drb ? F1AP_RLC_MODE_UM_BIDIR : F1AP_RLC_MODE_AM; + drb->dl_pdcp_sn_len = malloc_or_fail(sizeof(*drb->dl_pdcp_sn_len)); + *drb->dl_pdcp_sn_len = rrc_drb->pdcp_config.pdcp_SN_SizeDL == 1 ? F1AP_PDCP_SN_18B : F1AP_PDCP_SN_12B; + drb->ul_pdcp_sn_len = malloc_or_fail(sizeof(*drb->ul_pdcp_sn_len)); + *drb->ul_pdcp_sn_len = rrc_drb->pdcp_config.pdcp_SN_SizeUL == 1 ? F1AP_PDCP_SN_18B : F1AP_PDCP_SN_12B;; } return nb_drb; } @@ -168,32 +173,38 @@ static void nr_initiate_handover(const gNB_RRC_INST *rrc, target_du->assoc_id, target_du->setup_req->cell[0].info.nr_pci); - cu_to_du_rrc_information_t cu2du = { - .handoverPreparationInfo = ho_prep_info->buf, - .handoverPreparationInfo_length = ho_prep_info->len, - }; - - f1ap_drb_to_be_setup_t drbs[MAX_DRBS_PER_UE] = {0}; + f1ap_drb_to_setup_t *drbs = calloc_or_fail(MAX_DRBS_PER_UE, sizeof(*drbs)); int nb_drb = fill_drb_to_be_setup(rrc, ue, drbs); - f1ap_srb_to_be_setup_t srbs[2] = {{.srb_id = 1, .lcid = 1}, {.srb_id = 2, .lcid = 2}}; + int nb_srb = 2; + f1ap_srb_to_setup_t *srbs = calloc_or_fail(nb_srb, sizeof(*srbs)); + srbs[0].id = 1; + srbs[1].id = 2; + + byte_array_t *hpi = malloc_or_fail(sizeof(*hpi)); + *hpi = copy_byte_array(*ho_prep_info); + + uint64_t *ue_agg_mbr = malloc_or_fail(sizeof(*ue_agg_mbr)); + *ue_agg_mbr = 1000000000 /*bps*/; + f1ap_served_cell_info_t *cell_info = &target_du->setup_req->cell[0].info; RETURN_IF_INVALID_ASSOC_ID(target_du->assoc_id); - f1ap_ue_context_setup_t ue_context_setup_req = { + f1ap_ue_context_setup_req_t ue_context_setup_req = { .gNB_CU_ue_id = ue->rrc_ue_id, - .gNB_DU_ue_id = 0, /* TODO: this should be optional! */ .plmn.mcc = cell_info->plmn.mcc, .plmn.mnc = cell_info->plmn.mnc, .plmn.mnc_digit_length = cell_info->plmn.mnc_digit_length, .nr_cellid = cell_info->nr_cellid, - .servCellId = 0, // TODO: correct value? - .srbs_to_be_setup_length = 2, - .srbs_to_be_setup = srbs, - .drbs_to_be_setup_length = nb_drb, - .drbs_to_be_setup = drbs, - .cu_to_du_rrc_information = &cu2du, + .servCellIndex = 0, // TODO: correct value? + .srbs_len = nb_srb, + .srbs = srbs, + .drbs_len = nb_drb, + .drbs = drbs, + .cu_to_du_rrc_info.ho_prep_info = hpi, + .gnb_du_ue_agg_mbr_ul = ue_agg_mbr, }; rrc->mac_rrc.ue_context_setup_request(target_du->assoc_id, &ue_context_setup_req); + free_ue_context_setup_req(&ue_context_setup_req); } /* @@ -214,15 +225,15 @@ void nr_rrc_trigger_n2_ho(gNB_RRC_INST *rrc, int nr_cgi, uint8_t *ho_prep_info, typedef struct deliver_ue_ctxt_modification_data_t { gNB_RRC_INST *rrc; - f1ap_ue_context_modif_req_t *modification_req; + f1ap_ue_context_mod_req_t *modification_req; sctp_assoc_t assoc_id; } deliver_ue_ctxt_modification_data_t; static void rrc_deliver_ue_ctxt_modif_req(void *deliver_pdu_data, ue_id_t ue_id, int srb_id, char *buf, int size, int sdu_id) { DevAssert(deliver_pdu_data != NULL); deliver_ue_ctxt_modification_data_t *data = deliver_pdu_data; - data->modification_req->rrc_container = (uint8_t*)buf; - data->modification_req->rrc_container_length = size; + byte_array_t ba = {.buf = (uint8_t *) buf, .len = size}; + data->modification_req->rrc_container = &ba; data->rrc->mac_rrc.ue_context_modification_request(data->assoc_id, data->modification_req); } static void rrc_gNB_trigger_reconfiguration_for_handover(gNB_RRC_INST *rrc, gNB_RRC_UE_t *ue, uint8_t *rrc_reconf, int rrc_reconf_len) @@ -231,12 +242,9 @@ static void rrc_gNB_trigger_reconfiguration_for_handover(gNB_RRC_INST *rrc, gNB_ TransmActionInd_t transmission_action_indicator = TransmActionInd_STOP; RETURN_IF_INVALID_ASSOC_ID(ue_data.du_assoc_id); - f1ap_ue_context_modif_req_t ue_context_modif_req = { + f1ap_ue_context_mod_req_t ue_context_modif_req = { .gNB_CU_ue_id = ue->rrc_ue_id, .gNB_DU_ue_id = ue_data.secondary_ue, - .plmn = rrc->configuration.plmn[0], - .nr_cellid = rrc->nr_cellid, // TODO target cell ID - .servCellId = 0, // TODO: correct value? .transm_action_ind = &transmission_action_indicator, }; deliver_ue_ctxt_modification_data_t data = {.rrc = rrc, diff --git a/openair2/RRC/NR/rrc_gNB_nsa.c b/openair2/RRC/NR/rrc_gNB_nsa.c index 8ac172a21e..1ccdb3439a 100644 --- a/openair2/RRC/NR/rrc_gNB_nsa.c +++ b/openair2/RRC/NR/rrc_gNB_nsa.c @@ -71,6 +71,7 @@ #include "xer_decoder.h" #include "xer_encoder.h" #include "f1ap_common.h" +#include "lib/f1ap_ue_context.h" // In case of phy-test and do-ra mode, read UE capabilities directly from file // and put it into a CG-ConfigInfo field @@ -137,18 +138,16 @@ void rrc_add_nsa_user(gNB_RRC_INST *rrc, x2ap_ENDC_sgnb_addition_req_t *m, sctp_ nr_pdcp_entity_security_keys_and_algos_t security_parameters = {0}; uint8_t tmp[1024]; - uint8_t *cgci_buf = NULL; - uint32_t cgci_len = 0; + byte_array_t cgci = {0}; if (get_softmodem_params()->phy_test == 1 || get_softmodem_params()->do_ra == 1) { DevAssert(m == NULL); UE->rb_config = get_default_rbconfig(10 /* EPS bearer ID */, 1 /* drb ID */, NR_CipheringAlgorithm_nea0, NR_SecurityConfig__keyToUse_master, &rrc->pdcp_config); - cgci_len = cg_config_info_from_ue_cap_file(sizeof tmp, tmp); - DevAssert(cgci_len > 0); - cgci_buf = tmp; + int len = cg_config_info_from_ue_cap_file(sizeof tmp, tmp); + DevAssert(len > 0); + cgci = create_byte_array(len, tmp); } else { DevAssert(m != NULL); - cgci_buf = m->rrc_buffer; - cgci_len = m->rrc_buffer_size; + cgci = create_byte_array(m->rrc_buffer_size, m->rrc_buffer); /* TODO: handle more than one bearer */ if (m->nb_e_rabs_tobeadded != 1) { @@ -272,25 +271,24 @@ void rrc_add_nsa_user(gNB_RRC_INST *rrc, x2ap_ENDC_sgnb_addition_req_t *m, sctp_ UE->rb_config->drb_ToAddModList, &security_parameters); - cu_to_du_rrc_information_t cu2du = { - .cG_ConfigInfo = cgci_buf, - .cG_ConfigInfo_length = cgci_len, - }; /* assumption: only a single bearer, see above */ NR_DRB_ToAddModList_t *rb_list = UE->rb_config->drb_ToAddModList; AssertFatal(rb_list->list.count == 1, "can only handle one bearer for NSA/phy-test/do-ra, but has %d\n", rb_list->list.count); int drb_id = rb_list->list.array[0]->drb_Identity; - f1ap_flows_mapped_to_drb_t *flow = calloc(1, sizeof(f1ap_flows_mapped_to_drb_t)); - flow->qos_params.qos_characteristics.qos_type = NON_DYNAMIC; - flow->qfi = flow->qos_params.qos_characteristics.non_dynamic.fiveqi = 9; - f1ap_drb_to_be_setup_t drbs = { - .drb_id = drb_id, - .rlc_mode = F1AP_RLC_MODE_UM_BIDIR, // hardcoded keep it backwards compatible for now - // rrc->configuration.um_on_default_drb ? F1AP_RLC_MODE_UM_BIDIR : F1AP_RLC_MODE_AM, - .up_ul_tnl_length = 1, - .drb_info.flows_to_be_setup_length = 1, - .drb_info.flows_mapped_to_drb = flow, - }; + f1ap_drb_to_setup_t *drb = calloc_or_fail(1, sizeof(*drb)); + drb->id = drb_id; + // hardcoded keep it backwards compatible for now + // rrc->configuration.um_on_default_drb ? F1AP_RLC_MODE_UM_BIDIR : F1AP_RLC_MODE_AM, + drb->rlc_mode = F1AP_RLC_MODE_UM_BIDIR; + drb->up_ul_tnl_len = 1; + drb->qos_choice = F1AP_QOS_CHOICE_NR; // we don't have EUTRAN yet, "approximate" it + drb->nr.flows_len = 1; + f1ap_drb_flows_mapped_t *flow = drb->nr.flows = calloc_or_fail(drb->nr.flows_len, sizeof(*flow)); + flow->qfi = 9; + flow->param.qos_type = NON_DYNAMIC; + flow->param.nondyn.fiveQI = 9; + flow->param.arp.prio = 5; + // Note: E1 support for NSA/phy-test/do-ra not implemented yet instance_t f1inst = get_f1_gtp_instance(); if (f1inst >= 0) { @@ -305,25 +303,30 @@ void rrc_add_nsa_user(gNB_RRC_INST *rrc, x2ap_ENDC_sgnb_addition_req_t *m, sctp_ gtpv1u_gnb_create_tunnel_resp_t resp = {0}; int ret = gtpv1u_create_ngu_tunnel(f1inst, &req, &resp, NULL, NULL); AssertFatal(ret == 0, "gtpv1u_create_ngu_tunnel failed: ret %d\n", ret); - drbs.up_ul_tnl[0].port = rrc->eth_params_s.my_portd; - memcpy(&drbs.up_ul_tnl[0].tl_address, &resp.gnb_addr.buffer, 4); - drbs.up_ul_tnl[0].teid = resp.gnb_NGu_teid[0]; + memcpy(&drb->up_ul_tnl[0].tl_address, &resp.gnb_addr.buffer, 4); + drb->up_ul_tnl[0].teid = resp.gnb_NGu_teid[0]; + drb->up_ul_tnl_len = 1; } - f1ap_ue_context_setup_t req = { + uint64_t *ue_agg_mbr_ul = malloc_or_fail(sizeof(*ue_agg_mbr_ul)); + *ue_agg_mbr_ul = 1000000000; + byte_array_t *cg_configinfo = malloc_or_fail(sizeof(*cg_configinfo)); + *cg_configinfo = cgci; + f1ap_ue_context_setup_req_t req = { .gNB_CU_ue_id = UE->rrc_ue_id, - .gNB_DU_ue_id = 0xffffffff, /* not known yet */ .plmn.mcc = rrc->configuration.plmn[0].mcc, .plmn.mnc = rrc->configuration.plmn[0].mnc, .plmn.mnc_digit_length = rrc->configuration.plmn[0].mnc_digit_length, .nr_cellid = rrc->nr_cellid, - .servCellId = 0, - .drbs_to_be_setup_length = 1, - .drbs_to_be_setup = &drbs, - .cu_to_du_rrc_information = &cu2du, + .servCellIndex = 0, + .drbs_len = 1, + .drbs = drb, + .cu_to_du_rrc_info.cg_configinfo = cg_configinfo, + .gnb_du_ue_agg_mbr_ul = ue_agg_mbr_ul, }; f1_ue_data_t ue_data = cu_get_f1_ue_data(UE->rrc_ue_id); RETURN_IF_INVALID_ASSOC_ID(ue_data.du_assoc_id); rrc->mac_rrc.ue_context_setup_request(ue_data.du_assoc_id, &req); + free_ue_context_setup_req(&req); } static NR_RRCReconfiguration_IEs_t *get_default_reconfig(const NR_CellGroupConfig_t *secondaryCellGroup) From 6956e6ed11b5bc9d895ac7820e0b2d9ff19e3490 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Mon, 2 Jun 2025 09:01:38 +0200 Subject: [PATCH 12/36] Add F1AP UE context setup response message enc/dec + test See commit "Add F1AP UE context setup request message enc/dec + test" for more details on the approach taken. --- openair2/COMMON/f1ap_messages_types.h | 32 +++ openair2/F1AP/lib/f1ap_lib_includes.h | 1 + openair2/F1AP/lib/f1ap_ue_context.c | 375 ++++++++++++++++++++++++++ openair2/F1AP/lib/f1ap_ue_context.h | 6 + openair2/F1AP/tests/f1ap_lib_test.c | 96 +++++++ 5 files changed, 510 insertions(+) diff --git a/openair2/COMMON/f1ap_messages_types.h b/openair2/COMMON/f1ap_messages_types.h index 73b8162eb4..c8ebde936a 100644 --- a/openair2/COMMON/f1ap_messages_types.h +++ b/openair2/COMMON/f1ap_messages_types.h @@ -460,6 +460,11 @@ typedef struct f1ap_cu_to_du_rrc_info_s { byte_array_t *ho_prep_info; } f1ap_cu_to_du_rrc_info_t; +typedef struct f1ap_du_to_cu_rrc_info_t { + byte_array_t cell_group_config; + byte_array_t *meas_gap_config; +} f1ap_du_to_cu_rrc_info_t; + typedef struct du_to_cu_rrc_information_s { uint8_t * cellGroupConfig; uint32_t cellGroupConfig_length; @@ -494,6 +499,11 @@ typedef struct f1ap_srb_to_setup_t { int id; } f1ap_srb_to_setup_t; +typedef struct f1ap_srb_setup_t { + int id; + int lcid; +} f1ap_srb_setup_t; + /// 9.3.1.52 Packet Error Rate typedef struct f1ap_per_t { uint8_t scalar; @@ -560,6 +570,13 @@ typedef struct f1ap_drb_to_setup_t { f1ap_pdcp_sn_len_t *ul_pdcp_sn_len; } f1ap_drb_to_setup_t; +typedef struct f1ap_drb_setup_t { + int id; + int *lcid; + int up_dl_tnl_len; + f1ap_up_tnl_t up_dl_tnl[2]; +} f1ap_drb_setup_t; + typedef struct f1ap_drb_to_release_t { int id; } f1ap_drb_to_release_t; @@ -585,6 +602,21 @@ typedef struct f1ap_ue_context_setup_req_s { uint64_t *gnb_du_ue_agg_mbr_ul; // C-ifDRBSetup } f1ap_ue_context_setup_req_t; +typedef struct f1ap_ue_context_setup_resp_s { + uint32_t gNB_CU_ue_id; + uint32_t gNB_DU_ue_id; + + f1ap_du_to_cu_rrc_info_t du_to_cu_rrc_info; + + uint16_t *crnti; + + int drbs_len; + f1ap_drb_setup_t *drbs; + + int srbs_len; + f1ap_srb_setup_t *srbs; +} f1ap_ue_context_setup_resp_t; + typedef struct f1ap_ue_context_mod_req_t { uint32_t gNB_CU_ue_id; uint32_t gNB_DU_ue_id; diff --git a/openair2/F1AP/lib/f1ap_lib_includes.h b/openair2/F1AP/lib/f1ap_lib_includes.h index e34ec0598d..3f039bf6f0 100644 --- a/openair2/F1AP/lib/f1ap_lib_includes.h +++ b/openair2/F1AP/lib/f1ap_lib_includes.h @@ -46,5 +46,6 @@ #include "F1AP_Flows-Mapped-To-DRB-Item.h" #include "F1AP_NonDynamic5QIDescriptor.h" #include "F1AP_Dynamic5QIDescriptor.h" +#include "F1AP_DLUPTNLInformation-ToBeSetup-Item.h" #endif /* F1AP_LIB_INCLUDES_H_ */ diff --git a/openair2/F1AP/lib/f1ap_ue_context.c b/openair2/F1AP/lib/f1ap_ue_context.c index 332b0ad130..1559ee30d9 100644 --- a/openair2/F1AP/lib/f1ap_ue_context.c +++ b/openair2/F1AP/lib/f1ap_ue_context.c @@ -138,6 +138,58 @@ static void free_cu_to_du_rrc_info(f1ap_cu_to_du_rrc_info_t *cu2du) FREE_OPT_BYTE_ARRAY(cu2du->ho_prep_info); } +static F1AP_DUtoCURRCInformation_t encode_du_to_cu_rrc_info(const f1ap_du_to_cu_rrc_info_t *du2cu) +{ + F1AP_DUtoCURRCInformation_t enc = {0}; + + /* mandatory: cellGroupConfig */ + const byte_array_t *ba = &du2cu->cell_group_config; + OCTET_STRING_fromBuf(&enc.cellGroupConfig, (const char *)ba->buf, ba->len); + + /* optional: MeasGapConfig */ + if (du2cu->meas_gap_config) { + ba = du2cu->meas_gap_config; + asn1cCalloc(enc.measGapConfig, measGapConfig); + OCTET_STRING_fromBuf(measGapConfig, (const char *)ba->buf, ba->len); + } + + return enc; +} + +static bool decode_du_to_cu_rrc_info(f1ap_du_to_cu_rrc_info_t *dec, const F1AP_DUtoCURRCInformation_t *du2cu) +{ + const F1AP_CellGroupConfig_t *cgc = &du2cu->cellGroupConfig; + dec->cell_group_config = create_byte_array(cgc->size, (uint8_t *)cgc->buf); + + if (du2cu->measGapConfig) { + const F1AP_MeasGapConfig_t *mgc = du2cu->measGapConfig; + dec->meas_gap_config = calloc_or_fail(1, sizeof(*dec->meas_gap_config)); + *dec->meas_gap_config = create_byte_array(mgc->size, (uint8_t *)mgc->buf); + } + return true; +} + +static f1ap_du_to_cu_rrc_info_t cp_du_to_cu_rrc_info(const f1ap_du_to_cu_rrc_info_t *src) +{ + f1ap_du_to_cu_rrc_info_t cp = {0}; + cp.cell_group_config = copy_byte_array(src->cell_group_config); + CP_OPT_BYTE_ARRAY(cp.meas_gap_config, src->meas_gap_config); + return cp; +} + +static bool eq_du_to_cu_rrc_info(const f1ap_du_to_cu_rrc_info_t *a, const f1ap_du_to_cu_rrc_info_t *b) +{ + _F1_CHECK_EXP(eq_byte_array(&a->cell_group_config, &b->cell_group_config)); + _F1_EQ_CHECK_OPTIONAL_IE(a, b, meas_gap_config, eq_ba); + return true; +} + +static void free_du_to_cu_rrc_info(f1ap_du_to_cu_rrc_info_t *du2cu) +{ + free_byte_array(du2cu->cell_group_config); + FREE_OPT_BYTE_ARRAY(du2cu->meas_gap_config); +} + /* \brief Encode SRB-ToBeSetup List, for UE Context Setup Request, from * f1ap_srb_to_setup_t. */ static F1AP_SRBs_ToBeSetup_List_t encode_srbs_to_setup(int n, const f1ap_srb_to_setup_t *srbs) @@ -231,6 +283,59 @@ static void free_srb_to_setup(f1ap_srb_to_setup_t *srbs) // nothing to free } +static F1AP_SRBs_Setup_List_t encode_srbs_setup(int n, const f1ap_srb_setup_t *srbs) +{ + F1AP_SRBs_Setup_List_t list = {0}; + for (int i = 0; i < n; ++i) { + asn1cSequenceAdd(list, F1AP_SRBs_Setup_ItemIEs_t, itie); + itie->id = F1AP_ProtocolIE_ID_id_SRBs_Setup_Item; + itie->criticality = F1AP_Criticality_ignore; + itie->value.present = F1AP_SRBs_Setup_ItemIEs__value_PR_SRBs_Setup_Item; + F1AP_SRBs_Setup_Item_t *it = &itie->value.choice.SRBs_Setup_Item; + it->sRBID = srbs[i].id; + it->lCID = srbs[i].lcid; + } + return list; +} + +static bool decode_srbs_setup(const F1AP_SRBs_Setup_List_t *f1ap, int *n, f1ap_srb_setup_t **out) +{ + DevAssert(out != NULL); + *out = NULL; + int count = *n = f1ap->list.count; + if (count == 0) + return true; + + f1ap_srb_setup_t *srbs = *out = calloc_or_fail(count, sizeof(*srbs)); + for (int i = 0; i < count; ++i) { + const F1AP_SRBs_Setup_ItemIEs_t *itie = (F1AP_SRBs_Setup_ItemIEs_t *)f1ap->list.array[i]; + _F1_EQ_CHECK_LONG(itie->id, F1AP_ProtocolIE_ID_id_SRBs_Setup_Item); + _F1_EQ_CHECK_INT(itie->value.present, F1AP_SRBs_Setup_ItemIEs__value_PR_SRBs_Setup_Item); + const F1AP_SRBs_Setup_Item_t *it = &itie->value.choice.SRBs_Setup_Item; + srbs[i].id = it->sRBID; + srbs[i].lcid = it->lCID; + } + return true; +} + +static f1ap_srb_setup_t cp_srb_setup(const f1ap_srb_setup_t *orig) +{ + f1ap_srb_setup_t cp = {.id = orig->id, .lcid = orig->lcid}; + return cp; +} + +static bool eq_srb_setup(const f1ap_srb_setup_t *a, const f1ap_srb_setup_t *b) +{ + _F1_EQ_CHECK_INT(a->id, b->id); + _F1_EQ_CHECK_INT(a->lcid, b->lcid); + return true; +} + +static void free_srb_setup(f1ap_srb_setup_t *srbs) +{ + // nothing to free +} + static F1AP_QoSFlowLevelQoSParameters_t encode_qos_flow_param(const f1ap_qos_flow_param_t *p) { F1AP_QoSFlowLevelQoSParameters_t f1ap = {0}; @@ -784,6 +889,88 @@ static void free_drb_to_setup(f1ap_drb_to_setup_t *drb) free(drb->ul_pdcp_sn_len); } +static F1AP_DRBs_Setup_List_t encode_drbs_setup(int n, const f1ap_drb_setup_t *drbs) +{ + F1AP_DRBs_Setup_List_t list = {0}; + for (int i = 0; i < n; ++i) { + const f1ap_drb_setup_t *drb = &drbs[i]; + asn1cSequenceAdd(list, F1AP_DRBs_Setup_ItemIEs_t, itie); + itie->id = F1AP_ProtocolIE_ID_id_DRBs_Setup_Item; + itie->criticality = F1AP_Criticality_ignore; + itie->value.present = F1AP_DRBs_Setup_ItemIEs__value_PR_DRBs_Setup_Item; + + F1AP_DRBs_Setup_Item_t *it = &itie->value.choice.DRBs_Setup_Item; + it->dRBID = drb->id; + if (drb->lcid) + asn1cCallocOne(it->lCID, *drb->lcid); + for (int j = 0; j < drb->up_dl_tnl_len; ++j) { + DevAssert(drb->up_dl_tnl[j].teid > 0); + asn1cSequenceAdd(it->dLUPTNLInformation_ToBeSetup_List.list, F1AP_DLUPTNLInformation_ToBeSetup_Item_t, tnl_it); + tnl_it->dLUPTNLInformation = encode_up_tnl(&drb->up_dl_tnl[j]); + } + } + return list; +} + +static bool decode_drbs_setup(const F1AP_DRBs_Setup_List_t *f1ap, int *n, f1ap_drb_setup_t **out) +{ + DevAssert(out != NULL); + *out = NULL; + int count = *n = f1ap->list.count; + if (count == 0) + return true; + + f1ap_drb_setup_t *drbs = *out = calloc_or_fail(count, sizeof(*drbs)); + for (int i = 0; i < count; ++i) { + const F1AP_DRBs_Setup_ItemIEs_t *itie = (const F1AP_DRBs_Setup_ItemIEs_t *)f1ap->list.array[i]; + _F1_EQ_CHECK_LONG(itie->id, F1AP_ProtocolIE_ID_id_DRBs_Setup_Item); + _F1_EQ_CHECK_INT(itie->value.present, F1AP_DRBs_Setup_ItemIEs__value_PR_DRBs_Setup_Item); + const F1AP_DRBs_Setup_Item_t *it = &itie->value.choice.DRBs_Setup_Item; + + f1ap_drb_setup_t *drb = &drbs[i]; + drb->id = it->dRBID; + if (it->lCID) + _F1_MALLOC(drb->lcid, *it->lCID); + + drb->up_dl_tnl_len = it->dLUPTNLInformation_ToBeSetup_List.list.count; + _F1_EQ_CHECK_GENERIC(drb->up_dl_tnl_len > 0 && drb->up_dl_tnl_len <= 2, "%d", drb->up_dl_tnl_len, 1); + for (int j = 0; j < drb->up_dl_tnl_len; ++j) { + F1AP_DLUPTNLInformation_ToBeSetup_Item_t *it_tnl = it->dLUPTNLInformation_ToBeSetup_List.list.array[j]; + _F1_CHECK_EXP(decode_up_tnl(&it_tnl->dLUPTNLInformation, &drb->up_dl_tnl[j])); + } + } + + return true; +} + +static f1ap_drb_setup_t cp_drb_setup(const f1ap_drb_setup_t *orig) +{ + f1ap_drb_setup_t cp = { + .id = orig->id, + .up_dl_tnl_len = orig->up_dl_tnl_len, + .up_dl_tnl[0] = cp_up_tnl(&orig->up_dl_tnl[0]), + .up_dl_tnl[1] = cp_up_tnl(&orig->up_dl_tnl[1]), + }; + if (orig->lcid) + _F1_MALLOC(cp.lcid, *orig->lcid); + return cp; +} + +static bool eq_drb_setup(const f1ap_drb_setup_t *a, const f1ap_drb_setup_t *b) +{ + _F1_EQ_CHECK_INT(a->id, b->id); + _F1_EQ_CHECK_OPTIONAL_IE(a, b, lcid, _F1_EQ_CHECK_INT); + _F1_EQ_CHECK_INT(a->up_dl_tnl_len, b->up_dl_tnl_len); + for (int i = 0; i < a->up_dl_tnl_len; ++i) + _F1_CHECK_EXP(eq_up_tnl(&a->up_dl_tnl[i], &b->up_dl_tnl[i])); + return true; +} + +static void free_drb_setup(f1ap_drb_setup_t *drb) +{ + free(drb->lcid); +} + static F1AP_DRBs_ToBeReleased_List_t encode_drbs_to_release(int n, const f1ap_drb_to_release_t *drbs) { F1AP_DRBs_ToBeReleased_List_t list = {0}; @@ -1087,6 +1274,194 @@ void free_ue_context_setup_req(f1ap_ue_context_setup_req_t *req) free(req->gnb_du_ue_agg_mbr_ul); } +/** + * @brief Encode F1 UE context setup response to ASN.1 + */ +F1AP_F1AP_PDU_t *encode_ue_context_setup_resp(const f1ap_ue_context_setup_resp_t *msg) +{ + F1AP_F1AP_PDU_t *pdu = calloc_or_fail(1, sizeof(*pdu)); + + /* Message Type */ + pdu->present = F1AP_F1AP_PDU_PR_successfulOutcome; + asn1cCalloc(pdu->choice.successfulOutcome, tmp); + tmp->procedureCode = F1AP_ProcedureCode_id_UEContextSetup; + tmp->criticality = F1AP_Criticality_reject; + tmp->value.present = F1AP_SuccessfulOutcome__value_PR_UEContextSetupResponse; + F1AP_UEContextSetupResponse_t *out = &tmp->value.choice.UEContextSetupResponse; + + /* mandatory: GNB_CU_UE_F1AP_ID */ + asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextSetupResponseIEs_t, ie1); + ie1->id = F1AP_ProtocolIE_ID_id_gNB_CU_UE_F1AP_ID; + ie1->criticality = F1AP_Criticality_reject; + ie1->value.present = F1AP_UEContextSetupResponseIEs__value_PR_GNB_CU_UE_F1AP_ID; + ie1->value.choice.GNB_CU_UE_F1AP_ID = msg->gNB_CU_ue_id; + + /* mandatory: GNB_DU_UE_F1AP_ID */ + asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextSetupResponseIEs_t, ie2); + ie2->id = F1AP_ProtocolIE_ID_id_gNB_DU_UE_F1AP_ID; + ie2->criticality = F1AP_Criticality_reject; + ie2->value.present = F1AP_UEContextSetupResponseIEs__value_PR_GNB_DU_UE_F1AP_ID; + ie2->value.choice.GNB_DU_UE_F1AP_ID = msg->gNB_DU_ue_id; + + /* mandatory: DUtoCURRCInformation */ + asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextSetupResponseIEs_t, ie3); + ie3->id = F1AP_ProtocolIE_ID_id_DUtoCURRCInformation; + ie3->criticality = F1AP_Criticality_reject; + ie3->value.present = F1AP_UEContextSetupResponseIEs__value_PR_DUtoCURRCInformation; + ie3->value.choice.DUtoCURRCInformation = encode_du_to_cu_rrc_info(&msg->du_to_cu_rrc_info); + + /* optional: C-RNTI */ + if (msg->crnti) { + asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextSetupResponseIEs_t, ie4); + ie4->id = F1AP_ProtocolIE_ID_id_C_RNTI; + ie4->criticality = F1AP_Criticality_ignore; + ie4->value.present = F1AP_UEContextSetupResponseIEs__value_PR_C_RNTI; + ie4->value.choice.C_RNTI = *msg->crnti; + } + + /* optional: DRB Setup List */ + if (msg->drbs_len > 0) { + asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextSetupResponseIEs_t, ie7); + ie7->id = F1AP_ProtocolIE_ID_id_DRBs_Setup_List; + ie7->criticality = F1AP_Criticality_ignore; + ie7->value.present = F1AP_UEContextSetupResponseIEs__value_PR_DRBs_Setup_List; + ie7->value.choice.DRBs_Setup_List = encode_drbs_setup(msg->drbs_len, msg->drbs); + } + + /* optional: SRB Setup List */ + if (msg->srbs_len > 0) { + asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextSetupResponseIEs_t, ie11); + ie11->id = F1AP_ProtocolIE_ID_id_SRBs_Setup_List; + ie11->criticality = F1AP_Criticality_ignore; + ie11->value.present = F1AP_UEContextSetupResponseIEs__value_PR_SRBs_Setup_List; + ie11->value.choice.SRBs_Setup_List = encode_srbs_setup(msg->srbs_len, msg->srbs); + } + + return pdu; +} + +/** + * @brief Decode F1 UE Context Setup Response + */ +bool decode_ue_context_setup_resp(const struct F1AP_F1AP_PDU *pdu, f1ap_ue_context_setup_resp_t *out) +{ + DevAssert(out != NULL); + memset(out, 0, sizeof(*out)); + + F1AP_UEContextSetupResponse_t *in = &pdu->choice.successfulOutcome->value.choice.UEContextSetupResponse; + F1AP_UEContextSetupResponseIEs_t *ie; + + F1AP_LIB_FIND_IE(F1AP_UEContextSetupResponseIEs_t, ie, &in->protocolIEs.list, F1AP_ProtocolIE_ID_id_gNB_CU_UE_F1AP_ID, true); + F1AP_LIB_FIND_IE(F1AP_UEContextSetupResponseIEs_t, ie, &in->protocolIEs.list, F1AP_ProtocolIE_ID_id_gNB_DU_UE_F1AP_ID, true); + F1AP_LIB_FIND_IE(F1AP_UEContextSetupResponseIEs_t, ie, &in->protocolIEs.list, F1AP_ProtocolIE_ID_id_DUtoCURRCInformation, true); + + for (int i = 0; i < in->protocolIEs.list.count; ++i) { + ie = in->protocolIEs.list.array[i]; + AssertError(ie != NULL, return false, "in->protocolIEs.list.array[i] is NULL"); + switch (ie->id) { + case F1AP_ProtocolIE_ID_id_gNB_CU_UE_F1AP_ID: + _F1_EQ_CHECK_INT(ie->value.present, F1AP_UEContextSetupResponseIEs__value_PR_GNB_CU_UE_F1AP_ID); + out->gNB_CU_ue_id = ie->value.choice.GNB_CU_UE_F1AP_ID; + break; + case F1AP_ProtocolIE_ID_id_gNB_DU_UE_F1AP_ID: + _F1_EQ_CHECK_INT(ie->value.present, F1AP_UEContextSetupResponseIEs__value_PR_GNB_DU_UE_F1AP_ID); + out->gNB_DU_ue_id = ie->value.choice.GNB_DU_UE_F1AP_ID; + break; + case F1AP_ProtocolIE_ID_id_DUtoCURRCInformation: + _F1_EQ_CHECK_INT(ie->value.present, F1AP_UEContextSetupResponseIEs__value_PR_DUtoCURRCInformation); + _F1_CHECK_EXP(decode_du_to_cu_rrc_info(&out->du_to_cu_rrc_info, &ie->value.choice.DUtoCURRCInformation)); + break; + case F1AP_ProtocolIE_ID_id_C_RNTI: + _F1_EQ_CHECK_INT(ie->value.present, F1AP_UEContextSetupResponseIEs__value_PR_C_RNTI); + _F1_MALLOC(out->crnti, ie->value.choice.C_RNTI); + break; + case F1AP_ProtocolIE_ID_id_DRBs_Setup_List: + _F1_EQ_CHECK_INT(ie->value.present, F1AP_UEContextSetupResponseIEs__value_PR_DRBs_Setup_List); + _F1_CHECK_EXP(decode_drbs_setup(&ie->value.choice.DRBs_Setup_List, &out->drbs_len, &out->drbs)); + break; + case F1AP_ProtocolIE_ID_id_SRBs_Setup_List: + _F1_EQ_CHECK_INT(ie->value.present, F1AP_UEContextSetupResponseIEs__value_PR_SRBs_Setup_List); + _F1_CHECK_EXP(decode_srbs_setup(&ie->value.choice.SRBs_Setup_List, &out->srbs_len, &out->srbs)); + break; + default: + PRINT_ERROR("F1AP_ProtocolIE_ID_id %ld unknown, skipping\n", ie->id); + break; + } + } + + return true; +} + +/** + * @brief F1 UE Context Setup Response deep copy + */ +f1ap_ue_context_setup_resp_t cp_ue_context_setup_resp(const f1ap_ue_context_setup_resp_t *orig) +{ + f1ap_ue_context_setup_resp_t cp = { + .gNB_CU_ue_id = orig->gNB_CU_ue_id, + .gNB_DU_ue_id = orig->gNB_DU_ue_id, + .du_to_cu_rrc_info = cp_du_to_cu_rrc_info(&orig->du_to_cu_rrc_info), + // crnti below + .drbs_len = orig->drbs_len, + // drbs below + .srbs_len = orig->srbs_len, + // srbs below + }; + if (orig->crnti) + _F1_MALLOC(cp.crnti, *orig->crnti); + if (orig->drbs_len > 0 && orig->drbs) { + cp.drbs = calloc_or_fail(orig->drbs_len, sizeof(*cp.drbs)); + cp.drbs_len = orig->drbs_len; + for (int i = 0; i < cp.drbs_len; ++i) + cp.drbs[i] = cp_drb_setup(&orig->drbs[i]); + } + if (orig->srbs_len > 0 && orig->srbs) { + cp.srbs = calloc_or_fail(orig->srbs_len, sizeof(*cp.srbs)); + cp.srbs_len = orig->srbs_len; + for (int i = 0; i < cp.srbs_len; ++i) + cp.srbs[i] = cp_srb_setup(&orig->srbs[i]); + } + return cp; +} + +/** + * @brief F1 UE Context Setup Response equality check + */ +bool eq_ue_context_setup_resp(const f1ap_ue_context_setup_resp_t *a, const f1ap_ue_context_setup_resp_t *b) +{ + _F1_EQ_CHECK_INT(a->gNB_CU_ue_id, b->gNB_CU_ue_id); + _F1_EQ_CHECK_INT(a->gNB_DU_ue_id, b->gNB_DU_ue_id); + _F1_CHECK_EXP(eq_du_to_cu_rrc_info(&a->du_to_cu_rrc_info, &b->du_to_cu_rrc_info)); + _F1_EQ_CHECK_OPTIONAL_IE(a, b, crnti, _F1_EQ_CHECK_INT); + + _F1_EQ_CHECK_INT(a->drbs_len, b->drbs_len); + _F1_CHECK_EXP(a->drbs_len == 0 || (a->drbs && b->drbs)); + for (int i = 0; i < a->drbs_len; ++i) + _F1_CHECK_EXP(eq_drb_setup(&a->drbs[i], &b->drbs[i])); + + _F1_EQ_CHECK_INT(a->srbs_len, b->srbs_len); + _F1_CHECK_EXP(a->srbs_len == 0 || (a->srbs && b->srbs)); + for (int i = 0; i < a->srbs_len; ++i) + _F1_CHECK_EXP(eq_srb_setup(&a->srbs[i], &b->srbs[i])); + + return true; +} + +/** + * @brief Free Allocated F1 UE Context Setup Response + */ +void free_ue_context_setup_resp(f1ap_ue_context_setup_resp_t *resp) +{ + free_du_to_cu_rrc_info(&resp->du_to_cu_rrc_info); + free(resp->crnti); + for (int i = 0; i < resp->drbs_len; ++i) + free_drb_setup(&resp->drbs[i]); + free(resp->drbs); + for (int i = 0; i < resp->srbs_len; ++i) + free_srb_setup(&resp->srbs[i]); + free(resp->srbs); +} + /** * @brief Encode F1 UE context modification request to ASN.1 */ diff --git a/openair2/F1AP/lib/f1ap_ue_context.h b/openair2/F1AP/lib/f1ap_ue_context.h index 6ac521085b..3afb96fcc4 100644 --- a/openair2/F1AP/lib/f1ap_ue_context.h +++ b/openair2/F1AP/lib/f1ap_ue_context.h @@ -33,6 +33,12 @@ f1ap_ue_context_setup_req_t cp_ue_context_setup_req(const f1ap_ue_context_setup_ bool eq_ue_context_setup_req(const f1ap_ue_context_setup_req_t *a, const f1ap_ue_context_setup_req_t *b); void free_ue_context_setup_req(f1ap_ue_context_setup_req_t *req); +struct F1AP_F1AP_PDU *encode_ue_context_setup_resp(const f1ap_ue_context_setup_resp_t *msg); +bool decode_ue_context_setup_resp(const struct F1AP_F1AP_PDU *pdu, f1ap_ue_context_setup_resp_t *out); +f1ap_ue_context_setup_resp_t cp_ue_context_setup_resp(const f1ap_ue_context_setup_resp_t *orig); +bool eq_ue_context_setup_resp(const f1ap_ue_context_setup_resp_t *a, const f1ap_ue_context_setup_resp_t *b); +void free_ue_context_setup_resp(f1ap_ue_context_setup_resp_t *resp); + struct F1AP_F1AP_PDU *encode_ue_context_mod_req(const f1ap_ue_context_mod_req_t *msg); bool decode_ue_context_mod_req(const struct F1AP_F1AP_PDU *pdu, f1ap_ue_context_mod_req_t *out); f1ap_ue_context_mod_req_t cp_ue_context_mod_req(const f1ap_ue_context_mod_req_t *orig); diff --git a/openair2/F1AP/tests/f1ap_lib_test.c b/openair2/F1AP/tests/f1ap_lib_test.c index 159ea41470..0b0511c6bb 100644 --- a/openair2/F1AP/tests/f1ap_lib_test.c +++ b/openair2/F1AP/tests/f1ap_lib_test.c @@ -885,6 +885,100 @@ static void test_f1ap_ue_context_setup_request_simple() printf("%s() successful\n", __func__); } +static void test_f1ap_ue_context_setup_response() +{ + f1ap_ue_context_setup_resp_t orig = { + .gNB_CU_ue_id = 12, + .gNB_DU_ue_id = 13, + //.du_to_cu_rrc_info below + //.crnti below + //.drbs below + //.srbs below + }; + + orig.du_to_cu_rrc_info.cell_group_config = get_test_ba("CELL GROUP CONFIG"); + orig.du_to_cu_rrc_info.meas_gap_config = get_malloced_test_ba("MGC"); + + _F1_MALLOC(orig.crnti, 0x1234); + + orig.drbs_len = 2; + orig.drbs = calloc_or_fail(orig.drbs_len, sizeof(*orig.drbs)); + f1ap_drb_setup_t *drb1 = &orig.drbs[0]; + drb1->id = 12; + _F1_MALLOC(drb1->lcid, 12); + drb1->up_dl_tnl_len = 2; + inet_pton(AF_INET, "192.168.40.23", &drb1->up_dl_tnl[0].tl_address); + drb1->up_dl_tnl[0].teid = 0x11223344; + inet_pton(AF_INET, "192.168.40.23", &drb1->up_dl_tnl[1].tl_address); + drb1->up_dl_tnl[1].teid = 0x11223345; + f1ap_drb_setup_t *drb2 = &orig.drbs[1]; + drb2->id = 13; + _F1_MALLOC(drb2->lcid, 13); + drb2->up_dl_tnl_len = 2; + inet_pton(AF_INET, "192.168.50.23", &drb2->up_dl_tnl[0].tl_address); + drb2->up_dl_tnl[0].teid = 0x21223354; + inet_pton(AF_INET, "192.168.50.23", &drb2->up_dl_tnl[1].tl_address); + drb2->up_dl_tnl[1].teid = 0x21223355; + + orig.srbs_len = 2; + orig.srbs = calloc_or_fail(orig.srbs_len, sizeof(*orig.srbs)); + for (int i = 0; i < orig.srbs_len; ++i) { + orig.srbs[i].id = 1 + i; + orig.srbs[i].lcid = 1+i+10; + } + + F1AP_F1AP_PDU_t *f1enc = encode_ue_context_setup_resp(&orig); + F1AP_F1AP_PDU_t *f1dec = f1ap_encode_decode(f1enc); + f1ap_msg_free(f1enc); + + f1ap_ue_context_setup_resp_t decoded = {0}; + bool ret = decode_ue_context_setup_resp(f1dec, &decoded); + AssertFatal(ret, "decode_ue_context_setup_resp(): could not decode message\n"); + f1ap_msg_free(f1dec); + + ret = eq_ue_context_setup_resp(&orig, &decoded); + AssertFatal(ret, "eq_ue_context_setup_resp(): decoded message doesn't match\n"); + free_ue_context_setup_resp(&decoded); + + f1ap_ue_context_setup_resp_t cp = cp_ue_context_setup_resp(&orig); + ret = eq_ue_context_setup_resp(&orig, &cp); + AssertFatal(ret, "eq_ue_context_setup_resp(): copied message doesn't match\n"); + free_ue_context_setup_resp(&orig); + free_ue_context_setup_resp(&cp); + + printf("%s() successful\n", __func__); +} + +static void test_f1ap_ue_context_setup_response_simple() +{ + f1ap_ue_context_setup_resp_t orig = { + .gNB_CU_ue_id = 12, + .gNB_DU_ue_id = 13, + .du_to_cu_rrc_info.cell_group_config = get_test_ba("small cg"), + // rest is optional and intentionally left empty + }; + + F1AP_F1AP_PDU_t *f1enc = encode_ue_context_setup_resp(&orig); + F1AP_F1AP_PDU_t *f1dec = f1ap_encode_decode(f1enc); + f1ap_msg_free(f1enc); + + f1ap_ue_context_setup_resp_t decoded = {0}; + bool ret = decode_ue_context_setup_resp(f1dec, &decoded); + AssertFatal(ret, "decode_ue_context_setup_resp(): could not decode message\n"); + f1ap_msg_free(f1dec); + + ret = eq_ue_context_setup_resp(&orig, &decoded); + AssertFatal(ret, "eq_ue_context_setup_resp(): decoded message doesn't match\n"); + free_ue_context_setup_resp(&decoded); + + f1ap_ue_context_setup_resp_t cp = cp_ue_context_setup_resp(&orig); + ret = eq_ue_context_setup_resp(&orig, &cp); + AssertFatal(ret, "eq_ue_context_setup_resp(): copied message doesn't match\n"); + free_ue_context_setup_resp(&orig); + free_ue_context_setup_resp(&cp); + + printf("%s() successful\n", __func__); +} static void test_f1ap_ue_context_modification_request() { @@ -1012,6 +1106,8 @@ int main() test_f1ap_du_configuration_update_acknowledge(); test_f1ap_ue_context_setup_request(); test_f1ap_ue_context_setup_request_simple(); + test_f1ap_ue_context_setup_response(); + test_f1ap_ue_context_setup_response_simple(); test_f1ap_ue_context_modification_request(); test_f1ap_ue_context_modification_request_simple(); return 0; From 5c6aa46b03e3ddc71085ff88ee103db9099898e5 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Thu, 19 Jun 2025 08:39:14 +0200 Subject: [PATCH 13/36] Add F1AP UE context modification response message enc/dec + tes See commit "Add F1AP UE context setup request message enc/dec + test" for more details on the approach taken. --- openair2/COMMON/f1ap_messages_types.h | 13 ++ openair2/F1AP/lib/f1ap_ue_context.c | 273 ++++++++++++++++++++++++++ openair2/F1AP/lib/f1ap_ue_context.h | 6 + openair2/F1AP/tests/f1ap_lib_test.c | 84 ++++++++ 4 files changed, 376 insertions(+) diff --git a/openair2/COMMON/f1ap_messages_types.h b/openair2/COMMON/f1ap_messages_types.h index c8ebde936a..396b0837b7 100644 --- a/openair2/COMMON/f1ap_messages_types.h +++ b/openair2/COMMON/f1ap_messages_types.h @@ -645,6 +645,19 @@ typedef struct f1ap_ue_context_mod_req_t { lower_layer_status_t *status; } f1ap_ue_context_mod_req_t; +typedef struct f1ap_ue_context_mod_resp { + uint32_t gNB_CU_ue_id; + uint32_t gNB_DU_ue_id; + + f1ap_du_to_cu_rrc_info_t *du_to_cu_rrc_info; + + int drbs_len; + f1ap_drb_setup_t *drbs; + + int srbs_len; + f1ap_srb_setup_t *srbs; +} f1ap_ue_context_mod_resp_t; + typedef struct f1ap_ue_context_setup_s { uint32_t gNB_CU_ue_id; uint32_t gNB_DU_ue_id; diff --git a/openair2/F1AP/lib/f1ap_ue_context.c b/openair2/F1AP/lib/f1ap_ue_context.c index 1559ee30d9..588648fe37 100644 --- a/openair2/F1AP/lib/f1ap_ue_context.c +++ b/openair2/F1AP/lib/f1ap_ue_context.c @@ -298,6 +298,21 @@ static F1AP_SRBs_Setup_List_t encode_srbs_setup(int n, const f1ap_srb_setup_t *s return list; } +static F1AP_SRBs_SetupMod_List_t encode_srbs_setupmod(int n, const f1ap_srb_setup_t *srbs) +{ + F1AP_SRBs_SetupMod_List_t list = {0}; + for (int i = 0; i < n; ++i) { + asn1cSequenceAdd(list, F1AP_SRBs_SetupMod_ItemIEs_t, itie); + itie->id = F1AP_ProtocolIE_ID_id_SRBs_SetupMod_Item; + itie->criticality = F1AP_Criticality_ignore; + itie->value.present = F1AP_SRBs_SetupMod_ItemIEs__value_PR_SRBs_SetupMod_Item; + F1AP_SRBs_SetupMod_Item_t *it = &itie->value.choice.SRBs_SetupMod_Item; + it->sRBID = srbs[i].id; + it->lCID = srbs[i].lcid; + } + return list; +} + static bool decode_srbs_setup(const F1AP_SRBs_Setup_List_t *f1ap, int *n, f1ap_srb_setup_t **out) { DevAssert(out != NULL); @@ -318,6 +333,26 @@ static bool decode_srbs_setup(const F1AP_SRBs_Setup_List_t *f1ap, int *n, f1ap_s return true; } +static bool decode_srbs_setupmod(const F1AP_SRBs_SetupMod_List_t *f1ap, int *n, f1ap_srb_setup_t **out) +{ + DevAssert(out != NULL); + *out = NULL; + int count = *n = f1ap->list.count; + if (count == 0) + return true; + + f1ap_srb_setup_t *srbs = *out = calloc_or_fail(count, sizeof(*srbs)); + for (int i = 0; i < count; ++i) { + const F1AP_SRBs_SetupMod_ItemIEs_t *itie = (F1AP_SRBs_SetupMod_ItemIEs_t *)f1ap->list.array[i]; + _F1_EQ_CHECK_LONG(itie->id, F1AP_ProtocolIE_ID_id_SRBs_SetupMod_Item); + _F1_EQ_CHECK_INT(itie->value.present, F1AP_SRBs_SetupMod_ItemIEs__value_PR_SRBs_SetupMod_Item); + const F1AP_SRBs_SetupMod_Item_t *it = &itie->value.choice.SRBs_SetupMod_Item; + srbs[i].id = it->sRBID; + srbs[i].lcid = it->lCID; + } + return true; +} + static f1ap_srb_setup_t cp_srb_setup(const f1ap_srb_setup_t *orig) { f1ap_srb_setup_t cp = {.id = orig->id, .lcid = orig->lcid}; @@ -912,6 +947,29 @@ static F1AP_DRBs_Setup_List_t encode_drbs_setup(int n, const f1ap_drb_setup_t *d return list; } +static F1AP_DRBs_SetupMod_List_t encode_drbs_setupmod(int n, const f1ap_drb_setup_t *drbs) +{ + F1AP_DRBs_SetupMod_List_t list = {0}; + for (int i = 0; i < n; ++i) { + const f1ap_drb_setup_t *drb = &drbs[i]; + asn1cSequenceAdd(list, F1AP_DRBs_SetupMod_ItemIEs_t, itie); + itie->id = F1AP_ProtocolIE_ID_id_DRBs_SetupMod_Item; + itie->criticality = F1AP_Criticality_ignore; + itie->value.present = F1AP_DRBs_SetupMod_ItemIEs__value_PR_DRBs_SetupMod_Item; + + F1AP_DRBs_SetupMod_Item_t *it = &itie->value.choice.DRBs_SetupMod_Item; + it->dRBID = drb->id; + if (drb->lcid) + asn1cCallocOne(it->lCID, *drb->lcid); + for (int j = 0; j < drb->up_dl_tnl_len; ++j) { + DevAssert(drb->up_dl_tnl[j].teid > 0); + asn1cSequenceAdd(it->dLUPTNLInformation_ToBeSetup_List.list, F1AP_DLUPTNLInformation_ToBeSetup_Item_t, tnl_it); + tnl_it->dLUPTNLInformation = encode_up_tnl(&drb->up_dl_tnl[j]); + } + } + return list; +} + static bool decode_drbs_setup(const F1AP_DRBs_Setup_List_t *f1ap, int *n, f1ap_drb_setup_t **out) { DevAssert(out != NULL); @@ -943,6 +1001,37 @@ static bool decode_drbs_setup(const F1AP_DRBs_Setup_List_t *f1ap, int *n, f1ap_d return true; } +static bool decode_drbs_setupmod(const F1AP_DRBs_SetupMod_List_t *f1ap, int *n, f1ap_drb_setup_t **out) +{ + DevAssert(out != NULL); + *out = NULL; + int count = *n = f1ap->list.count; + if (count == 0) + return true; + + f1ap_drb_setup_t *drbs = *out = calloc_or_fail(count, sizeof(*drbs)); + for (int i = 0; i < count; ++i) { + const F1AP_DRBs_SetupMod_ItemIEs_t *itie = (const F1AP_DRBs_SetupMod_ItemIEs_t *)f1ap->list.array[i]; + _F1_EQ_CHECK_LONG(itie->id, F1AP_ProtocolIE_ID_id_DRBs_SetupMod_Item); + _F1_EQ_CHECK_INT(itie->value.present, F1AP_DRBs_SetupMod_ItemIEs__value_PR_DRBs_SetupMod_Item); + const F1AP_DRBs_SetupMod_Item_t *it = &itie->value.choice.DRBs_SetupMod_Item; + + f1ap_drb_setup_t *drb = &drbs[i]; + drb->id = it->dRBID; + if (it->lCID) + _F1_MALLOC(drb->lcid, *it->lCID); + + drb->up_dl_tnl_len = it->dLUPTNLInformation_ToBeSetup_List.list.count; + _F1_EQ_CHECK_GENERIC(drb->up_dl_tnl_len > 0 && drb->up_dl_tnl_len <= 2, "%d", drb->up_dl_tnl_len, 1); + for (int j = 0; j < drb->up_dl_tnl_len; ++j) { + F1AP_DLUPTNLInformation_ToBeSetup_Item_t *it_tnl = it->dLUPTNLInformation_ToBeSetup_List.list.array[j]; + _F1_CHECK_EXP(decode_up_tnl(&it_tnl->dLUPTNLInformation, &drb->up_dl_tnl[j])); + } + } + + return true; +} + static f1ap_drb_setup_t cp_drb_setup(const f1ap_drb_setup_t *orig) { f1ap_drb_setup_t cp = { @@ -1814,3 +1903,187 @@ void free_ue_context_mod_req(f1ap_ue_context_mod_req_t *req) free(req->drbs_rel); free(req->status); } + +/** + * @brief Encode F1 UE context modification response to ASN.1 + */ +F1AP_F1AP_PDU_t *encode_ue_context_mod_resp(const f1ap_ue_context_mod_resp_t *msg) +{ + F1AP_F1AP_PDU_t *pdu = calloc_or_fail(1, sizeof(*pdu)); + + /* Message Type */ + pdu->present = F1AP_F1AP_PDU_PR_successfulOutcome; + asn1cCalloc(pdu->choice.successfulOutcome, tmp); + tmp->procedureCode = F1AP_ProcedureCode_id_UEContextModification; + tmp->criticality = F1AP_Criticality_reject; + tmp->value.present = F1AP_SuccessfulOutcome__value_PR_UEContextModificationResponse; + F1AP_UEContextModificationResponse_t *out = &tmp->value.choice.UEContextModificationResponse; + + /* mandatory: GNB_CU_UE_F1AP_ID */ + asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextModificationResponseIEs_t, ie1); + ie1->id = F1AP_ProtocolIE_ID_id_gNB_CU_UE_F1AP_ID; + ie1->criticality = F1AP_Criticality_reject; + ie1->value.present = F1AP_UEContextModificationResponseIEs__value_PR_GNB_CU_UE_F1AP_ID; + ie1->value.choice.GNB_CU_UE_F1AP_ID = msg->gNB_CU_ue_id; + + /* mandatory: GNB_DU_UE_F1AP_ID */ + asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextModificationResponseIEs_t, ie2); + ie2->id = F1AP_ProtocolIE_ID_id_gNB_DU_UE_F1AP_ID; + ie2->criticality = F1AP_Criticality_reject; + ie2->value.present = F1AP_UEContextModificationResponseIEs__value_PR_GNB_DU_UE_F1AP_ID; + ie2->value.choice.GNB_DU_UE_F1AP_ID = msg->gNB_DU_ue_id; + + /* optional: DUtoCURRCInformation */ + if (msg->du_to_cu_rrc_info != NULL) { + asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextModificationResponseIEs_t, ie4); + ie4->id = F1AP_ProtocolIE_ID_id_DUtoCURRCInformation; + ie4->criticality = F1AP_Criticality_reject; + ie4->value.present = F1AP_UEContextModificationResponseIEs__value_PR_DUtoCURRCInformation; + ie4->value.choice.DUtoCURRCInformation = encode_du_to_cu_rrc_info(msg->du_to_cu_rrc_info); + } + + /* optional: DRBs_Setup_List */ + if (msg->drbs_len > 0) { + asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextModificationResponseIEs_t, ie5); + ie5->id = F1AP_ProtocolIE_ID_id_DRBs_SetupMod_List; + ie5->criticality = F1AP_Criticality_ignore; + ie5->value.present = F1AP_UEContextModificationResponseIEs__value_PR_DRBs_SetupMod_List; + ie5->value.choice.DRBs_SetupMod_List = encode_drbs_setupmod(msg->drbs_len, msg->drbs); + } + + if (msg->srbs_len > 0) { + asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextModificationResponseIEs_t, ie12); + ie12->id = F1AP_ProtocolIE_ID_id_SRBs_SetupMod_List; + ie12->criticality = F1AP_Criticality_ignore; + ie12->value.present = F1AP_UEContextModificationResponseIEs__value_PR_SRBs_SetupMod_List; + ie12->value.choice.SRBs_SetupMod_List = encode_srbs_setupmod(msg->srbs_len, msg->srbs); + } + + return pdu; +} + +/** + * @brief Decode F1 UE Context modification Response + */ +bool decode_ue_context_mod_resp(const struct F1AP_F1AP_PDU *pdu, f1ap_ue_context_mod_resp_t *out) +{ + DevAssert(out != NULL); + memset(out, 0, sizeof(*out)); + + F1AP_UEContextModificationResponse_t *in = &pdu->choice.successfulOutcome->value.choice.UEContextModificationResponse; + F1AP_UEContextModificationResponseIEs_t *ie; + + F1AP_LIB_FIND_IE(F1AP_UEContextModificationResponseIEs_t, ie, &in->protocolIEs.list, F1AP_ProtocolIE_ID_id_gNB_CU_UE_F1AP_ID, true); + F1AP_LIB_FIND_IE(F1AP_UEContextModificationResponseIEs_t, ie, &in->protocolIEs.list, F1AP_ProtocolIE_ID_id_gNB_DU_UE_F1AP_ID, true); + + for (int i = 0; i < in->protocolIEs.list.count; ++i) { + ie = in->protocolIEs.list.array[i]; + AssertError(ie != NULL, return false, "in->protocolIEs.list.array[i] is NULL"); + switch (ie->id) { + case F1AP_ProtocolIE_ID_id_gNB_CU_UE_F1AP_ID: + _F1_EQ_CHECK_INT(ie->value.present, F1AP_UEContextModificationResponseIEs__value_PR_GNB_CU_UE_F1AP_ID); + out->gNB_CU_ue_id = ie->value.choice.GNB_CU_UE_F1AP_ID; + break; + case F1AP_ProtocolIE_ID_id_gNB_DU_UE_F1AP_ID: + _F1_EQ_CHECK_INT(ie->value.present, F1AP_UEContextModificationResponseIEs__value_PR_GNB_DU_UE_F1AP_ID); + out->gNB_DU_ue_id = ie->value.choice.GNB_DU_UE_F1AP_ID; + break; + case F1AP_ProtocolIE_ID_id_DUtoCURRCInformation: + _F1_EQ_CHECK_INT(ie->value.present, F1AP_UEContextModificationResponseIEs__value_PR_DUtoCURRCInformation); + out->du_to_cu_rrc_info = calloc(1, sizeof(*out->du_to_cu_rrc_info)); + _F1_CHECK_EXP(decode_du_to_cu_rrc_info(out->du_to_cu_rrc_info, &ie->value.choice.DUtoCURRCInformation)); + break; + case F1AP_ProtocolIE_ID_id_DRBs_SetupMod_List: + _F1_EQ_CHECK_INT(ie->value.present, F1AP_UEContextModificationResponseIEs__value_PR_DRBs_SetupMod_List); + _F1_CHECK_EXP(decode_drbs_setupmod(&ie->value.choice.DRBs_SetupMod_List, &out->drbs_len, &out->drbs)); + break; + case F1AP_ProtocolIE_ID_id_SRBs_SetupMod_List: + _F1_EQ_CHECK_INT(ie->value.present, F1AP_UEContextModificationResponseIEs__value_PR_SRBs_SetupMod_List); + _F1_CHECK_EXP(decode_srbs_setupmod(&ie->value.choice.SRBs_SetupMod_List, &out->srbs_len, &out->srbs)); + break; + default: + PRINT_ERROR("F1AP_ProtocolIE_ID_id %ld unknown, skipping\n", ie->id); + break; + } + } + + return true; +} + +/** + * @brief F1 UE Context modification Response deep copy + */ +f1ap_ue_context_mod_resp_t cp_ue_context_mod_resp(const f1ap_ue_context_mod_resp_t *orig) +{ + f1ap_ue_context_mod_resp_t cp = { + .gNB_CU_ue_id = orig->gNB_CU_ue_id, + .gNB_DU_ue_id = orig->gNB_DU_ue_id, + // du_to_cu_rrc_info + .drbs_len = orig->drbs_len, + // drbs below + .srbs_len = orig->srbs_len, + // srbs below + }; + + if (orig->du_to_cu_rrc_info) { + f1ap_du_to_cu_rrc_info_t du2cu = cp_du_to_cu_rrc_info(orig->du_to_cu_rrc_info); + _F1_MALLOC(cp.du_to_cu_rrc_info, du2cu); + } + + if (orig->drbs_len > 0) { + DevAssert(orig->drbs); + cp.drbs = calloc_or_fail(orig->drbs_len, sizeof(*cp.drbs)); + cp.drbs_len = orig->drbs_len; + for (int i = 0; i < cp.drbs_len; ++i) + cp.drbs[i] = cp_drb_setup(&orig->drbs[i]); + } + + if (orig->srbs_len > 0) { + DevAssert(orig->srbs); + cp.srbs = calloc_or_fail(orig->srbs_len, sizeof(*cp.srbs)); + cp.srbs_len = orig->srbs_len; + for (int i = 0; i < cp.srbs_len; ++i) + cp.srbs[i] = cp_srb_setup(&orig->srbs[i]); + } + + return cp; +} + +/** + * @brief F1 UE Context modification Response equality check + */ +bool eq_ue_context_mod_resp(const f1ap_ue_context_mod_resp_t *a, const f1ap_ue_context_mod_resp_t *b) +{ + _F1_EQ_CHECK_INT(a->gNB_CU_ue_id, b->gNB_CU_ue_id); + _F1_EQ_CHECK_INT(a->gNB_DU_ue_id, b->gNB_DU_ue_id); + //_F1_EQ_CHECK_OPTIONAL_IE(a, b, du_to_cu_rrc_info, eq_du_to_cu_rrc_info); + _F1_CHECK_EXP((a->du_to_cu_rrc_info && b->du_to_cu_rrc_info) || (!a->du_to_cu_rrc_info && !b->du_to_cu_rrc_info)); + _F1_CHECK_EXP(!a->du_to_cu_rrc_info || eq_du_to_cu_rrc_info(a->du_to_cu_rrc_info, b->du_to_cu_rrc_info)); + + _F1_CHECK_EXP(a->drbs_len == 0 || (a->drbs && b->drbs)); + for (int i = 0; i < a->drbs_len; ++i) + _F1_CHECK_EXP(eq_drb_setup(&a->drbs[i], &b->drbs[i])); + + _F1_EQ_CHECK_INT(a->srbs_len, b->srbs_len); + _F1_CHECK_EXP(a->srbs_len == 0 || (a->srbs && b->srbs)); + for (int i = 0; i < a->srbs_len; ++i) + _F1_CHECK_EXP(eq_srb_setup(&a->srbs[i], &b->srbs[i])); + + return true; +} + +/** + * @brief Free Allocated F1 UE Context modification Response + */ +void free_ue_context_mod_resp(f1ap_ue_context_mod_resp_t *resp) +{ + if (resp->du_to_cu_rrc_info) + free_du_to_cu_rrc_info(resp->du_to_cu_rrc_info); + free(resp->du_to_cu_rrc_info); + for (int i = 0; i < resp->drbs_len; ++i) + free_drb_setup(&resp->drbs[i]); + free(resp->drbs); + for (int i = 0; i < resp->srbs_len; ++i) + free_srb_setup(&resp->srbs[i]); + free(resp->srbs); +} diff --git a/openair2/F1AP/lib/f1ap_ue_context.h b/openair2/F1AP/lib/f1ap_ue_context.h index 3afb96fcc4..ddf41689e0 100644 --- a/openair2/F1AP/lib/f1ap_ue_context.h +++ b/openair2/F1AP/lib/f1ap_ue_context.h @@ -45,4 +45,10 @@ f1ap_ue_context_mod_req_t cp_ue_context_mod_req(const f1ap_ue_context_mod_req_t bool eq_ue_context_mod_req(const f1ap_ue_context_mod_req_t *a, const f1ap_ue_context_mod_req_t *b); void free_ue_context_mod_req(f1ap_ue_context_mod_req_t *req); +struct F1AP_F1AP_PDU *encode_ue_context_mod_resp(const f1ap_ue_context_mod_resp_t *msg); +bool decode_ue_context_mod_resp(const struct F1AP_F1AP_PDU *pdu, f1ap_ue_context_mod_resp_t *out); +f1ap_ue_context_mod_resp_t cp_ue_context_mod_resp(const f1ap_ue_context_mod_resp_t *orig); +bool eq_ue_context_mod_resp(const f1ap_ue_context_mod_resp_t *a, const f1ap_ue_context_mod_resp_t *b); +void free_ue_context_mod_resp(f1ap_ue_context_mod_resp_t *resp); + #endif /* F1AP_UE_CONTEXT_SETUP_REQ_H_ */ diff --git a/openair2/F1AP/tests/f1ap_lib_test.c b/openair2/F1AP/tests/f1ap_lib_test.c index 0b0511c6bb..5baac1f5c6 100644 --- a/openair2/F1AP/tests/f1ap_lib_test.c +++ b/openair2/F1AP/tests/f1ap_lib_test.c @@ -1089,6 +1089,88 @@ static void test_f1ap_ue_context_modification_request_simple() printf("%s() successful\n", __func__); } +static void test_f1ap_ue_context_modification_response() +{ + f1ap_ue_context_mod_resp_t orig = { + .gNB_CU_ue_id = 9876, + .gNB_DU_ue_id = 5432, + // rest below + }; + + f1ap_du_to_cu_rrc_info_t cu2du = { + .cell_group_config = get_test_ba("update for the cellgroupconfig, extra long"), + .meas_gap_config = get_malloced_test_ba("new and shiny MeAs GaP cOnFiG"), + }; + _F1_MALLOC(orig.du_to_cu_rrc_info, cu2du); + + orig.drbs_len = 1; + orig.drbs = calloc_or_fail(orig.drbs_len, sizeof(*orig.drbs)); + f1ap_drb_setup_t *drb1 = &orig.drbs[0]; + drb1->id = 4; + _F1_MALLOC(drb1->lcid, 7); + drb1->up_dl_tnl_len = 1; + inet_pton(AF_INET, "127.0.0.1", &drb1->up_dl_tnl[0].tl_address); + drb1->up_dl_tnl[0].teid = 0xcafe; + + orig.srbs_len = 2; + orig.srbs = calloc_or_fail(orig.srbs_len, sizeof(*orig.srbs)); + orig.srbs[0].id = 1; + orig.srbs[0].lcid = 1; + orig.srbs[1].id = 2; + orig.srbs[1].lcid = 2; + + F1AP_F1AP_PDU_t *f1enc = encode_ue_context_mod_resp(&orig); + F1AP_F1AP_PDU_t *f1dec = f1ap_encode_decode(f1enc); + f1ap_msg_free(f1enc); + + f1ap_ue_context_mod_resp_t decoded = {0}; + bool ret = decode_ue_context_mod_resp(f1dec, &decoded); + AssertFatal(ret, "decode_ue_context_mod_resp(): could not decode message\n"); + f1ap_msg_free(f1dec); + + ret = eq_ue_context_mod_resp(&orig, &decoded); + AssertFatal(ret, "eq_ue_context_mod_resp(): decoded message doesn't match\n"); + free_ue_context_mod_resp(&decoded); + + f1ap_ue_context_mod_resp_t cp = cp_ue_context_mod_resp(&orig); + ret = eq_ue_context_mod_resp(&orig, &cp); + AssertFatal(ret, "eq_ue_context_mod_resp(): copied message doesn't match\n"); + free_ue_context_mod_resp(&orig); + free_ue_context_mod_resp(&cp); + + printf("%s() successful\n", __func__); +} + +static void test_f1ap_ue_context_modification_response_simple() +{ + f1ap_ue_context_mod_resp_t orig = { + .gNB_CU_ue_id = 9876, + .gNB_DU_ue_id = 5432, + // rest is optional and intentionally left out + }; + + F1AP_F1AP_PDU_t *f1enc = encode_ue_context_mod_resp(&orig); + F1AP_F1AP_PDU_t *f1dec = f1ap_encode_decode(f1enc); + f1ap_msg_free(f1enc); + + f1ap_ue_context_mod_resp_t decoded = {0}; + bool ret = decode_ue_context_mod_resp(f1dec, &decoded); + AssertFatal(ret, "decode_ue_context_mod_resp(): could not decode message\n"); + f1ap_msg_free(f1dec); + + ret = eq_ue_context_mod_resp(&orig, &decoded); + AssertFatal(ret, "eq_ue_context_mod_resp(): decoded message doesn't match\n"); + free_ue_context_mod_resp(&decoded); + + f1ap_ue_context_mod_resp_t cp = cp_ue_context_mod_resp(&orig); + ret = eq_ue_context_mod_resp(&orig, &cp); + AssertFatal(ret, "eq_ue_context_mod_resp(): copied message doesn't match\n"); + free_ue_context_mod_resp(&orig); + free_ue_context_mod_resp(&cp); + + printf("%s() successful\n", __func__); +} + int main() { test_initial_ul_rrc_message_transfer(); @@ -1110,5 +1192,7 @@ int main() test_f1ap_ue_context_setup_response_simple(); test_f1ap_ue_context_modification_request(); test_f1ap_ue_context_modification_request_simple(); + test_f1ap_ue_context_modification_response(); + test_f1ap_ue_context_modification_response_simple(); return 0; } From 04b5e1d7da37533229de79f5f0578042a6375429 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Fri, 27 Jun 2025 11:46:15 +0200 Subject: [PATCH 14/36] Use F1 UE context setup/mod Response in stack Similarly to the commit "Use F1 UE context setup/modif Request in stack", we do both UE context setup/modification response at once because of some functions that are shared by the MAC message handler. --- openair2/COMMON/f1ap_messages_def.h | 4 +- openair2/COMMON/f1ap_messages_types.h | 73 -- openair2/F1AP/f1ap_cu_ue_context_management.c | 258 +------ openair2/F1AP/f1ap_du_task.c | 1 + openair2/F1AP/f1ap_du_ue_context_management.c | 658 +----------------- openair2/F1AP/f1ap_du_ue_context_management.h | 4 +- .../LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.c | 97 +-- openair2/LAYER2/NR_MAC_gNB/mac_rrc_ul.h | 4 +- .../LAYER2/NR_MAC_gNB/mac_rrc_ul_direct.c | 81 +-- openair2/LAYER2/NR_MAC_gNB/mac_rrc_ul_f1ap.c | 69 +- openair2/RRC/NR/nr_rrc_proto.h | 2 +- openair2/RRC/NR/rrc_gNB.c | 62 +- openair2/RRC/NR/rrc_gNB_nsa.c | 10 +- 13 files changed, 112 insertions(+), 1211 deletions(-) diff --git a/openair2/COMMON/f1ap_messages_def.h b/openair2/COMMON/f1ap_messages_def.h index c713361aa5..5681848029 100644 --- a/openair2/COMMON/f1ap_messages_def.h +++ b/openair2/COMMON/f1ap_messages_def.h @@ -57,9 +57,9 @@ MESSAGE_DEF(F1AP_UE_CONTEXT_MODIFICATION_REQUIRED, MESSAGE_PRIORITY_MED, f1ap_ue MESSAGE_DEF(F1AP_DL_RRC_MESSAGE , MESSAGE_PRIORITY_MED, f1ap_dl_rrc_message_t , f1ap_dl_rrc_message ) //MESSAGE_DEF(F1AP_INITIAL_CONTEXT_SETUP_REQ , MESSAGE_PRIORITY_MED, f1ap_initial_context_setup_req_t , f1ap_initial_context_setup_req ) MESSAGE_DEF(F1AP_UE_CONTEXT_SETUP_REQ, MESSAGE_PRIORITY_MED, f1ap_ue_context_setup_req_t, f1ap_ue_context_setup_req) -MESSAGE_DEF(F1AP_UE_CONTEXT_SETUP_RESP, MESSAGE_PRIORITY_MED, f1ap_ue_context_setup_t, f1ap_ue_context_setup_resp) +MESSAGE_DEF(F1AP_UE_CONTEXT_SETUP_RESP, MESSAGE_PRIORITY_MED, f1ap_ue_context_setup_resp_t, f1ap_ue_context_setup_resp) MESSAGE_DEF(F1AP_UE_CONTEXT_MODIFICATION_REQ, MESSAGE_PRIORITY_MED, f1ap_ue_context_mod_req_t, f1ap_ue_context_mod_req) -MESSAGE_DEF(F1AP_UE_CONTEXT_MODIFICATION_RESP, MESSAGE_PRIORITY_MED, f1ap_ue_context_modif_resp_t, f1ap_ue_context_modification_resp) +MESSAGE_DEF(F1AP_UE_CONTEXT_MODIFICATION_RESP, MESSAGE_PRIORITY_MED, f1ap_ue_context_mod_resp_t, f1ap_ue_context_modification_resp) MESSAGE_DEF(F1AP_UE_CONTEXT_MODIFICATION_CONFIRM, MESSAGE_PRIORITY_MED, f1ap_ue_context_modif_confirm_t, f1ap_ue_context_modification_confirm) MESSAGE_DEF(F1AP_UE_CONTEXT_MODIFICATION_REFUSE, MESSAGE_PRIORITY_MED, f1ap_ue_context_modif_refuse_t, f1ap_ue_context_modification_refuse) diff --git a/openair2/COMMON/f1ap_messages_types.h b/openair2/COMMON/f1ap_messages_types.h index 396b0837b7..9394daa7f0 100644 --- a/openair2/COMMON/f1ap_messages_types.h +++ b/openair2/COMMON/f1ap_messages_types.h @@ -418,40 +418,6 @@ typedef struct f1ap_drb_information_s { } 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]; - uint8_t up_ul_tnl_length; - f1ap_up_tnl_t up_dl_tnl[2]; - uint8_t up_dl_tnl_length; - f1ap_drb_information_t drb_info; - f1ap_rlc_mode_t rlc_mode; - nssai_t nssai; -} f1ap_drb_to_be_setup_t; - -typedef struct f1ap_srb_to_be_setup_s { - long srb_id; - uint8_t lcid; -} f1ap_srb_to_be_setup_t; - -typedef struct f1ap_rb_failed_to_be_setup_s { - long rb_id; -} f1ap_rb_failed_to_be_setup_t; - -typedef struct f1ap_drb_to_be_released_t { - long rb_id; -} f1ap_drb_to_be_released_t; - -typedef struct cu_to_du_rrc_information_s { - uint8_t * cG_ConfigInfo; - uint32_t cG_ConfigInfo_length; - uint8_t * uE_CapabilityRAT_ContainerList; - uint32_t uE_CapabilityRAT_ContainerList_length; - uint8_t * measConfig; - uint32_t measConfig_length; - uint8_t *handoverPreparationInfo; - uint32_t handoverPreparationInfo_length; -}cu_to_du_rrc_information_t; typedef struct f1ap_cu_to_du_rrc_info_s { byte_array_t *cg_configinfo; @@ -474,11 +440,6 @@ typedef struct du_to_cu_rrc_information_s { uint32_t requestedP_MaxFR1_length; }du_to_cu_rrc_information_t; -typedef enum QoS_information_e { - NG_RAN_QoS = 0, - EUTRAN_QoS = 1, -} QoS_information_t; - typedef enum ReconfigurationCompl_e { RRCreconf_info_not_present = 0, RRCreconf_failure = 1, @@ -658,40 +619,6 @@ typedef struct f1ap_ue_context_mod_resp { f1ap_srb_setup_t *srbs; } f1ap_ue_context_mod_resp_t; -typedef struct f1ap_ue_context_setup_s { - uint32_t gNB_CU_ue_id; - uint32_t gNB_DU_ue_id; - // SpCell Info - plmn_id_t plmn; - uint64_t nr_cellid; - uint8_t servCellIndex; - uint8_t *cellULConfigured; - uint32_t servCellId; - cu_to_du_rrc_information_t *cu_to_du_rrc_information; - uint8_t cu_to_du_rrc_information_length; - //uint8_t *du_to_cu_rrc_information; - du_to_cu_rrc_information_t *du_to_cu_rrc_information; - uint32_t du_to_cu_rrc_information_length; - uint16_t *crnti; - f1ap_drb_to_be_setup_t *drbs_to_be_setup; - uint8_t drbs_to_be_setup_length; - f1ap_drb_to_be_setup_t *drbs_to_be_modified; - uint8_t drbs_to_be_modified_length; - QoS_information_t QoS_information_type; - uint8_t drbs_failed_to_be_setup_length; - f1ap_rb_failed_to_be_setup_t *drbs_failed_to_be_setup; - f1ap_srb_to_be_setup_t *srbs_to_be_setup; - uint8_t srbs_to_be_setup_length; - uint8_t srbs_failed_to_be_setup_length; - uint8_t drbs_to_be_released_length; - f1ap_drb_to_be_released_t *drbs_to_be_released; - f1ap_rb_failed_to_be_setup_t *srbs_failed_to_be_setup; - ReconfigurationCompl_t ReconfigComplOutcome; - uint8_t *rrc_container; - int rrc_container_length; - TransmActionInd_t *transm_action_ind; -} f1ap_ue_context_setup_t, f1ap_ue_context_modif_resp_t; - typedef enum F1ap_Cause_e { F1AP_CAUSE_NOTHING, /* No components present */ F1AP_CAUSE_RADIO_NETWORK, diff --git a/openair2/F1AP/f1ap_cu_ue_context_management.c b/openair2/F1AP/f1ap_cu_ue_context_management.c index 9dc9e8c086..597c20d258 100644 --- a/openair2/F1AP/f1ap_cu_ue_context_management.c +++ b/openair2/F1AP/f1ap_cu_ue_context_management.c @@ -69,134 +69,16 @@ int CU_send_UE_CONTEXT_SETUP_REQUEST(sctp_assoc_t assoc_id, const f1ap_ue_contex int CU_handle_UE_CONTEXT_SETUP_RESPONSE(instance_t instance, sctp_assoc_t assoc_id, uint32_t stream, F1AP_F1AP_PDU_t *pdu) { - MessageDef *msg_p; - F1AP_UEContextSetupResponse_t *container; - F1AP_UEContextSetupResponseIEs_t *ie; - DevAssert(pdu); - msg_p = itti_alloc_new_message(TASK_DU_F1, 0, F1AP_UE_CONTEXT_SETUP_RESP); - msg_p->ittiMsgHeader.originInstance = assoc_id; - f1ap_ue_context_setup_t *f1ap_ue_context_setup_resp = &F1AP_UE_CONTEXT_SETUP_RESP(msg_p); - container = &pdu->choice.successfulOutcome->value.choice.UEContextSetupResponse; - int i; - /* GNB_CU_UE_F1AP_ID */ - F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_UEContextSetupResponseIEs_t, ie, container, - F1AP_ProtocolIE_ID_id_gNB_CU_UE_F1AP_ID, true); - f1ap_ue_context_setup_resp->gNB_CU_ue_id = ie->value.choice.GNB_CU_UE_F1AP_ID; - LOG_D(F1AP, "f1ap_ue_context_setup_resp->gNB_CU_ue_id is: %d \n", f1ap_ue_context_setup_resp->gNB_CU_ue_id); - /* GNB_DU_UE_F1AP_ID */ - F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_UEContextSetupResponseIEs_t, ie, container, - F1AP_ProtocolIE_ID_id_gNB_DU_UE_F1AP_ID, true); - f1ap_ue_context_setup_resp->gNB_DU_ue_id = ie->value.choice.GNB_DU_UE_F1AP_ID; - LOG_D(F1AP, "f1ap_ue_context_setup_resp->gNB_DU_ue_id is: %d \n", f1ap_ue_context_setup_resp->gNB_DU_ue_id); - F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_UEContextSetupResponseIEs_t, ie, container, F1AP_ProtocolIE_ID_id_C_RNTI, false); - if (ie) { - f1ap_ue_context_setup_resp->crnti = calloc(1, sizeof(uint16_t)); - *f1ap_ue_context_setup_resp->crnti = ie->value.choice.C_RNTI; - } - - // DUtoCURRCInformation - F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_UEContextSetupResponseIEs_t, ie, container, - F1AP_ProtocolIE_ID_id_DUtoCURRCInformation, true); - - if (ie == NULL) { - LOG_E(F1AP,"%s %d: ie is a NULL pointer \n",__FILE__,__LINE__); + f1ap_ue_context_setup_resp_t resp = {0}; + if (!decode_ue_context_setup_resp(pdu, &resp)) { + LOG_E(F1AP, "cannot decode F1 UE Context Setup Resp\n"); + free_ue_context_setup_resp(&resp); return -1; } - f1ap_ue_context_setup_resp->du_to_cu_rrc_information = (du_to_cu_rrc_information_t *)calloc(1,sizeof(du_to_cu_rrc_information_t)); - f1ap_ue_context_setup_resp->du_to_cu_rrc_information->cellGroupConfig = (uint8_t *)calloc(1,ie->value.choice.DUtoCURRCInformation.cellGroupConfig.size); - memcpy(f1ap_ue_context_setup_resp->du_to_cu_rrc_information->cellGroupConfig, ie->value.choice.DUtoCURRCInformation.cellGroupConfig.buf, ie->value.choice.DUtoCURRCInformation.cellGroupConfig.size); - f1ap_ue_context_setup_resp->du_to_cu_rrc_information->cellGroupConfig_length = ie->value.choice.DUtoCURRCInformation.cellGroupConfig.size; - // DRBs_Setup_List - F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_UEContextSetupResponseIEs_t, ie, container, - F1AP_ProtocolIE_ID_id_DRBs_Setup_List, false); - - if(ie!=NULL) { - f1ap_ue_context_setup_resp->drbs_to_be_setup_length = ie->value.choice.DRBs_Setup_List.list.count; - f1ap_ue_context_setup_resp->drbs_to_be_setup = calloc(f1ap_ue_context_setup_resp->drbs_to_be_setup_length, - sizeof(f1ap_drb_to_be_setup_t)); - AssertFatal(f1ap_ue_context_setup_resp->drbs_to_be_setup, - "could not allocate memory for f1ap_ue_context_setup_resp->drbs_setup\n"); - - for (i = 0; i < f1ap_ue_context_setup_resp->drbs_to_be_setup_length; ++i) { - f1ap_drb_to_be_setup_t *drb_p = &f1ap_ue_context_setup_resp->drbs_to_be_setup[i]; - F1AP_DRBs_Setup_Item_t *drbs_setup_item_p; - drbs_setup_item_p = &((F1AP_DRBs_Setup_ItemIEs_t *)ie->value.choice.DRBs_Setup_List.list.array[i])->value.choice.DRBs_Setup_Item; - drb_p->drb_id = drbs_setup_item_p->dRBID; - // TODO in the following, assume only one UP UL TNL is present. - // this matches/assumes OAI CU/DU implementation, can be up to 2! - drb_p->up_dl_tnl_length = 1; - AssertFatal(drbs_setup_item_p->dLUPTNLInformation_ToBeSetup_List.list.count > 0, - "no DL UP TNL Information in DRBs to be Setup list\n"); - F1AP_DLUPTNLInformation_ToBeSetup_Item_t *dl_up_tnl_info_p = (F1AP_DLUPTNLInformation_ToBeSetup_Item_t *)drbs_setup_item_p->dLUPTNLInformation_ToBeSetup_List.list.array[0]; - F1AP_GTPTunnel_t *dl_up_tnl0 = dl_up_tnl_info_p->dLUPTNLInformation.choice.gTPTunnel; - BIT_STRING_TO_TRANSPORT_LAYER_ADDRESS_IPv4(&dl_up_tnl0->transportLayerAddress, drb_p->up_dl_tnl[0].tl_address); - OCTET_STRING_TO_UINT32(&dl_up_tnl0->gTP_TEID, drb_p->up_dl_tnl[0].teid); - } - } - - // SRBs_FailedToBeSetup_List - F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_UEContextSetupResponseIEs_t, ie, container, - F1AP_ProtocolIE_ID_id_SRBs_FailedToBeSetup_List, false); - - if(ie!=NULL) { - f1ap_ue_context_setup_resp->srbs_failed_to_be_setup_length = ie->value.choice.SRBs_FailedToBeSetup_List.list.count; - f1ap_ue_context_setup_resp->srbs_failed_to_be_setup = calloc(f1ap_ue_context_setup_resp->srbs_failed_to_be_setup_length, - sizeof(f1ap_rb_failed_to_be_setup_t)); - AssertFatal(f1ap_ue_context_setup_resp->srbs_failed_to_be_setup, - "could not allocate memory for f1ap_ue_context_setup_resp->srbs_failed_to_be_setup\n"); - - for (i = 0; i < f1ap_ue_context_setup_resp->srbs_failed_to_be_setup_length; ++i) { - f1ap_rb_failed_to_be_setup_t *srb_p = &f1ap_ue_context_setup_resp->srbs_failed_to_be_setup[i]; - srb_p->rb_id = ((F1AP_SRBs_FailedToBeSetup_Item_t *)ie->value.choice.SRBs_FailedToBeSetup_List.list.array[i])->sRBID; - } - } - - // DRBs_FailedToBeSetup_List - F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_UEContextSetupResponseIEs_t, ie, container, - F1AP_ProtocolIE_ID_id_DRBs_FailedToBeSetup_List, false); - - if(ie!=NULL) { - f1ap_ue_context_setup_resp->drbs_failed_to_be_setup_length = ie->value.choice.DRBs_FailedToBeSetup_List.list.count; - f1ap_ue_context_setup_resp->drbs_failed_to_be_setup = calloc(f1ap_ue_context_setup_resp->drbs_failed_to_be_setup_length, - sizeof(f1ap_rb_failed_to_be_setup_t)); - AssertFatal(f1ap_ue_context_setup_resp->drbs_failed_to_be_setup, - "could not allocate memory for f1ap_ue_context_setup_resp->drbs_failed_to_be_setup\n"); - - for (i = 0; i < f1ap_ue_context_setup_resp->drbs_failed_to_be_setup_length; ++i) { - f1ap_rb_failed_to_be_setup_t *drb_p = &f1ap_ue_context_setup_resp->drbs_failed_to_be_setup[i]; - drb_p->rb_id = ((F1AP_DRBs_FailedToBeSetup_Item_t *)ie->value.choice.DRBs_FailedToBeSetup_List.list.array[i])->dRBID; - } - } - - // SCell_FailedtoSetup_List - F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_UEContextSetupResponseIEs_t, ie, container, - F1AP_ProtocolIE_ID_id_SCell_FailedtoSetup_List, false); - - if(ie!=NULL) { - LOG_E (F1AP, "Not supporting handling of SCell_FailedtoSetup_List \n"); - } - - // SRBs_Setup_List - F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_UEContextSetupResponseIEs_t, ie, container, - F1AP_ProtocolIE_ID_id_SRBs_Setup_List, false); - - if(ie!=NULL) { - f1ap_ue_context_setup_resp->srbs_to_be_setup_length = ie->value.choice.SRBs_Setup_List.list.count; - f1ap_ue_context_setup_resp->srbs_to_be_setup = calloc(f1ap_ue_context_setup_resp->srbs_to_be_setup_length, - sizeof(f1ap_srb_to_be_setup_t)); - AssertFatal(f1ap_ue_context_setup_resp->srbs_to_be_setup, - "could not allocate memory for f1ap_ue_context_setup_resp->drbs_setup\n"); - - for (i = 0; i < f1ap_ue_context_setup_resp->srbs_to_be_setup_length; ++i) { - f1ap_srb_to_be_setup_t *srb_p = &f1ap_ue_context_setup_resp->srbs_to_be_setup[i]; - F1AP_SRBs_Setup_Item_t *srbs_setup_item_p; - srbs_setup_item_p = &((F1AP_SRBs_Setup_ItemIEs_t *)ie->value.choice.SRBs_Setup_List.list.array[i])->value.choice.SRBs_Setup_Item; - srb_p->srb_id = srbs_setup_item_p->sRBID; - srb_p->lcid = srbs_setup_item_p->lCID; - } - } - + MessageDef *msg_p = itti_alloc_new_message(TASK_DU_F1, 0, F1AP_UE_CONTEXT_SETUP_RESP); + msg_p->ittiMsgHeader.originInstance = assoc_id; + F1AP_UE_CONTEXT_SETUP_RESP(msg_p) = resp; itti_send_msg_to_task(TASK_RRC_GNB, instance, msg_p); return 0; } @@ -407,123 +289,17 @@ int CU_send_UE_CONTEXT_MODIFICATION_REQUEST(sctp_assoc_t assoc_id, const f1ap_ue int CU_handle_UE_CONTEXT_MODIFICATION_RESPONSE(instance_t instance, sctp_assoc_t assoc_id, uint32_t stream, F1AP_F1AP_PDU_t *pdu) { - MessageDef *msg_p; - F1AP_UEContextModificationResponse_t *container; - F1AP_UEContextModificationResponseIEs_t *ie; - DevAssert(pdu); - msg_p = itti_alloc_new_message(TASK_DU_F1, 0, F1AP_UE_CONTEXT_MODIFICATION_RESP); + f1ap_ue_context_mod_resp_t resp = {0}; + if (!decode_ue_context_mod_resp(pdu, &resp)) { + LOG_E(F1AP, "cannot decode F1 UE Context Modification Response\n"); + free_ue_context_mod_resp(&resp); + return -1; + } + MessageDef *msg_p = itti_alloc_new_message(TASK_DU_F1, 0, F1AP_UE_CONTEXT_MODIFICATION_RESP); msg_p->ittiMsgHeader.originInstance = assoc_id; - f1ap_ue_context_modif_resp_t *f1ap_ue_context_modification_resp = &F1AP_UE_CONTEXT_MODIFICATION_RESP(msg_p); - container = &pdu->choice.successfulOutcome->value.choice.UEContextModificationResponse; - int i; - - /* GNB_CU_UE_F1AP_ID */ - F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_UEContextModificationResponseIEs_t, ie, container, - F1AP_ProtocolIE_ID_id_gNB_CU_UE_F1AP_ID, true); - f1ap_ue_context_modification_resp->gNB_CU_ue_id = ie->value.choice.GNB_CU_UE_F1AP_ID; - - LOG_D(F1AP, "f1ap_ue_context_modif_resp->gNB_CU_ue_id is: %d \n", f1ap_ue_context_modification_resp->gNB_CU_ue_id); - - /* GNB_DU_UE_F1AP_ID */ - F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_UEContextModificationResponseIEs_t, ie, container, - F1AP_ProtocolIE_ID_id_gNB_DU_UE_F1AP_ID, true); - f1ap_ue_context_modification_resp->gNB_DU_ue_id = ie->value.choice.GNB_DU_UE_F1AP_ID; - - LOG_D(F1AP, "f1ap_ue_context_modification_resp->gNB_DU_ue_id is: %d \n", f1ap_ue_context_modification_resp->gNB_DU_ue_id); - - // DUtoCURRCInformation - F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_UEContextModificationResponseIEs_t, ie, container, - F1AP_ProtocolIE_ID_id_DUtoCURRCInformation, false); - if(ie!=NULL){ - f1ap_ue_context_modification_resp->du_to_cu_rrc_information = (du_to_cu_rrc_information_t *)calloc(1, sizeof(du_to_cu_rrc_information_t)); - f1ap_ue_context_modification_resp->du_to_cu_rrc_information->cellGroupConfig = (uint8_t *)calloc(1,ie->value.choice.DUtoCURRCInformation.cellGroupConfig.size); - - memcpy(f1ap_ue_context_modification_resp->du_to_cu_rrc_information->cellGroupConfig, ie->value.choice.DUtoCURRCInformation.cellGroupConfig.buf, ie->value.choice.DUtoCURRCInformation.cellGroupConfig.size); - f1ap_ue_context_modification_resp->du_to_cu_rrc_information->cellGroupConfig_length = ie->value.choice.DUtoCURRCInformation.cellGroupConfig.size; - } - - // DRBs_SetupMod_List - F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_UEContextModificationResponseIEs_t, ie, container, - F1AP_ProtocolIE_ID_id_DRBs_SetupMod_List, false); - if(ie!=NULL){ - f1ap_ue_context_modification_resp->drbs_to_be_setup_length = ie->value.choice.DRBs_SetupMod_List.list.count; - f1ap_ue_context_modification_resp->drbs_to_be_setup = calloc(f1ap_ue_context_modification_resp->drbs_to_be_setup_length, - sizeof(f1ap_drb_to_be_setup_t)); - AssertFatal(f1ap_ue_context_modification_resp->drbs_to_be_setup, - "could not allocate memory for f1ap_ue_context_setup_resp->drbs_setup\n"); - for (i = 0; i < f1ap_ue_context_modification_resp->drbs_to_be_setup_length; ++i) { - f1ap_drb_to_be_setup_t *drb_p = &f1ap_ue_context_modification_resp->drbs_to_be_setup[i]; - F1AP_DRBs_SetupMod_Item_t *drbs_setupmod_item_p; - drbs_setupmod_item_p = &((F1AP_DRBs_SetupMod_ItemIEs_t *)ie->value.choice.DRBs_SetupMod_List.list.array[i])->value.choice.DRBs_SetupMod_Item; - drb_p->drb_id = drbs_setupmod_item_p->dRBID; - // TODO in the following, assume only one UP UL TNL is present. - // this matches/assumes OAI CU/DU implementation, can be up to 2! - drb_p->up_dl_tnl_length = 1; - AssertFatal(drbs_setupmod_item_p->dLUPTNLInformation_ToBeSetup_List.list.count > 0, - "no DL UP TNL Information in DRBs to be Setup list\n"); - F1AP_DLUPTNLInformation_ToBeSetup_Item_t *dl_up_tnl_info_p = (F1AP_DLUPTNLInformation_ToBeSetup_Item_t *)drbs_setupmod_item_p->dLUPTNLInformation_ToBeSetup_List.list.array[0]; - F1AP_GTPTunnel_t *dl_up_tnl0 = dl_up_tnl_info_p->dLUPTNLInformation.choice.gTPTunnel; - BIT_STRING_TO_TRANSPORT_LAYER_ADDRESS_IPv4(&dl_up_tnl0->transportLayerAddress, drb_p->up_dl_tnl[0].tl_address); - OCTET_STRING_TO_UINT32(&dl_up_tnl0->gTP_TEID, drb_p->up_dl_tnl[0].teid); - } - } - // SRBs_FailedToBeSetupMod_List - F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_UEContextModificationResponseIEs_t, ie, container, - F1AP_ProtocolIE_ID_id_SRBs_FailedToBeSetupMod_List, false); - if(ie!=NULL){ - f1ap_ue_context_modification_resp->srbs_failed_to_be_setup_length = ie->value.choice.SRBs_FailedToBeSetupMod_List.list.count; - f1ap_ue_context_modification_resp->srbs_failed_to_be_setup = calloc(f1ap_ue_context_modification_resp->srbs_failed_to_be_setup_length, - sizeof(f1ap_rb_failed_to_be_setup_t)); - AssertFatal(f1ap_ue_context_modification_resp->srbs_failed_to_be_setup, - "could not allocate memory for f1ap_ue_context_setup_resp->srbs_failed_to_be_setup\n"); - for (i = 0; i < f1ap_ue_context_modification_resp->srbs_failed_to_be_setup_length; ++i) { - f1ap_rb_failed_to_be_setup_t *srb_p = &f1ap_ue_context_modification_resp->srbs_failed_to_be_setup[i]; - srb_p->rb_id = ((F1AP_SRBs_FailedToBeSetupMod_Item_t *)ie->value.choice.SRBs_FailedToBeSetupMod_List.list.array[i])->sRBID; - } - - } - // DRBs_FailedToBeSetupMod_List - F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_UEContextModificationResponseIEs_t, ie, container, - F1AP_ProtocolIE_ID_id_DRBs_FailedToBeSetupMod_List, false); - if(ie!=NULL){ - f1ap_ue_context_modification_resp->drbs_failed_to_be_setup_length = ie->value.choice.DRBs_FailedToBeSetupMod_List.list.count; - f1ap_ue_context_modification_resp->drbs_failed_to_be_setup = calloc(f1ap_ue_context_modification_resp->drbs_failed_to_be_setup_length, - sizeof(f1ap_rb_failed_to_be_setup_t)); - AssertFatal(f1ap_ue_context_modification_resp->drbs_failed_to_be_setup, - "could not allocate memory for f1ap_ue_context_setup_resp->drbs_failed_to_be_setup\n"); - for (i = 0; i < f1ap_ue_context_modification_resp->drbs_failed_to_be_setup_length; ++i) { - f1ap_rb_failed_to_be_setup_t *drb_p = &f1ap_ue_context_modification_resp->drbs_failed_to_be_setup[i]; - drb_p->rb_id = ((F1AP_DRBs_FailedToBeSetupMod_Item_t *)ie->value.choice.DRBs_FailedToBeSetupMod_List.list.array[i])->dRBID; - } - } - - // SCell_FailedtoSetupMod_List - F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_UEContextModificationResponseIEs_t, ie, container, - F1AP_ProtocolIE_ID_id_SCell_FailedtoSetupMod_List, false); - if(ie!=NULL){ - LOG_E (F1AP, "Not supporting handling of SCell_FailedtoSetupMod_List \n"); - } - - // SRBs_Setup_List - F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_UEContextModificationResponseIEs_t, ie, container, - F1AP_ProtocolIE_ID_id_SRBs_SetupMod_List, false); - if(ie!=NULL){ - f1ap_ue_context_modification_resp->srbs_to_be_setup_length = ie->value.choice.SRBs_SetupMod_List.list.count; - f1ap_ue_context_modification_resp->srbs_to_be_setup = calloc(f1ap_ue_context_modification_resp->srbs_to_be_setup_length, - sizeof(f1ap_srb_to_be_setup_t)); - AssertFatal(f1ap_ue_context_modification_resp->srbs_to_be_setup, - "could not allocate memory for f1ap_ue_context_setup_resp->drbs_setup\n"); - for (i = 0; i < f1ap_ue_context_modification_resp->srbs_to_be_setup_length; ++i) { - f1ap_srb_to_be_setup_t *srb_p = &f1ap_ue_context_modification_resp->srbs_to_be_setup[i]; - F1AP_SRBs_SetupMod_Item_t *srbs_setup_item_p; - srbs_setup_item_p = &((F1AP_SRBs_SetupMod_ItemIEs_t *)ie->value.choice.SRBs_SetupMod_List.list.array[i])->value.choice.SRBs_SetupMod_Item; - srb_p->srb_id = srbs_setup_item_p->sRBID; - srb_p->lcid = srbs_setup_item_p->lCID; - } - } - - itti_send_msg_to_task(TASK_RRC_GNB, instance, msg_p); - return 0; + F1AP_UE_CONTEXT_MODIFICATION_RESP(msg_p) = resp; + itti_send_msg_to_task(TASK_RRC_GNB, instance, msg_p); + return 0; } int CU_handle_UE_CONTEXT_MODIFICATION_FAILURE(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 cd76933d44..94b4befb76 100644 --- a/openair2/F1AP/f1ap_du_task.c +++ b/openair2/F1AP/f1ap_du_task.c @@ -189,6 +189,7 @@ void *F1AP_DU_task(void *arg) { case F1AP_UE_CONTEXT_SETUP_RESP: DU_send_UE_CONTEXT_SETUP_RESPONSE(assoc_id, &F1AP_UE_CONTEXT_SETUP_RESP(msg)); + free_ue_context_setup_resp(&F1AP_UE_CONTEXT_SETUP_RESP(msg)); break; case F1AP_UE_CONTEXT_MODIFICATION_RESP: diff --git a/openair2/F1AP/f1ap_du_ue_context_management.c b/openair2/F1AP/f1ap_du_ue_context_management.c index 13c9e92ec5..e6d36f9019 100644 --- a/openair2/F1AP/f1ap_du_ue_context_management.c +++ b/openair2/F1AP/f1ap_du_ue_context_management.c @@ -55,344 +55,19 @@ int DU_handle_UE_CONTEXT_SETUP_REQUEST(instance_t instance, sctp_assoc_t assoc_i return 0; } -int DU_send_UE_CONTEXT_SETUP_RESPONSE(sctp_assoc_t assoc_id, f1ap_ue_context_setup_t *resp) +int DU_send_UE_CONTEXT_SETUP_RESPONSE(sctp_assoc_t assoc_id, f1ap_ue_context_setup_resp_t *resp) { - F1AP_F1AP_PDU_t pdu= {0}; - F1AP_UEContextSetupResponse_t *out; - 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_UEContextSetup; - tmp->criticality = F1AP_Criticality_reject; - tmp->value.present = F1AP_SuccessfulOutcome__value_PR_UEContextSetupResponse; - out = &tmp->value.choice.UEContextSetupResponse; - /* mandatory */ - /* c1. GNB_CU_UE_F1AP_ID */ - asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextSetupResponseIEs_t, ie1); - ie1->id = F1AP_ProtocolIE_ID_id_gNB_CU_UE_F1AP_ID; - ie1->criticality = F1AP_Criticality_reject; - ie1->value.present = F1AP_UEContextSetupResponseIEs__value_PR_GNB_CU_UE_F1AP_ID; - ie1->value.choice.GNB_CU_UE_F1AP_ID = resp->gNB_CU_ue_id; - /* mandatory */ - /* c2. GNB_DU_UE_F1AP_ID */ - asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextSetupResponseIEs_t, ie2); - ie2->id = F1AP_ProtocolIE_ID_id_gNB_DU_UE_F1AP_ID; - ie2->criticality = F1AP_Criticality_reject; - ie2->value.present = F1AP_UEContextSetupResponseIEs__value_PR_GNB_DU_UE_F1AP_ID; - ie2->value.choice.GNB_DU_UE_F1AP_ID = resp->gNB_DU_ue_id; + F1AP_F1AP_PDU_t *pdu = encode_ue_context_setup_resp(resp); - /* mandatory */ - /* c3. DUtoCURRCInformation */ - if(resp->du_to_cu_rrc_information){ - asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextSetupResponseIEs_t, ie3); - ie3->id = F1AP_ProtocolIE_ID_id_DUtoCURRCInformation; - ie3->criticality = F1AP_Criticality_reject; - ie3->value.present = F1AP_UEContextSetupResponseIEs__value_PR_DUtoCURRCInformation; - if(resp->du_to_cu_rrc_information->cellGroupConfig!=NULL){ - /* cellGroupConfig */ - OCTET_STRING_fromBuf(&ie3->value.choice.DUtoCURRCInformation.cellGroupConfig, (const char *)resp->du_to_cu_rrc_information->cellGroupConfig, - resp->du_to_cu_rrc_information->cellGroupConfig_length); - } - - /* OPTIONAL */ - /* measGapConfig */ - if (resp->du_to_cu_rrc_information->measGapConfig!=NULL) { - OCTET_STRING_fromBuf(ie3->value.choice.DUtoCURRCInformation.measGapConfig, (const char *)resp->du_to_cu_rrc_information->measGapConfig, - resp->du_to_cu_rrc_information->measGapConfig_length); - } - - /* OPTIONAL */ - /* requestedP_MaxFR1 */ - if (resp->du_to_cu_rrc_information->requestedP_MaxFR1!=NULL) { - OCTET_STRING_fromBuf(ie3->value.choice.DUtoCURRCInformation.requestedP_MaxFR1, (const char *)resp->du_to_cu_rrc_information->requestedP_MaxFR1, - resp->du_to_cu_rrc_information->requestedP_MaxFR1_length); - } - } - - /* optional */ - /* c4. C_RNTI */ - if (resp->crnti!=NULL) { - asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextSetupResponseIEs_t, ie4); - ie4->id = F1AP_ProtocolIE_ID_id_C_RNTI; - ie4->criticality = F1AP_Criticality_ignore; - ie4->value.present = F1AP_UEContextSetupResponseIEs__value_PR_C_RNTI; - ie4->value.choice.C_RNTI = *resp->crnti; - } - - /* optional */ - /* c5. ResourceCoordinationTransferContainer */ - if (0) { - asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextSetupResponseIEs_t, ie5); - ie5->id = F1AP_ProtocolIE_ID_id_ResourceCoordinationTransferContainer; - ie5->criticality = F1AP_Criticality_ignore; - ie5->value.present = F1AP_UEContextSetupResponseIEs__value_PR_ResourceCoordinationTransferContainer; - OCTET_STRING_fromBuf(&ie5->value.choice.ResourceCoordinationTransferContainer, "asdsa", - strlen("asdsa")); - } - - /* optional */ - /* c6. FullConfiguration */ - if (0) { - asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextSetupResponseIEs_t, ie6); - ie6->id = F1AP_ProtocolIE_ID_id_FullConfiguration; - ie6->criticality = F1AP_Criticality_ignore; - ie6->value.present = F1AP_UEContextSetupResponseIEs__value_PR_FullConfiguration; - ie6->value.choice.FullConfiguration = F1AP_FullConfiguration_full; //enum - } - - /* mandatory */ - /* c7. DRBs_Setup_List */ - if(resp->drbs_to_be_setup_length > 0){ - asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextSetupResponseIEs_t, ie7); - ie7->id = F1AP_ProtocolIE_ID_id_DRBs_Setup_List; - ie7->criticality = F1AP_Criticality_ignore; - ie7->value.present = F1AP_UEContextSetupResponseIEs__value_PR_DRBs_Setup_List; - for (int i=0; i< resp->drbs_to_be_setup_length; i++) { - f1ap_drb_to_be_setup_t *drb = &resp->drbs_to_be_setup[i]; - // - asn1cSequenceAdd(ie7->value.choice.DRBs_Setup_List.list, - F1AP_DRBs_Setup_ItemIEs_t, drbs_setup_item_ies); - drbs_setup_item_ies->id = F1AP_ProtocolIE_ID_id_DRBs_Setup_Item; - drbs_setup_item_ies->criticality = F1AP_Criticality_ignore; - drbs_setup_item_ies->value.present = F1AP_DRBs_Setup_ItemIEs__value_PR_DRBs_Setup_Item; - /* 7.1 DRBs_Setup_Item */ - /* ADD */ - F1AP_DRBs_Setup_Item_t *drbs_setup_item=&drbs_setup_item_ies->value.choice.DRBs_Setup_Item; - /* dRBID */ - drbs_setup_item->dRBID = drb->drb_id; - - /* OPTIONAL */ - /* lCID */ - //drbs_setup_item.lCID = (F1AP_LCID_t *)calloc(1, sizeof(F1AP_LCID_t)); - //drbs_setup_item.lCID = 1L; - - for (int j = 0; j < drb->up_dl_tnl_length; j++) { - const f1ap_up_tnl_t *tnl = &drb->up_dl_tnl[j]; - DevAssert(tnl->teid > 0); - - /* ADD */ - asn1cSequenceAdd(drbs_setup_item->dLUPTNLInformation_ToBeSetup_List.list, - F1AP_DLUPTNLInformation_ToBeSetup_Item_t, dLUPTNLInformation_ToBeSetup_Item); - dLUPTNLInformation_ToBeSetup_Item->dLUPTNLInformation.present = F1AP_UPTransportLayerInformation_PR_gTPTunnel; - /* gTPTunnel */ - asn1cCalloc(dLUPTNLInformation_ToBeSetup_Item->dLUPTNLInformation.choice.gTPTunnel,gTPTunnel); - /* transportLayerAddress */ - TRANSPORT_LAYER_ADDRESS_IPv4_TO_BIT_STRING(tnl->tl_address, &gTPTunnel->transportLayerAddress); - /* gTP_TEID */ - INT32_TO_OCTET_STRING(tnl->teid, &gTPTunnel->gTP_TEID); - } // for j - } // for i - - } - - /* mandatory */ - /* c8. SRBs_FailedToBeSetup_List */ - if(0) { - asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextSetupResponseIEs_t, ie8); - ie8->id = F1AP_ProtocolIE_ID_id_SRBs_FailedToBeSetup_List; - ie8->criticality = F1AP_Criticality_ignore; - ie8->value.present = F1AP_UEContextSetupResponseIEs__value_PR_SRBs_FailedToBeSetup_List; - - for (int i=0; i<1; i++) { - // - asn1cSequenceAdd(ie8->value.choice.SRBs_FailedToBeSetup_List.list, - F1AP_SRBs_FailedToBeSetup_ItemIEs_t, srbs_failedToBeSetup_item_ies); - srbs_failedToBeSetup_item_ies->id = F1AP_ProtocolIE_ID_id_SRBs_FailedToBeSetup_Item; - srbs_failedToBeSetup_item_ies->criticality = F1AP_Criticality_ignore; - srbs_failedToBeSetup_item_ies->value.present = F1AP_SRBs_FailedToBeSetup_ItemIEs__value_PR_SRBs_FailedToBeSetup_Item; - /* 8.1 SRBs_Setup_Item */ - F1AP_SRBs_FailedToBeSetup_Item_t *srbs_failedToBeSetup_item= - &srbs_failedToBeSetup_item_ies->value.choice.SRBs_FailedToBeSetup_Item; - /* sRBID */ - srbs_failedToBeSetup_item->sRBID = 13L; - /* cause */ - asn1cCalloc(srbs_failedToBeSetup_item->cause, tmp); - // dummy value - tmp->present = F1AP_Cause_PR_radioNetwork; - - switch(tmp->present) { - case F1AP_Cause_PR_radioNetwork: - tmp->choice.radioNetwork = F1AP_CauseRadioNetwork_unspecified; - break; - - case F1AP_Cause_PR_transport: - tmp->choice.transport = F1AP_CauseTransport_unspecified; - break; - - case F1AP_Cause_PR_protocol: - tmp->choice.protocol = F1AP_CauseProtocol_unspecified; - break; - - case F1AP_Cause_PR_misc: - tmp->choice.misc = F1AP_CauseMisc_unspecified; - break; - - case F1AP_Cause_PR_NOTHING: - default: - break; - } // switch - } // for i - } - - /* */ - /* c9. DRBs_FailedToBeSetup_List */ - if(0) { - asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextSetupResponseIEs_t, ie9); - ie9->id = F1AP_ProtocolIE_ID_id_DRBs_FailedToBeSetup_List; - ie9->criticality = F1AP_Criticality_ignore; - ie9->value.present = F1AP_UEContextSetupResponseIEs__value_PR_DRBs_FailedToBeSetup_List; - - for (int i=0; i<1; i++) { - asn1cSequenceAdd(ie9->value.choice.DRBs_FailedToBeSetup_List.list, - F1AP_DRBs_FailedToBeSetup_ItemIEs_t, drbs_failedToBeSetup_item_ies); - drbs_failedToBeSetup_item_ies->id = F1AP_ProtocolIE_ID_id_DRBs_FailedToBeSetup_Item; - drbs_failedToBeSetup_item_ies->criticality = F1AP_Criticality_ignore; - drbs_failedToBeSetup_item_ies->value.present = F1AP_DRBs_FailedToBeSetup_ItemIEs__value_PR_DRBs_FailedToBeSetup_Item; - /* 9.1 DRBs_Setup_Item */ - /* ADD */ - F1AP_DRBs_FailedToBeSetup_Item_t *drbs_failedToBeSetup_item= - &drbs_failedToBeSetup_item_ies->value.choice.DRBs_FailedToBeSetup_Item; - /* dRBID */ - drbs_failedToBeSetup_item->dRBID = 14; - /* cause */ - asn1cCalloc(drbs_failedToBeSetup_item->cause,tmp); - // dummy value - tmp->present = F1AP_Cause_PR_radioNetwork; - - switch(tmp->present) { - case F1AP_Cause_PR_radioNetwork: - tmp->choice.radioNetwork = F1AP_CauseRadioNetwork_unspecified; - break; - - case F1AP_Cause_PR_transport: - tmp->choice.transport = F1AP_CauseTransport_unspecified; - break; - - case F1AP_Cause_PR_protocol: - tmp->choice.protocol = F1AP_CauseProtocol_unspecified; - break; - - case F1AP_Cause_PR_misc: - tmp->choice.misc = F1AP_CauseMisc_unspecified; - break; - - case F1AP_Cause_PR_NOTHING: - default: - break; - } // switch - } // for i - } - - // /* */ - /* c10. SCell_FailedtoSetup_List */ - if(0) { - asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextSetupResponseIEs_t, ie10); - ie10->id = F1AP_ProtocolIE_ID_id_SCell_FailedtoSetup_List; - ie10->criticality = F1AP_Criticality_ignore; - ie10->value.present = F1AP_UEContextSetupResponseIEs__value_PR_SCell_FailedtoSetup_List; - - for (int i=0; i<1; i++) { - asn1cSequenceAdd(ie10->value.choice.SCell_FailedtoSetup_List.list, - F1AP_SCell_FailedtoSetup_ItemIEs_t, sCell_FailedtoSetup_item_ies); - sCell_FailedtoSetup_item_ies->id = F1AP_ProtocolIE_ID_id_SCell_FailedtoSetup_Item; - sCell_FailedtoSetup_item_ies->criticality = F1AP_Criticality_ignore; - sCell_FailedtoSetup_item_ies->value.present = F1AP_SCell_FailedtoSetup_ItemIEs__value_PR_SCell_FailedtoSetup_Item; - /* 10.1 DRBs_Setup_Item */ - F1AP_SCell_FailedtoSetup_Item_t *sCell_FailedtoSetup_item= - &sCell_FailedtoSetup_item_ies->value.choice.SCell_FailedtoSetup_Item; - /* sCell_ID */ - AssertFatal(false, "handle correct CellID\n"); - f1ap_served_cell_info_t cellID = {0}; - addnRCGI(sCell_FailedtoSetup_item->sCell_ID, &cellID); - /* cause */ - asn1cCalloc(sCell_FailedtoSetup_item->cause, tmp); - // dummy value - tmp->present = F1AP_Cause_PR_radioNetwork; - - switch(tmp->present) { - case F1AP_Cause_PR_radioNetwork: - tmp->choice.radioNetwork = F1AP_CauseRadioNetwork_unspecified; - break; - - case F1AP_Cause_PR_transport: - tmp->choice.transport = F1AP_CauseTransport_unspecified; - break; - - case F1AP_Cause_PR_protocol: - tmp->choice.protocol = F1AP_CauseProtocol_unspecified; - break; - - case F1AP_Cause_PR_misc: - tmp->choice.misc = F1AP_CauseMisc_unspecified; - break; - - case F1AP_Cause_PR_NOTHING: - default: - break; - } // switch - } // for i - } - - /* mandatory */ - /* c11. SRBs_Setup_List */ - if(resp->srbs_to_be_setup_length > 0){ - asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextSetupResponseIEs_t, ie11); - ie11->id = F1AP_ProtocolIE_ID_id_SRBs_Setup_List; - ie11->criticality = F1AP_Criticality_ignore; - ie11->value.present = F1AP_UEContextSetupResponseIEs__value_PR_SRBs_Setup_List; - - for (int i=0; i< resp->srbs_to_be_setup_length; i++) {// - asn1cSequenceAdd(ie11->value.choice.SRBs_Setup_List.list, - F1AP_SRBs_Setup_ItemIEs_t, srbs_setup_item_ies); - srbs_setup_item_ies->id = F1AP_ProtocolIE_ID_id_SRBs_Setup_Item; - srbs_setup_item_ies->criticality = F1AP_Criticality_ignore; - srbs_setup_item_ies->value.present = F1AP_SRBs_Setup_ItemIEs__value_PR_SRBs_Setup_Item; - /* 11.1 SRBs_Setup_Item */ - /* ADD */ - F1AP_SRBs_Setup_Item_t *srbs_setup_item=&srbs_setup_item_ies->value.choice.SRBs_Setup_Item; - /* sRBID */ - srbs_setup_item->sRBID = resp->srbs_to_be_setup[i].srb_id; - srbs_setup_item->lCID = resp->srbs_to_be_setup[i].lcid; - } - } - - /* Optional */ - /* c12. InactivityMonitoringResponse */ - if (0) { - asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextSetupResponseIEs_t, ie11); - ie11->id = F1AP_ProtocolIE_ID_id_InactivityMonitoringResponse; - ie11->criticality = F1AP_Criticality_ignore; - ie11->value.present = F1AP_UEContextSetupResponseIEs__value_PR_InactivityMonitoringResponse; - ie11->value.choice.InactivityMonitoringResponse = F1AP_InactivityMonitoringResponse_not_supported; - } - - /* Optional */ - /* c13. CriticalityDiagnostics */ - if (0) { - asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextSetupResponseIEs_t, ie12); - ie12->id = F1AP_ProtocolIE_ID_id_CriticalityDiagnostics; - ie12->criticality = F1AP_Criticality_ignore; - ie12->value.present = F1AP_UEContextSetupResponseIEs__value_PR_CriticalityDiagnostics; - asn1cCallocOne(ie12->value.choice.CriticalityDiagnostics.procedureCode, - F1AP_ProcedureCode_id_UEContextSetup); - asn1cCallocOne(ie12->value.choice.CriticalityDiagnostics.triggeringMessage, - F1AP_TriggeringMessage_initiating_message); - asn1cCallocOne(ie12->value.choice.CriticalityDiagnostics.procedureCriticality, - F1AP_Criticality_reject); - asn1cCallocOne(ie12->value.choice.CriticalityDiagnostics.transactionID, - 0); - } - - /* encode */ - if (f1ap_encode_pdu(&pdu, &buffer, &len) < 0) { + uint8_t *buffer = NULL; + uint32_t len = 0; + if (f1ap_encode_pdu(pdu, &buffer, &len) < 0) { LOG_E(F1AP, "Failed to encode F1 UE CONTEXT SETUP RESPONSE\n"); return -1; } f1ap_itti_send_sctp_data_req(assoc_id, buffer, len); + ASN_STRUCT_FREE(asn_DEF_F1AP_F1AP_PDU, pdu); return 0; } @@ -635,325 +310,18 @@ int DU_handle_UE_CONTEXT_MODIFICATION_REQUEST(instance_t instance, sctp_assoc_t return 0; } -int DU_send_UE_CONTEXT_MODIFICATION_RESPONSE(sctp_assoc_t assoc_id, f1ap_ue_context_modif_resp_t *resp) +int DU_send_UE_CONTEXT_MODIFICATION_RESPONSE(sctp_assoc_t assoc_id, f1ap_ue_context_mod_resp_t *resp) { - F1AP_F1AP_PDU_t pdu= {0}; - F1AP_UEContextModificationResponse_t *out; - 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_UEContextModification; - tmp->criticality = F1AP_Criticality_reject; - tmp->value.present = F1AP_SuccessfulOutcome__value_PR_UEContextModificationResponse; - out = &tmp->value.choice.UEContextModificationResponse; - /* mandatory */ - /* c1. GNB_CU_UE_F1AP_ID */ - asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextModificationResponseIEs_t, ie1); - ie1->id = F1AP_ProtocolIE_ID_id_gNB_CU_UE_F1AP_ID; - ie1->criticality = F1AP_Criticality_reject; - ie1->value.present = F1AP_UEContextModificationResponseIEs__value_PR_GNB_CU_UE_F1AP_ID; - ie1->value.choice.GNB_CU_UE_F1AP_ID = resp->gNB_CU_ue_id; - /* mandatory */ - /* c2. GNB_DU_UE_F1AP_ID */ - asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextModificationResponseIEs_t, ie2); - ie2->id = F1AP_ProtocolIE_ID_id_gNB_DU_UE_F1AP_ID; - ie2->criticality = F1AP_Criticality_reject; - ie2->value.present = F1AP_UEContextModificationResponseIEs__value_PR_GNB_DU_UE_F1AP_ID; - ie2->value.choice.GNB_DU_UE_F1AP_ID = resp->gNB_DU_ue_id; + F1AP_F1AP_PDU_t *pdu = encode_ue_context_mod_resp(resp); - /* optional */ - /* c3. ResourceCoordinationTransferContainer */ - if (0) { - asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextModificationResponseIEs_t, ie3); - ie3->id = F1AP_ProtocolIE_ID_id_ResourceCoordinationTransferContainer; - ie3->criticality = F1AP_Criticality_ignore; - ie3->value.present = F1AP_UEContextModificationResponseIEs__value_PR_ResourceCoordinationTransferContainer; - OCTET_STRING_fromBuf(&ie3->value.choice.ResourceCoordinationTransferContainer, "asdsa1d32sa1d31asd31as", - strlen("asdsa1d32sa1d31asd31as")); - } - - /* optional */ - /* c4. DUtoCURRCInformation */ - if(resp->du_to_cu_rrc_information!=NULL){ - asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextModificationResponseIEs_t, ie4); - ie4->id = F1AP_ProtocolIE_ID_id_DUtoCURRCInformation; - ie4->criticality = F1AP_Criticality_reject; - ie4->value.present = F1AP_UEContextModificationResponseIEs__value_PR_DUtoCURRCInformation; - if(resp->du_to_cu_rrc_information->cellGroupConfig!=NULL){ - /* cellGroupConfig */ - OCTET_STRING_fromBuf(&ie4->value.choice.DUtoCURRCInformation.cellGroupConfig, (const char *)resp->du_to_cu_rrc_information->cellGroupConfig, - resp->du_to_cu_rrc_information->cellGroupConfig_length); - } - - /* OPTIONAL */ - /* measGapConfig */ - if (resp->du_to_cu_rrc_information->measGapConfig!=NULL) { - OCTET_STRING_fromBuf(ie4->value.choice.DUtoCURRCInformation.measGapConfig, (const char *)resp->du_to_cu_rrc_information->measGapConfig, - resp->du_to_cu_rrc_information->measGapConfig_length); - } - - /* OPTIONAL */ - /* requestedP_MaxFR1 */ - if (resp->du_to_cu_rrc_information->requestedP_MaxFR1!=NULL) { - OCTET_STRING_fromBuf(ie4->value.choice.DUtoCURRCInformation.requestedP_MaxFR1, (const char *)resp->du_to_cu_rrc_information->requestedP_MaxFR1, - resp->du_to_cu_rrc_information->requestedP_MaxFR1_length); - } - } - - - /* optional */ - /* c5. DRBs_Setup_List */ - if(resp->drbs_to_be_setup_length > 0) { - asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextModificationResponseIEs_t, ie5); - ie5->id = F1AP_ProtocolIE_ID_id_DRBs_SetupMod_List; - ie5->criticality = F1AP_Criticality_ignore; - ie5->value.present = F1AP_UEContextModificationResponseIEs__value_PR_DRBs_SetupMod_List; - for (int i=0; i< resp->drbs_to_be_setup_length; i++) { - asn1cSequenceAdd(ie5->value.choice.DRBs_SetupMod_List.list, F1AP_DRBs_SetupMod_ItemIEs_t, drbs_setupmod_item_ies); - drbs_setupmod_item_ies->id = F1AP_ProtocolIE_ID_id_DRBs_SetupMod_Item; - drbs_setupmod_item_ies->criticality = F1AP_Criticality_ignore; - drbs_setupmod_item_ies->value.present = F1AP_DRBs_SetupMod_ItemIEs__value_PR_DRBs_SetupMod_Item; - /* 7.1 DRBs_Setup_Item */ - /* ADD */ - F1AP_DRBs_SetupMod_Item_t *drbs_setupmod_item=&drbs_setupmod_item_ies->value.choice.DRBs_SetupMod_Item; - /* dRBID */ - drbs_setupmod_item->dRBID = resp->drbs_to_be_setup[i].drb_id; - - for (int j=0; jdrbs_to_be_setup[i].up_dl_tnl_length; j++) { - const f1ap_up_tnl_t *tnl = &resp->drbs_to_be_setup[i].up_dl_tnl[j]; - DevAssert(tnl->teid > 0); - - /* ADD */ - asn1cSequenceAdd(drbs_setupmod_item->dLUPTNLInformation_ToBeSetup_List.list, - F1AP_DLUPTNLInformation_ToBeSetup_Item_t, dLUPTNLInformation_ToBeSetup_Item); - dLUPTNLInformation_ToBeSetup_Item->dLUPTNLInformation.present = F1AP_UPTransportLayerInformation_PR_gTPTunnel; - /* gTPTunnel */ - asn1cCalloc(dLUPTNLInformation_ToBeSetup_Item->dLUPTNLInformation.choice.gTPTunnel,gTPTunnel); - /* transportLayerAddress */ - TRANSPORT_LAYER_ADDRESS_IPv4_TO_BIT_STRING(tnl->tl_address, &gTPTunnel->transportLayerAddress); - /* gTP_TEID */ - INT32_TO_OCTET_STRING(tnl->teid, &gTPTunnel->gTP_TEID); - } // for j - } // for i - } - - /* optional */ - /* c6. DRBs_Modified_List */ - if(resp->drbs_to_be_modified_length > 0){ - asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextModificationResponseIEs_t, ie6); - ie6->id = F1AP_ProtocolIE_ID_id_DRBs_Modified_List; - ie6->criticality = F1AP_Criticality_ignore; - ie6->value.present = F1AP_UEContextModificationResponseIEs__value_PR_DRBs_Modified_List; - - for (int i=0; idrbs_to_be_modified_length; i++) { - asn1cSequenceAdd(ie6->value.choice.DRBs_Modified_List.list, - F1AP_DRBs_Modified_ItemIEs_t, drbs_modified_item_ies); - drbs_modified_item_ies->id = F1AP_ProtocolIE_ID_id_DRBs_Modified_Item; - drbs_modified_item_ies->criticality = F1AP_Criticality_ignore; - drbs_modified_item_ies->value.present = F1AP_DRBs_Modified_ItemIEs__value_PR_DRBs_Modified_Item; - /* DRBs_modified_Item */ - F1AP_DRBs_Modified_Item_t *drbs_modified_item= &drbs_modified_item_ies->value.choice.DRBs_Modified_Item; - /* dRBID */ - drbs_modified_item->dRBID = resp->drbs_to_be_modified[i].drb_id; - - /* ULTunnels_Modified_List */ - for (int j=0; jdrbs_to_be_modified[i].up_dl_tnl_length; j++) { - /* DLTunnels_Modified_Item */ - asn1cSequenceAdd(drbs_modified_item->dLUPTNLInformation_ToBeSetup_List.list, - F1AP_DLUPTNLInformation_ToBeSetup_Item_t, dLUPTNLInformation_ToBeSetup_Item); - asn1cCalloc(dLUPTNLInformation_ToBeSetup_Item, tmp); - tmp->dLUPTNLInformation.present = F1AP_UPTransportLayerInformation_PR_gTPTunnel; - asn1cCalloc(dLUPTNLInformation_ToBeSetup_Item->dLUPTNLInformation.choice.gTPTunnel, gTPTunnel); - /* transportLayerAddress */ - struct sockaddr_in addr= {0}; - inet_pton(AF_INET, getCxt(0)->net_config.DU_f1u_ip_address, &addr.sin_addr.s_addr); - TRANSPORT_LAYER_ADDRESS_IPv4_TO_BIT_STRING(addr.sin_addr.s_addr, &gTPTunnel->transportLayerAddress); - /* gTP_TEID */ - INT32_TO_OCTET_STRING(resp->drbs_to_be_modified[i].up_dl_tnl[j].teid, &gTPTunnel->gTP_TEID); - } - } - } - - /* optional */ - /* c7. SRBs_FailedToBeSetupMod_List */ - if(resp->srbs_failed_to_be_setup_length > 0){ - asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextModificationResponseIEs_t, ie7); - ie7->id = F1AP_ProtocolIE_ID_id_SRBs_FailedToBeSetupMod_List; - ie7->criticality = F1AP_Criticality_reject; - ie7->value.present = F1AP_UEContextModificationResponseIEs__value_PR_SRBs_FailedToBeSetupMod_List; - - for (int i=0; isrbs_to_be_setup_length; i++) { - asn1cSequenceAdd(ie7->value.choice.SRBs_FailedToBeSetupMod_List.list, - F1AP_SRBs_FailedToBeSetupMod_ItemIEs_t, srbs_failedToBeSetupMod_item_ies); - srbs_failedToBeSetupMod_item_ies->id = F1AP_ProtocolIE_ID_id_SRBs_FailedToBeSetupMod_Item; - srbs_failedToBeSetupMod_item_ies->criticality = F1AP_Criticality_ignore; - srbs_failedToBeSetupMod_item_ies->value.present = F1AP_SRBs_FailedToBeSetupMod_ItemIEs__value_PR_SRBs_FailedToBeSetupMod_Item; - /* 9.1 SRBs_FailedToBeSetupMod_Item */ - F1AP_SRBs_FailedToBeSetupMod_Item_t *srbs_failedToBeSetupMod_item= - &srbs_failedToBeSetupMod_item_ies->value.choice.SRBs_FailedToBeSetupMod_Item; - /* - sRBID */ - srbs_failedToBeSetupMod_item->sRBID = resp->srbs_failed_to_be_setup[i].rb_id; - asn1cCalloc(srbs_failedToBeSetupMod_item->cause, tmp); - tmp->present = F1AP_Cause_PR_radioNetwork; - tmp->choice.radioNetwork = F1AP_CauseRadioNetwork_unknown_or_already_allocated_gnb_du_ue_f1ap_id; - } - } - - /* optional */ - /* c8. DRBs_FailedToBeSetupMod_List */ - if(resp->drbs_failed_to_be_setup_length > 0){ - asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextModificationResponseIEs_t, ie8); - ie8->id = F1AP_ProtocolIE_ID_id_DRBs_FailedToBeSetupMod_List; - ie8->criticality = F1AP_Criticality_reject; - ie8->value.present = F1AP_UEContextModificationResponseIEs__value_PR_DRBs_FailedToBeSetupMod_List; - - for (int i=0; idrbs_failed_to_be_setup_length; i++) { - asn1cSequenceAdd(ie8->value.choice.DRBs_FailedToBeSetupMod_List.list, - F1AP_DRBs_FailedToBeSetupMod_ItemIEs_t, drbs_failedToBeSetupMod_item_ies); - drbs_failedToBeSetupMod_item_ies->id = F1AP_ProtocolIE_ID_id_DRBs_FailedToBeSetupMod_Item; - drbs_failedToBeSetupMod_item_ies->criticality = F1AP_Criticality_reject; - drbs_failedToBeSetupMod_item_ies->value.present = F1AP_DRBs_FailedToBeSetupMod_ItemIEs__value_PR_DRBs_FailedToBeSetupMod_Item; - /* DRBs_FailedToBeSetupMod_Item */ - F1AP_DRBs_FailedToBeSetupMod_Item_t *drbs_failedToBeSetupMod_item= - &drbs_failedToBeSetupMod_item_ies->value.choice.DRBs_FailedToBeSetupMod_Item; - /* dRBID */ - drbs_failedToBeSetupMod_item->dRBID = resp->drbs_failed_to_be_setup[i].rb_id; - drbs_failedToBeSetupMod_item->cause = (F1AP_Cause_t *)calloc(1, sizeof(F1AP_Cause_t)); - drbs_failedToBeSetupMod_item->cause->present = F1AP_Cause_PR_radioNetwork; - drbs_failedToBeSetupMod_item->cause->choice.radioNetwork = F1AP_CauseRadioNetwork_unknown_or_already_allocated_gnb_du_ue_f1ap_id; - } - } - - /* optional */ - /* c9. SCell_FailedtoSetupMod_List */ - if(0){ - asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextModificationResponseIEs_t, ie9); - ie9->id = F1AP_ProtocolIE_ID_id_SCell_FailedtoSetupMod_List; - ie9->criticality = F1AP_Criticality_ignore; - ie9->value.present = F1AP_UEContextModificationResponseIEs__value_PR_SCell_FailedtoSetupMod_List; - - for (int i=0; i<1; i++) { - asn1cSequenceAdd(ie9->value.choice.SCell_FailedtoSetupMod_List.list, - F1AP_SCell_FailedtoSetupMod_ItemIEs_t, scell_failedtoSetupMod_item_ies); - scell_failedtoSetupMod_item_ies->id = F1AP_ProtocolIE_ID_id_SCell_FailedtoSetupMod_Item; - scell_failedtoSetupMod_item_ies->criticality = F1AP_Criticality_ignore; - scell_failedtoSetupMod_item_ies->value.present = F1AP_SCell_FailedtoSetupMod_ItemIEs__value_PR_SCell_FailedtoSetupMod_Item; - /* 8.1 SCell_ToBeSetup_Item */ - F1AP_SCell_FailedtoSetupMod_Item_t *scell_failedtoSetupMod_item=&scell_failedtoSetupMod_item_ies->value.choice.SCell_FailedtoSetupMod_Item; - /* - sCell_ID */ - addnRCGI(scell_failedtoSetupMod_item->sCell_ID, &getCxt(0)->setupReq.cell[i].info); - asn1cCalloc(scell_failedtoSetupMod_item->cause, tmp); - tmp->present = F1AP_Cause_PR_radioNetwork; - tmp->choice.radioNetwork = F1AP_CauseRadioNetwork_unknown_or_already_allocated_gnb_du_ue_f1ap_id; - } - } - - /* optional */ - /* c10. DRBs_FailedToBeModified_List */ - if(0){ - asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextModificationResponseIEs_t, ie10); - ie10->id = F1AP_ProtocolIE_ID_id_DRBs_FailedToBeModified_List; - ie10->criticality = F1AP_Criticality_reject; - ie10->value.present = F1AP_UEContextModificationResponseIEs__value_PR_DRBs_FailedToBeModified_List; - - for (int i=0; i<1; i++) { - asn1cSequenceAdd(ie10->value.choice.DRBs_FailedToBeModified_List.list, - F1AP_DRBs_FailedToBeModified_ItemIEs_t, drbs_failedToBeModified_item_ies); - drbs_failedToBeModified_item_ies->id = F1AP_ProtocolIE_ID_id_DRBs_FailedToBeModified_Item; - drbs_failedToBeModified_item_ies->criticality = F1AP_Criticality_reject; - drbs_failedToBeModified_item_ies->value.present = F1AP_DRBs_FailedToBeModified_ItemIEs__value_PR_DRBs_FailedToBeModified_Item; - /* 13.1 DRBs_FailedToBeModified_Item */ - F1AP_DRBs_FailedToBeModified_Item_t *drbs_failedToBeModified_item= - &drbs_failedToBeModified_item_ies->value.choice.DRBs_FailedToBeModified_Item ; - /* dRBID */ - drbs_failedToBeModified_item->dRBID = 30L; - asn1cCalloc(drbs_failedToBeModified_item->cause, tmp); - tmp->present = F1AP_Cause_PR_radioNetwork; - tmp->choice.radioNetwork = F1AP_CauseRadioNetwork_unknown_or_already_allocated_gnb_du_ue_f1ap_id; - } - } - - // /* */ - /* c11. CriticalityDiagnostics */ - if (0) { - asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextModificationResponseIEs_t, ie11); - ie11->id = F1AP_ProtocolIE_ID_id_CriticalityDiagnostics; - ie11->criticality = F1AP_Criticality_ignore; - ie11->value.present = F1AP_UEContextModificationResponseIEs__value_PR_CriticalityDiagnostics; - - // dummy value - /* optional */ - /* procedureCode */ - if (0) { - ie11->value.choice.CriticalityDiagnostics.procedureCode = (F1AP_ProcedureCode_t *)calloc(1, sizeof(F1AP_ProcedureCode_t)); - *ie11->value.choice.CriticalityDiagnostics.procedureCode = 0L; - } - - /* optional */ - /* triggeringMessage */ - if (0) { - ie11->value.choice.CriticalityDiagnostics.triggeringMessage = (F1AP_TriggeringMessage_t *)calloc(1, sizeof(F1AP_TriggeringMessage_t)); - *ie11->value.choice.CriticalityDiagnostics.triggeringMessage = F1AP_TriggeringMessage_successful_outcome; - } - - /* optional */ - /* procedureCriticality */ - if (0) { - ie11->value.choice.CriticalityDiagnostics.procedureCriticality = (F1AP_Criticality_t *)calloc(1, sizeof(F1AP_Criticality_t)); - *ie11->value.choice.CriticalityDiagnostics.procedureCriticality = F1AP_Criticality_reject; - } - - /* optional */ - /* transactionID */ - if (0) { - ie11->value.choice.CriticalityDiagnostics.transactionID = (F1AP_TransactionID_t *)calloc(1, sizeof(F1AP_TransactionID_t)); - *ie11->value.choice.CriticalityDiagnostics.transactionID = 0L; - } - - /* optional */ - /* F1AP_CriticalityDiagnostics_IE_List */ - if (0) { - for (int i=0; i<0; i++) { - asn1cSequenceAdd(ie11->value.choice.CriticalityDiagnostics.iEsCriticalityDiagnostics->list, F1AP_CriticalityDiagnostics_IE_Item_t, criticalityDiagnostics_ie_item); - criticalityDiagnostics_ie_item->iECriticality = F1AP_Criticality_reject; - criticalityDiagnostics_ie_item->iE_ID = 0L; - criticalityDiagnostics_ie_item->typeOfError = F1AP_TypeOfError_not_understood; - } - } - } - /* optional */ - /* c12. SRBs_Setup_List */ - if(resp->srbs_to_be_setup_length > 0){ - asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextModificationResponseIEs_t, ie12); - ie12->id = F1AP_ProtocolIE_ID_id_SRBs_SetupMod_List; - ie12->criticality = F1AP_Criticality_ignore; - ie12->value.present = F1AP_UEContextModificationResponseIEs__value_PR_SRBs_SetupMod_List; - - for (int i=0; i< resp->srbs_to_be_setup_length; i++) {// - asn1cSequenceAdd(ie12->value.choice.SRBs_SetupMod_List.list, - F1AP_SRBs_SetupMod_ItemIEs_t, srbs_setupmod_item_ies); - srbs_setupmod_item_ies->id = F1AP_ProtocolIE_ID_id_SRBs_SetupMod_Item; - srbs_setupmod_item_ies->criticality = F1AP_Criticality_ignore; - srbs_setupmod_item_ies->value.present = F1AP_SRBs_SetupMod_ItemIEs__value_PR_SRBs_SetupMod_Item; - /* 11.1 SRBs_Setup_Item */ - /* ADD */ - F1AP_SRBs_SetupMod_Item_t *srbs_setupmod_item=&srbs_setupmod_item_ies->value.choice.SRBs_SetupMod_Item; - /* sRBID */ - srbs_setupmod_item->sRBID = resp->srbs_to_be_setup[i].srb_id; - srbs_setupmod_item->lCID = resp->srbs_to_be_setup[i].srb_id; - } - } - - /* encode */ - if (f1ap_encode_pdu(&pdu, &buffer, &len) < 0) { - LOG_E(F1AP, "Failed to encode F1 UE CONTEXT MODIFICATION RESPONSE\n"); + uint8_t *buffer = NULL; + uint32_t len = 0; + if (f1ap_encode_pdu(pdu, &buffer, &len) < 0) { + LOG_E(F1AP, "Failed to encode F1 UE CONTEXT SETUP RESPONSE\n"); return -1; } - f1ap_itti_send_sctp_data_req(assoc_id, buffer, len); + ASN_STRUCT_FREE(asn_DEF_F1AP_F1AP_PDU, pdu); return 0; } diff --git a/openair2/F1AP/f1ap_du_ue_context_management.h b/openair2/F1AP/f1ap_du_ue_context_management.h index 43663ba538..8f38ac8dd9 100644 --- a/openair2/F1AP/f1ap_du_ue_context_management.h +++ b/openair2/F1AP/f1ap_du_ue_context_management.h @@ -36,7 +36,7 @@ /* * UE Context Setup */ -int DU_send_UE_CONTEXT_SETUP_RESPONSE(sctp_assoc_t assoc_id, f1ap_ue_context_setup_t *req); +int DU_send_UE_CONTEXT_SETUP_RESPONSE(sctp_assoc_t assoc_id, f1ap_ue_context_setup_resp_t *resp); int DU_handle_UE_CONTEXT_SETUP_REQUEST(instance_t instance, sctp_assoc_t assoc_id, uint32_t stream, F1AP_F1AP_PDU_t *pdu); int DU_send_UE_CONTEXT_SETUP_FAILURE(sctp_assoc_t assoc_id); @@ -63,7 +63,7 @@ int DU_send_UE_CONTEXT_RELEASE_COMPLETE(sctp_assoc_t assoc_id, f1ap_ue_context_r * UE Context Modification (gNB-CU initiated) */ int DU_handle_UE_CONTEXT_MODIFICATION_REQUEST(instance_t instance, sctp_assoc_t assoc_id, uint32_t stream, F1AP_F1AP_PDU_t *pdu); -int DU_send_UE_CONTEXT_MODIFICATION_RESPONSE(sctp_assoc_t assoc_id, f1ap_ue_context_modif_resp_t *resp); +int DU_send_UE_CONTEXT_MODIFICATION_RESPONSE(sctp_assoc_t assoc_id, f1ap_ue_context_mod_resp_t *resp); int DU_send_UE_CONTEXT_MODIFICATION_FAILURE(sctp_assoc_t assoc_id); 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 5f2e9b9dfa..58d8dbf86c 100644 --- a/openair2/LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.c +++ b/openair2/LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.c @@ -235,7 +235,7 @@ static NR_RLC_BearerConfig_t *get_bearerconfig_from_srb(const f1ap_srb_to_setup_ static int handle_ue_context_srbs_setup(NR_UE_info_t *UE, int srbs_len, const f1ap_srb_to_setup_t *req_srbs, - f1ap_srb_to_be_setup_t **resp_srbs, + f1ap_srb_setup_t **resp_srbs, NR_CellGroupConfig_t *cellGroupConfig, const nr_rlc_configuration_t *rlc_config) { @@ -252,7 +252,7 @@ static int handle_ue_context_srbs_setup(NR_UE_info_t *UE, nr_lc_config_t c = {.lcid = rlc_BearerConfig->logicalChannelIdentity, .priority = priority}; nr_mac_add_lcid(&UE->UE_sched_ctrl, &c); - (*resp_srbs)[i].srb_id = srb->id; + (*resp_srbs)[i].id = srb->id; (*resp_srbs)[i].lcid = c.lcid; if (rlc_BearerConfig->logicalChannelIdentity == 1) { @@ -308,7 +308,7 @@ static NR_QoS_config_t get_qos_config(const f1ap_qos_flow_param_t *qos) static int handle_ue_context_drbs_setup(NR_UE_info_t *UE, int drbs_len, const f1ap_drb_to_setup_t *req_drbs, - f1ap_drb_to_be_setup_t **resp_drbs, + f1ap_drb_setup_t **resp_drbs, NR_CellGroupConfig_t *cellGroupConfig, const nr_rlc_configuration_t *rlc_config) { @@ -322,7 +322,7 @@ static int handle_ue_context_drbs_setup(NR_UE_info_t *UE, for (int i = 0; i < drbs_len; i++) { const f1ap_drb_to_setup_t *drb = &req_drbs[i]; AssertFatal(drb->qos_choice == F1AP_QOS_CHOICE_NR, "only NR QoS supported\n"); - f1ap_drb_to_be_setup_t *resp_drb = &(*resp_drbs)[i]; + f1ap_drb_setup_t *resp_drb = &(*resp_drbs)[i]; NR_RLC_BearerConfig_t *rlc_BearerConfig = get_bearerconfig_from_drb(drb, rlc_config); nr_rlc_add_drb(UE->rnti, drb->id, rlc_BearerConfig); @@ -335,11 +335,12 @@ static int handle_ue_context_drbs_setup(NR_UE_info_t *UE, c.priority = prio; nr_mac_add_lcid(&UE->UE_sched_ctrl, &c); - resp_drb->drb_id = drb->id; - // TODO lcid + resp_drb->id = drb->id; + resp_drb->lcid = malloc_or_fail(sizeof(*resp_drb->lcid)); + *resp_drb->lcid = c.lcid; // just put same number of tunnels in DL as in UL DevAssert(drb->up_ul_tnl_len == 1); - resp_drb->up_dl_tnl_length = drb->up_ul_tnl_len; + resp_drb->up_dl_tnl_len = drb->up_ul_tnl_len; if (f1inst >= 0) { // we actually use F1-U int qfi = -1; // don't put PDU session marker in GTP @@ -608,8 +609,7 @@ void ue_context_setup_request(const f1ap_ue_context_setup_req_t *req) const bool is_SA = IS_SA_MODE(get_softmodem_params()); gNB_MAC_INST *mac = RC.nrmac[0]; - /* TODO: update response */ - f1ap_ue_context_setup_t resp = { + f1ap_ue_context_setup_resp_t resp = { .gNB_CU_ue_id = req->gNB_CU_ue_id, }; @@ -639,7 +639,8 @@ void ue_context_setup_request(const f1ap_ue_context_setup_req_t *req) if (!ue_id_provided) { UE = create_new_UE(mac, req->gNB_CU_ue_id, cg_configinfo); resp.gNB_DU_ue_id = UE->rnti; - resp.crnti = &UE->rnti; + resp.crnti = malloc_or_fail(sizeof(*resp.crnti)); + *resp.crnti = UE->rnti; } else { DevAssert(is_SA); UE = find_nr_UE(&mac->UE_info, *req->gNB_DU_ue_id); @@ -650,21 +651,12 @@ void ue_context_setup_request(const f1ap_ue_context_setup_req_t *req) NR_CellGroupConfig_t *new_CellGroup = clone_CellGroupConfig(UE->CellGroup); if (req->srbs_len > 0) { - resp.srbs_to_be_setup_length = handle_ue_context_srbs_setup(UE, - req->srbs_len, - req->srbs, - &resp.srbs_to_be_setup, - new_CellGroup, - &mac->rlc_config); + resp.srbs_len = handle_ue_context_srbs_setup(UE, req->srbs_len, req->srbs, &resp.srbs, new_CellGroup, &mac->rlc_config); } if (req->drbs_len > 0) { - resp.drbs_to_be_setup_length = handle_ue_context_drbs_setup(UE, - req->drbs_len, - req->drbs, - &resp.drbs_to_be_setup, - new_CellGroup, - &mac->rlc_config); + resp.drbs_len = + handle_ue_context_drbs_setup(UE, req->drbs_len, req->drbs, &resp.drbs, new_CellGroup, &mac->rlc_config); } if (req->rrc_container != NULL) { @@ -692,14 +684,12 @@ void ue_context_setup_request(const f1ap_ue_context_setup_req_t *req) } } - resp.du_to_cu_rrc_information = calloc(1, sizeof(du_to_cu_rrc_information_t)); - AssertFatal(resp.du_to_cu_rrc_information != NULL, "out of memory\n"); - resp.du_to_cu_rrc_information->cellGroupConfig = calloc(1,1024); - AssertFatal(resp.du_to_cu_rrc_information->cellGroupConfig != NULL, "out of memory\n"); + byte_array_t cgc = { .buf = calloc_or_fail(1,1024) }; asn_enc_rval_t enc_rval = - uper_encode_to_buffer(&asn_DEF_NR_CellGroupConfig, NULL, new_CellGroup, resp.du_to_cu_rrc_information->cellGroupConfig, 1024); + uper_encode_to_buffer(&asn_DEF_NR_CellGroupConfig, NULL, new_CellGroup, cgc.buf, 1024); AssertFatal(enc_rval.encoded > 0, "Could not encode CellGroup, failed element %s\n", enc_rval.failed_type->name); - resp.du_to_cu_rrc_information->cellGroupConfig_length = (enc_rval.encoded + 7) >> 3; + cgc.len = (enc_rval.encoded + 7) >> 3; + resp.du_to_cu_rrc_info.cell_group_config = cgc; ASN_STRUCT_FREE(asn_DEF_NR_CellGroupConfig, UE->CellGroup); UE->CellGroup = new_CellGroup; @@ -708,24 +698,16 @@ void ue_context_setup_request(const f1ap_ue_context_setup_req_t *req) NR_SCHED_UNLOCK(&mac->sched_lock); - /* some sanity checks, since we use the same type for request and response */ - DevAssert(resp.cu_to_du_rrc_information == NULL); - DevAssert(resp.du_to_cu_rrc_information != NULL); - DevAssert(resp.rrc_container == NULL && resp.rrc_container_length == 0); - mac->mac_rrc.ue_context_setup_response(&resp); /* free the memory we allocated above */ - free(resp.srbs_to_be_setup); - free(resp.drbs_to_be_setup); - free(resp.du_to_cu_rrc_information->cellGroupConfig); - free(resp.du_to_cu_rrc_information); + free_ue_context_setup_resp(&resp); } void ue_context_modification_request(const f1ap_ue_context_mod_req_t *req) { gNB_MAC_INST *mac = RC.nrmac[0]; - f1ap_ue_context_modif_resp_t resp = { + f1ap_ue_context_mod_resp_t resp = { .gNB_CU_ue_id = req->gNB_CU_ue_id, .gNB_DU_ue_id = req->gNB_DU_ue_id, }; @@ -751,25 +733,15 @@ void ue_context_modification_request(const f1ap_ue_context_mod_req_t *req) NR_CellGroupConfig_t *new_CellGroup = clone_CellGroupConfig(UE->CellGroup); if (req->srbs_len > 0) { - resp.srbs_to_be_setup_length = handle_ue_context_srbs_setup(UE, - req->srbs_len, - req->srbs, - &resp.srbs_to_be_setup, - new_CellGroup, - &mac->rlc_config); + resp.srbs_len = handle_ue_context_srbs_setup(UE, req->srbs_len, req->srbs, &resp.srbs, new_CellGroup, &mac->rlc_config); } if (req->drbs_len > 0) { - resp.drbs_to_be_setup_length = handle_ue_context_drbs_setup(UE, - req->drbs_len, - req->drbs, - &resp.drbs_to_be_setup, - new_CellGroup, - &mac->rlc_config); + resp.drbs_len = handle_ue_context_drbs_setup(UE, req->drbs_len, req->drbs, &resp.drbs, new_CellGroup, &mac->rlc_config); } if (req->drbs_rel_len > 0) { - resp.drbs_to_be_released_length = handle_ue_context_drbs_release(UE, req->drbs_rel_len, req->drbs_rel, new_CellGroup); + handle_ue_context_drbs_release(UE, req->drbs_rel_len, req->drbs_rel, new_CellGroup); } if (req->rrc_container != NULL) { @@ -808,17 +780,16 @@ void ue_context_modification_request(const f1ap_ue_context_mod_req_t *req) } if (req->srbs_len > 0 || req->drbs_len > 0 || req->drbs_rel_len > 0 || ue_cap != NULL) { - resp.du_to_cu_rrc_information = calloc(1, sizeof(du_to_cu_rrc_information_t)); - AssertFatal(resp.du_to_cu_rrc_information != NULL, "out of memory\n"); - resp.du_to_cu_rrc_information->cellGroupConfig = calloc(1, 1024); - AssertFatal(resp.du_to_cu_rrc_information->cellGroupConfig != NULL, "out of memory\n"); + resp.du_to_cu_rrc_info = calloc_or_fail(1, sizeof(du_to_cu_rrc_information_t)); + byte_array_t cgc = { .buf = calloc_or_fail(1, 1024) }; asn_enc_rval_t enc_rval = uper_encode_to_buffer(&asn_DEF_NR_CellGroupConfig, NULL, new_CellGroup, - resp.du_to_cu_rrc_information->cellGroupConfig, + cgc.buf, 1024); AssertFatal(enc_rval.encoded > 0, "Could not encode CellGroup, failed element %s\n", enc_rval.failed_type->name); - resp.du_to_cu_rrc_information->cellGroupConfig_length = (enc_rval.encoded + 7) >> 3; + cgc.len = (enc_rval.encoded + 7) >> 3; + resp.du_to_cu_rrc_info->cell_group_config = cgc; ASN_STRUCT_FREE(asn_DEF_NR_CellGroupConfig, UE->CellGroup); UE->CellGroup = new_CellGroup; @@ -833,20 +804,10 @@ void ue_context_modification_request(const f1ap_ue_context_mod_req_t *req) } NR_SCHED_UNLOCK(&mac->sched_lock); - /* some sanity checks, since we use the same type for request and response */ - DevAssert(resp.cu_to_du_rrc_information == NULL); - // resp.du_to_cu_rrc_information can be either NULL or not - DevAssert(resp.rrc_container == NULL && resp.rrc_container_length == 0); - mac->mac_rrc.ue_context_modification_response(&resp); /* free the memory we allocated above */ - free(resp.srbs_to_be_setup); - free(resp.drbs_to_be_setup); - if (resp.du_to_cu_rrc_information != NULL) { - free(resp.du_to_cu_rrc_information->cellGroupConfig); - free(resp.du_to_cu_rrc_information); - } + free_ue_context_mod_resp(&resp); } void ue_context_modification_confirm(const f1ap_ue_context_modif_confirm_t *confirm) diff --git a/openair2/LAYER2/NR_MAC_gNB/mac_rrc_ul.h b/openair2/LAYER2/NR_MAC_gNB/mac_rrc_ul.h index 6681b96032..033e8590d2 100644 --- a/openair2/LAYER2/NR_MAC_gNB/mac_rrc_ul.h +++ b/openair2/LAYER2/NR_MAC_gNB/mac_rrc_ul.h @@ -31,8 +31,8 @@ typedef void (*f1_reset_acknowledge_cu_initiated_func_t)(const f1ap_reset_ack_t 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); -typedef void (*ue_context_setup_response_func_t)(const f1ap_ue_context_setup_t *resp); -typedef void (*ue_context_modification_response_func_t)(const f1ap_ue_context_modif_resp_t *resp); +typedef void (*ue_context_setup_response_func_t)(const f1ap_ue_context_setup_resp_t *resp); +typedef void (*ue_context_modification_response_func_t)(const f1ap_ue_context_mod_resp_t *resp); typedef void (*ue_context_modification_required_func_t)(const f1ap_ue_context_modif_required_t *t); typedef void (*ue_context_release_request_func_t)(const f1ap_ue_context_release_req_t* req); typedef void (*ue_context_release_complete_func_t)(const f1ap_ue_context_release_complete_t *complete); 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 d1c9efbdfb..72308bdd66 100644 --- a/openair2/LAYER2/NR_MAC_gNB/mac_rrc_ul_direct.c +++ b/openair2/LAYER2/NR_MAC_gNB/mac_rrc_ul_direct.c @@ -25,6 +25,7 @@ #include "mac_rrc_ul.h" #include "lib/f1ap_rrc_message_transfer.h" #include "lib/f1ap_interface_management.h" +#include "lib/f1ap_ue_context.h" static void f1_reset_du_initiated_direct(const f1ap_reset_t *reset) { @@ -58,91 +59,19 @@ static void gnb_du_configuration_update_direct(const f1ap_gnb_du_configuration_u itti_send_msg_to_task(TASK_RRC_GNB, 0, msg); } -static void ue_context_setup_response_direct(const f1ap_ue_context_setup_t *resp) +static void ue_context_setup_response_direct(const f1ap_ue_context_setup_resp_t *resp) { MessageDef *msg = itti_alloc_new_message (TASK_MAC_GNB, 0, F1AP_UE_CONTEXT_SETUP_RESP); msg->ittiMsgHeader.originInstance = -1; // means monolithic - f1ap_ue_context_setup_t *f1ap_msg = &F1AP_UE_CONTEXT_SETUP_RESP(msg); - /* copy all fields, but reallocate memory buffers! */ - *f1ap_msg = *resp; - - if (resp->srbs_to_be_setup_length > 0) { - DevAssert(resp->srbs_to_be_setup != NULL); - f1ap_msg->srbs_to_be_setup_length = resp->srbs_to_be_setup_length; - f1ap_msg->srbs_to_be_setup = calloc(f1ap_msg->srbs_to_be_setup_length, sizeof(*f1ap_msg->srbs_to_be_setup)); - for (int i = 0; i < f1ap_msg->srbs_to_be_setup_length; ++i) - f1ap_msg->srbs_to_be_setup[i] = resp->srbs_to_be_setup[i]; - } - if (resp->drbs_to_be_setup_length > 0) { - DevAssert(resp->drbs_to_be_setup != NULL); - f1ap_msg->drbs_to_be_setup_length = resp->drbs_to_be_setup_length; - f1ap_msg->drbs_to_be_setup = calloc(f1ap_msg->drbs_to_be_setup_length, sizeof(*f1ap_msg->drbs_to_be_setup)); - for (int i = 0; i < f1ap_msg->drbs_to_be_setup_length; ++i) - f1ap_msg->drbs_to_be_setup[i] = resp->drbs_to_be_setup[i]; - } - - f1ap_msg->du_to_cu_rrc_information = malloc(sizeof(*resp->du_to_cu_rrc_information)); - AssertFatal(f1ap_msg->du_to_cu_rrc_information != NULL, "out of memory\n"); - f1ap_msg->du_to_cu_rrc_information_length = resp->du_to_cu_rrc_information_length; - du_to_cu_rrc_information_t *du2cu = f1ap_msg->du_to_cu_rrc_information; - du2cu->cellGroupConfig_length = resp->du_to_cu_rrc_information->cellGroupConfig_length; - du2cu->cellGroupConfig = calloc(du2cu->cellGroupConfig_length, sizeof(*du2cu->cellGroupConfig)); - AssertFatal(du2cu->cellGroupConfig != NULL, "out of memory\n"); - memcpy(du2cu->cellGroupConfig, resp->du_to_cu_rrc_information->cellGroupConfig, du2cu->cellGroupConfig_length); - + F1AP_UE_CONTEXT_SETUP_RESP(msg) = cp_ue_context_setup_resp(resp); itti_send_msg_to_task(TASK_RRC_GNB, 0, msg); } -static void ue_context_modification_response_direct(const f1ap_ue_context_modif_resp_t *resp) +static void ue_context_modification_response_direct(const f1ap_ue_context_mod_resp_t *resp) { MessageDef *msg = itti_alloc_new_message(TASK_MAC_GNB, 0, F1AP_UE_CONTEXT_MODIFICATION_RESP); msg->ittiMsgHeader.originInstance = -1; // means monolithic - f1ap_ue_context_modif_resp_t *f1ap_msg = &F1AP_UE_CONTEXT_MODIFICATION_RESP(msg); - - f1ap_msg->gNB_CU_ue_id = resp->gNB_CU_ue_id; - f1ap_msg->gNB_DU_ue_id = resp->gNB_DU_ue_id; - f1ap_msg->plmn = resp->plmn; - f1ap_msg->nr_cellid = resp->nr_cellid; - f1ap_msg->servCellIndex = resp->servCellIndex; - AssertFatal(resp->cellULConfigured == NULL, "not handled\n"); - f1ap_msg->servCellId = resp->servCellId; - - DevAssert(resp->cu_to_du_rrc_information == NULL && resp->cu_to_du_rrc_information_length == 0); - if (resp->du_to_cu_rrc_information) { - f1ap_msg->du_to_cu_rrc_information = malloc(sizeof(*resp->du_to_cu_rrc_information)); - AssertFatal(f1ap_msg->du_to_cu_rrc_information != NULL, "out of memory\n"); - f1ap_msg->du_to_cu_rrc_information_length = resp->du_to_cu_rrc_information_length; - du_to_cu_rrc_information_t *du2cu = f1ap_msg->du_to_cu_rrc_information; - du2cu->cellGroupConfig_length = resp->du_to_cu_rrc_information->cellGroupConfig_length; - du2cu->cellGroupConfig = calloc(du2cu->cellGroupConfig_length, sizeof(*du2cu->cellGroupConfig)); - AssertFatal(du2cu->cellGroupConfig != NULL, "out of memory\n"); - memcpy(du2cu->cellGroupConfig, resp->du_to_cu_rrc_information->cellGroupConfig, du2cu->cellGroupConfig_length); - } - - if (resp->drbs_to_be_setup_length > 0) { - DevAssert(resp->drbs_to_be_setup != NULL); - f1ap_msg->drbs_to_be_setup_length = resp->drbs_to_be_setup_length; - f1ap_msg->drbs_to_be_setup = calloc(f1ap_msg->drbs_to_be_setup_length, sizeof(*f1ap_msg->drbs_to_be_setup)); - for (int i = 0; i < f1ap_msg->drbs_to_be_setup_length; ++i) - f1ap_msg->drbs_to_be_setup[i] = resp->drbs_to_be_setup[i]; - } - - DevAssert(resp->drbs_to_be_modified == NULL && resp->drbs_to_be_modified_length == 0); - f1ap_msg->QoS_information_type = resp->QoS_information_type; - AssertFatal(resp->drbs_failed_to_be_setup_length == 0 && resp->drbs_failed_to_be_setup == NULL, "not implemented yet\n"); - - if (resp->srbs_to_be_setup_length > 0) { - DevAssert(resp->srbs_to_be_setup != NULL); - f1ap_msg->srbs_to_be_setup_length = resp->srbs_to_be_setup_length; - f1ap_msg->srbs_to_be_setup = calloc(f1ap_msg->srbs_to_be_setup_length, sizeof(*f1ap_msg->srbs_to_be_setup)); - for (int i = 0; i < f1ap_msg->srbs_to_be_setup_length; ++i) - f1ap_msg->srbs_to_be_setup[i] = resp->srbs_to_be_setup[i]; - } - - AssertFatal(resp->srbs_failed_to_be_setup_length == 0 && resp->srbs_failed_to_be_setup == NULL, "not implemented yet\n"); - - DevAssert(resp->rrc_container == NULL && resp->rrc_container_length == 0); - + F1AP_UE_CONTEXT_MODIFICATION_RESP(msg) = cp_ue_context_mod_resp(resp); 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 10b6206204..15101928e5 100644 --- a/openair2/LAYER2/NR_MAC_gNB/mac_rrc_ul_f1ap.c +++ b/openair2/LAYER2/NR_MAC_gNB/mac_rrc_ul_f1ap.c @@ -31,6 +31,7 @@ #include "lib/f1ap_rrc_message_transfer.h" #include "lib/f1ap_interface_management.h" +#include "lib/f1ap_ue_context.h" static f1ap_net_config_t read_DU_IP_config(const eth_params_t* f1_params, const char *f1u_ip_addr) { @@ -85,77 +86,17 @@ static void gnb_du_configuration_update_f1ap(const f1ap_gnb_du_configuration_upd itti_send_msg_to_task(TASK_DU_F1, 0, msg); } -static void ue_context_setup_response_f1ap(const f1ap_ue_context_setup_t *resp) +static void ue_context_setup_response_f1ap(const f1ap_ue_context_setup_resp_t *resp) { MessageDef *msg = itti_alloc_new_message (TASK_MAC_GNB, 0, F1AP_UE_CONTEXT_SETUP_RESP); - f1ap_ue_context_setup_t *f1ap_msg = &F1AP_UE_CONTEXT_SETUP_RESP(msg); - /* copy all fields, but reallocate rrc_containers! */ - *f1ap_msg = *resp; - - if (resp->srbs_to_be_setup_length > 0) { - DevAssert(resp->srbs_to_be_setup != NULL); - f1ap_msg->srbs_to_be_setup_length = resp->srbs_to_be_setup_length; - f1ap_msg->srbs_to_be_setup = calloc(f1ap_msg->srbs_to_be_setup_length, sizeof(*f1ap_msg->srbs_to_be_setup)); - for (int i = 0; i < f1ap_msg->srbs_to_be_setup_length; ++i) - f1ap_msg->srbs_to_be_setup[i] = resp->srbs_to_be_setup[i]; - } - if (resp->drbs_to_be_setup_length > 0) { - DevAssert(resp->drbs_to_be_setup != NULL); - f1ap_msg->drbs_to_be_setup_length = resp->drbs_to_be_setup_length; - f1ap_msg->drbs_to_be_setup = calloc(f1ap_msg->drbs_to_be_setup_length, sizeof(*f1ap_msg->drbs_to_be_setup)); - for (int i = 0; i < f1ap_msg->drbs_to_be_setup_length; ++i) - f1ap_msg->drbs_to_be_setup[i] = resp->drbs_to_be_setup[i]; - } - if (resp->crnti) { - f1ap_msg->crnti = calloc(1, sizeof(uint16_t)); - *f1ap_msg->crnti = *resp->crnti; - } - - f1ap_msg->du_to_cu_rrc_information = malloc(sizeof(*resp->du_to_cu_rrc_information)); - AssertFatal(f1ap_msg->du_to_cu_rrc_information != NULL, "out of memory\n"); - f1ap_msg->du_to_cu_rrc_information_length = resp->du_to_cu_rrc_information_length; - du_to_cu_rrc_information_t *du2cu = f1ap_msg->du_to_cu_rrc_information; - du2cu->cellGroupConfig_length = resp->du_to_cu_rrc_information->cellGroupConfig_length; - du2cu->cellGroupConfig = calloc(du2cu->cellGroupConfig_length, sizeof(*du2cu->cellGroupConfig)); - AssertFatal(du2cu->cellGroupConfig != NULL, "out of memory\n"); - memcpy(du2cu->cellGroupConfig, resp->du_to_cu_rrc_information->cellGroupConfig, du2cu->cellGroupConfig_length); - + F1AP_UE_CONTEXT_SETUP_RESP(msg) = cp_ue_context_setup_resp(resp); itti_send_msg_to_task(TASK_DU_F1, 0, msg); } -static void ue_context_modification_response_f1ap(const f1ap_ue_context_modif_resp_t *resp) +static void ue_context_modification_response_f1ap(const f1ap_ue_context_mod_resp_t *resp) { MessageDef *msg = itti_alloc_new_message(TASK_MAC_GNB, 0, F1AP_UE_CONTEXT_MODIFICATION_RESP); - f1ap_ue_context_modif_resp_t *f1ap_msg = &F1AP_UE_CONTEXT_MODIFICATION_RESP(msg); - /* copy all fields, but reallocate rrc_containers! */ - *f1ap_msg = *resp; - - if (resp->srbs_to_be_setup_length > 0) { - DevAssert(resp->srbs_to_be_setup != NULL); - f1ap_msg->srbs_to_be_setup_length = resp->srbs_to_be_setup_length; - f1ap_msg->srbs_to_be_setup = calloc(f1ap_msg->srbs_to_be_setup_length, sizeof(*f1ap_msg->srbs_to_be_setup)); - for (int i = 0; i < f1ap_msg->srbs_to_be_setup_length; ++i) - f1ap_msg->srbs_to_be_setup[i] = resp->srbs_to_be_setup[i]; - } - if (resp->drbs_to_be_setup_length > 0) { - DevAssert(resp->drbs_to_be_setup != NULL); - f1ap_msg->drbs_to_be_setup_length = resp->drbs_to_be_setup_length; - f1ap_msg->drbs_to_be_setup = calloc(f1ap_msg->drbs_to_be_setup_length, sizeof(*f1ap_msg->drbs_to_be_setup)); - for (int i = 0; i < f1ap_msg->drbs_to_be_setup_length; ++i) - f1ap_msg->drbs_to_be_setup[i] = resp->drbs_to_be_setup[i]; - } - - if (resp->du_to_cu_rrc_information != NULL) { - f1ap_msg->du_to_cu_rrc_information = calloc(1, sizeof(*resp->du_to_cu_rrc_information)); - AssertFatal(f1ap_msg->du_to_cu_rrc_information != NULL, "out of memory\n"); - f1ap_msg->du_to_cu_rrc_information_length = resp->du_to_cu_rrc_information_length; - du_to_cu_rrc_information_t *du2cu = f1ap_msg->du_to_cu_rrc_information; - du2cu->cellGroupConfig_length = resp->du_to_cu_rrc_information->cellGroupConfig_length; - du2cu->cellGroupConfig = calloc(du2cu->cellGroupConfig_length, sizeof(*du2cu->cellGroupConfig)); - AssertFatal(du2cu->cellGroupConfig != NULL, "out of memory\n"); - memcpy(du2cu->cellGroupConfig, resp->du_to_cu_rrc_information->cellGroupConfig, du2cu->cellGroupConfig_length); - } - + F1AP_UE_CONTEXT_MODIFICATION_RESP(msg) = cp_ue_context_mod_resp(resp); itti_send_msg_to_task(TASK_DU_F1, 0, msg); } diff --git a/openair2/RRC/NR/nr_rrc_proto.h b/openair2/RRC/NR/nr_rrc_proto.h index 3ac774c69f..c49a419556 100644 --- a/openair2/RRC/NR/nr_rrc_proto.h +++ b/openair2/RRC/NR/nr_rrc_proto.h @@ -44,7 +44,7 @@ #define SRB2 2 void rrc_add_nsa_user(gNB_RRC_INST *rrc, x2ap_ENDC_sgnb_addition_req_t *m, sctp_assoc_t assoc_id); -void rrc_add_nsa_user_resp(gNB_RRC_INST *rrc, gNB_RRC_UE_t *UE, const f1ap_ue_context_setup_t *resp); +void rrc_add_nsa_user_resp(gNB_RRC_INST *rrc, gNB_RRC_UE_t *UE, const f1ap_ue_context_setup_resp_t *resp); void rrc_release_nsa_user(gNB_RRC_INST *rrc, rrc_gNB_ue_context_t *ue_context); void rrc_remove_nsa_user_context(gNB_RRC_INST *rrc, rrc_gNB_ue_context_t *ue_context); diff --git a/openair2/RRC/NR/rrc_gNB.c b/openair2/RRC/NR/rrc_gNB.c index 6e53de1c10..eb51d4b799 100644 --- a/openair2/RRC/NR/rrc_gNB.c +++ b/openair2/RRC/NR/rrc_gNB.c @@ -1999,10 +1999,10 @@ void rrc_gNB_process_dc_overall_timeout(const module_id_t gnb_mod_idP, x2ap_ENDC /* \brief fill E1 bearer modification's DRB from F1 DRB * \param drb_e1 pointer to a DRB inside an E1 bearer modification message * \param drb_f1 pointer to a DRB inside an F1 UE Ctxt modification Response */ -static void fill_e1_bearer_modif(DRB_nGRAN_to_mod_t *drb_e1, const f1ap_drb_to_be_setup_t *drb_f1) +static void fill_e1_bearer_modif(DRB_nGRAN_to_mod_t *drb_e1, const f1ap_drb_setup_t *drb_f1) { - drb_e1->id = drb_f1->drb_id; - drb_e1->numDlUpParam = drb_f1->up_dl_tnl_length; + drb_e1->id = drb_f1->id; + drb_e1->numDlUpParam = drb_f1->up_dl_tnl_len; drb_e1->DlUpParamList[0].tl_info.tlAddress = drb_f1->up_dl_tnl[0].tl_address; drb_e1->DlUpParamList[0].tl_info.teId = drb_f1->up_dl_tnl[0].teid; } @@ -2019,20 +2019,20 @@ static gtpu_tunnel_t f1u_gtp_update(uint32_t teid, const in_addr_t addr) /** * @brief Update DRB TEID information in RRC storage from received DRB list */ -static void store_du_f1u_tunnel(const f1ap_drb_to_be_setup_t *drbs, int n, gNB_RRC_UE_t *ue) +static void store_du_f1u_tunnel(const f1ap_drb_setup_t *drbs, int n, gNB_RRC_UE_t *ue) { for (int i = 0; i < n; i++) { - const f1ap_drb_to_be_setup_t *drb_f1 = &drbs[i]; - AssertFatal(drb_f1->up_dl_tnl_length == 1, "can handle only one UP param\n"); - AssertFatal(drb_f1->drb_id < MAX_DRBS_PER_UE, "illegal DRB ID %ld\n", drb_f1->drb_id); - drb_t *drb = get_drb(ue, drb_f1->drb_id); + const f1ap_drb_setup_t *drb_f1 = &drbs[i]; + AssertFatal(drb_f1->up_dl_tnl_len == 1, "can handle only one UP param\n"); + AssertFatal(drb_f1->id < MAX_DRBS_PER_UE, "illegal DRB ID %d\n", drb_f1->id); + drb_t *drb = get_drb(ue, drb_f1->id); drb->du_tunnel_config = f1u_gtp_update(drb_f1->up_dl_tnl[0].teid, drb_f1->up_dl_tnl[0].tl_address); } } /* \brief use list of DRBs and send the corresponding bearer update message via * E1 to the CU of this UE. Also updates TEID info internally */ -static void e1_send_bearer_updates(gNB_RRC_INST *rrc, gNB_RRC_UE_t *UE, int n, f1ap_drb_to_be_setup_t *drbs) +static void e1_send_bearer_updates(gNB_RRC_INST *rrc, gNB_RRC_UE_t *UE, int n, f1ap_drb_setup_t *drbs) { // Quit bearer updates if no CU-UP is associated if (!is_cuup_associated(rrc)) { @@ -2046,10 +2046,10 @@ static void e1_send_bearer_updates(gNB_RRC_INST *rrc, gNB_RRC_UE_t *UE, int n, f }; for (int i = 0; i < n; i++) { - const f1ap_drb_to_be_setup_t *drb_f1 = &drbs[i]; - rrc_pdu_session_param_t *pdu_ue = find_pduSession_from_drbId(UE, drb_f1->drb_id); + const f1ap_drb_setup_t *drb_f1 = &drbs[i]; + rrc_pdu_session_param_t *pdu_ue = find_pduSession_from_drbId(UE, drb_f1->id); if (pdu_ue == NULL) { - LOG_E(RRC, "UE %d: UE Context Modif Response: no PDU session for DRB ID %ld\n", UE->rrc_ue_id, drb_f1->drb_id); + LOG_E(RRC, "UE %d: UE Context Modif Response: no PDU session for DRB ID %d\n", UE->rrc_ue_id, drb_f1->id); continue; } pdu_session_to_mod_t *pdu_e1 = find_or_next_pdu_session(&req, pdu_ue->param.pdusession_id); @@ -2074,7 +2074,7 @@ static void e1_send_bearer_updates(gNB_RRC_INST *rrc, gNB_RRC_UE_t *UE, int n, f static void rrc_CU_process_ue_context_setup_response(MessageDef *msg_p, instance_t instance) { - f1ap_ue_context_setup_t *resp = &F1AP_UE_CONTEXT_SETUP_RESP(msg_p); + f1ap_ue_context_setup_resp_t *resp = &F1AP_UE_CONTEXT_SETUP_RESP(msg_p); gNB_RRC_INST *rrc = RC.nrrrc[instance]; rrc_gNB_ue_context_t *ue_context_p = rrc_gNB_get_ue_context(rrc, resp->gNB_CU_ue_id); if (!ue_context_p) { @@ -2085,11 +2085,9 @@ static void rrc_CU_process_ue_context_setup_response(MessageDef *msg_p, instance UE->f1_ue_context_active = true; NR_CellGroupConfig_t *cellGroupConfig = NULL; - asn_dec_rval_t dec_rval = uper_decode_complete(NULL, - &asn_DEF_NR_CellGroupConfig, - (void **)&cellGroupConfig, - (uint8_t *)resp->du_to_cu_rrc_information->cellGroupConfig, - resp->du_to_cu_rrc_information->cellGroupConfig_length); + byte_array_t *cgc = &resp->du_to_cu_rrc_info.cell_group_config; + asn_dec_rval_t dec_rval = + uper_decode_complete(NULL, &asn_DEF_NR_CellGroupConfig, (void **)&cellGroupConfig, (uint8_t *)cgc->buf, cgc->len); AssertFatal(dec_rval.code == RC_OK && dec_rval.consumed > 0, "Cell group config decode error\n"); if (UE->masterCellGroup) { @@ -2105,16 +2103,16 @@ static void rrc_CU_process_ue_context_setup_response(MessageDef *msg_p, instance return; } - if (resp->drbs_to_be_setup_length > 0) { + if (resp->drbs_len > 0) { int num_drb = get_number_active_drbs(UE); - DevAssert(num_drb == 0 || num_drb == resp->drbs_to_be_setup_length); + DevAssert(num_drb == 0 || num_drb == resp->drbs_len); /* Note: we would ideally check that SRB2 is acked, but at least LiteOn DU * seems buggy and does not ack, so simply check that locally we activated */ AssertFatal(UE->Srb[1].Active && UE->Srb[2].Active, "SRBs 1 and 2 must be active during DRB Establishment"); - store_du_f1u_tunnel(resp->drbs_to_be_setup, resp->drbs_to_be_setup_length, UE); + store_du_f1u_tunnel(resp->drbs, resp->drbs_len, UE); if (num_drb == 0) - e1_send_bearer_updates(rrc, UE, resp->drbs_to_be_setup_length, resp->drbs_to_be_setup); + e1_send_bearer_updates(rrc, UE, resp->drbs_len, resp->drbs); else cuup_notify_reestablishment(rrc, UE); } @@ -2232,7 +2230,7 @@ static void rrc_CU_process_ue_context_release_complete(MessageDef *msg_p) static void rrc_CU_process_ue_context_modification_response(MessageDef *msg_p, instance_t instance) { - f1ap_ue_context_modif_resp_t *resp = &F1AP_UE_CONTEXT_MODIFICATION_RESP(msg_p); + f1ap_ue_context_mod_resp_t *resp = &F1AP_UE_CONTEXT_MODIFICATION_RESP(msg_p); gNB_RRC_INST *rrc = RC.nrrrc[instance]; rrc_gNB_ue_context_t *ue_context_p = rrc_gNB_get_ue_context(rrc, resp->gNB_CU_ue_id); if (!ue_context_p) { @@ -2241,18 +2239,16 @@ static void rrc_CU_process_ue_context_modification_response(MessageDef *msg_p, i } gNB_RRC_UE_t *UE = &ue_context_p->ue_context; - if (resp->drbs_to_be_setup_length > 0) { - store_du_f1u_tunnel(resp->drbs_to_be_setup, resp->drbs_to_be_setup_length, UE); - e1_send_bearer_updates(rrc, UE, resp->drbs_to_be_setup_length, resp->drbs_to_be_setup); + if (resp->drbs_len > 0) { + store_du_f1u_tunnel(resp->drbs, resp->drbs_len, UE); + e1_send_bearer_updates(rrc, UE, resp->drbs_len, resp->drbs); } - if (resp->du_to_cu_rrc_information != NULL && resp->du_to_cu_rrc_information->cellGroupConfig != NULL) { + if (resp->du_to_cu_rrc_info) { NR_CellGroupConfig_t *cellGroupConfig = NULL; - asn_dec_rval_t dec_rval = uper_decode_complete(NULL, - &asn_DEF_NR_CellGroupConfig, - (void **)&cellGroupConfig, - (uint8_t *)resp->du_to_cu_rrc_information->cellGroupConfig, - resp->du_to_cu_rrc_information->cellGroupConfig_length); + byte_array_t *cgc = &resp->du_to_cu_rrc_info->cell_group_config; + asn_dec_rval_t dec_rval = + uper_decode_complete(NULL, &asn_DEF_NR_CellGroupConfig, (void **)&cellGroupConfig, (uint8_t *)cgc->buf, cgc->len); AssertFatal(dec_rval.code == RC_OK && dec_rval.consumed > 0, "Cell group config decode error\n"); if (UE->masterCellGroup) { @@ -2769,10 +2765,12 @@ void *rrc_gnb_task(void *args_p) { case F1AP_UE_CONTEXT_SETUP_RESP: rrc_CU_process_ue_context_setup_response(msg_p, instance); + free_ue_context_setup_resp(&F1AP_UE_CONTEXT_SETUP_RESP(msg_p)); break; case F1AP_UE_CONTEXT_MODIFICATION_RESP: rrc_CU_process_ue_context_modification_response(msg_p, instance); + free_ue_context_mod_resp(&F1AP_UE_CONTEXT_MODIFICATION_RESP(msg_p)); break; case F1AP_UE_CONTEXT_MODIFICATION_REQUIRED: diff --git a/openair2/RRC/NR/rrc_gNB_nsa.c b/openair2/RRC/NR/rrc_gNB_nsa.c index 1ccdb3439a..78be16b100 100644 --- a/openair2/RRC/NR/rrc_gNB_nsa.c +++ b/openair2/RRC/NR/rrc_gNB_nsa.c @@ -385,7 +385,7 @@ static NR_CG_Config_t *generate_CG_Config(const NR_RRCReconfiguration_t *reconfi return cg_Config; } -void rrc_add_nsa_user_resp(gNB_RRC_INST *rrc, gNB_RRC_UE_t *UE, const f1ap_ue_context_setup_t *resp) +void rrc_add_nsa_user_resp(gNB_RRC_INST *rrc, gNB_RRC_UE_t *UE, const f1ap_ue_context_setup_resp_t *resp) { DevAssert(resp->crnti != NULL); /* we did not fill any DU-related ID info in rrc_add_nsa_user() */ @@ -400,12 +400,12 @@ void rrc_add_nsa_user_resp(gNB_RRC_INST *rrc, gNB_RRC_UE_t *UE, const f1ap_ue_co if (f1inst >= 0) { // Note: E1 support for NSA/phy-test/do-ra not implemented yet // so set up GTP from here - for (int i = 0; i < resp->drbs_to_be_setup_length; ++i) { - f1ap_drb_to_be_setup_t *drb = &resp->drbs_to_be_setup[i]; - DevAssert(drb->up_dl_tnl_length == 1); + for (int i = 0; i < resp->drbs_len; ++i) { + f1ap_drb_setup_t *drb = &resp->drbs[i]; + DevAssert(drb->up_dl_tnl_len == 1); in_addr_t addr = drb->up_dl_tnl[0].tl_address; uint32_t teid = drb->up_dl_tnl[0].teid; - GtpuUpdateTunnelOutgoingAddressAndTeid(f1inst, UE->rrc_ue_id, drb->drb_id, addr, teid); + GtpuUpdateTunnelOutgoingAddressAndTeid(f1inst, UE->rrc_ue_id, drb->id, addr, teid); } } From 4d08801e9a87355d3e7dde263b13a2b95a4afbc5 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Thu, 19 Jun 2025 18:14:14 +0200 Subject: [PATCH 15/36] Refactor: use malloc to avoid mem leaks Move the filling of DRBs to set up for UE context setup/modification request into the corresponding functions, and use malloc() deliberately to avoid memory leaks. In fact fill_drb_to_be_setup_from_e1_resp() allocates memory dynamically (and has to do that), so the easiest is to do the same for DRBs. The most straight-forward way seems to be to then dynamically allocate all memory for F1 UE context setup/modification request messages, and free with the corresponding free functions, which removes a couple of memory leaks. --- openair2/RRC/NR/nr_rrc_proto.h | 6 ++-- openair2/RRC/NR/rrc_gNB.c | 65 +++++++++++++++++++--------------- 2 files changed, 39 insertions(+), 32 deletions(-) diff --git a/openair2/RRC/NR/nr_rrc_proto.h b/openair2/RRC/NR/nr_rrc_proto.h index c49a419556..094f1791c1 100644 --- a/openair2/RRC/NR/nr_rrc_proto.h +++ b/openair2/RRC/NR/nr_rrc_proto.h @@ -106,13 +106,11 @@ int rrc_gNB_generate_pcch_msg(sctp_assoc_t assoc_id, const NR_SIB1_t *sib, uint3 void rrc_gNB_generate_UeContextSetupRequest(const gNB_RRC_INST *rrc, rrc_gNB_ue_context_t *const ue_context_pP, - int n_drbs, - const f1ap_drb_to_setup_t *drbs); + const e1ap_bearer_setup_resp_t *resp); void rrc_gNB_generate_UeContextModificationRequest(const gNB_RRC_INST *rrc, rrc_gNB_ue_context_t *const ue_context_pP, - int n_drbs, - const f1ap_drb_to_setup_t *drbs, + const e1ap_bearer_setup_resp_t *resp, int n_rel_drbs, const f1ap_drb_to_release_t *rel_drbs); diff --git a/openair2/RRC/NR/rrc_gNB.c b/openair2/RRC/NR/rrc_gNB.c index eb51d4b799..096e67ce0a 100644 --- a/openair2/RRC/NR/rrc_gNB.c +++ b/openair2/RRC/NR/rrc_gNB.c @@ -2483,14 +2483,10 @@ void rrc_gNB_process_e1_bearer_context_setup_resp(e1ap_bearer_setup_resp_t *resp } } - /* Instruction towards the DU for DRB configuration and tunnel creation */ - f1ap_drb_to_setup_t drbs[32]; // maximum DRB can be 32 - int nb_drb = fill_drb_to_be_setup_from_e1_resp(rrc, UE, resp->pduSession, resp->numPDUSessions, drbs); - if (!UE->f1_ue_context_active) - rrc_gNB_generate_UeContextSetupRequest(rrc, ue_context_p, nb_drb, drbs); + rrc_gNB_generate_UeContextSetupRequest(rrc, ue_context_p, resp); else - rrc_gNB_generate_UeContextModificationRequest(rrc, ue_context_p, nb_drb, drbs, 0, NULL); + rrc_gNB_generate_UeContextModificationRequest(rrc, ue_context_p, resp, 0, NULL); } /** @brief E1AP Bearer Context Setup Failure processing on CU-CP */ @@ -3023,8 +3019,7 @@ int rrc_gNB_generate_pcch_msg(sctp_assoc_t assoc_id, const NR_SIB1_t *sib1, uint //----------------------------------------------------------------------------- void rrc_gNB_generate_UeContextSetupRequest(const gNB_RRC_INST *rrc, rrc_gNB_ue_context_t *const ue_context_pP, - int n_drbs, - const f1ap_drb_to_setup_t *drbs) + const e1ap_bearer_setup_resp_t *resp) //----------------------------------------------------------------------------- { gNB_RRC_UE_t *ue_p = &ue_context_pP->ue_context; @@ -3033,25 +3028,31 @@ void rrc_gNB_generate_UeContextSetupRequest(const gNB_RRC_INST *rrc, AssertFatal(!NODE_IS_DU(rrc->node_type), "illegal node type DU!\n"); f1ap_cu_to_du_rrc_info_t cu2du = {0}; - if (ue_p->ue_cap_buffer.len > 0 && ue_p->ue_cap_buffer.buf != NULL) { - cu2du.ue_cap = &ue_p->ue_cap_buffer; + if (ue_p->ue_cap_buffer.len > 0) { + cu2du.ue_cap = malloc_or_fail(sizeof(byte_array_t)); + *cu2du.ue_cap = copy_byte_array(ue_p->ue_cap_buffer); } int nb_srb = 1; - f1ap_srb_to_setup_t srbs[1] = {{.id = 2, }}; - activate_srb(ue_p, 2); + f1ap_srb_to_setup_t *srbs = calloc_or_fail(nb_srb, sizeof(*srbs)); + srbs[0].id = 2; + activate_srb(ue_p, srbs[0].id); + + /* Instruction towards the DU for DRB configuration and tunnel creation */ + f1ap_drb_to_setup_t *drbs = calloc_or_fail(32, sizeof(*drbs)); // maximum DRB can be 32 + int n_drbs = fill_drb_to_be_setup_from_e1_resp(rrc, ue_p, resp->pduSession, resp->numPDUSessions, drbs); /* gNB-DU UE Aggregate Maximum Bit Rate Uplink is C- ifDRBSetup */ - uint64_t agg_mbr = 1000000000 /* bps */, *agg_mbr_p = NULL; - if (n_drbs > 0) - agg_mbr_p = &agg_mbr; + uint64_t *agg_mbr = malloc_or_fail(sizeof(*agg_mbr)); + *agg_mbr = 1000000000 /* bps */; - /* the callback will fill the UE context setup request and forward it */ f1_ue_data_t ue_data = cu_get_f1_ue_data(ue_p->rrc_ue_id); RETURN_IF_INVALID_ASSOC_ID(ue_data.du_assoc_id); + uint32_t *du_ue_id = malloc_or_fail(sizeof(*du_ue_id)); + *du_ue_id = ue_data.secondary_ue; f1ap_ue_context_setup_req_t ue_context_setup_req = { .gNB_CU_ue_id = ue_p->rrc_ue_id, - .gNB_DU_ue_id = &ue_data.secondary_ue, + .gNB_DU_ue_id = du_ue_id, .plmn.mcc = rrc->configuration.plmn[0].mcc, .plmn.mnc = rrc->configuration.plmn[0].mnc, .plmn.mnc_digit_length = rrc->configuration.plmn[0].mnc_digit_length, @@ -3060,21 +3061,20 @@ void rrc_gNB_generate_UeContextSetupRequest(const gNB_RRC_INST *rrc, .srbs_len = nb_srb, .srbs = srbs, .drbs_len = n_drbs, - .drbs = (f1ap_drb_to_setup_t *) drbs, // cast to avoid warning on const + .drbs = drbs, .cu_to_du_rrc_info = cu2du, - .gnb_du_ue_agg_mbr_ul = agg_mbr_p, + .gnb_du_ue_agg_mbr_ul = agg_mbr, }; rrc->mac_rrc.ue_context_setup_request(ue_data.du_assoc_id, &ue_context_setup_req); + free_ue_context_setup_req(&ue_context_setup_req); LOG_I(RRC, "UE %d trigger UE context setup request with %d DRBs\n", ue_p->rrc_ue_id, n_drbs); - // nothing to free for ue_context_setup_req } //----------------------------------------------------------------------------- void rrc_gNB_generate_UeContextModificationRequest(const gNB_RRC_INST *rrc, rrc_gNB_ue_context_t *const ue_context_pP, - int n_drbs, - const f1ap_drb_to_setup_t *drbs, + const e1ap_bearer_setup_resp_t *resp, int n_rel_drbs, const f1ap_drb_to_release_t *rel_drbs) //----------------------------------------------------------------------------- @@ -3085,23 +3085,32 @@ void rrc_gNB_generate_UeContextModificationRequest(const gNB_RRC_INST *rrc, AssertFatal(!NODE_IS_DU(rrc->node_type), "illegal node type DU!\n"); - f1ap_cu_to_du_rrc_info_t cu2du = {0}; - if (ue_p->ue_cap_buffer.len > 0 && ue_p->ue_cap_buffer.buf != NULL) { - cu2du.ue_cap = &ue_p->ue_cap_buffer; + f1ap_cu_to_du_rrc_info_t *cu2du = NULL; + if (ue_p->ue_cap_buffer.len > 0) { + cu2du = calloc_or_fail(1, sizeof(*cu2du)); + cu2du->ue_cap = calloc_or_fail(1, sizeof(*cu2du->ue_cap)); + *cu2du->ue_cap = copy_byte_array(ue_p->ue_cap_buffer); } + /* Instruction towards the DU for DRB configuration and tunnel creation */ + f1ap_drb_to_setup_t *drbs = calloc_or_fail(32, sizeof(*drbs)); // maximum DRB can be 32 + int n_drbs = fill_drb_to_be_setup_from_e1_resp(rrc, ue_p, resp->pduSession, resp->numPDUSessions, drbs); + f1_ue_data_t ue_data = cu_get_f1_ue_data(ue_p->rrc_ue_id); RETURN_IF_INVALID_ASSOC_ID(ue_data.du_assoc_id); f1ap_ue_context_mod_req_t ue_context_modif_req = { .gNB_CU_ue_id = ue_p->rrc_ue_id, .gNB_DU_ue_id = ue_data.secondary_ue, .drbs_len = n_drbs, - .drbs = (f1ap_drb_to_setup_t *)drbs, + .drbs = drbs, .drbs_rel_len = n_rel_drbs, .drbs_rel = (f1ap_drb_to_release_t *)rel_drbs, - .cu_to_du_rrc_info = &cu2du, + .cu_to_du_rrc_info = cu2du, }; rrc->mac_rrc.ue_context_modification_request(ue_data.du_assoc_id, &ue_context_modif_req); + // avoid attempt to release rel_drbs + ue_context_modif_req.drbs_rel_len = 0; + ue_context_modif_req.drbs_rel = NULL; + free_ue_context_mod_req(&ue_context_modif_req); LOG_I(RRC, "UE %d trigger UE context modification request with %d DRBs\n", ue_p->rrc_ue_id, n_drbs); - // nothing to free } From d13c94457ae11a9264d910718f0634dd8eb563d9 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Wed, 11 Jun 2025 07:59:29 +0200 Subject: [PATCH 16/36] Add F1AP UE context release request message enc/dec + test See commit "Add F1AP UE context setup request message enc/dec + test" for more details on the approach taken. --- openair2/COMMON/f1ap_messages_types.h | 7 ++ openair2/F1AP/lib/f1ap_ue_context.c | 112 ++++++++++++++++++++++++++ openair2/F1AP/lib/f1ap_ue_context.h | 6 ++ openair2/F1AP/tests/f1ap_lib_test.c | 32 ++++++++ 4 files changed, 157 insertions(+) diff --git a/openair2/COMMON/f1ap_messages_types.h b/openair2/COMMON/f1ap_messages_types.h index 9394daa7f0..c67a97b0f8 100644 --- a/openair2/COMMON/f1ap_messages_types.h +++ b/openair2/COMMON/f1ap_messages_types.h @@ -649,6 +649,13 @@ typedef struct f1ap_ue_context_modif_refuse_t { long cause_value; } f1ap_ue_context_modif_refuse_t; +typedef struct f1ap_ue_context_rel_req_t { + uint32_t gNB_CU_ue_id; + uint32_t gNB_DU_ue_id; + f1ap_Cause_t cause; + long cause_value; +} f1ap_ue_context_rel_req_t; + typedef struct f1ap_ue_context_release_s { uint32_t gNB_CU_ue_id; uint32_t gNB_DU_ue_id; diff --git a/openair2/F1AP/lib/f1ap_ue_context.c b/openair2/F1AP/lib/f1ap_ue_context.c index 588648fe37..53f1e11c67 100644 --- a/openair2/F1AP/lib/f1ap_ue_context.c +++ b/openair2/F1AP/lib/f1ap_ue_context.c @@ -2087,3 +2087,115 @@ void free_ue_context_mod_resp(f1ap_ue_context_mod_resp_t *resp) free_srb_setup(&resp->srbs[i]); free(resp->srbs); } + +/* + * @brief Encode F1 UE context release request to ASN.1 + */ +struct F1AP_F1AP_PDU *encode_ue_context_rel_req(const f1ap_ue_context_rel_req_t *msg) +{ + F1AP_F1AP_PDU_t *pdu = calloc_or_fail(1, sizeof(*pdu)); + + /* Message Type */ + pdu->present = F1AP_F1AP_PDU_PR_initiatingMessage; + asn1cCalloc(pdu->choice.initiatingMessage, tmp); + tmp->procedureCode = F1AP_ProcedureCode_id_UEContextReleaseRequest; + tmp->criticality = F1AP_Criticality_reject; + tmp->value.present = F1AP_InitiatingMessage__value_PR_UEContextReleaseRequest; + F1AP_UEContextReleaseRequest_t *out = &tmp->value.choice.UEContextReleaseRequest; + + /* mandatory: GNB_CU_UE_F1AP_ID */ + asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextReleaseRequestIEs_t, ie1); + ie1->id = F1AP_ProtocolIE_ID_id_gNB_CU_UE_F1AP_ID; + ie1->criticality = F1AP_Criticality_reject; + ie1->value.present = F1AP_UEContextReleaseRequestIEs__value_PR_GNB_CU_UE_F1AP_ID; + ie1->value.choice.GNB_CU_UE_F1AP_ID = msg->gNB_CU_ue_id; + + /* mandatory: GNB_DU_UE_F1AP_ID */ + asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextReleaseRequestIEs_t, ie2); + ie2->id = F1AP_ProtocolIE_ID_id_gNB_DU_UE_F1AP_ID; + ie2->criticality = F1AP_Criticality_reject; + ie2->value.present = F1AP_UEContextReleaseRequestIEs__value_PR_GNB_DU_UE_F1AP_ID; + ie2->value.choice.GNB_DU_UE_F1AP_ID = msg->gNB_DU_ue_id; + + /* mandatory: Cause */ + asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextReleaseRequestIEs_t, ie3); + ie3->id = F1AP_ProtocolIE_ID_id_Cause; + ie3->criticality = F1AP_Criticality_ignore; + ie3->value.present = F1AP_UEContextReleaseRequestIEs__value_PR_Cause; + ie3->value.choice.Cause = encode_f1ap_cause(msg->cause, msg->cause_value); + + return pdu; +} + +/** + * @brief Decode F1 UE Context Release Request + */ +bool decode_ue_context_rel_req(const struct F1AP_F1AP_PDU *pdu, f1ap_ue_context_rel_req_t *out) +{ + DevAssert(out != NULL); + memset(out, 0, sizeof(*out)); + + F1AP_UEContextReleaseRequest_t *in = &pdu->choice.initiatingMessage->value.choice.UEContextReleaseRequest; + F1AP_UEContextReleaseRequestIEs_t *ie; + F1AP_LIB_FIND_IE(F1AP_UEContextReleaseRequestIEs_t, ie, &in->protocolIEs.list, F1AP_ProtocolIE_ID_id_gNB_CU_UE_F1AP_ID, true); + F1AP_LIB_FIND_IE(F1AP_UEContextReleaseRequestIEs_t, ie, &in->protocolIEs.list, F1AP_ProtocolIE_ID_id_gNB_DU_UE_F1AP_ID, true); + F1AP_LIB_FIND_IE(F1AP_UEContextReleaseRequestIEs_t, ie, &in->protocolIEs.list, F1AP_ProtocolIE_ID_id_Cause, true); + + for (int i = 0; i < in->protocolIEs.list.count; ++i) { + ie = in->protocolIEs.list.array[i]; + AssertError(ie != NULL, return false, "in->protocolIEs.list.array[i] is NULL"); + switch (ie->id) { + case F1AP_ProtocolIE_ID_id_gNB_CU_UE_F1AP_ID: + _F1_EQ_CHECK_INT(ie->value.present, F1AP_UEContextReleaseRequestIEs__value_PR_GNB_CU_UE_F1AP_ID); + out->gNB_CU_ue_id = ie->value.choice.GNB_CU_UE_F1AP_ID; + break; + case F1AP_ProtocolIE_ID_id_gNB_DU_UE_F1AP_ID: + _F1_EQ_CHECK_INT(ie->value.present, F1AP_UEContextReleaseRequestIEs__value_PR_GNB_DU_UE_F1AP_ID); + out->gNB_DU_ue_id = ie->value.choice.GNB_DU_UE_F1AP_ID; + break; + case F1AP_ProtocolIE_ID_id_Cause: + _F1_EQ_CHECK_INT(ie->value.present, F1AP_UEContextReleaseRequestIEs__value_PR_Cause); + _F1_CHECK_EXP(decode_f1ap_cause(ie->value.choice.Cause, &out->cause, &out->cause_value)); + break; + default: + PRINT_ERROR("F1AP_ProtocolIE_ID_id %ld unknown, skipping\n", ie->id); + break; + } + } + + return true; +} + +/** + * @brief F1 UE Context Release Request deep copy + */ +f1ap_ue_context_rel_req_t cp_ue_context_rel_req(const f1ap_ue_context_rel_req_t *orig) +{ + f1ap_ue_context_rel_req_t cp = { + .gNB_CU_ue_id = orig->gNB_CU_ue_id, + .gNB_DU_ue_id = orig->gNB_DU_ue_id, + .cause = orig->cause, + .cause_value = orig->cause_value, + }; + return cp; +} + +/** + * @brief F1 UE Context Release Request equality check + */ +bool eq_ue_context_rel_req(const f1ap_ue_context_rel_req_t *a, const f1ap_ue_context_rel_req_t *b) +{ + _F1_EQ_CHECK_INT(a->gNB_CU_ue_id, b->gNB_CU_ue_id); + _F1_EQ_CHECK_INT(a->gNB_DU_ue_id, b->gNB_DU_ue_id); + _F1_EQ_CHECK_INT(a->cause, b->cause); + _F1_EQ_CHECK_LONG(a->cause_value, b->cause_value); + return true; +} + +/** + * @brief Free Allocated F1 UE Context Release Request + */ +void free_ue_context_rel_req(f1ap_ue_context_rel_req_t *req) +{ + // nothing to free +} diff --git a/openair2/F1AP/lib/f1ap_ue_context.h b/openair2/F1AP/lib/f1ap_ue_context.h index ddf41689e0..5e683fe1ab 100644 --- a/openair2/F1AP/lib/f1ap_ue_context.h +++ b/openair2/F1AP/lib/f1ap_ue_context.h @@ -51,4 +51,10 @@ f1ap_ue_context_mod_resp_t cp_ue_context_mod_resp(const f1ap_ue_context_mod_resp bool eq_ue_context_mod_resp(const f1ap_ue_context_mod_resp_t *a, const f1ap_ue_context_mod_resp_t *b); void free_ue_context_mod_resp(f1ap_ue_context_mod_resp_t *resp); +struct F1AP_F1AP_PDU *encode_ue_context_rel_req(const f1ap_ue_context_rel_req_t *msg); +bool decode_ue_context_rel_req(const struct F1AP_F1AP_PDU *pdu, f1ap_ue_context_rel_req_t *out); +f1ap_ue_context_rel_req_t cp_ue_context_rel_req(const f1ap_ue_context_rel_req_t *orig); +bool eq_ue_context_rel_req(const f1ap_ue_context_rel_req_t *a, const f1ap_ue_context_rel_req_t *b); +void free_ue_context_rel_req(f1ap_ue_context_rel_req_t *req); + #endif /* F1AP_UE_CONTEXT_SETUP_REQ_H_ */ diff --git a/openair2/F1AP/tests/f1ap_lib_test.c b/openair2/F1AP/tests/f1ap_lib_test.c index 5baac1f5c6..a26a80823e 100644 --- a/openair2/F1AP/tests/f1ap_lib_test.c +++ b/openair2/F1AP/tests/f1ap_lib_test.c @@ -1171,6 +1171,37 @@ static void test_f1ap_ue_context_modification_response_simple() printf("%s() successful\n", __func__); } +static void test_f1ap_ue_context_release_request() +{ + f1ap_ue_context_rel_req_t orig = { + .gNB_CU_ue_id = 1111, + .gNB_DU_ue_id = 2222, + .cause = F1AP_CAUSE_MISC, + .cause_value = 3, + }; + + F1AP_F1AP_PDU_t *f1enc = encode_ue_context_rel_req(&orig); + F1AP_F1AP_PDU_t *f1dec = f1ap_encode_decode(f1enc); + f1ap_msg_free(f1enc); + + f1ap_ue_context_rel_req_t decoded = {0}; + bool ret = decode_ue_context_rel_req(f1dec, &decoded); + AssertFatal(ret, "decode_ue_context_rel_req(): could not decode message\n"); + f1ap_msg_free(f1dec); + + ret = eq_ue_context_rel_req(&orig, &decoded); + AssertFatal(ret, "eq_ue_context_rel_req(): decoded message doesn't match\n"); + free_ue_context_rel_req(&decoded); + + f1ap_ue_context_rel_req_t cp = cp_ue_context_rel_req(&orig); + ret = eq_ue_context_rel_req(&orig, &cp); + AssertFatal(ret, "eq_ue_context_rel_req(): copied message doesn't match\n"); + free_ue_context_rel_req(&orig); + free_ue_context_rel_req(&cp); + + printf("%s() successful\n", __func__); +} + int main() { test_initial_ul_rrc_message_transfer(); @@ -1194,5 +1225,6 @@ int main() test_f1ap_ue_context_modification_request_simple(); test_f1ap_ue_context_modification_response(); test_f1ap_ue_context_modification_response_simple(); + test_f1ap_ue_context_release_request(); return 0; } From f7d747164da19b63c672a5df00daba1b9dab577c Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Thu, 19 Jun 2025 16:59:23 +0200 Subject: [PATCH 17/36] Use F1 UE context Release Request in stack Switch to the new type, remove the old one. --- openair2/COMMON/f1ap_messages_def.h | 2 +- openair2/COMMON/f1ap_messages_types.h | 2 +- openair2/F1AP/f1ap_cu_ue_context_management.c | 57 +++------------ openair2/F1AP/f1ap_du_ue_context_management.c | 72 +++---------------- openair2/F1AP/f1ap_du_ue_context_management.h | 4 +- .../NR_MAC_gNB/gNB_scheduler_primitives.c | 2 +- .../LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.c | 2 +- openair2/LAYER2/NR_MAC_gNB/mac_rrc_ul.h | 2 +- .../LAYER2/NR_MAC_gNB/mac_rrc_ul_direct.c | 5 +- openair2/LAYER2/NR_MAC_gNB/mac_rrc_ul_f1ap.c | 5 +- openair2/RRC/NR/rrc_gNB.c | 3 +- 11 files changed, 28 insertions(+), 128 deletions(-) diff --git a/openair2/COMMON/f1ap_messages_def.h b/openair2/COMMON/f1ap_messages_def.h index 5681848029..e9776c58ff 100644 --- a/openair2/COMMON/f1ap_messages_def.h +++ b/openair2/COMMON/f1ap_messages_def.h @@ -48,7 +48,7 @@ MESSAGE_DEF(F1AP_INITIAL_UL_RRC_MESSAGE , MESSAGE_PRIORITY_MED, f1ap_i MESSAGE_DEF(F1AP_UL_RRC_MESSAGE , MESSAGE_PRIORITY_MED, f1ap_ul_rrc_message_t , f1ap_ul_rrc_message) //MESSAGE_DEF(F1AP_INITIAL_CONTEXT_SETUP_RESP, MESSAGE_PRIORITY_MED, f1ap_initial_context_setup_resp_t, f1ap_initial_context_setup_resp) //MESSAGE_DEF(F1AP_INITIAL_CONTEXT_SETUP_FAILURE, MESSAGE_PRIORITY_MED, f1ap_initial_context_setup_failure_t, f1ap_initial_context_setup_failure) -MESSAGE_DEF(F1AP_UE_CONTEXT_RELEASE_REQ, MESSAGE_PRIORITY_MED, f1ap_ue_context_release_req_t, f1ap_ue_context_release_req) +MESSAGE_DEF(F1AP_UE_CONTEXT_RELEASE_REQ, MESSAGE_PRIORITY_MED, f1ap_ue_context_rel_req_t, f1ap_ue_context_release_req) MESSAGE_DEF(F1AP_UE_CONTEXT_RELEASE_CMD, MESSAGE_PRIORITY_MED, f1ap_ue_context_release_cmd_t, f1ap_ue_context_release_cmd) MESSAGE_DEF(F1AP_UE_CONTEXT_RELEASE_COMPLETE, MESSAGE_PRIORITY_MED, f1ap_ue_context_release_complete_t, f1ap_ue_context_release_complete) MESSAGE_DEF(F1AP_UE_CONTEXT_MODIFICATION_REQUIRED, MESSAGE_PRIORITY_MED, f1ap_ue_context_modif_required_t, f1ap_ue_context_modification_required) diff --git a/openair2/COMMON/f1ap_messages_types.h b/openair2/COMMON/f1ap_messages_types.h index c67a97b0f8..57365c931e 100644 --- a/openair2/COMMON/f1ap_messages_types.h +++ b/openair2/COMMON/f1ap_messages_types.h @@ -664,7 +664,7 @@ typedef struct f1ap_ue_context_release_s { uint8_t *rrc_container; int rrc_container_length; int srb_id; -} f1ap_ue_context_release_req_t, f1ap_ue_context_release_cmd_t, f1ap_ue_context_release_complete_t; +} f1ap_ue_context_release_cmd_t, f1ap_ue_context_release_complete_t; typedef struct f1ap_paging_ind_s { uint16_t ueidentityindexvalue; diff --git a/openair2/F1AP/f1ap_cu_ue_context_management.c b/openair2/F1AP/f1ap_cu_ue_context_management.c index 597c20d258..e0f1495f86 100644 --- a/openair2/F1AP/f1ap_cu_ue_context_management.c +++ b/openair2/F1AP/f1ap_cu_ue_context_management.c @@ -90,58 +90,17 @@ int CU_handle_UE_CONTEXT_SETUP_FAILURE(instance_t instance, sctp_assoc_t assoc_i int CU_handle_UE_CONTEXT_RELEASE_REQUEST(instance_t instance, sctp_assoc_t assoc_id, uint32_t stream, F1AP_F1AP_PDU_t *pdu) { + f1ap_ue_context_rel_req_t req = {0}; + if (!decode_ue_context_rel_req(pdu, &req)) { + LOG_E(F1AP, "cannot decode F1 UE Context Release Request\n"); + free_ue_context_rel_req(&req); + return -1; + } + MessageDef *msg = itti_alloc_new_message(TASK_CU_F1, 0, F1AP_UE_CONTEXT_RELEASE_REQ); msg->ittiMsgHeader.originInstance = assoc_id; - f1ap_ue_context_release_req_t *req = &F1AP_UE_CONTEXT_RELEASE_REQ(msg); - F1AP_UEContextReleaseRequest_t *container; - F1AP_UEContextReleaseRequestIEs_t *ie; - DevAssert(pdu); - container = &pdu->choice.initiatingMessage->value.choice.UEContextReleaseRequest; - /* GNB_CU_UE_F1AP_ID */ - F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_UEContextReleaseRequestIEs_t, ie, container, - F1AP_ProtocolIE_ID_id_gNB_CU_UE_F1AP_ID, true); - req->gNB_CU_ue_id = ie->value.choice.GNB_CU_UE_F1AP_ID; - - /* GNB_DU_UE_F1AP_ID */ - F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_UEContextReleaseRequestIEs_t, ie, container, - F1AP_ProtocolIE_ID_id_gNB_DU_UE_F1AP_ID, true); - req->gNB_DU_ue_id = ie->value.choice.GNB_DU_UE_F1AP_ID; - - /* Cause */ - F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_UEContextReleaseRequestIEs_t, ie, container, - F1AP_ProtocolIE_ID_id_Cause, true); - - switch(ie->value.choice.Cause.present) - { - case F1AP_Cause_PR_radioNetwork: - req->cause = F1AP_CAUSE_RADIO_NETWORK; - req->cause_value = ie->value.choice.Cause.choice.radioNetwork; - break; - case F1AP_Cause_PR_transport: - req->cause = F1AP_CAUSE_TRANSPORT; - req->cause_value = ie->value.choice.Cause.choice.transport; - break; - case F1AP_Cause_PR_protocol: - req->cause = F1AP_CAUSE_PROTOCOL; - req->cause_value = ie->value.choice.Cause.choice.protocol; - break; - case F1AP_Cause_PR_misc: - req->cause = F1AP_CAUSE_MISC; - req->cause_value = ie->value.choice.Cause.choice.misc; - break; - case F1AP_Cause_PR_NOTHING: - default: - req->cause = F1AP_CAUSE_NOTHING; - break; - } - - F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_UEContextReleaseRequestIEs_t, ie, container, F1AP_ProtocolIE_ID_id_targetCellsToCancel, false); - if (ie != NULL) { - LOG_W(F1AP, "ignoring list of target cells to cancel in UE Context Release Request: implementation missing\n"); - } - + F1AP_UE_CONTEXT_RELEASE_REQ(msg) = req; itti_send_msg_to_task(TASK_RRC_GNB, instance, msg); - return 0; } diff --git a/openair2/F1AP/f1ap_du_ue_context_management.c b/openair2/F1AP/f1ap_du_ue_context_management.c index e6d36f9019..a2179b8583 100644 --- a/openair2/F1AP/f1ap_du_ue_context_management.c +++ b/openair2/F1AP/f1ap_du_ue_context_management.c @@ -76,75 +76,19 @@ int DU_send_UE_CONTEXT_SETUP_FAILURE(sctp_assoc_t assoc_id) AssertFatal(1==0,"Not implemented yet\n"); } -int DU_send_UE_CONTEXT_RELEASE_REQUEST(sctp_assoc_t assoc_id, f1ap_ue_context_release_req_t *req) +int DU_send_UE_CONTEXT_RELEASE_REQUEST(sctp_assoc_t assoc_id, f1ap_ue_context_rel_req_t *req) { - F1AP_F1AP_PDU_t pdu = {0}; - F1AP_UEContextReleaseRequest_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_UEContextReleaseRequest; - tmp->criticality = F1AP_Criticality_reject; - tmp->value.present = F1AP_InitiatingMessage__value_PR_UEContextReleaseRequest; - out = &tmp->value.choice.UEContextReleaseRequest; - /* mandatory */ - /* c1. GNB_CU_UE_F1AP_ID */ - asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextReleaseRequestIEs_t, ie1); - ie1->id = F1AP_ProtocolIE_ID_id_gNB_CU_UE_F1AP_ID; - ie1->criticality = F1AP_Criticality_reject; - ie1->value.present = F1AP_UEContextReleaseRequestIEs__value_PR_GNB_CU_UE_F1AP_ID; - ie1->value.choice.GNB_CU_UE_F1AP_ID = req->gNB_CU_ue_id; - /* mandatory */ - /* c2. GNB_DU_UE_F1AP_ID */ - asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextReleaseRequestIEs_t, ie2); - ie2->id = F1AP_ProtocolIE_ID_id_gNB_DU_UE_F1AP_ID; - ie2->criticality = F1AP_Criticality_reject; - ie2->value.present = F1AP_UEContextReleaseRequestIEs__value_PR_GNB_DU_UE_F1AP_ID; - ie2->value.choice.GNB_DU_UE_F1AP_ID = req->gNB_DU_ue_id; - /* mandatory */ - /* c3. Cause */ - asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextReleaseRequestIEs_t, ie3); - ie3->id = F1AP_ProtocolIE_ID_id_Cause; - ie3->criticality = F1AP_Criticality_ignore; - ie3->value.present = F1AP_UEContextReleaseRequestIEs__value_PR_Cause; + F1AP_F1AP_PDU_t *pdu = encode_ue_context_rel_req(req); - switch (req->cause) { - case F1AP_CAUSE_RADIO_NETWORK: - ie3->value.choice.Cause.present = F1AP_Cause_PR_radioNetwork; - ie3->value.choice.Cause.choice.radioNetwork = req->cause_value; - break; - - case F1AP_CAUSE_TRANSPORT: - ie3->value.choice.Cause.present = F1AP_Cause_PR_transport; - ie3->value.choice.Cause.choice.transport = req->cause_value; - break; - - case F1AP_CAUSE_PROTOCOL: - ie3->value.choice.Cause.present = F1AP_Cause_PR_protocol; - ie3->value.choice.Cause.choice.protocol = req->cause_value; - break; - - case F1AP_CAUSE_MISC: - ie3->value.choice.Cause.present = F1AP_Cause_PR_misc; - ie3->value.choice.Cause.choice.misc = req->cause_value; - break; - - case F1AP_CAUSE_NOTHING: - default: - ie3->value.choice.Cause.present = F1AP_Cause_PR_NOTHING; - break; - } - - /* encode */ - if (f1ap_encode_pdu(&pdu, &buffer, &len) < 0) { + uint8_t *buffer = NULL; + uint32_t len = 0; + if (f1ap_encode_pdu(pdu, &buffer, &len) < 0) { LOG_E(F1AP, "Failed to encode F1 context release request\n"); return -1; } f1ap_itti_send_sctp_data_req(assoc_id, buffer, len); + ASN_STRUCT_FREE(asn_DEF_F1AP_F1AP_PDU, pdu); return 0; } @@ -153,8 +97,8 @@ int DU_handle_UE_CONTEXT_RELEASE_COMMAND(instance_t instance, sctp_assoc_t assoc F1AP_UEContextReleaseCommand_t *container; F1AP_UEContextReleaseCommandIEs_t *ie; - f1ap_ue_context_release_req_t ue_context_release = {0}; - f1ap_ue_context_release_req_t *f1ap_ue_context_release_cmd = &ue_context_release; + f1ap_ue_context_release_cmd_t ue_context_release = {0}; + f1ap_ue_context_release_cmd_t *f1ap_ue_context_release_cmd = &ue_context_release; DevAssert(pdu); container = &pdu->choice.initiatingMessage->value.choice.UEContextReleaseCommand; diff --git a/openair2/F1AP/f1ap_du_ue_context_management.h b/openair2/F1AP/f1ap_du_ue_context_management.h index 8f38ac8dd9..e9ef2bef8c 100644 --- a/openair2/F1AP/f1ap_du_ue_context_management.h +++ b/openair2/F1AP/f1ap_du_ue_context_management.h @@ -45,9 +45,7 @@ int DU_send_UE_CONTEXT_SETUP_FAILURE(sctp_assoc_t assoc_id); /* * UE Context Release Request (gNB-DU initiated) */ -int DU_send_UE_CONTEXT_RELEASE_REQUEST(sctp_assoc_t assoc_id, - f1ap_ue_context_release_req_t *req); - +int DU_send_UE_CONTEXT_RELEASE_REQUEST(sctp_assoc_t assoc_id, f1ap_ue_context_rel_req_t *req); /* * UE Context Release Command (gNB-CU initiated) diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c index a447d9f91c..b85c26b1a3 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c @@ -3385,7 +3385,7 @@ bool nr_mac_request_release_ue(const gNB_MAC_INST *nrmac, int rnti) return false; } f1_ue_data_t ue_data = du_get_f1_ue_data(rnti); - f1ap_ue_context_release_req_t request = { + f1ap_ue_context_rel_req_t request = { .gNB_CU_ue_id = ue_data.secondary_ue, .gNB_DU_ue_id = rnti, .cause = F1AP_CAUSE_RADIO_NETWORK, 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 58d8dbf86c..c625343c10 100644 --- a/openair2/LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.c +++ b/openair2/LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.c @@ -852,7 +852,7 @@ void ue_context_modification_refuse(const f1ap_ue_context_modif_refuse_t *refuse NR_SCHED_UNLOCK(&mac->sched_lock); - f1ap_ue_context_release_req_t request = { + f1ap_ue_context_rel_req_t request = { .gNB_CU_ue_id = refuse->gNB_CU_ue_id, .gNB_DU_ue_id = refuse->gNB_DU_ue_id, .cause = F1AP_CAUSE_RADIO_NETWORK, diff --git a/openair2/LAYER2/NR_MAC_gNB/mac_rrc_ul.h b/openair2/LAYER2/NR_MAC_gNB/mac_rrc_ul.h index 033e8590d2..3f54ae53b8 100644 --- a/openair2/LAYER2/NR_MAC_gNB/mac_rrc_ul.h +++ b/openair2/LAYER2/NR_MAC_gNB/mac_rrc_ul.h @@ -34,7 +34,7 @@ typedef void (*gnb_du_configuration_update_t)(const f1ap_gnb_du_configuration_up typedef void (*ue_context_setup_response_func_t)(const f1ap_ue_context_setup_resp_t *resp); typedef void (*ue_context_modification_response_func_t)(const f1ap_ue_context_mod_resp_t *resp); typedef void (*ue_context_modification_required_func_t)(const f1ap_ue_context_modif_required_t *t); -typedef void (*ue_context_release_request_func_t)(const f1ap_ue_context_release_req_t* req); +typedef void (*ue_context_release_request_func_t)(const f1ap_ue_context_rel_req_t* req); typedef void (*ue_context_release_complete_func_t)(const f1ap_ue_context_release_complete_t *complete); typedef void (*initial_ul_rrc_message_transfer_func_t)(module_id_t module_id, const f1ap_initial_ul_rrc_message_t *ul_rrc); 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 72308bdd66..9f719374c1 100644 --- a/openair2/LAYER2/NR_MAC_gNB/mac_rrc_ul_direct.c +++ b/openair2/LAYER2/NR_MAC_gNB/mac_rrc_ul_direct.c @@ -101,12 +101,11 @@ static void ue_context_modification_required_direct(const f1ap_ue_context_modif_ itti_send_msg_to_task(TASK_RRC_GNB, 0, msg); } -static void ue_context_release_request_direct(const f1ap_ue_context_release_req_t* req) +static void ue_context_release_request_direct(const f1ap_ue_context_rel_req_t* req) { MessageDef *msg = itti_alloc_new_message(TASK_MAC_GNB, 0, F1AP_UE_CONTEXT_RELEASE_REQ); msg->ittiMsgHeader.originInstance = -1; // means monolithic - f1ap_ue_context_release_req_t *f1ap_msg = &F1AP_UE_CONTEXT_RELEASE_REQ(msg); - *f1ap_msg = *req; + F1AP_UE_CONTEXT_RELEASE_REQ(msg) = cp_ue_context_rel_req(req); 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 15101928e5..29990cf3a9 100644 --- a/openair2/LAYER2/NR_MAC_gNB/mac_rrc_ul_f1ap.c +++ b/openair2/LAYER2/NR_MAC_gNB/mac_rrc_ul_f1ap.c @@ -125,11 +125,10 @@ static void ue_context_modification_required_f1ap(const f1ap_ue_context_modif_re itti_send_msg_to_task(TASK_DU_F1, 0, msg); } -static void ue_context_release_request_f1ap(const f1ap_ue_context_release_req_t* req) +static void ue_context_release_request_f1ap(const f1ap_ue_context_rel_req_t* req) { MessageDef *msg = itti_alloc_new_message(TASK_MAC_GNB, 0, F1AP_UE_CONTEXT_RELEASE_REQ); - f1ap_ue_context_release_req_t *f1ap_msg = &F1AP_UE_CONTEXT_RELEASE_REQ(msg); - *f1ap_msg = *req; + F1AP_UE_CONTEXT_RELEASE_REQ(msg) = cp_ue_context_rel_req(req); itti_send_msg_to_task(TASK_DU_F1, 0, msg); } diff --git a/openair2/RRC/NR/rrc_gNB.c b/openair2/RRC/NR/rrc_gNB.c index 096e67ce0a..a7ba899c82 100644 --- a/openair2/RRC/NR/rrc_gNB.c +++ b/openair2/RRC/NR/rrc_gNB.c @@ -2133,7 +2133,7 @@ static void rrc_CU_process_ue_context_setup_response(MessageDef *msg_p, instance static void rrc_CU_process_ue_context_release_request(MessageDef *msg_p, sctp_assoc_t assoc_id) { const int instance = 0; - f1ap_ue_context_release_req_t *req = &F1AP_UE_CONTEXT_RELEASE_REQ(msg_p); + f1ap_ue_context_rel_req_t *req = &F1AP_UE_CONTEXT_RELEASE_REQ(msg_p); gNB_RRC_INST *rrc = RC.nrrrc[instance]; rrc_gNB_ue_context_t *ue_context_p = rrc_gNB_get_ue_context(rrc, req->gNB_CU_ue_id); // TODO what happens if no AMF connected? should also handle, set an_release true @@ -2775,6 +2775,7 @@ void *rrc_gnb_task(void *args_p) { case F1AP_UE_CONTEXT_RELEASE_REQ: rrc_CU_process_ue_context_release_request(msg_p, msg_p->ittiMsgHeader.originInstance); + free_ue_context_rel_req(&F1AP_UE_CONTEXT_RELEASE_REQ(msg_p)); break; case F1AP_UE_CONTEXT_RELEASE_COMPLETE: From ec7a7973fb3c822c4f545f3520baf158a22a6b50 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Wed, 11 Jun 2025 08:59:43 +0200 Subject: [PATCH 18/36] Add F1AP UE context release command message enc/dec + test See commit "Add F1AP UE context setup request message enc/dec + test" for more details on the approach taken. --- openair2/COMMON/f1ap_messages_types.h | 12 ++ openair2/F1AP/lib/f1ap_ue_context.c | 171 ++++++++++++++++++++++++++ openair2/F1AP/lib/f1ap_ue_context.h | 6 + openair2/F1AP/tests/f1ap_lib_test.c | 36 ++++++ 4 files changed, 225 insertions(+) diff --git a/openair2/COMMON/f1ap_messages_types.h b/openair2/COMMON/f1ap_messages_types.h index 57365c931e..882ead3998 100644 --- a/openair2/COMMON/f1ap_messages_types.h +++ b/openair2/COMMON/f1ap_messages_types.h @@ -656,6 +656,18 @@ typedef struct f1ap_ue_context_rel_req_t { long cause_value; } f1ap_ue_context_rel_req_t; +typedef struct f1ap_ue_context_rel_cmd_t { + uint32_t gNB_CU_ue_id; + uint32_t gNB_DU_ue_id; + f1ap_Cause_t cause; + long cause_value; + + byte_array_t *rrc_container; + int *srb_id; // C-ifRRCContainer + + uint32_t *old_gNB_DU_ue_id; // if after reestablishment request +} f1ap_ue_context_rel_cmd_t; + typedef struct f1ap_ue_context_release_s { uint32_t gNB_CU_ue_id; uint32_t gNB_DU_ue_id; diff --git a/openair2/F1AP/lib/f1ap_ue_context.c b/openair2/F1AP/lib/f1ap_ue_context.c index 53f1e11c67..d070ca0cde 100644 --- a/openair2/F1AP/lib/f1ap_ue_context.c +++ b/openair2/F1AP/lib/f1ap_ue_context.c @@ -2199,3 +2199,174 @@ void free_ue_context_rel_req(f1ap_ue_context_rel_req_t *req) { // nothing to free } + +/* + * @brief Encode F1 UE context release command to ASN.1 + */ +struct F1AP_F1AP_PDU *encode_ue_context_rel_cmd(const f1ap_ue_context_rel_cmd_t *cmd) +{ + F1AP_F1AP_PDU_t *pdu = calloc_or_fail(1, sizeof(*pdu)); + + /* Message Type */ + pdu->present = F1AP_F1AP_PDU_PR_initiatingMessage; + asn1cCalloc(pdu->choice.initiatingMessage, tmp); + tmp->procedureCode = F1AP_ProcedureCode_id_UEContextRelease; + tmp->criticality = F1AP_Criticality_reject; + tmp->value.present = F1AP_InitiatingMessage__value_PR_UEContextReleaseCommand; + F1AP_UEContextReleaseCommand_t *out = &tmp->value.choice.UEContextReleaseCommand; + + /* mandatory: GNB_CU_UE_F1AP_ID */ + asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextReleaseCommandIEs_t, ie1); + ie1->id = F1AP_ProtocolIE_ID_id_gNB_CU_UE_F1AP_ID; + ie1->criticality = F1AP_Criticality_reject; + ie1->value.present = F1AP_UEContextReleaseCommandIEs__value_PR_GNB_CU_UE_F1AP_ID; + ie1->value.choice.GNB_CU_UE_F1AP_ID = cmd->gNB_CU_ue_id; + + /* mandatory: GNB_DU_UE_F1AP_ID */ + asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextReleaseCommandIEs_t, ie2); + ie2->id = F1AP_ProtocolIE_ID_id_gNB_DU_UE_F1AP_ID; + ie2->criticality = F1AP_Criticality_reject; + ie2->value.present = F1AP_UEContextReleaseCommandIEs__value_PR_GNB_DU_UE_F1AP_ID; + ie2->value.choice.GNB_DU_UE_F1AP_ID = cmd->gNB_DU_ue_id; + + /* mandatory: Cause */ + asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextReleaseCommandIEs_t, ie3); + ie3->id = F1AP_ProtocolIE_ID_id_Cause; + ie3->criticality = F1AP_Criticality_ignore; + ie3->value.present = F1AP_UEContextReleaseCommandIEs__value_PR_Cause; + ie3->value.choice.Cause = encode_f1ap_cause(cmd->cause, cmd->cause_value); + + /* optional: RRC Container */ + if (cmd->rrc_container != NULL) { + asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextReleaseCommandIEs_t, ie4); + ie4->id = F1AP_ProtocolIE_ID_id_RRCContainer; + ie4->criticality = F1AP_Criticality_ignore; + ie4->value.present = F1AP_UEContextReleaseCommandIEs__value_PR_RRCContainer; + const byte_array_t *ba = cmd->rrc_container; + OCTET_STRING_fromBuf(&ie4->value.choice.RRCContainer, (const char *)ba->buf, ba->len); + + // conditionally have SRBID if RRC Container + AssertFatal(cmd->srb_id != NULL, "UEContextReleaseCommand SRB-ID C-ifRRCContainer violated\n"); + asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextReleaseCommandIEs_t, ie5); + ie5->id = F1AP_ProtocolIE_ID_id_SRBID; + ie5->criticality = F1AP_Criticality_ignore; + ie5->value.present = F1AP_UEContextReleaseCommandIEs__value_PR_SRBID; + ie5->value.choice.SRBID = *cmd->srb_id; + } + + if (cmd->old_gNB_DU_ue_id != NULL) { + asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextReleaseCommandIEs_t, ie5); + ie5->id = F1AP_ProtocolIE_ID_id_oldgNB_DU_UE_F1AP_ID; + ie5->criticality = F1AP_Criticality_ignore; + ie5->value.present = F1AP_UEContextReleaseCommandIEs__value_PR_GNB_DU_UE_F1AP_ID_1; + ie5->value.choice.GNB_DU_UE_F1AP_ID_1 = *cmd->old_gNB_DU_ue_id; + } + + return pdu; +} + +/** + * @brief Decode F1 UE Context Release Command + */ +bool decode_ue_context_rel_cmd(const struct F1AP_F1AP_PDU *pdu, f1ap_ue_context_rel_cmd_t *out) +{ + DevAssert(out != NULL); + memset(out, 0, sizeof(*out)); + + F1AP_UEContextReleaseCommand_t *in = &pdu->choice.initiatingMessage->value.choice.UEContextReleaseCommand; + F1AP_UEContextReleaseCommandIEs_t *ie; + F1AP_LIB_FIND_IE(F1AP_UEContextReleaseCommandIEs_t, ie, &in->protocolIEs.list, F1AP_ProtocolIE_ID_id_gNB_CU_UE_F1AP_ID, true); + F1AP_LIB_FIND_IE(F1AP_UEContextReleaseCommandIEs_t, ie, &in->protocolIEs.list, F1AP_ProtocolIE_ID_id_gNB_DU_UE_F1AP_ID, true); + F1AP_LIB_FIND_IE(F1AP_UEContextReleaseCommandIEs_t, ie, &in->protocolIEs.list, F1AP_ProtocolIE_ID_id_Cause, true); + + for (int i = 0; i < in->protocolIEs.list.count; ++i) { + ie = in->protocolIEs.list.array[i]; + AssertError(ie != NULL, return false, "in->protocolIEs.list.array[i] is NULL"); + switch (ie->id) { + case F1AP_ProtocolIE_ID_id_gNB_CU_UE_F1AP_ID: + _F1_EQ_CHECK_INT(ie->value.present, F1AP_UEContextReleaseCommandIEs__value_PR_GNB_CU_UE_F1AP_ID); + out->gNB_CU_ue_id = ie->value.choice.GNB_CU_UE_F1AP_ID; + break; + case F1AP_ProtocolIE_ID_id_gNB_DU_UE_F1AP_ID: + _F1_EQ_CHECK_INT(ie->value.present, F1AP_UEContextReleaseCommandIEs__value_PR_GNB_DU_UE_F1AP_ID); + out->gNB_DU_ue_id = ie->value.choice.GNB_DU_UE_F1AP_ID; + break; + case F1AP_ProtocolIE_ID_id_Cause: + _F1_EQ_CHECK_INT(ie->value.present, F1AP_UEContextReleaseCommandIEs__value_PR_Cause); + _F1_CHECK_EXP(decode_f1ap_cause(ie->value.choice.Cause, &out->cause, &out->cause_value)); + break; + case F1AP_ProtocolIE_ID_id_RRCContainer: + _F1_EQ_CHECK_INT(ie->value.present, F1AP_UEContextReleaseCommandIEs__value_PR_RRCContainer); + out->rrc_container = malloc_or_fail(sizeof(*out->rrc_container)); + { + OCTET_STRING_t *os = &ie->value.choice.RRCContainer; + *out->rrc_container = create_byte_array(os->size, os->buf); + } + break; + case F1AP_ProtocolIE_ID_id_SRBID: + _F1_EQ_CHECK_INT(ie->value.present, F1AP_UEContextReleaseCommandIEs__value_PR_SRBID); + { + // SRB-ID + F1AP_UEContextReleaseCommandIEs_t *check_ie; + F1AP_LIB_FIND_IE(F1AP_UEContextReleaseCommandIEs_t, check_ie, &in->protocolIEs.list, F1AP_ProtocolIE_ID_id_RRCContainer, true); + } + _F1_MALLOC(out->srb_id, ie->value.choice.SRBID); + break; + case F1AP_ProtocolIE_ID_id_oldgNB_DU_UE_F1AP_ID: + _F1_EQ_CHECK_INT(ie->value.present, F1AP_UEContextReleaseCommandIEs__value_PR_GNB_DU_UE_F1AP_ID_1); + _F1_MALLOC(out->old_gNB_DU_ue_id, ie->value.choice.GNB_DU_UE_F1AP_ID_1); + break; + default: + PRINT_ERROR("F1AP_ProtocolIE_ID_id %ld unknown, skipping\n", ie->id); + break; + } + } + + return true; +} + +/** + * @brief F1 UE Context Release Command deep copy + */ +f1ap_ue_context_rel_cmd_t cp_ue_context_rel_cmd(const f1ap_ue_context_rel_cmd_t *orig) +{ + f1ap_ue_context_rel_cmd_t cp = { + .gNB_CU_ue_id = orig->gNB_CU_ue_id, + .gNB_DU_ue_id = orig->gNB_DU_ue_id, + .cause = orig->cause, + .cause_value = orig->cause_value, + }; + CP_OPT_BYTE_ARRAY(cp.rrc_container, orig->rrc_container); + if (orig->rrc_container) { + AssertFatal(orig->srb_id != NULL, "UEContextReleaseCommand SRB-ID C-ifRRCContainer violated\n"); + _F1_MALLOC(cp.srb_id, *orig->srb_id); + } + if (orig->old_gNB_DU_ue_id) + _F1_MALLOC(cp.old_gNB_DU_ue_id, *orig->old_gNB_DU_ue_id); + return cp; +} + +/** + * @brief F1 UE Context Release Command equality check + */ +bool eq_ue_context_rel_cmd(const f1ap_ue_context_rel_cmd_t *a, const f1ap_ue_context_rel_cmd_t *b) +{ + _F1_EQ_CHECK_INT(a->gNB_CU_ue_id, b->gNB_CU_ue_id); + _F1_EQ_CHECK_INT(a->gNB_DU_ue_id, b->gNB_DU_ue_id); + _F1_EQ_CHECK_INT(a->cause, b->cause); + _F1_EQ_CHECK_LONG(a->cause_value, b->cause_value); + _F1_EQ_CHECK_OPTIONAL_IE(a, b, rrc_container, eq_ba); + _F1_EQ_CHECK_OPTIONAL_IE(a, b, srb_id, _F1_EQ_CHECK_INT); + _F1_EQ_CHECK_OPTIONAL_IE(a, b, old_gNB_DU_ue_id, _F1_EQ_CHECK_INT); + return true; +} + +/** + * @brief Free Allocated F1 UE Context Release Command + */ +void free_ue_context_rel_cmd(f1ap_ue_context_rel_cmd_t *cmd) +{ + FREE_OPT_BYTE_ARRAY(cmd->rrc_container); + free(cmd->srb_id); + free(cmd->old_gNB_DU_ue_id); +} diff --git a/openair2/F1AP/lib/f1ap_ue_context.h b/openair2/F1AP/lib/f1ap_ue_context.h index 5e683fe1ab..34dd3035a3 100644 --- a/openair2/F1AP/lib/f1ap_ue_context.h +++ b/openair2/F1AP/lib/f1ap_ue_context.h @@ -57,4 +57,10 @@ f1ap_ue_context_rel_req_t cp_ue_context_rel_req(const f1ap_ue_context_rel_req_t bool eq_ue_context_rel_req(const f1ap_ue_context_rel_req_t *a, const f1ap_ue_context_rel_req_t *b); void free_ue_context_rel_req(f1ap_ue_context_rel_req_t *req); +struct F1AP_F1AP_PDU *encode_ue_context_rel_cmd(const f1ap_ue_context_rel_cmd_t *msg); +bool decode_ue_context_rel_cmd(const struct F1AP_F1AP_PDU *pdu, f1ap_ue_context_rel_cmd_t *out); +f1ap_ue_context_rel_cmd_t cp_ue_context_rel_cmd(const f1ap_ue_context_rel_cmd_t *orig); +bool eq_ue_context_rel_cmd(const f1ap_ue_context_rel_cmd_t *a, const f1ap_ue_context_rel_cmd_t *b); +void free_ue_context_rel_cmd(f1ap_ue_context_rel_cmd_t *cmd); + #endif /* F1AP_UE_CONTEXT_SETUP_REQ_H_ */ diff --git a/openair2/F1AP/tests/f1ap_lib_test.c b/openair2/F1AP/tests/f1ap_lib_test.c index a26a80823e..d46b93983b 100644 --- a/openair2/F1AP/tests/f1ap_lib_test.c +++ b/openair2/F1AP/tests/f1ap_lib_test.c @@ -1202,6 +1202,41 @@ static void test_f1ap_ue_context_release_request() printf("%s() successful\n", __func__); } +static void test_f1ap_ue_context_release_command() +{ + f1ap_ue_context_rel_cmd_t orig = { + .gNB_CU_ue_id = 1111, + .gNB_DU_ue_id = 2222, + .cause = F1AP_CAUSE_RADIO_NETWORK, + .cause_value = 2, + }; + + orig.rrc_container = get_malloced_test_ba("some reject message"); + _F1_MALLOC(orig.srb_id, 1); + _F1_MALLOC(orig.old_gNB_DU_ue_id, 3333); + + F1AP_F1AP_PDU_t *f1enc = encode_ue_context_rel_cmd(&orig); + F1AP_F1AP_PDU_t *f1dec = f1ap_encode_decode(f1enc); + f1ap_msg_free(f1enc); + + f1ap_ue_context_rel_cmd_t decoded = {0}; + bool ret = decode_ue_context_rel_cmd(f1dec, &decoded); + AssertFatal(ret, "decode_ue_context_rel_cmd(): could not decode message\n"); + f1ap_msg_free(f1dec); + + ret = eq_ue_context_rel_cmd(&orig, &decoded); + AssertFatal(ret, "eq_ue_context_rel_cmd(): decoded message doesn't match\n"); + free_ue_context_rel_cmd(&decoded); + + f1ap_ue_context_rel_cmd_t cp = cp_ue_context_rel_cmd(&orig); + ret = eq_ue_context_rel_cmd(&orig, &cp); + AssertFatal(ret, "eq_ue_context_rel_cmd(): copied message doesn't match\n"); + free_ue_context_rel_cmd(&orig); + free_ue_context_rel_cmd(&cp); + + printf("%s() successful\n", __func__); +} + int main() { test_initial_ul_rrc_message_transfer(); @@ -1226,5 +1261,6 @@ int main() test_f1ap_ue_context_modification_response(); test_f1ap_ue_context_modification_response_simple(); test_f1ap_ue_context_release_request(); + test_f1ap_ue_context_release_command(); return 0; } From e3b8121035aed0b9c4a06c06b572175c5f2cf96f Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Thu, 19 Jun 2025 17:11:04 +0200 Subject: [PATCH 19/36] Use F1 UE Context Release Command in stack Use the new type and remove the old one. --- openair2/COMMON/f1ap_messages_def.h | 2 +- openair2/COMMON/f1ap_messages_types.h | 2 +- openair2/F1AP/f1ap_cu_task.c | 1 + openair2/F1AP/f1ap_cu_ue_context_management.c | 86 ++----------------- openair2/F1AP/f1ap_cu_ue_context_management.h | 3 +- openair2/F1AP/f1ap_du_ue_context_management.c | 60 ++----------- .../LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.c | 9 +- .../LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.h | 2 +- openair2/RRC/NR/mac_rrc_dl.h | 2 +- openair2/RRC/NR/mac_rrc_dl_direct.c | 2 +- openair2/RRC/NR/mac_rrc_dl_f1ap.c | 11 +-- openair2/RRC/NR/rrc_gNB.c | 18 ++-- openair2/RRC/NR/rrc_gNB_mobility.c | 6 +- openair2/RRC/NR/rrc_gNB_nsa.c | 2 +- 14 files changed, 39 insertions(+), 167 deletions(-) diff --git a/openair2/COMMON/f1ap_messages_def.h b/openair2/COMMON/f1ap_messages_def.h index e9776c58ff..f46120a037 100644 --- a/openair2/COMMON/f1ap_messages_def.h +++ b/openair2/COMMON/f1ap_messages_def.h @@ -49,7 +49,7 @@ MESSAGE_DEF(F1AP_UL_RRC_MESSAGE , MESSAGE_PRIORITY_MED, f1ap_ul_r //MESSAGE_DEF(F1AP_INITIAL_CONTEXT_SETUP_RESP, MESSAGE_PRIORITY_MED, f1ap_initial_context_setup_resp_t, f1ap_initial_context_setup_resp) //MESSAGE_DEF(F1AP_INITIAL_CONTEXT_SETUP_FAILURE, MESSAGE_PRIORITY_MED, f1ap_initial_context_setup_failure_t, f1ap_initial_context_setup_failure) MESSAGE_DEF(F1AP_UE_CONTEXT_RELEASE_REQ, MESSAGE_PRIORITY_MED, f1ap_ue_context_rel_req_t, f1ap_ue_context_release_req) -MESSAGE_DEF(F1AP_UE_CONTEXT_RELEASE_CMD, MESSAGE_PRIORITY_MED, f1ap_ue_context_release_cmd_t, f1ap_ue_context_release_cmd) +MESSAGE_DEF(F1AP_UE_CONTEXT_RELEASE_CMD, MESSAGE_PRIORITY_MED, f1ap_ue_context_rel_cmd_t, f1ap_ue_context_release_cmd) MESSAGE_DEF(F1AP_UE_CONTEXT_RELEASE_COMPLETE, MESSAGE_PRIORITY_MED, f1ap_ue_context_release_complete_t, f1ap_ue_context_release_complete) MESSAGE_DEF(F1AP_UE_CONTEXT_MODIFICATION_REQUIRED, MESSAGE_PRIORITY_MED, f1ap_ue_context_modif_required_t, f1ap_ue_context_modification_required) diff --git a/openair2/COMMON/f1ap_messages_types.h b/openair2/COMMON/f1ap_messages_types.h index 882ead3998..243a8e5bcc 100644 --- a/openair2/COMMON/f1ap_messages_types.h +++ b/openair2/COMMON/f1ap_messages_types.h @@ -676,7 +676,7 @@ typedef struct f1ap_ue_context_release_s { uint8_t *rrc_container; int rrc_container_length; int srb_id; -} f1ap_ue_context_release_cmd_t, f1ap_ue_context_release_complete_t; +} f1ap_ue_context_release_complete_t; typedef struct f1ap_paging_ind_s { uint16_t ueidentityindexvalue; diff --git a/openair2/F1AP/f1ap_cu_task.c b/openair2/F1AP/f1ap_cu_task.c index 85375e4109..b7d19b7a6a 100644 --- a/openair2/F1AP/f1ap_cu_task.c +++ b/openair2/F1AP/f1ap_cu_task.c @@ -199,6 +199,7 @@ void *F1AP_CU_task(void *arg) { case F1AP_UE_CONTEXT_RELEASE_CMD: // from rrc CU_send_UE_CONTEXT_RELEASE_COMMAND(assoc_id, &F1AP_UE_CONTEXT_RELEASE_CMD(received_msg)); + free_ue_context_rel_cmd(&F1AP_UE_CONTEXT_RELEASE_CMD(received_msg)); break; case F1AP_PAGING_IND: diff --git a/openair2/F1AP/f1ap_cu_ue_context_management.c b/openair2/F1AP/f1ap_cu_ue_context_management.c index e0f1495f86..d29c52dec5 100644 --- a/openair2/F1AP/f1ap_cu_ue_context_management.c +++ b/openair2/F1AP/f1ap_cu_ue_context_management.c @@ -104,93 +104,19 @@ int CU_handle_UE_CONTEXT_RELEASE_REQUEST(instance_t instance, sctp_assoc_t assoc return 0; } -int CU_send_UE_CONTEXT_RELEASE_COMMAND(sctp_assoc_t assoc_id, f1ap_ue_context_release_cmd_t *cmd) +int CU_send_UE_CONTEXT_RELEASE_COMMAND(sctp_assoc_t assoc_id, f1ap_ue_context_rel_cmd_t *cmd) { - F1AP_F1AP_PDU_t pdu= {0}; - F1AP_UEContextReleaseCommand_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_UEContextRelease; - tmp->criticality = F1AP_Criticality_reject; - tmp->value.present = F1AP_InitiatingMessage__value_PR_UEContextReleaseCommand; - out = &tmp->value.choice.UEContextReleaseCommand; - /* mandatory */ - /* c1. GNB_CU_UE_F1AP_ID */ - asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextReleaseCommandIEs_t, ie1); - ie1->id = F1AP_ProtocolIE_ID_id_gNB_CU_UE_F1AP_ID; - ie1->criticality = F1AP_Criticality_reject; - ie1->value.present = F1AP_UEContextReleaseCommandIEs__value_PR_GNB_CU_UE_F1AP_ID; - ie1->value.choice.GNB_CU_UE_F1AP_ID = cmd->gNB_CU_ue_id; - /* mandatory */ - /* c2. GNB_DU_UE_F1AP_ID */ - asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextReleaseCommandIEs_t, ie2); - ie2->id = F1AP_ProtocolIE_ID_id_gNB_DU_UE_F1AP_ID; - ie2->criticality = F1AP_Criticality_reject; - ie2->value.present = F1AP_UEContextReleaseCommandIEs__value_PR_GNB_DU_UE_F1AP_ID; - ie2->value.choice.GNB_DU_UE_F1AP_ID = cmd->gNB_DU_ue_id; - /* mandatory */ - /* c3. Cause */ - asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextReleaseCommandIEs_t, ie3); - ie3->id = F1AP_ProtocolIE_ID_id_Cause; - ie3->criticality = F1AP_Criticality_ignore; - ie3->value.present = F1AP_UEContextReleaseCommandIEs__value_PR_Cause; + F1AP_F1AP_PDU_t *pdu = encode_ue_context_rel_cmd(cmd); - switch (cmd->cause) { - case F1AP_CAUSE_RADIO_NETWORK: - ie3->value.choice.Cause.present = F1AP_Cause_PR_radioNetwork; - ie3->value.choice.Cause.choice.radioNetwork = cmd->cause_value; - break; - - case F1AP_CAUSE_TRANSPORT: - ie3->value.choice.Cause.present = F1AP_Cause_PR_transport; - ie3->value.choice.Cause.choice.transport = cmd->cause_value; - break; - - case F1AP_CAUSE_PROTOCOL: - ie3->value.choice.Cause.present = F1AP_Cause_PR_protocol; - ie3->value.choice.Cause.choice.protocol = cmd->cause_value; - break; - - case F1AP_CAUSE_MISC: - ie3->value.choice.Cause.present = F1AP_Cause_PR_misc; - ie3->value.choice.Cause.choice.misc = cmd->cause_value; - break; - - case F1AP_CAUSE_NOTHING: - default: - ie3->value.choice.Cause.present = F1AP_Cause_PR_NOTHING; - break; - } - - /* optional */ - /* c4. RRCContainer */ - if(cmd->rrc_container!=NULL){ - asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextReleaseCommandIEs_t, ie4); - ie4->id = F1AP_ProtocolIE_ID_id_RRCContainer; - ie4->criticality = F1AP_Criticality_ignore; - ie4->value.present = F1AP_UEContextReleaseCommandIEs__value_PR_RRCContainer; - OCTET_STRING_fromBuf(&ie4->value.choice.RRCContainer, (const char *)cmd->rrc_container, - cmd->rrc_container_length); - - // conditionally have SRBID if RRC Container - asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextReleaseCommandIEs_t, ie5); - ie5->id = F1AP_ProtocolIE_ID_id_SRBID; - ie5->criticality = F1AP_Criticality_ignore; - ie5->value.present = F1AP_UEContextReleaseCommandIEs__value_PR_SRBID; - ie5->value.choice.SRBID = cmd->srb_id; - } - - /* encode */ - if (f1ap_encode_pdu(&pdu, &buffer, &len) < 0) { + uint8_t *buffer = NULL; + uint32_t len = 0; + if (f1ap_encode_pdu(pdu, &buffer, &len) < 0) { LOG_E(F1AP, "Failed to encode F1 context release command\n"); return -1; } f1ap_itti_send_sctp_data_req(assoc_id, buffer, len); + ASN_STRUCT_FREE(asn_DEF_F1AP_F1AP_PDU, pdu); return 0; } diff --git a/openair2/F1AP/f1ap_cu_ue_context_management.h b/openair2/F1AP/f1ap_cu_ue_context_management.h index ed76189c19..0bc1815658 100644 --- a/openair2/F1AP/f1ap_cu_ue_context_management.h +++ b/openair2/F1AP/f1ap_cu_ue_context_management.h @@ -50,8 +50,7 @@ int CU_handle_UE_CONTEXT_RELEASE_REQUEST(instance_t instance, sctp_assoc_t assoc /* * UE Context Release (gNB-CU initiated) */ -int CU_send_UE_CONTEXT_RELEASE_COMMAND(sctp_assoc_t assoc_id, - f1ap_ue_context_release_cmd_t *cmd); +int CU_send_UE_CONTEXT_RELEASE_COMMAND(sctp_assoc_t assoc_id, f1ap_ue_context_rel_cmd_t *cmd); int CU_handle_UE_CONTEXT_RELEASE_COMPLETE(instance_t instance, sctp_assoc_t assoc_id, uint32_t stream, F1AP_F1AP_PDU_t *pdu); diff --git a/openair2/F1AP/f1ap_du_ue_context_management.c b/openair2/F1AP/f1ap_du_ue_context_management.c index a2179b8583..7371b69a4f 100644 --- a/openair2/F1AP/f1ap_du_ue_context_management.c +++ b/openair2/F1AP/f1ap_du_ue_context_management.c @@ -94,61 +94,15 @@ int DU_send_UE_CONTEXT_RELEASE_REQUEST(sctp_assoc_t assoc_id, f1ap_ue_context_re int DU_handle_UE_CONTEXT_RELEASE_COMMAND(instance_t instance, sctp_assoc_t assoc_id, uint32_t stream, F1AP_F1AP_PDU_t *pdu) { - F1AP_UEContextReleaseCommand_t *container; - F1AP_UEContextReleaseCommandIEs_t *ie; - - f1ap_ue_context_release_cmd_t ue_context_release = {0}; - f1ap_ue_context_release_cmd_t *f1ap_ue_context_release_cmd = &ue_context_release; - - DevAssert(pdu); - container = &pdu->choice.initiatingMessage->value.choice.UEContextReleaseCommand; - // GNB_CU_UE_F1AP_ID - F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_UEContextReleaseCommandIEs_t, ie, container, - F1AP_ProtocolIE_ID_id_gNB_CU_UE_F1AP_ID, true); - f1ap_ue_context_release_cmd->gNB_CU_ue_id = ie->value.choice.GNB_CU_UE_F1AP_ID; - // GNB_DU_UE_F1AP_ID - F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_UEContextReleaseCommandIEs_t, ie, container, - F1AP_ProtocolIE_ID_id_gNB_DU_UE_F1AP_ID, true); - f1ap_ue_context_release_cmd->gNB_DU_ue_id = ie->value.choice.GNB_DU_UE_F1AP_ID; - - // We don't need the Cause - // Optional RRC Container: if present, send to UE - F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_UEContextReleaseCommandIEs_t, ie, container, - F1AP_ProtocolIE_ID_id_RRCContainer, false); - - if (ie != NULL) { - f1ap_ue_context_release_cmd->rrc_container = malloc(ie->value.choice.RRCContainer.size); - AssertFatal(f1ap_ue_context_release_cmd->rrc_container != NULL, "out of memory\n"); - memcpy(f1ap_ue_context_release_cmd->rrc_container, ie->value.choice.RRCContainer.buf, ie->value.choice.RRCContainer.size); - f1ap_ue_context_release_cmd->rrc_container_length = ie->value.choice.RRCContainer.size; - - // conditionally have SRB ID if there is RRC container - F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_UEContextReleaseCommandIEs_t, ie, container, F1AP_ProtocolIE_ID_id_SRBID, true); - f1ap_ue_context_release_cmd->srb_id = ie->value.choice.SRBID; + f1ap_ue_context_rel_cmd_t cmd = {0}; + if (!decode_ue_context_rel_cmd(pdu, &cmd)) { + LOG_E(F1AP, "cannot decode F1 UE Context Release Command\n"); + free_ue_context_rel_cmd(&cmd); + return -1; } - F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_UEContextReleaseCommandIEs_t, ie, container, - F1AP_ProtocolIE_ID_id_Cause, true); - switch (ie->value.choice.Cause.present){ - case F1AP_Cause_PR_radioNetwork: - f1ap_ue_context_release_cmd->cause = F1AP_CAUSE_RADIO_NETWORK; - break; - case F1AP_Cause_PR_transport: - f1ap_ue_context_release_cmd->cause = F1AP_CAUSE_TRANSPORT; - break; - case F1AP_Cause_PR_protocol: - f1ap_ue_context_release_cmd->cause = F1AP_CAUSE_PROTOCOL; - break; - case F1AP_Cause_PR_misc: - f1ap_ue_context_release_cmd->cause = F1AP_CAUSE_MISC; - break; - default: - LOG_W(F1AP, "Unknown cause for UE context release command\n"); - break; - - } - - ue_context_release_command(f1ap_ue_context_release_cmd); + ue_context_release_command(&cmd); + free_ue_context_rel_cmd(&cmd); return 0; } 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 c625343c10..74529c9dde 100644 --- a/openair2/LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.c +++ b/openair2/LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.c @@ -861,7 +861,7 @@ void ue_context_modification_refuse(const f1ap_ue_context_modif_refuse_t *refuse mac->mac_rrc.ue_context_release_request(&request); } -void ue_context_release_command(const f1ap_ue_context_release_cmd_t *cmd) +void ue_context_release_command(const f1ap_ue_context_rel_cmd_t *cmd) { /* mark UE as to be deleted after PUSCH failure */ gNB_MAC_INST *mac = RC.nrmac[0]; @@ -881,14 +881,15 @@ void ue_context_release_command(const f1ap_ue_context_release_cmd_t *cmd) if (f1inst >= 0) newGtpuDeleteAllTunnels(f1inst, cmd->gNB_DU_ue_id); - if (UE->UE_sched_ctrl.ul_failure || cmd->rrc_container_length == 0) { + if (UE->UE_sched_ctrl.ul_failure || !cmd->rrc_container) { /* 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 { + } else if (cmd->rrc_container && cmd->srb_id){ /* UE is in sync: forward release message and mark to be deleted * after UL failure */ - nr_rlc_srb_recv_sdu(cmd->gNB_DU_ue_id, cmd->srb_id, cmd->rrc_container, cmd->rrc_container_length); + byte_array_t *rrc_cont = cmd->rrc_container; + nr_rlc_srb_recv_sdu(cmd->gNB_DU_ue_id, *cmd->srb_id, (char *)rrc_cont->buf, rrc_cont->len); nr_mac_trigger_release_timer(&UE->UE_sched_ctrl, UE->current_UL_BWP.scs); } NR_SCHED_UNLOCK(&mac->sched_lock); 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 b3ecdad270..1ba31f8e80 100644 --- a/openair2/LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.h +++ b/openair2/LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.h @@ -36,7 +36,7 @@ void ue_context_setup_request(const f1ap_ue_context_setup_req_t *req); void ue_context_modification_request(const f1ap_ue_context_mod_req_t *req); void ue_context_modification_confirm(const f1ap_ue_context_modif_confirm_t *confirm); void ue_context_modification_refuse(const f1ap_ue_context_modif_refuse_t *refuse); -void ue_context_release_command(const f1ap_ue_context_release_cmd_t *cmd); +void ue_context_release_command(const f1ap_ue_context_rel_cmd_t *cmd); void dl_rrc_message_transfer(const f1ap_dl_rrc_message_t *dl_rrc); diff --git a/openair2/RRC/NR/mac_rrc_dl.h b/openair2/RRC/NR/mac_rrc_dl.h index f93bc1b7fe..4bd106d679 100644 --- a/openair2/RRC/NR/mac_rrc_dl.h +++ b/openair2/RRC/NR/mac_rrc_dl.h @@ -37,7 +37,7 @@ typedef void (*ue_context_setup_request_func_t)(sctp_assoc_t assoc_id, const f1a typedef void (*ue_context_modification_request_func_t)(sctp_assoc_t assoc_id, const f1ap_ue_context_mod_req_t *req); typedef void (*ue_context_modification_confirm_func_t)(sctp_assoc_t assoc_id, const f1ap_ue_context_modif_confirm_t *confirm); typedef void (*ue_context_modification_refuse_func_t)(sctp_assoc_t assoc_id, const f1ap_ue_context_modif_refuse_t *refuse); -typedef void (*ue_context_release_command_func_t)(sctp_assoc_t assoc_id, const f1ap_ue_context_release_cmd_t *cmd); +typedef void (*ue_context_release_command_func_t)(sctp_assoc_t assoc_id, const f1ap_ue_context_rel_cmd_t *cmd); typedef void (*dl_rrc_message_transfer_func_t)(sctp_assoc_t assoc_id, const f1ap_dl_rrc_message_t *dl_rrc); diff --git a/openair2/RRC/NR/mac_rrc_dl_direct.c b/openair2/RRC/NR/mac_rrc_dl_direct.c index 29592d4e43..83c1130fcb 100644 --- a/openair2/RRC/NR/mac_rrc_dl_direct.c +++ b/openair2/RRC/NR/mac_rrc_dl_direct.c @@ -82,7 +82,7 @@ static void ue_context_modification_refuse_direct(sctp_assoc_t assoc_id, const f ue_context_modification_refuse(refuse); } -static void ue_context_release_command_direct(sctp_assoc_t assoc_id, const f1ap_ue_context_release_cmd_t *cmd) +static void ue_context_release_command_direct(sctp_assoc_t assoc_id, const f1ap_ue_context_rel_cmd_t *cmd) { AssertFatal(assoc_id == -1, "illegal assoc_id %d\n", assoc_id); ue_context_release_command(cmd); diff --git a/openair2/RRC/NR/mac_rrc_dl_f1ap.c b/openair2/RRC/NR/mac_rrc_dl_f1ap.c index 47d1bc1d7e..37cb6d70f9 100644 --- a/openair2/RRC/NR/mac_rrc_dl_f1ap.c +++ b/openair2/RRC/NR/mac_rrc_dl_f1ap.c @@ -119,18 +119,11 @@ static void ue_context_modification_refuse_f1ap(sctp_assoc_t assoc_id, const f1a itti_send_msg_to_task(TASK_CU_F1, 0, msg); } -static void ue_context_release_command_f1ap(sctp_assoc_t assoc_id, const f1ap_ue_context_release_cmd_t *cmd) +static void ue_context_release_command_f1ap(sctp_assoc_t assoc_id, const f1ap_ue_context_rel_cmd_t *cmd) { MessageDef *message_p = itti_alloc_new_message (TASK_RRC_GNB, 0, F1AP_UE_CONTEXT_RELEASE_CMD); message_p->ittiMsgHeader.originInstance = assoc_id; - f1ap_ue_context_release_cmd_t *msg = &F1AP_UE_CONTEXT_RELEASE_CMD(message_p); - *msg = *cmd; - if (cmd->rrc_container_length > 0) { - msg->rrc_container = calloc(cmd->rrc_container_length, sizeof(*msg->rrc_container)); - AssertFatal(msg->rrc_container != NULL, "out of memory\n"); - msg->rrc_container_length = cmd->rrc_container_length; - memcpy(msg->rrc_container, cmd->rrc_container, cmd->rrc_container_length); - } + F1AP_UE_CONTEXT_RELEASE_CMD(message_p) = cp_ue_context_rel_cmd(cmd); itti_send_msg_to_task (TASK_CU_F1, 0, message_p); } diff --git a/openair2/RRC/NR/rrc_gNB.c b/openair2/RRC/NR/rrc_gNB.c index a7ba899c82..07f7eec659 100644 --- a/openair2/RRC/NR/rrc_gNB.c +++ b/openair2/RRC/NR/rrc_gNB.c @@ -113,7 +113,7 @@ mui_t rrc_gNB_mui = 0; typedef struct deliver_ue_ctxt_release_data_t { gNB_RRC_INST *rrc; - f1ap_ue_context_release_cmd_t *release_cmd; + f1ap_ue_context_rel_cmd_t *release_cmd; sctp_assoc_t assoc_id; } deliver_ue_ctxt_release_data_t; @@ -121,8 +121,8 @@ static void rrc_deliver_ue_ctxt_release_cmd(void *deliver_pdu_data, ue_id_t ue_i { DevAssert(deliver_pdu_data != NULL); deliver_ue_ctxt_release_data_t *data = deliver_pdu_data; - data->release_cmd->rrc_container = (uint8_t*) buf; - data->release_cmd->rrc_container_length = size; + byte_array_t rrc_cont = {.buf = (uint8_t *)buf, .len = size}; + data->release_cmd->rrc_container = &rrc_cont; data->rrc->mac_rrc.ue_context_release_command(data->assoc_id, data->release_cmd); } @@ -2142,12 +2142,12 @@ static void rrc_CU_process_ue_context_release_request(MessageDef *msg_p, sctp_as LOG_W(RRC, "could not find UE context for CU UE ID %u: auto-generate release command\n", req->gNB_CU_ue_id); uint8_t buffer[NR_RRC_BUF_SIZE] = {0}; int size = do_NR_RRCRelease(buffer, NR_RRC_BUF_SIZE, rrc_gNB_get_next_transaction_identifier(0)); - f1ap_ue_context_release_cmd_t ue_context_release_cmd = { + f1ap_ue_context_rel_cmd_t ue_context_release_cmd = { .gNB_CU_ue_id = req->gNB_CU_ue_id, .gNB_DU_ue_id = req->gNB_DU_ue_id, .cause = F1AP_CAUSE_RADIO_NETWORK, .cause_value = 10, // 10 = F1AP_CauseRadioNetwork_normal_release - .srb_id = srbid, + .srb_id = &srbid, // C-ifRRCContainer => is added below }; deliver_ue_ctxt_release_data_t data = {.rrc = rrc, .release_cmd = &ue_context_release_cmd}; nr_pdcp_data_req_srb(req->gNB_CU_ue_id, srbid, rrc_gNB_mui++, size, buffer, rrc_deliver_ue_ctxt_release_cmd, &data); @@ -2163,12 +2163,11 @@ static void rrc_CU_process_ue_context_release_request(MessageDef *msg_p, sctp_as // ongoing; free the UE, and remove the HO context. LOG_W(NR_RRC, "UE %d: release request from source DU ID %ld during HO, marking HO as complete\n", UE->rrc_ue_id, source_ctx->du->setup_req->gNB_DU_id); RETURN_IF_INVALID_ASSOC_ID(source_ctx->du->assoc_id); - f1ap_ue_context_release_cmd_t cmd = { + f1ap_ue_context_rel_cmd_t cmd = { .gNB_CU_ue_id = UE->rrc_ue_id, .gNB_DU_ue_id = source_ctx->du_ue_id, .cause = F1AP_CAUSE_RADIO_NETWORK, .cause_value = 5, // 5 = F1AP_CauseRadioNetwork_interaction_with_other_procedure - .srb_id = DL_SCH_LCID_DCCH, }; rrc->mac_rrc.ue_context_release_command(assoc_id, &cmd); nr_rrc_finalize_ho(UE); @@ -2914,12 +2913,13 @@ void rrc_gNB_generate_RRCRelease(gNB_RRC_INST *rrc, gNB_RRC_UE_t *UE) LOG_UE_DL_EVENT(UE, "Send RRC Release\n"); f1_ue_data_t ue_data = cu_get_f1_ue_data(UE->rrc_ue_id); RETURN_IF_INVALID_ASSOC_ID(ue_data.du_assoc_id); - f1ap_ue_context_release_cmd_t ue_context_release_cmd = { + int srbid = 1; + f1ap_ue_context_rel_cmd_t ue_context_release_cmd = { .gNB_CU_ue_id = UE->rrc_ue_id, .gNB_DU_ue_id = ue_data.secondary_ue, .cause = F1AP_CAUSE_RADIO_NETWORK, .cause_value = 10, // 10 = F1AP_CauseRadioNetwork_normal_release - .srb_id = DL_SCH_LCID_DCCH, + .srb_id = &srbid, // C-ifRRCContainer => is added below }; deliver_ue_ctxt_release_data_t data = {.rrc = rrc, .release_cmd = &ue_context_release_cmd, .assoc_id = ue_data.du_assoc_id}; nr_pdcp_data_req_srb(UE->rrc_ue_id, DL_SCH_LCID_DCCH, rrc_gNB_mui++, size, buffer, rrc_deliver_ue_ctxt_release_cmd, &data); diff --git a/openair2/RRC/NR/rrc_gNB_mobility.c b/openair2/RRC/NR/rrc_gNB_mobility.c index a08e446ef1..7312e2f631 100644 --- a/openair2/RRC/NR/rrc_gNB_mobility.c +++ b/openair2/RRC/NR/rrc_gNB_mobility.c @@ -307,12 +307,11 @@ static void nr_rrc_f1_ho_complete(gNB_RRC_INST *rrc, gNB_RRC_UE_t *UE) nr_ho_source_cu_t *source_ctx = UE->ho_context->source; DevAssert(source_ctx != NULL); RETURN_IF_INVALID_ASSOC_ID(source_ctx->du->assoc_id); - f1ap_ue_context_release_cmd_t cmd = { + f1ap_ue_context_rel_cmd_t cmd = { .gNB_CU_ue_id = UE->rrc_ue_id, .gNB_DU_ue_id = source_ctx->du_ue_id, .cause = F1AP_CAUSE_RADIO_NETWORK, .cause_value = 5, // 5 = F1AP_CauseRadioNetwork_interaction_with_other_procedure - .srb_id = DL_SCH_LCID_DCCH, }; rrc->mac_rrc.ue_context_release_command(source_ctx->du->assoc_id, &cmd); LOG_I(NR_RRC, "UE %d Handover: trigger release on DU assoc_id %d\n", UE->rrc_ue_id, source_ctx->du->assoc_id); @@ -323,12 +322,11 @@ static void nr_rrc_cancel_f1_ho(gNB_RRC_INST *rrc, gNB_RRC_UE_t *UE) DevAssert(UE->ho_context != NULL); nr_ho_target_cu_t *target_ctx = UE->ho_context->target; DevAssert(target_ctx != NULL); - f1ap_ue_context_release_cmd_t cmd = { + f1ap_ue_context_rel_cmd_t cmd = { .gNB_CU_ue_id = UE->rrc_ue_id, .gNB_DU_ue_id = target_ctx->du_ue_id, .cause = F1AP_CAUSE_RADIO_NETWORK, // better .cause_value = 5, // 5 = F1AP_CauseRadioNetwork_interaction_with_other_procedure - .srb_id = DL_SCH_LCID_DCCH, }; rrc->mac_rrc.ue_context_release_command(target_ctx->du->assoc_id, &cmd); } diff --git a/openair2/RRC/NR/rrc_gNB_nsa.c b/openair2/RRC/NR/rrc_gNB_nsa.c index 78be16b100..c2dfb3e20a 100644 --- a/openair2/RRC/NR/rrc_gNB_nsa.c +++ b/openair2/RRC/NR/rrc_gNB_nsa.c @@ -464,7 +464,7 @@ void rrc_release_nsa_user(gNB_RRC_INST *rrc, rrc_gNB_ue_context_t *ue_context) gNB_RRC_UE_t *UE = &ue_context->ue_context; f1_ue_data_t ue_data = cu_get_f1_ue_data(UE->rrc_ue_id); RETURN_IF_INVALID_ASSOC_ID(ue_data.du_assoc_id); - f1ap_ue_context_release_cmd_t cmd = { + f1ap_ue_context_rel_cmd_t cmd = { .gNB_CU_ue_id = UE->rrc_ue_id, .gNB_DU_ue_id = ue_data.secondary_ue, .cause = F1AP_CAUSE_RADIO_NETWORK, From bbb6b3f7ad2f93a7a5f87db1eac9ad53448da634 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Fri, 13 Jun 2025 11:26:23 +0200 Subject: [PATCH 20/36] Add F1AP UE context release complete message enc/dec + test See commit "Add F1AP UE context setup request message enc/dec + test" for more details on the approach taken. --- openair2/COMMON/f1ap_messages_types.h | 5 ++ openair2/F1AP/lib/f1ap_ue_context.c | 96 +++++++++++++++++++++++++++ openair2/F1AP/lib/f1ap_ue_context.h | 6 ++ openair2/F1AP/tests/f1ap_lib_test.c | 30 +++++++++ 4 files changed, 137 insertions(+) diff --git a/openair2/COMMON/f1ap_messages_types.h b/openair2/COMMON/f1ap_messages_types.h index 243a8e5bcc..46697e532e 100644 --- a/openair2/COMMON/f1ap_messages_types.h +++ b/openair2/COMMON/f1ap_messages_types.h @@ -668,6 +668,11 @@ typedef struct f1ap_ue_context_rel_cmd_t { uint32_t *old_gNB_DU_ue_id; // if after reestablishment request } f1ap_ue_context_rel_cmd_t; +typedef struct f1ap_ue_context_rel_cplt_t { + uint32_t gNB_CU_ue_id; + uint32_t gNB_DU_ue_id; +} f1ap_ue_context_rel_cplt_t; + typedef struct f1ap_ue_context_release_s { uint32_t gNB_CU_ue_id; uint32_t gNB_DU_ue_id; diff --git a/openair2/F1AP/lib/f1ap_ue_context.c b/openair2/F1AP/lib/f1ap_ue_context.c index d070ca0cde..a1b5531c2b 100644 --- a/openair2/F1AP/lib/f1ap_ue_context.c +++ b/openair2/F1AP/lib/f1ap_ue_context.c @@ -2370,3 +2370,99 @@ void free_ue_context_rel_cmd(f1ap_ue_context_rel_cmd_t *cmd) free(cmd->srb_id); free(cmd->old_gNB_DU_ue_id); } + +/* + * @brief Encode F1 UE context release complete to ASN.1 + */ +struct F1AP_F1AP_PDU *encode_ue_context_rel_cplt(const f1ap_ue_context_rel_cplt_t *cplt) +{ + F1AP_F1AP_PDU_t *pdu = calloc_or_fail(1, sizeof(*pdu)); + + /* Message Type */ + pdu->present = F1AP_F1AP_PDU_PR_successfulOutcome; + asn1cCalloc(pdu->choice.successfulOutcome, tmp); + tmp->procedureCode = F1AP_ProcedureCode_id_UEContextRelease; + tmp->criticality = F1AP_Criticality_reject; + tmp->value.present = F1AP_SuccessfulOutcome__value_PR_UEContextReleaseComplete; + F1AP_UEContextReleaseComplete_t *out = &tmp->value.choice.UEContextReleaseComplete; + + /* mandatory: GNB_CU_UE_F1AP_ID */ + asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextReleaseCompleteIEs_t, ie1); + ie1->id = F1AP_ProtocolIE_ID_id_gNB_CU_UE_F1AP_ID; + ie1->criticality = F1AP_Criticality_reject; + ie1->value.present = F1AP_UEContextReleaseCompleteIEs__value_PR_GNB_CU_UE_F1AP_ID; + ie1->value.choice.GNB_CU_UE_F1AP_ID = cplt->gNB_CU_ue_id; + + /* mandatory: GNB_DU_UE_F1AP_ID */ + asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextReleaseCompleteIEs_t, ie2); + ie2->id = F1AP_ProtocolIE_ID_id_gNB_DU_UE_F1AP_ID; + ie2->criticality = F1AP_Criticality_reject; + ie2->value.present = F1AP_UEContextReleaseCompleteIEs__value_PR_GNB_DU_UE_F1AP_ID; + ie2->value.choice.GNB_DU_UE_F1AP_ID = cplt->gNB_DU_ue_id; + + return pdu; +} + +/** + * @brief Decode F1 UE Context Release Complete + */ +bool decode_ue_context_rel_cplt(const struct F1AP_F1AP_PDU *pdu, f1ap_ue_context_rel_cplt_t *out) +{ + DevAssert(out != NULL); + memset(out, 0, sizeof(*out)); + + F1AP_UEContextReleaseComplete_t *in = &pdu->choice.successfulOutcome->value.choice.UEContextReleaseComplete; + F1AP_UEContextReleaseCompleteIEs_t *ie; + F1AP_LIB_FIND_IE(F1AP_UEContextReleaseCompleteIEs_t, ie, &in->protocolIEs.list, F1AP_ProtocolIE_ID_id_gNB_CU_UE_F1AP_ID, true); + F1AP_LIB_FIND_IE(F1AP_UEContextReleaseCompleteIEs_t, ie, &in->protocolIEs.list, F1AP_ProtocolIE_ID_id_gNB_DU_UE_F1AP_ID, true); + + for (int i = 0; i < in->protocolIEs.list.count; ++i) { + ie = in->protocolIEs.list.array[i]; + AssertError(ie != NULL, return false, "in->protocolIEs.list.array[i] is NULL"); + switch (ie->id) { + case F1AP_ProtocolIE_ID_id_gNB_CU_UE_F1AP_ID: + _F1_EQ_CHECK_INT(ie->value.present, F1AP_UEContextReleaseCompleteIEs__value_PR_GNB_CU_UE_F1AP_ID); + out->gNB_CU_ue_id = ie->value.choice.GNB_CU_UE_F1AP_ID; + break; + case F1AP_ProtocolIE_ID_id_gNB_DU_UE_F1AP_ID: + _F1_EQ_CHECK_INT(ie->value.present, F1AP_UEContextReleaseCompleteIEs__value_PR_GNB_DU_UE_F1AP_ID); + out->gNB_DU_ue_id = ie->value.choice.GNB_DU_UE_F1AP_ID; + break; + default: + PRINT_ERROR("F1AP_ProtocolIE_ID_id %ld unknown, skipping\n", ie->id); + break; + } + } + + return true; +} + +/** + * @brief F1 UE Context Release Complete deep copy + */ +f1ap_ue_context_rel_cplt_t cp_ue_context_rel_cplt(const f1ap_ue_context_rel_cplt_t *orig) +{ + f1ap_ue_context_rel_cplt_t cp = { + .gNB_CU_ue_id = orig->gNB_CU_ue_id, + .gNB_DU_ue_id = orig->gNB_DU_ue_id, + }; + return cp; +} + +/** + * @brief F1 UE Context Release Complete equality check + */ +bool eq_ue_context_rel_cplt(const f1ap_ue_context_rel_cplt_t *a, const f1ap_ue_context_rel_cplt_t *b) +{ + _F1_EQ_CHECK_INT(a->gNB_CU_ue_id, b->gNB_CU_ue_id); + _F1_EQ_CHECK_INT(a->gNB_DU_ue_id, b->gNB_DU_ue_id); + return true; +} + +/** + * @brief Free Allocated F1 UE Context Release Complete + */ +void free_ue_context_rel_cplt(f1ap_ue_context_rel_cplt_t *cplt) +{ + // nothing to free +} diff --git a/openair2/F1AP/lib/f1ap_ue_context.h b/openair2/F1AP/lib/f1ap_ue_context.h index 34dd3035a3..0e82e82a85 100644 --- a/openair2/F1AP/lib/f1ap_ue_context.h +++ b/openair2/F1AP/lib/f1ap_ue_context.h @@ -63,4 +63,10 @@ f1ap_ue_context_rel_cmd_t cp_ue_context_rel_cmd(const f1ap_ue_context_rel_cmd_t bool eq_ue_context_rel_cmd(const f1ap_ue_context_rel_cmd_t *a, const f1ap_ue_context_rel_cmd_t *b); void free_ue_context_rel_cmd(f1ap_ue_context_rel_cmd_t *cmd); +struct F1AP_F1AP_PDU *encode_ue_context_rel_cplt(const f1ap_ue_context_rel_cplt_t *msg); +bool decode_ue_context_rel_cplt(const struct F1AP_F1AP_PDU *pdu, f1ap_ue_context_rel_cplt_t *out); +f1ap_ue_context_rel_cplt_t cp_ue_context_rel_cplt(const f1ap_ue_context_rel_cplt_t *orig); +bool eq_ue_context_rel_cplt(const f1ap_ue_context_rel_cplt_t *a, const f1ap_ue_context_rel_cplt_t *b); +void free_ue_context_rel_cplt(f1ap_ue_context_rel_cplt_t *cplt); + #endif /* F1AP_UE_CONTEXT_SETUP_REQ_H_ */ diff --git a/openair2/F1AP/tests/f1ap_lib_test.c b/openair2/F1AP/tests/f1ap_lib_test.c index d46b93983b..ebf90fc648 100644 --- a/openair2/F1AP/tests/f1ap_lib_test.c +++ b/openair2/F1AP/tests/f1ap_lib_test.c @@ -1237,6 +1237,35 @@ static void test_f1ap_ue_context_release_command() printf("%s() successful\n", __func__); } +static void test_f1ap_ue_context_release_complete() +{ + f1ap_ue_context_rel_cplt_t orig = { + .gNB_CU_ue_id = 1111, + .gNB_DU_ue_id = 2222, + }; + + F1AP_F1AP_PDU_t *f1enc = encode_ue_context_rel_cplt(&orig); + F1AP_F1AP_PDU_t *f1dec = f1ap_encode_decode(f1enc); + f1ap_msg_free(f1enc); + + f1ap_ue_context_rel_cplt_t decoded = {0}; + bool ret = decode_ue_context_rel_cplt(f1dec, &decoded); + AssertFatal(ret, "decode_ue_context_rel_cplt(): could not decode message\n"); + f1ap_msg_free(f1dec); + + ret = eq_ue_context_rel_cplt(&orig, &decoded); + AssertFatal(ret, "eq_ue_context_rel_cplt(): decoded message doesn't match\n"); + free_ue_context_rel_cplt(&decoded); + + f1ap_ue_context_rel_cplt_t cp = cp_ue_context_rel_cplt(&orig); + ret = eq_ue_context_rel_cplt(&orig, &cp); + AssertFatal(ret, "eq_ue_context_rel_cplt(): copied message doesn't match\n"); + free_ue_context_rel_cplt(&orig); + free_ue_context_rel_cplt(&cp); + + printf("%s() successful\n", __func__); +} + int main() { test_initial_ul_rrc_message_transfer(); @@ -1262,5 +1291,6 @@ int main() test_f1ap_ue_context_modification_response_simple(); test_f1ap_ue_context_release_request(); test_f1ap_ue_context_release_command(); + test_f1ap_ue_context_release_complete(); return 0; } From abb3eff285a5193491f7290a333e3ea822c76793 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Thu, 19 Jun 2025 17:33:38 +0200 Subject: [PATCH 21/36] Use F1 UE context Release Complete in stack Use the new type and remove the old one. --- openair2/COMMON/f1ap_messages_def.h | 2 +- openair2/COMMON/f1ap_messages_types.h | 10 --- openair2/F1AP/f1ap_cu_ue_context_management.c | 36 ++------- openair2/F1AP/f1ap_du_ue_context_management.c | 81 ++----------------- openair2/F1AP/f1ap_du_ue_context_management.h | 2 +- .../NR_MAC_gNB/gNB_scheduler_primitives.c | 2 +- .../LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.c | 4 +- openair2/LAYER2/NR_MAC_gNB/mac_rrc_ul.h | 2 +- .../LAYER2/NR_MAC_gNB/mac_rrc_ul_direct.c | 5 +- openair2/LAYER2/NR_MAC_gNB/mac_rrc_ul_f1ap.c | 5 +- openair2/RRC/NR/rrc_gNB.c | 3 +- 11 files changed, 25 insertions(+), 127 deletions(-) diff --git a/openair2/COMMON/f1ap_messages_def.h b/openair2/COMMON/f1ap_messages_def.h index f46120a037..18b16563d8 100644 --- a/openair2/COMMON/f1ap_messages_def.h +++ b/openair2/COMMON/f1ap_messages_def.h @@ -50,7 +50,7 @@ MESSAGE_DEF(F1AP_UL_RRC_MESSAGE , MESSAGE_PRIORITY_MED, f1ap_ul_r //MESSAGE_DEF(F1AP_INITIAL_CONTEXT_SETUP_FAILURE, MESSAGE_PRIORITY_MED, f1ap_initial_context_setup_failure_t, f1ap_initial_context_setup_failure) MESSAGE_DEF(F1AP_UE_CONTEXT_RELEASE_REQ, MESSAGE_PRIORITY_MED, f1ap_ue_context_rel_req_t, f1ap_ue_context_release_req) MESSAGE_DEF(F1AP_UE_CONTEXT_RELEASE_CMD, MESSAGE_PRIORITY_MED, f1ap_ue_context_rel_cmd_t, f1ap_ue_context_release_cmd) -MESSAGE_DEF(F1AP_UE_CONTEXT_RELEASE_COMPLETE, MESSAGE_PRIORITY_MED, f1ap_ue_context_release_complete_t, f1ap_ue_context_release_complete) +MESSAGE_DEF(F1AP_UE_CONTEXT_RELEASE_COMPLETE, MESSAGE_PRIORITY_MED, f1ap_ue_context_rel_cplt_t, f1ap_ue_context_release_complete) MESSAGE_DEF(F1AP_UE_CONTEXT_MODIFICATION_REQUIRED, MESSAGE_PRIORITY_MED, f1ap_ue_context_modif_required_t, f1ap_ue_context_modification_required) /* RRC -> F1AP messages */ diff --git a/openair2/COMMON/f1ap_messages_types.h b/openair2/COMMON/f1ap_messages_types.h index 46697e532e..12f41a81f9 100644 --- a/openair2/COMMON/f1ap_messages_types.h +++ b/openair2/COMMON/f1ap_messages_types.h @@ -673,16 +673,6 @@ typedef struct f1ap_ue_context_rel_cplt_t { uint32_t gNB_DU_ue_id; } f1ap_ue_context_rel_cplt_t; -typedef struct f1ap_ue_context_release_s { - uint32_t gNB_CU_ue_id; - uint32_t gNB_DU_ue_id; - f1ap_Cause_t cause; - long cause_value; - uint8_t *rrc_container; - int rrc_container_length; - int srb_id; -} f1ap_ue_context_release_complete_t; - typedef struct f1ap_paging_ind_s { uint16_t ueidentityindexvalue; uint64_t fiveg_s_tmsi; diff --git a/openair2/F1AP/f1ap_cu_ue_context_management.c b/openair2/F1AP/f1ap_cu_ue_context_management.c index d29c52dec5..2d0959eb25 100644 --- a/openair2/F1AP/f1ap_cu_ue_context_management.c +++ b/openair2/F1AP/f1ap_cu_ue_context_management.c @@ -122,37 +122,17 @@ int CU_send_UE_CONTEXT_RELEASE_COMMAND(sctp_assoc_t assoc_id, f1ap_ue_context_re int CU_handle_UE_CONTEXT_RELEASE_COMPLETE(instance_t instance, sctp_assoc_t assoc_id, uint32_t stream, F1AP_F1AP_PDU_t *pdu) { - F1AP_UEContextReleaseComplete_t *container; - F1AP_UEContextReleaseCompleteIEs_t *ie; - DevAssert(pdu); - MessageDef *msg_p = itti_alloc_new_message(TASK_DU_F1, 0, F1AP_UE_CONTEXT_RELEASE_COMPLETE); - msg_p->ittiMsgHeader.originInstance = assoc_id; - f1ap_ue_context_release_complete_t *complete = &F1AP_UE_CONTEXT_RELEASE_COMPLETE(msg_p); - container = &pdu->choice.successfulOutcome->value.choice.UEContextReleaseComplete; - /* GNB_CU_UE_F1AP_ID */ - F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_UEContextReleaseCompleteIEs_t, ie, container, - F1AP_ProtocolIE_ID_id_gNB_CU_UE_F1AP_ID, true); - complete->gNB_CU_ue_id = ie->value.choice.GNB_CU_UE_F1AP_ID; - /* GNB_DU_UE_F1AP_ID */ - F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_UEContextReleaseCompleteIEs_t, ie, container, - F1AP_ProtocolIE_ID_id_gNB_DU_UE_F1AP_ID, true); - complete->gNB_DU_ue_id = ie->value.choice.GNB_DU_UE_F1AP_ID; - - /* Optional*/ - /* CriticalityDiagnostics */ - F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_UEContextReleaseCompleteIEs_t, ie, container, - F1AP_ProtocolIE_ID_id_CriticalityDiagnostics, false); - - if (ie) { - // ie->value.choice.CriticalityDiagnostics.procedureCode - // ie->value.choice.CriticalityDiagnostics.triggeringMessage - // ie->value.choice.CriticalityDiagnostics.procedureCriticality - // ie->value.choice.CriticalityDiagnostics.transactionID - // F1AP_CriticalityDiagnostics_IE_List + f1ap_ue_context_rel_cplt_t cplt = {0}; + if (!decode_ue_context_rel_cplt(pdu, &cplt)) { + LOG_E(F1AP, "cannot decode F1 UE Context Release Complete\n"); + free_ue_context_rel_cplt(&cplt); + return -1; } + MessageDef *msg_p = itti_alloc_new_message(TASK_DU_F1, 0, F1AP_UE_CONTEXT_RELEASE_COMPLETE); + msg_p->ittiMsgHeader.originInstance = assoc_id; + F1AP_UE_CONTEXT_RELEASE_COMPLETE(msg_p) = cplt; itti_send_msg_to_task(TASK_RRC_GNB, instance, msg_p); - return 0; } diff --git a/openair2/F1AP/f1ap_du_ue_context_management.c b/openair2/F1AP/f1ap_du_ue_context_management.c index 7371b69a4f..e09f038864 100644 --- a/openair2/F1AP/f1ap_du_ue_context_management.c +++ b/openair2/F1AP/f1ap_du_ue_context_management.c @@ -106,90 +106,19 @@ int DU_handle_UE_CONTEXT_RELEASE_COMMAND(instance_t instance, sctp_assoc_t assoc return 0; } -int DU_send_UE_CONTEXT_RELEASE_COMPLETE(sctp_assoc_t assoc_id, f1ap_ue_context_release_complete_t *complete) +int DU_send_UE_CONTEXT_RELEASE_COMPLETE(sctp_assoc_t assoc_id, f1ap_ue_context_rel_cplt_t *cplt) { - F1AP_F1AP_PDU_t pdu= {0}; - F1AP_UEContextReleaseComplete_t *out; - /* Create */ - /* 0. Message Type */ - pdu.present = F1AP_F1AP_PDU_PR_successfulOutcome; - asn1cCalloc(pdu.choice.successfulOutcome, tmp); - tmp->procedureCode = F1AP_ProcedureCode_id_UEContextRelease; - tmp->criticality = F1AP_Criticality_reject; - tmp->value.present = F1AP_SuccessfulOutcome__value_PR_UEContextReleaseComplete; - out = &tmp->value.choice.UEContextReleaseComplete; - /* mandatory */ - /* c1. GNB_CU_UE_F1AP_ID */ - asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextReleaseCompleteIEs_t, ie1); - ie1->id = F1AP_ProtocolIE_ID_id_gNB_CU_UE_F1AP_ID; - ie1->criticality = F1AP_Criticality_reject; - ie1->value.present = F1AP_UEContextReleaseCompleteIEs__value_PR_GNB_CU_UE_F1AP_ID; - ie1->value.choice.GNB_CU_UE_F1AP_ID = complete->gNB_CU_ue_id; - /* mandatory */ - /* c2. GNB_DU_UE_F1AP_ID */ - asn1cSequenceAdd(out->protocolIEs.list,F1AP_UEContextReleaseCompleteIEs_t, ie2); - ie2->id = F1AP_ProtocolIE_ID_id_gNB_DU_UE_F1AP_ID; - ie2->criticality = F1AP_Criticality_reject; - ie2->value.present = F1AP_UEContextReleaseCompleteIEs__value_PR_GNB_DU_UE_F1AP_ID; - ie2->value.choice.GNB_DU_UE_F1AP_ID = complete->gNB_DU_ue_id; - /* optional -> currently not used */ - /* c3. CriticalityDiagnostics */ - //if (0) { - // ie = (F1AP_UEContextReleaseCompleteIEs_t *)calloc(1, sizeof(F1AP_UEContextReleaseCompleteIEs_t)); - // ie->id = F1AP_ProtocolIE_ID_id_CriticalityDiagnostics; - // ie->criticality = F1AP_Criticality_ignore; - // ie->value.present = F1AP_UEContextReleaseCompleteIEs__value_PR_CriticalityDiagnostics; - // // dummy value - // /* optional */ - // /* procedureCode */ - // if (0) { - // ie->value.choice.CriticalityDiagnostics.procedureCode = (F1AP_ProcedureCode_t *)calloc(1, sizeof(F1AP_ProcedureCode_t)); - // ie->value.choice.CriticalityDiagnostics.procedureCode = 0L; - // } - // /* optional */ - // /* triggeringMessage */ - // if (0) { - // ie->value.choice.CriticalityDiagnostics.triggeringMessage = (F1AP_TriggeringMessage_t *)calloc(1, sizeof(F1AP_TriggeringMessage_t)); - // ie->value.choice.CriticalityDiagnostics.triggeringMessage = (F1AP_TriggeringMessage_t *)F1AP_TriggeringMessage_successful_outcome; - // } - // /* optional */ - // /* procedureCriticality */ - // if (0) { - // ie->value.choice.CriticalityDiagnostics.procedureCriticality = (F1AP_Criticality_t *)calloc(1, sizeof(F1AP_Criticality_t)); - // ie->value.choice.CriticalityDiagnostics.procedureCriticality = F1AP_Criticality_reject; - // } - // /* optional */ - // /* transactionID */ - // if (0) { - // ie->value.choice.CriticalityDiagnostics.transactionID = (F1AP_TransactionID_t *)calloc(1, sizeof(F1AP_TransactionID_t)); - // ie->value.choice.CriticalityDiagnostics.transactionID = 0L; - // } - // /* optional */ - // /* F1AP_CriticalityDiagnostics_IE_List */ - // if (0) { - // for (i=0; - // i<0; - // i++) { - // F1AP_CriticalityDiagnostics_IE_Item_t *criticalityDiagnostics_ie_item = (F1AP_CriticalityDiagnostics_IE_Item_t *)calloc(1, sizeof(F1AP_CriticalityDiagnostics_IE_Item_t));; - // criticalityDiagnostics_ie_item->iECriticality = F1AP_Criticality_reject; - // criticalityDiagnostics_ie_item->iE_ID = 0L; - // criticalityDiagnostics_ie_item->typeOfError = F1AP_TypeOfError_not_understood; - // asn1cSeqAdd(&ie->value.choice.CriticalityDiagnostics.iEsCriticalityDiagnostics->list, - // criticalityDiagnostics_ie_item); - // } - // } - // asn1cSeqAdd(&out->protocolIEs.list, ie); - //} - /* encode */ + F1AP_F1AP_PDU_t *pdu = encode_ue_context_rel_cplt(cplt); + uint8_t *buffer; uint32_t len; - - if (f1ap_encode_pdu(&pdu, &buffer, &len) < 0) { + if (f1ap_encode_pdu(pdu, &buffer, &len) < 0) { LOG_E(F1AP, "Failed to encode F1 context release complete\n"); return -1; } f1ap_itti_send_sctp_data_req(assoc_id, buffer, len); + ASN_STRUCT_FREE(asn_DEF_F1AP_F1AP_PDU, pdu); return 0; } diff --git a/openair2/F1AP/f1ap_du_ue_context_management.h b/openair2/F1AP/f1ap_du_ue_context_management.h index e9ef2bef8c..b6c12de18b 100644 --- a/openair2/F1AP/f1ap_du_ue_context_management.h +++ b/openair2/F1AP/f1ap_du_ue_context_management.h @@ -55,7 +55,7 @@ int DU_handle_UE_CONTEXT_RELEASE_COMMAND(instance_t instance, sctp_assoc_t assoc /* * UE Context Release Complete (gNB-DU initiated) */ -int DU_send_UE_CONTEXT_RELEASE_COMPLETE(sctp_assoc_t assoc_id, f1ap_ue_context_release_complete_t *complete); +int DU_send_UE_CONTEXT_RELEASE_COMPLETE(sctp_assoc_t assoc_id, f1ap_ue_context_rel_cplt_t *cplt); /* * UE Context Modification (gNB-CU initiated) diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c index b85c26b1a3..48fabb45e8 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c @@ -3124,7 +3124,7 @@ void nr_mac_trigger_release_complete(gNB_MAC_INST *mac, int rnti) // 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 = { + f1ap_ue_context_rel_cplt_t complete = { .gNB_CU_ue_id = ue_data.secondary_ue, .gNB_DU_ue_id = rnti, }; 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 74529c9dde..3b5fd80639 100644 --- a/openair2/LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.c +++ b/openair2/LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.c @@ -869,7 +869,7 @@ void ue_context_release_command(const f1ap_ue_context_rel_cmd_t *cmd) NR_UE_info_t *UE = find_nr_UE(&mac->UE_info, cmd->gNB_DU_ue_id); if (UE == NULL) { NR_SCHED_UNLOCK(&mac->sched_lock); - f1ap_ue_context_release_complete_t complete = { + f1ap_ue_context_rel_cplt_t complete = { .gNB_CU_ue_id = cmd->gNB_CU_ue_id, .gNB_DU_ue_id = cmd->gNB_DU_ue_id, }; @@ -889,7 +889,7 @@ void ue_context_release_command(const f1ap_ue_context_rel_cmd_t *cmd) /* UE is in sync: forward release message and mark to be deleted * after UL failure */ byte_array_t *rrc_cont = cmd->rrc_container; - nr_rlc_srb_recv_sdu(cmd->gNB_DU_ue_id, *cmd->srb_id, (char *)rrc_cont->buf, rrc_cont->len); + nr_rlc_srb_recv_sdu(cmd->gNB_DU_ue_id, *cmd->srb_id, rrc_cont->buf, rrc_cont->len); nr_mac_trigger_release_timer(&UE->UE_sched_ctrl, UE->current_UL_BWP.scs); } NR_SCHED_UNLOCK(&mac->sched_lock); diff --git a/openair2/LAYER2/NR_MAC_gNB/mac_rrc_ul.h b/openair2/LAYER2/NR_MAC_gNB/mac_rrc_ul.h index 3f54ae53b8..23dda86dfb 100644 --- a/openair2/LAYER2/NR_MAC_gNB/mac_rrc_ul.h +++ b/openair2/LAYER2/NR_MAC_gNB/mac_rrc_ul.h @@ -35,7 +35,7 @@ typedef void (*ue_context_setup_response_func_t)(const f1ap_ue_context_setup_res typedef void (*ue_context_modification_response_func_t)(const f1ap_ue_context_mod_resp_t *resp); typedef void (*ue_context_modification_required_func_t)(const f1ap_ue_context_modif_required_t *t); typedef void (*ue_context_release_request_func_t)(const f1ap_ue_context_rel_req_t* req); -typedef void (*ue_context_release_complete_func_t)(const f1ap_ue_context_release_complete_t *complete); +typedef void (*ue_context_release_complete_func_t)(const f1ap_ue_context_rel_cplt_t *complete); typedef void (*initial_ul_rrc_message_transfer_func_t)(module_id_t module_id, const f1ap_initial_ul_rrc_message_t *ul_rrc); 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 9f719374c1..cf6c5b2563 100644 --- a/openair2/LAYER2/NR_MAC_gNB/mac_rrc_ul_direct.c +++ b/openair2/LAYER2/NR_MAC_gNB/mac_rrc_ul_direct.c @@ -109,12 +109,11 @@ static void ue_context_release_request_direct(const f1ap_ue_context_rel_req_t* r itti_send_msg_to_task(TASK_RRC_GNB, 0, msg); } -static void ue_context_release_complete_direct(const f1ap_ue_context_release_complete_t *complete) +static void ue_context_release_complete_direct(const f1ap_ue_context_rel_cplt_t *complete) { MessageDef *msg = itti_alloc_new_message(TASK_MAC_GNB, 0, F1AP_UE_CONTEXT_RELEASE_COMPLETE); msg->ittiMsgHeader.originInstance = -1; // means monolithic - f1ap_ue_context_release_complete_t *f1ap_msg = &F1AP_UE_CONTEXT_RELEASE_COMPLETE(msg); - *f1ap_msg = *complete; + F1AP_UE_CONTEXT_RELEASE_COMPLETE(msg) = cp_ue_context_rel_cplt(complete); 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 29990cf3a9..19bf8039b6 100644 --- a/openair2/LAYER2/NR_MAC_gNB/mac_rrc_ul_f1ap.c +++ b/openair2/LAYER2/NR_MAC_gNB/mac_rrc_ul_f1ap.c @@ -132,13 +132,12 @@ static void ue_context_release_request_f1ap(const f1ap_ue_context_rel_req_t* req itti_send_msg_to_task(TASK_DU_F1, 0, msg); } -static void ue_context_release_complete_f1ap(const f1ap_ue_context_release_complete_t *complete) +static void ue_context_release_complete_f1ap(const f1ap_ue_context_rel_cplt_t *complete) { newGtpuDeleteAllTunnels(0, complete->gNB_DU_ue_id); MessageDef *msg = itti_alloc_new_message(TASK_MAC_GNB, 0, F1AP_UE_CONTEXT_RELEASE_COMPLETE); - f1ap_ue_context_release_complete_t *f1ap_msg = &F1AP_UE_CONTEXT_RELEASE_COMPLETE(msg); - *f1ap_msg = *complete; + F1AP_UE_CONTEXT_RELEASE_COMPLETE(msg) = cp_ue_context_rel_cplt(complete); itti_send_msg_to_task(TASK_DU_F1, 0, msg); } diff --git a/openair2/RRC/NR/rrc_gNB.c b/openair2/RRC/NR/rrc_gNB.c index 07f7eec659..9630493d15 100644 --- a/openair2/RRC/NR/rrc_gNB.c +++ b/openair2/RRC/NR/rrc_gNB.c @@ -2207,7 +2207,7 @@ void rrc_remove_ue(gNB_RRC_INST *rrc, rrc_gNB_ue_context_t *ue_context_p) static void rrc_CU_process_ue_context_release_complete(MessageDef *msg_p) { const int instance = 0; - f1ap_ue_context_release_complete_t *complete = &F1AP_UE_CONTEXT_RELEASE_COMPLETE(msg_p); + f1ap_ue_context_rel_cplt_t *complete = &F1AP_UE_CONTEXT_RELEASE_COMPLETE(msg_p); gNB_RRC_INST *rrc = RC.nrrrc[instance]; rrc_gNB_ue_context_t *ue_context_p = rrc_gNB_get_ue_context(rrc, complete->gNB_CU_ue_id); if (!ue_context_p) { @@ -2779,6 +2779,7 @@ void *rrc_gnb_task(void *args_p) { case F1AP_UE_CONTEXT_RELEASE_COMPLETE: rrc_CU_process_ue_context_release_complete(msg_p); + free_ue_context_rel_cplt(&F1AP_UE_CONTEXT_RELEASE_COMPLETE(msg_p)); break; case F1AP_LOST_CONNECTION: From 1a2aa1266c3d4c9de8191ba11e614d1aa72b26fe Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Thu, 19 Jun 2025 19:07:54 +0200 Subject: [PATCH 22/36] Remove more unused types --- openair2/COMMON/f1ap_messages_types.h | 42 --------------------------- 1 file changed, 42 deletions(-) diff --git a/openair2/COMMON/f1ap_messages_types.h b/openair2/COMMON/f1ap_messages_types.h index 12f41a81f9..89826e7ff5 100644 --- a/openair2/COMMON/f1ap_messages_types.h +++ b/openair2/COMMON/f1ap_messages_types.h @@ -363,7 +363,6 @@ typedef struct f1ap_ul_rrc_message_s { typedef struct f1ap_up_tnl_s { in_addr_t tl_address; // currently only IPv4 supported uint32_t teid; - uint16_t port; } f1ap_up_tnl_t; typedef enum preemption_capability_e { @@ -376,47 +375,6 @@ typedef enum preemption_vulnerability_e { PREEMPTABLE, } preemption_vulnerability_t; -typedef struct f1ap_qos_characteristics_s { - union { - struct { - long fiveqi; - long qos_priority_level; - } non_dynamic; - struct { - long fiveqi; // -1 -> optional - long qos_priority_level; - long packet_delay_budget; - struct { - long per_scalar; - long per_exponent; - } packet_error_rate; - } dynamic; - }; - fiveQI_t qos_type; -} f1ap_qos_characteristics_t; - -typedef struct f1ap_ngran_allocation_retention_priority_s { - uint16_t priority_level; - preemption_capability_t preemption_capability; - preemption_vulnerability_t preemption_vulnerability; -} f1ap_ngran_allocation_retention_priority_t; - -typedef struct f1ap_qos_flow_level_qos_parameters_s { - f1ap_qos_characteristics_t qos_characteristics; - f1ap_ngran_allocation_retention_priority_t alloc_reten_priority; -} f1ap_qos_flow_level_qos_parameters_t; - -typedef struct f1ap_flows_mapped_to_drb_s { - long qfi; // qos flow identifier - f1ap_qos_flow_level_qos_parameters_t qos_params; -} f1ap_flows_mapped_to_drb_t; - -typedef struct f1ap_drb_information_s { - f1ap_qos_flow_level_qos_parameters_t drb_qos; - f1ap_flows_mapped_to_drb_t *flows_mapped_to_drb; - 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_cu_to_du_rrc_info_s { From 332b2644e445eaaa59787e690a6207fd84019775 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Fri, 20 Jun 2025 08:13:50 +0200 Subject: [PATCH 23/36] Fix memory leak in cg_config_info_from_ue_cap_file() Indirect leak of 40 byte(s) in 1 object(s) allocated from: #0 0x7f7b2b4e6883 in calloc (/lib64/libasan.so.8+0xe6883) (BuildId: 7f1aa7e2e600e8c9d54ce6e3d36f3d31bfe7949a) #1 0x00000083e6e6 in calloc_or_fail /home/richie/w/f1-refactor-ue-context/common/utils/utils.h:74 #2 0x00000083e6e6 in cg_config_info_from_ue_cap_file /home/richie/w/f1-refactor-ue-context/openair2/RRC/NR/rrc_gNB_nsa.c:82 #3 0x00000083e6e6 in rrc_add_nsa_user /home/richie/w/f1-refactor-ue-context/openair2/RRC/NR/rrc_gNB_nsa.c:145 #4 0x000000886bcb in rrc_gNB_process_f1_setup_req /home/richie/w/f1-refactor-ue-context/openair2/RRC/NR/rrc_gNB_du.c:444 #5 0x000000833902 in rrc_gnb_task /home/richie/w/f1-refactor-ue-context/openair2/RRC/NR/rrc_gNB.c:2766 #6 0x7f7b2b428ee5 in asan_thread_start(void*) (/lib64/libasan.so.8+0x28ee5) (BuildId: 7f1aa7e2e600e8c9d54ce6e3d36f3d31bfe7949a) Indirect leak of 128 byte(s) in 1 object(s) allocated from: #0 0x7f7b2b4e6883 in calloc (/lib64/libasan.so.8+0xe6883) (BuildId: 7f1aa7e2e600e8c9d54ce6e3d36f3d31bfe7949a) #1 0x00000083e745 in calloc_or_fail /home/richie/w/f1-refactor-ue-context/common/utils/utils.h:74 #2 0x00000083e745 in cg_config_info_from_ue_cap_file /home/richie/w/f1-refactor-ue-context/openair2/RRC/NR/rrc_gNB_nsa.c:84 #3 0x00000083e745 in rrc_add_nsa_user /home/richie/w/f1-refactor-ue-context/openair2/RRC/NR/rrc_gNB_nsa.c:145 #4 0x000000886bcb in rrc_gNB_process_f1_setup_req /home/richie/w/f1-refactor-ue-context/openair2/RRC/NR/rrc_gNB_du.c:444 #5 0x000000833902 in rrc_gnb_task /home/richie/w/f1-refactor-ue-context/openair2/RRC/NR/rrc_gNB.c:2766 #6 0x7f7b2b428ee5 in asan_thread_start(void*) (/lib64/libasan.so.8+0x28ee5) (BuildId: 7f1aa7e2e600e8c9d54ce6e3d36f3d31bfe7949a) Direct leak of 64 byte(s) in 1 object(s) allocated from: #0 0x7f7b2b4e6883 in calloc (/lib64/libasan.so.8+0xe6883) (BuildId: 7f1aa7e2e600e8c9d54ce6e3d36f3d31bfe7949a) #1 0x00000083e6a5 in calloc_or_fail /home/richie/w/f1-refactor-ue-context/common/utils/utils.h:74 #2 0x00000083e6a5 in cg_config_info_from_ue_cap_file /home/richie/w/f1-refactor-ue-context/openair2/RRC/NR/rrc_gNB_nsa.c:80 #3 0x00000083e6a5 in rrc_add_nsa_user /home/richie/w/f1-refactor-ue-context/openair2/RRC/NR/rrc_gNB_nsa.c:145 #4 0x000000886bcb in rrc_gNB_process_f1_setup_req /home/richie/w/f1-refactor-ue-context/openair2/RRC/NR/rrc_gNB_du.c:444 #5 0x000000833902 in rrc_gnb_task /home/richie/w/f1-refactor-ue-context/openair2/RRC/NR/rrc_gNB.c:2766 #6 0x7f7b2b428ee5 in asan_thread_start(void*) (/lib64/libasan.so.8+0x28ee5) (BuildId: 7f1aa7e2e600e8c9d54ce6e3d36f3d31bfe7949a) --- openair2/RRC/NR/rrc_gNB_nsa.c | 1 + 1 file changed, 1 insertion(+) diff --git a/openair2/RRC/NR/rrc_gNB_nsa.c b/openair2/RRC/NR/rrc_gNB_nsa.c index c2dfb3e20a..d722236ce8 100644 --- a/openair2/RRC/NR/rrc_gNB_nsa.c +++ b/openair2/RRC/NR/rrc_gNB_nsa.c @@ -112,6 +112,7 @@ static int cg_config_info_from_ue_cap_file(uint32_t maxlen, uint8_t buf[maxlen]) //xer_fprint(stdout, &asn_DEF_NR_CG_ConfigInfo, cgci); asn_enc_rval_t rval = uper_encode_to_buffer(&asn_DEF_NR_CG_ConfigInfo, NULL, cgci, buf, maxlen); DevAssert(rval.encoded > 0); + ASN_STRUCT_FREE(asn_DEF_NR_CG_ConfigInfo, cgci); return (rval.encoded + 7) >> 3; } From c6954d3f9d46dc8428e0c3ff3e29e9790d61bb31 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Thu, 19 Jun 2025 17:45:14 +0200 Subject: [PATCH 24/36] Free UE capabilities memory when removing UE context Direct leak of 32 byte(s) in 1 object(s) allocated from: #0 0x7f672d6e5e2b in realloc.part.0 (/lib64/libasan.so.8+0xe5e2b) (BuildId: 7f1aa7e2e600e8c9d54ce6e3d36f3d31bfe7949a) #1 0x000000fbb4ed in encode_dyn_cb /home/richie/w/f1-refactor-ue-context/build/openair2/RRC/LTE/MESSAGES/per_encoder.c:23 #2 0x000000fbbeeb in _uper_encode_flush_outp /home/richie/w/f1-refactor-ue-context/build/openair2/RRC/LTE/MESSAGES/uper_encoder.c:126 #3 0x000000fbbeeb in uper_encode /home/richie/w/f1-refactor-ue-context/build/openair2/RRC/LTE/MESSAGES/uper_encoder.c:36 #4 0x000000fbc27a in uper_encode_to_new_buffer /home/richie/w/f1-refactor-ue-context/build/openair2/RRC/LTE/MESSAGES/uper_encoder.c:85 #5 0x00000081037c in handle_ueCapabilityInformation /home/richie/w/f1-refactor-ue-context/openair2/RRC/NR/rrc_gNB.c:1549 #6 0x000000813ced in rrc_gNB_decode_dcch /home/richie/w/f1-refactor-ue-context/openair2/RRC/NR/rrc_gNB.c:1902 #7 0x0000008334f2 in rrc_gnb_task /home/richie/w/f1-refactor-ue-context/openair2/RRC/NR/rrc_gNB.c:2741 #8 0x7f672d628ee5 in asan_thread_start(void*) (/lib64/libasan.so.8+0x28ee5) (BuildId: 7f1aa7e2e600e8c9d54ce6e3d36f3d31bfe7949a) --- openair2/RRC/NR/rrc_gNB.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/openair2/RRC/NR/rrc_gNB.c b/openair2/RRC/NR/rrc_gNB.c index 9630493d15..26193b7381 100644 --- a/openair2/RRC/NR/rrc_gNB.c +++ b/openair2/RRC/NR/rrc_gNB.c @@ -1547,7 +1547,7 @@ static void handle_ueCapabilityInformation(gNB_RRC_INST *rrc, gNB_RRC_UE_t *UE, ue_cap_info->criticalExtensions.choice.ueCapabilityInformation->ue_CapabilityRAT_ContainerList; /* Encode UE-CapabilityRAT-ContainerList for sending to the DU */ - free(UE->ue_cap_buffer.buf); + FREE_AND_ZERO_BYTE_ARRAY(UE->ue_cap_buffer); UE->ue_cap_buffer.len = uper_encode_to_new_buffer(&asn_DEF_NR_UE_CapabilityRAT_ContainerList, NULL, ue_CapabilityRAT_ContainerList, @@ -2189,6 +2189,7 @@ static void rrc_delete_ue_data(gNB_RRC_UE_t *UE) ASN_STRUCT_FREE(asn_DEF_NR_UE_NR_Capability, UE->UE_Capability_nr); ASN_STRUCT_FREE(asn_DEF_NR_CellGroupConfig, UE->masterCellGroup); ASN_STRUCT_FREE(asn_DEF_NR_MeasResults, UE->measResults); + FREE_AND_ZERO_BYTE_ARRAY(UE->ue_cap_buffer); free_MeasConfig(UE->measConfig); } From 5b9d682fdeeb86f51fdaa5832446ee763c568152 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Thu, 19 Jun 2025 17:45:28 +0200 Subject: [PATCH 25/36] Free F1 Setup Response after sending --- openair2/RRC/NR/rrc_gNB_du.c | 1 + 1 file changed, 1 insertion(+) diff --git a/openair2/RRC/NR/rrc_gNB_du.c b/openair2/RRC/NR/rrc_gNB_du.c index a650a03604..1b4e58489d 100644 --- a/openair2/RRC/NR/rrc_gNB_du.c +++ b/openair2/RRC/NR/rrc_gNB_du.c @@ -437,6 +437,7 @@ void rrc_gNB_process_f1_setup_req(f1ap_setup_req_t *req, sctp_assoc_t assoc_id) if (rrc->node_name != NULL) resp.gNB_CU_name = strdup(rrc->node_name); rrc->mac_rrc.f1_setup_response(assoc_id, &resp); + free_f1ap_setup_response(&resp); /* we need to setup one default UE for phy-test and do-ra modes in the MAC */ if (get_softmodem_params()->phy_test > 0 || get_softmodem_params()->do_ra > 0) From 7c65929ece779d69cb8d6636291d414d8ea6f63b Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Thu, 19 Jun 2025 17:45:49 +0200 Subject: [PATCH 26/36] Free cell F1 Setup Request after DU disconnection Direct leak of 72 byte(s) in 1 object(s) allocated from: #0 0x7fea71ee6883 in calloc (/lib64/libasan.so.8+0xe6883) (BuildId: 7f1aa7e2e600e8c9d54ce6e3d36f3d31bfe7949a) #1 0x000000886124 in rrc_gNB_process_f1_setup_req /home/richie/w/f1-refactor-ue-context/openair2/RRC/NR/rrc_gNB_du.c:384 #2 0x000000833902 in rrc_gnb_task /home/richie/w/f1-refactor-ue-context/openair2/RRC/NR/rrc_gNB.c:2765 #3 0x7fea71e28ee5 in asan_thread_start(void*) (/lib64/libasan.so.8+0x28ee5) (BuildId: 7f1aa7e2e600e8c9d54ce6e3d36f3d31bfe7949a) Indirect leak of 16592 byte(s) in 1 object(s) allocated from: #0 0x7fea71ee6883 in calloc (/lib64/libasan.so.8+0xe6883) (BuildId: 7f1aa7e2e600e8c9d54ce6e3d36f3d31bfe7949a) #1 0x000000886171 in rrc_gNB_process_f1_setup_req /home/richie/w/f1-refactor-ue-context/openair2/RRC/NR/rrc_gNB_du.c:391 #2 0x000000833902 in rrc_gnb_task /home/richie/w/f1-refactor-ue-context/openair2/RRC/NR/rrc_gNB.c:2765 #3 0x7fea71e28ee5 in asan_thread_start(void*) (/lib64/libasan.so.8+0x28ee5) (BuildId: 7f1aa7e2e600e8c9d54ce6e3d36f3d31bfe7949a) Indirect leak of 102 byte(s) in 1 object(s) allocated from: #0 0x7fea71ee6883 in calloc (/lib64/libasan.so.8+0xe6883) (BuildId: 7f1aa7e2e600e8c9d54ce6e3d36f3d31bfe7949a) #1 0x000000adb79a in calloc_or_fail /home/richie/w/f1-refactor-ue-context/common/utils/utils.h:74 #2 0x000000adb79a in copy_f1ap_gnb_du_system_info /home/richie/w/f1-refactor-ue-context/openair2/F1AP/lib/f1ap_interface_management.c:933 #3 0x000000ae60c9 in cp_f1ap_setup_request /home/richie/w/f1-refactor-ue-context/openair2/F1AP/lib/f1ap_interface_management.c:959 #4 0x0000008861c0 in rrc_gNB_process_f1_setup_req /home/richie/w/f1-refactor-ue-context/openair2/RRC/NR/rrc_gNB_du.c:394 #5 0x000000833902 in rrc_gnb_task /home/richie/w/f1-refactor-ue-context/openair2/RRC/NR/rrc_gNB.c:2765 #6 0x7fea71e28ee5 in asan_thread_start(void*) (/lib64/libasan.so.8+0x28ee5) (BuildId: 7f1aa7e2e600e8c9d54ce6e3d36f3d31bfe7949a) Indirect leak of 32 byte(s) in 1 object(s) allocated from: #0 0x7fea71ee6883 in calloc (/lib64/libasan.so.8+0xe6883) (BuildId: 7f1aa7e2e600e8c9d54ce6e3d36f3d31bfe7949a) #1 0x000000adb667 in calloc_or_fail /home/richie/w/f1-refactor-ue-context/common/utils/utils.h:74 #2 0x000000adb667 in copy_f1ap_gnb_du_system_info /home/richie/w/f1-refactor-ue-context/openair2/F1AP/lib/f1ap_interface_management.c:924 #3 0x000000ae60c9 in cp_f1ap_setup_request /home/richie/w/f1-refactor-ue-context/openair2/F1AP/lib/f1ap_interface_management.c:959 #4 0x0000008861c0 in rrc_gNB_process_f1_setup_req /home/richie/w/f1-refactor-ue-context/openair2/RRC/NR/rrc_gNB_du.c:394 #5 0x000000833902 in rrc_gnb_task /home/richie/w/f1-refactor-ue-context/openair2/RRC/NR/rrc_gNB.c:2765 #6 0x7fea71e28ee5 in asan_thread_start(void*) (/lib64/libasan.so.8+0x28ee5) (BuildId: 7f1aa7e2e600e8c9d54ce6e3d36f3d31bfe7949a) Indirect leak of 15 byte(s) in 1 object(s) allocated from: #0 0x7fea71ee0c80 in strdup (/lib64/libasan.so.8+0xe0c80) (BuildId: 7f1aa7e2e600e8c9d54ce6e3d36f3d31bfe7949a) #1 0x000000ae5f57 in cp_f1ap_setup_request /home/richie/w/f1-refactor-ue-context/openair2/F1AP/lib/f1ap_interface_management.c:950 #2 0x0000008861c0 in rrc_gNB_process_f1_setup_req /home/richie/w/f1-refactor-ue-context/openair2/RRC/NR/rrc_gNB_du.c:394 #3 0x000000833902 in rrc_gnb_task /home/richie/w/f1-refactor-ue-context/openair2/RRC/NR/rrc_gNB.c:2765 #4 0x7fea71e28ee5 in asan_thread_start(void*) (/lib64/libasan.so.8+0x28ee5) (BuildId: 7f1aa7e2e600e8c9d54ce6e3d36f3d31bfe7949a) Indirect leak of 7 byte(s) in 1 object(s) allocated from: #0 0x7fea71ee6883 in calloc (/lib64/libasan.so.8+0xe6883) (BuildId: 7f1aa7e2e600e8c9d54ce6e3d36f3d31bfe7949a) #1 0x000000ae5c28 in calloc_or_fail /home/richie/w/f1-refactor-ue-context/common/utils/utils.h:74 #2 0x000000ae5c28 in copy_f1ap_served_cell_info /home/richie/w/f1-refactor-ue-context/openair2/F1AP/lib/f1ap_interface_management.c:913 #3 0x000000ae609a in cp_f1ap_setup_request /home/richie/w/f1-refactor-ue-context/openair2/F1AP/lib/f1ap_interface_management.c:957 #4 0x0000008861c0 in rrc_gNB_process_f1_setup_req /home/richie/w/f1-refactor-ue-context/openair2/RRC/NR/rrc_gNB_du.c:394 #5 0x000000833902 in rrc_gnb_task /home/richie/w/f1-refactor-ue-context/openair2/RRC/NR/rrc_gNB.c:2765 #6 0x7fea71e28ee5 in asan_thread_start(void*) (/lib64/libasan.so.8+0x28ee5) (BuildId: 7f1aa7e2e600e8c9d54ce6e3d36f3d31bfe7949a) Indirect leak of 4 byte(s) in 1 object(s) allocated from: #0 0x7fea71ee6f0b in malloc (/lib64/libasan.so.8+0xe6f0b) (BuildId: 7f1aa7e2e600e8c9d54ce6e3d36f3d31bfe7949a) #1 0x000000ae5ae7 in malloc_or_fail /home/richie/w/f1-refactor-ue-context/common/utils/utils.h:86 #2 0x000000ae5ae7 in copy_f1ap_served_cell_info /home/richie/w/f1-refactor-ue-context/openair2/F1AP/lib/f1ap_interface_management.c:907 #3 0x000000ae609a in cp_f1ap_setup_request /home/richie/w/f1-refactor-ue-context/openair2/F1AP/lib/f1ap_interface_management.c:957 #4 0x0000008861c0 in rrc_gNB_process_f1_setup_req /home/richie/w/f1-refactor-ue-context/openair2/RRC/NR/rrc_gNB_du.c:394 #5 0x000000833902 in rrc_gnb_task /home/richie/w/f1-refactor-ue-context/openair2/RRC/NR/rrc_gNB.c:2765 #6 0x7fea71e28ee5 in asan_thread_start(void*) (/lib64/libasan.so.8+0x28ee5) (BuildId: 7f1aa7e2e600e8c9d54ce6e3d36f3d31bfe7949a) Indirect leak of 3 byte(s) in 1 object(s) allocated from: #0 0x7fea71ee6883 in calloc (/lib64/libasan.so.8+0xe6883) (BuildId: 7f1aa7e2e600e8c9d54ce6e3d36f3d31bfe7949a) #1 0x000000adb713 in calloc_or_fail /home/richie/w/f1-refactor-ue-context/common/utils/utils.h:74 #2 0x000000adb713 in copy_f1ap_gnb_du_system_info /home/richie/w/f1-refactor-ue-context/openair2/F1AP/lib/f1ap_interface_management.c:927 #3 0x000000ae60c9 in cp_f1ap_setup_request /home/richie/w/f1-refactor-ue-context/openair2/F1AP/lib/f1ap_interface_management.c:959 #4 0x0000008861c0 in rrc_gNB_process_f1_setup_req /home/richie/w/f1-refactor-ue-context/openair2/RRC/NR/rrc_gNB_du.c:394 #5 0x000000833902 in rrc_gnb_task /home/richie/w/f1-refactor-ue-context/openair2/RRC/NR/rrc_gNB.c:2765 #6 0x7fea71e28ee5 in asan_thread_start(void*) (/lib64/libasan.so.8+0x28ee5) (BuildId: 7f1aa7e2e600e8c9d54ce6e3d36f3d31bfe7949a) --- openair2/RRC/NR/rrc_gNB_du.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/openair2/RRC/NR/rrc_gNB_du.c b/openair2/RRC/NR/rrc_gNB_du.c index 1b4e58489d..868a7fb64a 100644 --- a/openair2/RRC/NR/rrc_gNB_du.c +++ b/openair2/RRC/NR/rrc_gNB_du.c @@ -601,9 +601,12 @@ void rrc_CU_process_f1_lost_connection(gNB_RRC_INST *rrc, f1ap_lost_connection_t ASN_STRUCT_FREE(asn_DEF_NR_MIB, du->mib); ASN_STRUCT_FREE(asn_DEF_NR_SIB1, du->sib1); ASN_STRUCT_FREE(asn_DEF_NR_MeasurementTimingConfiguration, du->mtc); - /* TODO: free setup request */ + if (du->setup_req) + free_f1ap_setup_request(du->setup_req); + free(du->setup_req); nr_rrc_du_container_t *removed = RB_REMOVE(rrc_du_tree, &rrc->dus, du); DevAssert(removed != NULL); + free(du); rrc->num_dus--; int num = invalidate_du_connections(rrc, assoc_id); From ec3ce8a3870c85f84868f10781028715b5890bbc Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Thu, 19 Jun 2025 18:20:28 +0200 Subject: [PATCH 27/36] Free at F1 Setup Response at MAC The F1 Setup Response is stored for possible look up of information. Free it at the end to avoid memory leaks. --- openair2/LAYER2/NR_MAC_gNB/main.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/openair2/LAYER2/NR_MAC_gNB/main.c b/openair2/LAYER2/NR_MAC_gNB/main.c index 0acc6fe0d2..fb932c83a3 100644 --- a/openair2/LAYER2/NR_MAC_gNB/main.c +++ b/openair2/LAYER2/NR_MAC_gNB/main.c @@ -63,6 +63,7 @@ #include "nr_pdcp/nr_pdcp_oai_api.h" #include "nr_rlc/nr_rlc_oai_api.h" #include "openair2/F1AP/f1ap_ids.h" +#include "openair2/F1AP/lib/f1ap_interface_management.h" #include "seq_arr.h" #include "system.h" #include "time_meas.h" @@ -342,6 +343,9 @@ void mac_top_destroy_gNB(gNB_MAC_INST *mac) for (int i = 0; i < sizeofArray(UE_info->access_ue_list); ++i) if (UE_info->access_ue_list[i]) delete_nr_ue_data(UE_info->access_ue_list[i], cc, &UE_info->uid_allocator); + if (mac->f1_config.setup_resp) + free_f1ap_setup_response(mac->f1_config.setup_resp); + free(mac->f1_config.setup_resp); } void nr_mac_send_f1_setup_req(void) From d4ad31bd1de6219fcbd8da4e8d6ac97c9b72cb00 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Thu, 19 Jun 2025 18:20:40 +0200 Subject: [PATCH 28/36] Correctly free E1AP context mod request Direct leak of 48 byte(s) in 1 object(s) allocated from: #0 0x7fea71ee6f0b in malloc (/lib64/libasan.so.8+0xe6f0b) (BuildId: 7f1aa7e2e600e8c9d54ce6e3d36f3d31bfe7949a) #1 0x0000007f29c0 in malloc_or_fail /home/richie/w/f1-refactor-ue-context/common/utils/utils.h:86 #2 0x0000007f29c0 in cuup_notify_reestablishment /home/richie/w/f1-refactor-ue-context/openair2/RRC/NR/rrc_gNB.c:872 #3 0x000000808002 in rrc_CU_process_ue_context_setup_response /home/richie/w/f1-refactor-ue-context/openair2/RRC/NR/rrc_gNB.c:2126 #4 0x0000008330d8 in rrc_gnb_task /home/richie/w/f1-refactor-ue-context/openair2/RRC/NR/rrc_gNB.c:2770 #5 0x7fea71e28ee5 in asan_thread_start(void*) (/lib64/libasan.so.8+0x28ee5) (BuildId: 7f1aa7e2e600e8c9d54ce6e3d36f3d31bfe7949a) --- openair2/RRC/NR/rrc_gNB.c | 1 + 1 file changed, 1 insertion(+) diff --git a/openair2/RRC/NR/rrc_gNB.c b/openair2/RRC/NR/rrc_gNB.c index 26193b7381..8c04754df7 100644 --- a/openair2/RRC/NR/rrc_gNB.c +++ b/openair2/RRC/NR/rrc_gNB.c @@ -892,6 +892,7 @@ static void cuup_notify_reestablishment(gNB_RRC_INST *rrc, gNB_RRC_UE_t *ue_p) /* Send E1 Bearer Context Modification Request (3GPP TS 38.463) */ sctp_assoc_t assoc_id = get_existing_cuup_for_ue(rrc, ue_p); rrc->cucp_cuup.bearer_context_mod(assoc_id, &req); + free_e1ap_context_mod_request(&req); } /** From c54cbdae54ea6f0ba484aa35d2c129be1544664e Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Fri, 20 Jun 2025 08:19:08 +0200 Subject: [PATCH 29/36] Fix memory leak in rrc_add_nsa_user_resp() Direct leak of 72 byte(s) in 1 object(s) allocated from: #0 0x7f83c10e6883 in calloc (/lib64/libasan.so.8+0xe6883) (BuildId: 7f1aa7e2e600e8c9d54ce6e3d36f3d31bfe7949a) #1 0x000000844ec5 in rrc_add_nsa_user_resp /home/richie/w/f1-refactor-ue-context/openair2/RRC/NR/rrc_gNB_nsa.c:413 #2 0x0000008079d1 in rrc_CU_process_ue_context_setup_response /home/richie/w/f1-refactor-ue-context/openair2/RRC/NR/rrc_gNB.c:2111 #3 0x0000008330a8 in rrc_gnb_task /home/richie/w/f1-refactor-ue-context/openair2/RRC/NR/rrc_gNB.c:2769 #4 0x7f83c1028ee5 in asan_thread_start(void*) (/lib64/libasan.so.8+0x28ee5) (BuildId: 7f1aa7e2e600e8c9d54ce6e3d36f3d31bfe7949a) Indirect leak of 40 byte(s) in 1 object(s) allocated from: #0 0x7f83c10e6883 in calloc (/lib64/libasan.so.8+0xe6883) (BuildId: 7f1aa7e2e600e8c9d54ce6e3d36f3d31bfe7949a) #1 0x000000844f9d in get_default_reconfig /home/richie/w/f1-refactor-ue-context/openair2/RRC/NR/rrc_gNB_nsa.c:343 #2 0x000000844f9d in rrc_add_nsa_user_resp /home/richie/w/f1-refactor-ue-context/openair2/RRC/NR/rrc_gNB_nsa.c:416 #3 0x0000008079d1 in rrc_CU_process_ue_context_setup_response /home/richie/w/f1-refactor-ue-context/openair2/RRC/NR/rrc_gNB.c:2111 #4 0x0000008330a8 in rrc_gnb_task /home/richie/w/f1-refactor-ue-context/openair2/RRC/NR/rrc_gNB.c:2769 #5 0x7f83c1028ee5 in asan_thread_start(void*) (/lib64/libasan.so.8+0x28ee5) (BuildId: 7f1aa7e2e600e8c9d54ce6e3d36f3d31bfe7949a) Indirect leak of 64 byte(s) in 1 object(s) allocated from: #0 0x7f83c10e6883 in calloc (/lib64/libasan.so.8+0xe6883) (BuildId: 7f1aa7e2e600e8c9d54ce6e3d36f3d31bfe7949a) #1 0x000000844f28 in get_default_reconfig /home/richie/w/f1-refactor-ue-context/openair2/RRC/NR/rrc_gNB_nsa.c:335 #2 0x000000844f28 in rrc_add_nsa_user_resp /home/richie/w/f1-refactor-ue-context/openair2/RRC/NR/rrc_gNB_nsa.c:416 #3 0x0000008079d1 in rrc_CU_process_ue_context_setup_response /home/richie/w/f1-refactor-ue-context/openair2/RRC/NR/rrc_gNB.c:2111 #4 0x0000008330a8 in rrc_gnb_task /home/richie/w/f1-refactor-ue-context/openair2/RRC/NR/rrc_gNB.c:2769 #5 0x7f83c1028ee5 in asan_thread_start(void*) (/lib64/libasan.so.8+0x28ee5) (BuildId: 7f1aa7e2e600e8c9d54ce6e3d36f3d31bfe7949a) Indirect leak of 327 byte(s) in 1 object(s) allocated from: #0 0x7f83c10e6f0b in malloc (/lib64/libasan.so.8+0xe6f0b) (BuildId: 7f1aa7e2e600e8c9d54ce6e3d36f3d31bfe7949a) #1 0x000000fb51ec in OCTET_STRING_fromBuf /home/richie/w/f1-refactor-ue-context/build/openair2/RRC/LTE/MESSAGES/OCTET_STRING.c:184 #2 0x000000844fd3 in get_default_reconfig /home/richie/w/f1-refactor-ue-context/openair2/RRC/NR/rrc_gNB_nsa.c:344 #3 0x000000844fd3 in rrc_add_nsa_user_resp /home/richie/w/f1-refactor-ue-context/openair2/RRC/NR/rrc_gNB_nsa.c:416 #4 0x0000008079d1 in rrc_CU_process_ue_context_setup_response /home/richie/w/f1-refactor-ue-context/openair2/RRC/NR/rrc_gNB.c:2111 #5 0x0000008330a8 in rrc_gnb_task /home/richie/w/f1-refactor-ue-context/openair2/RRC/NR/rrc_gNB.c:2769 #6 0x7f83c1028ee5 in asan_thread_start(void*) (/lib64/libasan.so.8+0x28ee5) (BuildId: 7f1aa7e2e600e8c9d54ce6e3d36f3d31bfe7949a) --- openair2/RRC/NR/rrc_gNB_nsa.c | 1 + 1 file changed, 1 insertion(+) diff --git a/openair2/RRC/NR/rrc_gNB_nsa.c b/openair2/RRC/NR/rrc_gNB_nsa.c index d722236ce8..cd7b5fb8d4 100644 --- a/openair2/RRC/NR/rrc_gNB_nsa.c +++ b/openair2/RRC/NR/rrc_gNB_nsa.c @@ -416,6 +416,7 @@ void rrc_add_nsa_user_resp(gNB_RRC_INST *rrc, gNB_RRC_UE_t *UE, const f1ap_ue_co reconfig->criticalExtensions.choice.rrcReconfiguration = get_default_reconfig(UE->masterCellGroup); NR_CG_Config_t *CG_Config = generate_CG_Config(reconfig, UE->rb_config); + ASN_STRUCT_FREE(asn_DEF_NR_RRCReconfiguration, reconfig); if (get_softmodem_params()->phy_test > 0 || get_softmodem_params()->do_ra > 0) { /* we are done, no X2 answer necessary */ From c3bb7dfd0484a1375830b083669f487464c031a4 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Fri, 20 Jun 2025 08:21:19 +0200 Subject: [PATCH 30/36] Fix memory leak in ue_context_setup_request() Direct leak of 64 byte(s) in 1 object(s) allocated from: #0 0x7fc885ae6883 in calloc (/lib64/libasan.so.8+0xe6883) (BuildId: 7f1aa7e2e600e8c9d54ce6e3d36f3d31bfe7949a) #1 0x000000fd0ac9 in SEQUENCE_decode_uper /home/richie/w/f1-refactor-ue-context/build/openair2/RRC/LTE/MESSAGES/constr_SEQUENCE_uper.c:37 #2 0x000000fbba1c in uper_decode /home/richie/w/f1-refactor-ue-context/build/openair2/RRC/LTE/MESSAGES/uper_decoder.c:83 #3 0x000000fbbbf9 in uper_decode_complete /home/richie/w/f1-refactor-ue-context/build/openair2/RRC/LTE/MESSAGES/uper_decoder.c:16 #4 0x0000009d65ce in get_cg_config_info /home/richie/w/f1-refactor-ue-context/openair2/LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.c:485 #5 0x0000009d65ce in ue_context_setup_request /home/richie/w/f1-refactor-ue-context/openair2/LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.c:619 #6 0x00000083fea2 in rrc_add_nsa_user /home/richie/w/f1-refactor-ue-context/openair2/RRC/NR/rrc_gNB_nsa.c:330 #7 0x000000886c8b in rrc_gNB_process_f1_setup_req /home/richie/w/f1-refactor-ue-context/openair2/RRC/NR/rrc_gNB_du.c:444 #8 0x000000833902 in rrc_gnb_task /home/richie/w/f1-refactor-ue-context/openair2/RRC/NR/rrc_gNB.c:2766 #9 0x7fc885a28ee5 in asan_thread_start(void*) (/lib64/libasan.so.8+0x28ee5) (BuildId: 7f1aa7e2e600e8c9d54ce6e3d36f3d31bfe7949a) Indirect leak of 128 byte(s) in 1 object(s) allocated from: #0 0x7fc885ae6883 in calloc (/lib64/libasan.so.8+0xe6883) (BuildId: 7f1aa7e2e600e8c9d54ce6e3d36f3d31bfe7949a) #1 0x000000fd0ac9 in SEQUENCE_decode_uper /home/richie/w/f1-refactor-ue-context/build/openair2/RRC/LTE/MESSAGES/constr_SEQUENCE_uper.c:37 #2 0x000000fca638 in CHOICE_decode_uper /home/richie/w/f1-refactor-ue-context/build/openair2/RRC/LTE/MESSAGES/constr_CHOICE_uper.c:84 #3 0x000000fca638 in CHOICE_decode_uper /home/richie/w/f1-refactor-ue-context/build/openair2/RRC/LTE/MESSAGES/constr_CHOICE_uper.c:84 #4 0x000000fd058e in SEQUENCE_decode_uper /home/richie/w/f1-refactor-ue-context/build/openair2/RRC/LTE/MESSAGES/constr_SEQUENCE_uper.c:118 #5 0x000000fbba1c in uper_decode /home/richie/w/f1-refactor-ue-context/build/openair2/RRC/LTE/MESSAGES/uper_decoder.c:83 #6 0x000000fbbbf9 in uper_decode_complete /home/richie/w/f1-refactor-ue-context/build/openair2/RRC/LTE/MESSAGES/uper_decoder.c:16 #7 0x0000009d65ce in get_cg_config_info /home/richie/w/f1-refactor-ue-context/openair2/LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.c:485 #8 0x0000009d65ce in ue_context_setup_request /home/richie/w/f1-refactor-ue-context/openair2/LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.c:619 #9 0x00000083fea2 in rrc_add_nsa_user /home/richie/w/f1-refactor-ue-context/openair2/RRC/NR/rrc_gNB_nsa.c:330 #10 0x000000886c8b in rrc_gNB_process_f1_setup_req /home/richie/w/f1-refactor-ue-context/openair2/RRC/NR/rrc_gNB_du.c:444 #11 0x000000833902 in rrc_gnb_task /home/richie/w/f1-refactor-ue-context/openair2/RRC/NR/rrc_gNB.c:2766 #12 0x7fc885a28ee5 in asan_thread_start(void*) (/lib64/libasan.so.8+0x28ee5) (BuildId: 7f1aa7e2e600e8c9d54ce6e3d36f3d31bfe7949a) Indirect leak of 40 byte(s) in 1 object(s) allocated from: #0 0x7fc885ae6883 in calloc (/lib64/libasan.so.8+0xe6883) (BuildId: 7f1aa7e2e600e8c9d54ce6e3d36f3d31bfe7949a) #1 0x000000fca7d7 in CHOICE_decode_uper /home/richie/w/f1-refactor-ue-context/build/openair2/RRC/LTE/MESSAGES/constr_CHOICE_uper.c:32 #2 0x000000fca638 in CHOICE_decode_uper /home/richie/w/f1-refactor-ue-context/build/openair2/RRC/LTE/MESSAGES/constr_CHOICE_uper.c:84 #3 0x000000fd058e in SEQUENCE_decode_uper /home/richie/w/f1-refactor-ue-context/build/openair2/RRC/LTE/MESSAGES/constr_SEQUENCE_uper.c:118 #4 0x000000fbba1c in uper_decode /home/richie/w/f1-refactor-ue-context/build/openair2/RRC/LTE/MESSAGES/uper_decoder.c:83 #5 0x000000fbbbf9 in uper_decode_complete /home/richie/w/f1-refactor-ue-context/build/openair2/RRC/LTE/MESSAGES/uper_decoder.c:16 #6 0x0000009d65ce in get_cg_config_info /home/richie/w/f1-refactor-ue-context/openair2/LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.c:485 #7 0x0000009d65ce in ue_context_setup_request /home/richie/w/f1-refactor-ue-context/openair2/LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.c:619 #8 0x00000083fea2 in rrc_add_nsa_user /home/richie/w/f1-refactor-ue-context/openair2/RRC/NR/rrc_gNB_nsa.c:330 #9 0x000000886c8b in rrc_gNB_process_f1_setup_req /home/richie/w/f1-refactor-ue-context/openair2/RRC/NR/rrc_gNB_du.c:444 #10 0x000000833902 in rrc_gnb_task /home/richie/w/f1-refactor-ue-context/openair2/RRC/NR/rrc_gNB.c:2766 #11 0x7fc885a28ee5 in asan_thread_start(void*) (/lib64/libasan.so.8+0x28ee5) (BuildId: 7f1aa7e2e600e8c9d54ce6e3d36f3d31bfe7949a) --- openair2/LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.c | 1 + 1 file changed, 1 insertion(+) 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 3b5fd80639..9c6559ad10 100644 --- a/openair2/LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.c +++ b/openair2/LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.c @@ -702,6 +702,7 @@ void ue_context_setup_request(const f1ap_ue_context_setup_req_t *req) /* free the memory we allocated above */ free_ue_context_setup_resp(&resp); + ASN_STRUCT_FREE(asn_DEF_NR_CG_ConfigInfo, cg_configinfo); } void ue_context_modification_request(const f1ap_ue_context_mod_req_t *req) From f26cef9cbe18838f3db70344992cb737479c7943 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Fri, 20 Jun 2025 09:37:10 +0200 Subject: [PATCH 31/36] Add invariant check to help debug During refactoring, I had asan errors in the next line. It took me some time to figure out that a DRB ID 0 is not valid (cf. get_next_available_drb_id() and get_drb(), they enforce this). --- openair2/RRC/NR/rrc_gNB_radio_bearers.c | 1 + 1 file changed, 1 insertion(+) diff --git a/openair2/RRC/NR/rrc_gNB_radio_bearers.c b/openair2/RRC/NR/rrc_gNB_radio_bearers.c index 7bed45ee64..5112029f87 100644 --- a/openair2/RRC/NR/rrc_gNB_radio_bearers.c +++ b/openair2/RRC/NR/rrc_gNB_radio_bearers.c @@ -58,6 +58,7 @@ rrc_pdu_session_param_t *find_pduSession(gNB_RRC_UE_t *ue, int id, bool create) rrc_pdu_session_param_t *find_pduSession_from_drbId(gNB_RRC_UE_t *ue, int drb_id) { + DevAssert(drb_id > 0 && drb_id <= 32); const drb_t *drb = &ue->established_drbs[drb_id - 1]; if (drb->status == DRB_INACTIVE) { LOG_E(NR_RRC, "UE %d: DRB %d inactive\n", ue->rrc_ue_id, drb_id); From 6cf7fc2bb26a7d1ed1803c69b17cd312239a1ae4 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Fri, 20 Jun 2025 09:50:25 +0200 Subject: [PATCH 32/36] Fix memory leak in nr_rrc_f1_ho_acknowledge() Direct leak of 512 byte(s) in 1 object(s) allocated from: #0 0x7f37634e5e2b in realloc.part.0 (/lib64/libasan.so.8+0xe5e2b) (BuildId: 7f1aa7e2e600e8c9d54ce6e3d36f3d31bfe7949a) #1 0x000000fbb9ad in encode_dyn_cb /home/richie/w/f1-refactor-ue-context/build/openair2/RRC/LTE/MESSAGES/per_encoder.c:23 #2 0x000000fc279e in asn_put_few_bits /home/richie/w/f1-refactor-ue-context/build/openair2/RRC/LTE/MESSAGES/asn_bit_data.c:220 #3 0x000000fc279e in asn_put_few_bits /home/richie/w/f1-refactor-ue-context/build/openair2/RRC/LTE/MESSAGES/asn_bit_data.c:192 #4 0x000000fc2ce5 in asn_put_many_bits /home/richie/w/f1-refactor-ue-context/build/openair2/RRC/LTE/MESSAGES/asn_bit_data.c:293 #5 0x000000fb8c33 in OCTET_STRING_encode_uper /home/richie/w/f1-refactor-ue-context/build/openair2/RRC/LTE/MESSAGES/OCTET_STRING_uper.c:306 #6 0x000000fd191a in SEQUENCE_encode_uper /home/richie/w/f1-refactor-ue-context/build/openair2/RRC/LTE/MESSAGES/constr_SEQUENCE_uper.c:403 #7 0x000000fd191a in SEQUENCE_encode_uper /home/richie/w/f1-refactor-ue-context/build/openair2/RRC/LTE/MESSAGES/constr_SEQUENCE_uper.c:403 #8 0x000000fcb140 in CHOICE_encode_uper /home/richie/w/f1-refactor-ue-context/build/openair2/RRC/LTE/MESSAGES/constr_CHOICE_uper.c:177 #9 0x000000fd191a in SEQUENCE_encode_uper /home/richie/w/f1-refactor-ue-context/build/openair2/RRC/LTE/MESSAGES/constr_SEQUENCE_uper.c:403 #10 0x000000fcb140 in CHOICE_encode_uper /home/richie/w/f1-refactor-ue-context/build/openair2/RRC/LTE/MESSAGES/constr_CHOICE_uper.c:177 #11 0x000000fcb140 in CHOICE_encode_uper /home/richie/w/f1-refactor-ue-context/build/openair2/RRC/LTE/MESSAGES/constr_CHOICE_uper.c:177 #12 0x000000fd191a in SEQUENCE_encode_uper /home/richie/w/f1-refactor-ue-context/build/openair2/RRC/LTE/MESSAGES/constr_SEQUENCE_uper.c:403 #13 0x000000fbc1ed in uper_encode /home/richie/w/f1-refactor-ue-context/build/openair2/RRC/LTE/MESSAGES/uper_encoder.c:27 #14 0x000000fbc73a in uper_encode_to_new_buffer /home/richie/w/f1-refactor-ue-context/build/openair2/RRC/LTE/MESSAGES/uper_encoder.c:85 #15 0x000000e10fbd in do_RRCReconfiguration /home/richie/w/f1-refactor-ue-context/openair2/RRC/NR/MESSAGES/asn1_msg.c:586 #16 0x000000805712 in rrc_gNB_encode_RRCReconfiguration /home/richie/w/f1-refactor-ue-context/openair2/RRC/NR/rrc_gNB.c:652 #17 0x000000893860 in nr_rrc_f1_ho_acknowledge /home/richie/w/f1-refactor-ue-context/openair2/RRC/NR/rrc_gNB_mobility.c:280 #18 0x0000008079ac in rrc_CU_process_ue_context_setup_response /home/richie/w/f1-refactor-ue-context/openair2/RRC/NR/rrc_gNB.c:2139 #19 0x0000008330d8 in rrc_gnb_task /home/richie/w/f1-refactor-ue-context/openair2/RRC/NR/rrc_gNB.c:2771 #20 0x7f3763428ee5 in asan_thread_start(void*) (/lib64/libasan.so.8+0x28ee5) (BuildId: 7f1aa7e2e600e8c9d54ce6e3d36f3d31bfe7949a) --- openair2/RRC/NR/rrc_gNB_mobility.c | 1 + 1 file changed, 1 insertion(+) diff --git a/openair2/RRC/NR/rrc_gNB_mobility.c b/openair2/RRC/NR/rrc_gNB_mobility.c index 7312e2f631..85c9597371 100644 --- a/openair2/RRC/NR/rrc_gNB_mobility.c +++ b/openair2/RRC/NR/rrc_gNB_mobility.c @@ -285,6 +285,7 @@ static void nr_rrc_f1_ho_acknowledge(gNB_RRC_INST *rrc, gNB_RRC_UE_t *UE) DevAssert(UE->ho_context->source != NULL); rrc_gNB_trigger_reconfiguration_for_handover(rrc, UE, buffer.buf, buffer.len); LOG_A(NR_RRC, "HO acknowledged: Send reconfiguration for UE %u/RNTI %04x...\n", UE->rrc_ue_id, UE->rnti); + free_byte_array(buffer); /* Re-establish SRB2 according to clause 5.3.5.6.3 of 3GPP TS 38.331 * (SRB1 is re-established with RRCReestablishment message) From bd5380ed097f0ebed0c9d2df16d42d697a23b9ba Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Fri, 20 Jun 2025 14:14:12 +0200 Subject: [PATCH 33/36] Make UE capabilities const: is read-only --- openair2/LAYER2/NR_MAC_gNB/nr_radio_config.c | 2 +- openair2/LAYER2/NR_MAC_gNB/nr_radio_config.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/openair2/LAYER2/NR_MAC_gNB/nr_radio_config.c b/openair2/LAYER2/NR_MAC_gNB/nr_radio_config.c index 41ace5014b..004e08d3be 100644 --- a/openair2/LAYER2/NR_MAC_gNB/nr_radio_config.c +++ b/openair2/LAYER2/NR_MAC_gNB/nr_radio_config.c @@ -3524,7 +3524,7 @@ NR_CellGroupConfig_t *get_initial_cellGroupConfig(int uid, void update_cellGroupConfig(NR_CellGroupConfig_t *cellGroupConfig, const int uid, - NR_UE_NR_Capability_t *uecap, + const NR_UE_NR_Capability_t *uecap, const nr_mac_config_t *configuration, const NR_ServingCellConfigCommon_t *scc) { diff --git a/openair2/LAYER2/NR_MAC_gNB/nr_radio_config.h b/openair2/LAYER2/NR_MAC_gNB/nr_radio_config.h index cdb4f5b792..bdf56a3310 100644 --- a/openair2/LAYER2/NR_MAC_gNB/nr_radio_config.h +++ b/openair2/LAYER2/NR_MAC_gNB/nr_radio_config.h @@ -89,7 +89,7 @@ NR_CellGroupConfig_t *get_initial_cellGroupConfig(int uid, const nr_rlc_configuration_t *default_rlc_config); void update_cellGroupConfig(NR_CellGroupConfig_t *cellGroupConfig, const int uid, - NR_UE_NR_Capability_t *uecap, + const NR_UE_NR_Capability_t *uecap, const nr_mac_config_t *configuration, const NR_ServingCellConfigCommon_t *scc); void free_cellGroupConfig(NR_CellGroupConfig_t *cellGroupConfig); From 5766d7ff5110b7280b7ecd4c9d99526afa7c77d6 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Fri, 20 Jun 2025 16:10:44 +0200 Subject: [PATCH 34/36] Debug core images: mount sources to right directory --- docker/debug_core_image.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docker/debug_core_image.sh b/docker/debug_core_image.sh index 3b2fc5db0a..307bd90bc5 100755 --- a/docker/debug_core_image.sh +++ b/docker/debug_core_image.sh @@ -54,7 +54,7 @@ fi # the source directory to show correct line numbers docker run --rm -it \ -v $COREDUMP:/tmp/coredump \ - -v $SOURCES:/opt/$TYPEPATH/src \ + -v $SOURCES:/oai-ran/ \ --entrypoint bash \ $IMAGE \ -c "gdb --dir=src/cmake_targets/ran_build/build $EXEC /tmp/coredump" From e33711cffa2f97567823731d75995c2547155c72 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Fri, 20 Jun 2025 18:55:30 +0200 Subject: [PATCH 35/36] Allocate twice to avoid double free We use the same resource for CSI meas report and RSRP (judging by the name of the functions), but the memory allocations need to be separate to avoid a double free: ==2063066==ERROR: AddressSanitizer: heap-use-after-free on address 0x7c27d43e3ce8 at pc 0x000000fcd279 bp 0x7be7cc9e7120 sp 0x7be7cc9e7118 READ of size 8 at 0x7c27d43e3ce8 thread T6 #0 0x000000fcd278 in SEQUENCE_free /home/richie/w/f1-refactor-ue-context/build/openair2/RRC/LTE/MESSAGES/constr_SEQUENCE.c:97 #1 0x000000fcd278 in SEQUENCE_free /home/richie/w/f1-refactor-ue-context/build/openair2/RRC/LTE/MESSAGES/constr_SEQUENCE.c:69 #2 0x000000fd6249 in SET_OF_free /home/richie/w/f1-refactor-ue-context/build/openair2/RRC/LTE/MESSAGES/constr_SET_OF.c:236 #3 0x000000fd6249 in SET_OF_free /home/richie/w/f1-refactor-ue-context/build/openair2/RRC/LTE/MESSAGES/constr_SET_OF.c:220 #4 0x000000fcd103 in SEQUENCE_free /home/richie/w/f1-refactor-ue-context/build/openair2/RRC/LTE/MESSAGES/constr_SEQUENCE.c:91 #5 0x000000fcd103 in SEQUENCE_free /home/richie/w/f1-refactor-ue-context/build/openair2/RRC/LTE/MESSAGES/constr_SEQUENCE.c:69 #6 0x000000fc90c9 in CHOICE_free /home/richie/w/f1-refactor-ue-context/build/openair2/RRC/LTE/MESSAGES/constr_CHOICE.c:185 #7 0x000000fc90c9 in CHOICE_free /home/richie/w/f1-refactor-ue-context/build/openair2/RRC/LTE/MESSAGES/constr_CHOICE.c:158 #8 0x000000fcd103 in SEQUENCE_free /home/richie/w/f1-refactor-ue-context/build/openair2/RRC/LTE/MESSAGES/constr_SEQUENCE.c:91 #9 0x000000fcd103 in SEQUENCE_free /home/richie/w/f1-refactor-ue-context/build/openair2/RRC/LTE/MESSAGES/constr_SEQUENCE.c:69 #10 0x000000fd6249 in SET_OF_free /home/richie/w/f1-refactor-ue-context/build/openair2/RRC/LTE/MESSAGES/constr_SET_OF.c:236 #11 0x000000fd6249 in SET_OF_free /home/richie/w/f1-refactor-ue-context/build/openair2/RRC/LTE/MESSAGES/constr_SET_OF.c:220 #12 0x000000fcd01a in SEQUENCE_free /home/richie/w/f1-refactor-ue-context/build/openair2/RRC/LTE/MESSAGES/constr_SEQUENCE.c:88 #13 0x000000fcd01a in SEQUENCE_free /home/richie/w/f1-refactor-ue-context/build/openair2/RRC/LTE/MESSAGES/constr_SEQUENCE.c:69 #14 0x000000fc90c9 in CHOICE_free /home/richie/w/f1-refactor-ue-context/build/openair2/RRC/LTE/MESSAGES/constr_CHOICE.c:185 #15 0x000000fc90c9 in CHOICE_free /home/richie/w/f1-refactor-ue-context/build/openair2/RRC/LTE/MESSAGES/constr_CHOICE.c:158 #16 0x000000fcd01a in SEQUENCE_free /home/richie/w/f1-refactor-ue-context/build/openair2/RRC/LTE/MESSAGES/constr_SEQUENCE.c:88 #17 0x000000fcd01a in SEQUENCE_free /home/richie/w/f1-refactor-ue-context/build/openair2/RRC/LTE/MESSAGES/constr_SEQUENCE.c:69 #18 0x000000fcd01a in SEQUENCE_free /home/richie/w/f1-refactor-ue-context/build/openair2/RRC/LTE/MESSAGES/constr_SEQUENCE.c:88 #19 0x000000fcd01a in SEQUENCE_free /home/richie/w/f1-refactor-ue-context/build/openair2/RRC/LTE/MESSAGES/constr_SEQUENCE.c:69 #20 0x000000fcd01a in SEQUENCE_free /home/richie/w/f1-refactor-ue-context/build/openair2/RRC/LTE/MESSAGES/constr_SEQUENCE.c:88 #21 0x000000fcd01a in SEQUENCE_free /home/richie/w/f1-refactor-ue-context/build/openair2/RRC/LTE/MESSAGES/constr_SEQUENCE.c:69 #22 0x0000009d78ae in ue_context_setup_request /home/richie/w/f1-refactor-ue-context/openair2/LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.c:692 #23 0x00000083fee2 in rrc_add_nsa_user /home/richie/w/f1-refactor-ue-context/openair2/RRC/NR/rrc_gNB_nsa.c:330 #24 0x000000886e8b in rrc_gNB_process_f1_setup_req /home/richie/w/f1-refactor-ue-context/openair2/RRC/NR/rrc_gNB_du.c:444 #25 0x000000833942 in rrc_gnb_task /home/richie/w/f1-refactor-ue-context/openair2/RRC/NR/rrc_gNB.c:2766 #26 0x7fe7d5e28ee5 in asan_thread_start(void*) (/lib64/libasan.so.8+0x28ee5) (BuildId: 7f1aa7e2e600e8c9d54ce6e3d36f3d31bfe7949a) #27 0x7fe7d527f1d3 in start_thread (/lib64/libc.so.6+0x711d3) (BuildId: 2b3c02fe7e4d3811767175b6f323692a10a4e116) #28 0x7fe7d5301ceb in __GI___clone3 (/lib64/libc.so.6+0xf3ceb) (BuildId: 2b3c02fe7e4d3811767175b6f323692a10a4e116) 0x7c27d43e3ce8 is located 24 bytes inside of 40-byte region [0x7c27d43e3cd0,0x7c27d43e3cf8) freed by thread T6 here: #0 0x7fe7d5ee5bcb in free.part.0 (/lib64/libasan.so.8+0xe5bcb) (BuildId: 7f1aa7e2e600e8c9d54ce6e3d36f3d31bfe7949a) #1 0x000000fd6249 in SET_OF_free /home/richie/w/f1-refactor-ue-context/build/openair2/RRC/LTE/MESSAGES/constr_SET_OF.c:236 #2 0x000000fd6249 in SET_OF_free /home/richie/w/f1-refactor-ue-context/build/openair2/RRC/LTE/MESSAGES/constr_SET_OF.c:220 #3 0x000000fcd103 in SEQUENCE_free /home/richie/w/f1-refactor-ue-context/build/openair2/RRC/LTE/MESSAGES/constr_SEQUENCE.c:91 #4 0x000000fcd103 in SEQUENCE_free /home/richie/w/f1-refactor-ue-context/build/openair2/RRC/LTE/MESSAGES/constr_SEQUENCE.c:69 #5 0x000000fc90c9 in CHOICE_free /home/richie/w/f1-refactor-ue-context/build/openair2/RRC/LTE/MESSAGES/constr_CHOICE.c:185 #6 0x000000fc90c9 in CHOICE_free /home/richie/w/f1-refactor-ue-context/build/openair2/RRC/LTE/MESSAGES/constr_CHOICE.c:158 #7 0x000000fcd103 in SEQUENCE_free /home/richie/w/f1-refactor-ue-context/build/openair2/RRC/LTE/MESSAGES/constr_SEQUENCE.c:91 #8 0x000000fcd103 in SEQUENCE_free /home/richie/w/f1-refactor-ue-context/build/openair2/RRC/LTE/MESSAGES/constr_SEQUENCE.c:69 #9 0x000000fd6249 in SET_OF_free /home/richie/w/f1-refactor-ue-context/build/openair2/RRC/LTE/MESSAGES/constr_SET_OF.c:236 #10 0x000000fd6249 in SET_OF_free /home/richie/w/f1-refactor-ue-context/build/openair2/RRC/LTE/MESSAGES/constr_SET_OF.c:220 #11 0x000000fcd01a in SEQUENCE_free /home/richie/w/f1-refactor-ue-context/build/openair2/RRC/LTE/MESSAGES/constr_SEQUENCE.c:88 #12 0x000000fcd01a in SEQUENCE_free /home/richie/w/f1-refactor-ue-context/build/openair2/RRC/LTE/MESSAGES/constr_SEQUENCE.c:69 #13 0x000000fc90c9 in CHOICE_free /home/richie/w/f1-refactor-ue-context/build/openair2/RRC/LTE/MESSAGES/constr_CHOICE.c:185 #14 0x000000fc90c9 in CHOICE_free /home/richie/w/f1-refactor-ue-context/build/openair2/RRC/LTE/MESSAGES/constr_CHOICE.c:158 #15 0x000000fcd01a in SEQUENCE_free /home/richie/w/f1-refactor-ue-context/build/openair2/RRC/LTE/MESSAGES/constr_SEQUENCE.c:88 #16 0x000000fcd01a in SEQUENCE_free /home/richie/w/f1-refactor-ue-context/build/openair2/RRC/LTE/MESSAGES/constr_SEQUENCE.c:69 #17 0x000000fcd01a in SEQUENCE_free /home/richie/w/f1-refactor-ue-context/build/openair2/RRC/LTE/MESSAGES/constr_SEQUENCE.c:88 #18 0x000000fcd01a in SEQUENCE_free /home/richie/w/f1-refactor-ue-context/build/openair2/RRC/LTE/MESSAGES/constr_SEQUENCE.c:69 #19 0x000000fcd01a in SEQUENCE_free /home/richie/w/f1-refactor-ue-context/build/openair2/RRC/LTE/MESSAGES/constr_SEQUENCE.c:88 #20 0x000000fcd01a in SEQUENCE_free /home/richie/w/f1-refactor-ue-context/build/openair2/RRC/LTE/MESSAGES/constr_SEQUENCE.c:69 #21 0x0000009d78ae in ue_context_setup_request /home/richie/w/f1-refactor-ue-context/openair2/LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.c:692 #22 0x00000083fee2 in rrc_add_nsa_user /home/richie/w/f1-refactor-ue-context/openair2/RRC/NR/rrc_gNB_nsa.c:330 #23 0x000000886e8b in rrc_gNB_process_f1_setup_req /home/richie/w/f1-refactor-ue-context/openair2/RRC/NR/rrc_gNB_du.c:444 #24 0x000000833942 in rrc_gnb_task /home/richie/w/f1-refactor-ue-context/openair2/RRC/NR/rrc_gNB.c:2766 #25 0x7fe7d5e28ee5 in asan_thread_start(void*) (/lib64/libasan.so.8+0x28ee5) (BuildId: 7f1aa7e2e600e8c9d54ce6e3d36f3d31bfe7949a) previously allocated by thread T6 here: #0 0x7fe7d5ee6883 in calloc (/lib64/libasan.so.8+0xe6883) (BuildId: 7f1aa7e2e600e8c9d54ce6e3d36f3d31bfe7949a) #1 0x000000a1ac53 in get_default_secondaryCellGroup /home/richie/w/f1-refactor-ue-context/openair2/LAYER2/NR_MAC_gNB/nr_radio_config.c:3969 #2 0x0000009d8913 in create_new_UE /home/richie/w/f1-refactor-ue-context/openair2/LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.c:571 #3 0x0000009d8913 in ue_context_setup_request /home/richie/w/f1-refactor-ue-context/openair2/LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.c:638 #4 0x00000083fee2 in rrc_add_nsa_user /home/richie/w/f1-refactor-ue-context/openair2/RRC/NR/rrc_gNB_nsa.c:330 #5 0x000000886e8b in rrc_gNB_process_f1_setup_req /home/richie/w/f1-refactor-ue-context/openair2/RRC/NR/rrc_gNB_du.c:444 #6 0x000000833942 in rrc_gnb_task /home/richie/w/f1-refactor-ue-context/openair2/RRC/NR/rrc_gNB.c:2766 #7 0x7fe7d5e28ee5 in asan_thread_start(void*) (/lib64/libasan.so.8+0x28ee5) (BuildId: 7f1aa7e2e600e8c9d54ce6e3d36f3d31bfe7949a) Thread T6 created by T0 here: #0 0x7fe7d5ede492 in pthread_create (/lib64/libasan.so.8+0xde492) (BuildId: 7f1aa7e2e600e8c9d54ce6e3d36f3d31bfe7949a) #1 0x0000012a4ba3 in threadCreate /home/richie/w/f1-refactor-ue-context/common/utils/system.c:283 #2 0x0000006b5fef in itti_create_task /home/richie/w/f1-refactor-ue-context/common/utils/ocp_itti/intertask_interface.cpp:317 #3 0x000000435c5f in create_gNB_tasks /home/richie/w/f1-refactor-ue-context/executables/nr-softmodem.c:310 #4 0x000000435c5f in main /home/richie/w/f1-refactor-ue-context/executables/nr-softmodem.c:620 #5 0x7fe7d52115f4 in __libc_start_call_main (/lib64/libc.so.6+0x35f4) (BuildId: 2b3c02fe7e4d3811767175b6f323692a10a4e116) #6 0x7fe7d52116a7 in __libc_start_main@@GLIBC_2.34 (/lib64/libc.so.6+0x36a7) (BuildId: 2b3c02fe7e4d3811767175b6f323692a10a4e116) #7 0x0000004672d4 in _start (/home/richie/w/f1-refactor-ue-context/build/nr-softmodem+0x4672d4) (BuildId: 81450e9a0b832ca9e36b1984ecc232efde59d424) Closes: #958 --- openair2/LAYER2/NR_MAC_gNB/nr_radio_config.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/openair2/LAYER2/NR_MAC_gNB/nr_radio_config.c b/openair2/LAYER2/NR_MAC_gNB/nr_radio_config.c index 004e08d3be..4246cc65aa 100644 --- a/openair2/LAYER2/NR_MAC_gNB/nr_radio_config.c +++ b/openair2/LAYER2/NR_MAC_gNB/nr_radio_config.c @@ -3969,7 +3969,6 @@ NR_CellGroupConfig_t *get_default_secondaryCellGroup(const NR_ServingCellConfigC NR_PUCCH_CSI_Resource_t *pucchcsires1 = calloc(1, sizeof(*pucchcsires1)); pucchcsires1->uplinkBandwidthPartId = bwp->bwp_Id; pucchcsires1->pucch_Resource = 2; - config_csi_meas_report(csi_MeasConfig, servingcellconfigcommon, pucchcsires1, @@ -3979,9 +3978,14 @@ NR_CellGroupConfig_t *get_default_secondaryCellGroup(const NR_ServingCellConfigC bwp->bwp_Id, uid, curr_bwp); + // this is the same resource as pucchcsires1, but duplicated to avoid + // double free when releasing the CellGroupConfig + NR_PUCCH_CSI_Resource_t *pucchcsires2 = calloc(1, sizeof(*pucchcsires2)); + pucchcsires2->uplinkBandwidthPartId = bwp->bwp_Id; + pucchcsires2->pucch_Resource = 2; config_rsrp_meas_report(csi_MeasConfig, servingcellconfigcommon, - pucchcsires1, + pucchcsires2, do_csirs, bwp->bwp_Id + 10, uid, From 43e87b669dc76ad17c42339c1f1f7fe9448f40d3 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Thu, 26 Jun 2025 13:38:29 +0200 Subject: [PATCH 36/36] cg_config_info_from_ue_cap_file(): avoid potential memory leaks Avoid potential memory leaks by first reading UE capabilities file (if present), and allocating only after the file read was successful. --- openair2/RRC/NR/rrc_gNB_nsa.c | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/openair2/RRC/NR/rrc_gNB_nsa.c b/openair2/RRC/NR/rrc_gNB_nsa.c index cd7b5fb8d4..d0cc63062b 100644 --- a/openair2/RRC/NR/rrc_gNB_nsa.c +++ b/openair2/RRC/NR/rrc_gNB_nsa.c @@ -77,13 +77,7 @@ // and put it into a CG-ConfigInfo field static int cg_config_info_from_ue_cap_file(uint32_t maxlen, uint8_t buf[maxlen]) { - NR_CG_ConfigInfo_t *cgci = calloc_or_fail(1, sizeof(*cgci)); - cgci->criticalExtensions.present = NR_CG_ConfigInfo__criticalExtensions_PR_c1; - cgci->criticalExtensions.choice.c1 = calloc_or_fail(1, sizeof(*cgci->criticalExtensions.choice.c1)); - cgci->criticalExtensions.choice.c1->present = NR_CG_ConfigInfo__criticalExtensions__c1_PR_cg_ConfigInfo; - NR_CG_ConfigInfo_IEs_t *cgci_ies = calloc_or_fail(1, sizeof(*cgci_ies)); - cgci->criticalExtensions.choice.c1->choice.cg_ConfigInfo = cgci_ies; - + OCTET_STRING_t *os_cap = NULL; if (uecap_file != NULL) { LOG_I(NR_RRC, "creating CG-ConfigInfo from UE capability file %s\n", uecap_file); @@ -104,11 +98,18 @@ static int cg_config_info_from_ue_cap_file(uint32_t maxlen, uint8_t buf[maxlen]) DevAssert(dec_rval.code == RC_OK); //xer_fprint(stdout, &asn_DEF_NR_UE_NR_Capability, cap); - OCTET_STRING_t *os_cap = calloc_or_fail(1, sizeof(*os_cap)); + os_cap = calloc_or_fail(1, sizeof(*os_cap)); os_cap->size = uper_encode_to_new_buffer(&asn_DEF_NR_UE_NR_Capability, NULL, cap, (void **)&os_cap->buf); - cgci_ies->ue_CapabilityInfo = os_cap; } + NR_CG_ConfigInfo_t *cgci = calloc_or_fail(1, sizeof(*cgci)); + cgci->criticalExtensions.present = NR_CG_ConfigInfo__criticalExtensions_PR_c1; + cgci->criticalExtensions.choice.c1 = calloc_or_fail(1, sizeof(*cgci->criticalExtensions.choice.c1)); + cgci->criticalExtensions.choice.c1->present = NR_CG_ConfigInfo__criticalExtensions__c1_PR_cg_ConfigInfo; + NR_CG_ConfigInfo_IEs_t *cgci_ies = calloc_or_fail(1, sizeof(*cgci_ies)); + cgci->criticalExtensions.choice.c1->choice.cg_ConfigInfo = cgci_ies; + cgci_ies->ue_CapabilityInfo = os_cap; + //xer_fprint(stdout, &asn_DEF_NR_CG_ConfigInfo, cgci); asn_enc_rval_t rval = uper_encode_to_buffer(&asn_DEF_NR_CG_ConfigInfo, NULL, cgci, buf, maxlen); DevAssert(rval.encoded > 0);