diff --git a/CMakeLists.txt b/CMakeLists.txt index 6d06d30c17..948f623f2b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -413,6 +413,7 @@ target_link_libraries(x2ap PRIVATE asn1_lte_rrc_hdrs asn1_nr_rrc_hdrs) set(F1AP_DIR ${OPENAIR2_DIR}/F1AP) add_library(f1ap ${F1AP_DIR}/f1ap_common.c + ${F1AP_DIR}/f1ap_ids.c ${F1AP_DIR}/f1ap_cu_interface_management.c ${F1AP_DIR}/f1ap_cu_paging.c ${F1AP_DIR}/f1ap_cu_rrc_message_transfer.c @@ -431,7 +432,7 @@ add_library(f1ap ${F1AP_DIR}/f1ap_itti_messaging.c) target_include_directories(f1ap PUBLIC F1AP_DIR) target_link_libraries(f1ap PUBLIC asn1_f1ap) -target_link_libraries(f1ap PRIVATE ngap nr_rrc) +target_link_libraries(f1ap PRIVATE ngap nr_rrc HASHTABLE) # LPP ############## diff --git a/openair2/F1AP/CMakeLists.txt b/openair2/F1AP/CMakeLists.txt index 7537bd661d..e6490b96b0 100644 --- a/openair2/F1AP/CMakeLists.txt +++ b/openair2/F1AP/CMakeLists.txt @@ -1 +1,8 @@ add_subdirectory(MESSAGES) + +if(ENABLE_TESTS) + add_executable(f1ap_ids_test f1ap_ids_test.c f1ap_ids.c) + target_link_libraries(f1ap_ids_test UTIL HASHTABLE minimal_lib) + add_dependencies(tests f1ap_ids_test) + add_test(NAME F1AP_ID_test COMMAND f1ap_ids_test) +endif() diff --git a/openair2/F1AP/f1ap_ids.c b/openair2/F1AP/f1ap_ids.c new file mode 100644 index 0000000000..e467e074fd --- /dev/null +++ b/openair2/F1AP/f1ap_ids.c @@ -0,0 +1,157 @@ +/* + * 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 + */ + +/* "standalone" module to store a "secondary" UE ID for each UE in DU/CU. + * Separate from the rest of F1, as it is also relevant for monolithic. */ + +#include "f1ap_ids.h" + +#include +#include "common/utils/hashtable/hashtable.h" +#include "common/utils/assertions.h" + + +/* we have separate versions for CU and DU, as both CU&DU might coexist in the + * same process */ +static hash_table_t *cu2du_ue_mapping; +static pthread_mutex_t cu2du_mutex = PTHREAD_MUTEX_INITIALIZER; + +void cu_init_f1_ue_data(void) +{ + pthread_mutex_lock(&cu2du_mutex); + DevAssert(cu2du_ue_mapping == NULL); + cu2du_ue_mapping = hashtable_create(1319, NULL, free); // 1319 is prime, default hash func (unit), free() + DevAssert(cu2du_ue_mapping != NULL); + pthread_mutex_unlock(&cu2du_mutex); +} + +bool cu_add_f1_ue_data(uint32_t ue_id, const f1_ue_data_t *data) +{ + pthread_mutex_lock(&cu2du_mutex); + DevAssert(cu2du_ue_mapping != NULL); + uint64_t key = ue_id; + if (hashtable_is_key_exists(cu2du_ue_mapping, key) == HASH_TABLE_OK) { + pthread_mutex_unlock(&cu2du_mutex); + return false; + } + f1_ue_data_t *idata = malloc(sizeof(*idata)); + AssertFatal(idata != NULL, "cannot allocate memory\n"); + *idata = *data; + hashtable_rc_t ret = hashtable_insert(cu2du_ue_mapping, key, idata); + pthread_mutex_unlock(&cu2du_mutex); + return ret == HASH_TABLE_OK; +} + +bool cu_exists_f1_ue_data(uint32_t ue_id) +{ + pthread_mutex_lock(&cu2du_mutex); + DevAssert(cu2du_ue_mapping != NULL); + uint64_t key = ue_id; + hashtable_rc_t ret = hashtable_is_key_exists(cu2du_ue_mapping, key); + pthread_mutex_unlock(&cu2du_mutex); + return ret == HASH_TABLE_OK; +} + +f1_ue_data_t cu_get_f1_ue_data(uint32_t ue_id) +{ + pthread_mutex_lock(&cu2du_mutex); + DevAssert(cu2du_ue_mapping != NULL); + uint64_t key = ue_id; + void *data = NULL; + hashtable_rc_t ret = hashtable_get(cu2du_ue_mapping, key, &data); + AssertFatal(ret == HASH_TABLE_OK && data != NULL, "element for ue_id %d not found\n", ue_id); + f1_ue_data_t ued = *(f1_ue_data_t *)data; + pthread_mutex_unlock(&cu2du_mutex); + return ued; +} + +bool cu_remove_f1_ue_data(uint32_t ue_id) +{ + pthread_mutex_lock(&cu2du_mutex); + DevAssert(cu2du_ue_mapping != NULL); + uint64_t key = ue_id; + hashtable_rc_t ret = hashtable_remove(cu2du_ue_mapping, key); + pthread_mutex_unlock(&cu2du_mutex); + return ret == HASH_TABLE_OK; +} + +/* DU version below */ +static hash_table_t *du2cu_ue_mapping; +static pthread_mutex_t du2cu_mutex = PTHREAD_MUTEX_INITIALIZER; + +void du_init_f1_ue_data(void) +{ + pthread_mutex_lock(&du2cu_mutex); + DevAssert(du2cu_ue_mapping == NULL); + du2cu_ue_mapping = hashtable_create(1319, NULL, free); // 1319 is prime, default hash func (unit), free() + DevAssert(du2cu_ue_mapping != NULL); + pthread_mutex_unlock(&du2cu_mutex); +} + +bool du_add_f1_ue_data(uint32_t ue_id, const f1_ue_data_t *data) +{ + pthread_mutex_lock(&du2cu_mutex); + DevAssert(du2cu_ue_mapping != NULL); + uint64_t key = ue_id; + if (hashtable_is_key_exists(du2cu_ue_mapping, key) == HASH_TABLE_OK) { + pthread_mutex_unlock(&du2cu_mutex); + return false; + } + f1_ue_data_t *idata = malloc(sizeof(*idata)); + AssertFatal(idata != NULL, "cannot allocate memory\n"); + *idata = *data; + hashtable_rc_t ret = hashtable_insert(du2cu_ue_mapping, key, idata); + pthread_mutex_unlock(&du2cu_mutex); + return ret == HASH_TABLE_OK; +} + +bool du_exists_f1_ue_data(uint32_t ue_id) +{ + pthread_mutex_lock(&du2cu_mutex); + DevAssert(du2cu_ue_mapping != NULL); + uint64_t key = ue_id; + hashtable_rc_t ret = hashtable_is_key_exists(du2cu_ue_mapping, key); + pthread_mutex_unlock(&du2cu_mutex); + return ret == HASH_TABLE_OK; +} + +f1_ue_data_t du_get_f1_ue_data(uint32_t ue_id) +{ + pthread_mutex_lock(&du2cu_mutex); + DevAssert(du2cu_ue_mapping != NULL); + uint64_t key = ue_id; + void *data = NULL; + hashtable_rc_t ret = hashtable_get(du2cu_ue_mapping, key, &data); + AssertFatal(ret == HASH_TABLE_OK && data != NULL, "element for ue_id %d not found\n", ue_id); + f1_ue_data_t ued = *(f1_ue_data_t *)data; + pthread_mutex_unlock(&du2cu_mutex); + return ued; +} + +bool du_remove_f1_ue_data(uint32_t ue_id) +{ + pthread_mutex_lock(&du2cu_mutex); + DevAssert(du2cu_ue_mapping != NULL); + uint64_t key = ue_id; + hashtable_rc_t ret = hashtable_remove(du2cu_ue_mapping, key); + pthread_mutex_unlock(&du2cu_mutex); + return ret == HASH_TABLE_OK; +} diff --git a/openair2/F1AP/f1ap_ids.h b/openair2/F1AP/f1ap_ids.h new file mode 100644 index 0000000000..96b146f6ba --- /dev/null +++ b/openair2/F1AP/f1ap_ids.h @@ -0,0 +1,48 @@ +/* + * 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 + */ + +/* "standalone" module to store a "secondary" UE ID for each UE in DU/CU. + * Separate from the rest of F1, as it is also relevant for monolithic. */ + +#ifndef F1AP_IDS_H_ +#define F1AP_IDS_H_ + +#include +#include + +typedef struct f1_ue_data_t { + uint32_t secondary_ue; + /* can be extended with F1-specific data also relevant for monolithic */ +} f1_ue_data_t; + +void cu_init_f1_ue_data(void); +bool cu_add_f1_ue_data(uint32_t ue_id, const f1_ue_data_t *data); +bool cu_exists_f1_ue_data(uint32_t ue_id); +f1_ue_data_t cu_get_f1_ue_data(uint32_t ue_id); +bool cu_remove_f1_ue_data(uint32_t ue_id); + +void du_init_f1_ue_data(void); +bool du_add_f1_ue_data(uint32_t ue_id, const f1_ue_data_t *data); +bool du_exists_f1_ue_data(uint32_t ue_id); +f1_ue_data_t du_get_f1_ue_data(uint32_t ue_id); +bool du_remove_f1_ue_data(uint32_t ue_id); + +#endif /* F1AP_IDS_H_ */ diff --git a/openair2/F1AP/f1ap_ids_test.c b/openair2/F1AP/f1ap_ids_test.c new file mode 100644 index 0000000000..3007db566a --- /dev/null +++ b/openair2/F1AP/f1ap_ids_test.c @@ -0,0 +1,42 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.openairinterface.org/?page_id=698 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ + +#include +#include +#include +#include "common/utils/assertions.h" +#include "f1ap_ids.h" + +int main() +{ + du_init_f1_ue_data(); + int rnti = 13; + f1_ue_data_t data = {.secondary_ue = 1}; + bool ret = du_add_f1_ue_data(rnti, &data); + DevAssert(ret); + ret = du_add_f1_ue_data(rnti, &data); + DevAssert(!ret); + bool exists = du_exists_f1_ue_data(rnti); + DevAssert(exists); + f1_ue_data_t rdata = du_get_f1_ue_data(rnti); + DevAssert(rdata.secondary_ue == data.secondary_ue); + return 0; +}