smf_app.cpp 80.5 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
#include <boost/uuid/random_generator.hpp>
33
#include <boost/algorithm/string.hpp>
34
#include <boost/uuid/uuid_io.hpp>
35
#include <cstdlib>
Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
36
37
#include <iostream>
#include <stdexcept>
38

Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
39
40
41
42
#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
43
#include "3gpp_conversions.hpp"
Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
44
45
46
47
48
49
#include "ProblemDetails.h"
#include "RefToBinaryData.h"
#include "SmContextCreateError.h"
#include "SmContextCreatedData.h"
#include "SmContextMessage.h"
#include "SmContextUpdateError.h"
50
51
52
53
#include "async_shell_cmd.hpp"
#include "common_defs.h"
#include "conversions.hpp"
#include "itti.hpp"
Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
54
#include "itti_msg_nx.hpp"
55
#include "logger.hpp"
Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
56
#include "pfcp.hpp"
57
#include "smf.h"
Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
58
#include "smf_event.hpp"
59
#include "smf_n1.hpp"
Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
60
#include "smf_sbi.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"
Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
64
#include "fqdn.hpp"
65

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

using namespace smf;

73
74
extern util::async_shell_cmd* async_shell_cmd_inst;
extern smf_app* smf_app_inst;
75
extern smf_config smf_cfg;
76
smf_n4* smf_n4_inst   = nullptr;
Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
77
smf_sbi* smf_sbi_inst = nullptr;
78
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
  paa_t paa = {};
87
88
89
  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;
90
      int range   = be32toh(cfg.ue_pool_range_high[pool_id].s_addr) -
Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
91
92
93
94
                  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
95
      Logger::smf_app().info("Applied config %s", cfg.dnn[ia].dnn.c_str());
96
      paa.ipv4_address = cfg.ue_pool_range_low[pool_id];
97
    }
98
99
    if (cfg.dnn[ia].pool_id_iv6 >= 0) {
      int pool_id = cfg.dnn[ia].pool_id_iv6;
100
101
102
      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]);
103
104
      paa.ipv6_address = cfg.paa_pool6_prefix[pool_id];

Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
105
      // TODO: check with dnn_label
106
107
      Logger::smf_app().info(
          "Applied config for IPv6 %s", cfg.dnn[ia].dnn.c_str());
108
109
110
111
    }
  }

  Logger::smf_app().info("Applied config");
Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
112
  return RETURNok;
113
114
115
116
117
}

//------------------------------------------------------------------------------
uint64_t smf_app::generate_seid() {
  std::unique_lock<std::mutex> ls(m_seid_n4_generator);
118
  uint64_t seid = ++seid_n4_generator;
119
  while ((is_seid_n4_exist(seid)) || (seid == UNASSIGNED_SEID)) {
120
    seid = ++seid_n4_generator;
121
122
123
124
125
126
  }
  set_seid_n4.insert(seid);
  ls.unlock();
  return seid;
}

127
//------------------------------------------------------------------------------
128
void smf_app::generate_smf_context_ref(std::string& smf_ref) {
129
130
131
132
  smf_ref = std::to_string(sm_context_ref_generator.get_uid());
}

//------------------------------------------------------------------------------
133
scid_t smf_app::generate_smf_context_ref() {
134
135
136
  return sm_context_ref_generator.get_uid();
}

137
138
139
140
141
//------------------------------------------------------------------------------
evsub_id_t smf_app::generate_ev_subscription_id() {
  return evsub_id_generator.get_uid();
}

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

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

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

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

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

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

//------------------------------------------------------------------------------
188
void smf_app_task(void*) {
189
190
191
192
193
  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);
194
    auto* msg                            = shared_msg.get();
195
    switch (msg->msg_type) {
196
      case N4_SESSION_ESTABLISHMENT_RESPONSE:
197
198
        if (itti_n4_session_establishment_response* m =
                dynamic_cast<itti_n4_session_establishment_response*>(msg)) {
199
200
201
          smf_app_inst->handle_itti_msg(std::ref(*m));
        }
        break;
202

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

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

217
218
219
220
221
222
223
224
225
226
227
      case N4_SESSION_REPORT_REQUEST:
        smf_app_inst->handle_itti_msg(
            std::static_pointer_cast<itti_n4_session_report_request>(
                shared_msg));
        break;

      case N4_NODE_FAILURE:
        smf_app_inst->handle_itti_msg(
            std::static_pointer_cast<itti_n4_node_failure>(shared_msg));
        break;

228
      case N11_SESSION_N1N2_MESSAGE_TRANSFER_RESPONSE_STATUS:
229
230
        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
231
                    msg)) {
232
233
234
          smf_app_inst->handle_itti_msg(std::ref(*m));
        }
        break;
235

236
      case N11_SESSION_UPDATE_PDU_SESSION_STATUS:
237
238
        if (itti_n11_update_pdu_session_status* m =
                dynamic_cast<itti_n11_update_pdu_session_status*>(msg)) {
239
240
241
242
          smf_app_inst->handle_itti_msg(std::ref(*m));
        }
        break;

243
      case N11_SESSION_CREATE_SM_CONTEXT_RESPONSE:
244
245
        if (itti_n11_create_sm_context_response* m =
                dynamic_cast<itti_n11_create_sm_context_response*>(msg)) {
246
247
248
249
250
          smf_app_inst->handle_itti_msg(std::ref(*m));
        }
        break;

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

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

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

271
      case N11_UPDATE_NF_INSTANCE_RESPONSE:
272
273
        if (itti_n11_update_nf_instance_response* m =
                dynamic_cast<itti_n11_update_nf_instance_response*>(msg)) {
274
275
276
277
          smf_app_inst->handle_itti_msg(std::ref(*m));
        }
        break;

278
      case TIME_OUT:
279
        if (itti_msg_timeout* to = dynamic_cast<itti_msg_timeout*>(msg)) {
280
281
282
283
284
          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;
285
            case TASK_SMF_APP_TIMEOUT_NRF_HEARTBEAT:
286
287
              smf_app_inst->timer_nrf_heartbeat_timeout(
                  to->timer_id, to->arg2_user);
288
              break;
Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
289
            case TASK_SMF_APP_TIMEOUT_NRF_DEREGISTRATION:
290
291
              smf_app_inst->timer_nrf_deregistration(
                  to->timer_id, to->arg2_user);
Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
292
              break;
Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
293
            default:;
294
          }
295
        }
296
        break;
297

298
      case TERMINATE:
299
300
        if (itti_msg_terminate* terminate =
                dynamic_cast<itti_msg_terminate*>(msg)) {
301
302
303
          Logger::smf_app().info("Received terminate message");
          return;
        }
304
305
        break;

306
307
      case HEALTH_PING:
        break;
308

309
310
      default:
        Logger::smf_app().info("no handler for msg type %d", msg->msg_type);
311
312
313
314
315
    }
  } while (true);
}

//------------------------------------------------------------------------------
316
smf_app::smf_app(const std::string& config_file)
Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
317
318
319
320
321
322
    : m_seid2smf_context(),
      m_supi2smf_context(),
      m_scid2smf_context(),
      m_sm_context_create_promises(),
      m_sm_context_update_promises(),
      m_sm_context_release_promises() {
323
324
  Logger::smf_app().startup("Starting...");

325
326
  supi2smf_context  = {};
  set_seid_n4       = {};
327
  seid_n4_generator = 0;
328

329
  apply_config(smf_cfg);
330

331
332
333
  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");
334
335
336
  }

  try {
337
    smf_n4_inst  = new smf_n4();
Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
338
    smf_sbi_inst = new smf_sbi();
339
  } catch (std::exception& e) {
340
    Logger::smf_app().error("Cannot create SMF_APP: %s", e.what());
341
342
343
    throw;
  }

344
345
346
347
348
349
350
351
352
353
354
355
356
  Logger::smf_app().startup("Started");
}

//------------------------------------------------------------------------------
smf_app::~smf_app() {
  Logger::smf_app().debug("Delete SMF_APP instance...");
  // TODO: Unregister NRF
  if (smf_n4_inst) delete smf_n4_inst;
  if (smf_sbi_inst) delete smf_sbi_inst;
}

//------------------------------------------------------------------------------
void smf_app::start_nf_registration_discovery() {
357
  if (smf_cfg.discover_upf) {
358
359
    // Trigger NFStatusNotify subscription to be noticed when a new UPF becomes
    // available (if this option is enabled)
360
    trigger_upf_status_notification_subscribe();
361
362
363
364
365
366
367
  } else {
    // TODO: should be done when SMF select UPF for a particular UE (should be
    // verified)
    for (std::vector<pfcp::node_id_t>::const_iterator it = smf_cfg.upfs.begin();
         it != smf_cfg.upfs.end(); ++it) {
      start_upf_association(*it);
    }
368
369
370
371
  }

  // Register to NRF (if this option is enabled)
  if (smf_cfg.register_nrf) {
372
373
    unsigned int microsecond = 10000;  // 10ms
    usleep(microsecond);
374
    register_to_nrf();
375
  }
376
377
}

Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
378
//------------------------------------------------------------------------------
379
void smf_app::start_upf_association(const pfcp::node_id_t& node_id) {
380
  std::time_t time_epoch = std::time(nullptr);
381
  uint64_t tv_ntp        = time_epoch + SECONDS_SINCE_FIRST_EPOCH;
382
383

  pfcp_associations::get_instance().add_peer_candidate_node(node_id);
Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
384
385
386
  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));
387

Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
388
  // n4_asc->trxn_id = smf_n4_inst->generate_trxn_id();
389
  pfcp::cp_function_features_s cp_function_features;
390
  cp_function_features      = {};
391
392
393
  cp_function_features.load = 1;
  cp_function_features.ovrl = 1;

Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
394
  pfcp::node_id_t this_node_id = {};
395
396
  if (smf_cfg.get_pfcp_node_id(this_node_id) == RETURNok) {
    n4_asc->pfcp_ies.set(this_node_id);
397
    pfcp::recovery_time_stamp_t r = {.recovery_time_stamp = (uint32_t) tv_ntp};
398
399
400
401
    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
402
403
      n4_asc->r_endpoint =
          endpoint(node_id.u1.ipv4_address, pfcp::default_port);
404
405
      int ret = itti_inst->send_msg(n4_asc);
      if (RETURNok != ret) {
Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
406
407
408
        Logger::smf_app().error(
            "Could not send ITTI message %s to task TASK_SMF_N4",
            n4_asc.get()->get_msg_name());
409
410
      }
    } else {
Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
411
      Logger::smf_app().warn("Start_association() node_id IPV6, FQDN!");
412
413
414
415
    }
  }
}

416
417
418
419
420
421
//------------------------------------------------------------------------------
void smf_app::start_upf_association(
    const pfcp::node_id_t& node_id, const upf_profile& profile) {
  std::time_t time_epoch = std::time(nullptr);
  uint64_t tv_ntp        = time_epoch + SECONDS_SINCE_FIRST_EPOCH;

422
  pfcp_associations::get_instance().add_peer_candidate_node(node_id, profile);
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
  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));

  // n4_asc->trxn_id = smf_n4_inst->generate_trxn_id();
  pfcp::cp_function_features_s cp_function_features;
  cp_function_features      = {};
  cp_function_features.load = 1;
  cp_function_features.ovrl = 1;

  pfcp::node_id_t this_node_id = {};
  if (smf_cfg.get_pfcp_node_id(this_node_id) == RETURNok) {
    n4_asc->pfcp_ies.set(this_node_id);
    pfcp::recovery_time_stamp_t r = {.recovery_time_stamp = (uint32_t) tv_ntp};
    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) {
      n4_asc->r_endpoint =
          endpoint(node_id.u1.ipv4_address, pfcp::default_port);
      int ret = itti_inst->send_msg(n4_asc);
      if (RETURNok != ret) {
        Logger::smf_app().error(
            "Could not send ITTI message %s to task TASK_SMF_N4",
            n4_asc.get()->get_msg_name());
      }
Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
449
450
451
452
453
454
455
456
457
    } else if (node_id.node_id_type == pfcp::NODE_ID_TYPE_FQDN) {
      n4_asc->r_endpoint =
          endpoint(node_id.u1.ipv4_address, pfcp::default_port);
      int ret = itti_inst->send_msg(n4_asc);
      if (RETURNok != ret) {
        Logger::smf_app().error(
            "Could not send ITTI message %s to task TASK_SMF_N4",
            n4_asc.get()->get_msg_name());
      }
458
    } else {
Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
459
      Logger::smf_app().warn("Start_association() node_id IPV6!");
460
461
462
463
    }
  }
}

464
//------------------------------------------------------------------------------
465
void smf_app::handle_itti_msg(itti_n4_session_establishment_response& seresp) {
Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
466
  std::shared_ptr<smf_context> pc = {};
467
468
469
  if (seid_2_smf_context(seresp.seid, pc)) {
    pc.get()->handle_itti_msg(seresp);
  } else {
Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
470
    Logger::smf_app().debug(
Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
471
472
        "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
473
        seresp.seid, seresp.trxn_id);
474
475
476
477
  }
}

//------------------------------------------------------------------------------
478
void smf_app::handle_itti_msg(itti_n4_session_modification_response& smresp) {
Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
479
  std::shared_ptr<smf_context> pc = {};
480
481
482
  if (seid_2_smf_context(smresp.seid, pc)) {
    pc.get()->handle_itti_msg(smresp);
  } else {
Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
483
    Logger::smf_app().debug(
Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
484
485
        "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
486
        smresp.seid, smresp.trxn_id);
487
488
489
490
  }
}

//------------------------------------------------------------------------------
491
void smf_app::handle_itti_msg(itti_n4_session_deletion_response& smresp) {
Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
492
  std::shared_ptr<smf_context> pc = {};
493
494
495
  if (seid_2_smf_context(smresp.seid, pc)) {
    pc.get()->handle_itti_msg(smresp);

496
    if (pc->get_number_dnn_contexts() == 0) {
497
498
499
      delete_smf_context(pc);
    }
  } else {
Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
500
    Logger::smf_app().debug(
Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
501
502
        "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
503
        smresp.seid, smresp.trxn_id);
504
505
506
507
  }
}

//------------------------------------------------------------------------------
Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
508
509
void smf_app::handle_itti_msg(
    std::shared_ptr<itti_n4_session_report_request> snr) {
Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
510
  std::shared_ptr<smf_context> pc = {};
511
512
513
  if (seid_2_smf_context(snr->seid, pc)) {
    pc.get()->handle_itti_msg(snr);
  } else {
514
515
516
517
    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);
518
519
520
  }
}

521
522
523
524
525
526
527
528
529
530
531
//------------------------------------------------------------------------------
void smf_app::handle_itti_msg(std::shared_ptr<itti_n4_node_failure> snf) {
  pfcp::node_id_t node_id = snf->node_id;

  for (auto it : scid2smf_context) {
    if (it.second->upf_node_id == node_id) {
      supi64_t supi64 = smf_supi_to_u64(it.second->supi);
      Logger::smf_app().debug(
          "Remove the associated PDU session (SUPI " SUPI_64_FMT
          ", PDU Sessin Id %d)",
          supi64, it.second->pdu_session_id);
532
      // TODO: remove the session
533
534
535
536
    }
  }
}

537
//------------------------------------------------------------------------------
Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
538
void smf_app::handle_itti_msg(
539
    itti_n11_n1n2_message_transfer_response_status& m) {
540
  Logger::smf_app().info("Process N1N2MessageTransfer Response");
541
542

  switch (m.procedure_type) {
Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
543
544
545
    case session_management_procedures_type_e::
        PDU_SESSION_ESTABLISHMENT_UE_REQUESTED: {
      // Update PDU Session accordingly
Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
546
      Logger::smf_app().info("PDU_SESSION_ESTABLISHMENT_UE_REQUESTED");
Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
547
548
549
550
551
552
553
554
      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)) {
555
556
557
558
        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;
559
          state  = upCnx_state_e::UPCNX_STATE_ACTIVATING;
560
561
562
563
        }
        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
564
565
            "Got successful response from AMF (response code %d), set session "
            "status to %s",
566
            m.response_code,
567
            pdu_session_status_e2str.at(static_cast<int>(status)).c_str());
568
      } else {
Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
569
        // TODO:
570
571
        Logger::smf_app().debug(
            "Got response from AMF (response code %d)", m.response_code);
572
      }
Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
573
    } break;
Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
574

Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
575
576
    case session_management_procedures_type_e::
        SERVICE_REQUEST_NETWORK_TRIGGERED: {
577
578
579
      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
580
581
582
583
      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)) {
584
        Logger::smf_app().debug("Send failure indication to UPF");
Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
585
586
        // TODO: to be completed
        pfcp::node_id_t up_node_id = {};
587
588
589
590
591
592
593
594
595
        // Get UPF node
        std::shared_ptr<smf_context_ref> scf = {};
        if (smf_app_inst->is_scid_2_smf_context(m.scid)) {
          scf        = scid_2_smf_context(m.scid);
          up_node_id = scf.get()->upf_node_id;
        } else {
          Logger::smf_app().warn(
              "SM Context associated with this id " SCID_FMT " does not exit!",
              m.scid);
596
597
598
          return;
        }

599
        itti_n4_session_failure_indication* itti_n4 =
600
            new itti_n4_session_failure_indication(TASK_SMF_APP, TASK_SMF_N4);
601
        itti_n4->seid    = m.seid;
602
        itti_n4->trxn_id = m.trxn_id;
Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
603
604
605
606
607
        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);
608

609
610
611
        Logger::smf_app().info(
            "Sending ITTI message %s to task TASK_SMF_N4",
            itti_n4->get_msg_name());
612
613
614
615
616
617
618
        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;
        }
619
      }
Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
620
    } break;
Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
621

622
    default: {
Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
623
      Logger::smf_app().warn("Unknown procedure type %d", m.procedure_type);
624
625
626
627
628
    }
  }
}

//------------------------------------------------------------------------------
629
void smf_app::handle_itti_msg(itti_n11_update_pdu_session_status& m) {
Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
630
631
  Logger::smf_app().info(
      "Set PDU Session Status to %s",
632
633
      pdu_session_status_e2str.at(static_cast<int>(m.pdu_session_status))
          .c_str());
634
635
636
  update_pdu_session_status(m.scid, m.pdu_session_status);
}

637
//------------------------------------------------------------------------------
638
void smf_app::handle_itti_msg(itti_n11_create_sm_context_response& m) {
639
640
  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
641
  pdu_session_create_sm_context_response sm_context_response = {};
642
  std::unique_lock lock(m_sm_context_create_promises);
Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
643
  if (sm_context_create_promises.count(m.pid) > 0) {
644
    sm_context_create_promises[m.pid]->set_value(m.res);
Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
645
    // Remove this promise from list
646
647
    sm_context_create_promises.erase(m.pid);
  }
648
649
650
}

//------------------------------------------------------------------------------
651
void smf_app::handle_itti_msg(itti_n11_update_sm_context_response& m) {
652
653
  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
654
  pdu_session_update_sm_context_response sm_context_response = {};
655
  std::unique_lock lock(m_sm_context_update_promises);
Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
656
  if (sm_context_update_promises.count(m.pid) > 0) {
657
    sm_context_update_promises[m.pid]->set_value(m.res);
Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
658
    // Remove this promise from list
659
660
    sm_context_update_promises.erase(m.pid);
  }
661
662
663
}

//------------------------------------------------------------------------------
664
void smf_app::handle_itti_msg(itti_n11_release_sm_context_response& m) {
665
666
  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
667
  pdu_session_release_sm_context_response sm_context_response = {};
668
  std::unique_lock lock(m_sm_context_release_promises);
Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
669
  if (sm_context_release_promises.count(m.pid) > 0) {
670
    sm_context_release_promises[m.pid]->set_value(m.res);
Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
671
    // Remove this promise from list
672
673
    sm_context_release_promises.erase(m.pid);
  }
674
675
}

676
//------------------------------------------------------------------------------
677
void smf_app::handle_itti_msg(itti_n11_register_nf_instance_response& r) {
678
  Logger::smf_app().debug("Handle NF Instance Registration response");
679

680
  nf_instance_profile = r.profile;
681
  // Set heartbeat timer
682
  Logger::smf_app().debug(
Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
683
684
      "Set value of NRF Heartbeat timer to %d",
      r.profile.get_nf_heartBeat_timer());
685
686
687
688
  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
689

Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
690
691
692
693
694
  /*  //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
  */
695
696
697
}

//------------------------------------------------------------------------------
698
void smf_app::handle_itti_msg(itti_n11_update_nf_instance_response& u) {
699
700
  Logger::smf_app().debug("NF Update NF response");

701
702
703
  Logger::smf_app().debug(
      "Set NRF Heartbeat timer (%d)",
      nf_instance_profile.get_nf_heartBeat_timer());
704
705
706

  // Set heartbeat timer
  //  timer_nrf_heartbeat = itti_inst->timer_setup(
707
  //      nf_instance_profile.get_nf_heartBeat_timer(), 0, TASK_SMF_APP,
708
  //      TASK_SMF_APP_TIMEOUT_NRF_HEARTBEAT, 0); //TODO arg2_user
709
}
710

711
//------------------------------------------------------------------------------
Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
712
713
714
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
715
716
      "Handle a PDU Session Create SM Context Request from an AMF (HTTP "
      "version %d)",
717
      smreq->http_version);
Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
718
  // Handle PDU Session Create SM Context Request (Section 4.3.2@3GPP TS 23.502)
719
  std::string n1_sm_message, n1_sm_message_hex;
720
721
  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
722
723
  pdu_session_type_t pdu_session_type = {.pdu_session_type =
                                             PDU_SESSION_TYPE_E_IPV4};
724

Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
725
  // Step 1. Decode NAS and get the necessary information
Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
726
727
  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
728

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

Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
733
    if (smf_n1::get_instance().create_n1_pdu_session_establishment_reject(
Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
734
735
            smreq->req, n1_sm_message,
            cause_value_5gsm_e::CAUSE_95_SEMANTICALLY_INCORRECT_MESSAGE)) {
736
      conv::convert_string_2_hex(n1_sm_message, n1_sm_message_hex);
Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
737
      // Trigger the reply to AMF
Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
738
739
740
741
      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);
742
    } else {
Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
743
      // Trigger the reply to AMF
744
745
746
747
      trigger_http_response(
          http_status_code_e::HTTP_STATUS_CODE_500_INTERNAL_SERVER_ERROR,
          smreq->pid, N11_SESSION_CREATE_SM_CONTEXT_RESPONSE);
    }
748
    return;
749
  }
750

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

754
  pdu_session_type.pdu_session_type = smreq->req.get_pdu_session_type();
Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
755
  // TODO: Support IPv4 only for now
756
757
  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;
758
759
760
  } 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)) {
761
762
    cause_n1 = cause_value_5gsm_e::CAUSE_28_UNKNOWN_PDU_SESSION_TYPE;
  }
763
764
765

  if ((pdu_session_type.pdu_session_type != PDU_SESSION_TYPE_E_IPV4) and
      (pdu_session_type.pdu_session_type != PDU_SESSION_TYPE_E_IPV4V6)) {
Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
766
767
768
    // PDU Session Establishment Reject
    if (smf_n1::get_instance().create_n1_pdu_session_establishment_reject(
            smreq->req, n1_sm_message, cause_n1)) {
769
      conv::convert_string_2_hex(n1_sm_message, n1_sm_message_hex);
Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
770
      // Trigger the reply to AMF
Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
771
772
773
774
      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);
775
776
777
778
779
    } else {
      trigger_http_response(
          http_status_code_e::HTTP_STATUS_CODE_500_INTERNAL_SERVER_ERROR,
          smreq->pid, N11_SESSION_CREATE_SM_CONTEXT_RESPONSE);
    }
780
    return;
781
782
  }

Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
783
784
785
786
787
  // 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
788
  Logger::smf_app().info(
Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
789
      "Handle a PDU Session Create SM Context Request message from AMF, "
Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
790
791
      "SUPI " SUPI_64_FMT ", SNSSAI SST %d, SD %s",
      supi64, snssai.sST, snssai.sD.c_str());
792

Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
793
  // Step 2. Verify Procedure transaction id, pdu session id, message type,
Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
794
795
796
797
798
  // 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
799
800
801
  if ((pti.procedure_transaction_id ==
       PROCEDURE_TRANSACTION_IDENTITY_UNASSIGNED) ||
      (pti.procedure_transaction_id > PROCEDURE_TRANSACTION_IDENTITY_LAST)) {
802
803
    Logger::smf_app().warn(
        "Invalid PTI value (pti = %d)", pti.procedure_transaction_id);
Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
804
805
    // 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
806
    if (smf_n1::get_instance().create_n1_pdu_session_establishment_reject(
Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
807
808
            smreq->req, n1_sm_message,
            cause_value_5gsm_e::CAUSE_81_INVALID_PTI_VALUE)) {
809
      conv::convert_string_2_hex(n1_sm_message, n1_sm_message_hex);
Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
810
      // Trigger the reply to AMF
Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
811
812
813
814
      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);
815
816
817
818
819
    } else {
      trigger_http_response(
          http_status_code_e::HTTP_STATUS_CODE_500_INTERNAL_SERVER_ERROR,
          smreq->pid, N11_SESSION_CREATE_SM_CONTEXT_RESPONSE);
    }
820
    return;
821
  }
822

Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
823
  // Check PDU Session ID
Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
824
825
  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
826
827
  if ((pdu_session_id == PDU_SESSION_IDENTITY_UNASSIGNED) ||
      (pdu_session_id > PDU_SESSION_IDENTITY_LAST)) {
Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
828
    Logger::smf_app().warn("Invalid PDU Session ID value (%d)", pdu_session_id);
Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
829
830
    // section 7.3.2@3GPP TS 24.501; NAS N1 SM message: ignore the message
    // trigger to send reply to AMF
831
832
833
    trigger_http_response(
        http_status_code_e::HTTP_STATUS_CODE_406_NOT_ACCEPTABLE, smreq->pid,
        N11_SESSION_CREATE_SM_CONTEXT_RESPONSE);
834
    return;
835
836
  }

Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
837
  // Check Message Type
Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
838
  uint8_t message_type = decoded_nas_msg.plain.sm.header.message_type;
839
  if (message_type != PDU_SESSION_ESTABLISHMENT_REQUEST) {
840
841
    Logger::smf_app().warn(
        "Invalid message type (message type = %d)", message_type);
Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
842
843
844
845
    // 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
846
    if (smf_n1::get_instance().create_n1_pdu_session_establishment_reject(
Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
847
848
849
            smreq->req, n1_sm_message,
            cause_value_5gsm_e::
                CAUSE_98_MESSAGE_TYPE_NOT_COMPATIBLE_WITH_PROTOCOL_STATE)) {
850
      conv::convert_string_2_hex(n1_sm_message, n1_sm_message_hex);
Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
851
      // Trigger the reply to AMF
Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
852
853
854
855
      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);
856
857
858
859
860
    } else {
      trigger_http_response(
          http_status_code_e::HTTP_STATUS_CODE_500_INTERNAL_SERVER_ERROR,
          smreq->pid, N11_SESSION_CREATE_SM_CONTEXT_RESPONSE);
    }
861
    return;
862
863
  }

Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
864
  // Check Request Type
Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
865
  std::string request_type = smreq->req.get_request_type();
866
  if (request_type.compare("INITIAL_REQUEST") != 0) {
867
868
    Logger::smf_app().warn(
        "Invalid request type (request type = %s)", request_type.c_str());
Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
869
    //"Existing PDU Session", AMF should use PDUSession_UpdateSMContext instead
870
    //(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
871
    // message
872
    return;
873
874
  }

Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
875
876
877
878
879
880
  // 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
881
882
  // TODO: For the moment, not support PDU session authentication and
  // authorization by the external DN
883

Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
884
  // Step 3. check if the DNN requested is valid
Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
885
886
887
  std::string nd_dnn;
  util::dotted_to_string(dnn, nd_dnn);
  dnn = nd_dnn;
Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
888
  // Update DNN
Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
889
  smreq->req.set_dnn(dnn);
890
891
  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
892
    Logger::smf_app().warn(
Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
893
894
        "Received a PDU Session Create SM Context Request: unknown requested "
        "DNN %s, ignore message!",
Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
895
        dnn.c_str());
896
    // PDU Session Establishment Reject
Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
897
    if (smf_n1::get_instance().create_n1_pdu_session_establishment_reject(
Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
898
899
            smreq->req, n1_sm_message,
            cause_value_5gsm_e::CAUSE_27_MISSING_OR_UNKNOWN_DNN)) {
900
      conv::convert_string_2_hex(n1_sm_message, n1_sm_message_hex);
Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
901
      // Trigger the reply to AMF
Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
902
903
904
905
      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);
906
907
908
909
910
    } else {
      trigger_http_response(
          http_status_code_e::HTTP_STATUS_CODE_500_INTERNAL_SERVER_ERROR,
          smreq->pid, N11_SESSION_CREATE_SM_CONTEXT_RESPONSE);
    }
911
912
913
    return;
  }

Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
914
  // Step 4. Create a context for this supi if not existed, otherwise update
Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
915
  std::shared_ptr<smf_context> sc = {};
916
  if (is_supi_2_smf_context(supi64)) {
917
918
    Logger::smf_app().debug(
        "Update SMF context with SUPI " SUPI_64_FMT "", supi64);
919
920
921
    sc = supi_2_smf_context(supi64);
    sc.get()->set_supi(supi);
  } else {
Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
922
923
    Logger::smf_app().debug(
        "Create a new SMF context with SUPI " SUPI_64_FMT "", supi64);
924
925
    sc = std::shared_ptr<smf_context>(new smf_context());
    sc.get()->set_supi(supi);
926
    sc.get()->set_supi_prefix(supi_prefix);
927
928
929
    set_supi_2_smf_context(supi64, sc);
  }

Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
930
931
  // Step 5. Create/update context with dnn information
  std::shared_ptr<dnn_context> sd = {};
932
933

  if (!sc.get()->find_dnn_context(snssai, dnn, sd)) {