gtpv1u_eNB.c 65.7 KB
Newer Older
1 2 3 4 5
/*
 * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The OpenAirInterface Software Alliance licenses this file to You under
6
 * the OAI Public License, Version 1.1  (the "License"); you may not use this file
7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
 * except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.openairinterface.org/?page_id=698
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *-------------------------------------------------------------------------------
 * For more information about the OpenAirInterface (OAI) Software Alliance:
 *      contact@openairinterface.org
 */

22 23
/*! \file gtpv1u_eNB.c
 * \brief
24
 * \author Sebastien ROUX, Lionel GAUTHIER, Navid Nikaein
25 26 27 28
 * \version 1.0
 * \company Eurecom
 * \email: lionel.gauthier@eurecom.fr
 */
Cedric Roux's avatar
 
Cedric Roux committed
29 30 31
#include <stdio.h>
#include <errno.h>

32 33
#include "mme_config.h"

34
#include "assertions.h"
35
#include "intertask_interface.h"
Lionel Gauthier's avatar
Lionel Gauthier committed
36
#include "msc.h"
37 38

#include "gtpv1u.h"
Cedric Roux's avatar
 
Cedric Roux committed
39 40
#include "NwGtpv1u.h"
#include "NwGtpv1uMsg.h"
Lionel Gauthier's avatar
 
Lionel Gauthier committed
41
#include "NwGtpv1uPrivate.h"
Cedric Roux's avatar
 
Cedric Roux committed
42 43
#include "NwLog.h"
#include "gtpv1u_eNB_defs.h"
44
#include "gtpv1_u_messages_types.h"
Lionel Gauthier's avatar
Lionel Gauthier committed
45
#include "udp_eNB_task.h"
46
#include "common/utils/LOG/log.h"
Cedric Roux's avatar
 
Cedric Roux committed
47
#include "COMMON/platform_types.h"
48
#include "COMMON/platform_constants.h"
49
#include "common/utils/LOG/vcd_signal_dumper.h"
50
#include "common/ran_context.h"
51
#include "gtpv1u_eNB_defs.h"
laurent's avatar
laurent committed
52
#include "gtpv1u_eNB_task.h"
luaihui's avatar
luaihui committed
53
#include "rrc_eNB_GTPV1U.h"
54

55
#undef GTP_DUMP_SOCKET
56

57
extern unsigned char NB_eNB_INST;
58
extern RAN_CONTEXT_t RC;
Lionel Gauthier's avatar
Lionel Gauthier committed
59

60
extern struct rrc_eNB_ue_context_s *
luaihui's avatar
luaihui committed
61
rrc_eNB_get_ue_context(
62
  eNB_RRC_INST *rrc_instance_pP,
luaihui's avatar
luaihui committed
63 64
  rnti_t rntiP);

65
#if defined(GTP_DUMP_SOCKET) && GTP_DUMP_SOCKET > 0
66 67 68 69
#include <linux/if.h>
static int           gtpv1u_dump_socket_g;

//-----------------------------------------------------------------------------
frtabu's avatar
frtabu committed
70
int gtpv1u_eNB_create_dump_socket(void) {
71 72 73 74
  struct ifreq ifr;
  int          hdrincl=1;

  if ((gtpv1u_dump_socket_g = socket(AF_INET, SOCK_RAW, IPPROTO_RAW)) < 0 ) {
75 76
    LOG_E(GTPU, "Could not create dump socket %d:%s\n", errno, strerror(errno));
    return -1;
77 78 79
  }

  if (setsockopt(gtpv1u_dump_socket_g,
80 81 82 83 84
                 IPPROTO_IP,
                 IP_HDRINCL,
                 &hdrincl,
                 sizeof(hdrincl))==-1) {
    LOG_E(GTPU, "%s:%d set IP_HDRINCL %d:%s\n",
85 86 87 88 89
          __FILE__, __LINE__, errno, strerror(errno));
  }

  memset(&ifr, 0, sizeof(ifr));
  snprintf(ifr.ifr_name, sizeof(ifr.ifr_name), "lo");
90 91 92

  if (setsockopt(gtpv1u_dump_socket_g, SOL_SOCKET, SO_BINDTODEVICE, (void *)&ifr, sizeof(ifr)) < 0) {
    LOG_E(GTPU, "%s:%d  setsockopt SO_BINDTODEVICE %d:%s\n",
93
          __FILE__, __LINE__, errno, strerror(errno));
94 95
    close(gtpv1u_dump_socket_g);
    return -1;
96 97 98 99
  }
}

//-----------------------------------------------------------------------------
frtabu's avatar
frtabu committed
100
static void gtpv1u_eNB_write_dump_socket(uint8_t *buffer_pP, uint32_t buffer_lengthP) {
101 102 103 104 105 106
  struct sockaddr_in sin;
  memset(&sin, 0, sizeof(sin));
  sin.sin_family = AF_INET;
  sin.sin_addr.s_addr = INADDR_LOOPBACK;

  if (sendto(gtpv1u_dump_socket_g, buffer_pP, (size_t)buffer_lengthP, 0, (struct sockaddr *)&sin, sizeof(struct sockaddr)) < 0)  {
107
    LOG_E(GTPU, "%s:%s:%d  sendto %d:%s\n",
108 109 110 111 112 113
          __FILE__, __FUNCTION__, __LINE__, errno, strerror(errno));
  }
}

#endif

luaihui's avatar
luaihui committed
114
//-----------------------------------------------------------------------------
115
static int gtpv1u_eNB_get_msgsource(struct rrc_eNB_ue_context_s *ue_context_p, teid_t teid) {
luaihui's avatar
luaihui committed
116 117 118
  int erab_index = 0;

  /* source enb */
119 120
  if(ue_context_p->ue_context.handover_info != NULL && ue_context_p->ue_context.handover_info->state == HO_COMPLETE) {
    return GTPV1U_MSG_FROM_SPGW;
luaihui's avatar
luaihui committed
121 122 123 124
  }

  /* target enb */
  for (erab_index = 0; erab_index < ue_context_p->ue_context.nb_x2u_e_rabs; erab_index++) {
125 126
    if(ue_context_p->ue_context.enb_gtp_x2u_teid[erab_index] == teid) {
      return GTPV1U_MSG_FROM_SOURCE_ENB;
luaihui's avatar
luaihui committed
127 128
    }
  }
129 130

  return GTPV1U_MSG_FROM_SPGW;
luaihui's avatar
luaihui committed
131 132
}

133
//-----------------------------------------------------------------------------
frtabu's avatar
frtabu committed
134
static int gtpv1u_eNB_send_init_udp(const Gtpv1uS1Req *req) {
135 136
  // Create and alloc new message
  MessageDef *message_p;
frtabu's avatar
frtabu committed
137
  struct in_addr addr= {0};
138
  message_p = itti_alloc_new_message(TASK_GTPV1_U, 0, UDP_INIT);
139 140 141 142

  if (message_p == NULL) {
    return -1;
  }
Cedric Roux's avatar
 
Cedric Roux committed
143

laurent's avatar
laurent committed
144 145
  UDP_INIT(message_p).port = req->enb_port_for_S1u_S12_S4_up;
  addr.s_addr = req->enb_ip_address_for_S1u_S12_S4_up;
146
  UDP_INIT(message_p).address = inet_ntoa(addr);
laurent's avatar
laurent committed
147
  LOG_I(GTPU, "Tx UDP_INIT IP addr %s (%x)\n", UDP_INIT(message_p).address,UDP_INIT(message_p).port);
148
  MSC_LOG_EVENT(
frtabu's avatar
frtabu committed
149 150 151 152
    MSC_GTPU_ENB,
    "0 UDP bind  %s:%u",
    UDP_INIT(message_p).address,
    UDP_INIT(message_p).port);
153
  return itti_send_msg_to_task(TASK_UDP, INSTANCE_DEFAULT, message_p);
154 155
}

laurent's avatar
laurent committed
156 157
static int gtpv1u_s1_req(
  const instance_t                             instanceP,
frtabu's avatar
frtabu committed
158
  const Gtpv1uS1Req *const req) {
laurent's avatar
laurent committed
159
  memcpy(&RC.gtpv1u_data_g->enb_ip_address_for_S1u_S12_S4_up,
frtabu's avatar
frtabu committed
160 161
         &req->enb_ip_address_for_S1u_S12_S4_up,
         sizeof (req->enb_ip_address_for_S1u_S12_S4_up));
laurent's avatar
laurent committed
162 163 164 165
  gtpv1u_eNB_send_init_udp(req);
  return 0;
}

166
//-----------------------------------------------------------------------------
167
NwGtpv1uRcT gtpv1u_eNB_log_request(NwGtpv1uLogMgrHandleT hLogMgr,
168
                                   uint32_t logLevel,
169
                                   NwCharT *file,
170
                                   uint32_t line,
frtabu's avatar
frtabu committed
171
                                   NwCharT *logStr) {
172 173
  LOG_D(GTPU, "%s\n", logStr);
  return NW_GTPV1U_OK;
Cedric Roux's avatar
 
Cedric Roux committed
174 175
}

176
//-----------------------------------------------------------------------------
177
NwGtpv1uRcT gtpv1u_eNB_send_udp_msg(
178
  NwGtpv1uUdpHandleT udpHandle,
179 180 181 182
  uint8_t *buffer,
  uint32_t buffer_len,
  uint32_t buffer_offset,
  uint32_t peerIpAddr,
frtabu's avatar
frtabu committed
183
  uint16_t peerPort) {
184 185 186
  // Create and alloc new message
  MessageDef     *message_p       = NULL;
  udp_data_req_t *udp_data_req_p  = NULL;
187
  message_p = itti_alloc_new_message(TASK_GTPV1_U, 0, UDP_DATA_REQ);
188

189
  if (message_p) {
190
#if defined(LOG_GTPU) && LOG_GTPU > 0
191
    LOG_D(GTPU, "Sending UDP_DATA_REQ length %u offset %u", buffer_len, buffer_offset);
192
#endif
193 194 195 196 197 198 199 200 201 202
    udp_data_req_p = &message_p->ittiMsg.udp_data_req;
    udp_data_req_p->peer_address  = peerIpAddr;
    udp_data_req_p->peer_port     = peerPort;
    udp_data_req_p->buffer        = buffer;
    udp_data_req_p->buffer_length = buffer_len;
    udp_data_req_p->buffer_offset = buffer_offset;
    return itti_send_msg_to_task(TASK_UDP, INSTANCE_DEFAULT, message_p);
  } else {
    return NW_GTPV1U_FAILURE;
  }
203 204 205
}


206
//-----------------------------------------------------------------------------
Cedric Roux's avatar
 
Cedric Roux committed
207
/* Callback called when a gtpv1u message arrived on UDP interface */
208
NwGtpv1uRcT gtpv1u_eNB_process_stack_req(
209
  NwGtpv1uUlpHandleT hUlp,
frtabu's avatar
frtabu committed
210
  NwGtpv1uUlpApiT   *pUlpApi) {
211
  boolean_t           result             = FALSE;
212 213 214 215
  teid_t              teid               = 0;
  hashtable_rc_t      hash_rc            = HASH_TABLE_KEY_NOT_EXISTS;
  gtpv1u_teid_data_t *gtpv1u_teid_data_p = NULL;
  protocol_ctxt_t     ctxt;
Cedric Roux's avatar
Cedric Roux committed
216
  NwGtpv1uRcT         rc;
217 218 219 220 221 222

  switch(pUlpApi->apiType) {
    /* Here there are two type of messages handled:
     * - T-PDU
     * - END-MARKER
     */
frtabu's avatar
frtabu committed
223 224 225
    case NW_GTPV1U_ULP_API_RECV_TPDU: {
      uint8_t              buffer[4096];
      uint32_t             buffer_len;
226
      struct rrc_eNB_ue_context_s        *ue_context_p;
luaihui's avatar
luaihui committed
227
      uint16_t             msgType = NW_GTP_GPDU;
228
      NwGtpv1uMsgT     *pMsg = NULL;
frtabu's avatar
frtabu committed
229 230 231 232
      /* Nw-gptv1u stack has processed a PDU. we can schedule it to PDCP
       * for transmission.
       */
      teid = pUlpApi->apiInfo.recvMsgInfo.teid;
luaihui's avatar
luaihui committed
233 234
      pMsg = (NwGtpv1uMsgT *) pUlpApi->apiInfo.recvMsgInfo.hMsg;
      msgType = pMsg->msgType;
frtabu's avatar
frtabu committed
235 236 237 238 239

      if (NW_GTPV1U_OK != nwGtpv1uMsgGetTpdu(pUlpApi->apiInfo.recvMsgInfo.hMsg,
                                             buffer, &buffer_len)) {
        LOG_E(GTPU, "Error while retrieving T-PDU");
      }
240

frtabu's avatar
frtabu committed
241
      itti_free(TASK_UDP, ((NwGtpv1uMsgT *)pUlpApi->apiInfo.recvMsgInfo.hMsg)->msgBuf);
242
#if defined(GTP_DUMP_SOCKET) && GTP_DUMP_SOCKET > 0
frtabu's avatar
frtabu committed
243
      gtpv1u_eNB_write_dump_socket(buffer,buffer_len);
244
#endif
frtabu's avatar
frtabu committed
245 246
      rc = nwGtpv1uMsgDelete(RC.gtpv1u_data_g->gtpv1u_stack,
                             pUlpApi->apiInfo.recvMsgInfo.hMsg);
247

frtabu's avatar
frtabu committed
248 249 250
      if (rc != NW_GTPV1U_OK) {
        LOG_E(GTPU, "nwGtpv1uMsgDelete failed: 0x%x\n", rc);
      }
Cedric Roux's avatar
Cedric Roux committed
251

frtabu's avatar
frtabu committed
252 253 254 255
      //-----------------------
      // GTPV1U->PDCP mapping
      //-----------------------
      hash_rc = hashtable_get(RC.gtpv1u_data_g->teid_mapping, teid, (void **)&gtpv1u_teid_data_p);
256

frtabu's avatar
frtabu committed
257
      if (hash_rc == HASH_TABLE_OK) {
258
#if defined(LOG_GTPU) && LOG_GTPU > 0
frtabu's avatar
frtabu committed
259 260 261 262 263 264
        LOG_D(GTPU, "Received T-PDU from gtpv1u stack teid  %u size %d -> enb module id %u ue module id %u rab id %u\n",
              teid,
              buffer_len,
              gtpv1u_teid_data_p->enb_id,
              gtpv1u_teid_data_p->ue_id,
              gtpv1u_teid_data_p->eps_bearer_id);
265
#endif
frtabu's avatar
frtabu committed
266 267 268 269 270 271 272 273 274 275
        //#warning "LG eps bearer mapping to DRB id to do (offset -4)"
        PROTOCOL_CTXT_SET_BY_MODULE_ID(&ctxt, gtpv1u_teid_data_p->enb_id, ENB_FLAG_YES,  gtpv1u_teid_data_p->ue_id, 0, 0,gtpv1u_teid_data_p->enb_id);
        MSC_LOG_TX_MESSAGE(
          MSC_GTPU_ENB,
          MSC_PDCP_ENB,
          NULL,0,
          MSC_AS_TIME_FMT" DATA-REQ rb %u size %u",
          0,0,
          (gtpv1u_teid_data_p->eps_bearer_id) ? gtpv1u_teid_data_p->eps_bearer_id - 4: 5-4,
          buffer_len);
276 277 278 279 280 281 282 283 284 285 286 287
        ue_context_p = rrc_eNB_get_ue_context(RC.rrc[ctxt.module_id], ctxt.rnti);

        if((ue_context_p != NULL) &&
            (ue_context_p->ue_context.handover_info != NULL) &&
            (ue_context_p->ue_context.handover_info->state < HO_FORWARDING_COMPLETE)) {
          if(msgType == NW_GTP_END_MARKER) {
            /* in the source enb, UE in RRC_HO_EXECUTION mode */
            if (ue_context_p->ue_context.Status == RRC_HO_EXECUTION && ue_context_p->ue_context.handover_info->state == HO_COMPLETE) {
              /* set handover state */
              //ue_context_p->ue_context.handover_info->state = HO_END_MARKER;
              MessageDef *msg;
              // Configure end marker
288
              msg = itti_alloc_new_message(TASK_GTPV1_U, 0, GTPV1U_ENB_END_MARKER_REQ);
289 290 291 292 293 294 295 296 297 298 299
              GTPV1U_ENB_END_MARKER_REQ(msg).buffer = itti_malloc(TASK_GTPV1_U, TASK_GTPV1_U, GTPU_HEADER_OVERHEAD_MAX + buffer_len);
              memcpy(&GTPV1U_ENB_END_MARKER_REQ(msg).buffer[GTPU_HEADER_OVERHEAD_MAX], buffer, buffer_len);
              GTPV1U_ENB_END_MARKER_REQ(msg).length = buffer_len;
              GTPV1U_ENB_END_MARKER_REQ(msg).rnti   = ctxt.rnti;
              GTPV1U_ENB_END_MARKER_REQ(msg).rab_id = gtpv1u_teid_data_p->eps_bearer_id;
              GTPV1U_ENB_END_MARKER_REQ(msg).offset = GTPU_HEADER_OVERHEAD_MAX;
              LOG_I(GTPU, "Send End Marker to GTPV1-U at frame %d and subframe %d \n", ctxt.frame,ctxt.subframe);
              itti_send_msg_to_task(TASK_GTPV1_U, ENB_MODULE_ID_TO_INSTANCE(ctxt.module_id), msg);
              return NW_GTPV1U_OK;
            }
          }
luaihui's avatar
luaihui committed
300

301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320
          if (ue_context_p->ue_context.Status == RRC_HO_EXECUTION || ue_context_p->ue_context.Status == RRC_RECONFIGURED) {
            int msgsrc = gtpv1u_eNB_get_msgsource(ue_context_p, teid);
            LOG_D(GTPU,"UE INFO.ueStatus %d, handover state %d, forwarding state %d, from %s. message type %s\n",
                  ue_context_p->ue_context.Status,
                  ue_context_p->ue_context.handover_info->state,
                  ue_context_p->ue_context.handover_info->forwarding_state,
                  msgsrc == GTPV1U_MSG_FROM_SOURCE_ENB?"Source eNB":"EPC",
                  msgsrc != GTPV1U_MSG_FROM_SOURCE_ENB? "UDP DATA" :
                  msgType == NW_GTP_END_MARKER?"END MARKER":"DATA FORWARDING");

            /* target enb */
            if(msgType == NW_GTP_END_MARKER) {
              LOG_I(GTPU, "target end receive END MARKER\n");
              ue_context_p->ue_context.handover_info->state = HO_END_MARKER;
              gtpv1u_enb_delete_tunnel_req_t delete_tunnel_req;
              memset(&delete_tunnel_req, 0, sizeof(delete_tunnel_req));
              delete_tunnel_req.rnti = ctxt.rnti;
              gtpv1u_delete_x2u_tunnel(ctxt.module_id, &delete_tunnel_req, GTPV1U_TARGET_ENB);
              return NW_GTPV1U_OK;
            }
luaihui's avatar
luaihui committed
321

322 323 324
            /* form source eNB message */
            if(msgsrc == GTPV1U_MSG_FROM_SOURCE_ENB) {
              LOG_I(GTPU, "Received a message data forwarding length %d\n", buffer_len);
luaihui's avatar
luaihui committed
325
#if defined(LOG_GTPU) && LOG_GTPU > 0
326
              LOG_T(GTPU, "forwarding data info:\n", buffer_len);
luaihui's avatar
luaihui committed
327

328 329
              for(int i=1; i<=buffer_len; i++) {
                LOG_T(GTPU, "%02x ", buffer[i-1]);
luaihui's avatar
luaihui committed
330

331 332
                if(i%20 == 0)LOG_T(GTPU, "\n");
              }
luaihui's avatar
luaihui committed
333

334
              LOG_T(GTPU, "\n");
luaihui's avatar
luaihui committed
335
#endif
336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360
              result = gtpv_data_req(
                         &ctxt,
                         (gtpv1u_teid_data_p->eps_bearer_id) ? gtpv1u_teid_data_p->eps_bearer_id - 4: 5-4,
                         0, // mui
                         SDU_CONFIRM_NO, // confirm
                         buffer_len,
                         buffer,
                         PDCP_TRANSMISSION_MODE_DATA,
                         TASK_DATA_FORWARDING
                       );

              if ( result == FALSE ) {
                LOG_W(GTPU, "DATA FORWARDING message save failed\n");
                return NW_GTPV1U_FAILURE;
              }

              ue_context_p->ue_context.handover_info->forwarding_state = FORWARDING_NO_EMPTY;
              return NW_GTPV1U_OK;
            }
            /* from epc message */
            else {
              /* in the source enb, UE in RRC_HO_EXECUTION mode */
              if (ue_context_p->ue_context.handover_info->state == HO_COMPLETE) {
                MessageDef *msg;
                // Configure target
361
                msg = itti_alloc_new_message(TASK_GTPV1_U, 0, GTPV1U_ENB_DATA_FORWARDING_REQ);
362 363 364 365 366 367 368 369
                GTPV1U_ENB_DATA_FORWARDING_REQ(msg).buffer = itti_malloc(TASK_GTPV1_U, TASK_GTPV1_U, GTPU_HEADER_OVERHEAD_MAX + buffer_len);
                memcpy(&GTPV1U_ENB_DATA_FORWARDING_REQ(msg).buffer[GTPU_HEADER_OVERHEAD_MAX], buffer, buffer_len);
                GTPV1U_ENB_DATA_FORWARDING_REQ(msg).length = buffer_len;
                GTPV1U_ENB_DATA_FORWARDING_REQ(msg).rnti   = ctxt.rnti;
                GTPV1U_ENB_DATA_FORWARDING_REQ(msg).rab_id = gtpv1u_teid_data_p->eps_bearer_id;
                GTPV1U_ENB_DATA_FORWARDING_REQ(msg).offset = GTPU_HEADER_OVERHEAD_MAX;
#if defined(LOG_GTPU) && LOG_GTPU > 0
                LOG_T(GTPU, "Send data forwarding sdu_buffer to target enb. len %d info\n", buffer);
luaihui's avatar
luaihui committed
370

371 372 373 374 375
                for(int i=1; i<=buffer_len; i++) {
                  LOG_T(GTPU, "%02x ", buffer[i-1]);

                  if(i%20 == 0)LOG_T(GTPU, "\n");
                }
luaihui's avatar
luaihui committed
376

377
                LOG_T(GTPU, "\n");
luaihui's avatar
luaihui committed
378
#endif
379 380 381 382 383 384 385 386 387 388 389
                LOG_I(GTPU, "Send data forwarding to GTPV1-U at frame %d and subframe %d \n", ctxt.frame,ctxt.subframe);
                itti_send_msg_to_task(TASK_GTPV1_U, ENB_MODULE_ID_TO_INSTANCE(ctxt.module_id), msg);
                return NW_GTPV1U_OK;
              }

              /* target eNB. x2ho forwarding is processing. spgw message save to TASK_END_MARKER */
              if(ue_context_p->ue_context.handover_info->state != HO_COMPLETE &&
                  ue_context_p->ue_context.handover_info->state != HO_END_MARKER ) {
                LOG_I(GTPU, "x2ho forwarding is processing. Received a spgw message. length %d\n", buffer_len);
#if defined(LOG_GTPU) && LOG_GTPU > 0
                LOG_T(GTPU, "spgw data info:\n", buffer_len);
luaihui's avatar
luaihui committed
390

391 392
                for(int i=1; i<=buffer_len; i++) {
                  LOG_T(GTPU, "%02x ", buffer[i-1]);
luaihui's avatar
luaihui committed
393

394 395
                  if(i%20 == 0)LOG_T(GTPU, "\n");
                }
luaihui's avatar
luaihui committed
396

397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420
                LOG_T(GTPU, "\n");
#endif
                result = gtpv_data_req(
                           &ctxt,
                           (gtpv1u_teid_data_p->eps_bearer_id) ? gtpv1u_teid_data_p->eps_bearer_id - 4: 5-4,
                           0, // mui
                           SDU_CONFIRM_NO, // confirm
                           buffer_len,
                           buffer,
                           PDCP_TRANSMISSION_MODE_DATA,
                           TASK_END_MARKER
                         );

                if ( result == FALSE ) {
                  LOG_W(GTPU, "DATA FORWARDING message save failed\n");
                  return NW_GTPV1U_FAILURE;
                }

                ue_context_p->ue_context.handover_info->endmark_state = ENDMARK_NO_EMPTY;
                return NW_GTPV1U_OK;
              }
            }
          }
        }
luaihui's avatar
luaihui committed
421

frtabu's avatar
frtabu committed
422 423 424 425 426 427 428 429
        result = pdcp_data_req(
                   &ctxt,
                   SRB_FLAG_NO,
                   (gtpv1u_teid_data_p->eps_bearer_id) ? gtpv1u_teid_data_p->eps_bearer_id - 4: 5-4,
                   0, // mui
                   SDU_CONFIRM_NO, // confirm
                   buffer_len,
                   buffer,
430
                   PDCP_TRANSMISSION_MODE_DATA,NULL, NULL
frtabu's avatar
frtabu committed
431 432 433 434
                 );

        if ( result == FALSE ) {
          if (ctxt.configured == FALSE )
luaihui's avatar
luaihui committed
435
            LOG_W(GTPU, "PDCP data request failed, cause: [UE:%x]RB is not configured!\n", ctxt.rnti) ;
frtabu's avatar
frtabu committed
436 437 438 439 440 441 442
          else
            LOG_W(GTPU, "PDCP data request failed\n");

          return NW_GTPV1U_FAILURE;
        }
      } else {
        LOG_W(GTPU, "Received T-PDU from gtpv1u stack teid %u unknown size %u", teid, buffer_len);
443
      }
Cedric Roux's avatar
 
Cedric Roux committed
444
    }
445
    break;
frtabu's avatar
frtabu committed
446 447 448 449 450 451 452

    default: {
      LOG_E(GTPU, "Received undefined UlpApi (%02x) from gtpv1u stack!\n",
            pUlpApi->apiType);
    }
  } // end of switch

453
  return NW_GTPV1U_OK;
Cedric Roux's avatar
 
Cedric Roux committed
454 455 456
}


457
//-----------------------------------------------------------------------------
458
int data_recv_callback(uint16_t  portP,
Cedric Roux's avatar
 
Cedric Roux committed
459 460 461
                       uint32_t  address,
                       uint8_t  *buffer,
                       uint32_t  length,
frtabu's avatar
frtabu committed
462
                       void     *arg_p) {
463
  gtpv1u_data_t        *gtpv1u_data_p;
Cedric Roux's avatar
 
Cedric Roux committed
464

465 466 467
  if (arg_p == NULL) {
    return -1;
  }
Cedric Roux's avatar
 
Cedric Roux committed
468

469 470 471 472 473 474
  gtpv1u_data_p = (gtpv1u_data_t *)arg_p;
  return nwGtpv1uProcessUdpReq(gtpv1u_data_p->gtpv1u_stack,
                               buffer,
                               length,
                               portP,
                               address);
Cedric Roux's avatar
 
Cedric Roux committed
475 476
}

477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570
//int
//gtpv1u_create_tunnel_endpoint(
//    gtpv1u_data_t *gtpv1u_data_pP,
//    uint8_t        ue_idP,
//    uint8_t        rab_idP,
//    char          *sgw_ip_addr_pP,
//    uint16_t       portP)
//{
//    uint32_t                     teid;
//    uint8_t                      max_attempt = 100;
//    NwGtpv1uRcT                  rc          = NW_GTPV1U_FAILURE;
//    NwGtpv1uUlpApiT              ulp_req;
//    struct gtpv1u_ue_data_s     *new_ue_p    = NULL;
//    struct gtpv1u_bearer_s      *bearer_p    = NULL;
//    hashtable_rc_t               hash_rc     = HASH_TABLE_KEY_NOT_EXISTS;;
//
//    if (rab_idP > GTPV1U_MAX_BEARERS_PER_UE) {
//        LOG_E(GTPU, "Could not use rab_id %d > max %d\n",
//              rab_idP, GTPV1U_MAX_BEARERS_PER_UE);
//        return -1;
//    }
//
//
//    if ((hash_rc = hashtable_get(gtpv1u_data_pP->ue_mapping, (uint64_t)ue_idP, (void**)&new_ue_p)) == HASH_TABLE_OK) {
//        /* A context for this UE already exist in the tree, use it */
//        /* We check that the tunnel is not already configured */
//        if (new_ue_p->bearers[rab_idP].state != BEARER_DOWN) {
//            LOG_E(GTPU, "Cannot create new end-point over already existing tunnel\n");
//            return -1;
//        }
//    } else {
//        /* Context doesn't exist, create it */
//        if (rab_idP != 0) {
//            /* UE should first establish Default bearer before trying to setup
//             * additional bearers.
//             */
//            LOG_E(GTPU, "UE context is not known and rab_id != 0\n");
//            return -1;
//        }
//        new_ue_p = calloc(1, sizeof(struct gtpv1u_ue_data_s));
//        new_ue_p->ue_id = ue_idP;
//
//        hash_rc = hashtable_insert(gtpv1u_data_pP->ue_mapping, (uint64_t)ue_idP, new_ue_p);
//
//        if ((hash_rc != HASH_TABLE_OK) && (hash_rc != HASH_TABLE_INSERT_OVERWRITTEN_DATA)) {
//            LOG_E(GTPU, "Failed to insert new UE context\n");
//            free(new_ue_p);
//            return -1;
//        }
//    }
//
//    bearer_p = &new_ue_p->bearers[rab_idP];
//
//    /* Configure the bearer */
//    bearer_p->state       = BEARER_IN_CONFIG;
//    bearer_p->sgw_ip_addr = inet_addr(sgw_ip_addr_pP);
//    bearer_p->port        = portP;
//
//    /* Create the new stack api request */
//    memset(&ulp_req, 0, sizeof(NwGtpv1uUlpApiT));
//    ulp_req.apiType = NW_GTPV1U_ULP_API_CREATE_TUNNEL_ENDPOINT;
//
//    /* Try to create new tunnel-endpoint.
//     * If teid generated is already present in the stack, just peek another random
//     * teid. This could be ok for small number of tunnel but more errors could be
//     * thrown if we reached high number of tunnels.
//     * TODO: find a solution for teid
//     */
//    do {
//        /* Request for a new random TEID */
//        teid = gtpv1u_new_teid();
//        ulp_req.apiInfo.createTunnelEndPointInfo.teid = teid;
//
//        rc = nwGtpv1uProcessUlpReq(gtpv1u_data_pP->gtpv1u_stack, &ulp_req);
//
//        if (rc == NW_GTPV1U_OK) {
////             LOG_D(GTPU, "Successfully created new tunnel endpoint for teid 0x%x\n",
////                   teid);
//            bearer_p->teid_eNB = teid;
////             gtpv1u_initial_req(gtpv1u_data_pP, teid, GTPV1U_UDP_PORT,
////                                inet_addr("192.168.56.101"));
//            LOG_I(GTPU, "Created eNB tunnel endpoint %u for ue id %u, rab id %u\n", teid, ue_idP, rab_idP);
//            return 0;
//        } else {
//            LOG_W(GTPU, "Teid %u already in use... %s\n",
//                  teid, (max_attempt > 1) ? "Trying another one" : "Last chance");
//        }
//    } while(max_attempt-- && rc != NW_GTPV1U_OK);
//
//    bearer_p->state = BEARER_DOWN;
//    LOG_I(GTPU, "Failed to created eNB tunnel endpoint %u for ue id %u, rab id %u, bearer down\n", teid, ue_idP, rab_idP);
//
//    return -1;
//}
Cedric Roux's avatar
 
Cedric Roux committed
571 572


573
//-----------------------------------------------------------------------------
574
static NwGtpv1uRcT gtpv1u_start_timer_wrapper(
575
  NwGtpv1uTimerMgrHandleT tmrMgrHandle,
576 577 578
  uint32_t                  timeoutSec,
  uint32_t                  timeoutUsec,
  uint32_t                  tmrType,
579
  void                   *timeoutArg,
frtabu's avatar
frtabu committed
580
  NwGtpv1uTimerHandleT   *hTmr) {
581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600
  NwGtpv1uRcT rc = NW_GTPV1U_OK;
  long        timer_id;

  if (tmrType == NW_GTPV1U_TMR_TYPE_ONE_SHOT) {
    timer_setup(timeoutSec,
                timeoutUsec,
                TASK_GTPV1_U,
                INSTANCE_DEFAULT,
                TIMER_ONE_SHOT,
                timeoutArg,
                &timer_id);
  } else {
    timer_setup(timeoutSec,
                timeoutUsec,
                TASK_GTPV1_U,
                INSTANCE_DEFAULT,
                TIMER_PERIODIC,
                timeoutArg,
                &timer_id);
  }
Cedric Roux's avatar
 
Cedric Roux committed
601

602
  return rc;
603
}
Cedric Roux's avatar
 
Cedric Roux committed
604 605


606 607 608
//-----------------------------------------------------------------------------
static NwGtpv1uRcT
gtpv1u_stop_timer_wrapper(
609
  NwGtpv1uTimerMgrHandleT tmrMgrHandle,
frtabu's avatar
frtabu committed
610
  NwGtpv1uTimerHandleT hTmr) {
611 612
  NwGtpv1uRcT rc = NW_GTPV1U_OK;
  return rc;
Cedric Roux's avatar
 
Cedric Roux committed
613 614
}

615

616
//-----------------------------------------------------------------------------
617 618
int
gtpv1u_initial_req(
619 620 621
  gtpv1u_data_t *gtpv1u_data_pP,
  teid_t         teidP,
  tcp_udp_port_t portP,
frtabu's avatar
frtabu committed
622
  uint32_t       address) {
623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638
  NwGtpv1uUlpApiT ulp_req;
  NwGtpv1uRcT     rc = NW_GTPV1U_FAILURE;
  memset(&ulp_req, 0, sizeof(NwGtpv1uUlpApiT));
  ulp_req.apiType = NW_GTPV1U_ULP_API_INITIAL_REQ;
  ulp_req.apiInfo.initialReqInfo.teid     = teidP;
  ulp_req.apiInfo.initialReqInfo.peerPort = portP;
  ulp_req.apiInfo.initialReqInfo.peerIp   = address;
  rc = nwGtpv1uProcessUlpReq(gtpv1u_data_pP->gtpv1u_stack, &ulp_req);

  if (rc == NW_GTPV1U_OK) {
    LOG_D(GTPU, "Successfully sent initial req for teid %u\n", teidP);
  } else {
    LOG_W(GTPU, "Could not send initial req for teid %u\n", teidP);
  }

  return (rc == NW_GTPV1U_OK) ? 0 : -1;
Cedric Roux's avatar
 
Cedric Roux committed
639 640
}

641
//-----------------------------------------------------------------------------
642 643
int
gtpv1u_new_data_req(
644 645
  uint8_t  enb_module_idP,
  rnti_t   ue_rntiP,
646 647 648 649
  uint8_t  rab_idP,
  uint8_t *buffer_pP,
  uint32_t buf_lenP,
  uint32_t buf_offsetP
frtabu's avatar
frtabu committed
650
) {
651 652 653 654 655 656 657 658
  NwGtpv1uUlpApiT          stack_req;
  NwGtpv1uRcT              rc            = NW_GTPV1U_FAILURE;
  struct gtpv1u_ue_data_s  ue;
  struct gtpv1u_ue_data_s *ue_inst_p     = NULL;
  struct gtpv1u_bearer_s  *bearer_p      = NULL;
  hashtable_rc_t           hash_rc       = HASH_TABLE_KEY_NOT_EXISTS;;
  gtpv1u_data_t           *gtpv1u_data_p = NULL;
  memset(&ue, 0, sizeof(struct gtpv1u_ue_data_s));
659 660
  ue.ue_id = ue_rntiP;
  AssertFatal(enb_module_idP >=0, "Bad parameter enb module id %u\n", enb_module_idP);
661
  AssertFatal((rab_idP - GTPV1U_BEARER_OFFSET)< GTPV1U_MAX_BEARERS_ID, "Bad parameter rab id %u\n", rab_idP);
662
  AssertFatal((rab_idP - GTPV1U_BEARER_OFFSET) >= 0, "Bad parameter rab id %u\n", rab_idP);
663
  gtpv1u_data_p = RC.gtpv1u_data_g;
664
  /* Check that UE context is present in ue map. */
frtabu's avatar
frtabu committed
665
  hash_rc = hashtable_get(gtpv1u_data_p->ue_mapping, (uint64_t)ue_rntiP, (void **)&ue_inst_p);
Cedric Roux's avatar
 
Cedric Roux committed
666

667
  if (hash_rc ==  HASH_TABLE_KEY_NOT_EXISTS ) {
668
    LOG_E(GTPU, "[UE %d] Trying to send data on non-existing UE context\n", ue_rntiP);
669 670
    return -1;
  }
Cedric Roux's avatar
 
Cedric Roux committed
671

672
  bearer_p = &ue_inst_p->bearers[rab_idP - GTPV1U_BEARER_OFFSET];
Cedric Roux's avatar
 
Cedric Roux committed
673

674 675 676 677 678 679 680
  /* Ensure the bearer in ready.
   * TODO: handle the cases where the bearer is in HANDOVER state.
   * In such case packets should be placed in FIFO.
   */
  if (bearer_p->state != BEARER_UP) {
    LOG_W(GTPU, "Trying to send data over bearer with state(%u) != BEARER_UP\n",
          bearer_p->state);
frtabu's avatar
frtabu committed
681
    //#warning  LG: HACK WHILE WAITING FOR NAS, normally return -1
Cedric Roux's avatar
 
Cedric Roux committed
682

683 684 685
    if (bearer_p->state != BEARER_IN_CONFIG)
      return -1;
  }
Cedric Roux's avatar
 
Cedric Roux committed
686

687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723
  memset(&stack_req, 0, sizeof(NwGtpv1uUlpApiT));
  stack_req.apiType                   = NW_GTPV1U_ULP_API_SEND_TPDU;
  stack_req.apiInfo.sendtoInfo.teid   = bearer_p->teid_sgw;
  stack_req.apiInfo.sendtoInfo.ipAddr = bearer_p->sgw_ip_addr;
  LOG_D(GTPU, "TX TO TEID %u addr 0x%x\n",bearer_p->teid_sgw, bearer_p->sgw_ip_addr);
  rc = nwGtpv1uGpduMsgNew(gtpv1u_data_p->gtpv1u_stack,
                          bearer_p->teid_sgw,
                          NW_FALSE,
                          gtpv1u_data_p->seq_num++,
                          buffer_pP,
                          buf_lenP,
                          buf_offsetP,
                          &(stack_req.apiInfo.sendtoInfo.hMsg));

  if (rc != NW_GTPV1U_OK) {
    LOG_E(GTPU, "nwGtpv1uGpduMsgNew failed: 0x%x\n", rc);
    return -1;
  }

  rc = nwGtpv1uProcessUlpReq(gtpv1u_data_p->gtpv1u_stack,
                             &stack_req);

  if (rc != NW_GTPV1U_OK) {
    LOG_E(GTPU, "nwGtpv1uProcessUlpReq failed: 0x%x\n", rc);
    return -1;
  }

  rc = nwGtpv1uMsgDelete(gtpv1u_data_p->gtpv1u_stack,
                         stack_req.apiInfo.sendtoInfo.hMsg);

  if (rc != NW_GTPV1U_OK) {
    LOG_E(GTPU, "nwGtpv1uMsgDelete failed: 0x%x\n", rc);
    return -1;
  }

  LOG_D(GTPU, "%s() return code OK\n", __FUNCTION__);
  return 0;
Cedric Roux's avatar
 
Cedric Roux committed
724 725
}

luaihui's avatar
luaihui committed
726 727 728 729
//-----------------------------------------------------------------------------
int
gtpv1u_create_x2u_tunnel(
  const instance_t                              instanceP,
730 731 732
  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
) {
luaihui's avatar
luaihui committed
733 734 735 736 737 738 739 740 741 742
  /* Create a new nw-gtpv1-u stack req using API */
  NwGtpv1uUlpApiT          stack_req;
  NwGtpv1uRcT              rc                   = NW_GTPV1U_FAILURE;
  /* Local tunnel end-point identifier */
  teid_t                   x2u_teid             = 0;
  gtpv1u_teid_data_t      *gtpv1u_teid_data_p   = NULL;
  hashtable_rc_t           hash_rc              = HASH_TABLE_KEY_NOT_EXISTS;
  int                      i;
  ebi_t                    eps_bearer_id        = 0;
  MSC_LOG_RX_MESSAGE(
743 744 745 746 747 748 749
    MSC_GTPU_ENB,
    MSC_RRC_ENB,
    NULL,0,
    MSC_AS_TIME_FMT" CREATE_X2U_TUNNEL_REQ RNTI %"PRIx16" inst %u ntuns %u ebid %u enb-x2u teid %u",
    0,0,create_tunnel_req_pP->rnti, instanceP,
    create_tunnel_req_pP->num_tunnels, create_tunnel_req_pP->eps_bearer_id[0],
    create_tunnel_req_pP->tenb_X2u_teid[0]);
luaihui's avatar
luaihui committed
750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770
  create_tunnel_resp_pP->rnti        = create_tunnel_req_pP->rnti;
  create_tunnel_resp_pP->status      = 0;
  create_tunnel_resp_pP->num_tunnels = 0;

  for (i = 0; i < create_tunnel_req_pP->num_tunnels; i++) {
    eps_bearer_id = create_tunnel_req_pP->eps_bearer_id[i];
    LOG_D(GTPU, "Rx GTPV1U_ENB_CREATE_X2U_TUNNEL_REQ ue rnti %x eps bearer id %u\n",
          create_tunnel_req_pP->rnti, eps_bearer_id);
    memset(&stack_req, 0, sizeof(NwGtpv1uUlpApiT));
    stack_req.apiType = NW_GTPV1U_ULP_API_CREATE_TUNNEL_ENDPOINT;

    do {
      x2u_teid = gtpv1u_new_teid();
      LOG_D(GTPU, "gtpv1u_create_x2u_tunnel() 0x%x %u(dec)\n", x2u_teid, x2u_teid);
      stack_req.apiInfo.createTunnelEndPointInfo.teid          = x2u_teid;
      stack_req.apiInfo.createTunnelEndPointInfo.hUlpSession   = 0;
      stack_req.apiInfo.createTunnelEndPointInfo.hStackSession = 0;
      rc = nwGtpv1uProcessUlpReq(RC.gtpv1u_data_g->gtpv1u_stack, &stack_req);
      LOG_D(GTPU, ".\n");
    } while (rc != NW_GTPV1U_OK);

771 772 773 774 775 776 777 778
    memcpy(&create_tunnel_resp_pP->enb_addr.buffer,
           &RC.gtpv1u_data_g->enb_ip_address_for_S1u_S12_S4_up,
           sizeof (in_addr_t));
    LOG_D(GTPU, "gtpv1u_create_x2u_tunnel() end addr %d.%d.%d.%d\n",
          create_tunnel_resp_pP->enb_addr.buffer[0],
          create_tunnel_resp_pP->enb_addr.buffer[1],
          create_tunnel_resp_pP->enb_addr.buffer[2],
          create_tunnel_resp_pP->enb_addr.buffer[3]);
luaihui's avatar
luaihui committed
779 780 781 782 783 784 785
    create_tunnel_resp_pP->enb_addr.length  = sizeof (in_addr_t);
    create_tunnel_resp_pP->eps_bearer_id[i] = eps_bearer_id;
    create_tunnel_resp_pP->num_tunnels      += 1;
    //-----------------------
    // GTPV1U->PDCP mapping
    //-----------------------
    create_tunnel_resp_pP->enb_X2u_teid[i] = x2u_teid;
786
    hash_rc = hashtable_get(RC.gtpv1u_data_g->teid_mapping, x2u_teid, (void **)&gtpv1u_teid_data_p);
luaihui's avatar
luaihui committed
787 788 789 790 791 792 793 794 795 796 797 798 799 800

    if (hash_rc == HASH_TABLE_KEY_NOT_EXISTS) {
      gtpv1u_teid_data_p = calloc (1, sizeof(gtpv1u_teid_data_t));
      gtpv1u_teid_data_p->enb_id        = 0; // TO DO
      gtpv1u_teid_data_p->ue_id         = create_tunnel_req_pP->rnti;
      gtpv1u_teid_data_p->eps_bearer_id = eps_bearer_id;
      hash_rc = hashtable_insert(RC.gtpv1u_data_g->teid_mapping, x2u_teid, gtpv1u_teid_data_p);
      AssertFatal(hash_rc == HASH_TABLE_OK, "Error inserting teid mapping in GTPV1U hashtable");
    } else {
      create_tunnel_resp_pP->enb_X2u_teid[i] = 0;
      create_tunnel_resp_pP->status         = 0xFF;
    }
  }

801 802 803 804 805 806 807
  MSC_LOG_TX_MESSAGE(
    MSC_GTPU_ENB,
    MSC_RRC_ENB,
    NULL,0,
    "0 GTPV1U_ENB_CREATE_TUNNEL_RESP rnti %x teid %x",
    create_tunnel_resp_pP->rnti,
    x2u_teid);
luaihui's avatar
luaihui committed
808 809 810 811 812 813 814 815 816
  LOG_D(GTPU, "Tx GTPV1U_ENB_CREATE_TUNNEL_RESP ue rnti %x status %d\n",
        create_tunnel_req_pP->rnti,
        create_tunnel_resp_pP->status);
  return 0;
}

//-----------------------------------------------------------------------------
int gtpv1u_delete_x2u_tunnel(
  const instance_t                             instanceP,
817 818
  const gtpv1u_enb_delete_tunnel_req_t *const req_pP,
  int                             enbflag) {
luaihui's avatar
luaihui committed
819 820 821 822 823 824
  gtpv1u_ue_data_t        *gtpv1u_ue_data_p     = NULL;
  hashtable_rc_t           hash_rc              = HASH_TABLE_KEY_NOT_EXISTS;
  int                      erab_index           = 0;
  ebi_t                    eps_bearer_id        = 0;
  struct rrc_eNB_ue_context_s *ue_context_p     = NULL;
  ue_context_p = rrc_eNB_get_ue_context(RC.rrc[instanceP], req_pP->rnti);
825 826

  if(ue_context_p != NULL) {
luaihui's avatar
luaihui committed
827
    /* in the source enb */
828 829
    if(enbflag == GTPV1U_SOURCE_ENB) {
      hash_rc = hashtable_get(RC.gtpv1u_data_g->ue_mapping, req_pP->rnti, (void **)&gtpv1u_ue_data_p);
luaihui's avatar
luaihui committed
830 831 832 833

      if (hash_rc == HASH_TABLE_OK) {
        for (erab_index = 0; erab_index < ue_context_p->ue_context.nb_x2u_e_rabs; erab_index++) {
          eps_bearer_id = ue_context_p->ue_context.enb_gtp_x2u_ebi[erab_index];
laurent's avatar
laurent committed
834
          LOG_I(GTPU, "gtpv1u_delete_x2u_tunnel user rnti %x teNB X2U teid %u eps bearer id %ld\n",
835 836 837
                req_pP->rnti,
                gtpv1u_ue_data_p->bearers[eps_bearer_id - GTPV1U_BEARER_OFFSET].teid_teNB,
                ue_context_p->ue_context.enb_gtp_x2u_ebi[erab_index]);
luaihui's avatar
luaihui committed
838 839 840 841
          gtpv1u_ue_data_p->bearers[eps_bearer_id - GTPV1U_BEARER_OFFSET].teid_teNB = 0;
          gtpv1u_ue_data_p->bearers[eps_bearer_id - GTPV1U_BEARER_OFFSET].tenb_ip_addr = 0;
          //gtpv1u_ue_data_p->bearers[eps_bearer_id - GTPV1U_BEARER_OFFSET].tenb_ip6_addr = 0;
        }
842

luaihui's avatar
luaihui committed
843 844 845 846
        ue_context_p->ue_context.nb_x2u_e_rabs = 0;
      }
    }
    /* in the target enb */
847
    else {
luaihui's avatar
luaihui committed
848 849 850 851 852 853 854 855 856 857 858
      for (erab_index = 0; erab_index < ue_context_p->ue_context.nb_x2u_e_rabs; erab_index++) {
        //-----------------------
        // GTPV1U->PDCP mapping
        //-----------------------
        hash_rc = hashtable_remove(RC.gtpv1u_data_g->teid_mapping, ue_context_p->ue_context.enb_gtp_x2u_teid[erab_index]);
        LOG_I(GTPU, "Removed user rnti %x , enb X2U teid %u\n", req_pP->rnti, ue_context_p->ue_context.enb_gtp_x2u_teid[erab_index]);

        if (hash_rc != HASH_TABLE_OK) {
          LOG_D(GTPU, "Removed user rnti %x , enb X2U teid %u not found\n", req_pP->rnti, ue_context_p->ue_context.enb_gtp_x2u_teid[erab_index]);
        }
      }
859

luaihui's avatar
luaihui committed
860 861 862
      ue_context_p->ue_context.nb_x2u_e_rabs = 0;
    }
  }
863

luaihui's avatar
luaihui committed
864 865 866
  return 0;
}

867
//-----------------------------------------------------------------------------
868
int
869
gtpv1u_create_s1u_tunnel(
870
  const instance_t                              instanceP,
frtabu's avatar
frtabu committed
871 872 873
  const gtpv1u_enb_create_tunnel_req_t *const  create_tunnel_req_pP,
  gtpv1u_enb_create_tunnel_resp_t *const create_tunnel_resp_pP
) {
874 875 876 877 878 879 880
  /* Create a new nw-gtpv1-u stack req using API */
  NwGtpv1uUlpApiT          stack_req;
  NwGtpv1uRcT              rc                   = NW_GTPV1U_FAILURE;
  /* Local tunnel end-point identifier */
  teid_t                   s1u_teid             = 0;
  gtpv1u_teid_data_t      *gtpv1u_teid_data_p   = NULL;
  gtpv1u_ue_data_t        *gtpv1u_ue_data_p     = NULL;
881
  //MessageDef              *message_p            = NULL;
882 883 884 885 886 887 888
  hashtable_rc_t           hash_rc              = HASH_TABLE_KEY_NOT_EXISTS;
  int                      i;
  ebi_t                    eps_bearer_id        = 0;
  //    int                      ipv4_addr            = 0;
  int                      ip_offset            = 0;
  in_addr_t                in_addr;
  int                      addrs_length_in_bytes= 0;
889 890
  int                      loop_counter         = 0;
  int                      ret                  = 0;
Lionel Gauthier's avatar
Lionel Gauthier committed
891
  MSC_LOG_RX_MESSAGE(
frtabu's avatar
frtabu committed
892 893 894 895 896 897 898
    MSC_GTPU_ENB,
    MSC_RRC_ENB,
    NULL,0,
    MSC_AS_TIME_FMT" CREATE_TUNNEL_REQ RNTI %"PRIx16" inst %u ntuns %u ebid %u sgw-s1u teid %u",
    0,0,create_tunnel_req_pP->rnti, instanceP,
    create_tunnel_req_pP->num_tunnels, create_tunnel_req_pP->eps_bearer_id[0],
    create_tunnel_req_pP->sgw_S1u_teid[0]);
899 900 901
  create_tunnel_resp_pP->rnti        = create_tunnel_req_pP->rnti;
  create_tunnel_resp_pP->status      = 0;
  create_tunnel_resp_pP->num_tunnels = 0;
902 903 904

  for (i = 0; i < create_tunnel_req_pP->num_tunnels; i++) {
    ip_offset               = 0;
905
    loop_counter            = 0;
906
    eps_bearer_id = create_tunnel_req_pP->eps_bearer_id[i];
907 908
    LOG_D(GTPU, "Rx GTPV1U_ENB_CREATE_TUNNEL_REQ ue rnti %x eps bearer id %u\n",
          create_tunnel_req_pP->rnti, eps_bearer_id);
909 910 911 912 913 914 915 916 917
    memset(&stack_req, 0, sizeof(NwGtpv1uUlpApiT));
    stack_req.apiType = NW_GTPV1U_ULP_API_CREATE_TUNNEL_ENDPOINT;

    do {
      s1u_teid = gtpv1u_new_teid();
      LOG_D(GTPU, "gtpv1u_create_s1u_tunnel() 0x%x %u(dec)\n", s1u_teid, s1u_teid);
      stack_req.apiInfo.createTunnelEndPointInfo.teid          = s1u_teid;
      stack_req.apiInfo.createTunnelEndPointInfo.hUlpSession   = 0;
      stack_req.apiInfo.createTunnelEndPointInfo.hStackSession = 0;
918
      rc = nwGtpv1uProcessUlpReq(RC.gtpv1u_data_g->gtpv1u_stack, &stack_req);
919
      LOG_D(GTPU, ".\n");
920 921
      loop_counter++;
    } while (rc != NW_GTPV1U_OK && loop_counter < 10);
922

923 924 925 926 927
    if ( rc != NW_GTPV1U_OK && loop_counter == 10 ) {
      LOG_E(GTPU,"NwGtpv1uCreateTunnelEndPoint failed 10 times,start next loop\n");
      ret = -1;
      continue;
    }
928 929 930 931

    //-----------------------
    // PDCP->GTPV1U mapping
    //-----------------------
932
    hash_rc = hashtable_get(RC.gtpv1u_data_g->ue_mapping, create_tunnel_req_pP->rnti, (void **)&gtpv1u_ue_data_p);
933 934 935 936

    if ((hash_rc == HASH_TABLE_KEY_NOT_EXISTS) || (hash_rc == HASH_TABLE_OK)) {
      if (hash_rc == HASH_TABLE_KEY_NOT_EXISTS) {
        gtpv1u_ue_data_p = calloc (1, sizeof(gtpv1u_ue_data_t));
937
        hash_rc = hashtable_insert(RC.gtpv1u_data_g->ue_mapping, create_tunnel_req_pP->rnti, gtpv1u_ue_data_p);
938 939 940
        AssertFatal(hash_rc == HASH_TABLE_OK, "Error inserting ue_mapping in GTPV1U hashtable");
      }

941
      gtpv1u_ue_data_p->ue_id       = create_tunnel_req_pP->rnti;
942
      gtpv1u_ue_data_p->instance_id = 0; // TO DO
943
      memcpy(&create_tunnel_resp_pP->enb_addr.buffer,
944
             &RC.gtpv1u_data_g->enb_ip_address_for_S1u_S12_S4_up,
945
             sizeof (in_addr_t));
946 947
     
      LOG_I(GTPU,"Configured GTPu address : %x\n",RC.gtpv1u_data_g->enb_ip_address_for_S1u_S12_S4_up);
948
      create_tunnel_resp_pP->enb_addr.length = sizeof (in_addr_t);
949 950 951 952 953 954 955 956 957
      addrs_length_in_bytes = create_tunnel_req_pP->sgw_addr[i].length / 8;
      AssertFatal((addrs_length_in_bytes == 4) ||
                  (addrs_length_in_bytes == 16) ||
                  (addrs_length_in_bytes == 20),
                  "Bad transport layer address length %d (bits) %d (bytes)",
                  create_tunnel_req_pP->sgw_addr[i].length, addrs_length_in_bytes);

      if ((addrs_length_in_bytes == 4) ||
          (addrs_length_in_bytes == 20)) {
frtabu's avatar
frtabu committed
958
        in_addr = *((in_addr_t *)create_tunnel_req_pP->sgw_addr[i].buffer);
959 960 961 962 963 964 965 966 967 968 969
        ip_offset = 4;
        gtpv1u_ue_data_p->bearers[eps_bearer_id - GTPV1U_BEARER_OFFSET].sgw_ip_addr = in_addr;
      }

      if ((addrs_length_in_bytes == 16) ||
          (addrs_length_in_bytes == 20)) {
        memcpy(gtpv1u_ue_data_p->bearers[eps_bearer_id - GTPV1U_BEARER_OFFSET].sgw_ip6_addr.s6_addr,
               &create_tunnel_req_pP->sgw_addr[i].buffer[ip_offset],
               16);
      }

970 971 972 973
      gtpv1u_ue_data_p->bearers[eps_bearer_id - GTPV1U_BEARER_OFFSET].state                  = BEARER_IN_CONFIG;
      gtpv1u_ue_data_p->bearers[eps_bearer_id - GTPV1U_BEARER_OFFSET].teid_eNB               = s1u_teid;
      gtpv1u_ue_data_p->bearers[eps_bearer_id - GTPV1U_BEARER_OFFSET].teid_eNB_stack_session = stack_req.apiInfo.createTunnelEndPointInfo.hStackSession;
      gtpv1u_ue_data_p->bearers[eps_bearer_id - GTPV1U_BEARER_OFFSET].teid_sgw               = create_tunnel_req_pP->sgw_S1u_teid[i];
974
      gtpv1u_ue_data_p->num_bearers++;
975
      create_tunnel_resp_pP->enb_S1u_teid[i] = s1u_teid;
976 977 978 979 980 981 982 983 984

      LOG_I(GTPU,"Copied to create_tunnel_resp tunnel: index %d target gNB ip %d.%d.%d.%d length %d gtp teid %u\n",
    		  i,
    		  create_tunnel_resp_pP->enb_addr.buffer[0],
    		  create_tunnel_resp_pP->enb_addr.buffer[1],
    		  create_tunnel_resp_pP->enb_addr.buffer[2],
    		  create_tunnel_resp_pP->enb_addr.buffer[3],
    		  create_tunnel_resp_pP->enb_addr.length,
    		  create_tunnel_resp_pP->enb_S1u_teid[i]);
985
    } else {
986 987
      create_tunnel_resp_pP->enb_S1u_teid[i] = 0;
      create_tunnel_resp_pP->status         = 0xFF;
988
    }
989

990 991
    create_tunnel_resp_pP->eps_bearer_id[i] = eps_bearer_id;
    create_tunnel_resp_pP->num_tunnels      += 1;
992 993 994
    //-----------------------
    // GTPV1U->PDCP mapping
    //-----------------------
frtabu's avatar
frtabu committed
995
    hash_rc = hashtable_get(RC.gtpv1u_data_g->teid_mapping, s1u_teid, (void **)&gtpv1u_teid_data_p);
996 997 998 999

    if (hash_rc == HASH_TABLE_KEY_NOT_EXISTS) {
      gtpv1u_teid_data_p = calloc (1, sizeof(gtpv1u_teid_data_t));
      gtpv1u_teid_data_p->enb_id        = 0; // TO DO
1000
      gtpv1u_teid_data_p->ue_id         = create_tunnel_req_pP->rnti;
1001
      gtpv1u_teid_data_p->eps_bearer_id = eps_bearer_id;
1002
      hash_rc = hashtable_insert(RC.gtpv1u_data_g->teid_mapping, s1u_teid, gtpv1u_teid_data_p);
1003 1004
      AssertFatal(hash_rc == HASH_TABLE_OK, "Error inserting teid mapping in GTPV1U hashtable");
    } else {
1005 1006
      create_tunnel_resp_pP->enb_S1u_teid[i] = 0;
      create_tunnel_resp_pP->status         = 0xFF;
1007
    }
1008 1009
  }

frtabu's avatar
frtabu committed
1010 1011 1012 1013 1014 1015 1016
  MSC_LOG_TX_MESSAGE(
    MSC_GTPU_ENB,
    MSC_RRC_ENB,
    NULL,0,
    "0 GTPV1U_ENB_CREATE_TUNNEL_RESP rnti %x teid %x",
    create_tunnel_resp_pP->rnti,
    s1u_teid);
1017 1018
  LOG_D(GTPU, "Tx GTPV1U_ENB_CREATE_TUNNEL_RESP ue rnti %x status %d\n",
        create_tunnel_req_pP->rnti,
1019
        create_tunnel_resp_pP->status);
1020 1021
  //return 0;
  return ret;
1022
}
Cedric Roux's avatar
 
Cedric Roux committed
1023

1024
int gtpv1u_update_s1u_tunnel(
frtabu's avatar
frtabu committed
1025 1026 1027 1028
  const instance_t                              instanceP,
  const gtpv1u_enb_create_tunnel_req_t *const  create_tunnel_req_pP,
  const rnti_t                                  prior_rnti
) {
1029 1030 1031 1032
  /* Local tunnel end-point identifier */
  teid_t                   s1u_teid             = 0;
  gtpv1u_teid_data_t      *gtpv1u_teid_data_p   = NULL;
  gtpv1u_ue_data_t        *gtpv1u_ue_data_p     = NULL;
1033
  gtpv1u_ue_data_t        *gtpv1u_ue_data_new_p     = NULL;
1034 1035
  //MessageDef              *message_p            = NULL;
  hashtable_rc_t           hash_rc              = HASH_TABLE_KEY_NOT_EXISTS;
1036 1037
  int                      i,j;
  uint8_t                  bearers_num = 0,bearers_total = 0;
1038 1039 1040 1041
  //-----------------------
  // PDCP->GTPV1U mapping
  //-----------------------
  hash_rc = hashtable_get(RC.gtpv1u_data_g->ue_mapping, prior_rnti, (void **)&gtpv1u_ue_data_p);
frtabu's avatar
frtabu committed
1042 1043

  if(hash_rc != HASH_TABLE_OK) {
1044 1045 1046
    LOG_E(GTPU,"Error get ue_mapping(rnti=%x) from GTPV1U hashtable error\n", prior_rnti);
    return -1;
  }
Cedric Roux's avatar
 
Cedric Roux committed
1047

1048 1049 1050 1051
  gtpv1u_ue_data_new_p = calloc (1, sizeof(gtpv1u_ue_data_t));
  memcpy(gtpv1u_ue_data_new_p,gtpv1u_ue_data_p,sizeof(gtpv1u_ue_data_t));
  gtpv1u_ue_data_new_p->ue_id       = create_tunnel_req_pP->rnti;
  hash_rc = hashtable_insert(RC.gtpv1u_data_g->ue_mapping, create_tunnel_req_pP->rnti, gtpv1u_ue_data_new_p);
1052

1053 1054 1055 1056 1057
  //AssertFatal(hash_rc == HASH_TABLE_OK, "Error inserting ue_mapping in GTPV1U hashtable");
  if ( hash_rc != HASH_TABLE_OK ) {
    LOG_E(GTPU,"Failed to insert ue_mapping(rnti=%x) in GTPV1U hashtable\n",create_tunnel_req_pP->rnti);
    return -1;
  } else {
1058 1059
    LOG_I(GTPU, "inserting ue_mapping(rnti=%x) in GTPV1U hashtable\n",
          create_tunnel_req_pP->rnti);
1060 1061
  }

1062 1063
  hash_rc = hashtable_remove(RC.gtpv1u_data_g->ue_mapping, prior_rnti);
  LOG_I(GTPU, "hashtable_remove ue_mapping(rnti=%x) in GTPV1U hashtable\n",
frtabu's avatar
frtabu committed
1064
        prior_rnti);
1065 1066 1067
  //-----------------------
  // GTPV1U->PDCP mapping
  //-----------------------
1068 1069
  bearers_total =gtpv1u_ue_data_new_p->num_bearers;

frtabu's avatar
frtabu committed
1070
  for(j = 0; j<GTPV1U_MAX_BEARERS_ID; j++) {
1071 1072 1073 1074
    if(gtpv1u_ue_data_new_p->bearers[j].state != BEARER_IN_CONFIG)
      continue;

    bearers_num++;
frtabu's avatar
frtabu committed
1075

1076 1077 1078 1079
    for (i = 0; i < create_tunnel_req_pP->num_tunnels; i++) {
      if(j == (create_tunnel_req_pP->eps_bearer_id[i]-GTPV1U_BEARER_OFFSET))
        break;
    }
frtabu's avatar
frtabu committed
1080 1081

    if(i < create_tunnel_req_pP->num_tunnels) {
1082
      s1u_teid = gtpv1u_ue_data_new_p->bearers[j].teid_eNB;
frtabu's avatar
frtabu committed
1083 1084
      hash_rc = hashtable_get(RC.gtpv1u_data_g->teid_mapping, s1u_teid, (void **)&gtpv1u_teid_data_p);

1085 1086 1087 1088 1089
      if (hash_rc == HASH_TABLE_OK) {
        gtpv1u_teid_data_p->ue_id         = create_tunnel_req_pP->rnti;
        gtpv1u_teid_data_p->eps_bearer_id = create_tunnel_req_pP->eps_bearer_id[i];
        LOG_I(GTPU, "updata teid_mapping te_id %u (prior_rnti %x rnti %x) in GTPV1U hashtable\n",
              s1u_teid,prior_rnti,create_tunnel_req_pP->rnti);
frtabu's avatar
frtabu committed
1090
      } else {
1091 1092
        LOG_W(GTPU, "Error get teid mapping(s1u_teid=%u) from GTPV1U hashtable", s1u_teid);
      }
frtabu's avatar
frtabu committed
1093
    } else {
1094 1095
      s1u_teid = gtpv1u_ue_data_new_p->bearers[j].teid_eNB;
      hash_rc = hashtable_remove(RC.gtpv1u_data_g->teid_mapping, s1u_teid);
Cedric Roux's avatar
 
Cedric Roux committed
1096

1097 1098 1099
      if (hash_rc != HASH_TABLE_OK) {
        LOG_D(GTPU, "Removed user rnti %x , enb S1U teid %u not found\n", prior_rnti, s1u_teid);
      }
frtabu's avatar
frtabu committed
1100

1101 1102 1103 1104 1105
      gtpv1u_ue_data_new_p->bearers[j].state = BEARER_DOWN;
      gtpv1u_ue_data_new_p->num_bearers--;
      LOG_I(GTPU, "delete teid_mapping te_id %u (rnti%x) bearer_id %d in GTPV1U hashtable\n",
            s1u_teid,prior_rnti,j+GTPV1U_BEARER_OFFSET);;
    }
frtabu's avatar
frtabu committed
1106

1107 1108
    if(bearers_num > bearers_total)
      break;
1109
  }
Cedric Roux's avatar
 
Cedric Roux committed
1110

frtabu's avatar
frtabu committed
1111
  return 0;
1112
}
Cedric Roux's avatar
 
Cedric Roux committed
1113

1114
//-----------------------------------------------------------------------------
1115
int gtpv1u_delete_s1u_tunnel(
1116
  const instance_t                             instanceP,
frtabu's avatar
frtabu committed
1117
  const gtpv1u_enb_delete_tunnel_req_t *const req_pP) {
1118 1119 1120 1121 1122 1123 1124
  NwGtpv1uUlpApiT          stack_req;
  NwGtpv1uRcT              rc                   = NW_GTPV1U_FAILURE;
  MessageDef              *message_p = NULL;
  gtpv1u_ue_data_t        *gtpv1u_ue_data_p     = NULL;
  hashtable_rc_t           hash_rc              = HASH_TABLE_KEY_NOT_EXISTS;
  teid_t                   teid_eNB             = 0;
  int                      erab_index           = 0;
1125
  message_p = itti_alloc_new_message(TASK_GTPV1_U, 0, GTPV1U_ENB_DELETE_TUNNEL_RESP);
1126
  GTPV1U_ENB_DELETE_TUNNEL_RESP(message_p).rnti     = req_pP->rnti;
1127
  GTPV1U_ENB_DELETE_TUNNEL_RESP(message_p).status       = 0;
frtabu's avatar
frtabu committed
1128
  hash_rc = hashtable_get(RC.gtpv1u_data_g->ue_mapping, req_pP->rnti, (void **)&gtpv1u_ue_data_p);
Lionel Gauthier's avatar
 
Lionel Gauthier committed
1129

1130 1131 1132
  if (hash_rc == HASH_TABLE_OK) {
    for (erab_index = 0; erab_index < req_pP->num_erab; erab_index++) {
      teid_eNB = gtpv1u_ue_data_p->bearers[req_pP->eps_bearer_id[erab_index] - GTPV1U_BEARER_OFFSET].teid_eNB;
1133 1134
      LOG_D(GTPU, "Rx GTPV1U_ENB_DELETE_TUNNEL user rnti %x eNB S1U teid %u eps bearer id %u\n",
            req_pP->rnti, teid_eNB, req_pP->eps_bearer_id[erab_index]);
1135 1136 1137 1138 1139 1140
      {
        memset(&stack_req, 0, sizeof(NwGtpv1uUlpApiT));
        stack_req.apiType = NW_GTPV1U_ULP_API_DESTROY_TUNNEL_ENDPOINT;
        LOG_D(GTPU, "gtpv1u_delete_s1u_tunnel erab %u  %u\n",
              req_pP->eps_bearer_id[erab_index],
              teid_eNB);
1141
        stack_req.apiInfo.destroyTunnelEndPointInfo.hStackSessionHandle   = gtpv1u_ue_data_p->bearers[req_pP->eps_bearer_id[erab_index] - GTPV1U_BEARER_OFFSET].teid_eNB_stack_session;
1142
        rc = nwGtpv1uProcessUlpReq(RC.gtpv1u_data_g->gtpv1u_stack, &stack_req);
1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160
        LOG_D(GTPU, ".\n");
      }

      if (rc != NW_GTPV1U_OK) {
        GTPV1U_ENB_DELETE_TUNNEL_RESP(message_p).status       |= 0xFF;
        LOG_E(GTPU, "NW_GTPV1U_ULP_API_DESTROY_TUNNEL_ENDPOINT failed");
      }

      //-----------------------
      // PDCP->GTPV1U mapping
      //-----------------------
      gtpv1u_ue_data_p->bearers[req_pP->eps_bearer_id[erab_index] - GTPV1U_BEARER_OFFSET].state       = BEARER_DOWN;
      gtpv1u_ue_data_p->bearers[req_pP->eps_bearer_id[erab_index] - GTPV1U_BEARER_OFFSET].teid_eNB    = 0;
      gtpv1u_ue_data_p->bearers[req_pP->eps_bearer_id[erab_index] - GTPV1U_BEARER_OFFSET].teid_sgw    = 0;
      gtpv1u_ue_data_p->bearers[req_pP->eps_bearer_id[erab_index] - GTPV1U_BEARER_OFFSET].sgw_ip_addr = 0;
      gtpv1u_ue_data_p->num_bearers -= 1;

      if (gtpv1u_ue_data_p->num_bearers == 0) {
1161
        hash_rc = hashtable_remove(RC.gtpv1u_data_g->ue_mapping, req_pP->rnti);
1162
        LOG_D(GTPU, "Removed user rnti %x,no more bearers configured\n", req_pP->rnti);
1163 1164 1165 1166 1167
      }

      //-----------------------
      // GTPV1U->PDCP mapping
      //-----------------------
1168
      hash_rc = hashtable_remove(RC.gtpv1u_data_g->teid_mapping, teid_eNB);
1169 1170

      if (hash_rc != HASH_TABLE_OK) {
1171
        LOG_D(GTPU, "Removed user rnti %x , enb S1U teid %u not found\n", req_pP->rnti, teid_eNB);
1172 1173 1174
      }
    }
  }// else silently do nothing
1175

1176 1177
  LOG_D(GTPU, "Tx GTPV1U_ENB_DELETE_TUNNEL_RESP user rnti %x eNB S1U teid %u status %u\n",
        GTPV1U_ENB_DELETE_TUNNEL_RESP(message_p).rnti,
1178
        GTPV1U_ENB_DELETE_TUNNEL_RESP(message_p).enb_S1u_teid,
Lionel Gauthier's avatar
 
Lionel Gauthier committed
1179
        GTPV1U_ENB_DELETE_TUNNEL_RESP(message_p).status);
Raymond Knopp's avatar
Raymond Knopp committed
1180
  MSC_LOG_TX_MESSAGE(
frtabu's avatar
frtabu committed
1181 1182 1183 1184 1185 1186
    MSC_GTPU_ENB,
    MSC_RRC_ENB,
    NULL,0,
    "0 GTPV1U_ENB_DELETE_TUNNEL_RESP rnti %x teid %x",
    GTPV1U_ENB_DELETE_TUNNEL_RESP(message_p).rnti,
    teid_eNB);
Cedric Roux's avatar
Cedric Roux committed
1187 1188 1189 1190
  if (req_pP->from_gnb)
    return itti_send_msg_to_task(TASK_RRC_GNB, instanceP, message_p);
  else
    return itti_send_msg_to_task(TASK_RRC_ENB, instanceP, message_p);
Cedric Roux's avatar
 
Cedric Roux committed
1191 1192
}

1193

1194
//-----------------------------------------------------------------------------
frtabu's avatar
frtabu committed
1195
int gtpv1u_eNB_init(void) {
1196 1197 1198 1199 1200
  NwGtpv1uRcT             rc = NW_GTPV1U_FAILURE;
  NwGtpv1uUlpEntityT      ulp;
  NwGtpv1uUdpEntityT      udp;
  NwGtpv1uLogMgrEntityT   log;
  NwGtpv1uTimerMgrEntityT tmr;
1201
  //  enb_properties_p = enb_config_get()->properties[0];
frtabu's avatar
frtabu committed
1202
  RC.gtpv1u_data_g = (gtpv1u_data_t *)calloc(sizeof(gtpv1u_data_t),1);
1203
  LOG_I(GTPU, "Initializing GTPU stack %p\n",&RC.gtpv1u_data_g);
1204 1205
  //gtpv1u_data_g.gtpv1u_stack;
  /* Initialize UE hashtable */
1206 1207 1208 1209
  RC.gtpv1u_data_g->ue_mapping      = hashtable_create (32, NULL, NULL);
  AssertFatal(RC.gtpv1u_data_g->ue_mapping != NULL, " ERROR Initializing TASK_GTPV1_U task interface: in hashtable_create returned %p\n", RC.gtpv1u_data_g->ue_mapping);
  RC.gtpv1u_data_g->teid_mapping    = hashtable_create (256, NULL, NULL);
  AssertFatal(RC.gtpv1u_data_g->teid_mapping != NULL, " ERROR Initializing TASK_GTPV1_U task interface: in hashtable_create\n");
frtabu's avatar
frtabu committed
1210
  //  RC.gtpv1u_data_g.enb_ip_address_for_S1u_S12_S4_up         = enb_properties_p->enb_ipv4_address_for_S1U;
1211
  //gtpv1u_data_g.udp_data;
1212 1213
  RC.gtpv1u_data_g->seq_num         = 0;
  RC.gtpv1u_data_g->restart_counter = 0;
1214
  RC.gtpv1u_data_g->enb_ip_address_for_S1u_S12_S4_up = 0;
1215
  /* Initializing GTPv1-U stack */
1216
  if ((rc = nwGtpv1uInitialize(&RC.gtpv1u_data_g->gtpv1u_stack, GTPU_STACK_ENB)) != NW_GTPV1U_OK) {
1217 1218 1219
    LOG_E(GTPU, "Failed to setup nwGtpv1u stack %x\n", rc);
    return -1;
  }
Cedric Roux's avatar
 
Cedric Roux committed
1220

1221
  if ((rc = nwGtpv1uSetLogLevel(RC.gtpv1u_data_g->gtpv1u_stack,
1222 1223 1224 1225
                                NW_LOG_LEVEL_DEBG)) != NW_GTPV1U_OK) {
    LOG_E(GTPU, "Failed to setup loglevel for stack %x\n", rc);
    return -1;
  }
Cedric Roux's avatar
 
Cedric Roux committed
1226

1227 1228 1229 1230
  /* Set the ULP API callback. Called once message have been processed by the
   * nw-gtpv1u stack.
   */
  ulp.ulpReqCallback = gtpv1u_eNB_process_stack_req;
1231
  memset((void *)&(ulp.hUlp), 0, sizeof(NwGtpv1uUlpHandleT));
1232

1233
  if ((rc = nwGtpv1uSetUlpEntity(RC.gtpv1u_data_g->gtpv1u_stack, &ulp)) != NW_GTPV1U_OK) {
1234 1235 1236
    LOG_E(GTPU, "nwGtpv1uSetUlpEntity: %x", rc);
    return -1;
  }
Cedric Roux's avatar
 
Cedric Roux committed
1237

1238 1239 1240 1241
  /* nw-gtpv1u stack requires an udp callback to send data over UDP.
   * We provide a wrapper to UDP task.
   */
  udp.udpDataReqCallback = gtpv1u_eNB_send_udp_msg;
1242
  memset((void *)&(udp.hUdp), 0, sizeof(NwGtpv1uUdpHandleT));
1243

1244
  if ((rc = nwGtpv1uSetUdpEntity(RC.gtpv1u_data_g->gtpv1u_stack, &udp)) != NW_GTPV1U_OK) {
1245 1246 1247
    LOG_E(GTPU, "nwGtpv1uSetUdpEntity: %x", rc);
    return -1;
  }
Cedric Roux's avatar
 
Cedric Roux committed
1248

1249
  log.logReqCallback = gtpv1u_eNB_log_request;
1250
  memset((void *)&(log.logMgrHandle), 0, sizeof(NwGtpv1uLogMgrHandleT));
1251

1252
  if ((rc = nwGtpv1uSetLogMgrEntity(RC.gtpv1u_data_g->gtpv1u_stack, &log)) != NW_GTPV1U_OK) {
1253 1254 1255
    LOG_E(GTPU, "nwGtpv1uSetLogMgrEntity: %x", rc);
    return -1;
  }
Cedric Roux's avatar
 
Cedric Roux committed
1256

1257 1258 1259 1260 1261 1262
  /* Timer interface is more complicated as both wrappers doesn't send a message
   * to the timer task but call the timer API functions start/stop timer.
   */
  tmr.tmrMgrHandle     = 0;
  tmr.tmrStartCallback = gtpv1u_start_timer_wrapper;
  tmr.tmrStopCallback  = gtpv1u_stop_timer_wrapper;
Cedric Roux's avatar
 
Cedric Roux committed
1263

1264
  if ((rc = nwGtpv1uSetTimerMgrEntity(RC.gtpv1u_data_g->gtpv1u_stack, &tmr)) != NW_GTPV1U_OK) {
1265 1266 1267
    LOG_E(GTPU, "nwGtpv1uSetTimerMgrEntity: %x", rc);
    return -1;
  }
Cedric Roux's avatar
 
Cedric Roux committed
1268

1269
#if defined(GTP_DUMP_SOCKET) && GTP_DUMP_SOCKET > 0
1270 1271 1272 1273 1274

  if ((ret = gtpv1u_eNB_create_dump_socket()) < 0) {
    return -1;
  }

1275
#endif
1276 1277
  LOG_D(GTPU, "Initializing GTPV1U interface for eNB: DONE\n");
  return 0;
1278
}
Cedric Roux's avatar
 
Cedric Roux committed
1279

1280
//-----------------------------------------------------------------------------
laurent's avatar
laurent committed
1281
void *gtpv1u_eNB_process_itti_msg(void *notUsed) {
frtabu's avatar
frtabu committed
1282 1283 1284 1285 1286 1287 1288 1289 1290 1291
  /* 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.
   */
  instance_t  instance;
  MessageDef *received_message_p = NULL;
  int         rc = 0;
  itti_receive_msg(TASK_GTPV1_U, &received_message_p);
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_GTPV1U_ENB_TASK, VCD_FUNCTION_IN);
  DevAssert(received_message_p != NULL);
1292
  instance = ITTI_MSG_DESTINATION_INSTANCE(received_message_p);
frtabu's avatar
frtabu committed
1293 1294 1295
  //msg_name_p = ITTI_MSG_NAME(received_message_p);

  switch (ITTI_MSG_ID(received_message_p)) {
laurent's avatar
laurent committed
1296 1297 1298
    case GTPV1U_ENB_S1_REQ:
      gtpv1u_s1_req(instance, &received_message_p->ittiMsg.gtpv1uS1Req);

1299
    case GTPV1U_ENB_DELETE_TUNNEL_REQ: {
1300
      gtpv1u_delete_s1u_tunnel(instance, &received_message_p->ittiMsg.Gtpv1uDeleteTunnelReq);
1301 1302 1303 1304 1305 1306 1307
    }
    break;

    // DATA COMING FROM UDP
    case UDP_DATA_IND: {
      udp_data_ind_t *udp_data_ind_p;
      udp_data_ind_p = &received_message_p->ittiMsg.udp_data_ind;
1308
      nwGtpv1uProcessUdpReq(RC.gtpv1u_data_g->gtpv1u_stack,
1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319
                            udp_data_ind_p->buffer,
                            udp_data_ind_p->buffer_length,
                            udp_data_ind_p->peer_port,
                            udp_data_ind_p->peer_address);
      //itti_free(ITTI_MSG_ORIGIN_ID(received_message_p), udp_data_ind_p->buffer);
    }
    break;

    // DATA TO BE SENT TO UDP
    case GTPV1U_ENB_TUNNEL_DATA_REQ: {
      gtpv1u_enb_tunnel_data_req_t *data_req_p           = NULL;
1320
      NwGtpv1uUlpApiT               stack_req;
1321 1322 1323 1324 1325
      NwGtpv1uRcT                   rc                   = NW_GTPV1U_FAILURE;
      hashtable_rc_t                hash_rc              = HASH_TABLE_KEY_NOT_EXISTS;
      gtpv1u_ue_data_t             *gtpv1u_ue_data_p     = NULL;
      teid_t                        enb_s1u_teid         = 0;
      teid_t                        sgw_s1u_teid         = 0;
1326
      VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_GTPV1U_PROCESS_TUNNEL_DATA_REQ, VCD_FUNCTION_IN);
1327 1328
      data_req_p = &GTPV1U_ENB_TUNNEL_DATA_REQ(received_message_p);
      //ipv4_send_data(ipv4_data_p->sd, data_ind_p->buffer, data_ind_p->length);
1329
#if defined(GTP_DUMP_SOCKET) && GTP_DUMP_SOCKET > 0
1330
      gtpv1u_eNB_write_dump_socket(&data_req_p->buffer[data_req_p->offset],data_req_p->length);
1331
#endif
1332
      memset(&stack_req, 0, sizeof(NwGtpv1uUlpApiT));
frtabu's avatar
frtabu committed
1333
      hash_rc = hashtable_get(RC.gtpv1u_data_g->ue_mapping, (uint64_t)data_req_p->rnti, (void **)&gtpv1u_ue_data_p);
1334 1335

      if (hash_rc == HASH_TABLE_KEY_NOT_EXISTS) {
1336
        LOG_E(GTPU, "nwGtpv1uProcessUlpReq failed: while getting ue rnti %x in hashtable ue_mapping\n", data_req_p->rnti);
1337
      } else {
1338
        if ((data_req_p->rab_id >= GTPV1U_BEARER_OFFSET) && (data_req_p->rab_id < max_val_LTE_DRB_Identity)) {
1339 1340 1341 1342 1343 1344
          enb_s1u_teid                        = gtpv1u_ue_data_p->bearers[data_req_p->rab_id - GTPV1U_BEARER_OFFSET].teid_eNB;
          sgw_s1u_teid                        = gtpv1u_ue_data_p->bearers[data_req_p->rab_id - GTPV1U_BEARER_OFFSET].teid_sgw;
          stack_req.apiType                   = NW_GTPV1U_ULP_API_SEND_TPDU;
          stack_req.apiInfo.sendtoInfo.teid   = sgw_s1u_teid;
          stack_req.apiInfo.sendtoInfo.ipAddr = gtpv1u_ue_data_p->bearers[data_req_p->rab_id - GTPV1U_BEARER_OFFSET].sgw_ip_addr;
          rc = nwGtpv1uGpduMsgNew(
1345
                 RC.gtpv1u_data_g->gtpv1u_stack,
1346 1347
                 sgw_s1u_teid,
                 NW_FALSE,
1348
                 RC.gtpv1u_data_g->seq_num++,
1349 1350 1351 1352 1353 1354 1355
                 data_req_p->buffer,
                 data_req_p->length,
                 data_req_p->offset,
                 &(stack_req.apiInfo.sendtoInfo.hMsg));

          if (rc != NW_GTPV1U_OK) {
            LOG_E(GTPU, "nwGtpv1uGpduMsgNew failed: 0x%x\n", rc);
1356
            MSC_LOG_EVENT(MSC_GTPU_ENB,"0 Failed send G-PDU ltid %u rtid %u size %u",
frtabu's avatar
frtabu committed
1357
                          enb_s1u_teid,sgw_s1u_teid,data_req_p->length);
1358
            (void)enb_s1u_teid; /* avoid gcc warning "set but not used" */
1359
          } else {
1360
            rc = nwGtpv1uProcessUlpReq(RC.gtpv1u_data_g->gtpv1u_stack, &stack_req);
1361 1362 1363

            if (rc != NW_GTPV1U_OK) {
              LOG_E(GTPU, "nwGtpv1uProcessUlpReq failed: 0x%x\n", rc);
1364
              MSC_LOG_EVENT(MSC_GTPU_ENB,"0 Failed send G-PDU ltid %u rtid %u size %u",
frtabu's avatar
frtabu committed
1365
                            enb_s1u_teid,sgw_s1u_teid,data_req_p->length);
Lionel Gauthier's avatar
Lionel Gauthier committed
1366
            } else {
frtabu's avatar
frtabu committed
1367 1368 1369 1370 1371 1372 1373 1374 1375 1376
              MSC_LOG_TX_MESSAGE(
                MSC_GTPU_ENB,
                MSC_GTPU_SGW,
                NULL,
                0,
                MSC_AS_TIME_FMT" G-PDU ltid %u rtid %u size %u",
                0,0,
                enb_s1u_teid,
                sgw_s1u_teid,
                data_req_p->length);
1377
            }
1378

1379
            rc = nwGtpv1uMsgDelete(RC.gtpv1u_data_g->gtpv1u_stack,
1380 1381 1382 1383
                                   stack_req.apiInfo.sendtoInfo.hMsg);

            if (rc != NW_GTPV1U_OK) {
              LOG_E(GTPU, "nwGtpv1uMsgDelete failed: 0x%x\n", rc);
1384
            }
1385
          }
1386
        }
1387 1388
      }

1389
      VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_GTPV1U_PROCESS_TUNNEL_DATA_REQ, VCD_FUNCTION_OUT);
1390 1391 1392 1393 1394
      /* Buffer still needed, do not free it */
      //itti_free(ITTI_MSG_ORIGIN_ID(received_message_p), data_req_p->buffer);
    }
    break;

luaihui's avatar
luaihui committed
1395
    case GTPV1U_ENB_DATA_FORWARDING_REQ: {
1396 1397 1398 1399 1400 1401 1402 1403 1404 1405
      gtpv1u_enb_data_forwarding_req_t *data_req_p           = NULL;
      NwGtpv1uUlpApiT               stack_req;
      NwGtpv1uRcT                   rc                   = NW_GTPV1U_FAILURE;
      hashtable_rc_t                hash_rc              = HASH_TABLE_KEY_NOT_EXISTS;
      gtpv1u_ue_data_t             *gtpv1u_ue_data_p     = NULL;
      teid_t                        enb_s1u_teid         = 0;
      teid_t                        tenb_x2u_teid         = 0;
      VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_GTPV1U_PROCESS_TUNNEL_DATA_REQ, VCD_FUNCTION_IN);
      data_req_p = &GTPV1U_ENB_DATA_FORWARDING_REQ(received_message_p);
      //ipv4_send_data(ipv4_data_p->sd, data_ind_p->buffer, data_ind_p->length);
luaihui's avatar
luaihui committed
1406
#if defined(GTP_DUMP_SOCKET) && GTP_DUMP_SOCKET > 0
1407
      gtpv1u_eNB_write_dump_socket(&data_req_p->buffer[data_req_p->offset],data_req_p->length);
luaihui's avatar
luaihui committed
1408
#endif
1409 1410
      memset(&stack_req, 0, sizeof(NwGtpv1uUlpApiT));
      hash_rc = hashtable_get(RC.gtpv1u_data_g->ue_mapping, (uint64_t)data_req_p->rnti, (void **)&gtpv1u_ue_data_p);
luaihui's avatar
luaihui committed
1411

1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429
      if (hash_rc == HASH_TABLE_KEY_NOT_EXISTS) {
        LOG_E(GTPU, "nwGtpv1uProcessUlpReq failed: while getting ue rnti %x in hashtable ue_mapping\n", data_req_p->rnti);
      } else {
        if ((data_req_p->rab_id >= GTPV1U_BEARER_OFFSET) && (data_req_p->rab_id <= max_val_LTE_DRB_Identity)) {
          enb_s1u_teid                        = gtpv1u_ue_data_p->bearers[data_req_p->rab_id - GTPV1U_BEARER_OFFSET].teid_eNB;
          tenb_x2u_teid                       = gtpv1u_ue_data_p->bearers[data_req_p->rab_id - GTPV1U_BEARER_OFFSET].teid_teNB; // target enb teid
          stack_req.apiType                   = NW_GTPV1U_ULP_API_SEND_TPDU;
          stack_req.apiInfo.sendtoInfo.teid   = tenb_x2u_teid;
          stack_req.apiInfo.sendtoInfo.ipAddr = gtpv1u_ue_data_p->bearers[data_req_p->rab_id - GTPV1U_BEARER_OFFSET].tenb_ip_addr;// target enb ip
          rc = nwGtpv1uGpduMsgNew(
                 RC.gtpv1u_data_g->gtpv1u_stack,
                 tenb_x2u_teid,
                 NW_FALSE,
                 RC.gtpv1u_data_g->seq_num++,
                 data_req_p->buffer,
                 data_req_p->length,
                 data_req_p->offset,
                 &(stack_req.apiInfo.sendtoInfo.hMsg));
luaihui's avatar
luaihui committed
1430 1431

          if (rc != NW_GTPV1U_OK) {
1432
            LOG_E(GTPU, "nwGtpv1uGpduMsgNew failed: 0x%x\n", rc);
luaihui's avatar
luaihui committed
1433
            MSC_LOG_EVENT(MSC_GTPU_ENB,"0 Failed send G-PDU ltid %u rtid %u size %u",
1434 1435
                          enb_s1u_teid,tenb_x2u_teid,data_req_p->length);
            (void)enb_s1u_teid; /* avoid gcc warning "set but not used" */
luaihui's avatar
luaihui committed
1436
          } else {
1437
            rc = nwGtpv1uProcessUlpReq(RC.gtpv1u_data_g->gtpv1u_stack, &stack_req);
luaihui's avatar
luaihui committed
1438

1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454
            if (rc != NW_GTPV1U_OK) {
              LOG_E(GTPU, "nwGtpv1uProcessUlpReq failed: 0x%x\n", rc);
              MSC_LOG_EVENT(MSC_GTPU_ENB,"0 Failed send G-PDU ltid %u rtid %u size %u",
                            enb_s1u_teid,tenb_x2u_teid,data_req_p->length);
            } else {
              MSC_LOG_TX_MESSAGE(
                MSC_GTPU_ENB,
                MSC_GTPU_SGW,
                NULL,
                0,
                MSC_AS_TIME_FMT" G-PDU ltid %u rtid %u size %u",
                0,0,
                enb_s1u_teid,
                tenb_x2u_teid,
                data_req_p->length);
            }
luaihui's avatar
luaihui committed
1455

1456 1457
            rc = nwGtpv1uMsgDelete(RC.gtpv1u_data_g->gtpv1u_stack,
                                   stack_req.apiInfo.sendtoInfo.hMsg);
luaihui's avatar
luaihui committed
1458

1459 1460 1461 1462
            if (rc != NW_GTPV1U_OK) {
              LOG_E(GTPU, "nwGtpv1uMsgDelete failed: 0x%x\n", rc);
            }
          }
luaihui's avatar
luaihui committed
1463 1464 1465
        }
      }

1466 1467 1468 1469 1470
      VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_GTPV1U_PROCESS_TUNNEL_DATA_REQ, VCD_FUNCTION_OUT);
      /* Buffer still needed, do not free it */
      //itti_free(ITTI_MSG_ORIGIN_ID(received_message_p), data_req_p->buffer)
    }
    break;
luaihui's avatar
luaihui committed
1471

1472 1473 1474 1475 1476 1477 1478 1479 1480 1481 1482 1483
    case GTPV1U_ENB_END_MARKER_REQ: {
      gtpv1u_enb_end_marker_req_t   *data_req_p           = NULL;
      NwGtpv1uUlpApiT               stack_req;
      NwGtpv1uRcT                   rc                    = NW_GTPV1U_FAILURE;
      hashtable_rc_t                hash_rc               = HASH_TABLE_KEY_NOT_EXISTS;
      gtpv1u_ue_data_t              *gtpv1u_ue_data_p     = NULL;
      teid_t                        enb_s1u_teid          = 0;
      teid_t                        tenb_x2u_teid         = 0;
      NwGtpv1uMsgT      *pMsg                 = NULL;
      VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_GTPV1U_PROCESS_TUNNEL_DATA_REQ, VCD_FUNCTION_IN);
      data_req_p = &GTPV1U_ENB_END_MARKER_REQ(received_message_p);
      //ipv4_send_data(ipv4_data_p->sd, data_ind_p->buffer, data_ind_p->length);
luaihui's avatar
luaihui committed
1484
#if defined(GTP_DUMP_SOCKET) && GTP_DUMP_SOCKET > 0
1485
      gtpv1u_eNB_write_dump_socket(&data_req_p->buffer[data_req_p->offset],data_req_p->length);
luaihui's avatar
luaihui committed
1486
#endif
1487 1488
      memset(&stack_req, 0, sizeof(NwGtpv1uUlpApiT));
      hash_rc = hashtable_get(RC.gtpv1u_data_g->ue_mapping, (uint64_t)data_req_p->rnti, (void **)&gtpv1u_ue_data_p);
luaihui's avatar
luaihui committed
1489

1490 1491 1492 1493 1494 1495 1496 1497 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507
      if (hash_rc == HASH_TABLE_KEY_NOT_EXISTS) {
        LOG_E(GTPU, "nwGtpv1uProcessUlpReq failed: while getting ue rnti %x in hashtable ue_mapping\n", data_req_p->rnti);
      } else {
        if ((data_req_p->rab_id >= GTPV1U_BEARER_OFFSET) && (data_req_p->rab_id <= max_val_LTE_DRB_Identity)) {
          enb_s1u_teid                        = gtpv1u_ue_data_p->bearers[data_req_p->rab_id - GTPV1U_BEARER_OFFSET].teid_eNB;
          tenb_x2u_teid                       = gtpv1u_ue_data_p->bearers[data_req_p->rab_id - GTPV1U_BEARER_OFFSET].teid_teNB; // target enb teid
          stack_req.apiType                   = NW_GTPV1U_ULP_API_SEND_TPDU;
          stack_req.apiInfo.sendtoInfo.teid   = tenb_x2u_teid;
          stack_req.apiInfo.sendtoInfo.ipAddr = gtpv1u_ue_data_p->bearers[data_req_p->rab_id - GTPV1U_BEARER_OFFSET].tenb_ip_addr;// target enb ip
          rc = nwGtpv1uGpduMsgNew(
                 RC.gtpv1u_data_g->gtpv1u_stack,
                 tenb_x2u_teid,
                 NW_FALSE,
                 RC.gtpv1u_data_g->seq_num++,
                 data_req_p->buffer,
                 data_req_p->length,
                 data_req_p->offset,
                 &(stack_req.apiInfo.sendtoInfo.hMsg));
luaihui's avatar
luaihui committed
1508 1509

          if (rc != NW_GTPV1U_OK) {
1510
            LOG_E(GTPU, "nwGtpv1uGpduMsgNew failed: 0x%x\n", rc);
luaihui's avatar
luaihui committed
1511
            MSC_LOG_EVENT(MSC_GTPU_ENB,"0 Failed send G-PDU ltid %u rtid %u size %u",
1512 1513
                          enb_s1u_teid,tenb_x2u_teid,data_req_p->length);
            (void)enb_s1u_teid; /* avoid gcc warning "set but not used" */
luaihui's avatar
luaihui committed
1514
          } else {
1515 1516 1517
            pMsg = (NwGtpv1uMsgT *) stack_req.apiInfo.sendtoInfo.hMsg;
            pMsg->msgType = NW_GTP_END_MARKER;
            rc = nwGtpv1uProcessUlpReq(RC.gtpv1u_data_g->gtpv1u_stack, &stack_req);
luaihui's avatar
luaihui committed
1518

1519 1520 1521 1522 1523 1524 1525 1526 1527 1528 1529 1530 1531 1532 1533 1534
            if (rc != NW_GTPV1U_OK) {
              LOG_E(GTPU, "nwGtpv1uProcessUlpReq failed: 0x%x\n", rc);
              MSC_LOG_EVENT(MSC_GTPU_ENB,"0 Failed send G-PDU ltid %u rtid %u size %u",
                            enb_s1u_teid,tenb_x2u_teid,data_req_p->length);
            } else {
              MSC_LOG_TX_MESSAGE(
                MSC_GTPU_ENB,
                MSC_GTPU_SGW,
                NULL,
                0,
                MSC_AS_TIME_FMT" G-PDU ltid %u rtid %u size %u",
                0,0,
                enb_s1u_teid,
                tenb_x2u_teid,
                data_req_p->length);
            }
luaihui's avatar
luaihui committed
1535

1536 1537
            rc = nwGtpv1uMsgDelete(RC.gtpv1u_data_g->gtpv1u_stack,
                                   stack_req.apiInfo.sendtoInfo.hMsg);
luaihui's avatar
luaihui committed
1538

1539 1540 1541
            if (rc != NW_GTPV1U_OK) {
              LOG_E(GTPU, "nwGtpv1uMsgDelete failed: 0x%x\n", rc);
            }
luaihui's avatar
luaihui committed
1542

1543 1544 1545 1546 1547
            gtpv1u_enb_delete_tunnel_req_t delete_tunnel_req;
            memset(&delete_tunnel_req, 0, sizeof(delete_tunnel_req));
            delete_tunnel_req.rnti = data_req_p->rnti;
            gtpv1u_delete_x2u_tunnel(instance, &delete_tunnel_req, GTPV1U_SOURCE_ENB);
          }
luaihui's avatar
luaihui committed
1548 1549 1550 1551 1552 1553 1554
        }
      }

      VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_GTPV1U_PROCESS_TUNNEL_DATA_REQ, VCD_FUNCTION_OUT);
    }
    break;

1555
    case TERMINATE_MESSAGE: {
1556
      if (RC.gtpv1u_data_g->ue_mapping != NULL) {
frtabu's avatar
frtabu committed
1557
        hashtable_destroy (&(RC.gtpv1u_data_g->ue_mapping));
1558 1559
      }

1560
      if (RC.gtpv1u_data_g->teid_mapping != NULL) {
frtabu's avatar
frtabu committed
1561
        hashtable_destroy (&(RC.gtpv1u_data_g->teid_mapping));
1562 1563
      }

1564
      LOG_W(GTPU, " *** Exiting GTPU thread\n");
1565 1566 1567 1568 1569 1570 1571 1572 1573 1574 1575 1576
      itti_exit_task();
    }
    break;

    case TIMER_HAS_EXPIRED:
      nwGtpv1uProcessTimeout(&received_message_p->ittiMsg.timer_has_expired.arg);
      break;

    default: {
      LOG_E(GTPU, "Unkwnon message ID %d:%s\n",
            ITTI_MSG_ID(received_message_p),
            ITTI_MSG_NAME(received_message_p));
1577
    }
1578
    break;
frtabu's avatar
frtabu committed
1579
  }
laurent's avatar
laurent committed
1580

frtabu's avatar
frtabu committed
1581 1582 1583 1584 1585
  rc = itti_free(ITTI_MSG_ORIGIN_ID(received_message_p), received_message_p);
  AssertFatal(rc == EXIT_SUCCESS, "Failed to free memory (%d)!\n", rc);
  received_message_p = NULL;
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_GTPV1U_ENB_TASK, VCD_FUNCTION_OUT);
  return NULL;
laurent's avatar
laurent committed
1586 1587 1588
}

//-----------------------------------------------------------------------------
frtabu's avatar
frtabu committed
1589
void *gtpv1u_eNB_task(void *args) {
laurent's avatar
laurent committed
1590 1591 1592 1593 1594 1595 1596 1597
  int rc = 0;
  rc = gtpv1u_eNB_init();
  AssertFatal(rc == 0, "gtpv1u_eNB_init Failed");
  itti_mark_task_ready(TASK_GTPV1_U);
  MSC_START_USE();

  while(1) {
    (void) gtpv1u_eNB_process_itti_msg (NULL);
1598 1599 1600
  }

  return NULL;
Cedric Roux's avatar
 
Cedric Roux committed
1601
}
1602