Commit fe06e1a6 authored by Tien-Thinh Nguyen's avatar Tien-Thinh Nguyen

Move N10 into N11 (becomes SBI later on)

parent 9d2804cb
...@@ -93,7 +93,7 @@ install_fb_folly_from_source(){ ...@@ -93,7 +93,7 @@ install_fb_folly_from_source(){
tar zxf release-1.8.0.tar.gz && \ tar zxf release-1.8.0.tar.gz && \
rm -f release-1.8.0.tar.gz && \ rm -f release-1.8.0.tar.gz && \
cd googletest-release-1.8.0 && \ cd googletest-release-1.8.0 && \
$CMAKE . && \ $CMAKE . -DBUILD_GMOCK=OFF && \
make && \ make && \
$SUDO make install $SUDO make install
ret=$?;[[ $ret -ne 0 ]] && popd && return $ret ret=$?;[[ $ret -ne 0 ]] && popd && return $ret
......
...@@ -55,7 +55,6 @@ add_library (SMF STATIC ...@@ -55,7 +55,6 @@ add_library (SMF STATIC
smf_pco.cpp smf_pco.cpp
smf_procedure.cpp smf_procedure.cpp
smf_n4.cpp smf_n4.cpp
smf_n10.cpp
smf_n11.cpp smf_n11.cpp
smf_event.cpp smf_event.cpp
smf_profile.cpp smf_profile.cpp
......
...@@ -56,7 +56,6 @@ ...@@ -56,7 +56,6 @@
#include "smf.h" #include "smf.h"
#include "smf_event.hpp" #include "smf_event.hpp"
#include "smf_n1.hpp" #include "smf_n1.hpp"
#include "smf_n10.hpp"
#include "smf_n11.hpp" #include "smf_n11.hpp"
#include "smf_n4.hpp" #include "smf_n4.hpp"
#include "smf_paa_dynamic.hpp" #include "smf_paa_dynamic.hpp"
...@@ -73,7 +72,6 @@ extern util::async_shell_cmd* async_shell_cmd_inst; ...@@ -73,7 +72,6 @@ extern util::async_shell_cmd* async_shell_cmd_inst;
extern smf_app* smf_app_inst; extern smf_app* smf_app_inst;
extern smf_config smf_cfg; extern smf_config smf_cfg;
smf_n4* smf_n4_inst = nullptr; smf_n4* smf_n4_inst = nullptr;
smf_n10* smf_n10_inst = nullptr;
smf_n11* smf_n11_inst = nullptr; smf_n11* smf_n11_inst = nullptr;
extern itti_mw* itti_inst; extern itti_mw* itti_inst;
...@@ -329,7 +327,6 @@ smf_app::smf_app(const std::string& config_file) ...@@ -329,7 +327,6 @@ smf_app::smf_app(const std::string& config_file)
try { try {
smf_n4_inst = new smf_n4(); smf_n4_inst = new smf_n4();
smf_n10_inst = new smf_n10();
smf_n11_inst = new smf_n11(); smf_n11_inst = new smf_n11();
} catch (std::exception& e) { } catch (std::exception& e) {
Logger::smf_app().error("Cannot create SMF_APP: %s", e.what()); Logger::smf_app().error("Cannot create SMF_APP: %s", e.what());
...@@ -926,7 +923,7 @@ void smf_app::handle_pdu_session_create_sm_context_request( ...@@ -926,7 +923,7 @@ void smf_app::handle_pdu_session_create_sm_context_request(
if (not use_local_configuration_subscription_data(dnn_selection_mode)) { if (not use_local_configuration_subscription_data(dnn_selection_mode)) {
Logger::smf_app().debug( Logger::smf_app().debug(
"Retrieve Session Management Subscription data from the UDM"); "Retrieve Session Management Subscription data from the UDM");
if (smf_n10_inst->get_sm_data(supi64, dnn, snssai, subscription)) { if (smf_n11_inst->get_sm_data(supi64, dnn, snssai, subscription)) {
// update dnn_context with subscription info // update dnn_context with subscription info
sc.get()->insert_dnn_subscription(snssai, subscription); sc.get()->insert_dnn_subscription(snssai, subscription);
} else { } else {
......
/*
* 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
*/
/*! \file smf_n10.cpp
\brief
\author Tien-Thinh NGUYEN
\company Eurecom
\date 2019
\email: tien-thinh.nguyen@eurecom.fr
*/
#include "smf_n10.hpp"
#include <stdexcept>
#include <curl/curl.h>
#include <nlohmann/json.hpp>
#include "common_defs.h"
#include "itti.hpp"
#include "logger.hpp"
#include "smf.h"
#include "smf_config.hpp"
using namespace smf;
using namespace std;
using json = nlohmann::json;
extern itti_mw* itti_inst;
extern smf_n10* smf_n10_inst;
extern smf_config smf_cfg;
void smf_n10_task(void*);
/*
* To read content of the response from UDM
*/
static std::size_t callback(
const char* in, std::size_t size, std::size_t num, std::string* out) {
const std::size_t totalBytes(size * num);
out->append(in, totalBytes);
return totalBytes;
}
//------------------------------------------------------------------------------
void smf_n10_task(void* args_p) {
const task_id_t task_id = TASK_SMF_N10;
itti_inst->notify_task_ready(task_id);
do {
std::shared_ptr<itti_msg> shared_msg = itti_inst->receive_msg(task_id);
auto* msg = shared_msg.get();
switch (msg->msg_type) {
case N10_SESSION_GET_SESSION_MANAGEMENT_SUBSCRIPTION:
break;
case TERMINATE:
if (itti_msg_terminate* terminate =
dynamic_cast<itti_msg_terminate*>(msg)) {
Logger::smf_n10().info("Received terminate message");
return;
}
break;
default:
Logger::smf_n10().info("no handler for msg type %d", msg->msg_type);
}
} while (true);
}
//------------------------------------------------------------------------------
smf_n10::smf_n10() {
Logger::smf_n10().startup("Starting...");
if (itti_inst->create_task(TASK_SMF_N10, smf_n10_task, nullptr)) {
Logger::smf_n10().error("Cannot create task TASK_SMF_N10");
throw std::runtime_error("Cannot create task TASK_SMF_N10");
}
Logger::smf_n10().startup("Started");
}
//------------------------------------------------------------------------------
bool smf_n10::get_sm_data(
const supi64_t& supi, const std::string& dnn, const snssai_t& snssai,
std::shared_ptr<session_management_subscription> subscription) {
// retrieve a UE's Session Management Subscription Data
nlohmann::json jsonData = {};
curl_global_init(CURL_GLOBAL_DEFAULT);
struct curl_slist* headers = nullptr;
headers = curl_slist_append(headers, "Accept: application/json");
headers = curl_slist_append(headers, "Content-Type: application/json");
headers = curl_slist_append(headers, "charsets: utf-8");
CURL* curl = curl_easy_init();
std::string url =
std::string(inet_ntoa(*((struct in_addr*) &smf_cfg.udm_addr.ipv4_addr))) +
":" + std::to_string(smf_cfg.udm_addr.port) + NUDM_SDM_BASE +
smf_cfg.udm_addr.api_version +
fmt::format(NUDM_SDM_GET_SM_DATA_URL, std::to_string(supi));
Logger::smf_n10().debug("UDM's URL: %s ", url.c_str());
if (curl) {
CURLcode res = {};
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, UDM_CURL_TIMEOUT_MS);
curl_easy_setopt(curl, CURLOPT_INTERFACE, smf_cfg.sbi.if_name.c_str());
// Response information.
long httpCode = {0};
std::unique_ptr<std::string> httpData(new std::string());
// Hook up data handling function.
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, &callback);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, httpData.get());
int numRetries = 0;
while (numRetries < UDM_NUMBER_RETRIES) {
res = curl_easy_perform(curl);
curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &httpCode);
Logger::smf_n10().debug("Response from UDM, HTTP Code: %d ", httpCode);
if (static_cast<http_response_codes_e>(httpCode) ==
http_response_codes_e::HTTP_RESPONSE_CODE_OK) {
Logger::smf_n10().debug(
"Got successful response from UDM, URL: %s ", url.c_str());
try {
jsonData = nlohmann::json::parse(*httpData.get());
break;
} catch (json::exception& e) {
Logger::smf_n10().warn("Could not parse json data from UDM");
}
numRetries++;
} else {
Logger::smf_n10().warn(
"Could not get response from UDM, URL %s, retry ...", url.c_str());
// retry
numRetries++;
}
}
curl_easy_cleanup(curl);
}
// process the response
if (!jsonData.empty()) {
Logger::smf_n10().debug("Response from UDM %s", jsonData.dump().c_str());
// retrieve SessionManagementSubscription and store in the context
for (nlohmann::json::iterator it = jsonData["dnnConfigurations"].begin();
it != jsonData["dnnConfigurations"].end(); ++it) {
Logger::smf_n10().debug("DNN %s", it.key().c_str());
try {
std::shared_ptr<dnn_configuration_t> dnn_configuration =
std::make_shared<dnn_configuration_t>();
pdu_session_type_t pdu_session_type(
pdu_session_type_e::PDU_SESSION_TYPE_E_IPV4);
std::string default_session_type =
it.value()["pduSessionTypes"]["defaultSessionType"];
Logger::smf_n10().debug(
"Default session type %s", default_session_type.c_str());
if (default_session_type.compare("IPV4") == 0) {
pdu_session_type.pdu_session_type =
pdu_session_type_e::PDU_SESSION_TYPE_E_IPV4;
} else if (default_session_type.compare("IPV6") == 0) {
pdu_session_type.pdu_session_type =
pdu_session_type_e::PDU_SESSION_TYPE_E_IPV6;
} else if (default_session_type.compare("IPV4V6") == 0) {
pdu_session_type.pdu_session_type =
pdu_session_type_e::PDU_SESSION_TYPE_E_IPV4V6;
}
dnn_configuration->pdu_session_types.default_session_type =
pdu_session_type;
// Ssc_Mode
ssc_mode_t ssc_mode(ssc_mode_e::SSC_MODE_1);
std::string default_ssc_mode = it.value()["sscModes"]["defaultSscMode"];
Logger::smf_n10().debug(
"Default SSC Mode %s", default_ssc_mode.c_str());
if (default_ssc_mode.compare("SSC_MODE_1") == 0) {
dnn_configuration->ssc_modes.default_ssc_mode =
ssc_mode_t(ssc_mode_e::SSC_MODE_1);
} else if (default_ssc_mode.compare("SSC_MODE_2") == 0) {
dnn_configuration->ssc_modes.default_ssc_mode =
ssc_mode_t(ssc_mode_e::SSC_MODE_2);
} else if (default_ssc_mode.compare("SSC_MODE_3") == 0) {
dnn_configuration->ssc_modes.default_ssc_mode =
ssc_mode_t(ssc_mode_e::SSC_MODE_3);
}
// 5gQosProfile
dnn_configuration->_5g_qos_profile._5qi =
it.value()["5gQosProfile"]["5qi"];
dnn_configuration->_5g_qos_profile.arp.priority_level =
it.value()["5gQosProfile"]["arp"]["priorityLevel"];
dnn_configuration->_5g_qos_profile.arp.preempt_cap =
it.value()["5gQosProfile"]["arp"]["preemptCap"];
dnn_configuration->_5g_qos_profile.arp.preempt_vuln =
it.value()["5gQosProfile"]["arp"]["preemptVuln"];
dnn_configuration->_5g_qos_profile.priority_level =
1; // TODO: hardcoded
// session_ambr
dnn_configuration->session_ambr.uplink =
it.value()["sessionAmbr"]["uplink"];
dnn_configuration->session_ambr.downlink =
it.value()["sessionAmbr"]["downlink"];
Logger::smf_n10().debug(
"Session AMBR Uplink %s, Downlink %s",
dnn_configuration->session_ambr.uplink.c_str(),
dnn_configuration->session_ambr.downlink.c_str());
subscription->insert_dnn_configuration(it.key(), dnn_configuration);
} catch (nlohmann::json::exception& e) {
Logger::smf_n10().warn(
"Exception message %s, exception id %d ", e.what(), e.id);
return false;
}
}
return true;
} else {
return false;
}
}
//------------------------------------------------------------------------------
void smf_n10::subscribe_sm_data() {
// TODO:
}
/*
* 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
*/
/*! \file smf_n10.hpp
\author Tien-Thinh NGUYEN
\company Eurecom
\date 2019
\email: tien-thinh.nguyen@eurecom.fr
*/
#ifndef FILE_SMF_N10_HPP_SEEN
#define FILE_SMF_N10_HPP_SEEN
#include <map>
#include <thread>
#include "3gpp_29.503.h"
#include "smf.h"
#include "smf_context.hpp"
namespace smf {
class smf_n10 {
private:
std::thread::id thread_id;
std::thread thread;
public:
smf_n10();
smf_n10(smf_n10 const&) = delete;
void operator=(smf_n10 const&) = delete;
/*
* Get SM subscription data from UDM
* @param [const supi64_t &] supi
* @param [const std::string &] dnn
* @param [const snssai_t &] snssai
* @param [std::shared_ptr<session_management_subscription>] subscription
* @return bool: True if successful, otherwise false
*
*/
bool get_sm_data(
const supi64_t& supi, const std::string& dnn, const snssai_t& snssai,
std::shared_ptr<session_management_subscription> subscription);
/*
* Subscribe to be notify from UDM
* @param []
* @return void
*
*/
void subscribe_sm_data();
};
} // namespace smf
#endif /* FILE_SMF_N10_HPP_SEEN */
...@@ -130,6 +130,9 @@ void smf_n11_task(void* args_p) { ...@@ -130,6 +130,9 @@ void smf_n11_task(void* args_p) {
shared_msg)); shared_msg));
break; break;
case N10_SESSION_GET_SESSION_MANAGEMENT_SUBSCRIPTION:
break;
case TERMINATE: case TERMINATE:
if (itti_msg_terminate* terminate = if (itti_msg_terminate* terminate =
dynamic_cast<itti_msg_terminate*>(msg)) { dynamic_cast<itti_msg_terminate*>(msg)) {
...@@ -990,3 +993,153 @@ void smf_n11::subscribe_upf_status_notify( ...@@ -990,3 +993,153 @@ void smf_n11::subscribe_upf_status_notify(
} }
curl_global_cleanup(); curl_global_cleanup();
} }
//------------------------------------------------------------------------------
bool smf_n11::get_sm_data(
const supi64_t& supi, const std::string& dnn, const snssai_t& snssai,
std::shared_ptr<session_management_subscription> subscription) {
// retrieve a UE's Session Management Subscription Data
nlohmann::json jsonData = {};
curl_global_init(CURL_GLOBAL_DEFAULT);
struct curl_slist* headers = nullptr;
headers = curl_slist_append(headers, "Accept: application/json");
headers = curl_slist_append(headers, "Content-Type: application/json");
headers = curl_slist_append(headers, "charsets: utf-8");
CURL* curl = curl_easy_init();
std::string url =
std::string(inet_ntoa(*((struct in_addr*) &smf_cfg.udm_addr.ipv4_addr))) +
":" + std::to_string(smf_cfg.udm_addr.port) + NUDM_SDM_BASE +
smf_cfg.udm_addr.api_version +
fmt::format(NUDM_SDM_GET_SM_DATA_URL, std::to_string(supi));
Logger::smf_n10().debug("UDM's URL: %s ", url.c_str());
if (curl) {
CURLcode res = {};
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, UDM_CURL_TIMEOUT_MS);
curl_easy_setopt(curl, CURLOPT_INTERFACE, smf_cfg.sbi.if_name.c_str());
// Response information.
long httpCode = {0};
std::unique_ptr<std::string> httpData(new std::string());
// Hook up data handling function.
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, &callback);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, httpData.get());
int numRetries = 0;
while (numRetries < UDM_NUMBER_RETRIES) {
res = curl_easy_perform(curl);
curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &httpCode);
Logger::smf_n10().debug("Response from UDM, HTTP Code: %d ", httpCode);
if (static_cast<http_response_codes_e>(httpCode) ==
http_response_codes_e::HTTP_RESPONSE_CODE_OK) {
Logger::smf_n10().debug(
"Got successful response from UDM, URL: %s ", url.c_str());
try {
jsonData = nlohmann::json::parse(*httpData.get());
break;
} catch (json::exception& e) {
Logger::smf_n10().warn("Could not parse json data from UDM");
}
numRetries++;
} else {
Logger::smf_n10().warn(
"Could not get response from UDM, URL %s, retry ...", url.c_str());
// retry
numRetries++;
}
}
curl_easy_cleanup(curl);
}
// process the response
if (!jsonData.empty()) {
Logger::smf_n10().debug("Response from UDM %s", jsonData.dump().c_str());
// retrieve SessionManagementSubscription and store in the context
for (nlohmann::json::iterator it = jsonData["dnnConfigurations"].begin();
it != jsonData["dnnConfigurations"].end(); ++it) {
Logger::smf_n10().debug("DNN %s", it.key().c_str());
try {
std::shared_ptr<dnn_configuration_t> dnn_configuration =
std::make_shared<dnn_configuration_t>();
pdu_session_type_t pdu_session_type(
pdu_session_type_e::PDU_SESSION_TYPE_E_IPV4);
std::string default_session_type =
it.value()["pduSessionTypes"]["defaultSessionType"];
Logger::smf_n10().debug(
"Default session type %s", default_session_type.c_str());
if (default_session_type.compare("IPV4") == 0) {
pdu_session_type.pdu_session_type =
pdu_session_type_e::PDU_SESSION_TYPE_E_IPV4;
} else if (default_session_type.compare("IPV6") == 0) {
pdu_session_type.pdu_session_type =
pdu_session_type_e::PDU_SESSION_TYPE_E_IPV6;
} else if (default_session_type.compare("IPV4V6") == 0) {
pdu_session_type.pdu_session_type =
pdu_session_type_e::PDU_SESSION_TYPE_E_IPV4V6;
}
dnn_configuration->pdu_session_types.default_session_type =
pdu_session_type;
// Ssc_Mode
ssc_mode_t ssc_mode(ssc_mode_e::SSC_MODE_1);
std::string default_ssc_mode = it.value()["sscModes"]["defaultSscMode"];
Logger::smf_n10().debug(
"Default SSC Mode %s", default_ssc_mode.c_str());
if (default_ssc_mode.compare("SSC_MODE_1") == 0) {
dnn_configuration->ssc_modes.default_ssc_mode =
ssc_mode_t(ssc_mode_e::SSC_MODE_1);
} else if (default_ssc_mode.compare("SSC_MODE_2") == 0) {
dnn_configuration->ssc_modes.default_ssc_mode =
ssc_mode_t(ssc_mode_e::SSC_MODE_2);
} else if (default_ssc_mode.compare("SSC_MODE_3") == 0) {
dnn_configuration->ssc_modes.default_ssc_mode =
ssc_mode_t(ssc_mode_e::SSC_MODE_3);
}
// 5gQosProfile
dnn_configuration->_5g_qos_profile._5qi =
it.value()["5gQosProfile"]["5qi"];
dnn_configuration->_5g_qos_profile.arp.priority_level =
it.value()["5gQosProfile"]["arp"]["priorityLevel"];
dnn_configuration->_5g_qos_profile.arp.preempt_cap =
it.value()["5gQosProfile"]["arp"]["preemptCap"];
dnn_configuration->_5g_qos_profile.arp.preempt_vuln =
it.value()["5gQosProfile"]["arp"]["preemptVuln"];
dnn_configuration->_5g_qos_profile.priority_level =
1; // TODO: hardcoded
// session_ambr
dnn_configuration->session_ambr.uplink =
it.value()["sessionAmbr"]["uplink"];
dnn_configuration->session_ambr.downlink =
it.value()["sessionAmbr"]["downlink"];
Logger::smf_n10().debug(
"Session AMBR Uplink %s, Downlink %s",
dnn_configuration->session_ambr.uplink.c_str(),
dnn_configuration->session_ambr.downlink.c_str());
subscription->insert_dnn_configuration(it.key(), dnn_configuration);
} catch (nlohmann::json::exception& e) {
Logger::smf_n10().warn(
"Exception message %s, exception id %d ", e.what(), e.id);
return false;
}
}
return true;
} else {
return false;
}
}
//------------------------------------------------------------------------------
void smf_n11::subscribe_sm_data() {
// TODO:
}
...@@ -141,6 +141,27 @@ class smf_n11 { ...@@ -141,6 +141,27 @@ class smf_n11 {
* @return pointer to the created curl * @return pointer to the created curl
*/ */
CURL* curl_create_handle(event_notification& ev_notif, std::string* data); CURL* curl_create_handle(event_notification& ev_notif, std::string* data);
/*
* Get SM subscription data from UDM
* @param [const supi64_t &] supi
* @param [const std::string &] dnn
* @param [const snssai_t &] snssai
* @param [std::shared_ptr<session_management_subscription>] subscription
* @return bool: True if successful, otherwise false
*
*/
bool get_sm_data(
const supi64_t& supi, const std::string& dnn, const snssai_t& snssai,
std::shared_ptr<session_management_subscription> subscription);
/*
* Subscribe to be notify from UDM
* @param []
* @return void
*
*/
void subscribe_sm_data();
}; };
} // namespace smf } // namespace smf
#endif /* FILE_SMF_N11_HPP_SEEN */ #endif /* FILE_SMF_N11_HPP_SEEN */
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