diff --git a/executables/nr-cuup.c b/executables/nr-cuup.c index 403f78ddb3..0c2c9cdf3f 100644 --- a/executables/nr-cuup.c +++ b/executables/nr-cuup.c @@ -150,7 +150,8 @@ int main(int argc, char **argv) time_manager_start(tick_functions, tick_functions_count, TIME_SOURCE_REALTIME); // strdup to put the sring in the core file for post mortem identification - LOG_I(HW, "Version: %s\n", strdup(OAI_PACKAGE_VERSION)); + char *v = strdup(OAI_PACKAGE_VERSION); + LOG_I(HW, "Version: %s\n", v); set_softmodem_sighandler(); itti_init(TASK_MAX, tasks_info); int rc; @@ -189,6 +190,8 @@ int main(int argc, char **argv) time_manager_finish(); + free(v); + logClean(); printf("Bye.\n"); return 0; diff --git a/openair2/E1AP/e1ap.c b/openair2/E1AP/e1ap.c index 1eff4ea529..168366f351 100644 --- a/openair2/E1AP/e1ap.c +++ b/openair2/E1AP/e1ap.c @@ -125,8 +125,8 @@ static void e1_task_handle_sctp_data_ind(instance_t instance, sctp_data_ind_t *s int e1ap_send_RESET(bool isCu, sctp_assoc_t assoc_id, E1AP_Reset_t *Reset) { AssertFatal(false, "Not implemented yet\n"); - E1AP_E1AP_PDU_t pdu = {0}; - return e1ap_encode_send(isCu, assoc_id, &pdu, 0, __func__); + E1AP_E1AP_PDU_t *pdu = calloc_or_fail(1, sizeof(*pdu)); + return e1ap_encode_send(isCu, assoc_id, pdu, 0, __func__); } int e1ap_send_RESET_ACKNOWLEDGE(instance_t instance, E1AP_Reset_t *Reset) @@ -304,9 +304,9 @@ static void fill_CONFIGURATION_UPDATE(E1AP_E1AP_PDU_t *pdu) void e1apCUUP_send_CONFIGURATION_UPDATE(sctp_assoc_t assoc_id) { - E1AP_E1AP_PDU_t pdu = {0}; - fill_CONFIGURATION_UPDATE(&pdu); - e1ap_encode_send(UPtype, assoc_id, &pdu, 0, __func__); + E1AP_E1AP_PDU_t *pdu = calloc_or_fail(1, sizeof(*pdu)); + fill_CONFIGURATION_UPDATE(pdu); + e1ap_encode_send(UPtype, assoc_id, pdu, 0, __func__); } int e1apCUCP_send_gNB_DU_CONFIGURATION_FAILURE(void) diff --git a/openair2/E1AP/e1ap_common.c b/openair2/E1AP/e1ap_common.c index 330d29567a..e102c7e151 100644 --- a/openair2/E1AP/e1ap_common.c +++ b/openair2/E1AP/e1ap_common.c @@ -226,7 +226,7 @@ int e1ap_encode_send(E1_t type, sctp_assoc_t assoc_id, E1AP_E1AP_PDU_t *pdu, uin void *buffer = NULL; ssize_t encoded = aper_encode_to_new_buffer(&asn_DEF_E1AP_E1AP_PDU, 0, pdu, &buffer); - ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_E1AP_E1AP_PDU, pdu); + ASN_STRUCT_FREE(asn_DEF_E1AP_E1AP_PDU, pdu); if (encoded < 0) { LOG_E(E1AP, "%s: Failed to encode E1AP message\n", func); diff --git a/openair2/LAYER2/nr_pdcp/cucp_cuup_handler.c b/openair2/LAYER2/nr_pdcp/cucp_cuup_handler.c index ed9cc37c18..4b95963257 100644 --- a/openair2/LAYER2/nr_pdcp/cucp_cuup_handler.c +++ b/openair2/LAYER2/nr_pdcp/cucp_cuup_handler.c @@ -153,7 +153,7 @@ static void e1_add_bearers(const int ue_id, const NR_DRB_ToAddModList_t *addMod, // get SDAP config sdap_config_t sdap = nr_sdap_get_config(GNB_FLAG_YES, drb->cnAssociation->choice.sdap_Config, drb->drb_Identity); // add SDAP entity - nr_sdap_addmod_entity(GNB_FLAG_YES, ue_id, sdap); + nr_sdap_addmod_entity(GNB_FLAG_YES, ue_id, &sdap); // add PDCP entity nr_pdcp_add_drb(GNB_FLAG_YES, ue_id, drb->pdcp_Config, &sdap, sp); } diff --git a/openair2/RRC/NR/rrc_gNB_nsa.c b/openair2/RRC/NR/rrc_gNB_nsa.c index 996dc3528e..3e3c462145 100644 --- a/openair2/RRC/NR/rrc_gNB_nsa.c +++ b/openair2/RRC/NR/rrc_gNB_nsa.c @@ -177,7 +177,7 @@ static void rrc_nsa_add_drb(const int ue_id, sdap.drb_id = drb->drb_Identity; sdap.defaultDRB = true; // add SDAP entity (terminated at gNB, since it's EPC) - nr_sdap_addmod_entity(GNB_FLAG_YES, ue_id, sdap); + nr_sdap_addmod_entity(GNB_FLAG_YES, ue_id, &sdap); // add PDCP entity nr_pdcp_add_drb(GNB_FLAG_YES, ue_id, drb->pdcp_Config, &sdap, sp); } diff --git a/openair2/RRC/NR_UE/rrc_UE.c b/openair2/RRC/NR_UE/rrc_UE.c index 6681eed855..15c713cb26 100644 --- a/openair2/RRC/NR_UE/rrc_UE.c +++ b/openair2/RRC/NR_UE/rrc_UE.c @@ -619,7 +619,7 @@ static void rrc_ue_add_bearer(const int ue_id, const NR_DRB_ToAddMod_t *drb, con sdap = nr_sdap_get_config(GNB_FLAG_NO, drb->cnAssociation->choice.sdap_Config, drb->drb_Identity); } // add SDAP entity - nr_sdap_addmod_entity(GNB_FLAG_NO, ue_id, sdap); + nr_sdap_addmod_entity(GNB_FLAG_NO, ue_id, &sdap); // add PDCP entity nr_pdcp_add_drb(GNB_FLAG_NO, ue_id, drb->pdcp_Config, &sdap, sp); } diff --git a/openair2/SDAP/nr_sdap/nr_sdap_entity.c b/openair2/SDAP/nr_sdap/nr_sdap_entity.c index f0e791c683..389213986e 100644 --- a/openair2/SDAP/nr_sdap/nr_sdap_entity.c +++ b/openair2/SDAP/nr_sdap/nr_sdap_entity.c @@ -210,8 +210,8 @@ static void nr_sdap_rx_entity(nr_sdap_entity_t *entity, { /* The offset of the SDAP header, it might be 0 if has_sdap_rx is not true in the pdcp entity. */ int offset=0; - int qfi = buf[0] & 0x3F; // QFI is always the first 6 bits in the first octet - if (qfi <= 0 || qfi >= SDAP_MAX_QFI) { + uint8_t qfi = buf[0] & 0x3F; // QFI is always the first 6 bits in the first octet + if (qfi >= SDAP_MAX_QFI) { LOG_E(SDAP, "Invalid QFI %d received in SDAP header\n", qfi); return; } @@ -450,7 +450,7 @@ static void nr_sdap_add_qos_flows_to_drb(nr_sdap_entity_t *entity, const sdap_co for (int i = 0; i < sdap->mappedQFIs2AddCount; i++) { uint8_t qfi = sdap->mappedQFIs2Add[i]; LOG_D(SDAP, "Adding QFI to DRB mapping rules: %d mapped QFIs for DRB %d\n", sdap->mappedQFIs2AddCount, sdap->drb_id); - if (qfi < SDAP_MAX_QFI && qfi > SDAP_MAP_RULE_EMPTY && sdap->drb_id > 0 && sdap->drb_id <= MAX_DRBS_PER_UE) { + if (qfi < SDAP_MAX_QFI && sdap->drb_id > SDAP_MAP_RULE_EMPTY && sdap->drb_id <= MAX_DRBS_PER_UE) { entity->qfi2drb_map_add(entity, qfi, sdap->drb_id, sdap->role); } else { LOG_E(SDAP, "Failed to add qfi2drb mapping: QFI=%d, DRB=%d\n", qfi, sdap->drb_id); @@ -487,13 +487,13 @@ static void nr_sdap_qfi2drb_map_update(nr_sdap_entity_t *entity, const sdap_conf * @param is_gnb, indicates whether it is for gNB or UE * @param ue_id, UE ID * @param sdap, SDAP configuration */ -static void nr_sdap_add_entity(const int is_gnb, const ue_id_t ue_id, const sdap_config_t sdap) +static void nr_sdap_add_entity(const int is_gnb, const ue_id_t ue_id, const sdap_config_t *sdap) { nr_sdap_entity_t *sdap_entity = calloc_or_fail(1, sizeof(*sdap_entity)); // SDAP entity ids sdap_entity->ue_id = ue_id; - sdap_entity->pdusession_id = sdap.pdusession_id; + sdap_entity->pdusession_id = sdap->pdusession_id; sdap_entity->is_gnb = is_gnb; // rx/tx entities @@ -513,13 +513,13 @@ static void nr_sdap_add_entity(const int is_gnb, const ue_id_t ue_id, const sdap sdap_entity->pdusession_sock = -1; // set default DRB - if (sdap.defaultDRB) { - sdap_entity->default_drb = sdap.drb_id; + if (sdap->defaultDRB) { + sdap_entity->default_drb = sdap->drb_id; LOG_I(SDAP, "Default DRB for the created SDAP entity: DRB %d \n", sdap_entity->default_drb); } // Add QoS flows to the DRB (initial configuration) - nr_sdap_add_qos_flows_to_drb(sdap_entity, &sdap); + nr_sdap_add_qos_flows_to_drb(sdap_entity, sdap); // update SDAP entity list pointers sdap_entity->next_entity = sdap_info.sdap_entity_llist; @@ -533,11 +533,11 @@ static void nr_sdap_add_entity(const int is_gnb, const ue_id_t ue_id, const sdap } /** @brief Add or modify an SDAP entity if it already exists */ -void nr_sdap_addmod_entity(const int is_gnb, const ue_id_t ue_id, const sdap_config_t sdap) +void nr_sdap_addmod_entity(const int is_gnb, const ue_id_t ue_id, const sdap_config_t *sdap) { - nr_sdap_entity_t *sdap_entity = nr_sdap_get_entity(ue_id, sdap.pdusession_id); + nr_sdap_entity_t *sdap_entity = nr_sdap_get_entity(ue_id, sdap->pdusession_id); if (sdap_entity) { - sdap_entity->qfi2drb_map_update(sdap_entity, &sdap); + sdap_entity->qfi2drb_map_update(sdap_entity, sdap); } else { nr_sdap_add_entity(is_gnb, ue_id, sdap); } diff --git a/openair2/SDAP/nr_sdap/nr_sdap_entity.h b/openair2/SDAP/nr_sdap/nr_sdap_entity.h index a206189035..e96836ac79 100644 --- a/openair2/SDAP/nr_sdap/nr_sdap_entity.h +++ b/openair2/SDAP/nr_sdap/nr_sdap_entity.h @@ -172,7 +172,7 @@ sdap_config_t nr_sdap_get_config(const int is_gnb, const NR_SDAP_Config_t *sdap_ void nr_sdap_release_drb(ue_id_t ue_id, int drb_id, int pdusession_id); /** @brief Add or modify an SDAP entity based on whether it already exists */ -void nr_sdap_addmod_entity(const int is_gnb, const ue_id_t ue_id, const sdap_config_t sdap); +void nr_sdap_addmod_entity(const int is_gnb, const ue_id_t ue_id, const sdap_config_t *sdap); /** * @brief Function to delete a single SDAP Entity based on the ue_id and pdusession_id. diff --git a/openair3/SCTP/sctp_eNB_task.c b/openair3/SCTP/sctp_eNB_task.c index 82afa451c0..567a166491 100644 --- a/openair3/SCTP/sctp_eNB_task.c +++ b/openair3/SCTP/sctp_eNB_task.c @@ -477,6 +477,7 @@ static void sctp_handle_new_association_req(const instance_t instance, if (errno != EINPROGRESS) { SCTP_ERROR("Connect failed: %s\n", strerror(errno)); sctp_itti_send_association_resp(requestor, instance, -1, req->ulp_cnx_id, SCTP_STATE_UNREACHABLE, 0, 0); + freeaddrinfo(serv); close(sd); return; } else { diff --git a/openair3/ocp-gtpu/gtp_itf.cpp b/openair3/ocp-gtpu/gtp_itf.cpp index aca2fcbb32..c524129098 100644 --- a/openair3/ocp-gtpu/gtp_itf.cpp +++ b/openair3/ocp-gtpu/gtp_itf.cpp @@ -152,6 +152,7 @@ class gtpEndPoint { } }; +static void gtpv1uReceiverCancel(pthread_t t); class gtpEndPoints { public: pthread_mutex_t gtp_lock = PTHREAD_MUTEX_INITIALIZER; @@ -168,8 +169,10 @@ class gtpEndPoints { ~gtpEndPoints() { // automatically close all sockets on quit - for (const auto &p : instances) + for (const auto &p : instances) { + gtpv1uReceiverCancel(p.second.thrData.t); close(p.first); + } } }; @@ -1283,7 +1286,7 @@ static int Gtpv1uHandleGpdu(int h, uint8_t *msgBuf, uint32_t msgBufLen, const st return !GTPNOK; } -static void gtpv1uReceiveHandleMessage(int h) +static bool gtpv1uReceiveHandleMessage(int h) { uint8_t udpData[65536]; int udpDataLen; @@ -1293,19 +1296,19 @@ static void gtpv1uReceiveHandleMessage(int h) if ((udpDataLen = recvfrom(h, udpData, sizeof(udpData), 0, (struct sockaddr *)&addr, &from_len)) < 0) { LOG_E(GTPU, "[%d] Recvfrom failed (%s)\n", h, strerror(errno)); - return; + return false; } else if (udpDataLen == 0) { LOG_W(GTPU, "[%d] Recvfrom returned 0\n", h); - return; + return true; } else { if (udpDataLen < (int)sizeof(Gtpv1uMsgHeaderT)) { LOG_W(GTPU, "[%d] received malformed gtp packet \n", h); - return; + return true; } Gtpv1uMsgHeaderT *msg = (Gtpv1uMsgHeaderT *)udpData; if ((int)(ntohs(msg->msgLength) + sizeof(Gtpv1uMsgHeaderT)) != udpDataLen) { LOG_W(GTPU, "[%d] received malformed gtp packet length\n", h); - return; + return true; } LOG_D(GTPU, "[%d] Received GTP data, msg type: %x\n", h, msg->msgType); switch (msg->msgType) { @@ -1337,18 +1340,27 @@ static void gtpv1uReceiveHandleMessage(int h) break; } } + return true; } static void* gtpv1uReceiver(void *thr) { gtpThread_t *gt = (gtpThread_t *)thr; - while (true) { - gtpv1uReceiveHandleMessage(gt->h); + while (gtpv1uReceiveHandleMessage(gt->h)) { } LOG_W(GTPU, "exiting thread\n"); return NULL; } +static void gtpv1uReceiverCancel(pthread_t t) +{ + int rc; + rc = pthread_cancel(t); + DevAssert(rc == 0); + rc = pthread_join(t, NULL); + DevAssert(rc == 0); +} + #include void *gtpv1uTask(void *args) @@ -1370,6 +1382,8 @@ void *gtpv1uTask(void *args) // DATA TO BE SENT TO UDP case TERMINATE_MESSAGE: + LOG_W(GTPU, "Exiting GTP instance %ld\n", myInstance); + itti_exit_task(); break; case TIMER_HAS_EXPIRED: diff --git a/tests/nr-cuup/CMakeLists.txt b/tests/nr-cuup/CMakeLists.txt index 02becb2496..9d48fd89e2 100644 --- a/tests/nr-cuup/CMakeLists.txt +++ b/tests/nr-cuup/CMakeLists.txt @@ -1,4 +1,14 @@ add_executable(nr-cuup-load-test nr-cuup-load-test.c) +add_dependencies(nr-cuup-load-test params_libconfig) target_link_libraries(nr-cuup-load-test PRIVATE GTPV1U ${T_LIB} utils ITTI e1ap SCTP_CLIENT) target_link_libraries(nr-cuup-load-test PRIVATE asn1_lte_rrc_hdrs asn1_nr_rrc_hdrs) # ITTI + +if(ENABLE_TESTS) + # we add also nr-cuup as it is required for the test + add_dependencies(tests nr-cuup-load-test nr-cuup) + add_test(NAME nr_cuup_functional_test + COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/nr-cuup-functional-test.sh ${CMAKE_CURRENT_SOURCE_DIR}/load-test.conf + WORKING_DIRECTORY ${CMAKE_BINARY_DIR} + ) +endif() diff --git a/tests/nr-cuup/nr-cuup-functional-test.sh b/tests/nr-cuup/nr-cuup-functional-test.sh new file mode 100755 index 0000000000..28a9b3779a --- /dev/null +++ b/tests/nr-cuup/nr-cuup-functional-test.sh @@ -0,0 +1,21 @@ +#!/bin/bash + +# this script takes one argument, which is the path to the CU-UP configuration +if [ $# -ne 1 ]; then + echo "usage: $0 " + exit 1 +fi + +CONFIG=$1 + +set -x + +# current dir should be CMAKE_BINARY_DIR +./nr-cuup -O ${CONFIG} & +CUUP_PID=$! + +timeout 5s ./tests/nr-cuup/nr-cuup-load-test -t 3 -d 10 -u 10 +RET=$? + +kill ${CUUP_PID} +exit ${RET} diff --git a/tests/nr-cuup/nr-cuup-load-test.c b/tests/nr-cuup/nr-cuup-load-test.c index 533b119c9e..0774b26b1b 100644 --- a/tests/nr-cuup/nr-cuup-load-test.c +++ b/tests/nr-cuup/nr-cuup-load-test.c @@ -28,6 +28,7 @@ #include "openair3/SCTP/sctp_eNB_task.h" #include "openair2/E1AP/e1ap.h" #include "openair3/ocp-gtpu/gtp_itf.h" +#include "openair2/E1AP/lib/e1ap_interface_management.h" configmodule_interface_t *uniqCfg; @@ -90,6 +91,7 @@ static void setup_cuup(sctp_assoc_t *assoc_id, e1ap_nssai_t *nssai) DevAssert(req->plmn[0].slice != NULL); *nssai = *req->plmn[0].slice; DevAssert(assoc_id != 0); + free_e1ap_cuup_setup_request(req); itti_free(TASK_GNB_APP, itti_req); // acknowledge the E1 setup request with a response @@ -664,6 +666,9 @@ int main(int argc, char *argv[]) success = false; } + free(ng_ip); + free(f1_ip); + if (success) LOG_A(GNB_APP, "test succeeded\n"); else