Commit 3b7c9f53 authored by Tien-Thinh Nguyen's avatar Tien-Thinh Nguyen

Add Handover Response supervision procedure

parent ffdf36a0
......@@ -479,3 +479,30 @@ void amf_app::trigger_nf_deregistration() {
itti_msg->get_msg_name());
}
}
//---------------------------------------------------------------------------------------------
void amf_app::add_promise(
uint32_t id, boost::shared_ptr<boost::promise<uint32_t>>& p) {
std::unique_lock lock(m_curl_handle_responses);
curl_handle_responses.emplace(id, p);
}
//---------------------------------------------------------------------------------------------
void amf_app::remove_promise(uint32_t id) {
std::unique_lock lock(m_curl_handle_responses);
curl_handle_responses.erase(id);
}
//------------------------------------------------------------------------------
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);
if (curl_handle_responses.count(pid) > 0) {
curl_handle_responses[pid]->set_value(http_code);
// Remove this promise from list
curl_handle_responses.erase(pid);
}
}
......@@ -40,6 +40,10 @@
#include "itti_msg_amf_app.hpp"
#include "ue_context.hpp"
#include "uint_generator.hpp"
#include <boost/thread.hpp>
#include <boost/thread/future.hpp>
using namespace config;
static uint32_t amf_app_ue_ngap_id_generator = 1;
......@@ -63,14 +67,6 @@ class amf_app {
// itti handlers
void handle_itti_message(itti_nas_signalling_establishment_request& itti_msg);
void handle_itti_message(itti_n1n2_message_transfer_request& itti_msg);
// context management
std::map<long, std::shared_ptr<ue_context>> amf_ue_ngap_id2ue_ctx;
mutable std::shared_mutex m_amf_ue_ngap_id2ue_ctx;
std::map<std::string, std::shared_ptr<ue_context>> ue_ctx_key;
mutable std::shared_mutex m_ue_ctx_key;
std::map<std::string, std::shared_ptr<ue_context>> supi2ue_ctx;
mutable std::shared_mutex m_supi2ue_ctx;
bool is_amf_ue_id_2_ue_context(const long& amf_ue_ngap_id) const;
std::shared_ptr<ue_context> amf_ue_id_2_ue_context(
......@@ -137,6 +133,47 @@ class amf_app {
* @return void
*/
void trigger_nf_deregistration();
/*
* Store the promise
* @param [uint32_t] pid: promise id
* @param [boost::shared_ptr<boost::promise<uint32_t>>&] p: promise
* @return void
*/
void add_promise(
uint32_t pid, boost::shared_ptr<boost::promise<uint32_t>>& p);
/*
* Remove the promise
* @param [uint32_t] pid: promise id
* @return void
*/
void remove_promise(uint32_t id);
/*
* Generate an unique value for promise id
* @param void
* @return generated promise id
*/
static uint64_t generate_promise_id() {
return util::uint_uid_generator<uint64_t>::get_instance().get_uid();
}
void trigger_process_response(uint32_t pid, uint32_t http_code);
private:
// context management
std::map<long, std::shared_ptr<ue_context>> amf_ue_ngap_id2ue_ctx;
mutable std::shared_mutex m_amf_ue_ngap_id2ue_ctx;
std::map<std::string, std::shared_ptr<ue_context>> ue_ctx_key;
mutable std::shared_mutex m_ue_ctx_key;
std::map<std::string, std::shared_ptr<ue_context>> supi2ue_ctx;
mutable std::shared_mutex m_supi2ue_ctx;
mutable std::shared_mutex m_curl_handle_responses;
std::map<uint32_t, boost::shared_ptr<boost::promise<uint32_t>>>
curl_handle_responses;
};
} // namespace amf_application
......
......@@ -212,7 +212,8 @@ void amf_n11::handle_itti_message(
octet_stream_2_hex_stream(
(uint8_t*) bdata(itti_msg.n2sm), blength(itti_msg.n2sm), n2SmMsg);
curl_http_client(
remote_uri, json_part, "", n2SmMsg, supi, itti_msg.pdu_session_id);
remote_uri, json_part, "", n2SmMsg, supi, itti_msg.pdu_session_id,
itti_msg.promise_id);
stacs.display();
}
......@@ -499,7 +500,8 @@ void amf_n11::handle_post_sm_context_response_error(
//------------------------------------------------------------------------------
void amf_n11::curl_http_client(
std::string remoteUri, std::string jsonData, std::string n1SmMsg,
std::string n2SmMsg, std::string supi, uint8_t pdu_session_id) {
std::string n2SmMsg, std::string supi, uint8_t pdu_session_id,
uint32_t promise_id) {
Logger::amf_n11().debug("Call SMF service: %s", remoteUri.c_str());
uint8_t number_parts = 0;
......@@ -580,6 +582,11 @@ void amf_n11::curl_http_client(
Logger::amf_n11().debug("Get response with HTTP code (%d)", httpCode);
Logger::amf_n11().debug("Response body %s", response.c_str());
// Notify to the result if necessary
if (promise_id > 0) {
amf_app_inst->trigger_process_response(promise_id, httpCode);
}
if (static_cast<http_response_codes_e>(httpCode) ==
http_response_codes_e::HTTP_RESPONSE_CODE_0) {
// TODO: should be removed
......@@ -1008,7 +1015,7 @@ void amf_n11::curl_http_client(
std::string cause = response_data["error"]["cause"];
Logger::amf_n1().info("Call Network Function services failure");
Logger::amf_n1().info("Cause value: %s", cause.c_str());
Logger::amf_n11().info("Cause value: %s", cause.c_str());
}
curl_slist_free_all(headers);
curl_easy_cleanup(curl);
......
......@@ -66,7 +66,8 @@ class amf_n11 {
void curl_http_client(
std::string remoteUri, std::string jsonData, std::string n1SmMsg,
std::string n2SmMsg, std::string supi, uint8_t pdu_session_id);
std::string n2SmMsg, std::string supi, uint8_t pdu_session_id,
uint32_t promise_id = 0);
void curl_http_client(
std::string remoteUri, std::string Method, std::string msgBody,
......
......@@ -52,6 +52,11 @@
#include "logger.hpp"
#include "sctp_server.hpp"
#include <boost/chrono.hpp>
#include <boost/chrono/chrono.hpp>
#include <boost/chrono/duration.hpp>
#include <boost/chrono/system_clocks.hpp>
extern "C" {
#include "dynamic_memory_check.h"
}
......@@ -1208,6 +1213,8 @@ bool amf_n2::handle_itti_message(itti_handover_required& itti_msg) {
std::vector<PDUSessionResourceSetupRequestItem_t> list;
PDUSessionResourceSetupRequestItem_t item = {};
std::map<uint32_t, boost::shared_future<uint32_t>> curl_responses;
for (auto pdu_session_resource : pdu_session_resource_list) {
std::shared_ptr<pdu_session_context> psc = {};
if (amf_app_inst->find_pdu_session_context(
......@@ -1225,6 +1232,18 @@ bool amf_n2::handle_itti_message(itti_handover_required& itti_msg) {
// Send PDUSessionUpdateSMContextRequest to SMF for each active PDU
// sessions
// Generate a promise and associate this promise to the curl handle
uint32_t promise_id = amf_app_inst->generate_promise_id();
Logger::amf_n2().debug("Promise ID generated %d", promise_id);
uint32_t* pid_ptr = &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();
amf_app_inst->add_promise(promise_id, p);
curl_responses.emplace(promise_id, f);
Logger::amf_n2().debug(
"Sending ITTI to trigger PDUSessionUpdateSMContextRequest to SMF to "
"task TASK_AMF_N11");
......@@ -1238,6 +1257,7 @@ bool amf_n2::handle_itti_message(itti_handover_required& itti_msg) {
itti_msg->n2sm_info_type = "HANDOVER_REQUIRED";
itti_msg->amf_ue_ngap_id = amf_ue_ngap_id;
itti_msg->ran_ue_ngap_id = ran_ue_ngap_id;
itti_msg->promise_id = promise_id;
std::shared_ptr<itti_nsmf_pdusession_update_sm_context> i =
std::shared_ptr<itti_nsmf_pdusession_update_sm_context>(itti_msg);
......@@ -1273,8 +1293,35 @@ bool amf_n2::handle_itti_message(itti_handover_required& itti_msg) {
// TODO: Handover Response supervision
// Wait until receiving all responses from SMFs before sending Handover
// Request to Target RAN
bool result = true;
while (!curl_responses.empty()) {
boost::future_status status;
// wait for timeout or ready
status = curl_responses.begin()->second.wait_for(
boost::chrono::milliseconds(FUTURE_STATUS_TIMEOUT_MS));
if (status == boost::future_status::ready) {
assert(curl_responses.begin()->second.is_ready());
assert(curl_responses.begin()->second.has_value());
assert(!curl_responses.begin()->second.has_exception());
// Wait for the result from APP and send reply to AMF
uint32_t response_code = curl_responses.begin()->second.get();
if (static_cast<http_response_codes_e>(response_code) ==
http_response_codes_e::HTTP_RESPONSE_CODE_200_OK) {
result = result && true;
} else {
result = false;
}
Logger::ngap().debug(
"Got result for promise ID %d", curl_responses.begin()->first);
} else {
result = true;
}
curl_responses.erase(curl_responses.begin());
}
// TODO: process result
// Request to Target RAN
handover_request->setPduSessionResourceSetupList(list);
handover_request->setAllowedNSSAI(Allowed_Nssai);
handover_request->setSourceToTarget_TransparentContainer(sourceTotarget);
......
......@@ -108,4 +108,6 @@ constexpr auto CURL_MIME_BOUNDARY = "----Boundary";
#define BUFFER_SIZE_512 512
#define BUFFER_SIZE_256 256
#define FUTURE_STATUS_TIMEOUT_MS 100
#endif
......@@ -82,6 +82,7 @@ class itti_nsmf_pdusession_update_sm_context : public itti_msg_n11 {
const task_id_t origin, const task_id_t destination)
: itti_msg_n11(NSMF_PDU_SESSION_UPDATE_SM_CTX, origin, destination) {
is_n2sm_set = false;
promise_id = 0;
}
itti_nsmf_pdusession_update_sm_context(
const itti_nsmf_pdusession_update_sm_context& i)
......@@ -90,6 +91,8 @@ class itti_nsmf_pdusession_update_sm_context : public itti_msg_n11 {
n2sm = i.n2sm;
is_n2sm_set = i.is_n2sm_set;
n2sm_info_type = i.n2sm_info_type;
promise_id = i.promise_id;
;
}
public:
......@@ -100,6 +103,7 @@ class itti_nsmf_pdusession_update_sm_context : public itti_msg_n11 {
std::string n2sm_info_type;
uint32_t ran_ue_ngap_id;
long amf_ue_ngap_id;
uint32_t promise_id;
};
class itti_nsmf_pdusession_release_sm_context : public itti_msg_n11 {
......
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