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
This commit is contained in:
@@ -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
|
||||
${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
|
||||
)
|
||||
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_library (GTPV1U_OCP
|
||||
${NR_RRC_DIR}/rrc_gNB_GTPV1U.c
|
||||
${RRC_DIR}/rrc_eNB_GTPV1U.c
|
||||
${OPENAIR3_DIR}/ocp-gtpu/gtp_itf.cpp
|
||||
)
|
||||
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,64 +113,152 @@ 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;
|
||||
|
||||
if(task_id == TASK_DATA_FORWARDING){
|
||||
|
||||
LOG_I(GTPU,"gtpv_data_req task_id = TASK_DATA_FORWARDING\n");
|
||||
|
||||
message_buffer = itti_malloc (TASK_GTPV1_U, TASK_DATA_FORWARDING, sdu_sizeP);
|
||||
|
||||
memcpy (message_buffer, buffer_pP, sdu_sizeP);
|
||||
|
||||
message_p = itti_alloc_new_message (TASK_GTPV1_U, 0, GTPV1U_ENB_DATA_FORWARDING_IND);
|
||||
GTPV1U_ENB_DATA_FORWARDING_IND (message_p).frame = ctxt_pP->frame;
|
||||
GTPV1U_ENB_DATA_FORWARDING_IND (message_p).enb_flag = ctxt_pP->enb_flag;
|
||||
GTPV1U_ENB_DATA_FORWARDING_IND (message_p).rb_id = rb_idP;
|
||||
GTPV1U_ENB_DATA_FORWARDING_IND (message_p).muip = muiP;
|
||||
GTPV1U_ENB_DATA_FORWARDING_IND (message_p).confirmp = confirmP;
|
||||
GTPV1U_ENB_DATA_FORWARDING_IND (message_p).sdu_size = sdu_sizeP;
|
||||
GTPV1U_ENB_DATA_FORWARDING_IND (message_p).sdu_p = message_buffer;
|
||||
GTPV1U_ENB_DATA_FORWARDING_IND (message_p).mode = modeP;
|
||||
GTPV1U_ENB_DATA_FORWARDING_IND (message_p).module_id = ctxt_pP->module_id;
|
||||
GTPV1U_ENB_DATA_FORWARDING_IND (message_p).rnti = ctxt_pP->rnti;
|
||||
GTPV1U_ENB_DATA_FORWARDING_IND (message_p).eNB_index = ctxt_pP->eNB_index;
|
||||
|
||||
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){
|
||||
|
||||
LOG_I(GTPU,"gtpv_data_req task_id = TASK_END_MARKER\n");
|
||||
|
||||
message_buffer = itti_malloc (TASK_GTPV1_U, TASK_END_MARKER, sdu_sizeP);
|
||||
|
||||
memcpy (message_buffer, buffer_pP, sdu_sizeP);
|
||||
|
||||
message_p = itti_alloc_new_message (TASK_GTPV1_U, 0, GTPV1U_ENB_END_MARKER_IND);
|
||||
GTPV1U_ENB_END_MARKER_IND (message_p).frame = ctxt_pP->frame;
|
||||
GTPV1U_ENB_END_MARKER_IND (message_p).enb_flag = ctxt_pP->enb_flag;
|
||||
GTPV1U_ENB_END_MARKER_IND (message_p).rb_id = rb_idP;
|
||||
GTPV1U_ENB_END_MARKER_IND (message_p).muip = muiP;
|
||||
GTPV1U_ENB_END_MARKER_IND (message_p).confirmp = confirmP;
|
||||
GTPV1U_ENB_END_MARKER_IND (message_p).sdu_size = sdu_sizeP;
|
||||
GTPV1U_ENB_END_MARKER_IND (message_p).sdu_p = message_buffer;
|
||||
GTPV1U_ENB_END_MARKER_IND (message_p).mode = modeP;
|
||||
GTPV1U_ENB_END_MARKER_IND (message_p).module_id = ctxt_pP->module_id;
|
||||
GTPV1U_ENB_END_MARKER_IND (message_p).rnti = ctxt_pP->rnti;
|
||||
GTPV1U_ENB_END_MARKER_IND (message_p).eNB_index = ctxt_pP->eNB_index;
|
||||
|
||||
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.
|
||||
}
|
||||
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;
|
||||
|
||||
if(task_id == TASK_DATA_FORWARDING){
|
||||
|
||||
LOG_I(GTPU,"gtpv_data_req task_id = TASK_DATA_FORWARDING\n");
|
||||
|
||||
message_buffer = itti_malloc (TASK_GTPV1_U, TASK_DATA_FORWARDING, sdu_sizeP);
|
||||
|
||||
memcpy (message_buffer, buffer_pP, sdu_sizeP);
|
||||
|
||||
message_p = itti_alloc_new_message (TASK_GTPV1_U, 0, GTPV1U_ENB_DATA_FORWARDING_IND);
|
||||
GTPV1U_ENB_DATA_FORWARDING_IND (message_p).frame = ctxt_pP->frame;
|
||||
GTPV1U_ENB_DATA_FORWARDING_IND (message_p).enb_flag = ctxt_pP->enb_flag;
|
||||
GTPV1U_ENB_DATA_FORWARDING_IND (message_p).rb_id = rb_idP;
|
||||
GTPV1U_ENB_DATA_FORWARDING_IND (message_p).muip = muiP;
|
||||
GTPV1U_ENB_DATA_FORWARDING_IND (message_p).confirmp = confirmP;
|
||||
GTPV1U_ENB_DATA_FORWARDING_IND (message_p).sdu_size = sdu_sizeP;
|
||||
GTPV1U_ENB_DATA_FORWARDING_IND (message_p).sdu_p = message_buffer;
|
||||
GTPV1U_ENB_DATA_FORWARDING_IND (message_p).mode = modeP;
|
||||
GTPV1U_ENB_DATA_FORWARDING_IND (message_p).module_id = ctxt_pP->module_id;
|
||||
GTPV1U_ENB_DATA_FORWARDING_IND (message_p).rnti = ctxt_pP->rnti;
|
||||
GTPV1U_ENB_DATA_FORWARDING_IND (message_p).eNB_index = ctxt_pP->eNB_index;
|
||||
|
||||
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){
|
||||
|
||||
LOG_I(GTPU,"gtpv_data_req task_id = TASK_END_MARKER\n");
|
||||
|
||||
message_buffer = itti_malloc (TASK_GTPV1_U, TASK_END_MARKER, sdu_sizeP);
|
||||
|
||||
memcpy (message_buffer, buffer_pP, sdu_sizeP);
|
||||
|
||||
message_p = itti_alloc_new_message (TASK_GTPV1_U, 0, GTPV1U_ENB_END_MARKER_IND);
|
||||
GTPV1U_ENB_END_MARKER_IND (message_p).frame = ctxt_pP->frame;
|
||||
GTPV1U_ENB_END_MARKER_IND (message_p).enb_flag = ctxt_pP->enb_flag;
|
||||
GTPV1U_ENB_END_MARKER_IND (message_p).rb_id = rb_idP;
|
||||
GTPV1U_ENB_END_MARKER_IND (message_p).muip = muiP;
|
||||
GTPV1U_ENB_END_MARKER_IND (message_p).confirmp = confirmP;
|
||||
GTPV1U_ENB_END_MARKER_IND (message_p).sdu_size = sdu_sizeP;
|
||||
GTPV1U_ENB_END_MARKER_IND (message_p).sdu_p = message_buffer;
|
||||
GTPV1U_ENB_END_MARKER_IND (message_p).mode = modeP;
|
||||
GTPV1U_ENB_END_MARKER_IND (message_p).module_id = ctxt_pP->module_id;
|
||||
GTPV1U_ENB_END_MARKER_IND (message_p).rnti = ctxt_pP->rnti;
|
||||
GTPV1U_ENB_END_MARKER_IND (message_p).eNB_index = ctxt_pP->eNB_index;
|
||||
|
||||
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.
|
||||
}
|
||||
return TRUE;
|
||||
|
||||
LOG_E(RRC, "Impossible state\n");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
//#endif
|
||||
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(>PV1U_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;
|
||||
}
|
||||
|
||||
/* 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;
|
||||
}
|
||||
|
||||
|
||||
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(>PV1U_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;
|
||||
|
||||
@@ -309,7 +309,7 @@ NwGtpv1uRcT gtpv1u_eNB_process_stack_req(
|
||||
msgsrc != GTPV1U_MSG_FROM_SOURCE_ENB? "UDP DATA" :
|
||||
msgType == NW_GTP_END_MARKER?"END MARKER":"DATA FORWARDING");
|
||||
|
||||
/* target enb */
|
||||
/* target enb */
|
||||
if(msgType == NW_GTP_END_MARKER) {
|
||||
LOG_I(GTPU, "target end receive END MARKER\n");
|
||||
ue_context_p->ue_context.handover_info->state = HO_END_MARKER;
|
||||
@@ -1498,15 +1498,15 @@ void *gtpv1u_eNB_process_itti_msg(void *notUsed) {
|
||||
stack_req.apiInfo.sendtoInfo.teid = tenb_x2u_teid;
|
||||
stack_req.apiInfo.sendtoInfo.ipAddr = gtpv1u_ue_data_p->bearers[data_req_p->rab_id - GTPV1U_BEARER_OFFSET].tenb_ip_addr;// target enb ip
|
||||
rc = nwGtpv1uGpduMsgNew(
|
||||
RC.gtpv1u_data_g->gtpv1u_stack,
|
||||
tenb_x2u_teid,
|
||||
NW_FALSE,
|
||||
RC.gtpv1u_data_g->seq_num++,
|
||||
data_req_p->buffer,
|
||||
data_req_p->length,
|
||||
data_req_p->offset,
|
||||
&(stack_req.apiInfo.sendtoInfo.hMsg));
|
||||
|
||||
RC.gtpv1u_data_g->gtpv1u_stack,
|
||||
tenb_x2u_teid,
|
||||
NW_FALSE,
|
||||
RC.gtpv1u_data_g->seq_num++,
|
||||
data_req_p->buffer,
|
||||
data_req_p->length,
|
||||
data_req_p->offset,
|
||||
&(stack_req.apiInfo.sendtoInfo.hMsg));
|
||||
|
||||
if (rc != NW_GTPV1U_OK) {
|
||||
LOG_E(GTPU, "nwGtpv1uGpduMsgNew failed: 0x%x\n", rc);
|
||||
MSC_LOG_EVENT(MSC_GTPU_ENB,"0 Failed send G-PDU ltid %u rtid %u size %u",
|
||||
@@ -1516,7 +1516,7 @@ void *gtpv1u_eNB_process_itti_msg(void *notUsed) {
|
||||
pMsg = (NwGtpv1uMsgT *) stack_req.apiInfo.sendtoInfo.hMsg;
|
||||
pMsg->msgType = NW_GTP_END_MARKER;
|
||||
rc = nwGtpv1uProcessUlpReq(RC.gtpv1u_data_g->gtpv1u_stack, &stack_req);
|
||||
|
||||
|
||||
if (rc != NW_GTPV1U_OK) {
|
||||
LOG_E(GTPU, "nwGtpv1uProcessUlpReq failed: 0x%x\n", rc);
|
||||
MSC_LOG_EVENT(MSC_GTPU_ENB,"0 Failed send G-PDU ltid %u rtid %u size %u",
|
||||
@@ -1536,11 +1536,11 @@ void *gtpv1u_eNB_process_itti_msg(void *notUsed) {
|
||||
|
||||
rc = nwGtpv1uMsgDelete(RC.gtpv1u_data_g->gtpv1u_stack,
|
||||
stack_req.apiInfo.sendtoInfo.hMsg);
|
||||
|
||||
|
||||
if (rc != NW_GTPV1U_OK) {
|
||||
LOG_E(GTPU, "nwGtpv1uMsgDelete failed: 0x%x\n", rc);
|
||||
}
|
||||
|
||||
|
||||
gtpv1u_enb_delete_tunnel_req_t delete_tunnel_req;
|
||||
memset(&delete_tunnel_req, 0, sizeof(delete_tunnel_req));
|
||||
delete_tunnel_req.rnti = data_req_p->rnti;
|
||||
@@ -1548,7 +1548,7 @@ void *gtpv1u_eNB_process_itti_msg(void *notUsed) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_GTPV1U_PROCESS_TUNNEL_DATA_REQ, VCD_FUNCTION_OUT);
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -0,0 +1,783 @@
|
||||
#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)),
|
||||
>PV1U_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)),
|
||||
>PV1U_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
|
||||
@@ -0,0 +1,71 @@
|
||||
#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
|
||||
@@ -1329,7 +1329,7 @@ extern "C" {
|
||||
if(is_equal(s->sample_rate, (double)7.68e6))
|
||||
s->tx_forward_nsamps = 50;
|
||||
|
||||
|
||||
|
||||
if (device->recplay_state != NULL) { // record mode
|
||||
device->recplay_state->ms_sample = (iqrec_t *) malloc(openair0_cfg[0].recplay_conf->u_sf_max * sizeof(iqrec_t));
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user