Commit 85eb18a3 authored by Tien-Thinh Nguyen's avatar Tien-Thinh Nguyen
Browse files

support PDUSession_CreateSMContextRequest

parent 8bd91b97
/*
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The OpenAirInterface Software Alliance licenses this file to You under
* the Apache License, Version 2.0 (the "License"); you may not use this file
* except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* 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
*/
#ifndef FILE_3GPP_29_502_SMF_SEEN
#define FILE_3GPP_29_502_SMF_SEEN
enum pdu_session_application_error_e {
PDU_SESSION_APPLICATION_ERROR_N1_SM_ERROR = 1,
PDU_SESSION_APPLICATION_ERROR_SNSSAI_DENIED = 2,
PDU_SESSION_APPLICATION_ERROR_DNN_DENIED = 3,
PDU_SESSION_APPLICATION_ERROR_PDUTYPE_DENIED = 4,
PDU_SESSION_APPLICATION_ERROR_SSC_DENIED = 5,
PDU_SESSION_APPLICATION_ERROR_SUBSCRIPTION_DENIED = 6,
PDU_SESSION_APPLICATION_ERROR_DNN_NOT_SUPPORTED = 7,
PDU_SESSION_APPLICATION_ERROR_PDUTYPE_NOT_SUPPORTED = 8,
PDU_SESSION_APPLICATION_ERROR_SSC_NOT_SUPPORTED = 9,
PDU_SESSION_APPLICATION_ERROR_HOME_ROUTED_ROAMING_REQUIRED = 10,
PDU_SESSION_APPLICATION_ERROR_OUT_OF_LADN_SERVICE_AREA = 11,
PDU_SESSION_APPLICATION_ERROR_N2_SM_ERROR = 12,
PDU_SESSION_APPLICATION_ERROR_PRIORITIZED_SERVICES_ONLY = 13,
PDU_SESSION_APPLICATION_ERROR_PDU_SESSION_ANCHOR_CHANGE = 14,
PDU_SESSION_APPLICATION_ERROR_TARGET_MME_CAPABILITY = 15,
PDU_SESSION_APPLICATION_ERROR_NO_EPS_5GS_CONTINUITY = 16,
PDU_SESSION_APPLICATION_ERROR_UNABLE_TO_PAGE_UE = 17,
PDU_SESSION_APPLICATION_ERROR_UE_NOT_RESPONDING = 18,
PDU_SESSION_APPLICATION_ERROR_REJECTED_BY_UE = 19,
PDU_SESSION_APPLICATION_ERROR_REJECTED_DUE_VPLMN_POLICY = 20,
PDU_SESSION_APPLICATION_ERROR_HO_TAU_IN_PROGRESS = 21,
PDU_SESSION_APPLICATION_ERROR_INTEGRITY_PROTECTED_MDR_NOT_ACCEPTABLE = 22,
PDU_SESSION_APPLICATION_ERROR_EBI_EXHAUSTED = 23,
PDU_SESSION_APPLICATION_ERROR_EBI_REJECTED_LOCAL_POLICY = 24,
PDU_SESSION_APPLICATION_ERROR_EBI_REJECTED_NO_N26 = 25,
PDU_SESSION_APPLICATION_ERROR_DEFAULT_EPS_BEARER_INACTIVE = 26,
PDU_SESSION_APPLICATION_ERROR_HANDOVER_RESOURCE_ALLOCATION_FAILURE = 27,
PDU_SESSION_APPLICATION_ERROR_CONTEXT_NOT_FOUND = 28,
PDU_SESSION_APPLICATION_ERROR_INSUFFICIENT_RESOURCES_SLICE = 29,
PDU_SESSION_APPLICATION_ERROR_INSUFFICIENT_RESOURCES_SLICE_DNN = 30,
PDU_SESSION_APPLICATION_ERROR_DNN_CONGESTION = 31,
PDU_SESSION_APPLICATION_ERROR_S_NSSAI_CONGESTION = 32,
PDU_SESSION_APPLICATION_ERROR_PEER_NOT_RESPONDING = 33,
PDU_SESSION_APPLICATION_ERROR_NETWORK_FAILURE = 34
};
static const std::vector<std::string> pdu_session_application_error_e2str = {
"UNKNOWN ERROR",
"N1_SM_ERROR",
"SNSSAI_DENIED",
"DNN_DENIED",
"PDUTYPE_DENIED",
"SSC_DENIED",
"SUBSCRIPTION_DENIED",
"DNN_NOT_SUPPORTED",
"PDUTYPE_NOT_SUPPORTED",
"SSC_NOT_SUPPORTED",
"HOME_ROUTED_ROAMING_REQUIRED",
"OUT_OF_LADN_SERVICE_AREA",
"N2_SM_ERROR",
"PRIORITIZED_SERVICES_ONLY",
"PDU_SESSION_ANCHOR_CHANGE",
"TARGET_MME_CAPABILITY",
"NO_EPS_5GS_CONTINUITY",
"UNABLE_TO_PAGE_UE",
"UE_NOT_RESPONDING",
"REJECTED_BY_UE",
"REJECTED_DUE_VPLMN_POLICY",
"HO_TAU_IN_PROGRESS",
"INTEGRITY_PROTECTED_MDR_NOT_ACCEPTABLE",
"EBI_EXHAUSTED",
"EBI_REJECTED_LOCAL_POLICY",
"EBI_REJECTED_NO_N26",
"DEFAULT_EPS_BEARER_INACTIVE",
"HANDOVER_RESOURCE_ALLOCATION_FAILURE",
"CONTEXT_NOT_FOUND",
"INSUFFICIENT_RESOURCES_SLICE",
"INSUFFICIENT_RESOURCES_SLICE_DNN",
"DNN_CONGESTION",
"S_NSSAI_CONGESTION",
"PEER_NOT_RESPONDING",
"NETWORK_FAILURE"
};
#endif
/*
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The OpenAirInterface Software Alliance licenses this file to You under
* the Apache License, Version 2.0 (the "License"); you may not use this file
* except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* 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
*/
#ifndef FILE_3GPP_29_503_SMF_SEEN
#define FILE_3GPP_29_503_SMF_SEEN
#include "smf.h"
enum ssc_mode_e {
SSC_MODE_1 = 1,
SSC_MODE_2 = 2,
SSC_MODE_3 = 3,
};
static const std::vector<std::string> ssc_mode_e2str = {"Error", "SSC_MODE_1", "SSC_MODE_2", "SSC_MODE_3"};
typedef struct ssc_mode_s {
uint8_t ssc_mode;
ssc_mode_s() : ssc_mode(SSC_MODE_1) {}
ssc_mode_s(ssc_mode_e mode) : ssc_mode(mode) {}
ssc_mode_s(const struct ssc_mode_s& p) : ssc_mode(p.ssc_mode) {}
} ssc_mode_t;
typedef struct pdu_session_types_s {
pdu_session_type_t default_session_type;
std::vector<pdu_session_type_t> allowed_session_types;
} pdu_session_types_t;
typedef struct ssc_modes_s {
ssc_mode_t default_ssc_mode;
std::vector<ssc_mode_t> allowed_ssc_modes;
} ssc_modes_t;
typedef struct session_ambr_s {
std::string uplink;
std::string downlink;
} session_ambr_t;
typedef struct dnn_configuration_s {
pdu_session_types_t pdu_session_types;
ssc_modes_t ssc_modes;
session_ambr_t session_ambr;
} dnn_configuration_t;
#endif
......@@ -39,6 +39,8 @@ add_library (PGWC STATIC
pgw_s5s8.cpp
pgwc_procedure.cpp
pgwc_sxab.cpp
smf_n10.cpp
smf_msg.cpp
#pgw_pcef_emulation.cpp
)
......@@ -34,9 +34,19 @@
#include "pgw_paa_dynamic.hpp"
#include "pgw_s5s8.hpp"
#include "pgwc_sxab.hpp"
#include "smf_n10.hpp"
#include "string.hpp"
#include "SmContextCreateError.h"
#include "3gpp_29.502.h"
extern "C" {
#include "sm_msg.h"
#include "PDUSessionEstablishmentRequest.h"
}
#include <stdexcept>
#include <iostream>
#include <cstdlib>
using namespace pgwc;
......@@ -46,6 +56,7 @@ extern pgw_app *pgw_app_inst;
extern pgw_config pgw_cfg;
pgw_s5s8 *pgw_s5s8_inst = nullptr;
pgwc_sxab *pgwc_sxab_inst = nullptr;
smf_n10 *smf_n10_inst = nullptr;
extern itti_mw *itti_inst;
void pgw_app_task (void*);
......@@ -286,6 +297,7 @@ pgw_app::pgw_app (const std::string& config_file) : m_s5s8_cp_teid_generator(),
try {
pgw_s5s8_inst = new pgw_s5s8();
pgwc_sxab_inst = new pgwc_sxab();
smf_n10_inst = new smf_n10();
} catch (std::exception& e) {
Logger::pgwc_app().error( "Cannot create PGW_APP: %s", e.what() );
throw;
......@@ -627,4 +639,144 @@ void pgw_app::handle_itti_msg (std::shared_ptr<itti_sxab_session_report_request>
}
}
//------------------------------------------------------------------------------
bool pgw_app::is_supi_2_smf_context(const supi64_t& supi) const
{
//TODO
//context doesn't exist
return false;
}
//------------------------------------------------------------------------------
std::shared_ptr<pgw_context> pgw_app::supi_2_smf_context(const supi64_t& supi) const
{
std::shared_lock lock(m_supi2smf_context);
return supi2pgw_context.at(supi);
}
//------------------------------------------------------------------------------
void pgw_app::set_supi_2_smf_context(const supi64_t& supi, std::shared_ptr<pgw_context> sc)
{
//TODO: from set_imsi64_2_pgw_context
}
//------------------------------------------------------------------------------
bool pgw_app::is_use_local_configuration_subscription_data(const std::string& dnn_selection_mode)
{
//TODO: should be implemented
return false; //get Session Management Subscription from UDM
}
//------------------------------------------------------------------------------
bool pgw_app::is_supi_dnn_snssai_subscription_data(supi_t& supi, std::string& dnn, snssai_t& snssai)
{
//TODO: should be implemented
return false; //Session Management Subscription from UDM isn't available
}
//------------------------------------------------------------------------------
bool pgw_app::is_create_sm_context_request_valid()
{
//TODO: should be implemented
return true;
}
//------------------------------------------------------------------------------
void pgw_app::send_create_session_response(Pistache::Http::ResponseWriter& httpResponse, oai::smf::model::SmContextCreateError& smContextCreateError, Pistache::Http::Code code)
{
//Send reply to AMF
nlohmann::json jsonData;
to_json(jsonData, smContextCreateError);
std::string resBody = jsonData.dump();
//httpResponse.headers().add<Pistache::Http::Header::Location>(url);
httpResponse.send(code, resBody);
}
//------------------------------------------------------------------------------
void pgw_app::handle_amf_msg(std::shared_ptr<pdu_session_create_sm_context_request>& sm_context_req_msg, Pistache::Http::ResponseWriter &httpResponse){
//handle PDU Session Create SM Context Request as specified in section 4.3.2 3GPP TS 23.502
Logger::pgwc_app().info("Handle AMF message");
//Step 1. get necessary information
Logger::pgwc_app().debug("Handle AMF message, supi " SUPI_64_FMT " ", sm_context_req_msg->get_supi());
std::string dnn = sm_context_req_msg->get_dnn();
snssai_t snssai = sm_context_req_msg->get_snssai();
std::string requestType = sm_context_req_msg->get_request_type();
supi_t supi = sm_context_req_msg->get_supi();
supi64_t supi64 = smf_supi_to_u64(supi);
oai::smf::model::ProblemDetails problem_details;
pdu_session_establishment_request_msg pdu_session_establishment_request = sm_context_req_msg->get_nas_msg() ;
pdu_session_type_t pdu_session_type = {.pdu_session_type = (uint8_t)pdu_session_establishment_request._pdusessiontype};
Logger::pgwc_app().debug("Handle AMF message, _pdusessiontype: %d", pdu_session_type.pdu_session_type);
//Step 2. check if the DNN requested is valid
if (not pgw_cfg.is_dotted_dnn_handled(dnn, pdu_session_type)) {
// Not a valid request...
Logger::pgwc_app().warn("Received PDU_SESSION_CREATESMCONTEXT_REQUEST unknown requested APN %s, ignore message", dnn.c_str());
oai::smf::model::SmContextCreateError smContextCreateError;
problem_details.setCause(pdu_session_application_error_e2str[PDU_SESSION_APPLICATION_ERROR_DNN_DENIED]);
//create a PDU Session Establishment Response by relying on NAS and assign to smContextCeateError.m_N1SmMsg
//Send response to AMF
send_create_session_response(httpResponse, smContextCreateError, Pistache::Http::Code::Forbidden);
return;
}
//Step 3. create a context for this supi if not existed, otherwise update
std::shared_ptr<pgw_context> sc;
if (is_supi_2_smf_context(supi64)) {
Logger::pgwc_app().debug("Update PGW context\n");
sc = supi_2_smf_context(supi64);
} else {
Logger::pgwc_app().debug("Create a new PGW context\n");
sc = std::shared_ptr<pgw_context>(new pgw_context());
set_supi_2_smf_context(supi64, sc);
}
//update context with dnn information
std::shared_ptr<dnn_context> sd;
if (!sc.get()->find_dnn_context(dnn, sd)) {
if (nullptr == sd.get()){
//create a new one and insert to the list
Logger::pgwc_app().debug("Create a DNN context and add to the PGW context\n");
sd = std::shared_ptr<dnn_context>(new dnn_context(dnn));
//sd.get()->in_use = true;
sc.get()->insert_dnn(sd);
}
}
// step 4. retrieve Session Management Subscription data from UDM if not available (step 4, section 4.3.2 3GPP TS 23.502)
std::string dnn_selection_mode = sm_context_req_msg->get_dnn_selection_mode();
if (not is_use_local_configuration_subscription_data(dnn_selection_mode) && not is_supi_dnn_snssai_subscription_data(supi, dnn, snssai))
{
//uses a dummy UDM to test this part
Logger::pgwc_app().debug("Retrieve Session Management Subscription data from UDM");
std::shared_ptr<session_management_subscription> subscription = std::shared_ptr<session_management_subscription>(new session_management_subscription (snssai));
if (smf_n10_inst->get_sm_data(supi64, dnn, snssai, subscription)) {
//update dnn_context with subscription info
sd.get()->insert_dnn_subscription(snssai, subscription);
//debug
//dnn_configuration_t dnn_configuration = subscription.get()->get_dnn_configuration(dnn);
//Logger::pgwc_app().debug("Retrieve Session Management Subscription data from UDM %s, %s, %s, %s", pdu_session_type_e2str[dnn_configuration.pdu_session_types.default_session_type.pdu_session_type].c_str(), ssc_mode_e2str[dnn_configuration.ssc_modes.default_ssc_mode.ssc_mode].c_str(), dnn_configuration.session_ambr.uplink.c_str(), dnn_configuration.session_ambr.downlink.c_str());
}
}
//Step 4. check the validity of the UE request, if valid send PDU Session Accept, otherwise send PDU Session Reject to AMF
//Step 5. let the context handle the message
//in this step, SMF will send N4 Session Establishment/Modification to UPF (step 10a, section 4.3.2 3GPP 23.502)
//SMF, then, sends response to AMF
sc.get()->handle_amf_msg(sm_context_req_msg, httpResponse);
}
......@@ -28,12 +28,22 @@
#ifndef FILE_PGW_APP_HPP_SEEN
#define FILE_PGW_APP_HPP_SEEN
#include "smf.h"
#include "3gpp_29.274.h"
#include "itti_msg_s5s8.hpp"
#include "itti_msg_sxab.hpp"
#include "pgw_context.hpp"
#include "pgw_pco.hpp"
#include "SmContextCreateData.h"
#include "SmContextCreateError.h"
#include "pistache/endpoint.h"
#include "pistache/http.h"
#include "pistache/router.h"
#include "smf_msg.hpp"
extern "C" {
#include "sm_msg.h"
}
#include <map>
#include <set>
......@@ -65,6 +75,11 @@ private:
mutable std::shared_mutex m_s5s8lteid2pgw_context;
mutable std::shared_mutex m_seid2pgw_context;
//for SMF
std::map<supi64_t, std::shared_ptr<pgw_context>> supi2pgw_context;
mutable std::shared_mutex m_supi2smf_context;
int apply_config(const pgw_config& cfg);
teid_t generate_s5s8_cp_teid();
......@@ -133,6 +148,68 @@ public:
void handle_itti_msg (itti_sxab_association_setup_request& m);
void restore_sx_sessions(const seid_t& seid) const;
/*
* Handle PDUSession_CreateSMContextRequest from AMF
* @param [std::shared_ptr<pdu_session_create_sm_context_request>&] sm_context_req_msg Request message
* @param [Pistache::Http::ResponseWriter& ] httpResponse To send a response to AMF
* @return void
*/
void handle_amf_msg(std::shared_ptr<pdu_session_create_sm_context_request>& sm_context_req_msg, Pistache::Http::ResponseWriter &httpResponse);
/*
* Verify if SM Context is existed for this Supi
* @param [supi_t] supi
* @return True if existed, otherwise false
*/
bool is_supi_2_smf_context(const supi64_t& supi) const;
/*
* Create/Update SMF context with the corresponding supi
* @param [supi_t] supi
* @param [std::shared_ptr<pgw_context>] sc Shared_ptr Pointer to an SMF context
* @return True if existed, otherwise false
*/
void set_supi_2_smf_context(const supi64_t& supi, std::shared_ptr<pgw_context> sc);
/*
* Get SM Context
* @param [supi_t] Supi
* @return Shared pointer to SM context
*/
std::shared_ptr<pgw_context> supi_2_smf_context(const supi64_t& supi) const;
/*
* Check whether SMF uses local configuration instead of retrieving Session Management Data from UDM
* @param [std::string] dnn_selection_mode
* @return True if SMF uses the local configuration to check the validity of the UE request, False otherwise
*/
bool is_use_local_configuration_subscription_data(const std::string& dnn_selection_mode);
/*
* Verify whether the Session Management Data is existed
* @param [supi_t] SUPI
* @param [std::string] DNN
* @param [snssai_t] S-NSSAI
* @return True if SMF uses the local configuration to check the validity of the UE request, False otherwise
*/
bool is_supi_dnn_snssai_subscription_data(supi_t& supi, std::string& dnn, snssai_t& snssai);
/*
* Verify whether the UE request is valid according to the user subscription and with local policies
* @param [..]
* @return True if the request is valid, otherwise False
*/
bool is_create_sm_context_request_valid();
/*
* Send create session response to AMF
* @param [Pistache::Http::ResponseWriter] httpResponse
* @param [ oai::smf::model::SmContextCreateError] smContextCreateError
*
*/
void send_create_session_response(Pistache::Http::ResponseWriter& httpResponse, oai::smf::model::SmContextCreateError& smContextCreateError, Pistache::Http::Code code);
};
}
#include "pgw_config.hpp"
......
......@@ -594,3 +594,25 @@ pgw_config::~pgw_config()
{
}
//------------------------------------------------------------------------------
bool pgw_config::is_dotted_dnn_handled(const std::string& dnn, const pdu_session_type_t& pdn_session_type)
{
return true; //test
Logger::pgwc_app().debug( "DNN: %s", dnn.c_str());
for (int i = 0; i < pgw_cfg.num_apn; i++) {
Logger::pgwc_app().debug( "apn_label: %s", pgw_cfg.apn[i].apn_label.c_str());
if (0 == dnn.compare(pgw_cfg.apn[i].apn_label)) {
if (pdn_session_type.pdu_session_type == pgw_cfg.apn[i].pdn_type.pdn_type) {
return true;
}
}
}
return false;
}
......@@ -35,6 +35,8 @@
#include "pfcp.hpp"
#include "thread_sched.hpp"
#include "smf.h"
#include <arpa/inet.h>
#include <libconfig.h++>
#include <netinet/in.h>
......@@ -246,6 +248,7 @@ public:
bool is_dotted_apn_handled(const std::string& apn, const pdn_type_t& pdn_type);
int get_pfcp_node_id(pfcp::node_id_t& node_id);
int get_pfcp_fseid(pfcp::fseid_t& fseid);
bool is_dotted_dnn_handled(const std::string& apn, const pdu_session_type_t& pdn_session_type);
};
} // namespace pgw
......
......@@ -33,6 +33,9 @@
#include "pgw_context.hpp"
#include "pgw_paa_dynamic.hpp"
#include "pgwc_procedure.hpp"
#include "ProblemDetails.h"
#include "3gpp_29.502.h"
#include <algorithm>
......@@ -967,8 +970,336 @@ std::string pgw_context::toString() const
s.append(it->toString());
}
//s.append("\tIMSI:\t"+toString(p.msisdn));
//apns.reserve(MAX_APN_PER_UE);
return s;
//s.append("\tIMSI:\t"+toString(p.msisdn));
//apns.reserve(MAX_APN_PER_UE);
return s;
}
//TTN
//------------------------------------------------------------------------------
void pgw_context::handle_amf_msg (std::shared_ptr<pdu_session_create_sm_context_request>& sm_context_req_msg, Pistache::Http::ResponseWriter &httpResponse)
{
Logger::pgwc_app().info("Handle AMF message");
//Step 1. get necessary information
Logger::pgwc_app().debug("Handle AMF message, supi " SUPI_64_FMT " ", sm_context_req_msg->get_supi());
std::string dnn = sm_context_req_msg->get_dnn();
//oai::smf::model::Snssai snssai_sm = smContextCreateData.getSNssai();
snssai_t snssai = sm_context_req_msg->get_snssai();
std::string requestType = sm_context_req_msg->get_request_type();
supi_t supi = sm_context_req_msg->get_supi();
supi64_t supi64 = smf_supi_to_u64(supi);
uint32_t pdu_session_id = sm_context_req_msg->get_pdu_sessionId();
oai::smf::model::SmContextCreateError smContextCreateError;
oai::smf::model::ProblemDetails problem_details;
bool request_accepted = true;
//problem_details.setCause()
//Step 2. check the validity of the UE request, if valid send PDU Session Accept, otherwise send PDU Session Reject to AMF
if (!verify_sm_context_request(sm_context_req_msg)){ //TODO: Need to implement this function
// Not a valid request...
Logger::pgwc_app().warn("Received PDU_SESSION_CREATESMCONTEXT_REQUEST, the request is not valid!");
problem_details.setCause(pdu_session_application_error_e2str[PDU_SESSION_APPLICATION_ERROR_SUBSCRIPTION_DENIED]); //TODO: add causes to header file
smContextCreateError.setError(problem_details);
//TODO: create a PDU Session Establishment Response by relying on NAS and assign to smContextCeateError.m_N1SmMsg
send_create_session_response_error(smContextCreateError, Pistache::Http::Code::Forbidden, httpResponse);
return;
}
//store HttpResponse and session-related information to be used when receiving the response from UPF
pgwc::pdu_session_create_sm_context_response *sm_context_resp = new pdu_session_create_sm_context_response(httpResponse);
std::shared_ptr<pdu_session_create_sm_context_response> sm_context_resp_pending = std::shared_ptr<pdu_session_create_sm_context_response>(sm_context_resp);
//step 3. find pdn_connection
std::shared_ptr<dnn_context> sd;
bool find_dnn = find_dnn_context (dnn, sd);
//step 3.1. create dnn context if not exist
//At this step, this context should be existed
if (nullptr == sd.get()) {
Logger::pgwc_app().debug("DNN context (dnn_in_use %s) is not existed yet!", dnn.c_str());
dnn_context *d = new (dnn_context);
d->in_use = true;
d->dnn_in_use = dnn;
//ambr
//insert
sd = std::shared_ptr<dnn_context> (d);
insert_dnn(sd);
} else {
sd.get()->dnn_in_use = dnn;
Logger::pgwc_app().debug("DNN context (dnn_in_use %s) is already existed", dnn.c_str());
}
//step 3.2. create pdn connection if not exist
std::shared_ptr<pgw_pdn_connection> sp;
bool find_pdn = sd.get()->find_pdn_connection(pdu_session_id, sp);
if (nullptr == sp.get()){
Logger::pgwc_app().debug("Create a new PDN connection!");
//create a new pdn connection
pgw_pdn_connection *p = new (pgw_pdn_connection);
p->pdn_type.pdn_type = sm_context_req_msg->get_pdu_session_type();
p->pdn_type.pdn_type = PDN_TYPE_E_IPV4; //TODO: should be removed after get the correct information from NAS_MSG
p->pdu_session_id = pdu_session_id; //should check also nas_msg.pdusessionidentity ??
//amf id
p->amf_id = sm_context_req_msg->get_serving_nfId();
sp = std::shared_ptr<pgw_pdn_connection>(p);
sd->insert_pdn_connection(sp);
} else{
Logger::pgwc_app().debug("PDN connection is already existed!");
//TODO:
}
//pending session??