From d1a03c993c904e59b96369d9255f8c3677b80fd2 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Mon, 3 Feb 2025 09:28:26 +0100 Subject: [PATCH] Reformat gtp_itf.cpp --- openair3/ocp-gtpu/gtp_itf.cpp | 854 ++++++++++++++++++---------------- 1 file changed, 442 insertions(+), 412 deletions(-) diff --git a/openair3/ocp-gtpu/gtp_itf.cpp b/openair3/ocp-gtpu/gtp_itf.cpp index 174f75d89b..50c46b809f 100644 --- a/openair3/ocp-gtpu/gtp_itf.cpp +++ b/openair3/ocp-gtpu/gtp_itf.cpp @@ -25,85 +25,85 @@ extern "C" { #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 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; -//TS 38.425, Figure 5.5.2.2-1 +// TS 38.425, Figure 5.5.2.2-1 typedef struct DlDataDeliveryStatus_flags { - uint8_t LPR:1; //Lost packet report - uint8_t FFI:1; //Final Frame Ind - uint8_t deliveredPdcpSn:1; //Highest Delivered NR PDCP SN Ind - uint8_t transmittedPdcpSn:1; //Highest Transmitted NR PDCP SN Ind - uint8_t pduType:4; //PDU type - uint8_t CR:1; //Cause Report - uint8_t deliveredReTxPdcpSn:1; //Delivered retransmitted NR PDCP SN Ind - uint8_t reTxPdcpSn:1; //Retransmitted NR PDCP SN Ind - uint8_t DRI:1; //Data Rate Indication - uint8_t deliveredPdcpSnRange:1; //Delivered NR PDCP SN Range Ind - uint8_t spare:3; - uint32_t drbBufferSize; //Desired buffer size for the data radio bearer + uint8_t LPR: 1; // Lost packet report + uint8_t FFI: 1; // Final Frame Ind + uint8_t deliveredPdcpSn: 1; // Highest Delivered NR PDCP SN Ind + uint8_t transmittedPdcpSn: 1; // Highest Transmitted NR PDCP SN Ind + uint8_t pduType: 4; // PDU type + uint8_t CR: 1; // Cause Report + uint8_t deliveredReTxPdcpSn: 1; // Delivered retransmitted NR PDCP SN Ind + uint8_t reTxPdcpSn: 1; // Retransmitted NR PDCP SN Ind + uint8_t DRI: 1; // Data Rate Indication + uint8_t deliveredPdcpSnRange: 1; // Delivered NR PDCP SN Range Ind + uint8_t spare: 3; + uint32_t drbBufferSize; // Desired buffer size for the data radio bearer } __attribute__((packed)) DlDataDeliveryStatus_flagsT; typedef struct Gtpv1uMsgHeaderOptFields { uint8_t seqNum1Oct; uint8_t seqNum2Oct; uint8_t NPDUNum; - uint8_t NextExtHeaderType; + uint8_t NextExtHeaderType; } __attribute__((packed)) Gtpv1uMsgHeaderOptFieldsT; #define DL_PDU_SESSION_INFORMATION 0 #define UL_PDU_SESSION_INFORMATION 1 - typedef struct PDUSessionContainer { - uint8_t spare:4; - uint8_t PDU_type:4; - uint8_t QFI:6; - uint8_t Reflective_QoS_activation:1; - uint8_t Paging_Policy_Indicator:1; +typedef struct PDUSessionContainer { + uint8_t spare: 4; + uint8_t PDU_type: 4; + uint8_t QFI: 6; + uint8_t Reflective_QoS_activation: 1; + uint8_t Paging_Policy_Indicator: 1; } __attribute__((packed)) PDUSessionContainerT; typedef struct Gtpv1uExtHeader { uint8_t ExtHeaderLen; PDUSessionContainerT pdusession_cntr; uint8_t NextExtHeaderType; -}__attribute__((packed)) Gtpv1uExtHeaderT; +} __attribute__((packed)) Gtpv1uExtHeaderT; #pragma pack() // TS 29.281, fig 5.2.1-3 -#define PDU_SESSION_CONTAINER (0x85) -#define NR_RAN_CONTAINER (0x84) +#define PDU_SESSION_CONTAINER (0x85) +#define NR_RAN_CONTAINER (0x84) // TS 29.281, 5.2.1 -#define EXT_HDR_LNTH_OCTET_UNITS (4) -#define NO_MORE_EXT_HDRS (0) +#define EXT_HDR_LNTH_OCTET_UNITS (4) +#define NO_MORE_EXT_HDRS (0) // 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) +#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 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; + 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; + tcp_udp_port_t outgoing_port; + uint16_t seqNum; + uint8_t npduNum; int outgoing_qfi; } gtpv1u_bearer_t; @@ -131,24 +131,27 @@ class gtpEndPoint { // we use the same port number for source and destination address // this allow using non standard gtp port number (different from 2152) // and so, for example tu run 4G and 5G cores on one system - tcp_udp_port_t get_dstport() { + tcp_udp_port_t get_dstport() + { return (tcp_udp_port_t)atol(addr.destinationService); } }; class gtpEndPoints { public: - pthread_mutex_t gtp_lock=PTHREAD_MUTEX_INITIALIZER; + pthread_mutex_t gtp_lock = PTHREAD_MUTEX_INITIALIZER; // the instance id will be the Linux socket handler, as this is uniq map instances; map te2ue_mapping; - gtpEndPoints() { + gtpEndPoints() + { unsigned int seed; fill_random(&seed, sizeof(seed)); srandom(seed); } - ~gtpEndPoints() { + ~gtpEndPoints() + { // automatically close all sockets on quit for (const auto &p : instances) close(p.first); @@ -158,7 +161,8 @@ class gtpEndPoints { static gtpEndPoints globGtp; // note TEid 0 is reserved for specific usage: echo req/resp, error and supported extensions -static teid_t gtpv1uNewTeid(void) { +static teid_t gtpv1uNewTeid(void) +{ #ifdef GTPV1U_LINEAR_TEID_ALLOCATION g_gtpv1u_teid = g_gtpv1u_teid + 1; return g_gtpv1u_teid; @@ -167,46 +171,45 @@ static teid_t gtpv1uNewTeid(void) { #endif } -instance_t legacyInstanceMapping=0; -#define compatInst(a) ((a)==0 || (a)==INSTANCE_DEFAULT ? legacyInstanceMapping:a) +instance_t legacyInstanceMapping = 0; +#define compatInst(a) ((a) == 0 || (a) == INSTANCE_DEFAULT ? legacyInstanceMapping : a) -#define getInstRetVoid(insT) \ - auto instChk=globGtp.instances.find(compatInst(insT)); \ - if (instChk == globGtp.instances.end()) { \ - LOG_E(GTPU,"try to get a gtp-u not existing output\n"); \ - pthread_mutex_unlock(&globGtp.gtp_lock); \ - return; \ - } \ - gtpEndPoint * inst=&instChk->second; - -#define getInstRetInt(insT) \ - auto instChk=globGtp.instances.find(compatInst(insT)); \ - if (instChk == globGtp.instances.end()) { \ - LOG_E(GTPU,"try to get a gtp-u not existing output\n"); \ - pthread_mutex_unlock(&globGtp.gtp_lock); \ - return GTPNOK; \ - } \ - gtpEndPoint * inst=&instChk->second; +#define getInstRetVoid(insT) \ + auto instChk = globGtp.instances.find(compatInst(insT)); \ + if (instChk == globGtp.instances.end()) { \ + LOG_E(GTPU, "try to get a gtp-u not existing output\n"); \ + pthread_mutex_unlock(&globGtp.gtp_lock); \ + return; \ + } \ + gtpEndPoint *inst = &instChk->second; +#define getInstRetInt(insT) \ + auto instChk = globGtp.instances.find(compatInst(insT)); \ + if (instChk == globGtp.instances.end()) { \ + LOG_E(GTPU, "try to get a gtp-u not existing output\n"); \ + pthread_mutex_unlock(&globGtp.gtp_lock); \ + return GTPNOK; \ + } \ + gtpEndPoint *inst = &instChk->second; -#define getUeRetVoid(insT, Ue) \ - auto ptrUe=insT->ue2te_mapping.find(Ue); \ - \ - if ( ptrUe==insT->ue2te_mapping.end() ) { \ +#define getUeRetVoid(insT, Ue) \ + auto ptrUe = insT->ue2te_mapping.find(Ue); \ + \ + if (ptrUe == insT->ue2te_mapping.end()) { \ LOG_E(GTPU, "[%ld] %s failed: while getting ue id %ld in hashtable ue_mapping\n", instance, __func__, ue_id); \ - pthread_mutex_unlock(&globGtp.gtp_lock); \ - return; \ + pthread_mutex_unlock(&globGtp.gtp_lock); \ + return; \ } - -#define getUeRetInt(insT, Ue) \ - auto ptrUe=insT->ue2te_mapping.find(Ue); \ - \ - if ( ptrUe==insT->ue2te_mapping.end() ) { \ + +#define getUeRetInt(insT, Ue) \ + auto ptrUe = insT->ue2te_mapping.find(Ue); \ + \ + if (ptrUe == insT->ue2te_mapping.end()) { \ LOG_E(GTPU, "[%ld] %s failed: while getting ue id %ld in hashtable ue_mapping\n", instance, __func__, ue_id); \ - pthread_mutex_unlock(&globGtp.gtp_lock); \ - return GTPNOK; \ + pthread_mutex_unlock(&globGtp.gtp_lock); \ + return GTPNOK; \ } - + #define HDR_MAX 256 // 256 is supposed to be larger than any gtp header static int gtpv1uCreateAndSendMsg(int h, uint32_t peerIp, @@ -221,29 +224,30 @@ static int gtpv1uCreateAndSendMsg(int h, int npduNum, int extHdrType, uint8_t *extensionHeader_buffer, - uint8_t extensionHeader_length) { + uint8_t extensionHeader_length) +{ LOG_D(GTPU, "Peer IP:%u peer port:%u outgoing teid:%u \n", peerIp, peerPort, teid); DevAssert(msgLen + HDR_MAX < 65536); // maximum size of UDP packet - uint8_t buffer[msgLen+HDR_MAX]; - uint8_t *curPtr=buffer; - Gtpv1uMsgHeaderT *msgHdr = (Gtpv1uMsgHeaderT *)buffer ; + uint8_t buffer[msgLen + HDR_MAX]; + uint8_t *curPtr = buffer; + 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->PN = npduNumFlag; + msgHdr->S = seqNumFlag; msgHdr->E = extHdrType != NO_MORE_EXT_HDRS; - msgHdr->spare=0; - //PT=0 is for GTP' TS 32.295 (charging) - msgHdr->PT=1; - msgHdr->version=1; - msgHdr->msgType=msgType; - msgHdr->teid=htonl(teid); + msgHdr->spare = 0; + // PT=0 is for GTP' TS 32.295 (charging) + msgHdr->PT = 1; + msgHdr->version = 1; + msgHdr->msgType = msgType; + msgHdr->teid = htonl(teid); - curPtr+=sizeof(Gtpv1uMsgHeaderT); + curPtr += sizeof(Gtpv1uMsgHeaderT); if (seqNumFlag || (extHdrType != NO_MORE_EXT_HDRS) || npduNumFlag) { *(uint16_t *)curPtr = seqNumFlag ? seqNum : 0x0000; - curPtr+=sizeof(uint16_t); + curPtr += sizeof(uint16_t); *(uint8_t *)curPtr = npduNumFlag ? npduNum : 0x00; curPtr++; *(uint8_t *)curPtr = extHdrType; @@ -255,7 +259,10 @@ static int gtpv1uCreateAndSendMsg(int h, if (extensionHeader_length > 0) { memcpy(curPtr, extensionHeader_buffer, extensionHeader_length); curPtr += extensionHeader_length; - LOG_D(GTPU, "Extension Header for DDD added. The length is: %d, extension header type is: %x \n", extensionHeader_length, *((uint8_t *)(buffer + 11))); + LOG_D(GTPU, + "Extension Header for DDD added. The length is: %d, extension header type is: %x \n", + extensionHeader_length, + *((uint8_t *)(buffer + 11))); extHdrType = extensionHeader_buffer[extensionHeader_length - 1]; LOG_D(GTPU, "Next extension header type is: %x \n", *((uint8_t *)(buffer + 11))); } else { @@ -263,28 +270,34 @@ static int gtpv1uCreateAndSendMsg(int h, } } - if (Msg!= NULL){ + if (Msg != NULL) { memcpy(curPtr, Msg, msgLen); - curPtr+=msgLen; + curPtr += msgLen; } - msgHdr->msgLength = htons(curPtr-(buffer+sizeof(Gtpv1uMsgHeaderT))); - AssertFatal(curPtr-(buffer+msgLen) < HDR_MAX, "fixed max size of all headers too short"); + msgHdr->msgLength = htons(curPtr - (buffer + sizeof(Gtpv1uMsgHeaderT))); + AssertFatal(curPtr - (buffer + msgLen) < HDR_MAX, "fixed max size of all headers too short"); // Fix me: add IPv6 support, using flag ipVersion - 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: %ld to %s\n",curPtr-buffer, inet_ntoa(to.sin_addr) ); + 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: %ld to %s\n", curPtr - buffer, inet_ntoa(to.sin_addr)); int ret; - if ((ret=sendto(h, (void *)buffer, curPtr-buffer, 0,(struct sockaddr *)&to, sizeof(to) )) != curPtr-buffer ) { - LOG_E(GTPU, "[SD %d] Failed to send data to " IPV4_ADDR " on port %d, buffer size %lu, ret: %d, errno: %d\n", - h, IPV4_ADDR_FORMAT(peerIp), peerPort, curPtr-buffer, ret, errno); + if ((ret = sendto(h, (void *)buffer, curPtr - buffer, 0, (struct sockaddr *)&to, sizeof(to))) != curPtr - buffer) { + LOG_E(GTPU, + "[SD %d] Failed to send data to " IPV4_ADDR " on port %d, buffer size %lu, ret: %d, errno: %d\n", + h, + IPV4_ADDR_FORMAT(peerIp), + peerPort, + curPtr - buffer, + ret, + errno); return GTPNOK; } - return !GTPNOK; + return !GTPNOK; } void gtpv1uSendDirect(instance_t instance, @@ -371,99 +384,104 @@ void gtpv1uSendDirect(instance_t instance, static void gtpv1uEndTunnel(instance_t instance, gtpv1u_enb_end_marker_req_t *req) { - ue_id_t ue_id=req->rnti; - int bearer_id=req->rab_id; + ue_id_t ue_id = req->rnti; + int bearer_id = req->rab_id; pthread_mutex_lock(&globGtp.gtp_lock); getInstRetVoid(compatInst(instance)); getUeRetVoid(inst, ue_id); - auto ptr2=ptrUe->second.bearers.find(bearer_id); + auto ptr2 = ptrUe->second.bearers.find(bearer_id); - if ( ptr2 == ptrUe->second.bearers.end() ) { - LOG_E(GTPU,"[%ld] GTP-U sending a packet to a non existant UE:RAB: %lx/%x\n", instance, ue_id, bearer_id); + if (ptr2 == ptrUe->second.bearers.end()) { + LOG_E(GTPU, "[%ld] GTP-U sending a packet to a non existant UE:RAB: %lx/%x\n", instance, ue_id, bearer_id); pthread_mutex_unlock(&globGtp.gtp_lock); return; } - LOG_D(GTPU,"[%ld] sending a end packet packet to UE:RAB:teid %lx/%x/%x\n", - instance, ue_id, bearer_id,ptr2->second.teid_outgoing); - gtpv1u_bearer_t tmp=ptr2->second; + LOG_D(GTPU, + "[%ld] sending a end packet packet to UE:RAB:teid %lx/%x/%x\n", + instance, + ue_id, + bearer_id, + ptr2->second.teid_outgoing); + gtpv1u_bearer_t tmp = ptr2->second; pthread_mutex_unlock(&globGtp.gtp_lock); - Gtpv1uMsgHeaderT msgHdr; + 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); + 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); + 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; char ip4[INET_ADDRSTRLEN]; - //char ip6[INET6_ADDRSTRLEN]; - LOG_D(GTPU,"[%ld] sending end packet to %s\n", instance, inet_ntoa(to.sin_addr) ); + // char ip6[INET6_ADDRSTRLEN]; + LOG_D(GTPU, "[%ld] sending end packet to %s\n", instance, inet_ntoa(to.sin_addr)); - if (sendto(compatInst(instance), (void *)&msgHdr, sizeof(msgHdr), 0,(struct sockaddr *)&to, sizeof(to) ) != sizeof(msgHdr)) { + if (sendto(compatInst(instance), (void *)&msgHdr, sizeof(msgHdr), 0, (struct sockaddr *)&to, sizeof(to)) != sizeof(msgHdr)) { LOG_E(GTPU, "[%ld] Failed to send data to %s on port %d, buffer size %lu\n", - compatInst(instance), inet_ntop(AF_INET, &tmp.outgoing_ip_addr, ip4, INET_ADDRSTRLEN), tmp.outgoing_port, sizeof(msgHdr)); + compatInst(instance), + inet_ntop(AF_INET, &tmp.outgoing_ip_addr, ip4, INET_ADDRSTRLEN), + tmp.outgoing_port, + sizeof(msgHdr)); } } -static int udpServerSocket(openAddr_s addr) { +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; + 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)); + LOG_E(GTPU, "getaddrinfo error: %s\n", gai_strerror(status)); return -1; } - int sockfd=-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)); + 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)); + LOG_W(GTPU, "bind: %s\n", strerror(errno)); continue; } else { // We create the gtp instance on the socket - globGtp.instances[sockfd].addr=addr; + 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; + 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; + 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"); + AssertFatal(false, "Local address is not IPv4 or IPv6"); } break; // if we get here, we must have connected successfully @@ -473,46 +491,61 @@ static int udpServerSocket(openAddr_s addr) { 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); + LOG_E(GTPU, "failed to bind socket: %s %s \n", addr.originHost, addr.originService); return -1; } - int sendbuff = 1000*1000*10; - AssertFatal(0==setsockopt(sockfd, SOL_SOCKET, SO_SNDBUF, &sendbuff, sizeof(sendbuff)),""); - LOG_D(GTPU,"[%d] Created listener for paquets to: %s:%s, send buffer size: %d\n", sockfd, addr.originHost, addr.originService,sendbuff); + int sendbuff = 1000 * 1000 * 10; + AssertFatal(0 == setsockopt(sockfd, SOL_SOCKET, SO_SNDBUF, &sendbuff, sizeof(sendbuff)), ""); + LOG_D(GTPU, + "[%d] Created listener for paquets to: %s:%s, send buffer size: %d\n", + sockfd, + addr.originHost, + addr.originService, + sendbuff); return sockfd; } -instance_t gtpv1Init(openAddr_t context) { +instance_t gtpv1Init(openAddr_t context) +{ pthread_mutex_lock(&globGtp.gtp_lock); - int id=udpServerSocket(context); + int id = udpServerSocket(context); - if (id>=0) { + if (id >= 0) { itti_subscribe_event_fd(TASK_GTPV1_U, id); } else - LOG_E(GTPU,"can't create GTP-U instance\n"); + LOG_E(GTPU, "can't create GTP-U instance\n"); pthread_mutex_unlock(&globGtp.gtp_lock); LOG_I(GTPU, "Created gtpu instance id: %d\n", id); return id; } -void GtpuUpdateTunnelOutgoingAddressAndTeid(instance_t instance, ue_id_t ue_id, ebi_t bearer_id, in_addr_t newOutgoingAddr, teid_t newOutgoingTeid) { +void GtpuUpdateTunnelOutgoingAddressAndTeid(instance_t instance, + ue_id_t ue_id, + ebi_t bearer_id, + in_addr_t newOutgoingAddr, + teid_t newOutgoingTeid) +{ pthread_mutex_lock(&globGtp.gtp_lock); getInstRetVoid(compatInst(instance)); getUeRetVoid(inst, ue_id); - auto ptr2=ptrUe->second.bearers.find(bearer_id); + auto ptr2 = ptrUe->second.bearers.find(bearer_id); - if ( ptr2 == ptrUe->second.bearers.end() ) { - LOG_E(GTPU,"[%ld] Update tunnel for a existing ue id %lu, but wrong bearer_id %u\n", instance, ue_id, bearer_id); + if (ptr2 == ptrUe->second.bearers.end()) { + LOG_E(GTPU, "[%ld] Update tunnel for a existing ue id %lu, but wrong bearer_id %u\n", instance, ue_id, bearer_id); pthread_mutex_unlock(&globGtp.gtp_lock); return; } ptr2->second.outgoing_ip_addr = newOutgoingAddr; ptr2->second.teid_outgoing = newOutgoingTeid; - LOG_I(GTPU, "[%ld] Tunnel Outgoing TEID updated to %x and address to %x\n", instance, ptr2->second.teid_outgoing, ptr2->second.outgoing_ip_addr); + LOG_I(GTPU, + "[%ld] Tunnel Outgoing TEID updated to %x and address to %x\n", + instance, + ptr2->second.teid_outgoing, + ptr2->second.outgoing_ip_addr); pthread_mutex_unlock(&globGtp.gtp_lock); return; } @@ -526,21 +559,22 @@ teid_t newGtpuCreateTunnel(instance_t instance, transport_layer_addr_t remoteAddr, int port, gtpCallback callBack, - gtpCallbackSDAP callBackSDAP) { + gtpCallbackSDAP callBackSDAP) +{ pthread_mutex_lock(&globGtp.gtp_lock); getInstRetInt(compatInst(instance)); - auto it=inst->ue2te_mapping.find(ue_id); + auto it = inst->ue2te_mapping.find(ue_id); - if ( it != inst->ue2te_mapping.end() && it->second.bearers.find(outgoing_bearer_id) != it->second.bearers.end()) { - LOG_W(GTPU,"[%ld] Create a config for a already existing GTP tunnel (ue id %lu)\n", instance, ue_id); + if (it != inst->ue2te_mapping.end() && it->second.bearers.find(outgoing_bearer_id) != it->second.bearers.end()) { + LOG_W(GTPU, "[%ld] Create a config for a already existing GTP tunnel (ue id %lu)\n", instance, ue_id); inst->ue2te_mapping.erase(it); } - teid_t incoming_teid=gtpv1uNewTeid(); + teid_t incoming_teid = gtpv1uNewTeid(); while (globGtp.te2ue_mapping.find(incoming_teid) != globGtp.te2ue_mapping.end()) { LOG_W(GTPU, "[%ld] generated a random Teid that exists, re-generating (%x)\n", instance, incoming_teid); - incoming_teid=gtpv1uNewTeid(); + incoming_teid = gtpv1uNewTeid(); }; globGtp.te2ue_mapping[incoming_teid].ue_id = ue_id; @@ -550,34 +584,31 @@ teid_t newGtpuCreateTunnel(instance_t instance, globGtp.te2ue_mapping[incoming_teid].callBackSDAP = callBackSDAP; globGtp.te2ue_mapping[incoming_teid].pdusession_id = (uint8_t)outgoing_bearer_id; - gtpv1u_bearer_t *tmp=&inst->ue2te_mapping[ue_id].bearers[outgoing_bearer_id]; + gtpv1u_bearer_t *tmp = &inst->ue2te_mapping[ue_id].bearers[outgoing_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); + memcpy(&tmp->outgoing_ip_addr, remoteAddr.buffer, 4); break; case 16: - memcpy(tmp->outgoing_ip6_addr.s6_addr,remoteAddr.buffer, - 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); + 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 = incoming_teid; - tmp->outgoing_port=port; - tmp->teid_outgoing= outgoing_teid; - tmp->outgoing_qfi=outgoing_qfi; + tmp->outgoing_port = port; + tmp->teid_outgoing = outgoing_teid; + tmp->outgoing_qfi = outgoing_qfi; pthread_mutex_unlock(&globGtp.gtp_lock); char ip4[INET_ADDRSTRLEN]; char ip6[INET6_ADDRSTRLEN]; @@ -593,28 +624,29 @@ teid_t newGtpuCreateTunnel(instance_t instance, } int gtpv1u_create_s1u_tunnel(instance_t instance, - const gtpv1u_enb_create_tunnel_req_t *create_tunnel_req, + const gtpv1u_enb_create_tunnel_req_t *create_tunnel_req, gtpv1u_enb_create_tunnel_resp_t *create_tunnel_resp, gtpCallback callBack) { - LOG_D(GTPU, "[%ld] Start create tunnels for UE ID %u, num_tunnels %d, sgw_S1u_teid %x\n", + LOG_D(GTPU, + "[%ld] Start create tunnels for UE ID %u, num_tunnels %d, sgw_S1u_teid %x\n", instance, create_tunnel_req->rnti, create_tunnel_req->num_tunnels, create_tunnel_req->sgw_S1u_teid[0]); pthread_mutex_lock(&globGtp.gtp_lock); getInstRetInt(compatInst(instance)); - - tcp_udp_port_t dstport=inst->get_dstport(); + + tcp_udp_port_t dstport = inst->get_dstport(); uint8_t addr[inst->foundAddrLen]; memcpy(addr, inst->foundAddr, inst->foundAddrLen); pthread_mutex_unlock(&globGtp.gtp_lock); - + for (int i = 0; i < create_tunnel_req->num_tunnels; i++) { AssertFatal(create_tunnel_req->eps_bearer_id[i] > 4, "From legacy code not clear, seems impossible (bearer=%d)\n", create_tunnel_req->eps_bearer_id[i]); - int incoming_rb_id=create_tunnel_req->eps_bearer_id[i]-4; + int incoming_rb_id = create_tunnel_req->eps_bearer_id[i] - 4; teid_t teid = newGtpuCreateTunnel(compatInst(instance), create_tunnel_req->rnti, incoming_rb_id, @@ -625,24 +657,24 @@ int gtpv1u_create_s1u_tunnel(instance_t instance, dstport, callBack, NULL); - 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->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,addr,sizeof(addr)); - create_tunnel_resp->enb_addr.length= sizeof(addr); + memcpy(create_tunnel_resp->enb_addr.buffer, addr, sizeof(addr)); + create_tunnel_resp->enb_addr.length = sizeof(addr); } return !GTPNOK; } -int 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, "[%ld] Start update tunnels for old RNTI %x, new RNTI %x, num_tunnels %d, sgw_S1u_teid %x, eps_bearer_id %x\n", +int 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, + "[%ld] Start update tunnels for old RNTI %x, new RNTI %x, num_tunnels %d, sgw_S1u_teid %x, eps_bearer_id %x\n", instance, prior_rnti, create_tunnel_req->rnti, @@ -652,22 +684,28 @@ int gtpv1u_update_s1u_tunnel( pthread_mutex_lock(&globGtp.gtp_lock); getInstRetInt(compatInst(instance)); - if ( inst->ue2te_mapping.find(create_tunnel_req->rnti) == inst->ue2te_mapping.end() ) { - LOG_E(GTPU,"[%ld] Update not already existing tunnel (new rnti %x, old rnti %x)\n", - instance, create_tunnel_req->rnti, prior_rnti); + if (inst->ue2te_mapping.find(create_tunnel_req->rnti) == inst->ue2te_mapping.end()) { + LOG_E(GTPU, + "[%ld] Update not already existing tunnel (new rnti %x, old rnti %x)\n", + instance, + create_tunnel_req->rnti, + prior_rnti); } - auto it=inst->ue2te_mapping.find(prior_rnti); + auto it = inst->ue2te_mapping.find(prior_rnti); - if ( it != inst->ue2te_mapping.end() ) { + if (it != inst->ue2te_mapping.end()) { pthread_mutex_unlock(&globGtp.gtp_lock); - AssertFatal(false, "logic bug: update of non-existing tunnel (new ue id %u, old ue id %u)\n", create_tunnel_req->rnti, prior_rnti); + AssertFatal(false, + "logic bug: update of non-existing tunnel (new ue id %u, old ue id %u)\n", + create_tunnel_req->rnti, + prior_rnti); /* we don't know if we need 4G or 5G PDCP and can therefore not create a * new tunnel */ return 0; } - inst->ue2te_mapping[create_tunnel_req->rnti]=it->second; + inst->ue2te_mapping[create_tunnel_req->rnti] = it->second; inst->ue2te_mapping.erase(it); pthread_mutex_unlock(&globGtp.gtp_lock); return 0; @@ -679,7 +717,8 @@ int gtpv1u_create_ngu_tunnel(const instance_t instance, gtpCallback callBack, gtpCallbackSDAP callBackSDAP) { - LOG_D(GTPU, "[%ld] Start create tunnels for ue id %lu, num_tunnels %d, sgw_S1u_teid %x\n", + LOG_D(GTPU, + "[%ld] Start create tunnels for ue id %lu, num_tunnels %d, sgw_S1u_teid %x\n", instance, create_tunnel_req->ue_id, create_tunnel_req->num_tunnels, @@ -702,12 +741,12 @@ int gtpv1u_create_ngu_tunnel(const instance_t instance, dstport, callBack, callBackSDAP); - create_tunnel_resp->status=0; - create_tunnel_resp->ue_id=create_tunnel_req->ue_id; - create_tunnel_resp->num_tunnels=create_tunnel_req->num_tunnels; - create_tunnel_resp->gnb_NGu_teid[i]=teid; - memcpy(create_tunnel_resp->gnb_addr.buffer,addr,sizeof(addr)); - create_tunnel_resp->gnb_addr.length= sizeof(addr); + create_tunnel_resp->status = 0; + create_tunnel_resp->ue_id = create_tunnel_req->ue_id; + create_tunnel_resp->num_tunnels = create_tunnel_req->num_tunnels; + create_tunnel_resp->gnb_NGu_teid[i] = teid; + memcpy(create_tunnel_resp->gnb_addr.buffer, addr, sizeof(addr)); + create_tunnel_resp->gnb_addr.length = sizeof(addr); create_tunnel_resp->pdusession_id[i] = create_tunnel_req->pdusession_id[i]; } @@ -742,11 +781,11 @@ int gtpv1u_update_ue_id(const instance_t instanceP, ue_id_t old_ue_id, ue_id_t n return !GTPNOK; } -int 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 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 newGtpuDeleteOneTunnel(instance_t instance, ue_id_t ue_id, int rb_id) @@ -770,23 +809,21 @@ int newGtpuDeleteOneTunnel(instance_t instance, ue_id_t ue_id, int rb_id) ue_it->second.bearers.erase(rb_id); pthread_mutex_unlock(&globGtp.gtp_lock); LOG_I(GTPU, "Deleted tunnel TEID %d (RB %d) for ue id %ld, remaining bearers:\n", teid, rb_id, ue_id); - for (auto b: ue_it->second.bearers) + for (auto b : ue_it->second.bearers) LOG_I(GTPU, "bearer %ld\n", b.first); return !GTPNOK; } -int newGtpuDeleteAllTunnels(instance_t instance, ue_id_t ue_id) { - LOG_D(GTPU, "[%ld] Start delete tunnels for ue id %lu\n", - instance, ue_id); +int newGtpuDeleteAllTunnels(instance_t instance, ue_id_t ue_id) +{ + LOG_D(GTPU, "[%ld] Start delete tunnels for ue id %lu\n", instance, ue_id); pthread_mutex_lock(&globGtp.gtp_lock); getInstRetInt(compatInst(instance)); getUeRetInt(inst, ue_id); - int nb=0; + int nb = 0; - for (auto j=ptrUe->second.bearers.begin(); - j!=ptrUe->second.bearers.end(); - ++j) { + for (auto j = ptrUe->second.bearers.begin(); j != ptrUe->second.bearers.end(); ++j) { globGtp.te2ue_mapping.erase(j->second.teid_incoming); nb++; } @@ -797,8 +834,8 @@ int newGtpuDeleteAllTunnels(instance_t instance, ue_id_t ue_id) { return !GTPNOK; } -int 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) +{ LOG_D(GTPU, "[%ld] Start delete tunnels for RNTI %x\n", instance, req_pP->rnti); pthread_mutex_lock(&globGtp.gtp_lock); auto inst = &globGtp.instances[compatInst(instance)]; @@ -842,25 +879,24 @@ int gtpv1u_delete_all_s1u_tunnel(const instance_t instance, const rnti_t rnti) int newGtpuDeleteTunnels(instance_t instance, ue_id_t ue_id, int nbTunnels, int *pdusession_id) { - LOG_D(GTPU, "[%ld] Start delete tunnels for ue id %lu\n", - instance, ue_id); + LOG_D(GTPU, "[%ld] Start delete tunnels for ue id %lu\n", instance, ue_id); pthread_mutex_lock(&globGtp.gtp_lock); getInstRetInt(compatInst(instance)); getUeRetInt(inst, ue_id); - int nb=0; + int nb = 0; - for (int i=0; isecond.bearers.find(pdusession_id[i]); + for (int i = 0; i < nbTunnels; i++) { + auto ptr2 = ptrUe->second.bearers.find(pdusession_id[i]); - if ( ptr2 == ptrUe->second.bearers.end() ) { - LOG_E(GTPU,"[%ld] GTP-U instance: delete of not existing tunnel UE ID:RAB: %ld/%x\n", instance, ue_id, pdusession_id[i]); + if (ptr2 == ptrUe->second.bearers.end()) { + LOG_E(GTPU, "[%ld] GTP-U instance: delete of not existing tunnel UE ID:RAB: %ld/%x\n", instance, ue_id, pdusession_id[i]); } else { globGtp.te2ue_mapping.erase(ptr2->second.teid_incoming); nb++; } } - if (ptrUe->second.bearers.size() == 0 ) + if (ptrUe->second.bearers.size() == 0) // no tunnels on this ue id, erase the ue entry inst->ue2te_mapping.erase(ptrUe); @@ -869,56 +905,60 @@ int newGtpuDeleteTunnels(instance_t instance, ue_id_t ue_id, int nbTunnels, int return !GTPNOK; } -int gtpv1u_delete_x2u_tunnel( const instance_t instanceP, - const gtpv1u_enb_delete_tunnel_req_t *const req_pP) { - LOG_E(GTPU,"x2 tunnel not implemented\n"); +int gtpv1u_delete_x2u_tunnel(const instance_t instanceP, const gtpv1u_enb_delete_tunnel_req_t *const req_pP) +{ + LOG_E(GTPU, "x2 tunnel not implemented\n"); return 0; } -int gtpv1u_delete_ngu_tunnel( const instance_t instance, - gtpv1u_gnb_delete_tunnel_req_t *req) { - return newGtpuDeleteTunnels(instance, req->ue_id, req->num_pdusession, req->pdusession_id); +int gtpv1u_delete_ngu_tunnel(const instance_t instance, gtpv1u_gnb_delete_tunnel_req_t *req) +{ + return newGtpuDeleteTunnels(instance, req->ue_id, req->num_pdusession, req->pdusession_id); } -static int Gtpv1uHandleEchoReq(int h, - uint8_t *msgBuf, - uint32_t msgBufLen, - uint16_t peerPort, - uint32_t peerIp) { - Gtpv1uMsgHeaderT *msgHdr = (Gtpv1uMsgHeaderT *) msgBuf; +static int Gtpv1uHandleEchoReq(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 ) { + if (msgHdr->version != 1 || msgHdr->PT != 1) { LOG_E(GTPU, "[%d] Received a packet that is not GTP header\n", h); return GTPNOK; } - if ( msgHdr->S != 1 ) { + if (msgHdr->S != 1) { LOG_E(GTPU, "[%d] Received a echo request packet with no sequence number \n", h); return GTPNOK; } - uint16_t seq=ntohs(*(uint16_t *)(msgHdr+1)); + uint16_t seq = ntohs(*(uint16_t *)(msgHdr + 1)); LOG_D(GTPU, "[%d] Received a echo request, TEID: %d, seq: %hu\n", h, msgHdr->teid, seq); - uint8_t recovery[2]= {14,0}; - return gtpv1uCreateAndSendMsg(h, peerIp, peerPort, GTP_ECHO_RSP, ntohl(msgHdr->teid), recovery, sizeof recovery, true, false, seq, 0, NO_MORE_EXT_HDRS, NULL, 0); + uint8_t recovery[2] = {14, 0}; + return gtpv1uCreateAndSendMsg(h, + peerIp, + peerPort, + GTP_ECHO_RSP, + ntohl(msgHdr->teid), + recovery, + sizeof recovery, + true, + false, + seq, + 0, + NO_MORE_EXT_HDRS, + NULL, + 0); } -static int Gtpv1uHandleError(int h, - uint8_t *msgBuf, - uint32_t msgBufLen, - uint16_t peerPort, - uint32_t peerIp) { +static int Gtpv1uHandleError(int h, uint8_t *msgBuf, uint32_t msgBufLen, uint16_t peerPort, uint32_t peerIp) +{ LOG_E(GTPU, "Received GTP error indication (error handling is missing/not implemented)\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,"Supported extensions to be dev\n"); +static int Gtpv1uHandleSupportedExt(int h, uint8_t *msgBuf, uint32_t msgBufLen, uint16_t peerPort, uint32_t peerIp) +{ + LOG_E(GTPU, "Supported extensions to be dev\n"); int rc = GTPNOK; return rc; } @@ -926,14 +966,11 @@ static int Gtpv1uHandleSupportedExt(int h, // 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; +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 ) { + if (msgHdr->version != 1 || msgHdr->PT != 1) { LOG_E(GTPU, "[%d] Received a packet that is not GTP header\n", h); return GTPNOK; } @@ -945,7 +982,7 @@ static int Gtpv1uHandleEndMarker(int h, auto tunnel = globGtp.te2ue_mapping.find(ntohl(msgHdr->teid)); if (tunnel == globGtp.te2ue_mapping.end()) { - LOG_E(GTPU,"[%d] Received a incoming packet on unknown teid (%x) Dropping!\n", h, msgHdr->teid); + LOG_E(GTPU, "[%d] Received a incoming packet on unknown teid (%x) Dropping!\n", h, msgHdr->teid); pthread_mutex_unlock(&globGtp.gtp_lock); return GTPNOK; } @@ -962,39 +999,27 @@ static int Gtpv1uHandleEndMarker(int h, ctxt.subframe = 0; ctxt.eNB_index = 0; ctxt.brOption = 0; - const srb_flag_t srb_flag=SRB_FLAG_NO; - const rb_id_t rb_id=tunnel->second.incoming_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; + const srb_flag_t srb_flag = SRB_FLAG_NO; + const rb_id_t rb_id = tunnel->second.incoming_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,"[%d] down layer refused incoming packet\n", h); + if (!tunnel->second.callBack(&ctxt, srb_flag, rb_id, mui, confirm, 0, NULL, mode, &sourceL2Id, &destinationL2Id)) + LOG_E(GTPU, "[%d] down layer refused incoming packet\n", h); - LOG_D(GTPU,"[%d] Received END marker packet for: teid:%x\n", h, ntohl(msgHdr->teid)); + LOG_D(GTPU, "[%d] Received END marker packet for: teid:%x\n", h, 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; +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 ) { + if (msgHdr->version != 1 || msgHdr->PT != 1) { LOG_E(GTPU, "[%d] Received a packet that is not GTP header\n", h); return GTPNOK; } @@ -1005,13 +1030,13 @@ static int Gtpv1uHandleGpdu(int h, auto tunnel = globGtp.te2ue_mapping.find(ntohl(msgHdr->teid)); if (tunnel == globGtp.te2ue_mapping.end()) { - LOG_E(GTPU,"[%d] Received a incoming packet on unknown teid (%x) Dropping!\n", h, ntohl(msgHdr->teid)); + LOG_E(GTPU, "[%d] Received a incoming packet on unknown teid (%x) Dropping!\n", h, ntohl(msgHdr->teid)); pthread_mutex_unlock(&globGtp.gtp_lock); return GTPNOK; } /* see TS 29.281 5.1 */ - //Minimum length of GTP-U header if non of the optional fields are present + // Minimum length of GTP-U header if non of the optional fields are present unsigned int offset = sizeof(Gtpv1uMsgHeaderT); int8_t qfi = -1; @@ -1019,7 +1044,7 @@ static int Gtpv1uHandleGpdu(int h, uint32_t NR_PDCP_PDU_SN = 0; /* if E, S, or PN is set then there are 4 more bytes of header */ - if( msgHdr->E || msgHdr->S ||msgHdr->PN) + if (msgHdr->E || msgHdr->S || msgHdr->PN) offset += 4; if (msgHdr->E) { @@ -1030,53 +1055,53 @@ static int Gtpv1uHandleGpdu(int h, extension_header_length = msgBuf[offset]; switch (next_extension_header_type) { case PDU_SESSION_CONTAINER: { - if (offset + sizeof(PDUSessionContainerT) > msgBufLen ) { - LOG_E(GTPU, "gtp-u received header is malformed, ignore gtp packet\n"); - return GTPNOK; - } + if (offset + sizeof(PDUSessionContainerT) > msgBufLen) { + LOG_E(GTPU, "gtp-u received header is malformed, ignore gtp packet\n"); + return GTPNOK; + } PDUSessionContainerT *pdusession_cntr = (PDUSessionContainerT *)(msgBuf + offset + 1); qfi = pdusession_cntr->QFI; rqi = pdusession_cntr->Reflective_QoS_activation; break; } case NR_RAN_CONTAINER: { - if (offset + 1 > msgBufLen ) { - LOG_E(GTPU, "gtp-u received header is malformed, ignore gtp packet\n"); - return GTPNOK; - } - uint8_t PDU_type = (msgBuf[offset+1]>>4) & 0x0f; - if (PDU_type == 0){ //DL USER Data Format - int additional_offset = 6; //Additional offset capturing the first non-mandatory octet (TS 38.425, Figure 5.5.2.1-1) - if(msgBuf[offset+1]>>2 & 0x1){ //DL Discard Blocks flag is present - LOG_I(GTPU, "DL User Data: DL Discard Blocks handling not enabled\n"); - additional_offset = additional_offset + 9; //For the moment ignore + if (offset + 1 > msgBufLen) { + LOG_E(GTPU, "gtp-u received header is malformed, ignore gtp packet\n"); + return GTPNOK; + } + uint8_t PDU_type = (msgBuf[offset + 1] >> 4) & 0x0f; + if (PDU_type == 0) { // DL USER Data Format + int additional_offset = 6; // Additional offset capturing the first non-mandatory octet (TS 38.425, Figure 5.5.2.1-1) + if (msgBuf[offset + 1] >> 2 & 0x1) { // DL Discard Blocks flag is present + LOG_I(GTPU, "DL User Data: DL Discard Blocks handling not enabled\n"); + additional_offset = additional_offset + 9; // For the moment ignore } - if(msgBuf[offset+1]>>1 & 0x1){ //DL Flush flag is present + if (msgBuf[offset + 1] >> 1 & 0x1) { // DL Flush flag is present LOG_I(GTPU, "DL User Data: DL Flush handling not enabled\n"); - additional_offset = additional_offset + 3; //For the moment ignore + additional_offset = additional_offset + 3; // For the moment ignore } - if((msgBuf[offset+2]>>3)& 0x1){ //"Report delivered" enabled (TS 38.425, 5.4) + if ((msgBuf[offset + 2] >> 3) & 0x1) { //"Report delivered" enabled (TS 38.425, 5.4) /*Store the NR PDCP PDU SN for which a delivery status report shall be generated once the *PDU gets forwarded to the lower layers*/ - //NR_PDCP_PDU_SN = msgBuf[offset+6] << 16 | msgBuf[offset+7] << 8 | msgBuf[offset+8]; - NR_PDCP_PDU_SN = msgBuf[offset+additional_offset] << 16 | msgBuf[offset+additional_offset+1] << 8 | msgBuf[offset+additional_offset+2]; - LOG_D(GTPU, " NR_PDCP_PDU_SN: %u \n", NR_PDCP_PDU_SN); + // NR_PDCP_PDU_SN = msgBuf[offset+6] << 16 | msgBuf[offset+7] << 8 | msgBuf[offset+8]; + NR_PDCP_PDU_SN = msgBuf[offset + additional_offset] << 16 | msgBuf[offset + additional_offset + 1] << 8 + | msgBuf[offset + additional_offset + 2]; + LOG_D(GTPU, " NR_PDCP_PDU_SN: %u \n", NR_PDCP_PDU_SN); } - } - else{ + } else { LOG_W(GTPU, "NR-RAN container type: %d not supported \n", PDU_type); } break; } default: LOG_W(GTPU, "unhandled extension 0x%2.2x, skipping\n", next_extension_header_type); - break; + break; } offset += extension_header_length * EXT_HDR_LNTH_OCTET_UNITS; - if (offset > msgBufLen ) { - LOG_E(GTPU, "gtp-u received header is malformed, ignore gtp packet\n"); - return GTPNOK; + if (offset > msgBufLen) { + LOG_E(GTPU, "gtp-u received header is malformed, ignore gtp packet\n"); + return GTPNOK; } next_extension_header_type = msgBuf[offset - 1]; } @@ -1094,51 +1119,43 @@ static int Gtpv1uHandleGpdu(int h, ctxt.subframe = 0; ctxt.eNB_index = 0; ctxt.brOption = 0; - const srb_flag_t srb_flag=SRB_FLAG_NO; - const rb_id_t rb_id=tunnel->second.incoming_rb_id; - const mui_t mui=RLC_MUI_UNDEFINED; - const confirm_t confirm=RLC_SDU_CONFIRM_NO; + const srb_flag_t srb_flag = SRB_FLAG_NO; + const rb_id_t rb_id = tunnel->second.incoming_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; + 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 (sdu_buffer_size > 0) { if (qfi != -1 && tunnel->second.callBackSDAP) { - if ( !tunnel->second.callBackSDAP(&ctxt, - tunnel->second.ue_id, - srb_flag, - rb_id, - mui, - confirm, - sdu_buffer_size, - sdu_buffer, - mode, - &sourceL2Id, - &destinationL2Id, - qfi, - rqi, - tunnel->second.pdusession_id) ) - LOG_E(GTPU,"[%d] down layer refused incoming packet\n", h); + if (!tunnel->second.callBackSDAP(&ctxt, + tunnel->second.ue_id, + srb_flag, + rb_id, + mui, + confirm, + sdu_buffer_size, + sdu_buffer, + mode, + &sourceL2Id, + &destinationL2Id, + qfi, + rqi, + tunnel->second.pdusession_id)) + LOG_E(GTPU, "[%d] down layer refused incoming packet\n", h); } else { - if ( !tunnel->second.callBack(&ctxt, - srb_flag, - rb_id, - mui, - confirm, - sdu_buffer_size, - sdu_buffer, - mode, - &sourceL2Id, - &destinationL2Id) ) - LOG_E(GTPU,"[%d] down layer refused incoming packet\n", h); + if (!tunnel->second + .callBack(&ctxt, srb_flag, rb_id, mui, confirm, sdu_buffer_size, sdu_buffer, mode, &sourceL2Id, &destinationL2Id)) + LOG_E(GTPU, "[%d] down layer refused incoming packet\n", h); } } - if(NR_PDCP_PDU_SN > 0 && NR_PDCP_PDU_SN %5 ==0){ - LOG_D (GTPU, "Create and send DL DATA Delivery status for the previously received PDU, NR_PDCP_PDU_SN: %u \n", NR_PDCP_PDU_SN); + if (NR_PDCP_PDU_SN > 0 && NR_PDCP_PDU_SN % 5 == 0) { + LOG_D(GTPU, "Create and send DL DATA Delivery status for the previously received PDU, NR_PDCP_PDU_SN: %u \n", NR_PDCP_PDU_SN); int rlc_tx_buffer_space = nr_rlc_get_available_tx_space(ctxt.rntiMaybeUEid, rb_id + 3); LOG_D(GTPU, "Available buffer size in RLC for Tx: %d \n", rlc_tx_buffer_space); /*Total size of DDD_status PDU = 1 octet to report extension header length @@ -1146,87 +1163,99 @@ static int Gtpv1uHandleGpdu(int h, * 1 octet for padding + 1 octet for next extension header type, * according to TS 38.425: Fig. 5.5.2.2-1 and section 5.5.3.24*/ extensionHeader_t *extensionHeader; - extensionHeader = (extensionHeader_t *) calloc(1, sizeof(extensionHeader_t)) ; - extensionHeader->buffer[0] = (1+sizeof(DlDataDeliveryStatus_flagsT)+3+1+1)/4; + extensionHeader = (extensionHeader_t *)calloc(1, sizeof(extensionHeader_t)); + extensionHeader->buffer[0] = (1 + sizeof(DlDataDeliveryStatus_flagsT) + 3 + 1 + 1) / 4; DlDataDeliveryStatus_flagsT DlDataDeliveryStatus; DlDataDeliveryStatus.deliveredPdcpSn = 0; - DlDataDeliveryStatus.transmittedPdcpSn= 1; + DlDataDeliveryStatus.transmittedPdcpSn = 1; DlDataDeliveryStatus.pduType = 1; - DlDataDeliveryStatus.drbBufferSize = htonl(rlc_tx_buffer_space); //htonl(10000000); //hardcoded for now but normally we should extract it from RLC - memcpy(extensionHeader->buffer+1, &DlDataDeliveryStatus, sizeof(DlDataDeliveryStatus_flagsT)); - uint8_t offset = sizeof(DlDataDeliveryStatus_flagsT)+1; + DlDataDeliveryStatus.drbBufferSize = + htonl(rlc_tx_buffer_space); // htonl(10000000); //hardcoded for now but normally we should extract it from RLC + memcpy(extensionHeader->buffer + 1, &DlDataDeliveryStatus, sizeof(DlDataDeliveryStatus_flagsT)); + uint8_t offset = sizeof(DlDataDeliveryStatus_flagsT) + 1; - extensionHeader->buffer[offset] = (NR_PDCP_PDU_SN >> 16) & 0xff; - extensionHeader->buffer[offset+1] = (NR_PDCP_PDU_SN >> 8) & 0xff; - extensionHeader->buffer[offset+2] = NR_PDCP_PDU_SN & 0xff; - LOG_D(GTPU, "Octets reporting NR_PDCP_PDU_SN, extensionHeader-> %u:%u:%u \n", + extensionHeader->buffer[offset] = (NR_PDCP_PDU_SN >> 16) & 0xff; + extensionHeader->buffer[offset + 1] = (NR_PDCP_PDU_SN >> 8) & 0xff; + extensionHeader->buffer[offset + 2] = NR_PDCP_PDU_SN & 0xff; + LOG_D(GTPU, + "Octets reporting NR_PDCP_PDU_SN, extensionHeader-> %u:%u:%u \n", extensionHeader->buffer[offset], - extensionHeader->buffer[offset+1], - extensionHeader->buffer[offset+2]); - extensionHeader->buffer[offset+3] = 0x00; //Padding octet - extensionHeader->buffer[offset+4] = 0x00; //No more extension headers + extensionHeader->buffer[offset + 1], + extensionHeader->buffer[offset + 2]); + extensionHeader->buffer[offset + 3] = 0x00; // Padding octet + extensionHeader->buffer[offset + 4] = 0x00; // No more extension headers /*Total size of DDD_status PDU = size of mandatory part + * 3 octets for highest transmitted/delivered PDCP SN + * 1 octet for padding + 1 octet for next extension header type, * according to TS 38.425: Fig. 5.5.2.2-1 and section 5.5.3.24*/ - extensionHeader->length = 1+sizeof(DlDataDeliveryStatus_flagsT)+3+1+1; - gtpv1uCreateAndSendMsg( - h, peerIp, peerPort, GTP_GPDU, globGtp.te2ue_mapping[ntohl(msgHdr->teid)].outgoing_teid, NULL, 0, false, false, 0, 0, NR_RAN_CONTAINER, extensionHeader->buffer, extensionHeader->length); + extensionHeader->length = 1 + sizeof(DlDataDeliveryStatus_flagsT) + 3 + 1 + 1; + gtpv1uCreateAndSendMsg(h, + peerIp, + peerPort, + GTP_GPDU, + globGtp.te2ue_mapping[ntohl(msgHdr->teid)].outgoing_teid, + NULL, + 0, + false, + false, + 0, + 0, + NR_RAN_CONTAINER, + extensionHeader->buffer, + extensionHeader->length); } - LOG_D(GTPU,"[%d] Received a %d bytes packet for: teid:%x\n", h, - msgBufLen-offset, - ntohl(msgHdr->teid)); + LOG_D(GTPU, "[%d] Received a %d bytes packet for: teid:%x\n", h, msgBufLen - offset, ntohl(msgHdr->teid)); return !GTPNOK; } -void gtpv1uReceiver(int h) { - uint8_t udpData[65536]; - int udpDataLen; - socklen_t from_len; +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) { + if ((udpDataLen = recvfrom(h, udpData, sizeof(udpData), 0, (struct sockaddr *)&addr, &from_len)) < 0) { LOG_E(GTPU, "[%d] Recvfrom failed (%s)\n", h, strerror(errno)); return; } else if (udpDataLen == 0) { LOG_W(GTPU, "[%d] Recvfrom returned 0\n", h); return; } else { - if ( udpDataLen < (int)sizeof(Gtpv1uMsgHeaderT) ) { + if (udpDataLen < (int)sizeof(Gtpv1uMsgHeaderT)) { LOG_W(GTPU, "[%d] received malformed gtp packet \n", h); return; } - Gtpv1uMsgHeaderT* msg=(Gtpv1uMsgHeaderT*) udpData; - if ( (int)(ntohs(msg->msgLength) + sizeof(Gtpv1uMsgHeaderT)) != udpDataLen ) { + Gtpv1uMsgHeaderT *msg = (Gtpv1uMsgHeaderT *)udpData; + if ((int)(ntohs(msg->msgLength) + sizeof(Gtpv1uMsgHeaderT)) != udpDataLen) { LOG_W(GTPU, "[%d] received malformed gtp packet length\n", h); return; } LOG_D(GTPU, "[%d] Received GTP data, msg type: %x\n", h, msg->msgType); - switch(msg->msgType) { + switch (msg->msgType) { case GTP_ECHO_RSP: break; case GTP_ECHO_REQ: - Gtpv1uHandleEchoReq( h, udpData, udpDataLen, htons(addr.sin_port), addr.sin_addr.s_addr); + 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); + 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); + 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); + 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); + Gtpv1uHandleGpdu(h, udpData, udpDataLen, htons(addr.sin_port), addr.sin_addr.s_addr); break; default: @@ -1238,8 +1267,9 @@ void gtpv1uReceiver(int h) { #include -void *gtpv1uTask(void *args) { - while(1) { +void *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. @@ -1247,8 +1277,8 @@ void *gtpv1uTask(void *args) { MessageDef *message_p = NULL; itti_receive_msg(TASK_GTPV1_U, &message_p); - if (message_p != NULL ) { - openAddr_t addr= {{0}}; + if (message_p != NULL) { + openAddr_t addr = {{0}}; const instance_t myInstance = ITTI_MSG_DESTINATION_INSTANCE(message_p); const int msgType = ITTI_MSG_ID(message_p); LOG_D(GTPU, "GTP-U received %s for instance %ld\n", messages_info[msgType].name, myInstance); @@ -1278,8 +1308,8 @@ void *gtpv1uTask(void *args) { // to be dev: should be removed, to use API strcpy(addr.originHost, GTPV1U_REQ(message_p).localAddrStr); strcpy(addr.originService, GTPV1U_REQ(message_p).localPortStr); - strcpy(addr.destinationService,addr.originService); - AssertFatal((legacyInstanceMapping=gtpv1Init(addr))!=0,"Instance 0 reserved for legacy\n"); + strcpy(addr.destinationService, addr.originService); + AssertFatal((legacyInstanceMapping = gtpv1Init(addr)) != 0, "Instance 0 reserved for legacy\n"); break; default: @@ -1288,14 +1318,14 @@ void *gtpv1uTask(void *args) { break; } - AssertFatal(EXIT_SUCCESS==itti_free(TASK_GTPV1_U, message_p), "Failed to free memory!\n"); + AssertFatal(EXIT_SUCCESS == itti_free(TASK_GTPV1_U, message_p), "Failed to free memory!\n"); } struct epoll_event events[20]; int nb_events = itti_get_events(TASK_GTPV1_U, events, 20); for (int i = 0; i < nb_events; i++) - if ((events[i].events&EPOLLIN)) + if ((events[i].events & EPOLLIN)) gtpv1uReceiver(events[i].data.fd); }