ngap_gNB.c 22 KB
Newer Older
zhenghuangkun's avatar
zhenghuangkun committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
/*
 * 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
 * the OAI Public License, Version 1.1  (the "License"); you may not use this file
 * 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
 */

/*! \file ngap_gNB.c
 * \brief NGAP gNB task
zhenghuangkun's avatar
zhenghuangkun committed
24 25 26
 * \author  Yoshio INOUE, Masayuki HARADA
 * \date 2020
 * \email: yoshio.inoue@fujitsu.com,masayuki.harada@fujitsu.com (yoshio.inoue%40fujitsu.com%2cmasayuki.harada%40fujitsu.com)
zhenghuangkun's avatar
zhenghuangkun committed
27 28 29 30
 * \version 1.0
 * @ingroup _ngap
 */

zhenghuangkun's avatar
zhenghuangkun committed
31

zhenghuangkun's avatar
zhenghuangkun committed
32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <crypt.h>

#include "tree.h"
#include "queue.h"

#include "intertask_interface.h"

#include "ngap_gNB_default_values.h"

#include "ngap_common.h"

#include "ngap_gNB_defs.h"
#include "ngap_gNB.h"
#include "ngap_gNB_encoder.h"
#include "ngap_gNB_handlers.h"
#include "ngap_gNB_nnsf.h"

#include "ngap_gNB_nas_procedures.h"
#include "ngap_gNB_management_procedures.h"
#include "ngap_gNB_context_management_procedures.h"

#include "ngap_gNB_itti_messaging.h"

#include "ngap_gNB_ue_context.h" // test, to be removed

#include "assertions.h"
#include "conversions.h"
wujing's avatar
wujing committed
63 64 65
#if defined(TEST_S1C_AMF)
  #include "oaisim_amf_test_s1c.h"
#endif
zhenghuangkun's avatar
zhenghuangkun committed
66

67
ngap_gNB_config_t ngap_config;
zhenghuangkun's avatar
zhenghuangkun committed
68

zhenghuangkun's avatar
zhenghuangkun committed
69 70
static int ngap_gNB_generate_ng_setup_request(
  ngap_gNB_instance_t *instance_p, ngap_gNB_amf_data_t *ngap_amf_data_p);
zhenghuangkun's avatar
zhenghuangkun committed
71

zhenghuangkun's avatar
zhenghuangkun committed
72
void ngap_gNB_handle_register_gNB(instance_t instance, ngap_register_gnb_req_t *ngap_register_gNB);
zhenghuangkun's avatar
zhenghuangkun committed
73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89

void ngap_gNB_handle_sctp_association_resp(instance_t instance, sctp_new_association_resp_t *sctp_new_association_resp);

uint32_t ngap_generate_gNB_id(void) {
  char    *out;
  char     hostname[50];
  int      ret;
  uint32_t gNB_id;
  /* Retrieve the host name */
  ret = gethostname(hostname, sizeof(hostname));
  DevAssert(ret == 0);
  out = crypt(hostname, "eurecom");
  DevAssert(out != NULL);
  gNB_id = ((out[0] << 24) | (out[1] << 16) | (out[2] << 8) | out[3]);
  return gNB_id;
}

zhenghuangkun's avatar
zhenghuangkun committed
90 91
static void ngap_gNB_register_amf(ngap_gNB_instance_t *instance_p,
                                  net_ip_address_t    *amf_ip_address,
zhenghuangkun's avatar
zhenghuangkun committed
92 93 94 95 96 97 98
                                  net_ip_address_t    *local_ip_addr,
                                  uint16_t             in_streams,
                                  uint16_t             out_streams,
                                  uint8_t              broadcast_plmn_num,
                                  uint8_t              broadcast_plmn_index[PLMN_LIST_MAX_SIZE]) {
  MessageDef                 *message_p                   = NULL;
  sctp_new_association_req_t *sctp_new_association_req_p  = NULL;
zhenghuangkun's avatar
zhenghuangkun committed
99
  ngap_gNB_amf_data_t        *ngap_amf_data_p             = NULL;
Xue Song's avatar
Xue Song committed
100

zhenghuangkun's avatar
zhenghuangkun committed
101
  DevAssert(instance_p != NULL);
zhenghuangkun's avatar
zhenghuangkun committed
102
  DevAssert(amf_ip_address != NULL);
103
  message_p = itti_alloc_new_message(TASK_NGAP, 0, SCTP_NEW_ASSOCIATION_REQ);
zhenghuangkun's avatar
zhenghuangkun committed
104 105 106 107 108 109
  sctp_new_association_req_p = &message_p->ittiMsg.sctp_new_association_req;
  sctp_new_association_req_p->port = NGAP_PORT_NUMBER;
  sctp_new_association_req_p->ppid = NGAP_SCTP_PPID;
  sctp_new_association_req_p->in_streams  = in_streams;
  sctp_new_association_req_p->out_streams = out_streams;
  memcpy(&sctp_new_association_req_p->remote_address,
zhenghuangkun's avatar
zhenghuangkun committed
110 111
         amf_ip_address,
         sizeof(*amf_ip_address));
zhenghuangkun's avatar
zhenghuangkun committed
112 113 114
  memcpy(&sctp_new_association_req_p->local_address,
         local_ip_addr,
         sizeof(*local_ip_addr));
115
  NGAP_INFO("[gNB %ld] check the amf registration state\n",instance_p->instance);
Xue Song's avatar
Xue Song committed
116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138

  /* Create new AMF descriptor */
  ngap_amf_data_p = calloc(1, sizeof(*ngap_amf_data_p));
  DevAssert(ngap_amf_data_p != NULL);
  ngap_amf_data_p->cnx_id                = ngap_gNB_fetch_add_global_cnx_id();
  sctp_new_association_req_p->ulp_cnx_id = ngap_amf_data_p->cnx_id;
  ngap_amf_data_p->assoc_id          = -1;
  ngap_amf_data_p->broadcast_plmn_num = broadcast_plmn_num;
  memcpy(&ngap_amf_data_p->amf_s1_ip,
        amf_ip_address,
        sizeof(*amf_ip_address));
  for (int i = 0; i < broadcast_plmn_num; ++i)
    ngap_amf_data_p->broadcast_plmn_index[i] = broadcast_plmn_index[i];

  ngap_amf_data_p->ngap_gNB_instance = instance_p;
  STAILQ_INIT(&ngap_amf_data_p->served_guami);
  /* Insert the new descriptor in list of known AMF
   * but not yet associated.
   */
  RB_INSERT(ngap_amf_map, &instance_p->ngap_amf_head, ngap_amf_data_p);
  ngap_amf_data_p->state = NGAP_GNB_STATE_DISCONNECTED;
  instance_p->ngap_amf_nb ++;
  instance_p->ngap_amf_pending_nb ++;
zhenghuangkun's avatar
zhenghuangkun committed
139 140 141 142

  itti_send_msg_to_task(TASK_SCTP, instance_p->instance, message_p);
}

zhenghuangkun's avatar
zhenghuangkun committed
143
void ngap_gNB_handle_register_gNB(instance_t instance, ngap_register_gnb_req_t *ngap_register_gNB) {
zhenghuangkun's avatar
zhenghuangkun committed
144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167
  ngap_gNB_instance_t *new_instance;
  uint8_t index;
  DevAssert(ngap_register_gNB != NULL);
  /* Look if the provided instance already exists */
  new_instance = ngap_gNB_get_instance(instance);

  if (new_instance != NULL) {
    /* Checks if it is a retry on the same gNB */
    DevCheck(new_instance->gNB_id == ngap_register_gNB->gNB_id, new_instance->gNB_id, ngap_register_gNB->gNB_id, 0);
    DevCheck(new_instance->cell_type == ngap_register_gNB->cell_type, new_instance->cell_type, ngap_register_gNB->cell_type, 0);
    DevCheck(new_instance->num_plmn == ngap_register_gNB->num_plmn, new_instance->num_plmn, ngap_register_gNB->num_plmn, 0);
    DevCheck(new_instance->tac == ngap_register_gNB->tac, new_instance->tac, ngap_register_gNB->tac, 0);

    for (int i = 0; i < new_instance->num_plmn; i++) {
      DevCheck(new_instance->mcc[i] == ngap_register_gNB->mcc[i], new_instance->mcc[i], ngap_register_gNB->mcc[i], 0);
      DevCheck(new_instance->mnc[i] == ngap_register_gNB->mnc[i], new_instance->mnc[i], ngap_register_gNB->mnc[i], 0);
      DevCheck(new_instance->mnc_digit_length[i] == ngap_register_gNB->mnc_digit_length[i], new_instance->mnc_digit_length[i], ngap_register_gNB->mnc_digit_length[i], 0);
    }

    DevCheck(new_instance->default_drx == ngap_register_gNB->default_drx, new_instance->default_drx, ngap_register_gNB->default_drx, 0);
  } else {
    new_instance = calloc(1, sizeof(ngap_gNB_instance_t));
    DevAssert(new_instance != NULL);
    RB_INIT(&new_instance->ngap_ue_head);
zhenghuangkun's avatar
zhenghuangkun committed
168
    RB_INIT(&new_instance->ngap_amf_head);
zhenghuangkun's avatar
zhenghuangkun committed
169 170 171 172 173 174 175
    /* Copy usefull parameters */
    new_instance->instance         = instance;
    new_instance->gNB_name         = ngap_register_gNB->gNB_name;
    new_instance->gNB_id           = ngap_register_gNB->gNB_id;
    new_instance->cell_type        = ngap_register_gNB->cell_type;
    new_instance->tac              = ngap_register_gNB->tac;
    
zhenghuangkun's avatar
zhenghuangkun committed
176
    memcpy(&new_instance->gNB_ng_ip,
zhenghuangkun's avatar
zhenghuangkun committed
177 178
       &ngap_register_gNB->gnb_ip_address,
       sizeof(ngap_register_gNB->gnb_ip_address));
zhenghuangkun's avatar
zhenghuangkun committed
179 180 181 182 183

    for (int i = 0; i < ngap_register_gNB->num_plmn; i++) {
      new_instance->mcc[i]              = ngap_register_gNB->mcc[i];
      new_instance->mnc[i]              = ngap_register_gNB->mnc[i];
      new_instance->mnc_digit_length[i] = ngap_register_gNB->mnc_digit_length[i];
184 185
      
      new_instance->num_nssai[i]        = ngap_register_gNB->num_nssai[i];
zhenghuangkun's avatar
zhenghuangkun committed
186 187 188 189
    }

    new_instance->num_plmn         = ngap_register_gNB->num_plmn;
    new_instance->default_drx      = ngap_register_gNB->default_drx;
190 191 192

    memcpy(new_instance->s_nssai, ngap_register_gNB->s_nssai, sizeof(ngap_register_gNB->s_nssai));

zhenghuangkun's avatar
zhenghuangkun committed
193 194
    /* Add the new instance to the list of gNB (meaningfull in virtual mode) */
    ngap_gNB_insert_new_instance(new_instance);
195
    NGAP_INFO("Registered new gNB[%ld] and %s gNB id %u\n",
zhenghuangkun's avatar
zhenghuangkun committed
196 197 198 199 200
              instance,
              ngap_register_gNB->cell_type == CELL_MACRO_GNB ? "macro" : "home",
              ngap_register_gNB->gNB_id);
  }

zhenghuangkun's avatar
zhenghuangkun committed
201 202
  DevCheck(ngap_register_gNB->nb_amf <= NGAP_MAX_NB_AMF_IP_ADDRESS,
           NGAP_MAX_NB_AMF_IP_ADDRESS, ngap_register_gNB->nb_amf, 0);
zhenghuangkun's avatar
zhenghuangkun committed
203

zhenghuangkun's avatar
zhenghuangkun committed
204 205 206 207 208
  /* Trying to connect to provided list of AMF ip address */
  for (index = 0; index < ngap_register_gNB->nb_amf; index++) {
    net_ip_address_t *amf_ip = &ngap_register_gNB->amf_ip_address[index];
    struct ngap_gNB_amf_data_s *amf = NULL;
    RB_FOREACH(amf, ngap_amf_map, &new_instance->ngap_amf_head) {
zhenghuangkun's avatar
zhenghuangkun committed
209 210
      /* Compare whether IPv4 and IPv6 information is already present, in which
       * wase we do not register again */
zhenghuangkun's avatar
zhenghuangkun committed
211 212 213 214
      if (amf->amf_s1_ip.ipv4 == amf_ip->ipv4 && (!amf_ip->ipv4
              || strncmp(amf->amf_s1_ip.ipv4_address, amf_ip->ipv4_address, 16) == 0)
          && amf->amf_s1_ip.ipv6 == amf_ip->ipv6 && (!amf_ip->ipv6
              || strncmp(amf->amf_s1_ip.ipv6_address, amf_ip->ipv6_address, 46) == 0))
zhenghuangkun's avatar
zhenghuangkun committed
215 216
        break;
    }
zhenghuangkun's avatar
zhenghuangkun committed
217
    if (amf)
zhenghuangkun's avatar
zhenghuangkun committed
218
      continue;
zhenghuangkun's avatar
zhenghuangkun committed
219 220 221
    ngap_gNB_register_amf(new_instance,
                          amf_ip,
                          &ngap_register_gNB->gnb_ip_address,
zhenghuangkun's avatar
zhenghuangkun committed
222 223 224 225 226 227 228 229 230
                          ngap_register_gNB->sctp_in_streams,
                          ngap_register_gNB->sctp_out_streams,
                          ngap_register_gNB->broadcast_plmn_num[index],
                          ngap_register_gNB->broadcast_plmn_index[index]);
  }
}

void ngap_gNB_handle_sctp_association_resp(instance_t instance, sctp_new_association_resp_t *sctp_new_association_resp) {
  ngap_gNB_instance_t *instance_p;
zhenghuangkun's avatar
zhenghuangkun committed
231
  ngap_gNB_amf_data_t *ngap_amf_data_p;
zhenghuangkun's avatar
zhenghuangkun committed
232 233 234
  DevAssert(sctp_new_association_resp != NULL);
  instance_p = ngap_gNB_get_instance(instance);
  DevAssert(instance_p != NULL);
zhenghuangkun's avatar
zhenghuangkun committed
235
  ngap_amf_data_p = ngap_gNB_get_AMF(instance_p, -1,
zhenghuangkun's avatar
zhenghuangkun committed
236
                                     sctp_new_association_resp->ulp_cnx_id);
zhenghuangkun's avatar
zhenghuangkun committed
237
  DevAssert(ngap_amf_data_p != NULL);
zhenghuangkun's avatar
zhenghuangkun committed
238 239

  if (sctp_new_association_resp->sctp_state != SCTP_STATE_ESTABLISHED) {
240
    NGAP_WARN("Received unsuccessful result for SCTP association (%u), instance %ld, cnx_id %u\n",
zhenghuangkun's avatar
zhenghuangkun committed
241 242 243
              sctp_new_association_resp->sctp_state,
              instance,
              sctp_new_association_resp->ulp_cnx_id);
zhenghuangkun's avatar
zhenghuangkun committed
244
    ngap_handle_ng_setup_message(ngap_amf_data_p, sctp_new_association_resp->sctp_state == SCTP_STATE_SHUTDOWN);
zhenghuangkun's avatar
zhenghuangkun committed
245 246 247 248
    return;
  }

  /* Update parameters */
zhenghuangkun's avatar
zhenghuangkun committed
249 250 251 252 253
  ngap_amf_data_p->assoc_id    = sctp_new_association_resp->assoc_id;
  ngap_amf_data_p->in_streams  = sctp_new_association_resp->in_streams;
  ngap_amf_data_p->out_streams = sctp_new_association_resp->out_streams;
  /* Prepare new NG Setup Request */
  ngap_gNB_generate_ng_setup_request(instance_p, ngap_amf_data_p);
zhenghuangkun's avatar
zhenghuangkun committed
254 255 256 257 258 259
}

static
void ngap_gNB_handle_sctp_data_ind(sctp_data_ind_t *sctp_data_ind) {
  int result;
  DevAssert(sctp_data_ind != NULL);
wujing's avatar
wujing committed
260 261 262 263
#if defined(TEST_S1C_AMF)
  amf_test_s1_notify_sctp_data_ind(sctp_data_ind->assoc_id, sctp_data_ind->stream,
                                   sctp_data_ind->buffer, sctp_data_ind->buffer_length);
#else
zhenghuangkun's avatar
zhenghuangkun committed
264 265
  ngap_gNB_handle_message(sctp_data_ind->assoc_id, sctp_data_ind->stream,
                          sctp_data_ind->buffer, sctp_data_ind->buffer_length);
wujing's avatar
wujing committed
266
#endif
zhenghuangkun's avatar
zhenghuangkun committed
267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293
  result = itti_free(TASK_UNKNOWN, sctp_data_ind->buffer);
  AssertFatal (result == EXIT_SUCCESS, "Failed to free memory (%d)!\n", result);
}

void ngap_gNB_init(void) {
  NGAP_DEBUG("Starting NGAP layer\n");
  ngap_gNB_prepare_internal_data();
  itti_mark_task_ready(TASK_NGAP);
}

void *ngap_gNB_process_itti_msg(void *notUsed) {
  MessageDef *received_msg = NULL;
  int         result;
  itti_receive_msg(TASK_NGAP, &received_msg);

  switch (ITTI_MSG_ID(received_msg)) {
    case TERMINATE_MESSAGE:
      NGAP_WARN(" *** Exiting NGAP thread\n");
      itti_exit_task();
      break;

    case NGAP_REGISTER_GNB_REQ: {
      /* Register a new gNB.
       * in Virtual mode gNBs will be distinguished using the mod_id/
       * Each gNB has to send an NGAP_REGISTER_GNB message with its
       * own parameters.
       */
294
      ngap_gNB_handle_register_gNB(ITTI_MSG_DESTINATION_INSTANCE(received_msg),
zhenghuangkun's avatar
zhenghuangkun committed
295 296 297 298 299
                                   &NGAP_REGISTER_GNB_REQ(received_msg));
    }
    break;

    case SCTP_NEW_ASSOCIATION_RESP: {
300
      ngap_gNB_handle_sctp_association_resp(ITTI_MSG_DESTINATION_INSTANCE(received_msg),
zhenghuangkun's avatar
zhenghuangkun committed
301 302 303 304 305 306 307 308 309 310
                                            &received_msg->ittiMsg.sctp_new_association_resp);
    }
    break;

    case SCTP_DATA_IND: {
      ngap_gNB_handle_sctp_data_ind(&received_msg->ittiMsg.sctp_data_ind);
    }
    break;

    case NGAP_NAS_FIRST_REQ: {
311
      ngap_gNB_handle_nas_first_req(ITTI_MSG_DESTINATION_INSTANCE(received_msg),
zhenghuangkun's avatar
zhenghuangkun committed
312 313 314 315 316
                                    &NGAP_NAS_FIRST_REQ(received_msg));
    }
    break;

    case NGAP_UPLINK_NAS: {
317
      ngap_gNB_nas_uplink(ITTI_MSG_DESTINATION_INSTANCE(received_msg),
zhenghuangkun's avatar
zhenghuangkun committed
318 319 320 321 322
                          &NGAP_UPLINK_NAS(received_msg));
    }
    break;

    case NGAP_UE_CAPABILITIES_IND: {
323
      ngap_gNB_ue_capabilities(ITTI_MSG_DESTINATION_INSTANCE(received_msg),
zhenghuangkun's avatar
zhenghuangkun committed
324 325 326 327 328
                               &NGAP_UE_CAPABILITIES_IND(received_msg));
    }
    break;

    case NGAP_INITIAL_CONTEXT_SETUP_RESP: {
329
      ngap_gNB_initial_ctxt_resp(ITTI_MSG_DESTINATION_INSTANCE(received_msg),
zhenghuangkun's avatar
zhenghuangkun committed
330 331 332 333
                                 &NGAP_INITIAL_CONTEXT_SETUP_RESP(received_msg));
    }
    break;

zhenghuangkun's avatar
zhenghuangkun committed
334
    case NGAP_PDUSESSION_SETUP_RESP: {
335
      ngap_gNB_pdusession_setup_resp(ITTI_MSG_DESTINATION_INSTANCE(received_msg),
zhenghuangkun's avatar
zhenghuangkun committed
336
                                &NGAP_PDUSESSION_SETUP_RESP(received_msg));
zhenghuangkun's avatar
zhenghuangkun committed
337 338 339
    }
    break;

zhenghuangkun's avatar
zhenghuangkun committed
340
    case NGAP_PDUSESSION_MODIFY_RESP: {
341
      ngap_gNB_pdusession_modify_resp(ITTI_MSG_DESTINATION_INSTANCE(received_msg),
zhenghuangkun's avatar
zhenghuangkun committed
342
                                 &NGAP_PDUSESSION_MODIFY_RESP(received_msg));
zhenghuangkun's avatar
zhenghuangkun committed
343 344 345 346
    }
    break;

    case NGAP_NAS_NON_DELIVERY_IND: {
347
      ngap_gNB_nas_non_delivery_ind(ITTI_MSG_DESTINATION_INSTANCE(received_msg),
zhenghuangkun's avatar
zhenghuangkun committed
348 349 350 351 352
                                    &NGAP_NAS_NON_DELIVERY_IND(received_msg));
    }
    break;

    case NGAP_PATH_SWITCH_REQ: {
353
      ngap_gNB_path_switch_req(ITTI_MSG_DESTINATION_INSTANCE(received_msg),
zhenghuangkun's avatar
zhenghuangkun committed
354 355 356 357
                               &NGAP_PATH_SWITCH_REQ(received_msg));
    }
    break;

zhenghuangkun's avatar
zhenghuangkun committed
358
    case NGAP_PDUSESSION_MODIFICATION_IND: {
359
    	ngap_gNB_generate_PDUSESSION_Modification_Indication(ITTI_MSG_DESTINATION_INSTANCE(received_msg),
zhenghuangkun's avatar
zhenghuangkun committed
360
    	                               &NGAP_PDUSESSION_MODIFICATION_IND(received_msg));
zhenghuangkun's avatar
zhenghuangkun committed
361 362 363 364
    }
    break;

    case NGAP_UE_CONTEXT_RELEASE_COMPLETE: {
365
      ngap_ue_context_release_complete(ITTI_MSG_DESTINATION_INSTANCE(received_msg),
zhenghuangkun's avatar
zhenghuangkun committed
366 367 368 369 370 371 372
                                       &NGAP_UE_CONTEXT_RELEASE_COMPLETE(received_msg));
    }
    break;

    case NGAP_UE_CONTEXT_RELEASE_REQ: {
      ngap_gNB_instance_t               *ngap_gNB_instance_p           = NULL; // test
      struct ngap_gNB_ue_context_s      *ue_context_p                  = NULL; // test
373
      ngap_ue_context_release_req(ITTI_MSG_DESTINATION_INSTANCE(received_msg),
zhenghuangkun's avatar
zhenghuangkun committed
374
                                  &NGAP_UE_CONTEXT_RELEASE_REQ(received_msg));
375
      ngap_gNB_instance_p = ngap_gNB_get_instance(ITTI_MSG_DESTINATION_INSTANCE(received_msg)); // test
zhenghuangkun's avatar
zhenghuangkun committed
376 377 378 379 380 381 382 383 384 385 386
      DevAssert(ngap_gNB_instance_p != NULL); // test

      if ((ue_context_p = ngap_gNB_get_ue_context(ngap_gNB_instance_p,
                          NGAP_UE_CONTEXT_RELEASE_REQ(received_msg).gNB_ue_ngap_id)) == NULL) { // test
        /* The context for this gNB ue ngap id doesn't exist in the map of gNB UEs */
        NGAP_ERROR("Failed to find ue context associated with gNB ue ngap id: %u\n",
                   NGAP_UE_CONTEXT_RELEASE_REQ(received_msg).gNB_ue_ngap_id); // test
      }  // test
    }
    break;

zhenghuangkun's avatar
zhenghuangkun committed
387
    case NGAP_PDUSESSION_RELEASE_RESPONSE: {
388
      ngap_gNB_pdusession_release_resp(ITTI_MSG_DESTINATION_INSTANCE(received_msg),
zhenghuangkun's avatar
zhenghuangkun committed
389
                                  &NGAP_PDUSESSION_RELEASE_RESPONSE(received_msg));
zhenghuangkun's avatar
zhenghuangkun committed
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 415 416 417
    }
    break;

    default:
      NGAP_ERROR("Received unhandled message: %d:%s\n",
                 ITTI_MSG_ID(received_msg), ITTI_MSG_NAME(received_msg));
      break;
  }

  result = itti_free (ITTI_MSG_ORIGIN_ID(received_msg), received_msg);
  AssertFatal (result == EXIT_SUCCESS, "Failed to free memory (%d)!\n", result);
  received_msg = NULL;
  return NULL;
}


void *ngap_gNB_task(void *arg) {
  ngap_gNB_init();

  while (1) {
    (void) ngap_gNB_process_itti_msg(NULL);
  }

  return NULL;
}

//-----------------------------------------------------------------------------
/*
zhenghuangkun's avatar
zhenghuangkun committed
418
* gNB generate a NG setup request towards AMF
zhenghuangkun's avatar
zhenghuangkun committed
419
*/
zhenghuangkun's avatar
zhenghuangkun committed
420
static int ngap_gNB_generate_ng_setup_request(
zhenghuangkun's avatar
zhenghuangkun committed
421
  ngap_gNB_instance_t *instance_p,
zhenghuangkun's avatar
zhenghuangkun committed
422
  ngap_gNB_amf_data_t *ngap_amf_data_p)
zhenghuangkun's avatar
zhenghuangkun committed
423 424 425
//-----------------------------------------------------------------------------
{
  NGAP_NGAP_PDU_t            pdu;
zhenghuangkun's avatar
zhenghuangkun committed
426 427 428 429 430
  NGAP_NGSetupRequest_t      *out = NULL;
  NGAP_NGSetupRequestIEs_t   *ie = NULL;
  NGAP_SupportedTAItem_t     *ta = NULL;
  NGAP_BroadcastPLMNItem_t   *plmn = NULL;
  NGAP_SliceSupportItem_t    *ssi = NULL;
zhenghuangkun's avatar
zhenghuangkun committed
431 432 433 434
  uint8_t  *buffer = NULL;
  uint32_t  len = 0;
  int       ret = 0;
  DevAssert(instance_p != NULL);
zhenghuangkun's avatar
zhenghuangkun committed
435 436
  DevAssert(ngap_amf_data_p != NULL);
  ngap_amf_data_p->state = NGAP_GNB_STATE_WAITING;
zhenghuangkun's avatar
zhenghuangkun committed
437 438 439
  /* Prepare the NGAP message to encode */
  memset(&pdu, 0, sizeof(pdu));
  pdu.present = NGAP_NGAP_PDU_PR_initiatingMessage;
440 441 442 443 444
  pdu.choice.initiatingMessage = CALLOC(1, sizeof(struct NGAP_InitiatingMessage));
  pdu.choice.initiatingMessage->procedureCode = NGAP_ProcedureCode_id_NGSetup;
  pdu.choice.initiatingMessage->criticality = NGAP_Criticality_reject;
  pdu.choice.initiatingMessage->value.present = NGAP_InitiatingMessage__value_PR_NGSetupRequest;
  out = &pdu.choice.initiatingMessage->value.choice.NGSetupRequest;
zhenghuangkun's avatar
zhenghuangkun committed
445
  /* mandatory */
zhenghuangkun's avatar
zhenghuangkun committed
446 447
  ie = (NGAP_NGSetupRequestIEs_t *)calloc(1, sizeof(NGAP_NGSetupRequestIEs_t));
  ie->id = NGAP_ProtocolIE_ID_id_GlobalRANNodeID;
zhenghuangkun's avatar
zhenghuangkun committed
448
  ie->criticality = NGAP_Criticality_reject;
zhenghuangkun's avatar
zhenghuangkun committed
449 450
  ie->value.present = NGAP_NGSetupRequestIEs__value_PR_GlobalRANNodeID;
  ie->value.choice.GlobalRANNodeID.present = NGAP_GlobalRANNodeID_PR_globalGNB_ID;
451
  ie->value.choice.GlobalRANNodeID.choice.globalGNB_ID = CALLOC(1, sizeof(struct NGAP_GlobalGNB_ID));
zhenghuangkun's avatar
zhenghuangkun committed
452 453 454
  MCC_MNC_TO_PLMNID(instance_p->mcc[ngap_amf_data_p->broadcast_plmn_index[0]],
                    instance_p->mnc[ngap_amf_data_p->broadcast_plmn_index[0]],
                    instance_p->mnc_digit_length[ngap_amf_data_p->broadcast_plmn_index[0]],
455 456
                    &(ie->value.choice.GlobalRANNodeID.choice.globalGNB_ID->pLMNIdentity));
  ie->value.choice.GlobalRANNodeID.choice.globalGNB_ID->gNB_ID.present = NGAP_GNB_ID_PR_gNB_ID;
zhenghuangkun's avatar
zhenghuangkun committed
457
  MACRO_GNB_ID_TO_BIT_STRING(instance_p->gNB_id,
458
                             &ie->value.choice.GlobalRANNodeID.choice.globalGNB_ID->gNB_ID.choice.gNB_ID);
zhenghuangkun's avatar
zhenghuangkun committed
459
  NGAP_INFO("%u -> %02x%02x%02x%02x\n", instance_p->gNB_id,
460 461 462 463
            ie->value.choice.GlobalRANNodeID.choice.globalGNB_ID->gNB_ID.choice.gNB_ID.buf[0],
            ie->value.choice.GlobalRANNodeID.choice.globalGNB_ID->gNB_ID.choice.gNB_ID.buf[1],
            ie->value.choice.GlobalRANNodeID.choice.globalGNB_ID->gNB_ID.choice.gNB_ID.buf[2],
            ie->value.choice.GlobalRANNodeID.choice.globalGNB_ID->gNB_ID.choice.gNB_ID.buf[3]);
zhenghuangkun's avatar
zhenghuangkun committed
464 465 466 467
  ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);

  /* optional */
  if (instance_p->gNB_name) {
zhenghuangkun's avatar
zhenghuangkun committed
468 469
    ie = (NGAP_NGSetupRequestIEs_t *)calloc(1, sizeof(NGAP_NGSetupRequestIEs_t));
    ie->id = NGAP_ProtocolIE_ID_id_RANNodeName;
zhenghuangkun's avatar
zhenghuangkun committed
470
    ie->criticality = NGAP_Criticality_ignore;
zhenghuangkun's avatar
zhenghuangkun committed
471 472
    ie->value.present = NGAP_NGSetupRequestIEs__value_PR_RANNodeName;
    OCTET_STRING_fromBuf(&ie->value.choice.RANNodeName, instance_p->gNB_name,
zhenghuangkun's avatar
zhenghuangkun committed
473 474 475 476 477
                         strlen(instance_p->gNB_name));
    ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
  }

  /* mandatory */
zhenghuangkun's avatar
zhenghuangkun committed
478 479
  ie = (NGAP_NGSetupRequestIEs_t *)calloc(1, sizeof(NGAP_NGSetupRequestIEs_t));
  ie->id = NGAP_ProtocolIE_ID_id_SupportedTAList;
zhenghuangkun's avatar
zhenghuangkun committed
480
  ie->criticality = NGAP_Criticality_reject;
zhenghuangkun's avatar
zhenghuangkun committed
481
  ie->value.present = NGAP_NGSetupRequestIEs__value_PR_SupportedTAList;
zhenghuangkun's avatar
zhenghuangkun committed
482
  {
zhenghuangkun's avatar
zhenghuangkun committed
483
    ta = (NGAP_SupportedTAItem_t *)calloc(1, sizeof(NGAP_SupportedTAItem_t));
484
    INT24_TO_OCTET_STRING(instance_p->tac, &ta->tAC);
zhenghuangkun's avatar
zhenghuangkun committed
485
    {
zhenghuangkun's avatar
zhenghuangkun committed
486 487 488 489 490
      for (int i = 0; i < ngap_amf_data_p->broadcast_plmn_num; ++i) {
        plmn = (NGAP_BroadcastPLMNItem_t *)calloc(1, sizeof(NGAP_BroadcastPLMNItem_t));
        MCC_MNC_TO_TBCD(instance_p->mcc[ngap_amf_data_p->broadcast_plmn_index[i]],
                        instance_p->mnc[ngap_amf_data_p->broadcast_plmn_index[i]],
                        instance_p->mnc_digit_length[ngap_amf_data_p->broadcast_plmn_index[i]],
heshanyun's avatar
heshanyun committed
491
                        &plmn->pLMNIdentity);
zhenghuangkun's avatar
zhenghuangkun committed
492 493 494 495 496

        for(int si = 0; si < instance_p->num_nssai[i]; si++) {
          ssi = (NGAP_SliceSupportItem_t *)calloc(1, sizeof(NGAP_SliceSupportItem_t));
          INT8_TO_OCTET_STRING(instance_p->s_nssai[i][si].sST, &ssi->s_NSSAI.sST);

497
          if (instance_p->s_nssai[i][si].sD_flag) {
zhenghuangkun's avatar
zhenghuangkun committed
498 499 500 501 502 503 504 505 506 507 508 509 510
            ssi->s_NSSAI.sD = calloc(1, sizeof(NGAP_SD_t));
            ssi->s_NSSAI.sD->buf = calloc(3, sizeof(uint8_t));
            ssi->s_NSSAI.sD->size = 3;
            ssi->s_NSSAI.sD->buf[0] = instance_p->s_nssai[i][si].sD[0];
            ssi->s_NSSAI.sD->buf[1] = instance_p->s_nssai[i][si].sD[1];
            ssi->s_NSSAI.sD->buf[2] = instance_p->s_nssai[i][si].sD[2];
          }
          

          ASN_SEQUENCE_ADD(&plmn->tAISliceSupportList.list, ssi);
        }
        
        ASN_SEQUENCE_ADD(&ta->broadcastPLMNList.list, plmn);
zhenghuangkun's avatar
zhenghuangkun committed
511 512
      }
    }
zhenghuangkun's avatar
zhenghuangkun committed
513
    ASN_SEQUENCE_ADD(&ie->value.choice.SupportedTAList.list, ta);
zhenghuangkun's avatar
zhenghuangkun committed
514 515
  }
  ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
zhenghuangkun's avatar
zhenghuangkun committed
516
  
zhenghuangkun's avatar
zhenghuangkun committed
517
  /* mandatory */
zhenghuangkun's avatar
zhenghuangkun committed
518
  ie = (NGAP_NGSetupRequestIEs_t *)calloc(1, sizeof(NGAP_NGSetupRequestIEs_t));
zhenghuangkun's avatar
zhenghuangkun committed
519 520
  ie->id = NGAP_ProtocolIE_ID_id_DefaultPagingDRX;
  ie->criticality = NGAP_Criticality_ignore;
zhenghuangkun's avatar
zhenghuangkun committed
521
  ie->value.present = NGAP_NGSetupRequestIEs__value_PR_PagingDRX;
zhenghuangkun's avatar
zhenghuangkun committed
522 523 524 525 526
  ie->value.choice.PagingDRX = instance_p->default_drx;
  ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);


  if (ngap_gNB_encode_pdu(&pdu, &buffer, &len) < 0) {
zhenghuangkun's avatar
zhenghuangkun committed
527
    NGAP_ERROR("Failed to encode NG setup request\n");
zhenghuangkun's avatar
zhenghuangkun committed
528 529 530 531
    return -1;
  }

  /* Non UE-Associated signalling -> stream = 0 */
zhenghuangkun's avatar
zhenghuangkun committed
532
  ngap_gNB_itti_send_sctp_data_req(instance_p->instance, ngap_amf_data_p->assoc_id, buffer, len, 0);
zhenghuangkun's avatar
zhenghuangkun committed
533 534 535 536 537 538
  return ret;
}