gtpv1u_eNB.c 42.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"
53

54
#undef GTP_DUMP_SOCKET
55

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

59
#if defined(GTP_DUMP_SOCKET) && GTP_DUMP_SOCKET > 0
60 61 62 63
#include <linux/if.h>
static int           gtpv1u_dump_socket_g;

//-----------------------------------------------------------------------------
frtabu's avatar
frtabu committed
64
int gtpv1u_eNB_create_dump_socket(void) {
65 66 67 68
  struct ifreq ifr;
  int          hdrincl=1;

  if ((gtpv1u_dump_socket_g = socket(AF_INET, SOCK_RAW, IPPROTO_RAW)) < 0 ) {
69 70
    LOG_E(GTPU, "Could not create dump socket %d:%s\n", errno, strerror(errno));
    return -1;
71 72 73
  }

  if (setsockopt(gtpv1u_dump_socket_g,
74 75 76 77 78
                 IPPROTO_IP,
                 IP_HDRINCL,
                 &hdrincl,
                 sizeof(hdrincl))==-1) {
    LOG_E(GTPU, "%s:%d set IP_HDRINCL %d:%s\n",
79 80 81 82 83
          __FILE__, __LINE__, errno, strerror(errno));
  }

  memset(&ifr, 0, sizeof(ifr));
  snprintf(ifr.ifr_name, sizeof(ifr.ifr_name), "lo");
84 85 86

  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",
87
          __FILE__, __LINE__, errno, strerror(errno));
88 89
    close(gtpv1u_dump_socket_g);
    return -1;
90 91 92 93
  }
}

//-----------------------------------------------------------------------------
frtabu's avatar
frtabu committed
94
static void gtpv1u_eNB_write_dump_socket(uint8_t *buffer_pP, uint32_t buffer_lengthP) {
95 96 97 98 99 100
  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)  {
101
    LOG_E(GTPU, "%s:%s:%d  sendto %d:%s\n",
102 103 104 105 106 107 108
          __FILE__, __FUNCTION__, __LINE__, errno, strerror(errno));
  }
}

#endif

//-----------------------------------------------------------------------------
frtabu's avatar
frtabu committed
109
static int gtpv1u_eNB_send_init_udp(const Gtpv1uS1Req *req) {
110 111
  // Create and alloc new message
  MessageDef *message_p;
frtabu's avatar
frtabu committed
112
  struct in_addr addr= {0};
113 114 115 116 117
  message_p = itti_alloc_new_message(TASK_GTPV1_U, UDP_INIT);

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

laurent's avatar
laurent committed
119 120
  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;
121
  UDP_INIT(message_p).address = inet_ntoa(addr);
laurent's avatar
laurent committed
122
  LOG_I(GTPU, "Tx UDP_INIT IP addr %s (%x)\n", UDP_INIT(message_p).address,UDP_INIT(message_p).port);
123
  MSC_LOG_EVENT(
frtabu's avatar
frtabu committed
124 125 126 127
    MSC_GTPU_ENB,
    "0 UDP bind  %s:%u",
    UDP_INIT(message_p).address,
    UDP_INIT(message_p).port);
128
  return itti_send_msg_to_task(TASK_UDP, INSTANCE_DEFAULT, message_p);
129 130
}

laurent's avatar
laurent committed
131 132
static int gtpv1u_s1_req(
  const instance_t                             instanceP,
frtabu's avatar
frtabu committed
133
  const Gtpv1uS1Req *const req) {
laurent's avatar
laurent committed
134
  memcpy(&RC.gtpv1u_data_g->enb_ip_address_for_S1u_S12_S4_up,
frtabu's avatar
frtabu committed
135 136
         &req->enb_ip_address_for_S1u_S12_S4_up,
         sizeof (req->enb_ip_address_for_S1u_S12_S4_up));
laurent's avatar
laurent committed
137 138 139 140
  gtpv1u_eNB_send_init_udp(req);
  return 0;
}

141
//-----------------------------------------------------------------------------
142
NwGtpv1uRcT gtpv1u_eNB_log_request(NwGtpv1uLogMgrHandleT hLogMgr,
143
                                   uint32_t logLevel,
144
                                   NwCharT *file,
145
                                   uint32_t line,
frtabu's avatar
frtabu committed
146
                                   NwCharT *logStr) {
147 148
  LOG_D(GTPU, "%s\n", logStr);
  return NW_GTPV1U_OK;
Cedric Roux's avatar
 
Cedric Roux committed
149 150
}

151
//-----------------------------------------------------------------------------
152
NwGtpv1uRcT gtpv1u_eNB_send_udp_msg(
153
  NwGtpv1uUdpHandleT udpHandle,
154 155 156 157
  uint8_t *buffer,
  uint32_t buffer_len,
  uint32_t buffer_offset,
  uint32_t peerIpAddr,
frtabu's avatar
frtabu committed
158
  uint16_t peerPort) {
159 160 161 162
  // Create and alloc new message
  MessageDef     *message_p       = NULL;
  udp_data_req_t *udp_data_req_p  = NULL;
  message_p = itti_alloc_new_message(TASK_GTPV1_U, UDP_DATA_REQ);
163

164
  if (message_p) {
165
#if defined(LOG_GTPU) && LOG_GTPU > 0
166
    LOG_D(GTPU, "Sending UDP_DATA_REQ length %u offset %u", buffer_len, buffer_offset);
167
#endif
168 169 170 171 172 173 174 175 176 177
    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;
  }
178 179 180
}


181
//-----------------------------------------------------------------------------
Cedric Roux's avatar
 
Cedric Roux committed
182
/* Callback called when a gtpv1u message arrived on UDP interface */
183
NwGtpv1uRcT gtpv1u_eNB_process_stack_req(
184
  NwGtpv1uUlpHandleT hUlp,
frtabu's avatar
frtabu committed
185
  NwGtpv1uUlpApiT   *pUlpApi) {
186
  boolean_t           result             = FALSE;
187 188 189 190
  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
191
  NwGtpv1uRcT         rc;
192 193 194 195 196 197

  switch(pUlpApi->apiType) {
    /* Here there are two type of messages handled:
     * - T-PDU
     * - END-MARKER
     */
frtabu's avatar
frtabu committed
198 199 200 201 202 203 204 205 206 207 208 209
    case NW_GTPV1U_ULP_API_RECV_TPDU: {
      uint8_t              buffer[4096];
      uint32_t             buffer_len;
      /* Nw-gptv1u stack has processed a PDU. we can schedule it to PDCP
       * for transmission.
       */
      teid = pUlpApi->apiInfo.recvMsgInfo.teid;

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

frtabu's avatar
frtabu committed
211
      itti_free(TASK_UDP, ((NwGtpv1uMsgT *)pUlpApi->apiInfo.recvMsgInfo.hMsg)->msgBuf);
212
#if defined(GTP_DUMP_SOCKET) && GTP_DUMP_SOCKET > 0
frtabu's avatar
frtabu committed
213
      gtpv1u_eNB_write_dump_socket(buffer,buffer_len);
214
#endif
frtabu's avatar
frtabu committed
215 216
      rc = nwGtpv1uMsgDelete(RC.gtpv1u_data_g->gtpv1u_stack,
                             pUlpApi->apiInfo.recvMsgInfo.hMsg);
217

frtabu's avatar
frtabu committed
218 219 220
      if (rc != NW_GTPV1U_OK) {
        LOG_E(GTPU, "nwGtpv1uMsgDelete failed: 0x%x\n", rc);
      }
Cedric Roux's avatar
Cedric Roux committed
221

frtabu's avatar
frtabu committed
222 223 224 225
      //-----------------------
      // GTPV1U->PDCP mapping
      //-----------------------
      hash_rc = hashtable_get(RC.gtpv1u_data_g->teid_mapping, teid, (void **)&gtpv1u_teid_data_p);
226

frtabu's avatar
frtabu committed
227
      if (hash_rc == HASH_TABLE_OK) {
228
#if defined(LOG_GTPU) && LOG_GTPU > 0
frtabu's avatar
frtabu committed
229 230 231 232 233 234
        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);
235
#endif
frtabu's avatar
frtabu committed
236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254
        //#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);
        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,
                   PDCP_TRANSMISSION_MODE_DATA
255
#if (LTE_RRC_VERSION >= MAKE_VERSION(14, 0, 0))
frtabu's avatar
frtabu committed
256
                   ,NULL, NULL
257
#endif
frtabu's avatar
frtabu committed
258 259 260 261 262 263 264 265 266 267 268 269
                 );

        if ( result == FALSE ) {
          if (ctxt.configured == FALSE )
            LOG_W(GTPU, "PDCP data request failed, cause: RB is not configured!\n") ;
          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);
270
      }
Cedric Roux's avatar
 
Cedric Roux committed
271
    }
272
    break;
frtabu's avatar
frtabu committed
273 274 275 276 277 278 279

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

280
  return NW_GTPV1U_OK;
Cedric Roux's avatar
 
Cedric Roux committed
281 282 283
}


284
//-----------------------------------------------------------------------------
285
int data_recv_callback(uint16_t  portP,
Cedric Roux's avatar
 
Cedric Roux committed
286 287 288
                       uint32_t  address,
                       uint8_t  *buffer,
                       uint32_t  length,
frtabu's avatar
frtabu committed
289
                       void     *arg_p) {
290
  gtpv1u_data_t        *gtpv1u_data_p;
Cedric Roux's avatar
 
Cedric Roux committed
291

292 293 294
  if (arg_p == NULL) {
    return -1;
  }
Cedric Roux's avatar
 
Cedric Roux committed
295

296 297 298 299 300 301
  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
302 303
}

304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 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 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397
//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
398 399


400
//-----------------------------------------------------------------------------
401
static NwGtpv1uRcT gtpv1u_start_timer_wrapper(
402
  NwGtpv1uTimerMgrHandleT tmrMgrHandle,
403 404 405
  uint32_t                  timeoutSec,
  uint32_t                  timeoutUsec,
  uint32_t                  tmrType,
406
  void                   *timeoutArg,
frtabu's avatar
frtabu committed
407
  NwGtpv1uTimerHandleT   *hTmr) {
408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427
  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
428

429
  return rc;
430
}
Cedric Roux's avatar
 
Cedric Roux committed
431 432


433 434 435
//-----------------------------------------------------------------------------
static NwGtpv1uRcT
gtpv1u_stop_timer_wrapper(
436
  NwGtpv1uTimerMgrHandleT tmrMgrHandle,
frtabu's avatar
frtabu committed
437
  NwGtpv1uTimerHandleT hTmr) {
438 439
  NwGtpv1uRcT rc = NW_GTPV1U_OK;
  return rc;
Cedric Roux's avatar
 
Cedric Roux committed
440 441
}

442

443
//-----------------------------------------------------------------------------
444 445
int
gtpv1u_initial_req(
446 447 448
  gtpv1u_data_t *gtpv1u_data_pP,
  teid_t         teidP,
  tcp_udp_port_t portP,
frtabu's avatar
frtabu committed
449
  uint32_t       address) {
450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465
  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
466 467
}

468
//-----------------------------------------------------------------------------
469 470
int
gtpv1u_new_data_req(
471 472
  uint8_t  enb_module_idP,
  rnti_t   ue_rntiP,
473 474 475 476
  uint8_t  rab_idP,
  uint8_t *buffer_pP,
  uint32_t buf_lenP,
  uint32_t buf_offsetP
frtabu's avatar
frtabu committed
477
) {
478 479 480 481 482 483 484 485
  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));
486 487
  ue.ue_id = ue_rntiP;
  AssertFatal(enb_module_idP >=0, "Bad parameter enb module id %u\n", enb_module_idP);
488 489
  AssertFatal((rab_idP - GTPV1U_BEARER_OFFSET)< GTPV1U_MAX_BEARERS_ID, "Bad parameter rab id %u\n", rab_idP);
  AssertFatal((rab_idP - GTPV1U_BEARER_OFFSET) >= 0 , "Bad parameter rab id %u\n", rab_idP);
490
  gtpv1u_data_p = RC.gtpv1u_data_g;
491
  /* Check that UE context is present in ue map. */
frtabu's avatar
frtabu committed
492
  hash_rc = hashtable_get(gtpv1u_data_p->ue_mapping, (uint64_t)ue_rntiP, (void **)&ue_inst_p);
Cedric Roux's avatar
 
Cedric Roux committed
493

494
  if (hash_rc ==  HASH_TABLE_KEY_NOT_EXISTS ) {
495
    LOG_E(GTPU, "[UE %d] Trying to send data on non-existing UE context\n", ue_rntiP);
496 497
    return -1;
  }
Cedric Roux's avatar
 
Cedric Roux committed
498

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

501 502 503 504 505 506 507
  /* 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
508
    //#warning  LG: HACK WHILE WAITING FOR NAS, normally return -1
Cedric Roux's avatar
 
Cedric Roux committed
509

510 511 512
    if (bearer_p->state != BEARER_IN_CONFIG)
      return -1;
  }
Cedric Roux's avatar
 
Cedric Roux committed
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
  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
551 552
}

553
//-----------------------------------------------------------------------------
554
int
555
gtpv1u_create_s1u_tunnel(
556
  const instance_t                              instanceP,
frtabu's avatar
frtabu committed
557 558 559
  const gtpv1u_enb_create_tunnel_req_t *const  create_tunnel_req_pP,
  gtpv1u_enb_create_tunnel_resp_t *const create_tunnel_resp_pP
) {
560 561 562 563 564 565 566
  /* 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;
567
  //MessageDef              *message_p            = NULL;
568 569 570 571 572 573 574
  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;
575 576 577 578
  int                      loop_counter         = 0;
  int                      ret                  = 0;


Lionel Gauthier's avatar
Lionel Gauthier committed
579
  MSC_LOG_RX_MESSAGE(
frtabu's avatar
frtabu committed
580 581 582 583 584 585 586
    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]);
587 588 589
  create_tunnel_resp_pP->rnti        = create_tunnel_req_pP->rnti;
  create_tunnel_resp_pP->status      = 0;
  create_tunnel_resp_pP->num_tunnels = 0;
590 591 592

  for (i = 0; i < create_tunnel_req_pP->num_tunnels; i++) {
    ip_offset               = 0;
593
    loop_counter            = 0;
594
    eps_bearer_id = create_tunnel_req_pP->eps_bearer_id[i];
595 596
    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);
597 598 599 600 601 602 603 604 605
    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;
606
      rc = nwGtpv1uProcessUlpReq(RC.gtpv1u_data_g->gtpv1u_stack, &stack_req);
607
      LOG_D(GTPU, ".\n");
608 609 610 611 612 613 614
      loop_counter++;
    } while (rc != NW_GTPV1U_OK && loop_counter < 10);
    if ( rc != NW_GTPV1U_OK && loop_counter == 10 ) {
      LOG_E(GTPU,"NwGtpv1uCreateTunnelEndPoint failed 10 times,start next loop\n");
      ret = -1;
      continue;
    }
615 616 617 618

    //-----------------------
    // PDCP->GTPV1U mapping
    //-----------------------
619
    hash_rc = hashtable_get(RC.gtpv1u_data_g->ue_mapping, create_tunnel_req_pP->rnti, (void **)&gtpv1u_ue_data_p);
620 621 622 623

    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));
624
        hash_rc = hashtable_insert(RC.gtpv1u_data_g->ue_mapping, create_tunnel_req_pP->rnti, gtpv1u_ue_data_p);
625 626 627
        AssertFatal(hash_rc == HASH_TABLE_OK, "Error inserting ue_mapping in GTPV1U hashtable");
      }

628
      gtpv1u_ue_data_p->ue_id       = create_tunnel_req_pP->rnti;
629
      gtpv1u_ue_data_p->instance_id = 0; // TO DO
630
      memcpy(&create_tunnel_resp_pP->enb_addr.buffer,
631
             &RC.gtpv1u_data_g->enb_ip_address_for_S1u_S12_S4_up,
632
             sizeof (in_addr_t));
633
      create_tunnel_resp_pP->enb_addr.length = sizeof (in_addr_t);
634 635 636 637 638 639 640 641 642
      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
643
        in_addr = *((in_addr_t *)create_tunnel_req_pP->sgw_addr[i].buffer);
644 645 646 647 648 649 650 651 652 653 654
        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);
      }

655 656 657 658
      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];
659
      gtpv1u_ue_data_p->num_bearers++;
660
      create_tunnel_resp_pP->enb_S1u_teid[i] = s1u_teid;
661
    } else {
662 663
      create_tunnel_resp_pP->enb_S1u_teid[i] = 0;
      create_tunnel_resp_pP->status         = 0xFF;
664
    }
665

666 667
    create_tunnel_resp_pP->eps_bearer_id[i] = eps_bearer_id;
    create_tunnel_resp_pP->num_tunnels      += 1;
668 669 670
    //-----------------------
    // GTPV1U->PDCP mapping
    //-----------------------
frtabu's avatar
frtabu committed
671
    hash_rc = hashtable_get(RC.gtpv1u_data_g->teid_mapping, s1u_teid, (void **)&gtpv1u_teid_data_p);
672 673 674 675

    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
676
      gtpv1u_teid_data_p->ue_id         = create_tunnel_req_pP->rnti;
677
      gtpv1u_teid_data_p->eps_bearer_id = eps_bearer_id;
678
      hash_rc = hashtable_insert(RC.gtpv1u_data_g->teid_mapping, s1u_teid, gtpv1u_teid_data_p);
679 680
      AssertFatal(hash_rc == HASH_TABLE_OK, "Error inserting teid mapping in GTPV1U hashtable");
    } else {
681 682
      create_tunnel_resp_pP->enb_S1u_teid[i] = 0;
      create_tunnel_resp_pP->status         = 0xFF;
683
    }
684 685
  }

frtabu's avatar
frtabu committed
686 687 688 689 690 691 692
  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);
693 694
  LOG_D(GTPU, "Tx GTPV1U_ENB_CREATE_TUNNEL_RESP ue rnti %x status %d\n",
        create_tunnel_req_pP->rnti,
695
        create_tunnel_resp_pP->status);
696 697
  //return 0;
  return ret;
698
}
Cedric Roux's avatar
 
Cedric Roux committed
699

700
int gtpv1u_update_s1u_tunnel(
frtabu's avatar
frtabu committed
701 702 703 704
  const instance_t                              instanceP,
  const gtpv1u_enb_create_tunnel_req_t *const  create_tunnel_req_pP,
  const rnti_t                                  prior_rnti
) {
705 706 707 708
  /* 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;
709
  gtpv1u_ue_data_t        *gtpv1u_ue_data_new_p     = NULL;
710 711
  //MessageDef              *message_p            = NULL;
  hashtable_rc_t           hash_rc              = HASH_TABLE_KEY_NOT_EXISTS;
712 713
  int                      i,j;
  uint8_t                  bearers_num = 0,bearers_total = 0;
714 715 716 717
  //-----------------------
  // 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
718 719

  if(hash_rc != HASH_TABLE_OK) {
720 721 722
    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
723

724 725 726 727
  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);
728 729 730 731 732
  //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 {
733
  LOG_I(GTPU, "inserting ue_mapping(rnti=%x) in GTPV1U hashtable\n",
frtabu's avatar
frtabu committed
734
        create_tunnel_req_pP->rnti);
735 736
  }

737 738
  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
739
        prior_rnti);
740 741 742
  //-----------------------
  // GTPV1U->PDCP mapping
  //-----------------------
743 744
  bearers_total =gtpv1u_ue_data_new_p->num_bearers;

frtabu's avatar
frtabu committed
745
  for(j = 0; j<GTPV1U_MAX_BEARERS_ID; j++) {
746 747 748 749
    if(gtpv1u_ue_data_new_p->bearers[j].state != BEARER_IN_CONFIG)
      continue;

    bearers_num++;
frtabu's avatar
frtabu committed
750

751 752 753 754
    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
755 756

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

760 761 762 763 764
      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
765
      } else {
766 767
        LOG_W(GTPU, "Error get teid mapping(s1u_teid=%u) from GTPV1U hashtable", s1u_teid);
      }
frtabu's avatar
frtabu committed
768
    } else {
769 770
      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
771

772 773 774
      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
775

776 777 778 779 780
      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
781

782 783
    if(bearers_num > bearers_total)
      break;
784
  }
Cedric Roux's avatar
 
Cedric Roux committed
785

frtabu's avatar
frtabu committed
786
  return 0;
787
}
Cedric Roux's avatar
 
Cedric Roux committed
788

789
//-----------------------------------------------------------------------------
790
int gtpv1u_delete_s1u_tunnel(
791
  const instance_t                             instanceP,
frtabu's avatar
frtabu committed
792
  const gtpv1u_enb_delete_tunnel_req_t *const req_pP) {
793 794 795 796 797 798 799 800
  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;
  message_p = itti_alloc_new_message(TASK_GTPV1_U, GTPV1U_ENB_DELETE_TUNNEL_RESP);
801
  GTPV1U_ENB_DELETE_TUNNEL_RESP(message_p).rnti     = req_pP->rnti;
802
  GTPV1U_ENB_DELETE_TUNNEL_RESP(message_p).status       = 0;
frtabu's avatar
frtabu committed
803
  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
804

805 806 807
  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;
808 809
      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]);
810 811 812 813 814 815
      {
        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);
816
        stack_req.apiInfo.destroyTunnelEndPointInfo.hStackSessionHandle   = gtpv1u_ue_data_p->bearers[req_pP->eps_bearer_id[erab_index] - GTPV1U_BEARER_OFFSET].teid_eNB_stack_session;
817
        rc = nwGtpv1uProcessUlpReq(RC.gtpv1u_data_g->gtpv1u_stack, &stack_req);
818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835
        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) {
836
        hash_rc = hashtable_remove(RC.gtpv1u_data_g->ue_mapping, req_pP->rnti);
837
        LOG_D(GTPU, "Removed user rnti %x,no more bearers configured\n", req_pP->rnti);
838 839 840 841 842
      }

      //-----------------------
      // GTPV1U->PDCP mapping
      //-----------------------
843
      hash_rc = hashtable_remove(RC.gtpv1u_data_g->teid_mapping, teid_eNB);
844 845

      if (hash_rc != HASH_TABLE_OK) {
846
        LOG_D(GTPU, "Removed user rnti %x , enb S1U teid %u not found\n", req_pP->rnti, teid_eNB);
847 848 849
      }
    }
  }// else silently do nothing
850

851 852
  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,
853
        GTPV1U_ENB_DELETE_TUNNEL_RESP(message_p).enb_S1u_teid,
Lionel Gauthier's avatar
 
Lionel Gauthier committed
854
        GTPV1U_ENB_DELETE_TUNNEL_RESP(message_p).status);
Raymond Knopp's avatar
Raymond Knopp committed
855
  MSC_LOG_TX_MESSAGE(
frtabu's avatar
frtabu committed
856 857 858 859 860 861
    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);
862
  return itti_send_msg_to_task(TASK_RRC_ENB, instanceP, message_p);
Cedric Roux's avatar
 
Cedric Roux committed
863 864
}

865

866
//-----------------------------------------------------------------------------
frtabu's avatar
frtabu committed
867
int gtpv1u_eNB_init(void) {
868 869 870 871 872
  NwGtpv1uRcT             rc = NW_GTPV1U_FAILURE;
  NwGtpv1uUlpEntityT      ulp;
  NwGtpv1uUdpEntityT      udp;
  NwGtpv1uLogMgrEntityT   log;
  NwGtpv1uTimerMgrEntityT tmr;
873
  //  enb_properties_p = enb_config_get()->properties[0];
frtabu's avatar
frtabu committed
874
  RC.gtpv1u_data_g = (gtpv1u_data_t *)calloc(sizeof(gtpv1u_data_t),1);
875
  LOG_I(GTPU, "Initializing GTPU stack %p\n",&RC.gtpv1u_data_g);
876 877
  //gtpv1u_data_g.gtpv1u_stack;
  /* Initialize UE hashtable */
878 879 880 881
  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
882
  //  RC.gtpv1u_data_g.enb_ip_address_for_S1u_S12_S4_up         = enb_properties_p->enb_ipv4_address_for_S1U;
883
  //gtpv1u_data_g.udp_data;
884 885
  RC.gtpv1u_data_g->seq_num         = 0;
  RC.gtpv1u_data_g->restart_counter = 0;
886 887

  /* Initializing GTPv1-U stack */
888
  if ((rc = nwGtpv1uInitialize(&RC.gtpv1u_data_g->gtpv1u_stack, GTPU_STACK_ENB)) != NW_GTPV1U_OK) {
889 890 891
    LOG_E(GTPU, "Failed to setup nwGtpv1u stack %x\n", rc);
    return -1;
  }
Cedric Roux's avatar
 
Cedric Roux committed
892

893
  if ((rc = nwGtpv1uSetLogLevel(RC.gtpv1u_data_g->gtpv1u_stack,
894 895 896 897
                                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
898

899 900 901 902
  /* Set the ULP API callback. Called once message have been processed by the
   * nw-gtpv1u stack.
   */
  ulp.ulpReqCallback = gtpv1u_eNB_process_stack_req;
903
  memset((void *)&(ulp.hUlp), 0, sizeof(NwGtpv1uUlpHandleT));
904
  if ((rc = nwGtpv1uSetUlpEntity(RC.gtpv1u_data_g->gtpv1u_stack, &ulp)) != NW_GTPV1U_OK) {
905 906 907
    LOG_E(GTPU, "nwGtpv1uSetUlpEntity: %x", rc);
    return -1;
  }
Cedric Roux's avatar
 
Cedric Roux committed
908

909 910 911 912
  /* 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;
913
  memset((void *)&(udp.hUdp), 0, sizeof(NwGtpv1uUdpHandleT));
914
  if ((rc = nwGtpv1uSetUdpEntity(RC.gtpv1u_data_g->gtpv1u_stack, &udp)) != NW_GTPV1U_OK) {
915 916 917
    LOG_E(GTPU, "nwGtpv1uSetUdpEntity: %x", rc);
    return -1;
  }
Cedric Roux's avatar
 
Cedric Roux committed
918

919
  log.logReqCallback = gtpv1u_eNB_log_request;
920
  memset((void *)&(log.logMgrHandle), 0, sizeof(NwGtpv1uLogMgrHandleT));
921
  if ((rc = nwGtpv1uSetLogMgrEntity(RC.gtpv1u_data_g->gtpv1u_stack, &log)) != NW_GTPV1U_OK) {
922 923 924
    LOG_E(GTPU, "nwGtpv1uSetLogMgrEntity: %x", rc);
    return -1;
  }
Cedric Roux's avatar
 
Cedric Roux committed
925

926 927 928 929 930 931
  /* 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
932

933
  if ((rc = nwGtpv1uSetTimerMgrEntity(RC.gtpv1u_data_g->gtpv1u_stack, &tmr)) != NW_GTPV1U_OK) {
934 935 936
    LOG_E(GTPU, "nwGtpv1uSetTimerMgrEntity: %x", rc);
    return -1;
  }
Cedric Roux's avatar
 
Cedric Roux committed
937

938
#if defined(GTP_DUMP_SOCKET) && GTP_DUMP_SOCKET > 0
939 940 941 942 943

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

944
#endif
945 946
  LOG_D(GTPU, "Initializing GTPV1U interface for eNB: DONE\n");
  return 0;
947
}
Cedric Roux's avatar
 
Cedric Roux committed
948

949
//-----------------------------------------------------------------------------
laurent's avatar
laurent committed
950
void *gtpv1u_eNB_process_itti_msg(void *notUsed) {
frtabu's avatar
frtabu committed
951 952 953 954 955 956 957 958 959 960 961 962 963 964
  /* 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);
  instance = ITTI_MSG_INSTANCE(received_message_p);
  //msg_name_p = ITTI_MSG_NAME(received_message_p);

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

968
    case GTPV1U_ENB_DELETE_TUNNEL_REQ: {
969
      gtpv1u_delete_s1u_tunnel(instance, &received_message_p->ittiMsg.Gtpv1uDeleteTunnelReq);
970 971 972 973 974 975 976
    }
    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;
977
      nwGtpv1uProcessUdpReq(RC.gtpv1u_data_g->gtpv1u_stack,
978 979 980 981 982 983 984 985 986 987 988
                            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;
989
      NwGtpv1uUlpApiT               stack_req;
990 991 992 993 994
      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;
995
      VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_GTPV1U_PROCESS_TUNNEL_DATA_REQ, VCD_FUNCTION_IN);
996 997
      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);
998
#if defined(GTP_DUMP_SOCKET) && GTP_DUMP_SOCKET > 0
999
      gtpv1u_eNB_write_dump_socket(&data_req_p->buffer[data_req_p->offset],data_req_p->length);
1000
#endif
1001
      memset(&stack_req, 0, sizeof(NwGtpv1uUlpApiT));
frtabu's avatar
frtabu committed
1002
      hash_rc = hashtable_get(RC.gtpv1u_data_g->ue_mapping, (uint64_t)data_req_p->rnti, (void **)&gtpv1u_ue_data_p);
1003 1004

      if (hash_rc == HASH_TABLE_KEY_NOT_EXISTS) {
1005
        LOG_E(GTPU, "nwGtpv1uProcessUlpReq failed: while getting ue rnti %x in hashtable ue_mapping\n", data_req_p->rnti);
1006
      } else {
1007
        if ((data_req_p->rab_id >= GTPV1U_BEARER_OFFSET) && (data_req_p->rab_id < max_val_LTE_DRB_Identity)) {
1008 1009 1010 1011 1012 1013
          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(
1014
                 RC.gtpv1u_data_g->gtpv1u_stack,
1015 1016
                 sgw_s1u_teid,
                 NW_FALSE,
1017
                 RC.gtpv1u_data_g->seq_num++,
1018 1019 1020 1021 1022 1023 1024
                 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);
1025
            MSC_LOG_EVENT(MSC_GTPU_ENB,"0 Failed send G-PDU ltid %u rtid %u size %u",
frtabu's avatar
frtabu committed
1026
                          enb_s1u_teid,sgw_s1u_teid,data_req_p->length);
1027
            (void)enb_s1u_teid; /* avoid gcc warning "set but not used" */
1028
          } else {
1029
            rc = nwGtpv1uProcessUlpReq(RC.gtpv1u_data_g->gtpv1u_stack, &stack_req);
1030 1031 1032

            if (rc != NW_GTPV1U_OK) {
              LOG_E(GTPU, "nwGtpv1uProcessUlpReq failed: 0x%x\n", rc);
1033
              MSC_LOG_EVENT(MSC_GTPU_ENB,"0 Failed send G-PDU ltid %u rtid %u size %u",
frtabu's avatar
frtabu committed
1034
                            enb_s1u_teid,sgw_s1u_teid,data_req_p->length);
Lionel Gauthier's avatar
Lionel Gauthier committed
1035
            } else {
frtabu's avatar
frtabu committed
1036 1037 1038 1039 1040 1041 1042 1043 1044 1045
              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);
1046
            }
1047

1048
            rc = nwGtpv1uMsgDelete(RC.gtpv1u_data_g->gtpv1u_stack,
1049 1050 1051 1052
                                   stack_req.apiInfo.sendtoInfo.hMsg);

            if (rc != NW_GTPV1U_OK) {
              LOG_E(GTPU, "nwGtpv1uMsgDelete failed: 0x%x\n", rc);
1053
            }
1054
          }
1055
        }
1056 1057
      }

1058
      VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_GTPV1U_PROCESS_TUNNEL_DATA_REQ, VCD_FUNCTION_OUT);
1059 1060 1061 1062 1063 1064
      /* Buffer still needed, do not free it */
      //itti_free(ITTI_MSG_ORIGIN_ID(received_message_p), data_req_p->buffer);
    }
    break;

    case TERMINATE_MESSAGE: {
1065
      if (RC.gtpv1u_data_g->ue_mapping != NULL) {
frtabu's avatar
frtabu committed
1066
        hashtable_destroy (&(RC.gtpv1u_data_g->ue_mapping));
1067 1068
      }

1069
      if (RC.gtpv1u_data_g->teid_mapping != NULL) {
frtabu's avatar
frtabu committed
1070
        hashtable_destroy (&(RC.gtpv1u_data_g->teid_mapping));
1071 1072
      }

1073
      LOG_W(GTPU, " *** Exiting GTPU thread\n");
1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085
      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));
1086
    }
1087
    break;
frtabu's avatar
frtabu committed
1088
  }
laurent's avatar
laurent committed
1089

frtabu's avatar
frtabu committed
1090 1091 1092 1093 1094
  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
1095 1096 1097
}

//-----------------------------------------------------------------------------
frtabu's avatar
frtabu committed
1098
void *gtpv1u_eNB_task(void *args) {
laurent's avatar
laurent committed
1099 1100 1101 1102 1103 1104 1105 1106
  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);
1107 1108 1109
  }

  return NULL;
Cedric Roux's avatar
 
Cedric Roux committed
1110
}
1111