From 8eca2e0591bc0f9e03b1cbeff44b6bd2ccec4a89 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Thu, 23 Jan 2025 14:58:46 +0100 Subject: [PATCH 1/2] Correctly link function ran_func_kpm.c uses cp_ba_to_str(), but it is not defined in OAI. Define it so we can link properly, instead of relying on FlexRIC (where it was defined). --- common/utils/ds/byte_array.c | 14 ++++++++++++++ common/utils/ds/byte_array.h | 1 + openair2/E2AP/RAN_FUNCTION/CMakeLists.txt | 4 ++-- openair2/E2AP/RAN_FUNCTION/O-RAN/ran_func_kpm.c | 1 + 4 files changed, 18 insertions(+), 2 deletions(-) diff --git a/common/utils/ds/byte_array.c b/common/utils/ds/byte_array.c index 78e1ef4e31..d6ad97e324 100644 --- a/common/utils/ds/byte_array.c +++ b/common/utils/ds/byte_array.c @@ -72,3 +72,17 @@ byte_array_t cp_str_to_ba(const char* str) return dst; } + +char* cp_ba_to_str(const byte_array_t ba) +{ + assert(ba.len > 0); + + const size_t sz = ba.len; + char* str = calloc(sz+1, sizeof(char)); + assert(str != NULL && "Memory exhausted"); + + memcpy(str, ba.buf, sz); + str[sz] = '\0'; + + return str; +} diff --git a/common/utils/ds/byte_array.h b/common/utils/ds/byte_array.h index 236f3e683f..18adb33047 100644 --- a/common/utils/ds/byte_array.h +++ b/common/utils/ds/byte_array.h @@ -42,5 +42,6 @@ void free_byte_array(byte_array_t ba); bool eq_byte_array(const byte_array_t* m0, const byte_array_t* m1); byte_array_t cp_str_to_ba(const char* str); +char* cp_ba_to_str(const byte_array_t ba); #endif diff --git a/openair2/E2AP/RAN_FUNCTION/CMakeLists.txt b/openair2/E2AP/RAN_FUNCTION/CMakeLists.txt index 1d47f029d9..578bf489df 100644 --- a/openair2/E2AP/RAN_FUNCTION/CMakeLists.txt +++ b/openair2/E2AP/RAN_FUNCTION/CMakeLists.txt @@ -12,7 +12,7 @@ add_library(e2_ran_func_cuup STATIC ../flexric/test/rnd/fill_rnd_data_tc.c ) -target_link_libraries(e2_ran_func_cuup PUBLIC asn1_nr_rrc nr_rrc asn1_nr_rrc_hdrs e2_time_obj kpm_ric_info_common_obj 3gpp_derived_ie_obj sm_common_ie_obj) +target_link_libraries(e2_ran_func_cuup PUBLIC asn1_nr_rrc nr_rrc asn1_nr_rrc_hdrs e2_time_obj kpm_ric_info_common_obj 3gpp_derived_ie_obj sm_common_ie_obj ds) target_compile_definitions(e2_ran_func_cuup PUBLIC ${E2AP_VERSION} ${KPM_VERSION} NGRAN_GNB_CUUP) @@ -35,7 +35,7 @@ add_library(e2_ran_func_du_cucp_cuup STATIC ../flexric/test/rnd/fill_rnd_data_tc.c ) -target_link_libraries(e2_ran_func_du_cucp_cuup PUBLIC asn1_nr_rrc nr_rrc asn1_nr_rrc_hdrs e2_time_obj kpm_ric_info_common_obj 3gpp_derived_ie_obj e2sm_rc_ir_obj sm_common_ie_obj) +target_link_libraries(e2_ran_func_du_cucp_cuup PUBLIC asn1_nr_rrc nr_rrc asn1_nr_rrc_hdrs e2_time_obj kpm_ric_info_common_obj 3gpp_derived_ie_obj e2sm_rc_ir_obj sm_common_ie_obj ds) target_compile_definitions(e2_ran_func_du_cucp_cuup PUBLIC ${E2AP_VERSION} ${KPM_VERSION} NGRAN_GNB_DU NGRAN_GNB_CUCP NGRAN_GNB_CUUP) # Current implementation: diff --git a/openair2/E2AP/RAN_FUNCTION/O-RAN/ran_func_kpm.c b/openair2/E2AP/RAN_FUNCTION/O-RAN/ran_func_kpm.c index 40371df046..c9620e871f 100644 --- a/openair2/E2AP/RAN_FUNCTION/O-RAN/ran_func_kpm.c +++ b/openair2/E2AP/RAN_FUNCTION/O-RAN/ran_func_kpm.c @@ -23,6 +23,7 @@ #include "ran_func_kpm_subs.h" #include "ran_e2sm_ue_id.h" +#include "common/utils/ds/byte_array.h" #include "openair2/E1AP/e1ap_common.h" #include "openair2/E2AP/flexric/src/util/time_now_us.h" #include "openair2/F1AP/f1ap_ids.h" From 84c69e50642bd00640e3550d8c83fd0327456031 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Thu, 16 Jan 2025 14:29:40 +0100 Subject: [PATCH 2/2] Avoid huge calloc by alloc'ing TBs independently Prior to this this commit, the structure NR_UE_info_t is 4881632 bytes. On some machines, e.g., one of the CI systems, this can lead to realtime problems when doing the initial calloc() of the data structure. Commit e586efb29d34865b749fd4da94039b189c06a982 ("Enable 32 HARQ Processes in DL, UL") introduced the real-time problems by increasing the number of HARQ processes. The reason NR_UE_info_t is that big is that it contains buffers for DL HARQ data that might need to be retransmitted (the L1 is stateless, it cannot store this for the L2). To reduce the size, dynamically allocate the DL HARQ buffers when they are needed. This also reduces the size of NR_UE_info_t to 15840 bytes. Encapsulate transportBlock in byte_array and accessory functions, and allocate in big chunks of multiple of ~32kB. Reported-By: Cedric Roux Fixes: e586efb29d34865b749fd4da94039b189c06a982 Closes: #875 --- openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c | 6 ++--- .../LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c | 8 +++---- .../NR_MAC_gNB/gNB_scheduler_primitives.c | 23 +++++++++++++++++++ openair2/LAYER2/NR_MAC_gNB/mac_proto.h | 3 +++ openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h | 8 +++---- 5 files changed, 37 insertions(+), 11 deletions(-) diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c index 7b010ad5bc..6ffdce88f0 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c @@ -2126,7 +2126,7 @@ static void nr_generate_Msg4_MsgB(module_id_t module_idP, harq->tb_size = tb_size; - uint8_t *buf = (uint8_t *) harq->transportBlock; + uint8_t *buf = allocate_transportBlock_buffer(&harq->transportBlock, tb_size); // Bytes to be transmitted if (harq->round == 0) { uint16_t mac_pdu_length = 0; @@ -2206,11 +2206,11 @@ static void nr_generate_Msg4_MsgB(module_id_t module_idP, } T(T_GNB_MAC_DL_PDU_WITH_DATA, T_INT(module_idP), T_INT(CC_id), T_INT(ra->rnti), - T_INT(frameP), T_INT(slotP), T_INT(current_harq_pid), T_BUFFER(harq->transportBlock, harq->tb_size)); + T_INT(frameP), T_INT(slotP), T_INT(current_harq_pid), T_BUFFER(harq->transportBlock.buf, harq->tb_size)); // DL TX request nfapi_nr_pdu_t *tx_req = &TX_req->pdu_list[TX_req->Number_of_PDUs]; - memcpy(tx_req->TLVs[0].value.direct, harq->transportBlock, sizeof(uint8_t) * harq->tb_size); + memcpy(tx_req->TLVs[0].value.direct, harq->transportBlock.buf, sizeof(uint8_t) * harq->tb_size); tx_req->PDU_index = pduindex; tx_req->num_TLV = 1; tx_req->TLVs[0].length = harq->tb_size; diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c index ce5bbfe9fd..48a72b527b 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c @@ -1280,12 +1280,12 @@ void nr_schedule_ue_spec(module_id_t module_id, UE->rnti, current_harq_pid); T(T_GNB_MAC_RETRANSMISSION_DL_PDU_WITH_DATA, T_INT(module_id), T_INT(CC_id), T_INT(rnti), - T_INT(frame), T_INT(slot), T_INT(current_harq_pid), T_INT(harq->round), T_BUFFER(harq->transportBlock, TBS)); + T_INT(frame), T_INT(slot), T_INT(current_harq_pid), T_INT(harq->round), T_BUFFER(harq->transportBlock.buf, TBS)); UE->mac_stats.dl.total_rbs_retx += sched_pdsch->rbSize; gNB_mac->mac_stats.used_prb_aggregate += sched_pdsch->rbSize; } else { /* initial transmission */ LOG_D(NR_MAC, "Initial HARQ transmission in %d.%d\n", frame, slot); - uint8_t *buf = (uint8_t *) harq->transportBlock; + uint8_t *buf = allocate_transportBlock_buffer(&harq->transportBlock, TBS); /* first, write all CEs that might be there */ int written = nr_write_ce_dlsch_pdu(module_id, sched_ctrl, @@ -1420,7 +1420,7 @@ void nr_schedule_ue_spec(module_id_t module_id, } T(T_GNB_MAC_DL_PDU_WITH_DATA, T_INT(module_id), T_INT(CC_id), T_INT(rnti), - T_INT(frame), T_INT(slot), T_INT(current_harq_pid), T_BUFFER(harq->transportBlock, TBS)); + T_INT(frame), T_INT(slot), T_INT(current_harq_pid), T_BUFFER(harq->transportBlock.buf, TBS)); } const int ntx_req = TX_req->Number_of_PDUs; @@ -1429,7 +1429,7 @@ void nr_schedule_ue_spec(module_id_t module_id, tx_req->num_TLV = 1; tx_req->TLVs[0].length = TBS; tx_req->PDU_length = compute_PDU_length(tx_req->num_TLV, tx_req->TLVs[0].length); - memcpy(tx_req->TLVs[0].value.direct, harq->transportBlock, TBS); + memcpy(tx_req->TLVs[0].value.direct, harq->transportBlock.buf, TBS); TX_req->Number_of_PDUs++; TX_req->SFN = frame; TX_req->Slot = slot; diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c index 708337640c..ec243fcd86 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c @@ -2079,12 +2079,35 @@ void delete_nr_ue_data(NR_UE_info_t *UE, NR_COMMON_channels_t *ccPtr, uid_alloca destroy_nr_list(&sched_ctrl->available_ul_harq); destroy_nr_list(&sched_ctrl->feedback_ul_harq); destroy_nr_list(&sched_ctrl->retrans_ul_harq); + for (int i = 0; i < NR_MAX_HARQ_PROCESSES; ++i) + free_transportBlock_buffer(&sched_ctrl->harq_processes[i].transportBlock); free_sched_pucch_list(sched_ctrl); uid_linear_allocator_free(uia, UE->uid); LOG_I(NR_MAC, "Remove NR rnti 0x%04x\n", UE->rnti); free(UE); } +#define TB_SINGLE_LAYER (32 * 1024) +uint8_t *allocate_transportBlock_buffer(byte_array_t *tb, uint32_t needed) +{ + DevAssert(needed > 0); + if (tb->buf != NULL && needed <= tb->len) + return tb->buf; // nothing to do, current is enough + + uint32_t size = TB_SINGLE_LAYER; + while (needed > size) + size *= 2; + LOG_D(NR_MAC, "allocating new TB block of size %d\n", size); + free(tb->buf); + tb->buf = malloc_or_fail(size); + tb->len = size; + return tb->buf; +} + +void free_transportBlock_buffer(byte_array_t *tb) +{ + free_byte_array(*tb); +} void set_max_fb_time(NR_UE_UL_BWP_t *UL_BWP, const NR_UE_DL_BWP_t *DL_BWP) { diff --git a/openair2/LAYER2/NR_MAC_gNB/mac_proto.h b/openair2/LAYER2/NR_MAC_gNB/mac_proto.h index d8c876439b..46deef46e8 100644 --- a/openair2/LAYER2/NR_MAC_gNB/mac_proto.h +++ b/openair2/LAYER2/NR_MAC_gNB/mac_proto.h @@ -381,6 +381,9 @@ void handle_nr_ul_harq(const int CC_idP, sub_frame_t slot, const nfapi_nr_crc_t *crc_pdu); +uint8_t *allocate_transportBlock_buffer(byte_array_t *tb, uint32_t needed); +void free_transportBlock_buffer(byte_array_t *tb); + void handle_nr_srs_measurements(const module_id_t module_id, const frame_t frame, const sub_frame_t slot, diff --git a/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h b/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h index c94f64dfef..bb1fba0fe8 100644 --- a/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h +++ b/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h @@ -44,6 +44,7 @@ #include #include "common/utils/ds/seq_arr.h" #include "common/utils/nr/nr_common.h" +#include "common/utils/ds/byte_array.h" #define NR_SCHED_LOCK(lock) \ do { \ @@ -481,10 +482,9 @@ typedef struct NR_UE_harq { uint16_t feedback_frame; uint16_t feedback_slot; - /* Transport block to be sent using this HARQ process, its size is in - * sched_pdsch */ - uint32_t transportBlock[38016]; // valid up to 4 layers - uint32_t tb_size; + /* Transport block to be sent using this HARQ process */ + byte_array_t transportBlock; + uint32_t tb_size; // size of currently stored TB /// sched_pdsch keeps information on MCS etc used for the initial transmission NR_sched_pdsch_t sched_pdsch;