Compare commits

...

22 Commits

Author SHA1 Message Date
mir
878b3c3857 Added documentation for ds and ald 2023-04-13 17:08:13 +02:00
mir
e2de6719ee Reverse order of BIT_STRING_TO_TRANSPORT_LAYER_ADDRESS_IPv4 to original order 2023-04-13 17:08:13 +02:00
Raymond Knopp
e69feb9384 Removed #include <bits/types/struct_itimerspec.h> as it does not exist the path in Fedora 2023-04-13 17:08:13 +02:00
mir
65abd4b55b return value of malloc checked 2023-04-13 17:08:13 +02:00
Robert Schmidt
0583c5411a Add E2AP encoding/decoding tests 2023-04-13 17:08:13 +02:00
Robert Schmidt
2e0a39816e Provide config option to switch agent on/off 2023-04-13 17:08:13 +02:00
Robert Schmidt
d060ae2008 Provide build option to enable E2 Agent, default off 2023-04-13 17:08:13 +02:00
Robert Schmidt
95ba33d955 Rename E2AP Cmake variable to idenfify E2 library, Remove -fopt-info 2023-04-13 17:08:12 +02:00
Robert Schmidt
3e5e7abaab Integrate E2 Agent with OAI config system 2023-04-13 17:08:12 +02:00
Robert Schmidt
76216713db init_sctp_conn_client(): check return, null-terminate 2023-04-13 17:08:12 +02:00
Robert Schmidt
f10ca57b77 KPM SM updates 2023-04-13 17:08:12 +02:00
Robert Schmidt
8e8c6a7da3 Only load SM plugins ending on .so 2023-04-13 17:08:12 +02:00
Robert Schmidt
155761417d Generate SM SO in common directory 2023-04-13 17:08:12 +02:00
Robert Schmidt
1324d151ea Use OAI-provided time_average_now() function; rename to time_now_us() 2023-04-13 17:08:12 +02:00
Robert Schmidt
b385f1778c Use OAI-provided ngran_types 2023-04-13 17:08:12 +02:00
Robert Schmidt
d4ff3e8fb7 Use OAI-provided conversions.h 2023-04-13 17:08:12 +02:00
Robert Schmidt
28010c223c Move algs to common/ 2023-04-13 17:08:12 +02:00
Robert Schmidt
b3fd97bb99 Move E2AP data structures to common, reorganize E2AP build 2023-04-13 17:08:12 +02:00
Robert Schmidt
89108aa716 Remove unused data structures in E2 agent 2023-04-13 17:08:12 +02:00
Robert Schmidt
781f85e35d Create KPM ASN.1 during build time and Auto-trigger build 2023-04-13 17:08:12 +02:00
Robert Schmidt
e3a96bbeef Create E2AP during build time; prepend E2AP_ for E2AP types 2023-04-13 17:08:12 +02:00
mir
d370df812a First commit to add E2AP 2023-04-13 17:08:12 +02:00
269 changed files with 36608 additions and 26 deletions

View File

@@ -302,6 +302,19 @@ if (DEBUG_ASN1C)
add_definitions(-DHAVE_CONFIG_H)
endif()
#########################
##### E2 AGENT
#########################
#add_boolean_option() does not work -- why?
set(E2_AGENT "OFF" CACHE STRING "O-RAN E2 Agent")
set_property(CACHE E2_AGENT PROPERTY STRINGS "ON" "OFF")
if(E2_AGENT)
include_directories(openair2/E2AP)
endif()
##################################################
# ASN.1 grammar C code generation & dependencies #
##################################################
@@ -1553,6 +1566,10 @@ add_library(L2
)
target_link_libraries(L2 PRIVATE x2ap s1ap lte_rrc m2ap)
target_link_libraries(L2 PRIVATE asn1_lte_rrc_hdrs asn1_nr_rrc_hdrs)
if(E2_AGENT)
target_link_libraries(L2 PUBLIC e2_agent)
target_compile_definitions(L2 PRIVATE E2_AGENT)
endif()
add_library(MAC_NR ${MAC_NR_SRC})
target_link_libraries(MAC_NR PRIVATE asn1_lte_rrc_hdrs asn1_nr_rrc_hdrs)
@@ -1583,6 +1600,10 @@ add_library(e1_pdcp_if
target_link_libraries(e1_pdcp_if PRIVATE asn1_nr_rrc_hdrs asn1_lte_rrc_hdrs)
target_link_libraries(L2_NR PRIVATE f1ap x2ap s1ap ngap nr_rrc e1ap)
if(E2_AGENT)
target_link_libraries(L2_NR PUBLIC e2_agent)
target_compile_definitions(L2_NR PRIVATE E2_AGENT)
endif()
add_library(L2_LTE_NR
${L2_RRC_SRC}
@@ -2163,6 +2184,9 @@ target_link_libraries(lte-softmodem PRIVATE pthread m CONFIG_LIB rt crypt ${CRYP
target_link_libraries(lte-softmodem PRIVATE ${T_LIB})
target_link_libraries(lte-softmodem PRIVATE asn1_nr_rrc_hdrs asn1_lte_rrc_hdrs)
if(E2_AGENT)
target_compile_definitions(lte-softmodem PRIVATE E2_AGENT)
endif()
add_executable(oairu
${OPENAIR_DIR}/executables/lte-ru.c
@@ -2274,7 +2298,10 @@ endif()
# force the generation of ASN.1 so that we don't need to wait during the build
target_link_libraries(nr-softmodem PRIVATE
asn1_lte_rrc asn1_nr_rrc asn1_s1ap asn1_ngap asn1_m2ap asn1_m3ap asn1_x2ap asn1_f1ap asn1_lpp)
asn1_lte_rrc asn1_nr_rrc asn1_s1ap asn1_ngap asn1_m2ap asn1_m3ap asn1_x2ap asn1_f1ap asn1_lpp)
if(E2_AGENT)
target_compile_definitions(nr-softmodem PRIVATE E2_AGENT)
endif()
add_executable(nr-cuup
executables/nr-cuup.c
@@ -2668,6 +2695,9 @@ make_driver(ue_ip ${OPENAIR2_DIR}/NETWORK_DRIVER/UE_IP ${ue_ip_src})
include(${OPENAIR1_DIR}/PHY/CODING/nrLDPC_decoder/nrLDPC_tools/CMakeLists.txt)
enable_testing()
add_subdirectory(common)
add_subdirectory(doc)
add_subdirectory(openair1)

View File

@@ -261,3 +261,9 @@ log_config :
rrc_log_level ="info";
};
e2_agent = {
enable = 1;
address = "127.0.0.1";
port = 36421;
sm_dir = "/path/where/the/SMs/are/located/"
}

View File

@@ -78,6 +78,8 @@ Options:
Pass the supplied option verbatim to cmake.
-d | --build-dir
Sets build directory (will be <oai-root>/cmake_targets/<build-dir>/build)
--build-e2
Enable the the E2 Agent
-I | --install-external-packages
Installs required packages such as LibXML, asn1.1 compiler, ...
This option will require root password
@@ -197,6 +199,10 @@ function main() {
-d | --build-dir)
BUILD_DIR=$2
shift 2;;
--build-e2)
CMAKE_CMD="$CMAKE_CMD -DE2_AGENT=ON"
shift
;;
-I | --install-external-packages)
INSTALL_EXTERNAL=1
echo_info "Will install external packages"

View File

@@ -1 +1,3 @@
add_subdirectory(utils)
add_library(ngran_types OBJECT ngran_types.c)

22
common/ngran_types.c Normal file
View File

@@ -0,0 +1,22 @@
#include "ngran_types.h"
#include <assert.h>
#include <stddef.h>
char* get_ngran_name(ngran_node_t ran_type)
{
assert(ran_type >= 0);
switch (ran_type)
{
case ngran_eNB: return "ngran_eNB";
case ngran_ng_eNB: return "ngran_ng_eNB";
case ngran_gNB: return "ngran_gNB";
case ngran_eNB_CU: return "ngran_eNB_CU";
case ngran_ng_eNB_CU: return "ngran_ng_eNB_CU";
case ngran_gNB_CU: return "ngran_gNB_CU";
case ngran_eNB_DU: return "ngran_eNB_DU";
case ngran_gNB_DU: return "ngran_gNB_DU";
case ngran_eNB_MBMS_STA: return "ngran_eNB_MBMS_STA";
default: return NULL;
}
}

View File

@@ -57,4 +57,7 @@ typedef enum { CPtype = 0, UPtype } E1_t;
typedef enum { non_dynamic, dynamic } fiveQI_type_t;
#define maxSRBs 4
char* get_ngran_name(ngran_node_t ran_type);
#endif

View File

@@ -1,3 +1,4 @@
add_subdirectory(alg)
add_subdirectory(ds)
add_boolean_option(ENABLE_TELNETSRV OFF "Whether to build telnet support in modems" OFF)
if(ENABLE_TELNETSRV)

View File

@@ -0,0 +1,6 @@
add_library(alg OBJECT
defer.c
find.c
)
target_include_directories(alg PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})
target_link_libraries(alg PUBLIC ds)

66
common/utils/alg/alg.h Normal file
View File

@@ -0,0 +1,66 @@
/*
MIT License
Copyright (c) 2021 Mikel Irazabal
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#ifndef ALG_MIR_H
#define ALG_MIR_H
#include <assert.h>
#include <stddef.h>
#include <stdint.h>
#include <string.h>
#include "find.h"
#include "defer.h"
/*
* Check at compile time that something is of a particular type.
* Always evaluates to 1 so you may use it easily in comparisons.
*/
#define typecheck(type, x) \
({ \
type __dummy; \
typeof(x) __dummy2; \
(void)(&__dummy == &__dummy2); \
1; \
})
#define swap(x,y) do \ { uint8_t swap_temp[sizeof(x) == sizeof(y) ? (signed)sizeof(x) : -1]; \
memcpy(swap_temp,&y,sizeof(x)); \
memcpy(&y,&x, sizeof(x)); \
memcpy(&x,swap_temp,sizeof(x)); \
} while(0)
/*
* Find an element in a data structure if the predicate is true
*/
#define find_if(T,U,W,X,Y) _Generic ((T), seq_arr_t*: find_if_arr, \
assoc_rb_tree_t*: find_if_rb_tree, \
default: find_if_arr) (T,U,W,X,Y)
#endif

39
common/utils/alg/defer.c Normal file
View File

@@ -0,0 +1,39 @@
/*
MIT License
Copyright (c) 2021 Mikel Irazabal
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#include "defer.h"
#if defined __clang__ // requires -fblocks (lambdas)
void cleanup_deferred (void (^*d) (void))
{
(*d)();
}
#elif defined __GNUC__ // nested-function-in-stmt-expressionstatic
void cleanup_deferred (void (**d) (void))
{
(*d)();
}
#endif

67
common/utils/alg/defer.h Normal file
View File

@@ -0,0 +1,67 @@
/*
MIT License
Copyright (c) 2021 Mikel Irazabal
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#ifndef DEFER_H
#define DEFER_H
/*
* Defer mechanism taken from http://www.open-std.org/jtc1/sc22/wg14/www/docs/n2542.pdf
* It may become part of the C2X standard in <stddefer.h>
* Basically, what is included in the defer statement, will be executed when the end of the
* scope where it was defined happened i.e., it uses the same mechanims as the C++ destructors
*/
#define CONCAT_IMPL( x, y ) x##y
#define MACRO_CONCAT( x, y ) CONCAT_IMPL( x, y )
#define FUNC_DEFER4 MACRO_CONCAT(DF_, __LINE__ )
#define FUNC_DEFER3 MACRO_CONCAT(FUNC_DEFER4, _line_ )
#define FUNC_DEFER2 MACRO_CONCAT(FUNC_DEFER3, __COUNTER__ )
#define FUNC_DEFER MACRO_CONCAT(FUNC_DEFER2, _counter )
#define FUNC_DEFER_IMPL MACRO_CONCAT(FUNC_DEFER3, __impl )
#if defined __clang__ // requires -fblocks (lambdas) and -lBlocksRuntime in the linker
void cleanup_deferred (void (^*d) (void));
#define defer(...) \
__attribute__((__cleanup__ (cleanup_deferred))) \
__attribute__((unused)) void (^FUNC_DEFER) (void) = ^__VA_ARGS__
#elif defined __GNUC__ // nested-function-in-stmt-expression
void cleanup_deferred (void (**d) (void));
#define defer(...) \
__attribute__((__cleanup__ (cleanup_deferred))) \
void (*FUNC_DEFER) (void) = ({ \
void FUNC_DEFER_IMPL (void) __VA_ARGS__ \
FUNC_DEFER_IMPL; })
#endif
#endif

82
common/utils/alg/find.c Normal file
View File

@@ -0,0 +1,82 @@
/*
MIT License
Copyright (c) 2021 Mikel Irazabal
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#include "find.h"
#include <assert.h>
#include <stdlib.h>
#include <stdio.h>
void* find_if_arr(seq_arr_t* arr, void* start_it, void* end_it, void* value, bool (*f)(const void*, const void*))
{
assert(arr != NULL);
while (start_it != end_it) {
if (f(value, start_it))
return start_it;
start_it = seq_next(arr, start_it);
}
return start_it;
}
void* find_if_rb_tree(assoc_rb_tree_t* tree, void* start_it, void* end_it, void const* value, bool (*f)(const void*, const void*))
{
assert(tree != NULL);
while (start_it != end_it) {
if (f(value, assoc_key(tree, start_it)))
return start_it;
start_it = assoc_next(tree, start_it);
}
return start_it;
}
bml_iter_t find_if_bi_map_left(bi_map_t* map, bml_iter_t start_it, bml_iter_t end_it, void const* value, bool (*f)(const void*, const void*))
{
assert(map != NULL);
assert(start_it.it != NULL);
while (start_it.it != end_it.it) {
if (f(value, assoc_key(&map->left, start_it.it)))
return start_it;
start_it = bi_map_next_left(map, start_it);
}
return start_it;
}
bmr_iter_t find_if_bi_map_right(bi_map_t* map, bmr_iter_t start_it, bmr_iter_t end_it, void const* value, bool (*f)(const void*, const void*))
{
assert(map != NULL);
assert(start_it.it != NULL);
while (start_it.it != end_it.it) {
if (f(value, start_it.it) == true)
return start_it;
start_it = bi_map_next_right(map, start_it);
}
return start_it;
}

57
common/utils/alg/find.h Normal file
View File

@@ -0,0 +1,57 @@
/*
MIT License
Copyright (c) 2021 Mikel Irazabal
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#ifndef FIND_ALGORITHM
#define FIND_ALGORITHM
#include <stdbool.h>
#include <stddef.h>
#include "seq_container/seq_generic.h"
#include "assoc_container/assoc_generic.h"
#include "assoc_container/bimap.h"
/*
* It returns the first position in the data structure where the predicate i.e., param f, returns true
* @param ds: data structure
* @param start_it: valid iterator position within the seq_arr_t.
* @param end_it: end iterator position. range [start_it, end). end needs to be reacheable from start_it.
* @param value: the value to compare with.
* @param f: the predicate. Returns true if the value and the object pointed to by the iterator match. value is
* the first argument and the iterator the second
* */
// Sequencial containers
void* find_if_arr(seq_arr_t* ds, void* start_it, void* end_it, void* value, bool (*f)(const void*, const void*));
// Associative containers
void* find_if_rb_tree(assoc_rb_tree_t* ds, void* start_it, void* end_it, void const* value, bool (*f)(const void*, const void*));
bml_iter_t find_if_bi_map_left(bi_map_t* ds, bml_iter_t start_it, bml_iter_t end_it, void const* value, bool (*f)(const void*, const void*));
bmr_iter_t find_if_bi_map_right(bi_map_t* ds, bmr_iter_t start_it, bmr_iter_t end_it, void const* value, bool (*f)(const void*, const void*));
#endif

View File

@@ -0,0 +1,36 @@
cmake_minimum_required(VERSION 3.5)
project(lock_guard)
set(default_build_type "Debug")
set(SANITIZER "ADDRESS" CACHE STRING "Sanitizers")
set_property(CACHE SANITIZER PROPERTY STRINGS "NONE" "ADDRESS" "THREAD")
message(STATUS "Selected SANITIZER TYPE: ${SANITIZER}")
if(SANITIZER STREQUAL "ADDRESS")
add_compile_options("-fno-omit-frame-pointer;-fsanitize=address;-Wall;-Werror;-g")
add_link_options("-fsanitize=address")
elseif(SANITIZER STREQUAL "THREAD" )
add_compile_options("-fsanitize=thread;-g;")
add_link_options("-fsanitize=thread;")
endif()
option(CODE_COVERAGE "Code coverage" ON)
if(CODE_COVERAGE)
add_compile_options("-fprofile-arcs;-ftest-coverage")
add_link_options("-lgcov;-coverage;")
message("Code Coverage cmd: cd CMakeFiles/tc.dir && lcov --capture --directory . --output-file coverage.info && genhtml coverage.info --output-directory out && cd out && firefox index.html")
endif()
option(CODE_PROFILER "Code Profiler" ON)
if(CODE_PROFILER)
add_compile_options("-pg")
add_link_options("-pg")
message("Code Profiler cmd: gprof tc gmon.out > analysis.txt && vim analysis.txt ")
endif()
add_executable(test_lock_guard test.c)
target_link_libraries(test_lock_guard PRIVATE pthread alg)

View File

@@ -0,0 +1,68 @@
/*
MIT License
Copyright (c) 2022 Mikel Irazabal
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#ifndef MIR_LOCK_GUARD_H
#define MIR_LOCK_GUARD_H
#include "defer.h"
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <pthread.h>
/*
* Lock guard mechanism in C, similar to std::lock_guard. The lock unlocks at the end of the scope.
* Very helpfull to avoid forgetting unlock from functions with multiple return statements.
* Similar to the mechanism found at QEMU_LOCK_GUARD
* @param X pthread_mutex_t* or pthread_mutex_t const*
*/
void mir_dummy_lock_guard();
void mir_dummy_lock_guard_const();
#define CHECK_TYPE_INLINE(val, type) (void)_Generic((val), type: mir_dummy_lock_guard, const type: mir_dummy_lock_guard_const)
#define lock_guard(X) \
do{ CHECK_TYPE_INLINE(X, pthread_mutex_t*);\
int rc = pthread_mutex_lock(X); \
if (rc != 0){ \
fprintf(stdout, "Error while locking, possibly the lock is already locked: %s\n", strerror(rc)); \
fflush(stdout); \
assert(0!=0); \
exit(-1); \
} \
} while(0); \
defer( { int rc = pthread_mutex_unlock(X); \
if(rc != 0){ \
fprintf(stdout, "Error while unlocking: %s\n", strerror(rc) ); \
fflush(stdout); \
assert(0!=0); \
exit(-1); \
} \
}); \
#endif

View File

@@ -0,0 +1,72 @@
/*
MIT License
Copyright (c) 2021 Mikel Irazabal
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#include "lock_guard.h"
#include <stdio.h>
static
int dummy_func(pthread_mutex_t* m)
{
lock_guard(m);
for(int i =0; i < 10; ++i){
printf("Value of the function = %d \n",i);
}
return 0;
}
int main()
{
pthread_mutex_t mtx; // = PTHREAD_MUTEX_INITIALIZER;
pthread_mutexattr_t attr;
int rc = pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_ERRORCHECK);
assert(rc == 0);
rc = pthread_mutex_init(&mtx, &attr);
assert(rc == 0);
dummy_func(&mtx);
{
lock_guard(&mtx);
}
lock_guard(&mtx);
// rc = pthread_mutex_unlock(&mtx);
// if(rc != 0){
// fprintf(stdout, "Error while locking: %s\n", strerror(rc) );
// exit(-1);
// }
for(int i =0; i < 10; ++i){
printf("Value of i = %d \n",i);
}
return 0;
}

View File

@@ -1,5 +1,8 @@
add_library(ds OBJECT
byte_array.c
assoc_container/assoc_rb_tree.c
assoc_container/bimap.c
seq_container/seq_arr.c
)
target_include_directories(ds PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})

View File

@@ -0,0 +1,66 @@
/*
MIT License
Copyright (c) 2021 Mikel Irazabal
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#ifndef ASSOCCIATIVE_CONTAINERS_GENERIC
#define ASSOCCIATIVE_CONTAINERS_GENERIC
#include "assoc_rb_tree.h"
// Initialization
#define assoc_init(T, KS, C, F) _Generic ((T), assoc_rb_tree_t*: assoc_rb_tree_init, \
default: assoc_rb_tree_init) (T, KS, C, F)
#define assoc_free(T) _Generic ((T), assoc_rb_tree_t*: assoc_rb_tree_free, \
default: assoc_rb_tree_free)(T)
// Modifiers
#define assoc_insert(T, K, KS, V) _Generic ((T), assoc_rb_tree_t*: assoc_rb_tree_insert, \
default: assoc_rb_tree_insert)(T,K,KS,V)
#define assoc_extract(T, K) _Generic ((T), assoc_rb_tree_t*: assoc_rb_tree_extract, \
default: assoc_rb_tree_extract)(T,K)
#define assoc_key(T,U) _Generic ((T), assoc_rb_tree_t*: assoc_rb_tree_key, \
default: assoc_rb_tree_key)(T,U)
#define assoc_value(T,U) _Generic ((T), assoc_rb_tree_t*: assoc_rb_tree_value, \
default: assoc_rb_tree_value)(T,U)
// Capacity
#define assoc_size(T) _Generic ((T), assoc_rb_tree_t*: assoc_rb_tree_size, \
default: assoc_rb_tree_size)(T)
// Forward Iterator Concept
#define assoc_front(T) _Generic ((T), assoc_rb_tree_t*: assoc_rb_tree_front, \
default: assoc_rb_tree_front)(T)
#define assoc_next(T,U) _Generic((T), assoc_rb_tree_t*: assoc_rb_tree_next, \
default: assoc_rb_tree_next)(T,U)
#define assoc_end(T) _Generic((T), assoc_rb_tree_t*: assoc_rb_tree_end, \
default: assoc_rb_tree_end)(T)
#endif

View File

@@ -0,0 +1,499 @@
/*
MIT License
Copyright (c) 2021 Mikel Irazabal
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
/*
RB tree implemented a la CLRS by mir
Red-Black trees have 5 properties:
1- Every node is Red or Black
2- The root is black
3- Every leaf is black
4- If a node is red, then both its children are black
5- For each node, all simple paths from the node to descendant leaves contain the same number of black nodes
Lemma 1: a red-black tree with n internal nodes has a height at most 2lg(n+1)
*/
#include "assoc_rb_tree.h"
#include <assert.h>
#include <stddef.h>
#include <stdlib.h>
#include <string.h>
typedef enum {
ASSOC_BLACK,
ASSOC_RED,
} assoc_color_e;
typedef struct assoc_node_s {
void* key;
void* value;
struct assoc_node_s* parent;
struct assoc_node_s* left;
struct assoc_node_s* right;
assoc_color_e color;
} assoc_node_t;
static assoc_node_t* init_node(void* key, void* value)
{
assoc_node_t* n = malloc(sizeof(assoc_node_t));
assert(n != NULL && "Memory exhausted");
n->key = key;
n->value = value;
n->parent = NULL;
n->left = NULL;
n->right = NULL;
n->color = ASSOC_RED;
return n;
}
static assoc_node_t* create_node_rb_tree(assoc_rb_tree_t* tree, void* key, void* value)
{
assoc_node_t* x = init_node(key, value);
x->parent = tree->dummy;
x->left = tree->dummy;
x->right = tree->dummy;
return x;
}
static void free_node_rb_tree(assoc_node_t* n)
{
assert(n != NULL);
free(n->key);
// free(n->value);
free(n);
}
static void depth_first_search_free(assoc_rb_tree_t* tree, assoc_node_t* node, void (*f)(void* key, void* value))
{
assert(tree != NULL);
assert(node != NULL);
if (node != tree->dummy) {
depth_first_search_free(tree, node->left, f);
depth_first_search_free(tree, node->right, f);
if (f != NULL)
f(node->key, node->value);
free_node_rb_tree(node);
}
}
void assoc_rb_tree_init(assoc_rb_tree_t* tree, size_t key_sz, int (*comp_func)(const void*, const void*), free_func_t free_func)
{
assert(tree != NULL);
assert(key_sz > 0);
tree->dummy = init_node(NULL, NULL);
tree->dummy->color = ASSOC_BLACK;
tree->root = tree->dummy;
tree->comp = comp_func;
tree->size = 0;
tree->key_sz = key_sz;
tree->free_func = free_func;
}
void assoc_rb_tree_free(assoc_rb_tree_t* tree)
{
assert(tree != NULL);
depth_first_search_free(tree, tree->root, tree->free_func);
free(tree->dummy);
}
static void left_rotate(assoc_rb_tree_t* tree, assoc_node_t* x_node)
{
assert(tree != NULL);
assert(x_node != NULL);
assert(x_node->right != tree->dummy);
assoc_node_t* y_node = x_node->right;
x_node->right = y_node->left;
if (y_node->left != tree->dummy)
y_node->left->parent = x_node;
y_node->parent = x_node->parent;
if (x_node->parent == tree->dummy)
tree->root = y_node;
else if (x_node == x_node->parent->left)
x_node->parent->left = y_node;
else
x_node->parent->right = y_node;
y_node->left = x_node;
x_node->parent = y_node;
}
static void right_rotate(assoc_rb_tree_t* tree, assoc_node_t* x_node)
{
assert(tree != NULL);
assert(x_node != NULL);
assert(x_node->left != tree->dummy);
assoc_node_t* y_node = x_node->left;
x_node->left = y_node->right;
if (y_node->right != tree->dummy)
y_node->right->parent = x_node;
y_node->parent = x_node->parent;
if (x_node->parent == tree->dummy)
tree->root = y_node;
else if (x_node->parent->left == x_node)
x_node->parent->left = y_node;
else
x_node->parent->right = y_node;
y_node->right = x_node;
x_node->parent = y_node;
}
static void insert_fixup(assoc_rb_tree_t* tree, assoc_node_t* z_node)
{
while (z_node->parent->color == ASSOC_RED) {
// z_node->parent.color == RED) which means:
// 1- violating only property 4 of the red-black tree
// 2- z_node->parent was not the root by property 2, root must be black
// 3- z_node->parent->parent must exist and is Black, since Red-Red is illegal
assoc_node_t* parent = z_node->parent;
assoc_node_t* grand_parent = z_node->parent->parent;
if (parent == grand_parent->left) {
assoc_node_t* uncle = grand_parent->right;
// Case 1: uncle is Red, flip colors and continue up the tree
if (uncle->color == ASSOC_RED) {
parent->color = ASSOC_BLACK;
uncle->color = ASSOC_BLACK;
grand_parent->color = ASSOC_RED;
z_node = grand_parent;
} else { // uncle is BLACK
// Case 2: z_node at right
if (z_node == parent->right) {
z_node = parent;
left_rotate(tree, z_node);
parent = z_node->parent; // the grand_parent is the same, so do not refresh
}
// Case 3: z_node at left
parent->color = ASSOC_BLACK;
grand_parent->color = ASSOC_RED;
right_rotate(tree, grand_parent);
}
} else {
assoc_node_t* uncle = grand_parent->left;
if (uncle->color == ASSOC_RED) {
parent->color = ASSOC_BLACK;
uncle->color = ASSOC_BLACK;
grand_parent->color = ASSOC_RED;
z_node = grand_parent;
} else { // uncle->color == BLACK
if (z_node == parent->left) {
z_node = parent;
right_rotate(tree, z_node);
parent = z_node->parent; // the grand_parent is the same, so do not refresh
}
parent->color = ASSOC_BLACK;
grand_parent->color = ASSOC_RED;
left_rotate(tree, grand_parent);
}
}
}
// Assure that property 2 of the red-black tree is maintained
tree->root->color = ASSOC_BLACK;
}
void assoc_rb_tree_insert(assoc_rb_tree_t* tree, void const* key, size_t key_sz, void* value)
{
assert(tree != NULL);
assert(tree->key_sz == key_sz && "Size mismatch");
void* key_dst = malloc(key_sz);
assert(key_dst != NULL && "Memory exhausted");
memcpy(key_dst, key, key_sz);
assoc_node_t* z_node = create_node_rb_tree(tree, key_dst, value);
assert(z_node != tree->dummy);
assert(z_node->parent == tree->dummy);
assert(z_node->left == tree->dummy);
assert(z_node->right == tree->dummy);
assert(z_node->color == ASSOC_RED);
assoc_node_t* x_node = tree->root;
assoc_node_t* y_node = tree->dummy;
// Find leaf to insert
while (x_node != tree->dummy) {
y_node = x_node;
if (tree->comp(z_node->key, x_node->key) == 1)
x_node = x_node->left;
else
x_node = x_node->right;
}
z_node->parent = y_node;
if (y_node == tree->dummy)
tree->root = z_node;
else if (tree->comp(z_node->key, y_node->key) == 1)
y_node->left = z_node;
else
y_node->right = z_node;
insert_fixup(tree, z_node);
tree->size++;
}
static void delete_fixup(assoc_rb_tree_t* tree, assoc_node_t* x_node)
{
while (x_node != tree->root && x_node->color == ASSOC_BLACK) {
if (x_node == x_node->parent->left) {
assoc_node_t* w_node = x_node->parent->right;
// Case 1: x's sibling is RED
if (w_node->color == ASSOC_RED) {
w_node->color = ASSOC_BLACK;
x_node->parent->color = ASSOC_RED;
left_rotate(tree, x_node->parent);
w_node = x_node->parent->right;
}
assert(w_node->color == ASSOC_BLACK);
// Case 2: x's siblings nodes are both black and w itself is black
if (w_node->left->color == ASSOC_BLACK && w_node->right->color == ASSOC_BLACK) {
w_node->color = ASSOC_RED;
// if we come from Case 1, this will terminate, as x_node->parent == RED
// else, spread the problem to upper levels in the tree
// (maybe left and right branch decompensated after removing
// black node in the left branch).
x_node = x_node->parent;
} else {
// Case 3: x's sibling w is black w->left->color == RED && w->right->color == BLACK
if (w_node->right->color == ASSOC_BLACK) {
assert(w_node->color == ASSOC_BLACK);
assert(w_node->left->color == ASSOC_RED);
w_node->left->color = ASSOC_BLACK;
w_node->color = ASSOC_RED;
right_rotate(tree, w_node);
w_node = x_node->parent->right;
}
// Case 4: x's sibling is black and w's right child is red
assert(w_node->color == ASSOC_BLACK);
assert(w_node->right->color == ASSOC_RED);
w_node->color = x_node->parent->color;
x_node->parent->color = ASSOC_BLACK;
// since w_node->right->color == RED we insert a new black
// in the w_node path, changing the color
w_node->right->color = ASSOC_BLACK;
// the rotation adds one black in the x_node path and deletes
// one in the w_node path. As a result after the function, the x_node path
// gets one extra black in the w_node, and ends with the number of blacks
// +1, -1
left_rotate(tree, x_node->parent);
x_node = tree->root;
}
} else {
assoc_node_t* w_node = x_node->parent->left;
// Case 1: x' sibling is red
if (w_node->color == ASSOC_RED) {
w_node->color = ASSOC_BLACK;
x_node->parent->color = ASSOC_RED;
right_rotate(tree, x_node->parent);
w_node = x_node->parent->left;
}
assert(w_node->color == ASSOC_BLACK);
// Case 2: x' siblings nodes are both black and w itself is black
if (w_node->left->color == ASSOC_BLACK && w_node->right->color == ASSOC_BLACK) {
w_node->color = ASSOC_RED;
x_node = x_node->parent;
} else {
// Case 3: x's sibling w is black w->left == RED && w->right == BLACK
if (w_node->left->color == ASSOC_BLACK) {
assert(w_node->color == ASSOC_BLACK);
assert(w_node->right->color == ASSOC_RED);
w_node->right->color = ASSOC_BLACK;
w_node->color = ASSOC_RED;
left_rotate(tree, w_node);
w_node = x_node->parent->left;
}
// Case 4: x's sibling is black and w's left child is red
assert(w_node->color == ASSOC_BLACK);
assert(w_node->left->color == ASSOC_RED);
w_node->color = x_node->parent->color;
x_node->parent->color = ASSOC_BLACK;
w_node->left->color = ASSOC_BLACK;
right_rotate(tree, x_node->parent);
x_node = tree->root;
}
}
}
x_node->color = ASSOC_BLACK;
}
static void transplant(assoc_rb_tree_t* tree, assoc_node_t* u_node, assoc_node_t* v_node)
{
assert(u_node != tree->dummy);
if (u_node->parent == tree->dummy)
tree->root = v_node;
else if (u_node == u_node->parent->left)
u_node->parent->left = v_node;
else
u_node->parent->right = v_node;
v_node->parent = u_node->parent;
}
static assoc_node_t* minimum(assoc_rb_tree_t const* tree, assoc_node_t* x_node)
{
if (x_node == tree->dummy)
return tree->dummy;
while (x_node->left != tree->dummy)
x_node = x_node->left;
return x_node;
}
static assoc_node_t* find_rb_tree(assoc_rb_tree_t* tree, assoc_node_t* node, void* key)
{
assert(tree != NULL);
assert(node != NULL);
assert(key != NULL);
while (node != tree->dummy) {
int rc = tree->comp(key, node->key);
if (rc == 1)
node = node->left;
else if (rc == -1)
node = node->right;
else {
assert(rc == 0);
break;
}
}
return node;
}
void* assoc_rb_tree_extract(assoc_rb_tree_t* tree, void* key)
{
assert(tree != NULL);
assert(key != NULL);
assoc_node_t* z_node = find_rb_tree(tree, tree->root, key);
assert(z_node != tree->dummy && "Trying to extract a key not found in the tree");
assoc_color_e original_color = z_node->color;
assoc_node_t* x_node = z_node;
assoc_node_t* y_node = z_node;
if (z_node->left == tree->dummy) {
x_node = z_node->right;
transplant(tree, z_node, z_node->right);
// note that nobody points to z_node, even though z_node still points to parent and right
} else if (z_node->right == tree->dummy) {
x_node = z_node->left;
transplant(tree, z_node, z_node->left);
} else {
y_node = minimum(tree, z_node->right);
original_color = y_node->color;
x_node = y_node->right;
if (y_node->parent == z_node) {
x_node->parent = y_node; // necessary when x_node is the dummy node
} else {
transplant(tree, y_node, y_node->right);
y_node->right = z_node->right;
y_node->right->parent = y_node;
}
transplant(tree, z_node, y_node);
y_node->left = z_node->left;
y_node->left->parent = y_node;
y_node->color = z_node->color;
}
void* value = z_node->value;
// free(z_node->key);
// free(z_node);
free_node_rb_tree(z_node);
if (original_color == ASSOC_BLACK)
delete_fixup(tree, x_node);
assert(tree->size != 0);
tree->size--;
return value;
}
void* assoc_rb_tree_front(assoc_rb_tree_t const* tree)
{
assert(tree != NULL);
// Returns, tree's most left child node
assoc_node_t* node = minimum(tree, tree->root);
return node;
}
void* assoc_rb_tree_next(assoc_rb_tree_t const* tree, void* it)
{
assert(tree != NULL);
assert(it != NULL);
assoc_node_t* node = (assoc_node_t*)it;
assert(node != tree->dummy && "No next node since the end reached");
// a) If you have right child node find it
if (node->right != tree->dummy) {
node = minimum(tree, node->right);
return node;
}
// b) If you come from the parent's left stop. Otherwise go up untill
// c) you come from parent's left or
// d) you found the end of the tree
assoc_node_t* p = node->parent;
while (p != tree->dummy && p->left != node) {
node = p;
p = node->parent;
}
return p;
}
void* assoc_rb_tree_end(assoc_rb_tree_t const* tree)
{
assert(tree != NULL);
return tree->dummy;
}
void* assoc_rb_tree_key(assoc_rb_tree_t* tree, void* it)
{
assert(tree != NULL);
assert(it != tree->dummy && "end iterator passed?");
return ((assoc_node_t*)it)->key;
}
// Get the value pointer form an iterator
void* assoc_rb_tree_value(assoc_rb_tree_t* tree, void* it)
{
assert(tree != NULL);
assert(it != tree->dummy && "end iterator passed?");
return ((assoc_node_t*)it)->value;
}
size_t assoc_rb_tree_size(assoc_rb_tree_t* tree)
{
assert(tree != NULL);
return tree->size;
}

View File

@@ -0,0 +1,155 @@
/*
MIT License
Copyright (c) 2021 Mikel Irazabal
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#ifndef ASSOCIATIVE_RB_TREE_NAIVE
#define ASSOCIATIVE_RB_TREE_NAIVE
/*
RB tree implemented a la CLRS
Red-Black trees have 5 properties:
1- Every node is Red or Black
2- The root is black
3- Every leaf is black
4- If a node is red, then both its children are black
5- For each node, all simple paths from the node to descendant leaves contain the same number of black nodes
Lemma 1: a red-black tree with n internal nodes has a height at most 2lg(n+1)
*/
#include <stdbool.h>
#include <stddef.h>
typedef struct assoc_node_s assoc_node_t;
typedef void (*free_func_t)(void* key, void* value);
typedef struct {
assoc_node_t* dummy; // node
assoc_node_t* root; // node
int (*comp)(const void*, const void*);
size_t size;
// size key
size_t key_sz;
free_func_t free_func;
// size value
// size_t val_sz; // Value is always a pointer to the type
} assoc_rb_tree_t;
/*
* Init the rb ds
* @param tree: the ds to initialize
* @param key_sz: Size of the key i.e., sizeof(T), that the rb_tree will store.
* @param comp: Compare function in the RB tree.
* @param t: Free function to free the value if needed
*/
void assoc_rb_tree_init(assoc_rb_tree_t* tree, size_t key_sz, int (*comp)(const void*, const void*), free_func_t f);
/*
* Free the rb ds
* @param tree: the ds
*/
void assoc_rb_tree_free(assoc_rb_tree_t* tree);
// Modifiers
// The tree is responsible for freeing the void* key and value memory later
/*
* Insert key-value
* @param tree: the ds
* @param key a pointer to the key
* @param key_sz sizeof(key)
* @param value Pointer to the value. Ownership is transfere i.e., the RB tree will
* free it. It needs to be allocated in the heap
*/
void assoc_rb_tree_insert(assoc_rb_tree_t* tree, void const* key, size_t key_sz, void* value);
/*
* Extract value It returns the void* of value. the void* of the key is freed
* @param tree: the ds
* @param key a pointer to the key
* @return value
* @pre @p key must exist in the ds
*/
void* assoc_rb_tree_extract(assoc_rb_tree_t* tree, void* key);
/*
* Get the key from an iterator
* @param tree: the ds
* @param it a pointer to the key
* @return key from the ds. It does not free it.
* @pre @p it must exist in the ds
*/
void* assoc_rb_tree_key(assoc_rb_tree_t* tree, void* it);
/*
* Get the value pointer form an iterator
* @param tree: the ds
* @param it a pointer to the key
* @return key from the ds. It does not free it.
* @pre @p it must exist in the ds
*/
void* assoc_rb_tree_value(assoc_rb_tree_t* tree, void* it);
/*
* Size of the current ds
* @param tree: the ds
* @return number of elements in the ds
*/
size_t assoc_rb_tree_size(assoc_rb_tree_t* tree);
// Forward Iterator Concept
/*
* Get the iterator to the first element
* @param tree: the ds
* @return iterator to the first element
*/
void* assoc_rb_tree_front(assoc_rb_tree_t const* tree);
/*
* Get the next iterator
* @param tree: the ds
* @param it iterator
* @return iterator to the next element
* @pre iterator must be in the ds
*/
void* assoc_rb_tree_next(assoc_rb_tree_t const* tree, void* it);
/*
* Get the last iterator
* @param tree: the ds
* @return iterator to one past the last element in the ds
*/
void* assoc_rb_tree_end(assoc_rb_tree_t const* tree);
#endif

View File

@@ -0,0 +1,188 @@
/*
MIT License
Copyright (c) 2021 Mikel Irazabal
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#include "bimap.h"
#include "assoc_generic.h"
#include <assert.h>
#include <stdlib.h>
#include <string.h>
void bi_map_init(bi_map_t* map, size_t key_sz1, size_t key_sz2, bi_map_cmp cmp1, bi_map_cmp cmp2, free_func_t free1, free_func_t free2)
{
assert(map != NULL);
assert(key_sz1 > 0);
assert(key_sz2 > 0);
assert(cmp1 != NULL);
assert(cmp2 != NULL);
assoc_init(&map->left, key_sz1, cmp1, free1);
assoc_init(&map->right, key_sz2, cmp2, free2);
}
void bi_map_free(bi_map_t* map)
{
assert(map != NULL);
assoc_free(&map->left);
assoc_free(&map->right);
}
// Modifiers
void bi_map_insert(bi_map_t* map, void const* key1, size_t key_sz1, void const* key2, size_t key_sz2)
{
assert(map != NULL);
assert(key1 != NULL);
assert(key_sz1 > 0);
assert(key2 != NULL);
assert(key_sz2 > 0);
void* val1 = malloc(key_sz2);
assert(val1 != NULL && "Memory exhausted");
memcpy(val1, key2, key_sz2);
assoc_insert(&map->left, key1, key_sz1, val1);
void* val2 = malloc(key_sz1);
assert(val2 != NULL && "Memory exhausted");
memcpy(val2, key1, key_sz1);
assoc_insert(&map->right, key2, key_sz2, val2);
}
// It returns the void* of key2. the void* of the key1 is freed
void* bi_map_extract_left(bi_map_t* map, void* key1, size_t key1_sz)
{
assert(map != NULL);
assert(key1 != NULL);
assert(key1_sz == map->left.key_sz);
void* key2 = assoc_extract(&map->left, key1);
void* key3 = assoc_extract(&map->right, key2);
// I do not like this trick. The memory should also be the same
int cmp = map->left.comp(key2, key3);
// int cmp = memcmp(key1, key3, map->right.key_sz);
assert(cmp == 0);
free(key3);
size_t sz_1 = assoc_size(&map->left);
size_t sz_2 = assoc_size(&map->right);
assert(sz_1 == sz_2);
return key2;
}
// It returns the void* of key1. the void* of the key2 is freed
void* bi_map_extract_right(bi_map_t* map, void* key2, size_t key2_sz)
{
assert(map != NULL);
assert(key2 != NULL);
assert(key2_sz == map->right.key_sz);
void* key1 = assoc_extract(&map->right, key2);
void* key3 = assoc_extract(&map->left, key1);
int cmp = map->right.comp(key2, key3);
// int cmp = memcmp(key2, key3, map->right.key_sz);
assert(cmp == 0);
free(key3);
size_t sz_1 = assoc_size(&map->left);
size_t sz_2 = assoc_size(&map->right);
assert(sz_1 == sz_2);
return key1;
}
// Capacity
size_t bi_map_size(bi_map_t* map)
{
assert(map != NULL);
size_t cap = assoc_size(&map->left);
assert(cap == assoc_size(&map->right) && "Mismatch in the ds");
return cap;
}
// Forward Iterator Concept
bml_iter_t bi_map_front_left(bi_map_t* map)
{
assert(map != NULL);
bml_iter_t it = {.it = assoc_front(&map->left)};
return it;
}
bml_iter_t bi_map_next_left(bi_map_t* map, bml_iter_t it)
{
assert(map != NULL);
assert(it.it != NULL);
bml_iter_t it_next = {.it = assoc_next(&map->left, it.it)};
return it_next;
}
bml_iter_t bi_map_end_left(bi_map_t* map)
{
assert(map != NULL);
bml_iter_t it = {.it = assoc_front(&map->left)};
return it;
}
bmr_iter_t bi_map_front_right(bi_map_t* map)
{
assert(map != NULL);
bmr_iter_t it = {.it = assoc_front(&map->right)};
return it;
}
bmr_iter_t bi_map_next_right(bi_map_t* map, bmr_iter_t it)
{
assert(map != NULL);
assert(it.it != NULL);
bmr_iter_t it_next = {.it = assoc_next(&map->right, it.it)};
return it_next;
}
bmr_iter_t bi_map_end_right(bi_map_t* map)
{
assert(map != NULL);
bmr_iter_t it = {.it = assoc_end(&map->right)};
return it;
}
void* bi_map_value_left(bi_map_t* map, bml_iter_t it)
{
assert(map != NULL);
return assoc_value(&map->left, it.it);
}
void* bi_map_value_right(bi_map_t* map, bml_iter_t it)
{
assert(map != NULL);
return assoc_value(&map->right, it.it);
}

View File

@@ -0,0 +1,178 @@
/*
MIT License
Copyright (c) 2021 Mikel Irazabal
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#ifndef BIDIRECTIONAL_HASH_MAP
#define BIDIRECTIONAL_HASH_MAP
/*
* Naive bidirectional map. K1->K2 and K2->K1
* It is implemented with 2 RB trees
* https://en.wikipedia.org/wiki/Bidirectional_map
*/
#include "assoc_rb_tree.h"
typedef int (*bi_map_cmp)(void const*, void const*);
typedef void (*free_func_t)(void* key, void* value);
typedef struct {
assoc_rb_tree_t left;
assoc_rb_tree_t right;
} bi_map_t;
typedef struct {
void* it;
} bml_iter_t;
typedef struct {
void* it;
} bmr_iter_t;
/*
* Init the bimap ds
* @param map the ds to initialize
* @param key_sz_1: Size of the first key i.e., sizeof(T), that the rb_tree will store.
* @param key_sz_2: Size of the second key i.e., sizeof(T), that the rb_tree will store.
* @param comp1 Compare function in the left RB tree.
* @param comp2 Compare function in the right RB tree.
* @param free1: Free function to free the left key
* @param free2: Free function to free the right key
*/
void bi_map_init(bi_map_t* map, size_t key_sz_1, size_t key_sz_2, bi_map_cmp cmp1, bi_map_cmp cmp2, free_func_t free1, free_func_t free2);
/*
* Free the bimap ds
* @param map the ds
*/
void bi_map_free(bi_map_t* map);
// Modifiers
/*
* Insert K1 and K2 in the bimap ds
* @param map the ds
* @param key_1: key1 pointer of the first key
* @param key_2: key2 pointer of the second key
* @param key_sz_1: Size of the first key i.e., sizeof(T)
* @param key_sz_2: Size of the second key i.e., sizeof(T)
*/
void bi_map_insert(bi_map_t* map, void const* key1, size_t key_sz1, void const* key2, size_t key_sz2);
/*
* It returns the void* of key2. the void* of the key1 is freed
* @param map the ds
* @param key_1: key1 pointer of the first key
* @param key_sz_1: Size of the first key i.e., sizeof(T)
* @return key2
*/
void* bi_map_extract_left(bi_map_t* map, void* key1, size_t key1_sz);
/*
* It returns the void* of key1. the void* of the key2 is freed
* @param map the ds
* @param key_2: key2 pointer of the second key
* @param key_sz_2: Size of the first key i.e., sizeof(T)
* @return key1
*/
void* bi_map_extract_right(bi_map_t* map, void* key2, size_t key1_sz);
/*
* It returns the void* of key2. the void* of the key1 is not freed
* @param map the ds
* @param bml_iter_t bimap left iterator
* @return key2
*/
void* bi_map_value_left(bi_map_t* map, bml_iter_t it);
/*
* It returns the void* of key1. the void* of the key2 is not freed
* @param map the ds
* @param bml_iter_t valid bimap iterator
* @return key1
*/
void* bi_map_value_right(bi_map_t* map, bml_iter_t it);
// Capacity
/*
* Number of elements in the ds
* @param map the ds
* @return number of elements in the ds
*/
size_t bi_map_size(bi_map_t* map);
// Forward Iterator Concept
/*
* Front left Iterator front of the left rb tree
* @param map the ds
* @return iterator to the front left rb tree
*/
bml_iter_t bi_map_front_left(bi_map_t* map);
/*
* Next Iterator in the left rb tree
* @param map the ds
* @param it iterator to the next element from the left rb tree
* @return iterator to the next iterator in the left rb tree
*/
bml_iter_t bi_map_next_left(bi_map_t* map, bml_iter_t it);
/*
* End Iterator in the left rb tree
* @param map the ds
* @return iterator to the one past the end iterator in the left rb tree
*/
bml_iter_t bi_map_end_left(bi_map_t* map);
/*
* Front right Iterator front of the right rb tree
* @param map the ds
* @return iterator to the front right rb tree
*/
bmr_iter_t bi_map_front_right(bi_map_t* map);
/*
* Next Iterator in the right rb tree
* @param map the ds
* @param it iterator to the next element from the right rb tree
* @return iterator to the next iterator in the right rb tree
*/
bmr_iter_t bi_map_next_right(bi_map_t* map, bmr_iter_t);
/*
* End Iterator in the right rb tree
* @param map the ds
* @return iterator to the one past the end iterator in the right rb tree
*/
bmr_iter_t bi_map_end_right(bi_map_t* map);
#endif

View File

@@ -28,7 +28,7 @@ byte_array_t copy_byte_array(byte_array_t src)
{
byte_array_t dst = {0};
dst.buf = malloc(src.len);
DevAssert(dst.buf != NULL && "Memory exhausted");
AssertFatal(dst.buf != NULL, "Memory exhausted\n");
memcpy(dst.buf, src.buf, src.len);
dst.len = src.len;
return dst;

View File

@@ -24,16 +24,42 @@
#include <stdbool.h>
#include <stdint.h>
#include <stdlib.h>
#include <stddef.h>
#include <string.h>
#include "common/utils/assertions.h"
/*
* Simple and efficient data structure to bring together the length and the pointer
* You can cheaply copy and return it as it only utilizes two registers in x86-64
*/
typedef struct {
size_t len;
uint8_t* buf;
} byte_array_t;
typedef struct {
uint8_t buf[32];
} byte_array_32_t;
/////////////////////////////////////////////////////////////
// These macros need to be removed once the KPM is upgraded
/////////////////////////////////////////////////////////////
/* create on the stack a byte_array_t named 'name' implemented as array of length 'length'*/
#define BYTE_ARRAY_STACK(name, length) \
uint8_t(name##_BuF)[(length)]; \
memset((name##_BuF), 0, sizeof((name##_BuF))); \
byte_array_t(name) = {.buf = (name##_BuF), .len = (length)}
/* create on the heap a new 'byte_array_t' data structure named 'ba' from OCTET_STRING_t named 'octet' pointer*/
#define BYTE_ARRAY_HEAP_CP_FROM_OCTET_STRING_POINTERS(ba, octet) \
ba->buf = calloc(1, octet->size); \
AssertFatal(ba->buf != NULL, "Memory exhausted"); \
memcpy(ba->buf, octet->buf, octet->size); \
ba->len = octet->size;
#define BYTE_ARRAY_HEAP_CP_FROM_OCTET_STRING(ba, octet) \
ba.buf = calloc(1, octet.size); \
AssertFatalu(ba.buf != NULL, "Memory exhausted"); \
memcpy(ba.buf, octet.buf, octet.size); \
ba.len = octet.size;
byte_array_t copy_byte_array(byte_array_t src);
void free_byte_array(byte_array_t ba);

View File

@@ -0,0 +1,176 @@
#include "seq_arr.h"
#include <assert.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
static
const size_t MIN_SIZE = 8;
static
void maybe_expand(seq_arr_t* arr)
{
if(arr->size + 1 == arr->cap){
//void* p = reallocarray(arr->data, arr->cap*2, arr->elt_size);
arr->data = realloc(arr->data, 2*arr->cap*arr->elt_size);
assert(arr->data != NULL && "realloc failed to allocate memory");
arr->cap *=2;
}
}
static
void maybe_shrink(seq_arr_t* arr)
{
const float occ = (float)arr->size / (float)arr->cap;
//printf("Occ = %f and size = %ld \n", occ, arr->size);
if(arr->size > MIN_SIZE && occ < 0.25){
assert(arr->cap > MIN_SIZE);
seq_arr_t tmp = {.data = NULL, .size = arr->size, .elt_size = arr->elt_size, .cap = arr->cap/2};
tmp.data = calloc(tmp.cap, tmp.cap);
assert(tmp.data != NULL && "Memory exhausted");
assert(arr->size <= tmp.cap);
memcpy(tmp.data, arr->data, arr->size*arr->elt_size);
free(arr->data);
memcpy(arr, &tmp, sizeof(seq_arr_t));
}
}
void seq_arr_init(seq_arr_t* arr, size_t elt_size) //__attribute__(malloc)
{
assert(arr != NULL);
seq_arr_t tmp = {.data = NULL, .size = 0, .elt_size = elt_size, .cap = MIN_SIZE};
memcpy(arr, &tmp, sizeof(seq_arr_t));
arr->data = calloc(arr->cap, elt_size);
assert(arr->data != NULL);
}
void seq_arr_free(seq_arr_t* arr, void (*free_func)(void*) )
{
assert(arr != NULL);
assert(arr->data != NULL);
if(free_func != NULL) {
void* start_it = seq_arr_front(arr);
void* end_it = seq_arr_end(arr);
while(start_it != end_it){
free_func(start_it);
start_it = seq_arr_next(arr, start_it);
}
}
free(arr->data);
}
void seq_arr_push_back(seq_arr_t* arr, void* data, size_t len)
{
assert(arr != NULL);
//assert(data != NULL);
assert(len == arr->elt_size);
maybe_expand(arr);
const size_t offset = arr->size * arr->elt_size;
memcpy(&arr->data[offset], data, arr->elt_size);
arr->size += 1;
};
void seq_arr_erase(seq_arr_t* arr, void* start_it, void* end_it)
{
// start_it && end_it must be in the range of arr->data
assert(arr != NULL);
assert(start_it != NULL);
assert(end_it != NULL);
assert(end_it >= start_it);
if(start_it == end_it) return;
const int num_bytes_move = seq_arr_end(arr) - end_it;
assert(num_bytes_move > -1);
memmove(start_it, end_it, num_bytes_move);
const int num_bytes_erase = end_it - start_it;
const int32_t num_elm_erase = num_bytes_erase/arr->elt_size;
assert(num_elm_erase > 0);
arr->size -= num_elm_erase;
memset(seq_arr_end(arr), 0, num_bytes_erase);
maybe_shrink(arr);
}
/*
void seq_arr_erase_free(seq_arr_t *arr, void *start_it, void *end_it,
void (*free_func)(void *)) {
assert(arr != NULL);
assert(start_it != NULL);
assert(end_it != NULL);
assert(end_it >= start_it);
assert(free_func != NULL && "Use seq_arr_erase instead ");
while (start_it != end_it) {
free_func(start_it);
start_it = seq_arr_next(arr, start_it);
}
seq_arr_erase(arr, start_it, end_it);
}
*/
size_t seq_arr_size(seq_arr_t* arr)
{
assert(arr != NULL);
return arr->size;
}
void* seq_arr_front(seq_arr_t* arr)
{
return arr->data;
}
void* seq_arr_next(seq_arr_t* arr, void* it)
{
assert(arr != NULL);
assert(it != NULL);
return (uint8_t*)it + arr->elt_size;
}
void* seq_arr_end(seq_arr_t* arr)
{
assert(arr != NULL);
return &arr->data[arr->size*arr->elt_size];
}
void* seq_arr_at(seq_arr_t* arr, uint32_t pos)
{
assert(pos < arr->size);
return arr->data + pos*arr->elt_size;
}
ptrdiff_t seq_arr_dist(seq_arr_t* arr, void* first, void* last)
{
assert(arr != NULL);
assert(first != NULL);
assert(last != NULL);
const ptrdiff_t pos = (last - first)/arr->elt_size;
assert(pos > -1);
return pos;
}
bool seq_arr_equal(seq_arr_t* arr, void* it_1, void* it_2)
{
assert(arr!= NULL);
assert(it_1 != NULL);
assert(it_2 != NULL);
return it_1 == it_2;
}
void* seq_arr_value(seq_arr_t* arr, void* it)
{
assert(arr != NULL);
assert(it != NULL);
assert(0!=0 && "Not implemented!");
return NULL;
}

View File

@@ -0,0 +1,126 @@
#ifndef SEQ_CONTAINER_ARRAY
#define SEQ_CONTAINER_ARRAY
#include <stdbool.h>
#include <stddef.h>
#include <stdlib.h>
#include <stdint.h>
/*
* Dynamic array data structure that shrinks and expands as needed, similar to std::vector
*/
typedef struct seq_arr_s{
uint8_t* data;
size_t size;
const size_t elt_size;
size_t cap;
} seq_arr_t;
typedef void (*seq_free_func)(void*);
/*
* Init the seq_array ds
* @param arr: the ds to initialize
* @param sz: Size of the data type i.e., sizeof(T), that the seq_array_t will store.
*/
void seq_arr_init(seq_arr_t* arr, size_t sz);
/*
* Free the seq_array ds
* @param arr: the ds
* @param seq_free_func: Function that every element will call before being freed e.g., usefull to free
* "deep" objects.
* */
void seq_arr_free(seq_arr_t*, seq_free_func );
/*
* Push back
* @param arr: the ds
* @param data: Pointer to the data that will ve copied. This a swallow copy i.e., memcpy
* @param len: Lenght of the data to be stored i.e.,sizeof(T). This parameter is only used
* to guarantee that the object copied and the underlying array initialized at
* seq_arr_init have the same lenght
* */
void seq_arr_push_back(seq_arr_t* arr, void* data, size_t len);
/*
* Erase a half-open range [start_it, end_it)
* @param arr: the ds
* @param start_it Starting iterator of the range
* @param end_it Ending iterator of the range
* @pre Precondition: the range is valid and @p end_it can be reached from @p start_it
*/
void seq_arr_erase(seq_arr_t*, void* start_it , void* end_it);
/*
* Size
* @param arr: the ds
* @return the number of elements in the ds s
* */
size_t seq_arr_size(seq_arr_t*);
/*
* Front
* @param arr: the ds
* @return the iterator to the first element
* */
void* seq_arr_front(seq_arr_t*);
/*
* Next
* @param arr the ds
* @param it Iterator
* @return Iterator to the next element in the ds
* @pre Precondition: iterator @p it, is valid and not equal to the end iterator
* */
void* seq_arr_next(seq_arr_t*, void* it);
/*
* End
* @param arr: the ds
* @return one past the last element in the ds
* */
void* seq_arr_end(seq_arr_t*);
/*
* End
* @param arr: the ds
* @param nth: Position of the element
* @return the iterator the nth element
* Precondition: @p nth is not greater than seq_arr_size()
*/
void* seq_arr_at(seq_arr_t*, uint32_t nth);
/*
* Distance
* @param arr: the ds
* @param it_a Iterator
* @param it_b Iterator
* @return the of the amount of elements between it_a and it_b
* @pre Precondition: @p it_a and @p it_b are valid and @p it_a < @p it_b
*/
ptrdiff_t seq_arr_dist(seq_arr_t* arr, void* it_a, void* it_b);
/*
* Equality
* @param arr: the ds
* @param it_a: iterator from the seq_array ds
* @param it_b: iterator from the seq_array ds
* @return true if both iterators point to the same element
* @pre Precondition: @p it_a and @p it_b are valid iterators
*/
bool seq_arr_equal(seq_arr_t* arr, void* it_a ,void* it_b);
#endif

View File

@@ -0,0 +1,65 @@
#ifndef SEQUENCE_CONTAINERS_GENERIC
#define SEQUENCE_CONTAINERS_GENERIC
#include "seq_arr.h"
/*
*Generic sequence container file. Nomenclature from the C++ sequence containers
*/
// Initialization
#define seq_init(T,U) _Generic ((T), seq_arr_t*: seq_arr_init, \
default: seq_arr_init) (T,U)
#define seq_free(T,U) _Generic ((T), seq_arr_t*: seq_arr_free, \
default: seq_arr_free)(T,U)
// Modifiers
#define seq_push_back(T,U,W) _Generic ((T), seq_arr_t*: seq_arr_push_back, \
default: seq_arr_push_back)(T,U,W)
#define seq_erase(T,U,W) _Generic ((T), seq_arr_t*: seq_arr_erase, \
default: seq_arr_erase)(T,U,W)
#define seq_erase_free(T, U, W, X) \
_Generic((T), seq_arr_t * \
: seq_arr_erase_free, default \
: seq_arr_erase_free)(T, U, W, X)
// Capacity
#define seq_size(T) _Generic ((T), seq_arr_t*: seq_arr_size, \
default: seq_arr_size)(T)
// Forward Iterator Concept
#define seq_front(T) _Generic ((T), seq_arr_t*: seq_arr_front, \
default: seq_arr_front)(T)
#define seq_next(T,U) _Generic((T), seq_arr_t*: seq_arr_next, \
default: seq_arr_next)(T,U)
#define seq_end(T) _Generic((T), seq_arr_t*: seq_arr_end, \
default: seq_arr_end)(T)
// at position starting from zero
#define seq_at(T,U) _Generic((T), seq_arr_t*: seq_arr_at, \
default: seq_arr_at)(T,U)
//
#define seq_distance(T,U,V) _Generic((T), seq_arr_t*: seq_arr_dist,\
default: seq_arr_dist)(T,U,V)
// Equality
#define seq_equal(T,U,V) _Generic((T), seq_arr_t*: seq_arr_equal, \
default: seq_arr_equal)(U,V)
#define seq_value(T,U) _Generic((T), seq_arr_t*: seq_arr_value, \
default: seq_arr_value)(U)
#endif

View File

@@ -117,7 +117,7 @@ double time_average_get_average(time_average_t *t, uint64_t time)
return (double)t->accumulated_value / t->r.size;
}
uint64_t time_average_now(void)
uint64_t time_now_us(void)
{
struct timespec t;
uint64_t ret;

View File

@@ -59,6 +59,6 @@ void time_average_add(time_average_t *t, uint64_t time, uint64_t value);
double time_average_get_average(time_average_t *t, uint64_t time);
/* unit microsecond */
uint64_t time_average_now(void);
uint64_t time_now_us(void);
#endif /* _COMMON_UTIL_TIME_STAT_H_ */

View File

@@ -90,6 +90,18 @@ unsigned short config_frames[4] = {2,9,11,13};
# include "sys/gmon.h"
#endif
#ifdef E2_AGENT
#include "openair2/E2AP/sm/agent_if/read/sm_ag_if_rd.h"
#include "openair2/E2AP/sm/agent_if/write/sm_ag_if_wr.h"
#include "openair2/E2AP/sm/sm_io.h"
#include "openair2/E2AP/agent/e2_agent_api.h"
#include <time.h>
#endif // E2_AGENT
pthread_cond_t nfapi_sync_cond;
pthread_mutex_t nfapi_sync_mutex;
int nfapi_sync_var=-1; //!< protected by mutex \ref nfapi_sync_mutex
@@ -440,6 +452,28 @@ static void wait_nfapi_init(char *thread_name) {
printf( "NFAPI: got sync (%s)\n", thread_name);
}
#ifdef E2_AGENT
static
void read_RAN(sm_ag_if_rd_t* data)
{
assert(data != NULL);
assert(false && "not implemented");
}
static
sm_ag_if_ans_t write_RAN(sm_ag_if_wr_t const* data)
{
assert(data != NULL);
assert(false && "not implemented");
sm_ag_if_ans_t ans = {};
return ans;
}
#endif // E2_AGENT
int main ( int argc, char **argv )
{
int CC_id = 0;
@@ -492,6 +526,33 @@ int main ( int argc, char **argv )
}
if (RC.nb_inst > 0) {
#ifdef E2_AGENT
//////////////////////////////////
//////////////////////////////////
//// Init the E2 Agent
e2_agent_args_t args = {0};
if (RCconfig_E2agent(&args)) {
sleep(1);
const eNB_RRC_INST* rrc = RC.rrc[0];
assert(rrc != NULL && "rrc cannot be NULL");
const int mcc = rrc->configuration.mcc[0];
const int mnc = rrc->configuration.mnc[0];
const int mnc_digit_len = rrc->configuration.mnc_digit_length[0];
const int nb_id = rrc->configuration.cell_identity;
// TODO: node_type = 0 // ngran_eNB
const int cu_du_id = 0;
sm_io_ag_t io = {.read = read_RAN, .write = write_RAN};
printf("[E2 NODE]: mcc = %d mnc = %d mnc_digit = %d nd_id = %d \n", mcc, mnc, mnc_digit_len, nb_id);
init_agent_api( mcc, mnc, mnc_digit_len, nb_id, cu_du_id, 0, io, &args);
}
#endif // E2_AGENT
/* initializes PDCP and sets correct RLC Request/PDCP Indication callbacks */
init_pdcp();

View File

@@ -82,6 +82,24 @@ unsigned short config_frames[4] = {2,9,11,13};
#include "openair2/E1AP/e1ap_common.h"
#include "openair2/E1AP/e1ap_api.h"
#ifdef E2_AGENT
#include "openair2/E2AP/sm/agent_if/read/sm_ag_if_rd.h"
#include "openair2/E2AP/sm/sm_io.h"
#include "openair2/E2AP/agent/e2_agent_api.h"
#include "openair2/LAYER2/nr_rlc/nr_rlc_entity.h"
#include "openair2/LAYER2/nr_pdcp/nr_pdcp_entity.h"
#include "openair2/LAYER2/nr_rlc/nr_rlc_oai_api.h"
#include "openair2/LAYER2/nr_pdcp/nr_pdcp.h"
#include "openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h"
#include "openair2/LAYER2/NR_MAC_gNB/mac_proto.h"
#include "openair2/RRC/NR/rrc_gNB_UE_context.h"
#include <time.h>
#endif // E2_AGENT
pthread_cond_t nfapi_sync_cond;
pthread_mutex_t nfapi_sync_mutex;
int nfapi_sync_var=-1; //!< protected by mutex \ref nfapi_sync_mutex
@@ -568,6 +586,184 @@ void init_pdcp(void) {
}
}
#ifdef E2_AGENT
static
void read_kpm_sm(kpm_ind_data_t* data)
{
assert(data != NULL);
// Fill KPM indication header
kpm_ind_hdr_t* hdr = &data->hdr;
int64_t t = time_now_us();
hdr->collectStartTime = t / 1000000; // needs to be truncated to 32 bits to arrive to a resolution of seconds
hdr->fileFormatversion = NULL;
hdr->senderName = NULL;
hdr->senderType = NULL;
hdr->vendorName = NULL;
// Fill KPM indication message
kpm_ind_msg_t* msg = &data->msg;
// TODO: assign MeaData_len according to eventPeriod/granulPeriod from the action definition or subscription request
msg->MeasData_len = 1;
if (msg->MeasData_len > 0) {
msg->MeasData = calloc(msg->MeasData_len, sizeof(adapter_MeasDataItem_t));
assert(msg->MeasData != NULL && "Memory exhausted" );
}
// get the number of connected UEs
NR_UEs_t *UE_info = &RC.nrmac[0]->UE_info;
size_t num_ues = 0;
UE_iterator(UE_info->list, ue) {
if (ue)
num_ues += 1;
}
if (num_ues > 0) {
// get the info to calculate the resource utilization
NR_ServingCellConfigCommon_t *scc = RC.nrmac[0]->common_channels[0].ServingCellConfigCommon;
int cur_slot = RC.nrmac[0]->slot;
// int num_dl_slots = scc->tdd_UL_DL_ConfigurationCommon->pattern1.nrofDownlinkSlots;
// get total number of available resource blocks
int n_rb_sched = 0;
if (UE_info->list[0] != NULL) {
/* Get bwpSize and TDA from the first UE */
/* This is temporary and it assumes all UEs have the same BWP and TDA*/
NR_UE_info_t *UE = UE_info->list[0];
NR_UE_sched_ctrl_t *sched_ctrl = &UE->UE_sched_ctrl;
NR_UE_DL_BWP_t *current_BWP = &UE->current_DL_BWP;
const int tda = get_dl_tda(RC.nrmac[0], scc, cur_slot);
int startSymbolIndex, nrOfSymbols;
const int coresetid = sched_ctrl->coreset->controlResourceSetId;
const struct NR_PDSCH_TimeDomainResourceAllocationList *tdaList = get_dl_tdalist(current_BWP, coresetid, sched_ctrl->search_space->searchSpaceType->present, NR_RNTI_C);
AssertFatal(tda < tdaList->list.count, "time_domain_allocation %d>=%d\n", tda, tdaList->list.count);
const int startSymbolAndLength = tdaList->list.array[tda]->startSymbolAndLength;
SLIV2SL(startSymbolAndLength, &startSymbolIndex, &nrOfSymbols);
const uint16_t bwpSize = coresetid == 0 ? RC.nrmac[0]->cset0_bwp_size : current_BWP->BWPSize;
const uint16_t BWPStart = coresetid == 0 ? RC.nrmac[0]->cset0_bwp_start : current_BWP->BWPStart;
const uint16_t slbitmap = SL_to_bitmap(startSymbolIndex, nrOfSymbols);
uint16_t *vrb_map = RC.nrmac[0]->common_channels[0].vrb_map;
uint16_t rballoc_mask[bwpSize];
for (int i = 0; i < bwpSize; i++) {
// calculate mask: init with "NOT" vrb_map:
// if any RB in vrb_map is blocked (1), the current RBG will be 0
rballoc_mask[i] = (~vrb_map[i + BWPStart]) & 0x3fff; //bitwise not and 14 symbols
// if all the pdsch symbols are free
if ((rballoc_mask[i] & slbitmap) == slbitmap) {
n_rb_sched++;
}
}
}
// TODO: assign the MeasData every granulPeriod
for (size_t i = 0; i < msg->MeasData_len; i++) {
adapter_MeasDataItem_t* item = &msg->MeasData[i];
// TODO: assign measRecord_len according to
// (1) the length of Measurements Information List IE (format1) or
// (2) Measurements Information Condition UE List IE (format2)
// from the action definition or subscription request
// TODO: only support KPM format 1, and it only can handle one UE's information
// assume to record one data: DL resource utilization
item->measRecord_len = 1;
if (item->measRecord_len > 0) {
item->measRecord = calloc(item->measRecord_len, sizeof(adapter_MeasRecord_t));
assert(item->measRecord != NULL && "Memory exhausted");
}
UE_iterator(UE_info->list, UE)
{
int dl_rb_usage = 0;
if (is_xlsch_in_slot(RC.nrmac[0]->dlsch_slot_bitmap[cur_slot / 64], cur_slot))
dl_rb_usage = UE->mac_stats.dl.current_rbs*100/n_rb_sched;
// TODO: go through the measRecord according to the Measurements Information (format 1) or Information Condition UE (format 2) List IE
adapter_MeasRecord_t *record_PrbDlUsage = &item->measRecord[0];
record_PrbDlUsage->type = MeasRecord_int;
record_PrbDlUsage->int_val = dl_rb_usage;
}
// incompleteFlag = -1, the data is reliable
item->incompleteFlag = -1;
}
// TODO: assign MeasInfo_len according to the action definition or subscription request
msg->MeasInfo_len = 1;
if (msg->MeasInfo_len > 0) {
msg->MeasInfo = calloc(msg->MeasInfo_len, sizeof(MeasInfo_t));
assert(msg->MeasInfo != NULL && "Memory exhausted" );
MeasInfo_t* info = &msg->MeasInfo[0];
info->meas_type = KPM_V2_MEASUREMENT_TYPE_NAME;
char* measName = "PrbDlUsage";
info->measName.len = strlen(measName);
info->measName.buf = malloc(strlen(measName));
assert(info->measName.buf != NULL && "memory exhausted");
memcpy(info->measName.buf, measName, msg->MeasInfo[0].measName.len);
// TODO: assign labelInfo_len according to the action definition (?)
info->labelInfo_len = 1;
info->labelInfo = calloc(info->labelInfo_len, sizeof(adapter_LabelInfoItem_t));
assert(info->labelInfo != NULL && "memory exhausted");
adapter_LabelInfoItem_t* label = &info->labelInfo[0];
label->noLabel = calloc(1, sizeof(long));
assert(label->noLabel != NULL && "memory exhausted");
*(label->noLabel) = 0;
}
} else {
for (size_t i = 0; i < msg->MeasData_len; i++) {
adapter_MeasDataItem_t* item = &msg->MeasData[i];
item->measRecord_len = 1;
if (item->measRecord_len > 0) {
item->measRecord = calloc(item->measRecord_len, sizeof(adapter_MeasRecord_t));
assert(item->measRecord != NULL && "Memory exhausted");
}
adapter_MeasRecord_t *record_nodata = &item->measRecord[0];
record_nodata->type = MeasRecord_int;
record_nodata->int_val = 0;
// incompleteFlag = 0, the data is not reliable
item->incompleteFlag = 0;
}
msg->MeasInfo_len = 0;
msg->MeasInfo = NULL;
}
msg->granulPeriod = NULL;
}
static
void read_RAN(sm_ag_if_rd_t* data)
{
assert(data != NULL);
assert(data->type == KPM_STATS_V0);
if(data->type == KPM_STATS_V0){
read_kpm_sm(&data->kpm_stats);
} else {
assert(false && "Unknown data type!");
}
}
static
sm_ag_if_ans_t write_RAN(sm_ag_if_wr_t const* data)
{
assert(data != NULL);
assert(false && "Not implemented");
sm_ag_if_ans_t ans = {.type = SM_AGENT_IF_ANS_V0_END };
return ans;
}
#endif // E2_AGENT
int main( int argc, char **argv ) {
int ru_id, CC_id = 0;
start_background_system();
@@ -683,6 +879,43 @@ int main( int argc, char **argv ) {
config_sync_var=0;
#ifdef E2_AGENT
//////////////////////////////////
//////////////////////////////////
//// Init the E2 Agent
e2_agent_args_t args = {0};
if (RCconfig_NR_E2agent(&args)) {
sleep(1);
const gNB_RRC_INST* rrc = RC.nrrrc[0];
assert(rrc != NULL && "rrc cannot be NULL");
const int mcc = rrc->configuration.mcc[0];
const int mnc = rrc->configuration.mnc[0];
const int mnc_digit_len = rrc->configuration.mnc_digit_length[0];
const ngran_node_t node_type = rrc->node_type;
int nb_id = 0;
int cu_du_id = 0;
if (node_type == ngran_gNB) {
nb_id = rrc->configuration.cell_identity;
} else if (node_type == ngran_gNB_DU) {
cu_du_id = rrc->configuration.cell_identity;
} else if (node_type == ngran_gNB_CU) {
cu_du_id = rrc->node_id;
} else {
LOG_E(NR_RRC, "not supported ran type detect\n");
}
sm_io_ag_t io = {.read = read_RAN, .write = write_RAN};
printf("[E2 NODE]: mcc = %d mnc = %d mnc_digit = %d nd_id = %d \n", mcc, mnc, mnc_digit_len, nb_id);
init_agent_api( mcc, mnc, mnc_digit_len, nb_id, cu_du_id, node_type, io, &args);
}
#endif // E2_AGENT
if (NFAPI_MODE==NFAPI_MODE_PNF) {
wait_nfapi_init("main?");
}

View File

@@ -3,3 +3,10 @@ add_subdirectory(F1AP)
add_subdirectory(M2AP)
add_subdirectory(X2AP)
add_subdirectory(RRC)
if(E2_AGENT STREQUAL "ON")
add_subdirectory(E2AP)
message(STATUS "Building E2 Agent")
else()
message(STATUS "NOT building E2 Agent")
endif()

View File

@@ -0,0 +1,33 @@
set(E2AP_LIBRARY "STATIC" CACHE STRING "Static or dynamic library")
set_property(CACHE E2AP_LIBRARY PROPERTY STRINGS "STATIC" "DYNAMIC")
message(STATUS "Selected LIBRARY TYPE: ${E2AP_LIBRARY}")
if(E2AP_LIBRARY STREQUAL "STATIC")
add_compile_options("-W;-Wall;-Wextra;-g;-Wno-unused-result;")
elseif(E2AP_LIBRARY STREQUAL "DYNAMIC")
# -fPIC flag
set(CMAKE_POSITION_INDEPENDENT_CODE ON)
add_compile_options("-W;-Wall;-Wextra;-g")
else()
message(FATAL_ERROR "Unknown building type. Either choose a static or a dynamic library")
endif()
set(E2AP_ENCODING "E2AP_ASN" CACHE STRING "The E2AP encoding to use")
set_property(CACHE E2AP_ENCODING PROPERTY STRINGS "E2AP_ASN" "E2AP_FLATBUFFERS")
message(STATUS "Selected E2AP_ENCODING: ${E2AP_ENCODING}")
#######
## Service Models
#######
# KPM service Model encoding definitions
set(SM_ENCODING_KPM "E2SM_KPM_ASN" CACHE STRING "The KPM SM encoding to use")
set_property(CACHE SM_ENCODING_KPM PROPERTY STRINGS "E2SM_KPM_PLAIN" "E2SM_KPM_ASN" "E2SM_KPM_FLATBUFFERS")
message(STATUS "Selected SM_ENCODING_KPM: ${SM_ENCODING_KPM}")
add_subdirectory(agent)
add_subdirectory(lib)
add_subdirectory(sm)
add_subdirectory(test)

View File

@@ -0,0 +1,72 @@
if(E2AP_LIBRARY STREQUAL "STATIC")
set(E2_AGENT_BLD_LIB "STATIC")
elseif(E2AP_LIBRARY STREQUAL "DYNAMIC")
set(E2_AGENT_BLD_LIB "SHARED")
else()
message(FATAL_ERROR "Unknown type")
endif()
set(E2_AGENT_SRC
asio_agent.c
e2ap_agent.c
e2_agent.c
e2_agent_api.c
endpoint_agent.c
msg_handler_agent.c
e2_agent_api.c
plugin_agent.c
not_handler_agent.c
../sm/sm_proc_data.c
)
if(E2AP_ENCODING STREQUAL "E2AP_ASN")
add_library(e2_agent STATIC ${E2_AGENT_SRC})
target_link_libraries(e2_agent PRIVATE asn1_e2ap)
elseif(E2AP_ENCODING STREQUAL "E2AP_FLATBUFFERS")
add_library(e2_agent ${E2_AGENT_BLD_LIB} #STATIC or SHARED
${E2_AGENT_SRC}
)
#bundle_static_library(e2_agent libflatccrt_d.a)
else()
message(FATAL_ERROR "Error, while compiling the agent" )
endif()
if(INCL_WHAT_YOU_USE)
find_program(iwyu_path NAMES include-what-you-use iwyu REQUIRED)
set_property(TARGET e2_agent PROPERTY C_INCLUDE_WHAT_YOU_USE ${iwyu_path})
endif()
if(${E2AP_LIBRARY} STREQUAL "DYNAMIC" )
target_link_libraries(e2_agent
PUBLIC
-pthread
-lsctp
-ldl
)
endif()
target_compile_definitions(e2_agent PRIVATE ${E2AP_ENCODING})
target_link_libraries(e2_agent PUBLIC
e2ap_ap_obj
e2ap_ep_obj
pending_events_obj
e2ap_types_obj
e2ap_msg_enc_obj
e2ap_msg_dec_obj
e2ap_msg_free_obj
)
target_link_libraries(e2_agent PRIVATE alg ngran_types)
target_link_libraries(e2_agent PUBLIC ds) # for byte_array_t
# list of SMs for which build should be triggered
add_dependencies(e2_agent kpm_sm)

View File

@@ -0,0 +1,141 @@
/*
* 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 "asio_agent.h"
#include <assert.h> // for assert
#include <errno.h> // for errno
#include <fcntl.h> // for fcntl, F_GETFL, F_SETFL
#include <stdio.h> // for NULL, fprintf, stderr
#include <string.h> // for strerror
#include <sys/epoll.h> // for epoll_event, epoll_ctl
#include <sys/time.h> // for CLOCK_MONOTONIC
#include <sys/timerfd.h> // for timerfd_create, timerfd_se...
#include <sys/types.h> // for time_t
#include <time.h> // for timespec, itimerspec
#include <unistd.h> // for close
static
void set_fd_non_blocking(int sfd)
{
int flags = fcntl (sfd, F_GETFL, 0);
flags |= O_NONBLOCK;
fcntl (sfd, F_SETFL, flags);
}
static
int init_epoll(void)
{
const int flags = EPOLL_CLOEXEC;
const int efd = epoll_create1(flags);
assert(efd != -1);
return efd;
}
void init_asio_agent(asio_agent_t* io)
{
assert(io != NULL);
io->efd = init_epoll();
set_fd_non_blocking(io->efd);
}
void add_fd_asio_agent(asio_agent_t* io, int fd)
{
assert(io != NULL);
const int op = EPOLL_CTL_ADD;
const epoll_data_t e_data = {.fd = fd};
const int e_events = EPOLLIN | EPOLLET; // open for reading and edge triggered instead of level triggered
struct epoll_event event = {.events = e_events, .data = e_data};
int rc = epoll_ctl(io->efd, op, fd, &event);
assert(rc != -1);
}
void rm_fd_asio_agent(asio_agent_t* io, int fd)
{
assert(io != NULL);
const int op = EPOLL_CTL_DEL;
const epoll_data_t e_data = {.fd = fd};
const int e_events = EPOLLIN; // open for reading
struct epoll_event event = {.events = e_events, .data = e_data};
int rc = epoll_ctl(io->efd, op, fd, &event);
assert(rc != -1);
rc = close(fd);
assert(rc == 0);
}
int create_timer_ms_asio_agent(asio_agent_t* io, long initial_ms, long interval_ms)
{
assert(io != NULL);
assert(initial_ms > -1);
assert(interval_ms > -1);
// Create the timer
const int clockid = CLOCK_MONOTONIC;
const int flags = TFD_NONBLOCK | TFD_CLOEXEC;
const int tfd = timerfd_create(clockid, flags);
assert(tfd != -1);
const time_t initial_sec = initial_ms / 1000;
const long initial_nsec = (initial_ms * 1000000) % 1000000000;
/* Initial expiration */
const struct timespec it_value = {.tv_sec = initial_sec, .tv_nsec = initial_nsec};
const time_t interval_sec = interval_ms / 1000;
const long interval_nsec = (interval_ms * 1000000) % 1000000000;
/* Interval for periodic timer */
const struct timespec it_interval = {.tv_sec = interval_sec, .tv_nsec = interval_nsec};
const int flags_2 = 0;
struct itimerspec *old_value = NULL; // not interested in how the timer was previously configured
const struct itimerspec new_value = {.it_interval = it_interval, .it_value = it_value};
int rc = timerfd_settime(tfd, flags_2, &new_value, old_value);
assert(rc != -1);
add_fd_asio_agent(io, tfd);
return tfd;
}
int event_asio_agent(asio_agent_t const* io)
{
assert(io != NULL);
const int maxevents = 1;
struct epoll_event events[maxevents];
const int timeout_ms = 1000;
const int events_ready = epoll_wait(io->efd, events, maxevents, timeout_ms);
if (events_ready < 0) {
fprintf(stderr, "epoll_wait() returned -1: errno %d, %s\n", errno, strerror(errno));
assert(0);
}
assert(events_ready == 0 || events_ready == 1);
if(events_ready == 0)
return -1;
// Max. one event ready
assert((events[0].events & EPOLLERR) == 0);
return events[0].data.fd;
}

View File

@@ -0,0 +1,57 @@
/*
* 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 ASYNC_INPUT_OUTPUT_AGENT_H
#define ASYNC_INPUT_OUTPUT_AGENT_H
typedef struct{
// epoll based fd
int efd;
} asio_agent_t;
/*
typedef enum
{
NET_PKT_ASIO_EVENT,
IND_MSG_ASIO_EVENT,
PENDING_TIMEOUT_EVENT,
} asio_ev_t ;
*/
void init_asio_agent(asio_agent_t* io);
void add_fd_asio_agent(asio_agent_t* io, int fd);
void rm_fd_asio_agent(asio_agent_t* io, int fd);
int create_timer_ms_asio_agent(asio_agent_t* io, long initial_ms, long interval_ms);
int event_asio_agent(asio_agent_t const* io);
#endif

View File

@@ -0,0 +1,520 @@
/*
* 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 "asio_agent.h"
#include "e2_agent.h"
#include "endpoint_agent.h"
#include "msg_handler_agent.h"
#include "not_handler_agent.h"
#include "lib/async_event.h"
#include "lib/v1/ap/e2ap_ap.h"
#include "lib/v1/ap/free/e2ap_msg_free.h"
//#include "sm/mac_sm/mac_sm_agent.h"
//#include "sm/rlc_sm/rlc_sm_agent.h"
#include "alg.h"
#include "util/compare.h"
#include <assert.h>
#include <stdio.h>
static
e2_setup_request_t generate_setup_request(e2_agent_t* ag)
{
assert(ag != NULL);
const size_t len_rf = assoc_size(&ag->plugin.sm_ds);
assert(len_rf > 0 && "No RAN function/service model registered. Check if the Service Models are located at shared library paths, default location is /usr/local/flexric/");
ran_function_t* ran_func = calloc(len_rf, sizeof(*ran_func));
assert(ran_func != NULL);
e2_setup_request_t sr = {
.id = ag->global_e2_node_id,
.ran_func_item = ran_func,
.len_rf = len_rf,
.comp_conf_update = NULL,
.len_ccu = 0
};
void* it = assoc_front(&ag->plugin.sm_ds);
for(size_t i = 0; i < len_rf; ++i){
sm_agent_t* sm = assoc_value( &ag->plugin.sm_ds, it);
assert(sm->ran_func_id == *(uint16_t*)assoc_key(&ag->plugin.sm_ds, it) && "RAN function mismatch");
ran_func[i].id = sm->ran_func_id;
ran_func[i].rev = 0;
ran_func[i].oid = NULL;
sm_e2_setup_t def = sm->proc.on_e2_setup(sm);
byte_array_t ba = {.len = def.len_rfd, .buf = def.ran_fun_def};
ran_func[i].def = ba;
it = assoc_next(&ag->plugin.sm_ds ,it);
}
assert(it == assoc_end(&ag->plugin.sm_ds) && "Length mismatch");
return sr;
}
static
ric_indication_t generate_indication(e2_agent_t* ag, sm_ind_data_t* data, ind_event_t* i_ev)
{
assert(ag != NULL);
assert(data != NULL);
assert(i_ev != NULL);
ric_indication_t ind = {
.ric_id = i_ev->ric_id,
.action_id = i_ev->action_id,
.sn = NULL,
.type = RIC_IND_REPORT };
ind.hdr.len = data->len_hdr;
ind.hdr.buf = data->ind_hdr;
ind.msg.len = data->len_msg;
ind.msg.buf = data->ind_msg;
if(data->call_process_id != NULL){
ind.call_process_id = malloc(sizeof(data->len_cpid) );
assert(ind.call_process_id != NULL && "Memory exhausted" );
ind.call_process_id->buf = data->call_process_id;
ind.call_process_id->len = data->len_cpid;
}
return ind;
}
static inline
void free_fd(void* key, void* value)
{
assert(key != NULL);
assert(value != NULL);
int* fd = (int*) key;
assert(*fd > 0 );
free(value);
}
static inline
void free_pending_ev(void* key, void* value)
{
assert(key != NULL);
assert(value != NULL);
pending_event_t* ev = (pending_event_t*)key;
assert(valid_pending_event(*ev));
free(value);
}
static inline
void free_pending_agent(e2_agent_t* ag)
{
assert(ag != NULL);
bi_map_free(&ag->pending);
}
static inline
void free_indication_event(e2_agent_t* ag)
{
assert(ag != NULL);
bi_map_free(&ag->ind_event);
}
static inline
void init_pending_events(e2_agent_t* ag)
{
assert(ag != NULL);
size_t fd_sz = sizeof(int);
size_t event_sz = sizeof( pending_event_t );
bi_map_init(&ag->pending, fd_sz, event_sz, cmp_fd, cmp_pending_event, free_fd, free_pending_ev );
}
static inline
void free_ind_event(void* key, void* value)
{
assert(key != NULL);
assert(value != NULL);
(void)key;
ind_event_t* ev = (ind_event_t* )value;
free(ev);
}
static inline
void free_key(void* key, void* value)
{
assert(key != NULL);
assert(value != NULL);
(void)key;
int* fd = (int* )value;
free(fd);
}
static inline
void init_indication_event(e2_agent_t* ag)
{
assert(ag != NULL);
size_t key_sz_fd = sizeof(int);
size_t key_sz_ind = sizeof(ind_event_t);
bi_map_init(&ag->ind_event, key_sz_fd, key_sz_ind, cmp_fd, cmp_ind_event, free_ind_event, free_key);
}
static inline
void* ind_fd(e2_agent_t* ag, int fd)
{
assert(ag != NULL);
assert(fd > 0);
void* start_it = assoc_front(&ag->ind_event.left);
void* end_it = assoc_end(&ag->ind_event.left);
void* it = find_if(&ag->ind_event.left, start_it, end_it, &fd, eq_fd );
return it;
}
static inline
bool net_pkt(const e2_agent_t* ag, int fd)
{
assert(ag != NULL);
assert(fd > 0);
return fd == ag->ep.base.fd;
}
static inline
bool ind_event(e2_agent_t* ag, int fd, ind_event_t** i_ev)
{
assert(*i_ev == NULL);
void* it = ind_fd(ag, fd);
void* end_it = assoc_end(&ag->ind_event.left); // bi_map_end_left(&ag->ind_event);
if(it != end_it){
*i_ev = assoc_value(&ag->ind_event.left, it);
return true;
}
return false;
}
static inline
bool pend_event(e2_agent_t* ag, int fd, pending_event_t** p_ev)
{
assert(ag != NULL);
assert(fd > 0);
assert(*p_ev == NULL);
assert(bi_map_size(&ag->pending) == 1 );
void* start_it = assoc_front(&ag->pending.left);
void* end_it = assoc_end(&ag->pending.left);
void* it = find_if(&ag->pending.left,start_it, end_it, &fd, eq_fd);
assert(it != end_it);
*p_ev = assoc_value(&ag->pending.left ,it);
return *p_ev != NULL;
}
/*
static
async_event_t find_event_type(e2_agent_t* ag, int fd)
{
assert(ag != NULL);
assert(fd > 0);
async_event_t e = {.type = UNKNOWN_EVENT };
if (net_pkt(ag, fd) == true){
e.type = NETWORK_EVENT;
} else if (ind_event(ag, fd, &e.i_ev) == true) {
e.type = INDICATION_EVENT;
} else if (pend_event(ag, fd, &e.p_ev) == true){
e.type = PENDING_EVENT;
} else{
assert("Unknown event happened!");
}
return e;
}
*/
static
void consume_fd(int fd)
{
assert(fd > 0);
uint64_t read_buf = 0;
ssize_t const bytes = read(fd,&read_buf, sizeof(read_buf));
assert(bytes == sizeof(read_buf));
}
static
async_event_t next_async_event_agent(e2_agent_t* ag)
{
assert(ag != NULL);
int const fd = event_asio_agent(&ag->io);
async_event_t e = {.type = UNKNOWN_EVENT,
.fd = fd};
if(fd == -1){ // no event happened. Just for checking the stop_token condition
e.type = CHECK_STOP_TOKEN_EVENT;
} else if (net_pkt(ag, fd) == true){
e.msg = e2ap_recv_msg_agent(&ag->ep);
if(e.msg.type == SCTP_MSG_NOTIFICATION){
e.type = SCTP_CONNECTION_SHUTDOWN_EVENT;
} else if (e.msg.type == SCTP_MSG_PAYLOAD){
e.type = SCTP_MSG_ARRIVED_EVENT;
} else {
assert(0!=0 && "Unknown type");
}
} else if (ind_event(ag, fd, &e.i_ev) == true) {
e.type = INDICATION_EVENT;
} else if (pend_event(ag, fd, &e.p_ev) == true){
e.type = PENDING_EVENT;
} else {
assert(0!=0 && "Unknown event happened!");
}
return e;
}
static
void e2_event_loop_agent(e2_agent_t* ag)
{
assert(ag != NULL);
while(ag->stop_token == false){
async_event_t e = next_async_event_agent(ag);
assert(e.type != UNKNOWN_EVENT && "Unknown event triggered ");
switch(e.type){
case SCTP_MSG_ARRIVED_EVENT:
{
defer({free_sctp_msg(&e.msg);});
e2ap_msg_t msg = e2ap_msg_dec_ag(&ag->ap, e.msg.ba);
defer( { e2ap_msg_free_ag(&ag->ap, &msg);} );
e2ap_msg_t ans = e2ap_msg_handle_agent(ag, &msg);
defer( { e2ap_msg_free_ag(&ag->ap, &ans);} );
if(ans.type != NONE_E2_MSG_TYPE){
byte_array_t ba_ans = e2ap_msg_enc_ag(&ag->ap, &ans);
defer ({free_byte_array(ba_ans); } );
e2ap_send_bytes_agent(&ag->ep, ba_ans);
}
break;
}
case INDICATION_EVENT:
{
sm_agent_t* sm = e.i_ev->sm;
sm_ind_data_t data = sm->proc.on_indication(sm);
ric_indication_t ind = generate_indication(ag, &data, e.i_ev);
defer({ e2ap_free_indication(&ind); } );
byte_array_t ba = e2ap_enc_indication_ag(&ag->ap, &ind);
defer({ free_byte_array(ba); } );
e2ap_send_bytes_agent(&ag->ep, ba);
consume_fd(e.fd);
break;
}
case PENDING_EVENT:
{
assert(*e.p_ev == SETUP_REQUEST_PENDING_EVENT && "Unforeseen pending event happened!" );
// Resend the subscription request message
e2_setup_request_t sr = generate_setup_request(ag);
defer({ e2ap_free_setup_request(&sr); } );
printf("[E2AP] Resending Setup Request after timeout\n");
byte_array_t ba = e2ap_enc_setup_request_ag(&ag->ap, &sr);
defer({ free_byte_array(ba); } );
e2ap_send_bytes_agent(&ag->ep, ba);
consume_fd(e.fd);
break;
}
case SCTP_CONNECTION_SHUTDOWN_EVENT:
{
notification_handle_ag(ag, &e.msg);
break;
}
case CHECK_STOP_TOKEN_EVENT:
{
break;
}
default:
{
assert(0!=0 && "Unknown event happened");
break;
}
}
}
printf("ag->agent_stopped = true \n");
ag->agent_stopped = true;
}
e2_agent_t* e2_init_agent(const char* addr, int port, global_e2_node_id_t ge2nid, sm_io_ag_t io, const char* libs_dir)
{
assert(addr != NULL);
assert(port > 0 && port < 65535);
printf("[E2 AGENT]: Initializing ... \n");
e2_agent_t* ag = calloc(1, sizeof(*ag));
assert(ag != NULL && "Memory exhausted");
e2ap_init_ep_agent(&ag->ep, addr, port);
init_asio_agent(&ag->io);
add_fd_asio_agent(&ag->io, ag->ep.base.fd);
init_ap(&ag->ap.base.type);
init_handle_msg_agent(&ag->handle_msg);
init_plugin_ag(&ag->plugin, libs_dir, io);
init_pending_events(ag);
init_indication_event(ag);
ag->global_e2_node_id = ge2nid;
ag->stop_token = false;
ag->agent_stopped = false;
return ag;
}
void e2_start_agent(e2_agent_t* ag)
{
assert(ag != NULL);
// Resend the subscription request message
e2_setup_request_t sr = generate_setup_request(ag);
defer({ e2ap_free_setup_request(&sr); } );
printf("[E2-AGENT]: Sending setup request\n");
byte_array_t ba = e2ap_enc_setup_request_ag(&ag->ap, &sr);
defer({free_byte_array(ba); } );
e2ap_send_bytes_agent(&ag->ep, ba);
// A pending event is created along with a timer of 3000 ms,
// after which an event will be generated
pending_event_t ev = SETUP_REQUEST_PENDING_EVENT;
long const wait_ms = 3000;
int fd_timer = create_timer_ms_asio_agent(&ag->io, wait_ms, wait_ms);
//printf("fd_timer with value created == %d\n", fd_timer);
bi_map_insert(&ag->pending, &fd_timer, sizeof(fd_timer), &ev, sizeof(ev));
e2_event_loop_agent(ag);
}
void e2_free_agent(e2_agent_t* ag)
{
ag->stop_token = true;
while(ag->agent_stopped == false){
usleep(1000);
}
free_plugin_ag(&ag->plugin);
free_pending_agent(ag);
free_indication_event(ag);
free(ag);
}
//////////////////////////////////
/////////////////////////////////
void e2_send_subscription_response(e2_agent_t* ag, const ric_subscription_response_t* sr)
{
assert(ag != NULL);
assert(sr != NULL);
byte_array_t ba = e2ap_enc_subscription_response_ag(&ag->ap, sr);
e2ap_send_bytes_agent(&ag->ep, ba);
free_byte_array(ba);
}
void e2_send_subscription_failure(e2_agent_t* ag, const ric_subscription_failure_t* sf)
{
assert(ag != NULL);
assert(sf != NULL);
byte_array_t ba = e2ap_enc_subscription_failure_ag(&ag->ap, sf);
e2ap_send_bytes_agent(&ag->ep, ba);
free_byte_array(ba);
}
void e2_send_indication_agent(e2_agent_t* ag, const ric_indication_t* indication)
{
assert(ag != NULL);
assert(indication != NULL);
byte_array_t ba = e2ap_enc_indication_ag(&ag->ap, indication);
e2ap_send_bytes_agent(&ag->ep, ba);
free_byte_array(ba);
}
void e2_send_subscription_delete_response(e2_agent_t* ag, const ric_subscription_delete_response_t* sdr)
{
assert(ag != NULL);
assert(sdr != NULL);
byte_array_t ba = e2ap_enc_subscription_delete_response_ag(&ag->ap, sdr);
e2ap_send_bytes_agent(&ag->ep, ba);
free_byte_array(ba);
}
void e2_send_subscription_delete_failure(e2_agent_t* ag, const ric_subscription_delete_failure_t* sdf)
{
byte_array_t ba = e2ap_enc_subscription_delete_failure_ag(&ag->ap, sdf );
e2ap_send_bytes_agent(&ag->ep, ba);
free_byte_array(ba);
}
void e2_send_control_acknowledge(e2_agent_t* ag, const ric_control_acknowledge_t* ca)
{
byte_array_t ba = e2ap_enc_control_acknowledge_ag(&ag->ap, ca);
e2ap_send_bytes_agent(&ag->ep, ba);
free_byte_array(ba);
}
void e2_send_control_failure(e2_agent_t* ag, const ric_control_failure_t* cf)
{
byte_array_t ba = e2ap_enc_control_failure_ag(&ag->ap, cf);
e2ap_send_bytes_agent(&ag->ep, ba);
free_byte_array(ba);
}

View File

@@ -0,0 +1,100 @@
/*
* 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 E2_AGENT_H
#define E2_AGENT_H
#include "assoc_container/assoc_generic.h"
#include "assoc_container/bimap.h"
#include "common/ngran_types.h"
#include "lib/v1/ap/global_consts.h"
#include "lib/v1/ap/type_defs.h"
#include "asio_agent.h"
#include "e2ap_agent.h"
#include "endpoint_agent.h"
#include "plugin_agent.h"
#include "sm/sm_io.h"
#include <stdatomic.h>
#include <stdbool.h>
typedef struct e2_agent_s e2_agent_t;
typedef e2ap_msg_t (*handle_msg_fp_agent)(struct e2_agent_s*, const e2ap_msg_t* msg) ;
typedef struct e2_agent_s
{
e2ap_ep_ag_t ep;
e2ap_agent_t ap;
asio_agent_t io;
handle_msg_fp_agent handle_msg[30]; // 26 E2AP + 4 E42AP note that not all the slots will be occupied
// Registered SMs
plugin_ag_t plugin;
// Registered Indication events
bi_map_t ind_event; // key1:fd, key2:ind_event_t
// Pending events
bi_map_t pending; // left: fd, right: pending_event_t
global_e2_node_id_t global_e2_node_id;
atomic_bool stop_token;
atomic_bool agent_stopped;
} e2_agent_t;
e2_agent_t* e2_init_agent(const char* addr, int port, global_e2_node_id_t ge2nid, sm_io_ag_t io, const char* libs_dir);
// Blocking call
void e2_start_agent(e2_agent_t* ag);
void e2_free_agent(e2_agent_t* ag);
///////////////////////////////////////////////
// E2AP AGENT FUNCTIONAL PROCEDURES MESSAGES //
///////////////////////////////////////////////
void e2_send_subscription_response(e2_agent_t* ag, const ric_subscription_response_t* sr);
void e2_send_subscription_failure(e2_agent_t* ag, const ric_subscription_failure_t* sf);
void e2_send_subscription_delete_response(e2_agent_t* ag, const ric_subscription_delete_response_t* sdr);
void e2_send_subscription_delete_failure(e2_agent_t* ag, const ric_subscription_delete_failure_t* sdf);
void e2_send_indication_agent(e2_agent_t* ag, const ric_indication_t* indication);
void e2_send_control_acknowledge(e2_agent_t* ag, const ric_control_acknowledge_t* ca);
void e2_send_control_failure(e2_agent_t* ag, const ric_control_failure_t* cf);
////////////////////////////////////////////////
#endif

View File

@@ -0,0 +1,91 @@
/*
* 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 "e2_agent_api.h"
#include <assert.h> // for assert
#include <pthread.h> // for pthread_cr...
#include <stdlib.h>
#include <stdio.h> // for NULL
#include "e2_agent.h" // for e2_free_agent
#include "lib/v1/ap/e2ap_types/common/e2ap_global_node_id.h" // for global_e2_...
#include "lib/v1/ap/e2ap_types/common/e2ap_plmn.h" // for plmn_t
#include "common/ngran_types.h" // for ngran_gNB
static
e2_agent_t* agent = NULL;
static
pthread_t thrd_agent;
static inline
void* static_start_agent(void* a)
{
(void)a;
// Blocking...
e2_start_agent(agent);
return NULL;
}
void init_agent_api(int mcc, int mnc, int mnc_digit_len, int nb_id, int cu_du_id, ngran_node_t ran_type, sm_io_ag_t io, e2_agent_args_t const* args)
{
assert(agent == NULL);
assert(mcc > 0);
assert(mnc > 0);
assert(mnc_digit_len > 0);
assert(nb_id > 0);
assert(ran_type >= 0);
const plmn_t plmn = {.mcc = mcc, .mnc = mnc, .mnc_digit_len = mnc_digit_len};
global_e2_node_id_t ge2ni = {.type = ran_type, .plmn = plmn, .nb_id = nb_id, .cu_du_id = NULL};
char* ran_type_str = get_ngran_name(ran_type);
if (NODE_IS_MONOLITHIC(ran_type)) {
printf("[E2 AGENT]: nearRT-RIC IP Address = %s, PORT = %d, RAN type = %s, nb_id = %d\n", args->ip, args->port, ran_type_str, nb_id);
} else if (NODE_IS_CU(ran_type) || NODE_IS_DU(ran_type)) {
assert(cu_du_id > 0);
ge2ni.cu_du_id = calloc(1, sizeof(uint64_t));
assert(ge2ni.cu_du_id != NULL && "memory exhausted");
*ge2ni.cu_du_id = cu_du_id;
printf("[E2 AGENT]: nearRT-RIC IP Address = %s, PORT = %d, RAN type = %s, nb_id = %d, cu_du_id = %ld\n", args->ip, args->port, ran_type_str, nb_id, *ge2ni.cu_du_id);
} else {
assert(0 != 0 && "not support RAN type\n");
}
agent = e2_init_agent(args->ip, args->port, ge2ni, io, args->sm_dir);
// Spawn a new thread for the agent
const int rc = pthread_create(&thrd_agent, NULL, static_start_agent, NULL);
assert(rc == 0);
}
void stop_agent_api(void)
{
assert(agent != NULL);
e2_free_agent(agent);
int const rc = pthread_join(thrd_agent,NULL);
assert(rc == 0);
}

View File

@@ -0,0 +1,40 @@
/*
* 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 E2_AGENT_API_MOSAIC_H
#define E2_AGENT_API_MOSAIC_H
#include "sm/sm_io.h"
#include "common/ngran_types.h"
typedef struct {
const char *ip;
uint16_t port;
const char *sm_dir;
} e2_agent_args_t;
void init_agent_api(int mcc, int mnc, int mnc_digit_len, int nb_id, int cu_du_id, ngran_node_t ran_type, sm_io_ag_t io, e2_agent_args_t const *args);
void stop_agent_api(void);
#endif

View File

@@ -0,0 +1,128 @@
/*
* 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 "e2ap_agent.h"
#include <assert.h>
#include <stdlib.h>
#include "lib/v1/ap/type_defs.h"
#include "lib/v1/ap/enc/e2ap_msg_enc_generic.h"
#include "lib/v1/ap/dec/e2ap_msg_dec_generic.h"
//#include "lib/ap/free/e2ap_msg_free.h"
void e2ap_msg_free_ag(e2ap_agent_t* ap, e2ap_msg_t* msg)
{
assert(ap != NULL);
assert(msg != NULL);
e2_msg_type_t const msg_type = msg->type;
if(msg_type == NONE_E2_MSG_TYPE) // Nothing to free
return;
assert(msg_type < NONE_E2_MSG_TYPE);
ap->base.type.free_msg[msg_type](msg);
}
//
// Encoding
//
byte_array_t e2ap_msg_enc_ag(e2ap_agent_t* ap, const e2ap_msg_t* msg)
{
assert(ap != NULL);
assert(msg != NULL);
e2_msg_type_t const msg_type = msg->type ;
assert(msg_type < NONE_E2_MSG_TYPE);
return ap->base.type.enc_msg[msg_type](msg);
}
byte_array_t e2ap_enc_setup_request_ag(e2ap_agent_t* ap, e2_setup_request_t* sr)
{
assert(ap != NULL);
assert(sr != NULL);
return e2ap_enc_setup_request_gen(&ap->base.type, sr);
}
byte_array_t e2ap_enc_subscription_response_ag(e2ap_agent_t* ap, const ric_subscription_response_t* sr)
{
assert(ap != NULL);
assert(sr != NULL);
return e2ap_enc_subscription_response_gen(&ap->base.type, sr);
}
byte_array_t e2ap_enc_subscription_failure_ag(e2ap_agent_t* ap,const ric_subscription_failure_t* sf)
{
assert(ap != NULL);
assert(sf != NULL);
return e2ap_enc_subscription_failure_gen(&ap->base.type,sf);
}
byte_array_t e2ap_enc_indication_ag(e2ap_agent_t* ap, const ric_indication_t* ind)
{
assert(ap != NULL);
assert(ind != NULL);
return e2ap_enc_indication_gen(&ap->base.type, ind);
}
byte_array_t e2ap_enc_subscription_delete_response_ag(e2ap_agent_t* ap, const ric_subscription_delete_response_t* sdr)
{
assert(ap != NULL);
assert(sdr != NULL);
return e2ap_enc_subscription_delete_response_gen(&ap->base.type, sdr);
}
byte_array_t e2ap_enc_subscription_delete_failure_ag(e2ap_agent_t* ap, const ric_subscription_delete_failure_t* sdf)
{
assert(ap != NULL);
assert(sdf != NULL);
return e2ap_enc_subscription_delete_failure_gen(&ap->base.type, sdf);
}
byte_array_t e2ap_enc_control_acknowledge_ag(e2ap_agent_t* ap, const ric_control_acknowledge_t* ca)
{
assert(ap != NULL);
assert(ca != NULL);
return e2ap_enc_control_acknowledge_gen(&ap->base.type, ca);
}
byte_array_t e2ap_enc_control_failure_ag(e2ap_agent_t* ap, const ric_control_failure_t* cf)
{
assert(ap != NULL);
assert(cf != NULL);
return e2ap_enc_control_failure_gen(&ap->base.type, cf);
}
//
// Decoding
//
e2ap_msg_t e2ap_msg_dec_ag(e2ap_agent_t* ap, byte_array_t ba)
{
assert(ap != NULL);
assert(ba.buf != NULL);
return e2ap_msg_dec_gen(&ap->base.type, ba);
}

View File

@@ -0,0 +1,77 @@
/*
* 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 E2AP_AGENT_H
#define E2AP_AGENT_H
#include "lib/v1/ap/e2ap_ap.h" // for e2ap...
#include "lib/v1/ap/e2ap_types/e2_setup_request.h" // for e2_s...
#include "lib/v1/ap/e2ap_types/ric_control_ack.h" // for ric_...
#include "lib/v1/ap/e2ap_types/ric_control_failure.h" // for ric_...
#include "lib/v1/ap/e2ap_types/ric_indication.h" // for ric_...
#include "lib/v1/ap/e2ap_types/ric_subscription_delete_failure.h" // for ric_...
#include "lib/v1/ap/e2ap_types/ric_subscription_delete_response.h" // for ric_...
#include "lib/v1/ap/e2ap_types/ric_subscription_failure.h" // for ric_...
#include "lib/v1/ap/e2ap_types/ric_subscription_response.h" // for ric_...
#include "lib/v1/ap/type_defs.h" // for e2ap...
#include "byte_array.h" // for byte...
typedef struct e2ap_agent_s
{
e2ap_ap_t base;
} e2ap_agent_t;
void e2ap_msg_free_ag(e2ap_agent_t* ag, e2ap_msg_t* msg);
/////////////
// Encoding
//////////////
byte_array_t e2ap_msg_enc_ag(e2ap_agent_t* ap, const e2ap_msg_t* msg);
byte_array_t e2ap_enc_setup_request_ag(e2ap_agent_t* ap, e2_setup_request_t* sr);
byte_array_t e2ap_enc_subscription_response_ag(e2ap_agent_t* ap, const ric_subscription_response_t* sr);
byte_array_t e2ap_enc_subscription_failure_ag(e2ap_agent_t* ap,const ric_subscription_failure_t* sf);
byte_array_t e2ap_enc_indication_ag(e2ap_agent_t* ap, const ric_indication_t* ind);
byte_array_t e2ap_enc_subscription_delete_response_ag(e2ap_agent_t* ap, const ric_subscription_delete_response_t* sdr);
byte_array_t e2ap_enc_subscription_delete_failure_ag(e2ap_agent_t* ap, const ric_subscription_delete_failure_t* sdf);
byte_array_t e2ap_enc_control_acknowledge_ag(e2ap_agent_t* ap, const ric_control_acknowledge_t* ca);
byte_array_t e2ap_enc_control_failure_ag(e2ap_agent_t* ap, const ric_control_failure_t* cf);
//
// Decoding
//
e2ap_msg_t e2ap_msg_dec_ag(e2ap_agent_t* ap, byte_array_t ba);
#endif

View File

@@ -0,0 +1,121 @@
/*
* 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 "endpoint_agent.h"
#include <arpa/inet.h> // for inet_pton
#include <assert.h> // for assert
#include <netinet/sctp.h>
#include <netinet/in.h> // for sockaddr_in, IPPROTO_SCTP, htonl, htons
#include <stdio.h> // for NULL
#include <stdlib.h> // for malloc
#include <string.h> // for strlen, strncpy
#include <strings.h> // for bzero
#include <sys/socket.h> // for setsockopt, AF_INET, socket, SOCK_SEQPACKET
#include "lib/ep/e2ap_ep.h" // for e2ap_ep_t, e2ap_recv_bytes, e2ap_send_bytes
static
void init_sctp_conn_client(e2ap_ep_ag_t* ep, const char* addr, int port)
{
int sock_fd = socket(AF_INET, SOCK_SEQPACKET, IPPROTO_SCTP);
assert(sock_fd != -1);
struct sockaddr_in servaddr = { .sin_family = AF_INET,
.sin_port = htons(port),
.sin_addr.s_addr = htonl(INADDR_ANY)};
int rc = inet_pton(AF_INET, addr, &servaddr.sin_addr);
assert(rc == 1);
struct sctp_event_subscribe evnts = { .sctp_data_io_event = 1,
.sctp_shutdown_event = 1};
rc = setsockopt(sock_fd, IPPROTO_SCTP, SCTP_EVENTS, &evnts, sizeof (evnts));
assert(rc == 0);
const int close_time = 0; // No automatic close https://www.rfc-editor.org/rfc/pdfrfc/rfc6458.txt.pdf p. 65
rc = setsockopt(sock_fd, IPPROTO_SCTP, SCTP_AUTOCLOSE, &close_time, sizeof(close_time));
assert(rc == 0);
const int no_delay = 1;
rc = setsockopt(sock_fd, IPPROTO_SCTP, SCTP_NODELAY, &no_delay, sizeof(no_delay));
assert(rc == 0);
ep->to = servaddr;
*(int*)(&ep->base.port) = port;
*(int*)(&ep->base.fd) = sock_fd;
strncpy((char*)(&ep->base.addr), addr, 15);
*(char*)(&ep->base.addr[15]) = 0;
}
void e2ap_init_ep_agent(e2ap_ep_ag_t* ep, const char* addr, int port)
{
assert(ep != NULL);
assert(addr != NULL);
assert(strlen(addr) < 16);
assert(port > 0 && port < 65535);
init_sctp_conn_client(ep, addr, port);
}
/*
static
bool eq_sockaddr(struct sockaddr_in* m0, struct sockaddr_in* m1)
{
assert(m0 != NULL);
assert(m1 != NULL);
if(m0->sin_addr.s_addr != m1->sin_addr.s_addr)
return false;
if(m0->sin_port != m1->sin_port)
return false;
if(m0->sin_family != m1->sin_family)
return false;
return true;
}
*/
sctp_msg_t e2ap_recv_msg_agent(e2ap_ep_ag_t* ep)
{
assert(ep != NULL);
sctp_msg_t rcv = e2ap_recv_sctp_msg(&ep->base);// , &ba);
return rcv;
}
void e2ap_send_bytes_agent(e2ap_ep_ag_t* ep, byte_array_t ba)
{
assert(ep != NULL);
assert(ba.buf && ba.len > 0);
sctp_msg_t msg = { .info.addr = ep->to,
.info.sri = ep->sri,
.ba = ba};
e2ap_send_sctp_msg(&ep->base, &msg);
}
void e2ap_free_ep_agent(e2ap_ep_ag_t* ep)
{
assert(ep != NULL);
assert(0!=0 && "Not implemented!");
}

View File

@@ -0,0 +1,50 @@
/*
* 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 ENDPOINT_AGENT
#define ENDPOINT_AGENT
#include "lib/ep/e2ap_ep.h" // for e2ap_ep_t
#include "byte_array.h" // for byte_array_t
typedef struct e2ap_ep_ag
{
e2ap_ep_t base;
// Only one connection supported
struct sockaddr_in to;
struct sctp_sndrcvinfo sri;
int msg_flags;
} e2ap_ep_ag_t;
void e2ap_init_ep_agent(e2ap_ep_ag_t* ep, const char* addr, int port);
void e2ap_free_ep_agent(e2ap_ep_ag_t* ep);
sctp_msg_t e2ap_recv_msg_agent(e2ap_ep_ag_t* ep);
void e2ap_send_bytes_agent(e2ap_ep_ag_t* ep, byte_array_t ba);
#endif

View File

@@ -0,0 +1,379 @@
/*
* 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 "msg_handler_agent.h"
#include "lib/ind_event.h"
#include "lib/pending_events.h"
#include "sm/sm_agent.h"
#include "alg.h"
#include "util/compare.h"
#include <stdio.h>
static
bool check_valid_msg_type(e2_msg_type_t msg_type )
{
return msg_type == RIC_SUBSCRIPTION_REQUEST
|| msg_type == RIC_SUBSCRIPTION_DELETE_REQUEST
|| msg_type == RIC_CONTROL_REQUEST
|| msg_type == E2AP_ERROR_INDICATION
|| msg_type == E2_SETUP_RESPONSE
|| msg_type == E2_SETUP_FAILURE
|| msg_type == E2AP_RESET_REQUEST
|| msg_type == E2AP_RESET_RESPONSE
|| msg_type == RIC_SERVICE_UPDATE_ACKNOWLEDGE
|| msg_type == RIC_SERVICE_UPDATE_FAILURE
|| msg_type == RIC_SERVICE_QUERY
|| msg_type == E2_NODE_CONFIGURATION_UPDATE_ACKNOWLEDGE
|| msg_type == E2_NODE_CONFIGURATION_UPDATE_FAILURE
|| msg_type == E2_CONNECTION_UPDATE;
}
static
void stop_ind_event(e2_agent_t* ag, ric_gen_id_t id)
{
assert(ag != NULL);
ind_event_t tmp = {.ric_id = id, .sm = NULL, .action_id =0 };
int* fd = bi_map_extract_right(&ag->ind_event, &tmp, sizeof(tmp) );
assert(*fd > 0);
//printf("fd value in stopping pending event = %d \n", *fd);
rm_fd_asio_agent(&ag->io, *fd);
free(fd);
}
void init_handle_msg_agent(handle_msg_fp_agent (*handle_msg)[30])
{
memset((*handle_msg), 0, sizeof(handle_msg_fp_agent)*30);
(*handle_msg)[RIC_SUBSCRIPTION_REQUEST] = e2ap_handle_subscription_request_agent;
(*handle_msg)[RIC_SUBSCRIPTION_DELETE_REQUEST] = e2ap_handle_subscription_delete_request_agent;
(*handle_msg)[RIC_CONTROL_REQUEST] = e2ap_handle_control_request_agent;
(*handle_msg)[E2AP_ERROR_INDICATION] = e2ap_handle_error_indication_agent;
(*handle_msg)[E2_SETUP_RESPONSE] = e2ap_handle_setup_response_agent;
(*handle_msg)[E2_SETUP_FAILURE] = e2ap_handle_setup_failure_agent;
(*handle_msg)[E2AP_RESET_REQUEST] = e2ap_handle_reset_request_agent;
(*handle_msg)[E2AP_RESET_RESPONSE] = e2ap_handle_reset_response_agent;
(*handle_msg)[RIC_SERVICE_UPDATE_ACKNOWLEDGE] = e2ap_handle_service_update_ack_agent;
(*handle_msg)[RIC_SERVICE_UPDATE_FAILURE] = e2ap_handle_service_update_failure_agent;
(*handle_msg)[RIC_SERVICE_QUERY] = e2ap_handle_service_query_agent;
(*handle_msg)[E2_NODE_CONFIGURATION_UPDATE_ACKNOWLEDGE] = e2ap_handle_node_configuration_update_ack_agent;
(*handle_msg)[E2_NODE_CONFIGURATION_UPDATE_FAILURE] = e2ap_handle_node_configuration_update_failure_agent;
(*handle_msg)[E2_CONNECTION_UPDATE] = e2ap_handle_connection_update_agent;
}
e2ap_msg_t e2ap_msg_handle_agent(e2_agent_t* ag, const e2ap_msg_t* msg)
{
assert(msg != NULL);
const e2_msg_type_t msg_type = msg->type;
assert(check_valid_msg_type(msg_type) == true);
assert(ag->handle_msg[ msg_type ] != NULL);
return ag->handle_msg[msg_type](ag, msg);
}
static inline
bool supported_ric_subscription_request(ric_subscription_request_t const* sr)
{
assert(sr != NULL);
assert(sr->len_action == 1 && "Only one action supported" );
assert(sr->action->type == RIC_ACT_REPORT && "Only report supported" );
return true;
}
static
sm_subs_data_t generate_sm_subs_data( ric_subscription_request_t const* sr )
{
assert(sr != NULL);
sm_subs_data_t data = { .event_trigger = sr->event_trigger.buf,
.len_et = sr->event_trigger.len };
if(sr->action->definition != NULL){
data.action_def = sr->action->definition->buf;
data.len_ad = sr->action->definition->len;
}
return data;
}
static
ric_subscription_response_t generate_subscription_response(ric_gen_id_t const* ric_id, uint8_t ric_act_id)
{
ric_subscription_response_t sr = {
.ric_id = *ric_id,
.not_admitted = 0,
.len_na = 0,
};
sr.admitted = calloc(1, sizeof(ric_action_admitted_t));
assert(sr.admitted != NULL && "Memory exahusted");
sr.admitted->ric_act_id = ric_act_id;
sr.len_admitted = 1;
return sr;
}
e2ap_msg_t e2ap_handle_subscription_request_agent(e2_agent_t* ag, const e2ap_msg_t* msg)
{
assert(ag != NULL);
assert(msg != NULL);
assert(msg->type == RIC_SUBSCRIPTION_REQUEST);
printf("[E2-AGENT]: RIC_SUBSCRIPTION_REQUEST rx\n");
ric_subscription_request_t const* sr = &msg->u_msgs.ric_sub_req;
assert(supported_ric_subscription_request(sr) == true);
sm_subs_data_t data = generate_sm_subs_data(sr);
uint16_t const ran_func_id = sr->ric_id.ran_func_id;
sm_agent_t* sm = sm_plugin_ag(&ag->plugin, ran_func_id);
subscribe_timer_t t = sm->proc.on_subscription(sm, &data);
int fd_timer = create_timer_ms_asio_agent(&ag->io, t.ms, t.ms);
//printf("fd_timer for subscription value created == %d\n", fd_timer);
// Register the indication event
ind_event_t ev;
ev.action_id = sr->action[0].id;
ev.ric_id = sr->ric_id;
ev.sm = sm;
bi_map_insert(&ag->ind_event, &fd_timer, sizeof(fd_timer), &ev, sizeof(ev));
uint8_t const ric_act_id = sr->action[0].id;
e2ap_msg_t ans = {.type = RIC_SUBSCRIPTION_RESPONSE,
.u_msgs.ric_sub_resp = generate_subscription_response(&sr->ric_id, ric_act_id) };
return ans;
}
static inline
bool eq_ind_event(const void* value, const void* key)
{
assert(value != NULL);
assert(key != NULL);
ric_gen_id_t* ric_id = (ric_gen_id_t*)value;
ind_event_t* ind_ev = (ind_event_t*)key;
return eq_ric_gen_id(ric_id, &ind_ev->ric_id );
}
e2ap_msg_t e2ap_handle_subscription_delete_request_agent(e2_agent_t* ag, const e2ap_msg_t* msg)
{
assert(ag != NULL);
assert(msg != NULL);
assert(msg->type == RIC_SUBSCRIPTION_DELETE_REQUEST);
printf("[E2-AGENT]: RIC_SUBSCRIPTION_DELETE_REQUEST rx\n");
const ric_subscription_delete_request_t* sdr = &msg->u_msgs.ric_sub_del_req;
stop_ind_event(ag, sdr->ric_id);
ric_subscription_delete_response_t sub_del = {.ric_id = sdr->ric_id };
e2ap_msg_t ans = {.type = RIC_SUBSCRIPTION_DELETE_RESPONSE};
ans.u_msgs.ric_sub_del_resp = sub_del;
return ans;
}
static
byte_array_t* ba_from_ctrl_out(sm_ctrl_out_data_t const* data)
{
assert(data != NULL);
byte_array_t* ba = NULL;
size_t const sz = data->len_out;
if(sz > 0){
ba = malloc(sizeof(byte_array_t ) ) ;
assert(ba != NULL && "Memory exhausted!");
ba->len = sz;
ba->buf = malloc(sz);
assert(ba->buf != NULL && "Memory exhausted");
memcpy(ba->buf, data->ctrl_out, sz);
}
return ba;
}
// The purpose of the RIC Control procedure is to initiate or resume a specific functionality in the E2 Node.
e2ap_msg_t e2ap_handle_control_request_agent(e2_agent_t* ag, const e2ap_msg_t* msg)
{
assert(ag != NULL);
assert(msg != NULL);
assert(msg->type == RIC_CONTROL_REQUEST);
ric_control_request_t const* ctrl_req = &msg->u_msgs.ric_ctrl_req;
assert(ctrl_req->ack_req != NULL && *ctrl_req->ack_req == RIC_CONTROL_REQUEST_ACK );
sm_ctrl_req_data_t data = {.ctrl_hdr = ctrl_req->hdr.buf,
.len_hdr = ctrl_req->hdr.len,
.ctrl_msg = ctrl_req->msg.buf,
.len_msg = ctrl_req->msg.len};
uint16_t const ran_func_id = ctrl_req->ric_id.ran_func_id;
sm_agent_t* sm = sm_plugin_ag(&ag->plugin, ran_func_id);
sm_ctrl_out_data_t ctrl_ans = sm->proc.on_control(sm, &data);
defer({ free_sm_ctrl_out_data(&ctrl_ans); } );
byte_array_t* ba_ctrl_ans = ba_from_ctrl_out(&ctrl_ans);
ric_control_acknowledge_t ric_ctrl_ack = {.ric_id = ctrl_req->ric_id,
.call_process_id = NULL,
.status = RIC_CONTROL_STATUS_SUCCESS,
.control_outcome = ba_ctrl_ans } ;
printf("[E2-AGENT]: CONTROL ACKNOWLEDGE sent\n");
e2ap_msg_t ans = {.type = RIC_CONTROL_ACKNOWLEDGE};
ans.u_msgs.ric_ctrl_ack = ric_ctrl_ack;
return ans;
}
e2ap_msg_t e2ap_handle_error_indication_agent(e2_agent_t* ag, const e2ap_msg_t* msg)
{
assert(ag != NULL);
assert(msg != NULL);
assert(0!=0 && "Not implemented");
e2ap_msg_t ans = {0};
return ans;
}
static
void stop_pending_event(e2_agent_t* ag, pending_event_t event)
{
assert(ag != NULL);
int* fd = bi_map_extract_right(&ag->pending, &event, sizeof(event));
assert(*fd > 0);
printf("[E2-AGENT]: stopping pending\n");
//event = %d \n", *fd);
rm_fd_asio_agent(&ag->io, *fd);
free(fd);
}
e2ap_msg_t e2ap_handle_setup_response_agent(e2_agent_t* ag, const e2ap_msg_t* msg)
{
assert(ag != NULL);
assert(msg != NULL);
assert(msg->type == E2_SETUP_RESPONSE);
printf("[E2-AGENT]: SETUP-RESPONSE received\n");
// Stop the timer
stop_pending_event(ag, SETUP_REQUEST_PENDING_EVENT);
e2ap_msg_t ans = {.type = NONE_E2_MSG_TYPE};
return ans;
}
e2ap_msg_t e2ap_handle_setup_failure_agent(e2_agent_t* ag, const e2ap_msg_t* msg)
{
assert(ag != NULL);
assert(msg != NULL);
assert(0!=0 && "Not implemented");
e2ap_msg_t ans = {.type = NONE_E2_MSG_TYPE};
return ans;
}
e2ap_msg_t e2ap_handle_reset_request_agent(e2_agent_t* ag, const e2ap_msg_t* msg)
{
assert(ag != NULL);
assert(msg != NULL);
assert(0!=0 && "Not implemented");
e2ap_msg_t ans = {.type = NONE_E2_MSG_TYPE};
return ans;
}
e2ap_msg_t e2ap_handle_reset_response_agent(e2_agent_t* ag, const e2ap_msg_t* msg)
{
assert(ag != NULL);
assert(msg != NULL);
assert(0!=0 && "Not implemented");
e2ap_msg_t ans = {.type = NONE_E2_MSG_TYPE};
return ans;
}
e2ap_msg_t e2ap_handle_service_update_ack_agent(e2_agent_t* ag, const e2ap_msg_t* msg)
{
assert(ag != NULL);
assert(msg != NULL);
assert(0!=0 && "Not implemented");
e2ap_msg_t ans = {.type = NONE_E2_MSG_TYPE};
return ans;
}
e2ap_msg_t e2ap_handle_service_update_failure_agent(e2_agent_t* ag, const e2ap_msg_t* msg)
{
assert(ag != NULL);
assert(msg != NULL);
assert(0!=0 && "Not implemented");
e2ap_msg_t ans = {.type = NONE_E2_MSG_TYPE};
return ans;
}
e2ap_msg_t e2ap_handle_service_query_agent(e2_agent_t* ag, const e2ap_msg_t* msg)
{
assert(ag != NULL);
assert(msg != NULL);
assert(0!=0 && "Not implemented");
e2ap_msg_t ans = {.type = NONE_E2_MSG_TYPE};
return ans;
}
e2ap_msg_t e2ap_handle_node_configuration_update_ack_agent(e2_agent_t* ag, const e2ap_msg_t* msg)
{
assert(ag != NULL);
assert(msg != NULL);
assert(0!=0 && "Not implemented");
e2ap_msg_t ans = {.type = NONE_E2_MSG_TYPE};
return ans;
}
e2ap_msg_t e2ap_handle_node_configuration_update_failure_agent(e2_agent_t* ag, const e2ap_msg_t* msg)
{
assert(ag != NULL);
assert(msg != NULL);
assert(0!=0 && "Not implemented");
e2ap_msg_t ans = {.type = NONE_E2_MSG_TYPE};
return ans;
}
e2ap_msg_t e2ap_handle_connection_update_agent(e2_agent_t* ag, const e2ap_msg_t* msg)
{
assert(ag != NULL);
assert(msg != NULL);
assert(0!=0 && "Not implemented");
e2ap_msg_t ans = {.type = NONE_E2_MSG_TYPE};
return ans;
}

View File

@@ -0,0 +1,95 @@
/*
* 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 MSG_HANDLER_AGENT
#define MSG_HANDLER_AGENT
#include "e2_agent.h"
#include "lib/v1/ap/type_defs.h"
void init_handle_msg_agent(handle_msg_fp_agent (*handle_msg)[30]);
e2ap_msg_t e2ap_msg_handle_agent(e2_agent_t* agent, const e2ap_msg_t* msg);
///////////////////////////////////////////////////////////////////////////////////////////////////
// O-RAN E2APv01.01: Messages for Global Procedures ///////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////
// RIC -> E2
e2ap_msg_t e2ap_handle_subscription_request_agent(e2_agent_t* ag, const e2ap_msg_t* msg);
//RIC -> E2
e2ap_msg_t e2ap_handle_subscription_delete_request_agent(e2_agent_t* ag, const e2ap_msg_t* msg);
// RIC -> E2
e2ap_msg_t e2ap_handle_control_request_agent(e2_agent_t* ag, const e2ap_msg_t* msg);
///////////////////////////////////////////////////////////////////////////////////////////////////
// O-RAN E2APv01.01: Messages for Global Procedures ///////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////
// RIC <-> E2
e2ap_msg_t e2ap_handle_error_indication_agent(e2_agent_t* ag, const e2ap_msg_t* msg);
// RIC -> E2
e2ap_msg_t e2ap_handle_setup_response_agent(e2_agent_t* ag, const e2ap_msg_t* msg);
// RIC -> E2
e2ap_msg_t e2ap_handle_setup_failure_agent(e2_agent_t* ag, const e2ap_msg_t* msg);
// RIC <-> E2
e2ap_msg_t e2ap_handle_reset_request_agent(e2_agent_t* ag, const e2ap_msg_t* msg);
// RIC <-> E2
e2ap_msg_t e2ap_handle_reset_response_agent(e2_agent_t* ag, const e2ap_msg_t* msg);
// RIC -> E2
e2ap_msg_t e2ap_handle_service_update_ack_agent(e2_agent_t* ag, const e2ap_msg_t* msg);
// RIC -> E2
e2ap_msg_t e2ap_handle_service_update_failure_agent(e2_agent_t* ag, const e2ap_msg_t* msg);
// RIC -> E2
e2ap_msg_t e2ap_handle_service_query_agent(e2_agent_t* ag, const e2ap_msg_t* msg);
// RIC -> E2
e2ap_msg_t e2ap_handle_node_configuration_update_ack_agent(e2_agent_t* ag, const e2ap_msg_t* msg);
// RIC -> E2
e2ap_msg_t e2ap_handle_node_configuration_update_failure_agent(e2_agent_t* ag, const e2ap_msg_t* msg);
// RIC -> E2
e2ap_msg_t e2ap_handle_connection_update_agent(e2_agent_t* ag, const e2ap_msg_t* msg);
#endif

View File

@@ -0,0 +1,26 @@
#include "not_handler_agent.h"
#include <assert.h>
#include <stdbool.h>
#include <stdio.h>
#include "../lib/pending_events.h"
void notification_handle_ag(e2_agent_t* ag, sctp_msg_t const* msg)
{
assert(ag != NULL);
assert(msg != NULL && msg->type == SCTP_MSG_NOTIFICATION);
// A pending event is created along with a timer of 3000 ms,
// after which an event will be generated
pending_event_t ev = SETUP_REQUEST_PENDING_EVENT;
long const wait_ms = 3000;
int fd_timer = create_timer_ms_asio_agent(&ag->io, wait_ms, wait_ms);
bi_map_insert(&ag->pending, &fd_timer, sizeof(fd_timer), &ev, sizeof(ev));
puts("E2 AGENT: Communication with the nearRT-RIC lost\n" );
}

View File

@@ -0,0 +1,9 @@
#ifndef NOTIFICATION_HANDLER_AGENT_H
#define NOTIFICATION_HANDLER_AGENT_H
#include "e2_agent.h"
void notification_handle_ag(e2_agent_t* ag, sctp_msg_t const* msg);
#endif

View File

@@ -0,0 +1,260 @@
/*
* 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 "plugin_agent.h"
#include "alg.h"
#include "lock_guard/lock_guard.h"
#include "util/compare.h"
#include <assert.h>
#include <arpa/inet.h>
#include <dlfcn.h>
#include <dirent.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <unistd.h>
static inline
void free_sm_agent(void* key, void* value)
{
assert(key != NULL);
assert(value != NULL);
sm_agent_t* sm = (sm_agent_t*)value;
void* handle = sm->handle;
sm->free_sm(sm);
if(handle != NULL)
dlclose(handle);
}
static inline
void check_dl_error(void)
{
const char* error = dlerror();
if (error != NULL) {
printf("Error from dlerror = %s \n", error);
fflush(stdout);
assert(0 != 0 && "error loading the init of the shared object");
}
}
static
int is_regular_file(const char *path)
{
struct stat path_stat;
stat(path, &path_stat);
return S_ISREG(path_stat.st_mode);
}
static
bool file_ends_on(const char *path, size_t plen, const char *end, size_t elen)
{
size_t end_start = plen - elen;
/* check including the terminating null byte */
return strncmp(&path[end_start], end, elen + 1) == 0;
}
static
void load_all_pugin_ag(plugin_ag_t* p, const char* dir_path)
{
/* Scanning the in directory */
printf("[E2 AGENT] loading plugins from directory %s\n", dir_path);
DIR* fd = opendir(dir_path);
assert(fd != NULL && "Error opening the input directory");
struct dirent* in_file = readdir(fd);
while (in_file != NULL) {
// We don't want current and parent directories
if (!strncmp(in_file->d_name, ".", 2)) {
in_file = readdir(fd);
continue;
}
if (!strncmp(in_file->d_name, "..", 3)) {
in_file = readdir(fd);
continue;
}
// We don't want anything that does not end on .so
const size_t len = strlen(in_file->d_name);
if (!file_ends_on(in_file->d_name, len, ".so", 3)) {
in_file = readdir(fd);
continue;
}
char file_path[FILENAME_MAX] = {0};
strncat(file_path, dir_path, FILENAME_MAX - 1);
const size_t fp_len = strlen(file_path);
strncat(file_path + fp_len, in_file->d_name, FILENAME_MAX - fp_len - 1);
if (is_regular_file(file_path))
load_plugin_ag(p, file_path);
in_file = readdir(fd);
}
closedir(fd);
}
void unload_all_pugin_ag(plugin_ag_t* p, const char* path)
{
assert(p != NULL);
assert(path != NULL);
assert(0!=0 && "Not implemented!");
}
void init_plugin_ag(plugin_ag_t* p, const char* dir_path, sm_io_ag_t io)
{
assert(p != NULL);
assert(dir_path != NULL);
p->dir_path = (char*)dir_path;
p->io = io;
p->flag_shutdown = false;
pthread_mutexattr_t attr= {0};
pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_ERRORCHECK);
int rc = pthread_mutex_init(&p->sm_ds_mtx, &attr);
assert(rc == 0);
const size_t ran_func_size = sizeof(uint16_t);
assoc_init(&p->sm_ds, ran_func_size, cmp_ran_func_id, free_sm_agent );
load_all_pugin_ag(p, dir_path);
}
void free_plugin_ag(plugin_ag_t* p)
{
assert(p != NULL);
assoc_free(&p->sm_ds);
pthread_mutex_destroy(&p->sm_ds_mtx);
// Thread management
p->flag_shutdown = true;
}
static inline
bool absolute_path(const char* path)
{
return path != NULL ? true : false;
}
void load_plugin_ag(plugin_ag_t* p, const char* path)
{
//ToDo: Looks code from a sophomore. DO IT PROPERLY
assert(p != NULL);
assert(path != NULL);
printf("[E2 AGENT]: Opening plugin from path = %s \n", path );
void* handle = dlopen(path, RTLD_NOW);
if(handle == NULL){
printf("Error while opening the shared object = %s \n", dlerror());
return;
}
assert(handle != NULL && "Could not open the file path");
dlerror();
char* so_name = strrchr(path, '/');
char* ptr_so_name = NULL;
if(absolute_path(so_name) == true){
ptr_so_name = so_name + strlen("/lib");
assert(so_name != NULL);
} else {
ptr_so_name = (char*)path + strlen("lib");
}
char symbol_so[256] = {'m','a','k','e','_'};
char* needle = "_sm.so";
char* match = strstr( ptr_so_name, needle);
assert(match != NULL && "Could not find the string _sm.so in the so\n");
char* ptr = &symbol_so[5];
assert(match > ptr_so_name);
strncat(ptr, ptr_so_name , match - ptr_so_name);
ptr += match - ptr_so_name;
const char* suffix = "_sm_agent";
strncat(ptr,suffix, strlen(suffix));
sm_agent_t* (*fp)(sm_io_ag_t);
fp = dlsym(handle, symbol_so);
check_dl_error();
sm_agent_t* sm = fp(p->io);
sm->handle = handle;
assert(sm != NULL);
const uint16_t ran_func_id = sm->ran_func_id;
{
lock_guard(&p->sm_ds_mtx);
assoc_insert(&p->sm_ds, &ran_func_id, sizeof(ran_func_id), sm);
}
// printf("AGENT: Accepting SM ID = %d with def = %s \n", sm->ran_func_id, sm->ran_func_name);
}
void unload_plugin_ag(plugin_ag_t* p, uint16_t key)
{
assert(p != NULL);
assert(key != 0);
assert(0!=0 && "Not implemented!");
}
sm_agent_t* sm_plugin_ag(plugin_ag_t* p, uint16_t key)
{
assert(p != NULL);
assert(key > 0 && "Reserved value");
lock_guard(&p->sm_ds_mtx);
void* start_it = assoc_front(&p->sm_ds);
void* end_it = assoc_end(&p->sm_ds);
void* it = find_if(&p->sm_ds, start_it, end_it, &key, eq_ran_func_id);
assert(it != end_it && "RAN function ID not found in the RAN");
sm_agent_t* sm = assoc_value(&p->sm_ds, it);
assert(sm->ran_func_id == key);
return sm;
}
size_t size_plugin_ag(plugin_ag_t* p)
{
assert(p != NULL);
lock_guard(&p->sm_ds_mtx);
size_t s = assoc_size(&p->sm_ds);
return s;
}

View File

@@ -0,0 +1,68 @@
/*
* 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 E2_PLUGIN_AGENT_H
#define E2_PLUGIN_AGENT_H
#include <stddef.h>
#include <stdint.h>
#include <stdatomic.h>
#include <pthread.h>
#include "assoc_container/assoc_generic.h"
#include "sm/sm_agent.h"
#include "sm/sm_io.h"
typedef struct
{
sm_io_ag_t io;
const char* dir_path;
// Registered SMs
assoc_rb_tree_t sm_ds; // key: ran_func_id, value: sm_agent_t*
pthread_mutex_t sm_ds_mtx;
int sockfd;
pthread_t thread_rx;
atomic_bool flag_shutdown;
} plugin_ag_t;
void init_plugin_ag(plugin_ag_t* p, const char* path, sm_io_ag_t io);
void free_plugin_ag(plugin_ag_t* p);
void load_plugin_ag(plugin_ag_t* p, const char* path);
void unload_plugin_ag(plugin_ag_t* p, uint16_t key);
sm_agent_t* sm_plugin_ag(plugin_ag_t* p, uint16_t key);
size_t size_plugin_ag(plugin_ag_t* p);
#endif

View File

@@ -0,0 +1,11 @@
add_subdirectory(v1)
add_subdirectory(ep)
add_subdirectory(msg_hand)
add_library(pending_events_obj OBJECT
pending_events.c
pending_event_ric.c
ind_event.c
)
target_link_libraries(pending_events_obj PRIVATE e2ap_types_obj e2ap_ap_obj ds)

View File

@@ -0,0 +1,52 @@
/*
* 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 ASYNC_EVENT_H
#define ASYNC_EVENT_H
#include "ind_event.h"
#include "pending_events.h"
#include "ep/sctp_msg.h"
typedef enum
{
CHECK_STOP_TOKEN_EVENT,
SCTP_CONNECTION_SHUTDOWN_EVENT,
SCTP_MSG_ARRIVED_EVENT,
INDICATION_EVENT,
PENDING_EVENT,
UNKNOWN_EVENT,
} async_event_e;
typedef struct
{
async_event_e type;
int fd;
union{
pending_event_t* p_ev;
ind_event_t* i_ev;
sctp_msg_t msg;
};
} async_event_t;
#endif

View File

@@ -0,0 +1,3 @@
add_library(e2ap_ep_obj OBJECT e2ap_ep.c sctp_msg.c )
target_link_libraries(e2ap_ep_obj PRIVATE sctp alg)
target_link_libraries(e2ap_ep_obj PUBLIC ds)

View File

@@ -0,0 +1,190 @@
/*
* 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 "e2ap_ep.h"
#include "lock_guard/lock_guard.h"
#include <pthread.h>
void e2ap_ep_init(e2ap_ep_t* ep)
{
int rc = pthread_mutex_init(&ep->mtx, NULL);
assert(rc == 0);
}
void e2ap_ep_free(e2ap_ep_t* ep)
{
assert(ep != NULL);
int rc = pthread_mutex_destroy(&ep->mtx);
assert(rc == 0);
}
void e2ap_send_sctp_msg(const e2ap_ep_t* ep, sctp_msg_t* msg)
{
assert(ep != NULL);
assert(msg->ba.buf && msg->ba.len > 0);
struct sockaddr_in const* addr = &msg->info.addr;
struct sctp_sndrcvinfo const* sri = &msg->info.sri;
byte_array_t const ba = msg->ba;
lock_guard(&((e2ap_ep_t*)ep)->mtx);
const int rc = sctp_sendmsg(ep->fd, (void*)ba.buf, ba.len, (struct sockaddr *)addr, sizeof(*addr), sri->sinfo_ppid, sri->sinfo_flags, sri->sinfo_stream, 0, 0) ;
assert(rc != 0);
}
static
struct sctp_shutdown_event cp_sn_shutdown_event(struct sctp_shutdown_event const* src)
{
struct sctp_shutdown_event dst = { .sse_type = src->sse_type,
.sse_flags = src->sse_flags,
.sse_length = src->sse_length,
.sse_assoc_id = src->sse_assoc_id };
return dst;
}
static
struct sctp_assoc_change cp_sn_assoc_change( struct sctp_assoc_change const* src)
{
struct sctp_assoc_change dst = {.sac_state = src->sac_state};
switch(src->sac_state) {
case SCTP_COMM_UP:
assert(0 !=0 && "Not implemented");
break;
case SCTP_COMM_LOST:
assert(0 !=0 && "Not implemented");
break;
case SCTP_RESTART:
assert(0 !=0 && "Not implemented");
break;
case SCTP_SHUTDOWN_COMP:
assert(0 !=0 && "Not implemented");
break;
case SCTP_CANT_STR_ASSOC:
assert(0 !=0 && "Not implemented");
break;
default:
assert(0!=0 && "Impossible data path. enum sctp_sac_state only has 5 states" );
}
return dst;
}
static
union sctp_notification cp_sctp_notification(union sctp_notification const* src, size_t len)
{
assert(src != NULL);
assert(sizeof(((union sctp_notification*)NULL)->sn_header) <= len);
union sctp_notification dst = {.sn_header.sn_type = src-> sn_header.sn_type};
switch(src->sn_header.sn_type) {
case SCTP_ASSOC_CHANGE: //This tag indicates that an association has either been opened or closed. Refer to Section 6.1.1 for details.
assert(sizeof(struct sctp_assoc_change) >= len && "Error notification msg size is smaller than struct sctp_assoc_change size\n");
dst.sn_assoc_change = cp_sn_assoc_change(&src->sn_assoc_change);
break;
case SCTP_PEER_ADDR_CHANGE: //This tag indicates that an address that is part of an existing association has experienced a change of state (e.g., a failure or return to service of the reachability of an endpoint via a specific transport address). Please see Section 6.1.2 for data structure details.
assert(0!=0 && "Not implemented");
break;
case SCTP_REMOTE_ERROR: // The attached error message is an Operation Error message received from the remote peer. It includes the complete TLV sent by the remote endpoint. See Section 6.1.3 for the detailed format.
assert(0!=0 && "Not implemented");
break;
case SCTP_SEND_FAILED: //The attached datagram could not be sent to the remote endpoint. This structure includes the original SCTP_SNDINFO that was used in sending this message; i.e., this structure uses the sctp_sndinfo per Section 6.1.11.
assert(0!=0 && "Not implemented");
break;
case SCTP_SHUTDOWN_EVENT: // The peer has sent a SHUTDOWN. No further data should be sent on this socket.
assert( sizeof(struct sctp_shutdown_event) >= len);
dst.sn_shutdown_event = cp_sn_shutdown_event(&src->sn_shutdown_event);
break;
case SCTP_ADAPTATION_INDICATION: //This notification holds the peers indicated adaptation layer. Please see Section 6.1.6.
assert(0!=0 && "Not implemented");
break;
case SCTP_PARTIAL_DELIVERY_EVENT: //This notification is used to tell a receiver that the partial delivery has been aborted. This may indicate that the association is about to be aborted. Please see Section 6.1.7.
assert(0!=0 && "Not implemented");
break;
//case SCTP_AUTHENTICATION_EVENT: //This notification is used to tell a receiver that either an error occurred on authentication, or a new key was made active. See Section 6.1.8.
// assert(0!=0 && "Not implemented");
// break;
case SCTP_SENDER_DRY_EVENT:
assert(0!=0 && "Not implemented");
break;
default:
assert(0!=0 && "Not implemented");
break;
}
return dst;
}
sctp_msg_t e2ap_recv_sctp_msg(e2ap_ep_t* ep)
{
assert(ep != NULL);
sctp_msg_t from = {0};
from.ba.len = 16384;
from.ba.buf = malloc(16384);
assert(from.ba.buf != NULL && "Memory exhausted");
socklen_t len = sizeof(from.info.addr);
int msg_flags = 0;
lock_guard(&((e2ap_ep_t*)ep)->mtx);
int const rc = sctp_recvmsg(ep->fd, from.ba.buf, from.ba.len, (struct sockaddr*)&from.info.addr, &len, &from.info.sri, &msg_flags);
assert(rc > -1 && rc != 0 && rc < (int)from.ba.len);
if(msg_flags & MSG_NOTIFICATION){
assert((msg_flags & MSG_EOR) && "Notification received but the buffer is not large enough");
uint8_t buf[2048] = {0};
memcpy(buf, from.ba.buf, 2048);
free(from.ba.buf);
from.type = SCTP_MSG_NOTIFICATION;
from.notif = cp_sctp_notification((union sctp_notification*) buf, rc);
} else {
from.type = SCTP_MSG_PAYLOAD;
from.ba.len = rc; // set actually received number of bytes
}
return from;
}

View File

@@ -0,0 +1,55 @@
/*
* 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 E2AP_EP
#define E2AP_EP
#include <assert.h>
#include <arpa/inet.h>
#include <errno.h>
#include <netinet/in.h>
#include <netinet/sctp.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <unistd.h>
#include "sctp_msg.h"
typedef struct{
const char addr[16]; // only ipv4 supported
const int port;
const int fd;
pthread_mutex_t mtx;
} e2ap_ep_t;
void e2ap_ep_init(e2ap_ep_t* ep);
void e2ap_ep_free(e2ap_ep_t* ep);
void e2ap_send_sctp_msg(const e2ap_ep_t* ep, sctp_msg_t* msg);
sctp_msg_t e2ap_recv_sctp_msg(e2ap_ep_t* ep);
#endif

View File

@@ -0,0 +1,107 @@
/*
* 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 "sctp_msg.h"
void free_sctp_msg(sctp_msg_t* rcv)
{
assert(rcv != NULL);
if(rcv->type == SCTP_MSG_PAYLOAD)
free_byte_array(rcv->ba);
}
static
int cmp_sockaddr_in(struct sockaddr_in const* m0, struct sockaddr_in const* m1)
{
assert(m0 != NULL);
assert(m1 != NULL);
if(m0->sin_port < m1->sin_port)
return 1;
if(m0->sin_port > m1->sin_port)
return -1;
if(m0->sin_addr.s_addr < m1->sin_addr.s_addr)
return 1;
if(m0->sin_addr.s_addr > m1->sin_addr.s_addr)
return -1;
if(m0->sin_family < m1->sin_family)
return 1;
if(m0->sin_family > m1->sin_family)
return -1;
return 0;
}
static
int cmp_sctp_sndrcvinfo(struct sctp_sndrcvinfo* m0, struct sctp_sndrcvinfo* m1)
{
assert(m0 != NULL && m1 != NULL);
/*
struct sctp_sndrcvinfo {
uint16_t sinfo_stream;
uint16_t sinfo_ssn;
uint16_t sinfo_flags;
uint32_t sinfo_ppid;
uint32_t sinfo_context;
uint32_t sinfo_timetolive;
uint32_t sinfo_tsn;
uint32_t sinfo_cumtsn;
sctp_assoc_t sinfo_assoc_id;
};
*/
return 0;
}
int cmp_sctp_info_wrapper(void const* m0_v, void const* m1_v)
{
if(m0_v == NULL && m1_v == NULL)
return 0;
if(m0_v == NULL)
return 1;
if(m1_v == NULL)
return -1;
sctp_info_t* m0 = (sctp_info_t*)m0_v;
sctp_info_t* m1 = (sctp_info_t*)m1_v;
int cmp = cmp_sockaddr_in(&m0->addr, &m1->addr);
if(cmp != 0) return cmp;
return cmp_sctp_sndrcvinfo(&m0->sri, &m1->sri);
}
bool eq_sctp_info_wrapper(void const* m0, void const* m1)
{
return cmp_sctp_info_wrapper(m0,m1) == 0;
}

View File

@@ -0,0 +1,65 @@
/*
* 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 SCTP_MSG_H
#define SCTP_MSG_H
#include <assert.h>
#include <arpa/inet.h>
#include <errno.h>
#include <netinet/in.h>
#include <netinet/sctp.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <unistd.h>
#include <stdbool.h>
#include "byte_array.h"
typedef enum {
SCTP_MSG_PAYLOAD,
SCTP_MSG_NOTIFICATION
} sctp_msg_type_t;
typedef struct{
struct sockaddr_in addr;
struct sctp_sndrcvinfo sri;
} sctp_info_t ;
int cmp_sctp_info_wrapper(void const* m0, void const* m1);
bool eq_sctp_info_wrapper(void const* m0, void const* m1);
typedef struct{
sctp_msg_type_t type;
sctp_info_t info;
union{
byte_array_t ba;
union sctp_notification notif;
};
} sctp_msg_t;
void free_sctp_msg(sctp_msg_t* rcv);
#endif

View File

@@ -0,0 +1,38 @@
/*
* 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 "ind_event.h"
#include <assert.h>
#include <stdlib.h>
int cmp_ind_event(void const* m0_v, void const* m1_v)
{
assert(m0_v != NULL);
assert(m1_v != NULL);
ind_event_t* m0 = (ind_event_t*)m0_v;
ind_event_t* m1 = (ind_event_t*)m1_v;
int cmp = cmp_ric_gen_id(&m0->ric_id, &m1->ric_id);
return cmp;
}

View File

@@ -0,0 +1,41 @@
/*
* 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 INDICATION_EVENT_H
#define INDICATION_EVENT_H
#include <stdint.h> // for uint8_t
#include "v1/ap/e2ap_types/common/ric_gen_id.h" // for ric_gen_id_t
#include "../sm/sm_agent.h"
typedef struct
{
ric_gen_id_t ric_id;
sm_agent_t* sm;
uint8_t action_id;
} ind_event_t;
int cmp_ind_event(void const* m0_v, void const* m1_v);
#endif

View File

@@ -0,0 +1,6 @@
add_library(msg_hand_obj OBJECT
reg_e2_nodes.c
e2_node_arr.c
)

View File

@@ -0,0 +1,46 @@
/*
* 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 "e2_node_arr.h"
#include <assert.h>
#include <stdlib.h>
void free_e2_node_arr(e2_node_arr_t* xapp)
{
assert(xapp != NULL);
for(size_t i = 0; i < xapp->len; ++i){
for(size_t j = 0; j < xapp->n[i].len_rf; ++j){
free_ran_function(&xapp->n[i].ack_rf[j]);
}
if( xapp->n[i].len_rf > 0)
free(xapp->n[i].ack_rf);
free_global_e2_node_id(&xapp->n[i].id);
}
if(xapp->len > 0){
free(xapp->n);
}
}

View File

@@ -0,0 +1,46 @@
/*
* 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 E2_NODE_ARR_H
#define E2_NODE_ARR_H
#ifdef __cplusplus
extern "C" {
#endif
#include <stdint.h>
#include "../ap/e2ap_types/e2_node_connected.h"
typedef struct{
uint8_t len;
e2_node_connected_t* n;
} e2_node_arr_t;
void free_e2_node_arr(e2_node_arr_t*);
#ifdef __cplusplus
}
#endif
#endif

View File

@@ -0,0 +1,298 @@
/*
* 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 "reg_e2_nodes.h"
#include "lock_guard/lock_guard.h"
#include "find.h"
#include "alg.h"
#include "../../lib/ap/e2ap_types/common/e2ap_global_node_id.h"
#include <assert.h>
#include <pthread.h>
static
void free_ran_function_pointer(void* rf_p)
{
assert(rf_p != NULL);
ran_function_t* rf = *(ran_function_t**)rf_p;
free_ran_function_wrapper(rf);
free(rf);
}
static inline
void free_e2_nodes(void* key, void* value)
{
assert(key != NULL);
assert(value != NULL);
(void)key;
seq_arr_t* arr_node = (seq_arr_t*)value;
//assert(seq_size(arr_node) == 2);
seq_free_func f = free_ran_function_pointer;
seq_arr_free(arr_node, f);
free(arr_node);
global_e2_node_id_t* e2node = (global_e2_node_id_t*) key;
free_global_e2_node_id(e2node);
}
void init_reg_e2_node(reg_e2_nodes_t* i)
{
assert(i != NULL);
assoc_init(&i->node_to_rf, sizeof(global_e2_node_id_t), cmp_global_e2_node_id_wrapper, free_e2_nodes);
pthread_mutexattr_t* attr = NULL;
#ifdef DEBUG
*attr = PTHREAD_MUTEX_ERRORCHECK;
#endif
int const rc = pthread_mutex_init(&i->mtx, attr);
assert(rc == 0);
}
void free_reg_e2_node(reg_e2_nodes_t* i)
{
assert(i != NULL);
assoc_free(&i->node_to_rf);
// assoc_free(&i->rf_to_node);
int const rc = pthread_mutex_destroy(&i->mtx);
assert(rc == 0);
}
void add_reg_e2_node(reg_e2_nodes_t* i, global_e2_node_id_t const* id, size_t len, ran_function_t const ran_func[len])
{
assert(i != NULL);
assert(id != NULL);
assert(len > 0);
assert(ran_func != NULL);
seq_arr_t* arr = calloc(1, sizeof(seq_arr_t));
assert(arr != NULL && "Memory exhausted");
seq_init(arr, sizeof(ran_function_t*));
for(size_t i = 0; i < len; ++i){
ran_function_t* tmp = calloc(1, sizeof(ran_function_t) );
assert(tmp != NULL && "Memory exhausted");
*tmp = cp_ran_function(&ran_func[i]);
seq_push_back(arr, &tmp, sizeof(ran_function_t*) );
}
lock_guard(&i->mtx);
if(assoc_size(&i->node_to_rf) > 0){
void* it_node = assoc_front(&i->node_to_rf);
void* end_node = assoc_end(&i->node_to_rf);
it_node = find_if(&i->node_to_rf, it_node, end_node, id, eq_global_e2_node_id_wrapper );
assert(it_node == end_node && "Trying to add an already existing E2 Node");
}
// if(it_node != end_node) {
// seq_arr_t* old_arr = assoc_extract(&i->node_to_rf,(global_e2_node_id_t*)id);
// seq_free(old_arr, free_ran_function_wrapper);
// free(old_arr);
// }
assoc_insert(&i->node_to_rf, id, sizeof(global_e2_node_id_t), arr);
// void* it_n = assoc_front(&i->node_to_rf);
// seq_arr_t* arr_tmp = assoc_value(&i->node_to_rf, it_n);
// assert(seq_size(arr_tmp) == 2 && "Only for current test valid");
}
static inline
assoc_rb_tree_t available_e2node(reg_e2_nodes_t* n, size_t len, ran_function_t rf[len])
{
assert(n != NULL);
assert(len > 0);
assert(rf != NULL);
assoc_rb_tree_t ret = {0};
assoc_init(&ret, sizeof(global_e2_node_id_t), cmp_global_e2_node_id_wrapper, free_e2_nodes);
lock_guard(&n->mtx);
void* it = assoc_front(&n->node_to_rf);
void* end = assoc_end(&n->node_to_rf);
while(it != end){ // per E2 Node
seq_arr_t* arr_v = assoc_value(&n->node_to_rf, it);
const size_t sz = seq_size(arr_v);
for(size_t i = 0; i < len; ++i){
for(size_t j = 0; j < sz ; ++j){
ran_function_t* r = *(ran_function_t**)seq_at(arr_v, j);
// Add the RAN functions that have permission
if(eq_ran_function(r,&rf[i]) == true){
global_e2_node_id_t* id = assoc_key(&ret, it);
void* it_ret = assoc_front(&ret);
void* end_ret = assoc_end(&ret);
it_ret = find_if(&ret, it_ret, end_ret, id, eq_global_e2_node_id_wrapper);
seq_arr_t* arr = NULL;
if(it_ret == end_ret){
arr = calloc(1, sizeof(seq_arr_t));
assert(arr != NULL && "memory exhasuted");
seq_init(arr,sizeof(ran_function_t*));
assoc_insert(&ret, id, sizeof(global_e2_node_id_t), arr);
} else{
arr = assoc_value(&ret, it_ret);
}
ran_function_t* tmp = calloc(1, sizeof(ran_function_t));
assert(tmp != NULL && "Memory exhausted");
*tmp = cp_ran_function(r);
seq_push_back(arr, tmp, sizeof(ran_function_t*));
}
}
}
it = assoc_next(&n->node_to_rf, it);
}
return ret;
}
size_t sz_reg_e2_node(reg_e2_nodes_t* n)
{
assert(n != NULL);
lock_guard(&n->mtx);
return assoc_size(&n->node_to_rf);
}
assoc_rb_tree_t cp_reg_e2_node(reg_e2_nodes_t* n)
{
assert(n != 0);
// key:global_e2_node_id_t | value: seq_arr_t* of ran_function_t
assoc_rb_tree_t ans = {0};
assoc_init(&ans, sizeof(global_e2_node_id_t), cmp_global_e2_node_id_wrapper, free_e2_nodes);
lock_guard(&n->mtx);
void* it = assoc_front(&n->node_to_rf);
void* end = assoc_end(&n->node_to_rf);
while(it != end){
global_e2_node_id_t* tmp = assoc_key(&n->node_to_rf, it );
global_e2_node_id_t cp_tmp = cp_global_e2_node_id(tmp);
seq_arr_t* arr = assoc_value(&n->node_to_rf, it);
seq_arr_t* new_arr = calloc(1, sizeof(seq_arr_t));
assert(new_arr != NULL);
seq_init(new_arr, sizeof(ran_function_t*));
void* it_arr = seq_front(arr);
void* end_arr = seq_end(arr);
while(it_arr != end_arr){
ran_function_t* r = *(ran_function_t**)it_arr;
ran_function_t* tmp_r = calloc(1, sizeof(ran_function_t));
assert(tmp_r != NULL);
*tmp_r = cp_ran_function(r);
seq_push_back(new_arr, &tmp_r, sizeof(ran_function_t*));
it_arr = seq_next(arr, it_arr);
}
assoc_insert(&ans,&cp_tmp, sizeof(global_e2_node_id_t), new_arr);
it = assoc_next(&n->node_to_rf, it);
}
assert(assoc_size(&ans) == assoc_size(&n->node_to_rf) );
return ans;
}
e2_node_arr_t generate_e2_node_arr(reg_e2_nodes_t* n)
{
assoc_rb_tree_t t = cp_reg_e2_node(n);
defer({ assoc_free(&t); }; );
e2_node_arr_t ans = {0};
ans.len = assoc_size(&t);
if(ans.len > 0){
ans.n = calloc(ans.len, sizeof(e2_node_connected_t) );
assert(ans.n != NULL && "Memory exhausted" );
}
uint32_t i = 0;
void* it = assoc_front(&t);
void* end = assoc_end(&t);
while(it != end){
global_e2_node_id_t* tmp_id = assoc_key(&t, it);
ans.n[i].id = cp_global_e2_node_id(tmp_id);
seq_arr_t* tmp_arr = assoc_value(&t, it);
assert(tmp_arr->elt_size == sizeof(ran_function_t*));
const size_t sz = seq_size(tmp_arr);
ans.n[i].len_rf = sz;
if(sz > 0){
ans.n[i].ack_rf = calloc(sz, sizeof(ran_function_t));
assert(ans.n[i].ack_rf != NULL && "memory exhausted");
}
for(size_t j = 0; j < sz; ++j){
ran_function_t* r = *(ran_function_t**)seq_at(tmp_arr, j);
ans.n[i].ack_rf[j] = cp_ran_function(r);
}
i += 1;
it = assoc_next(&t, it);
}
return ans;
}
void rm_reg_e2_node(reg_e2_nodes_t* n, global_e2_node_id_t const* id)
{
assert(n != NULL);
assert(id != NULL);
printf("[NEAR-RIC]: Removing E2 Node MCC %d MNC %d NB_ID %u \n", id->plmn.mcc, id->plmn.mnc, id->nb_id);
{
lock_guard(&n->mtx);
void* it = assoc_front(&n->node_to_rf);
void* end = assoc_end(&n->node_to_rf);
it = find_if(&n->node_to_rf, it, end, id, eq_global_e2_node_id_wrapper );
assert(it != end && "Not registed e2 Node passed");
seq_arr_t* arr = assoc_extract(&n->node_to_rf, (global_e2_node_id_t*)id);;
free_e2_nodes((void*)id , arr);
}
}

View File

@@ -0,0 +1,56 @@
/*
* 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 REGISTERED_E2_NODES_H
#define REGISTERED_E2_NODES_H
#include "assoc_container/assoc_generic.h"
#include "../ap/e2ap_types/e2_node_connected.h"
#include "e2_node_arr.h"
#include <stddef.h>
#include <stdint.h>
#include <pthread.h>
typedef struct{
// key:global_e2_node_id_t | value: seq_arr_t* of ran_function_t
assoc_rb_tree_t node_to_rf;
pthread_mutex_t mtx;
} reg_e2_nodes_t;
void init_reg_e2_node(reg_e2_nodes_t* n);
void free_reg_e2_node(reg_e2_nodes_t* n);
void add_reg_e2_node(reg_e2_nodes_t* n, global_e2_node_id_t const* id, size_t len, ran_function_t const ran_func[len]);
void rm_reg_e2_node(reg_e2_nodes_t* n, global_e2_node_id_t const* id);
size_t sz_reg_e2_node(reg_e2_nodes_t* n);
assoc_rb_tree_t cp_reg_e2_node(reg_e2_nodes_t* n);
e2_node_arr_t generate_e2_node_arr(reg_e2_nodes_t* n);
#endif

View File

@@ -0,0 +1,44 @@
/*
* 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 "pending_event_ric.h"
#include <assert.h>
#include <stdlib.h>
int cmp_pending_event_ric(void const* p_v1, void const* p_v2)
{
assert(p_v1 != NULL);
assert(p_v2 != NULL);
pending_event_ric_t* p1 = (pending_event_ric_t*)p_v1;
pending_event_ric_t* p2 = (pending_event_ric_t*)p_v2;
int cmp_ev = cmp_pending_event(p1, p2);
if(cmp_ev != 0)
return cmp_ev;
return cmp_ric_gen_id(&p1->id, &p2->id);
}

View File

@@ -0,0 +1,40 @@
/*
* 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 PENDING_EVENT_RIC_H
#define PENDING_EVENT_RIC_H
#include "lib/pending_events.h"
#include "lib/v1/ap/e2ap_types/common/ric_gen_id.h"
typedef struct
{
pending_event_t ev;
ric_gen_id_t id;
} pending_event_ric_t;
int cmp_pending_event_ric(void const* p_v1, void const* p_v2);
#endif

View File

@@ -0,0 +1,51 @@
/*
* 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 "pending_events.h"
#include <assert.h>
#include <stdlib.h>
int cmp_pending_event(void const* pend_v1, void const* pend_v2)
{
assert(pend_v1 != NULL);
assert(pend_v2 != NULL);
pending_event_t* ev1 = (pending_event_t*)pend_v1;
pending_event_t* ev2 = (pending_event_t*)pend_v2;
if(*ev1 < *ev2) return 1;
if(*ev1 == *ev2) return 0;
return -1;
}
bool valid_pending_event(pending_event_t ev)
{
assert(ev == SETUP_REQUEST_PENDING_EVENT
|| ev == SUBSCRIPTION_REQUEST_PENDING_EVENT
|| ev == SUBSCRIPTION_DELETE_REQUEST_PENDING_EVENT
|| ev == E42_SETUP_REQUEST_PENDING_EVENT
);
return true;
}

View File

@@ -0,0 +1,54 @@
/*
* 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 PENDING_EVENTS_H
#define PENDING_EVENTS_H
#include <stdbool.h>
typedef enum pending_event_e
{
// AGENT
SETUP_REQUEST_PENDING_EVENT,
// RIC
SUBSCRIPTION_REQUEST_PENDING_EVENT,
SUBSCRIPTION_DELETE_REQUEST_PENDING_EVENT,
CONTROL_REQUEST_PENDING_EVENT,
// xApp
E42_SETUP_REQUEST_PENDING_EVENT,
E42_RIC_SUBSCRIPTION_REQUEST_PENDING_EVENT,
RIC_SUBSCRIPTION_DELETE_REQUEST_PENDING_EVENT,
E42_RIC_SUBSCRIPTION_DELETE_REQUEST_PENDING_EVENT,
E42_RIC_CONTROL_REQUEST_PENDING_EVENT,
} pending_event_t;
int cmp_pending_event(void const* pend_v1, void const* pend_v2);
bool valid_pending_event(pending_event_t ev);
#endif

View File

@@ -0,0 +1,2 @@
add_subdirectory(ap)

View File

@@ -0,0 +1,24 @@
add_subdirectory(e2ap_types)
add_subdirectory(ie)
add_subdirectory(enc)
add_subdirectory(dec)
add_subdirectory(free)
if(E2AP_ENCODING STREQUAL "E2AP_ASN")
add_library(e2ap_ap_obj OBJECT e2ap_ap_asn.c)
elseif(E2AP_ENCODING STREQUAL "E2AP_FLATBUFFERS")
add_library(e2ap_ap_obj OBJECT e2ap_ap_fb.c)
else()
message(FATAL_ERROR "Unknown E2AP encoding type")
endif()
# Set the MACRO variable that will be used by the compiler to select the encoding/decoding
target_compile_definitions(e2ap_ap_obj PRIVATE ${E2AP_ENCODING})
target_link_libraries(e2ap_ap_obj PUBLIC
e2ap_types_obj
e2ap_msg_enc_obj
e2ap_msg_dec_obj
e2ap_msg_free_obj)

View File

@@ -0,0 +1,16 @@
if(E2AP_ENCODING STREQUAL "E2AP_ASN")
add_library(e2ap_msg_dec_obj OBJECT e2ap_msg_dec_asn.c)
target_link_libraries(e2ap_msg_dec_obj PRIVATE asn1_e2ap)
target_compile_options(e2ap_msg_dec_obj PRIVATE -DASN_DISABLE_OER_SUPPORT)
elseif(E2AP_ENCODING STREQUAL "E2AP_FLATBUFFERS")
add_library(e2ap_msg_dec_obj OBJECT e2ap_msg_dec_fb.c)
target_link_libraries(e2ap_msg_dec_obj PRIVATE e2ap_fb_obj)
else()
message(FATAL_ERROR "no E2AP encoding scheme selected")
endif()
add_compile_definitions(PRIVATE ${E2AP_ENCODING})
target_link_libraries(e2ap_msg_dec_obj PRIVATE e2ap_types_obj)

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,138 @@
/*
* 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 E2AP_MSG_DEC_ASN_H
#define E2AP_MSG_DEC_ASN_H
#include "lib/v1/ap/type_defs.h"
struct E2AP_E2AP_PDU;
typedef struct e2ap_asn e2ap_asn_t;
e2ap_msg_t e2ap_msg_dec_asn(e2ap_asn_t* asn, byte_array_t ba);
void e2ap_msg_free_asn(struct e2ap_asn* enc, e2ap_msg_t* msg);
void init_ap_asn(struct e2ap_asn*);
///////////////////////////////////////////////////////////////////////////////////////////////////
// O-RAN E2APv01.01: Messages for Global Procedures ///////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////
// RIC -> E2
e2ap_msg_t e2ap_dec_subscription_request(const struct E2AP_E2AP_PDU* pdu);
// E2 -> RIC
e2ap_msg_t e2ap_dec_subscription_response(const struct E2AP_E2AP_PDU* pdu);
//E2 -> RIC
e2ap_msg_t e2ap_dec_subscription_failure(const struct E2AP_E2AP_PDU* pdu);
//RIC -> E2
e2ap_msg_t e2ap_dec_subscription_delete_request(const struct E2AP_E2AP_PDU* pdu);
// E2 -> RIC
e2ap_msg_t e2ap_dec_subscription_delete_response(const struct E2AP_E2AP_PDU* pdu);
//E2 -> RIC
e2ap_msg_t e2ap_dec_subscription_delete_failure(const struct E2AP_E2AP_PDU* pdu);
// E2 -> RIC
e2ap_msg_t e2ap_dec_indication(const struct E2AP_E2AP_PDU* pdu);
// RIC -> E2
e2ap_msg_t e2ap_dec_control_request(const struct E2AP_E2AP_PDU* pdu);
// E2 -> RIC
e2ap_msg_t e2ap_dec_control_ack(const struct E2AP_E2AP_PDU* pdu);
// E2 -> RIC
e2ap_msg_t e2ap_dec_control_failure(const struct E2AP_E2AP_PDU* pdu);
///////////////////////////////////////////////////////////////////////////////////////////////////
// O-RAN E2APv01.01: Messages for Global Procedures ///////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////
// RIC <-> E2
e2ap_msg_t e2ap_dec_error_indication(const struct E2AP_E2AP_PDU* pdu);
// E2 -> RIC
e2ap_msg_t e2ap_dec_setup_request(const struct E2AP_E2AP_PDU* pdu);
// RIC -> E2
e2ap_msg_t e2ap_dec_setup_response(const struct E2AP_E2AP_PDU* pdu);
// RIC -> E2
e2ap_msg_t e2ap_dec_setup_failure(const struct E2AP_E2AP_PDU* pdu);
// RIC <-> E2
e2ap_msg_t e2ap_dec_reset_request(const struct E2AP_E2AP_PDU* pdu);
// RIC <-> E2
e2ap_msg_t e2ap_dec_reset_response(const struct E2AP_E2AP_PDU* pdu);
// E2 -> RIC
e2ap_msg_t e2ap_dec_service_update(const struct E2AP_E2AP_PDU* pdu);
// RIC -> E2
e2ap_msg_t e2ap_dec_service_update_ack(const struct E2AP_E2AP_PDU* pdu);
// RIC -> E2
e2ap_msg_t e2ap_dec_service_update_failure(const struct E2AP_E2AP_PDU* pdu);
// RIC -> E2
e2ap_msg_t e2ap_dec_service_query(const struct E2AP_E2AP_PDU* pdu);
// E2 -> RIC
e2ap_msg_t e2ap_dec_node_configuration_update(const struct E2AP_E2AP_PDU* pdu);
// RIC -> E2
e2ap_msg_t e2ap_dec_node_configuration_update_ack(const struct E2AP_E2AP_PDU* pdu);
// RIC -> E2
e2ap_msg_t e2ap_dec_node_configuration_update_failure(const struct E2AP_E2AP_PDU* pdu);
// RIC -> E2
e2ap_msg_t e2ap_dec_connection_update(const struct E2AP_E2AP_PDU* pdu);
// E2 -> RIC
e2ap_msg_t e2ap_dec_connection_update_ack(const struct E2AP_E2AP_PDU* pdu);
// E2 -> RIC
e2ap_msg_t e2ap_dec_connection_update_failure(const struct E2AP_E2AP_PDU* pdu);
// xApp -> iApp
e2ap_msg_t e2ap_dec_e42_setup_request(const struct E2AP_E2AP_PDU* pdu);
// iApp -> xApp
e2ap_msg_t e2ap_dec_e42_setup_response(const struct E2AP_E2AP_PDU* pdu);
// xApp -> iApp
e2ap_msg_t e2ap_dec_e42_subscription_request(const struct E2AP_E2AP_PDU* pdu);
// xApp -> iApp
e2ap_msg_t e2ap_dec_e42_subscription_delete_request(const struct E2AP_E2AP_PDU* pdu);
// xApp -> iApp
e2ap_msg_t e2ap_dec_e42_control_request(const struct E2AP_E2AP_PDU* pdu);
#endif

View File

@@ -0,0 +1,945 @@
/*
* 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 "e2ap_msg_dec_fb.h"
#include "../free/e2ap_msg_free.h"
#include "../e2ap_ap.h"
#include "../ie/fb/e2ap_reader.h"
#include "../global_consts.h"
#include <stdio.h>
static inline
cause_t copy_cause(e2ap_Cause_union_t cause)
{
assert(e2ap_Cause_is_known_type(cause.type));
cause_t ret;
switch (cause.type) {
case e2ap_Cause_ricRequest:
assert(e2ap_RicRequest_ricRequestCause(cause.value) < 11);
ret.ricRequest = e2ap_RicRequest_ricRequestCause(cause.value);
ret.present = CAUSE_RICREQUEST;
break;
case e2ap_Cause_ricService:
assert(e2ap_RicService_ricServiceCause(cause.value) < 3);
ret.ricService = e2ap_RicService_ricServiceCause(cause.value);
ret.present = CAUSE_RICSERVICE;
break;
case e2ap_Cause_transportLayer:
assert(e2ap_TransportLayer_transportLayerCause(cause.value) < 2);
ret.transport = e2ap_TransportLayer_transportLayerCause(cause.value);
ret.present = CAUSE_TRANSPORT;
break;
case e2ap_Cause_protocol:
assert(e2ap_Protocol_protocolCause(cause.value) < 7);
ret.protocol = e2ap_Protocol_protocolCause(cause.value);
ret.present = CAUSE_PROTOCOL;
break;
case e2ap_Cause_misc:
assert(e2ap_Misc_miscellaneousCause(cause.value) < 4);
ret.misc = e2ap_Misc_miscellaneousCause(cause.value);
ret.present = CAUSE_MISC;
break;
case e2ap_Cause_NONE:
assert(0 && "not implemented");
break;
}
return ret;
}
static inline
uint32_t get_time_to_wait(uint32_t ttw)
{
/* the ASN.1 encoding treats the time_to_wait_ms type as an enum, although it
* is a uint32_t (in ms). For the time being, we will do the same, but
* convert it from the ms value of the flatbuffers */
if (ttw == 0)
return 0;
else if (ttw == 1)
return 1;
else if (ttw == 2)
return 2;
else if (ttw <= 5)
return 3;
else if (ttw <= 10)
return 4;
else if (ttw <= 20)
return 5;
else if (ttw <= 30)
return 6;
else if (ttw <= 40)
return 7;
else if (ttw <= 50)
return 8;
else if (ttw <= 100)
return 9;
else if (ttw <= 200)
return 10;
else if (ttw <= 500)
return 11;
else if (ttw <= 1000)
return 12;
else if (ttw <= 2000)
return 13;
else if (ttw <= 5000)
return 14;
else if (ttw <= 10000)
return 15;
else if (ttw <= 20000)
return 16;
else if (ttw <= 60000)
return 17;
else
assert("illegal value for time to wait, cannot map to enum");
assert(0 && "illegal code path");
}
static inline
byte_array_t copy_vec_uint8_to_ba(const uint8_t *b, size_t l)
{
uint8_t* buf = malloc(l);
assert(buf);
memcpy(buf, b, l);
return (byte_array_t) { .buf = buf, .len = l};
}
e2ap_msg_t e2ap_dec_subscription_request_fb(e2ap_E2Message_table_t e2mt)
{
assert(e2mt);
e2ap_Message_union_t fb_msg = e2ap_E2Message_msg_union(e2mt);
assert(fb_msg.type == e2ap_Message_subscriptionRequest);
e2ap_RicSubscriptionRequest_table_t fb_rsr = fb_msg.value;
e2ap_msg_t ret = {.type = RIC_SUBSCRIPTION_REQUEST};
ric_subscription_request_t* sr = &ret.u_msgs.ric_sub_req;
assert(e2ap_RicSubscriptionRequest_requestId_is_present(fb_rsr));
e2ap_RicRequestId_struct_t ricreq = e2ap_RicSubscriptionRequest_requestId(fb_rsr);
sr->ric_id.ric_req_id = ricreq->ricRequestorId;
sr->ric_id.ric_inst_id = ricreq->ricInstanceId;
assert(e2ap_RicSubscriptionRequest_ranFunctionId_is_present(fb_rsr));
sr->ric_id.ran_func_id = e2ap_RicSubscriptionRequest_ranFunctionId(fb_rsr);
const uint8_t* event = e2ap_RicSubscriptionRequest_eventTriggerDefinition(fb_rsr);
const size_t event_len = flatbuffers_uint8_vec_len(event);
assert(event && event_len > 0);
sr->event_trigger.buf = malloc(event_len);
assert(sr->event_trigger.buf);
memcpy(sr->event_trigger.buf, event, event_len);
sr->event_trigger.len = event_len;
e2ap_Action_vec_t actions = e2ap_RicSubscriptionRequest_actions(fb_rsr);
const int len_ra = e2ap_Action_vec_len(actions);
assert(len_ra > 0 && len_ra <= MAX_NUM_ACTION_DEF );
sr->len_action = len_ra;
sr->action = calloc(len_ra, sizeof(ric_action_t));
assert(sr->action);
for (int i = 0; i < len_ra; ++i) {
e2ap_Action_table_t action = e2ap_Action_vec_at(actions, i);
ric_action_t * dst = &sr->action[i];
dst->id = e2ap_Action_id(action);
dst->type = e2ap_Action_type(action); /* maps one-to-one */
const uint8_t* definition = e2ap_Action_definition(action);
const size_t definition_len = flatbuffers_uint8_vec_len(definition);
if (definition && definition_len > 0) {
dst->definition = malloc(sizeof(byte_array_t));
assert(dst->definition);
dst->definition->buf = malloc(definition_len);
assert(dst->definition->buf);
memcpy(dst->definition->buf, definition, definition_len);
dst->definition->len = definition_len;
}
e2ap_RicSubsequentAction_table_t rsa = e2ap_Action_subsequentAction(action);
if (rsa) {
dst->subseq_action = calloc(1, sizeof(ric_subsequent_action_t));
assert(dst->subseq_action);
e2ap_RicSubsequentActionType_enum_t rsat = e2ap_RicSubsequentAction_type(rsa);
assert(rsat);
dst->subseq_action->type = rsat;
if (e2ap_RicSubsequentAction_timeToWait(rsa) != 0) {
dst->subseq_action->time_to_wait_ms = malloc(sizeof(uint32_t));
assert(dst->subseq_action->time_to_wait_ms);
*dst->subseq_action->time_to_wait_ms = get_time_to_wait(e2ap_RicSubsequentAction_timeToWait(rsa));
}
}
}
return ret;
}
e2ap_msg_t e2ap_dec_subscription_response_fb(e2ap_E2Message_table_t e2mt)
{
assert(e2mt);
e2ap_Message_union_t fb_msg = e2ap_E2Message_msg_union(e2mt);
assert(fb_msg.type == e2ap_Message_subscriptionResponse);
e2ap_RicSubscriptionResponse_table_t fb_rsr = fb_msg.value;
e2ap_msg_t ret = {.type = RIC_SUBSCRIPTION_RESPONSE};
ric_subscription_response_t* sr = &ret.u_msgs.ric_sub_resp;
assert(e2ap_RicSubscriptionResponse_requestId_is_present(fb_rsr));
e2ap_RicRequestId_struct_t ricreq = e2ap_RicSubscriptionResponse_requestId(fb_rsr);
sr->ric_id.ric_req_id = ricreq->ricRequestorId;
sr->ric_id.ric_inst_id = ricreq->ricInstanceId;
assert(e2ap_RicSubscriptionResponse_ranFunctionId_is_present(fb_rsr));
sr->ric_id.ran_func_id = e2ap_RicSubscriptionResponse_ranFunctionId(fb_rsr);
e2ap_RicActionAdmitted_vec_t al = e2ap_RicSubscriptionResponse_admittedActions(fb_rsr);
sr->len_admitted = e2ap_RicActionAdmitted_vec_len(al);
assert(sr->len_admitted > 0);
sr->admitted = calloc(sr->len_admitted, sizeof(*sr->admitted));
assert(sr->admitted);
for (size_t i = 0; i < sr->len_admitted; ++i) {
e2ap_RicActionAdmitted_table_t admitted = e2ap_RicActionAdmitted_vec_at(al, i);
ric_action_admitted_t* dst = &sr->admitted[i];
dst->ric_act_id = e2ap_RicActionAdmitted_id(admitted);
}
e2ap_RicActionNotAdmitted_vec_t nal = e2ap_RicSubscriptionResponse_notAdmittedActions(fb_rsr);
sr->len_na = e2ap_RicActionNotAdmitted_vec_len(nal);
if (sr->len_na > 0) {
sr->not_admitted = calloc(sr->len_na, sizeof(ric_action_not_admitted_t));
assert(sr->not_admitted);
for (size_t i = 0; i < sr->len_na; ++i) {
e2ap_RicActionNotAdmitted_table_t not_admitted = e2ap_RicActionNotAdmitted_vec_at(nal, i);
ric_action_not_admitted_t* dst = &sr->not_admitted[i];
dst->ric_act_id = e2ap_RicActionNotAdmitted_id(not_admitted);
dst->cause = copy_cause(e2ap_RicActionNotAdmitted_cause_union(not_admitted));
}
}
return ret;
}
e2ap_msg_t e2ap_dec_subscription_failure_fb(e2ap_E2Message_table_t e2mt)
{
assert(e2mt);
e2ap_Message_union_t fb_msg = e2ap_E2Message_msg_union(e2mt);
assert(fb_msg.type == e2ap_Message_subscriptionFailure);
e2ap_RicSubscriptionFailure_table_t fb_rsf = fb_msg.value;
e2ap_msg_t ret = {.type = RIC_SUBSCRIPTION_FAILURE};
ric_subscription_failure_t* sf = &ret.u_msgs.ric_sub_fail;
assert(e2ap_RicSubscriptionFailure_requestId_is_present(fb_rsf));
e2ap_RicRequestId_struct_t ricreq = e2ap_RicSubscriptionFailure_requestId(fb_rsf);
sf->ric_id.ric_req_id = ricreq->ricRequestorId;
sf->ric_id.ric_inst_id = ricreq->ricInstanceId;
assert(e2ap_RicSubscriptionFailure_ranFunctionId_is_present(fb_rsf));
sf->ric_id.ran_func_id = e2ap_RicSubscriptionFailure_ranFunctionId(fb_rsf);
e2ap_RicActionNotAdmitted_vec_t naa = e2ap_RicSubscriptionFailure_notAdmittedActions(fb_rsf);
sf->len_na = e2ap_RicActionNotAdmitted_vec_len(naa);
if (sf->len_na > 0) {
sf->not_admitted = calloc(sf->len_na, sizeof(ric_action_not_admitted_t));
assert(sf->not_admitted);
for (size_t i = 0; i < sf->len_na; ++i) {
e2ap_RicActionNotAdmitted_table_t not_admitted = e2ap_RicActionNotAdmitted_vec_at(naa, i);
ric_action_not_admitted_t* dst = &sf->not_admitted[i];
dst->ric_act_id = e2ap_RicActionNotAdmitted_id(not_admitted);
dst->cause = copy_cause(e2ap_RicActionNotAdmitted_cause_union(not_admitted));
}
}
assert(!e2ap_RicSubscriptionFailure_criticalityDiagnostics_is_present(fb_rsf) && "decoding of criticality diagnostics is not implemented");
return ret;
}
e2ap_msg_t e2ap_dec_subscription_delete_request_fb(e2ap_E2Message_table_t e2mt)
{
assert(e2mt);
e2ap_Message_union_t fb_msg = e2ap_E2Message_msg_union(e2mt);
assert(fb_msg.type == e2ap_Message_subscriptionDeleteRequest);
e2ap_RicSubscriptionDeleteRequest_table_t fb_sdr = fb_msg.value;
e2ap_msg_t ret = {.type = RIC_SUBSCRIPTION_DELETE_REQUEST};
ric_subscription_delete_request_t* dr = &ret.u_msgs.ric_sub_del_req;
assert(e2ap_RicSubscriptionDeleteRequest_requestId_is_present(fb_sdr));
e2ap_RicRequestId_struct_t ricreq = e2ap_RicSubscriptionDeleteRequest_requestId(fb_sdr);
dr->ric_id.ric_req_id = ricreq->ricRequestorId;
dr->ric_id.ric_inst_id = ricreq->ricInstanceId;
assert(e2ap_RicSubscriptionDeleteRequest_ranFunctionId_is_present(fb_sdr));
dr->ric_id.ran_func_id = e2ap_RicSubscriptionDeleteRequest_ranFunctionId(fb_sdr);
return ret;
}
e2ap_msg_t e2ap_dec_subscription_delete_response_fb(e2ap_E2Message_table_t e2mt)
{
assert(e2mt);
e2ap_Message_union_t fb_msg = e2ap_E2Message_msg_union(e2mt);
assert(fb_msg.type == e2ap_Message_subscriptionDeleteResponse);
e2ap_RicSubscriptionDeleteResponse_table_t fb_sdr = fb_msg.value;
e2ap_msg_t ret = {.type = RIC_SUBSCRIPTION_DELETE_RESPONSE};
ric_subscription_delete_response_t* dr = &ret.u_msgs.ric_sub_del_resp;
assert(e2ap_RicSubscriptionDeleteResponse_requestId_is_present(fb_sdr));
e2ap_RicRequestId_struct_t ricreq = e2ap_RicSubscriptionDeleteResponse_requestId(fb_sdr);
dr->ric_id.ric_req_id = ricreq->ricRequestorId;
dr->ric_id.ric_inst_id = ricreq->ricInstanceId;
assert(e2ap_RicSubscriptionDeleteResponse_ranFunctionId_is_present(fb_sdr));
dr->ric_id.ran_func_id = e2ap_RicSubscriptionDeleteResponse_ranFunctionId(fb_sdr);
return ret;
}
e2ap_msg_t e2ap_dec_subscription_delete_failure_fb(e2ap_E2Message_table_t e2mt)
{
assert(e2mt);
e2ap_Message_union_t fb_msg = e2ap_E2Message_msg_union(e2mt);
assert(fb_msg.type == e2ap_Message_subscriptionDeleteFailure);
e2ap_RicSubscriptionDeleteFailure_table_t fb_sdf = fb_msg.value;
e2ap_msg_t ret = {.type = RIC_SUBSCRIPTION_DELETE_FAILURE};
ric_subscription_delete_failure_t* df = &ret.u_msgs.ric_sub_del_fail;
assert(e2ap_RicSubscriptionDeleteFailure_requestId_is_present(fb_sdf));
e2ap_RicRequestId_struct_t ricreq = e2ap_RicSubscriptionDeleteFailure_requestId(fb_sdf);
df->ric_id.ric_req_id = ricreq->ricRequestorId;
df->ric_id.ric_inst_id = ricreq->ricInstanceId;
assert(e2ap_RicSubscriptionDeleteFailure_ranFunctionId_is_present(fb_sdf));
df->ric_id.ran_func_id = e2ap_RicSubscriptionDeleteFailure_ranFunctionId(fb_sdf);
assert(e2ap_RicSubscriptionDeleteFailure_cause_is_present(fb_sdf));
df->cause = copy_cause(e2ap_RicSubscriptionDeleteFailure_cause_union(fb_sdf));
assert(!e2ap_RicSubscriptionDeleteFailure_criticalityDiagnostics_is_present(fb_sdf) && "decoding of criticality diagnostics is not implemented");
return ret;
}
e2ap_msg_t e2ap_dec_indication_fb(e2ap_E2Message_table_t e2mt)
{
assert(e2mt);
e2ap_Message_union_t fb_msg = e2ap_E2Message_msg_union(e2mt);
assert(fb_msg.type == e2ap_Message_indication);
e2ap_RicIndication_table_t fb_sdr = fb_msg.value;
e2ap_msg_t ret = {.type = RIC_INDICATION};
ric_indication_t* ind = &ret.u_msgs.ric_ind;
assert(e2ap_RicIndication_requestId_is_present(fb_sdr));
e2ap_RicRequestId_struct_t ricreq = e2ap_RicIndication_requestId(fb_sdr);
ind->ric_id.ric_req_id = ricreq->ricRequestorId;
ind->ric_id.ric_inst_id = ricreq->ricInstanceId;
assert(e2ap_RicIndication_ranFunctionId_is_present(fb_sdr));
ind->ric_id.ran_func_id = e2ap_RicIndication_ranFunctionId(fb_sdr);
assert(e2ap_RicIndication_actionId_is_present(fb_sdr));
ind->action_id = e2ap_RicIndication_actionId(fb_sdr);
if (e2ap_RicIndication_sn_is_present(fb_sdr)) {
ind->sn = malloc(sizeof(*ind->sn));
assert(ind->sn);
*ind->sn = e2ap_RicIndication_sn(fb_sdr);
}
assert(e2ap_RicIndication_indicationType_is_present(fb_sdr));
ind->type = e2ap_RicIndication_indicationType(fb_sdr);
assert(e2ap_RicIndication_header_is_present(fb_sdr));
const uint8_t* hdr = e2ap_RicIndication_header(fb_sdr);
const size_t hdr_len = flatbuffers_uint8_vec_len(hdr);
ind->hdr.buf = malloc(hdr_len);
assert(ind->hdr.buf);
memcpy(ind->hdr.buf, hdr, hdr_len);
ind->hdr.len = hdr_len;
assert(e2ap_RicIndication_message_is_present(fb_sdr));
const uint8_t* msg = e2ap_RicIndication_message(fb_sdr);
const size_t msg_len = flatbuffers_uint8_vec_len(msg);
ind->msg.buf = malloc(msg_len);
assert(ind->msg.buf);
memcpy(ind->msg.buf, msg, msg_len);
ind->msg.len = msg_len;
if (e2ap_RicIndication_callProcessId_is_present(fb_sdr)) {
const uint8_t* cpi = e2ap_RicIndication_callProcessId(fb_sdr);
const size_t cpi_len = flatbuffers_uint8_vec_len(cpi);
ind->call_process_id = malloc(cpi_len);
assert(ind->call_process_id);
memcpy(ind->call_process_id->buf, cpi, cpi_len);
ind->call_process_id->len = cpi_len;
}
return ret;
}
e2ap_msg_t e2ap_dec_control_request_fb(e2ap_E2Message_table_t e2mt)
{
assert(e2mt);
e2ap_Message_union_t fb_msg = e2ap_E2Message_msg_union(e2mt);
assert(fb_msg.type == e2ap_Message_controlRequest);
e2ap_RicControlRequest_table_t fb_cr = fb_msg.value;
e2ap_msg_t ret = {.type = RIC_CONTROL_REQUEST };
ric_control_request_t* ctrl = &ret.u_msgs.ric_ctrl_req;
assert(e2ap_RicControlRequest_requestId_is_present(fb_cr));
e2ap_RicRequestId_struct_t ricreq = e2ap_RicControlRequest_requestId(fb_cr);
ctrl->ric_id.ric_req_id = ricreq->ricRequestorId;
ctrl->ric_id.ric_inst_id = ricreq->ricInstanceId;
/* the ran Function ID is not written in enc() when it is the default (0), so
* do not assert on its presence */
//assert(e2ap_RicControlRequest_ranFunctionId_is_present(fb_cr));
ctrl->ric_id.ran_func_id = e2ap_RicControlRequest_ranFunctionId(fb_cr);
if (e2ap_RicControlRequest_callProcessId_is_present(fb_cr)) {
const uint8_t* cpi = e2ap_RicControlRequest_callProcessId(fb_cr);
const size_t cpi_len = flatbuffers_uint8_vec_len(cpi);
ctrl->call_process_id = malloc(cpi_len);
assert(ctrl->call_process_id);
*ctrl->call_process_id = copy_vec_uint8_to_ba(cpi, cpi_len);
}
assert(e2ap_RicControlRequest_header_is_present(fb_cr));
const uint8_t* hdr = e2ap_RicControlRequest_header(fb_cr);
const size_t hdr_len = flatbuffers_uint8_vec_len(hdr);
ctrl->hdr = copy_vec_uint8_to_ba(hdr, hdr_len);
assert(e2ap_RicControlRequest_message_is_present(fb_cr));
const uint8_t* msg = e2ap_RicControlRequest_message(fb_cr);
const size_t msg_len = flatbuffers_uint8_vec_len(msg);
ctrl->msg = copy_vec_uint8_to_ba(msg, msg_len);
if (e2ap_RicControlRequest_ackRequest_is_present(fb_cr)) {
ctrl->ack_req = malloc(sizeof(*ctrl->ack_req));
assert(ctrl->ack_req);
*ctrl->ack_req = e2ap_RicControlRequest_ackRequest(fb_cr);
}
return ret;
}
e2ap_msg_t e2ap_dec_control_ack_fb(e2ap_E2Message_table_t e2mt)
{
assert(e2mt);
e2ap_Message_union_t fb_msg = e2ap_E2Message_msg_union(e2mt);
assert(fb_msg.type == e2ap_Message_controlAcknowledge);
e2ap_RicControlAcknowledge_table_t fb_ca = fb_msg.value;
e2ap_msg_t ret = {.type = RIC_CONTROL_ACKNOWLEDGE};
ric_control_acknowledge_t* ca = &ret.u_msgs.ric_ctrl_ack;
assert(e2ap_RicControlAcknowledge_requestId_is_present(fb_ca));
e2ap_RicRequestId_struct_t ricreq = e2ap_RicControlAcknowledge_requestId(fb_ca);
ca->ric_id.ric_req_id = ricreq->ricRequestorId;
ca->ric_id.ric_inst_id = ricreq->ricInstanceId;
assert(e2ap_RicControlAcknowledge_ranFunctionId_is_present(fb_ca));
ca->ric_id.ran_func_id = e2ap_RicControlAcknowledge_ranFunctionId(fb_ca);
if (e2ap_RicControlAcknowledge_callProcessId_is_present(fb_ca)) {
const uint8_t* cpi = e2ap_RicControlAcknowledge_callProcessId(fb_ca);
const size_t cpi_len = flatbuffers_uint8_vec_len(cpi);
ca->call_process_id = malloc(cpi_len);
assert(ca->call_process_id);
*ca->call_process_id = copy_vec_uint8_to_ba(cpi, cpi_len);
}
/* the outcome is not written in enc() when it is the default (0), so
* do not assert on its presence */
//assert(e2ap_RicControlAcknowledge_outcome_is_present(fb_ca));
ca->status = e2ap_RicControlAcknowledge_status(fb_ca);
if (e2ap_RicControlAcknowledge_outcome_is_present(fb_ca)) {
const uint8_t* oc = e2ap_RicControlAcknowledge_outcome(fb_ca);
const size_t oc_len = flatbuffers_uint8_vec_len(oc);
ca->control_outcome = malloc(oc_len);
assert(ca->control_outcome);
*ca->control_outcome = copy_vec_uint8_to_ba(oc, oc_len);
}
return ret;
}
e2ap_msg_t e2ap_dec_control_failure_fb(e2ap_E2Message_table_t e2mt)
{
assert(e2mt);
e2ap_Message_union_t fb_msg = e2ap_E2Message_msg_union(e2mt);
assert(fb_msg.type == e2ap_Message_controlFailure);
e2ap_RicControlFailure_table_t fb_cf = fb_msg.value;
e2ap_msg_t ret = {.type = RIC_CONTROL_FAILURE};
ric_control_failure_t* cf = &ret.u_msgs.ric_ctrl_fail;
assert(e2ap_RicControlFailure_requestId_is_present(fb_cf));
e2ap_RicRequestId_struct_t ricreq = e2ap_RicControlFailure_requestId(fb_cf);
cf->ric_id.ric_req_id = ricreq->ricRequestorId;
cf->ric_id.ric_inst_id = ricreq->ricInstanceId;
assert(e2ap_RicControlFailure_ranFunctionId_is_present(fb_cf));
cf->ric_id.ran_func_id = e2ap_RicControlFailure_ranFunctionId(fb_cf);
if (e2ap_RicControlFailure_callProcessId_is_present(fb_cf)) {
const uint8_t* cpi = e2ap_RicControlFailure_callProcessId(fb_cf);
const size_t cpi_len = flatbuffers_uint8_vec_len(cpi);
cf->call_process_id = malloc(cpi_len);
assert(cf->call_process_id);
*cf->call_process_id = copy_vec_uint8_to_ba(cpi, cpi_len);
}
assert(e2ap_RicControlFailure_cause_is_present(fb_cf));
cf->cause = copy_cause(e2ap_RicControlFailure_cause_union(fb_cf));
if (e2ap_RicControlFailure_outcome_is_present(fb_cf)) {
const uint8_t* oc = e2ap_RicControlFailure_outcome(fb_cf);
const size_t oc_len = flatbuffers_uint8_vec_len(oc);
cf->control_outcome = malloc(oc_len);
assert(cf->control_outcome);
*cf->control_outcome = copy_vec_uint8_to_ba(oc, oc_len);
}
return ret;
}
e2ap_msg_t e2ap_dec_error_indication_fb(e2ap_E2Message_table_t e2mt)
{
assert(0!=0 && "Not implemented");
(void) e2mt;
e2ap_msg_t ret = {.type = E2AP_ERROR_INDICATION};
return ret;
}
e2ap_msg_t e2ap_dec_setup_request_fb(e2ap_E2Message_table_t e2mt)
{
assert(e2mt);
e2ap_Message_union_t fb_msg = e2ap_E2Message_msg_union(e2mt);
assert(fb_msg.type == e2ap_Message_setupRequest);
e2ap_E2SetupRequest_table_t fb_sr = fb_msg.value;
e2ap_msg_t ret = {.type = E2_SETUP_REQUEST};
e2_setup_request_t* sr = &ret.u_msgs.e2_stp_req;
e2ap_GlobalE2NodeId_union_t id = e2ap_E2SetupRequest_id_union(fb_sr);
switch (id.type) {
case e2ap_GlobalE2NodeId_gNB:
sr->id.type = ngran_gNB;
sr->id.plmn.mcc = e2ap_GNB_plmn(id.value)->mcc;
sr->id.plmn.mnc = e2ap_GNB_plmn(id.value)->mnc;
sr->id.plmn.mnc_digit_len = e2ap_GNB_plmn(id.value)->mnc_digit_length;
sr->id.nb_id = e2ap_GNB_id(id.value);
//if (e2ap_GNB_cu_up_id_is_present(id.value)) e2ap_GNB_cu_up_id(id.value)
//if (e2ap_GNB_du_id_is_present(id.value)) e2ap_GNB_du_id(id.value)
break;
case e2ap_GlobalE2NodeId_engNB:
//sr->id.type = ngran_ng_eNB_CU??;
//e2ap_EngNB_plmn(id.value)->mcc, e2ap_EngNB_plmn(id.value)->mnc_digit_length,
//e2ap_EngNB_plmn(id.value)->mnc, e2ap_EngNB_id(id.value)
assert(0 && "en-gNB not implemented");
break;
case e2ap_GlobalE2NodeId_ngeNB:
sr->id.type = ngran_ng_eNB;
sr->id.plmn.mcc = e2ap_NgeNB_plmn(id.value)->mcc;
sr->id.plmn.mnc = e2ap_NgeNB_plmn(id.value)->mnc;
sr->id.plmn.mnc_digit_len = e2ap_NgeNB_plmn(id.value)->mnc_digit_length;
sr->id.nb_id = e2ap_NgeNB_id(id.value);
break;
case e2ap_GlobalE2NodeId_eNB:
sr->id.type = ngran_eNB;
sr->id.plmn.mcc = e2ap_ENB_plmn(id.value)->mcc;
sr->id.plmn.mnc = e2ap_ENB_plmn(id.value)->mnc;
sr->id.plmn.mnc_digit_len = e2ap_ENB_plmn(id.value)->mnc_digit_length;
sr->id.nb_id = e2ap_ENB_id(id.value);
break;
default:
assert(0 && "no ID present\n");
break;
}
e2ap_RanFunction_vec_t ranFunctions = e2ap_E2SetupRequest_ranFunctions(fb_sr);
const size_t len_rf = e2ap_RanFunction_vec_len(ranFunctions);
sr->len_rf = len_rf;
if (sr->len_rf > 0) {
sr->ran_func_item = calloc(len_rf, sizeof(*sr->ran_func_item));
assert(sr->ran_func_item);
for (size_t i = 0; i < len_rf; ++i) {
e2ap_RanFunction_table_t rf = e2ap_RanFunction_vec_at(ranFunctions, i);
ran_function_t* dst = &sr->ran_func_item[i];
assert(e2ap_RanFunction_id(rf) <= MAX_RAN_FUNC_ID);
dst->id = e2ap_RanFunction_id(rf);
assert(e2ap_RanFunction_revision(rf) > -1 && e2ap_RanFunction_revision(rf) <= MAX_RAN_FUNC_REV);
dst->rev = e2ap_RanFunction_revision(rf);
const uint8_t* definition = e2ap_RanFunction_definition(rf);
const size_t definition_len = flatbuffers_uint8_vec_len(definition);
assert(definition && definition_len > 0);
dst->def = copy_vec_uint8_to_ba(definition, definition_len);
if (e2ap_RanFunction_oid_is_present(rf)) {
dst->oid = malloc(sizeof(*dst->oid));
assert(dst->oid);
const char* oid = e2ap_RanFunction_oid(rf);
const size_t oid_len = flatbuffers_string_len(oid);
*dst->oid = copy_vec_uint8_to_ba((uint8_t*) oid, oid_len);
}
}
}
e2ap_E2NodeCompConfUpdateItem_vec_t e2nccuis = e2ap_E2SetupRequest_e2NodeComponentConfigurationUpdateList(fb_sr);
const size_t len_ccu = e2ap_RanFunction_vec_len(e2nccuis);
sr->len_ccu = len_ccu;
if (sr->len_ccu > 0) {
sr->comp_conf_update = calloc(len_ccu, sizeof(*sr->ran_func_item));
assert(sr->comp_conf_update);
for (size_t i = 0; i < len_ccu; ++i) {
e2ap_E2NodeCompConfUpdateItem_table_t e2nccui = e2ap_E2NodeCompConfUpdateItem_vec_at(e2nccuis, i);
e2_node_component_config_update_t* dst = &sr->comp_conf_update[i];
dst->e2_node_component_type = e2ap_E2NodeCompConfUpdateItem_type(e2nccui);
if (e2ap_E2NodeCompConfUpdateItem_id_is_present(e2nccui)) {
dst->id_present = malloc(sizeof(*dst->id_present));
assert(dst->id_present);
e2ap_E2NodeCompId_union_t id = e2ap_E2NodeCompConfUpdateItem_id_union(e2nccui);
switch (id.type) {
case e2ap_E2NodeCompId_gnb_cu_up:
*dst->id_present = E2_NODE_COMPONENT_ID_E2_NODE_COMPONENT_TYPE_GNB_CU_UP;
dst->gnb_cu_up_id = e2ap_E2NCId_id(id.value);
break;
case e2ap_E2NodeCompId_gnb_du:
*dst->id_present = E2_NODE_COMPONENT_ID_E2_NODE_COMPONENT_TYPE_GNB_DU;
dst->gnb_du_id = e2ap_E2NCId_id(id.value);
break;
default:
assert(0 && "unhandled E2NodeCompId type");
break;
}
}
e2ap_E2NodeCompConfUpdate_union_t ccu = e2ap_E2NodeCompConfUpdateItem_update_union(e2nccui);
switch (ccu.type) {
case e2ap_E2NodeCompConfUpdate_gnb:
assert(0 && "not implemented yet");
break;
case e2ap_E2NodeCompConfUpdate_en_gnb:
dst->update_present = E2_NODE_COMPONENT_CONFIG_UPDATE_EN_GNB_CONFIG_UPDATE;
const uint8_t* x2ap_en_gnb = e2ap_en_gnbE2NodeCompConfUpdate_x2ap_en_gnb(ccu.value);
const size_t x2ap_en_gnb_len = flatbuffers_uint8_vec_len(x2ap_en_gnb);
if (x2ap_en_gnb && x2ap_en_gnb_len > 0) {
dst->en_gnb.x2ap_en_gnb = malloc(sizeof(byte_array_t) );
assert(dst->en_gnb.x2ap_en_gnb);
*dst->en_gnb.x2ap_en_gnb = copy_vec_uint8_to_ba(x2ap_en_gnb, x2ap_en_gnb_len);
}
break;
case e2ap_E2NodeCompConfUpdate_ng_enb:
assert(0 && "not implemented yet");
break;
case e2ap_E2NodeCompConfUpdate_enb:
assert(0 && "not implemented yet");
break;
default:
assert(0 && "unhandled E2NodeCompConfUpdate");
break;
}
}
}
return ret;
}
e2ap_msg_t e2ap_dec_setup_response_fb(e2ap_E2Message_table_t e2mt)
{
assert(e2mt);
e2ap_Message_union_t fb_msg = e2ap_E2Message_msg_union(e2mt);
assert(fb_msg.type == e2ap_Message_setupResponse);
e2ap_E2SetupResponse_table_t fb_sr = fb_msg.value;
e2ap_msg_t ret = {.type = E2_SETUP_RESPONSE };
e2_setup_response_t* sr = &ret.u_msgs.e2_stp_resp;
assert(e2ap_E2SetupResponse_globalRicId_is_present(fb_sr));
e2ap_GlobalRicId_table_t id = e2ap_E2SetupResponse_globalRicId(fb_sr);
sr->id.plmn.mcc = e2ap_GlobalRicId_plmn(id)->mcc;
sr->id.plmn.mnc = e2ap_GlobalRicId_plmn(id)->mnc;
sr->id.plmn.mnc_digit_len = e2ap_GlobalRicId_plmn(id)->mnc_digit_length;
sr->id.near_ric_id.double_word = e2ap_GlobalRicId_nearRtRicId(id);
flatbuffers_uint16_vec_t accepted = e2ap_E2SetupResponse_acceptedRanFunctions(fb_sr);
const size_t len_acc = flatbuffers_uint16_vec_len(accepted);
sr->len_acc = len_acc;
if (len_acc > 0) {
sr->accepted = malloc(sr->len_acc * sizeof(*sr->accepted));
assert(sr->accepted);
for (size_t i = 0; i < sr->len_acc; ++i)
sr->accepted[i] = flatbuffers_uint16_vec_at(accepted, i);
}
e2ap_RejectedRanFunction_vec_t rejected = e2ap_E2SetupResponse_rejectedRanFunctions(fb_sr);
const size_t len_rej = e2ap_RejectedRanFunction_vec_len(rejected);
sr->len_rej = len_rej;
if (len_rej > 0) {
sr->rejected = malloc(sr->len_rej * sizeof(*sr->rejected));
assert(sr->rejected);
for (size_t i = 0; i < sr->len_rej; ++i) {
e2ap_RejectedRanFunction_table_t rej = e2ap_RejectedRanFunction_vec_at(rejected, i);
rejected_ran_function_t* dst = &sr->rejected[i];
dst->id = e2ap_RejectedRanFunction_ranFunctionId(rej);
dst->cause = copy_cause(e2ap_RejectedRanFunction_cause_union(rej));
}
}
e2ap_E2NodeCompConfUpdateAckItem_vec_t updateAcks = e2ap_E2SetupResponse_updateAck(fb_sr);
const size_t len_ccual = e2ap_E2NodeCompConfUpdateAckItem_vec_len(updateAcks);
sr->len_ccual = len_ccual;
if (len_ccual > 0) {
sr->comp_conf_update_ack_list = malloc(sr->len_ccual * sizeof(*sr->comp_conf_update_ack_list));
assert(sr->comp_conf_update_ack_list);
for (size_t i = 0; i < sr->len_ccual; ++i) {
e2ap_E2NodeCompConfUpdateAckItem_table_t ua = e2ap_E2NodeCompConfUpdateAckItem_vec_at(updateAcks, i);
assert(0 && "not implemented");
/*
printf(" [%d] acked Update Item type %s",
i, e2ap_E2NodeCompType_name(e2ap_E2NodeCompConfUpdateAckItem_type(ua)));
if (e2ap_E2NodeCompConfUpdateAckItem_id_is_present(ua)) {
e2ap_E2NodeCompId_union_t id = e2ap_E2NodeCompConfUpdateAckItem_id_union(ua);
switch (id.type) {
case e2ap_E2NodeCompId_gnb_cu_up:
printf(" ID gNB CU-UP %ld", ((e2ap_E2NCId_t *)id.value)->id);
break;
case e2ap_E2NodeCompId_gnb_du:
printf(" ID gNB DU %ld", ((e2ap_E2NCId_t *)id.value)->id);
break;
}
}
e2ap_E2NodeCompConfUpdateAck_table_t ack = e2ap_E2NodeCompConfUpdateAckItem_updateAck(ua);
if (e2ap_E2NodeCompConfUpdateAck_outcome(ack) == e2ap_E2NodeCompConfUpdateAckOutcome_Success)
printf(" outcome SUCCESS\n");
else
printf(" outcome Failure Cause %s\n", get_e2ap_Cause_name(e2ap_E2NodeCompConfUpdateAck_cause_union(ack)));
*/
}
}
return ret;
}
// RIC -> E2
e2ap_msg_t e2ap_dec_setup_failure_fb(e2ap_E2Message_table_t t)
{
assert(0!=0 && "Not implemented");
e2ap_msg_t ans = {0};
return ans;
}
// RIC <-> E2
e2ap_msg_t e2ap_dec_reset_request_fb(e2ap_E2Message_table_t t)
{
assert(0!=0 && "Not implemented");
e2ap_msg_t ans = {0};
return ans;
}
// RIC <-> E2
e2ap_msg_t e2ap_dec_reset_response_fb(e2ap_E2Message_table_t t)
{
assert(0!=0 && "Not implemented");
e2ap_msg_t ans = {0};
return ans;
}
// E2 -> RIC
e2ap_msg_t e2ap_dec_service_update_fb(e2ap_E2Message_table_t t)
{
assert(0!=0 && "Not implemented");
e2ap_msg_t ans = {0};
return ans;
}
// RIC -> E2
e2ap_msg_t e2ap_dec_service_update_ack_fb(e2ap_E2Message_table_t t)
{
assert(0!=0 && "Not implemented");
e2ap_msg_t ans = {0};
return ans;
}
// RIC -> E2
e2ap_msg_t e2ap_dec_service_update_failure_fb(e2ap_E2Message_table_t t)
{
assert(0!=0 && "Not implemented");
e2ap_msg_t ans = {0};
return ans;
}
// RIC -> E2
e2ap_msg_t e2ap_dec_service_query_fb(e2ap_E2Message_table_t t)
{
assert(0!=0 && "Not implemented");
e2ap_msg_t ans = {0};
return ans;
}
// E2 -> RIC
e2ap_msg_t e2ap_dec_node_configuration_update_fb(e2ap_E2Message_table_t t)
{
assert(0!=0 && "Not implemented");
e2ap_msg_t ans = {0};
return ans;
}
// RIC -> E2
e2ap_msg_t e2ap_dec_node_configuration_update_ack_fb(e2ap_E2Message_table_t t)
{
assert(0!=0 && "Not implemented");
e2ap_msg_t ans = {0};
return ans;
}
// RIC -> E2
e2ap_msg_t e2ap_dec_node_configuration_update_failure_fb(e2ap_E2Message_table_t t)
{
assert(0!=0 && "Not implemented");
e2ap_msg_t ans = {0};
return ans;
}
// RIC -> E2
e2ap_msg_t e2ap_dec_connection_update_fb(e2ap_E2Message_table_t t)
{
assert(0!=0 && "Not implemented");
e2ap_msg_t ans = {0};
return ans;
}
// E2 -> RIC
e2ap_msg_t e2ap_dec_connection_update_ack_fb(e2ap_E2Message_table_t t)
{
assert(0!=0 && "Not implemented");
e2ap_msg_t ans = {0};
return ans;
}
// E2 -> RIC
e2ap_msg_t e2ap_dec_connection_update_failure_fb(e2ap_E2Message_table_t t)
{
assert(0!=0 && "Not implemented");
e2ap_msg_t ans = {0};
return ans;
}
static
e2_msg_type_t e2ap_get_msg_type(e2ap_Message_union_type_t e2mut)
{
switch (e2mut) {
case e2ap_Message_setupRequest: return E2_SETUP_REQUEST;
case e2ap_Message_setupResponse: return E2_SETUP_RESPONSE;
//case e2ap_Message_setupFailure: return E2_SETUP_FAILURE;
//case e2ap_Message_errorIndication: return E2AP_ERROR_INDICATION;
//case e2ap_Message_resetRequest: return E2AP_RESET_REQUEST;
//case e2ap_Message_resetResponse: return E2AP_RESET_RESPONSE;
case e2ap_Message_controlRequest: return RIC_CONTROL_REQUEST;
case e2ap_Message_controlAcknowledge: return RIC_CONTROL_ACKNOWLEDGE;
case e2ap_Message_controlFailure: return RIC_CONTROL_FAILURE;
case e2ap_Message_indication: return RIC_INDICATION;
//case e2ap_Message_serviceQuery: return RIC_SERVICE_QUERY;
//case e2ap_Message_serviceUpdate: return RIC_SERVICE_UPDATE;
//case e2ap_Message_serviceUpdateAcknowledge: return RIC_SERVICE_UPDATE_ACKNOWLEDGE;
//case e2ap_Message_serviceUpdateFailure: return RIC_SERVICE_UPDATE_FAILURE;
case e2ap_Message_subscriptionRequest: return RIC_SUBSCRIPTION_REQUEST;
case e2ap_Message_subscriptionResponse: return RIC_SUBSCRIPTION_RESPONSE;
case e2ap_Message_subscriptionFailure: return RIC_SUBSCRIPTION_FAILURE;
case e2ap_Message_subscriptionDeleteRequest: return RIC_SUBSCRIPTION_DELETE_REQUEST;
case e2ap_Message_subscriptionDeleteResponse: return RIC_SUBSCRIPTION_DELETE_RESPONSE;
case e2ap_Message_subscriptionDeleteFailure: return RIC_SUBSCRIPTION_DELETE_FAILURE;
//case e2ap_Message_nodeConfigurationUpdate: return E2_NODE_CONFIGURATION_UPDATE;
//case e2ap_Message_nodeConfigurationUpdateAcknowledge: return E2_NODE_CONFIGURATION_UPDATE_ACKNOWLEDGE;
//case e2ap_Message_nodeConfigurationUpdateFailure: return E2_NODE_CONFIGURATION_UPDATE_FAILURE;
//case e2ap_Message_connectionUpdate: return E2_CONNECTION_UPDATE;
//case e2ap_Message_connectionUpdateAcknowledge: return E2_CONNECTION_UPDATE_ACKNOWLEDGE;
//case e2ap_Message_connectionUpdateFailure: return E2_CONNECTION_UPDATE_FAILURE;
default: assert(0 && "unhandled message");
}
assert(0 && "invalid path");
}
e2ap_msg_t e2ap_msg_dec_fb(e2ap_fb_t* fb, byte_array_t ba)
{
assert(ba.buf != NULL && ba.len > 0);
e2ap_E2Message_table_t e2m = e2ap_E2Message_as_root(ba.buf);
assert(e2m);
e2ap_Message_union_t fb_msg = e2ap_E2Message_msg_union(e2m);
const e2_msg_type_t msg_type = e2ap_get_msg_type(fb_msg.type);
assert(fb->dec_msg[msg_type] && "unhandled message");
e2ap_msg_t msg = fb->dec_msg[msg_type](e2m);
return msg;
}

View File

@@ -0,0 +1,143 @@
/*
* 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 E2AP_MSG_DEC_FB_H
#define E2AP_MSG_DEC_FB_H
#include "lib/v1/ap/type_defs.h"
typedef const struct e2ap_E2Message_table *e2ap_E2Message_table_t;
struct e2ap_fb;
e2ap_msg_t e2ap_msg_dec_fb(struct e2ap_fb* enc, byte_array_t ba);
void init_ap_fb(struct e2ap_fb*);
///////////////////////////////////////////////////////////////////////////////////////////////////
// O-RAN E2APv01.01: Messages for Global Procedures ///////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////
// RIC -> E2
e2ap_msg_t e2ap_dec_subscription_request_fb(e2ap_E2Message_table_t);
// E2 -> RIC
e2ap_msg_t e2ap_dec_subscription_response_fb(e2ap_E2Message_table_t);
//E2 -> RIC
e2ap_msg_t e2ap_dec_subscription_failure_fb(e2ap_E2Message_table_t);
//RIC -> E2
e2ap_msg_t e2ap_dec_subscription_delete_request_fb(e2ap_E2Message_table_t);
// E2 -> RIC
e2ap_msg_t e2ap_dec_subscription_delete_response_fb(e2ap_E2Message_table_t);
//E2 -> RIC
e2ap_msg_t e2ap_dec_subscription_delete_failure_fb(e2ap_E2Message_table_t);
// E2 -> RIC
e2ap_msg_t e2ap_dec_indication_fb(e2ap_E2Message_table_t);
// RIC -> E2
e2ap_msg_t e2ap_dec_control_request_fb( e2ap_E2Message_table_t);
// E2 -> RIC
e2ap_msg_t e2ap_dec_control_ack_fb(e2ap_E2Message_table_t);
// E2 -> RIC
e2ap_msg_t e2ap_dec_control_failure_fb(e2ap_E2Message_table_t);
///////////////////////////////////////////////////////////////////////////////////////////////////
// O-RAN E2APv01.01: Messages for Global Procedures ///////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////
// RIC <-> E2
e2ap_msg_t e2ap_dec_error_indication_fb(e2ap_E2Message_table_t);
// E2 -> RIC
e2ap_msg_t e2ap_dec_setup_request_fb(e2ap_E2Message_table_t);
// RIC -> E2
e2ap_msg_t e2ap_dec_setup_response_fb(e2ap_E2Message_table_t);
// RIC -> E2
e2ap_msg_t e2ap_dec_setup_failure_fb(e2ap_E2Message_table_t);
// RIC <-> E2
e2ap_msg_t e2ap_dec_reset_request_fb(e2ap_E2Message_table_t);
// RIC <-> E2
e2ap_msg_t e2ap_dec_reset_response_fb(e2ap_E2Message_table_t );
// E2 -> RIC
e2ap_msg_t e2ap_dec_service_update_fb(e2ap_E2Message_table_t);
// RIC -> E2
e2ap_msg_t e2ap_dec_service_update_ack_fb(e2ap_E2Message_table_t);
// RIC -> E2
e2ap_msg_t e2ap_dec_service_update_failure_fb(e2ap_E2Message_table_t);
// RIC -> E2
e2ap_msg_t e2ap_dec_service_query_fb(e2ap_E2Message_table_t);
// E2 -> RIC
e2ap_msg_t e2ap_dec_node_configuration_update_fb(e2ap_E2Message_table_t);
// RIC -> E2
e2ap_msg_t e2ap_dec_node_configuration_update_ack_fb(e2ap_E2Message_table_t);
// RIC -> E2
e2ap_msg_t e2ap_dec_node_configuration_update_failure_fb(e2ap_E2Message_table_t);
// RIC -> E2
e2ap_msg_t e2ap_dec_connection_update_fb(e2ap_E2Message_table_t);
// E2 -> RIC
e2ap_msg_t e2ap_dec_connection_update_ack_fb(e2ap_E2Message_table_t);
// E2 -> RIC
e2ap_msg_t e2ap_dec_connection_update_failure_fb(e2ap_E2Message_table_t);
#endif

View File

@@ -0,0 +1,40 @@
/*
* 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 E2AP_MSG_DEC_GENERIC_H
#define E2AP_MSG_DEC_GENERIC_H
#include "e2ap_msg_dec_asn.h"
#include "e2ap_msg_dec_fb.h"
#define e2ap_msg_dec_gen(T,U) _Generic ((T), e2ap_asn_t*: e2ap_msg_dec_asn, \
e2ap_fb_t*: e2ap_msg_dec_fb, \
default: e2ap_msg_dec_asn) (T,U)
#endif

View File

@@ -0,0 +1,75 @@
/*
* 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 E2AP_APPLICATION_PROTOCOL
#define E2AP_APPLICATION_PROTOCOL
#include <assert.h>
#include "lib/v1/ap/type_defs.h"
#include "e2ap_ap_asn.h"
#include "e2ap_ap_fb.h"
struct E2AP_E2AP_PDU;
typedef e2ap_msg_t (*e2ap_gen_dec_asn_fp)(const struct E2AP_E2AP_PDU*);
typedef byte_array_t (*e2ap_gen_enc_asn_fp)(const e2ap_msg_t*);
struct e2ap_E2Message_table;
typedef e2ap_msg_t (*e2ap_gen_dec_fb_fp)(const struct e2ap_E2Message_table*);
typedef byte_array_t (*e2ap_gen_enc_fb_fp)(const e2ap_msg_t*);
typedef void (*e2ap_free_fp)(e2ap_msg_t*);
typedef struct e2ap_asn{
e2ap_gen_enc_asn_fp enc_msg[31];
e2ap_gen_dec_asn_fp dec_msg[31];
e2ap_free_fp free_msg[31];
} e2ap_asn_t;
typedef struct e2ap_fb{
e2ap_gen_enc_fb_fp enc_msg[31];
e2ap_gen_dec_fb_fp dec_msg[31];
e2ap_free_fp free_msg[31];
} e2ap_fb_t;
typedef struct{
#ifdef E2AP_ASN
e2ap_asn_t type;
#elif E2AP_FLATBUFFERS
e2ap_fb_t type;
#else
static_assert(0!=0, "Error. No encoding scheme selected");
#endif
} e2ap_ap_t;
#define init_ap(T) _Generic ((T), e2ap_asn_t*: init_ap_asn, \
e2ap_fb_t*: init_ap_fb, \
default: init_ap_asn) (T)
#endif

View File

@@ -0,0 +1,139 @@
/*
* 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 "e2ap_ap_asn.h"
#include <assert.h>
#include <stdlib.h>
#include "lib/v1/ap/dec/e2ap_msg_dec_generic.h"
#include "lib/v1/ap/enc/e2ap_msg_enc_generic.h"
#include "lib/v1/ap/free/e2ap_msg_free.h"
void init_ap_asn(e2ap_asn_t* asn)
{
assert(asn != NULL);
// Encoding functions
asn->enc_msg[0] = e2ap_enc_subscription_request_asn_msg;
asn->enc_msg[1] = e2ap_enc_subscription_response_asn_msg;
asn->enc_msg[2] = e2ap_enc_subscription_failure_asn_msg;
asn->enc_msg[3] = e2ap_enc_subscription_delete_request_asn_msg;
asn->enc_msg[4] = e2ap_enc_subscription_delete_response_asn_msg;
asn->enc_msg[5] = e2ap_enc_subscription_delete_failure_asn_msg;
asn->enc_msg[6] = e2ap_enc_indication_asn_msg;
asn->enc_msg[7] = e2ap_enc_control_request_asn_msg;
asn->enc_msg[8] = e2ap_enc_control_ack_asn_msg;
asn->enc_msg[9] = e2ap_enc_control_failure_asn_msg;
asn->enc_msg[10] = e2ap_enc_error_indication_asn_msg;
asn->enc_msg[11] = e2ap_enc_setup_request_asn_msg;
asn->enc_msg[12] = e2ap_enc_setup_response_asn_msg;
asn->enc_msg[13] = e2ap_enc_setup_failure_asn_msg;
asn->enc_msg[14] = e2ap_enc_reset_request_asn_msg;
asn->enc_msg[15] = e2ap_enc_reset_response_asn_msg;
asn->enc_msg[16] = e2ap_enc_service_update_asn_msg;
asn->enc_msg[17] = e2ap_enc_service_update_ack_asn_msg;
asn->enc_msg[18] = e2ap_enc_service_update_failure_asn_msg;
asn->enc_msg[19] = e2ap_enc_service_query_asn_msg;
asn->enc_msg[20] = e2ap_enc_node_configuration_update_asn_msg;
asn->enc_msg[21] = e2ap_enc_node_configuration_update_ack_asn_msg;
asn->enc_msg[22] = e2ap_enc_node_configuration_update_failure_asn_msg;
asn->enc_msg[23] = e2ap_enc_node_connection_update_asn_msg;
asn->enc_msg[24] = e2ap_enc_node_connection_update_ack_asn_msg;
asn->enc_msg[25] = e2ap_enc_node_connection_update_failure_asn_msg;
asn->enc_msg[26] = e2ap_enc_e42_setup_request_asn_msg;
asn->enc_msg[27] = e2ap_enc_e42_setup_response_asn_msg;
asn->enc_msg[28] = e2ap_enc_e42_subscription_request_asn_msg;
asn->enc_msg[29] = e2ap_enc_e42_subscription_delete_request_asn_msg;
asn->enc_msg[30] = e2ap_enc_e42_control_request_asn_msg;
// Decoding Functions
asn->dec_msg[0] = e2ap_dec_subscription_request;
asn->dec_msg[1] = e2ap_dec_subscription_response;
asn->dec_msg[2] = e2ap_dec_subscription_failure;
asn->dec_msg[3] = e2ap_dec_subscription_delete_request;
asn->dec_msg[4] = e2ap_dec_subscription_delete_response;
asn->dec_msg[5] = e2ap_dec_subscription_delete_failure;
asn->dec_msg[6] = e2ap_dec_indication;
asn->dec_msg[7] = e2ap_dec_control_request;
asn->dec_msg[8] = e2ap_dec_control_ack;
asn->dec_msg[9] = e2ap_dec_control_failure;
asn->dec_msg[10] = e2ap_dec_error_indication;
asn->dec_msg[11] = e2ap_dec_setup_request;
asn->dec_msg[12] = e2ap_dec_setup_response;
asn->dec_msg[13] = e2ap_dec_setup_failure;
asn->dec_msg[14] = e2ap_dec_reset_request;
asn->dec_msg[15] = e2ap_dec_reset_response;
asn->dec_msg[16] = e2ap_dec_service_update;
asn->dec_msg[17] = e2ap_dec_service_update_ack;
asn->dec_msg[18] = e2ap_dec_service_update_failure;
asn->dec_msg[19] = e2ap_dec_service_query;
asn->dec_msg[20] = e2ap_dec_node_configuration_update;
asn->dec_msg[21] = e2ap_dec_node_configuration_update_ack;
asn->dec_msg[22] = e2ap_dec_node_configuration_update_failure;
asn->dec_msg[23] = e2ap_dec_connection_update;
asn->dec_msg[24] = e2ap_dec_connection_update_ack;
asn->dec_msg[25] = e2ap_dec_connection_update_failure;
asn->dec_msg[26] = e2ap_dec_e42_setup_request;
asn->dec_msg[27] = e2ap_dec_e42_setup_response;
asn->dec_msg[28] = e2ap_dec_e42_subscription_request;
asn->dec_msg[29] = e2ap_dec_e42_subscription_delete_request;
asn->dec_msg[30] = e2ap_dec_e42_control_request;
// Free Functions
asn->free_msg[0] = e2ap_free_subscription_request_msg;
asn->free_msg[1] = e2ap_free_subscription_response_msg;
asn->free_msg[2] = e2ap_free_subscription_failure_msg;
asn->free_msg[3] = e2ap_free_subscription_delete_request_msg;
asn->free_msg[4] = e2ap_free_subscription_delete_response_msg;
asn->free_msg[5] = e2ap_free_subscription_delete_failure_msg;
asn->free_msg[6] = e2ap_free_indication_msg;
asn->free_msg[7] = e2ap_free_control_request_msg;
asn->free_msg[8] = e2ap_free_control_ack_msg;
asn->free_msg[9] = e2ap_free_control_failure_msg;
asn->free_msg[10] = e2ap_free_error_indication_msg;
asn->free_msg[11] = e2ap_free_setup_request_msg;
asn->free_msg[12] = e2ap_free_setup_response_msg;
asn->free_msg[13] = e2ap_free_setup_failure_msg;
asn->free_msg[14] = e2ap_free_reset_request_msg;
asn->free_msg[15] = e2ap_free_reset_response_msg;
asn->free_msg[16] = e2ap_free_service_update_msg;
asn->free_msg[17] = e2ap_free_service_update_ack_msg;
asn->free_msg[18] = e2ap_free_service_update_failure_msg;
asn->free_msg[19] = e2ap_free_service_query_msg;
asn->free_msg[20] = e2ap_free_node_configuration_update_msg;
asn->free_msg[21] = e2ap_free_node_configuration_update_ack_msg;
asn->free_msg[22] = e2ap_free_node_configuration_update_failure_msg;
asn->free_msg[23] = e2ap_free_node_connection_update_msg;
asn->free_msg[24] = e2ap_free_node_connection_update_ack_msg;
asn->free_msg[25] = e2ap_free_node_connection_update_failure_msg;
asn->free_msg[26] = e2ap_free_e42_setup_request_msg;
asn->free_msg[27] = e2ap_free_e42_setup_response_msg;
asn->free_msg[28] = e2ap_free_e42_ric_subscription_request_msg;
asn->free_msg[29] = e2ap_free_e42_ric_subscription_delete_request_msg;
asn->free_msg[30] = e2ap_free_e42_ric_control_request_msg;
}

View File

@@ -0,0 +1,35 @@
/*
* 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 E2AP_APPLICATION_PROTOCOL_ASN
#define E2AP_APPLICATION_PROTOCOL_ASN
#include "e2ap_ap.h"
typedef struct e2ap_asn e2ap_asn_t;
void init_ap_asn(e2ap_asn_t* asn);
#endif

View File

@@ -0,0 +1,121 @@
/*
* 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 "e2ap_ap_fb.h"
#include <assert.h>
#include <stdlib.h>
#include "dec/e2ap_msg_dec_generic.h"
#include "enc/e2ap_msg_enc_generic.h"
#include "free/e2ap_msg_free.h"
void init_ap_fb(e2ap_fb_t* fb)
{
assert(fb != NULL);
// Encoding Fucntions
fb->enc_msg[0] = e2ap_enc_subscription_request_fb_msg;
fb->enc_msg[1] = e2ap_enc_subscription_response_fb_msg;
fb->enc_msg[2] = e2ap_enc_subscription_failure_fb_msg;
fb->enc_msg[3] = e2ap_enc_subscription_delete_request_fb_msg;
fb->enc_msg[4] = e2ap_enc_subscription_delete_response_fb_msg;
fb->enc_msg[5] = e2ap_enc_subscription_delete_failure_fb_msg;
fb->enc_msg[6] = e2ap_enc_indication_fb_msg;
fb->enc_msg[7] = e2ap_enc_control_request_fb_msg;
fb->enc_msg[8] = e2ap_enc_control_ack_fb_msg;
fb->enc_msg[9] = e2ap_enc_control_failure_fb_msg;
fb->enc_msg[10] = NULL;//e2ap_dec_error_indication;
fb->enc_msg[11] = e2ap_enc_setup_request_fb_msg;
fb->enc_msg[12] = e2ap_enc_setup_response_fb_msg;
fb->enc_msg[13] = NULL;//e2ap_dec_setup_failure;
fb->enc_msg[14] = NULL;//e2ap_dec_reset_request;
fb->enc_msg[15] = NULL;//e2ap_dec_reset_response;
fb->enc_msg[16] = NULL;//e2ap_dec_service_update;
fb->enc_msg[17] = NULL;//e2ap_dec_service_update_ack;
fb->enc_msg[18] = NULL;//e2ap_dec_service_update_failure;
fb->enc_msg[19] = NULL;//e2ap_dec_service_query;
fb->enc_msg[20] = NULL;//e2ap_dec_node_configuration_update;
fb->enc_msg[21] = NULL;//e2ap_dec_node_configuration_update_ack;
fb->enc_msg[22] = NULL;//e2ap_dec_node_configuration_update_failure;
fb->enc_msg[23] = NULL;//e2ap_dec_connection_update;
fb->enc_msg[24] = NULL;//e2ap_dec_connection_update_ack;
fb->enc_msg[25] = NULL;//e2ap_dec_connection_update_failure;
// Decoding Functions
fb->dec_msg[0] = e2ap_dec_subscription_request_fb;
fb->dec_msg[1] = e2ap_dec_subscription_response_fb;
fb->dec_msg[2] = e2ap_dec_subscription_failure_fb;
fb->dec_msg[3] = e2ap_dec_subscription_delete_request_fb;
fb->dec_msg[4] = e2ap_dec_subscription_delete_response_fb;
fb->dec_msg[5] = e2ap_dec_subscription_delete_failure_fb;
fb->dec_msg[6] = e2ap_dec_indication_fb;
fb->dec_msg[7] = e2ap_dec_control_request_fb;
fb->dec_msg[8] = e2ap_dec_control_ack_fb;
fb->dec_msg[9] = e2ap_dec_control_failure_fb;
fb->dec_msg[10] = NULL;//e2ap_dec_error_indication;
fb->dec_msg[11] = e2ap_dec_setup_request_fb;
fb->dec_msg[12] = e2ap_dec_setup_response_fb;
fb->dec_msg[13] = NULL;//e2ap_dec_setup_failure;
fb->dec_msg[14] = NULL;//e2ap_dec_reset_request;
fb->dec_msg[15] = NULL;//e2ap_dec_reset_response;
fb->dec_msg[16] = NULL;//e2ap_dec_service_update;
fb->dec_msg[17] = NULL;//e2ap_dec_service_update_ack;
fb->dec_msg[18] = NULL;//e2ap_dec_service_update_failure;
fb->dec_msg[19] = NULL;//e2ap_dec_service_query;
fb->dec_msg[20] = NULL;//e2ap_dec_node_configuration_update;
fb->dec_msg[21] = NULL;//e2ap_dec_node_configuration_update_ack;
fb->dec_msg[22] = NULL;//e2ap_dec_node_configuration_update_failure;
fb->dec_msg[23] = NULL;//e2ap_dec_connection_update;
fb->dec_msg[24] = NULL;//e2ap_dec_connection_update_ack;
fb->dec_msg[25] = NULL;//e2ap_dec_connection_update_failure;
// Free Functions
fb->free_msg[0] = e2ap_free_subscription_request_msg;
fb->free_msg[1] = e2ap_free_subscription_response_msg;
fb->free_msg[2] = e2ap_free_subscription_failure_msg;
fb->free_msg[3] = e2ap_free_subscription_delete_request_msg;
fb->free_msg[4] = e2ap_free_subscription_delete_response_msg;
fb->free_msg[5] = e2ap_free_subscription_delete_failure_msg;
fb->free_msg[6] = e2ap_free_indication_msg;
fb->free_msg[7] = e2ap_free_control_request_msg;
fb->free_msg[8] = e2ap_free_control_ack_msg;
fb->free_msg[9] = e2ap_free_control_failure_msg;
fb->free_msg[10] = e2ap_free_error_indication_msg;
fb->free_msg[11] = e2ap_free_setup_request_msg;
fb->free_msg[12] = e2ap_free_setup_response_msg;
fb->free_msg[13] = e2ap_free_setup_failure_msg;
fb->free_msg[14] = e2ap_free_reset_request_msg;
fb->free_msg[15] = e2ap_free_reset_response_msg;
fb->free_msg[16] = e2ap_free_service_update_msg;
fb->free_msg[17] = e2ap_free_service_update_ack_msg;
fb->free_msg[18] = e2ap_free_service_update_failure_msg;
fb->free_msg[19] = e2ap_free_service_query_msg;
fb->free_msg[20] = e2ap_free_node_configuration_update_msg;
fb->free_msg[21] = e2ap_free_node_configuration_update_ack_msg;
fb->free_msg[22] = e2ap_free_node_configuration_update_failure_msg;
fb->free_msg[23] = e2ap_free_node_connection_update_msg;
fb->free_msg[24] = e2ap_free_node_connection_update_ack_msg;
fb->free_msg[25] = e2ap_free_node_connection_update_failure_msg;
}

View File

@@ -0,0 +1,35 @@
/*
* 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 E2AP_APPLICATION_PROTOCOL_FB
#define E2AP_APPLICATION_PROTOCOL_FB
#include "e2ap_ap.h"
typedef struct e2ap_fb e2ap_fb_t;
void init_ap_fb(e2ap_fb_t* fb);
#endif

View File

@@ -0,0 +1,51 @@
set(e2ap_src_types
ric_subscription_request.c
ric_subscription_response.c
ric_subscription_failure.c
ric_indication.c
ric_subscription_delete_request.c
ric_subscription_delete_response.c
ric_subscription_delete_failure.c
ric_control_request.c
ric_control_ack.c
ric_control_failure.c
e2ap_error_indication.c
e2_setup_request.c
e2_setup_response.c
e2_setup_failure.c
e42_setup_request.c
e42_setup_response.c
e42_ric_control_request.c
e2_node_connected.c
e42_ric_subscription_request.c
e42_ric_subscription_delete_request.c
e2ap_reset_request.c
e2ap_reset_response.c
ric_service_update.c
ric_service_update_ack.c
ric_service_update_failure.c
ric_service_query.c
e2_node_configuration_update.c
common/e2ap_ran_function_id_rev.c
common/e2ap_ran_function_id.c
common/ric_action.c
common/ric_gen_id.c
common/ric_action_admitted.c
common/ric_action_not_admitted.c
common/e2ap_criticality_diagnostics.c
common/e2ap_cause.c
common/e2ap_global_node_id.c
common/e2ap_global_ric_id.c
common/e2ap_ran_function.c
common/e2ap_time_to_wait.c
common/e2ap_rejected_ran_function.c
common/e2ap_node_component_config_update.c
common/transport_layer_info.c
common/e2ap_plmn.c
common/ric_subsequent_action.c
)
add_library(e2ap_types_obj OBJECT ${e2ap_src_types})
target_link_libraries(e2ap_types_obj PUBLIC ds)

View File

@@ -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
*/
#include "e2ap_cause.h"
#include <assert.h>
#include <stddef.h>
#include <string.h>
bool eq_cause(const cause_t* m0, const cause_t* m1)
{
if(m0 == m1) return true;
if(m0 == NULL || m1 == NULL)
return false;
const int rc = memcmp(m0, m1, sizeof(cause_t));
if( rc != 0) return false;
return true;
}
cause_t cp_cause(cause_t const* src)
{
assert(src != NULL);
cause_t dst = *src;
return dst;
}

View File

@@ -0,0 +1,95 @@
/*
* 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 E2AP_CAUSE_H
#define E2AP_CAUSE_H
#include <stdbool.h>
typedef enum {
CAUSE_NOTHING, /* NO COMPONENTS PRESENT */
CAUSE_RICREQUEST,
CAUSE_RICSERVICE,
CAUSE_TRANSPORT,
CAUSE_PROTOCOL,
CAUSE_MISC
} cause_e;
typedef enum {
CAUSE_RIC_RAN_FUNCTION_ID_INVALID = 0,
CAUSE_RIC_ACTION_NOT_SUPPORTED = 1,
CAUSE_RIC_EXCESSIVE_ACTIONS = 2,
CAUSE_RIC_DUPLICATE_ACTION = 3,
CAUSE_RIC_DUPLICATE_EVENT = 4,
CAUSE_RIC_FUNCTION_RESOURCE_LIMIT = 5,
CAUSE_RIC_REQUEST_ID_UNKNOWN = 6,
CAUSE_RIC_INCONSISTENT_ACTION_SUBSEQUENT_ACTION_SEQUENCE = 7,
CAUSE_RIC_CONTROL_MESSAGE_INVALID = 8,
CAUSE_RIC_CALL_PROCESS_ID_INVALID = 9,
CAUSE_RIC_UNSPECIFIED = 10
} cause_RIC_e;
typedef enum {
CAUSE_RICSERVICE_FUNCTION_NOT_REQUIRED = 0,
CAUSE_RICSERVICE_EXCESSIVE_FUNCTIONS = 1,
CAUSE_RICSERVICE_RIC_RESOURCE_LIMIT = 2
} cause_RIC_service_e;
typedef enum {
CAUSE_TRANSPORT_UNSPECIFIED = 0,
CAUSE_TRANSPORT_TRANSPORT_RESOURCE_UNAVAILABLE = 1
} cause_transport_e;
typedef enum {
CAUSE_PROTOCOL_TRANSFER_SYNTAX_ERROR = 0,
CAUSE_PROTOCOL_ABSTRACT_SYNTAX_ERROR_REJECT = 1,
CAUSE_PROTOCOL_ABSTRACT_SYNTAX_ERROR_IGNORE_AND_NOTIFY = 2,
CAUSE_PROTOCOL_MESSAGE_NOT_COMPATIBLE_WITH_RECEIVER_STATE = 3,
CAUSE_PROTOCOL_SEMANTIC_ERROR = 4,
CAUSE_PROTOCOL_ABSTRACT_SYNTAX_ERROR_FALSELY_CONSTRUCTED_MESSAGE = 5,
CAUSE_PROTOCOL_UNSPECIFIED = 6
} cause_protocol_e;
typedef enum {
CAUSE_MISC_CONTROL_PROCESSING_OVERLOAD = 0,
CAUSE_MISC_HARDWARE_FAILURE = 1,
CAUSE_MISC_OM_INTERVENTION = 2,
CAUSE_MISC_UNSPECIFIED = 3
} cause_misc_e;
/* Cause */
typedef struct {
cause_e present;
union {
cause_RIC_e ricRequest;
cause_RIC_service_e ricService;
cause_transport_e transport;
cause_protocol_e protocol;
cause_misc_e misc;
};
} cause_t;
bool eq_cause(const cause_t* m0, const cause_t* m1);
cause_t cp_cause(cause_t const* src);
#endif

View File

@@ -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 E2AP_CONNECTION_SETUP_FAILED_H
#define E2AP_CONNECTION_SETUP_FAILED_H
#include "e2ap_cause.h"
#include "e2ap_tnl_information.h"
typedef struct{
cause_t cause;
e2ap_tnl_information_t info;
} e2_connection_setup_failed_t;
#endif

View File

@@ -0,0 +1,34 @@
/*
* 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 E2AP_CONNECTION_UPDATE_H
#define E2AP_CONNECTION_UPDATE_H
#include "e2ap_tnl_information.h"
#include "e2ap_tnl_usage.h"
typedef struct{
e2ap_tnl_information_t info;
e2ap_tnl_usage_e usage;
} e2_connection_update_item_t;
#endif

View File

@@ -0,0 +1,34 @@
/*
* 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 E2AP_CONNECTIOIN_UPDATE_REMOVE_H
#define E2AP_CONNECTIOIN_UPDATE_REMOVE_H
#include "e2ap_tnl_information.h"
typedef struct{
e2ap_tnl_information_t info;
} e2_connection_update_remove_item_t;
#endif

View File

@@ -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 E2AP_CRITICALITY_H
#define E2AP_CRITICALITY_H
typedef enum {
REJECT,
IGNORE,
NOTIFY
} criticality_e;
#endif

View File

@@ -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
*/
#include "e2ap_criticality_diagnostics.h"
#include <assert.h>
bool eq_criticality_diagnostics(const criticality_diagnostics_t* m0, const criticality_diagnostics_t* m1)
{
if(m0 == m1) return true;
if(m0 != NULL || m1 != NULL) return false;
assert(0!=0 && "Not implemented");
return true;
}

View File

@@ -0,0 +1,54 @@
/*
* 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 E2AP_CRITICALITY_DIAGNOSTICS_H
#define E2AP_CRITICALITY_DIAGNOSTICS_H
#include <stddef.h>
#include <stdint.h>
#include "ric_gen_id.h"
#include "e2ap_criticality.h"
#include "ric_gen_id.h"
#include "e2ap_ie_criticality_diagnostics.h"
typedef enum {
INITIATING_MESSAGE,
SUCCESSFUL_OUTCOME,
UNSUCCESSFUL_OUTCOME
} triggering_message_e;
typedef struct {
uint8_t* procedure_code; //optional
triggering_message_e* trig_msg; // optional
criticality_e* proc_crit; // optional
ric_gen_id_t* req_id; // optional
ie_criticality_diagnostics_t* ie;
size_t len_ie;
} criticality_diagnostics_t;
bool eq_criticality_diagnostics(const criticality_diagnostics_t* m0, const criticality_diagnostics_t* m1);
#endif

View File

@@ -0,0 +1,187 @@
/*
* 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 "e2ap_global_node_id.h"
#include <assert.h>
#include <stddef.h>
#include <stdlib.h>
#include <string.h>
bool eq_global_e2_node_id(const global_e2_node_id_t* m0, const global_e2_node_id_t* m1)
{
if(m0 == m1) return true;
if(m0 == NULL || m1 == NULL) return false;
if (NODE_IS_MONOLITHIC(m0->type) && NODE_IS_MONOLITHIC(m1->type)) {
// compare gNB/eNB
if(m0->type != m1->type)
return false;
if(eq_plmn(&m0->plmn, &m1->plmn) == false)
return false;
if(m0->nb_id != m1->nb_id)
return false;
return true;
} else if ((NODE_IS_CU(m0->type) || NODE_IS_DU(m0->type)) && (NODE_IS_CU(m1->type) || NODE_IS_DU(m1->type))) {
// compare gNB/eNB-CU/DU
if(m0->cu_du_id == NULL || m1->cu_du_id == NULL) return false;
if(m0->type != m1->type)
return false;
if(eq_plmn(&m0->plmn, &m1->plmn) == false)
return false;
if(m0->nb_id != m1->nb_id)
return false;
if(*m0->cu_du_id != *m1->cu_du_id)
return false;
return true;
} else {
// compare gNB/eNB and gNB/eNB-CU/DU
// avoid diff type with same plmn/nb_id
if(eq_plmn(&m0->plmn, &m1->plmn) == false)
return false;
if(m0->nb_id != m1->nb_id)
return false;
return true;
}
}
global_e2_node_id_t cp_global_e2_node_id(global_e2_node_id_t const* src)
{
assert(src != NULL);
global_e2_node_id_t dst = {0};
dst.type = src->type;
dst.plmn = cp_plmn(&src->plmn);
dst.nb_id = src->nb_id;
if (src->cu_du_id != NULL) {
dst.cu_du_id = calloc(1, sizeof(uint64_t));
assert(dst.cu_du_id != NULL && "memory exhausted");
*dst.cu_du_id = *src->cu_du_id;
}
return dst;
}
void free_global_e2_node_id(global_e2_node_id_t* src)
{
if (src->cu_du_id != NULL)
free (src->cu_du_id);
}
bool eq_global_e2_node_id_wrapper(const void* m0_v, const void* m1_v)
{
assert(m0_v != NULL);
assert(m1_v != NULL);
global_e2_node_id_t* m0 = (global_e2_node_id_t*)m0_v;
global_e2_node_id_t* m1 = (global_e2_node_id_t*)m1_v;
return eq_global_e2_node_id(m0,m1);
}
int cmp_global_e2_node_id(const global_e2_node_id_t* m0, const global_e2_node_id_t* m1)
{
assert(m0 != NULL);
assert(m1 != NULL);
if (NODE_IS_MONOLITHIC(m0->type) && NODE_IS_MONOLITHIC(m1->type)) {
// compare gNB/eNB
if (m0->type < m1->type)
return -1;
else if(m0->type > m1->type)
return 1;
int rc = cmp_plmn(&m0->plmn, &m1->plmn);
if(rc != 0)
return rc;
if (m0->nb_id < m1->nb_id)
return -1;
else if(m0->nb_id > m1->nb_id)
return 1;
return 0;
} else if ((NODE_IS_CU(m0->type) || NODE_IS_DU(m0->type)) && (NODE_IS_CU(m1->type) || NODE_IS_DU(m1->type))) {
// compare gNB/eNB-CU/DU
if (m0->type < m1->type)
return -1;
else if(m0->type > m1->type)
return 1;
int rc = cmp_plmn(&m0->plmn, &m1->plmn);
if(rc != 0)
return rc;
if (m0->nb_id < m1->nb_id)
return -1;
else if(m0->nb_id > m1->nb_id)
return 1;
if (*m0->cu_du_id < *m1->cu_du_id)
return -1;
else if(*m0->cu_du_id > *m1->cu_du_id)
return 1;
return 0;
} else {
// compare gNB/eNB and gNB/eNB-CU/DU
// avoid diff type with same plmn/nb_id
int rc = cmp_plmn(&m0->plmn, &m1->plmn);
if(rc != 0)
return rc;
if (m0->nb_id < m1->nb_id)
return -1;
else if(m0->nb_id > m1->nb_id)
return 1;
return 0;
}
}
int cmp_global_e2_node_id_wrapper(const void* m0_v, const void* m1_v)
{
assert(m0_v != NULL);
assert(m1_v != NULL);
global_e2_node_id_t* m0 = (global_e2_node_id_t*)m0_v;
global_e2_node_id_t* m1 = (global_e2_node_id_t*)m1_v;
return cmp_global_e2_node_id(m0,m1);
}

View File

@@ -0,0 +1,63 @@
/*
* 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 E2AP_GLOBAL_NODE_ID_H
#define E2AP_GLOBAL_NODE_ID_H
#ifdef __cplusplus
extern "C" {
#endif
#include "e2ap_plmn.h"
#include "common/ngran_types.h"
#include <stdbool.h>
#include <stdint.h>
typedef struct global_e2_node_id {
ngran_node_t type;
plmn_t plmn;
uint32_t nb_id;
uint64_t *cu_du_id;
} global_e2_node_id_t;
global_e2_node_id_t cp_global_e2_node_id(global_e2_node_id_t const* src);
void free_global_e2_node_id(global_e2_node_id_t* src);
bool eq_global_e2_node_id(const global_e2_node_id_t* m0, const global_e2_node_id_t* m1);
bool eq_global_e2_node_id(const global_e2_node_id_t* m0, const global_e2_node_id_t* m1);
bool eq_global_e2_node_id_wrapper(const void* m0_v, const void* m1_v );
int cmp_global_e2_node_id(const global_e2_node_id_t* m0, const global_e2_node_id_t* m1);
int cmp_global_e2_node_id_wrapper(const void* m0_v, const void* m1_v);
#ifdef __cplusplus
}
#endif
#endif

View File

@@ -0,0 +1,40 @@
/*
* 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 "e2ap_global_ric_id.h"
#include <stddef.h>
bool eq_global_ric_id(const global_ric_id_t* m0, const global_ric_id_t* m1)
{
if(m0 == m1) return true;
if(m0 == NULL || m1 == NULL) return false;
if(eq_plmn(&m0->plmn, &m1->plmn) == false)
return false;
if(m0->near_ric_id.double_word != m1->near_ric_id.double_word)
return false;
return true;
};

View File

@@ -0,0 +1,44 @@
/*
* 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 E2AP_GLOBAL_RIC_H
#define E2AP_GLOBAL_RIC_H
#include "e2ap_plmn.h"
#include <stdint.h>
typedef struct{
plmn_t plmn;
union{
uint32_t double_word;
uint8_t bytes[4];
} near_ric_id;
} global_ric_id_t;
bool eq_global_ric_id(const global_ric_id_t* m0, const global_ric_id_t* m1);
#endif

View File

@@ -0,0 +1,44 @@
/*
* 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 E2AP_IE_CRITICALITY_DIAGNOSTICS_H
#define E2AP_IE_CRITICALITY_DIAGNOSTICS_H
#include "stdint.h"
#include "e2ap_criticality.h"
typedef enum {
NOT_UNDERSTOOD,
MISSING
} type_of_error_t;
typedef struct ie_criticality_diagnostics {
criticality_e crit;
uint16_t id;
type_of_error_t type;
} ie_criticality_diagnostics_t;
#endif

View File

@@ -0,0 +1,163 @@
/*
* 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 "e2ap_node_component_config_update.h"
#include <assert.h>
#include <stdlib.h>
static
byte_array_t* create_assign_ba(byte_array_t* src)
{
byte_array_t* dst = calloc(1, sizeof(byte_array_t));
assert(dst != NULL && "Memory ehausted");
*dst = copy_byte_array(*src);
return dst;
}
e2_node_component_config_update_t cp_e2_node_component_config_update(const e2_node_component_config_update_t* src)
{
assert(src != NULL);
e2_node_component_config_update_t dst = {
.e2_node_component_type = src->e2_node_component_type,
};
if(src->id_present != NULL){
dst.id_present = calloc(1,sizeof(e2_node_component_id_present_e ));
assert(dst.id_present != NULL && "Memory exhausted");
dst.id_present = src->id_present;
// Does not matter the value of src->id_present
dst.gnb_cu_up_id = src->gnb_cu_up_id;
}
dst.update_present = src->update_present;
if(dst.update_present == E2_NODE_COMPONENT_CONFIG_UPDATE_GNB_CONFIG_UPDATE){
dst.gnb.ngap_gnb_cu_cp = create_assign_ba(src->gnb.ngap_gnb_cu_cp);
dst.gnb.xnap_gnb_cu_cp = create_assign_ba(src->gnb.xnap_gnb_cu_cp);
dst.gnb.e1ap_gnb_cu_cp = create_assign_ba(src->gnb.e1ap_gnb_cu_cp);
dst.gnb.f1ap_gnb_cu_cp = create_assign_ba(src->gnb.f1ap_gnb_cu_cp);
} else if (dst.update_present == E2_NODE_COMPONENT_CONFIG_UPDATE_EN_GNB_CONFIG_UPDATE ){
dst.en_gnb.x2ap_en_gnb = create_assign_ba(src->en_gnb.x2ap_en_gnb);
} else if (dst.update_present == E2_NODE_COMPONENT_CONFIG_UPDATE_NG_ENB_CONFIG_UPDATE ){
dst.ng_enb.ngap_ng_enb = create_assign_ba(src->ng_enb.ngap_ng_enb);
dst.ng_enb.xnap_ng_enb = create_assign_ba(src->ng_enb.xnap_ng_enb);
} else if (dst.update_present == E2_NODE_COMPONENT_CONFIG_UPDATE_ENB_CONFIG_UPDATE ){
dst.enb.s1ap_enb = create_assign_ba(src->enb.s1ap_enb);
dst.enb.x2ap_enb = create_assign_ba(src->enb.x2ap_enb);
} else {
assert(0 != 0 && "Not foreseen switch case");
}
return dst;
}
void free_e2_node_component_config_update(e2_node_component_config_update_t* src)
{
assert(src != NULL);
if(src->id_present != NULL){
free(src->id_present);
}
if(src->update_present == E2_NODE_COMPONENT_CONFIG_UPDATE_GNB_CONFIG_UPDATE){
free_byte_array(*src->gnb.ngap_gnb_cu_cp);
free_byte_array(*src->gnb.xnap_gnb_cu_cp);
free_byte_array(*src->gnb.e1ap_gnb_cu_cp);
free_byte_array(*src->gnb.f1ap_gnb_cu_cp);
} else if (src->update_present == E2_NODE_COMPONENT_CONFIG_UPDATE_EN_GNB_CONFIG_UPDATE ){
free_byte_array(*src->en_gnb.x2ap_en_gnb);
} else if (src->update_present == E2_NODE_COMPONENT_CONFIG_UPDATE_NG_ENB_CONFIG_UPDATE ){
free_byte_array(*src->ng_enb.ngap_ng_enb);
free_byte_array(*src->ng_enb.xnap_ng_enb);
} else if (src->update_present == E2_NODE_COMPONENT_CONFIG_UPDATE_ENB_CONFIG_UPDATE ){
free_byte_array(*src->enb.s1ap_enb);
free_byte_array(*src->enb.x2ap_enb);
} else {
assert(0 != 0 && "Not foreseen switch case");
}
}
static
bool eq_e2_node_component_id_present(const e2_node_component_id_present_e* m0, const e2_node_component_id_present_e* m1)
{
if(m0 == m1) return true;
if(m0 == NULL || m1 == NULL)
return false;
if(*m0 != *m1)
return false;
return true;
}
bool eq_e2_node_component_config_update(const e2_node_component_config_update_t* m0, const e2_node_component_config_update_t* m1)
{
if(m0 == m1) return true;
if(m0 == NULL || m1 == NULL) return false;
if(m0->e2_node_component_type != m1->e2_node_component_type)
return false;
if(eq_e2_node_component_id_present(m0->id_present,m1->id_present) == false)
return false;
if(m0->gnb_cu_up_id != m1->gnb_cu_up_id)
return false;
if(m0->update_present != m1->update_present)
return false;
if(m0->update_present == E2_NODE_COMPONENT_CONFIG_UPDATE_GNB_CONFIG_UPDATE){
if(eq_byte_array(m0->gnb.ngap_gnb_cu_cp, m1->gnb.ngap_gnb_cu_cp) == false)
return false;
if(eq_byte_array(m0->gnb.xnap_gnb_cu_cp, m1->gnb.xnap_gnb_cu_cp) == false )
return false;
if(eq_byte_array(m0->gnb.e1ap_gnb_cu_cp, m1->gnb.e1ap_gnb_cu_cp) == false )
return false;
if(eq_byte_array(m0->gnb.f1ap_gnb_cu_cp, m1->gnb.f1ap_gnb_cu_cp) == false )
return false;
} else if (m0->update_present == E2_NODE_COMPONENT_CONFIG_UPDATE_EN_GNB_CONFIG_UPDATE){
if(eq_byte_array(m0->en_gnb.x2ap_en_gnb, m1->en_gnb.x2ap_en_gnb) == false)
return false;
} else if(m0->update_present == E2_NODE_COMPONENT_CONFIG_UPDATE_NG_ENB_CONFIG_UPDATE){
if(eq_byte_array(m0->ng_enb.ngap_ng_enb, m1->ng_enb.ngap_ng_enb) == false)
return false;
if(eq_byte_array(m0->ng_enb.xnap_ng_enb, m1->ng_enb.xnap_ng_enb) == false)
return false;
} else if(m0->update_present == E2_NODE_COMPONENT_CONFIG_UPDATE_ENB_CONFIG_UPDATE){
if(eq_byte_array(m0->enb.s1ap_enb, m1->enb.s1ap_enb) == false)
return false;
if(eq_byte_array(m0->enb.x2ap_enb, m1->enb.x2ap_enb) == false)
return false;
} else {
assert(0!=0 && "Error, case not foreseen");
}
return true;
}

View File

@@ -0,0 +1,89 @@
/*
* 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 E2AP_NODE_COMPONENT_CONFIG_UPDATE_H
#define E2AP_NODE_COMPONENT_CONFIG_UPDATE_H
#include "byte_array.h"
#include <stdint.h>
typedef enum {
E2_NODE_COMPONENT_CONFIG_UPDATE_NOTHING,
E2_NODE_COMPONENT_CONFIG_UPDATE_GNB_CONFIG_UPDATE,
E2_NODE_COMPONENT_CONFIG_UPDATE_EN_GNB_CONFIG_UPDATE,
E2_NODE_COMPONENT_CONFIG_UPDATE_NG_ENB_CONFIG_UPDATE,
E2_NODE_COMPONENT_CONFIG_UPDATE_ENB_CONFIG_UPDATE
} e2_node_component_config_update_present_e;
typedef enum {
E2_NODE_COMPONENT_ID_E2_NODE_COMPONENT_TYPE_GNB_CU_UP,
E2_NODE_COMPONENT_ID_E2_NODE_COMPONENT_TYPE_GNB_DU
} e2_node_component_id_present_e;
typedef enum {
E2_NODE_COMPONENT_TYPE_GNB = 0,
E2_NODE_COMPONENT_TYPE_GNB_CU_UP = 1,
E2_NODE_COMPONENT_TYPE_GNB_DU = 2,
E2_NODE_COMPONENT_TYPE_EN_GNB = 3,
E2_NODE_COMPONENT_TYPE_ENB = 4,
E2_NODE_COMPONENT_TYPE_NG_ENB = 5
} e2_node_component_type_e;
typedef struct {
e2_node_component_type_e e2_node_component_type;
e2_node_component_id_present_e* id_present; // optional
union {
uint64_t gnb_cu_up_id;
uint64_t gnb_du_id;
};
e2_node_component_config_update_present_e update_present;
union {
struct {
byte_array_t* ngap_gnb_cu_cp;
byte_array_t* xnap_gnb_cu_cp;
byte_array_t* e1ap_gnb_cu_cp;
byte_array_t* f1ap_gnb_cu_cp;
} gnb;
struct {
byte_array_t* x2ap_en_gnb;
} en_gnb;
struct {
byte_array_t* ngap_ng_enb;
byte_array_t* xnap_ng_enb;
} ng_enb;
struct {
byte_array_t* s1ap_enb;
byte_array_t* x2ap_enb;
} enb;
};
} e2_node_component_config_update_t;
e2_node_component_config_update_t cp_e2_node_component_config_update(const e2_node_component_config_update_t* src);
void free_e2_node_component_config_update(e2_node_component_config_update_t* src);
bool eq_e2_node_component_config_update(const e2_node_component_config_update_t* m0, const e2_node_component_config_update_t* m1);
#endif

View File

@@ -0,0 +1,43 @@
/*
* 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 E2_NODE_CONFIGURATION_UPDATE_ACK_ITEM_H
#define E2_NODE_CONFIGURATION_UPDATE_ACK_ITEM_H
#include "e2ap_cause.h"
#include "e2ap_node_component_config_update.h"
typedef struct{
e2_node_component_type_e e2_node_component_type;
e2_node_component_id_present_e* id_present; // optional
union {
uint64_t gnb_cu_up_id;
uint64_t gnb_du_id;
};
long update_outcome;
cause_t *failure_cause; /* OPTIONAL */
} e2_node_component_config_update_ack_item_t;
#endif

View File

@@ -0,0 +1,83 @@
/*
* 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 "e2ap_plmn.h"
#include <assert.h>
#include <stddef.h>
plmn_t cp_plmn(const plmn_t* src)
{
assert(src != NULL);
plmn_t dst = {0};
dst.mcc = src->mcc;
dst.mnc = src->mnc;
dst.mnc_digit_len = src->mnc_digit_len;
return dst;
}
bool eq_plmn(const plmn_t* m0, const plmn_t* m1)
{
if(m0 == m1) return true;
if(m0 == NULL || m1 == NULL) return false;
if(m0->mcc != m1->mcc)
return false;
if(m0->mnc != m1->mnc)
return false;
if(m0->mnc_digit_len != m1->mnc_digit_len)
return false;
return true;
}
int cmp_plmn(const plmn_t* m0, const plmn_t* m1)
{
assert(m0 != NULL);
assert(m1 != NULL);
if(m0->mcc < m1->mcc)
return -1;
else if(m0->mcc > m1->mcc )
return 1;
if(m0->mnc < m1->mnc)
return -1;
else if(m0->mnc > m1->mnc )
return 1;
if(m0->mnc_digit_len < m1->mnc_digit_len)
return -1;
else if(m0->mnc_digit_len > m1->mnc_digit_len)
return 1;
return 0;
}

View File

@@ -0,0 +1,54 @@
/*
* 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 E2AP_PLMN_H
#define E2AP_PLMN_H
#ifdef __cplusplus
extern "C" {
#endif
#include <stdbool.h>
#include <stdint.h>
typedef struct {
uint16_t mcc;
uint16_t mnc;
uint8_t mnc_digit_len;
} plmn_t;
bool eq_plmn(const plmn_t* m0, const plmn_t* m1);
plmn_t cp_plmn(const plmn_t* src);
int cmp_plmn(const plmn_t* m0, const plmn_t* m1);
#ifdef __cplusplus
}
#endif
#endif

Some files were not shown because too many files have changed in this diff Show More