void nwEgtPingHandleSignal(int sigNum) { printf("\n--- %s ("NW_IPV4_ADDR") EGTPING statistics --- ", egtPing.targetIpStr, NW_IPV4_ADDR_FORMAT(inet_addr(egtPing.targetIpStr))); printf("\n%u requests sent, %u response received, %d%% packet loss \n\n", udpObj.packetsSent, udpObj.packetsRcvd, (udpObj.packetsSent ? 100 * (udpObj.packetsSent - udpObj.packetsRcvd ) / udpObj.packetsSent : 0) ); exit(sigNum); }
NwSdpRcT nwSdpProcessGtpuDataIndication(NwSdpT* thiz, NwSdpFlowContextT* pFlowContext, NwGtpv1uMsgHandleT hMsg) { NwSdpRcT rc; /* * Send Message Request to GTPv1u Stack Instance */ switch(pFlowContext->egressEndPoint.flowType) { case NW_FLOW_TYPE_IPv4: { NwIpv4UlpApiT ulpReq; NwU8T* pIpv4Pdu; if(thiz->hIpv4Stack) { /* Send over IP*/ rc = nwIpv4MsgFromBufferNew(thiz->hIpv4Stack, nwGtpv1uMsgGetTpduHandle(hMsg), nwGtpv1uMsgGetTpduLength(hMsg), &(ulpReq.apiInfo.sendtoInfo.hMsg)); NW_ASSERT(NW_OK == rc); #ifdef NW_SDP_RESPOND_ICMP_PING pIpv4Pdu = nwIpv4MsgGetBufHandle(thiz->hIpv4Stack, ulpReq.apiInfo.sendtoInfo.hMsg); if(*(pIpv4Pdu + 20) == 0x08) { #define NW_MAX_ICMP_PING_DATA_SIZE (1024) NwU8T pingRspPdu[14 + NW_MAX_ICMP_PING_DATA_SIZE]; NwU32T pingRspPduLen; *(pIpv4Pdu + 20) = 0x00; pingRspPdu[12] = 0x08; pingRspPdu[13] = 0x00; pingRspPduLen = (NW_MAX_ICMP_PING_DATA_SIZE > nwIpv4MsgGetLength(thiz->hIpv4Stack, ulpReq.apiInfo.sendtoInfo.hMsg) ? nwIpv4MsgGetLength(thiz->hIpv4Stack, ulpReq.apiInfo.sendtoInfo.hMsg) : NW_MAX_ICMP_PING_DATA_SIZE); memcpy(pingRspPdu + 14, pIpv4Pdu, pingRspPduLen); memcpy(pingRspPdu + 14 + 16, pIpv4Pdu + 12, 4); memcpy(pingRspPdu + 14 + 12, pIpv4Pdu + 16, 4); /* TODO: Add ip-checksum */ rc = nwSdpProcessIpv4DataInd(thiz, 0, pingRspPdu, pingRspPduLen + 14); } else { #endif ulpReq.apiType = NW_IPv4_ULP_API_SEND_TPDU; rc = nwIpv4ProcessUlpReq(thiz->hIpv4Stack, &ulpReq); NW_ASSERT( rc == NW_SDP_OK ); #ifdef NW_SDP_RESPOND_ICMP_PING } #endif rc = nwIpv4MsgDelete(thiz->hIpv4Stack, (ulpReq.apiInfo.sendtoInfo.hMsg)); NW_ASSERT( rc == NW_SDP_OK ); } else { NW_LOG(thiz, NW_LOG_LEVEL_ERRO, "Cannot send PDU over IPv4! IPv4 service does not exist on data plane."); } } break; case NW_FLOW_TYPE_GTPU: { NwGtpv1uUlpApiT ulpReq; ulpReq.apiType = NW_GTPV1U_ULP_API_SEND_TPDU; ulpReq.apiInfo.sendtoInfo.teid = pFlowContext->egressEndPoint.flowKey.gtpuTeid; ulpReq.apiInfo.sendtoInfo.ipAddr = pFlowContext->egressEndPoint.ipv4Addr; if(thiz->hGtpv1uStack) { rc = nwGtpv1uMsgFromMsgNew( thiz->hGtpv1uStack, hMsg, &(ulpReq.apiInfo.sendtoInfo.hMsg)); NW_ASSERT( rc == NW_SDP_OK ); rc = nwGtpv1uProcessUlpReq(thiz->hGtpv1uStack, &ulpReq); NW_ASSERT( rc == NW_SDP_OK ); rc = nwGtpv1uMsgDelete(thiz->hGtpv1uStack, (ulpReq.apiInfo.sendtoInfo.hMsg)); NW_ASSERT( rc == NW_SDP_OK ); NW_LOG(thiz, NW_LOG_LEVEL_DEBG, "Sending GTPU PDU over teid 0x%x "NW_IPV4_ADDR, ulpReq.apiInfo.sendtoInfo.teid, NW_IPV4_ADDR_FORMAT(ntohl(ulpReq.apiInfo.sendtoInfo.ipAddr))); } else { NW_LOG(thiz, NW_LOG_LEVEL_ERRO, "Cannot send PDU over GTPU! GTPU service does not exist on data plane."); } } break; case NW_FLOW_TYPE_GRE: { NW_LOG(thiz, NW_LOG_LEVEL_WARN, "Cannot send TPDU over GRE! Not supported yet!"); } break; default: { NW_LOG(thiz, NW_LOG_LEVEL_ERRO, "Unsupported egress flow end point type! Dropping GTP TPDU."); } break; } return NW_SDP_OK; }
NwSdpRcT nwSdpProcessIpv4DataIndication(NwSdpT* thiz, NwSdpFlowContextT* pFlowContext, NwIpv4MsgHandleT hMsg) { NwSdpRcT rc; /* * Send Message Request to GTPv1u Stack Instance */ switch(pFlowContext->egressEndPoint.flowType) { case NW_FLOW_TYPE_GTPU: { NwGtpv1uUlpApiT ulpReq; NW_ASSERT(pFlowContext->egressEndPoint.ipv4Addr != 0); NW_LOG(thiz, NW_LOG_LEVEL_DEBG, "Sending IP PDU over GTPU teid 0x%x to "NW_IPV4_ADDR, pFlowContext->egressEndPoint.flowKey.gtpuTeid, NW_IPV4_ADDR_FORMAT(htonl(pFlowContext->egressEndPoint.ipv4Addr))); ulpReq.apiType = NW_GTPV1U_ULP_API_SEND_TPDU; ulpReq.apiInfo.sendtoInfo.teid = pFlowContext->egressEndPoint.flowKey.gtpuTeid; ulpReq.apiInfo.sendtoInfo.ipAddr = pFlowContext->egressEndPoint.ipv4Addr; rc = nwGtpv1uGpduMsgNew( thiz->hGtpv1uStack, pFlowContext->egressEndPoint.flowKey.gtpuTeid, /* TEID */ NW_FALSE, /* Seq Num Present Flag */ 0, /* seqNum */ (NwU8T*) nwIpv4MsgGetBufHandle(thiz->hIpv4Stack, hMsg), nwIpv4MsgGetLength(thiz->hIpv4Stack, hMsg), (NwGtpv1uMsgHandleT*)&(ulpReq.apiInfo.sendtoInfo.hMsg)); NW_ASSERT( rc == NW_SDP_OK ); rc = nwGtpv1uProcessUlpReq(thiz->hGtpv1uStack, &ulpReq); NW_ASSERT( rc == NW_SDP_OK ); rc = nwGtpv1uMsgDelete(thiz->hGtpv1uStack, (ulpReq.apiInfo.sendtoInfo.hMsg)); NW_ASSERT( rc == NW_SDP_OK ); } break; case NW_FLOW_TYPE_GRE: { NW_LOG(thiz, NW_LOG_LEVEL_DEBG, "Cannot send IP PDU over GRE! Not supported yet!"); } break; default: { NW_LOG(thiz, NW_LOG_LEVEL_ERRO, "Unsupported egress flow end point type! Dropping IP PDU."); } break; } return NW_SDP_OK; }
static NwSdpRcT nwSdpCreateFlowEndPoint( NW_IN NwSdpT* thiz, NW_IN NwSdpFlowContextT* pFlowContext, NW_IN NwSdpFlowEndPointT* pFlowEndPoint) { NwSdpRcT rc = NW_SDP_OK; switch(pFlowEndPoint->flowType) { case NW_FLOW_TYPE_IPv4: { NwIpv4UlpApiT ulpReq; NW_LOG(thiz, NW_LOG_LEVEL_DEBG, "Creating IPv4 tunnel endpoint with teid "NW_IPV4_ADDR, NW_IPV4_ADDR_FORMAT(pFlowEndPoint->flowKey.ipv4Addr)); if(thiz->hIpv4Stack) { ulpReq.apiType = NW_IPv4_ULP_API_CREATE_TUNNEL_ENDPOINT; ulpReq.apiInfo.createTunnelEndPointInfo.ipv4Addr = pFlowEndPoint->flowKey.ipv4Addr; ulpReq.apiInfo.createTunnelEndPointInfo.hUlpSession = (NwGtpv1uUlpSessionHandleT)pFlowContext; rc = nwIpv4ProcessUlpReq(thiz->hIpv4Stack, &ulpReq); pFlowEndPoint->hTunnelEndPoint.ipv4 = ulpReq.apiInfo.createTunnelEndPointInfo.hStackSession; } else { NW_LOG(thiz, NW_LOG_LEVEL_ERRO, "IPv4 service does not exist on data plane!"); rc = NW_SDP_OK; } } break; case NW_FLOW_TYPE_GTPU: { NwGtpv1uUlpApiT ulpReq; NW_LOG(thiz, NW_LOG_LEVEL_DEBG, "Creating GTPU tunnel endpoint with teid 0x%x", pFlowEndPoint->flowKey.gtpuTeid); if(thiz->hGtpv1uStack) { ulpReq.apiType = NW_GTPV1U_ULP_API_CREATE_TUNNEL_ENDPOINT; ulpReq.apiInfo.createTunnelEndPointInfo.teid = pFlowEndPoint->flowKey.gtpuTeid; ulpReq.apiInfo.createTunnelEndPointInfo.hUlpSession = (NwGtpv1uUlpSessionHandleT)pFlowContext; rc = nwGtpv1uProcessUlpReq(thiz->hGtpv1uStack, &ulpReq); pFlowEndPoint->hTunnelEndPoint.gtpu = ulpReq.apiInfo.createTunnelEndPointInfo.hStackSession; } else { NW_LOG(thiz, NW_LOG_LEVEL_ERRO, "GTPU service does not exist on data plane!"); rc = NW_SDP_OK; } } break; case NW_FLOW_TYPE_GRE: { NwGreUlpApiT ulpReq; NW_LOG(thiz, NW_LOG_LEVEL_DEBG, "Creating GRE tunnel endpoint with key %d", pFlowEndPoint->flowKey.greKey); if(thiz->hGreStack) { ulpReq.apiType = NW_GRE_ULP_API_CREATE_TUNNEL_ENDPOINT; ulpReq.apiInfo.createTunnelEndPointInfo.greKey = pFlowEndPoint->flowKey.greKey; ulpReq.apiInfo.createTunnelEndPointInfo.hUlpSession = (NwGtpv1uUlpSessionHandleT)pFlowContext; rc = nwGreProcessUlpReq(thiz->hGreStack, &ulpReq); pFlowEndPoint->hTunnelEndPoint.gre = ulpReq.apiInfo.createTunnelEndPointInfo.hStackSession; } else { NW_LOG(thiz, NW_LOG_LEVEL_ERRO, "GRE service does not exist on data plane!"); rc = NW_SDP_OK; } } break; case NW_FLOW_TYPE_UDP: { #ifdef NW_SDP_SUPPORT_UDP_FLOW_TYPE /* * Create local udp listening endpoint */ struct sockaddr_in addr; int sd = socket(AF_INET, SOCK_DGRAM, 0); if (sd < 0) { NW_LOG(thiz, NW_LOG_LEVEL_ERRO, "%s", strerror(errno)); NW_ASSERT(0); } addr.sin_family = AF_INET; addr.sin_port = htons(pFlowEndPoint->flowKey.udp.port); addr.sin_addr.s_addr = pFlowEndPoint->flowKey.udp.ipv4Addr; memset(addr.sin_zero, '\0', sizeof (addr.sin_zero)); if(bind(sd, (struct sockaddr *)&addr, sizeof(addr)) < 0) { NW_LOG(thiz, NW_LOG_LEVEL_ERRO, "bind - %s", strerror(errno)); } NW_LOG(thiz, NW_LOG_LEVEL_NOTI, "Creating UDP tunnel endpoint with port %d", pFlowEndPoint->flowKey.udp.port); event_set(&(pFlowContext->ev), sd, EV_READ|EV_PERSIST, nwSdpUdpDataIndicationCallback, pFlowContext); event_add(&(pFlowContext->ev), NULL); pFlowEndPoint->hTunnelEndPoint.udp = sd; #else NW_LOG(thiz, NW_LOG_LEVEL_ERRO, "Flow type UDP not supported"); #endif } break; default: { NW_LOG(thiz, NW_LOG_LEVEL_NOTI, "Unsupported encapsulation type %u", pFlowEndPoint->flowType); return NW_SDP_FAILURE; } } return NW_SDP_OK; }
int main(int argc, char* argv[]) { NwRcT rc; uint32_t logLevel; uint8_t* logLevelStr; NwGtpv2cStackHandleT hGtpv2cStack = 0; NwGtpv2cUlpEntityT ulp; NwGtpv2cUdpEntityT udp; NwGtpv2cTimerMgrEntityT tmrMgr; NwGtpv2cLogMgrEntityT logMgr; printf("EGTPING 0.1, Copyright (C) 2011 Amit Chawre.\n"); rc = nwEgtPingParseCmdLineOpts(argc, argv); if(rc != NW_OK) { rc = nwEgtPingHelp(); exit(rc); } logLevelStr = getenv ("NW_LOG_LEVEL"); if(logLevelStr == NULL) { logLevel = NW_LOG_LEVEL_INFO; } else { if(strncmp(logLevelStr, "EMER",4) == 0) logLevel = NW_LOG_LEVEL_EMER; else if(strncmp(logLevelStr, "ALER",4) == 0) logLevel = NW_LOG_LEVEL_ALER; else if(strncmp(logLevelStr, "CRIT",4) == 0) logLevel = NW_LOG_LEVEL_CRIT; else if(strncmp(logLevelStr, "ERRO",4) == 0) logLevel = NW_LOG_LEVEL_ERRO ; else if(strncmp(logLevelStr, "WARN",4) == 0) logLevel = NW_LOG_LEVEL_WARN; else if(strncmp(logLevelStr, "NOTI",4) == 0) logLevel = NW_LOG_LEVEL_NOTI; else if(strncmp(logLevelStr, "INFO",4) == 0) logLevel = NW_LOG_LEVEL_INFO; else if(strncmp(logLevelStr, "DEBG",4) == 0) logLevel = NW_LOG_LEVEL_DEBG; } /*--------------------------------------------------------------------------- * Initialize event library *--------------------------------------------------------------------------*/ NW_EVT_INIT(); /*--------------------------------------------------------------------------- * Initialize Log Manager *--------------------------------------------------------------------------*/ nwMiniLogMgrInit(nwMiniLogMgrGetInstance(), logLevel); /*--------------------------------------------------------------------------- * Initialize Gtpv2c Stack Instance *--------------------------------------------------------------------------*/ rc = nwGtpv2cInitialize(&hGtpv2cStack); if(rc != NW_OK) { NW_LOG(NW_LOG_LEVEL_ERRO, "Failed to create gtpv2c stack instance. Error '%u' occured", rc); exit(1); } rc = nwGtpv2cSetLogLevel(hGtpv2cStack, logLevel); /*--------------------------------------------------------------------------- * Set up Ulp Entity *--------------------------------------------------------------------------*/ rc = nwGtpv2cUlpInit(&ulpObj, hGtpv2cStack, egtPing.localIpStr); NW_ASSERT(NW_OK == rc); ulp.hUlp = (NwGtpv2cUlpHandleT) &ulpObj; ulp.ulpReqCallback = nwGtpv2cUlpProcessStackReqCallback; rc = nwGtpv2cSetUlpEntity(hGtpv2cStack, &ulp); NW_ASSERT(NW_OK == rc); /*--------------------------------------------------------------------------- * Set up Udp Entity *--------------------------------------------------------------------------*/ rc = nwGtpv2cUdpInit(&udpObj, hGtpv2cStack, egtPing.localIpStr); NW_ASSERT(NW_OK == rc); udp.hUdp = (NwGtpv2cUdpHandleT) &udpObj; udp.udpDataReqCallback = nwGtpv2cUdpDataReq; rc = nwGtpv2cSetUdpEntity(hGtpv2cStack, &udp); NW_ASSERT(NW_OK == rc); /*--------------------------------------------------------------------------- * Set up Log Entity *--------------------------------------------------------------------------*/ tmrMgr.tmrMgrHandle = 0; tmrMgr.tmrStartCallback = nwTimerStart; tmrMgr.tmrStopCallback = nwTimerStop; rc = nwGtpv2cSetTimerMgrEntity(hGtpv2cStack, &tmrMgr); NW_ASSERT(NW_OK == rc); /*--------------------------------------------------------------------------- * Set up Log Entity *--------------------------------------------------------------------------*/ logMgr.logMgrHandle = (NwGtpv2cLogMgrHandleT) nwMiniLogMgrGetInstance(); logMgr.logReqCallback = nwMiniLogMgrLogRequest; rc = nwGtpv2cSetLogMgrEntity(hGtpv2cStack, &logMgr); NW_ASSERT(NW_OK == rc); /*--------------------------------------------------------------------------- * Send Message Request to Gtpv2c Stack Instance *--------------------------------------------------------------------------*/ NW_LOG(NW_LOG_LEVEL_NOTI, "EGTPING %s ("NW_IPV4_ADDR")", egtPing.targetIpStr, NW_IPV4_ADDR_FORMAT(inet_addr(egtPing.targetIpStr))); rc = nwGtpv2cUlpPing(&ulpObj, inet_addr(egtPing.targetIpStr), egtPing.pingCount, egtPing.pingInterval, 2, 3); NW_ASSERT(NW_OK == rc); /*--------------------------------------------------------------------------- * Install signal handler *--------------------------------------------------------------------------*/ signal(SIGINT, nwEgtPingHandleSignal); /*--------------------------------------------------------------------------- * Event loop *--------------------------------------------------------------------------*/ NW_EVT_LOOP(); NW_LOG(NW_LOG_LEVEL_ERRO, "Exit from eventloop, no events to process!"); /*--------------------------------------------------------------------------- * Destroy Gtpv2c Stack Instance *--------------------------------------------------------------------------*/ rc = nwGtpv2cFinalize(hGtpv2cStack); if(rc != NW_OK) { NW_LOG(NW_LOG_LEVEL_ERRO, "Failed to finalize gtpv2c stack instance. Error '%u' occured", rc); } return rc; }
static NwGtpv1uRcT nwGtpv1uProcessGpdu( NwGtpv1uStackT *thiz, NW_IN uint8_t *gpdu, NW_IN uint32_t gpduLen, NW_IN uint32_t peerIp) { NwGtpv1uRcT rc = NW_GTPV1U_FAILURE; NwGtpv1uMsgHeaderT *msgHdr = NULL; NwGtpv1uTunnelEndPointT *pTunnelEndPoint = NULL; NwGtpv1uTunnelEndPointT tunnelEndPointKey; // uint16_t hdr_len = 0; #if defined(LOG_GTPU) && LOG_GTPU > 0 NW_ENTER(thiz); #endif // no buffer offset msgHdr = (NwGtpv1uMsgHeaderT *) gpdu; tunnelEndPointKey.teid = ntohl(msgHdr->teid); pTunnelEndPoint = RB_FIND(NwGtpv1uTunnelEndPointIdentifierMap, &(thiz->teidMap), &tunnelEndPointKey); if(pTunnelEndPoint) { NwGtpv1uMsgHandleT hMsg; rc = nwGtpv1uMsgFromBufferNew( (NwGtpv1uStackHandleT)thiz, (uint8_t *)gpdu, gpduLen, &hMsg); /* uint8_t* msgBuf; uint32_t msgBufLen; uint32_t msgBufOffset; */ if(NW_GTPV1U_OK == rc) { NwGtpv1uMsgT *pMsg = (NwGtpv1uMsgT *) hMsg; #if defined(LOG_GTPU) && LOG_GTPU > 0 GTPU_DEBUG("Received T-PDU over tunnel end-point '%x' of size %u (%u) (decapsulated %u)from "NW_IPV4_ADDR"\n", ntohl(msgHdr->teid), gpduLen, pMsg->msgLen, pMsg->msgBufLen, NW_IPV4_ADDR_FORMAT((peerIp))); #endif MSC_LOG_RX_MESSAGE( (thiz->stackType == GTPU_STACK_ENB) ? MSC_GTPU_ENB:MSC_GTPU_SGW, (thiz->stackType == GTPU_STACK_ENB) ? MSC_GTPU_SGW:MSC_GTPU_ENB, NULL, 0, " G-PDU ltid %u size %u", tunnelEndPointKey.teid, gpduLen); rc = nwGtpSessionSendMsgApiToUlpEntity(pTunnelEndPoint, pMsg); } } else { MSC_LOG_RX_DISCARDED_MESSAGE( (thiz->stackType == GTPU_STACK_ENB) ? MSC_GTPU_ENB:MSC_GTPU_SGW, (thiz->stackType == GTPU_STACK_ENB) ? MSC_GTPU_SGW:MSC_GTPU_ENB, NULL, 0, " G-PDU ltid %u size %u", tunnelEndPointKey.teid, gpduLen); GTPU_ERROR("Received T-PDU over non-existent tunnel end-point '%x' from "NW_IPV4_ADDR"\n", ntohl(msgHdr->teid), NW_IPV4_ADDR_FORMAT((peerIp))); } #if defined(LOG_GTPU) && LOG_GTPU > 0 NW_LEAVE(thiz); #endif return rc; }