gtpv1u_eNB.c 44 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 36
#include "intertask_interface.h"
#include "timer.h"
Lionel Gauthier's avatar
Lionel Gauthier committed
37
#include "msc.h"
38 39

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

54
#undef GTP_DUMP_SOCKET
55

oai's avatar
oai committed
56
/*
57
extern boolean_t pdcp_data_req(
58 59 60 61 62 63 64
  const protocol_ctxt_t* const  ctxt_pP,
  const srb_flag_t     srb_flagP,
  const rb_id_t        rb_idP,
  const mui_t          muiP,
  const confirm_t      confirmP,
  const sdu_size_t     sdu_buffer_sizeP,
  unsigned char *const sdu_buffer_pP,
65 66 67 68 69 70 71
  const pdcp_transmission_mode_t modeP
#ifdef Rel14
    ,const uint32_t * const sourceL2Id
    ,const uint32_t * const destinationL2Id
#endif
    );

72
  const pdcp_transmission_mode_t modeP);
oai's avatar
oai committed
73
*/
74
extern unsigned char NB_eNB_INST;
75
extern RAN_CONTEXT_t RC;
Lionel Gauthier's avatar
Lionel Gauthier committed
76 77

static int
78 79
gtpv1u_eNB_send_init_udp(
  uint16_t port_number);
Lionel Gauthier's avatar
Lionel Gauthier committed
80 81

NwGtpv1uRcT
82 83
gtpv1u_eNB_log_request(
  NwGtpv1uLogMgrHandleT   hLogMgr,
84
  uint32_t                  logLevel,
85
  NwCharT                *file,
86
  uint32_t                  line,
87
  NwCharT                *logStr);
Lionel Gauthier's avatar
Lionel Gauthier committed
88 89

NwGtpv1uRcT
90 91
gtpv1u_eNB_send_udp_msg(
  NwGtpv1uUdpHandleT      udpHandle,
92 93 94 95 96
  uint8_t                  *buffer,
  uint32_t                  buffer_len,
  uint32_t                  buffer_offset,
  uint32_t                  peerIpAddr,
  uint16_t                  peerPort);
Lionel Gauthier's avatar
Lionel Gauthier committed
97 98

NwGtpv1uRcT
99 100 101
gtpv1u_eNB_process_stack_req(
  NwGtpv1uUlpHandleT hUlp,
  NwGtpv1uUlpApiT   *pUlpApi);
Lionel Gauthier's avatar
Lionel Gauthier committed
102 103

int
104 105 106 107 108 109
data_recv_callback(
  uint16_t  portP,
  uint32_t  address,
  uint8_t  *buffer,
  uint32_t  length,
  void     *arg_p);
110 111 112 113 114 115 116
//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);
Lionel Gauthier's avatar
Lionel Gauthier committed
117
static NwGtpv1uRcT
118 119
gtpv1u_start_timer_wrapper(
  NwGtpv1uTimerMgrHandleT tmrMgrHandle,
120 121 122
  uint32_t                  timeoutSec,
  uint32_t                  timeoutUsec,
  uint32_t                  tmrType,
123 124
  void                   *timeoutArg,
  NwGtpv1uTimerHandleT   *hTmr);
Lionel Gauthier's avatar
Lionel Gauthier committed
125 126

static NwGtpv1uRcT
127 128 129
gtpv1u_stop_timer_wrapper(
  NwGtpv1uTimerMgrHandleT     tmrMgrHandle,
  NwGtpv1uTimerHandleT         hTmr);
Lionel Gauthier's avatar
Lionel Gauthier committed
130

131 132
int
gtpv1u_initial_req(
133 134 135 136
  gtpv1u_data_t *gtpv1u_data_pP,
  teid_t         teidP,
  tcp_udp_port_t portP,
  uint32_t       address);
Lionel Gauthier's avatar
Lionel Gauthier committed
137

138 139
int
gtpv1u_new_data_req(
140 141
  uint8_t  enb_module_idP,
  rnti_t   ue_rntiP,
142 143 144
  uint8_t  rab_idP,
  uint8_t *buffer_pP,
  uint32_t buf_lenP,
145 146
  uint32_t buf_offsetP
);
Lionel Gauthier's avatar
Lionel Gauthier committed
147

148
int
149
gtpv1u_create_s1u_tunnel(
150
  const instance_t instanceP,
151 152
  const gtpv1u_enb_create_tunnel_req_t *  const create_tunnel_req_pP,
        gtpv1u_enb_create_tunnel_resp_t * const create_tunnel_resp_pP);
Lionel Gauthier's avatar
Lionel Gauthier committed
153 154

static int
155 156 157
gtpv1u_delete_s1u_tunnel(
  const instance_t instanceP,
  const gtpv1u_enb_delete_tunnel_req_t * const req_pP);
Lionel Gauthier's avatar
Lionel Gauthier committed
158 159

static int
160
gtpv1u_eNB_init(void);
Lionel Gauthier's avatar
Lionel Gauthier committed
161 162

void *
163
gtpv1u_eNB_task(void *args);
Lionel Gauthier's avatar
Lionel Gauthier committed
164

165
//static gtpv1u_data_t gtpv1u_data_g;
166

167
#if defined(GTP_DUMP_SOCKET) && GTP_DUMP_SOCKET > 0
168 169 170 171
#include <linux/if.h>
static int           gtpv1u_dump_socket_g;

//-----------------------------------------------------------------------------
172 173
int gtpv1u_eNB_create_dump_socket(void)
{
174 175 176 177
  struct ifreq ifr;
  int          hdrincl=1;

  if ((gtpv1u_dump_socket_g = socket(AF_INET, SOCK_RAW, IPPROTO_RAW)) < 0 ) {
178 179
    LOG_E(GTPU, "Could not create dump socket %d:%s\n", errno, strerror(errno));
    return -1;
180 181 182
  }

  if (setsockopt(gtpv1u_dump_socket_g,
183 184 185 186 187
                 IPPROTO_IP,
                 IP_HDRINCL,
                 &hdrincl,
                 sizeof(hdrincl))==-1) {
    LOG_E(GTPU, "%s:%d set IP_HDRINCL %d:%s\n",
188 189 190 191 192
          __FILE__, __LINE__, errno, strerror(errno));
  }

  memset(&ifr, 0, sizeof(ifr));
  snprintf(ifr.ifr_name, sizeof(ifr.ifr_name), "lo");
193 194 195

  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",
196
          __FILE__, __LINE__, errno, strerror(errno));
197 198
    close(gtpv1u_dump_socket_g);
    return -1;
199 200 201 202
  }
}

//-----------------------------------------------------------------------------
203 204
static void gtpv1u_eNB_write_dump_socket(uint8_t *buffer_pP, uint32_t buffer_lengthP)
{
205 206 207 208 209 210
  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)  {
211
    LOG_E(GTPU, "%s:%s:%d  sendto %d:%s\n",
212 213 214 215 216 217 218
          __FILE__, __FUNCTION__, __LINE__, errno, strerror(errno));
  }
}

#endif

//-----------------------------------------------------------------------------
219 220
static int gtpv1u_eNB_send_init_udp(uint16_t port_number)
{
221 222 223
  // Create and alloc new message
  MessageDef *message_p;
  struct in_addr addr;
Cedric Roux's avatar
 
Cedric Roux committed
224

225 226 227 228 229
  message_p = itti_alloc_new_message(TASK_GTPV1_U, UDP_INIT);

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

231 232
  UDP_INIT(message_p).port = port_number;
  //LG UDP_INIT(message_p).address = "0.0.0.0"; //ANY address
Cedric Roux's avatar
 
Cedric Roux committed
233

234
  addr.s_addr = RC.gtpv1u_data_g->enb_ip_address_for_S1u_S12_S4_up;
235
  UDP_INIT(message_p).address = inet_ntoa(addr);
236
  LOG_I(GTPU, "Tx UDP_INIT IP addr %s (%x)\n", UDP_INIT(message_p).address,RC.gtpv1u_data_g->enb_ip_address_for_S1u_S12_S4_up);
Cedric Roux's avatar
 
Cedric Roux committed
237

238 239 240 241 242
  MSC_LOG_EVENT(
	  MSC_GTPU_ENB,
	  "0 UDP bind  %s:%u",
	  UDP_INIT(message_p).address,
	  UDP_INIT(message_p).port);
243
  return itti_send_msg_to_task(TASK_UDP, INSTANCE_DEFAULT, message_p);
244 245
}

246
//-----------------------------------------------------------------------------
247
NwGtpv1uRcT gtpv1u_eNB_log_request(NwGtpv1uLogMgrHandleT hLogMgr,
248
                                   uint32_t logLevel,
249
                                   NwCharT *file,
250
                                   uint32_t line,
251
                                   NwCharT *logStr)
Cedric Roux's avatar
 
Cedric Roux committed
252
{
253 254
  LOG_D(GTPU, "%s\n", logStr);
  return NW_GTPV1U_OK;
Cedric Roux's avatar
 
Cedric Roux committed
255 256
}

257
//-----------------------------------------------------------------------------
258
NwGtpv1uRcT gtpv1u_eNB_send_udp_msg(
259
  NwGtpv1uUdpHandleT udpHandle,
260 261 262 263 264
  uint8_t *buffer,
  uint32_t buffer_len,
  uint32_t buffer_offset,
  uint32_t peerIpAddr,
  uint16_t peerPort)
265
{
266 267 268
  // Create and alloc new message
  MessageDef     *message_p       = NULL;
  udp_data_req_t *udp_data_req_p  = NULL;
269

270
  message_p = itti_alloc_new_message(TASK_GTPV1_U, UDP_DATA_REQ);
271

272
  if (message_p) {
273
#if defined(LOG_GTPU) && LOG_GTPU > 0
274
    LOG_D(GTPU, "Sending UDP_DATA_REQ length %u offset %u", buffer_len, buffer_offset);
275
#endif
276 277 278 279 280 281 282 283 284 285
    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;
  }
286 287 288
}


289
//-----------------------------------------------------------------------------
Cedric Roux's avatar
 
Cedric Roux committed
290
/* Callback called when a gtpv1u message arrived on UDP interface */
291
NwGtpv1uRcT gtpv1u_eNB_process_stack_req(
292 293
  NwGtpv1uUlpHandleT hUlp,
  NwGtpv1uUlpApiT   *pUlpApi)
Cedric Roux's avatar
 
Cedric Roux committed
294
{
295
  boolean_t           result             = FALSE;
296 297 298 299
  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
300
  NwGtpv1uRcT         rc;
301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320

  switch(pUlpApi->apiType) {
    /* Here there are two type of messages handled:
     * - T-PDU
     * - END-MARKER
     */
  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");
    }

    itti_free(TASK_UDP, ((NwGtpv1uMsgT*)pUlpApi->apiInfo.recvMsgInfo.hMsg)->msgBuf);
321
#if defined(GTP_DUMP_SOCKET) && GTP_DUMP_SOCKET > 0
322
    gtpv1u_eNB_write_dump_socket(buffer,buffer_len);
323
#endif
324

Cedric Roux's avatar
Cedric Roux committed
325 326 327 328 329 330
    rc = nwGtpv1uMsgDelete(RC.gtpv1u_data_g->gtpv1u_stack,
                           pUlpApi->apiInfo.recvMsgInfo.hMsg);
    if (rc != NW_GTPV1U_OK) {
      LOG_E(GTPU, "nwGtpv1uMsgDelete failed: 0x%x\n", rc);
    }

331 332 333
    //-----------------------
    // GTPV1U->PDCP mapping
    //-----------------------
334
    hash_rc = hashtable_get(RC.gtpv1u_data_g->teid_mapping, teid, (void**)&gtpv1u_teid_data_p);
335 336

    if (hash_rc == HASH_TABLE_OK) {
337
#if defined(LOG_GTPU) && LOG_GTPU > 0
338 339 340 341 342 343
      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);
344
#endif
345

346
//#warning "LG eps bearer mapping to DRB id to do (offset -4)"
347
      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);
348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364
      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,
365 366 367 368 369
			     PDCP_TRANSMISSION_MODE_DATA
#ifdef Rel14
              ,NULL, NULL
#endif
              );
370
      
371 372 373 374 375 376 377 378 379 380 381
      
      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;
      }
      
382
    } else {
383
      LOG_W(GTPU, "Received T-PDU from gtpv1u stack teid %u unknown size %u", teid, buffer_len);
Cedric Roux's avatar
 
Cedric Roux committed
384
    }
385
  }
386 387
    break;
    
388 389 390 391
  default: {
    LOG_E(GTPU, "Received undefined UlpApi (%02x) from gtpv1u stack!\n",
          pUlpApi->apiType);
  }
392 393 394
  
  } // end of switch 
  
395
  return NW_GTPV1U_OK;
Cedric Roux's avatar
 
Cedric Roux committed
396 397 398
}


399
//-----------------------------------------------------------------------------
400
int data_recv_callback(uint16_t  portP,
Cedric Roux's avatar
 
Cedric Roux committed
401 402 403 404 405
                       uint32_t  address,
                       uint8_t  *buffer,
                       uint32_t  length,
                       void     *arg_p)
{
406
  gtpv1u_data_t        *gtpv1u_data_p;
Cedric Roux's avatar
 
Cedric Roux committed
407

408 409 410
  if (arg_p == NULL) {
    return -1;
  }
Cedric Roux's avatar
 
Cedric Roux committed
411

412
  gtpv1u_data_p = (gtpv1u_data_t *)arg_p;
Cedric Roux's avatar
 
Cedric Roux committed
413

414 415 416 417 418
  return nwGtpv1uProcessUdpReq(gtpv1u_data_p->gtpv1u_stack,
                               buffer,
                               length,
                               portP,
                               address);
Cedric Roux's avatar
 
Cedric Roux committed
419 420
}

421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 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
//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
515 516


517
//-----------------------------------------------------------------------------
518
static NwGtpv1uRcT gtpv1u_start_timer_wrapper(
519
  NwGtpv1uTimerMgrHandleT tmrMgrHandle,
520 521 522
  uint32_t                  timeoutSec,
  uint32_t                  timeoutUsec,
  uint32_t                  tmrType,
523 524
  void                   *timeoutArg,
  NwGtpv1uTimerHandleT   *hTmr)
525
{
Cedric Roux's avatar
 
Cedric Roux committed
526

527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546
  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
547

548
  return rc;
549
}
Cedric Roux's avatar
 
Cedric Roux committed
550 551


552 553 554
//-----------------------------------------------------------------------------
static NwGtpv1uRcT
gtpv1u_stop_timer_wrapper(
555 556
  NwGtpv1uTimerMgrHandleT tmrMgrHandle,
  NwGtpv1uTimerHandleT hTmr)
557
{
Cedric Roux's avatar
 
Cedric Roux committed
558

559
  NwGtpv1uRcT rc = NW_GTPV1U_OK;
Cedric Roux's avatar
 
Cedric Roux committed
560

561
  return rc;
Cedric Roux's avatar
 
Cedric Roux committed
562 563
}

564

565
//-----------------------------------------------------------------------------
566 567
int
gtpv1u_initial_req(
568 569 570 571
  gtpv1u_data_t *gtpv1u_data_pP,
  teid_t         teidP,
  tcp_udp_port_t portP,
  uint32_t       address)
Cedric Roux's avatar
 
Cedric Roux committed
572
{
573 574
  NwGtpv1uUlpApiT ulp_req;
  NwGtpv1uRcT     rc = NW_GTPV1U_FAILURE;
Cedric Roux's avatar
 
Cedric Roux committed
575

576
  memset(&ulp_req, 0, sizeof(NwGtpv1uUlpApiT));
Cedric Roux's avatar
 
Cedric Roux committed
577

578 579 580 581
  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;
Cedric Roux's avatar
 
Cedric Roux committed
582

583 584 585 586 587 588 589 590 591
  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
592 593
}

594
//-----------------------------------------------------------------------------
595 596
int
gtpv1u_new_data_req(
597 598
  uint8_t  enb_module_idP,
  rnti_t   ue_rntiP,
599 600 601 602 603
  uint8_t  rab_idP,
  uint8_t *buffer_pP,
  uint32_t buf_lenP,
  uint32_t buf_offsetP
)
Cedric Roux's avatar
 
Cedric Roux committed
604
{
605

606 607 608 609 610 611 612
  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;
Cedric Roux's avatar
 
Cedric Roux committed
613

614
  memset(&ue, 0, sizeof(struct gtpv1u_ue_data_s));
615
  ue.ue_id = ue_rntiP;
Cedric Roux's avatar
 
Cedric Roux committed
616

617
  AssertFatal(enb_module_idP >=0, "Bad parameter enb module id %u\n", enb_module_idP);
618 619
  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);
Cedric Roux's avatar
 
Cedric Roux committed
620

621
  gtpv1u_data_p = RC.gtpv1u_data_g;
622
  /* Check that UE context is present in ue map. */
623
  hash_rc = hashtable_get(gtpv1u_data_p->ue_mapping, (uint64_t)ue_rntiP, (void**)&ue_inst_p);
Cedric Roux's avatar
 
Cedric Roux committed
624

625
  if (hash_rc ==  HASH_TABLE_KEY_NOT_EXISTS ) {
626
    LOG_E(GTPU, "[UE %d] Trying to send data on non-existing UE context\n", ue_rntiP);
627 628
    return -1;
  }
Cedric Roux's avatar
 
Cedric Roux committed
629

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

632 633 634 635 636 637 638
  /* 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);
639
//#warning  LG: HACK WHILE WAITING FOR NAS, normally return -1
Cedric Roux's avatar
 
Cedric Roux committed
640

641 642 643
    if (bearer_p->state != BEARER_IN_CONFIG)
      return -1;
  }
Cedric Roux's avatar
 
Cedric Roux committed
644

645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683
  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
684 685
}

686
//-----------------------------------------------------------------------------
687
int
688
gtpv1u_create_s1u_tunnel(
689 690 691 692
  const instance_t                              instanceP,
  const gtpv1u_enb_create_tunnel_req_t * const  create_tunnel_req_pP,
        gtpv1u_enb_create_tunnel_resp_t * const create_tunnel_resp_pP
  )
Cedric Roux's avatar
 
Cedric Roux committed
693
{
694 695 696 697 698 699 700
  /* 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;
701
  //MessageDef              *message_p            = NULL;
702 703 704 705 706 707 708 709
  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;

Lionel Gauthier's avatar
Lionel Gauthier committed
710 711 712 713 714 715 716 717 718 719

  MSC_LOG_RX_MESSAGE(
		  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]);

720 721 722
  create_tunnel_resp_pP->rnti        = create_tunnel_req_pP->rnti;
  create_tunnel_resp_pP->status      = 0;
  create_tunnel_resp_pP->num_tunnels = 0;
723 724 725 726

  for (i = 0; i < create_tunnel_req_pP->num_tunnels; i++) {
    ip_offset               = 0;
    eps_bearer_id = create_tunnel_req_pP->eps_bearer_id[i];
727 728
    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);
729
    memset(&stack_req, 0, sizeof(NwGtpv1uUlpApiT));
730

731 732 733 734 735 736 737 738 739
    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;

740
      rc = nwGtpv1uProcessUlpReq(RC.gtpv1u_data_g->gtpv1u_stack, &stack_req);
741 742 743 744 745 746
      LOG_D(GTPU, ".\n");
    } while (rc != NW_GTPV1U_OK);

    //-----------------------
    // PDCP->GTPV1U mapping
    //-----------------------
747
    hash_rc = hashtable_get(RC.gtpv1u_data_g->ue_mapping, create_tunnel_req_pP->rnti, (void **)&gtpv1u_ue_data_p);
748 749 750 751 752

    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));
753
        hash_rc = hashtable_insert(RC.gtpv1u_data_g->ue_mapping, create_tunnel_req_pP->rnti, gtpv1u_ue_data_p);
754 755 756
        AssertFatal(hash_rc == HASH_TABLE_OK, "Error inserting ue_mapping in GTPV1U hashtable");
      }

757
      gtpv1u_ue_data_p->ue_id       = create_tunnel_req_pP->rnti;
758
      gtpv1u_ue_data_p->instance_id = 0; // TO DO
759
      memcpy(&create_tunnel_resp_pP->enb_addr.buffer,
760
             &RC.gtpv1u_data_g->enb_ip_address_for_S1u_S12_S4_up,
761
             sizeof (in_addr_t));
762
      create_tunnel_resp_pP->enb_addr.length = sizeof (in_addr_t);
763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784

      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)) {
        in_addr = *((in_addr_t*)create_tunnel_req_pP->sgw_addr[i].buffer);
        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);
      }

785 786 787 788
      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];
789
      gtpv1u_ue_data_p->num_bearers++;
790
      create_tunnel_resp_pP->enb_S1u_teid[i] = s1u_teid;
791

792
    } else {
793 794
      create_tunnel_resp_pP->enb_S1u_teid[i] = 0;
      create_tunnel_resp_pP->status         = 0xFF;
795
    }
796

797 798
    create_tunnel_resp_pP->eps_bearer_id[i] = eps_bearer_id;
    create_tunnel_resp_pP->num_tunnels      += 1;
799 800 801 802

    //-----------------------
    // GTPV1U->PDCP mapping
    //-----------------------
803
    hash_rc = hashtable_get(RC.gtpv1u_data_g->teid_mapping, s1u_teid, (void**)&gtpv1u_teid_data_p);
804 805 806 807

    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
808
      gtpv1u_teid_data_p->ue_id         = create_tunnel_req_pP->rnti;
809
      gtpv1u_teid_data_p->eps_bearer_id = eps_bearer_id;
810
      hash_rc = hashtable_insert(RC.gtpv1u_data_g->teid_mapping, s1u_teid, gtpv1u_teid_data_p);
811 812
      AssertFatal(hash_rc == HASH_TABLE_OK, "Error inserting teid mapping in GTPV1U hashtable");
    } else {
813 814
      create_tunnel_resp_pP->enb_S1u_teid[i] = 0;
      create_tunnel_resp_pP->status         = 0xFF;
815
    }
816
  }
Raymond Knopp's avatar
Raymond Knopp committed
817 818 819 820 821
  MSC_LOG_TX_MESSAGE(
		  MSC_GTPU_ENB,
		  MSC_RRC_ENB,
		  NULL,0,
		  "0 GTPV1U_ENB_CREATE_TUNNEL_RESP rnti %x teid %x",
822
		  create_tunnel_resp_pP->rnti,
Raymond Knopp's avatar
Raymond Knopp committed
823
		  s1u_teid);
824

825 826
  LOG_D(GTPU, "Tx GTPV1U_ENB_CREATE_TUNNEL_RESP ue rnti %x status %d\n",
        create_tunnel_req_pP->rnti,
827 828
        create_tunnel_resp_pP->status);
  return 0;
829
}
Cedric Roux's avatar
 
Cedric Roux committed
830

831 832 833 834 835 836
int gtpv1u_update_s1u_tunnel(
    const instance_t                              instanceP,
    const gtpv1u_enb_create_tunnel_req_t * const  create_tunnel_req_pP,
    const rnti_t                                  prior_rnti
    )
{
837

838 839 840 841
  /* 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;
842
  gtpv1u_ue_data_t        *gtpv1u_ue_data_new_p     = NULL;
843 844
  //MessageDef              *message_p            = NULL;
  hashtable_rc_t           hash_rc              = HASH_TABLE_KEY_NOT_EXISTS;
845 846
  int                      i,j;
  uint8_t                  bearers_num = 0,bearers_total = 0;
847 848 849 850 851

  //-----------------------
  // PDCP->GTPV1U mapping
  //-----------------------
  hash_rc = hashtable_get(RC.gtpv1u_data_g->ue_mapping, prior_rnti, (void **)&gtpv1u_ue_data_p);
852 853 854 855
  if(hash_rc != HASH_TABLE_OK){
    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
856

857 858 859
  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;
860

861
  hash_rc = hashtable_insert(RC.gtpv1u_data_g->ue_mapping, create_tunnel_req_pP->rnti, gtpv1u_ue_data_new_p);
862 863 864 865
  AssertFatal(hash_rc == HASH_TABLE_OK, "Error inserting ue_mapping in GTPV1U hashtable");
  LOG_I(GTPU, "inserting ue_mapping(rnti=%x) in GTPV1U hashtable\n",
      create_tunnel_req_pP->rnti);

866 867 868
  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",
		  prior_rnti);
869 870 871
  //-----------------------
  // GTPV1U->PDCP mapping
  //-----------------------
872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897
  bearers_total =gtpv1u_ue_data_new_p->num_bearers;
  for(j = 0;j<GTPV1U_MAX_BEARERS_ID;j++){

    if(gtpv1u_ue_data_new_p->bearers[j].state != BEARER_IN_CONFIG)
      continue;

    bearers_num++;
    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;
    }
    if(i < create_tunnel_req_pP->num_tunnels){
      s1u_teid = gtpv1u_ue_data_new_p->bearers[j].teid_eNB;
      hash_rc = hashtable_get(RC.gtpv1u_data_g->teid_mapping, s1u_teid, (void**)&gtpv1u_teid_data_p);
      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);
      }else{
        LOG_W(GTPU, "Error get teid mapping(s1u_teid=%u) from GTPV1U hashtable", s1u_teid);
      }
    }else{
      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
898

899 900 901 902 903 904 905 906 907 908
      if (hash_rc != HASH_TABLE_OK) {
        LOG_D(GTPU, "Removed user rnti %x , enb S1U teid %u not found\n", prior_rnti, s1u_teid);
      }
      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);;
    }
    if(bearers_num > bearers_total)
      break;
909 910
  }
  return 0;
Cedric Roux's avatar
 
Cedric Roux committed
911

912
}
Cedric Roux's avatar
 
Cedric Roux committed
913

914
//-----------------------------------------------------------------------------
915 916 917
static int gtpv1u_delete_s1u_tunnel(
  const instance_t                             instanceP,
  const gtpv1u_enb_delete_tunnel_req_t * const req_pP)
918
{
919 920 921 922 923 924 925
  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;
926

927
  message_p = itti_alloc_new_message(TASK_GTPV1_U, GTPV1U_ENB_DELETE_TUNNEL_RESP);
928

929
  GTPV1U_ENB_DELETE_TUNNEL_RESP(message_p).rnti     = req_pP->rnti;
930
  GTPV1U_ENB_DELETE_TUNNEL_RESP(message_p).status       = 0;
931 932


933
  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
934

935
  if (hash_rc == HASH_TABLE_OK) {
Lionel Gauthier's avatar
 
Lionel Gauthier committed
936

937 938
    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;
939 940
      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]);
Lionel Gauthier's avatar
 
Lionel Gauthier committed
941

942 943 944 945 946 947
      {
        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);
948
        stack_req.apiInfo.destroyTunnelEndPointInfo.hStackSessionHandle   = gtpv1u_ue_data_p->bearers[req_pP->eps_bearer_id[erab_index] - GTPV1U_BEARER_OFFSET].teid_eNB_stack_session;
949

950
        rc = nwGtpv1uProcessUlpReq(RC.gtpv1u_data_g->gtpv1u_stack, &stack_req);
951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968
        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) {
969
        hash_rc = hashtable_remove(RC.gtpv1u_data_g->ue_mapping, req_pP->rnti);
970
        LOG_D(GTPU, "Removed user rnti %x,no more bearers configured\n", req_pP->rnti);
971 972 973 974 975
      }

      //-----------------------
      // GTPV1U->PDCP mapping
      //-----------------------
976
      hash_rc = hashtable_remove(RC.gtpv1u_data_g->teid_mapping, teid_eNB);
977 978

      if (hash_rc != HASH_TABLE_OK) {
979
        LOG_D(GTPU, "Removed user rnti %x , enb S1U teid %u not found\n", req_pP->rnti, teid_eNB);
980 981 982
      }
    }
  }// else silently do nothing
983 984


985 986
  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,
987
        GTPV1U_ENB_DELETE_TUNNEL_RESP(message_p).enb_S1u_teid,
Lionel Gauthier's avatar
 
Lionel Gauthier committed
988
        GTPV1U_ENB_DELETE_TUNNEL_RESP(message_p).status);
Raymond Knopp's avatar
Raymond Knopp committed
989 990 991 992 993 994 995 996 997

  MSC_LOG_TX_MESSAGE(
		  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);

998
  return itti_send_msg_to_task(TASK_RRC_ENB, instanceP, message_p);
Cedric Roux's avatar
 
Cedric Roux committed
999 1000
}

1001

1002
//-----------------------------------------------------------------------------
1003
static int gtpv1u_eNB_init(void)
Cedric Roux's avatar
 
Cedric Roux committed
1004
{
1005 1006 1007 1008 1009 1010
  int                     ret;
  NwGtpv1uRcT             rc = NW_GTPV1U_FAILURE;
  NwGtpv1uUlpEntityT      ulp;
  NwGtpv1uUdpEntityT      udp;
  NwGtpv1uLogMgrEntityT   log;
  NwGtpv1uTimerMgrEntityT tmr;
1011

Cedric Roux's avatar
 
Cedric Roux committed
1012

1013 1014 1015
  //  enb_properties_p = enb_config_get()->properties[0];
  RC.gtpv1u_data_g = (gtpv1u_data_t*)malloc(sizeof(gtpv1u_data_t));
  memset(RC.gtpv1u_data_g, 0, sizeof(gtpv1u_data_t));
1016

1017
  RCconfig_gtpu();
1018 1019


1020
  LOG_I(GTPU, "Initializing GTPU stack %p\n",&RC.gtpv1u_data_g);
1021 1022
  //gtpv1u_data_g.gtpv1u_stack;
  /* Initialize UE hashtable */
1023 1024 1025 1026 1027 1028 1029
  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");
//  RC.gtpv1u_data_g.enb_ip_address_for_S1u_S12_S4_up         = enb_properties_p->enb_ipv4_address_for_S1U;
  RC.gtpv1u_data_g->ip_addr         = NULL;

1030
  //gtpv1u_data_g.udp_data;
1031 1032
  RC.gtpv1u_data_g->seq_num         = 0;
  RC.gtpv1u_data_g->restart_counter = 0;
1033 1034

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

1040
  if ((rc = nwGtpv1uSetLogLevel(RC.gtpv1u_data_g->gtpv1u_stack,
1041 1042 1043 1044
                                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
1045

1046

1047 1048 1049 1050
  /* Set the ULP API callback. Called once message have been processed by the
   * nw-gtpv1u stack.
   */
  ulp.ulpReqCallback = gtpv1u_eNB_process_stack_req;
1051

1052
  if ((rc = nwGtpv1uSetUlpEntity(RC.gtpv1u_data_g->gtpv1u_stack, &ulp)) != NW_GTPV1U_OK) {
1053 1054 1055
    LOG_E(GTPU, "nwGtpv1uSetUlpEntity: %x", rc);
    return -1;
  }
Cedric Roux's avatar
 
Cedric Roux committed
1056

1057 1058 1059 1060
  /* 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;
Cedric Roux's avatar
 
Cedric Roux committed
1061

1062
  if ((rc = nwGtpv1uSetUdpEntity(RC.gtpv1u_data_g->gtpv1u_stack, &udp)) != NW_GTPV1U_OK) {
1063 1064 1065
    LOG_E(GTPU, "nwGtpv1uSetUdpEntity: %x", rc);
    return -1;
  }
Cedric Roux's avatar
 
Cedric Roux committed
1066

1067
  log.logReqCallback = gtpv1u_eNB_log_request;
Cedric Roux's avatar
 
Cedric Roux committed
1068

1069
  if ((rc = nwGtpv1uSetLogMgrEntity(RC.gtpv1u_data_g->gtpv1u_stack, &log)) != NW_GTPV1U_OK) {
1070 1071 1072
    LOG_E(GTPU, "nwGtpv1uSetLogMgrEntity: %x", rc);
    return -1;
  }
Cedric Roux's avatar
 
Cedric Roux committed
1073

1074 1075 1076 1077 1078 1079
  /* 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
1080

1081
  if ((rc = nwGtpv1uSetTimerMgrEntity(RC.gtpv1u_data_g->gtpv1u_stack, &tmr)) != NW_GTPV1U_OK) {
1082 1083 1084
    LOG_E(GTPU, "nwGtpv1uSetTimerMgrEntity: %x", rc);
    return -1;
  }
Cedric Roux's avatar
 
Cedric Roux committed
1085

1086
#if defined(GTP_DUMP_SOCKET) && GTP_DUMP_SOCKET > 0
1087 1088 1089 1090 1091

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

1092
#endif
1093
  ret = gtpv1u_eNB_send_init_udp(RC.gtpv1u_data_g->enb_port_for_S1u_S12_S4_up);
1094 1095 1096 1097

  if (ret < 0) {
    return ret;
  }
Cedric Roux's avatar
 
Cedric Roux committed
1098

1099 1100
  LOG_D(GTPU, "Initializing GTPV1U interface for eNB: DONE\n");
  return 0;
1101
}
Cedric Roux's avatar
 
Cedric Roux committed
1102 1103


1104
//-----------------------------------------------------------------------------
1105 1106
void *gtpv1u_eNB_task(void *args)
{
1107 1108
  int                       rc = 0;
  instance_t                instance;
1109
  //const char               *msg_name_p;
1110

1111 1112 1113
  rc = gtpv1u_eNB_init();
  AssertFatal(rc == 0, "gtpv1u_eNB_init Failed");
  itti_mark_task_ready(TASK_GTPV1_U);
1114
  MSC_START_USE();
1115 1116 1117 1118 1119 1120 1121 1122

  while(1) {
    /* Trying to fetch a message from the message queue.
     * If the queue is empty, this function will block till a
     * message is sent to the task.
     */
    MessageDef *received_message_p = NULL;
    itti_receive_msg(TASK_GTPV1_U, &received_message_p);
1123
    VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_GTPV1U_ENB_TASK, VCD_FUNCTION_IN);
1124 1125
    DevAssert(received_message_p != NULL);

1126
    instance = ITTI_MSG_INSTANCE(received_message_p);
1127
    //msg_name_p = ITTI_MSG_NAME(received_message_p);
1128

1129
    switch (ITTI_MSG_ID(received_message_p)) {
1130

1131
    case GTPV1U_ENB_DELETE_TUNNEL_REQ: {
1132
      gtpv1u_delete_s1u_tunnel(instance, &received_message_p->ittiMsg.Gtpv1uDeleteTunnelReq);
1133 1134 1135 1136 1137 1138 1139
    }
    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;
1140
      nwGtpv1uProcessUdpReq(RC.gtpv1u_data_g->gtpv1u_stack,
1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151
                            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;
1152
      NwGtpv1uUlpApiT               stack_req;
1153 1154 1155 1156 1157 1158
      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;

1159
      VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_GTPV1U_PROCESS_TUNNEL_DATA_REQ, VCD_FUNCTION_IN);
1160 1161
      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);
1162

1163
#if defined(GTP_DUMP_SOCKET) && GTP_DUMP_SOCKET > 0
1164
      gtpv1u_eNB_write_dump_socket(&data_req_p->buffer[data_req_p->offset],data_req_p->length);
1165
#endif
1166 1167
      memset(&stack_req, 0, sizeof(NwGtpv1uUlpApiT));

1168
      hash_rc = hashtable_get(RC.gtpv1u_data_g->ue_mapping, (uint64_t)data_req_p->rnti, (void**)&gtpv1u_ue_data_p);
1169 1170

      if (hash_rc == HASH_TABLE_KEY_NOT_EXISTS) {
1171
        LOG_E(GTPU, "nwGtpv1uProcessUlpReq failed: while getting ue rnti %x in hashtable ue_mapping\n", data_req_p->rnti);
1172 1173 1174 1175 1176 1177 1178 1179 1180
      } else {
        if ((data_req_p->rab_id >= GTPV1U_BEARER_OFFSET) && (data_req_p->rab_id <= max_val_DRB_Identity)) {
          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(
1181
                 RC.gtpv1u_data_g->gtpv1u_stack,
1182 1183
                 sgw_s1u_teid,
                 NW_FALSE,
1184
                 RC.gtpv1u_data_g->seq_num++,
1185 1186 1187 1188 1189 1190 1191
                 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);
1192
            MSC_LOG_EVENT(MSC_GTPU_ENB,"0 Failed send G-PDU ltid %u rtid %u size %u",
Lionel Gauthier's avatar
Lionel Gauthier committed
1193
            		enb_s1u_teid,sgw_s1u_teid,data_req_p->length);
1194
            (void)enb_s1u_teid; /* avoid gcc warning "set but not used" */
1195
          } else {
1196
            rc = nwGtpv1uProcessUlpReq(RC.gtpv1u_data_g->gtpv1u_stack, &stack_req);
1197 1198 1199

            if (rc != NW_GTPV1U_OK) {
              LOG_E(GTPU, "nwGtpv1uProcessUlpReq failed: 0x%x\n", rc);
1200
              MSC_LOG_EVENT(MSC_GTPU_ENB,"0 Failed send G-PDU ltid %u rtid %u size %u",
Lionel Gauthier's avatar
Lionel Gauthier committed
1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213
              		enb_s1u_teid,sgw_s1u_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,
            			  sgw_s1u_teid,
            			  data_req_p->length);

1214
            }
1215

1216
            rc = nwGtpv1uMsgDelete(RC.gtpv1u_data_g->gtpv1u_stack,
1217 1218 1219 1220
                                   stack_req.apiInfo.sendtoInfo.hMsg);

            if (rc != NW_GTPV1U_OK) {
              LOG_E(GTPU, "nwGtpv1uMsgDelete failed: 0x%x\n", rc);
1221
            }
1222
          }
1223
        }
1224 1225
      }

1226
      VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_GTPV1U_PROCESS_TUNNEL_DATA_REQ, VCD_FUNCTION_OUT);
1227 1228 1229 1230 1231 1232
      /* Buffer still needed, do not free it */
      //itti_free(ITTI_MSG_ORIGIN_ID(received_message_p), data_req_p->buffer);
    }
    break;

    case TERMINATE_MESSAGE: {
1233 1234
      if (RC.gtpv1u_data_g->ue_mapping != NULL) {
        hashtable_destroy (RC.gtpv1u_data_g->ue_mapping);
1235 1236
      }

1237 1238
      if (RC.gtpv1u_data_g->teid_mapping != NULL) {
        hashtable_destroy (RC.gtpv1u_data_g->teid_mapping);
1239 1240
      }

1241
      LOG_W(GTPU, " *** Exiting GTPU thread\n");
1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253
      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));
1254
    }
1255 1256 1257 1258 1259 1260
    break;
    }

    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;
1261
    VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_GTPV1U_ENB_TASK, VCD_FUNCTION_OUT);
1262 1263 1264
  }

  return NULL;
Cedric Roux's avatar
 
Cedric Roux committed
1265
}
1266