smf_app.cpp 75.4 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
Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
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
9
10
11
12
13
14
15
16
17
18
19
20
21
22
 *
 *      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 smf_app.cpp
23
24
25
26
27
 \brief
 \author  Lionel GAUTHIER, Tien-Thinh NGUYEN
 \company Eurecom
 \date 2019
 \email: lionel.gauthier@eurecom.fr, tien-thinh.nguyen@eurecom.fr
28
 */
29

30
#include "smf_app.hpp"
31

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

Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
38
39
40
41
#include "3gpp_24.007.h"
#include "3gpp_24.501.h"
#include "3gpp_29.500.h"
#include "3gpp_29.502.h"
Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
42
#include "3gpp_conversions.hpp"
Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
43
44
45
46
47
48
#include "ProblemDetails.h"
#include "RefToBinaryData.h"
#include "SmContextCreateError.h"
#include "SmContextCreatedData.h"
#include "SmContextMessage.h"
#include "SmContextUpdateError.h"
49
50
51
52
#include "async_shell_cmd.hpp"
#include "common_defs.h"
#include "conversions.hpp"
#include "itti.hpp"
Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
53
#include "itti_msg_nx.hpp"
54
#include "logger.hpp"
Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
55
#include "pfcp.hpp"
56
#include "smf.h"
Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
57
#include "smf_event.hpp"
58
#include "smf_n1.hpp"
59
60
#include "smf_n10.hpp"
#include "smf_n11.hpp"
Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
61
62
63
#include "smf_n4.hpp"
#include "smf_paa_dynamic.hpp"
#include "string.hpp"
64

65
extern "C" {
66
#include "dynamic_memory_check.h"
Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
67
#include "nas_message.h"
68
69
70
71
}

using namespace smf;

72
73
extern util::async_shell_cmd* async_shell_cmd_inst;
extern smf_app* smf_app_inst;
74
extern smf_config smf_cfg;
75
76
77
78
smf_n4* smf_n4_inst   = nullptr;
smf_n10* smf_n10_inst = nullptr;
smf_n11* smf_n11_inst = nullptr;
extern itti_mw* itti_inst;
79

80
void smf_app_task(void*);
81
82

//------------------------------------------------------------------------------
83
int smf_app::apply_config(const smf_config& cfg) {
84
85
  Logger::smf_app().info("Apply config...");

86
87
88
  for (int ia = 0; ia < cfg.num_dnn; ia++) {
    if (cfg.dnn[ia].pool_id_iv4 >= 0) {
      int pool_id = cfg.dnn[ia].pool_id_iv4;
89
      int range   = be32toh(cfg.ue_pool_range_high[pool_id].s_addr) -
Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
90
91
92
93
                  be32toh(cfg.ue_pool_range_low[pool_id].s_addr);
      paa_dynamic::get_instance().add_pool(
          cfg.dnn[ia].dnn, pool_id, cfg.ue_pool_range_low[pool_id], range);
      // TODO: check with dnn_label
94
      Logger::smf_app().info("Applied config %s", cfg.dnn[ia].dnn.c_str());
95
    }
96
97
    if (cfg.dnn[ia].pool_id_iv6 >= 0) {
      int pool_id = cfg.dnn[ia].pool_id_iv6;
98
99
100
      paa_dynamic::get_instance().add_pool(
          cfg.dnn[ia].dnn, pool_id, cfg.paa_pool6_prefix[pool_id],
          cfg.paa_pool6_prefix_len[pool_id]);
Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
101
      // TODO: check with dnn_label
102
103
104
105
    }
  }

  Logger::smf_app().info("Applied config");
Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
106
  return RETURNok;
107
108
109
110
111
}

//------------------------------------------------------------------------------
uint64_t smf_app::generate_seid() {
  std::unique_lock<std::mutex> ls(m_seid_n4_generator);
112
  uint64_t seid = ++seid_n4_generator;
113
  while ((is_seid_n4_exist(seid)) || (seid == UNASSIGNED_SEID)) {
114
    seid = ++seid_n4_generator;
115
116
117
118
119
120
  }
  set_seid_n4.insert(seid);
  ls.unlock();
  return seid;
}

121
//------------------------------------------------------------------------------
122
void smf_app::generate_smf_context_ref(std::string& smf_ref) {
123
124
125
126
  smf_ref = std::to_string(sm_context_ref_generator.get_uid());
}

//------------------------------------------------------------------------------
127
scid_t smf_app::generate_smf_context_ref() {
128
129
130
  return sm_context_ref_generator.get_uid();
}

131
//------------------------------------------------------------------------------
132
void smf_app::generate_ev_subscription_id(std::string& sub_id) {
133
134
135
136
137
138
139
140
  sub_id = std::to_string(evsub_id_generator.get_uid());
}

//------------------------------------------------------------------------------
evsub_id_t smf_app::generate_ev_subscription_id() {
  return evsub_id_generator.get_uid();
}

141
//------------------------------------------------------------------------------
142
bool smf_app::is_seid_n4_exist(const uint64_t& seid) const {
Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
143
  return bool{set_seid_n4.count(seid) > 0};
144
145
146
}

//------------------------------------------------------------------------------
147
void smf_app::free_seid_n4(const uint64_t& seid) {
148
  std::unique_lock<std::mutex> ls(m_seid_n4_generator);
149
  set_seid_n4.erase(seid);
150
  ls.unlock();
151
152
153
}

//------------------------------------------------------------------------------
154
155
void smf_app::set_seid_2_smf_context(
    const seid_t& seid, std::shared_ptr<smf_context>& pc) {
156
157
158
159
160
  std::unique_lock lock(m_seid2smf_context);
  seid2smf_context[seid] = pc;
}

//------------------------------------------------------------------------------
161
162
bool smf_app::seid_2_smf_context(
    const seid_t& seid, std::shared_ptr<smf_context>& pc) const {
163
  std::shared_lock lock(m_seid2smf_context);
Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
164
165
  std::map<seid_t, std::shared_ptr<smf_context>>::const_iterator it =
      seid2smf_context.find(seid);
166
167
168
169
170
171
172
173
  if (it != seid2smf_context.end()) {
    pc = it->second;
    return true;
  }
  return false;
}

//------------------------------------------------------------------------------
174
void smf_app::delete_smf_context(std::shared_ptr<smf_context> spc) {
175
  supi64_t supi64 = smf_supi_to_u64(spc.get()->get_supi());
176
177
178
179
180
  std::unique_lock lock(m_supi2smf_context);
  supi2smf_context.erase(supi64);
}

//------------------------------------------------------------------------------
181
void smf_app::restore_n4_sessions(const seid_t& seid) const {
182
  std::shared_lock lock(m_seid2smf_context);
Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
183
  // TODO
184
185
186
}

//------------------------------------------------------------------------------
187
void smf_app_task(void*) {
188
189
190
191
192
  const task_id_t task_id = TASK_SMF_APP;
  itti_inst->notify_task_ready(task_id);

  do {
    std::shared_ptr<itti_msg> shared_msg = itti_inst->receive_msg(task_id);
193
    auto* msg                            = shared_msg.get();
194
    switch (msg->msg_type) {
195
      case N4_SESSION_ESTABLISHMENT_RESPONSE:
196
197
        if (itti_n4_session_establishment_response* m =
                dynamic_cast<itti_n4_session_establishment_response*>(msg)) {
198
199
200
          smf_app_inst->handle_itti_msg(std::ref(*m));
        }
        break;
201

202
      case N4_SESSION_MODIFICATION_RESPONSE:
203
204
        if (itti_n4_session_modification_response* m =
                dynamic_cast<itti_n4_session_modification_response*>(msg)) {
205
206
207
          smf_app_inst->handle_itti_msg(std::ref(*m));
        }
        break;
208

209
      case N4_SESSION_DELETION_RESPONSE:
210
211
        if (itti_n4_session_deletion_response* m =
                dynamic_cast<itti_n4_session_deletion_response*>(msg)) {
212
213
214
          smf_app_inst->handle_itti_msg(std::ref(*m));
        }
        break;
215

216
      case N11_SESSION_N1N2_MESSAGE_TRANSFER_RESPONSE_STATUS:
217
218
        if (itti_n11_n1n2_message_transfer_response_status* m =
                dynamic_cast<itti_n11_n1n2_message_transfer_response_status*>(
Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
219
                    msg)) {
220
221
222
          smf_app_inst->handle_itti_msg(std::ref(*m));
        }
        break;
223

224
      case N11_SESSION_UPDATE_PDU_SESSION_STATUS:
225
226
        if (itti_n11_update_pdu_session_status* m =
                dynamic_cast<itti_n11_update_pdu_session_status*>(msg)) {
227
228
229
230
231
          smf_app_inst->handle_itti_msg(std::ref(*m));
        }
        break;

      case N4_SESSION_REPORT_REQUEST:
Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
232
233
234
        smf_app_inst->handle_itti_msg(
            std::static_pointer_cast<itti_n4_session_report_request>(
                shared_msg));
235
236
        break;

237
      case N11_SESSION_CREATE_SM_CONTEXT_RESPONSE:
238
239
        if (itti_n11_create_sm_context_response* m =
                dynamic_cast<itti_n11_create_sm_context_response*>(msg)) {
240
241
242
243
244
          smf_app_inst->handle_itti_msg(std::ref(*m));
        }
        break;

      case N11_SESSION_UPDATE_SM_CONTEXT_RESPONSE:
245
246
        if (itti_n11_update_sm_context_response* m =
                dynamic_cast<itti_n11_update_sm_context_response*>(msg)) {
247
248
249
250
251
          smf_app_inst->handle_itti_msg(std::ref(*m));
        }
        break;

      case N11_SESSION_RELEASE_SM_CONTEXT_RESPONSE:
252
253
        if (itti_n11_release_sm_context_response* m =
                dynamic_cast<itti_n11_release_sm_context_response*>(msg)) {
254
255
256
257
          smf_app_inst->handle_itti_msg(std::ref(*m));
        }
        break;

258
      case N11_REGISTER_NF_INSTANCE_RESPONSE:
259
260
        if (itti_n11_register_nf_instance_response* m =
                dynamic_cast<itti_n11_register_nf_instance_response*>(msg)) {
261
262
263
264
          smf_app_inst->handle_itti_msg(std::ref(*m));
        }
        break;

265
      case N11_UPDATE_NF_INSTANCE_RESPONSE:
266
267
        if (itti_n11_update_nf_instance_response* m =
                dynamic_cast<itti_n11_update_nf_instance_response*>(msg)) {
268
269
270
271
          smf_app_inst->handle_itti_msg(std::ref(*m));
        }
        break;

272
      case TIME_OUT:
273
        if (itti_msg_timeout* to = dynamic_cast<itti_msg_timeout*>(msg)) {
274
275
276
277
278
          Logger::smf_app().info("TIME-OUT event timer id %d", to->timer_id);
          switch (to->arg1_user) {
            case TASK_SMF_APP_TRIGGER_T3591:
              smf_app_inst->timer_t3591_timeout(to->timer_id, to->arg2_user);
              break;
279
            case TASK_SMF_APP_TIMEOUT_NRF_HEARTBEAT:
280
281
              smf_app_inst->timer_nrf_heartbeat_timeout(
                  to->timer_id, to->arg2_user);
282
              break;
Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
283
            case TASK_SMF_APP_TIMEOUT_NRF_DEREGISTRATION:
284
285
              smf_app_inst->timer_nrf_deregistration(
                  to->timer_id, to->arg2_user);
Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
286
              break;
Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
287
            default:;
288
          }
289
        }
290
        break;
291

292
      case TERMINATE:
293
294
        if (itti_msg_terminate* terminate =
                dynamic_cast<itti_msg_terminate*>(msg)) {
295
296
297
          Logger::smf_app().info("Received terminate message");
          return;
        }
298
299
        break;

300
301
      case HEALTH_PING:
        break;
302

303
304
      default:
        Logger::smf_app().info("no handler for msg type %d", msg->msg_type);
305
306
307
308
309
    }
  } while (true);
}

//------------------------------------------------------------------------------
310
smf_app::smf_app(const std::string& config_file)
Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
311
312
313
314
315
316
    : m_seid2smf_context(),
      m_supi2smf_context(),
      m_scid2smf_context(),
      m_sm_context_create_promises(),
      m_sm_context_update_promises(),
      m_sm_context_release_promises() {
317
318
  Logger::smf_app().startup("Starting...");

319
320
  supi2smf_context  = {};
  set_seid_n4       = {};
321
  seid_n4_generator = 0;
322

323
  apply_config(smf_cfg);
324

325
326
327
  if (itti_inst->create_task(TASK_SMF_APP, smf_app_task, nullptr)) {
    Logger::smf_app().error("Cannot create task TASK_SMF_APP");
    throw std::runtime_error("Cannot create task TASK_SMF_APP");
328
329
330
  }

  try {
331
    smf_n4_inst  = new smf_n4();
332
333
    smf_n10_inst = new smf_n10();
    smf_n11_inst = new smf_n11();
334
  } catch (std::exception& e) {
335
    Logger::smf_app().error("Cannot create SMF_APP: %s", e.what());
336
337
338
    throw;
  }

Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
339
340
  // TODO: should be done when SMF select UPF for a particular UE (should be
  // verified)
Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
341
  for (std::vector<pfcp::node_id_t>::const_iterator it = smf_cfg.upfs.begin();
Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
342
       it != smf_cfg.upfs.end(); ++it) {
343
344
345
    start_upf_association(*it);
  }

346
  // Register to NRF
347
  register_to_nrf();
348
349
350
351
  // Trigger NFStatusNotify
  unsigned int microsecond = 10000;  // 10ms
  usleep(microsecond);
  trigger_upf_status_notification_subscribe();
352

353
  Logger::smf_app().startup("Started");
354
355
}

356
//------------------------------------------------------------------------------
357
void smf_app::start_upf_association(const pfcp::node_id_t& node_id) {
358
  std::time_t time_epoch = std::time(nullptr);
359
  uint64_t tv_ntp        = time_epoch + SECONDS_SINCE_FIRST_EPOCH;
360
361

  pfcp_associations::get_instance().add_peer_candidate_node(node_id);
Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
362
363
364
  std::shared_ptr<itti_n4_association_setup_request> n4_asc =
      std::shared_ptr<itti_n4_association_setup_request>(
          new itti_n4_association_setup_request(TASK_SMF_APP, TASK_SMF_N4));
365

Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
366
  // n4_asc->trxn_id = smf_n4_inst->generate_trxn_id();
367
  pfcp::cp_function_features_s cp_function_features;
368
  cp_function_features      = {};
369
370
371
  cp_function_features.load = 1;
  cp_function_features.ovrl = 1;

Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
372
  pfcp::node_id_t this_node_id = {};
373
374
  if (smf_cfg.get_pfcp_node_id(this_node_id) == RETURNok) {
    n4_asc->pfcp_ies.set(this_node_id);
375
    pfcp::recovery_time_stamp_t r = {.recovery_time_stamp = (uint32_t) tv_ntp};
376
377
378
379
    n4_asc->pfcp_ies.set(r);

    n4_asc->pfcp_ies.set(cp_function_features);
    if (node_id.node_id_type == pfcp::NODE_ID_TYPE_IPV4_ADDRESS) {
Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
380
381
      n4_asc->r_endpoint =
          endpoint(node_id.u1.ipv4_address, pfcp::default_port);
382
383
      int ret = itti_inst->send_msg(n4_asc);
      if (RETURNok != ret) {
Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
384
385
386
        Logger::smf_app().error(
            "Could not send ITTI message %s to task TASK_SMF_N4",
            n4_asc.get()->get_msg_name());
387
388
      }
    } else {
Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
389
      Logger::smf_app().warn("Start_association() node_id IPV6, FQDN!");
390
391
392
393
    }
  }
}

394
//------------------------------------------------------------------------------
395
void smf_app::handle_itti_msg(itti_n4_session_establishment_response& seresp) {
Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
396
  std::shared_ptr<smf_context> pc = {};
397
398
399
  if (seid_2_smf_context(seresp.seid, pc)) {
    pc.get()->handle_itti_msg(seresp);
  } else {
Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
400
    Logger::smf_app().debug(
Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
401
402
        "Received N4 Session Establishment Response seid" TEID_FMT
        "  pfcp_tx_id %" PRIX64 ", smf_context not found, discarded!",
Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
403
        seresp.seid, seresp.trxn_id);
404
405
406
407
  }
}

//------------------------------------------------------------------------------
408
void smf_app::handle_itti_msg(itti_n4_session_modification_response& smresp) {
Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
409
  std::shared_ptr<smf_context> pc = {};
410
411
412
  if (seid_2_smf_context(smresp.seid, pc)) {
    pc.get()->handle_itti_msg(smresp);
  } else {
Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
413
    Logger::smf_app().debug(
Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
414
415
        "Received N4 Session Modification Response seid" TEID_FMT
        "  pfcp_tx_id %" PRIX64 ", smf_context not found, discarded!",
Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
416
        smresp.seid, smresp.trxn_id);
417
418
419
420
  }
}

//------------------------------------------------------------------------------
421
void smf_app::handle_itti_msg(itti_n4_session_deletion_response& smresp) {
Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
422
  std::shared_ptr<smf_context> pc = {};
423
424
425
  if (seid_2_smf_context(smresp.seid, pc)) {
    pc.get()->handle_itti_msg(smresp);

426
    if (pc->get_number_dnn_contexts() == 0) {
427
428
429
      delete_smf_context(pc);
    }
  } else {
Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
430
    Logger::smf_app().debug(
Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
431
432
        "Received N4 Session Deletion Response seid" TEID_FMT
        "  pfcp_tx_id %" PRIX64 ", smf_context not found, discarded!",
Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
433
        smresp.seid, smresp.trxn_id);
434
435
436
437
  }
}

//------------------------------------------------------------------------------
Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
438
439
void smf_app::handle_itti_msg(
    std::shared_ptr<itti_n4_session_report_request> snr) {
Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
440
  std::shared_ptr<smf_context> pc = {};
441
442
443
  if (seid_2_smf_context(snr->seid, pc)) {
    pc.get()->handle_itti_msg(snr);
  } else {
444
445
446
447
    Logger::smf_app().debug(
        "Received N4 Session Report Request seid" TEID_FMT
        "  pfcp_tx_id %" PRIX64 ", smf_context not found, discarded!",
        snr->seid, snr->trxn_id);
448
449
450
  }
}

451
//------------------------------------------------------------------------------
Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
452
void smf_app::handle_itti_msg(
453
    itti_n11_n1n2_message_transfer_response_status& m) {
454
  Logger::smf_app().info("Process N1N2MessageTransfer Response");
455
456

  switch (m.procedure_type) {
Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
457
458
459
    case session_management_procedures_type_e::
        PDU_SESSION_ESTABLISHMENT_UE_REQUESTED: {
      // Update PDU Session accordingly
Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
460
      Logger::smf_app().info("PDU_SESSION_ESTABLISHMENT_UE_REQUESTED");
Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
461
462
463
464
465
466
467
468
      pdu_session_status_e status = {
          pdu_session_status_e::PDU_SESSION_INACTIVE};
      upCnx_state_e state = {upCnx_state_e::UPCNX_STATE_DEACTIVATED};

      if ((static_cast<http_response_codes_e>(m.response_code) ==
           http_response_codes_e::HTTP_RESPONSE_CODE_OK) or
          (static_cast<http_response_codes_e>(m.response_code) ==
           http_response_codes_e::HTTP_RESPONSE_CODE_ACCEPTED)) {
469
470
471
472
        if (m.msg_type == PDU_SESSION_ESTABLISHMENT_REJECT) {
          status = pdu_session_status_e::PDU_SESSION_INACTIVE;
        } else if (m.msg_type == PDU_SESSION_ESTABLISHMENT_ACCEPT) {
          status = pdu_session_status_e::PDU_SESSION_ESTABLISHMENT_PENDING;
473
          state  = upCnx_state_e::UPCNX_STATE_ACTIVATING;
474
475
476
477
        }
        update_pdu_session_status(m.scid, status);
        update_pdu_session_upCnx_state(m.scid, state);
        Logger::smf_app().debug(
Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
478
479
            "Got successful response from AMF (response code %d), set session "
            "status to %s",
480
            m.response_code,
481
            pdu_session_status_e2str.at(static_cast<int>(status)).c_str());
482
      } else {
Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
483
        // TODO:
484
485
        Logger::smf_app().debug(
            "Got response from AMF (response code %d)", m.response_code);
486
      }
Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
487
    } break;
Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
488

Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
489
490
    case session_management_procedures_type_e::
        SERVICE_REQUEST_NETWORK_TRIGGERED: {
491
492
493
      Logger::smf_app().debug(
          "Got response from AMF (response code %d) with cause %s",
          m.response_code, m.cause.c_str());
Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
494
495
496
497
      if ((static_cast<http_response_codes_e>(m.response_code) !=
           http_response_codes_e::HTTP_RESPONSE_CODE_OK) and
          (static_cast<http_response_codes_e>(m.response_code) !=
           http_response_codes_e::HTTP_RESPONSE_CODE_ACCEPTED)) {
498
        Logger::smf_app().debug("Send failure indication to UPF");
Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
499
500
        // TODO: to be completed
        pfcp::node_id_t up_node_id = {};
501
        if (not pfcp_associations::get_instance().select_up_node(
Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
502
                up_node_id, NODE_SELECTION_CRITERIA_MIN_PFCP_SESSIONS)) {
503
504
505
506
          Logger::smf_app().info("REMOTE_PEER_NOT_RESPONDING");
          return;
        }

507
        itti_n4_session_failure_indication* itti_n4 =
508
            new itti_n4_session_failure_indication(TASK_SMF_APP, TASK_SMF_N4);
509
        itti_n4->seid    = m.seid;
510
        itti_n4->trxn_id = m.trxn_id;
Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
511
512
513
514
515
        itti_n4->r_endpoint =
            endpoint(up_node_id.u1.ipv4_address, pfcp::default_port);
        std::shared_ptr<itti_n4_session_failure_indication>
            itti_n4_failure_indication =
                std::shared_ptr<itti_n4_session_failure_indication>(itti_n4);
516

517
518
519
        Logger::smf_app().info(
            "Sending ITTI message %s to task TASK_SMF_N4",
            itti_n4->get_msg_name());
520
521
522
523
524
525
526
        int ret = itti_inst->send_msg(itti_n4_failure_indication);
        if (RETURNok != ret) {
          Logger::smf_app().error(
              "Could not send ITTI message %s to task TASK_SMF_N4",
              itti_n4->get_msg_name());
          return;
        }
527
      }
Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
528
    } break;
Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
529

530
    default: {
Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
531
      Logger::smf_app().warn("Unknown procedure type %d", m.procedure_type);
532
533
534
535
536
    }
  }
}

//------------------------------------------------------------------------------
537
void smf_app::handle_itti_msg(itti_n11_update_pdu_session_status& m) {
Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
538
539
  Logger::smf_app().info(
      "Set PDU Session Status to %s",
540
541
      pdu_session_status_e2str.at(static_cast<int>(m.pdu_session_status))
          .c_str());
542
543
544
  update_pdu_session_status(m.scid, m.pdu_session_status);
}

545
//------------------------------------------------------------------------------
546
void smf_app::handle_itti_msg(itti_n11_create_sm_context_response& m) {
547
548
  Logger::smf_app().debug(
      "PDU Session Create SM Context: Set promise with ID %d to ready", m.pid);
Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
549
  pdu_session_create_sm_context_response sm_context_response = {};
550
  std::unique_lock lock(m_sm_context_create_promises);
Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
551
  if (sm_context_create_promises.count(m.pid) > 0) {
552
    sm_context_create_promises[m.pid]->set_value(m.res);
Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
553
    // Remove this promise from list
554
555
    sm_context_create_promises.erase(m.pid);
  }
556
557
558
}

//------------------------------------------------------------------------------
559
void smf_app::handle_itti_msg(itti_n11_update_sm_context_response& m) {
560
561
  Logger::smf_app().debug(
      "PDU Session Update SM Context: Set promise with ID %d to ready", m.pid);
Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
562
  pdu_session_update_sm_context_response sm_context_response = {};
563
  std::unique_lock lock(m_sm_context_update_promises);
Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
564
  if (sm_context_update_promises.count(m.pid) > 0) {
565
    sm_context_update_promises[m.pid]->set_value(m.res);
Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
566
    // Remove this promise from list
567
568
    sm_context_update_promises.erase(m.pid);
  }
569
570
571
}

//------------------------------------------------------------------------------
572
void smf_app::handle_itti_msg(itti_n11_release_sm_context_response& m) {
573
574
  Logger::smf_app().debug(
      "PDU Session Release SM Context: Set promise with ID %d to ready", m.pid);
Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
575
  pdu_session_release_sm_context_response sm_context_response = {};
576
  std::unique_lock lock(m_sm_context_release_promises);
Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
577
  if (sm_context_release_promises.count(m.pid) > 0) {
578
    sm_context_release_promises[m.pid]->set_value(m.res);
Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
579
    // Remove this promise from list
580
581
    sm_context_release_promises.erase(m.pid);
  }
582
583
}

584
//------------------------------------------------------------------------------
585
void smf_app::handle_itti_msg(itti_n11_register_nf_instance_response& r) {
586
  Logger::smf_app().debug("Handle NF Instance Registration response");
587

588
  nf_instance_profile = r.profile;
589
  // Set heartbeat timer
590
  Logger::smf_app().debug(
Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
591
592
      "Set value of NRF Heartbeat timer to %d",
      r.profile.get_nf_heartBeat_timer());
593
594
595
596
  timer_nrf_heartbeat = itti_inst->timer_setup(
      r.profile.get_nf_heartBeat_timer(), 0, TASK_SMF_APP,
      TASK_SMF_APP_TIMEOUT_NRF_HEARTBEAT,
      0);  // TODO arg2_user
Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
597

Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
598
599
600
601
602
  /*  //Set timer to send NF Deregistration (for testing purpose)
    itti_inst->timer_setup(50, 0,
                               TASK_SMF_APP,
    TASK_SMF_APP_TIMEOUT_NRF_DEREGISTRATION, 0);  // TODO arg2_user
  */
603
604
605
}

//------------------------------------------------------------------------------
606
void smf_app::handle_itti_msg(itti_n11_update_nf_instance_response& u) {
607
608
  Logger::smf_app().debug("NF Update NF response");

609
610
611
  Logger::smf_app().debug(
      "Set NRF Heartbeat timer (%d)",
      nf_instance_profile.get_nf_heartBeat_timer());
612
613
614

  // Set heartbeat timer
  //  timer_nrf_heartbeat = itti_inst->timer_setup(
615
  //      nf_instance_profile.get_nf_heartBeat_timer(), 0, TASK_SMF_APP,
616
  //      TASK_SMF_APP_TIMEOUT_NRF_HEARTBEAT, 0); //TODO arg2_user
617
}
618

619
//------------------------------------------------------------------------------
Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
620
621
622
void smf_app::handle_pdu_session_create_sm_context_request(
    std::shared_ptr<itti_n11_create_sm_context_request> smreq) {
  Logger::smf_app().info(
Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
623
624
      "Handle a PDU Session Create SM Context Request from an AMF (HTTP "
      "version %d)",
625
      smreq->http_version);
Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
626
627
  // handle PDU Session Create SM Context Request as specified in section 4.3.2
  // 3GPP TS 23.502
628
  std::string n1_sm_message, n1_sm_message_hex;
629
630
  nas_message_t decoded_nas_msg       = {};
  cause_value_5gsm_e cause_n1         = {cause_value_5gsm_e::CAUSE_0_UNKNOWN};
Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
631
632
  pdu_session_type_t pdu_session_type = {.pdu_session_type =
                                             PDU_SESSION_TYPE_E_IPV4};
633

Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
634
  // Step 1. Decode NAS and get the necessary information
Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
635
  // std::string n1_sm_msg = smreq->req.get_n1_sm_message();
636

Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
637
638
  int decoder_rc = smf_n1::get_instance().decode_n1_sm_container(
      decoded_nas_msg, smreq->req.get_n1_sm_message());
Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
639

Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
640
  // Failed to decode, send reply to AMF with PDU Session Establishment Reject
641
  if (decoder_rc != RETURNok) {
642
    Logger::smf_app().warn("N1 SM container cannot be decoded correctly!");
Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
643

Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
644
    if (smf_n1::get_instance().create_n1_pdu_session_establishment_reject(
Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
645
646
            smreq->req, n1_sm_message,
            cause_value_5gsm_e::CAUSE_95_SEMANTICALLY_INCORRECT_MESSAGE)) {
647
      smf_app_inst->convert_string_2_hex(n1_sm_message, n1_sm_message_hex);
Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
648
649
650
651
652
      // trigger to send reply to AMF
      trigger_create_context_error_response(
          http_status_code_e::HTTP_STATUS_CODE_403_FORBIDDEN,
          PDU_SESSION_APPLICATION_ERROR_N1_SM_ERROR, n1_sm_message_hex,
          smreq->pid);
653
    } else {
Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
654
      // trigger to send reply to AMF
655
656
657
658
      trigger_http_response(
          http_status_code_e::HTTP_STATUS_CODE_500_INTERNAL_SERVER_ERROR,
          smreq->pid, N11_SESSION_CREATE_SM_CONTEXT_RESPONSE);
    }
659
    return;
660
  }
661

Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
662
663
  // Get necessary info from NAS
  xgpp_conv::sm_context_request_from_nas(decoded_nas_msg, smreq->req);
664

Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
665
  // TODO: Support IPv4 only for now
666
667
  if (pdu_session_type.pdu_session_type == PDU_SESSION_TYPE_E_IPV6) {
    cause_n1 = cause_value_5gsm_e::CAUSE_50_PDU_SESSION_TYPE_IPV4_ONLY_ALLOWED;
668
669
670
  } else if (
      (pdu_session_type.pdu_session_type == PDU_SESSION_TYPE_E_ETHERNET) or
      (pdu_session_type.pdu_session_type == PDU_SESSION_TYPE_E_UNSTRUCTURED)) {
671
672
673
    cause_n1 = cause_value_5gsm_e::CAUSE_28_UNKNOWN_PDU_SESSION_TYPE;
  }
  if (pdu_session_type.pdu_session_type != PDU_SESSION_TYPE_E_IPV4) {
Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
674
675
676
    // PDU Session Establishment Reject
    if (smf_n1::get_instance().create_n1_pdu_session_establishment_reject(
            smreq->req, n1_sm_message, cause_n1)) {
677
      smf_app_inst->convert_string_2_hex(n1_sm_message, n1_sm_message_hex);
Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
678
679
680
681
682
      // trigger to send reply to AMF
      trigger_create_context_error_response(
          http_status_code_e::HTTP_STATUS_CODE_403_FORBIDDEN,
          PDU_SESSION_APPLICATION_ERROR_PDUTYPE_DENIED, n1_sm_message_hex,
          smreq->pid);
683
684
685
686
687
    } else {
      trigger_http_response(
          http_status_code_e::HTTP_STATUS_CODE_500_INTERNAL_SERVER_ERROR,
          smreq->pid, N11_SESSION_CREATE_SM_CONTEXT_RESPONSE);
    }
688
    return;
689
690
  }

Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
691
692
693
694
695
  // Get SUPI, SNSSAI
  supi_t supi             = smreq->req.get_supi();
  std::string supi_prefix = smreq->req.get_supi_prefix();
  supi64_t supi64         = smf_supi_to_u64(supi);
  snssai_t snssai         = smreq->req.get_snssai();
Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
696
  Logger::smf_app().info(
Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
697
      "Handle a PDU Session Create SM Context Request message from AMF, "
Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
698
699
      "SUPI " SUPI_64_FMT ", SNSSAI SST %d, SD %s",
      supi64, snssai.sST, snssai.sD.c_str());
700

Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
701
  // Step 2. Verify Procedure transaction id, pdu session id, message type,
Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
702
703
704
705
706
  // request type, etc.
  // Check PTI
  procedure_transaction_id_t pti = {
      .procedure_transaction_id =
          decoded_nas_msg.plain.sm.header.procedure_transaction_identity};
Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
707
708
709
  if ((pti.procedure_transaction_id ==
       PROCEDURE_TRANSACTION_IDENTITY_UNASSIGNED) ||
      (pti.procedure_transaction_id > PROCEDURE_TRANSACTION_IDENTITY_LAST)) {
710
711
    Logger::smf_app().warn(
        "Invalid PTI value (pti = %d)", pti.procedure_transaction_id);
Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
712
713
    // PDU Session Establishment Reject including cause "#81 Invalid PTI value"
    // (section 7.3.1 @3GPP TS 24.501)
Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
714
    if (smf_n1::get_instance().create_n1_pdu_session_establishment_reject(
Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
715
716
            smreq->req, n1_sm_message,
            cause_value_5gsm_e::CAUSE_81_INVALID_PTI_VALUE)) {
717
      smf_app_inst->convert_string_2_hex(n1_sm_message, n1_sm_message_hex);
Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
718
719
720
721
722
      // trigger to send reply to AMF
      trigger_create_context_error_response(
          http_status_code_e::HTTP_STATUS_CODE_403_FORBIDDEN,
          PDU_SESSION_APPLICATION_ERROR_N1_SM_ERROR, n1_sm_message_hex,
          smreq->pid);
723
724
725
726
727
    } else {
      trigger_http_response(
          http_status_code_e::HTTP_STATUS_CODE_500_INTERNAL_SERVER_ERROR,
          smreq->pid, N11_SESSION_CREATE_SM_CONTEXT_RESPONSE);
    }
728
    return;
729
  }
730

Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
731
732
733
  // Check pdu session id
  pdu_session_id_t pdu_session_id =
      decoded_nas_msg.plain.sm.header.pdu_session_identity;
Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
734
735
  if ((pdu_session_id == PDU_SESSION_IDENTITY_UNASSIGNED) ||
      (pdu_session_id > PDU_SESSION_IDENTITY_LAST)) {
Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
736
    Logger::smf_app().warn("Invalid PDU Session ID value (%d)", pdu_session_id);
Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
737
738
    // section 7.3.2@3GPP TS 24.501; NAS N1 SM message: ignore the message
    // trigger to send reply to AMF
739
740
741
    trigger_http_response(
        http_status_code_e::HTTP_STATUS_CODE_406_NOT_ACCEPTABLE, smreq->pid,
        N11_SESSION_CREATE_SM_CONTEXT_RESPONSE);
742
    return;
743
744
  }

Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
745
746
  // Check message type
  uint8_t message_type = decoded_nas_msg.plain.sm.header.message_type;
747
  if (message_type != PDU_SESSION_ESTABLISHMENT_REQUEST) {
748
749
    Logger::smf_app().warn(
        "Invalid message type (message type = %d)", message_type);
Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
750
751
752
753
    // PDU Session Establishment Reject
    //(24.501 (section 7.4)) implementation dependent->do similar to UE:
    // response with a 5GSM STATUS message including cause "#98 message type not
    // compatible with protocol state."
Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
754
    if (smf_n1::get_instance().create_n1_pdu_session_establishment_reject(
Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
755
756
757
            smreq->req, n1_sm_message,
            cause_value_5gsm_e::
                CAUSE_98_MESSAGE_TYPE_NOT_COMPATIBLE_WITH_PROTOCOL_STATE)) {
758
      smf_app_inst->convert_string_2_hex(n1_sm_message, n1_sm_message_hex);
Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
759
760
761
762
763
      // trigger to send reply to AMF
      trigger_create_context_error_response(
          http_status_code_e::HTTP_STATUS_CODE_403_FORBIDDEN,
          PDU_SESSION_APPLICATION_ERROR_N1_SM_ERROR, n1_sm_message_hex,
          smreq->pid);
764
765
766
767
768
    } else {
      trigger_http_response(
          http_status_code_e::HTTP_STATUS_CODE_500_INTERNAL_SERVER_ERROR,
          smreq->pid, N11_SESSION_CREATE_SM_CONTEXT_RESPONSE);
    }
769
    return;
770
771
  }

Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
772
773
  // Check request type
  std::string request_type = smreq->req.get_request_type();
774
  if (request_type.compare("INITIAL_REQUEST") != 0) {
775
776
    Logger::smf_app().warn(
        "Invalid request type (request type = %s)", request_type.c_str());
Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
777
    //"Existing PDU Session", AMF should use PDUSession_UpdateSMContext instead
778
    //(see step 3, section 4.3.2.2.1 @ 3GPP TS 23.502 v16.0.0) ignore the
Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
779
    // message
780
    return;
781
782
  }

Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
783
784
785
786
787
788
  // If no DNN information from UE, set to default value
  std::string dnn = smreq->req.get_dnn();
  if (dnn.length() == 0) {
    dnn == smf_cfg.get_default_dnn();
  }

Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
789
790
  // TODO: For the moment, not support PDU session authentication and
  // authorization by the external DN
791

Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
792
  // Step 3. check if the DNN requested is valid
793
794
  if (not smf_cfg.is_dotted_dnn_handled(dnn, pdu_session_type)) {
    // Not a valid request...
Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
795
    Logger::smf_app().warn(
Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
796
797
        "Received a PDU Session Create SM Context Request: unknown requested "
        "DNN %s, ignore message!",
Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
798
        dnn.c_str());
799
    // PDU Session Establishment Reject
Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
800
    if (smf_n1::get_instance().create_n1_pdu_session_establishment_reject(
Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
801
802
            smreq->req, n1_sm_message,
            cause_value_5gsm_e::CAUSE_27_MISSING_OR_UNKNOWN_DNN)) {
803
      smf_app_inst->convert_string_2_hex(n1_sm_message, n1_sm_message_hex);
Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
804
805
806
807
808
      // trigger to send reply to AMF
      trigger_create_context_error_response(
          http_status_code_e::HTTP_STATUS_CODE_403_FORBIDDEN,
          PDU_SESSION_APPLICATION_ERROR_DNN_DENIED, n1_sm_message_hex,
          smreq->pid);
809
810
811
812
813
    } else {
      trigger_http_response(
          http_status_code_e::HTTP_STATUS_CODE_500_INTERNAL_SERVER_ERROR,
          smreq->pid, N11_SESSION_CREATE_SM_CONTEXT_RESPONSE);
    }
814
815
816
    return;
  }

Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
817
818
  // Step 4. create a context for this supi if not existed, otherwise update
  std::shared_ptr<smf_context> sc = {};
819
  if (is_supi_2_smf_context(supi64)) {
820
821
    Logger::smf_app().debug(
        "Update SMF context with SUPI " SUPI_64_FMT "", supi64);
822
823
824
    sc = supi_2_smf_context(supi64);
    sc.get()->set_supi(supi);
  } else {
Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
825
826
    Logger::smf_app().debug(
        "Create a new SMF context with SUPI " SUPI_64_FMT "", supi64);
827
828
    sc = std::shared_ptr<smf_context>(new smf_context());
    sc.get()->set_supi(supi);
829
    sc.get()->set_supi_prefix(supi_prefix);
830
831
832
    set_supi_2_smf_context(supi64, sc);
  }

Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
833
834
  // Step 5. Create/update context with dnn information
  std::shared_ptr<dnn_context> sd = {};
835
836

  if (!sc.get()->find_dnn_context(snssai, dnn, sd)) {
837
    if (nullptr == sd.get()) {
Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
838
      // create a new one and insert to the list
Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
839
840
      Logger::smf_app().debug(
          "Create a DNN context and add to the SMF context");
841
842
      sd                   = std::shared_ptr<dnn_context>(new dnn_context(dnn));
      sd.get()->in_use     = true;
843
      sd.get()->dnn_in_use = dnn;
844
      sd.get()->nssai      = snssai;
845
846
847
848
      sc.get()->insert_dnn(sd);
    }
  }

Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
849
850
851
852
853
854
855
  // Step 6. if colliding with an existing SM context (session is already
  // existed and request type is INITIAL_REQUEST)  Delete the local context
  // (including and any associated resources in the UPF and PCF) and create a
  // new one
  if (is_scid_2_smf_context(supi64, dnn, snssai, pdu_session_id) &&
      (request_type.compare("INITIAL_REQUEST") == 0)) {
    // remove smf_pdu_session (including all flows associated to this session)
856
857
    sd.get()->remove_pdu_session(pdu_session_id);
    Logger::smf_app().warn(
Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
858
859
        "PDU Session already existed (SUPI " SUPI_64_FMT
        ", DNN %s, NSSAI (sst %d, sd %s), PDU Session ID %d)",
860
861
862
        supi64, dnn.c_str(), snssai.sST, snssai.sD.c_str(), pdu_session_id);
  }

Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
863
864
  // Step 7. retrieve Session Management Subscription data from UDM if not
  // available (step 4, section 4.3.2 3GPP TS 23.502)
865
  std::string dnn_selection_mode = smreq->req.get_dnn_selection_mode();
Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
866
867
  // if the Session Management Subscription data is not available, get from
  // configuration file or UDM
868
  if (not sc.get()->is_dnn_snssai_subscription_data(dnn, snssai)) {
Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
869
    Logger::smf_app().debug(
870
871
        "The Session Management Subscription data is not available");

872
    session_management_subscription* s =
Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
873
        new session_management_subscription(snssai);
Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
874
875
    std::shared_ptr<session_management_subscription> subscription =
        std::shared_ptr<session_management_subscription>(s);
876
877
878
879
880

    if (not use_local_configuration_subscription_data(dnn_selection_mode)) {
      Logger::smf_app().debug(
          "Retrieve Session Management Subscription data from the UDM");
      if (smf_n10_inst->get_sm_data(supi64, dnn, snssai, subscription)) {
Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
881
        // update dnn_context with subscription info
882
883
        sc.get()->insert_dnn_subscription(snssai, subscription);
      } else {
Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
884
885
        // Cannot retrieve information from UDM, reject PDU session
        // establishment
886
        Logger::smf_app().warn(
Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
887
888
889
            "Received a PDU Session Create SM Context Request, couldn't "
            "retrieve the Session Management Subscription from UDM, ignore "
            "message!");
890
        // PDU Session Establishment Reject
Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
891