Commit 860bbfd1 authored by Tien-Thinh Nguyen's avatar Tien-Thinh Nguyen

Fix Deregistration procedure

parent f06e392e
...@@ -872,6 +872,11 @@ void amf_app::trigger_nf_deregistration() { ...@@ -872,6 +872,11 @@ void amf_app::trigger_nf_deregistration() {
} }
} }
void amf_app::add_promise(
uint32_t pid, boost::shared_ptr<boost::promise<uint32_t>>& p) {
std::unique_lock lock(m_curl_handle_responses_smf);
curl_handle_responses_smf.emplace(pid, p);
}
//--------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------
void amf_app::add_promise( void amf_app::add_promise(
uint32_t id, boost::shared_ptr<boost::promise<std::string>>& p) { uint32_t id, boost::shared_ptr<boost::promise<std::string>>& p) {
...@@ -886,6 +891,18 @@ void amf_app::add_promise( ...@@ -886,6 +891,18 @@ void amf_app::add_promise(
curl_handle_responses_n11.emplace(pid, p); curl_handle_responses_n11.emplace(pid, p);
} }
void amf_app::trigger_process_response(uint32_t pid, uint32_t http_code) {
Logger::amf_app().debug(
"Trigger process response: Set promise with ID %u "
"to ready",
pid);
std::unique_lock lock(m_curl_handle_responses_smf);
if (curl_handle_responses_smf.count(pid) > 0) {
curl_handle_responses_smf[pid]->set_value(http_code);
// Remove this promise from list
curl_handle_responses_smf.erase(pid);
}
}
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
void amf_app::trigger_process_response(uint32_t pid, std::string n2_sm) { void amf_app::trigger_process_response(uint32_t pid, std::string n2_sm) {
Logger::amf_app().debug( Logger::amf_app().debug(
......
...@@ -83,6 +83,10 @@ class amf_app { ...@@ -83,6 +83,10 @@ class amf_app {
std::map<std::string, std::shared_ptr<ue_context>> supi2ue_ctx; std::map<std::string, std::shared_ptr<ue_context>> supi2ue_ctx;
mutable std::shared_mutex m_supi2ue_ctx; mutable std::shared_mutex m_supi2ue_ctx;
mutable std::shared_mutex m_curl_handle_responses_smf;
std::map<uint32_t, boost::shared_ptr<boost::promise<uint32_t>>>
curl_handle_responses_smf;
mutable std::shared_mutex m_curl_handle_responses_n2_sm; mutable std::shared_mutex m_curl_handle_responses_n2_sm;
std::map<uint32_t, boost::shared_ptr<boost::promise<std::string>>> std::map<uint32_t, boost::shared_ptr<boost::promise<std::string>>>
curl_handle_responses_n2_sm; curl_handle_responses_n2_sm;
......
...@@ -2761,29 +2761,95 @@ void amf_n1::ue_initiate_de_registration_handle( ...@@ -2761,29 +2761,95 @@ void amf_n1::ue_initiate_de_registration_handle(
} }
// decode NAS msg // decode NAS msg
DeregistrationRequest* deregReq = new DeregistrationRequest(); DeregistrationRequest* dereg_request = new DeregistrationRequest();
deregReq->decodefrombuffer(NULL, (uint8_t*) bdata(nas), blength(nas)); dereg_request->decodefrombuffer(NULL, (uint8_t*) bdata(nas), blength(nas));
/*
_5gs_deregistration_type_t type = {};
deregReq->getDeregistrationType(type);
uint8_t deregType = 0;
deregReq->getDeregistrationType(deregType);
Logger::amf_n1().debug("Deregistration Type %X", deregType);
*/
// TODO: validate 5G Mobile Identity // TODO: validate 5G Mobile Identity
uint8_t mobile_id_type = 0; uint8_t mobile_id_type = 0;
deregReq->getMobilityIdentityType(mobile_id_type); dereg_request->getMobilityIdentityType(mobile_id_type);
Logger::amf_n1().debug("5G Mobile Identity %X", mobile_id_type); Logger::amf_n1().debug("5G Mobile Identity %X", mobile_id_type);
switch (mobile_id_type) { switch (mobile_id_type) {
case _5G_GUTI: { case _5G_GUTI: {
Logger::amf_n1().debug( Logger::amf_n1().debug(
"5G Mobile Identity, GUTI %s", deregReq->get_5g_guti().c_str()); "5G Mobile Identity, GUTI %s", dereg_request->get_5g_guti().c_str());
} break; } break;
default: { default: {
} }
} }
// Send request to SMF to release the established PDU sessions if needed
// Get list of PDU sessions
std::vector<std::shared_ptr<pdu_session_context>> sessions_ctx;
std::shared_ptr<ue_context> uc = {};
if (!find_ue_context(nc, uc)) {
Logger::amf_n1().warn("Cannot find the UE context");
return;
}
if (uc.get() != nullptr) {
if (uc->get_pdu_sessions_context(sessions_ctx)) {
// Send Nsmf_PDUSession_ReleaseSMContext to SMF to release the PDU session
std::map<uint32_t, boost::shared_future<uint32_t>> smf_responses;
for (auto session : sessions_ctx) {
std::shared_ptr<itti_nsmf_pdusession_release_sm_context> itti_msg =
std::make_shared<itti_nsmf_pdusession_release_sm_context>(
TASK_AMF_N1, TASK_AMF_N11);
// Generate a promise and associate this promise to the ITTI message
uint32_t promise_id = amf_app_inst->generate_promise_id();
Logger::amf_n1().debug("Promise ID generated %d", promise_id);
boost::shared_ptr<boost::promise<uint32_t>> p =
boost::make_shared<boost::promise<uint32_t>>();
boost::shared_future<uint32_t> f = p->get_future();
// Store the future to be processed later
smf_responses.emplace(promise_id, f);
amf_app_inst->add_promise(promise_id, p);
itti_msg->supi = uc->supi;
itti_msg->pdu_session_id = session->pdu_session_id;
itti_msg->promise_id = promise_id;
itti_msg->context_location = session->smf_context_location;
int ret = itti_inst->send_msg(itti_msg);
if (0 != ret) {
Logger::amf_n1().error(
"Could not send ITTI message %s to task TASK_AMF_N11",
itti_msg->get_msg_name());
}
}
// Wait for the response from SMF
while (!smf_responses.empty()) {
boost::future_status status;
// wait for timeout or ready
status = smf_responses.begin()->second.wait_for(
boost::chrono::milliseconds(FUTURE_STATUS_TIMEOUT_MS));
if (status == boost::future_status::ready) {
assert(smf_responses.begin()->second.is_ready());
assert(smf_responses.begin()->second.has_value());
assert(!smf_responses.begin()->second.has_exception());
// Wait for the result from APP and send reply to AMF
uint32_t http_response_code = smf_responses.begin()->second.get();
// TODO: process response code
}
smf_responses.erase(smf_responses.begin());
}
} else {
Logger::amf_n1().debug("No PDU session available");
}
}
// Check Deregistration type
uint8_t deregType = 0;
dereg_request->getDeregistrationType(deregType);
Logger::amf_n1().debug("Deregistration Type 0x%x", deregType);
// If UE switch-off, don't need to send Deregistration Accept
if ((deregType & 0b00001000) == 0) {
// Prepare DeregistrationAccept // Prepare DeregistrationAccept
DeregistrationAccept* deregAccept = new DeregistrationAccept(); DeregistrationAccept* deregAccept = new DeregistrationAccept();
deregAccept->setHeader(PLAIN_5GS_MSG); deregAccept->setHeader(PLAIN_5GS_MSG);
...@@ -2792,7 +2858,8 @@ void amf_n1::ue_initiate_de_registration_handle( ...@@ -2792,7 +2858,8 @@ void amf_n1::ue_initiate_de_registration_handle(
int encoded_size = deregAccept->encode2buffer(buffer, BUFFER_SIZE_512); int encoded_size = deregAccept->encode2buffer(buffer, BUFFER_SIZE_512);
comUt::print_buffer( comUt::print_buffer(
"amf_n1", "De-registration Accept message buffer", buffer, encoded_size); "amf_n1", "De-registration Accept message buffer", buffer,
encoded_size);
if (encoded_size < 1) { if (encoded_size < 1) {
Logger::nas_mm().error("Encode De-registration Accept message error!"); Logger::nas_mm().error("Encode De-registration Accept message error!");
return; return;
...@@ -2800,6 +2867,7 @@ void amf_n1::ue_initiate_de_registration_handle( ...@@ -2800,6 +2867,7 @@ void amf_n1::ue_initiate_de_registration_handle(
bstring b = blk2bstr(buffer, encoded_size); bstring b = blk2bstr(buffer, encoded_size);
itti_send_dl_nas_buffer_to_task_n2(b, ran_ue_ngap_id, amf_ue_ngap_id); itti_send_dl_nas_buffer_to_task_n2(b, ran_ue_ngap_id, amf_ue_ngap_id);
}
set_5gmm_state(nc, _5GMM_DEREGISTERED); set_5gmm_state(nc, _5GMM_DEREGISTERED);
......
...@@ -105,6 +105,14 @@ void amf_n11_task(void*) { ...@@ -105,6 +105,14 @@ void amf_n11_task(void*) {
amf_n11_inst->handle_itti_message(ref(*m)); amf_n11_inst->handle_itti_message(ref(*m));
} break; } break;
case NSMF_PDU_SESSION_RELEASE_SM_CTX: {
Logger::amf_n11().info(
"Receive Nsmf_PDUSessionReleaseSMContext, handling ...");
itti_nsmf_pdusession_release_sm_context* m =
dynamic_cast<itti_nsmf_pdusession_release_sm_context*>(msg);
amf_n11_inst->handle_itti_message(ref(*m));
} break;
case PDU_SESSION_RESOURCE_SETUP_RESPONSE: { case PDU_SESSION_RESOURCE_SETUP_RESPONSE: {
Logger::amf_n11().info( Logger::amf_n11().info(
"Receive PDU Session Resource Setup response, handling ..."); "Receive PDU Session Resource Setup response, handling ...");
...@@ -550,6 +558,7 @@ void amf_n11::handle_itti_message( ...@@ -550,6 +558,7 @@ void amf_n11::handle_itti_message(
string smf_addr = {}; string smf_addr = {};
std::string smf_api_version = {}; std::string smf_api_version = {};
std::string remote_uri = {};
if (!psc.get()->smf_available) { if (!psc.get()->smf_available) {
Logger::amf_n11().error("No SMF is available for this PDU session"); Logger::amf_n11().error("No SMF is available for this PDU session");
...@@ -558,24 +567,34 @@ void amf_n11::handle_itti_message( ...@@ -558,24 +567,34 @@ void amf_n11::handle_itti_message(
smf_api_version = psc->smf_api_version; smf_api_version = psc->smf_api_version;
} }
string remote_uri = psc.get()->location + "release"; remote_uri = psc.get()->smf_context_location + "/release";
nlohmann::json pdu_session_release_request; nlohmann::json pdu_session_release_request;
pdu_session_release_request["supi"] = itti_msg.supi.c_str(); pdu_session_release_request["supi"] = itti_msg.supi.c_str();
pdu_session_release_request["dnn"] = psc.get()->dnn.c_str(); pdu_session_release_request["dnn"] = psc.get()->dnn.c_str();
pdu_session_release_request["sNssai"]["sst"] = pdu_session_release_request["sNssai"]["sst"] = psc.get()->snssai.sST;
1; // TODO: check hardcoded value pdu_session_release_request["sNssai"]["sd"] = psc.get()->snssai.sD;
pdu_session_release_request["sNssai"]["sd"] =
"0"; // TODO: check hardcoded value
pdu_session_release_request["pduSessionId"] = psc.get()->pdu_session_id; pdu_session_release_request["pduSessionId"] = psc.get()->pdu_session_id;
pdu_session_release_request["cause"] = "REL_DUE_TO_REACTIVATION"; pdu_session_release_request["cause"] = "REL_DUE_TO_REACTIVATION"; // TODO:
pdu_session_release_request["ngApCause"] = "radioNetwork"; pdu_session_release_request["ngApCause"] = "radioNetwork";
std::string json_part = pdu_session_release_request.dump(); std::string msg_body = pdu_session_release_request.dump();
uint8_t http_version = 1; uint8_t http_version = 1;
if (amf_cfg.support_features.use_http2) http_version = 2; if (amf_cfg.support_features.use_http2) http_version = 2;
nlohmann::json response_json = {};
uint32_t response_code = 0;
// curl_http_client(
// remote_uri, json_part, "", "", itti_msg.supi,
// psc.get()->pdu_session_id, http_version);
curl_http_client( curl_http_client(
remote_uri, json_part, "", "", itti_msg.supi, psc.get()->pdu_session_id, remote_uri, "POST", msg_body, response_json, response_code, http_version);
http_version);
// Notify to the result
if (itti_msg.promise_id > 0) {
amf_app_inst->trigger_process_response(itti_msg.promise_id, response_code);
return;
}
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
......
...@@ -72,7 +72,10 @@ typedef enum { ...@@ -72,7 +72,10 @@ typedef enum {
PDU_SESSION_RESOURCE_SETUP_REQUEST, PDU_SESSION_RESOURCE_SETUP_REQUEST,
PDU_SESSION_RESOURCE_MODIFY_REQUEST, PDU_SESSION_RESOURCE_MODIFY_REQUEST,
PDU_SESSION_RESOURCE_RELEASE_COMMAND, PDU_SESSION_RESOURCE_RELEASE_COMMAND,
PDU_SESSION_RESOURCE_SETUP_RESPONSE,
NSMF_PDU_SESSION_RELEASE_SM_CTX,
UE_CONTEXT_RELEASE_REQUEST, UE_CONTEXT_RELEASE_REQUEST,
UE_CONTEXT_RELEASE_COMMAND,
UE_CONTEXT_RELEASE_COMPLETE, UE_CONTEXT_RELEASE_COMPLETE,
UE_RADIO_CAP_IND, UE_RADIO_CAP_IND,
UL_NAS_DATA_IND, // task amf_n1 message id UL_NAS_DATA_IND, // task amf_n1 message id
...@@ -95,13 +98,10 @@ typedef enum { ...@@ -95,13 +98,10 @@ typedef enum {
SBI_NOTIFICATION_DATA, SBI_NOTIFICATION_DATA,
SBI_NOTIFY_SUBSCRIBED_EVENT, SBI_NOTIFY_SUBSCRIBED_EVENT,
SBI_N1_MESSAGE_NOTIFICATION, SBI_N1_MESSAGE_NOTIFICATION,
UE_CONTEXT_RELEASE_COMMAND,
NSMF_PDU_SESSION_RELEASE_SM_CTX,
HANDOVER_REQUIRED, HANDOVER_REQUIRED,
HANDOVER_REQUEST_ACK, HANDOVER_REQUEST_ACK,
HANDOVER_NOTIFY, HANDOVER_NOTIFY,
UPLINK_RAN_STATUS_TRANSFER, UPLINK_RAN_STATUS_TRANSFER,
PDU_SESSION_RESOURCE_SETUP_RESPONSE,
PAGING, PAGING,
TIME_OUT, TIME_OUT,
HEALTH_PING, HEALTH_PING,
......
...@@ -119,11 +119,15 @@ class itti_nsmf_pdusession_release_sm_context : public itti_msg_n11 { ...@@ -119,11 +119,15 @@ class itti_nsmf_pdusession_release_sm_context : public itti_msg_n11 {
: itti_msg_n11(i) { : itti_msg_n11(i) {
supi = i.supi; supi = i.supi;
pdu_session_id = i.pdu_session_id; pdu_session_id = i.pdu_session_id;
promise_id = i.promise_id;
context_location = i.context_location;
} }
public: public:
std::string supi; std::string supi;
uint8_t pdu_session_id; uint8_t pdu_session_id;
uint32_t promise_id;
std::string context_location;
}; };
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
......
...@@ -47,7 +47,7 @@ _5GSDeregistrationType::_5GSDeregistrationType( ...@@ -47,7 +47,7 @@ _5GSDeregistrationType::_5GSDeregistrationType(
_5gs_deregistration_type_t type) { _5gs_deregistration_type_t type) {
u1.b = 0; u1.b = 0;
u1.bf.switch_off = type.switch_off; u1.bf.switch_off = type.switch_off;
u1.bf.dereg_required = type.dereg_required; u1.bf.re_registration_required = type.re_registration_required;
u1.bf.access_type = type.access_type; u1.bf.access_type = type.access_type;
u1.bf.iei = type.iei; u1.bf.iei = type.iei;
} }
...@@ -59,7 +59,7 @@ _5GSDeregistrationType::~_5GSDeregistrationType() {} ...@@ -59,7 +59,7 @@ _5GSDeregistrationType::~_5GSDeregistrationType() {}
void _5GSDeregistrationType::set(_5gs_deregistration_type_t type) { void _5GSDeregistrationType::set(_5gs_deregistration_type_t type) {
u1.b = 0; u1.b = 0;
u1.bf.switch_off = type.switch_off; u1.bf.switch_off = type.switch_off;
u1.bf.dereg_required = type.dereg_required; u1.bf.re_registration_required = type.re_registration_required;
u1.bf.access_type = type.access_type; u1.bf.access_type = type.access_type;
u1.bf.iei = type.iei; u1.bf.iei = type.iei;
} }
...@@ -67,7 +67,7 @@ void _5GSDeregistrationType::set(_5gs_deregistration_type_t type) { ...@@ -67,7 +67,7 @@ void _5GSDeregistrationType::set(_5gs_deregistration_type_t type) {
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
void _5GSDeregistrationType::get(_5gs_deregistration_type_t& type) { void _5GSDeregistrationType::get(_5gs_deregistration_type_t& type) {
type.switch_off = u1.bf.switch_off; type.switch_off = u1.bf.switch_off;
type.dereg_required = u1.bf.dereg_required; type.re_registration_required = u1.bf.re_registration_required;
type.access_type = u1.bf.access_type; type.access_type = u1.bf.access_type;
type.iei = u1.bf.iei; type.iei = u1.bf.iei;
} }
......
...@@ -35,7 +35,7 @@ namespace nas { ...@@ -35,7 +35,7 @@ namespace nas {
typedef struct _5gs_deregistration_type_s { typedef struct _5gs_deregistration_type_s {
uint8_t iei : 4; uint8_t iei : 4;
uint8_t switch_off : 1; uint8_t switch_off : 1;
uint8_t dereg_required : 1; uint8_t re_registration_required : 1;
uint8_t access_type : 2; uint8_t access_type : 2;
} _5gs_deregistration_type_t; } _5gs_deregistration_type_t;
...@@ -58,7 +58,7 @@ class _5GSDeregistrationType { ...@@ -58,7 +58,7 @@ class _5GSDeregistrationType {
struct { struct {
uint8_t iei : 4; uint8_t iei : 4;
uint8_t switch_off : 1; uint8_t switch_off : 1;
uint8_t dereg_required : 1; uint8_t re_registration_required : 1;
uint8_t access_type : 2; uint8_t access_type : 2;
} bf; } bf;
uint8_t b; uint8_t b;
......
...@@ -37,10 +37,10 @@ using namespace nas; ...@@ -37,10 +37,10 @@ using namespace nas;
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
DeregistrationRequest::DeregistrationRequest() { DeregistrationRequest::DeregistrationRequest() {
plain_header = NULL; plain_header = nullptr;
ie_deregistrationtype = NULL; ie_deregistrationtype = nullptr;
ie_ngKSI = NULL; ie_ngKSI = nullptr;
ie_5gs_mobility_id = NULL; ie_5gs_mobility_id = nullptr;
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
...@@ -72,13 +72,13 @@ void DeregistrationRequest::setngKSI(uint8_t tsc, uint8_t key_set_id) { ...@@ -72,13 +72,13 @@ void DeregistrationRequest::setngKSI(uint8_t tsc, uint8_t key_set_id) {
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
void DeregistrationRequest::getDeregistrationType(uint8_t& dereg_type) { void DeregistrationRequest::getDeregistrationType(uint8_t& dereg_type) {
ie_deregistrationtype->get(dereg_type); if (ie_deregistrationtype) ie_deregistrationtype->get(dereg_type);
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
void DeregistrationRequest::getDeregistrationType( void DeregistrationRequest::getDeregistrationType(
_5gs_deregistration_type_t& type) { _5gs_deregistration_type_t& type) {
ie_deregistrationtype->get(type); if (ie_deregistrationtype) ie_deregistrationtype->get(type);
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
...@@ -99,8 +99,8 @@ void DeregistrationRequest::setSUCI_SUPI_format_IMSI( ...@@ -99,8 +99,8 @@ void DeregistrationRequest::setSUCI_SUPI_format_IMSI(
uint8_t protection_sch_id, const string msin) { uint8_t protection_sch_id, const string msin) {
if (protection_sch_id != NULL_SCHEME) { if (protection_sch_id != NULL_SCHEME) {
Logger::nas_mm().error( Logger::nas_mm().error(
"encoding suci and supi format for imsi error, please choose right " "Encoding SUCI and SUPI format for IMSI error, please choose correct "
"interface"); "protection scheme");
return; return;
} else { } else {
ie_5gs_mobility_id = ie_5gs_mobility_id =
...@@ -184,7 +184,7 @@ int DeregistrationRequest::encode2buffer(uint8_t* buf, int len) { ...@@ -184,7 +184,7 @@ int DeregistrationRequest::encode2buffer(uint8_t* buf, int len) {
return 0; return 0;
} }
} else { } else {
Logger::nas_mm().error("Encoding IE Deregistrationt Type error"); Logger::nas_mm().error("Encoding IE Deregistration Type error");
return 0; return 0;
} }
if (int size = ie_5gs_mobility_id->encode2buffer( if (int size = ie_5gs_mobility_id->encode2buffer(
......
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