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

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

32 33
#include "mme_config.h"

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

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

54
#undef GTP_DUMP_SOCKET
55

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

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

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

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

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

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

  if (setsockopt(gtpv1u_dump_socket_g, SOL_SOCKET, SO_BINDTODEVICE, (void *)&ifr, sizeof(ifr)) < 0) {
    LOG_E(GTPU, "%s:%d  setsockopt SO_BINDTODEVICE %d:%s\n",
87
          __FILE__, __LINE__, errno, strerror(errno));
88 89
    close(gtpv1u_dump_socket_g);
    return -1;
90 91 92 93
  }
}

//-----------------------------------------------------------------------------
frtabu's avatar
frtabu committed
94
static void gtpv1u_eNB_write_dump_socket(uint8_t *buffer_pP, uint32_t buffer_lengthP) {
95 96 97 98 99 100
  struct sockaddr_in sin;
  memset(&sin, 0, sizeof(sin));
  sin.sin_family = AF_INET;
  sin.sin_addr.s_addr = INADDR_LOOPBACK;

  if (sendto(gtpv1u_dump_socket_g, buffer_pP, (size_t)buffer_lengthP, 0, (struct sockaddr *)&sin, sizeof(struct sockaddr)) < 0)  {
101
    LOG_E(GTPU, "%s:%s:%d  sendto %d:%s\n",
102 103 104 105 106 107 108
          __FILE__, __FUNCTION__, __LINE__, errno, strerror(errno));
  }
}

#endif

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

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

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

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

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

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

164
  if (message_p) {
165
#if defined(LOG_GTPU) && LOG_GTPU > 0
166
    LOG_D(GTPU, "Sending UDP_DATA_REQ length %u offset %u", buffer_len, buffer_offset);
167
#endif
168 169 170 171 172 173 174 175 176 177
    udp_data_req_p = &message_p->ittiMsg.udp_data_req;
    udp_data_req_p->peer_address  = peerIpAddr;
    udp_data_req_p->peer_port     = peerPort;
    udp_data_req_p->buffer        = buffer;
    udp_data_req_p->buffer_length = buffer_len;
    udp_data_req_p->buffer_offset = buffer_offset;
    return itti_send_msg_to_task(TASK_UDP, INSTANCE_DEFAULT, message_p);
  } else {
    return NW_GTPV1U_FAILURE;
  }
178 179 180
}


181
//-----------------------------------------------------------------------------
Cedric Roux's avatar
 
Cedric Roux committed
182
/* Callback called when a gtpv1u message arrived on UDP interface */
183
NwGtpv1uRcT gtpv1u_eNB_process_stack_req(
184
  NwGtpv1uUlpHandleT hUlp,
frtabu's avatar
frtabu committed
185
  NwGtpv1uUlpApiT   *pUlpApi) {
186
  boolean_t           result             = FALSE;
187 188 189 190
  teid_t              teid               = 0;
  hashtable_rc_t      hash_rc            = HASH_TABLE_KEY_NOT_EXISTS;
  gtpv1u_teid_data_t *gtpv1u_teid_data_p = NULL;
  protocol_ctxt_t     ctxt;
Cedric Roux's avatar
Cedric Roux committed
191
  NwGtpv1uRcT         rc;
192 193 194 195 196 197

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

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

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

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

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

frtabu's avatar
frtabu committed
227
      if (hash_rc == HASH_TABLE_OK) {
228
#if defined(LOG_GTPU) && LOG_GTPU > 0
frtabu's avatar
frtabu committed
229 230 231 232 233 234
        LOG_D(GTPU, "Received T-PDU from gtpv1u stack teid  %u size %d -> enb module id %u ue module id %u rab id %u\n",
              teid,
              buffer_len,
              gtpv1u_teid_data_p->enb_id,
              gtpv1u_teid_data_p->ue_id,
              gtpv1u_teid_data_p->eps_bearer_id);
235
#endif
frtabu's avatar
frtabu committed
236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254
        //#warning "LG eps bearer mapping to DRB id to do (offset -4)"
        PROTOCOL_CTXT_SET_BY_MODULE_ID(&ctxt, gtpv1u_teid_data_p->enb_id, ENB_FLAG_YES,  gtpv1u_teid_data_p->ue_id, 0, 0,gtpv1u_teid_data_p->enb_id);
        MSC_LOG_TX_MESSAGE(
          MSC_GTPU_ENB,
          MSC_PDCP_ENB,
          NULL,0,
          MSC_AS_TIME_FMT" DATA-REQ rb %u size %u",
          0,0,
          (gtpv1u_teid_data_p->eps_bearer_id) ? gtpv1u_teid_data_p->eps_bearer_id - 4: 5-4,
          buffer_len);
        result = pdcp_data_req(
                   &ctxt,
                   SRB_FLAG_NO,
                   (gtpv1u_teid_data_p->eps_bearer_id) ? gtpv1u_teid_data_p->eps_bearer_id - 4: 5-4,
                   0, // mui
                   SDU_CONFIRM_NO, // confirm
                   buffer_len,
                   buffer,
                   PDCP_TRANSMISSION_MODE_DATA
255
#if (LTE_RRC_VERSION >= MAKE_VERSION(14, 0, 0))
frtabu's avatar
frtabu committed
256
                   ,NULL, NULL
257
#endif
frtabu's avatar
frtabu committed
258 259 260 261 262 263 264 265 266 267 268 269
                 );

        if ( result == FALSE ) {
          if (ctxt.configured == FALSE )
            LOG_W(GTPU, "PDCP data request failed, cause: RB is not configured!\n") ;
          else
            LOG_W(GTPU, "PDCP data request failed\n");

          return NW_GTPV1U_FAILURE;
        }
      } else {
        LOG_W(GTPU, "Received T-PDU from gtpv1u stack teid %u unknown size %u", teid, buffer_len);
270
      }
Cedric Roux's avatar
 
Cedric Roux committed
271
    }
272
    break;
frtabu's avatar
frtabu committed
273 274 275 276 277 278 279

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

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


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

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

296 297 298 299 300 301
  gtpv1u_data_p = (gtpv1u_data_t *)arg_p;
  return nwGtpv1uProcessUdpReq(gtpv1u_data_p->gtpv1u_stack,
                               buffer,
                               length,
                               portP,
                               address);
Cedric Roux's avatar
 
Cedric Roux committed
302 303
}

304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397
//int
//gtpv1u_create_tunnel_endpoint(
//    gtpv1u_data_t *gtpv1u_data_pP,
//    uint8_t        ue_idP,
//    uint8_t        rab_idP,
//    char          *sgw_ip_addr_pP,
//    uint16_t       portP)
//{
//    uint32_t                     teid;
//    uint8_t                      max_attempt = 100;
//    NwGtpv1uRcT                  rc          = NW_GTPV1U_FAILURE;
//    NwGtpv1uUlpApiT              ulp_req;
//    struct gtpv1u_ue_data_s     *new_ue_p    = NULL;
//    struct gtpv1u_bearer_s      *bearer_p    = NULL;
//    hashtable_rc_t               hash_rc     = HASH_TABLE_KEY_NOT_EXISTS;;
//
//    if (rab_idP > GTPV1U_MAX_BEARERS_PER_UE) {
//        LOG_E(GTPU, "Could not use rab_id %d > max %d\n",
//              rab_idP, GTPV1U_MAX_BEARERS_PER_UE);
//        return -1;
//    }
//
//
//    if ((hash_rc = hashtable_get(gtpv1u_data_pP->ue_mapping, (uint64_t)ue_idP, (void**)&new_ue_p)) == HASH_TABLE_OK) {
//        /* A context for this UE already exist in the tree, use it */
//        /* We check that the tunnel is not already configured */
//        if (new_ue_p->bearers[rab_idP].state != BEARER_DOWN) {
//            LOG_E(GTPU, "Cannot create new end-point over already existing tunnel\n");
//            return -1;
//        }
//    } else {
//        /* Context doesn't exist, create it */
//        if (rab_idP != 0) {
//            /* UE should first establish Default bearer before trying to setup
//             * additional bearers.
//             */
//            LOG_E(GTPU, "UE context is not known and rab_id != 0\n");
//            return -1;
//        }
//        new_ue_p = calloc(1, sizeof(struct gtpv1u_ue_data_s));
//        new_ue_p->ue_id = ue_idP;
//
//        hash_rc = hashtable_insert(gtpv1u_data_pP->ue_mapping, (uint64_t)ue_idP, new_ue_p);
//
//        if ((hash_rc != HASH_TABLE_OK) && (hash_rc != HASH_TABLE_INSERT_OVERWRITTEN_DATA)) {
//            LOG_E(GTPU, "Failed to insert new UE context\n");
//            free(new_ue_p);
//            return -1;
//        }
//    }
//
//    bearer_p = &new_ue_p->bearers[rab_idP];
//
//    /* Configure the bearer */
//    bearer_p->state       = BEARER_IN_CONFIG;
//    bearer_p->sgw_ip_addr = inet_addr(sgw_ip_addr_pP);
//    bearer_p->port        = portP;
//
//    /* Create the new stack api request */
//    memset(&ulp_req, 0, sizeof(NwGtpv1uUlpApiT));
//    ulp_req.apiType = NW_GTPV1U_ULP_API_CREATE_TUNNEL_ENDPOINT;
//
//    /* Try to create new tunnel-endpoint.
//     * If teid generated is already present in the stack, just peek another random
//     * teid. This could be ok for small number of tunnel but more errors could be
//     * thrown if we reached high number of tunnels.
//     * TODO: find a solution for teid
//     */
//    do {
//        /* Request for a new random TEID */
//        teid = gtpv1u_new_teid();
//        ulp_req.apiInfo.createTunnelEndPointInfo.teid = teid;
//
//        rc = nwGtpv1uProcessUlpReq(gtpv1u_data_pP->gtpv1u_stack, &ulp_req);
//
//        if (rc == NW_GTPV1U_OK) {
////             LOG_D(GTPU, "Successfully created new tunnel endpoint for teid 0x%x\n",
////                   teid);
//            bearer_p->teid_eNB = teid;
////             gtpv1u_initial_req(gtpv1u_data_pP, teid, GTPV1U_UDP_PORT,
////                                inet_addr("192.168.56.101"));
//            LOG_I(GTPU, "Created eNB tunnel endpoint %u for ue id %u, rab id %u\n", teid, ue_idP, rab_idP);
//            return 0;
//        } else {
//            LOG_W(GTPU, "Teid %u already in use... %s\n",
//                  teid, (max_attempt > 1) ? "Trying another one" : "Last chance");
//        }
//    } while(max_attempt-- && rc != NW_GTPV1U_OK);
//
//    bearer_p->state = BEARER_DOWN;
//    LOG_I(GTPU, "Failed to created eNB tunnel endpoint %u for ue id %u, rab id %u, bearer down\n", teid, ue_idP, rab_idP);
//
//    return -1;
//}
Cedric Roux's avatar
 
Cedric Roux committed
398 399


400
//-----------------------------------------------------------------------------
401
static NwGtpv1uRcT gtpv1u_start_timer_wrapper(
402
  NwGtpv1uTimerMgrHandleT tmrMgrHandle,
403 404 405
  uint32_t                  timeoutSec,
  uint32_t                  timeoutUsec,
  uint32_t                  tmrType,
406
  void                   *timeoutArg,
frtabu's avatar
frtabu committed
407
  NwGtpv1uTimerHandleT   *hTmr) {
408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427
  NwGtpv1uRcT rc = NW_GTPV1U_OK;
  long        timer_id;

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

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


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

442

443
//-----------------------------------------------------------------------------
444 445
int
gtpv1u_initial_req(
446 447 448
  gtpv1u_data_t *gtpv1u_data_pP,
  teid_t         teidP,
  tcp_udp_port_t portP,
frtabu's avatar
frtabu committed
449
  uint32_t       address) {
450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465
  NwGtpv1uUlpApiT ulp_req;
  NwGtpv1uRcT     rc = NW_GTPV1U_FAILURE;
  memset(&ulp_req, 0, sizeof(NwGtpv1uUlpApiT));
  ulp_req.apiType = NW_GTPV1U_ULP_API_INITIAL_REQ;
  ulp_req.apiInfo.initialReqInfo.teid     = teidP;
  ulp_req.apiInfo.initialReqInfo.peerPort = portP;
  ulp_req.apiInfo.initialReqInfo.peerIp   = address;
  rc = nwGtpv1uProcessUlpReq(gtpv1u_data_pP->gtpv1u_stack, &ulp_req);

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

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

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

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

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

501 502 503 504 505 506 507
  /* Ensure the bearer in ready.
   * TODO: handle the cases where the bearer is in HANDOVER state.
   * In such case packets should be placed in FIFO.
   */
  if (bearer_p->state != BEARER_UP) {
    LOG_W(GTPU, "Trying to send data over bearer with state(%u) != BEARER_UP\n",
          bearer_p->state);
frtabu's avatar
frtabu committed
508
    //#warning  LG: HACK WHILE WAITING FOR NAS, normally return -1
Cedric Roux's avatar
 
Cedric Roux committed
509

510 511 512
    if (bearer_p->state != BEARER_IN_CONFIG)
      return -1;
  }
Cedric Roux's avatar
 
Cedric Roux committed
513

514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550
  memset(&stack_req, 0, sizeof(NwGtpv1uUlpApiT));
  stack_req.apiType                   = NW_GTPV1U_ULP_API_SEND_TPDU;
  stack_req.apiInfo.sendtoInfo.teid   = bearer_p->teid_sgw;
  stack_req.apiInfo.sendtoInfo.ipAddr = bearer_p->sgw_ip_addr;
  LOG_D(GTPU, "TX TO TEID %u addr 0x%x\n",bearer_p->teid_sgw, bearer_p->sgw_ip_addr);
  rc = nwGtpv1uGpduMsgNew(gtpv1u_data_p->gtpv1u_stack,
                          bearer_p->teid_sgw,
                          NW_FALSE,
                          gtpv1u_data_p->seq_num++,
                          buffer_pP,
                          buf_lenP,
                          buf_offsetP,
                          &(stack_req.apiInfo.sendtoInfo.hMsg));

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

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

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

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

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

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

553
//-----------------------------------------------------------------------------
554
int
555
gtpv1u_create_s1u_tunnel(
556
  const instance_t                              instanceP,
frtabu's avatar
frtabu committed
557 558 559
  const gtpv1u_enb_create_tunnel_req_t *const  create_tunnel_req_pP,
  gtpv1u_enb_create_tunnel_resp_t *const create_tunnel_resp_pP
) {
560 561 562 563 564 565 566
  /* Create a new nw-gtpv1-u stack req using API */
  NwGtpv1uUlpApiT          stack_req;
  NwGtpv1uRcT              rc                   = NW_GTPV1U_FAILURE;
  /* Local tunnel end-point identifier */
  teid_t                   s1u_teid             = 0;
  gtpv1u_teid_data_t      *gtpv1u_teid_data_p   = NULL;
  gtpv1u_ue_data_t        *gtpv1u_ue_data_p     = NULL;
567
  //MessageDef              *message_p            = NULL;
568 569 570 571 572 573 574
  hashtable_rc_t           hash_rc              = HASH_TABLE_KEY_NOT_EXISTS;
  int                      i;
  ebi_t                    eps_bearer_id        = 0;
  //    int                      ipv4_addr            = 0;
  int                      ip_offset            = 0;
  in_addr_t                in_addr;
  int                      addrs_length_in_bytes= 0;
Lionel Gauthier's avatar
Lionel Gauthier committed
575
  MSC_LOG_RX_MESSAGE(
frtabu's avatar
frtabu committed
576 577 578 579 580 581 582
    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]);
583 584 585
  create_tunnel_resp_pP->rnti        = create_tunnel_req_pP->rnti;
  create_tunnel_resp_pP->status      = 0;
  create_tunnel_resp_pP->num_tunnels = 0;
586 587 588 589

  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];
590 591
    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);
592 593 594 595 596 597 598 599 600
    memset(&stack_req, 0, sizeof(NwGtpv1uUlpApiT));
    stack_req.apiType = NW_GTPV1U_ULP_API_CREATE_TUNNEL_ENDPOINT;

    do {
      s1u_teid = gtpv1u_new_teid();
      LOG_D(GTPU, "gtpv1u_create_s1u_tunnel() 0x%x %u(dec)\n", s1u_teid, s1u_teid);
      stack_req.apiInfo.createTunnelEndPointInfo.teid          = s1u_teid;
      stack_req.apiInfo.createTunnelEndPointInfo.hUlpSession   = 0;
      stack_req.apiInfo.createTunnelEndPointInfo.hStackSession = 0;
601
      rc = nwGtpv1uProcessUlpReq(RC.gtpv1u_data_g->gtpv1u_stack, &stack_req);
602 603 604 605 606 607
      LOG_D(GTPU, ".\n");
    } while (rc != NW_GTPV1U_OK);

    //-----------------------
    // PDCP->GTPV1U mapping
    //-----------------------
608
    hash_rc = hashtable_get(RC.gtpv1u_data_g->ue_mapping, create_tunnel_req_pP->rnti, (void **)&gtpv1u_ue_data_p);
609 610 611 612

    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));
613
        hash_rc = hashtable_insert(RC.gtpv1u_data_g->ue_mapping, create_tunnel_req_pP->rnti, gtpv1u_ue_data_p);
614 615 616
        AssertFatal(hash_rc == HASH_TABLE_OK, "Error inserting ue_mapping in GTPV1U hashtable");
      }

617
      gtpv1u_ue_data_p->ue_id       = create_tunnel_req_pP->rnti;
618
      gtpv1u_ue_data_p->instance_id = 0; // TO DO
619
      memcpy(&create_tunnel_resp_pP->enb_addr.buffer,
620
             &RC.gtpv1u_data_g->enb_ip_address_for_S1u_S12_S4_up,
621
             sizeof (in_addr_t));
622
      create_tunnel_resp_pP->enb_addr.length = sizeof (in_addr_t);
623 624 625 626 627 628 629 630 631
      addrs_length_in_bytes = create_tunnel_req_pP->sgw_addr[i].length / 8;
      AssertFatal((addrs_length_in_bytes == 4) ||
                  (addrs_length_in_bytes == 16) ||
                  (addrs_length_in_bytes == 20),
                  "Bad transport layer address length %d (bits) %d (bytes)",
                  create_tunnel_req_pP->sgw_addr[i].length, addrs_length_in_bytes);

      if ((addrs_length_in_bytes == 4) ||
          (addrs_length_in_bytes == 20)) {
frtabu's avatar
frtabu committed
632
        in_addr = *((in_addr_t *)create_tunnel_req_pP->sgw_addr[i].buffer);
633 634 635 636 637 638 639 640 641 642 643
        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);
      }

644 645 646 647
      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];
648
      gtpv1u_ue_data_p->num_bearers++;
649
      create_tunnel_resp_pP->enb_S1u_teid[i] = s1u_teid;
650
    } else {
651 652
      create_tunnel_resp_pP->enb_S1u_teid[i] = 0;
      create_tunnel_resp_pP->status         = 0xFF;
653
    }
654

655 656
    create_tunnel_resp_pP->eps_bearer_id[i] = eps_bearer_id;
    create_tunnel_resp_pP->num_tunnels      += 1;
657 658 659
    //-----------------------
    // GTPV1U->PDCP mapping
    //-----------------------
frtabu's avatar
frtabu committed
660
    hash_rc = hashtable_get(RC.gtpv1u_data_g->teid_mapping, s1u_teid, (void **)&gtpv1u_teid_data_p);
661 662 663 664

    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
665
      gtpv1u_teid_data_p->ue_id         = create_tunnel_req_pP->rnti;
666
      gtpv1u_teid_data_p->eps_bearer_id = eps_bearer_id;
667
      hash_rc = hashtable_insert(RC.gtpv1u_data_g->teid_mapping, s1u_teid, gtpv1u_teid_data_p);
668 669
      AssertFatal(hash_rc == HASH_TABLE_OK, "Error inserting teid mapping in GTPV1U hashtable");
    } else {
670 671
      create_tunnel_resp_pP->enb_S1u_teid[i] = 0;
      create_tunnel_resp_pP->status         = 0xFF;
672
    }
673 674
  }

frtabu's avatar
frtabu committed
675 676 677 678 679 680 681
  MSC_LOG_TX_MESSAGE(
    MSC_GTPU_ENB,
    MSC_RRC_ENB,
    NULL,0,
    "0 GTPV1U_ENB_CREATE_TUNNEL_RESP rnti %x teid %x",
    create_tunnel_resp_pP->rnti,
    s1u_teid);
682 683
  LOG_D(GTPU, "Tx GTPV1U_ENB_CREATE_TUNNEL_RESP ue rnti %x status %d\n",
        create_tunnel_req_pP->rnti,
684 685
        create_tunnel_resp_pP->status);
  return 0;
686
}
Cedric Roux's avatar
 
Cedric Roux committed
687

688
int gtpv1u_update_s1u_tunnel(
frtabu's avatar
frtabu committed
689 690 691 692
  const instance_t                              instanceP,
  const gtpv1u_enb_create_tunnel_req_t *const  create_tunnel_req_pP,
  const rnti_t                                  prior_rnti
) {
693 694 695 696
  /* 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;
697
  gtpv1u_ue_data_t        *gtpv1u_ue_data_new_p     = NULL;
698 699
  //MessageDef              *message_p            = NULL;
  hashtable_rc_t           hash_rc              = HASH_TABLE_KEY_NOT_EXISTS;
700 701
  int                      i,j;
  uint8_t                  bearers_num = 0,bearers_total = 0;
702 703 704 705
  //-----------------------
  // PDCP->GTPV1U mapping
  //-----------------------
  hash_rc = hashtable_get(RC.gtpv1u_data_g->ue_mapping, prior_rnti, (void **)&gtpv1u_ue_data_p);
frtabu's avatar
frtabu committed
706 707

  if(hash_rc != HASH_TABLE_OK) {
708 709 710
    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
711

712 713 714 715
  gtpv1u_ue_data_new_p = calloc (1, sizeof(gtpv1u_ue_data_t));
  memcpy(gtpv1u_ue_data_new_p,gtpv1u_ue_data_p,sizeof(gtpv1u_ue_data_t));
  gtpv1u_ue_data_new_p->ue_id       = create_tunnel_req_pP->rnti;
  hash_rc = hashtable_insert(RC.gtpv1u_data_g->ue_mapping, create_tunnel_req_pP->rnti, gtpv1u_ue_data_new_p);
716 717
  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",
frtabu's avatar
frtabu committed
718
        create_tunnel_req_pP->rnti);
719 720
  hash_rc = hashtable_remove(RC.gtpv1u_data_g->ue_mapping, prior_rnti);
  LOG_I(GTPU, "hashtable_remove ue_mapping(rnti=%x) in GTPV1U hashtable\n",
frtabu's avatar
frtabu committed
721
        prior_rnti);
722 723 724
  //-----------------------
  // GTPV1U->PDCP mapping
  //-----------------------
725 726
  bearers_total =gtpv1u_ue_data_new_p->num_bearers;

frtabu's avatar
frtabu committed
727
  for(j = 0; j<GTPV1U_MAX_BEARERS_ID; j++) {
728 729 730 731
    if(gtpv1u_ue_data_new_p->bearers[j].state != BEARER_IN_CONFIG)
      continue;

    bearers_num++;
frtabu's avatar
frtabu committed
732

733 734 735 736
    for (i = 0; i < create_tunnel_req_pP->num_tunnels; i++) {
      if(j == (create_tunnel_req_pP->eps_bearer_id[i]-GTPV1U_BEARER_OFFSET))
        break;
    }
frtabu's avatar
frtabu committed
737 738

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

742 743 744 745 746
      if (hash_rc == HASH_TABLE_OK) {
        gtpv1u_teid_data_p->ue_id         = create_tunnel_req_pP->rnti;
        gtpv1u_teid_data_p->eps_bearer_id = create_tunnel_req_pP->eps_bearer_id[i];
        LOG_I(GTPU, "updata teid_mapping te_id %u (prior_rnti %x rnti %x) in GTPV1U hashtable\n",
              s1u_teid,prior_rnti,create_tunnel_req_pP->rnti);
frtabu's avatar
frtabu committed
747
      } else {
748 749
        LOG_W(GTPU, "Error get teid mapping(s1u_teid=%u) from GTPV1U hashtable", s1u_teid);
      }
frtabu's avatar
frtabu committed
750
    } else {
751 752
      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
753

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

758 759 760 761 762
      gtpv1u_ue_data_new_p->bearers[j].state = BEARER_DOWN;
      gtpv1u_ue_data_new_p->num_bearers--;
      LOG_I(GTPU, "delete teid_mapping te_id %u (rnti%x) bearer_id %d in GTPV1U hashtable\n",
            s1u_teid,prior_rnti,j+GTPV1U_BEARER_OFFSET);;
    }
frtabu's avatar
frtabu committed
763

764 765
    if(bearers_num > bearers_total)
      break;
766
  }
Cedric Roux's avatar
 
Cedric Roux committed
767

frtabu's avatar
frtabu committed
768
  return 0;
769
}
Cedric Roux's avatar
 
Cedric Roux committed
770

771
//-----------------------------------------------------------------------------
772 773
static int gtpv1u_delete_s1u_tunnel(
  const instance_t                             instanceP,
frtabu's avatar
frtabu committed
774
  const gtpv1u_enb_delete_tunnel_req_t *const req_pP) {
775 776 777 778 779 780 781 782
  NwGtpv1uUlpApiT          stack_req;
  NwGtpv1uRcT              rc                   = NW_GTPV1U_FAILURE;
  MessageDef              *message_p = NULL;
  gtpv1u_ue_data_t        *gtpv1u_ue_data_p     = NULL;
  hashtable_rc_t           hash_rc              = HASH_TABLE_KEY_NOT_EXISTS;
  teid_t                   teid_eNB             = 0;
  int                      erab_index           = 0;
  message_p = itti_alloc_new_message(TASK_GTPV1_U, GTPV1U_ENB_DELETE_TUNNEL_RESP);
783
  GTPV1U_ENB_DELETE_TUNNEL_RESP(message_p).rnti     = req_pP->rnti;
784
  GTPV1U_ENB_DELETE_TUNNEL_RESP(message_p).status       = 0;
frtabu's avatar
frtabu committed
785
  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
786

787 788 789
  if (hash_rc == HASH_TABLE_OK) {
    for (erab_index = 0; erab_index < req_pP->num_erab; erab_index++) {
      teid_eNB = gtpv1u_ue_data_p->bearers[req_pP->eps_bearer_id[erab_index] - GTPV1U_BEARER_OFFSET].teid_eNB;
790 791
      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]);
792 793 794 795 796 797
      {
        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);
798
        stack_req.apiInfo.destroyTunnelEndPointInfo.hStackSessionHandle   = gtpv1u_ue_data_p->bearers[req_pP->eps_bearer_id[erab_index] - GTPV1U_BEARER_OFFSET].teid_eNB_stack_session;
799
        rc = nwGtpv1uProcessUlpReq(RC.gtpv1u_data_g->gtpv1u_stack, &stack_req);
800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817
        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) {
818
        hash_rc = hashtable_remove(RC.gtpv1u_data_g->ue_mapping, req_pP->rnti);
819
        LOG_D(GTPU, "Removed user rnti %x,no more bearers configured\n", req_pP->rnti);
820 821 822 823 824
      }

      //-----------------------
      // GTPV1U->PDCP mapping
      //-----------------------
825
      hash_rc = hashtable_remove(RC.gtpv1u_data_g->teid_mapping, teid_eNB);
826 827

      if (hash_rc != HASH_TABLE_OK) {
828
        LOG_D(GTPU, "Removed user rnti %x , enb S1U teid %u not found\n", req_pP->rnti, teid_eNB);
829 830 831
      }
    }
  }// else silently do nothing
832

833 834
  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,
835
        GTPV1U_ENB_DELETE_TUNNEL_RESP(message_p).enb_S1u_teid,
Lionel Gauthier's avatar
 
Lionel Gauthier committed
836
        GTPV1U_ENB_DELETE_TUNNEL_RESP(message_p).status);
Raymond Knopp's avatar
Raymond Knopp committed
837
  MSC_LOG_TX_MESSAGE(
frtabu's avatar
frtabu committed
838 839 840 841 842 843
    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);
844
  return itti_send_msg_to_task(TASK_RRC_ENB, instanceP, message_p);
Cedric Roux's avatar
 
Cedric Roux committed
845 846
}

847

848
//-----------------------------------------------------------------------------
frtabu's avatar
frtabu committed
849
int gtpv1u_eNB_init(void) {
850 851 852 853 854
  NwGtpv1uRcT             rc = NW_GTPV1U_FAILURE;
  NwGtpv1uUlpEntityT      ulp;
  NwGtpv1uUdpEntityT      udp;
  NwGtpv1uLogMgrEntityT   log;
  NwGtpv1uTimerMgrEntityT tmr;
855
  //  enb_properties_p = enb_config_get()->properties[0];
frtabu's avatar
frtabu committed
856
  RC.gtpv1u_data_g = (gtpv1u_data_t *)calloc(sizeof(gtpv1u_data_t),1);
857
  LOG_I(GTPU, "Initializing GTPU stack %p\n",&RC.gtpv1u_data_g);
858 859
  //gtpv1u_data_g.gtpv1u_stack;
  /* Initialize UE hashtable */
860 861 862 863
  RC.gtpv1u_data_g->ue_mapping      = hashtable_create (32, NULL, NULL);
  AssertFatal(RC.gtpv1u_data_g->ue_mapping != NULL, " ERROR Initializing TASK_GTPV1_U task interface: in hashtable_create returned %p\n", RC.gtpv1u_data_g->ue_mapping);
  RC.gtpv1u_data_g->teid_mapping    = hashtable_create (256, NULL, NULL);
  AssertFatal(RC.gtpv1u_data_g->teid_mapping != NULL, " ERROR Initializing TASK_GTPV1_U task interface: in hashtable_create\n");
frtabu's avatar
frtabu committed
864
  //  RC.gtpv1u_data_g.enb_ip_address_for_S1u_S12_S4_up         = enb_properties_p->enb_ipv4_address_for_S1U;
865
  //gtpv1u_data_g.udp_data;
866 867
  RC.gtpv1u_data_g->seq_num         = 0;
  RC.gtpv1u_data_g->restart_counter = 0;
868 869

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

875
  if ((rc = nwGtpv1uSetLogLevel(RC.gtpv1u_data_g->gtpv1u_stack,
876 877 878 879
                                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
880

881 882 883 884
  /* Set the ULP API callback. Called once message have been processed by the
   * nw-gtpv1u stack.
   */
  ulp.ulpReqCallback = gtpv1u_eNB_process_stack_req;
885

886
  if ((rc = nwGtpv1uSetUlpEntity(RC.gtpv1u_data_g->gtpv1u_stack, &ulp)) != NW_GTPV1U_OK) {
887 888 889
    LOG_E(GTPU, "nwGtpv1uSetUlpEntity: %x", rc);
    return -1;
  }
Cedric Roux's avatar
 
Cedric Roux committed
890

891 892 893 894
  /* 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
895

896
  if ((rc = nwGtpv1uSetUdpEntity(RC.gtpv1u_data_g->gtpv1u_stack, &udp)) != NW_GTPV1U_OK) {
897 898 899
    LOG_E(GTPU, "nwGtpv1uSetUdpEntity: %x", rc);
    return -1;
  }
Cedric Roux's avatar
 
Cedric Roux committed
900

901
  log.logReqCallback = gtpv1u_eNB_log_request;
Cedric Roux's avatar
 
Cedric Roux committed
902

903
  if ((rc = nwGtpv1uSetLogMgrEntity(RC.gtpv1u_data_g->gtpv1u_stack, &log)) != NW_GTPV1U_OK) {
904 905 906
    LOG_E(GTPU, "nwGtpv1uSetLogMgrEntity: %x", rc);
    return -1;
  }
Cedric Roux's avatar
 
Cedric Roux committed
907

908 909 910 911 912 913
  /* 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
914

915
  if ((rc = nwGtpv1uSetTimerMgrEntity(RC.gtpv1u_data_g->gtpv1u_stack, &tmr)) != NW_GTPV1U_OK) {
916 917 918
    LOG_E(GTPU, "nwGtpv1uSetTimerMgrEntity: %x", rc);
    return -1;
  }
Cedric Roux's avatar
 
Cedric Roux committed
919

920
#if defined(GTP_DUMP_SOCKET) && GTP_DUMP_SOCKET > 0
921 922 923 924 925

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

926
#endif
927 928
  LOG_D(GTPU, "Initializing GTPV1U interface for eNB: DONE\n");
  return 0;
929
}
Cedric Roux's avatar
 
Cedric Roux committed
930

931
//-----------------------------------------------------------------------------
laurent's avatar
laurent committed
932
void *gtpv1u_eNB_process_itti_msg(void *notUsed) {
frtabu's avatar
frtabu committed
933 934 935 936 937 938 939 940 941 942 943 944 945 946
  /* Trying to fetch a message from the message queue.
   * If the queue is empty, this function will block till a
   * message is sent to the task.
   */
  instance_t  instance;
  MessageDef *received_message_p = NULL;
  int         rc = 0;
  itti_receive_msg(TASK_GTPV1_U, &received_message_p);
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_GTPV1U_ENB_TASK, VCD_FUNCTION_IN);
  DevAssert(received_message_p != NULL);
  instance = ITTI_MSG_INSTANCE(received_message_p);
  //msg_name_p = ITTI_MSG_NAME(received_message_p);

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

950
    case GTPV1U_ENB_DELETE_TUNNEL_REQ: {
951
      gtpv1u_delete_s1u_tunnel(instance, &received_message_p->ittiMsg.Gtpv1uDeleteTunnelReq);
952 953 954 955 956 957 958
    }
    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;
959
      nwGtpv1uProcessUdpReq(RC.gtpv1u_data_g->gtpv1u_stack,
960 961 962 963 964 965 966 967 968 969 970
                            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;
971
      NwGtpv1uUlpApiT               stack_req;
972 973 974 975 976
      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;
977
      VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_GTPV1U_PROCESS_TUNNEL_DATA_REQ, VCD_FUNCTION_IN);
978 979
      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);
980
#if defined(GTP_DUMP_SOCKET) && GTP_DUMP_SOCKET > 0
981
      gtpv1u_eNB_write_dump_socket(&data_req_p->buffer[data_req_p->offset],data_req_p->length);
982
#endif
983
      memset(&stack_req, 0, sizeof(NwGtpv1uUlpApiT));
frtabu's avatar
frtabu committed
984
      hash_rc = hashtable_get(RC.gtpv1u_data_g->ue_mapping, (uint64_t)data_req_p->rnti, (void **)&gtpv1u_ue_data_p);
985 986

      if (hash_rc == HASH_TABLE_KEY_NOT_EXISTS) {
987
        LOG_E(GTPU, "nwGtpv1uProcessUlpReq failed: while getting ue rnti %x in hashtable ue_mapping\n", data_req_p->rnti);
988
      } else {
989
        if ((data_req_p->rab_id >= GTPV1U_BEARER_OFFSET) && (data_req_p->rab_id <= max_val_LTE_DRB_Identity)) {
990 991 992 993 994 995
          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(
996
                 RC.gtpv1u_data_g->gtpv1u_stack,
997 998
                 sgw_s1u_teid,
                 NW_FALSE,
999
                 RC.gtpv1u_data_g->seq_num++,
1000 1001 1002 1003 1004 1005 1006
                 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);
1007
            MSC_LOG_EVENT(MSC_GTPU_ENB,"0 Failed send G-PDU ltid %u rtid %u size %u",
frtabu's avatar
frtabu committed
1008
                          enb_s1u_teid,sgw_s1u_teid,data_req_p->length);
1009
            (void)enb_s1u_teid; /* avoid gcc warning "set but not used" */
1010
          } else {
1011
            rc = nwGtpv1uProcessUlpReq(RC.gtpv1u_data_g->gtpv1u_stack, &stack_req);
1012 1013 1014

            if (rc != NW_GTPV1U_OK) {
              LOG_E(GTPU, "nwGtpv1uProcessUlpReq failed: 0x%x\n", rc);
1015
              MSC_LOG_EVENT(MSC_GTPU_ENB,"0 Failed send G-PDU ltid %u rtid %u size %u",
frtabu's avatar
frtabu committed
1016
                            enb_s1u_teid,sgw_s1u_teid,data_req_p->length);
Lionel Gauthier's avatar
Lionel Gauthier committed
1017
            } else {
frtabu's avatar
frtabu committed
1018 1019 1020 1021 1022 1023 1024 1025 1026 1027
              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);
1028
            }
1029

1030
            rc = nwGtpv1uMsgDelete(RC.gtpv1u_data_g->gtpv1u_stack,
1031 1032 1033 1034
                                   stack_req.apiInfo.sendtoInfo.hMsg);

            if (rc != NW_GTPV1U_OK) {
              LOG_E(GTPU, "nwGtpv1uMsgDelete failed: 0x%x\n", rc);
1035
            }
1036
          }
1037
        }
1038 1039
      }

1040
      VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_GTPV1U_PROCESS_TUNNEL_DATA_REQ, VCD_FUNCTION_OUT);
1041 1042 1043 1044 1045 1046
      /* Buffer still needed, do not free it */
      //itti_free(ITTI_MSG_ORIGIN_ID(received_message_p), data_req_p->buffer);
    }
    break;

    case TERMINATE_MESSAGE: {
1047
      if (RC.gtpv1u_data_g->ue_mapping != NULL) {
frtabu's avatar
frtabu committed
1048
        hashtable_destroy (&(RC.gtpv1u_data_g->ue_mapping));
1049 1050
      }

1051
      if (RC.gtpv1u_data_g->teid_mapping != NULL) {
frtabu's avatar
frtabu committed
1052
        hashtable_destroy (&(RC.gtpv1u_data_g->teid_mapping));
1053 1054
      }

1055
      LOG_W(GTPU, " *** Exiting GTPU thread\n");
1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067
      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));
1068
    }
1069
    break;
frtabu's avatar
frtabu committed
1070
  }
laurent's avatar
laurent committed
1071

frtabu's avatar
frtabu committed
1072 1073 1074 1075 1076
  rc = itti_free(ITTI_MSG_ORIGIN_ID(received_message_p), received_message_p);
  AssertFatal(rc == EXIT_SUCCESS, "Failed to free memory (%d)!\n", rc);
  received_message_p = NULL;
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_GTPV1U_ENB_TASK, VCD_FUNCTION_OUT);
  return NULL;
laurent's avatar
laurent committed
1077 1078 1079
}

//-----------------------------------------------------------------------------
frtabu's avatar
frtabu committed
1080
void *gtpv1u_eNB_task(void *args) {
laurent's avatar
laurent committed
1081 1082 1083 1084 1085 1086 1087 1088
  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);
1089 1090 1091
  }

  return NULL;
Cedric Roux's avatar
 
Cedric Roux committed
1092
}
1093