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);
}
Beispiel #2
0
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;
}
Beispiel #3
0
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;
}
Beispiel #4
0
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;
}