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

Add Spgwu profile, nrf

parent a7dc32fa
/*
* 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
*/
#ifndef FILE_3GPP_29_510_NRF_SEEN
#define FILE_3GPP_29_510_NRF_SEEN
#include <vector>
typedef struct s_nssai // section 28.4, TS23.003
{
uint8_t sST;
std::string sD;
s_nssai(const uint8_t& sst, const std::string sd) : sST(sst), sD(sd) {}
s_nssai() : sST(), sD() {}
s_nssai(const s_nssai& p) : sST(p.sST), sD(p.sD) {}
bool operator==(const struct s_nssai& s) const {
if ((s.sST == this->sST) && (s.sD.compare(this->sD) == 0)) {
return true;
} else {
return false;
}
}
} snssai_t;
typedef struct dnai_s {
} dnai_t;
typedef struct dnn_upf_info_item_s {
std::string dnn;
// std::vector<std::string> dnai_list
// std::vector<std::string> pdu_session_types
} dnn_upf_info_item_t;
typedef struct snssai_upf_info_item_s {
snssai_t snssai;
std::vector<dnn_upf_info_item_t> dnn_upf_info_list;
} snssai_upf_info_item_t;
typedef struct upf_info_s {
std::vector<snssai_upf_info_item_t> snssai_upf_info_list;
} upf_info_t;
#define NRF_CURL_TIMEOUT_MS 100L
#endif
/*
* 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
*/
/*
* itti_msg_nrf.hpp
*
* Created on:
* Author:
*/
#ifndef ITTI_MSG_NRF_HPP_INCLUDED_
#define ITTI_MSG_NRF_HPP_INCLUDED_
#include "itti_msg.hpp"
#include "spgwu_profile.hpp"
//#include "PatchItem.h"
class itti_nrf_msg : public itti_msg {
public:
itti_nrf_msg(const itti_msg_type_t msg_type, const task_id_t orig,
const task_id_t dest)
:
itti_msg(msg_type, orig, dest) {
}
itti_nrf_msg(const itti_nrf_msg &i)
:
itti_msg(i) {
}
itti_nrf_msg(const itti_nrf_msg &i, const task_id_t orig,
const task_id_t dest)
:
itti_nrf_msg(i) {
origin = orig;
destination = dest;
}
};
//-----------------------------------------------------------------------------
class itti_nrf_register_nf_instance_request : public itti_nrf_msg {
public:
itti_nrf_register_nf_instance_request(const task_id_t orig,
const task_id_t dest)
: itti_nrf_msg(NRF_REGISTER_NF_INSTANCE_REQUEST, orig, dest),
http_version(1) {}
const char *get_msg_name() { return "NRF_REGISTER_NF_INSTANCE_REQUEST"; };
spgwu::spgwu_profile profile;
uint8_t http_version;
};
//-----------------------------------------------------------------------------
class itti_nrf_register_nf_instance_response : public itti_nrf_msg {
public:
itti_nrf_register_nf_instance_response(const task_id_t orig,
const task_id_t dest)
: itti_nrf_msg(NRF_REGISTER_NF_INSTANCE_RESPONSE, orig, dest),
http_version(1) {}
const char *get_msg_name() { return "NRF_REGISTER_NF_INSTANCE_RESPONSE"; };
spgwu::spgwu_profile profile;
uint8_t http_version;
uint8_t http_response_code;
};
//-----------------------------------------------------------------------------
class itti_nrf_update_nf_instance_request : public itti_nrf_msg {
public:
itti_nrf_update_nf_instance_request(const task_id_t orig,
const task_id_t dest)
: itti_nrf_msg(NRF_UPDATE_NF_INSTANCE_REQUEST, orig, dest),
http_version(1) {}
const char *get_msg_name() { return "NRF_UPDATE_NF_INSTANCE_REQUEST"; };
//std::vector<oai::smf_server::model::PatchItem> patch_items;
uint8_t http_version;
std::string upf_instance_id;
};
//-----------------------------------------------------------------------------
class itti_nrf_update_nf_instance_response : public itti_nrf_msg {
public:
itti_nrf_update_nf_instance_response(const task_id_t orig,
const task_id_t dest)
: itti_nrf_msg(NRF_UPDATE_NF_INSTANCE_RESPONSE, orig, dest),
http_version(1) {}
const char *get_msg_name() { return "NRF_UPDATE_NF_INSTANCE_RESPONSE"; };
uint8_t http_version;
std::string upf_instance_id;
uint8_t http_response_code;
};
//-----------------------------------------------------------------------------
class itti_nrf_deregister_nf_instance : public itti_nrf_msg {
public:
itti_nrf_deregister_nf_instance(const task_id_t orig,
const task_id_t dest)
: itti_nrf_msg(NRF_DEREGISTER_NF_INSTANCE, orig, dest),
http_version(1) {}
const char *get_msg_name() { return "NRF_DEREGISTER_NF_INSTANCE"; };
uint8_t http_version;
std::string upf_instance_id;
};
#endif /* ITTI_MSG_NRF_HPP_INCLUDED_ */
...@@ -53,6 +53,7 @@ typedef enum { ...@@ -53,6 +53,7 @@ typedef enum {
TASK_SPGWU_SX, TASK_SPGWU_SX,
TASK_SPGWU_S1U, TASK_SPGWU_S1U,
TASK_SGW_UDP, TASK_SGW_UDP,
TASK_SPGWU_NRF,
TASK_MAX, TASK_MAX,
TASK_NONE, TASK_NONE,
TASK_ALL = 255 TASK_ALL = 255
...@@ -137,6 +138,11 @@ typedef enum { ...@@ -137,6 +138,11 @@ typedef enum {
UDP_INIT, UDP_INIT,
UDP_DATA_REQ, UDP_DATA_REQ,
UDP_DATA_IND, UDP_DATA_IND,
NRF_REGISTER_NF_INSTANCE_REQUEST,
NRF_REGISTER_NF_INSTANCE_RESPONSE,
NRF_UPDATE_NF_INSTANCE_REQUEST,
NRF_UPDATE_NF_INSTANCE_RESPONSE,
NRF_DEREGISTER_NF_INSTANCE,
TIME_OUT, TIME_OUT,
HEALTH_PING, HEALTH_PING,
TERMINATE, TERMINATE,
......
...@@ -300,5 +300,5 @@ ENDIF(STATIC_LINKING) ...@@ -300,5 +300,5 @@ ENDIF(STATIC_LINKING)
# folly glog dl double-conversion for FB folly library # folly glog dl double-conversion for FB folly library
target_link_libraries (spgwu ${ASAN} -Wl,--start-group CN_UTILS SPGWU SPGW_SWITCH UDP GTPV1U PFCP 3GPP_COMMON_TYPES gflags glog dl double-conversion folly -Wl,--end-group target_link_libraries (spgwu ${ASAN} -Wl,--start-group CN_UTILS SPGWU SPGW_SWITCH UDP GTPV1U PFCP 3GPP_COMMON_TYPES gflags glog dl double-conversion folly -Wl,--end-group
pthread m rt config++ event boost_system) pthread m rt config++ event boost_system pistache curl)
...@@ -37,6 +37,8 @@ add_library (SPGWU STATIC ...@@ -37,6 +37,8 @@ add_library (SPGWU STATIC
spgwu_app.cpp spgwu_app.cpp
spgwu_config.cpp spgwu_config.cpp
spgwu_sx.cpp spgwu_sx.cpp
spgwu_profile.cpp
spgwu_nrf.cpp
) )
...@@ -33,6 +33,7 @@ ...@@ -33,6 +33,7 @@
#include "spgwu_config.hpp" #include "spgwu_config.hpp"
#include "spgwu_s1u.hpp" #include "spgwu_s1u.hpp"
#include "spgwu_sx.hpp" #include "spgwu_sx.hpp"
#include "spgwu_nrf.hpp"
#include <stdexcept> #include <stdexcept>
...@@ -44,6 +45,7 @@ using namespace std; ...@@ -44,6 +45,7 @@ using namespace std;
spgwu_sx* spgwu_sx_inst = nullptr; spgwu_sx* spgwu_sx_inst = nullptr;
spgwu_s1u* spgwu_s1u_inst = nullptr; spgwu_s1u* spgwu_s1u_inst = nullptr;
spgwu_nrf* spgwu_nrf_inst = nullptr;
extern itti_mw* itti_inst; extern itti_mw* itti_inst;
extern pfcp_switch* pfcp_switch_inst; extern pfcp_switch* pfcp_switch_inst;
...@@ -157,6 +159,12 @@ spgwu_app::spgwu_app(const std::string& config_file) { ...@@ -157,6 +159,12 @@ spgwu_app::spgwu_app(const std::string& config_file) {
Logger::spgwu_app().error("Cannot create PFCP_SWITCH: %s", e.what()); Logger::spgwu_app().error("Cannot create PFCP_SWITCH: %s", e.what());
throw; throw;
} }
try {
spgwu_nrf_inst = new spgwu_nrf();
} catch (std::exception& e) {
Logger::spgwu_app().error("Cannot create SPGWU_NRF: %s", e.what());
throw;
}
Logger::spgwu_app().startup("Started"); Logger::spgwu_app().startup("Started");
} }
......
/*
* 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 spgwu_nrf.cpp
\brief
\author Lionel GAUTHIER, Tien-Thinh NGUYEN
\company Eurecom
\date 2021
\email: lionel.gauthier@eurecom.fr, tien-thinh.nguyen@eurecom.fr
*/
#include "spgwu_nrf.hpp"
#include <stdexcept>
#include <curl/curl.h>
#include <pistache/http.h>
#include <pistache/mime.h>
#include <nlohmann/json.hpp>
#include "itti.hpp"
#include "logger.hpp"
#include "3gpp_29.510.h"
#include "spgwu_config.hpp"
using namespace Pistache::Http;
using namespace Pistache::Http::Mime;
using namespace spgwu;
using json = nlohmann::json;
extern itti_mw *itti_inst;
extern spgwu_nrf *spgwu_nrf_inst;
extern spgwu_config spgwu_cfg;
void spgwu_nrf_task(void *);
// To read content of the response from NF
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 spgwu_nrf_task(void *args_p) {
const task_id_t task_id = TASK_SPGWU_NRF;
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 NRF_REGISTER_NF_INSTANCE_REQUEST:
spgwu_nrf_inst->register_nf_instance(
std::static_pointer_cast<itti_nrf_register_nf_instance_request>(
shared_msg));
break;
case NRF_UPDATE_NF_INSTANCE_REQUEST:
spgwu_nrf_inst->update_nf_instance(
std::static_pointer_cast<itti_nrf_update_nf_instance_request>(
shared_msg));
break;
case NRF_DEREGISTER_NF_INSTANCE:
spgwu_nrf_inst->deregister_nf_instance(
std::static_pointer_cast<itti_nrf_deregister_nf_instance>(
shared_msg));
break;
case TERMINATE:
if (itti_msg_terminate *terminate =
dynamic_cast<itti_msg_terminate *>(msg)) {
Logger::spgwu_app().info("Received terminate message");
return;
}
break;
default:
Logger::spgwu_app().info("no handler for msg type %d", msg->msg_type);
}
} while (true);
}
//------------------------------------------------------------------------------
spgwu_nrf::spgwu_nrf() {
Logger::spgwu_app().startup("Starting...");
if (itti_inst->create_task(TASK_SPGWU_NRF, spgwu_nrf_task, nullptr)) {
Logger::spgwu_app().error("Cannot create task TASK_SPGWU_NRF");
throw std::runtime_error("Cannot create task TASK_SPGWU_NRF");
}
Logger::spgwu_app().startup("Started");
}
//-----------------------------------------------------------------------------------------------------
void spgwu_nrf::register_nf_instance(
std::shared_ptr<itti_nrf_register_nf_instance_request> msg) {
Logger::spgwu_app().debug(
"Send NF Instance Registration to NRF (HTTP version %d)",
msg->http_version);
nlohmann::json json_data = {};
msg->profile.to_json(json_data);
std::string url;
/*
std::string(inet_ntoa(*((struct in_addr *)&smf_cfg.nrf_addr.ipv4_addr))) +
":" + std::to_string(smf_cfg.nrf_addr.port) + NNRF_NFM_BASE +
smf_cfg.nrf_addr.api_version + NNRF_NF_REGISTER_URL +
msg->profile.get_nf_instance_id();
*/
Logger::spgwu_app().debug("Send NF Instance Registration to NRF (NRF URL %s)",
url.c_str());
std::string body = json_data.dump();
Logger::spgwu_app().debug(
"Send NF Instance Registration to NRF, msg body: \n %s", body.c_str());
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_CUSTOMREQUEST, "PUT");
curl_easy_setopt(curl, CURLOPT_TIMEOUT_MS, NRF_CURL_TIMEOUT_MS);
// 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);
Logger::spgwu_app().debug("Response from NRF, Http Code: %d", httpCode);
if (httpCode == 201) {
json response_data = {};
try {
response_data = json::parse(*httpData.get());
} catch (json::exception &e) {
Logger::spgwu_app().warn("Could not parse json from the NRF response");
}
Logger::spgwu_app().debug("Response from NRF, Json data: \n %s",
response_data.dump().c_str());
// send response to APP to process
std::shared_ptr<itti_nrf_register_nf_instance_response> itti_msg =
std::make_shared<itti_nrf_register_nf_instance_response>(
TASK_SPGWU_NRF, TASK_SPGWU_APP);
itti_msg->http_response_code = httpCode;
itti_msg->http_version = msg->http_version;
Logger::spgwu_app().debug("Registered SMF profile (from NRF)");
itti_msg->profile.from_json(response_data);
int ret = itti_inst->send_msg(itti_msg);
if (RETURNok != ret) {
Logger::spgwu_app().error(
"Could not send ITTI message %s to task TASK_SPGWU_APP",
itti_msg->get_msg_name());
}
} else {
Logger::spgwu_app().warn("Could not get response from NRF");
}
curl_slist_free_all(headers);
curl_easy_cleanup(curl);
}
curl_global_cleanup();
}
//-----------------------------------------------------------------------------------------------------
void spgwu_nrf::update_nf_instance(
std::shared_ptr<itti_nrf_update_nf_instance_request> msg) {
Logger::spgwu_app().debug("Send NF Update to NRF (HTTP version %d)",
msg->http_version);
/*
nlohmann::json json_data = nlohmann::json::array();
for (auto i : msg->patch_items) {
nlohmann::json item = {};
to_json(item, i);
json_data.push_back(item);
}
std::string body = json_data.dump();
Logger::spgwu_app().debug("Send NF Update to NRF (Msg body %s)", body.c_str());
std::string url =
std::string(inet_ntoa(*((struct in_addr *)&smf_cfg.nrf_addr.ipv4_addr))) +
":" + std::to_string(smf_cfg.nrf_addr.port) + NNRF_NFM_BASE +
smf_cfg.nrf_addr.api_version + NNRF_NF_REGISTER_URL +
msg->smf_instance_id;
Logger::spgwu_app().debug("Send NF Update to NRF (NRF URL %s)", url.c_str());
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_CUSTOMREQUEST, "PATCH");
curl_easy_setopt(curl, CURLOPT_TIMEOUT_MS, NRF_CURL_TIMEOUT_MS);
if (msg->http_version == 2) {
curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L);
// we use a self-signed test server, skip verification during debugging
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L);
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0L);
curl_easy_setopt(curl, CURLOPT_HTTP_VERSION,
CURL_HTTP_VERSION_2_PRIOR_KNOWLEDGE);
}
// 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);
Logger::spgwu_app().debug("Response from NRF, Http Code: %d", httpCode);
if ((static_cast<http_response_codes_e>(httpCode) ==
http_response_codes_e::HTTP_RESPONSE_CODE_OK) or
(static_cast<http_response_codes_e>(httpCode) ==
http_response_codes_e::HTTP_RESPONSE_CODE_NO_CONTENT)) {
Logger::spgwu_app().debug("Got successful response from NRF");
// TODO: in case of response containing NF profile
// send response to APP to process
std::shared_ptr<itti_nrf_update_nf_instance_response> itti_msg =
std::make_shared<itti_nrf_update_nf_instance_response>(TASK_SPGWU_NRF,
TASK_SPGWU_APP);
itti_msg->http_response_code = httpCode;
itti_msg->http_version = msg->http_version;
itti_msg->smf_instance_id = msg->smf_instance_id;
int ret = itti_inst->send_msg(itti_msg);
if (RETURNok != ret) {
Logger::spgwu_app().error(
"Could not send ITTI message %s to task TASK_SPGWU_APP",
itti_msg->get_msg_name());
}
} else {
Logger::spgwu_app().warn("Could not get response from NRF");
}
curl_slist_free_all(headers);
curl_easy_cleanup(curl);
}
curl_global_cleanup();
*/
}
//-----------------------------------------------------------------------------------------------------
void spgwu_nrf::deregister_nf_instance(
std::shared_ptr<itti_nrf_deregister_nf_instance> msg) {
Logger::spgwu_app().debug("Send NF De-register to NRF (HTTP version %d)",
msg->http_version);
std::string url ;
/*=
std::string(inet_ntoa(*((struct in_addr *)&smf_cfg.nrf_addr.ipv4_addr))) +
":" + std::to_string(smf_cfg.nrf_addr.port) + NNRF_NFM_BASE +
smf_cfg.nrf_addr.api_version + NNRF_NF_REGISTER_URL +
msg->smf_instance_id;
*/
Logger::spgwu_app().debug("Send NF De-register to NRF (NRF URL %s)",
url.c_str());
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_CUSTOMREQUEST, "DELETE");
curl_easy_setopt(curl, CURLOPT_TIMEOUT_MS, NRF_CURL_TIMEOUT_MS);
// 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());
res = curl_easy_perform(curl);
curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &httpCode);
Logger::spgwu_app().debug("Response from NRF, Http Code: %d", httpCode);
curl_slist_free_all(headers);
curl_easy_cleanup(curl);
}
curl_global_cleanup();
}
/*
* 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 spgwu_nrf.hpp
\author Lionel GAUTHIER, Tien-Thinh NGUYEN
\company Eurecom
\date 2021
\email: lionel.gauthier@eurecom.fr, tien-thinh.nguyen@eurecom.fr
*/
#ifndef FILE_SPGWU_NRF_HPP_SEEN
#define FILE_SPGWU_NRF_HPP_SEEN
#include <map>
#include <thread>
#include <curl/curl.h>
#include "3gpp_29.510.h"
#include "itti_msg_nrf.hpp"
namespace spgwu {
#define TASK_SPGWU_NRF_TIMEOUT_NRF_HEARTBEAT_REQUEST 1
class spgwu_nrf {
private:
std::thread::id thread_id;
std::thread thread;
public:
spgwu_nrf();
spgwu_nrf(spgwu_nrf const &) = delete;
void operator=(spgwu_nrf const &) = delete;
/*
* Send NF instance registration to NRF
* @param [std::shared_ptr<itti_nrf_register_nf_instance_request>] msg:
* Content of message to be sent
* @return void
*/
void register_nf_instance(
std::shared_ptr<itti_nrf_register_nf_instance_request> msg);
/*
* Send NF instance update to NRF
* @param [std::shared_ptr<itti_nrf_update_nf_instance_request>] msg: Content
* of message to be sent
* @return void
*/
void update_nf_instance(
std::shared_ptr<itti_nrf_update_nf_instance_request> msg);
/*
* Send NF deregister to NRF
* @param [std::shared_ptr<itti_nrf_deregister_nf_instance>] msg: Content
* of message to be sent
* @return void
*/
void deregister_nf_instance(
std::shared_ptr<itti_nrf_deregister_nf_instance> msg);
};
} // namespace smf
#endif /* FILE_SPGWU_NRF_HPP_SEEN */
/*
* 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 spgwu_profile.cpp
\brief
\author Tien-Thinh NGUYEN
\company Eurecom
\date 2021
\email: Tien-Thinh.Nguyen@eurecom.fr
*/
#include <boost/algorithm/string/classification.hpp>
#include <boost/algorithm/string/split.hpp>
#include "logger.hpp"
#include "spgwu_profile.hpp"
#include "string.hpp"
using namespace std;
using namespace spgwu;
//------------------------------------------------------------------------------
void spgwu_profile::set_nf_instance_id(const std::string &instance_id) {
nf_instance_id = instance_id;
}
//------------------------------------------------------------------------------
void spgwu_profile::get_nf_instance_id(std::string &instance_id) const {
instance_id = nf_instance_id;
}
//------------------------------------------------------------------------------
std::string spgwu_profile::get_nf_instance_id() const { return nf_instance_id; }
//------------------------------------------------------------------------------
void spgwu_profile::set_nf_instance_name(const std::string &instance_name) {
nf_instance_name = instance_name;
}
//------------------------------------------------------------------------------
void spgwu_profile::get_nf_instance_name(std::string &instance_name) const {
instance_name = nf_instance_name;
}
//------------------------------------------------------------------------------
std::string spgwu_profile::get_nf_instance_name() const {
return nf_instance_name;
}
//------------------------------------------------------------------------------
void spgwu_profile::set_nf_type(const std::string &type) { nf_type = type; }
//------------------------------------------------------------------------------
std::string spgwu_profile::get_nf_type() const { return nf_type; }
//------------------------------------------------------------------------------
void spgwu_profile::set_nf_status(const std::string &status) {
nf_status = status;
}
//------------------------------------------------------------------------------
void spgwu_profile::get_nf_status(std::string &status) const {
status = nf_status;
}
//------------------------------------------------------------------------------
std::string spgwu_profile::get_nf_status() const { return nf_status; }
//------------------------------------------------------------------------------
void spgwu_profile::set_nf_heartBeat_timer(const int32_t &timer) {
heartBeat_timer = timer;
}
//------------------------------------------------------------------------------
void spgwu_profile::get_nf_heartBeat_timer(int32_t &timer) const {
timer = heartBeat_timer;
}
//------------------------------------------------------------------------------
int32_t spgwu_profile::get_nf_heartBeat_timer() const { return heartBeat_timer; }
//------------------------------------------------------------------------------
void spgwu_profile::set_nf_priority(const uint16_t &p) { priority = p; }
//------------------------------------------------------------------------------
void spgwu_profile::get_nf_priority(uint16_t &p) const { p = priority; }
//------------------------------------------------------------------------------
uint16_t spgwu_profile::get_nf_priority() const { return priority; }
//------------------------------------------------------------------------------
void spgwu_profile::set_nf_capacity(const uint16_t &c) { capacity = c; }
//------------------------------------------------------------------------------
void spgwu_profile::get_nf_capacity(uint16_t &c) const { c = capacity; }
//------------------------------------------------------------------------------
uint16_t spgwu_profile::get_nf_capacity() const { return capacity; }
//------------------------------------------------------------------------------
void spgwu_profile::set_nf_snssais(const std::vector<snssai_t> &s) {
snssais = s;
}
//------------------------------------------------------------------------------
void spgwu_profile::get_nf_snssais(std::vector<snssai_t> &s) const {
s = snssais;
}
//------------------------------------------------------------------------------
void spgwu_profile::add_snssai(const snssai_t &s) { snssais.push_back(s); }
//------------------------------------------------------------------------------
void spgwu_profile::set_nf_ipv4_addresses(const std::vector<struct in_addr> &a) {
ipv4_addresses = a;
}
//------------------------------------------------------------------------------
void spgwu_profile::add_nf_ipv4_addresses(const struct in_addr &a) {
ipv4_addresses.push_back(a);
}
//------------------------------------------------------------------------------
void spgwu_profile::get_nf_ipv4_addresses(std::vector<struct in_addr> &a) const {
a = ipv4_addresses;
}
//------------------------------------------------------------------------------
void spgwu_profile::set_upf_info(const upf_info_t &s) { upf_info = s; }
//------------------------------------------------------------------------------
void spgwu_profile::add_upf_info_item(const snssai_upf_info_item_t &s) {
upf_info.snssai_upf_info_list.push_back(s);
}
//------------------------------------------------------------------------------
void spgwu_profile::get_upf_info(upf_info_t &s) const { s = upf_info; }
//------------------------------------------------------------------------------
void spgwu_profile::display() const {
Logger::spgwu_app().debug("NF instance info");
Logger::spgwu_app().debug("\tInstance ID: %s", nf_instance_id.c_str());
Logger::spgwu_app().debug("\tInstance name: %s", nf_instance_name.c_str());
Logger::spgwu_app().debug("\tInstance type: %s", nf_type.c_str());
Logger::spgwu_app().debug("\tStatus: %s", nf_status.c_str());
Logger::spgwu_app().debug("\tHeartBeat timer: %d", heartBeat_timer);
Logger::spgwu_app().debug("\tPriority: %d", priority);
Logger::spgwu_app().debug("\tCapacity: %d", capacity);
// SNSSAIs
if (snssais.size() > 0) {
Logger::spgwu_app().debug("\tSNSSAI:");
}
for (auto s : snssais) {
Logger::spgwu_app().debug("\t\t SST, SD: %d, %s", s.sST, s.sD.c_str());
}
// IPv4 Addresses
if (ipv4_addresses.size() > 0) {
Logger::spgwu_app().debug("\tIPv4 Addr:");
}
for (auto address : ipv4_addresses) {
Logger::spgwu_app().debug("\t\t %s", inet_ntoa(address));
}
// UPF info
if (upf_info.snssai_upf_info_list.size() > 0) {
Logger::spgwu_app().debug("\tUPF Info:");
}
for (auto s : upf_info.snssai_upf_info_list) {
Logger::spgwu_app().debug("\t\tParameters supported by the UPF:");
Logger::spgwu_app().debug("\t\t\tSNSSAI (SST %d, SD %s)", s.snssai.sST,
s.snssai.sD.c_str());
for (auto d : s.dnn_upf_info_list) {
Logger::spgwu_app().debug("\t\t\tDNN %s", d.dnn.c_str());
}
}
}
//------------------------------------------------------------------------------
void spgwu_profile::to_json(nlohmann::json &data) const {
data["nfInstanceId"] = nf_instance_id;
data["nfInstanceName"] = nf_instance_name;
data["nfType"] = nf_type;
data["nfStatus"] = nf_status;
data["heartBeatTimer"] = heartBeat_timer;
// SNSSAIs
data["sNssais"] = nlohmann::json::array();
for (auto s : snssais) {
nlohmann::json tmp = {};
tmp["sst"] = s.sST;
tmp["sd"] = s.sD;
;
data["sNssais"].push_back(tmp);
}
// ipv4_addresses
data["ipv4Addresses"] = nlohmann::json::array();
for (auto address : ipv4_addresses) {
nlohmann::json tmp = inet_ntoa(address);
data["ipv4Addresses"].push_back(tmp);
}
data["priority"] = priority;
data["capacity"] = capacity;
// UPF info
data["smfInfo"] = {};
data["smfInfo"]["sNssaiSmfInfoList"] = nlohmann::json::array();
for (auto s : upf_info.snssai_upf_info_list) {
nlohmann::json tmp = {};
tmp["sNssai"]["sst"] = s.snssai.sST;
tmp["sNssai"]["sd"] = s.snssai.sD;
tmp["dnnSmfInfoList"] = nlohmann::json::array();
for (auto d : s.dnn_upf_info_list) {
nlohmann::json dnn_json = {};
dnn_json["dnn"] = d.dnn;
tmp["dnnSmfInfoList"].push_back(dnn_json);
}
data["smfInfo"]["sNssaiSmfInfoList"].push_back(tmp);
}
Logger::spgwu_app().debug("UPF profile to json:\n %s", data.dump().c_str());
}
//------------------------------------------------------------------------------
void spgwu_profile::from_json(const nlohmann::json &data) {
if (data.find("nfInstanceId") != data.end()) {
nf_instance_id = data["nfInstanceId"].get<std::string>();
}
if (data.find("nfInstanceName") != data.end()) {
nf_instance_name = data["nfInstanceName"].get<std::string>();
}
if (data.find("nfType") != data.end()) {
nf_type = data["nfType"].get<std::string>();
}
if (data.find("nfStatus") != data.end()) {
nf_status = data["nfStatus"].get<std::string>();
}
if (data.find("heartBeatTimer") != data.end()) {
heartBeat_timer = data["heartBeatTimer"].get<int>();
}
// sNssais
if (data.find("sNssais") != data.end()) {
for (auto it : data["sNssais"]) {
snssai_t s = {};
s.sST = it["sst"].get<int>();
s.sD = it["sd"].get<std::string>();
snssais.push_back(s);
// Logger::spgwu_app().debug("Added SNSSAI (SST %d, SD %s)", s.sST,
// s.sD.c_str());
}
}
if (data.find("ipv4Addresses") != data.end()) {
nlohmann::json addresses = data["ipv4Addresses"];
for (auto it : addresses) {
struct in_addr addr4 = {};
std::string address = it.get<std::string>();
unsigned char buf_in_addr[sizeof(struct in_addr)];
if (inet_pton(AF_INET, util::trim(address).c_str(), buf_in_addr) == 1) {
memcpy(&addr4, buf_in_addr, sizeof(struct in_addr));
} else {
Logger::spgwu_app().warn("Address conversion: Bad value %s",
util::trim(address).c_str());
}
// Logger::spgwu_app().debug("\tIPv4 Addr: %s", address.c_str());
add_nf_ipv4_addresses(addr4);
}
}
if (data.find("priority") != data.end()) {
priority = data["priority"].get<int>();
}
if (data.find("capacity") != data.end()) {
capacity = data["capacity"].get<int>();
}
// UPF info
if (data.find("smfInfo") != data.end()) {
nlohmann::json info = data["smfInfo"];
dnn_upf_info_item_t dnn_item = {};
if (info.find("sNssaiSmfInfoList") != info.end()) {
nlohmann::json snssai_upf_info_list =
data["smfInfo"]["sNssaiSmfInfoList"];
for (auto it : snssai_upf_info_list) {
snssai_upf_info_item_t upf_info_item = {};
if (it.find("sNssai") != it.end()) {
if (it["sNssai"].find("sst") != it["sNssai"].end())
upf_info_item.snssai.sST = it["sNssai"]["sst"].get<int>();
if (it["sNssai"].find("sd") != it["sNssai"].end())
upf_info_item.snssai.sD = it["sNssai"]["sd"].get<std::string>();
}
if (it.find("dnnSmfInfoList") != it.end()) {
for (auto d : it["dnnSmfInfoList"]) {
if (d.find("dnn") != d.end()) {
dnn_item.dnn = d["dnn"].get<std::string>();
upf_info_item.dnn_upf_info_list.push_back(dnn_item);
}
}
}
upf_info.snssai_upf_info_list.push_back(upf_info_item);
}
}
}
display();
}
//------------------------------------------------------------------------------
void spgwu_profile::handle_heartbeart_timeout(uint64_t ms) {
Logger::spgwu_app().info("Handle heartbeart timeout profile %s, time %d",
nf_instance_id.c_str(), ms);
set_nf_status("SUSPENDED");
}
/*
* 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 spgwu_profile.hpp
\brief
\author Tien-Thinh NGUYEN
\company Eurecom
\date 2021
\email: Tien-Thinh.Nguyen@eurecom.fr
*/
#ifndef FILE_UPF_PROFILE_HPP_SEEN
#define FILE_UPF_PROFILE_HPP_SEEN
#include <arpa/inet.h>
#include <netinet/in.h>
#include <map>
#include <memory>
#include <nlohmann/json.hpp>
#include <shared_mutex>
#include <utility>
#include <vector>
#include "logger.hpp"
#include "3gpp_29.510.h"
namespace spgwu {
//using namespace std;
class spgwu_profile : public std::enable_shared_from_this<spgwu_profile> {
public:
spgwu_profile()
: nf_type("NF_TYPE_UNKNOWN"),
heartBeat_timer(0),
snssais(),
ipv4_addresses(),
priority(0),
capacity(0) {
nf_instance_name = "";
nf_status = "";
}
spgwu_profile(const std::string &id)
: nf_instance_id(id),
heartBeat_timer(0),
snssais(),
ipv4_addresses(),
priority(0),
capacity(0),
nf_type("NF_TYPE_UNKNOWN") {
nf_instance_name = "";
nf_status = "";
}
spgwu_profile &operator=(const spgwu_profile &s) {
nf_instance_id = s.nf_instance_id;
heartBeat_timer = s.heartBeat_timer;
snssais = s.snssais;
ipv4_addresses = s.ipv4_addresses;
priority = s.priority;
capacity = s.capacity;
nf_type = s.nf_type;
nf_instance_name = s.nf_instance_name;
nf_status = s.nf_status;
upf_info = s.upf_info;
}
// spgwu_profile(spgwu_profile &b) = delete;
virtual ~spgwu_profile() {
Logger::spgwu_app().debug("Delete UPF Profile instance...");
}
/*
* Set NF instance ID
* @param [const std::string &] instance_id: instance id
* @return void
*/
void set_nf_instance_id(const std::string &instance_id);
/*
* Get NF instance ID
* @param [std::string &] instance_id: store instance id
* @return void:
*/
void get_nf_instance_id(std::string &instance_id) const;
/*
* Get NF instance ID
* @param [std::string &] instance_id: store instance id
* @return void:
*/
std::string get_nf_instance_id() const;
/*
* Set NF instance name
* @param [const std::string &] instance_name: instance name
* @return void
*/
void set_nf_instance_name(const std::string &instance_name);
/*
* Get NF instance ID
* @param [std::string &] instance_name: store instance name
* @return void:
*/
void get_nf_instance_name(std::string &instance_name) const;
/*
* Get NF instance name
* @param
* @return [std::string] instance name
*/
std::string get_nf_instance_name() const;
/*
* Set NF instance status
* @param [const std::string &] status: instance status
* @return void
*/
void set_nf_status(const std::string &status);
/*
* Get NF instance status
* @param [std::string &] status: store instance status
* @return void:
*/
void get_nf_status(std::string &status) const;
/*
* Get NF status
* @param
* @return [std::string] instance status
*/
std::string get_nf_status() const;
/*
* Get NF type
* @param
* @return [std::string] nf type
*/
std::string get_nf_type() const;
/*
* Set NF type
* @param [const nf_type_t &] type: nf type
* @return void
*/
void set_nf_type(const std::string &type);
/*
* Set NF instance heartBeat_timer
* @param [const std::string &] timer: heartBeat_timer
* @return void
*/
void set_nf_heartBeat_timer(const int32_t &timer);
/*
* Get NF instance heartBeat_timer
* @param [std::string &] timer: store heartBeat_timer
* @return void:
*/
void get_nf_heartBeat_timer(int32_t &timer) const;
/*
* Get NF heartBeat_timer
* @param void
* @return heartBeat_timer
*/
int32_t get_nf_heartBeat_timer() const;
/*
* Set NF instance priority
* @param [const uint16_t] p: instance priority
* @return void
*/
void set_nf_priority(const uint16_t &p);
/*
* Get NF instance priority
* @param [uint16_t] p: store instance priority
* @return void:
*/
void get_nf_priority(uint16_t &p) const;
/*
* Get NF instance priority
* @param void
* @return [uint16_t] instance priority
*/
uint16_t get_nf_priority() const;
/*
* Set NF instance capacity
* @param [const uint16_t] c: instance capacity
* @return void
*/
void set_nf_capacity(const uint16_t &c);
/*
* Get NF instance priority
* @param [uint16_t ] c: store instance capacity
* @return void:
*/
void get_nf_capacity(uint16_t &c) const;
/*
* Get NF instance priority
* @param void
* @return [uint16_t ] instance capacity
*/
uint16_t get_nf_capacity() const;
/*
* Set NF instance SNSSAIs
* @param [std::vector<snssai_t> &] s: SNSSAIs
* @return void
*/
void set_nf_snssais(const std::vector<snssai_t> &s);
/*
* Add SNSSAI
* @param [snssai_t &] s: SNSSAI
* @return void
*/
void add_snssai(const snssai_t &s);
/*
* Get NF instance SNSSAIs
* @param [std::vector<snssai_t> &] s: store instance's SNSSAIs
* @return void:
*/
void get_nf_snssais(std::vector<snssai_t> &s) const;
/*
* Set NF instance ipv4_addresses
* @param [std::vector<struct in_addr> &] a: ipv4_addresses
* @return void
*/
void set_nf_ipv4_addresses(const std::vector<struct in_addr> &a);
/*
* Add an IPv4 address to the list of addresses
* @param [const struct in_addr &] a: ipv4_address
* @return void
*/
void add_nf_ipv4_addresses(const struct in_addr &a);
/*
* Get NF instance ipv4_addresses
* @param [std::vector<struct in_addr> &] a: store instance's ipv4_addresses
* @return void:
*/
void get_nf_ipv4_addresses(std::vector<struct in_addr> &a) const;
/*
* Set upf info
* @param [upf_info_t &] s: upf info
* @return void
*/
void set_upf_info(const upf_info_t &s);
/*
* Add an snssai_upf_info_item to the upf info
* @param [const snssai_upf_info_item_t &] s: snssai_smf_info_item
* @return void
*/
void add_upf_info_item(const snssai_upf_info_item_t &s);
/*
* Get NF instance smf info
* @param [smf_info_t &] s: store instance's smf info
* @return void:
*/
void get_upf_info(upf_info_t &s) const;
/*
* Print related-information for NF profile
* @param void
* @return void:
*/
void display() const;
/*
* Represent NF profile as json object
* @param [nlohmann::json &] data: Json data
* @return void
*/
void to_json(nlohmann::json &data) const;
/*
* Covert from a json represetation to SMF profile
* @param [nlohmann::json &] data: Json data
* @return void
*/
void from_json(const nlohmann::json &data);
/*
* Handle heartbeart timeout event
* @param [uint64_t] ms: current time
* @return void
*/
void handle_heartbeart_timeout(uint64_t ms);
protected:
// From NFProfile (Section 6.1.6.2.2@3GPP TS 29.510 V16.0.0 (2019-06))
std::string nf_instance_id;
std::string nf_instance_name;
std::string nf_type;
std::string nf_status;
int32_t heartBeat_timer;
std::vector<snssai_t> snssais;
std::vector<struct in_addr> ipv4_addresses;
uint16_t priority;
uint16_t capacity;
upf_info_t upf_info;
};
} // namespace spgwu
#endif
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