Commit 6af52519 authored by Tien Thinh NGUYEN's avatar Tien Thinh NGUYEN

First version for UE-requested PDU Session Release

parent 660c662e
......@@ -840,7 +840,10 @@ void smf_context::handle_itti_msg(itti_n4_session_deletion_response& sdresp) {
auto proc_session_delete =
std::static_pointer_cast<session_release_sm_context_procedure>(proc);
send_pdu_session_release_response(
proc_session_delete->n11_triggered_pending);
proc_session_delete->n11_trigger,
proc_session_delete->n11_triggered_pending,
proc_session_delete->session_procedure_type,
proc_session_delete->sps);
remove_procedure(proc.get());
}
} else {
......@@ -3083,6 +3086,12 @@ bool smf_context::handle_pdu_session_update_sm_context_request(
smreq->req.get_n2_sm_info_type());
}
// check if update message contain N1 SM Msg
if (sm_context_req_msg.n1_sm_msg_is_set()) {
sm_context_rel_req_msg.set_n1_sm_message(
smreq->req.get_n1_sm_message());
}
// Create an itti_n11_release_sm_context_request message and handling it
// accordingly
std::shared_ptr<itti_n11_release_sm_context_request> smreq_release =
......@@ -3113,6 +3122,7 @@ bool smf_context::handle_pdu_session_update_sm_context_request(
auto proc = std::make_shared<session_release_sm_context_procedure>(sp);
std::shared_ptr<smf_procedure> sproc = proc;
proc->session_procedure_type = procedure_type;
insert_procedure(sproc);
......@@ -5311,22 +5321,127 @@ void smf_context::send_pdu_session_update_response(
}
void smf_context::send_pdu_session_release_response(
const std::shared_ptr<itti_n11_release_sm_context_response>& resp) {
const std::shared_ptr<itti_n11_release_sm_context_request>& req,
const std::shared_ptr<itti_n11_release_sm_context_response>& resp,
const session_management_procedures_type_e& session_procedure_type,
const std::shared_ptr<smf_pdu_session>& sps) {
if (resp->res.get_cause() ==
static_cast<uint8_t>(cause_value_5gsm_e::CAUSE_255_REQUEST_ACCEPTED)) {
smf_app_inst->trigger_http_response(
http_status_code_e::HTTP_STATUS_CODE_204_NO_CONTENT, resp->pid,
N11_SESSION_RELEASE_SM_CONTEXT_RESPONSE);
switch (session_procedure_type) {
case session_management_procedures_type_e::
PDU_SESSION_RELEASE_UE_REQUESTED_STEP1: {
// UE-initiated PDU Session Release
Logger::smf_app().info("PDU Session Release UE-initiated (Step 1))");
std::shared_ptr<pdu_session_release_sm_context_response>
session_release_msg =
std::make_shared<pdu_session_release_sm_context_response>(
resp->res);
// Create N1 SM message (PDU Session Release Command)
std::string n1_sm_msg = {};
std::string n1_sm_msg_hex = {};
smf_n1::get_instance().create_n1_pdu_session_release_command(
session_release_msg, n1_sm_msg,
cause_value_5gsm_e::CAUSE_36_REGULAR_DEACTIVATION); // TODO: check
// Cause
conv::convert_string_2_hex(n1_sm_msg, n1_sm_msg_hex);
resp->res.set_n1_sm_message(n1_sm_msg_hex);
// Create N2 SM info (if the UP connection of the PDU Session is active)
if (sps->get_upCnx_state() == upCnx_state_e::UPCNX_STATE_ACTIVATED) {
// N2 SM Information
std::string n2_sm_info = {};
std::string n2_sm_info_hex = {};
smf_n2::get_instance()
.create_n2_pdu_session_resource_release_command_transfer(
session_release_msg, n2_sm_info_type_e::PDU_RES_REL_CMD,
n2_sm_info);
conv::convert_string_2_hex(n2_sm_info, n2_sm_info_hex);
resp->res.set_n2_sm_information(n2_sm_info_hex);
// Prepare response to send to AMF
// (PDUSession_UpdateSMContextResponse)
nlohmann::json sm_context_response_data = {};
sm_context_response_data["n1MessageContainer"]["n1MessageClass"] =
N1N2_MESSAGE_CLASS;
sm_context_response_data["n1MessageContainer"]["n1MessageContent"]
["contentId"] = N1_SM_CONTENT_ID;
sm_context_response_data["n2InfoContainer"]["n2InformationClass"] =
N1N2_MESSAGE_CLASS;
sm_context_response_data["n2InfoContainer"]["smInfo"]
["PduSessionId"] =
resp->res.get_pdu_session_id();
sm_context_response_data["n2InfoContainer"]["smInfo"]["n2InfoContent"]
["ngapData"]["contentId"] = N2_SM_CONTENT_ID;
sm_context_response_data["n2SmInfoType"] =
"PDU_RES_REL_CMD"; // NGAP message
resp->res.set_json_data(sm_context_response_data);
} else {
// fill the content of SmContextUpdatedData
nlohmann::json json_data = {};
json_data["n1MessageContainer"]["n1MessageClass"] =
N1N2_MESSAGE_CLASS;
json_data["n1MessageContainer"]["n1MessageContent"]["contentId"] =
N1_SM_CONTENT_ID;
resp->res.set_json_data(json_data);
}
// Update PDU session status to PDU_SESSION_INACTIVE_PENDING
sps->set_pdu_session_status(
pdu_session_status_e::PDU_SESSION_INACTIVE_PENDING);
// set UpCnxState to DEACTIVATED
sps->set_upCnx_state(upCnx_state_e::UPCNX_STATE_DEACTIVATED);
// TODO: To be completed
// TODO: start timer T3592 (see Section 6.3.3@3GPP TS 24.501)
// get smf_pdu_session and set the corresponding timer
scid_t scid = {};
try {
scid = (scid_t) std::stoul(req->scid, nullptr, 10);
} catch (const std::exception& e) {
Logger::smf_n1().warn(
"Error when converting from string to int for SCID, "
"error: %s",
e.what());
// TODO Stefan: I could not find a better response code here
smf_app_inst->trigger_update_context_error_response(
http_status_code_e::HTTP_STATUS_CODE_403_FORBIDDEN,
PDU_SESSION_APPLICATION_ERROR_NETWORK_FAILURE, resp->pid);
return;
}
resp->res.set_http_code(http_status_code_e::HTTP_STATUS_CODE_200_OK);
// Store the context for the timer handling
sps.get()->set_pending_n11_msg(
std::dynamic_pointer_cast<itti_n11_msg>(resp));
sps->timer_T3592 = itti_inst->timer_setup(
T3592_TIMER_VALUE_SEC, 0, TASK_SMF_APP, TASK_SMF_APP_TRIGGER_T3592,
scid);
// Trigger response to AMF
nlohmann::json response_message_json = {};
resp->res.to_json(response_message_json);
smf_app_inst->trigger_http_response(
response_message_json, resp->pid,
N11_SESSION_RELEASE_SM_CONTEXT_RESPONSE);
} break;
default: {
smf_app_inst->trigger_http_response(
http_status_code_e::HTTP_STATUS_CODE_204_NO_CONTENT, resp->pid,
N11_SESSION_RELEASE_SM_CONTEXT_RESPONSE);
}
}
} else {
oai::smf_server::model::ProblemDetails problem_details = {};
problem_details.setCause(pdu_session_application_error_e2str.at(
PDU_SESSION_APPLICATION_ERROR_NETWORK_FAILURE));
// TODO Stefan: Why is this commented out??
/*
smf_app_inst->trigger_http_response(
http_status_code_e::HTTP_STATUS_CODE_406_NOT_ACCEPTABLE,
n11_triggered_pending->pid, N11_SESSION_RELEASE_SM_CONTEXT_RESPONSE);
*/
}
}
......@@ -1338,7 +1338,10 @@ class smf_context : public std::enable_shared_from_this<smf_context> {
* @param resp
*/
void send_pdu_session_release_response(
const std::shared_ptr<itti_n11_release_sm_context_response>& resp);
const std::shared_ptr<itti_n11_release_sm_context_request>& req,
const std::shared_ptr<itti_n11_release_sm_context_response>& resp,
const session_management_procedures_type_e& session_procedure_type,
const std::shared_ptr<smf_pdu_session>& sps);
private:
std::vector<std::shared_ptr<smf_procedure>> pending_procedures;
......
......@@ -843,47 +843,16 @@ void pdu_session_update_sm_context_response::from_json(
* class: PDU Session Release SM Context Response
*/
//-----------------------------------------------------------------------------
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;
}
//-----------------------------------------------------------------------------
void pdu_session_release_sm_context_response::set_http_code(
const uint32_t code) {
m_http_code = code;
}
//-----------------------------------------------------------------------------
uint32_t pdu_session_release_sm_context_response::get_http_code() const {
return m_http_code;
}
//-----------------------------------------------------------------------------
void pdu_session_release_sm_context_response::to_json(
nlohmann::json& data) const {
pdu_session_msg::to_json(data);
data["cause"] = m_cause;
data["http_code"] = m_http_code;
pdu_session_sm_context_response::to_json(data);
}
//-----------------------------------------------------------------------------
void pdu_session_release_sm_context_response::from_json(
const nlohmann::json& data) {
pdu_session_msg::from_json(data);
if (data.find("cause") != data.end()) {
m_cause = data["cause"].get<int>();
}
if (data.find("http_code") != data.end()) {
m_http_code = data["http_code"].get<int>();
}
pdu_session_sm_context_response::from_json(data);
}
/*
......
......@@ -476,24 +476,17 @@ class pdu_session_release_sm_context_request : public pdu_session_msg {
};
//---------------------------------------------------------------------------------------
class pdu_session_release_sm_context_response : public pdu_session_msg {
class pdu_session_release_sm_context_response
: public pdu_session_sm_context_response {
public:
pdu_session_release_sm_context_response()
: pdu_session_msg(PDU_SESSION_RELEASE_SM_CONTEXT_RESPONSE) {
m_cause = 0;
m_http_code = 0;
};
void set_cause(uint8_t cause);
uint8_t get_cause();
void set_http_code(const uint32_t code);
uint32_t get_http_code() const;
: pdu_session_sm_context_response(
PDU_SESSION_RELEASE_SM_CONTEXT_RESPONSE){};
void to_json(nlohmann::json& data) const;
void from_json(const nlohmann::json& data);
private:
uint8_t m_cause;
uint32_t m_http_code;
};
//---------------------------------------------------------------------------------------
......
......@@ -717,6 +717,71 @@ bool smf_n1::create_n1_pdu_session_release_reject(
}
}
//-----------------------------------------------------------------------------------------------------
bool smf_n1::create_n1_pdu_session_release_command(
const std::shared_ptr<pdu_session_msg>& msg, std::string& nas_msg_str,
cause_value_5gsm_e sm_cause) {
Logger::smf_n1().info("Create N1 SM Container, PDU Session Release Command");
int bytes = {0};
unsigned char data[BUF_LEN] = {'\0'};
nas_message_t nas_msg = {};
nas_msg.header.extended_protocol_discriminator =
EPD_5GS_SESSION_MANAGEMENT_MESSAGES;
nas_msg.header.security_header_type = SECURITY_HEADER_TYPE_NOT_PROTECTED;
SM_msg* sm_msg = &nas_msg.plain.sm;
// Fill the content of SM header
sm_msg->header.extended_protocol_discriminator =
EPD_5GS_SESSION_MANAGEMENT_MESSAGES;
sm_msg->header.pdu_session_identity = msg->get_pdu_session_id();
Logger::smf_n1().info("PDU_SESSION_RELEASE_COMMAND, encode starting...");
// Fill the content of PDU Session Release Command
sm_msg->header.pdu_session_identity = msg->get_pdu_session_id();
sm_msg->header.procedure_transaction_identity =
msg->get_pti()
.procedure_transaction_id; // TODO: if PDU session release procedure
// is not triggered by a UE-requested PDU
// session release set the PTI IE of the
// PDU SESSION RELEASE COMMAND message
// to "No procedure transaction identity
// assigned"
sm_msg->header.message_type = PDU_SESSION_RELEASE_COMMAND;
sm_msg->pdu_session_release_command._5gsmcause =
static_cast<uint8_t>(sm_cause);
// TODO: to be updated when adding the following IEs
sm_msg->pdu_session_release_command.presence = 0x00;
// GPRSTimer3
// EAPMessage
//_5GSMCongestionReattemptIndicator
// ExtendedProtocolConfigurationOptions
Logger::smf_n1().debug(
"SM message, 5GSM Cause: 0x%x",
sm_msg->pdu_session_release_command._5gsmcause);
// Encode NAS message
bytes = nas_message_encode(
data, &nas_msg, sizeof(data) /*don't know the size*/, nullptr);
#if DEBUG_IS_ON
Logger::smf_n1().debug("Buffer Data: ");
for (int i = 0; i < bytes; i++) printf("%02x ", data[i]);
printf(" (bytes %d)\n", bytes);
#endif
if (bytes > 0) {
std::string n1Message((char*) data, bytes);
nas_msg_str = n1Message;
return true;
} else {
return false;
}
}
//-----------------------------------------------------------------------------------------------------
bool smf_n1::create_n1_pdu_session_release_command(
pdu_session_update_sm_context_response& sm_context_res,
......
......@@ -135,6 +135,9 @@ class smf_n1 {
pdu_session_update_sm_context_request& sm_context_res,
std::string& nas_msg_str, cause_value_5gsm_e sm_cause);
bool create_n1_pdu_session_release_command(
const std::shared_ptr<pdu_session_msg>& msg, std::string& nas_msg_str,
cause_value_5gsm_e sm_cause);
/*
* Create N1 SM Container: PDU Session Release Command
* Included in PDU Session Update SM Context Response (PDU Session Release
......
......@@ -845,6 +845,55 @@ bool smf_n2::create_n2_pdu_session_resource_modify_request_transfer(
return result;
}
//------------------------------------------------------------------------------
bool smf_n2::create_n2_pdu_session_resource_release_command_transfer(
const std::shared_ptr<pdu_session_msg>& msg,
n2_sm_info_type_e ngap_info_type, std::string& ngap_msg_str) {
Logger::smf_n2().debug(
"Create N2 SM Information: NGAP PDU Session Resource Release Command "
"Transfer IE");
bool result = false;
Ngap_PDUSessionResourceReleaseCommandTransfer_t*
ngap_resource_release_command_transfer = nullptr;
ngap_resource_release_command_transfer =
(Ngap_PDUSessionResourceReleaseCommandTransfer_t*) calloc(
1, sizeof(Ngap_PDUSessionResourceReleaseCommandTransfer_t));
// TODO: To be completed, here's an example
ngap_resource_release_command_transfer->cause.present =
Ngap_Cause_PR_radioNetwork;
ngap_resource_release_command_transfer->cause.choice.radioNetwork = 1;
// encode
size_t buffer_size = BUF_LEN;
char* buffer = (char*) calloc(1, buffer_size);
ssize_t encoded_size = aper_encode_to_new_buffer(
&asn_DEF_Ngap_PDUSessionResourceReleaseCommandTransfer, nullptr,
ngap_resource_release_command_transfer, (void**) &buffer);
if (encoded_size < 0) {
Logger::smf_n2().warn(
"NGAP PDU Session Release Command encode failed (encoded size %d)",
encoded_size);
result = false;
} else {
#if DEBUG_IS_ON
Logger::smf_n2().debug("N2 SM buffer data: ");
for (int i = 0; i < encoded_size; i++) printf("%02x ", (char) buffer[i]);
Logger::smf_n2().debug(" (%d bytes) \n", encoded_size);
#endif
std::string ngap_message((char*) buffer, encoded_size);
ngap_msg_str = ngap_message;
result = true;
}
// free memory
free_wrapper((void**) &ngap_resource_release_command_transfer);
free_wrapper((void**) &buffer);
return result;
}
//------------------------------------------------------------------------------
bool smf_n2::create_n2_pdu_session_resource_release_command_transfer(
pdu_session_update_sm_context_response& sm_context_res,
......
......@@ -162,6 +162,10 @@ class smf_n2 {
pdu_session_update_sm_context_response& sm_context_res,
n2_sm_info_type_e ngap_info_type, std::string& ngap_msg_str);
bool create_n2_pdu_session_resource_release_command_transfer(
const std::shared_ptr<pdu_session_msg>& msg,
n2_sm_info_type_e ngap_info_type, std::string& ngap_msg_str);
/*
* Create N2 SM Information: PDU Session Resource Release Command Transfer IE
* This IE is included in the following messages:
......
......@@ -257,7 +257,8 @@ class session_release_sm_context_procedure : public smf_session_procedure {
: smf_session_procedure(ps),
n4_triggered(),
n11_triggered_pending(),
n11_trigger() {}
n11_trigger(),
session_procedure_type() {}
/*
* Execute N11 Release SM Context Request procedure
......@@ -285,6 +286,7 @@ class session_release_sm_context_procedure : public smf_session_procedure {
std::shared_ptr<itti_n11_release_sm_context_request> n11_trigger;
std::shared_ptr<itti_n11_release_sm_context_response> n11_triggered_pending;
session_management_procedures_type_e session_procedure_type;
private:
smf_procedure_code send_n4_session_deletion_request();
......
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