Commit 0d1c5fd6 authored by Tien-Thinh Nguyen's avatar Tien-Thinh Nguyen

add Release SM Context procedure

parent 0590fb18
...@@ -87,84 +87,16 @@ void IndividualSMContextApi::setupRoutes() { ...@@ -87,84 +87,16 @@ void IndividualSMContextApi::setupRoutes() {
void IndividualSMContextApi::release_sm_context_handler( void IndividualSMContextApi::release_sm_context_handler(
const Pistache::Rest::Request &request, const Pistache::Rest::Request &request,
Pistache::Http::ResponseWriter response) { Pistache::Http::ResponseWriter response) {
// Getting the path params
auto smContextRef = request.param(":smContextRef").as<std::string>();
//TODO: to be updated as update_sm_context_handler
Logger::smf_api_server().info(
"Received a Nsmf_PDUSession_UpdateSMContext: PDU Session Release request from AMF");
Logger::smf_api_server().debug("Request body: %s\n", request.body().c_str());
SmContextReleaseMessage smContextReleaseMessage = { };
//find boundary
std::size_t found = request.body().find("Content-Type");
std::string boundary_str = request.body().substr(2, found - 4);
Logger::smf_api_server().debug("Boundary: %s", boundary_str.c_str());
//step 1. use multipartparser to decode the request
multipartparser_callbacks_init(&g_callbacks);
g_callbacks.on_body_begin = &on_body_begin;
g_callbacks.on_part_begin = &on_part_begin;
g_callbacks.on_header_field = &on_header_field;
g_callbacks.on_header_value = &on_header_value;
g_callbacks.on_headers_complete = &on_headers_complete;
g_callbacks.on_data = &on_data;
g_callbacks.on_part_end = &on_part_end;
g_callbacks.on_body_end = &on_body_end;
multipartparser parser = { };
init_globals();
multipartparser_init(&parser,
reinterpret_cast<const char*>(boundary_str.c_str()));
unsigned int str_len = request.body().length();
unsigned char *data = (unsigned char*) malloc(str_len + 1);
memset(data, 0, str_len + 1);
memcpy((void*) data, (void*) request.body().c_str(), str_len);
//if ((multipartparser_execute(&parser, &g_callbacks, request.body().c_str(), strlen(request.body().c_str())) != strlen(request.body().c_str())) or (!g_body_begin_called)){
if ((multipartparser_execute(&parser, &g_callbacks,
reinterpret_cast<const char*>(data), str_len)
!= strlen(request.body().c_str())) or (!g_body_begin_called)) {
Logger::smf_api_server().warn(
"The received message can not be parsed properly!");
//TODO: fix this issue
//response.send(Pistache::Http::Code::Bad_Request, "");
//return;
}
free_wrapper((void**) &data);
uint8_t size = g_parts.size();
Logger::smf_api_server().debug("Number of g_parts %d", g_parts.size());
part p0 = g_parts.front();
g_parts.pop_front();
Logger::smf_api_server().debug("Request body, part 1: %s", p0.body.c_str());
part p1 = { };
if (size > 1) {
p1 = g_parts.front();
g_parts.pop_front();
Logger::smf_api_server().debug("Request body, part 2: %s (%d bytes)",
p1.body.c_str(), p1.body.length());
//part p2 = g_parts.front(); g_parts.pop_front();
//Logger::smf_api_server().debug("Request body, part 3: \n %s",p2.body.c_str());
}
// Getting the body param // Getting the body param
SmContextReleaseData smContextReleaseData = { };
try { SmContextReleaseData smContextReleaseData;
nlohmann::json::parse(p0.body.c_str()).get_to(smContextReleaseData);
smContextReleaseMessage.setJsonData(smContextReleaseData);
if (size > 1) {
if (smContextReleaseData.n2SmInfoIsSet()) {
//N2 SM (for Session establishment, or for session modification)
Logger::smf_api_server().debug("N2 SM information is set");
smContextReleaseMessage.setBinaryDataN2SmInformation(p1.body);
}
}
// Getting the path params
auto smContextRef = request.param(":smContextRef").as<std::string>();
this->release_sm_context(smContextRef, smContextReleaseMessage, response);
try {
nlohmann::json::parse(request.body()).get_to(smContextReleaseData);
this->release_sm_context(smContextRef, smContextReleaseData, response);
} catch (nlohmann::detail::exception &e) { } catch (nlohmann::detail::exception &e) {
//send a 400 error //send a 400 error
response.send(Pistache::Http::Code::Bad_Request, e.what()); response.send(Pistache::Http::Code::Bad_Request, e.what());
...@@ -176,6 +108,7 @@ void IndividualSMContextApi::release_sm_context_handler( ...@@ -176,6 +108,7 @@ void IndividualSMContextApi::release_sm_context_handler(
} }
} }
void IndividualSMContextApi::retrieve_sm_context_handler( void IndividualSMContextApi::retrieve_sm_context_handler(
const Pistache::Rest::Request &request, const Pistache::Rest::Request &request,
Pistache::Http::ResponseWriter response) { Pistache::Http::ResponseWriter response) {
......
...@@ -98,7 +98,7 @@ class IndividualSMContextApi { ...@@ -98,7 +98,7 @@ class IndividualSMContextApi {
/// <param name="smContextReleaseData">representation of the data to be sent to the SMF when releasing the SM context (optional)</param> /// <param name="smContextReleaseData">representation of the data to be sent to the SMF when releasing the SM context (optional)</param>
virtual void release_sm_context( virtual void release_sm_context(
const std::string &smContextRef, const std::string &smContextRef,
const SmContextReleaseMessage &smContextReleaseMessage, const SmContextReleaseData &smContextReleaseData,
Pistache::Http::ResponseWriter &response) = 0; Pistache::Http::ResponseWriter &response) = 0;
/// <summary> /// <summary>
......
...@@ -50,7 +50,7 @@ IndividualSMContextApiImpl::IndividualSMContextApiImpl( ...@@ -50,7 +50,7 @@ IndividualSMContextApiImpl::IndividualSMContextApiImpl(
void IndividualSMContextApiImpl::release_sm_context( void IndividualSMContextApiImpl::release_sm_context(
const std::string &smContextRef, const std::string &smContextRef,
const SmContextReleaseMessage &smContextReleaseMessage, const SmContextReleaseData &smContextReleaseData,
Pistache::Http::ResponseWriter &response) { Pistache::Http::ResponseWriter &response) {
//TODO: to be updated as update_sm_context_handler //TODO: to be updated as update_sm_context_handler
...@@ -58,30 +58,15 @@ void IndividualSMContextApiImpl::release_sm_context( ...@@ -58,30 +58,15 @@ void IndividualSMContextApiImpl::release_sm_context(
//handle Nsmf_PDUSession_UpdateSMContext Request //handle Nsmf_PDUSession_UpdateSMContext Request
Logger::smf_api_server().info( Logger::smf_api_server().info(
"Received a PDUSession_UpdateSMContext Request: PDU Session Release request from AMF."); "Received a PDUSession_ReleaseSMContext Request: PDU Session Release request from AMF.");
//Get the SmContextUpdateData from this message and process in smf_app std::shared_ptr<itti_n11_release_sm_context_request> itti_msg =
smf::pdu_session_update_sm_context_request sm_context_req_msg = { }; std::make_shared<itti_n11_release_sm_context_request>(TASK_SMF_N11,
TASK_SMF_APP,
SmContextReleaseData smContextReleaseData = smContextReleaseMessage response,
.getJsonData(); smContextRef);
if (smContextReleaseData.n2SmInfoIsSet()) {
//N2 SM (for Session establishment)
std::string n2_sm_information = smContextReleaseMessage
.getBinaryDataN2SmInformation();
Logger::smf_api_server().debug("smContextMessage, n2 sm information %s",
n2_sm_information.c_str());
std::string n2_sm_info_type = smContextReleaseData.getN2SmInfoType();
sm_context_req_msg.set_n2_sm_information(n2_sm_information);
sm_context_req_msg.set_n2_sm_info_type(n2_sm_info_type);
}
//Step 2. TODO: initialize necessary values for sm context req from smContextReleaseData
//Step 3. Handle the itti_n11_update_sm_context_request message in smf_app itti_msg->scid = smContextRef;
//std::shared_ptr<itti_n11_update_sm_context_request> itti_msg = std::make_shared<itti_n11_update_sm_context_request>(TASK_SMF_N11, TASK_SMF_APP, response, smContextRef); m_smf_app->handle_pdu_session_release_sm_context_request(itti_msg);
//itti_msg->req = sm_context_req_msg;
//itti_msg->scid = smContextRef;
//m_smf_app->handle_pdu_session_update_sm_context_request(itti_msg);
} }
......
...@@ -76,7 +76,7 @@ class IndividualSMContextApiImpl : ...@@ -76,7 +76,7 @@ class IndividualSMContextApiImpl :
void release_sm_context( void release_sm_context(
const std::string &smContextRef, const std::string &smContextRef,
const SmContextReleaseMessage &smContextReleaseMessage, const SmContextReleaseData &smContextReleaseData,
Pistache::Http::ResponseWriter &response); Pistache::Http::ResponseWriter &response);
void retrieve_sm_context(const std::string &smContextRef, void retrieve_sm_context(const std::string &smContextRef,
const SmContextRetrieveData &smContextRetrieveData, const SmContextRetrieveData &smContextRetrieveData,
......
...@@ -346,4 +346,86 @@ class itti_n11_n1n2_message_transfer_response_status : public itti_n11_msg { ...@@ -346,4 +346,86 @@ class itti_n11_n1n2_message_transfer_response_status : public itti_n11_msg {
}; };
//-----------------------------------------------------------------------------
class itti_n11_release_sm_context_request : public itti_n11_msg {
public:
itti_n11_release_sm_context_request(const task_id_t orig,
const task_id_t dest,
Pistache::Http::ResponseWriter &response)
:
itti_n11_msg(N11_SESSION_RELEASE_SM_CONTEXT_REQUEST, orig, dest),
http_response(response) {
}
itti_n11_release_sm_context_request(const task_id_t orig,
const task_id_t dest,
Pistache::Http::ResponseWriter &response,
const std::string id)
:
itti_n11_msg(N11_SESSION_RELEASE_SM_CONTEXT_REQUEST, orig, dest),
http_response(response),
scid(id) {
}
itti_n11_release_sm_context_request(
const itti_n11_release_sm_context_request &i)
:
itti_n11_msg(i),
http_response(i.http_response),
scid(i.scid),
req(i.req) {
}
itti_n11_release_sm_context_request(
const itti_n11_release_sm_context_request &i, const task_id_t orig,
const task_id_t dest)
:
itti_n11_msg(i, orig, dest),
http_response(i.http_response),
scid(i.scid),
req(i.req) {
}
const char* get_msg_name() {
return "N11_SESSION_RELEASE_SM_CONTEXT_REQUEST";
}
;
smf::pdu_session_release_sm_context_request req;
Pistache::Http::ResponseWriter &http_response;
std::string scid; //SM Context ID
};
//-----------------------------------------------------------------------------
class itti_n11_release_sm_context_response : public itti_n11_msg {
public:
itti_n11_release_sm_context_response(const task_id_t orig,
const task_id_t dest,
Pistache::Http::ResponseWriter &response)
:
itti_n11_msg(N11_SESSION_RELEASE_SM_CONTEXT_RESPONSE, orig, dest),
http_response(response.clone()),
res() {
}
itti_n11_release_sm_context_response(
const itti_n11_release_sm_context_response &i)
:
itti_n11_msg(i),
res(i.res),
http_response(i.http_response.clone()) {
}
itti_n11_release_sm_context_response(
const itti_n11_release_sm_context_response &i, const task_id_t orig,
const task_id_t dest)
:
itti_n11_msg(i, orig, dest),
res(i.res),
http_response(i.http_response.clone()) {
}
const char* get_msg_name() {
return "N11_SESSION_RELEASE_SM_CONTEXT_RESPONSE";
}
;
smf::pdu_session_release_sm_context_response res;
Pistache::Http::ResponseWriter http_response;
};
#endif /* ITTI_MSG_N11_HPP_INCLUDED_ */ #endif /* ITTI_MSG_N11_HPP_INCLUDED_ */
...@@ -114,6 +114,8 @@ typedef enum { ...@@ -114,6 +114,8 @@ typedef enum {
N11_SESSION_MODIFICATION_REQUEST_SMF_REQUESTED, N11_SESSION_MODIFICATION_REQUEST_SMF_REQUESTED,
N11_SESSION_UPDATE_PDU_SESSION_STATUS, N11_SESSION_UPDATE_PDU_SESSION_STATUS,
N11_SESSION_N1N2_MESSAGE_TRANSFER_RESPONSE_STATUS, N11_SESSION_N1N2_MESSAGE_TRANSFER_RESPONSE_STATUS,
N11_SESSION_RELEASE_SM_CONTEXT_REQUEST,
N11_SESSION_RELEASE_SM_CONTEXT_RESPONSE,
NX_SESSION_MODIFICATION_REQUEST_NETWORK_REQUESTED, NX_SESSION_MODIFICATION_REQUEST_NETWORK_REQUESTED,
UDP_INIT, UDP_INIT,
UDP_DATA_REQ, UDP_DATA_REQ,
......
...@@ -542,7 +542,7 @@ void smf_app::handle_pdu_session_create_sm_context_request( ...@@ -542,7 +542,7 @@ void smf_app::handle_pdu_session_create_sm_context_request(
smContextCreateError.setN1SmMsg(refToBinaryData); smContextCreateError.setN1SmMsg(refToBinaryData);
//PDU Session Establishment Reject //PDU Session Establishment Reject
smf_n1_n2_inst.create_n1_sm_container(smreq->req, smf_n1_n2_inst.create_n1_sm_container(smreq->req,
PDU_SESSION_ESTABLISHMENT_REJECT, PDU_SESSION_ESTABLISHMENT_REJECT,
n1_sm_message, cause_n1); n1_sm_message, cause_n1);
smf_app_inst->convert_string_2_hex(n1_sm_message, n1_sm_message_hex); smf_app_inst->convert_string_2_hex(n1_sm_message, n1_sm_message_hex);
smf_n11_inst->send_pdu_session_create_sm_context_response( smf_n11_inst->send_pdu_session_create_sm_context_response(
...@@ -844,6 +844,85 @@ void smf_app::handle_pdu_session_update_sm_context_request( ...@@ -844,6 +844,85 @@ void smf_app::handle_pdu_session_update_sm_context_request(
} }
//------------------------------------------------------------------------------
void smf_app::handle_pdu_session_release_sm_context_request(
std::shared_ptr<itti_n11_release_sm_context_request> smreq) {
//TODO:
//handle PDU Session Release SM Context Request
Logger::smf_app().info(
"Handle a PDU Session Release SM Context Request from an AMF");
//Step 1. get supi, dnn, nssai, pdu_session id from sm_context
//SM Context ID - uint32_t in our case
scid_t scid = { };
try {
scid = std::stoi(smreq->scid);
} catch (const std::exception &err) {
Logger::smf_app().warn(
"Received a PDU Session Release SM Context Request, couldn't retrieve the corresponding SMF context, ignore message!");
smf_n11_inst->send_pdu_session_release_sm_context_response(
smreq->http_response, Pistache::Http::Code::Not_Found);
return;
}
std::shared_ptr<smf_context_ref> scf = { };
if (is_scid_2_smf_context(scid)) {
scf = scid_2_smf_context(scid);
} else {
Logger::smf_app().warn(
"Context associated with this id " SCID_FMT " does not exit!", scid);
smf_n11_inst->send_pdu_session_release_sm_context_response(
smreq->http_response, Pistache::Http::Code::Not_Found);
return;
}
//Step 2. store supi, dnn, nssai in itti_n11_update_sm_context_request to be processed later on
supi64_t supi64 = smf_supi_to_u64(scf.get()->supi);
smreq->req.set_supi(scf.get()->supi);
smreq->req.set_dnn(scf.get()->dnn);
smreq->req.set_snssai(scf.get()->nssai);
smreq->req.set_pdu_session_id(scf.get()->pdu_session_id);
//Step 2. find the smf context
std::shared_ptr<smf_context> sc = { };
if (is_supi_2_smf_context(supi64)) {
sc = supi_2_smf_context(supi64);
Logger::smf_app().debug("Retrieve SMF context with SUPI " SUPI_64_FMT "",
supi64);
} else {
//send PDUSession_SMReleaseContext Response to AMF
Logger::smf_app().warn(
"Received PDU Session Release SM Context Request with Supi " SUPI_64_FMT "couldn't retrieve the corresponding SMF context, ignore message!",
supi64);
smf_n11_inst->send_pdu_session_release_sm_context_response(
smreq->http_response, Pistache::Http::Code::Not_Found);
return;
}
//get dnn context
std::shared_ptr<dnn_context> sd = { };
if (!sc.get()->find_dnn_context(scf.get()->nssai, scf.get()->dnn, sd)) {
if (nullptr == sd.get()) {
//Error, DNN context doesn't exist, send PDUSession_SMUpdateContext Response to AMF
Logger::smf_app().warn(
"Received PDU Session Release SM Context Request, couldn't retrieve the corresponding SMF context, ignore message!");
smf_n11_inst->send_pdu_session_release_sm_context_response(
smreq->http_response, Pistache::Http::Code::Not_Found);
return;
}
}
//Step 3. handle the message in smf_context
sc.get()->handle_pdu_session_release_sm_context_request(smreq);
}
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
void smf_app::handle_network_requested_pdu_session_modification() { void smf_app::handle_network_requested_pdu_session_modification() {
std::shared_ptr<itti_nx_modify_pdu_session_request_network_requested> itti_msg = std::shared_ptr<itti_nx_modify_pdu_session_request_network_requested> itti_msg =
......
...@@ -209,6 +209,14 @@ class smf_app { ...@@ -209,6 +209,14 @@ class smf_app {
void handle_pdu_session_update_sm_context_request( void handle_pdu_session_update_sm_context_request(
std::shared_ptr<itti_n11_update_sm_context_request> smreq); std::shared_ptr<itti_n11_update_sm_context_request> smreq);
/*
* Handle PDUSession_ReleaseSMContextRequest from AMF
* @param [std::shared_ptr<itti_n11_release_sm_context_request>&] Request message
* @return void
*/
void handle_pdu_session_release_sm_context_request(
std::shared_ptr<itti_n11_release_sm_context_request> smreq);
/* /*
* Handle network-requested pdu session modification * Handle network-requested pdu session modification
* @param should be updated * @param should be updated
......
...@@ -2269,6 +2269,64 @@ void smf_context::handle_pdu_session_update_sm_context_request( ...@@ -2269,6 +2269,64 @@ void smf_context::handle_pdu_session_update_sm_context_request(
} }
//-------------------------------------------------------------------------------------
void smf_context::handle_pdu_session_release_sm_context_request(
std::shared_ptr<itti_n11_release_sm_context_request> smreq) {
Logger::smf_app().info(
"Handle a PDU Session Release SM Context Request message from AMF");
bool update_upf = false;
//Step 1. get DNN, SMF PDU session context. At this stage, dnn_context and pdu_session must be existed
std::shared_ptr<dnn_context> sd = { };
std::shared_ptr<smf_pdu_session> sp = { };
bool find_dnn = find_dnn_context(smreq->req.get_snssai(),
smreq->req.get_dnn(), sd);
bool find_pdu = false;
if (find_dnn) {
find_pdu = sd.get()->find_pdu_session(
smreq->req.get_pdu_session_id(), sp);
}
if (!find_dnn or !find_pdu) {
//error, send reply to AMF with error code "Context Not Found"
Logger::smf_app().warn("DNN or PDU session context does not exist!");
smf_n11_inst->send_pdu_session_release_sm_context_response(
smreq->http_response,
Pistache::Http::Code::Not_Found);
return;
}
//we need to store HttpResponse and session-related information to be used when receiving the response from UPF
itti_n11_release_sm_context_response *n11_sm_context_resp =
new itti_n11_release_sm_context_response(TASK_SMF_APP, TASK_SMF_N11,
smreq->http_response);
std::shared_ptr<itti_n11_release_sm_context_response> sm_context_resp_pending =
std::shared_ptr<itti_n11_release_sm_context_response>(n11_sm_context_resp);
n11_sm_context_resp->res.set_supi(smreq->req.get_supi());
n11_sm_context_resp->res.set_supi_prefix(
smreq->req.get_supi_prefix());
n11_sm_context_resp->res.set_cause(REQUEST_ACCEPTED);
n11_sm_context_resp->res.set_pdu_session_id(
smreq->req.get_pdu_session_id());
n11_sm_context_resp->res.set_snssai(smreq->req.get_snssai());
n11_sm_context_resp->res.set_dnn(smreq->req.get_dnn());
session_release_sm_context_procedure *proc =
new session_release_sm_context_procedure(sp);
std::shared_ptr<smf_procedure> sproc = std::shared_ptr<smf_procedure>(proc);
insert_procedure(sproc);
if (proc->run(smreq, sm_context_resp_pending, shared_from_this())) {
// error !
Logger::smf_app().info(
"PDU Release SM Context Request procedure failed");
}
}
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
void smf_context::insert_dnn_subscription( void smf_context::insert_dnn_subscription(
const snssai_t &snssai, const snssai_t &snssai,
......
...@@ -340,7 +340,7 @@ class smf_context : public std::enable_shared_from_this<smf_context> { ...@@ -340,7 +340,7 @@ class smf_context : public std::enable_shared_from_this<smf_context> {
void handle_itti_msg(std::shared_ptr<itti_n4_session_report_request>&); void handle_itti_msg(std::shared_ptr<itti_n4_session_report_request>&);
/* /*
* Handle messages from AMF (e.g., PDU_SESSION_CREATESMContextRequest) * Handle messages from AMF (e.g., PDU_SESSION_CreateSMContextRequest)
* @param [std::shared_ptr<itti_n11_create_sm_context_request] smreq Request message * @param [std::shared_ptr<itti_n11_create_sm_context_request] smreq Request message
* @return void * @return void
*/ */
...@@ -348,14 +348,21 @@ class smf_context : public std::enable_shared_from_this<smf_context> { ...@@ -348,14 +348,21 @@ class smf_context : public std::enable_shared_from_this<smf_context> {
std::shared_ptr<itti_n11_create_sm_context_request> smreq); std::shared_ptr<itti_n11_create_sm_context_request> smreq);
/* /*
* Handle messages from AMF (e.g., PDU_SESSION_UPDATESMContextRequest) * Handle messages from AMF (e.g., PDU_SESSION_UpdateSMContextRequest)
* @param [std::shared_ptr<itti_n11_update_sm_context_request] smreq Request message * @param [std::shared_ptr<itti_n11_update_sm_context_request] smreq Request message
* @param [pdu_session_procedure_t procedure] pdu session procedure: session establishment/modification/release
* @return void * @return void
*/ */
void handle_pdu_session_update_sm_context_request( void handle_pdu_session_update_sm_context_request(
std::shared_ptr<itti_n11_update_sm_context_request> smreq); std::shared_ptr<itti_n11_update_sm_context_request> smreq);
/*
* Handle messages from AMF (e.g., PDU_SESSION_ReleaseSMContextRequest)
* @param [std::shared_ptr<itti_n11_release_sm_context_request] smreq Request message
* @return void
*/
void handle_pdu_session_release_sm_context_request(
std::shared_ptr<itti_n11_release_sm_context_request> smreq);
/* /*
* Find DNN context with name * Find DNN context with name
* @param [const std::string&] dnn * @param [const std::string&] dnn
......
...@@ -556,3 +556,14 @@ void pdu_session_update_sm_context_response::remove_all_qos_flow_context_updated ...@@ -556,3 +556,14 @@ void pdu_session_update_sm_context_response::remove_all_qos_flow_context_updated
qos_flow_context_updateds.clear(); qos_flow_context_updateds.clear();
} }
//-----------------------------------------------------------------------------
void pdu_session_release_sm_context_response::set_cause(uint8_t cause) {
m_cause = cause;
}
//-----------------------------------------------------------------------------
uint8_t pdu_session_release_sm_context_response::get_cause() {
return m_cause;
}
...@@ -51,6 +51,8 @@ typedef enum { ...@@ -51,6 +51,8 @@ typedef enum {
PDU_SESSION_CREATE_SM_CONTEXT_RESPONSE, PDU_SESSION_CREATE_SM_CONTEXT_RESPONSE,
PDU_SESSION_UPDATE_SM_CONTEXT_REQUEST, PDU_SESSION_UPDATE_SM_CONTEXT_REQUEST,
PDU_SESSION_UPDATE_SM_CONTEXT_RESPONSE, PDU_SESSION_UPDATE_SM_CONTEXT_RESPONSE,
PDU_SESSION_RELEASE_SM_CONTEXT_REQUEST,
PDU_SESSION_RELEASE_SM_CONTEXT_RESPONSE,
PDU_SESSION_MSG_TYPE_MAX PDU_SESSION_MSG_TYPE_MAX
} pdu_session_msg_type_t; } pdu_session_msg_type_t;
...@@ -550,6 +552,34 @@ class pdu_session_update_sm_context_response : public pdu_session_msg { ...@@ -550,6 +552,34 @@ class pdu_session_update_sm_context_response : public pdu_session_msg {
}; };
class pdu_session_release_sm_context_request : public pdu_session_msg {
public:
pdu_session_release_sm_context_request()
:
pdu_session_msg(PDU_SESSION_RELEASE_SM_CONTEXT_REQUEST) {
}
;
private:
};
class pdu_session_release_sm_context_response : public pdu_session_msg {
public:
pdu_session_release_sm_context_response()
:
pdu_session_msg(PDU_SESSION_RELEASE_SM_CONTEXT_RESPONSE) {
m_cause = 0;
}
;
void set_cause(uint8_t cause);
uint8_t get_cause();
private:
uint8_t m_cause;
};
} }
#endif #endif
...@@ -474,6 +474,18 @@ void smf_n11::send_pdu_session_update_sm_context_response( ...@@ -474,6 +474,18 @@ void smf_n11::send_pdu_session_update_sm_context_response(
} }
break; break;
case session_management_procedures_type_e::PDU_SESSION_RELEASE_UE_REQUESTED_STEP2: {
Logger::smf_n11().info("PDU_SESSION_RELEASE_UE_REQUESTED (step 2)");
sm_context_res->http_response.send(Pistache::Http::Code::No_Content);
}
break;
case session_management_procedures_type_e::PDU_SESSION_RELEASE_UE_REQUESTED_STEP3: {
Logger::smf_n11().info("PDU_SESSION_RELEASE_UE_REQUESTED (step 3)");
sm_context_res->http_response.send(Pistache::Http::Code::No_Content);
}
break;
default: { default: {
Logger::smf_n11().debug("Session management procedure: unknown!"); Logger::smf_n11().debug("Session management procedure: unknown!");
} }
...@@ -592,6 +604,33 @@ void smf_n11::send_n1n2_message_transfer_request( ...@@ -592,6 +604,33 @@ void smf_n11::send_n1n2_message_transfer_request(
//TODO: //TODO:
} }
//------------------------------------------------------------------------------
void smf_n11::send_pdu_session_release_sm_context_response(
Pistache::Http::ResponseWriter &httpResponse, Pistache::Http::Code code) {
Logger::smf_n11().debug(
"[SMF N11] Send PDUSessionReleaseContextResponse to AMF!");
httpResponse.send(code);
}
//------------------------------------------------------------------------------
void smf_n11::send_pdu_session_release_sm_context_response(
Pistache::Http::ResponseWriter &httpResponse,
oai::smf_server::model::ProblemDetails &problem,
Pistache::Http::Code code) {
Logger::smf_n11().debug(
"[SMF N11] Send PDUSessionReleaseContextResponse to AMF!");
nlohmann::json json_data = { };
to_json(json_data, problem);
if (!json_data.empty()) {
httpResponse.headers().add<Pistache::Http::Header::ContentType>(
Pistache::Http::Mime::MediaType("application/json"));
httpResponse.send(code, json_data.dump().c_str());
} else {
httpResponse.send(code);
}
}
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
void smf_n11::create_multipart_related_content(std::string &body, void smf_n11::create_multipart_related_content(std::string &body,
std::string &json_part, std::string &json_part,
......
...@@ -152,6 +152,27 @@ class smf_n11 { ...@@ -152,6 +152,27 @@ class smf_n11 {
oai::smf_server::model::SmContextCreatedData &smContextCreatedData, oai::smf_server::model::SmContextCreatedData &smContextCreatedData,
Pistache::Http::Code code); Pistache::Http::Code code);
/*
* Send release session response to AMF
* @param [Pistache::Http::ResponseWriter] httpResponse
* @param [Pistache::Http::Code] code, response code
*
*/
void send_pdu_session_release_sm_context_response(
Pistache::Http::ResponseWriter &httpResponse, Pistache::Http::Code code);
/*
* Send release session response to AMF
* @param [Pistache::Http::ResponseWriter] httpResponse
* @param [oai::smf_server::model::ProblemDetails] problem
* @param [Pistache::Http::Code] code, response code
*
*/
void send_pdu_session_release_sm_context_response(
Pistache::Http::ResponseWriter &httpResponse,
oai::smf_server::model::ProblemDetails &problem,
Pistache::Http::Code code);
/* /*
* Create HTTP body content for multipart/related message * Create HTTP body content for multipart/related message
* @param [std::string] body: Body of the created message * @param [std::string] body: Body of the created message
......
...@@ -1321,3 +1321,86 @@ void session_update_sm_context_procedure::handle_itti_msg( ...@@ -1321,3 +1321,86 @@ void session_update_sm_context_procedure::handle_itti_msg(
} }
//------------------------------------------------------------------------------
int session_release_sm_context_procedure::run(
std::shared_ptr<itti_n11_release_sm_context_request> sm_context_req,
std::shared_ptr<itti_n11_release_sm_context_response> sm_context_res,
std::shared_ptr<smf::smf_context> sc) {
Logger::smf_app().info("Release SM Context Request");
// TODO check if compatible with ongoing procedures if any
pfcp::node_id_t up_node_id = { };
if (not pfcp_associations::get_instance().select_up_node(
up_node_id, NODE_SELECTION_CRITERIA_MIN_PFCP_SESSIONS)) {
// TODO
sm_context_res->res.set_cause(REMOTE_PEER_NOT_RESPONDING); //verify for 5G??
Logger::smf_app().info("REMOTE_PEER_NOT_RESPONDING");
return RETURNerror ;
}
//-------------------
n11_trigger = sm_context_req;
n11_triggered_pending = sm_context_res;
uint64_t seid = smf_app_inst->generate_seid();
sp->set_seid(seid);
itti_n4_session_deletion_request *n4_ser =
new itti_n4_session_deletion_request(TASK_SMF_APP, TASK_SMF_N4);
n4_ser->seid = sp->up_fseid.seid;
n4_ser->trxn_id = this->trxn_id;
n4_ser->r_endpoint = endpoint(up_node_id.u1.ipv4_address, pfcp::default_port);
n4_triggered = std::shared_ptr<itti_n4_session_deletion_request>(n4_ser);
Logger::smf_app().info("Sending ITTI message %s to task TASK_SMF_N4",
n4_ser->get_msg_name());
int ret = itti_inst->send_msg(n4_triggered);
if (RETURNok != ret) {
Logger::smf_app().error(
"Could not send ITTI message %s to task TASK_SMF_N4",
n4_ser->get_msg_name());
return RETURNerror ;
}
return RETURNok ;
}
//------------------------------------------------------------------------------
void session_release_sm_context_procedure::handle_itti_msg(
itti_n4_session_deletion_response &resp,
std::shared_ptr<smf::smf_context> sc) {
Logger::smf_app().info(
"Handle itti_n4_session_deletion_response (Release SM Context Request): pdu-session-id %d",
n11_trigger.get()->req.get_pdu_session_id());
pfcp::cause_t cause = { };
::cause_t cause_gtp = { .cause_value = REQUEST_ACCEPTED };
// must be there
if (resp.pfcp_ies.get(cause)) {
xgpp_conv::pfcp_cause_to_core_cause(cause, cause_gtp);
}
if (cause.cause_value == CAUSE_VALUE_REQUEST_ACCEPTED) {
Logger::smf_app().info("PDU Session Release SM Context accepted by UPF");
//clear the resources including addresses allocated to this Session and associated QoS flows
sp->deallocate_ressources(n11_trigger.get()->req.get_dnn()); //TODO: for IPv6 (only for Ipv4 for the moment)
smf_n11_inst->send_pdu_session_release_sm_context_response(
n11_triggered_pending->http_response, Pistache::Http::Code::No_Content);
} else {
oai::smf_server::model::ProblemDetails problem_details = { };
problem_details.setCause(
pdu_session_application_error_e2str[PDU_SESSION_APPLICATION_ERROR_NETWORK_FAILURE]); //To be updated
smf_n11_inst->send_pdu_session_release_sm_context_response(
n11_triggered_pending->http_response, Pistache::Http::Code::Not_Acceptable);
}
//TODO:
/* If it is the last PDU Session the SMF is handling for the UE for the associated (DNN, S-
NSSAI), the SMF unsubscribes from Session Management Subscription data changes notification with the UDM
by means of the Nudm_SDM_Unsubscribe service operation. The SMF invokes the
Nudm_UECM_Deregistration service operation so that the UDM removes the association it had stored between
the SMF identity and the associated DNN and PDU Session Id
*/
}
...@@ -173,21 +173,20 @@ class session_update_sm_context_procedure : public smf_procedure { ...@@ -173,21 +173,20 @@ class session_update_sm_context_procedure : public smf_procedure {
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
class session_release_pdu_session_procedure : public smf_procedure { class session_release_sm_context_procedure : public smf_procedure {
public: public:
explicit session_release_pdu_session_procedure( explicit session_release_sm_context_procedure(
std::shared_ptr<smf_pdu_session> &sppc) std::shared_ptr<smf_pdu_session> &sps)
: :
smf_procedure(), smf_procedure(),
ppc(sppc), sp(sps),
n4_triggered(), n4_triggered(),
n11_triggered_pending(), n11_triggered_pending(),
n11_trigger(), n11_trigger() {
session_procedure_type() {
} }
int run(std::shared_ptr<itti_n11_update_sm_context_request> req, int run(std::shared_ptr<itti_n11_release_sm_context_request> req,
std::shared_ptr<itti_n11_update_sm_context_response> resp, std::shared_ptr<itti_n11_release_sm_context_response> resp,
std::shared_ptr<smf::smf_context> sc); std::shared_ptr<smf::smf_context> sc);
/* /*
* Handle N4 modification response from UPF * Handle N4 modification response from UPF
...@@ -195,16 +194,15 @@ class session_release_pdu_session_procedure : public smf_procedure { ...@@ -195,16 +194,15 @@ class session_release_pdu_session_procedure : public smf_procedure {
* @param [std::shared_ptr<smf::smf_context>] sc smf context * @param [std::shared_ptr<smf::smf_context>] sc smf context
* @return void * @return void
*/ */
void handle_itti_msg(itti_n4_session_modification_response &resp, void handle_itti_msg(itti_n4_session_deletion_response &resp,
std::shared_ptr<smf::smf_context> sc); std::shared_ptr<smf::smf_context> sc);
std::shared_ptr<itti_n4_session_modification_request> n4_triggered; std::shared_ptr<itti_n4_session_deletion_request> n4_triggered;
std::shared_ptr<smf_pdu_session> ppc; std::shared_ptr<smf_pdu_session> sp;
std::shared_ptr<smf::smf_context> pc; std::shared_ptr<smf::smf_context> sc;
std::shared_ptr<itti_n11_update_sm_context_request> n11_trigger; std::shared_ptr<itti_n11_release_sm_context_request> n11_trigger;
std::shared_ptr<itti_n11_update_sm_context_response> n11_triggered_pending; std::shared_ptr<itti_n11_release_sm_context_response> n11_triggered_pending;
session_management_procedures_type_e session_procedure_type;
}; };
......
...@@ -383,13 +383,12 @@ void send_pdu_session_update_sm_context_establishment( ...@@ -383,13 +383,12 @@ void send_pdu_session_update_sm_context_establishment(
free(buffer); free(buffer);
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
void send_pdu_session_modification_request_step1(std::string smf_ip_address) { void send_pdu_session_modification_request_step1(std::string smf_ip_address) {
std::cout << "[AMF N11] PDU Session Modification Request (SM Context Update, Step 1)" std::cout
<< std::endl; << "[AMF N11] PDU Session Modification Request (SM Context Update, Step 1)"
<< std::endl;
nlohmann::json pdu_session_modification_request; nlohmann::json pdu_session_modification_request;
//encode PDU Session Modification Request //encode PDU Session Modification Request
...@@ -403,28 +402,27 @@ void send_pdu_session_modification_request_step1(std::string smf_ip_address) { ...@@ -403,28 +402,27 @@ void send_pdu_session_modification_request_step1(std::string smf_ip_address) {
ENCODE_U8(buffer + size, 0x01, size); //PDUSessionIdentity ENCODE_U8(buffer + size, 0x01, size); //PDUSessionIdentity
ENCODE_U8(buffer + size, 0x01, size); //ProcedureTransactionIdentity ENCODE_U8(buffer + size, 0x01, size); //ProcedureTransactionIdentity
ENCODE_U8(buffer + size, 0xc9, size); //MessageType - PDU Session Modification Request ENCODE_U8(buffer + size, 0xc9, size); //MessageType - PDU Session Modification Request
ENCODE_U8(buffer + size, 0x28, size); //_5GSMCapability ENCODE_U8(buffer + size, 0x28, size); //_5GSMCapability
ENCODE_U8(buffer + size, 0x01, size); //_5GSMCapability ENCODE_U8(buffer + size, 0x01, size); //_5GSMCapability
ENCODE_U8(buffer + size, 0x00, size); //_5GSMCapability ENCODE_U8(buffer + size, 0x00, size); //_5GSMCapability
ENCODE_U8(buffer + size, 0x59, size); //_5GSMCause ENCODE_U8(buffer + size, 0x59, size); //_5GSMCause
ENCODE_U8(buffer + size, 0x00, size); //_5GSMCause ENCODE_U8(buffer + size, 0x00, size); //_5GSMCause
ENCODE_U8(buffer + size, 0x7a, size); //QoS Rules IE ENCODE_U8(buffer + size, 0x7a, size); //QoS Rules IE
ENCODE_U8(buffer + size, 0x00, size); //QoS Rules length ENCODE_U8(buffer + size, 0x00, size); //QoS Rules length
ENCODE_U8(buffer + size, 0x09, size); //QoS Rules length ENCODE_U8(buffer + size, 0x09, size); //QoS Rules length
ENCODE_U8(buffer + size, 0x01, size); //QoS Rules rule id ENCODE_U8(buffer + size, 0x01, size); //QoS Rules rule id
ENCODE_U8(buffer + size, 0x00, size); //QoS Rules rule length ENCODE_U8(buffer + size, 0x00, size); //QoS Rules rule length
ENCODE_U8(buffer + size, 0x06, size); //QoS Rules rule length ENCODE_U8(buffer + size, 0x06, size); //QoS Rules rule length
ENCODE_U8(buffer + size, 0x31, size); //QoS Rules ENCODE_U8(buffer + size, 0x31, size); //QoS Rules
ENCODE_U8(buffer + size, 0x31, size); //QoS Rules ENCODE_U8(buffer + size, 0x31, size); //QoS Rules
ENCODE_U8(buffer + size, 0x01, size); //QoS Rules filter 1 length ENCODE_U8(buffer + size, 0x01, size); //QoS Rules filter 1 length
ENCODE_U8(buffer + size, 0x01, size); //QoS Rules ENCODE_U8(buffer + size, 0x01, size); //QoS Rules
ENCODE_U8(buffer + size, 0x01, size); //QoS Rules ENCODE_U8(buffer + size, 0x01, size); //QoS Rules
ENCODE_U8(buffer + size, 0x3c, size); //QoS Rules ENCODE_U8(buffer + size, 0x3c, size); //QoS Rules
// ENCODE_U8(buffer + size, 0x00, size); //MaximumNumberOfSupportedPacketFilters // ENCODE_U8(buffer + size, 0x00, size); //MaximumNumberOfSupportedPacketFilters
// ENCODE_U8(buffer + size, 0x01, size); //MaximumNumberOfSupportedPacketFilters // ENCODE_U8(buffer + size, 0x01, size); //MaximumNumberOfSupportedPacketFilters
std::cout << "Buffer: " << std::endl; std::cout << "Buffer: " << std::endl;
for (int i = 0; i < size; i++) { for (int i = 0; i < size; i++) {
printf("%02x ", buffer[i]); printf("%02x ", buffer[i]);
...@@ -498,8 +496,6 @@ void send_pdu_session_modification_request_step1(std::string smf_ip_address) { ...@@ -498,8 +496,6 @@ void send_pdu_session_modification_request_step1(std::string smf_ip_address) {
free(buffer); free(buffer);
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
void send_pdu_session_release_request(std::string smf_ip_address) { void send_pdu_session_release_request(std::string smf_ip_address) {
...@@ -594,8 +590,7 @@ void send_pdu_session_release_request(std::string smf_ip_address) { ...@@ -594,8 +590,7 @@ void send_pdu_session_release_request(std::string smf_ip_address) {
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
void send_pdu_session_release_resource_release_ack( void send_pdu_session_release_resource_release_ack(std::string smf_ip_address) {
std::string smf_ip_address) {
std::cout std::cout
<< "[AMF N11] PDU Session Release Ack (Update SM Context): N2 SM - Resource Release Ack" << "[AMF N11] PDU Session Release Ack (Update SM Context): N2 SM - Resource Release Ack"
...@@ -777,14 +772,12 @@ void send_pdu_session_release_complete(std::string smf_ip_address) { ...@@ -777,14 +772,12 @@ void send_pdu_session_release_complete(std::string smf_ip_address) {
free(buffer); free(buffer);
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
void send_pdu_session_update_sm_context_ue_service_request( void send_pdu_session_update_sm_context_ue_service_request(
std::string smf_ip_address) { std::string smf_ip_address) {
std::cout << "[AMF N11] UE-triggered Service Request (SM Context Update Step 1)" std::cout
<< std::endl; << "[AMF N11] UE-triggered Service Request (SM Context Update Step 1)"
<< std::endl;
nlohmann::json service_requests; nlohmann::json service_requests;
//NO NAS, No NGAP //NO NAS, No NGAP
...@@ -808,8 +801,7 @@ void send_pdu_session_update_sm_context_ue_service_request( ...@@ -808,8 +801,7 @@ void send_pdu_session_update_sm_context_ue_service_request(
CURLcode res = { }; CURLcode res = { };
struct curl_slist *headers = nullptr; struct curl_slist *headers = nullptr;
//headers = curl_slist_append(headers, "charsets: utf-8"); //headers = curl_slist_append(headers, "charsets: utf-8");
headers = curl_slist_append( headers = curl_slist_append(headers, "content-type: application/json");
headers, "content-type: application/json");
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers); curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
curl_easy_setopt(curl, CURLOPT_URL, url.c_str()); curl_easy_setopt(curl, CURLOPT_URL, url.c_str());
curl_easy_setopt(curl, CURLOPT_HTTPGET, 1); curl_easy_setopt(curl, CURLOPT_HTTPGET, 1);
...@@ -847,12 +839,12 @@ void send_pdu_session_update_sm_context_ue_service_request( ...@@ -847,12 +839,12 @@ void send_pdu_session_update_sm_context_ue_service_request(
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
void send_pdu_session_update_sm_context_ue_service_request_step2( void send_pdu_session_update_sm_context_ue_service_request_step2(
std::string smf_ip_address) { std::string smf_ip_address) {
std::cout << "[AMF N11] UE-triggered Service Request (SM Context Update Step 2)" std::cout
<< std::endl; << "[AMF N11] UE-triggered Service Request (SM Context Update Step 2)"
<< std::endl;
nlohmann::json service_requests; nlohmann::json service_requests;
//encode PDU Session Resource Setup Response Transfer IE //encode PDU Session Resource Setup Response Transfer IE
...@@ -898,7 +890,6 @@ void send_pdu_session_update_sm_context_ue_service_request_step2( ...@@ -898,7 +890,6 @@ void send_pdu_session_update_sm_context_ue_service_request_step2(
service_requests["anType"] = "3GPP_ACCESS"; service_requests["anType"] = "3GPP_ACCESS";
service_requests["ratType"] = "NR"; service_requests["ratType"] = "NR";
std::string body; std::string body;
std::string boundary = "----Boundary"; std::string boundary = "----Boundary";
std::string json_part = service_requests.dump(); std::string json_part = service_requests.dump();
...@@ -962,6 +953,66 @@ void send_pdu_session_update_sm_context_ue_service_request_step2( ...@@ -962,6 +953,66 @@ void send_pdu_session_update_sm_context_ue_service_request_step2(
free(buffer); free(buffer);
} }
//------------------------------------------------------------------------------
void send_release_sm_context_request(std::string smf_ip_address) {
std::cout << "[AMF N11] PDU Session Release SM context Request" << std::endl;
nlohmann::json send_release_sm_context_request;
std::string url = std::string("http://");
url.append(smf_ip_address);
url.append(std::string("/nsmf-pdusession/v2/sm-contexts/1/release"));
//Fill the json part
send_release_sm_context_request["pduSessionId"] = 1;
std::string body = send_release_sm_context_request.dump();
curl_global_init(CURL_GLOBAL_ALL);
CURL *curl = curl = curl_easy_init();
if (curl) {
CURLcode res = { };
struct curl_slist *headers = nullptr;
//headers = curl_slist_append(headers, "charsets: utf-8");
headers = curl_slist_append(headers, "content-type: application/json");
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
curl_easy_setopt(curl, CURLOPT_URL, url.c_str());
curl_easy_setopt(curl, CURLOPT_HTTPGET, 1);
curl_easy_setopt(curl, CURLOPT_TIMEOUT_MS, 100L);
//curl_easy_setopt(curl, CURLOPT_INTERFACE, "eno1:amf"); //hardcoded
// Response information.
long httpCode = { 0 };
std::unique_ptr<std::string> httpData(new std::string());
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, &callback);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, httpData.get());
curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, body.length());
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, body.c_str());
res = curl_easy_perform(curl);
curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &httpCode);
//get cause from the response
nlohmann::json response_data;
try {
response_data = nlohmann::json::parse(*httpData.get());
} catch (nlohmann::json::exception &e) {
std::cout << "Could not get json data from the response" << std::endl;
}
std::cout
<< "[AMF N11] PDU Session Release SM Context Request, response from SMF, Http Code "
<< httpCode << std::endl;
curl_easy_cleanup(curl);
}
curl_global_cleanup();
}
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
int main(int argc, char *argv[]) { int main(int argc, char *argv[]) {
...@@ -1010,6 +1061,9 @@ int main(int argc, char *argv[]) { ...@@ -1010,6 +1061,9 @@ int main(int argc, char *argv[]) {
usleep(200000); usleep(200000);
send_pdu_session_release_complete(smf_ip_address); send_pdu_session_release_complete(smf_ip_address);
usleep(200000); usleep(200000);
//Release SM context
send_release_sm_context_request(smf_ip_address);
return 0; return 0;
} }
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment