amf_app.cpp 39.8 KB
Newer Older
Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
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 7 8
 * 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
Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
 *
 *      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 amf_app.cpp
 \brief
24
 \author  Keliang DU (BUPT), Tien-Thinh NGUYEN (EURECOM)
Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
25 26 27 28
 \date 2020
 \email: contact@openairinterface.org
 */

dukl's avatar
dukl committed
29
#include "amf_app.hpp"
30

Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
31 32
#include <boost/uuid/random_generator.hpp>
#include <boost/uuid/uuid_io.hpp>
33
#include <cstdlib>
34 35
#include <iostream>
#include <stdexcept>
36

37
#include "DLNASTransport.hpp"
dukl's avatar
dukl committed
38 39
#include "amf_config.hpp"
#include "amf_n1.hpp"
dukl's avatar
dukl committed
40
#include "amf_n11.hpp"
41
#include "amf_n2.hpp"
dukl's avatar
dukl committed
42
#include "amf_statistics.hpp"
43
#include "itti.hpp"
44
#include "ngap_app.hpp"
45
#include "comUt.hpp"
46 47
#include "RegistrationContextContainer.h"
#include "GlobalRanNodeId.h"
48
#include "UeN1N2InfoSubscriptionCreatedData.h"
dukl's avatar
dukl committed
49

dukl's avatar
dukl committed
50
using namespace ngap;
dukl's avatar
dukl committed
51 52
using namespace nas;
using namespace amf_application;
dukl's avatar
dukl committed
53 54
using namespace config;

Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
55 56 57 58 59
extern amf_app* amf_app_inst;
extern itti_mw* itti_inst;
amf_n2* amf_n2_inst   = nullptr;
amf_n1* amf_n1_inst   = nullptr;
amf_n11* amf_n11_inst = nullptr;
dukl's avatar
dukl committed
60 61 62
extern amf_config amf_cfg;
extern statistics stacs;

Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
63
void amf_app_task(void*);
Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
64

Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
65
//------------------------------------------------------------------------------
66 67 68 69
amf_app::amf_app(const amf_config& amf_cfg)
    : m_amf_ue_ngap_id2ue_ctx(),
      m_ue_ctx_key(),
      m_supi2ue_ctx(),
70 71 72 73 74
      m_curl_handle_responses_n2_sm() {
  amf_ue_ngap_id2ue_ctx       = {};
  ue_ctx_key                  = {};
  supi2ue_ctx                 = {};
  curl_handle_responses_n2_sm = {};
Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
75 76 77 78
  Logger::amf_app().startup("Creating AMF application functionality layer");
  if (itti_inst->create_task(TASK_AMF_APP, amf_app_task, nullptr)) {
    Logger::amf_app().error("Cannot create task TASK_AMF_APP");
    throw std::runtime_error("Cannot create task TASK_AMF_APP");
dukl's avatar
dukl committed
79
  }
80

Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
81
  try {
dukl's avatar
dukl committed
82
    amf_n1_inst = new amf_n1();
83 84
    amf_n2_inst =
        new amf_n2(std::string(inet_ntoa(amf_cfg.n2.addr4)), amf_cfg.n2.port);
dukl's avatar
dukl committed
85
    amf_n11_inst = new amf_n11();
Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
86
  } catch (std::exception& e) {
87 88
    Logger::amf_app().error("Cannot create AMF APP: %s", e.what());
    throw;
dukl's avatar
dukl committed
89
  }
90

91 92 93
  // Generate an AMF profile (including NF instance)
  generate_amf_profile();

94
  // Register to NRF if needed
95 96 97
  if (amf_cfg.support_features.enable_nf_registration and
      amf_cfg.support_features.enable_external_nrf)
    register_to_nrf();
Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
98 99 100 101

  timer_id_t tid = itti_inst->timer_setup(
      amf_cfg.statistics_interval, 0, TASK_AMF_APP,
      TASK_AMF_APP_PERIODIC_STATISTICS, 0);
102
  Logger::amf_app().startup("Started timer (%d)", tid);
dukl's avatar
dukl committed
103 104
}

Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
105
//------------------------------------------------------------------------------
Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
106
void amf_app::allRegistredModulesInit(const amf_modules& modules) {
Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
107
  Logger::amf_app().info("Initiating all registered modules");
dukl's avatar
dukl committed
108 109
}

Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
110
//------------------------------------------------------------------------------
Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
111
void amf_app_task(void*) {
dukl's avatar
dukl committed
112 113 114 115
  const task_id_t task_id = TASK_AMF_APP;
  itti_inst->notify_task_ready(task_id);
  do {
    std::shared_ptr<itti_msg> shared_msg = itti_inst->receive_msg(task_id);
Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
116
    auto* msg                            = shared_msg.get();
dukl's avatar
dukl committed
117
    timer_id_t tid;
Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
118 119
    switch (msg->msg_type) {
      case NAS_SIG_ESTAB_REQ: {
dukl's avatar
dukl committed
120
        Logger::amf_app().debug("Received NAS_SIG_ESTAB_REQ");
Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
121 122
        itti_nas_signalling_establishment_request* m =
            dynamic_cast<itti_nas_signalling_establishment_request*>(msg);
dukl's avatar
dukl committed
123
        amf_app_inst->handle_itti_message(ref(*m));
124
      } break;
dukl's avatar
dukl committed
125

Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
126
      case N1N2_MESSAGE_TRANSFER_REQ: {
dukl's avatar
dukl committed
127
        Logger::amf_app().debug("Received N1N2_MESSAGE_TRANSFER_REQ");
Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
128 129
        itti_n1n2_message_transfer_request* m =
            dynamic_cast<itti_n1n2_message_transfer_request*>(msg);
dukl's avatar
dukl committed
130
        amf_app_inst->handle_itti_message(ref(*m));
131
      } break;
dukl's avatar
dukl committed
132

133 134 135 136 137 138 139
      case SBI_N1_MESSAGE_NOTIFICATION: {
        Logger::amf_app().debug("Received SBI_N1_MESSAGE_NOTIFICATION");
        itti_sbi_n1_message_notification* m =
            dynamic_cast<itti_sbi_n1_message_notification*>(msg);
        amf_app_inst->handle_itti_message(ref(*m));
      } break;

140 141 142 143 144 145 146 147 148 149 150 151 152 153
      case SBI_N1N2_MESSAGE_SUBSCRIBE: {
        Logger::amf_app().debug("Received SBI_N1N2_MESSAGE_SUBSCRIBE");
        itti_sbi_n1n2_message_subscribe* m =
            dynamic_cast<itti_sbi_n1n2_message_subscribe*>(msg);
        amf_app_inst->handle_itti_message(ref(*m));
      } break;

      case SBI_N1N2_MESSAGE_UNSUBSCRIBE: {
        Logger::amf_app().debug("Received SBI_N1N2_MESSAGE_UNSUBSCRIBE");
        itti_sbi_n1n2_message_unsubscribe* m =
            dynamic_cast<itti_sbi_n1n2_message_unsubscribe*>(msg);
        amf_app_inst->handle_itti_message(ref(*m));
      } break;

154 155 156 157 158 159 160
      case SBI_AMF_CONFIGURATION: {
        Logger::amf_app().debug("Received N11_AMF_CONFIGURATION");
        itti_sbi_amf_configuration* m =
            dynamic_cast<itti_sbi_amf_configuration*>(msg);
        amf_app_inst->handle_itti_message(ref(*m));
      } break;

Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
161
      case TIME_OUT: {
Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
162
        if (itti_msg_timeout* to = dynamic_cast<itti_msg_timeout*>(msg)) {
Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
163
          switch (to->arg1_user) {
dukl's avatar
dukl committed
164
            case TASK_AMF_APP_PERIODIC_STATISTICS:
Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
165 166 167
              tid = itti_inst->timer_setup(
                  amf_cfg.statistics_interval, 0, TASK_AMF_APP,
                  TASK_AMF_APP_PERIODIC_STATISTICS, 0);
dukl's avatar
dukl committed
168 169 170
              stacs.display();
              break;
            default:
Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
171 172 173
              Logger::amf_app().info(
                  "No handler for timer(%d) with arg1_user(%d) ", to->timer_id,
                  to->arg1_user);
dukl's avatar
dukl committed
174
          }
Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
175
        }
Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
176
      } break;
177

Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
178 179 180 181 182 183 184
      case TERMINATE: {
        if (itti_msg_terminate* terminate =
                dynamic_cast<itti_msg_terminate*>(msg)) {
          Logger::amf_n2().info("Received terminate message");
          return;
        }
      } break;
dukl's avatar
dukl committed
185
      default:
186
        Logger::amf_app().info("No handler for msg type %d", msg->msg_type);
dukl's avatar
dukl committed
187
    }
Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
188
  } while (true);
dukl's avatar
dukl committed
189
}
dukl's avatar
dukl committed
190

Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
191 192
//------------------------------------------------------------------------------
long amf_app::generate_amf_ue_ngap_id() {
dukl's avatar
dukl committed
193
  long tmp = 0;
Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
194
  tmp      = __sync_fetch_and_add(&amf_app_ue_ngap_id_generator, 1);
dukl's avatar
dukl committed
195 196 197
  return tmp & 0xffffffffff;
}

Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
198
//------------------------------------------------------------------------------
Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
199
bool amf_app::is_amf_ue_id_2_ue_context(const long& amf_ue_ngap_id) const {
dukl's avatar
dukl committed
200
  std::shared_lock lock(m_amf_ue_ngap_id2ue_ctx);
201
  return bool{amf_ue_ngap_id2ue_ctx.count(amf_ue_ngap_id) > 0};
dukl's avatar
dukl committed
202 203
}

Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
204
//------------------------------------------------------------------------------
Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
205
std::shared_ptr<ue_context> amf_app::amf_ue_id_2_ue_context(
Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
206
    const long& amf_ue_ngap_id) const {
dukl's avatar
dukl committed
207 208 209 210
  std::shared_lock lock(m_amf_ue_ngap_id2ue_ctx);
  return amf_ue_ngap_id2ue_ctx.at(amf_ue_ngap_id);
}

Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
211
//------------------------------------------------------------------------------
Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
212
void amf_app::set_amf_ue_ngap_id_2_ue_context(
213
    const long& amf_ue_ngap_id, const std::shared_ptr<ue_context>& uc) {
Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
214
  std::unique_lock lock(m_amf_ue_ngap_id2ue_ctx);
dukl's avatar
dukl committed
215 216 217
  amf_ue_ngap_id2ue_ctx[amf_ue_ngap_id] = uc;
}

Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
218
//------------------------------------------------------------------------------
Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
219
bool amf_app::is_ran_amf_id_2_ue_context(const string& ue_context_key) const {
Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
220
  std::shared_lock lock(m_ue_ctx_key);
221
  return bool{ue_ctx_key.count(ue_context_key) > 0};
Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
222 223
}

Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
224
//------------------------------------------------------------------------------
Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
225
std::shared_ptr<ue_context> amf_app::ran_amf_id_2_ue_context(
Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
226
    const string& ue_context_key) const {
Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
227 228 229 230
  std::shared_lock lock(m_ue_ctx_key);
  return ue_ctx_key.at(ue_context_key);
}

231
//------------------------------------------------------------------------------
232 233 234 235 236 237 238 239 240 241
bool amf_app::ran_amf_id_2_ue_context(
    const std::string& ue_context_key, std::shared_ptr<ue_context>& uc) const {
  std::shared_lock lock(m_ue_ctx_key);
  if (ue_ctx_key.count(ue_context_key) > 0) {
    uc = ue_ctx_key.at(ue_context_key);
    if (uc.get() == nullptr) return false;
    return true;
  } else
    return false;
}
242

Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
243
//------------------------------------------------------------------------------
Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
244
void amf_app::set_ran_amf_id_2_ue_context(
245
    const string& ue_context_key, const std::shared_ptr<ue_context>& uc) {
Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
246
  std::unique_lock lock(m_ue_ctx_key);
Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
247 248
  ue_ctx_key[ue_context_key] = uc;
}
Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
249

250 251 252 253 254 255 256 257 258 259 260 261 262 263 264
//------------------------------------------------------------------------------
bool amf_app::is_supi_2_ue_context(const string& supi) const {
  std::shared_lock lock(m_supi2ue_ctx);
  return bool{supi2ue_ctx.count(supi) > 0};
}

//------------------------------------------------------------------------------
std::shared_ptr<ue_context> amf_app::supi_2_ue_context(
    const string& supi) const {
  std::shared_lock lock(m_supi2ue_ctx);
  return supi2ue_ctx.at(supi);
}

//------------------------------------------------------------------------------
void amf_app::set_supi_2_ue_context(
265
    const string& supi, const std::shared_ptr<ue_context>& uc) {
Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
266
  std::unique_lock lock(m_supi2ue_ctx);
267 268 269
  supi2ue_ctx[supi] = uc;
}

270
//------------------------------------------------------------------------------
Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
271 272 273
bool amf_app::find_pdu_session_context(
    const string& supi, const std::uint8_t pdu_session_id,
    std::shared_ptr<pdu_session_context>& psc) {
274 275
  if (!is_supi_2_ue_context(supi)) return false;
  std::shared_ptr<ue_context> uc = {};
Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
276
  uc                             = supi_2_ue_context(supi);
277 278 279 280
  if (!uc.get()->find_pdu_session_context(pdu_session_id, psc)) return false;
  return true;
}

281
//------------------------------------------------------------------------------
282 283 284 285 286 287 288 289 290 291
bool amf_app::get_pdu_sessions_context(
    const string& supi,
    std::vector<std::shared_ptr<pdu_session_context>>& sessions_ctx) {
  if (!is_supi_2_ue_context(supi)) return false;
  std::shared_ptr<ue_context> uc = {};
  uc                             = supi_2_ue_context(supi);
  if (!uc.get()->get_pdu_sessions_context(sessions_ctx)) return false;
  return true;
}

292 293 294 295 296
//------------------------------------------------------------------------------
evsub_id_t amf_app::generate_ev_subscription_id() {
  return evsub_id_generator.get_uid();
}

297 298 299 300 301
//------------------------------------------------------------------------------
n1n2sub_id_t amf_app::generate_n1n2_message_subscription_id() {
  return n1n2sub_id_generator.get_uid();
}

Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
302
//------------------------------------------------------------------------------
Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
303
void amf_app::handle_itti_message(
Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
304
    itti_n1n2_message_transfer_request& itti_msg) {
305
  if (itti_msg.is_ppi_set) {  // Paging procedure
Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
306 307
    Logger::amf_app().info(
        "Handle ITTI N1N2 Message Transfer Request for Paging");
308 309
    std::shared_ptr<itti_paging> i =
        std::make_shared<itti_paging>(TASK_AMF_APP, TASK_AMF_N2);
310 311
    amf_n1_inst->supi_2_amf_id(itti_msg.supi, i.get()->amf_ue_ngap_id);
    amf_n1_inst->supi_2_ran_id(itti_msg.supi, i.get()->ran_ue_ngap_id);
312 313 314 315 316 317 318

    int ret = itti_inst->send_msg(i);
    if (0 != ret) {
      Logger::amf_app().error(
          "Could not send ITTI message %s to task TASK_AMF_N2",
          i->get_msg_name());
    }
Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
319
  } else {
Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
320
    Logger::amf_app().info("Handle ITTI N1N2 Message Transfer Request");
321 322 323 324 325 326 327 328 329 330
    // Encode DL NAS TRANSPORT message(NAS message)
    DLNASTransport* dl = new DLNASTransport();
    dl->setHeader(PLAIN_5GS_MSG);
    dl->setPayload_Container_Type(N1_SM_INFORMATION);
    dl->setPayload_Container(
        (uint8_t*) bdata(itti_msg.n1sm), blength(itti_msg.n1sm));
    dl->setPDUSessionId(itti_msg.pdu_session_id);

    uint8_t nas[BUFFER_SIZE_1024];
    int encoded_size = dl->encode2buffer(nas, BUFFER_SIZE_1024);
331
    comUt::print_buffer("amf_app", "n1n2 transfer", nas, encoded_size);
332 333 334 335 336 337 338 339 340 341 342 343 344
    bstring dl_nas = blk2bstr(nas, encoded_size);

    itti_downlink_nas_transfer* dl_msg =
        new itti_downlink_nas_transfer(TASK_AMF_APP, TASK_AMF_N1);
    dl_msg->dl_nas = dl_nas;
    if (!itti_msg.is_n2sm_set) {
      dl_msg->is_n2sm_set = false;
    } else {
      dl_msg->n2sm           = itti_msg.n2sm;
      dl_msg->pdu_session_id = itti_msg.pdu_session_id;
      dl_msg->is_n2sm_set    = true;
      dl_msg->n2sm_info_type = itti_msg.n2sm_info_type;
    }
345 346
    amf_n1_inst->supi_2_amf_id(itti_msg.supi, dl_msg->amf_ue_ngap_id);
    amf_n1_inst->supi_2_ran_id(itti_msg.supi, dl_msg->ran_ue_ngap_id);
347 348 349 350 351 352 353 354
    std::shared_ptr<itti_downlink_nas_transfer> i =
        std::shared_ptr<itti_downlink_nas_transfer>(dl_msg);
    int ret = itti_inst->send_msg(i);
    if (0 != ret) {
      Logger::amf_app().error(
          "Could not send ITTI message %s to task TASK_AMF_N1",
          i->get_msg_name());
    }
dukl's avatar
dukl committed
355 356 357
  }
}

Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
358
//------------------------------------------------------------------------------
Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
359
void amf_app::handle_itti_message(
Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
360
    itti_nas_signalling_establishment_request& itti_msg) {
Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
361 362 363 364
  // 1. Generate amf_ue_ngap_id
  // 2. Create UE Context and store related information information
  // 3. Send nas-pdu to task_amf_n1

dukl's avatar
dukl committed
365
  long amf_ue_ngap_id = 0;
366
  std::shared_ptr<ue_context> uc;
dukl's avatar
dukl committed
367

368
  // Check UE Context with 5g-s-tmsi
369
  if ((amf_ue_ngap_id = itti_msg.amf_ue_ngap_id) == -1) {
dukl's avatar
dukl committed
370 371
    amf_ue_ngap_id = generate_amf_ue_ngap_id();
  }
Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
372

373 374
  string ue_context_key = "app_ue_ranid_" + to_string(itti_msg.ran_ue_ngap_id) +
                          ":amfid_" + to_string(amf_ue_ngap_id);
Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
375
  if (!is_ran_amf_id_2_ue_context(ue_context_key)) {
Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
376 377 378
    Logger::amf_app().debug(
        "No existing UE Context, Create a new one with ran_amf_id %s",
        ue_context_key.c_str());
379
    uc = std::shared_ptr<ue_context>(new ue_context());
Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
380
    set_ran_amf_id_2_ue_context(ue_context_key, uc);
dukl's avatar
dukl committed
381
  }
Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
382

383 384 385 386
  // Update AMF UE NGAP ID
  std::shared_ptr<ue_ngap_context> unc = {};
  if (!amf_n2_inst->is_ran_ue_id_2_ue_ngap_context(itti_msg.ran_ue_ngap_id)) {
    Logger::amf_n1().error(
387 388
        "Could not find UE NGAP Context with ran_ue_ngap_id "
        "(" GNB_UE_NGAP_ID_FMT ")",
389 390
        itti_msg.ran_ue_ngap_id);
  } else {
391
    unc = amf_n2_inst->ran_ue_id_2_ue_ngap_context(itti_msg.ran_ue_ngap_id);
392
    unc.get()->amf_ue_ngap_id = amf_ue_ngap_id;
393
    amf_n2_inst->set_amf_ue_ngap_id_2_ue_ngap_context(amf_ue_ngap_id, unc);
394 395
  }

Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
396
  if (uc.get() == nullptr) {
Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
397 398 399
    Logger::amf_app().error(
        "Failed to create ue_context with ran_amf_id %s",
        ue_context_key.c_str());
Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
400
  } else {
dukl's avatar
dukl committed
401 402
    uc.get()->cgi = itti_msg.cgi;
    uc.get()->tai = itti_msg.tai;
Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
403
    if (itti_msg.rrc_cause != -1)
404
      uc.get()->rrc_estb_cause =
Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
405
          (e_Ngap_RRCEstablishmentCause) itti_msg.rrc_cause;
Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
406
    if (itti_msg.ueCtxReq == -1)
dukl's avatar
dukl committed
407 408 409 410 411 412
      uc.get()->isUeContextRequest = false;
    else
      uc.get()->isUeContextRequest = true;
    uc.get()->ran_ue_ngap_id = itti_msg.ran_ue_ngap_id;
    uc.get()->amf_ue_ngap_id = amf_ue_ngap_id;

Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
413 414 415
    std::string guti;
    bool is_guti_valid = false;
    if (itti_msg.is_5g_s_tmsi_present) {
416 417
      guti = itti_msg.tai.mcc + itti_msg.tai.mnc + amf_cfg.guami.regionID +
             itti_msg._5g_s_tmsi;
dukl's avatar
dukl committed
418
      is_guti_valid = true;
Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
419
      Logger::amf_app().debug("Receiving GUTI %s", guti.c_str());
dukl's avatar
dukl committed
420 421
    }

Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
422
    itti_uplink_nas_data_ind* itti_n1_msg =
423
        new itti_uplink_nas_data_ind(TASK_AMF_APP, TASK_AMF_N1);
Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
424 425
    itti_n1_msg->amf_ue_ngap_id              = amf_ue_ngap_id;
    itti_n1_msg->ran_ue_ngap_id              = itti_msg.ran_ue_ngap_id;
dukl's avatar
dukl committed
426
    itti_n1_msg->is_nas_signalling_estab_req = true;
Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
427 428 429 430
    itti_n1_msg->nas_msg                     = itti_msg.nas_buf;
    itti_n1_msg->mcc                         = itti_msg.tai.mcc;
    itti_n1_msg->mnc                         = itti_msg.tai.mnc;
    itti_n1_msg->is_guti_valid               = is_guti_valid;
Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
431
    if (is_guti_valid) {
dukl's avatar
dukl committed
432 433
      itti_n1_msg->guti = guti;
    }
434 435
    std::shared_ptr<itti_uplink_nas_data_ind> i =
        std::shared_ptr<itti_uplink_nas_data_ind>(itti_n1_msg);
dukl's avatar
dukl committed
436
    int ret = itti_inst->send_msg(i);
Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
437
    if (0 != ret) {
Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
438 439 440
      Logger::amf_app().error(
          "Could not send ITTI message %s to task TASK_AMF_N1",
          i->get_msg_name());
dukl's avatar
dukl committed
441 442 443
    }
  }
}
dukl's avatar
dukl committed
444

445 446 447
//------------------------------------------------------------------------------
void amf_app::handle_itti_message(itti_sbi_n1_message_notification& itti_msg) {
  Logger::amf_app().info(
448 449
      "Target AMF, handling a N1 Message Notification from the initial AMF");

450 451 452 453 454 455 456 457 458 459 460 461 462
  // Step 1. Get UE, gNB related information

  // Get NAS message (RegistrationRequest, this message included
  // in N1 Message Notify is actually is RegistrationRequest from UE to the
  // initial AMF)
  bstring n1sm;
  conv::msg_str_2_msg_hex(itti_msg.n1sm, n1sm);

  // get RegistrationContextContainer including gNB info
  // UE context information, N1 message from UE, AN address
  oai::amf::model::RegistrationContextContainer registration_context =
      itti_msg.notification_msg.getRegistrationCtxtContainer();

463
  // Step 2. Create gNB context if necessary
464

465 466 467
  // TODO: How to get SCTP-related information and establish a new SCTP
  // connection between the Target AMF and gNB?
  std::shared_ptr<gnb_context> gc = {};
468 469 470 471 472 473 474 475 476 477 478 479 480 481 482

  // GlobalRAN Node ID (~in NGSetupRequest)
  oai::amf::model::GlobalRanNodeId ran_node_id =
      registration_context.getRanNodeId();
  // RAN UE NGAP ID
  uint32_t ran_ue_ngap_id = registration_context.getAnN2ApId();

  if (ran_node_id.gNbIdIsSet()) {
    oai::amf::model::GNbId gnb_id_model = ran_node_id.getGNbId();
    uint32_t gnb_id                     = {};

    try {
      gnb_id = std::stoul(gnb_id_model.getGNBValue(), nullptr, 10);
    } catch (const std::exception& e) {
      Logger::amf_app().warn(
483
          "Error when converting from string to uint32_t for gNB Value: %s",
484 485 486 487 488 489 490 491 492 493 494
          e.what());
      return;
    }

    gc->globalRanNodeId = gnb_id;
    // TODO:   gc->gnb_name
    // TODO: DefaultPagingDRX
    // TODO: Supported TA List
    amf_n2_inst->set_gnb_id_2_gnb_context(gnb_id, gc);
  }

495 496 497 498 499 500 501 502
  // UserLocation getUserLocation()
  // std::string getAnN2IPv4Addr()
  // AllowedNssai getAllowedNssai()
  // std::vector<ConfiguredSnssai>& getConfiguredNssai();
  // rejectedNssaiInPlmn
  // rejectedNssaiInTa
  // std::string getInitialAmfName()

503
  // Step 3. Create UE Context
504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527
  oai::amf::model::UeContext ue_ctx = registration_context.getUeContext();
  std::string supi                  = {};
  std::shared_ptr<ue_context> uc    = {};

  if (ue_ctx.supiIsSet()) {
    supi = ue_ctx.getSupi();
    if (!is_supi_2_ue_context(supi)) {
      // Create a new UE Context
      Logger::amf_app().debug(
          "No existing UE Context, Create a new one with SUPI %s",
          supi.c_str());
      uc                 = std::shared_ptr<ue_context>(new ue_context());
      uc->amf_ue_ngap_id = -1;
      uc->supi           = supi;
      set_supi_2_ue_context(supi, uc);
    } else {  // Update UE Context
      uc = supi_2_ue_context(supi);
    }
  }

  // TODO: 5gMmCapability
  // TODO: MmContext
  // TODO: PduSessionContext

528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 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 584 585 586 587 588 589 590 591 592 593 594
  /*
  if (!is_supi_2_ue_context(itti_msg.ue_id)) {
    // TODO: Create a new UE Context
  } else {  // Update UE Context
    uc = supi_2_ue_context(itti_msg.ue_id);
  }
*/

  long amf_ue_ngap_id = -1;
  // Generate AMF UE NGAP ID if necessary
  if (!uc.get()) {  // No UE context existed
    amf_ue_ngap_id = generate_amf_ue_ngap_id();
  } else {
    if ((amf_ue_ngap_id = uc->amf_ue_ngap_id) == -1) {
      amf_ue_ngap_id = generate_amf_ue_ngap_id();
    }
  }

  string ue_context_key = "app_ue_ranid_" + to_string(ran_ue_ngap_id) +
                          ":amfid_" + to_string(amf_ue_ngap_id);
  if (!is_ran_amf_id_2_ue_context(ue_context_key)) {
    Logger::amf_app().debug(
        "No existing UE Context associated with UE Context Key %s",
        ue_context_key.c_str());
    if (!uc.get()) {
      // Create a new UE Context
      Logger::amf_app().debug(
          "Create a new UE Context with UE Context Key",
          ue_context_key.c_str());
      uc = std::shared_ptr<ue_context>(new ue_context());
    }
    set_ran_amf_id_2_ue_context(ue_context_key, uc);
  } else {
    uc = ran_amf_id_2_ue_context(ue_context_key);
  }
  // Return if UE Context is still invalid
  if (!uc.get()) {
    Logger::amf_app().error("Failed to get UE Context");
    return;
  }

  // Update info for UE context
  uc.get()->amf_ue_ngap_id = amf_ue_ngap_id;
  uc.get()->ran_ue_ngap_id = ran_ue_ngap_id;
  // RrcEstCause
  if (registration_context.rrcEstCauseIsSet()) {
    uint8_t rrc_cause = {};
    try {
      rrc_cause =
          std::stoul(registration_context.getRrcEstCause(), nullptr, 10);
    } catch (const std::exception& e) {
      Logger::amf_app().warn(
          "Error when converting from string to int for RrcEstCause: %s",
          e.what());
      rrc_cause = 0;
    }

    uc.get()->rrc_estb_cause = (e_Ngap_RRCEstablishmentCause) rrc_cause;
  }
  // ueContextRequest
  uc.get()->isUeContextRequest = registration_context.isUeContextRequest();

  // Step 4. Create UE NGAP Context if necessary
  // Create/Update UE NGAP Context
  std::shared_ptr<ue_ngap_context> unc = {};
  if (!amf_n2_inst->is_ran_ue_id_2_ue_ngap_context(ran_ue_ngap_id)) {
    Logger::amf_app().debug(
595
        "Create a new UE NGAP context with ran_ue_ngap_id " GNB_UE_NGAP_ID_FMT,
596 597 598 599 600 601 602
        ran_ue_ngap_id);
    unc = std::shared_ptr<ue_ngap_context>(new ue_ngap_context());
    amf_n2_inst->set_ran_ue_ngap_id_2_ue_ngap_context(ran_ue_ngap_id, unc);
  } else {
    unc = amf_n2_inst->ran_ue_id_2_ue_ngap_context(ran_ue_ngap_id);
    if (!unc.get()) {
      Logger::amf_app().error(
603 604
          "Failed to get UE NGAP context for "
          "ran_ue_ngap_id " GNB_UE_NGAP_ID_FMT,
605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627
          ran_ue_ngap_id);
      return;
    }
  }

  // Store related information into UE NGAP context
  unc.get()->ran_ue_ngap_id = ran_ue_ngap_id;
  // TODO:  unc.get()->sctp_stream_recv
  // TODO: unc.get()->sctp_stream_send
  // TODO: gc.get()->next_sctp_stream
  // TODO: unc.get()->gnb_assoc_id
  // TODO: unc.get()->tai

  // Step 5. Trigger the procedure following RegistrationRequest

  itti_uplink_nas_data_ind* itti_n1_msg =
      new itti_uplink_nas_data_ind(TASK_AMF_APP, TASK_AMF_N1);
  itti_n1_msg->amf_ue_ngap_id              = amf_ue_ngap_id;
  itti_n1_msg->ran_ue_ngap_id              = ran_ue_ngap_id;
  itti_n1_msg->is_nas_signalling_estab_req = true;
  itti_n1_msg->nas_msg                     = n1sm;
  itti_n1_msg->mcc                         = ran_node_id.getPlmnId().getMcc();
  itti_n1_msg->mnc                         = ran_node_id.getPlmnId().getMnc();
628
  itti_n1_msg->is_guti_valid               = false;
629 630 631 632 633 634 635 636 637 638 639 640

  std::shared_ptr<itti_uplink_nas_data_ind> i =
      std::shared_ptr<itti_uplink_nas_data_ind>(itti_n1_msg);
  int ret = itti_inst->send_msg(i);
  if (0 != ret) {
    Logger::amf_app().error(
        "Could not send ITTI message %s to task TASK_AMF_N1",
        i->get_msg_name());
  }

  return;
}
Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
641

642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707
//------------------------------------------------------------------------------
void amf_app::handle_itti_message(itti_sbi_n1n2_message_subscribe& itti_msg) {
  Logger::amf_app().info(
      "Handle an N1N2MessageSubscribe from a NF (HTTP version "
      "%d)",
      itti_msg.http_version);

  // Generate a subscription ID Id and store the corresponding information in a
  // map (subscription id, info)
  n1n2sub_id_t n1n2sub_id = generate_n1n2_message_subscription_id();
  std::shared_ptr<oai::amf::model::UeN1N2InfoSubscriptionCreateData>
      subscription_data =
          std::make_shared<oai::amf::model::UeN1N2InfoSubscriptionCreateData>(
              itti_msg.subscription_data);
  add_n1n2_message_subscription(
      itti_msg.ue_cxt_id, n1n2sub_id, subscription_data);

  std::string location =
      amf_cfg.get_amf_n1n2_message_subscribe_uri(itti_msg.ue_cxt_id) + "/" +
      std::to_string((uint32_t) n1n2sub_id);

  // Trigger the response from AMF API Server
  oai::amf::model::UeN1N2InfoSubscriptionCreatedData created_data = {};
  created_data.setN1n2NotifySubscriptionId(
      std::to_string((uint32_t) n1n2sub_id));
  nlohmann::json created_data_json = {};
  to_json(created_data_json, created_data);

  nlohmann::json response_data      = {};
  response_data["createdData"]      = created_data;
  response_data["httpResponseCode"] = 201;  // TODO:
  response_data["location"]         = location;

  // Notify to the result
  if (itti_msg.promise_id > 0) {
    trigger_process_response(itti_msg.promise_id, response_data);
    return;
  }
}

//------------------------------------------------------------------------------
void amf_app::handle_itti_message(itti_sbi_n1n2_message_unsubscribe& itti_msg) {
  Logger::amf_app().info(
      "Handle an N1N2MessageUnSubscribe from a NF (HTTP version "
      "%d)",
      itti_msg.http_version);

  // Process the request and trigger the response from AMF API Server
  nlohmann::json response_data = {};
  if (remove_n1n2_message_subscription(
          itti_msg.ue_cxt_id, itti_msg.subscription_id)) {
    response_data["httpResponseCode"] = 204;  // TODO:
  } else {
    response_data["httpResponseCode"]               = 400;  // TODO:
    oai::amf::model::ProblemDetails problem_details = {};
    // TODO set problem_details
    to_json(response_data["ProblemDetails"], problem_details);
  }

  // Notify to the result
  if (itti_msg.promise_id > 0) {
    trigger_process_response(itti_msg.promise_id, response_data);
    return;
  }
}

708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741
//------------------------------------------------------------------------------
void amf_app::handle_itti_message(itti_sbi_amf_configuration& itti_msg) {
  Logger::amf_app().info(
      "Handle an SBIAMFConfiguration from a NF (HTTP version "
      "%d)",
      itti_msg.http_version);

  // Process the request and trigger the response from AMF API Server
  nlohmann::json response_data = {};
  response_data["content"]     = {};
  if (read_amf_configuration(response_data["content"])) {
    Logger::amf_app().debug(
        "AMF configuration:\n %s", response_data["content"].dump().c_str());
    response_data["httpResponseCode"] = 200;  // TODO:
  } else {
    response_data["httpResponseCode"]               = 400;  // TODO:
    oai::amf::model::ProblemDetails problem_details = {};
    // TODO set problem_details
    to_json(response_data["ProblemDetails"], problem_details);
  }

  // Notify to the result
  if (itti_msg.promise_id > 0) {
    trigger_process_response(itti_msg.promise_id, response_data);
    return;
  }
}

//---------------------------------------------------------------------------------------------
bool amf_app::read_amf_configuration(nlohmann::json& json_data) {
  amf_cfg.to_json(json_data);
  return true;
}

742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779
//---------------------------------------------------------------------------------------------
void amf_app::add_n1n2_message_subscription(
    const std::string& ue_ctx_id, const n1n2sub_id_t& sub_id,
    std::shared_ptr<oai::amf::model::UeN1N2InfoSubscriptionCreateData>&
        subscription_data) {
  Logger::amf_app().debug("Add an N1N2 Message Subscribe (Sub ID %d)", sub_id);
  std::unique_lock lock(m_n1n2_message_subscribe);
  n1n2_message_subscribe.emplace(
      std::make_pair(ue_ctx_id, sub_id), subscription_data);
}

//---------------------------------------------------------------------------------------------
bool amf_app::remove_n1n2_message_subscription(
    const std::string& ue_ctx_id, const std::string& sub_id) {
  Logger::amf_app().debug(
      "Remove an N1N2 Message Subscribe (UE Context ID %s, Sub ID %s)",
      ue_ctx_id.c_str(), sub_id.c_str());

  // Verify Subscription ID
  n1n2sub_id_t n1n2sub_id = {};
  try {
    n1n2sub_id = std::stoi(sub_id);
  } catch (const std::exception& err) {
    Logger::amf_app().warn(
        "Received a Unsubscribe Request, couldn't find the corresponding "
        "subscription");
    return false;
  }

  // Remove from the list
  std::unique_lock lock(m_n1n2_message_subscribe);
  if (n1n2_message_subscribe.erase(std::make_pair(ue_ctx_id, n1n2sub_id)) == 1)
    return true;
  else
    return false;
  return true;
}

780 781 782 783 784
//------------------------------------------------------------------------------
uint32_t amf_app::generate_tmsi() {
  return tmsi_generator.get_uid();
}

Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
785
//------------------------------------------------------------------------------
Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
786
bool amf_app::generate_5g_guti(
787 788
    const uint32_t ranid, const long amfid, string& mcc, string& mnc,
    uint32_t& tmsi) {
789 790
  string ue_context_key =
      "app_ue_ranid_" + to_string(ranid) + ":amfid_" + to_string(amfid);
Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
791
  if (!is_ran_amf_id_2_ue_context(ue_context_key)) {
Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
792 793
    Logger::amf_app().error(
        "No UE context for ran_amf_id %s, exit", ue_context_key.c_str());
Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
794 795
    return false;
  }
796 797 798 799 800 801
  std::shared_ptr<ue_context> uc = {};
  uc                             = ran_amf_id_2_ue_context(ue_context_key);
  mcc                            = uc.get()->tai.mcc;
  mnc                            = uc.get()->tai.mnc;
  tmsi                           = generate_tmsi();
  uc.get()->tmsi                 = tmsi;
Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
802
  return true;
Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
803
}
Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
804

805 806 807 808 809 810 811 812 813 814 815 816
//------------------------------------------------------------------------------
evsub_id_t amf_app::handle_event_exposure_subscription(
    std::shared_ptr<itti_sbi_event_exposure_request> msg) {
  Logger::amf_app().info(
      "Handle an Event Exposure Subscription Request from a NF (HTTP version "
      "%d)",
      msg->http_version);

  // Generate a subscription ID Id and store the corresponding information in a
  // map (subscription id, info)
  evsub_id_t evsub_id = generate_ev_subscription_id();

817 818 819
  std::vector<amf_event_t> event_subscriptions =
      msg->event_exposure.get_event_subs();

820
  // store subscription
821
  for (auto i : event_subscriptions) {
822 823 824 825 826 827 828 829 830 831 832 833
    std::shared_ptr<amf_subscription> ss = std::make_shared<amf_subscription>();
    ss.get()->sub_id                     = evsub_id;
    // TODO:
    if (msg->event_exposure.is_supi_is_set()) {
      ss.get()->supi        = msg->event_exposure.get_supi();
      ss.get()->supi_is_set = true;
    }
    ss.get()->notify_correlation_id =
        msg->event_exposure.get_notify_correlation_id();
    ss.get()->notify_uri = msg->event_exposure.get_notify_uri();
    ss.get()->nf_id      = msg->event_exposure.get_nf_id();
    ss.get()->ev_type    = i.type;
834
    add_event_subscription(evsub_id, i.type, ss);
835
    ss.get()->display();
836
  }
837 838 839
  return evsub_id;
}

840
//---------------------------------------------------------------------------------------------
841 842 843 844 845 846 847 848 849 850 851 852 853 854 855
bool amf_app::handle_event_exposure_delete(const std::string& subscription_id) {
  // verify Subscription ID
  evsub_id_t sub_id = {};
  try {
    sub_id = std::stoi(subscription_id);
  } catch (const std::exception& err) {
    Logger::amf_app().warn(
        "Received a Unsubscribe Request, couldn't find the corresponding "
        "subscription");
    return false;
  }

  return remove_event_subscription(sub_id);
}

856 857 858
//------------------------------------------------------------------------------
bool amf_app::handle_nf_status_notification(
    std::shared_ptr<itti_sbi_notification_data>& msg,
859
    oai::amf::model::ProblemDetails& problem_details, uint32_t& http_code) {
860 861 862 863 864
  Logger::amf_app().info(
      "Handle a NF status notification from NRF (HTTP version "
      "%d)",
      msg->http_version);
  // TODO
865
  http_code = 204;  // HTTP_STATUS_CODE_204_NO_CONTENT;
866 867 868
  return true;
}

Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
869 870 871 872 873
//------------------------------------------------------------------------------
void amf_app::generate_uuid() {
  amf_instance_id = to_string(boost::uuids::random_generator()());
}

874 875
//---------------------------------------------------------------------------------------------
void amf_app::add_event_subscription(
876
    const evsub_id_t& sub_id, const amf_event_type_t& ev,
877
    std::shared_ptr<amf_subscription> ss) {
878 879 880 881 882 883
  Logger::amf_app().debug(
      "Add an Event subscription (Sub ID %d, Event %d)", sub_id, (uint8_t) ev);
  std::unique_lock lock(m_amf_event_subscriptions);
  amf_event_subscriptions.emplace(std::make_pair(sub_id, ev), ss);
}

884
//---------------------------------------------------------------------------------------------
885
bool amf_app::remove_event_subscription(const evsub_id_t& sub_id) {
886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903
  Logger::amf_app().debug("Remove an Event subscription (Sub ID %d)", sub_id);
  std::unique_lock lock(m_amf_event_subscriptions);
  for (auto it = amf_event_subscriptions.cbegin();
       it != amf_event_subscriptions.cend();) {
    if ((uint8_t) std::get<0>(it->first) == (uint32_t) sub_id) {
      Logger::amf_app().debug(
          "Found an event subscription (Event ID %d)",
          (uint8_t) std::get<0>(it->first));
      amf_event_subscriptions.erase(it++);
      // it = amf_event_subscriptions.erase(it)
      return true;
    } else {
      ++it;
    }
  }
  return false;
}

904 905
//---------------------------------------------------------------------------------------------
void amf_app::get_ee_subscriptions(
906
    const amf_event_type_t& ev,
907 908 909 910 911 912 913 914 915 916 917 918 919
    std::vector<std::shared_ptr<amf_subscription>>& subscriptions) {
  for (auto const& i : amf_event_subscriptions) {
    if ((uint8_t) std::get<1>(i.first) == (uint8_t) ev) {
      Logger::amf_app().debug(
          "Found an event subscription (Event ID %d, Event %d)",
          (uint8_t) std::get<0>(i.first), (uint8_t) ev);
      subscriptions.push_back(i.second);
    }
  }
}

//---------------------------------------------------------------------------------------------
void amf_app::get_ee_subscriptions(
920
    const evsub_id_t& sub_id,
921 922 923 924 925 926 927 928 929 930
    std::vector<std::shared_ptr<amf_subscription>>& subscriptions) {
  for (auto const& i : amf_event_subscriptions) {
    if (i.first.first == sub_id) {
      subscriptions.push_back(i.second);
    }
  }
}

//---------------------------------------------------------------------------------------------
void amf_app::get_ee_subscriptions(
931
    const amf_event_type_t& ev, std::string& supi,
932 933 934 935 936 937 938 939
    std::vector<std::shared_ptr<amf_subscription>>& subscriptions) {
  for (auto const& i : amf_event_subscriptions) {
    if ((i.first.second == ev) && (i.second->supi == supi)) {
      subscriptions.push_back(i.second);
    }
  }
}

Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964
//---------------------------------------------------------------------------------------------
void amf_app::generate_amf_profile() {
  // generate UUID
  generate_uuid();
  nf_instance_profile.set_nf_instance_id(amf_instance_id);
  nf_instance_profile.set_nf_instance_name("OAI-AMF");
  nf_instance_profile.set_nf_type("AMF");
  nf_instance_profile.set_nf_status("REGISTERED");
  nf_instance_profile.set_nf_heartBeat_timer(50);
  nf_instance_profile.set_nf_priority(1);
  nf_instance_profile.set_nf_capacity(100);
  nf_instance_profile.add_nf_ipv4_addresses(amf_cfg.n11.addr4);

  // NF services
  nf_service_t nf_service        = {};
  nf_service.service_instance_id = "namf_communication";
  nf_service.service_name        = "namf_communication";
  nf_service_version_t version   = {};
  version.api_version_in_uri     = "v1";
  version.api_full_version       = "1.0.0";  // TODO: to be updated
  nf_service.versions.push_back(version);
  nf_service.scheme            = "http";
  nf_service.nf_service_status = "REGISTERED";
  // IP Endpoint
  ip_endpoint_t endpoint = {};
965 966 967
  endpoint.ipv4_address  = amf_cfg.n11.addr4;
  endpoint.transport     = "TCP";
  endpoint.port          = amf_cfg.n11.port;
Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991
  nf_service.ip_endpoints.push_back(endpoint);

  nf_instance_profile.add_nf_service(nf_service);

  // TODO: custom info
  // AMF info
  amf_info_t info    = {};
  info.amf_region_id = amf_cfg.guami.regionID;
  info.amf_set_id    = amf_cfg.guami.AmfSetID;
  for (auto g : amf_cfg.guami_list) {
    guami_5g_t guami = {};
    guami.amf_id =
        g.regionID + ":" + g.AmfSetID + ":" + g.AmfPointer;  // TODO verify??
    guami.plmn.mcc = g.mcc;
    guami.plmn.mnc = g.mnc;
    info.guami_list.push_back(guami);
  }

  nf_instance_profile.set_amf_info(info);

  // Display the profile
  nf_instance_profile.display();
}

992 993 994 995 996
//---------------------------------------------------------------------------------------------
std::string amf_app::get_nf_instance() const {
  return amf_instance_id;
}

Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011
//---------------------------------------------------------------------------------------------
void amf_app::register_to_nrf() {
  // send request to N11 to send NF registration to NRF
  trigger_nf_registration_request();
}

//------------------------------------------------------------------------------
void amf_app::trigger_nf_registration_request() {
  Logger::amf_app().debug(
      "Send ITTI msg to N11 task to trigger the registration request to NRF");

  std::shared_ptr<itti_n11_register_nf_instance_request> itti_msg =
      std::make_shared<itti_n11_register_nf_instance_request>(
          TASK_AMF_APP, TASK_AMF_N11);
  itti_msg->profile = nf_instance_profile;
1012 1013 1014 1015

  amf_n11_inst->register_nf_instance(itti_msg);
  /*

Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
1016 1017 1018 1019 1020 1021
  int ret           = itti_inst->send_msg(itti_msg);
  if (RETURNok != ret) {
    Logger::amf_app().error(
        "Could not send ITTI message %s to task TASK_AMF_N11",
        itti_msg->get_msg_name());
  }
1022
  */
Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
1023 1024 1025
}

//------------------------------------------------------------------------------
1026
void amf_app::trigger_nf_deregistration() const {
Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040
  Logger::amf_app().debug(
      "Send ITTI msg to N11 task to trigger the deregistration request to NRF");

  std::shared_ptr<itti_n11_deregister_nf_instance> itti_msg =
      std::make_shared<itti_n11_deregister_nf_instance>(
          TASK_AMF_APP, TASK_AMF_N11);
  itti_msg->amf_instance_id = amf_instance_id;
  int ret                   = itti_inst->send_msg(itti_msg);
  if (RETURNok != ret) {
    Logger::amf_app().error(
        "Could not send ITTI message %s to task TASK_AMF_N11",
        itti_msg->get_msg_name());
  }
}
1041

1042
//---------------------------------------------------------------------------------------------
1043
void amf_app::add_promise(
1044
    const uint32_t pid, const boost::shared_ptr<boost::promise<uint32_t>>& p) {
1045 1046 1047
  std::unique_lock lock(m_curl_handle_responses_smf);
  curl_handle_responses_smf.emplace(pid, p);
}
1048

1049 1050
//---------------------------------------------------------------------------------------------
void amf_app::add_promise(
1051 1052
    const uint32_t id,
    const boost::shared_ptr<boost::promise<std::string>>& p) {
1053 1054
  std::unique_lock lock(m_curl_handle_responses_n2_sm);
  curl_handle_responses_n2_sm.emplace(id, p);
1055 1056
}

1057 1058
//---------------------------------------------------------------------------------------------
void amf_app::add_promise(
1059 1060
    const uint32_t pid,
    const boost::shared_ptr<boost::promise<nlohmann::json>>& p) {
1061 1062 1063 1064
  std::unique_lock lock(m_curl_handle_responses_n11);
  curl_handle_responses_n11.emplace(pid, p);
}

1065
//---------------------------------------------------------------------------------------------
1066 1067
void amf_app::trigger_process_response(
    const uint32_t pid, const uint32_t http_code) {
1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078
  Logger::amf_app().debug(
      "Trigger process response: Set promise with ID %u "
      "to ready",
      pid);
  std::unique_lock lock(m_curl_handle_responses_smf);
  if (curl_handle_responses_smf.count(pid) > 0) {
    curl_handle_responses_smf[pid]->set_value(http_code);
    // Remove this promise from list
    curl_handle_responses_smf.erase(pid);
  }
}
1079

1080
//------------------------------------------------------------------------------
1081 1082
void amf_app::trigger_process_response(
    const uint32_t pid, const std::string& n2_sm) {
1083 1084 1085 1086
  Logger::amf_app().debug(
      "Trigger process response: Set promise with ID %u "
      "to ready",
      pid);
1087 1088 1089
  std::unique_lock lock(m_curl_handle_responses_n2_sm);
  if (curl_handle_responses_n2_sm.count(pid) > 0) {
    curl_handle_responses_n2_sm[pid]->set_value(n2_sm);
1090
    // Remove this promise from list
1091
    curl_handle_responses_n2_sm.erase(pid);
1092 1093
  }
}
1094 1095 1096

//------------------------------------------------------------------------------
void amf_app::trigger_process_response(
1097
    const uint32_t pid, const nlohmann::json& json_data) {
1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108
  Logger::amf_app().debug(
      "Trigger process response: Set promise with ID %u "
      "to ready",
      pid);
  std::unique_lock lock(m_curl_handle_responses_n11);
  if (curl_handle_responses_n11.count(pid) > 0) {
    curl_handle_responses_n11[pid]->set_value(json_data);
    // Remove this promise from list
    curl_handle_responses_n11.erase(pid);
  }
}