gtpv1u_eNB.c 41.8 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;

//-----------------------------------------------------------------------------
64 65
int gtpv1u_eNB_create_dump_socket(void)
{
66 67 68 69
  struct ifreq ifr;
  int          hdrincl=1;

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

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

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

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

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

#endif

//-----------------------------------------------------------------------------
laurent's avatar
laurent committed
111
static int gtpv1u_eNB_send_init_udp(const Gtpv1uS1Req * req)
112
{
113 114
  // Create and alloc new message
  MessageDef *message_p;
laurent's avatar
laurent committed
115
  struct in_addr addr={0};
Cedric Roux's avatar
 
Cedric Roux committed
116

117 118 119 120 121
  message_p = itti_alloc_new_message(TASK_GTPV1_U, UDP_INIT);

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

laurent's avatar
laurent committed
123 124
  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;
125
  UDP_INIT(message_p).address = inet_ntoa(addr);
laurent's avatar
laurent committed
126
  LOG_I(GTPU, "Tx UDP_INIT IP addr %s (%x)\n", UDP_INIT(message_p).address,UDP_INIT(message_p).port);
Cedric Roux's avatar
 
Cedric Roux committed
127

128 129 130 131 132
  MSC_LOG_EVENT(
	  MSC_GTPU_ENB,
	  "0 UDP bind  %s:%u",
	  UDP_INIT(message_p).address,
	  UDP_INIT(message_p).port);
133
  return itti_send_msg_to_task(TASK_UDP, INSTANCE_DEFAULT, message_p);
134 135
}

laurent's avatar
laurent committed
136 137 138 139 140 141 142 143 144 145
static int gtpv1u_s1_req(
  const instance_t                             instanceP,
  const Gtpv1uS1Req * const req) {
  memcpy(&RC.gtpv1u_data_g->enb_ip_address_for_S1u_S12_S4_up,
	 &req->enb_ip_address_for_S1u_S12_S4_up, 
	 sizeof (req->enb_ip_address_for_S1u_S12_S4_up));
  gtpv1u_eNB_send_init_udp(req);
  return 0;
}

146
//-----------------------------------------------------------------------------
147
NwGtpv1uRcT gtpv1u_eNB_log_request(NwGtpv1uLogMgrHandleT hLogMgr,
148
                                   uint32_t logLevel,
149
                                   NwCharT *file,
150
                                   uint32_t line,
151
                                   NwCharT *logStr)
Cedric Roux's avatar
 
Cedric Roux committed
152
{
153 154
  LOG_D(GTPU, "%s\n", logStr);
  return NW_GTPV1U_OK;
Cedric Roux's avatar
 
Cedric Roux committed
155 156
}

157
//-----------------------------------------------------------------------------
158
NwGtpv1uRcT gtpv1u_eNB_send_udp_msg(
159
  NwGtpv1uUdpHandleT udpHandle,
160 161 162 163 164
  uint8_t *buffer,
  uint32_t buffer_len,
  uint32_t buffer_offset,
  uint32_t peerIpAddr,
  uint16_t peerPort)
165
{
166 167 168
  // Create and alloc new message
  MessageDef     *message_p       = NULL;
  udp_data_req_t *udp_data_req_p  = NULL;
169

170
  message_p = itti_alloc_new_message(TASK_GTPV1_U, UDP_DATA_REQ);
171

172
  if (message_p) {
173
#if defined(LOG_GTPU) && LOG_GTPU > 0
174
    LOG_D(GTPU, "Sending UDP_DATA_REQ length %u offset %u", buffer_len, buffer_offset);
175
#endif
176 177 178 179 180 181 182 183 184 185
    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;
  }
186 187 188
}


189
//-----------------------------------------------------------------------------
Cedric Roux's avatar
 
Cedric Roux committed
190
/* Callback called when a gtpv1u message arrived on UDP interface */
191
NwGtpv1uRcT gtpv1u_eNB_process_stack_req(
192 193
  NwGtpv1uUlpHandleT hUlp,
  NwGtpv1uUlpApiT   *pUlpApi)
Cedric Roux's avatar
 
Cedric Roux committed
194
{
195
  boolean_t           result             = FALSE;
196 197 198 199
  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
200
  NwGtpv1uRcT         rc;
201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220

  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);
221
#if defined(GTP_DUMP_SOCKET) && GTP_DUMP_SOCKET > 0
222
    gtpv1u_eNB_write_dump_socket(buffer,buffer_len);
223
#endif
224

Cedric Roux's avatar
Cedric Roux committed
225 226 227 228 229 230
    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);
    }

231 232 233
    //-----------------------
    // GTPV1U->PDCP mapping
    //-----------------------
234
    hash_rc = hashtable_get(RC.gtpv1u_data_g->teid_mapping, teid, (void**)&gtpv1u_teid_data_p);
235 236

    if (hash_rc == HASH_TABLE_OK) {
237
#if defined(LOG_GTPU) && LOG_GTPU > 0
238 239 240 241 242 243
      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);
244
#endif
245

246
//#warning "LG eps bearer mapping to DRB id to do (offset -4)"
247
      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);
248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264
      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,
265
			     PDCP_TRANSMISSION_MODE_DATA
266
#if (LTE_RRC_VERSION >= MAKE_VERSION(14, 0, 0))
267 268 269
              ,NULL, NULL
#endif
              );
270
      
271 272 273 274 275 276 277 278 279 280 281
      
      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;
      }
      
282
    } else {
283
      LOG_W(GTPU, "Received T-PDU from gtpv1u stack teid %u unknown size %u", teid, buffer_len);
Cedric Roux's avatar
 
Cedric Roux committed
284
    }
285
  }
286 287
    break;
    
288 289 290 291
  default: {
    LOG_E(GTPU, "Received undefined UlpApi (%02x) from gtpv1u stack!\n",
          pUlpApi->apiType);
  }
292 293 294
  
  } // end of switch 
  
295
  return NW_GTPV1U_OK;
Cedric Roux's avatar
 
Cedric Roux committed
296 297 298
}


299
//-----------------------------------------------------------------------------
300
int data_recv_callback(uint16_t  portP,
Cedric Roux's avatar
 
Cedric Roux committed
301 302 303 304 305
                       uint32_t  address,
                       uint8_t  *buffer,
                       uint32_t  length,
                       void     *arg_p)
{
306
  gtpv1u_data_t        *gtpv1u_data_p;
Cedric Roux's avatar
 
Cedric Roux committed
307

308 309 310
  if (arg_p == NULL) {
    return -1;
  }
Cedric Roux's avatar
 
Cedric Roux committed
311

312
  gtpv1u_data_p = (gtpv1u_data_t *)arg_p;
Cedric Roux's avatar
 
Cedric Roux committed
313

314 315 316 317 318
  return nwGtpv1uProcessUdpReq(gtpv1u_data_p->gtpv1u_stack,
                               buffer,
                               length,
                               portP,
                               address);
Cedric Roux's avatar
 
Cedric Roux committed
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 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414
//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
415 416


417
//-----------------------------------------------------------------------------
418
static NwGtpv1uRcT gtpv1u_start_timer_wrapper(
419
  NwGtpv1uTimerMgrHandleT tmrMgrHandle,
420 421 422
  uint32_t                  timeoutSec,
  uint32_t                  timeoutUsec,
  uint32_t                  tmrType,
423 424
  void                   *timeoutArg,
  NwGtpv1uTimerHandleT   *hTmr)
425
{
Cedric Roux's avatar
 
Cedric Roux committed
426

427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446
  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
447

448
  return rc;
449
}
Cedric Roux's avatar
 
Cedric Roux committed
450 451


452 453 454
//-----------------------------------------------------------------------------
static NwGtpv1uRcT
gtpv1u_stop_timer_wrapper(
455 456
  NwGtpv1uTimerMgrHandleT tmrMgrHandle,
  NwGtpv1uTimerHandleT hTmr)
457
{
Cedric Roux's avatar
 
Cedric Roux committed
458

459
  NwGtpv1uRcT rc = NW_GTPV1U_OK;
Cedric Roux's avatar
 
Cedric Roux committed
460

461
  return rc;
Cedric Roux's avatar
 
Cedric Roux committed
462 463
}

464

465
//-----------------------------------------------------------------------------
466 467
int
gtpv1u_initial_req(
468 469 470 471
  gtpv1u_data_t *gtpv1u_data_pP,
  teid_t         teidP,
  tcp_udp_port_t portP,
  uint32_t       address)
Cedric Roux's avatar
 
Cedric Roux committed
472
{
473 474
  NwGtpv1uUlpApiT ulp_req;
  NwGtpv1uRcT     rc = NW_GTPV1U_FAILURE;
Cedric Roux's avatar
 
Cedric Roux committed
475

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

478 479 480 481
  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
482

483 484 485 486 487 488 489 490 491
  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
492 493
}

494
//-----------------------------------------------------------------------------
495 496
int
gtpv1u_new_data_req(
497 498
  uint8_t  enb_module_idP,
  rnti_t   ue_rntiP,
499 500 501 502 503
  uint8_t  rab_idP,
  uint8_t *buffer_pP,
  uint32_t buf_lenP,
  uint32_t buf_offsetP
)
Cedric Roux's avatar
 
Cedric Roux committed
504
{
505

506 507 508 509 510 511 512
  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
513

514
  memset(&ue, 0, sizeof(struct gtpv1u_ue_data_s));
515
  ue.ue_id = ue_rntiP;
Cedric Roux's avatar
 
Cedric Roux committed
516

517
  AssertFatal(enb_module_idP >=0, "Bad parameter enb module id %u\n", enb_module_idP);
518 519
  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
520

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

525
  if (hash_rc ==  HASH_TABLE_KEY_NOT_EXISTS ) {
526
    LOG_E(GTPU, "[UE %d] Trying to send data on non-existing UE context\n", ue_rntiP);
527 528
    return -1;
  }
Cedric Roux's avatar
 
Cedric Roux committed
529

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

532 533 534 535 536 537 538
  /* 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);
539
//#warning  LG: HACK WHILE WAITING FOR NAS, normally return -1
Cedric Roux's avatar
 
Cedric Roux committed
540

541 542 543
    if (bearer_p->state != BEARER_IN_CONFIG)
      return -1;
  }
Cedric Roux's avatar
 
Cedric Roux committed
544

545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583
  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
584 585
}

586
//-----------------------------------------------------------------------------
587
int
588
gtpv1u_create_s1u_tunnel(
589 590 591 592
  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
593
{
594 595 596 597 598 599 600
  /* 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;
601
  //MessageDef              *message_p            = NULL;
602 603 604 605 606 607 608 609
  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
610 611 612 613 614 615 616 617 618 619

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

620 621 622
  create_tunnel_resp_pP->rnti        = create_tunnel_req_pP->rnti;
  create_tunnel_resp_pP->status      = 0;
  create_tunnel_resp_pP->num_tunnels = 0;
623 624 625 626

  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];
627 628
    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);
629
    memset(&stack_req, 0, sizeof(NwGtpv1uUlpApiT));
630

631 632 633 634 635 636 637 638 639
    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;

640
      rc = nwGtpv1uProcessUlpReq(RC.gtpv1u_data_g->gtpv1u_stack, &stack_req);
641 642 643 644 645 646
      LOG_D(GTPU, ".\n");
    } while (rc != NW_GTPV1U_OK);

    //-----------------------
    // PDCP->GTPV1U mapping
    //-----------------------
647
    hash_rc = hashtable_get(RC.gtpv1u_data_g->ue_mapping, create_tunnel_req_pP->rnti, (void **)&gtpv1u_ue_data_p);
648 649 650 651 652

    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));
653
        hash_rc = hashtable_insert(RC.gtpv1u_data_g->ue_mapping, create_tunnel_req_pP->rnti, gtpv1u_ue_data_p);
654 655 656
        AssertFatal(hash_rc == HASH_TABLE_OK, "Error inserting ue_mapping in GTPV1U hashtable");
      }

657
      gtpv1u_ue_data_p->ue_id       = create_tunnel_req_pP->rnti;
658
      gtpv1u_ue_data_p->instance_id = 0; // TO DO
659
      memcpy(&create_tunnel_resp_pP->enb_addr.buffer,
660
             &RC.gtpv1u_data_g->enb_ip_address_for_S1u_S12_S4_up,
661
             sizeof (in_addr_t));
662
      create_tunnel_resp_pP->enb_addr.length = sizeof (in_addr_t);
663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684

      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);
      }

685 686 687 688
      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];
689
      gtpv1u_ue_data_p->num_bearers++;
690
      create_tunnel_resp_pP->enb_S1u_teid[i] = s1u_teid;
691

692
    } else {
693 694
      create_tunnel_resp_pP->enb_S1u_teid[i] = 0;
      create_tunnel_resp_pP->status         = 0xFF;
695
    }
696

697 698
    create_tunnel_resp_pP->eps_bearer_id[i] = eps_bearer_id;
    create_tunnel_resp_pP->num_tunnels      += 1;
699 700 701 702

    //-----------------------
    // GTPV1U->PDCP mapping
    //-----------------------
703
    hash_rc = hashtable_get(RC.gtpv1u_data_g->teid_mapping, s1u_teid, (void**)&gtpv1u_teid_data_p);
704 705 706 707

    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
708
      gtpv1u_teid_data_p->ue_id         = create_tunnel_req_pP->rnti;
709
      gtpv1u_teid_data_p->eps_bearer_id = eps_bearer_id;
710
      hash_rc = hashtable_insert(RC.gtpv1u_data_g->teid_mapping, s1u_teid, gtpv1u_teid_data_p);
711 712
      AssertFatal(hash_rc == HASH_TABLE_OK, "Error inserting teid mapping in GTPV1U hashtable");
    } else {
713 714
      create_tunnel_resp_pP->enb_S1u_teid[i] = 0;
      create_tunnel_resp_pP->status         = 0xFF;
715
    }
716
  }
Raymond Knopp's avatar
Raymond Knopp committed
717 718 719 720 721
  MSC_LOG_TX_MESSAGE(
		  MSC_GTPU_ENB,
		  MSC_RRC_ENB,
		  NULL,0,
		  "0 GTPV1U_ENB_CREATE_TUNNEL_RESP rnti %x teid %x",
722
		  create_tunnel_resp_pP->rnti,
Raymond Knopp's avatar
Raymond Knopp committed
723
		  s1u_teid);
724

725 726
  LOG_D(GTPU, "Tx GTPV1U_ENB_CREATE_TUNNEL_RESP ue rnti %x status %d\n",
        create_tunnel_req_pP->rnti,
727 728
        create_tunnel_resp_pP->status);
  return 0;
729
}
Cedric Roux's avatar
 
Cedric Roux committed
730

731 732 733 734 735 736
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
    )
{
737

738 739 740 741
  /* 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;
742
  gtpv1u_ue_data_t        *gtpv1u_ue_data_new_p     = NULL;
743 744
  //MessageDef              *message_p            = NULL;
  hashtable_rc_t           hash_rc              = HASH_TABLE_KEY_NOT_EXISTS;
745 746
  int                      i,j;
  uint8_t                  bearers_num = 0,bearers_total = 0;
747 748 749 750 751

  //-----------------------
  // PDCP->GTPV1U mapping
  //-----------------------
  hash_rc = hashtable_get(RC.gtpv1u_data_g->ue_mapping, prior_rnti, (void **)&gtpv1u_ue_data_p);
752 753 754 755
  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
756

757 758 759
  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;
760

761
  hash_rc = hashtable_insert(RC.gtpv1u_data_g->ue_mapping, create_tunnel_req_pP->rnti, gtpv1u_ue_data_new_p);
762 763 764 765
  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);

766 767 768
  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);
769 770 771
  //-----------------------
  // GTPV1U->PDCP mapping
  //-----------------------
772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797
  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
798

799 800 801 802 803 804 805 806 807 808
      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;
809 810
  }
  return 0;
Cedric Roux's avatar
 
Cedric Roux committed
811

812
}
Cedric Roux's avatar
 
Cedric Roux committed
813

814
//-----------------------------------------------------------------------------
815
int gtpv1u_delete_s1u_tunnel(
816 817
  const instance_t                             instanceP,
  const gtpv1u_enb_delete_tunnel_req_t * const req_pP)
818
{
819 820 821 822 823 824 825
  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;
826

827
  message_p = itti_alloc_new_message(TASK_GTPV1_U, GTPV1U_ENB_DELETE_TUNNEL_RESP);
828

829
  GTPV1U_ENB_DELETE_TUNNEL_RESP(message_p).rnti     = req_pP->rnti;
830
  GTPV1U_ENB_DELETE_TUNNEL_RESP(message_p).status       = 0;
831 832


833
  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
834

835
  if (hash_rc == HASH_TABLE_OK) {
Lionel Gauthier's avatar
 
Lionel Gauthier committed
836

837 838
    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;
839 840
      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
841

842 843 844 845 846 847
      {
        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);
848
        stack_req.apiInfo.destroyTunnelEndPointInfo.hStackSessionHandle   = gtpv1u_ue_data_p->bearers[req_pP->eps_bearer_id[erab_index] - GTPV1U_BEARER_OFFSET].teid_eNB_stack_session;
849

850
        rc = nwGtpv1uProcessUlpReq(RC.gtpv1u_data_g->gtpv1u_stack, &stack_req);
851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868
        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) {
869
        hash_rc = hashtable_remove(RC.gtpv1u_data_g->ue_mapping, req_pP->rnti);
870
        LOG_D(GTPU, "Removed user rnti %x,no more bearers configured\n", req_pP->rnti);
871 872 873 874 875
      }

      //-----------------------
      // GTPV1U->PDCP mapping
      //-----------------------
876
      hash_rc = hashtable_remove(RC.gtpv1u_data_g->teid_mapping, teid_eNB);
877 878

      if (hash_rc != HASH_TABLE_OK) {
879
        LOG_D(GTPU, "Removed user rnti %x , enb S1U teid %u not found\n", req_pP->rnti, teid_eNB);
880 881 882
      }
    }
  }// else silently do nothing
883 884


885 886
  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,
887
        GTPV1U_ENB_DELETE_TUNNEL_RESP(message_p).enb_S1u_teid,
Lionel Gauthier's avatar
 
Lionel Gauthier committed
888
        GTPV1U_ENB_DELETE_TUNNEL_RESP(message_p).status);
Raymond Knopp's avatar
Raymond Knopp committed
889 890 891 892 893 894 895 896 897

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

898
  return itti_send_msg_to_task(TASK_RRC_ENB, instanceP, message_p);
Cedric Roux's avatar
 
Cedric Roux committed
899 900
}

901

902
//-----------------------------------------------------------------------------
laurent's avatar
laurent committed
903
int gtpv1u_eNB_init(void)
Cedric Roux's avatar
 
Cedric Roux committed
904
{
905 906 907 908 909
  NwGtpv1uRcT             rc = NW_GTPV1U_FAILURE;
  NwGtpv1uUlpEntityT      ulp;
  NwGtpv1uUdpEntityT      udp;
  NwGtpv1uLogMgrEntityT   log;
  NwGtpv1uTimerMgrEntityT tmr;
910

911
  //  enb_properties_p = enb_config_get()->properties[0];
laurent's avatar
laurent committed
912 913
  RC.gtpv1u_data_g = (gtpv1u_data_t*)calloc(sizeof(gtpv1u_data_t),1);
  
914
  LOG_I(GTPU, "Initializing GTPU stack %p\n",&RC.gtpv1u_data_g);
915 916
  //gtpv1u_data_g.gtpv1u_stack;
  /* Initialize UE hashtable */
917 918 919 920 921 922
  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;

923
  //gtpv1u_data_g.udp_data;
924 925
  RC.gtpv1u_data_g->seq_num         = 0;
  RC.gtpv1u_data_g->restart_counter = 0;
926 927

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

933
  if ((rc = nwGtpv1uSetLogLevel(RC.gtpv1u_data_g->gtpv1u_stack,
934 935 936 937
                                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
938

939

940 941 942 943
  /* Set the ULP API callback. Called once message have been processed by the
   * nw-gtpv1u stack.
   */
  ulp.ulpReqCallback = gtpv1u_eNB_process_stack_req;
944

945
  if ((rc = nwGtpv1uSetUlpEntity(RC.gtpv1u_data_g->gtpv1u_stack, &ulp)) != NW_GTPV1U_OK) {
946 947 948
    LOG_E(GTPU, "nwGtpv1uSetUlpEntity: %x", rc);
    return -1;
  }
Cedric Roux's avatar
 
Cedric Roux committed
949

950 951 952 953
  /* 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
954

955
  if ((rc = nwGtpv1uSetUdpEntity(RC.gtpv1u_data_g->gtpv1u_stack, &udp)) != NW_GTPV1U_OK) {
956 957 958
    LOG_E(GTPU, "nwGtpv1uSetUdpEntity: %x", rc);
    return -1;
  }
Cedric Roux's avatar
 
Cedric Roux committed
959

960
  log.logReqCallback = gtpv1u_eNB_log_request;
Cedric Roux's avatar
 
Cedric Roux committed
961

962
  if ((rc = nwGtpv1uSetLogMgrEntity(RC.gtpv1u_data_g->gtpv1u_stack, &log)) != NW_GTPV1U_OK) {
963 964 965
    LOG_E(GTPU, "nwGtpv1uSetLogMgrEntity: %x", rc);
    return -1;
  }
Cedric Roux's avatar
 
Cedric Roux committed
966

967 968 969 970 971 972
  /* 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
973

974
  if ((rc = nwGtpv1uSetTimerMgrEntity(RC.gtpv1u_data_g->gtpv1u_stack, &tmr)) != NW_GTPV1U_OK) {
975 976 977
    LOG_E(GTPU, "nwGtpv1uSetTimerMgrEntity: %x", rc);
    return -1;
  }
Cedric Roux's avatar
 
Cedric Roux committed
978

979
#if defined(GTP_DUMP_SOCKET) && GTP_DUMP_SOCKET > 0
980 981 982 983 984

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

985
#endif
Cedric Roux's avatar
 
Cedric Roux committed
986

987 988
  LOG_D(GTPU, "Initializing GTPV1U interface for eNB: DONE\n");
  return 0;
989
}
Cedric Roux's avatar
 
Cedric Roux committed
990

991
//-----------------------------------------------------------------------------
laurent's avatar
laurent committed
992
void *gtpv1u_eNB_process_itti_msg(void *notUsed) {
993 994 995 996
    /* 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.
     */
laurent's avatar
laurent committed
997
    instance_t  instance;
998
    MessageDef *received_message_p = NULL;
laurent's avatar
laurent committed
999 1000
    int         rc = 0;
    
1001
    itti_receive_msg(TASK_GTPV1_U, &received_message_p);
1002
    VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_GTPV1U_ENB_TASK, VCD_FUNCTION_IN);
1003 1004
    DevAssert(received_message_p != NULL);

1005
    instance = ITTI_MSG_INSTANCE(received_message_p);
1006
    //msg_name_p = ITTI_MSG_NAME(received_message_p);
1007

1008
    switch (ITTI_MSG_ID(received_message_p)) {
1009

laurent's avatar
laurent committed
1010 1011 1012
    case GTPV1U_ENB_S1_REQ:
      gtpv1u_s1_req(instance, &received_message_p->ittiMsg.gtpv1uS1Req);

1013
    case GTPV1U_ENB_DELETE_TUNNEL_REQ: {
1014
      gtpv1u_delete_s1u_tunnel(instance, &received_message_p->ittiMsg.Gtpv1uDeleteTunnelReq);
1015 1016 1017 1018 1019 1020 1021
    }
    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;
1022
      nwGtpv1uProcessUdpReq(RC.gtpv1u_data_g->gtpv1u_stack,
1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033
                            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;
1034
      NwGtpv1uUlpApiT               stack_req;
1035 1036 1037 1038 1039 1040
      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;

1041
      VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_GTPV1U_PROCESS_TUNNEL_DATA_REQ, VCD_FUNCTION_IN);
1042 1043
      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);
1044

1045
#if defined(GTP_DUMP_SOCKET) && GTP_DUMP_SOCKET > 0
1046
      gtpv1u_eNB_write_dump_socket(&data_req_p->buffer[data_req_p->offset],data_req_p->length);
1047
#endif
1048 1049
      memset(&stack_req, 0, sizeof(NwGtpv1uUlpApiT));

1050
      hash_rc = hashtable_get(RC.gtpv1u_data_g->ue_mapping, (uint64_t)data_req_p->rnti, (void**)&gtpv1u_ue_data_p);
1051 1052

      if (hash_rc == HASH_TABLE_KEY_NOT_EXISTS) {
1053
        LOG_E(GTPU, "nwGtpv1uProcessUlpReq failed: while getting ue rnti %x in hashtable ue_mapping\n", data_req_p->rnti);
1054
      } else {
1055
        if ((data_req_p->rab_id >= GTPV1U_BEARER_OFFSET) && (data_req_p->rab_id <= max_val_LTE_DRB_Identity)) {
1056 1057 1058 1059 1060 1061 1062
          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(
1063
                 RC.gtpv1u_data_g->gtpv1u_stack,
1064 1065
                 sgw_s1u_teid,
                 NW_FALSE,
1066
                 RC.gtpv1u_data_g->seq_num++,
1067 1068 1069 1070 1071 1072 1073
                 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);
1074
            MSC_LOG_EVENT(MSC_GTPU_ENB,"0 Failed send G-PDU ltid %u rtid %u size %u",
Lionel Gauthier's avatar
Lionel Gauthier committed
1075
            		enb_s1u_teid,sgw_s1u_teid,data_req_p->length);
1076
            (void)enb_s1u_teid; /* avoid gcc warning "set but not used" */
1077
          } else {
1078
            rc = nwGtpv1uProcessUlpReq(RC.gtpv1u_data_g->gtpv1u_stack, &stack_req);
1079 1080 1081

            if (rc != NW_GTPV1U_OK) {
              LOG_E(GTPU, "nwGtpv1uProcessUlpReq failed: 0x%x\n", rc);
1082
              MSC_LOG_EVENT(MSC_GTPU_ENB,"0 Failed send G-PDU ltid %u rtid %u size %u",
Lionel Gauthier's avatar
Lionel Gauthier committed
1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095
              		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);

1096
            }
1097

1098
            rc = nwGtpv1uMsgDelete(RC.gtpv1u_data_g->gtpv1u_stack,
1099 1100 1101 1102
                                   stack_req.apiInfo.sendtoInfo.hMsg);

            if (rc != NW_GTPV1U_OK) {
              LOG_E(GTPU, "nwGtpv1uMsgDelete failed: 0x%x\n", rc);
1103
            }
1104
          }
1105
        }
1106 1107
      }

1108
      VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_GTPV1U_PROCESS_TUNNEL_DATA_REQ, VCD_FUNCTION_OUT);
1109 1110 1111 1112 1113 1114
      /* Buffer still needed, do not free it */
      //itti_free(ITTI_MSG_ORIGIN_ID(received_message_p), data_req_p->buffer);
    }
    break;

    case TERMINATE_MESSAGE: {
1115 1116
      if (RC.gtpv1u_data_g->ue_mapping != NULL) {
        hashtable_destroy (RC.gtpv1u_data_g->ue_mapping);
1117 1118
      }

1119 1120
      if (RC.gtpv1u_data_g->teid_mapping != NULL) {
        hashtable_destroy (RC.gtpv1u_data_g->teid_mapping);
1121 1122
      }

1123
      LOG_W(GTPU, " *** Exiting GTPU thread\n");
1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135
      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));
1136
    }
1137 1138 1139 1140 1141 1142
    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;
1143
    VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_GTPV1U_ENB_TASK, VCD_FUNCTION_OUT);
laurent's avatar
laurent committed
1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159

    return NULL;
}

//-----------------------------------------------------------------------------
void *gtpv1u_eNB_task(void *args)
{
  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);
1160 1161 1162
  }

  return NULL;
Cedric Roux's avatar
 
Cedric Roux committed
1163
}
1164