From 954b0f559d83304754ee06be8b338e7fc4628eba Mon Sep 17 00:00:00 2001 From: Laurent Thomas Date: Mon, 25 Jan 2021 12:59:38 +0100 Subject: [PATCH] new gtp before tests --- cmake_targets/CMakeLists.txt | 4 +- doc/SW_archi.md | 22 ++ openair2/COMMON/gtpv1_u_messages_types.h | 2 + openair2/ENB_APP/enb_config.c | 5 +- openair2/GNB_APP/gnb_config.c | 6 +- openair2/LAYER2/PDCP_v10.1.0/pdcp.c | 3 +- openair2/LAYER2/PDCP_v10.1.0/pdcp.h | 7 +- openair2/LAYER2/nr_pdcp/nr_pdcp_oai_api.c | 3 +- openair2/RRC/LTE/rrc_eNB.c | 2 +- openair2/RRC/LTE/rrc_eNB_S1AP.c | 2 +- openair2/RRC/NR/rrc_gNB_nsa.c | 3 +- openair3/ocp-gtpu/gtp_itf.cpp | 369 +++++++++++----------- openair3/ocp-gtpu/gtp_itf.h | 49 ++- 13 files changed, 274 insertions(+), 203 deletions(-) diff --git a/cmake_targets/CMakeLists.txt b/cmake_targets/CMakeLists.txt index 1b93dea0c0..1a4a0a88f7 100644 --- a/cmake_targets/CMakeLists.txt +++ b/cmake_targets/CMakeLists.txt @@ -2883,8 +2883,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 - PHY_COMMON PHY PHY_RU LFDS L2 L2_LTE NFAPI_COMMON_LIB NFAPI_LIB NFAPI_VNF_LIB NFAPI_PNF_LIB NFAPI_USER_LIB LFDS7 + RRC_LIB NR_RRC_LIB S1AP_LIB S1AP_ENB F1AP_LIB F1AP M2AP_LIB M2AP_ENB X2AP_LIB X2AP_ENB M3AP_LIB M3AP_ENB 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 ${GTPV1U} NFAPI_COMMON_LIB NFAPI_LIB NFAPI_VNF_LIB NFAPI_PNF_LIB NFAPI_USER_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) diff --git a/doc/SW_archi.md b/doc/SW_archi.md index 412dad402d..f6114c33c2 100644 --- a/doc/SW_archi.md +++ b/doc/SW_archi.md @@ -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 diff --git a/openair2/COMMON/gtpv1_u_messages_types.h b/openair2/COMMON/gtpv1_u_messages_types.h index 14b6e7c0b1..a0c1a9e817 100644 --- a/openair2/COMMON/gtpv1_u_messages_types.h +++ b/openair2/COMMON/gtpv1_u_messages_types.h @@ -170,6 +170,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; #endif /* GTPV1_U_MESSAGES_TYPES_H_ */ diff --git a/openair2/ENB_APP/enb_config.c b/openair2/ENB_APP/enb_config.c index de77d783c7..9b0bc14f70 100644 --- a/openair2/ENB_APP/enb_config.c +++ b/openair2/ENB_APP/enb_config.c @@ -57,6 +57,7 @@ #include "enb_paramdef.h" #include "proto_agent.h" #include "executables/thread-common.h" +#include 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); @@ -2055,7 +2056,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"); diff --git a/openair2/GNB_APP/gnb_config.c b/openair2/GNB_APP/gnb_config.c index 3785ded9e9..19ff268668 100644 --- a/openair2/GNB_APP/gnb_config.c +++ b/openair2/GNB_APP/gnb_config.c @@ -57,6 +57,7 @@ //#include "RRC_config_tools.h" #include "gnb_paramdef.h" #include "NR_MAC_gNB/mac_proto.h" +#include #include "NR_asn_constant.h" #include "executables/thread-common.h" @@ -740,8 +741,9 @@ int RCconfig_nr_gtpu(void ) { 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 = 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"); diff --git a/openair2/LAYER2/PDCP_v10.1.0/pdcp.c b/openair2/LAYER2/PDCP_v10.1.0/pdcp.c index 9b6de7c168..9c5438b589 100644 --- a/openair2/LAYER2/PDCP_v10.1.0/pdcp.c +++ b/openair2/LAYER2/PDCP_v10.1.0/pdcp.c @@ -61,6 +61,7 @@ # include "gtpv1u_eNB_task.h" # include "gtpv1u.h" +#include #include "ENB_APP/enb_config.h" @@ -937,7 +938,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 { diff --git a/openair2/LAYER2/PDCP_v10.1.0/pdcp.h b/openair2/LAYER2/PDCP_v10.1.0/pdcp.h index c8ab4499ee..52efc3c03e 100644 --- a/openair2/LAYER2/PDCP_v10.1.0/pdcp.h +++ b/openair2/LAYER2/PDCP_v10.1.0/pdcp.h @@ -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) diff --git a/openair2/LAYER2/nr_pdcp/nr_pdcp_oai_api.c b/openair2/LAYER2/nr_pdcp/nr_pdcp_oai_api.c index 9b33b2715d..1e5ec1ee59 100644 --- a/openair2/LAYER2/nr_pdcp/nr_pdcp_oai_api.c +++ b/openair2/LAYER2/nr_pdcp/nr_pdcp_oai_api.c @@ -33,6 +33,7 @@ /* from OAI */ #include "pdcp.h" #include "LAYER2/nr_rlc/nr_rlc_oai_api.h" +#include #define TODO do { \ printf("%s:%d:%s: todo\n", __FILE__, __LINE__, __FUNCTION__); \ @@ -442,7 +443,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); } } diff --git a/openair2/RRC/LTE/rrc_eNB.c b/openair2/RRC/LTE/rrc_eNB.c index 2564983d47..5624bf80d8 100644 --- a/openair2/RRC/LTE/rrc_eNB.c +++ b/openair2/RRC/LTE/rrc_eNB.c @@ -5034,7 +5034,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); diff --git a/openair2/RRC/LTE/rrc_eNB_S1AP.c b/openair2/RRC/LTE/rrc_eNB_S1AP.c index 9edfa50f12..49450e2deb 100644 --- a/openair2/RRC/LTE/rrc_eNB_S1AP.c +++ b/openair2/RRC/LTE/rrc_eNB_S1AP.c @@ -1763,7 +1763,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); } diff --git a/openair2/RRC/NR/rrc_gNB_nsa.c b/openair2/RRC/NR/rrc_gNB_nsa.c index 8f1fa9f81f..e1c511c4f9 100644 --- a/openair2/RRC/NR/rrc_gNB_nsa.c +++ b/openair2/RRC/NR/rrc_gNB_nsa.c @@ -39,6 +39,7 @@ #include "openair2/RRC/LTE/rrc_eNB_GTPV1U.h" #include "executables/softmodem-common.h" #include +#include extern boolean_t nr_rrc_pdcp_config_asn1_req( const protocol_ctxt_t *const ctxt_pP, @@ -341,7 +342,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); diff --git a/openair3/ocp-gtpu/gtp_itf.cpp b/openair3/ocp-gtpu/gtp_itf.cpp index 5a5717c726..f9fc506860 100644 --- a/openair3/ocp-gtpu/gtp_itf.cpp +++ b/openair3/ocp-gtpu/gtp_itf.cpp @@ -1,3 +1,9 @@ +#include +using namespace std; + +#ifdef __cplusplus +extern "C" { +#endif #include #include #include @@ -10,9 +16,8 @@ #include #include #include +#include //#include -#include -using namespace std; #pragma pack(1) @@ -25,13 +30,13 @@ typedef struct Gtpv1uMsgHeader { uint8_t version:3; uint8_t msgType; uint16_t msgLength; - uint32_t teid; + 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) +// 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) @@ -57,11 +62,14 @@ typedef struct { typedef struct { rnti_t rnti; + gtpCallback callBack; } rntiData_t; class gtpEndPoint { public: openAddr_t addr; + uint8_t foundAddr[20]; + int foundAddrLen; map ue2te_mapping; map te2ue_mapping; }; @@ -75,10 +83,6 @@ class gtpEndPoints { gtpEndPoints globGtp; -#ifdef __cplusplus -extern "C" { -#endif - static uint32_t gtpv1uNewTeid(void) { #ifdef GTPV1U_LINEAR_TEID_ALLOCATION g_gtpv1u_teid = g_gtpv1u_teid + 1; @@ -90,7 +94,7 @@ static uint32_t gtpv1uNewTeid(void) { #define GTPV1U_HEADER_SIZE (8) -static int gtpv1uCreateAndSendMsg(int h, uint32_t peerIp, uint16_t peerPort, uint32_t teid, uint8_t *Msg,int msgLen, +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; @@ -203,6 +207,11 @@ static int udpServerSocket(openAddr_s addr) { 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; + memcpy(globGtp.instances[sockfd].foundAddr, p->ai_addr, p->ai_addrlen); + globGtp.instances[sockfd].foundAddrLen=p->ai_addrlen; } break; // if we get here, we must have connected successfully @@ -215,6 +224,28 @@ static int udpServerSocket(openAddr_s addr) { } 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); @@ -226,16 +257,66 @@ instance_t ocp_gtpv1Init(openAddr_t context) { int id=udpServerSocket(context); if (id>=0) { - globGtp.instances[id].addr=context; 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].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) { @@ -243,96 +324,23 @@ int ocp_gtpv1u_create_s1u_tunnel(instance_t instance, create_tunnel_req->rnti, create_tunnel_req->num_tunnels, create_tunnel_req->sgw_S1u_teid[0]); - pthread_mutex_lock(&globGtp.gtp_lock); - auto inst=&globGtp.instances[instance]; - auto it=inst->ue2te_mapping.find(create_tunnel_req->rnti); - - if ( it != inst->ue2te_mapping.end() ) { - LOG_W(GTPU,"Create a config for a already existing GTP tunnel (rnti %x)\n", create_tunnel_req->rnti); - inst->ue2te_mapping.erase(it); - } - - rntiData_t rntiData= {create_tunnel_req->rnti}; for (int i = 0; i < create_tunnel_req->num_tunnels; i++) { - ocp_gtpv1u_bearer_t gtpv1u_ue_data; - 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]=rntiData; - - int addrs_length_in_bytes = create_tunnel_req->sgw_addr[i].length / 8; - - switch (addrs_length_in_bytes) { - case 4: - memcpy(>pv1u_ue_data.outgoing_ip_addr,create_tunnel_req->sgw_addr[i].buffer,4); - break; - - case 16: - memcpy(>pv1u_ue_data.outgoing_ip6_addr.s6_addr, - create_tunnel_req->sgw_addr[i].buffer, - 16); - break; - - case 20: - memcpy(>pv1u_ue_data.outgoing_ip_addr,create_tunnel_req->sgw_addr[i].buffer,4); - memcpy(>pv1u_ue_data.outgoing_ip6_addr.s6_addr, - create_tunnel_req->sgw_addr[i].buffer+4, - 16); - - default: - AssertFatal(false, "SGW Address size impossible"); - } - - gtpv1u_ue_data.teid_incoming = s1u_teid; - gtpv1u_ue_data.outgoing_port=2152; - gtpv1u_ue_data.teid_outgoing= create_tunnel_req->sgw_S1u_teid[i]; - inst->ue2te_mapping[create_tunnel_req->rnti].bearers[create_tunnel_req->eps_bearer_id[i]]=gtpv1u_ue_data; - LOG_D(GTPU, "Created tunnel %x for RNTI %x, SGW: " IPV4_ADDR ":%d\n", - s1u_teid, create_tunnel_req->rnti, - IPV4_ADDR_FORMAT(inst->ue2te_mapping[create_tunnel_req->rnti].bearers[create_tunnel_req->eps_bearer_id[i]].outgoing_ip_addr), - inst->ue2te_mapping[create_tunnel_req->rnti].bearers[create_tunnel_req->eps_bearer_id[i]].outgoing_port ); + teid_t teid=newGtpuCreateTunnel(instance, create_tunnel_req->rnti, + create_tunnel_req->eps_bearer_id[i], + create_tunnel_req->eps_bearer_id[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]=gtpv1u_ue_data.teid_incoming; + create_tunnel_resp->enb_S1u_teid[i]=teid; create_tunnel_resp->eps_bearer_id[i] = create_tunnel_req->eps_bearer_id[i]; - //TBD: fix me this is quite bad, for IPv4 only and - // Overcomplex stuff to fill InitialContextSetupResponse in S1AP - int status; - struct addrinfo hints= {0}, *servinfo, *p; - hints.ai_family = AF_UNSPEC; - hints.ai_socktype = SOCK_DGRAM; - hints.ai_flags = AI_PASSIVE; - openAddr_t *addr=&globGtp.instances[instance].addr; - - if ((status = getaddrinfo(addr->originHost, addr->originService, &hints, &servinfo)) != 0) { - LOG_E(GTPU,"getaddrinfo error: %s\n", gai_strerror(status)); - pthread_mutex_unlock(&globGtp.gtp_lock); - return -1; - } - - // TBD: we take the first IPv4 addr, but it should be coded in the right way - for(p = servinfo; p != NULL; p = p->ai_next) - if (p->ai_family == AF_INET) { - struct sockaddr_in *ipv4P=(struct sockaddr_in *)p->ai_addr; - memcpy(create_tunnel_resp->enb_addr.buffer, - &ipv4P->sin_addr.s_addr, sizeof(ipv4P->sin_addr.s_addr)); - create_tunnel_resp->enb_addr.length = sizeof(ipv4P->sin_addr.s_addr); - break; - } - - if ( p == NULL ) - LOG_E(GTPU,"can't translate IP address string: %s\n",addr->originHost); - - freeaddrinfo(servinfo); // all done with this structure + memcpy(create_tunnel_resp->enb_addr.buffer,globGtp.instances[instance].foundAddr, + globGtp.instances[instance].foundAddrLen); + create_tunnel_resp->enb_addr.length= globGtp.instances[instance].foundAddrLen; } - pthread_mutex_unlock(&globGtp.gtp_lock); return !GTPNOK; } @@ -358,9 +366,9 @@ int ocp_gtpv1u_update_s1u_tunnel( 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); - pthread_mutex_unlock(&globGtp.gtp_lock); return 0; } @@ -369,16 +377,16 @@ int ocp_gtpv1u_update_s1u_tunnel( 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){ + 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 ocp_gtpv1u_delete_s1u_tunnel( const instance_t instance, - const gtpv1u_enb_delete_tunnel_req_t *const req_pP) { + const gtpv1u_enb_delete_tunnel_req_t *const req_pP) { LOG_D(GTPU, "Start delete tunnels for RNTI %x, num_erab %d, eps_bearer_id %d \n", req_pP->rnti, req_pP->num_erab, @@ -422,22 +430,22 @@ static int Gtpv1uHandleError(int h, int rc = GTPNOK; return rc; } - + static int Gtpv1uHandleSupportedExt(int h, - uint8_t *msgBuf, - uint32_t msgBufLen, - uint16_t peerPort, - uint32_t peerIp) { + 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 Gtpv1uHandleEndMarker(int h, - uint8_t *msgBuf, - uint32_t msgBufLen, - uint16_t peerPort, - uint32_t peerIp) { + +static int Gtpv1uHandleEndMarker(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; @@ -460,52 +468,52 @@ static int Gtpv1uHandleGpdu(int h, auto tunnel=inst->te2ue_mapping.find(ntohl(msgHdr->teid)); if ( tunnel == inst->te2ue_mapping.end() ) { - LOG_E(GTPU,"Received a incoming packet on non open teid (%d)\n", msgHdr->teid); + 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; - /* - gtpv1u_enb_tunnel_data_ind_t tmp; + + // 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 = 0; - ctxt.frame = 0; - ctxt.subframe = 0; - ctxt.eNB_index = 0; - ctxt.configured = 1; - ctxt.brOption = 0; - result = pdcp_data_req(&ctxt, - SRB_FLAG_YES, - RRC_DCCH_DATA_REQ(msg_p).rb_id, - RRC_DCCH_DATA_REQ(msg_p).muip, - RRC_DCCH_DATA_REQ(msg_p).confirmp, - RRC_DCCH_DATA_REQ(msg_p).sdu_size, - RRC_DCCH_DATA_REQ(msg_p).sdu_p, - RRC_DCCH_DATA_REQ(msg_p).mode, - NULL, NULL); - - - ctxt.rnti = rnti; - pdcp_data_req(&ctxt, SRB_FLAG_NO, rb_id, RLC_MUI_UNDEFINED, - RLC_SDU_CONFIRM_NO, len, (unsigned char *)rx_buf, - PDCP_TRANSMISSION_MODE_DATA, NULL, NULL); - - MessageDef *msg_p=itti_alloc_new_message_sized(OCP_GTPV1_U,GTPV1U_ENB_TUNNEL_DATA_IND, - sizeof(MessageDef) + msgBufLen); - GTPV1U_ENB_TUNNEL_DATA_IND(msg_p).buffer=(uint8_t *)(msg_p+1); - memcpy(GTPV1U_ENB_TUNNEL_DATA_IND(msg_p).buffer,msgBuf,msgBufLen); - GTPV1U_ENB_TUNNEL_DATA_IND(msg_p).length=msgBufLen; - GTPV1U_ENB_TUNNEL_DATA_IND(msg_p).offset=offset; + 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 = 1; + ctxt.brOption = 0; + const srb_flag_t srb_flag=SRB_FLAG_NO; + const rb_id_t rb_id=0; + 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); - inst->addr.dlCallBack(msg_p); - */ - // could be a full itti msg, make it in the call back if you need - //itti_send_msg_to_task(TASK_RRC_ENB, ENB_MODULE_ID_TO_INSTANCE(0), msg_p); + + 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)); @@ -541,26 +549,28 @@ void gtpv1uReceiver(int h) { case GTP_ERROR_INDICATION: Gtpv1uHandleError( h, udpData, udpDataLen, htons(addr.sin_port), addr.sin_addr.s_addr); break; - - case GTP_SUPPORTED_EXTENSION_HEADER_INDICATION: + + 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; + 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 + void *ocp_gtpv1uTask(void *args) { while(1) { /* Trying to fetch a message from the message queue. @@ -571,6 +581,8 @@ void *ocp_gtpv1uTask(void *args) { 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: { @@ -587,19 +599,24 @@ void *ocp_gtpv1uTask(void *args) { 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_DATA_FORWARDING_REQ: - case GTPV1U_ENB_DATA_FORWARDING_IND: - case GTPV1U_ENB_END_MARKER_REQ: - case GTPV1U_ENB_END_MARKER_IND: - case GTPV1U_ENB_S1_REQ: - LOG_E(GTPU, "to be developped %s\n", ITTI_MSG_NAME(message_p)); - abort(); - break; - - default: - LOG_E(GTPU, "Received unexpected message %s\n", ITTI_MSG_NAME(message_p)); - abort(); + case GTPV1U_ENB_DATA_FORWARDING_REQ: + case GTPV1U_ENB_DATA_FORWARDING_IND: + case GTPV1U_ENB_END_MARKER_REQ: + 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(ocp_gtpv1Init(addr),"Only one instance 0 supprted\n"); + break; + + default: + LOG_E(GTPU, "Received unexpected message %s\n", ITTI_MSG_NAME(message_p)); + abort(); break; } diff --git a/openair3/ocp-gtpu/gtp_itf.h b/openair3/ocp-gtpu/gtp_itf.h index e09f2194eb..24b1adaa6f 100644 --- a/openair3/ocp-gtpu/gtp_itf.h +++ b/openair3/ocp-gtpu/gtp_itf.h @@ -1,5 +1,5 @@ -#ifndef __UDP_ITF_H__ -#define __UDP_ITF_H__ +#ifndef __GTPUNEW_ITF_H__ +#define __GTPUNEW_ITF_H__ #define GTPNOK -1 # define GTPU_HEADER_OVERHEAD_MAX 64 @@ -9,11 +9,27 @@ extern "C" { #include #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 - #endif +#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 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]; @@ -25,7 +41,6 @@ typedef struct openAddr_s { // 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 -instance_t ocp_gtpv1Init(openAddr_t context); 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, @@ -36,13 +51,19 @@ int ocp_gtpv1u_update_s1u_tunnel(const instance_t instanceP, ); 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( + +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); - void *ocp_gtpv1uTask(void *args); - + 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