Commit 1a1dd6ea authored by Tien-Thinh Nguyen's avatar Tien-Thinh Nguyen

Merge branch 'develop' into 'improve_smf_context_handling'

# Conflicts:
#   src/smf_app/smf_app.cpp
#   src/smf_app/smf_context.cpp
#   src/smf_app/smf_context.hpp
#   src/smf_app/smf_procedure.cpp
parents f975276f 71b5eb69
......@@ -3,13 +3,13 @@
INSTANCE=1
PREFIX='/usr/local/etc/oai'
sudo mkdir -m 0777 -p $PREFIX
mkdir -m 0777 -p $PREFIX
cp ../../etc/smf.conf $PREFIX
declare -A SMF_CONF
SMF_CONF[@INSTANCE@]=$INSTANCE
SMF_CONF[@PREFIX@]=$PREFIX
# SMF_CONF[@PREFIX@]=$PREFIX
SMF_CONF[@PID_DIRECTORY@]='/var/run'
SMF_CONF[@SMF_INTERFACE_NAME_FOR_N4@]='wlo1'
......@@ -27,7 +27,7 @@ SMF_CONF[@UDM_PORT@]='80'
SMF_CONF[@UDM_API_VERSION@]='v2'
SMF_CONF[@UDM_FQDN@]='localhost'
SMF_CONF[@AMF_IPV4_ADDRESS@]='192.168.122.183'
SMF_CONF[@AMF_IPV4_ADDRESS@]='192.168.74.195'
SMF_CONF[@AMF_PORT@]='80'
SMF_CONF[@AMF_API_VERSION@]='v1'
SMF_CONF[@AMF_FQDN@]='localhost'
......@@ -35,7 +35,7 @@ SMF_CONF[@AMF_FQDN@]='localhost'
SMF_CONF[@UPF_IPV4_ADDRESS@]='192.168.12.245'
SMF_CONF[@UPF_FQDN@]='localhost'
SMF_CONF[@NRF_IPV4_ADDRESS@]='192.168.1.23'
SMF_CONF[@NRF_IPV4_ADDRESS@]='127.0.0.1'
SMF_CONF[@NRF_PORT@]='8080'
SMF_CONF[@NRF_API_VERSION@]='v1'
SMF_CONF[@NRF_FQDN@]='localhost'
......
......@@ -114,6 +114,10 @@ pipeline {
error "Stopping pipeline!"
}
}
if (params.DockerHubCredentials == null) {
echo '\u26D4 \u001B[31mNo Credentials to push to DockerHub!\u001B[0m'
error "Stopping pipeline!"
}
}
}
}
......@@ -197,6 +201,10 @@ pipeline {
myShCmd('docker build --no-cache --target oai-smf --tag oai-smf:' + smf_tag + ' --file ci-scripts/docker/Dockerfile.ci.ubuntu.18.04 . > archives/smf_docker_image_build.log 2>&1', rem_u18_host_flag, rem_u18_host_user, rem_u18_host)
}
myShCmd('docker image ls >> archives/smf_docker_image_build.log', rem_u18_host_flag, rem_u18_host_user, rem_u18_host)
// We will keep also the TMP image in U18 case.
if ("MERGE".equals(env.gitlabActionType)) {
myShCmd('docker image tag oai-smf:' + smf_tag + ' oai-smf:' + rhel_smf_tag, rem_u18_host_flag, rem_u18_host_user, rem_u18_host)
}
}
}
}
......@@ -403,6 +411,25 @@ pipeline {
}
}
}
// For the moment it is Docker-Hub, but we might have a new one internally.
stage ('Pushing Image to Official Registry') {
steps {
script {
// Only in case of push to target branch!
if ("PUSH".equals(env.gitlabActionType)) {
withCredentials([
[$class: 'UsernamePasswordMultiBinding', credentialsId: "${params.DockerHubCredentials}", usernameVariable: 'DH_Username', passwordVariable: 'DH_Password']
]) {
myShCmd("echo ${DH_Password} | docker login --username ${DH_Username} --password-stdin", rem_u18_host_flag, rem_u18_host_user, rem_u18_host)
myShCmd("docker image tag oai-smf:develop ${DH_Username}/oai-smf:develop", rem_u18_host_flag, rem_u18_host_user, rem_u18_host)
myShCmd("docker push ${DH_Username}/oai-smf:develop", rem_u18_host_flag, rem_u18_host_user, rem_u18_host)
myShCmd("docker rmi ${DH_Username}/oai-smf:develop", rem_u18_host_flag, rem_u18_host_user, rem_u18_host)
myShCmd("docker logout", rem_u18_host_flag, rem_u18_host_user, rem_u18_host)
}
}
}
}
}
}
post {
success {
......
......@@ -55,7 +55,7 @@ SMF =
IPV4_LIST = (
{RANGE = "12.1.1.2 - 12.1.1.128";}, # STRING, IPv4 RANGE IP_start - IP_end, YOUR NETWORK CONFIG HERE.
{RANGE = "12.1.1.129 - 12.1.1.224";}, # STRING, IPv4 RANGE IP_start - IP_end, YOUR NETWORK CONFIG HERE.
{RANGE = "10.10.10.2 - 10.10.10.253";} # STRING, IPv4 RANGE IP_start - IP_end, YOUR NETWORK CONFIG HERE.
{RANGE = "10.10.10.2 - 10.10.10.253";} # STRING, IPv4 RANGE IP_start - IP_end, YOUR NETWORK CONFIG HERE.
);
IPV6_LIST = (
......@@ -68,8 +68,8 @@ SMF =
DNN_LIST = (
# IPV4_POOL, IPV6_POOL are index in IPV4_LIST, IPV6_LIST, PDU_SESSION_TYPE choice in {IPv4, IPv6, IPv4v6}
{DNN_NI = "default"; PDU_SESSION_TYPE = "IPv4"; IPV4_POOL = 0; IPV6_POOL = -1},
{DNN_NI = "carrier.com"; PDU_SESSION_TYPE = "IPv4"; IPV4_POOL = 1; IPV6_POOL = -1},
{DNN_NI = "oai"; PDU_SESSION_TYPE = "IPv4"; IPV4_POOL = 2; IPV6_POOL = -1}
{DNN_NI = "carrier.com"; PDU_SESSION_TYPE = "IPv4"; IPV4_POOL = 2; IPV6_POOL = -1},
{DNN_NI = "oai"; PDU_SESSION_TYPE = "IPv4"; IPV4_POOL = 1; IPV6_POOL = -1}
);
# DNS address communicated to UEs
......@@ -77,7 +77,11 @@ SMF =
DEFAULT_DNS_SEC_IPV4_ADDRESS = "@DEFAULT_DNS_SEC_IPV4_ADDRESS@"; # YOUR DNS CONFIG HERE
DEFAULT_DNS_IPV6_ADDRESS = "2001:4860:4860::8888"; # YOUR DNS CONFIG HERE
DEFAULT_DNS_SEC_IPV6_ADDRESS = "2001:4860:4860::8844"; # YOUR DNS CONFIG HERE
#Default UE MTU
UE_MTU = 1358;
# SUPPORT FEATURES
SUPPORT_FEATURES:
{
# STRING, {"yes", "no"},
......@@ -87,6 +91,8 @@ SMF =
# but you may need to set to yes for UE that do not explicitly request a PDN address through NAS signalling
USE_LOCAL_SUBSCRIPTION_INFO = "yes"; # Set to yes if SMF uses local subscription information instead of from an UDM
USE_FQDN_DNS = "@USE_FQDN_DNS@"; # Set to yes if AMF/UDM/NRF/UPF will relying on a DNS to resolve FQDN
HTTP_VERSION = @HTTP_VERSION@; # YOUR NRF CONFIG HERE (default: 1)
USE_NETWORK_INSTANCE = "@USE_NETWORK_INSTANCE@" # Set yes if network instance is to be used for given UPF
}
AMF :
......@@ -114,8 +120,8 @@ SMF =
};
UPF_LIST = (
{IPV4_ADDRESS = "@UPF_IPV4_ADDRESS@" ; FQDN = "@UPF_FQDN_0@"} # YOUR UPF CONFIG HERE
);
{IPV4_ADDRESS = "@UPF_IPV4_ADDRESS@" ; FQDN = "@UPF_FQDN_0@"; NWI_LIST = ({DOMAIN_ACCESS = "@DOMAIN_ACCESS@", DOMAIN_CORE = "@DOMAIN_CORE@"})} # YOUR UPF CONFIG HERE
); # NWI_LIST IS OPTIONAL PARAMETER
LOCAL_CONFIGURATION :
{
......@@ -123,9 +129,9 @@ SMF =
{ NSSAI_SST = 222, NSSAI_SD = "123", DNN = "default", DEFAULT_SESSION_TYPE = "IPV4", DEFAULT_SSC_MODE = 1,
QOS_PROFILE_5QI = 6, QOS_PROFILE_PRIORITY_LEVEL = 1, QOS_PROFILE_ARP_PRIORITY_LEVEL = 1, QOS_PROFILE_ARP_PREEMPTCAP = "NOT_PREEMPT",
QOS_PROFILE_ARP_PREEMPTVULN = "NOT_PREEMPTABLE", SESSION_AMBR_UL = "20Mbps", SESSION_AMBR_DL = "22Mbps"},
{ NSSAI_SST = 111; NSSAI_SD = "124", DNN = "oai", DEFAULT_SESSION_TYPE = "IPV4", DEFAULT_SSC_MODE = 1,
{ NSSAI_SST = 1; NSSAI_SD = "1", DNN = "oai", DEFAULT_SESSION_TYPE = "IPV4", DEFAULT_SSC_MODE = 1,
QOS_PROFILE_5QI = 7, QOS_PROFILE_PRIORITY_LEVEL = 1, QOS_PROFILE_ARP_PRIORITY_LEVEL = 1, QOS_PROFILE_ARP_PREEMPTCAP = "NOT_PREEMPT",
QOS_PROFILE_ARP_PREEMPTVULN = "NOT_PREEMPTABLE", SESSION_AMBR_UL = "10Mbps", SESSION_AMBR_DL = "11Mbps"}
QOS_PROFILE_ARP_PREEMPTVULN = "NOT_PREEMPTABLE", SESSION_AMBR_UL = "20Mbps", SESSION_AMBR_DL = "22Mbps"}
);
};
......
......@@ -5,12 +5,18 @@ set -euo pipefail
CONFIG_DIR="/openair-smf/etc"
# Default values
# (Default NWI Domain for all UPFs in OAI-Integration)
USE_NETWORK_INSTANCE=${USE_NETWORK_INSTANCE:-no}
DOMAIN_ACCESS=${DOMAIN_ACCESS:-access.oai.org}
DOMAIN_CORE=${DOMAIN_CORE:-core.oai.org}
if [[ ${USE_FQDN_DNS} == "yes" ]];then
AMF_IPV4_ADDRESS=${AMF_IPV4_ADDRESS:-0.0.0.0}
NRF_IPV4_ADDRESS=${NRF_IPV4_ADDRESS:-0.0.0.0}
UPF_IPV4_ADDRESS=${UPF_IPV4_ADDRESS:-0.0.0.0}
UDM_IPV4_ADDRESS=${UDM_IPV4_ADDRESS:-0.0.0.0}
fi
HTTP_VERSION=${HTTP_VERSION:-1}
for c in ${CONFIG_DIR}/*.conf; do
# grep variable names (format: ${VAR}) from template to be rendered
......
......@@ -63,10 +63,16 @@ void from_json(const nlohmann::json& j, InterfaceUpfInfoItem& o) {
}
}
UPInterfaceType InterfaceUpfInfoItem::getInterfaceType() const {
// UPInterfaceType InterfaceUpfInfoItem::getInterfaceType() const {
// return m_InterfaceType;
// }
// void InterfaceUpfInfoItem::setInterfaceType(UPInterfaceType const& value) {
// m_InterfaceType = value;
// }
std::string InterfaceUpfInfoItem::getInterfaceType() const {
return m_InterfaceType;
}
void InterfaceUpfInfoItem::setInterfaceType(UPInterfaceType const& value) {
void InterfaceUpfInfoItem::setInterfaceType(std::string const& value) {
m_InterfaceType = value;
}
std::vector<std::string>& InterfaceUpfInfoItem::getIpv4EndpointAddresses() {
......
......@@ -45,8 +45,10 @@ class InterfaceUpfInfoItem {
/// <summary>
///
/// </summary>
UPInterfaceType getInterfaceType() const;
void setInterfaceType(UPInterfaceType const& value);
// UPInterfaceType getInterfaceType() const;
// void setInterfaceType(UPInterfaceType const& value);
std::string getInterfaceType() const;
void setInterfaceType(std::string const& value);
/// <summary>
///
/// </summary>
......@@ -80,7 +82,8 @@ class InterfaceUpfInfoItem {
friend void from_json(const nlohmann::json& j, InterfaceUpfInfoItem& o);
protected:
UPInterfaceType m_InterfaceType;
// UPInterfaceType m_InterfaceType;
std::string m_InterfaceType;
std::vector<std::string> m_Ipv4EndpointAddresses;
bool m_Ipv4EndpointAddressesIsSet;
......
......@@ -270,9 +270,13 @@ bool NsmfEventExposure::altNotifIpv6AddrsIsSet() const {
void NsmfEventExposure::unsetAltNotifIpv6Addrs() {
m_AltNotifIpv6AddrsIsSet = false;
}
std::vector<EventSubscription>& NsmfEventExposure::getEventSubs() {
std::vector<EventSubscription> NsmfEventExposure::getEventSubs() const {
return m_EventSubs;
}
void NsmfEventExposure::getEventSubs(std::vector<EventSubscription>& es) const {
es = m_EventSubs;
}
void NsmfEventExposure::setEventSubs(
std::vector<EventSubscription> const& value) {
m_EventSubs = value;
......
......@@ -119,7 +119,8 @@ class NsmfEventExposure {
/// <summary>
/// Subscribed events
/// </summary>
std::vector<EventSubscription>& getEventSubs();
std::vector<EventSubscription> getEventSubs() const;
void getEventSubs(std::vector<EventSubscription>&) const;
void setEventSubs(std::vector<EventSubscription> const& value);
/// <summary>
///
......
......@@ -25,11 +25,23 @@ void SmfEvent::validate() {
// TODO: implement validation
}
void SmfEvent::set_value(std::string value) {
this->value = value;
}
void SmfEvent::get_value(std::string& value) const {
value = this->value;
}
std::string SmfEvent::get_value() const {
return value;
}
void to_json(nlohmann::json& j, const SmfEvent& o) {
j = nlohmann::json();
j = o.get_value();
}
void from_json(const nlohmann::json& j, SmfEvent& o) {}
void from_json(const nlohmann::json& j, SmfEvent& o) {
o.set_value(j.get<std::string>());
}
} // namespace model
} // namespace smf_server
......
......@@ -39,6 +39,9 @@ class SmfEvent {
void validate();
void set_value(std::string value);
void get_value(std::string& value) const;
std::string get_value() const;
/////////////////////////////////////////////
/// SmfEvent members
......@@ -46,6 +49,8 @@ class SmfEvent {
friend void from_json(const nlohmann::json& j, SmfEvent& o);
protected:
private:
std::string value;
};
} // namespace model
......
......@@ -316,6 +316,31 @@ void smf_http2_server::start() {
});
});
// NFStatusNotify
server.handle(
NNRF_NF_STATUS_NOTIFY_BASE + smf_cfg.sbi_api_version +
NNRF_NF_STATUS_SUBSCRIBE_URL,
[&](const request& request, const response& response) {
request.on_data([&](const uint8_t* data, std::size_t len) {
std::string msg((char*) data, len);
try {
if (request.method().compare("POST") == 0 && len > 0) {
smf::data_notification_msg notification_msg = {};
NotificationData notificationData = {};
nlohmann::json::parse(msg.c_str()).get_to(notificationData);
this->nf_status_notify_handler(notificationData, response);
}
} catch (nlohmann::detail::exception& e) {
Logger::smf_sbi().warn(
"Can not parse the json data (error: %s)!", e.what());
response.write_head(
http_status_code_e::HTTP_STATUS_CODE_400_BAD_REQUEST);
response.end();
return;
}
});
});
if (server.listen_and_serve(ec, m_address, std::to_string(m_port))) {
std::cerr << "HTTP Server error: " << ec.message() << std::endl;
}
......@@ -453,24 +478,27 @@ void smf_http2_server::update_sm_context_handler(
sm_context_response.get_n1_sm_message(),
sm_context_response.get_n2_sm_information(), json_format);
h.emplace(
"content-type", header_value{"multipart/related; boundary=" +
std::string(CURL_MIME_BOUNDARY)});
"content-type",
header_value{
"multipart/related; boundary=" + std::string(CURL_MIME_BOUNDARY)});
} else if (sm_context_response.n1_sm_msg_is_set()) {
mime_parser::create_multipart_related_content(
body, json_data.dump(), CURL_MIME_BOUNDARY,
sm_context_response.get_n1_sm_message(),
multipart_related_content_part_e::NAS, json_format);
h.emplace(
"content-type", header_value{"multipart/related; boundary=" +
std::string(CURL_MIME_BOUNDARY)});
"content-type",
header_value{
"multipart/related; boundary=" + std::string(CURL_MIME_BOUNDARY)});
} else if (sm_context_response.n2_sm_info_is_set()) {
mime_parser::create_multipart_related_content(
body, json_data.dump(), CURL_MIME_BOUNDARY,
sm_context_response.get_n2_sm_information(),
multipart_related_content_part_e::NGAP, json_format);
h.emplace(
"content-type", header_value{"multipart/related; boundary=" +
std::string(CURL_MIME_BOUNDARY)});
"content-type",
header_value{
"multipart/related; boundary=" + std::string(CURL_MIME_BOUNDARY)});
} else {
h.emplace("content-type", header_value{json_format});
body = json_data.dump().c_str();
......@@ -526,6 +554,39 @@ void smf_http2_server::release_sm_context_handler(
response.end();
}
void smf_http2_server::nf_status_notify_handler(
const NotificationData& notificationData, const response& response) {
Logger::smf_api_server().info(
"NFStatusNotifyApiImpl, received a NF status notification...");
smf::data_notification_msg notification_msg = {};
nlohmann::json json_data = {};
std::string content_type = "application/problem+json";
// convert from NotificationData to data_notification_msg
xgpp_conv::data_notification_from_openapi(notificationData, notification_msg);
// Handle the message in smf_app
std::shared_ptr<itti_sbi_notification_data> itti_msg =
std::make_shared<itti_sbi_notification_data>(TASK_SMF_SBI, TASK_SMF_APP);
itti_msg->notification_msg = notification_msg;
itti_msg->http_version = 2;
ProblemDetails problem_details = {};
uint8_t http_code = 0;
header_map h;
if (m_smf_app->handle_nf_status_notification(
itti_msg, problem_details, http_code)) {
http_code = 204;
response.write_head(http_code, h);
response.end();
} else {
to_json(json_data, problem_details);
h.emplace("content-type", header_value{content_type});
response.end(json_data.dump().c_str());
}
}
//------------------------------------------------------------------------------
void smf_http2_server::stop() {
server.stop();
......
......@@ -35,6 +35,7 @@
#include "SmContextUpdateMessage.h"
#include "SmContextMessage.h"
#include "SmContextReleaseMessage.h"
#include "NFStatusNotifyApiImpl.h"
#include "uint_generator.hpp"
#include "smf.h"
......@@ -59,6 +60,10 @@ class smf_http2_server {
const std::string& smf_ref,
const SmContextReleaseMessage& smContextReleaseMessage,
const response& response);
void nf_status_notify_handler(
const NotificationData& notificationData, const response& response);
void stop();
private:
......
......@@ -318,6 +318,18 @@ typedef struct pdu_session_type_s {
pdu_session_type_s(const uint8_t& p) : pdu_session_type(p) {}
pdu_session_type_s(const struct pdu_session_type_s& p)
: pdu_session_type(p.pdu_session_type) {}
pdu_session_type_s(const std::string& s) {
if (s.compare("IPV4") == 0) {
pdu_session_type = pdu_session_type_e::PDU_SESSION_TYPE_E_IPV4;
} else if (s.compare("IPV6") == 0) {
pdu_session_type = pdu_session_type_e::PDU_SESSION_TYPE_E_IPV6;
} else if (s.compare("IPV4V6") == 0) {
pdu_session_type = pdu_session_type_e::PDU_SESSION_TYPE_E_IPV4V6;
} else {
pdu_session_type =
pdu_session_type_e::PDU_SESSION_TYPE_E_IPV4; // Default value
}
}
bool operator==(const struct pdu_session_type_s& p) const {
return (p.pdu_session_type == pdu_session_type);
}
......@@ -329,6 +341,7 @@ typedef struct pdu_session_type_s {
const std::string& toString() const {
return pdu_session_type_e2str.at(pdu_session_type);
}
} pdu_session_type_t;
//-------------------------------------
......
......@@ -142,15 +142,6 @@ struct imsi_s {
};
typedef struct imsi_s imsi_t;
//-------------------------------------
// 8.9 IP Address
typedef struct ip_address_s {
bool is_ipv4; // if not ipv4, then it is ipv6
union {
struct in_addr ipv4_address;
struct in6_addr ipv6_address;
} address;
} ip_address_t;
//-------------------------------------
// 8.10 Mobile Equipment Identity (MEI)
// The ME Identity field contains either the IMEI or the IMEISV as defined in
......
......@@ -38,6 +38,26 @@ typedef struct ssc_mode_s {
ssc_mode_s() : ssc_mode(SSC_MODE_1) {}
ssc_mode_s(ssc_mode_e mode) : ssc_mode(mode) {}
ssc_mode_s(const struct ssc_mode_s& p) : ssc_mode(p.ssc_mode) {}
ssc_mode_s(const std::string& s) {
if (s.compare("SSC_MODE_1") == 0) {
ssc_mode = ssc_mode_e::SSC_MODE_1;
} else if (s.compare("SSC_MODE_2") == 0) {
ssc_mode = ssc_mode_e::SSC_MODE_2;
} else if (s.compare("SSC_MODE_3") == 0) {
ssc_mode = ssc_mode_e::SSC_MODE_3;
} else {
ssc_mode = ssc_mode_e::SSC_MODE_1; // default mode
}
}
ssc_mode_s& operator=(const ssc_mode_s& s) {
ssc_mode = s.ssc_mode;
return *this;
}
virtual ~ssc_mode_s(){};
} ssc_mode_t;
typedef struct pdu_session_types_s {
......@@ -50,12 +70,133 @@ typedef struct ssc_modes_s {
std::vector<ssc_mode_t> allowed_ssc_modes;
} ssc_modes_t;
enum ip_address_type_value_e {
IP_ADDRESS_TYPE_IPV4_ADDRESS = 0,
IP_ADDRESS_TYPE_IPV6_ADDRESS = 1,
IP_ADDRESS_TYPE_IPV6_PREFIX = 2
};
typedef struct ipv6_prefix_s {
struct in6_addr prefix;
uint8_t prefix_len;
std::string to_string() const {
return conv::toString(prefix) + "/" + std::to_string(prefix_len);
}
} ipv6_prefix_t;
typedef struct ip_address_s {
uint8_t ip_address_type;
union {
struct in_addr ipv4_address;
struct in6_addr ipv6_address;
ipv6_prefix_t ipv6_prefix;
} u1;
bool operator==(const struct ip_address_s& i) const {
if ((i.ip_address_type == this->ip_address_type) &&
(i.u1.ipv4_address.s_addr == this->u1.ipv4_address.s_addr) &&
(i.u1.ipv6_address.s6_addr32[0] ==
this->u1.ipv6_address.s6_addr32[0]) &&
(i.u1.ipv6_address.s6_addr32[1] ==
this->u1.ipv6_address.s6_addr32[1]) &&
(i.u1.ipv6_address.s6_addr32[2] ==
this->u1.ipv6_address.s6_addr32[2]) &&
(i.u1.ipv6_address.s6_addr32[3] ==
this->u1.ipv6_address.s6_addr32[3]) &&
(i.u1.ipv6_prefix.prefix_len == this->u1.ipv6_prefix.prefix_len) &&
(i.u1.ipv6_prefix.prefix.s6_addr32[0] ==
this->u1.ipv6_prefix.prefix.s6_addr32[0]) &&
(i.u1.ipv6_prefix.prefix.s6_addr32[1] ==
this->u1.ipv6_prefix.prefix.s6_addr32[1]) &&
(i.u1.ipv6_prefix.prefix.s6_addr32[2] ==
this->u1.ipv6_prefix.prefix.s6_addr32[2]) &&
(i.u1.ipv6_prefix.prefix.s6_addr32[3] ==
this->u1.ipv6_prefix.prefix.s6_addr32[3])) {
return true;
} else {
return false;
}
};
bool operator==(const struct in_addr& a) const {
if ((IP_ADDRESS_TYPE_IPV4_ADDRESS == this->ip_address_type) &&
(a.s_addr == u1.ipv4_address.s_addr)) {
return true;
} else {
return false;
}
};
bool operator==(const struct in6_addr& i) const {
if ((IP_ADDRESS_TYPE_IPV6_ADDRESS == this->ip_address_type) &&
(i.s6_addr32[0] == this->u1.ipv6_address.s6_addr32[0]) &&
(i.s6_addr32[1] == this->u1.ipv6_address.s6_addr32[1]) &&
(i.s6_addr32[2] == this->u1.ipv6_address.s6_addr32[2]) &&
(i.s6_addr32[3] == this->u1.ipv6_address.s6_addr32[3])) {
return true;
} else {
return false;
}
};
bool operator==(const ipv6_prefix_t& i) const {
if ((IP_ADDRESS_TYPE_IPV6_PREFIX == this->ip_address_type) &&
(i.prefix_len == this->u1.ipv6_prefix.prefix_len) &&
(i.prefix.s6_addr32[0] == this->u1.ipv6_prefix.prefix.s6_addr32[0]) &&
(i.prefix.s6_addr32[1] == this->u1.ipv6_prefix.prefix.s6_addr32[1]) &&
(i.prefix.s6_addr32[2] == this->u1.ipv6_prefix.prefix.s6_addr32[2]) &&
(i.prefix.s6_addr32[3] == this->u1.ipv6_prefix.prefix.s6_addr32[3])) {
return true;
} else {
return false;
}
};
ip_address_s& operator=(const struct in_addr& a) {
ip_address_type = IP_ADDRESS_TYPE_IPV4_ADDRESS;
u1.ipv4_address.s_addr = a.s_addr;
return *this;
}
ip_address_s& operator=(const struct in6_addr& a) {
ip_address_type = IP_ADDRESS_TYPE_IPV6_ADDRESS;
u1.ipv6_address.s6_addr32[0] = a.s6_addr32[0];
u1.ipv6_address.s6_addr32[1] = a.s6_addr32[1];
u1.ipv6_address.s6_addr32[2] = a.s6_addr32[2];
u1.ipv6_address.s6_addr32[3] = a.s6_addr32[3];
return *this;
}
ip_address_s& operator=(const ipv6_prefix_t& a) {
ip_address_type = IP_ADDRESS_TYPE_IPV6_PREFIX;
u1.ipv6_prefix.prefix_len = a.prefix_len;
u1.ipv6_prefix.prefix.s6_addr32[0] = a.prefix.s6_addr32[0];
u1.ipv6_prefix.prefix.s6_addr32[1] = a.prefix.s6_addr32[1];
u1.ipv6_prefix.prefix.s6_addr32[2] = a.prefix.s6_addr32[2];
u1.ipv6_prefix.prefix.s6_addr32[3] = a.prefix.s6_addr32[3];
return *this;
}
virtual ~ip_address_s(){};
std::string to_string() const {
if (IP_ADDRESS_TYPE_IPV4_ADDRESS == this->ip_address_type) {
return conv::toString(u1.ipv4_address);
} else if (IP_ADDRESS_TYPE_IPV6_ADDRESS == this->ip_address_type) {
return conv::toString(u1.ipv6_address);
} else if (IP_ADDRESS_TYPE_IPV6_PREFIX == this->ip_address_type) {
return u1.ipv6_prefix.to_string();
}
return std::string("Unknown IP Address Type");
}
} ip_address_t;
typedef struct dnn_configuration_s {
pdu_session_types_t pdu_session_types;
ssc_modes_t ssc_modes;
session_ambr_t session_ambr;
subscribed_default_qos_t _5g_qos_profile;
// staticIpAddresses
std::vector<ip_address_t> static_ip_addresses;
} dnn_configuration_t;
#endif
......@@ -30,9 +30,21 @@ typedef enum smf_event_e {
SMF_EVENT_PDU_SES_REL = 3,
SMF_EVENT_PLMN_CH = 4,
SMF_EVENT_UE_IP_CH = 5,
SMF_EVENT_DDDS = 6
SMF_EVENT_DDDS = 6,
SMF_EVENT_FLEXCN = 99
} smf_event_t;
static std::string smf_event_from_enum(smf_event_t e) {
if (e == smf_event_t::SMF_EVENT_AC_TY_CH) return "AC_TY_CH";
if (e == smf_event_t::SMF_EVENT_UP_PATH_CH) return "UP_PATH_CH";
if (e == smf_event_t::SMF_EVENT_PDU_SES_REL) return "PDU_SES_REL";
if (e == smf_event_t::SMF_EVENT_PLMN_CH) return "PLMN_CH";
if (e == smf_event_t::SMF_EVENT_UE_IP_CH) return "UE_IP_CH";
if (e == smf_event_t::SMF_EVENT_DDDS) return "DDDS";
if (e == smf_event_t::SMF_EVENT_FLEXCN) return "FLEXCN";
return "";
}
static const std::vector<std::string> smf_event_e2str = {
"SMF_EVENT_UNKNOWN",
"Access Type Change",
......@@ -40,7 +52,8 @@ static const std::vector<std::string> smf_event_e2str = {
"PDU Session Release",
"PLMN Change",
"UE IP address change",
"Downlink data delivery status"};
"Downlink data delivery status",
"FlexCN"};
enum class notification_method_e {
PERIODIC = 1,
......
......@@ -217,6 +217,7 @@ typedef struct qos_profile_s {
#define NNRF_NFM_BASE "/nnrf-nfm/"
#define NNRF_NF_REGISTER_URL "/nf-instances/"
#define NNRF_NF_STATUS_SUBSCRIBE_URL "/subscriptions"
#define NNRF_NF_STATUS_NOTIFY_BASE "/nsmf-nfstatus-notify/"
// for CURL
#define NF_CURL_TIMEOUT_MS 100L
......@@ -330,7 +331,16 @@ typedef struct snssai_upf_info_item_s {
std::vector<dnn_upf_info_item_t> dnn_upf_info_list;
} snssai_upf_info_item_t;
typedef struct interface_upf_info_item_s {
std::string interface_type;
std::vector<struct in_addr> ipv4_addresses;
std::vector<struct in6_addr> ipv6_addresses;
std::string endpoint_fqdn;
std::string network_instance;
} interface_upf_info_item_t;
typedef struct upf_info_s {
std::vector<interface_upf_info_item_t> interface_upf_info_list;
std::vector<snssai_upf_info_item_t> snssai_upf_info_list;
} upf_info_t;
......
......@@ -35,6 +35,7 @@
#include "SmContextCreateData.h"
#include "SmContextUpdateData.h"
#include "SmContextReleaseData.h"
#include "EventSubscription.h"
#include "3gpp_29.500.h"
#include "3gpp_24.501.h"
#include "conversions.hpp"
......@@ -506,23 +507,51 @@ void xgpp_conv::smf_event_exposure_notification_from_openapi(
Logger::smf_api_server().debug("PDU Session ID %d", nee.getPduSeId());
eem.set_pdu_session_id(nee.getPduSeId());
}
// TODO: groupId
// TODO: DNN
// TODO: GUAMI
eem.set_notif_id(nee.getNotifId()); // NotifId
eem.set_notif_uri(nee.getNotifUri()); // NotifUri
// EventSubscription: TODO
event_subscription_t event_subscription = {};
event_subscription.smf_event = smf_event_t::SMF_EVENT_PDU_SES_REL;
std::vector<oai::smf_server::model::EventSubscription> event_subcription_api =
{};
nee.getEventSubs(event_subcription_api);
std::vector<event_subscription_t> event_subscriptions = {};
event_subscriptions.push_back(event_subscription);
eem.set_event_subs(event_subscriptions);
for (auto e : event_subcription_api) {
// EventSubscription: TODO
event_subscription_t event_subscription = {};
uint8_t event_id_enum = 0;
std::string event_id = e.getEvent().get_value();
if (event_id.compare("AC_TY_CH") == 0) {
event_subscription.smf_event = smf_event_e::SMF_EVENT_AC_TY_CH;
} else if (event_id.compare("UP_PATH_CH") == 0) {
event_subscription.smf_event = smf_event_e::SMF_EVENT_UP_PATH_CH;
} else if (event_id.compare("PDU_SES_REL") == 0) {
event_subscription.smf_event = smf_event_e::SMF_EVENT_PDU_SES_REL;
} else if (event_id.compare("PLMN_CH") == 0) {
event_subscription.smf_event = smf_event_e::SMF_EVENT_PLMN_CH;
} else if (event_id.compare("UE_IP_CH") == 0) {
event_subscription.smf_event = smf_event_e::SMF_EVENT_UE_IP_CH;
} else if (event_id.compare("DDDS") == 0) {
event_subscription.smf_event = smf_event_e::SMF_EVENT_DDDS;
} else if (event_id.compare("FLEXCN") == 0) {
event_subscription.smf_event = smf_event_e::SMF_EVENT_FLEXCN;
} else {
Logger::smf_api_server().debug("Unknown SMF Event %s", event_id.c_str());
break;
}
// std::vector<EventSubscription> eventSubscriptions;
// for (auto it: nee.getEventSubs()){
// event_subscription.smf_event = it.getEvent();
// getDnaiChgType
// event_subscriptions.push_back(event_subscription);
//}
// event_subscription.smf_event =
// static_cast<smf_event_t>(e.getEvent().get_value());
// TODO: dnaiChType (for event UP path change)
// TODO: dddTraDes/ddsStati (for event downlink data delivery status)
// TODO: altNotifIpv4Addrs, altNotifIpv6Addrs, serviceName, ImmeRep,
// notifMethod, maxReportNbr, expiry
event_subscriptions.push_back(event_subscription);
}
eem.set_event_subs(event_subscriptions);
}
//------------------------------------------------------------------------------
......
......@@ -107,6 +107,7 @@ std::string conv::mccToString(
s.append(std::to_string(mcc16));
return s;
}
//------------------------------------------------------------------------------
std::string conv::mncToString(
const uint8_t digit1, const uint8_t digit2, const uint8_t digit3) {
......@@ -122,6 +123,7 @@ std::string conv::mncToString(
return s;
}
//------------------------------------------------------------------------------
bool conv::plmnFromString(
plmn_t& p, const std::string mcc, const std::string mnc) {
// MCC
......@@ -159,6 +161,23 @@ bool conv::plmnFromString(
return true;
}
//------------------------------------------------------------------------------
void conv::plmnToMccMnc(
const plmn_t& plmn, std::string& mcc, std::string& mnc) {
uint16_t mcc_dec = 0;
uint16_t mnc_dec = 0;
uint16_t mnc_len = 0;
mcc_dec = plmn.mcc_digit1 * 100 + plmn.mcc_digit2 * 10 + plmn.mcc_digit3;
mnc_len = (plmn.mnc_digit3 == 0x0 ? 2 : 3);
mnc_dec = plmn.mnc_digit1 * 10 + plmn.mnc_digit2;
mnc_dec = (mnc_len == 2 ? mnc_dec : mnc_dec * 10 + plmn.mnc_digit3);
mcc = std::to_string(mcc_dec);
mnc = std::to_string(mnc_dec);
return;
}
//------------------------------------------------------------------------------
struct in_addr conv::fromString(const std::string addr4) {
unsigned char buf[sizeof(struct in6_addr)] = {};
......
......@@ -57,6 +57,8 @@ class conv {
static struct in_addr fromString(const std::string addr4);
static bool plmnFromString(
plmn_t& p, const std::string mcc, const std::string mnc);
static void plmnToMccMnc(
const plmn_t& plmn, std::string& mcc, std::string& mnc);
static std::string toString(const struct in_addr& inaddr);
static std::string toString(const struct in6_addr& in6addr);
static std::string mccToString(
......
......@@ -1272,6 +1272,12 @@ pfcp_msg::pfcp_msg(const pfcp_session_modification_request& pfcp_ies)
std::shared_ptr<pfcp_update_qer_ie> sie(new pfcp_update_qer_ie(it));
add_ie(sie);
}
for (auto it : pfcp_ies.query_urrs) {
std::shared_ptr<pfcp_query_urr_ie> sie(new pfcp_query_urr_ie(it));
add_ie(sie);
}
// if (pfcp_ies.update_bar.first) {std::shared_ptr<pfcp_update_bar_ie>
// sie(new pfcp_update_bar_ie(pfcp_ies.update_bar.second)); add_ie(sie);} if
// (pfcp_ies.update_traffic_endpoint.first)
......
......@@ -1469,6 +1469,7 @@ class pfcp_transport_level_marking_ie : public pfcp_ie {
s.set(v);
}
};
//-------------------------------------
// IE VOLUME_THRESHOLD
class pfcp_volume_threshold_ie : public pfcp_ie {
......@@ -4494,6 +4495,35 @@ class pfcp_urr_id_ie : public pfcp_ie {
s.set(v);
}
};
class pfcp_query_urr_ie : public pfcp_grouped_ie {
public:
//--------
explicit pfcp_query_urr_ie(const pfcp::query_urr& b)
: pfcp_grouped_ie(PFCP_IE_QUERY_URR) {
tlv.set_length(0);
if (b.urr_id.first) {
std::shared_ptr<pfcp::pfcp_urr_id_ie> sie(
new pfcp::pfcp_urr_id_ie(b.urr_id.second));
add_ie(sie);
}
}
pfcp_query_urr_ie() : pfcp_grouped_ie(PFCP_IE_QUERY_URR) {}
explicit pfcp_query_urr_ie(const pfcp_tlv& t) : pfcp_grouped_ie(t) {}
//--------
void to_core_type(pfcp::duplicating_parameters& c) {
for (auto sie : ies) {
sie.get()->to_core_type(c);
}
}
//--------
void to_core_type(pfcp_ies_container& s) {
pfcp::query_urr i = {};
to_core_type(i);
s.set(i);
}
};
////-------------------------------------
//// IE LINKED_URR_ID
// class pfcp_linked_urr_id_ie : public pfcp_ie {
......
......@@ -6741,6 +6741,9 @@ class pfcp_session_modification_request : public pfcp_ies_container {
std::vector<pfcp::create_pdr> create_pdrs;
std::vector<pfcp::create_far> create_fars;
std::vector<pfcp::create_urr> create_urrs;
std::vector<pfcp::query_urr> query_urrs;
std::vector<pfcp::create_qer> create_qers;
std::pair<bool, pfcp::create_bar> create_bar;
std::pair<bool, pfcp::create_traffic_endpoint> create_traffic_endpoint;
......@@ -6774,6 +6777,7 @@ class pfcp_session_modification_request : public pfcp_ies_container {
create_fars(),
create_urrs(),
create_qers(),
query_urrs(),
create_bar(),
create_traffic_endpoint(),
update_pdrs(),
......@@ -6804,6 +6808,7 @@ class pfcp_session_modification_request : public pfcp_ies_container {
create_fars(i.create_fars),
create_urrs(i.create_urrs),
create_qers(i.create_qers),
query_urrs(i.query_urrs),
create_bar(i.create_bar),
create_traffic_endpoint(i.create_traffic_endpoint),
update_pdrs(i.update_pdrs),
......@@ -6956,6 +6961,7 @@ class pfcp_session_modification_request : public pfcp_ies_container {
void set(const pfcp::remove_far& v) { remove_fars.push_back(v); }
void set(const pfcp::remove_urr& v) { remove_urrs.push_back(v); }
void set(const pfcp::remove_qer& v) { remove_qers.push_back(v); }
void set(const pfcp::query_urr& v) { query_urrs.push_back(v); }
void set(const pfcp::remove_bar& v) {
remove_bar.first = true;
remove_bar.second = v;
......
......@@ -942,6 +942,7 @@ void smf_app::handle_pdu_session_create_sm_context_request(
sc.get()->set_supi(supi);
sc.get()->set_supi_prefix(supi_prefix);
set_supi_2_smf_context(supi64, sc);
sc.get()->set_plmn(smreq->req.get_plmn()); // PLMN
}
// Step 5. If colliding with an existing SM context (session is already
......@@ -972,7 +973,9 @@ void smf_app::handle_pdu_session_create_sm_context_request(
if (not use_local_configuration_subscription_data(dnn_selection_mode)) {
Logger::smf_app().debug(
"Retrieve Session Management Subscription data from the UDM");
if (smf_sbi_inst->get_sm_data(supi64, dnn, snssai, subscription)) {
plmn_t plmn = {};
sc.get()->get_plmn(plmn);
if (smf_sbi_inst->get_sm_data(supi64, dnn, snssai, subscription, plmn)) {
// Update dnn_context with subscription info
sc.get()->insert_dnn_subscription(snssai, dnn, subscription);
} else {
......@@ -1014,9 +1017,6 @@ void smf_app::handle_pdu_session_create_sm_context_request(
}
}
// Step 7. Store PLMN
sc.get()->set_plmn(smreq->req.get_plmn());
// Step 8. Generate a SMF context Id and store the corresponding information
// in a map (SM_Context_ID, (supi, pdu_session_id))
scid_t scid = generate_smf_context_ref();
......@@ -1617,6 +1617,7 @@ void smf_app::timer_nrf_heartbeat_timeout(
patch_item.setValue("REGISTERED");
itti_msg->patch_items.push_back(patch_item);
itti_msg->smf_instance_id = smf_instance_id;
itti_msg->http_version = smf_cfg.http_version;
int ret = itti_inst->send_msg(itti_msg);
if (RETURNok != ret) {
......@@ -2062,8 +2063,9 @@ void smf_app::trigger_nf_registration_request() {
std::shared_ptr<itti_n11_register_nf_instance_request> itti_msg =
std::make_shared<itti_n11_register_nf_instance_request>(
TASK_SMF_APP, TASK_SMF_SBI);
itti_msg->profile = nf_instance_profile;
int ret = itti_inst->send_msg(itti_msg);
itti_msg->profile = nf_instance_profile;
itti_msg->http_version = smf_cfg.http_version;
int ret = itti_inst->send_msg(itti_msg);
if (RETURNok != ret) {
Logger::smf_app().error(
"Could not send ITTI message %s to task TASK_SMF_SBI",
......@@ -2080,6 +2082,7 @@ void smf_app::trigger_nf_deregistration() {
std::make_shared<itti_n11_deregister_nf_instance>(
TASK_SMF_APP, TASK_SMF_SBI);
itti_msg->smf_instance_id = smf_instance_id;
itti_msg->http_version = smf_cfg.http_version;
int ret = itti_inst->send_msg(itti_msg);
if (RETURNok != ret) {
Logger::smf_app().error(
......@@ -2099,10 +2102,12 @@ void smf_app::trigger_upf_status_notification_subscribe() {
TASK_SMF_APP, TASK_SMF_SBI);
nlohmann::json json_data = {};
unsigned int port = smf_cfg.sbi.port;
if (smf_cfg.http_version == 2) port = smf_cfg.sbi_http2_port;
// TODO: remove hardcoded values
json_data["nfStatusNotificationUri"] =
std::string(inet_ntoa(*((struct in_addr*) &smf_cfg.sbi.addr4))) + ":" +
std::to_string(smf_cfg.sbi.port) + "/nsmf-nfstatus-notify/" +
std::to_string(port) + "/nsmf-nfstatus-notify/" +
smf_cfg.sbi_api_version + "/subscriptions";
json_data["subscrCond"]["NfTypeCond"]["nfType"] = "UPF";
......@@ -2116,9 +2121,10 @@ void smf_app::trigger_upf_status_notification_subscribe() {
":" + std::to_string(smf_cfg.nrf_addr.port) + NNRF_NFM_BASE +
smf_cfg.nrf_addr.api_version + NNRF_NF_STATUS_SUBSCRIBE_URL;
itti_msg->url = url;
itti_msg->json_data = json_data;
int ret = itti_inst->send_msg(itti_msg);
itti_msg->url = url;
itti_msg->json_data = json_data;
itti_msg->http_version = smf_cfg.http_version;
int ret = itti_inst->send_msg(itti_msg);
if (RETURNok != ret) {
Logger::smf_app().error(
"Could not send ITTI message %s to task TASK_SMF_SBI",
......
......@@ -553,6 +553,7 @@ int smf_config::load(const string& config_file) {
astring.c_str());
}
// UE MTU
smf_cfg.lookupValue(SMF_CONFIG_STRING_UE_MTU, ue_mtu);
// Support features
......@@ -560,6 +561,7 @@ int smf_config::load(const string& config_file) {
const Setting& support_features =
smf_cfg[SMF_CONFIG_STRING_SUPPORT_FEATURES];
string opt;
unsigned int httpVersion = {0};
support_features.lookupValue(
SMF_CONFIG_STRING_SUPPORT_FEATURES_REGISTER_NRF, opt);
if (boost::iequals(opt, "yes")) {
......@@ -599,6 +601,18 @@ int smf_config::load(const string& config_file) {
use_fqdn_dns = false;
}
support_features.lookupValue(
SMF_CONFIG_STRING_SUPPORT_FEATURES_SBI_HTTP_VERSION, httpVersion);
http_version = httpVersion;
support_features.lookupValue(
SMF_CONFIG_STRING_SUPPORT_FEATURES_USE_NETWORK_INSTANCE, opt);
if (boost::iequals(opt, "yes")) {
use_nwi = true;
} else {
use_nwi = false;
}
} catch (const SettingNotFoundException& nfex) {
Logger::smf_app().error(
"%s : %s, using defaults", nfex.what(), nfex.getPath());
......@@ -702,12 +716,13 @@ int smf_config::load(const string& config_file) {
for (int i = 0; i < count; i++) {
const Setting& upf_cfg = upf_list_cfg[i];
// TODO FQDN
string address = {};
string address = {};
pfcp::node_id_t n = {};
if (!use_fqdn_dns) {
if (upf_cfg.lookupValue(
SMF_CONFIG_STRING_UPF_IPV4_ADDRESS, address)) {
pfcp::node_id_t n = {};
n.node_id_type = pfcp::NODE_ID_TYPE_IPV4_ADDRESS; // actually
// pfcp::node_id_t n = {};
n.node_id_type = pfcp::NODE_ID_TYPE_IPV4_ADDRESS; // actually
if (inet_pton(AF_INET, util::trim(address).c_str(), buf_in_addr) ==
1) {
memcpy(&n.u1.ipv4_address, buf_in_addr, sizeof(struct in_addr));
......@@ -736,9 +751,9 @@ int smf_config::load(const string& config_file) {
// TODO:
throw("DO NOT SUPPORT IPV6 ADDR FOR NRF!");
} else { // IPv4
pfcp::node_id_t n = {};
n.node_id_type = pfcp::NODE_ID_TYPE_IPV4_ADDRESS; // actually
n.fqdn = astring;
// pfcp::node_id_t n = {};
n.node_id_type = pfcp::NODE_ID_TYPE_IPV4_ADDRESS; // actually
n.fqdn = astring;
if (inet_pton(AF_INET, util::trim(address).c_str(), buf_in_addr) ==
1) {
memcpy(&n.u1.ipv4_address, buf_in_addr, sizeof(struct in_addr));
......@@ -752,6 +767,25 @@ int smf_config::load(const string& config_file) {
upfs.push_back(n);
}
}
// Network Instance
if (upf_cfg.exists(SMF_CONFIG_STRING_NWI_LIST) & use_nwi) {
const Setting& nwi_cfg = upf_cfg[SMF_CONFIG_STRING_NWI_LIST];
count = nwi_cfg.getLength();
// Check if NWI list for given UPF is present
if (count > 0) {
upf_nwi_list_t upf_nwi;
nwi_cfg[0].lookupValue(
SMF_CONFIG_STRING_DOMAIN_ACCESS, upf_nwi.domain_access);
nwi_cfg[0].lookupValue(
SMF_CONFIG_STRING_DOMAIN_CORE, upf_nwi.domain_core);
upf_nwi.upf_id = n;
Logger::smf_app().debug(
"NWI config found for UP node:-\t Nwi access: %s , \t Nwi "
"core: %s",
upf_nwi.domain_access.c_str(), upf_nwi.domain_core.c_str());
upf_nwi_list.push_back(upf_nwi);
}
}
}
}
......@@ -792,8 +826,17 @@ int smf_config::load(const string& config_file) {
IPV4_STR_ADDR_TO_INADDR(
util::trim(address).c_str(), nrf_ipv4_addr,
"BAD IPv4 ADDRESS FORMAT FOR NRF !");
nrf_addr.ipv4_addr = nrf_ipv4_addr;
nrf_addr.port = nrf_port;
nrf_addr.ipv4_addr = nrf_ipv4_addr;
// nrf_addr.port = nrf_port;
// We hardcode nrf port from config for the moment
if (!(nrf_cfg.lookupValue(SMF_CONFIG_STRING_NRF_PORT, nrf_port))) {
Logger::smf_app().error(SMF_CONFIG_STRING_NRF_PORT "failed");
throw(SMF_CONFIG_STRING_NRF_PORT "failed");
}
nrf_addr.port = nrf_port;
//
nrf_addr.api_version = "v1"; // TODO: to get API version from DNS
nrf_addr.fqdn = astring;
}
......@@ -884,7 +927,7 @@ int smf_config::load(const string& config_file) {
//------------------------------------------------------------------------------
void smf_config::display() {
Logger::smf_app().info(
"==== EURECOM %s v%s ====", PACKAGE_NAME, PACKAGE_VERSION);
"==== OAI-CN5G %s v%s ====", PACKAGE_NAME, PACKAGE_VERSION);
Logger::smf_app().info("Configuration SMF:");
Logger::smf_app().info("- Instance ..............: %d\n", instance);
Logger::smf_app().info("- PID dir ...............: %s\n", pid_dir.c_str());
......@@ -944,6 +987,7 @@ void smf_config::display() {
Logger::smf_app().info(
" Scheduling prio .....: %d",
itti.async_cmd_sched_params.sched_priority);
Logger::smf_app().info("- " SMF_CONFIG_STRING_IP_ADDRESS_POOL ":");
for (int i = 0; i < num_ue_pool; i++) {
std::string range_low(inet_ntoa(ue_pool_range_low[dnn[i].pool_id_iv4]));
......@@ -1002,6 +1046,7 @@ void smf_config::display() {
}
}
Logger::smf_app().info("- Default UE MTU: %d", ue_mtu);
Logger::smf_app().info("- Supported Features:");
Logger::smf_app().info(
" Register to NRF............: %s", register_nrf ? "Yes" : "No");
......@@ -1014,6 +1059,8 @@ void smf_config::display() {
" Push PCO (DNS+MTU).........: %s", force_push_pco ? "Yes" : "No");
Logger::smf_app().info(
" Use FQDN ..................: %s", use_fqdn_dns ? "Yes" : "No");
Logger::smf_app().info(
" Use NWI ..................: %s", use_nwi ? "Yes" : "No");
Logger::smf_app().info("- AMF:");
Logger::smf_app().info(
......@@ -1182,3 +1229,34 @@ std::string smf_config::get_default_dnn() {
Logger::smf_app().debug("Default DNN: %s", smf_cfg.dnn[0].dnn.c_str());
return smf_cfg.dnn[0].dnn;
}
//------------------------------------------------------------------------------
bool smf_config::get_nwi_list_index(
bool nwi_enabled, uint8_t nwi_list_index, pfcp::node_id_t node_id) {
Logger::smf_app().debug("Default DNN: %s", smf_cfg.dnn[0].dnn.c_str());
// return smf_cfg.dnn[0].dnn;
if (node_id.node_id_type == pfcp::NODE_ID_TYPE_IPV4_ADDRESS) {
for (int i = 0; i < upf_nwi_list.size(); i++) {
if (node_id.u1.ipv4_address.s_addr ==
upf_nwi_list[i].upf_id.u1.ipv4_address.s_addr) {
nwi_list_index = i;
nwi_enabled = true;
return true;
}
}
nwi_enabled = false;
return false;
}
if (node_id.node_id_type == pfcp::NODE_ID_TYPE_FQDN) {
for (int i = 0; i < upf_nwi_list.size(); i++) {
if (node_id.fqdn == upf_nwi_list[i].upf_id.fqdn) {
nwi_list_index = i;
nwi_enabled = true;
return true;
}
}
nwi_enabled = false;
return false;
}
return true;
}
......@@ -111,6 +111,11 @@
#define SMF_CONFIG_STRING_NRF_IPV4_ADDRESS "IPV4_ADDRESS"
#define SMF_CONFIG_STRING_NRF_PORT "PORT"
#define SMF_CONFIG_STRING_NWI_LIST "NWI_LIST"
#define SMF_CONFIG_STRING_DOMAIN_ACCESS "DOMAIN_ACCESS"
#define SMF_CONFIG_STRING_DOMAIN_CORE "DOMAIN_CORE"
#define SMF_CONFIG_STRING_DOMAIN_SGI_LAN "DOMAIN_SGI_LAN"
#define SMF_CONFIG_STRING_LOCAL_CONFIGURATION "LOCAL_CONFIGURATION"
#define SMF_CONFIG_STRING_SESSION_MANAGEMENT_SUBSCRIPTION_LIST \
"SESSION_MANAGEMENT_SUBSCRIPTION_LIST"
......@@ -139,6 +144,9 @@
#define SMF_CONFIG_STRING_NAS_FORCE_PUSH_PCO \
"FORCE_PUSH_PROTOCOL_CONFIGURATION_OPTIONS"
#define SMF_CONFIG_STRING_SUPPORT_FEATURES_USE_FQDN_DNS "USE_FQDN_DNS"
#define SMF_CONFIG_STRING_SUPPORT_FEATURES_SBI_HTTP_VERSION "HTTP_VERSION"
#define SMF_CONFIG_STRING_SUPPORT_FEATURES_USE_NETWORK_INSTANCE \
"USE_NETWORK_INSTANCE"
#define SMF_MAX_ALLOCATED_PDN_ADDRESSES 1024
......@@ -221,6 +229,8 @@ class smf_config {
bool discover_upf;
bool use_local_subscription_info;
bool use_fqdn_dns;
unsigned int http_version;
bool use_nwi;
struct {
struct in_addr ipv4_addr;
......@@ -241,10 +251,23 @@ class smf_config {
struct {
struct in_addr ipv4_addr;
unsigned int port;
unsigned int http_version;
std::string api_version;
std::string fqdn;
} nrf_addr;
// Network instance
// bool network_instance_configuration;
struct upf_nwi_list_s {
pfcp::node_id_t upf_id;
std::string domain_access;
std::string domain_core;
// std::string domain_sgi_lan;
};
typedef struct upf_nwi_list_s upf_nwi_list_t;
std::vector<upf_nwi_list_t> upf_nwi_list;
#define SMF_NUM_SESSION_MANAGEMENT_SUBSCRIPTION_MAX 10
struct {
snssai_t single_nssai;
......@@ -286,7 +309,7 @@ class smf_config {
ue_pool_excluded[i] = {};
}
force_push_pco = true;
ue_mtu = 1500;
ue_mtu = 1358;
itti.itti_timer_sched_params.sched_priority = 85;
itti.n4_sched_params.sched_priority = 84;
......@@ -338,6 +361,8 @@ class smf_config {
bool is_dotted_dnn_handled(
const std::string& dnn, const pdu_session_type_t& pdn_session_type);
std::string get_default_dnn();
bool get_nwi_list_index(
bool nwi_enabled, uint8_t nwi_list_index, pfcp::node_id_t node_id);
};
} // namespace smf
......
This diff is collapsed.
......@@ -159,6 +159,9 @@ class smf_pdu_session : public std::enable_shared_from_this<smf_pdu_session> {
smf_pdu_session(smf_pdu_session& b) = delete;
void get_pdu_session_id(uint32_t& psi) const;
uint32_t get_pdu_session_id() const;
/*
* Set UE Address for this session
* @param [paa_t &] paa: PAA
......@@ -605,6 +608,22 @@ class smf_context : public std::enable_shared_from_this<smf_context> {
ee_pdu_session_release_connection =
event_sub.subscribe_ee_pdu_session_release(boost::bind(
&smf_context::handle_ee_pdu_session_release, this, _1, _2, _3));
// Subscribe to UE IP Change Event
ee_ue_ip_change_connection = event_sub.subscribe_ee_ue_ip_change(
boost::bind(&smf_context::handle_ue_ip_change, this, _1, _2));
// Subscribe to PLMN Change Event
ee_plmn_change_connection = event_sub.subscribe_ee_plmn_change(
boost::bind(&smf_context::handle_plmn_change, this, _1, _2));
// Subscribe to DDDS event
ee_ddds_connection = event_sub.subscribe_ee_ddds(
boost::bind(&smf_context::handle_ddds, this, _1, _2));
// Subscribe to FlexCN event
ee_flexcn = event_sub.subscribe_ee_flexcn_event(
boost::bind(&smf_context::handle_flexcn_event, this, _1, _2));
}
smf_context(smf_context& b) = delete;
......@@ -616,6 +635,12 @@ class smf_context : public std::enable_shared_from_this<smf_context> {
sm_context_status_connection.disconnect();
if (ee_pdu_session_release_connection.connected())
ee_pdu_session_release_connection.disconnect();
if (ee_ue_ip_change_connection.connected())
ee_ue_ip_change_connection.disconnect();
if (ee_plmn_change_connection.connected())
ee_plmn_change_connection.disconnect();
if (ee_ddds_connection.connected()) ee_ddds_connection.disconnect();
if (ee_flexcn.connected()) ee_flexcn.disconnect();
}
/*
......@@ -1141,6 +1166,17 @@ class smf_context : public std::enable_shared_from_this<smf_context> {
void handle_ee_pdu_session_release(
supi64_t supi, pdu_session_id_t pdu_session_id, uint8_t http_version);
void trigger_ue_ip_change(scid_t scid, uint8_t http_version);
void handle_ue_ip_change(scid_t scid, uint8_t http_version);
void trigger_plmn_change(scid_t scid, uint8_t http_version);
void handle_plmn_change(scid_t scid, uint8_t http_version);
void trigger_ddds(scid_t scid, uint8_t http_version);
void handle_ddds(scid_t scid, uint8_t http_version);
void trigger_flexcn_event(scid_t scid, uint8_t http_version);
void handle_flexcn_event(scid_t scid, uint8_t http_version);
/*
* Update QoS information in the Response message according to the content of
* decoded NAS msg
......@@ -1268,6 +1304,10 @@ class smf_context : public std::enable_shared_from_this<smf_context> {
smf_event event_sub;
bs2::connection sm_context_status_connection;
bs2::connection ee_pdu_session_release_connection;
bs2::connection ee_ue_ip_change_connection;
bs2::connection ee_plmn_change_connection;
bs2::connection ee_ddds_connection;
bs2::connection ee_flexcn;
};
} // namespace smf
......
......@@ -47,3 +47,27 @@ bs2::connection smf_event::subscribe_ee_pdu_session_release(
const ee_pdu_session_release_sig_t::slot_type& sig) {
return ee_pdu_session_release.connect(sig);
}
//------------------------------------------------------------------------------
bs2::connection smf_event::subscribe_ee_ue_ip_change(
const ee_ue_ip_change_sig_t::slot_type& sig) {
return ee_ue_ip_change.connect(sig);
}
//------------------------------------------------------------------------------
bs2::connection smf_event::subscribe_ee_plmn_change(
const ee_plmn_change_sig_t::slot_type& sig) {
return ee_plmn_change.connect(sig);
}
//------------------------------------------------------------------------------
bs2::connection smf_event::subscribe_ee_ddds(
const ee_ddds_sig_t::slot_type& sig) {
return ee_ddds.connect(sig);
}
//------------------------------------------------------------------------------
bs2::connection smf_event::subscribe_ee_flexcn_event(
const ee_flexcn_sig_t::slot_type& sig) {
return ee_flexcn.connect(sig);
}
......@@ -73,11 +73,27 @@ class smf_event {
bs2::connection subscribe_ee_pdu_session_release(
const ee_pdu_session_release_sig_t::slot_type& sig);
bs2::connection subscribe_ee_ue_ip_change(
const ee_ue_ip_change_sig_t::slot_type& sig);
bs2::connection subscribe_ee_plmn_change(
const ee_plmn_change_sig_t::slot_type& sig);
// download link data status
bs2::connection subscribe_ee_ddds(const ee_ddds_sig_t::slot_type& sig);
bs2::connection subscribe_ee_flexcn_event(
const ee_flexcn_sig_t::slot_type& sig);
private:
sm_context_status_sig_t
sm_context_status; // Signal for SM Context status update
ee_pdu_session_release_sig_t
ee_pdu_session_release; // Signal for SM Context status update
ee_pdu_session_release; // Signal for PDU Session Release
ee_ue_ip_change_sig_t ee_ue_ip_change; // Signal for UE IP Addr change
ee_plmn_change_sig_t ee_plmn_change; // Signal for UE IP Addr change
ee_ddds_sig_t ee_ddds;
ee_flexcn_sig_t ee_flexcn; // Signal for FlexCN Event
};
} // namespace smf
#endif /* FILE_SMF_EVENT_HPP_SEEN */
......@@ -52,10 +52,29 @@ typedef bs2::signal_type<
ee_pdu_session_release_sig_t;
// TODO: ee_ue_ip_address_change_sig_t; //UI IP Address, UE ID
// Signal for Event exposure
// UE Addr Change, SUPI, PDU SessionID, HTTP version
typedef bs2::signal_type<
void(supi64_t, uint8_t), bs2::keywords::mutex_type<bs2::dummy_mutex>>::type
ee_ue_ip_change_sig_t;
// TODO: Access Type Change
// TODO: UP Path Change
// TODO: PLMN Change
typedef bs2::signal_type<
void(scid_t, uint8_t), bs2::keywords::mutex_type<bs2::dummy_mutex>>::type
ee_plmn_change_sig_t;
// TODO: Downlink data delivery status
typedef bs2::signal_type<
void(scid_t, uint8_t), bs2::keywords::mutex_type<bs2::dummy_mutex>>::type
ee_ddds_sig_t;
// Signal for FlexCN event (for Event Exposure)
// SCID, HTTP version
typedef bs2::signal_type<
void(scid_t, uint8_t), bs2::keywords::mutex_type<bs2::dummy_mutex>>::type
ee_flexcn_sig_t;
} // namespace smf
#endif /* FILE_SMF_EVENT_SIG_HPP_SEEN */
......@@ -976,11 +976,42 @@ void event_exposure_msg::set_event_subs(
void event_notification::set_smf_event(const smf_event_t& ev) {
m_event = ev;
}
//-----------------------------------------------------------------------------
smf_event_t event_notification::get_smf_event() const {
return m_event;
}
//-----------------------------------------------------------------------------
// ddds change
void event_notification::set_Ddds(
oai::smf_server::model::DddStatus const& value) {
m_DddStatus = value;
m_DddStatusIsSet = true;
}
oai::smf_server::model::DddStatus event_notification::get_ddds() const {
return m_DddStatus;
}
bool event_notification::is_ddds_is_set() const {
return m_DddStatusIsSet;
}
//-----------------------------------------------------------------------------
void event_notification::set_timestamp(const std::string& ss) {
m_timestamp = ss;
}
//-----------------------------------------------------------------------------
void event_notification::get_timestamp(std::string& ss) const {
ss = m_timestamp;
}
//-----------------------------------------------------------------------------
std::string event_notification::get_timestamp() const {
return m_timestamp;
}
//-----------------------------------------------------------------------------
supi64_t event_notification::get_supi() const {
return m_supi;
......@@ -1029,6 +1060,21 @@ bool event_notification::is_re_ipv4_addr_is_set() const {
return m_re_ipv4_addr_is_set;
}
// m_PlmnId
void event_notification::set_PlmnId(
oai::smf_server::model::PlmnId const& value) {
m_PlmnId = value;
m_PlmnIdIsSet = true;
}
oai::smf_server::model::PlmnId event_notification::get_plmnid() const {
return m_PlmnId;
}
bool event_notification::is_plmnid_is_set() const {
return m_PlmnIdIsSet;
}
//-----------------------------------------------------------------------------
void event_notification::set_pdu_session_id(const pdu_session_id_t value) {
m_pdu_session_id = value;
......@@ -1065,6 +1111,16 @@ std::string event_notification::get_notif_id() const {
return m_notif_id;
}
//------------------------------------------------------------------------------
void event_notification::set_custom_info(const nlohmann::json& c) {
custom_info = c;
}
//------------------------------------------------------------------------------
void event_notification::get_custom_info(nlohmann::json& c) const {
c = custom_info;
}
//-----------------------------------------------------------------------------
void data_notification_msg::set_notification_event_type(
const std::string& type) {
......
......@@ -35,11 +35,13 @@
#include "3gpp_24.501.h"
#include "3gpp_29.244.h"
#include "3gpp_29.508.h"
#include "3gpp_29.518.h"
#include "3gpp_29.571.h"
#include "NgRanTargetId.h"
#include "pistache/http.h"
#include "smf_profile.hpp"
#include "3gpp_29.518.h"
#include "PlmnId.h"
#include "DddStatus.h"
extern "C" {
#include "QOSRules.h"
......@@ -604,6 +606,10 @@ class event_notification {
void set_smf_event(const smf_event_t& ev);
smf_event_t get_smf_event() const;
void set_timestamp(const std::string& ss);
void get_timestamp(std::string& ss) const;
std::string get_timestamp() const;
void set_supi(const supi64_t& supi);
supi64_t get_supi() const;
bool is_supi_is_set() const;
......@@ -616,6 +622,16 @@ class event_notification {
std::string get_re_ipv4_addr() const;
bool is_re_ipv4_addr_is_set() const;
// m_PlmnId
void set_PlmnId(oai::smf_server::model::PlmnId const& value);
oai::smf_server::model::PlmnId get_plmnid() const;
bool is_plmnid_is_set() const;
// ddds change
void set_Ddds(oai::smf_server::model::DddStatus const& value);
oai::smf_server::model::DddStatus get_ddds() const;
bool is_ddds_is_set() const;
void set_pdu_session_id(const pdu_session_id_t value);
pdu_session_id_t get_pdu_session_id() const;
bool is_psi_is_set() const;
......@@ -624,13 +640,16 @@ class event_notification {
std::string get_notif_uri() const;
void set_notif_id(std::string const& value);
std::string get_notif_id() const;
void set_custom_info(const nlohmann::json& c);
void get_custom_info(nlohmann::json& c) const;
private:
std::string m_notif_uri; // m_NotifUri;
std::string m_notif_id; // m_NotifId;
nlohmann::json custom_info; // store extra json data
std::string m_notif_uri; // m_NotifUri;
std::string m_notif_id; // m_NotifId;
smf_event_t m_event; // SmfEvent
// std::string m_TimeStamp;
std::string m_timestamp;
supi64_t m_supi;
bool m_supi_is_set;
......@@ -642,8 +661,12 @@ class event_notification {
bool m_re_ipv4_addr_is_set; // m_ReIpv4AddrIsSet;
// for a PLMN Change
// PlmnId m_PlmnId;
// bool m_PlmnIdIsSet;
oai::smf_server::model::PlmnId m_PlmnId;
bool m_PlmnIdIsSet;
// for ddds change
oai::smf_server::model::DddStatus m_DddStatus;
bool m_DddStatusIsSet;
// for an access type change
// AccessType m_AccType;
......@@ -679,8 +702,6 @@ class event_notification {
// bool m_AdIpv6PrefixIsSet;
// Ipv6Prefix m_ReIpv6Prefix;
// bool m_ReIpv6PrefixIsSet;
// DddStatus m_DddStatus;
// bool m_DddStatusIsSet;
// std::string m_MaxWaitTime;
// bool m_MaxWaitTimeIsSet;
};
......
......@@ -163,6 +163,15 @@ int session_create_sm_context_procedure::run(
cp_fseid.seid = sps->seid;
n4_triggered->pfcp_ies.set(cp_fseid);
//-------------------
// IE network instance
//-------------------
bool nwi_list_present = false;
uint8_t nwi_list_index = 0;
if (smf_cfg.get_nwi_list_index(nwi_list_present, nwi_list_index, up_node_id) &
smf_cfg.use_nwi)
nwi_list_present = true;
//*******************
// UPLINK
//*******************
......@@ -183,7 +192,14 @@ int session_create_sm_context_procedure::run(
destination_interface.interface_value =
pfcp::INTERFACE_VALUE_CORE; // ACCESS is for downlink, CORE for uplink
forwarding_parameters.set(destination_interface);
// TODO: Network Instance
if (nwi_list_present) {
pfcp::network_instance_t network_instance = {};
network_instance.network_instance =
smf_cfg.upf_nwi_list[nwi_list_index].domain_core;
forwarding_parameters.set(network_instance);
}
// TODO: Redirect Information
// TODO: Outer Header Creation (e.g., in case of N9)
......@@ -230,6 +246,13 @@ int session_create_sm_context_procedure::run(
// Session Establishment Request, 3GPP TS 29.244 V16.0.0) source interface
source_interface.interface_value = pfcp::INTERFACE_VALUE_ACCESS;
pdi.set(source_interface);
if (nwi_list_present) {
pfcp::network_instance_t network_instance = {};
network_instance.network_instance = smf_cfg.upf_nwi_list[0].domain_access;
pdi.set(network_instance);
}
// CN tunnel info
local_fteid.ch =
1; // SMF requests the UPF to assign a local F-TEID to the PDR
......@@ -564,6 +587,15 @@ int session_update_sm_context_procedure::run(
}
*/
//-------------------
// IE network instance
//-------------------
bool nwi_list_present = false;
uint8_t nwi_list_index = 0;
if (smf_cfg.get_nwi_list_index(nwi_list_present, nwi_list_index, up_node_id) &
smf_cfg.use_nwi)
nwi_list_present = true;
//-------------------
n11_trigger = sm_context_req;
n11_triggered_pending = sm_context_resp;
......@@ -697,6 +729,12 @@ int session_update_sm_context_procedure::run(
destination_interface.interface_value =
pfcp::INTERFACE_VALUE_ACCESS; // ACCESS is for downlink, CORE for
// uplink
if (nwi_list_present) {
pfcp::network_instance_t network_instance = {};
network_instance.network_instance =
smf_cfg.upf_nwi_list[0].domain_access;
forwarding_parameters.set(network_instance);
}
forwarding_parameters.set(destination_interface);
outer_header_creation.outer_header_creation_description =
OUTER_HEADER_CREATION_GTPU_UDP_IPV4;
......@@ -749,7 +787,13 @@ int session_update_sm_context_procedure::run(
// pfcp::framed_routing_t framed_routing = {};
// pfcp::framed_ipv6_route_t framed_ipv6_route = {};
source_interface.interface_value = pfcp::INTERFACE_VALUE_CORE;
if (nwi_list_present) {
pfcp::network_instance_t network_instance =
{}; // mandatory for travelping
network_instance.network_instance =
smf_cfg.upf_nwi_list[0].domain_core;
pdi.set(network_instance);
}
// local_fteid.from_core_fteid(qos_flow.qos_flow.dl_fteid);
if (sps->ipv4) {
ue_ip_address.v4 = 1;
......@@ -831,6 +875,13 @@ int session_update_sm_context_procedure::run(
precedence.precedence = flow.precedence.precedence;
source_interface.interface_value = pfcp::INTERFACE_VALUE_CORE;
if (nwi_list_present) {
pfcp::network_instance_t network_instance =
{}; // mandatory for travelping
network_instance.network_instance =
smf_cfg.upf_nwi_list[0].domain_core;
pdi.set(network_instance);
}
pdi.set(source_interface);
pdi.set(ue_ip_address);
......@@ -1143,9 +1194,16 @@ void session_update_sm_context_procedure::handle_itti_msg(
// set UpCnxState to ACTIVATED
sps->set_upCnx_state(upCnx_state_e::UPCNX_STATE_ACTIVATED);
Logger::smf_app().info(
"SMF context: \n %s", sc.get()->toString().c_str());
// Trigger Event_exposure event
std::string str_scid = n11_trigger.get()->scid;
// TODO: validate the str_scid
//
scid_t scid = (scid_t) std::stoul(str_scid, nullptr, 0);
sc.get()->trigger_ue_ip_change(scid, 1);
sc.get()->trigger_plmn_change(scid, 1);
sc.get()->trigger_ddds(scid, 1);
sc.get()->trigger_flexcn_event(scid, 1);
} break;
......
......@@ -519,6 +519,26 @@ void upf_profile::display() const {
Logger::smf_app().debug("\t\t\tDNN %s", d.dnn.c_str());
}
}
if (!upf_info.interface_upf_info_list.empty()) {
for (auto s : upf_info.interface_upf_info_list) {
std::string network_instance = {};
std::string endpoint_fqdn = {};
std::vector<struct in_addr> ipv4_addresses = {};
// std::vector<struct in6_addr> ipv6_addresses = {};
if (!s.network_instance.empty()) network_instance = s.network_instance;
if (!s.endpoint_fqdn.empty()) endpoint_fqdn = s.endpoint_fqdn;
Logger::smf_app().debug(
"\t\tINTERFACE UPF Info List, Interface Type : %s, Network Instance "
"%s, EndpointFqdn: %s",
s.interface_type.c_str(), s.network_instance.c_str(),
s.endpoint_fqdn.c_str());
if (s.ipv4_addresses.size() > 0)
Logger::smf_app().debug("\t\t\tINTERFACE UPF Info List, IPv4 Addr:");
for (auto address : s.ipv4_addresses) {
Logger::smf_app().debug("\t\t\t\t\t\t %s", inet_ntoa(address));
}
}
}
}
//------------------------------------------------------------------------------
......@@ -540,7 +560,24 @@ void upf_profile::to_json(nlohmann::json& data) const {
}
data["upfInfo"]["sNssaiUpfInfoList"].push_back(tmp);
}
if (!upf_info.interface_upf_info_list.empty()) {
data["upfInfo"]["interfaceUpfInfoList"] = nlohmann::json::array();
for (auto s : upf_info.interface_upf_info_list) {
nlohmann::json tmp = {};
tmp["interfaceType"] = s.interface_type;
if (!s.endpoint_fqdn.empty()) tmp["endpointFqdn"] = s.endpoint_fqdn;
if (!s.network_instance.empty())
tmp["networkInstance"] = s.network_instance;
if (s.ipv4_addresses.size() > 0) {
tmp["ipv4EndpointAddresses"] = nlohmann::json::array();
for (auto address : s.ipv4_addresses) {
tmp["ipv4EndpointAddresses"].push_back(inet_ntoa(address));
}
}
// ToDo for ipv6
data["upfInfo"]["interfaceUpfInfoList"].push_back(tmp);
}
}
Logger::smf_app().debug("UPF profile to json:\n %s", data.dump().c_str());
}
......@@ -576,6 +613,42 @@ void upf_profile::from_json(const nlohmann::json& data) {
upf_info.snssai_upf_info_list.push_back(upf_info_item);
}
}
if (info.find("interfaceUpfInfoList") != info.end()) {
nlohmann::json interface_upf_info_list =
data["upfInfo"]["interfaceUpfInfoList"];
for (auto it : interface_upf_info_list) {
interface_upf_info_item_t up_interface_info_item = {};
if (it.find("interfaceType") != it.end())
up_interface_info_item.interface_type =
it["interfaceType"].get<std::string>();
if (it.find("networkInstance") != it.end())
up_interface_info_item.network_instance =
it["networkInstance"].get<std::string>();
if (it.find("endpointFqdn") != it.end())
up_interface_info_item.endpoint_fqdn =
it["endpointFqdn"].get<std::string>();
if (it.find("ipv4EndpointAddresses") != it.end()) {
nlohmann::json addresses = it["ipv4EndpointAddresses"];
for (auto d : addresses) {
struct in_addr addr4 = {};
std::string address = d.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::smf_app().warn(
"Address conversion: Bad value %s",
util::trim(address).c_str());
}
up_interface_info_item.ipv4_addresses.push_back(addr4);
}
}
// ToDo for ipv6
upf_info.interface_upf_info_list.push_back(up_interface_info_item);
}
}
}
display();
......
This diff is collapsed.
......@@ -157,7 +157,8 @@ class smf_sbi {
*/
bool get_sm_data(
const supi64_t& supi, const std::string& dnn, const snssai_t& snssai,
std::shared_ptr<session_management_subscription> subscription);
std::shared_ptr<session_management_subscription>& subscription,
plmn_t plmn = {});
/*
* Subscribe to be notify from UDM
......
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