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

update PDUSessionCreateSMContext Req process

parent c2099bd2
......@@ -43,16 +43,16 @@ git checkout develop
## install dependencies
cd /oai-cn5g-smf/build/scripts
./build_spgwc -I -f
./build_smf -I -f
## build SMF
./build_spgwc -c -V -b Debug -j
./build_smf -c -V -b Debug -j
## Create configuration file for SMF
cd /oai-cn5g-smf/src/test/inputs
./spgwc_conf.sh
./smf_conf.sh
## launch SMF
sudo spgwc -c /usr/local/etc/oai/spgw_c.conf -o
sudo smf -c /usr/local/etc/oai/smf.conf -o
## Build UPF (SPGWU)
git clone https://github.com/OPENAIRINTERFACE/openair-cn-cups/
......
################################################################################
# Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
# contributor license agreements. See the NOTICE file distributed with
# this work for additional information regarding copyright ownership.
# The OpenAirInterface Software Alliance licenses this file to You under
# the OAI Public License, Version 1.1 (the "License"); you may not use this file
# except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.openairinterface.org/?page_id=698
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#-------------------------------------------------------------------------------
# For more information about the OpenAirInterface (OAI) Software Alliance:
# contact@openairinterface.org
################################################################################
cmake_minimum_required (VERSION 3.0.2)
# Override options for SPGW
set ( PACKAGE_NAME "S/P-GW-C" )
set ( STATIC_LINKING False )
#############################################
# Base directories, compatible with legacy OAI building
################################################
set (OPENAIRCN_DIR $ENV{OPENAIRCN_DIR})
set (BUILD_TOP_DIR ${OPENAIRCN_DIR}/build)
set (SRC_TOP_DIR $ENV{OPENAIRCN_DIR}/src)
include(${CMAKE_CURRENT_SOURCE_DIR}/../../src/oai_spgwc/CMakeLists.txt)
ADD_SUBDIRECTORY(${CMAKE_CURRENT_SOURCE_DIR}/../../src/sgwc ${CMAKE_CURRENT_BINARY_DIR}/sgwc)
ADD_SUBDIRECTORY(${CMAKE_CURRENT_SOURCE_DIR}/../../src/pgwc ${CMAKE_CURRENT_BINARY_DIR}/pgwc)
......@@ -29,7 +29,10 @@ void IndividualSMContextApiImpl::retrieve_sm_context(const std::string &smContex
response.send(Pistache::Http::Code::Ok, "Do some magic\n");
}
void IndividualSMContextApiImpl::update_sm_context(const std::string &smContextRef, const SmContextUpdateData &smContextUpdateData, Pistache::Http::ResponseWriter &response) {
response.send(Pistache::Http::Code::Ok, "Do some magic\n");
//handle Nsmf_PDUSession_UpdateSMContext Request
//Handle the pdu_session_create_sm_context_request message in pwg_app
//m_smf_app->handle_amf_msg(sm_context_req_msg, response);
response.send(Pistache::Http::Code::Ok, "Do some magic\n");
}
}
......
......@@ -13,6 +13,7 @@
#include "SMContextsCollectionApiImpl.h"
#include "logger.hpp"
#include "smf_msg.hpp"
#include "itti_msg_n11.hpp"
extern "C" {
#include "nas_message.h"
......@@ -73,24 +74,23 @@ void SMContextsCollectionApiImpl::post_sm_contexts(const SmContextMessage &smCon
decoded_nas_msg.header.message_authentication_code);
//Step 2. Create a pdu_session_create_sm_context_request message and store the necessary information
pgwc::pdu_session_create_sm_context_request *sm_context_req = new pgwc::pdu_session_create_sm_context_request();
std::shared_ptr<pgwc::pdu_session_create_sm_context_request> sm_context_req_msg = std::shared_ptr<pgwc::pdu_session_create_sm_context_request>(sm_context_req);
pgwc::pdu_session_create_sm_context_request sm_context_req_msg = {};
//supi
supi_t supi = {.length = 0};
smf_string_to_supi(&supi, smContextCreateData.getSupi().c_str());
sm_context_req_msg->set_supi(supi);
sm_context_req_msg.set_supi(supi);
//dnn
sm_context_req_msg->set_dnn(smContextCreateData.getDnn());
sm_context_req_msg.set_dnn(smContextCreateData.getDnn());
//S-Nssai
snssai_t snssai(smContextCreateData.getSNssai().getSst(), smContextCreateData.getSNssai().getSd());
sm_context_req_msg->set_snssai(snssai);
sm_context_req_msg.set_snssai(snssai);
//PDU session ID
sm_context_req_msg->set_pdu_session_id(smContextCreateData.getPduSessionId());
sm_context_req_msg.set_pdu_session_id(smContextCreateData.getPduSessionId());
//AMF ID
sm_context_req_msg->set_serving_nf_id(smContextCreateData.getServingNfId()); //TODO: should be verified that AMF ID is stored in GUAMI or ServingNfId
sm_context_req_msg.set_serving_nf_id(smContextCreateData.getServingNfId()); //TODO: should be verified that AMF ID is stored in GUAMI or ServingNfId
//Request Type
sm_context_req_msg->set_request_type(smContextCreateData.getRequestType());
sm_context_req_msg.set_request_type(smContextCreateData.getRequestType());
//PCF ID
// Priority Access
//User Location Information
......@@ -99,13 +99,13 @@ void SMContextsCollectionApiImpl::post_sm_contexts(const SmContextMessage &smCon
//GPSI
// UE presence in LADN service area
// DNN Selection Mode
sm_context_req_msg->set_dnn_selection_mode(smContextCreateData.getSelMode());
sm_context_req_msg.set_dnn_selection_mode(smContextCreateData.getSelMode());
//Subscription for PDU Session Status Notification
// Trace requirement
//From N1 Container (NAS)
//Extended protocol discriminator (Mandatory)
sm_context_req_msg->set_epd(decoded_nas_msg.header.extended_protocol_discriminator);
sm_context_req_msg.set_epd(decoded_nas_msg.header.extended_protocol_discriminator);
//PDU session ID (Mandatory)
//TODO:
//PTI (Mandatory)
......@@ -115,10 +115,10 @@ void SMContextsCollectionApiImpl::post_sm_contexts(const SmContextMessage &smCon
//sm_context_req_msg->set_message_type(decoded_nas_msg.plain.sm.pdu_session_establishment_request.messagetype);
//Logger::smf_api_server().debug("nas decode messaget type %d\n",
// decoded_nas_msg.plain.sm.pdu_session_establishment_request.messagetype);
sm_context_req_msg->set_message_type (PDU_SESSION_ESTABLISHMENT_REQUEST); //Temporary - should be removed
sm_context_req_msg.set_message_type (PDU_SESSION_ESTABLISHMENT_REQUEST); //Temporary - should be removed
//Integrity protection maximum data rate (Mandatory)
//PDU session type (Optional)
sm_context_req_msg->set_pdu_session_type(PDN_TYPE_E_IPV4);//TODO: should get from NAS msg
sm_context_req_msg.set_pdu_session_type(PDN_TYPE_E_IPV4);//TODO: should get from NAS msg
//SSC mode (Optional)
//5GSM capability (Optional)
//Maximum number of supported (Optional)
......@@ -128,7 +128,16 @@ void SMContextsCollectionApiImpl::post_sm_contexts(const SmContextMessage &smCon
//Extended protocol configuration options (Optional) e.g, FOR DHCP
//Step 3. Handle the pdu_session_create_sm_context_request message in pwg_app
m_smf_app->handle_amf_msg(sm_context_req_msg, response);
//m_smf_app->handle_amf_msg(sm_context_req_msg, response);
itti_n11_create_sm_context_request *itti_msg = new itti_n11_create_sm_context_request(TASK_SMF_N11, TASK_PGWC_APP, response);
itti_msg->req = sm_context_req_msg;
std::shared_ptr<itti_n11_create_sm_context_request> i = std::shared_ptr<itti_n11_create_sm_context_request>(itti_msg);
m_smf_app->handle_amf_msg(i);
}
......
......@@ -33,6 +33,9 @@ class Snssai
{
public:
Snssai();
Snssai(uint8_t sst, uint32_t sd): m_Sst(sst), m_Sd(sd) {
m_SdIsSet = true;
};
virtual ~Snssai();
void validate();
......
......@@ -24,6 +24,7 @@
#define FILE_3GPP_29_503_SMF_SEEN
#include "smf.h"
#include "3gpp_29.571.h"
enum ssc_mode_e {
SSC_MODE_1 = 1,
......@@ -51,15 +52,15 @@ typedef struct ssc_modes_s {
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;
//5gQoSProfile (subscribedDefaultQoS)
//5qi
//staticIpAddresses
} dnn_configuration_t;
......
/*
* 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_571_SEEN
#define FILE_3GPP_29_571_SEEN
typedef struct session_ambr_s {
std::string uplink;
std::string downlink;
} session_ambr_t;
enum preemtion_capability_e {
NOT_PREEMPT = 1,
MAY_PREEMPT = 2
};
static const std::vector<std::string> preemtion_capability_e2str = {"Error", "NOT_PREEMPT", "MAY_PREEMPT"};
typedef struct arp_s {
uint8_t priority_level;// (integer 1-15)
std::string preempt_cap;
std::string preempt_vuln; //NOT_PREEMPTABLE, PREEMPTABLE
} arp_5gc_t;
typedef struct subscribed_default_qos_s{
uint8_t _5qi;
arp_5gc_t arp;
uint8_t priority_level;//1-127
};
#endif
......@@ -40,6 +40,7 @@ add_library (PGWC STATIC
pgwc_procedure.cpp
pgwc_sxab.cpp
smf_n10.cpp
smf_n11.cpp
smf_msg.cpp
#pgw_pcef_emulation.cpp
)
......
......@@ -35,6 +35,7 @@
#include "pgw_s5s8.hpp"
#include "pgwc_sxab.hpp"
#include "smf_n10.hpp"
#include "smf_n11.hpp"
#include "string.hpp"
#include "SmContextCreateError.h"
#include "3gpp_29.502.h"
......@@ -55,6 +56,7 @@ extern pgw_config pgw_cfg;
pgw_s5s8 *pgw_s5s8_inst = nullptr;
pgwc_sxab *pgwc_sxab_inst = nullptr;
smf_n10 *smf_n10_inst = nullptr;
smf_n11 *smf_n11_inst = nullptr;
extern itti_mw *itti_inst;
void pgw_app_task (void*);
......@@ -299,6 +301,7 @@ pgw_app::pgw_app (const std::string& config_file) : m_s5s8_cp_teid_generator(),
pgw_s5s8_inst = new pgw_s5s8();
pgwc_sxab_inst = new pgwc_sxab();
smf_n10_inst = new smf_n10();
smf_n11_inst = new smf_n11();
} catch (std::exception& e) {
Logger::pgwc_app().error( "Cannot create PGW_APP: %s", e.what() );
throw;
......@@ -640,6 +643,142 @@ void pgw_app::handle_itti_msg (std::shared_ptr<itti_sxab_session_report_request>
}
}
//------------------------------------------------------------------------------
void pgw_app::handle_amf_msg (std::shared_ptr<itti_n11_create_sm_context_request> smreq)
{
//handle PDU Session Create SM Context Request as specified in section 4.3.2 3GPP TS 23.502
pdu_session_create_sm_context_request sm_context_req_msg = smreq->req;
oai::smf::model::SmContextCreateError smContextCreateError;
oai::smf::model::ProblemDetails problem_details;
//Step 1. get necessary information
supi_t supi = smreq->req.get_supi();
supi64_t supi64 = smf_supi_to_u64(supi);
std::string dnn = smreq->req.get_dnn();
snssai_t snssai = smreq->req.get_snssai();
procedure_transaction_id_t pti = smreq->req.get_pti();
pdu_session_type_t pdu_session_type = {.pdu_session_type = smreq->req.get_pdu_session_type()};
pdu_session_id_t pdu_session_id = smreq->req.get_pdu_session_id();
uint8_t message_type = smreq->req.get_message_type();
request_type_t request_type = smreq->req.get_request_type();
Logger::pgwc_app().info("Handle a PDU Session Create SM Context Request message from AMF, supi " SUPI_64_FMT ", dnn %s, snssai_sst %d", supi64, dnn.c_str(), snssai.sST );
//check pti
if ((pti.procedure_transaction_id == PROCEDURE_TRANSACTION_IDENTITY_UNASSIGNED) || (pti.procedure_transaction_id > PROCEDURE_TRANSACTION_IDENTITY_LAST)){
Logger::pgwc_app().warn(" Invalid PTI value (pti = %d)\n", pti.procedure_transaction_id);
problem_details.setCause(pdu_session_application_error_e2str[PDU_SESSION_APPLICATION_ERROR_N1_SM_ERROR]);
smContextCreateError.setError(problem_details);
//create a PDU Session Establishment Response by relying on NAS and assign to smContextCeateError.m_N1SmMsg
//TODO: (24.501 (section 7.3.1)) NAS N1 SM message: response with a 5GSM STATUS message including cause "#81 Invalid PTI value"
//Send response to AMF
send_create_session_response(smreq->http_response, smContextCreateError, Pistache::Http::Code::Forbidden);
}
//check pdu session id
if ((pdu_session_id == PDU_SESSION_IDENTITY_UNASSIGNED) || (pdu_session_id > PDU_SESSION_IDENTITY_LAST)){
Logger::pgwc_app().warn(" Invalid PDU Session ID value (psi = %d)\n", pdu_session_id);
//TODO: (24.501 (section 7.3.2)) NAS N1 SM message: ignore the message
//return;
}
//check message type
if (message_type != PDU_SESSION_ESTABLISHMENT_REQUEST) {
Logger::pgwc_app().warn("Invalid message type (message type = %d)\n", message_type);
//TODO:
problem_details.setCause(pdu_session_application_error_e2str[PDU_SESSION_APPLICATION_ERROR_N1_SM_ERROR]);
smContextCreateError.setError(problem_details);
//create a PDU Session Establishment Response by relying on NAS and assign to smContextCeateError.m_N1SmMsg
//TODO: (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."
//Send response to AMF
send_create_session_response(smreq->http_response, smContextCreateError, Pistache::Http::Code::Forbidden);
}
//check request type
if ((request_type & 0x07) != INITIAL_REQUEST){
Logger::pgwc_app().warn("Invalid request type (request type = %s)\n", request_type_e2str[request_type & 0x07]);
//TODO:
}
//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());
problem_details.setCause(pdu_session_application_error_e2str[PDU_SESSION_APPLICATION_ERROR_DNN_DENIED]);
smContextCreateError.setError(problem_details);
//create a PDU Session Establishment Response by relying on NAS and assign to smContextCeateError.m_N1SmMsg
//Send response to AMF
send_create_session_response(smreq->http_response, 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 = smreq->req.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
sc.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());
} else {
// Not accept to establish a PDU session
Logger::pgwc_app().warn("Received PDU_SESSION_CREATESMCONTEXT_REQUEST, couldn't retrieve the Session Management Subscription from UDM, ignore message!");
problem_details.setCause(pdu_session_application_error_e2str[PDU_SESSION_APPLICATION_ERROR_SUBSCRIPTION_DENIED]);
smContextCreateError.setError(problem_details);
//create a PDU Session Establishment Response by relying on NAS and assign to smContextCeateError.m_N1SmMsg
//Send response to AMF
send_create_session_response(smreq->http_response, smContextCreateError, Pistache::Http::Code::Forbidden);
return;
}
}
//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(smreq);
}
//------------------------------------------------------------------------------
bool pgw_app::is_supi_2_smf_context(const supi64_t& supi) const
{
......@@ -799,7 +938,7 @@ void pgw_app::handle_amf_msg(std::shared_ptr<pdu_session_create_sm_context_reque
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);
sc.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());
......
......@@ -32,6 +32,7 @@
#include "3gpp_29.274.h"
#include "itti_msg_s5s8.hpp"
#include "itti_msg_sxab.hpp"
#include "itti_msg_n11.hpp"
#include "pgw_context.hpp"
#include "pgw_pco.hpp"
#include "SmContextCreateData.h"
......@@ -153,6 +154,7 @@ public:
*/
void handle_amf_msg(std::shared_ptr<pdu_session_create_sm_context_request>& sm_context_req_msg, Pistache::Http::ResponseWriter &httpResponse);
void handle_amf_msg (std::shared_ptr<itti_n11_create_sm_context_request> smreq);
/*
* Verify if SM Context is existed for this Supi
* @param [supi_t] supi
......
......@@ -36,7 +36,7 @@
#include "ProblemDetails.h"
#include "3gpp_29.502.h"
#include "3gpp_24.501.h"
#include "SmContextCreatedData.h"
#include <algorithm>
using namespace pgwc;
......@@ -982,7 +982,7 @@ std::string pgw_context::toString() const
//------------------------------------------------------------------------------
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");
oai::smf::model::SmContextCreateError smContextCreateError;
......@@ -1093,7 +1093,7 @@ void pgw_context::handle_amf_msg (std::shared_ptr<pdu_session_create_sm_context_
std::shared_ptr<session_management_subscription> ss;
std::shared_ptr<dnn_configuration_t> sdc;
sd.get()->find_dnn_subscription(snssai, ss);
find_dnn_subscription(snssai, ss);
if (nullptr != ss.get()){
ss.get()->find_dnn_configuration(sd->dnn_in_use, sdc);
if (nullptr != sdc.get()){
......@@ -1143,8 +1143,10 @@ void pgw_context::handle_amf_msg (std::shared_ptr<pdu_session_create_sm_context_
break;
}
//step 8. create session establishment procedure and run the procedure
//TODO: if "Integrity Protection is required", check UE Integrity Protection Maximum Data Rate
//TODO: (Optional) Secondary authentication/authorization
//step 8. create session establishment procedure and run the procedure
//if request is accepted
if (request_accepted){
if (set_paa) {
......@@ -1158,6 +1160,20 @@ void pgw_context::handle_amf_msg (std::shared_ptr<pdu_session_create_sm_context_
//}
}
//IMPORTANT!!
//should send PDU SessionCreate SM Context Response here in stead of after receiving N4 Session Establishment Response
//Send reply to AMF
//location header contains the URI of the created resource
Logger::pgwc_app().info("Sending response to AMF!");
nlohmann::json jsonData;
oai::smf::model::SmContextCreatedData smContextCreatedData;
//include only SmfServiceInstanceId (See section 6.1.6.2.3, 3GPP TS 29.502 v16.0.0)
to_json(jsonData, smContextCreatedData);
std::string resBody = jsonData.dump();
httpResponse.send(Pistache::Http::Code::Created, resBody);
session_establishment_procedure* proc = new session_establishment_procedure(sp);
std::shared_ptr<pgw_procedure> sproc = std::shared_ptr<pgw_procedure>(proc);
......@@ -1169,7 +1185,228 @@ void pgw_context::handle_amf_msg (std::shared_ptr<pdu_session_create_sm_context_
}
}else{ //if request is rejected
//TODO:
//un-subscribe to the modifications of Session Management Subscription data for (SUPI, DNN, S-NSSAI)
}
//step 9. send ITTI message to PGW s5s8 for the pending session?
//TODO:
*/
}
//------------------------------------------------------------------------------
void pgw_context::handle_amf_msg (std::shared_ptr<itti_n11_create_sm_context_request> smreq)
{
Logger::pgwc_app().info("Handle AMF message");
pdu_session_create_sm_context_request sm_context_req_msg = smreq->req;
oai::smf::model::SmContextCreateError smContextCreateError;
oai::smf::model::ProblemDetails problem_details;
bool request_accepted = true;
//Step 1. get necessary information
std::string dnn = sm_context_req_msg.get_dnn();
snssai_t snssai = sm_context_req_msg.get_snssai();
request_type_t request_type = 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_session_id();
//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(smreq)){ //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, smreq->http_response);
return;
}
//store HttpResponse and session-related information to be used when receiving the response from UPF
itti_n11_create_sm_context_response *sm_context_resp = new itti_n11_create_sm_context_response(TASK_PGWC_APP, TASK_SMF_N11, smreq->http_response);
//pgwc::pdu_session_create_sm_context_response *sm_context_resp = new pdu_session_create_sm_context_response(smreq->http_response);
std::shared_ptr<itti_n11_create_sm_context_response> sm_context_resp_pending = std::shared_ptr<itti_n11_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->pdu_session_id = pdu_session_id; //should check also nas_msg.pdusessionidentity ??
//amf id
p->amf_id = sm_context_req_msg.get_serving_nf_id();
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??
//step 4. check if supi is authenticated
//address allocation based on PDN type
//step 5. paa
bool set_paa = false;
paa_t paa = {};
//step 6. pco
//section 6.2.4.2, TS 24.501
//If the UE wants to use DHCPv4 for IPv4 address assignment, it shall indicate that to the network within the Extended
//protocol configuration options IE in the PDU SESSION ESTABLISHMENT REQUEST
//Extended protocol configuration options: See subclause 10.5.6.3A in 3GPP TS 24.008.
//ExtendedProtocolConfigurationOptions extended_protocol_options = (sm_context_req_msg.get_nas_msg()).extendedprotocolconfigurationoptions;
//TODO: PCO