new gtp before tests
This commit is contained in:
@@ -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)
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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_ */
|
||||
|
||||
@@ -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);
|
||||
@@ -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");
|
||||
|
||||
|
||||
@@ -57,6 +57,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"
|
||||
@@ -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");
|
||||
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -33,6 +33,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__); \
|
||||
@@ -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);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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>
|
||||
|
||||
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);
|
||||
|
||||
+193
-176
@@ -1,3 +1,9 @@
|
||||
#include <map>
|
||||
using namespace std;
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
@@ -10,9 +16,8 @@
|
||||
#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>
|
||||
#include <map>
|
||||
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<int,teidData_t> ue2te_mapping;
|
||||
map<int,rntiData_t> 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 <openair2/ENB_APP/enb_paramdef.h>
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
+35
-14
@@ -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 <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
|
||||
#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
|
||||
|
||||
Reference in New Issue
Block a user