Commit c4745c3e authored by hardy's avatar hardy

Merge remote-tracking branch 'origin/new-gtpu' into integration_2020_wk15

 Conflicts:
	cmake_targets/CMakeLists.txt
	openair1/PHY/TOOLS/time_meas.h
	openair2/LAYER2/PDCP_v10.1.0/pdcp_fifo.c
	openair2/LAYER2/RLC/rlc.h
parents 246afc7c 657b525e
......@@ -412,6 +412,7 @@ add_boolean_option(UE_AUTOTEST_TRACE False "Activate UE autotest specific logs
add_boolean_option(UE_DEBUG_TRACE False "Activate UE debug trace")
add_boolean_option(UE_TIMING_TRACE False "Activate UE timing trace")
add_boolean_option(DEBUG_CONSOLE False "makes debugging easier, disables stdout/stderr buffering")
add_boolean_option(NEW_GTPU False "NEW_GTP")
set (OCP_ITTI ${OPENAIR_DIR}/common/utils/ocp_itti)
add_library(ITTI
......@@ -420,7 +421,6 @@ add_library(ITTI
)
add_dependencies(ITTI rrc_flag)
set(ITTI_LIB ITTI)
set(GTPU_need_ITTI ${OPENAIR3_DIR}/GTPV1-U/gtpv1u_eNB.c)
##################################################
......@@ -2235,26 +2235,21 @@ add_library(CN_UTILS
)
set(GTPV1U_DIR ${OPENAIR3_DIR}/GTPV1-U)
set (GTPV1U_SRC
add_library (GTPV1U_OCP
${NR_RRC_DIR}/rrc_gNB_GTPV1U.c
${RRC_DIR}/rrc_eNB_GTPV1U.c
${GTPV1U_DIR}/nw-gtpv1u/src/NwGtpv1uTunnelEndPoint.c
${GTPV1U_DIR}/nw-gtpv1u/src/NwGtpv1uTrxn.c
${GTPV1U_DIR}/nw-gtpv1u/src/NwGtpv1uMsg.c
${GTPV1U_DIR}/nw-gtpv1u/src/NwGtpv1u.c
${GTPV1U_DIR}/gtpv1u_teid_pool.c
${OPENAIR3_DIR}/ocp-gtpu/gtp_itf.cpp
)
add_library(GTPV1U ${GTPV1U_SRC})
add_dependencies(GTPV1U rrc_flag)
#add_library (GTPV1U_OCP
#${OPENAIR3_DIR}/ocp-gtp/gtp_itf.cpp
#)
#include_directories(${OPENAIR3_DIR}/ocp-gtp)
add_dependencies(GTPV1U_OCP rrc_flag)
include_directories(${OPENAIR3_DIR}/ocp-gtp)
#NR case
set (NR_GTPV1U_SRC
${NR_RRC_DIR}/rrc_gNB_GTPV1U.c
${RRC_DIR}/rrc_eNB_GTPV1U.c
${GTPV1U_DIR}/gtpv1u_eNB.c
${GTPV1U_DIR}/gtpv1u_gNB.c
${GTPV1U_DIR}/nw-gtpv1u/src/NwGtpv1uTunnelEndPoint.c
${GTPV1U_DIR}/nw-gtpv1u/src/NwGtpv1uTrxn.c
${GTPV1U_DIR}/nw-gtpv1u/src/NwGtpv1uMsg.c
......@@ -2264,6 +2259,12 @@ set (NR_GTPV1U_SRC
add_library(NR_GTPV1U ${NR_GTPV1U_SRC})
add_dependencies(NR_GTPV1U rrc_flag)
if (${NEW_GTPU})
set(GTPV1U GTPV1U_OCP)
else()
set(GTPV1U NR_GTPV1U)
endif()
set (MME_APP_SRC
${OPENAIR3_DIR}/MME_APP/mme_app.c
${OPENAIR3_DIR}/MME_APP/mme_config.c
......@@ -2905,7 +2906,6 @@ add_executable(lte-softmodem
${OPENAIR3_DIR}/NAS/UE/nas_ue_task.c
${OPENAIR_DIR}/common/utils/utils.c
${OPENAIR_DIR}/common/utils/system.c
${GTPU_need_ITTI}
${XFORMSINTERFACE_SOURCE}
${T_SOURCE}
${CONFIG_SOURCES}
......@@ -2915,7 +2915,8 @@ add_dependencies(lte-softmodem rrc_flag s1ap_flag x2_flag oai_iqplayer)
target_link_libraries (lte-softmodem
-Wl,--start-group
RRC_LIB NR_RRC_LIB S1AP_LIB S1AP_ENB F1AP_LIB F1AP M2AP_LIB M2AP_ENB X2AP_LIB X2AP_ENB M3AP_LIB M3AP_ENB GTPV1U SECU_CN SECU_OSA UTIL HASHTABLE SCTP_CLIENT MME_APP UDP SCHED_LIB SCHED_RU_LIB
RRC_LIB NR_RRC_LIB S1AP_LIB S1AP_ENB F1AP_LIB F1AP M2AP_LIB M2AP_ENB X2AP_LIB X2AP_ENB M3AP_LIB M3AP_ENB ${GTPV1U} SECU_CN SECU_OSA UTIL HASHTABLE SCTP_CLIENT MME_APP UDP SCHED_LIB SCHED_RU_LIB
PHY_COMMON PHY PHY_RU LFDS L2 L2_LTE NFAPI_COMMON_LIB NFAPI_LIB NFAPI_VNF_LIB NFAPI_PNF_LIB NFAPI_USER_LIB MISC_NFAPI_LTE_LIB LFDS7
${MSC_LIB} ${RAL_LIB} ${NAS_UE_LIB} ${ITTI_LIB} ${FLPT_MSG_LIB} ${ASYNC_IF_LIB} ${FLEXRAN_AGENT_LIB} ${FSPT_MSG_LIB} ${PROTO_AGENT_LIB}
-Wl,--end-group z dl)
......@@ -2946,7 +2947,6 @@ add_executable(ocp-enb
${OPENAIR3_DIR}/NAS/UE/nas_ue_task.c
${OPENAIR_DIR}/common/utils/utils.c
${OPENAIR_DIR}/common/utils/system.c
${GTPU_need_ITTI}
${XFORMSINTERFACE_SOURCE}
${T_SOURCE}
${CONFIG_SOURCES}
......@@ -2956,7 +2956,8 @@ add_dependencies(ocp-enb rrc_flag s1ap_flag x2_flag oai_iqplayer coding params_l
target_link_libraries (ocp-enb
-Wl,--start-group
RRC_LIB NR_RRC_LIB S1AP_LIB S1AP_ENB F1AP_LIB F1AP M2AP_LIB M2AP_ENB X2AP_LIB X2AP_ENB M3AP_LIB M3AP_ENB GTPV1U SECU_CN SECU_OSA UTIL HASHTABLE SCTP_CLIENT MME_APP UDP SCHED_LIB SCHED_RU_LIB
RRC_LIB NR_RRC_LIB S1AP_LIB S1AP_ENB F1AP_LIB F1AP M2AP_LIB M2AP_ENB X2AP_LIB X2AP_ENB M3AP_LIB M3AP_ENB ${GTPV1U} SECU_CN SECU_OSA UTIL HASHTABLE SCTP_CLIENT MME_APP UDP SCHED_LIB SCHED_RU_LIB
PHY_COMMON PHY PHY_RU LFDS L2 L2_LTE NFAPI_COMMON_LIB NFAPI_LIB MISC_NFAPI_LTE_LIB NFAPI_VNF_LIB NFAPI_PNF_LIB NFAPI_USER_LIB LFDS7 SIMU_COMMON
${MSC_LIB} ${RAL_LIB} ${NAS_UE_LIB} ${ITTI_LIB} ${FLPT_MSG_LIB} ${ASYNC_IF_LIB} ${FLEXRAN_AGENT_LIB} ${FSPT_MSG_LIB} ${PROTO_AGENT_LIB}
-Wl,--end-group z dl)
......@@ -3026,7 +3027,8 @@ endif()
target_link_libraries (lte-uesoftmodem
-Wl,--start-group
RRC_LIB NR_RRC_LIB S1AP_LIB S1AP_ENB X2AP_LIB X2AP_ENB M2AP_LIB M2AP_ENB M3AP_LIB M3AP_ENB F1AP F1AP_LIB
GTPV1U SECU_CN SECU_OSA UTIL HASHTABLE SCTP_CLIENT MME_APP UDP SCHED_RU_LIB SCHED_UE_LIB PHY_COMMON
${GTPV1U} SECU_CN SECU_OSA UTIL HASHTABLE SCTP_CLIENT MME_APP UDP SCHED_RU_LIB SCHED_UE_LIB PHY_COMMON
PHY_UE PHY_RU LFDS L2_UE L2_LTE LFDS7 SIMU_COMMON SIMU NFAPI_COMMON_LIB NFAPI_LIB NFAPI_PNF_LIB NFAPI_USER_LIB MISC_NFAPI_LTE_LIB
${MSC_LIB} ${RAL_LIB} ${NAS_UE_LIB} ${ITTI_LIB} ${FLPT_MSG_LIB} ${ASYNC_IF_LIB} ${ATLAS_LIBRARIES}
-Wl,--end-group z dl)
......@@ -3054,12 +3056,10 @@ add_executable(nr-softmodem
${OPENAIR_TARGETS}/ARCH/COMMON/record_player.c
${OPENAIR2_DIR}/RRC/NAS/nas_config.c
${OPENAIR2_DIR}/RRC/NAS/rb_config.c
${OPENAIR3_DIR}/GTPV1-U/gtpv1u_gNB.c
${OPENAIR1_DIR}/SIMULATION/ETH_TRANSPORT/netlink_init.c
${OPENAIR_DIR}/common/utils/utils.c
${OPENAIR_DIR}/common/utils/system.c
${OPENAIR_DIR}/common/utils/nr/nr_common.c
${GTPU_need_ITTI}
${XFORMSINTERFACE_SOURCE}
${T_SOURCE}
${CONFIG_SOURCES}
......@@ -3069,7 +3069,7 @@ add_executable(nr-softmodem
target_link_libraries (nr-softmodem
-Wl,--start-group
UTIL HASHTABLE SCTP_CLIENT UDP SCHED_LIB SCHED_RU_LIB SCHED_NR_LIB PHY_NR PHY PHY_COMMON PHY_NR_COMMON PHY_RU LFDS NR_GTPV1U SECU_CN SECU_OSA
UTIL HASHTABLE SCTP_CLIENT UDP SCHED_LIB SCHED_RU_LIB SCHED_NR_LIB PHY_NR PHY PHY_COMMON PHY_NR_COMMON PHY_RU LFDS ${GTPV1U} SECU_CN SECU_OSA
${ITTI_LIB} ${FLPT_MSG_LIB} ${ASYNC_IF_LIB} ${FLEXRAN_AGENT_LIB} LFDS7 ${MSC_LIB} ${RAL_LIB} ${NAS_UE_LIB} RRC_LIB NR_RRC_LIB
NGAP_LIB NGAP_GNB S1AP_LIB S1AP_ENB L2_LTE_NR L2_NR MAC_NR_COMMON NFAPI_COMMON_LIB NFAPI_LIB NFAPI_VNF_LIB NFAPI_PNF_LIB NFAPI_USER_LIB
X2AP_LIB X2AP_ENB F1AP_LIB F1AP M2AP_LIB M2AP_ENB M3AP_LIB M3AP_ENB ${PROTO_AGENT_LIB} ${FSPT_MSG_LIB}
......@@ -3099,8 +3099,6 @@ add_executable(ocp-gnb
${OPENAIR_DIR}/common/utils/nr/nr_common.c
${OPENAIR_DIR}/common/utils/utils.c
${OPENAIR_DIR}/common/utils/system.c
${OPENAIR3_DIR}/GTPV1-U/gtpv1u_gNB.c
${GTPU_need_ITTI}
${XFORMS_SOURCE_NR}
${T_SOURCE}
${CONFIG_SOURCES}
......@@ -3110,7 +3108,7 @@ add_executable(ocp-gnb
target_link_libraries (ocp-gnb
-Wl,--start-group
UTIL HASHTABLE SCTP_CLIENT UDP SCHED_LIB SCHED_RU_LIB SCHED_NR_LIB PHY_NR PHY PHY_COMMON PHY_NR_COMMON PHY_RU LFDS NR_GTPV1U SECU_CN SECU_OSA
UTIL HASHTABLE SCTP_CLIENT UDP SCHED_LIB SCHED_RU_LIB SCHED_NR_LIB PHY_NR PHY PHY_COMMON PHY_NR_COMMON PHY_RU LFDS ${GTPV1U} SECU_CN SECU_OSA
${ITTI_LIB} ${FLPT_MSG_LIB} ${ASYNC_IF_LIB} LFDS7 ${MSC_LIB} ${RAL_LIB} ${NAS_UE_LIB} RRC_LIB NR_RRC_LIB
NGAP_LIB NGAP_GNB S1AP_LIB S1AP_ENB L2_LTE_NR L2_NR MAC_NR_COMMON NFAPI_COMMON_LIB NFAPI_LIB NFAPI_VNF_LIB NFAPI_PNF_LIB NFAPI_USER_LIB
X2AP_LIB X2AP_ENB F1AP_LIB F1AP M2AP_LIB M2AP_ENB M3AP_LIB M3AP_ENB SIMU_COMMON
......@@ -3432,7 +3430,7 @@ add_executable(test_epc_generate_scenario
${OPENAIR3_DIR}/S1AP/s1ap_eNB_defs.h
)
target_link_libraries (test_epc_generate_scenario
-Wl,--start-group RRC_LIB S1AP_LIB S1AP_ENB X2AP_LIB X2AP_ENB M2AP_LIB M2AP_ENB M3AP_LIB M3AP_ENB F1AP_LIB F1AP GTPV1U LIB_NAS_UE SECU_CN UTIL HASHTABLE SCTP_CLIENT MME_APP UDP SCHED_LIB PHY LFDS ${ITTI_LIB} ${MSC_LIB} L2 -Wl,--end-group pthread m rt crypt sctp ${LIBXML2_LIBRARIES} ${LIBXSLT_LIBRARIES} ${CRYPTO_LIBRARIES} ${OPENSSL_LIBRARIES} ${CONFIG_LIB}
-Wl,--start-group RRC_LIB S1AP_LIB S1AP_ENB X2AP_LIB X2AP_ENB M2AP_LIB M2AP_ENB M3AP_LIB M3AP_ENB F1AP_LIB F1AP ${GTPV1U} LIB_NAS_UE SECU_CN UTIL HASHTABLE SCTP_CLIENT MME_APP UDP SCHED_LIB PHY LFDS ${ITTI_LIB} ${MSC_LIB} L2 -Wl,--end-group pthread m rt crypt sctp ${LIBXML2_LIBRARIES} ${LIBXSLT_LIBRARIES} ${CRYPTO_LIBRARIES} ${OPENSSL_LIBRARIES} ${CONFIG_LIB}
)
add_executable(test_epc_play_scenario
......@@ -3451,7 +3449,7 @@ add_executable(test_epc_play_scenario
)
target_include_directories(test_epc_play_scenario PUBLIC /usr/local/share/asn1c)
target_link_libraries (test_epc_play_scenario
-Wl,--start-group RRC_LIB S1AP_LIB X2AP_LIB X2AP_ENB M3AP_LIB M3AP_ENB F1AP_LIB F1AP GTPV1U LIB_NAS_UE SECU_CN UTIL HASHTABLE SCTP_CLIENT MME_APP UDP SCHED_LIB PHY_NR_COMMON PHY_COMMON PHY PHY_UE LFDS ${ITTI_LIB} ${MSC_LIB} -Wl,--end-group pthread m rt crypt sctp ${LIBXML2_LIBRARIES} ${LIBXSLT_LIBRARIES} ${CRYPTO_LIBRARIES} ${OPENSSL_LIBRARIES} ${CONFIG_LIB}
-Wl,--start-group RRC_LIB S1AP_LIB X2AP_LIB X2AP_ENB M3AP_LIB M3AP_ENB F1AP_LIB F1AP ${GTPV1U} LIB_NAS_UE SECU_CN UTIL HASHTABLE SCTP_CLIENT MME_APP UDP SCHED_LIB PHY_NR_COMMON PHY_COMMON PHY PHY_UE LFDS ${ITTI_LIB} ${MSC_LIB} -Wl,--end-group pthread m rt crypt sctp ${LIBXML2_LIBRARIES} ${LIBXSLT_LIBRARIES} ${CRYPTO_LIBRARIES} ${OPENSSL_LIBRARIES} ${CONFIG_LIB}
)
......@@ -3497,7 +3495,7 @@ if (${T_TRACER})
NFAPI_COMMON_LIB NFAPI_LIB NFAPI_PNF_LIB NFAPI_VNF_LIB NFAPI_USER_LIB
PHY_COMMON PHY PHY_UE PHY_NR PHY_NR_COMMON PHY_NR_UE PHY_RU PHY_MEX
L2 L2_LTE L2_NR L2_LTE_NR L2_UE NR_L2_UE L2_UE_LTE_NR MAC_NR_COMMON MAC_NR MAC_UE_NR NGAP_GNB
CN_UTILS GTPV1U NR_GTPV1U SCTP_CLIENT MME_APP UDP LIB_NAS_UE NB_IoT LFDS LFDS7 SIMU_COMMON SIMU SIMU_ETH OPENAIR0_LIB
CN_UTILS ${GTPV1U} SCTP_CLIENT MME_APP UDP LIB_NAS_UE NB_IoT LFDS LFDS7 SIMU_COMMON SIMU SIMU_ETH OPENAIR0_LIB
ldpc_orig ldpc_optim ldpc_optim8seg ldpc PROTO_AGENT dfts)
if (TARGET ${i})
add_dependencies(${i} generate_T)
......@@ -3588,14 +3586,12 @@ add_executable(nr-ittisim
${OPENAIR_TARGETS}/ARCH/COMMON/record_player.c
${OPENAIR2_DIR}/RRC/NAS/nas_config.c
${OPENAIR2_DIR}/RRC/NAS/rb_config.c
${OPENAIR3_DIR}/GTPV1-U/gtpv1u_gNB.c
${OPENAIR1_DIR}/SIMULATION/ETH_TRANSPORT/netlink_init.c
${OPENAIR3_DIR}/NAS/UE/nas_ue_task.c
${OPENAIR_DIR}/common/utils/utils.c
${OPENAIR_DIR}/common/utils/system.c
${OPENAIR_DIR}/common/utils/nr/nr_common.c
${OPENAIR_DIR}/common/utils/threadPool/thread-pool.c
${GTPU_need_ITTI}
${XFORMSINTERFACE_SOURCE}
${T_SOURCE}
${CONFIG_SOURCES}
......@@ -3604,7 +3600,7 @@ add_executable(nr-ittisim
target_link_libraries (nr-ittisim
-Wl,--start-group
UTIL HASHTABLE SCTP_CLIENT UDP SCHED_LIB SCHED_RU_LIB SCHED_NR_LIB PHY_NR PHY PHY_COMMON PHY_NR_COMMON PHY_RU LFDS NR_GTPV1U SECU_CN SECU_OSA
UTIL HASHTABLE SCTP_CLIENT UDP SCHED_LIB SCHED_RU_LIB SCHED_NR_LIB PHY_NR PHY PHY_COMMON PHY_NR_COMMON PHY_RU LFDS ${GTPV1U} SECU_CN SECU_OSA
${ITTI_LIB} ${FLPT_MSG_LIB} ${ASYNC_IF_LIB} ${FLEXRAN_AGENT_LIB} LFDS7 ${MSC_LIB} ${RAL_LIB} ${NAS_SIM_LIB} RRC_LIB NR_RRC_LIB
NGAP_LIB NGAP_GNB S1AP_LIB S1AP_ENB L2_LTE_NR L2_NR MAC_NR_COMMON NFAPI_COMMON_LIB NFAPI_LIB NFAPI_VNF_LIB NFAPI_PNF_LIB NFAPI_USER_LIB
X2AP_LIB X2AP_ENB F1AP_LIB F1AP M2AP_LIB M2AP_ENB M3AP_LIB M3AP_ENB ${PROTO_AGENT_LIB} ${FSPT_MSG_LIB}
......
......@@ -340,6 +340,7 @@ void *rrc_enb_process_msg(void *);
TASK_DEF(TASK_RAL_UE, TASK_PRIORITY_MED, 200, NULL, NULL) \
TASK_DEF(TASK_MSC, TASK_PRIORITY_MED, 200, NULL, NULL)\
TASK_DEF(TASK_GTPV1_U, TASK_PRIORITY_MED, 1000,NULL, NULL)\
TASK_DEF(OCP_GTPV1_U, TASK_PRIORITY_MED, 1000,NULL, NULL)\
TASK_DEF(TASK_UDP, TASK_PRIORITY_MED, 1000, NULL, NULL)\
TASK_DEF(TASK_CU_F1, TASK_PRIORITY_MED, 200, NULL, NULL) \
TASK_DEF(TASK_DU_F1, TASK_PRIORITY_MED, 200, NULL, NULL) \
......@@ -471,6 +472,9 @@ void itti_subscribe_event_fd(task_id_t task_id, int fd);
void itti_unsubscribe_event_fd(task_id_t task_id, int fd);
/** \brief Return the list of events excluding the fd associated with itti
\the fd associated with itti can return, but it is marked events[i].events &= ~EPOLLIN
\as it is not EPOLLIN, the reader should ignore this fd
\or it can manage the list of fd's in his interest, so ignore the other ones
\param task_id Task ID of the task
\param events events list
@returns number of events to handle
......
......@@ -85,7 +85,7 @@ static inline notifiedFIFO_elt_t *newNotifiedFIFO_elt(int size,
ret->reponseFifo=reponseFifo;
ret->processingFunc=processingFunc;
// We set user data piece aligend 32 bytes to be able to process it with SIMD
ret->msgData=(void *)ret+(sizeof(notifiedFIFO_elt_t)/32+1)*32;
ret->msgData=(void *)((uint8_t*)ret+(sizeof(notifiedFIFO_elt_t)/32+1)*32);
ret->malloced=true;
return ret;
}
......
......@@ -296,6 +296,28 @@ gtp thread calls directly pdcp_data_req(), so it runs inside it's context intern
## inside other threads
gtpv1u_create_s1u_tunnel(), delete tunnel, ... functions are called inside the other threads, without mutex.
# New GTP
## initialization
Coexistance until full merge with legacy GTP
cmake new option: NEW_GTPU to use the new implementation (it changes for the entire executable)
It is possible to use both old and new GTP in same executable because the itti task and all functions names are different
Current status of new implementation: not tested, X2 not developped, 5G new GTP option not developped, remain issues on data coming from void: muid, enb_flag, ...
ocp_gtpv1uTask(): this creates only the thread, doesn't configure anything
gtpv1Init(): creates a listening socket to Linux for a given reception and select a local IP address
newGtpuCreateTunnel() this function will replace the xxx_create_tunnel_xxx() for various cases
This creates a outgoing context for a teid (in input), it computes and return the incoming teid that will be used for incoming packets
These teids and in a "instance", so in a Linux socket: same teid can co-exist for different sockets
Remain here a lack to fill: the information given in the legacy funtions is not enough to fullfil the data needed by the callback
stuff like enb_flag, but also mui and more important data are not given explicitly by any legacy function (gtpv1u_create_s1u_tunnel), but the legacy and the new interface to lower layer (like pdcp) require this data.
The datamodel is still not fully understood, so this data source remain unknown
A new parameter is the callback function: will be pdpcp_data_req() and gtpv_data_req() (x2 case) for existing implementation and later other call backs like the F1-U implementation.
incoming packets
the gtp layer retrieves the data, the teid, find out the related data: rnti, bearer and quite a lot of other parameters (not clear why, because it looks like all is statefull, so the lower layer should have the context)
if lower layers can be stateless, it is a good idea to keep the context in the gtp layer and pass it to the callback, but the design remain obfuscated.
# NGAP
NGAP would be a itti thread as is S1AP (+twin thread SCTP that is almost void processing)?
About all messages are exchanged with RRC thread
......
......@@ -82,7 +82,6 @@ int otg_enabled;
uint64_t downlink_frequency[MAX_NUM_CCs][4];
int32_t uplink_frequency_offset[MAX_NUM_CCs][4];
int split73;
int usrp_tx_thread = 0;
char * split73_config;
int split73;
AGENT_RRC_xface *agent_rrc_xface[NUM_MAX_ENB]= {0};
......
......@@ -119,7 +119,6 @@ uint16_t sl_ahead;
extern int emulate_rf;
extern int numerology;
extern int usrp_tx_thread;
/*************************************************************/
/* Functions to attach and configure RRU */
......
......@@ -85,6 +85,7 @@ unsigned short config_frames[4] = {2,9,11,13};
#include "x2ap_eNB.h"
#include "ngap_gNB.h"
#include "gnb_paramdef.h"
#include <openair3/ocp-gtpu/gtp_itf.h>
#include "nfapi/oai_integration/vendor_ext.h"
pthread_cond_t nfapi_sync_cond;
......@@ -179,7 +180,6 @@ extern void *udp_eNB_task(void *args_p);
int transmission_mode=1;
int emulate_rf = 0;
int numerology = 0;
int usrp_tx_thread = 0;
static char *parallel_config = NULL;
......
......@@ -147,7 +147,7 @@ int chain_offset = 0;
int card_offset = 0;
uint64_t num_missed_slots = 0; // counter for the number of missed slots
int transmission_mode = 1;
int usrp_tx_thread = 0;
int numerology = 0;
int oaisim_flag = 0;
int emulate_rf = 0;
......
......@@ -68,7 +68,6 @@ uint32_t timing_advance = 0;
int transmission_mode=1;
int emulate_rf = 0;
int numerology = 0;
int usrp_tx_thread = 0;
int config_sync_var=-1;
......
......@@ -45,6 +45,8 @@
static softmodem_params_t softmodem_params;
char *parallel_config=NULL;
char *worker_config=NULL;
msc_interface_t msc_interface;
int usrp_tx_thread = 0;
uint8_t nfapi_mode=0;
......
......@@ -91,6 +91,7 @@ extern "C"
#define CONFIG_HLP_RFSIM "Run in rf simulator mode (also known as basic simulator)\n"
#define CONFIG_HLP_NOKRNMOD "(noS1 only): Use tun instead of namesh module \n"
#define CONFIG_HLP_DISABLNBIOT "disable nb-iot, even if defined in config\n"
#define CONFIG_HLP_USRP_THREAD "having extra thead for usrp tx\n"
#define CONFIG_HLP_NFAPI "Change the nFAPI mode for NR\n"
/*-----------------------------------------------------------------------------------------------------------------------------------------------------*/
......@@ -117,6 +118,7 @@ extern "C"
#define DEFAULT_RFCONFIG_FILE "/usr/local/etc/syriq/ue.band7.tm1.PRB100.NR40.dat";
extern int usrp_tx_thread;
#define CMDLINE_PARAMS_DESC { \
{"rf-config-file", CONFIG_HLP_RFCFGF, 0, strptr:(char **)&RF_CONFIG_FILE, defstrval:NULL, TYPE_STRING, sizeof(RF_CONFIG_FILE)},\
{"split73", CONFIG_HLP_SPLIT73, 0, strptr:(char **)&SPLIT73, defstrval:NULL, TYPE_STRING, sizeof(SPLIT73)},\
......@@ -144,6 +146,7 @@ extern "C"
{"nokrnmod", CONFIG_HLP_NOKRNMOD, PARAMFLAG_BOOL, uptr:&nokrnmod, defintval:0, TYPE_INT, 0}, \
{"nbiot-disable", CONFIG_HLP_DISABLNBIOT, PARAMFLAG_BOOL, uptr:&nonbiot, defuintval:0, TYPE_INT, 0}, \
{"use-256qam-table", CONFIG_HLP_256QAM, PARAMFLAG_BOOL, iptr:&USE_256QAM_TABLE, defintval:0, TYPE_INT, 0}, \
{"usrp-tx-thread-config", CONFIG_HLP_USRP_THREAD, 0, iptr:&usrp_tx_thread, defstrval:0, TYPE_INT, 0}, \
{"nfapi", CONFIG_HLP_NFAPI, 0, u8ptr:&nfapi_mode, defintval:0, TYPE_UINT8, 0}, \
}
......
......@@ -26,6 +26,7 @@
// global var for openair performance profiler
int opp_enabled = 0;
double cpu_freq_GHz __attribute__ ((aligned(32)));
double cpu_freq_GHz __attribute__ ((aligned(32)))=0.0;
double get_cpu_freq_GHz(void)
......
......@@ -33,6 +33,7 @@
#include <linux/types.h>
// global var to enable openair performance profiler
extern int opp_enabled;
extern double cpu_freq_GHz __attribute__ ((aligned(32)));;
#if defined(__x86_64__) || defined(__i386__)
typedef struct {
......
......@@ -70,6 +70,7 @@ msc_interface_t msc_interface;
//void dump_nr_prach_config(NR_DL_FRAME_PARMS *frame_parms,uint8_t subframe);
/* temporary dummy implem of get_softmodem_optmask, till basic simulators implemented as device */
msc_interface_t msc_interface;
uint64_t get_softmodem_optmask(void) {return 0;}
softmodem_params_t *get_softmodem_params(void) {return 0;}
int oai_nfapi_dl_tti_req(nfapi_nr_dl_tti_request_t *dl_config_req) { return(0); }
......
......@@ -175,6 +175,8 @@ typedef struct gtpv1u_enb_end_marker_ind_s {
typedef struct {
in_addr_t enb_ip_address_for_S1u_S12_S4_up;
tcp_udp_port_t enb_port_for_S1u_S12_S4_up;
char addrStr[256];
char portStr[256];
} Gtpv1uS1Req;
typedef struct {
......
......@@ -57,6 +57,7 @@
#include "enb_paramdef.h"
#include "proto_agent.h"
#include "executables/thread-common.h"
#include <openair3/ocp-gtpu/gtp_itf.h>
extern uint32_t to_earfcn_DL(int eutra_bandP, uint32_t dl_CarrierFreq, uint32_t bw);
extern uint32_t to_earfcn_UL(int eutra_bandP, uint32_t ul_CarrierFreq, uint32_t bw);
......@@ -2058,7 +2059,9 @@ int RCconfig_gtpu(void ) {
IPV4_STR_ADDR_TO_INT_NWBO ( address, GTPV1U_ENB_S1_REQ(message).enb_ip_address_for_S1u_S12_S4_up, "BAD IP ADDRESS FORMAT FOR eNB S1_U !\n" );
LOG_I(GTPU,"Configuring GTPu address : %s -> %x\n",address,GTPV1U_ENB_S1_REQ(message).enb_ip_address_for_S1u_S12_S4_up);
GTPV1U_ENB_S1_REQ(message).enb_port_for_S1u_S12_S4_up = enb_port_for_S1U;
itti_send_msg_to_task (TASK_GTPV1_U, 0, message); // data model is wrong: gtpu doesn't have enb_id (or module_id)
strcpy(GTPV1U_ENB_S1_REQ(message).addrStr,address);
sprintf(GTPV1U_ENB_S1_REQ(message).portStr,"%d", enb_port_for_S1U);
itti_send_msg_to_task (TASK_VARIABLE, 0, message); // data model is wrong: gtpu doesn't have enb_id (or module_id)
} else
LOG_E(GTPU,"invalid address for S1U\n");
......
......@@ -58,6 +58,7 @@
//#include "RRC_config_tools.h"
#include "gnb_paramdef.h"
#include "NR_MAC_gNB/mac_proto.h"
#include <openair3/ocp-gtpu/gtp_itf.h>
#include "NR_asn_constant.h"
#include "executables/thread-common.h"
......@@ -1028,8 +1029,9 @@ int RCconfig_nr_gtpu(void ) {
LOG_I(GTPU,"Configuring GTPu address : %s -> %x\n",address,GTPV1U_GNB_NG_REQ(message).gnb_ip_address_for_NGu_up);
GTPV1U_GNB_NG_REQ(message).gnb_port_for_NGu_up = gnb_port_for_NGU;
}
itti_send_msg_to_task (TASK_GTPV1_U, 0, message); // data model is wrong: gtpu doesn't have enb_id (or module_id)
strcpy(GTPV1U_ENB_S1_REQ(message).addrStr,address);
sprintf(GTPV1U_ENB_S1_REQ(message).portStr,"%d", gnb_port_for_NGU);
itti_send_msg_to_task (TASK_VARIABLE, 0, message); // data model is wrong: gtpu doesn't have enb_id (or module_id)
} else
LOG_E(GTPU,"invalid address for NGU\n");
......
......@@ -78,4 +78,5 @@ extern eNB_UE_STATS pre_scd_eNB_UE_stats[MAX_NUM_CCs][NUMBER_OF_UE_MAX];
extern mac_rlc_am_muilist_t rlc_am_mui;
extern SCHEDULER_MODES global_scheduler_mode;
extern rb_id_t mbms_rab_id;
#endif //DEF_H
......@@ -61,6 +61,7 @@
# include "gtpv1u_eNB_task.h"
# include "gtpv1u.h"
#include <openair3/ocp-gtpu/gtp_itf.h>
#include "ENB_APP/enb_config.h"
......@@ -985,7 +986,7 @@ pdcp_data_ind(
GTPV1U_ENB_TUNNEL_DATA_REQ(message_p).offset = GTPU_HEADER_OVERHEAD_MAX;
GTPV1U_ENB_TUNNEL_DATA_REQ(message_p).rnti = ctxt_pP->rnti;
GTPV1U_ENB_TUNNEL_DATA_REQ(message_p).rab_id = rb_id + 4;
itti_send_msg_to_task(TASK_GTPV1_U, INSTANCE_DEFAULT, message_p);
itti_send_msg_to_task(TASK_VARIABLE, INSTANCE_DEFAULT, message_p);
packet_forwarded = TRUE;
}
} else {
......
......@@ -242,17 +242,18 @@ typedef struct pdcp_mbms_s {
* \note None
* @ingroup _pdcp
*/
boolean_t pdcp_data_req(
protocol_ctxt_t *ctxt_pP,
const srb_flag_t srb_flagP,
const rb_id_t rb_id,
const mui_t muiP,
const confirm_t confirmP, \
const confirm_t confirmP,
const sdu_size_t sdu_buffer_size,
unsigned char *const sdu_buffer,
const pdcp_transmission_mode_t mode,
const uint32_t *const sourceL2Id,
const uint32_t *const destinationL2Id
const uint32_t * sourceL2Id,
const uint32_t * destinationL2Id
);
/*! \fn boolean_t pdcp_data_ind(const protocol_ctxt_t* const, srb_flag_t, MBMS_flag_t, rb_id_t, sdu_size_t, mem_block_t*, boolean_t)
......
......@@ -78,8 +78,6 @@ extern int nas_sock_fd[MAX_MOBILES_PER_ENB];
extern int nas_sock_mbms_fd;
extern struct msghdr nas_msg_tx;
extern struct msghdr nas_msg_rx;
......
......@@ -71,6 +71,8 @@ rlc_mbms_id_t rlc_mbms_lcid2service_session_id_eNB[MAX_eNB][RLC_MAX_MBMS_
hash_table_t *rlc_coll_p __attribute__ ((aligned(32)));
logical_chan_id_t rlc_mbms_rbid2lcid_ue [MAX_MOBILES_PER_ENB][NB_RB_MBMS_MAX]; /*!< \brief Pairing logical channel identifier with radio bearer identifer. */
logical_chan_id_t rlc_mbms_rbid2lcid_eNB[MAX_eNB][NB_RB_MBMS_MAX]; /*!< \brief Pairing logical channel identifier with radio bearer identifer. */
//-----------------------------------------------------------------------------
void rlc_util_print_hex_octets(comp_name_t componentP, unsigned char *dataP, const signed long sizeP)
//-----------------------------------------------------------------------------
......
......@@ -34,6 +34,7 @@
/* from OAI */
#include "pdcp.h"
#include "LAYER2/nr_rlc/nr_rlc_oai_api.h"
#include <openair3/ocp-gtpu/gtp_itf.h>
#define TODO do { \
printf("%s:%d:%s: todo\n", __FILE__, __LINE__, __FUNCTION__); \
......@@ -450,7 +451,7 @@ static void deliver_sdu_drb(void *_ue, nr_pdcp_entity_t *entity,
LOG_D(PDCP, "%s() (drb %d) sending message to gtp size %d\n", __func__, rb_id, size);
//for (i = 0; i < size; i++) printf(" %2.2x", (unsigned char)buf[i]);
//printf("\n");
itti_send_msg_to_task(TASK_GTPV1_U, INSTANCE_DEFAULT, message_p);
itti_send_msg_to_task(TASK_VARIABLE, INSTANCE_DEFAULT, message_p);
}
}
......
......@@ -87,6 +87,7 @@
#include "pdcp.h"
#include "gtpv1u_eNB_task.h"
#include <openair3/ocp-gtpu/gtp_itf.h>
#include "intertask_interface.h"
......@@ -4968,7 +4969,7 @@ void rrc_eNB_handover_ue_context_release(
ue_context_p->ue_context.enb_gtp_ebi[e_rab] = 0;
}
itti_send_msg_to_task(TASK_GTPV1_U, ctxt_pP->module_id, msg_delete_tunnels_p);
itti_send_msg_to_task(TASK_VARIABLE, ctxt_pP->module_id, msg_delete_tunnels_p);
struct rrc_ue_s1ap_ids_s *rrc_ue_s1ap_ids = NULL;
rrc_ue_s1ap_ids = rrc_eNB_S1AP_get_ue_ids(RC.rrc[ctxt_pP->module_id], 0, eNB_ue_s1ap_id);
......
......@@ -40,6 +40,7 @@
# include "common/ran_context.h"
#include <openair3/ocp-gtpu/gtp_itf.h>
extern RAN_CONTEXT_t RC;
......@@ -92,7 +93,6 @@ rrc_eNB_process_GTPV1U_CREATE_TUNNEL_RESP(
}
}
//------------------------------------------------------------------------------
boolean_t
gtpv_data_req(
......@@ -113,7 +113,6 @@ gtpv_data_req(
return FALSE;
}
LOG_D(GTPU,"gtpv_data_req ue rnti %x sdu_sizeP %d rb id %ld", ctxt_pP->rnti, sdu_sizeP, rb_idP);
{
MessageDef *message_p;
// Uses a new buffer to avoid issue with PDCP buffer content that could be changed by PDCP (asynchronous message handling).
uint8_t *message_buffer;
......@@ -141,7 +140,7 @@ gtpv_data_req(
itti_send_msg_to_task (TASK_DATA_FORWARDING, ctxt_pP->instance, message_p);
return TRUE; // TODO should be changed to a CNF message later, currently RRC lite does not used the returned value anyway.
}else if(task_id == TASK_END_MARKER){
} else if (task_id == TASK_END_MARKER){
LOG_I(GTPU,"gtpv_data_req task_id = TASK_END_MARKER\n");
......@@ -165,12 +164,101 @@ gtpv_data_req(
itti_send_msg_to_task (TASK_END_MARKER, ctxt_pP->instance, message_p);
return TRUE; // TODO should be changed to a CNF message later, currently RRC lite does not used the returned value anyway.
}
LOG_E(RRC, "Impossible state\n");
return FALSE;
}
boolean_t gtpv_data_req_new (
protocol_ctxt_t *ctxt,
const srb_flag_t srb_flagP,
const rb_id_t rb_idP,
const mui_t muiP,
const confirm_t confirmP,
const sdu_size_t sdu_buffer_sizeP,
unsigned char *const sdu_buffer_pP,
const pdcp_transmission_mode_t modeP,
const uint32_t *sourceL2Id,
const uint32_t *destinationL2Id) {
int task;
if (sdu_buffer_sizeP==0)
task=TASK_END_MARKER;
else
task=TASK_DATA_FORWARDING;
struct rrc_eNB_ue_context_s *ue_context_p = rrc_eNB_get_ue_context(RC.rrc[ctxt->module_id], ctxt->rnti);
if(ue_context_p == NULL || ue_context_p->ue_context.handover_info == NULL ||
ue_context_p->ue_context.Status != RRC_HO_EXECUTION) {
LOG_E(RRC,"incoming GTP-U for X2 in non HO context\n");
return false;
}
/* in the source enb, UE in RRC_HO_EXECUTION mode */
// We have 2*2=4 cases (data or end marker) * (from slave, from EPC)
if (ue_context_p->ue_context.handover_info->state == HO_COMPLETE) {
LOG_I(GTPU, "source receive END MARKER\n");
/* set handover state */
//ue_context_p->ue_context.handover_info->state = HO_END_MARKER;
MessageDef *msg;
// Configure end marker
msg = itti_alloc_new_message(TASK_GTPV1_U, 0, GTPV1U_ENB_END_MARKER_REQ);
GTPV1U_ENB_END_MARKER_REQ(msg).buffer = itti_malloc(TASK_GTPV1_U, TASK_GTPV1_U, GTPU_HEADER_OVERHEAD_MAX + sdu_buffer_sizeP);
memcpy(&GTPV1U_ENB_END_MARKER_REQ(msg).buffer[GTPU_HEADER_OVERHEAD_MAX], sdu_buffer_pP, sdu_buffer_sizeP);
GTPV1U_ENB_END_MARKER_REQ(msg).length = sdu_buffer_sizeP;
GTPV1U_ENB_END_MARKER_REQ(msg).rnti = ctxt->rnti;
GTPV1U_ENB_END_MARKER_REQ(msg).rab_id = rb_idP;
GTPV1U_ENB_END_MARKER_REQ(msg).offset = GTPU_HEADER_OVERHEAD_MAX;
LOG_I(GTPU, "Send End Marker to GTPV1-U at frame %d and subframe %d \n", ctxt->frame,ctxt->subframe);
itti_send_msg_to_task(TASK_GTPV1_U, ENB_MODULE_ID_TO_INSTANCE(ctxt->module_id), msg);
return NW_GTPV1U_OK;
}
return TRUE;
/* target enb */
// We have 2*2=4 cases (data or end marker) * (from source, from EPC)
if (ue_context_p->ue_context.Status == RRC_RECONFIGURED) {
// It should come from remote eNB
// case end marker by EPC is not possible ?
if (task==TASK_END_MARKER) {
LOG_I(GTPU, "target end receive END MARKER\n");
// We close the HO, nothing to send to remote ?
ue_context_p->ue_context.handover_info->state = HO_END_MARKER;
gtpv1u_enb_delete_tunnel_req_t delete_tunnel_req;
memset(&delete_tunnel_req, 0, sizeof(delete_tunnel_req));
delete_tunnel_req.rnti = ctxt->rnti;
gtpv1u_delete_x2u_tunnel(ctxt->module_id, &delete_tunnel_req, GTPV1U_TARGET_ENB);
return true;
} else {
/* data packet */
LOG_I(GTPU, "Received a message data forwarding length %d\n", sdu_buffer_sizeP);
// Is it from remote ENB
// We have to push it to the UE ?
if(ue_context_p->ue_context.handover_info->state != HO_COMPLETE) {
int result = pdcp_data_req(
ctxt,
srb_flagP,
rb_idP,
muiP, // mui
confirmP, // confirm
sdu_buffer_sizeP,
sdu_buffer_pP,
modeP,
sourceL2Id,
destinationL2Id
);
ue_context_p->ue_context.handover_info->forwarding_state = FORWARDING_NO_EMPTY;
return result;
} else { /* It is from from epc message */
/* in the source enb, UE in RRC_HO_EXECUTION mode */
MessageDef *msg;
// ?????
return true;
}
}
}
LOG_E(RRC,"This function should return before the end\n");
return false;
}
//#endif
void rrc_eNB_send_GTPV1U_ENB_DELETE_TUNNEL_REQ(
module_id_t enb_mod_idP,
......@@ -181,21 +269,16 @@ void rrc_eNB_send_GTPV1U_ENB_DELETE_TUNNEL_REQ(
LOG_W(RRC, "[eNB] In %s: invalid UE\n", __func__);
return;
}
gtpv1u_enb_delete_tunnel_req_t tmp={0};
MSC_LOG_TX_MESSAGE(MSC_RRC_ENB, MSC_GTPU_ENB, NULL, 0,
"0 GTPV1U_ENB_DELETE_TUNNEL_REQ rnti %x ",
ue_context_pP->ue_context.eNB_ue_s1ap_id);
MessageDef *msg = itti_alloc_new_message(TASK_RRC_ENB, 0, GTPV1U_ENB_DELETE_TUNNEL_REQ);
memset(&GTPV1U_ENB_DELETE_TUNNEL_REQ(msg), 0, sizeof(GTPV1U_ENB_DELETE_TUNNEL_REQ(msg)));
GTPV1U_ENB_DELETE_TUNNEL_REQ(msg).rnti = ue_context_pP->ue_context.rnti;
GTPV1U_ENB_DELETE_TUNNEL_REQ(msg).from_gnb = 0;
GTPV1U_ENB_DELETE_TUNNEL_REQ(msg).num_erab = ue_context_pP->ue_context.nb_of_e_rabs;
tmp.rnti = ue_context_pP->ue_context.rnti;
tmp.from_gnb = 0;
tmp.num_erab = ue_context_pP->ue_context.nb_of_e_rabs;
for (int e_rab = 0; e_rab < ue_context_pP->ue_context.nb_of_e_rabs; e_rab++) {
const rb_id_t gtp_ebi = ue_context_pP->ue_context.enb_gtp_ebi[e_rab];
GTPV1U_ENB_DELETE_TUNNEL_REQ(msg).eps_bearer_id[e_rab] = gtp_ebi;
tmp.eps_bearer_id[e_rab] = gtp_ebi;
}
itti_send_msg_to_task(TASK_GTPV1_U, ENB_MODULE_ID_TO_INSTANCE(enb_mod_idP), msg);
gtpv1u_delete_s1u_tunnel(enb_mod_idP,&tmp);
}
......@@ -48,11 +48,12 @@
#include "pdcp_primitives.h"
#include "UTIL/OSA/osa_defs.h"
#include "msc.h"
#include <common/utils/msc/msc.h>
#include "LTE_UERadioAccessCapabilityInformation.h"
#include "gtpv1u_eNB_task.h"
#include <openair3/ocp-gtpu/gtp_itf.h>
#include "RRC/LTE/rrc_eNB_GTPV1U.h"
#include "TLVDecoder.h"
......@@ -1787,7 +1788,7 @@ int rrc_eNB_process_S1AP_E_RAB_RELEASE_COMMAND(MessageDef *msg_p, const char *ms
}
}
itti_send_msg_to_task(TASK_GTPV1_U, instance, msg_delete_tunnels_p);
itti_send_msg_to_task(TASK_VARIABLE, instance, msg_delete_tunnels_p);
//S1AP_E_RAB_RELEASE_RESPONSE
rrc_eNB_send_S1AP_E_RAB_RELEASE_RESPONSE(&ctxt, ue_context_p, xid);
}
......
......@@ -39,6 +39,7 @@
#include "openair2/RRC/LTE/rrc_eNB_GTPV1U.h"
#include "executables/softmodem-common.h"
#include <openair2/RRC/NR/rrc_gNB_UE_context.h>
#include <openair3/ocp-gtpu/gtp_itf.h>
#include "UTIL/OSA/osa_defs.h"
extern boolean_t nr_rrc_pdcp_config_asn1_req(
......@@ -425,7 +426,7 @@ void rrc_remove_nsa_user(gNB_RRC_INST *rrc, int rnti) {
ue_context->ue_context.gnb_gtp_ebi[e_rab] = 0;
}
itti_send_msg_to_task(TASK_GTPV1_U, rrc->module_id, msg_delete_tunnels_p);
itti_send_msg_to_task(TASK_VARIABLE, rrc->module_id, msg_delete_tunnels_p);
/* remove context */
rrc_gNB_remove_ue_context(&ctxt, rrc, ue_context);
......
......@@ -145,7 +145,6 @@ extern void *udp_eNB_task(void *args_p);
int transmission_mode=1;
int emulate_rf = 0;
int numerology = 0;
int usrp_tx_thread = 0;
double cpuf;
......
#include <map>
using namespace std;
#ifdef __cplusplus
extern "C" {
#endif
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/types.h>
#include <netdb.h>
#include <openair2/COMMON/platform_types.h>
#include <openair3/UTILS/conversions.h>
#include "common/utils/LOG/log.h"
#include <common/utils/ocp_itti/intertask_interface.h>
#include <openair2/COMMON/gtpv1_u_messages_types.h>
#include <openair3/ocp-gtpu/gtp_itf.h>
#include <openair2/LAYER2/PDCP_v10.1.0/pdcp.h>
//#include <openair1/PHY/phy_extern.h>
#pragma pack(1)
typedef struct Gtpv1uMsgHeader {
uint8_t PN:1;
uint8_t S:1;
uint8_t E:1;
uint8_t spare:1;
uint8_t PT:1;
uint8_t version:3;
uint8_t msgType;
uint16_t msgLength;
teid_t teid;
} __attribute__((packed)) Gtpv1uMsgHeaderT;
#pragma pack()
// TS 29.060, table 7.1 defines the possible message types
// here are all the possible messages (3GPP R16)
#define GTP_ECHO_REQ (1)
#define GTP_ECHO_RSP (2)
#define GTP_ERROR_INDICATION (26)
#define GTP_SUPPORTED_EXTENSION_HEADER_INDICATION (31)
#define GTP_END_MARKER (254)
#define GTP_GPDU (255)
typedef struct ocp_gtpv1u_bearer_s {
/* TEID used in dl and ul */
teid_t teid_incoming; ///< eNB TEID
teid_t teid_outgoing; ///< Remote TEID
in_addr_t outgoing_ip_addr;
struct in6_addr outgoing_ip6_addr;
tcp_udp_port_t outgoing_port;
uint16_t seqNum;
uint8_t npduNum;
} ocp_gtpv1u_bearer_t;
typedef struct {
map<int, ocp_gtpv1u_bearer_t> bearers;
} teidData_t;
typedef struct {
rnti_t rnti;
ebi_t rb_id;
gtpCallback callBack;
} rntiData_t;
class gtpEndPoint {
public:
openAddr_t addr;
uint8_t foundAddr[20];
int foundAddrLen;
int ipVersion;
map<int,teidData_t> ue2te_mapping;
map<int,rntiData_t> te2ue_mapping;
};
class gtpEndPoints {
public:
pthread_mutex_t gtp_lock=PTHREAD_MUTEX_INITIALIZER;
// the instance id will be the Linux socket handler, as this is uniq
map<int, gtpEndPoint> instances;
};
gtpEndPoints globGtp;
// note TEid 0 is reserved for specific usage: echo req/resp, error and supported extensions
static uint32_t gtpv1uNewTeid(void) {
#ifdef GTPV1U_LINEAR_TEID_ALLOCATION
g_gtpv1u_teid = g_gtpv1u_teid + 1;
return g_gtpv1u_teid;
#else
return random() + random() % (RAND_MAX - 1) + 1;
#endif
}
int legacyInstanceMapping=0;
#define compatInst(a) ((a)==0 || (a)==INSTANCE_DEFAULT?legacyInstanceMapping:a)
#define GTPV1U_HEADER_SIZE (8)
static int gtpv1uCreateAndSendMsg(int h, uint32_t peerIp, uint16_t peerPort, teid_t teid, uint8_t *Msg,int msgLen,
bool seqNumFlag, bool npduNumFlag, bool extHdrFlag, int seqNum, int npduNum, int extHdrType) {
AssertFatal(extHdrFlag==false,"Not developped");
int headerAdditional=0;
if ( seqNumFlag || npduNumFlag || extHdrFlag)
headerAdditional=4;
uint8_t *buffer;
int fullSize=GTPV1U_HEADER_SIZE+headerAdditional+msgLen;
AssertFatal((buffer=(uint8_t *) malloc(fullSize)) != NULL, "");
Gtpv1uMsgHeaderT *msgHdr = (Gtpv1uMsgHeaderT *)buffer ;
// N should be 0 for us (it was used only in 2G and 3G)
msgHdr->PN=npduNumFlag;
msgHdr->S=seqNumFlag;
msgHdr->E=extHdrFlag;
msgHdr->spare=0;
//PT=0 is for GTP' TS 32.295 (charging)
msgHdr->PT=1;
msgHdr->version=1;
msgHdr->msgType=GTP_GPDU;
msgHdr->msgLength=htons(msgLen);
if ( seqNumFlag || extHdrFlag || npduNumFlag)
msgHdr->msgLength+=4;
msgHdr->teid=htonl(teid);
if(seqNumFlag || extHdrFlag || npduNumFlag) {
*((uint16_t *) (buffer+8)) = seqNumFlag ? htons(seqNum) : 0x0000;
*((uint8_t *) (buffer+10)) = npduNumFlag ? htons(npduNum) : 0x00;
*((uint8_t *) (buffer+11)) = extHdrFlag ? htons(extHdrType) : 0x00;
}
memcpy(buffer+GTPV1U_HEADER_SIZE+headerAdditional, Msg, msgLen);
// Fix me: add IPv6 support, using flag ipVersion
static struct sockaddr_in to= {0};
to.sin_family = AF_INET;
to.sin_port = htons(peerPort);
to.sin_addr.s_addr = peerIp ;
LOG_D(GTPU,"sending packet size: %d to %s\n",fullSize, inet_ntoa(to.sin_addr) );
if (sendto(h, (void *)buffer, (size_t)fullSize, 0,(struct sockaddr *)&to, sizeof(to) ) != fullSize ) {
LOG_E(GTPU,
"[SD %d] Failed to send data to " IPV4_ADDR " on port %d, buffer size %u\n",
h, IPV4_ADDR_FORMAT(peerIp), peerPort, fullSize);
free(buffer);
return GTPNOK;
}
free(buffer);
return !GTPNOK;
}
static void gtpv1uSend(instance_t instance, gtpv1u_enb_tunnel_data_req_t *req, bool seqNumFlag, bool npduNumFlag) {
uint8_t *buffer=req->buffer+req->offset;
size_t length=req->length;
uint64_t rnti=req->rnti;
int rab_id=req->rab_id;
pthread_mutex_lock(&globGtp.gtp_lock);
auto inst=&globGtp.instances[compatInst(instance)];
auto ptrRnti=inst->ue2te_mapping.find(rnti);
if ( ptrRnti==inst->ue2te_mapping.end() ) {
LOG_E(GTPU, "gtpv1uSend failed: while getting ue rnti %lx in hashtable ue_mapping\n", rnti);
pthread_mutex_unlock(&globGtp.gtp_lock);
return;
}
auto ptr=ptrRnti->second.bearers;
if ( ptr.find(rab_id) == ptr.end() ) {
LOG_E(GTPU,"sending a packet to a non existant RNTI:RAB: %lx/%x\n", rnti, rab_id);
pthread_mutex_unlock(&globGtp.gtp_lock);
return;
} else
LOG_D(GTPU,"sending a packet to RNTI:RAB:teid %lx/%x/%x, len %lu, oldseq %d, oldnum %d\n",
rnti, rab_id,ptr[rab_id].teid_outgoing,length, ptr[rab_id].seqNum,ptr[rab_id].npduNum );
if(seqNumFlag)
ptr[rab_id].seqNum++;
if(npduNumFlag)
ptr[rab_id].npduNum++;
// We will release the lock, let's copy data before
ocp_gtpv1u_bearer_t tmp=ptr[rab_id];
pthread_mutex_unlock(&globGtp.gtp_lock);
gtpv1uCreateAndSendMsg(compatInst(instance),
tmp.outgoing_ip_addr,
tmp.outgoing_port,
tmp.teid_outgoing,
buffer, length, seqNumFlag, npduNumFlag, false, tmp.seqNum, tmp.npduNum, 0) ;
}
static void gtpv1uEndTunnel(instance_t instance, gtpv1u_enb_tunnel_data_req_t *req) {
uint64_t rnti=req->rnti;
int rab_id=req->rab_id;
pthread_mutex_lock(&globGtp.gtp_lock);
auto inst=&globGtp.instances[compatInst(instance)];
auto ptrRnti=inst->ue2te_mapping.find(rnti);
if ( ptrRnti==inst->ue2te_mapping.end() ) {
LOG_E(GTPU, "gtpv1uSend failed: while getting ue rnti %lx in hashtable ue_mapping\n", rnti);
pthread_mutex_unlock(&globGtp.gtp_lock);
return;
}
auto ptr=ptrRnti->second.bearers;
if ( ptr.find(rab_id) == ptr.end() ) {
LOG_E(GTPU,"sending a packet to a non existant RNTI:RAB: %lx/%x\n", rnti, rab_id);
pthread_mutex_unlock(&globGtp.gtp_lock);
return;
} else
LOG_D(GTPU,"sending a end packet packet to RNTI:RAB:teid %lx/%x/%x\n",
rnti, rab_id,ptr[rab_id].teid_outgoing);
ocp_gtpv1u_bearer_t tmp=ptr[rab_id];
pthread_mutex_unlock(&globGtp.gtp_lock);
Gtpv1uMsgHeaderT msgHdr;
// N should be 0 for us (it was used only in 2G and 3G)
msgHdr.PN=0;
msgHdr.S=0;
msgHdr.E=0;
msgHdr.spare=0;
//PT=0 is for GTP' TS 32.295 (charging)
msgHdr.PT=1;
msgHdr.version=1;
msgHdr.msgType=GTP_END_MARKER;
msgHdr.msgLength=htons(0);
msgHdr.teid=htonl(tmp.teid_outgoing);
// Fix me: add IPv6 support, using flag ipVersion
static struct sockaddr_in to= {0};
to.sin_family = AF_INET;
to.sin_port = htons(tmp.outgoing_port);
to.sin_addr.s_addr = tmp.outgoing_ip_addr;
LOG_D(GTPU,"sending end packet to %s\n", inet_ntoa(to.sin_addr) );
if (sendto(compatInst(instance), (void *)&msgHdr, sizeof(msgHdr), 0,(struct sockaddr *)&to, sizeof(to) ) != sizeof(msgHdr)) {
LOG_E(GTPU,
"[SD %ld] Failed to send data to " IPV4_ADDR " on port %d, buffer size %lu\n",
compatInst(instance), IPV4_ADDR_FORMAT(tmp.outgoing_ip_addr), tmp.outgoing_port, sizeof(msgHdr));
}
}
static int udpServerSocket(openAddr_s addr) {
LOG_I(GTPU, "Initializing UDP for local address %s with port %s\n", addr.originHost, addr.originService);
int status;
struct addrinfo hints= {0}, *servinfo, *p;
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_DGRAM;
hints.ai_flags = AI_PASSIVE;
if ((status = getaddrinfo(addr.originHost, addr.originService, &hints, &servinfo)) != 0) {
LOG_E(GTPU,"getaddrinfo error: %s\n", gai_strerror(status));
return -1;
}
int sockfd=-1;
// loop through all the results and bind to the first we can
for(p = servinfo; p != NULL; p = p->ai_next) {
if ((sockfd = socket(p->ai_family, p->ai_socktype,
p->ai_protocol)) == -1) {
LOG_W(GTPU,"socket: %s\n", strerror(errno));
continue;
}
if (bind(sockfd, p->ai_addr, p->ai_addrlen) == -1) {
close(sockfd);
LOG_W(GTPU,"bind: %s\n", strerror(errno));
continue;
} else {
// We create the gtp instance on the socket
globGtp.instances[sockfd].addr=addr;
if (p->ai_family == AF_INET) {
struct sockaddr_in *ipv4=(struct sockaddr_in *)p->ai_addr;
memcpy(globGtp.instances[sockfd].foundAddr,
&ipv4->sin_addr.s_addr, sizeof(ipv4->sin_addr.s_addr));
globGtp.instances[sockfd].foundAddrLen=sizeof(ipv4->sin_addr.s_addr);
globGtp.instances[sockfd].ipVersion=4;
break;
} else if (p->ai_family == AF_INET6) {
LOG_W(GTPU,"Local address is IP v6\n");
struct sockaddr_in6 *ipv6=(struct sockaddr_in6 *)p->ai_addr;
memcpy(globGtp.instances[sockfd].foundAddr,
&ipv6->sin6_addr.s6_addr, sizeof(ipv6->sin6_addr.s6_addr));
globGtp.instances[sockfd].foundAddrLen=sizeof(ipv6->sin6_addr.s6_addr);
globGtp.instances[sockfd].ipVersion=6;
} else
AssertFatal(false,"Local address is not IPv4 or IPv6");
}
break; // if we get here, we must have connected successfully
}
if (p == NULL) {
// looped off the end of the list with no successful bind
LOG_E(GTPU,"failed to bind socket: %s %s \n", addr.originHost, addr.originService);
return -1;
}
freeaddrinfo(servinfo); // all done with this structure
if (strlen(addr.destinationHost)>1) {
struct addrinfo hints;
memset(&hints,0,sizeof(hints));
hints.ai_family=AF_UNSPEC;
hints.ai_socktype=SOCK_DGRAM;
hints.ai_protocol=0;
hints.ai_flags=AI_PASSIVE|AI_ADDRCONFIG;
struct addrinfo *res=0;
int err=getaddrinfo(addr.destinationHost,addr.destinationService,&hints,&res);
if (err==0) {
for(p = res; p != NULL; p = p->ai_next) {
if ((err=connect(sockfd, p->ai_addr, p->ai_addrlen))==0)
break;
}
}
if (err)
LOG_E(GTPU,"Can't filter remote host: %s, %s\n", addr.destinationHost,addr.destinationService);
}
int sendbuff = 1000*1000*10;
AssertFatal(0==setsockopt(sockfd, SOL_SOCKET, SO_SNDBUF, &sendbuff, sizeof(sendbuff)),"");
LOG_D(GTPU,"Created listener for paquets to: %s:%s, send buffer size: %d\n", addr.originHost, addr.originService,sendbuff);
return sockfd;
}
instance_t ocp_gtpv1Init(openAddr_t context) {
pthread_mutex_lock(&globGtp.gtp_lock);
int id=udpServerSocket(context);
if (id>=0) {
itti_subscribe_event_fd(OCP_GTPV1_U, id);
} else
LOG_E(GTPU,"can't create GTP-U instance\n");
pthread_mutex_unlock(&globGtp.gtp_lock);
return id;
}
teid_t newGtpuCreateTunnel(instance_t instance, rnti_t rnti, int bearer_id, teid_t teid, transport_layer_addr_t remoteAddr, int port, gtpCallback callBack) {
pthread_mutex_lock(&globGtp.gtp_lock);
auto inst=&globGtp.instances[instance];
auto it=inst->ue2te_mapping.find(rnti);
if ( it != inst->ue2te_mapping.end() ) {
LOG_W(GTPU,"Create a config for a already existing GTP tunnel (rnti %x)\n", rnti);
inst->ue2te_mapping.erase(it);
}
uint32_t s1u_teid=gtpv1uNewTeid();
while ( inst->te2ue_mapping.find(s1u_teid) != inst->te2ue_mapping.end() ) {
LOG_W(GTPU, "generated a random Teid that exists, re-generating (%u)\n",s1u_teid);
s1u_teid=gtpv1uNewTeid();
};
inst->te2ue_mapping[s1u_teid].rnti=rnti;
inst->te2ue_mapping[s1u_teid].rb_id= teid;
inst->te2ue_mapping[s1u_teid].callBack=callBack;
auto tmp=&inst->ue2te_mapping[rnti].bearers[bearer_id];
int addrs_length_in_bytes = remoteAddr.length / 8;
switch (addrs_length_in_bytes) {
case 4:
memcpy(&tmp->outgoing_ip_addr,remoteAddr.buffer,4);
break;
case 16:
memcpy(tmp->outgoing_ip6_addr.s6_addr,remoteAddr.buffer,
16);
break;
case 20:
memcpy(&tmp->outgoing_ip_addr,remoteAddr.buffer,4);
memcpy(&tmp->outgoing_ip6_addr.s6_addr,
remoteAddr.buffer+4,
16);
default:
AssertFatal(false, "SGW Address size impossible");
}
tmp->teid_incoming = s1u_teid;
tmp->outgoing_port=port;
tmp->teid_outgoing= teid;
pthread_mutex_unlock(&globGtp.gtp_lock);
return s1u_teid;
}
int ocp_gtpv1u_create_s1u_tunnel(instance_t instance,
const gtpv1u_enb_create_tunnel_req_t *create_tunnel_req,
gtpv1u_enb_create_tunnel_resp_t *create_tunnel_resp) {
LOG_D(GTPU, "Start create tunnels for RNTI %x, num_tunnels %d, sgw_S1u_teid %d\n",
create_tunnel_req->rnti,
create_tunnel_req->num_tunnels,
create_tunnel_req->sgw_S1u_teid[0]);
for (int i = 0; i < create_tunnel_req->num_tunnels; i++) {
teid_t teid=newGtpuCreateTunnel(compatInst(instance), create_tunnel_req->rnti,
create_tunnel_req->eps_bearer_id[i],
create_tunnel_req->sgw_S1u_teid[i],
create_tunnel_req->sgw_addr[i], 2152,
pdcp_data_req);
create_tunnel_resp->status=0;
create_tunnel_resp->rnti=create_tunnel_req->rnti;
create_tunnel_resp->num_tunnels=create_tunnel_req->num_tunnels;
create_tunnel_resp->enb_S1u_teid[i]=teid;
create_tunnel_resp->eps_bearer_id[i] = create_tunnel_req->eps_bearer_id[i];
memcpy(create_tunnel_resp->enb_addr.buffer,globGtp.instances[compatInst(instance)].foundAddr,
globGtp.instances[compatInst(instance)].foundAddrLen);
create_tunnel_resp->enb_addr.length= globGtp.instances[compatInst(instance)].foundAddrLen;
}
return !GTPNOK;
}
int ocp_gtpv1u_update_s1u_tunnel(
const instance_t instance,
const gtpv1u_enb_create_tunnel_req_t *const create_tunnel_req,
const rnti_t prior_rnti
) {
LOG_D(GTPU, "Start update tunnels for old RNTI %x, new RNTI %x, num_tunnels %d, sgw_S1u_teid %d, eps_bearer_id %d\n",
prior_rnti,
create_tunnel_req->rnti,
create_tunnel_req->num_tunnels,
create_tunnel_req->sgw_S1u_teid[0],
create_tunnel_req->eps_bearer_id[0]);
pthread_mutex_lock(&globGtp.gtp_lock);
auto inst=&globGtp.instances[compatInst(instance)];
if ( inst->ue2te_mapping.find(create_tunnel_req->rnti) == inst->ue2te_mapping.end() ) {
LOG_E(GTPU,"Update not already existing tunnel (new rnti %x, old rnti %x)\n", create_tunnel_req->rnti, prior_rnti);
}
auto it=inst->ue2te_mapping.find(prior_rnti);
if ( it != inst->ue2te_mapping.end() ) {
LOG_W(GTPU,"Update a not existing tunnel, start create the new one (new rnti %x, old rnti %x)\n", create_tunnel_req->rnti, prior_rnti);
pthread_mutex_unlock(&globGtp.gtp_lock);
gtpv1u_enb_create_tunnel_resp_t tmp;
(void)ocp_gtpv1u_create_s1u_tunnel(instance, create_tunnel_req, &tmp);
return 0;
}
inst->ue2te_mapping[create_tunnel_req->rnti]=it->second;
inst->ue2te_mapping.erase(it);
pthread_mutex_unlock(&globGtp.gtp_lock);
return 0;
}
int ocp_gtpv1u_create_x2u_tunnel(
const instance_t instanceP,
const gtpv1u_enb_create_x2u_tunnel_req_t *const create_tunnel_req_pP,
gtpv1u_enb_create_x2u_tunnel_resp_t *const create_tunnel_resp_pP) {
AssertFatal( false, "to be developped\n");
}
int newGtpuDeleteTunnel(instance_t instance, rnti_t rnti) {
LOG_D(GTPU, "Start delete tunnels for RNTI %x\n",
rnti);
pthread_mutex_lock(&globGtp.gtp_lock);
auto inst=&globGtp.instances[compatInst(instance)];
auto it=inst->ue2te_mapping.find(rnti);
if ( it == inst->ue2te_mapping.end() ) {
LOG_W(GTPU,"Delete a non existing GTP tunnel\n");
pthread_mutex_unlock(&globGtp.gtp_lock);
return -1;
}
for (auto j=it->second.bearers.begin();
j!=it->second.bearers.end();
++j)
inst->te2ue_mapping.erase(j->second.teid_incoming);
inst->ue2te_mapping.erase(it);
pthread_mutex_unlock(&globGtp.gtp_lock);
return !GTPNOK;
}
// Legacy delete tunnel finish by deleting all the rnti
// so the list of bearer provided is only a design bug
int ocp_gtpv1u_delete_s1u_tunnel( const instance_t instance,
const gtpv1u_enb_delete_tunnel_req_t *const req_pP) {
return newGtpuDeleteTunnel(instance, req_pP->rnti);
}
static int Gtpv1uHandleEchoReq(int h,
uint8_t *msgBuf,
uint32_t msgBufLen,
uint16_t peerPort,
uint32_t peerIp) {
LOG_E(GTPU,"to be dev\n");
int rc = GTPNOK;
return rc;
}
static int Gtpv1uHandleError(int h,
uint8_t *msgBuf,
uint32_t msgBufLen,
uint16_t peerPort,
uint32_t peerIp) {
LOG_E(GTPU,"to be dev\n");
int rc = GTPNOK;
return rc;
}
static int Gtpv1uHandleSupportedExt(int h,
uint8_t *msgBuf,
uint32_t msgBufLen,
uint16_t peerPort,
uint32_t peerIp) {
LOG_E(GTPU,"to be dev\n");
int rc = GTPNOK;
return rc;
}
// When end marker arrives, we notify the client with buffer size = 0
// The client will likely call "delete tunnel"
// nevertheless we don't take the initiative
static int Gtpv1uHandleEndMarker(int h,
uint8_t *msgBuf,
uint32_t msgBufLen,
uint16_t peerPort,
uint32_t peerIp) {
Gtpv1uMsgHeaderT *msgHdr = (Gtpv1uMsgHeaderT *) msgBuf;
if ( msgHdr->version != 1 || msgHdr->PT != 1 ) {
LOG_E(GTPU, "Received a packet that is not GTP header\n");
return GTPNOK;
}
pthread_mutex_lock(&globGtp.gtp_lock);
// the socket Linux file handler is the instance id
auto inst=&globGtp.instances[h];
auto tunnel=inst->te2ue_mapping.find(ntohl(msgHdr->teid));
if ( tunnel == inst->te2ue_mapping.end() ) {
LOG_E(GTPU,"Received a incoming packet on unknown teid (%d) Dropping!\n", msgHdr->teid);
pthread_mutex_unlock(&globGtp.gtp_lock);
return GTPNOK;
}
// This context is not good for gtp
// frame, ... has no meaning
// manyother attributes may come from create tunnel
protocol_ctxt_t ctxt;
ctxt.module_id = 0;
ctxt.enb_flag = 1;
ctxt.instance = inst->addr.originInstance;
ctxt.rnti = tunnel->second.rnti;
ctxt.frame = 0;
ctxt.subframe = 0;
ctxt.eNB_index = 0;
ctxt.configured = 0;
ctxt.brOption = 0;
const srb_flag_t srb_flag=SRB_FLAG_NO;
const rb_id_t rb_id=tunnel->second.rb_id;
const mui_t mui=RLC_MUI_UNDEFINED;
const confirm_t confirm=RLC_SDU_CONFIRM_NO;
const pdcp_transmission_mode_t mode=PDCP_TRANSMISSION_MODE_DATA;
const uint32_t sourceL2Id=0;
const uint32_t destinationL2Id=0;
pthread_mutex_unlock(&globGtp.gtp_lock);
if ( !tunnel->second.callBack(&ctxt,
srb_flag,
rb_id,
mui,
confirm,
0,
NULL,
mode,
&sourceL2Id,
&destinationL2Id) )
LOG_E(GTPU,"down layer refused incoming packet\n");
LOG_D(GTPU,"Received END marker packet for: teid:%x\n", ntohl(msgHdr->teid));
return !GTPNOK;
}
static int Gtpv1uHandleGpdu(int h,
uint8_t *msgBuf,
uint32_t msgBufLen,
uint16_t peerPort,
uint32_t peerIp) {
Gtpv1uMsgHeaderT *msgHdr = (Gtpv1uMsgHeaderT *) msgBuf;
if ( msgHdr->version != 1 || msgHdr->PT != 1 ) {
LOG_E(GTPU, "Received a packet that is not GTP header\n");
return GTPNOK;
}
pthread_mutex_lock(&globGtp.gtp_lock);
// the socket Linux file handler is the instance id
auto inst=&globGtp.instances[h];
auto tunnel=inst->te2ue_mapping.find(ntohl(msgHdr->teid));
if ( tunnel == inst->te2ue_mapping.end() ) {
LOG_E(GTPU,"Received a incoming packet on unknown teid (%d) Dropping!\n", msgHdr->teid);
pthread_mutex_unlock(&globGtp.gtp_lock);
return GTPNOK;
}
int offset=8;
if( msgHdr->E || msgHdr->S ||msgHdr->PN)
offset+=4;
// This context is not good for gtp
// frame, ... has no meaning
// manyother attributes may come from create tunnel
protocol_ctxt_t ctxt;
ctxt.module_id = 0;
ctxt.enb_flag = 1;
ctxt.instance = inst->addr.originInstance;
ctxt.rnti = tunnel->second.rnti;
ctxt.frame = 0;
ctxt.subframe = 0;
ctxt.eNB_index = 0;
ctxt.configured = 0;
ctxt.brOption = 0;
const srb_flag_t srb_flag=SRB_FLAG_NO;
const rb_id_t rb_id=tunnel->second.rb_id;
const mui_t mui=RLC_MUI_UNDEFINED;
const confirm_t confirm=RLC_SDU_CONFIRM_NO;
const sdu_size_t sdu_buffer_size=msgBufLen-offset;
unsigned char *const sdu_buffer=msgBuf+offset;
const pdcp_transmission_mode_t mode=PDCP_TRANSMISSION_MODE_DATA;
const uint32_t sourceL2Id=0;
const uint32_t destinationL2Id=0;
pthread_mutex_unlock(&globGtp.gtp_lock);
if ( !tunnel->second.callBack(&ctxt,
srb_flag,
rb_id,
mui,
confirm,
sdu_buffer_size,
sdu_buffer,
mode,
&sourceL2Id,
&destinationL2Id) )
LOG_E(GTPU,"down layer refused incoming packet\n");
LOG_D(GTPU,"Received a %d bytes packet for: teid:%x\n",
msgBufLen-offset,
ntohl(msgHdr->teid));
return !GTPNOK;
}
void gtpv1uReceiver(int h) {
uint8_t udpData[65536];
int udpDataLen;
socklen_t from_len;
struct sockaddr_in addr;
from_len = (socklen_t)sizeof(struct sockaddr_in);
if ((udpDataLen = recvfrom(h, udpData, sizeof(udpData), 0,
(struct sockaddr *)&addr, &from_len)) < 0) {
LOG_E(GTPU, "Recvfrom failed on %d (%s)\n", h, strerror(errno));
return;
} else if (udpDataLen == 0) {
LOG_W(GTPU, "Recvfrom returned 0\n");
return;
} else {
uint8_t msgType = *((uint8_t *)(udpData + 1));
LOG_D(GTPU, "Received GTP data, msg type: %x\n", msgType);
switch(msgType) {
case GTP_ECHO_RSP:
break;
case GTP_ECHO_REQ:
Gtpv1uHandleEchoReq( h, udpData, udpDataLen, htons(addr.sin_port), addr.sin_addr.s_addr);
break;
case GTP_ERROR_INDICATION:
Gtpv1uHandleError( h, udpData, udpDataLen, htons(addr.sin_port), addr.sin_addr.s_addr);
break;
case GTP_SUPPORTED_EXTENSION_HEADER_INDICATION:
Gtpv1uHandleSupportedExt( h, udpData, udpDataLen, htons(addr.sin_port), addr.sin_addr.s_addr);
break;
case GTP_END_MARKER:
Gtpv1uHandleEndMarker( h, udpData, udpDataLen, htons(addr.sin_port), addr.sin_addr.s_addr);
break;
case GTP_GPDU:
Gtpv1uHandleGpdu( h, udpData, udpDataLen, htons(addr.sin_port), addr.sin_addr.s_addr);
break;
default:
LOG_E(GTPU, "Received a GTP packet of unknown type: %d\n",msgType);
break;
}
}
}
#include <openair2/ENB_APP/enb_paramdef.h>
void *ocp_gtpv1uTask(void *args) {
while(1) {
/* Trying to fetch a message from the message queue.
If the queue is empty, this function will block till a
message is sent to the task.
*/
MessageDef *message_p = NULL;
itti_receive_msg(OCP_GTPV1_U, &message_p);
if (message_p != NULL ) {
openAddr_t addr= {0};
switch (ITTI_MSG_ID(message_p)) {
// DATA TO BE SENT TO UDP
case GTPV1U_ENB_TUNNEL_DATA_REQ: {
gtpv1uSend(compatInst(ITTI_MSG_DESTINATION_INSTANCE(message_p)),
&GTPV1U_ENB_TUNNEL_DATA_REQ(message_p), false, false);
itti_free(OCP_GTPV1_U, GTPV1U_ENB_TUNNEL_DATA_REQ(message_p).buffer);
}
break;
case TERMINATE_MESSAGE:
break;
case TIMER_HAS_EXPIRED:
LOG_E(GTPU, "Received unexpected timer expired (no need of timers in this version) %s\n", ITTI_MSG_NAME(message_p));
break;
case GTPV1U_ENB_END_MARKER_REQ:
gtpv1uEndTunnel(compatInst(ITTI_MSG_DESTINATION_INSTANCE(message_p)),
&GTPV1U_ENB_TUNNEL_DATA_REQ(message_p));
itti_free(OCP_GTPV1_U, GTPV1U_ENB_TUNNEL_DATA_REQ(message_p).buffer);
break;
case GTPV1U_ENB_DATA_FORWARDING_REQ:
case GTPV1U_ENB_DATA_FORWARDING_IND:
case GTPV1U_ENB_END_MARKER_IND:
LOG_E(GTPU, "to be developped %s\n", ITTI_MSG_NAME(message_p));
abort();
break;
case GTPV1U_ENB_S1_REQ:
// to be dev: should be removed, to use API
strcpy(addr.originHost, GTPV1U_ENB_S1_REQ(message_p).addrStr);
strcpy(addr.originService, GTPV1U_ENB_S1_REQ(message_p).portStr);
AssertFatal((legacyInstanceMapping=ocp_gtpv1Init(addr))!=0,"Instance 0 reserved for legacy\n");
break;
default:
LOG_E(GTPU, "Received unexpected message %s\n", ITTI_MSG_NAME(message_p));
abort();
break;
}
AssertFatal(EXIT_SUCCESS==itti_free(OCP_GTPV1_U, message_p), "Failed to free memory!\n");
}
struct epoll_event *events;
int nb_events = itti_get_events(OCP_GTPV1_U, &events);
for (int i = 0; i < nb_events; i++)
if ((events[i].events&EPOLLIN))
gtpv1uReceiver(events[i].data.fd);
}
return NULL;
}
#ifdef __cplusplus
}
#endif
#ifndef __GTPUNEW_ITF_H__
#define __GTPUNEW_ITF_H__
#define GTPNOK -1
# define GTPU_HEADER_OVERHEAD_MAX 64
#ifdef __cplusplus
extern "C" {
#endif
#include <openair3/GTPV1-U/gtpv1u_eNB_defs.h>
#if defined(NEW_GTPU)
#define gtpv1u_create_s1u_tunnel ocp_gtpv1u_create_s1u_tunnel
#define gtpv1u_update_s1u_tunnel ocp_gtpv1u_update_s1u_tunnel
#define gtpv1u_delete_s1u_tunnel ocp_gtpv1u_delete_s1u_tunnel
#define gtpv1u_create_x2u_tunnel ocp_gtpv1u_create_x2u_tunnel
#define gtpv1u_eNB_task ocp_gtpv1uTask
#define gtpv1u_gNB_task ocp_gtpv1uTask
#define TASK_VARIABLE OCP_GTPV1_U
#else
#define TASK_VARIABLE TASK_GTPV1_U
#endif
typedef boolean_t (*gtpCallback)(
protocol_ctxt_t *ctxt_pP,
const srb_flag_t srb_flagP,
const rb_id_t rb_idP,
const mui_t muiP,
const confirm_t confirmP,
const sdu_size_t sdu_buffer_sizeP,
unsigned char *const sdu_buffer_pP,
const pdcp_transmission_mode_t modeP,
const uint32_t *sourceL2Id,
const uint32_t *destinationL2Id);
typedef struct openAddr_s {
char originHost[HOST_NAME_MAX];
char originService[HOST_NAME_MAX];
char destinationHost[HOST_NAME_MAX];
char destinationService[HOST_NAME_MAX];
instance_t originInstance;
} openAddr_t;
// the init function create a gtp instance and return the gtp instance id
// the parameter originInstance will be sent back in each message from gtp to the creator
void ocp_gtpv1uReceiver(int h);
void ocp_gtpv1uProcessTimeout(int handle,void *arg);
int ocp_gtpv1u_create_s1u_tunnel(const instance_t instance, const gtpv1u_enb_create_tunnel_req_t *create_tunnel_req,
gtpv1u_enb_create_tunnel_resp_t *create_tunnel_resp);
int ocp_gtpv1u_update_s1u_tunnel(const instance_t instanceP,
const gtpv1u_enb_create_tunnel_req_t *create_tunnel_req_pP,
const rnti_t prior_rnti
);
int ocp_gtpv1u_delete_s1u_tunnel( const instance_t instance, const gtpv1u_enb_delete_tunnel_req_t *const req_pP);
int gtpv1u_delete_s1u_tunnel( const instance_t instance, const gtpv1u_enb_delete_tunnel_req_t *const req_pP);
int ocp_gtpv1u_create_x2u_tunnel(
const instance_t instanceP,
const gtpv1u_enb_create_x2u_tunnel_req_t *const create_tunnel_req_pP,
gtpv1u_enb_create_x2u_tunnel_resp_t *const create_tunnel_resp_pP);
// New API
teid_t newGtpuCreateTunnel(instance_t instance, rnti_t rnti, int bearer_id, teid_t teid,
transport_layer_addr_t remoteAddr, int port, gtpCallback callBack);
instance_t ocp_gtpv1Init(openAddr_t context);
void *ocp_gtpv1uTask(void *args);
#ifdef __cplusplus
}
#endif
#endif
......@@ -42,6 +42,7 @@
# include "enb_app.h"
# include "openair2/LAYER2/MAC/mac_proto.h"
#include <executables/split_headers.h>
#include <openair3/ocp-gtpu/gtp_itf.h>
extern RAN_CONTEXT_t RC;
......
......@@ -47,6 +47,7 @@
# include "mce_app.h"
# include "mme_app.h"
#include <openair3/ocp-gtpu/gtp_itf.h>
//extern RAN_CONTEXT_t RC;
int create_tasks_mbms(uint32_t enb_nb) {
......
......@@ -175,7 +175,6 @@ extern void init_eNB_afterRU(void);
int transmission_mode=1;
int emulate_rf = 0;
int numerology = 0;
int usrp_tx_thread = 0;
THREAD_STRUCT thread_struct;
/* struct for ethernet specific parameters given in eNB conf file */
......
......@@ -169,7 +169,6 @@ extern void get_uethreads_params(void);
int transmission_mode=1;
int usrp_tx_thread = 0;
char *usrp_args=NULL;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment