Commit 89d041b9 authored by Tien-Thinh Nguyen's avatar Tien-Thinh Nguyen

Merge branch 'release_v1.0' into 'develop'

Merge Release v1.0 into Develop

See merge request oai/oai-cn5g-smf!11
parents ef0b47fa 994a83df
......@@ -71,13 +71,13 @@ SMF =
);
};
APN_LIST = (
DNN_LIST = (
# IPV4_POOL, IPV6_POOL are index in IPV4_LIST, IPV6_LIST, PDN_TYPE choice in {IPv4, IPv6, IPv4v6}
{APN_NI = "default"; PDN_TYPE = "IPv4"; IPV4_POOL = 0; IPV6_POOL = -1},
{APN_NI = "carrier.com"; PDN_TYPE = "IPv4"; IPV4_POOL = 1; IPV6_POOL = -1},
{APN_NI = "apn2"; PDN_TYPE = "IPv4"; IPV4_POOL = 2; IPV6_POOL = -1},
{APN_NI = "apn3"; PDN_TYPE = "IPv4"; IPV4_POOL = 3; IPV6_POOL = -1},
{APN_NI = "apn4"; PDN_TYPE = "IPv4"; IPV4_POOL = 4; IPV6_POOL = -1}
{DNN_NI = "default"; PDN_TYPE = "IPv4"; IPV4_POOL = 0; IPV6_POOL = -1},
{DNN_NI = "carrier.com"; PDN_TYPE = "IPv4"; IPV4_POOL = 1; IPV6_POOL = -1},
{DNN_NI = "apn2"; PDN_TYPE = "IPv4"; IPV4_POOL = 2; IPV6_POOL = -1},
{DNN_NI = "apn3"; PDN_TYPE = "IPv4"; IPV4_POOL = 3; IPV6_POOL = -1},
{DNN_NI = "apn4"; PDN_TYPE = "IPv4"; IPV4_POOL = 4; IPV6_POOL = -1}
);
# DNS address communicated to UEs
......@@ -97,12 +97,26 @@ SMF =
UDM :
{
IPV4_ADDRESS="@UDM_IPV4_ADDRESS@";
PORT = @UDM_PORT@; #should be removed (default 80)
PORT = @UDM_PORT@; #should be removed (default 80)
};
UPF_LIST = (
{IPV4_ADDRESS="@UPF_IPV4_ADDRESS@" ;}
);
LOCAL_CONFIGURATION :
{
USE_LOCAL_CONFIGURATION = "yes";
SESSION_MANAGEMENT_SUBSCRIPTION_LIST = (
{ 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 = 222; NSSAI_SD = "123", DNN = "carrier.com", 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"}
);
};
};
......@@ -43,10 +43,7 @@
#include "logger.hpp"
#include "Helpers.h"
extern "C" {
#include "multipartparser.h"
#include "dynamic_memory_check.h"
}
#include "simple_parser.hpp"
namespace oai {
namespace smf_server {
......@@ -141,91 +138,39 @@ void IndividualSMContextApi::update_sm_context_handler(
Logger::smf_api_server().info(
"Received a SM context update request from AMF.");
Logger::smf_api_server().debug("Request body: %s\n", request.body().c_str());
//find boundary
std::size_t found = request.body().find("Content-Type");
std::string boundary_str = request.body().substr(2, found - 4);
Logger::smf_api_server().debug("Boundary: %s", boundary_str.c_str());
SmContextUpdateMessage smContextUpdateMessage = { };
//step 1. use multipartparser to decode the request
multipartparser_callbacks_init(&g_callbacks);
g_callbacks.on_body_begin = &on_body_begin;
g_callbacks.on_part_begin = &on_part_begin;
g_callbacks.on_header_field = &on_header_field;
g_callbacks.on_header_value = &on_header_value;
g_callbacks.on_headers_complete = &on_headers_complete;
g_callbacks.on_data = &on_data;
g_callbacks.on_part_end = &on_part_end;
g_callbacks.on_body_end = &on_body_end;
multipartparser parser = { };
init_globals();
multipartparser_init(&parser,
reinterpret_cast<const char*>(boundary_str.c_str()));
unsigned int str_len = request.body().length();
unsigned char *data = (unsigned char*) malloc(str_len + 1);
memset(data, 0, str_len + 1);
memcpy((void*) data, (void*) request.body().c_str(), str_len);
//if ((multipartparser_execute(&parser, &g_callbacks, request.body().c_str(), strlen(request.body().c_str())) != strlen(request.body().c_str())) or (!g_body_begin_called)){
if ((multipartparser_execute(&parser, &g_callbacks,
reinterpret_cast<const char*>(data), str_len)
!= strlen(request.body().c_str())) or (!g_body_begin_called)) {
Logger::smf_api_server().debug(
"The received message can not be parsed properly!");
//TODO: fix this issue
//response.send(Pistache::Http::Code::Bad_Request, "");
//return;
}
//simple parser
simple_parser sp = { };
sp.parse(request.body());
free_wrapper((void**) &data);
uint8_t size = g_parts.size();
Logger::smf_api_server().debug("Number of MIME parts %d", g_parts.size());
part p0 = { };
part p1 = { };
if (size > 0) {
p0 = g_parts.front();
g_parts.pop_front();
Logger::smf_api_server().debug("Request body, part 1: %s", p0.body.c_str());
}
if (size > 1) {
p1 = g_parts.front();
g_parts.pop_front();
Logger::smf_api_server().debug("Request body, part 2: %s (%d bytes)",
p1.body.c_str(), p1.body.length());
//part p2 = g_parts.front(); g_parts.pop_front();
//Logger::smf_api_server().debug("Request body, part 3: \n %s",p2.body.c_str());
}
std::vector<mime_part> parts = { };
sp.get_mime_parts(parts);
uint8_t size = parts.size();
Logger::smf_api_server().debug("Number of MIME parts %d", size);
// Getting the body param
SmContextUpdateData smContextUpdateData = { };
try {
if (size > 0) {
nlohmann::json::parse(p0.body.c_str()).get_to(smContextUpdateData);
nlohmann::json::parse(parts[0].body.c_str()).get_to(smContextUpdateData);
} else {
nlohmann::json::parse(request.body().c_str()).get_to(smContextUpdateData);
}
smContextUpdateMessage.setJsonData(smContextUpdateData);
if (size > 1) {
if (smContextUpdateData.n2SmInfoIsSet()) {
//N2 SM (for Session establishment, or for session modification)
Logger::smf_api_server().debug("N2 SM information is set");
smContextUpdateMessage.setBinaryDataN2SmInformation(p1.body);
}
if (smContextUpdateData.n1SmMsgIsSet()) {
//N1 SM (for session modification, UE-initiated)
for (int i = 1; i < size; i++) {
if (parts[i].content_type.compare("application/vnd.3gpp.5gnas") == 0) {
smContextUpdateMessage.setBinaryDataN1SmMessage(parts[i].body);
Logger::smf_api_server().debug("N1 SM message is set");
smContextUpdateMessage.setBinaryDataN1SmMessage(p1.body);
} else if (parts[i].content_type.compare("application/vnd.3gpp.ngap")
== 0) {
smContextUpdateMessage.setBinaryDataN2SmInformation(parts[i].body);
Logger::smf_api_server().debug("N2 SM information is set");
}
}
// Getting the path params
auto smContextRef = request.param(":smContextRef").as<std::string>();
this->update_sm_context(smContextRef, smContextUpdateMessage, response);
......
......@@ -43,8 +43,9 @@
#include "logger.hpp"
#include "Helpers.h"
#include "simple_parser.hpp"
extern "C" {
#include "multipartparser.h"
#include "dynamic_memory_check.h"
}
......@@ -85,77 +86,34 @@ void SMContextsCollectionApi::post_sm_contexts_handler(
Logger::smf_api_server().debug("");
Logger::smf_api_server().info(
"Received a SM context create request from AMF.");
Logger::smf_api_server().debug("Request body: %s", request.body().c_str());
//find boundary
std::size_t found = request.body().find("Content-Type");
std::string boundary_str = request.body().substr(2, found - 4);
Logger::smf_api_server().debug("Boundary: %s", boundary_str.c_str());
SmContextMessage smContextMessage = { };
SmContextCreateData smContextCreateData = { };
//step 1. use multipartparser to decode the request
multipartparser_callbacks_init(&g_callbacks);
g_callbacks.on_body_begin = &on_body_begin;
g_callbacks.on_part_begin = &on_part_begin;
g_callbacks.on_header_field = &on_header_field;
g_callbacks.on_header_value = &on_header_value;
g_callbacks.on_headers_complete = &on_headers_complete;
g_callbacks.on_data = &on_data;
g_callbacks.on_part_end = &on_part_end;
g_callbacks.on_body_end = &on_body_end;
multipartparser parser = { };
init_globals();
multipartparser_init(&parser,
reinterpret_cast<const char*>(boundary_str.c_str()));
unsigned int str_len = request.body().length();
unsigned char *data = (unsigned char*) malloc(str_len + 1);
memset(data, 0, str_len + 1);
memcpy((void*) data, (void*) request.body().c_str(), str_len);
//if ((multipartparser_execute(&parser, &g_callbacks, request.body().c_str(), strlen(request.body().c_str())) != strlen(request.body().c_str())) or (!g_body_begin_called)){
if ((multipartparser_execute(&parser, &g_callbacks,
reinterpret_cast<const char*>(data), str_len)
!= strlen(request.body().c_str())) or (!g_body_begin_called)) {
Logger::smf_api_server().debug(
"The received message can not be parsed properly!");
//TODO: fix this issue
//response.send(Pistache::Http::Code::Bad_Request, "");
//return;
}
free_wrapper((void**) &data);
//simple parser
simple_parser sp = { };
sp.parse(request.body());
uint8_t size = g_parts.size();
Logger::smf_api_server().debug("Number of MIME parts %d", g_parts.size());
std::vector<mime_part> parts = { };
sp.get_mime_parts(parts);
uint8_t size = parts.size();
Logger::smf_api_server().debug("Number of MIME parts %d", size);
//at least 2 parts for Json data and N1 (+ N2)
if (g_parts.size() < 2) {
if (size < 2) {
response.send(Pistache::Http::Code::Bad_Request, "");
return;
}
part p0 = g_parts.front();
g_parts.pop_front();
Logger::smf_api_server().debug("Request body, part 1: \n%s", p0.body.c_str());
part p1 = g_parts.front();
g_parts.pop_front();
Logger::smf_api_server().debug("Request body, part 2: \n %s",
p1.body.c_str());
if (g_parts.size() > 0) {
part p2 = g_parts.front();
g_parts.pop_front();
Logger::smf_api_server().debug("Request body, part 3: \n %s",
p2.body.c_str());
}
//step 2. process the request
try {
nlohmann::json::parse(p0.body.c_str()).get_to(smContextCreateData);
nlohmann::json::parse(parts[0].body.c_str()).get_to(smContextCreateData);
smContextMessage.setJsonData(smContextCreateData);
smContextMessage.setBinaryDataN1SmMessage(p1.body);
if (parts[1].content_type.compare("application/vnd.3gpp.5gnas") == 0) {
smContextMessage.setBinaryDataN1SmMessage(parts[1].body);
} else if (parts[1].content_type.compare("application/vnd.3gpp.ngap")
== 0) {
smContextMessage.setBinaryDataN2SmInformation(parts[1].body);
}
this->post_sm_contexts(smContextMessage, response);
} catch (nlohmann::detail::exception &e) {
//send a 400 error
......
/*
* 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 Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
*
* 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_AMF_SEEN
#define FILE_AMF_SEEN
#endif
......@@ -300,7 +300,11 @@ class itti_n11_n1n2_message_transfer_response_status : public itti_n11_msg {
dest),
scid(0),
response_code(0),
msg_type(0) {
msg_type(0),
procedure_type(
session_management_procedures_type_e::PROCEDURE_TYPE_UNKNOWN),
seid(0),
trxn_id(0) {
}
itti_n11_n1n2_message_transfer_response_status(
const itti_n11_n1n2_message_transfer_response_status &i)
......@@ -308,7 +312,10 @@ class itti_n11_n1n2_message_transfer_response_status : public itti_n11_msg {
itti_n11_msg(i),
scid(i.scid),
response_code(i.response_code),
msg_type(i.msg_type) {
msg_type(i.msg_type),
procedure_type(i.procedure_type),
seid(i.seid),
trxn_id(i.trxn_id) {
}
itti_n11_n1n2_message_transfer_response_status(
const itti_n11_n1n2_message_transfer_response_status &i,
......@@ -317,7 +324,10 @@ class itti_n11_n1n2_message_transfer_response_status : public itti_n11_msg {
itti_n11_msg(i, orig, dest),
scid(i.scid),
response_code(i.response_code),
msg_type(i.msg_type) {
msg_type(i.msg_type),
procedure_type(i.procedure_type),
seid(i.seid),
trxn_id(i.trxn_id) {
}
const char* get_msg_name() {
return "N11_SESSION_N1N2_MESSAGE_TRANSFER_RESPONSE_STATUS";
......@@ -339,10 +349,28 @@ class itti_n11_n1n2_message_transfer_response_status : public itti_n11_msg {
msg_type = type;
}
;
void set_procedure_type(session_management_procedures_type_e type) {
procedure_type = type;
}
;
void set_seid(const seid_t &s) {
seid = s;
}
;
void set_trxn_id(uint64_t t) {
trxn_id = t;
}
;
scid_t scid; //SM Context ID
int16_t response_code;
std::string cause;
uint8_t msg_type;
session_management_procedures_type_e procedure_type;
seid_t seid;
uint64_t trxn_id;
};
......@@ -396,8 +424,8 @@ class itti_n11_release_sm_context_request : public itti_n11_msg {
class itti_n11_release_sm_context_response : public itti_n11_msg {
public:
itti_n11_release_sm_context_response(const task_id_t orig,
const task_id_t dest,
Pistache::Http::ResponseWriter &response)
const task_id_t dest,
Pistache::Http::ResponseWriter &response)
:
itti_n11_msg(N11_SESSION_RELEASE_SM_CONTEXT_RESPONSE, orig, dest),
http_response(response.clone()),
......@@ -427,5 +455,30 @@ class itti_n11_release_sm_context_response : public itti_n11_msg {
};
//-----------------------------------------------------------------------------
class itti_n11_session_report_request : public itti_n11_msg {
public:
itti_n11_session_report_request(const task_id_t orig, const task_id_t dest)
:
itti_n11_msg(N11_SESSION_REPORT_RESPONSE, orig, dest),
res() {
}
itti_n11_session_report_request(const itti_n11_session_report_request &i)
:
itti_n11_msg(i) {
}
itti_n11_session_report_request(const itti_n11_session_report_request &i,
const task_id_t orig, const task_id_t dest)
:
itti_n11_msg(i, orig, dest),
res(i.res) {
}
const char* get_msg_name() {
return "N11_SESSION_REPORT_RESPONSE";
}
;
smf::pdu_session_report_response res;
};
#endif /* ITTI_MSG_N11_HPP_INCLUDED_ */
......@@ -705,4 +705,33 @@ class itti_n4_session_report_response : public itti_n4_msg {
pfcp::pfcp_session_report_response pfcp_ies;
};
//-----------------------------------------------------------------------------
class itti_n4_session_failure_indication : public itti_n4_msg {
public:
itti_n4_session_failure_indication(const task_id_t origin,
const task_id_t destination)
:
itti_n4_msg(N4_SESSION_REPORT_RESPONSE, origin, destination) {
}
itti_n4_session_failure_indication(const itti_n4_session_failure_indication &i)
:
itti_n4_msg(i) {
pfcp_ies = i.pfcp_ies;
}
itti_n4_session_failure_indication(const itti_n4_session_failure_indication &i,
const task_id_t orig, const task_id_t dest)
:
itti_n4_msg(i, orig, dest) {
pfcp_ies = i.pfcp_ies;
}
const char* get_msg_name() {
return typeid(itti_n4_session_failure_indication).name();
}
;
pfcp::pfcp_session_modification_request pfcp_ies;
};
#endif /* ITTI_MSG_N4_HPP_INCLUDED_ */
......@@ -28,7 +28,6 @@
typedef uint64_t supi64_t;
#define SUPI_64_FMT "%" SCNu64
//typedef imsi_t supi_t;
#define SUPI_DIGITS_MAX 15
......@@ -110,22 +109,23 @@ enum class http_response_codes_e {
//From 23.502
enum class session_management_procedures_type_e {
PDU_SESSION_ESTABLISHMENT_UE_REQUESTED = 0,
SERVICE_REQUEST_UE_TRIGGERED_STEP1 = 1,
SERVICE_REQUEST_UE_TRIGGERED_STEP2 = 2,
SERVICE_REQUEST_NETWORK_TRIGGERED = 3,
PDU_SESSION_MODIFICATION_UE_INITIATED_STEP1 = 4,
PDU_SESSION_MODIFICATION_UE_INITIATED_STEP2 = 5,
PDU_SESSION_MODIFICATION_UE_INITIATED_STEP3 = 6,
PDU_SESSION_MODIFICATION_SMF_REQUESTED = 7,
PDU_SESSION_MODIFICATION_AN_REQUESTED = 8,
PDU_SESSION_RELEASE_UE_REQUESTED_STEP1 = 9,
PDU_SESSION_RELEASE_UE_REQUESTED_STEP2 = 10,
PDU_SESSION_RELEASE_UE_REQUESTED_STEP3 = 11,
PDU_SESSION_RELEASE_SMF_INITIATED = 12,
PDU_SESSION_RELEASE_AMF_INITIATED = 13,
PDU_SESSION_RELEASE_AN_INITIATED = 14,
PDU_SESSION_TEST = 15
PROCEDURE_TYPE_UNKNOWN = 0,
PDU_SESSION_ESTABLISHMENT_UE_REQUESTED = 1,
SERVICE_REQUEST_UE_TRIGGERED_STEP1 = 2,
SERVICE_REQUEST_UE_TRIGGERED_STEP2 = 3,
SERVICE_REQUEST_NETWORK_TRIGGERED = 4,
PDU_SESSION_MODIFICATION_UE_INITIATED_STEP1 = 5,
PDU_SESSION_MODIFICATION_UE_INITIATED_STEP2 = 6,
PDU_SESSION_MODIFICATION_UE_INITIATED_STEP3 = 7,
PDU_SESSION_MODIFICATION_SMF_REQUESTED = 8,
PDU_SESSION_MODIFICATION_AN_REQUESTED = 9,
PDU_SESSION_RELEASE_UE_REQUESTED_STEP1 = 10,
PDU_SESSION_RELEASE_UE_REQUESTED_STEP2 = 11,
PDU_SESSION_RELEASE_UE_REQUESTED_STEP3 = 12,
PDU_SESSION_RELEASE_SMF_INITIATED = 13,
PDU_SESSION_RELEASE_AMF_INITIATED = 14,
PDU_SESSION_RELEASE_AN_INITIATED = 15,
PDU_SESSION_TEST = 16
};
static const std::vector<std::string> session_management_procedures_type_e2str =
......@@ -191,6 +191,12 @@ static const std::vector<std::string> multipart_related_content_part_e2str = {
#define AMF_NUMBER_RETRIES 3
#define UDM_CURL_TIMEOUT_MS 100L
#define UDM_NUMBER_RETRIES 3
constexpr auto CURL_MIME_BOUNDARY = "----Boundary";
//for N1N2
#define BUF_LEN 512
//for PFCP
constexpr uint64_t SECONDS_SINCE_FIRST_EPOCH = 2208988800;
#endif
......@@ -36,6 +36,7 @@ set(CN_UTILS_SRC STATIC
${CMAKE_CURRENT_SOURCE_DIR}/pid_file.cpp
${CMAKE_CURRENT_SOURCE_DIR}/string.cpp
${CMAKE_CURRENT_SOURCE_DIR}/thread_sched.cpp
${CMAKE_CURRENT_SOURCE_DIR}/simple_parser.cpp
)
......
......@@ -363,62 +363,62 @@ std::string Utility::epc(const unsigned char *plmnid) {
return epc(mnc, mcc);
}
std::string Utility::apn_fqdn(const char *apnoi, const char *mnc,
std::string Utility::dnn_fqdn(const char *apnoi, const char *mnc,
const char *mcc) {
std::string s;
// '(.+)\.apn\.epc\.mnc(\d{3})\.mcc(\d{3})\.3gppnetworks\.org$'
s.append(apnoi).append(".apn.epc.").APPEND_MNC( mnc ).APPEND_MCC( mcc ).
// '(.+)\.dnn\.epc\.mnc(\d{3})\.mcc(\d{3})\.3gppnetworks\.org$'
s.append(apnoi).append(".dnn.epc.").APPEND_MNC( mnc ).APPEND_MCC( mcc ).
APPEND_3GPPNETWORK;
return s;
}
std::string Utility::apn_fqdn(const char *apnoi, const unsigned char *plmnid) {
std::string Utility::dnn_fqdn(const char *apnoi, const unsigned char *plmnid) {
PARSE_PLMNID(plmnid);
return apn_fqdn(apnoi, mnc, mcc);
return dnn_fqdn(apnoi, mnc, mcc);
}
std::string Utility::apn(const char *apnoi, const char *mnc, const char *mcc) {
std::string Utility::dnn(const char *apnoi, const char *mnc, const char *mcc) {
std::string s;
// '(.+)\.apn\.mnc(\d{3})\.mcc(\d{3})\.gprs$'}
s.append(apnoi).append(".apn.").APPEND_MNC( mnc ).APPEND_MCC( mcc ).append(
// '(.+)\.dnn\.mnc(\d{3})\.mcc(\d{3})\.gprs$'}
s.append(apnoi).append(".dnn.").APPEND_MNC( mnc ).APPEND_MCC( mcc ).append(
"gprs");
return s;
}
std::string Utility::apn(const char *apnoi, const unsigned char *plmnid) {
std::string Utility::dnn(const char *apnoi, const unsigned char *plmnid) {
PARSE_PLMNID(plmnid);
return apn(apnoi, mnc, mcc);
return dnn(apnoi, mnc, mcc);
}
std::string Utility::apn_label(const std::string &apn) {
std::string apn_label = { };
std::string Utility::dnn_label(const std::string &dnn) {
std::string dnn_label = { };
bool to_count = true;
uint8_t counted = 0;
int index = 0;
apn_label.push_back('?');
dnn_label.push_back('?');
for (int i = 0; i < apn.length(); ++i) {
if (isalnum(apn[i]) || (apn[i] == '-')) {
apn_label.push_back(apn[i]);
for (int i = 0; i < dnn.length(); ++i) {
if (isalnum(dnn[i]) || (dnn[i] == '-')) {
dnn_label.push_back(dnn[i]);
counted++;
} else if (apn[i] == '.') {
apn_label.push_back('?');
} else if (dnn[i] == '.') {
dnn_label.push_back('?');
if (to_count) { // always true
apn_label[index] = counted;
dnn_label[index] = counted;
}
to_count = true;
counted = 0;
index = apn_label.length() - 1;
index = dnn_label.length() - 1;
}
}
if (to_count) {
apn_label[index] = counted;
dnn_label[index] = counted;
}
return apn_label;
return dnn_label;
}
......@@ -336,12 +336,12 @@ class Utility {
const unsigned char *plmnid);
static std::string epc(const char *mnc, const char *mcc);
static std::string epc(const unsigned char *plmnid);
static std::string apn_fqdn(const char *apnoi, const char *mnc,
static std::string dnn_fqdn(const char *apnoi, const char *mnc,
const char *mcc);
static std::string apn_fqdn(const char *apnoi, const unsigned char *plmnid);
static std::string apn(const char *apnoi, const char *mnc, const char *mcc);
static std::string apn(const char *apnoi, const unsigned char *plmnid);
static std::string apn_label(const std::string &apn);
static std::string dnn_fqdn(const char *apnoi, const unsigned char *plmnid);
static std::string dnn(const char *apnoi, const char *mnc, const char *mcc);
static std::string dnn(const char *apnoi, const unsigned char *plmnid);
static std::string dnn_label(const std::string &dnn);
static AppServiceEnum getAppService(const std::string &s);
static AppProtocolEnum getAppProtocol(const std::string &p);
......
/* From https://gist.github.com/javiermon/6272065#file-gateway_netlink-c */
/*
* Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
*
* 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.
*/
#include "simple_parser.hpp"
#include "logger.hpp"
bool simple_parser::parse(const std::string &str) {
std::string CRLF = "\r\n";
Logger::smf_app().debug("");
Logger::smf_app().debug("Simple parser, parsing a string:");
Logger::smf_app().debug("%s", str.c_str());
//find boundary
std::size_t content_type_pos = str.find("Content-Type"); //first part
if ((content_type_pos <= 4) or (content_type_pos == std::string::npos))
return false;
std::string boundary_str = str.substr(2, content_type_pos - 4); // 2 for -- and 2 for CRLF
Logger::smf_app().debug("Boundary: %s", boundary_str.c_str());
std::string boundary_full = "--" + boundary_str + CRLF;
std::string last_boundary = "--" + boundary_str + "--" + CRLF;
std::size_t crlf_pos = str.find(CRLF, content_type_pos);
std::size_t boundary_pos = str.find(boundary_full);
std::size_t boundary_last_post = str.find(last_boundary);
while (boundary_pos < boundary_last_post) {
mime_part p = { };
content_type_pos = str.find("Content-Type", boundary_pos);
crlf_pos = str.find(CRLF, content_type_pos);
if ((content_type_pos == std::string::npos)
or (crlf_pos == std::string::npos))
break;
p.content_type = str.substr(content_type_pos + 14,
crlf_pos - (content_type_pos + 14));
Logger::smf_app().debug("Content Type: %s", p.content_type.c_str());
crlf_pos = str.find(CRLF + CRLF, content_type_pos); //beginning of content
boundary_pos = str.find(boundary_full, crlf_pos);
if (boundary_pos == std::string::npos) {
boundary_pos = str.find(last_boundary, crlf_pos);
}
if (boundary_pos > 0) {
p.body = str.substr(crlf_pos + 4, boundary_pos - 2 - (crlf_pos + 4));
Logger::smf_app().debug("Body: %s", p.body.c_str());
mime_parts.push_back(p);
}
}
return true;
}
void simple_parser::get_mime_parts(std::vector<mime_part> &parts) const {
for (auto it : mime_parts) {
parts.push_back(it);
}
}
/*
* 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 Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
*
* 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 simple_parser.hpp
\brief
\author
\company Eurecom
\email:
*/
#ifndef FILE_SIMPLE_PARSER_HPP_SEEN
#define FILE_SIMPLE_PARSER_HPP_SEEN
# include <string>
#include <map>
#include <vector>
typedef struct mime_part {
std::string content_type;
std::string body;
} mime_part;
class simple_parser {
public:
bool parse(const std::string &str);
void get_mime_parts(std::vector<mime_part> &parts) const;
private:
std::vector<mime_part> mime_parts;
};
#endif /* FILE_SIMPLE_PARSER_HPP_SEEN */
......@@ -28,6 +28,5 @@ include_directories(${SRC_TOP_DIR}/common/msg)
include_directories(${SRC_TOP_DIR}/common/utils)
include_directories(${SRC_TOP_DIR}/gtpv2c)
include_directories(${SRC_TOP_DIR}/itti)
include_directories(${SRC_TOP_DIR}/oai_spgw_c)
include_directories(${SRC_TOP_DIR}/udp)
include_directories(${SRC_TOP_DIR}/../build/ext/spdlog/include)
......@@ -116,6 +116,7 @@ typedef enum {
N11_SESSION_N1N2_MESSAGE_TRANSFER_RESPONSE_STATUS,
N11_SESSION_RELEASE_SM_CONTEXT_REQUEST,
N11_SESSION_RELEASE_SM_CONTEXT_RESPONSE,
N11_SESSION_REPORT_RESPONSE,
NX_TRIGGER_SESSION_MODIFICATION,
UDP_INIT,
UDP_DATA_REQ,
......
......@@ -79,24 +79,24 @@ void smf_app_task(void*);
int smf_app::apply_config(const smf_config &cfg) {
Logger::smf_app().info("Apply config...");
for (int ia = 0; ia < cfg.num_apn; ia++) {
if (cfg.apn[ia].pool_id_iv4 >= 0) {
int pool_id = cfg.apn[ia].pool_id_iv4;
for (int ia = 0; ia < cfg.num_dnn; ia++) {
if (cfg.dnn[ia].pool_id_iv4 >= 0) {
int pool_id = cfg.dnn[ia].pool_id_iv4;
int range =
be32toh(
cfg.ue_pool_range_high[pool_id].s_addr) - be32toh(cfg.ue_pool_range_low[pool_id].s_addr);
paa_dynamic::get_instance().add_pool(cfg.apn[ia].apn, pool_id,
paa_dynamic::get_instance().add_pool(cfg.dnn[ia].dnn, pool_id,
cfg.ue_pool_range_low[pool_id],
range);
//TODO: check with apn_label
Logger::smf_app().info("Applied config %s", cfg.apn[ia].apn.c_str());
//TODO: check with dnn_label
Logger::smf_app().info("Applied config %s", cfg.dnn[ia].dnn.c_str());
}
if (cfg.apn[ia].pool_id_iv6 >= 0) {
int pool_id = cfg.apn[ia].pool_id_iv6;
paa_dynamic::get_instance().add_pool(cfg.apn[ia].apn, pool_id,
if (cfg.dnn[ia].pool_id_iv6 >= 0) {
int pool_id = cfg.dnn[ia].pool_id_iv6;
paa_dynamic::get_instance().add_pool(cfg.dnn[ia].dnn, pool_id,
cfg.paa_pool6_prefix[pool_id],
cfg.paa_pool6_prefix_len[pool_id]);
//TODO: check with apn_label
//TODO: check with dnn_label
}
}
......@@ -287,24 +287,9 @@ smf_app::smf_app(const std::string &config_file)
//------------------------------------------------------------------------------
//From SPGWU
void smf_app::start_upf_association(const pfcp::node_id_t &node_id) {
// TODO refine this, look at RFC5905
std::tm tm_epoch = { 0 }; // Feb 8th, 2036
tm_epoch.tm_year = 2036 - 1900; // years count from 1900
tm_epoch.tm_mon = 2 - 1; // months count from January=0
tm_epoch.tm_mday = 8 - 1; // days count from 1
std::time_t time_epoch = std::mktime(&tm_epoch);
std::chrono::time_point<std::chrono::system_clock> now =
std::chrono::system_clock::now();
std::time_t now_c = std::chrono::system_clock::to_time_t(now);
std::time_t ellapsed = now_c - time_epoch;
uint64_t recovery_time_stamp = ellapsed;
//char* dt = ctime(&now_c);
//Logger::smf_app().info( "Current time %s", dt);
// convert now to tm struct for UTC
tm *gmtm = gmtime(&now_c);
char *dt = asctime(gmtm);
Logger::smf_app().info("Current time (UTC) %s", dt);
std::time_t time_epoch = std::time(nullptr);
uint64_t tv_ntp = time_epoch + SECONDS_SINCE_FIRST_EPOCH;
pfcp_associations::get_instance().add_peer_candidate_node(node_id);
std::shared_ptr<itti_n4_association_setup_request> n4_asc = std::shared_ptr<
......@@ -317,34 +302,12 @@ void smf_app::start_upf_association(const pfcp::node_id_t &node_id) {
cp_function_features.load = 1;
cp_function_features.ovrl = 1;
/*
pfcp::up_function_features_s up_function_features;
// TODO load from config when features available ?
up_function_features = {};
up_function_features.bucp = 0;
up_function_features.ddnd = 0;
up_function_features.dlbd = 0;
up_function_features.trst = 0;
up_function_features.ftup = 1;
up_function_features.pfdm = 0;
up_function_features.heeu = 0;
up_function_features.treu = 0;
up_function_features.empu = 0;
up_function_features.pdiu = 0;
up_function_features.udbc = 0;
up_function_features.quoac = 0;
up_function_features.trace = 0;
up_function_features.frrt = 0;
*/
pfcp::node_id_t this_node_id = { };
if (smf_cfg.get_pfcp_node_id(this_node_id) == RETURNok) {
n4_asc->pfcp_ies.set(this_node_id);
pfcp::recovery_time_stamp_t r = { .recovery_time_stamp =
(uint32_t) recovery_time_stamp };
pfcp::recovery_time_stamp_t r = { .recovery_time_stamp = (uint32_t) tv_ntp };
n4_asc->pfcp_ies.set(r);
//n4_asc->pfcp_ies.set(up_function_features);
n4_asc->pfcp_ies.set(cp_function_features);
if (node_id.node_id_type == pfcp::NODE_ID_TYPE_IPV4_ADDRESS) {
n4_asc->r_endpoint = endpoint(node_id.u1.ipv4_address,
......@@ -417,31 +380,82 @@ void smf_app::handle_itti_msg(
//------------------------------------------------------------------------------
void smf_app::handle_itti_msg(
itti_n11_n1n2_message_transfer_response_status &m) {
//see TS29518_Namf_Communication.yaml
Logger::smf_app().info("Process N1N2MessageTransfer Response");
//Update PDU Session accordingly
//TODO: to be completed (process cause)
pdu_session_status_e status = { pdu_session_status_e::PDU_SESSION_INACTIVE };
upCnx_state_e state = { upCnx_state_e::UPCNX_STATE_DEACTIVATED };
if ((static_cast<http_response_codes_e>(m.response_code)
== http_response_codes_e::HTTP_RESPONSE_CODE_OK)
or (static_cast<http_response_codes_e>(m.response_code)
== http_response_codes_e::HTTP_RESPONSE_CODE_ACCEPTED)) {
if (m.msg_type == PDU_SESSION_ESTABLISHMENT_REJECT) {
status = pdu_session_status_e::PDU_SESSION_INACTIVE;
} else if (m.msg_type == PDU_SESSION_ESTABLISHMENT_ACCEPT) {
status = pdu_session_status_e::PDU_SESSION_ESTABLISHMENT_PENDING;
state = upCnx_state_e::UPCNX_STATE_ACTIVATING;
switch (m.procedure_type) {
case session_management_procedures_type_e::PDU_SESSION_ESTABLISHMENT_UE_REQUESTED: {
//Update PDU Session accordingly
pdu_session_status_e status =
{ pdu_session_status_e::PDU_SESSION_INACTIVE };
upCnx_state_e state = { upCnx_state_e::UPCNX_STATE_DEACTIVATED };
if ((static_cast<http_response_codes_e>(m.response_code)
== http_response_codes_e::HTTP_RESPONSE_CODE_OK)
or (static_cast<http_response_codes_e>(m.response_code)
== http_response_codes_e::HTTP_RESPONSE_CODE_ACCEPTED)) {
if (m.msg_type == PDU_SESSION_ESTABLISHMENT_REJECT) {
status = pdu_session_status_e::PDU_SESSION_INACTIVE;
} else if (m.msg_type == PDU_SESSION_ESTABLISHMENT_ACCEPT) {
status = pdu_session_status_e::PDU_SESSION_ESTABLISHMENT_PENDING;
state = upCnx_state_e::UPCNX_STATE_ACTIVATING;
}
update_pdu_session_status(m.scid, status);
update_pdu_session_upCnx_state(m.scid, state);
Logger::smf_app().debug(
"Got successful response from AMF (Response code %d), set session status to %s",
m.response_code,
pdu_session_status_e2str[static_cast<int>(status)].c_str());
} else {
//TODO:
Logger::smf_app().debug("Got response from AMF (Response code %d)",
m.response_code);
}
}
break;
case session_management_procedures_type_e::SERVICE_REQUEST_NETWORK_TRIGGERED: {
Logger::smf_app().debug("Got response from AMF (Response code %d) with cause %s",
m.response_code, m.cause.c_str());
if ((static_cast<http_response_codes_e>(m.response_code)
!= http_response_codes_e::HTTP_RESPONSE_CODE_OK)
and (static_cast<http_response_codes_e>(m.response_code)
!= http_response_codes_e::HTTP_RESPONSE_CODE_ACCEPTED)) {
//send failure indication to UPF
Logger::smf_app().debug("Send failure indication to UPF");
//TODO: to be completed
pfcp::node_id_t up_node_id = { };
if (not pfcp_associations::get_instance().select_up_node(
up_node_id, NODE_SELECTION_CRITERIA_MIN_PFCP_SESSIONS)) {
// TODO
Logger::smf_app().info("REMOTE_PEER_NOT_RESPONDING");
return;
}
itti_n4_session_failure_indication *itti_n4 =
new itti_n4_session_failure_indication(TASK_SMF_APP, TASK_SMF_N4);
itti_n4->seid = m.seid;
itti_n4->trxn_id = m.trxn_id;
itti_n4->r_endpoint = endpoint(up_node_id.u1.ipv4_address,
pfcp::default_port);
std::shared_ptr<itti_n4_session_failure_indication> itti_n4_failure_indication =
std::shared_ptr<itti_n4_session_failure_indication>(itti_n4);
Logger::smf_app().info(
"Sending ITTI message %s to task TASK_SMF_N4",
itti_n4->get_msg_name());
int ret = itti_inst->send_msg(itti_n4_failure_indication);
if (RETURNok != ret) {
Logger::smf_app().error(
"Could not send ITTI message %s to task TASK_SMF_N4",
itti_n4->get_msg_name());
return;
}
}
}
break;
default: {
}
update_pdu_session_status(m.scid, status);
update_pdu_session_upCnx_state(m.scid, state);
Logger::smf_app().debug(
"Got successful response from AMF (Response code %d), set session status to %s",
m.response_code,
pdu_session_status_e2str[static_cast<int>(status)].c_str());
} else {
//TODO:
Logger::smf_app().debug("Got response from AMF (Response code %d)",
m.response_code);
}
}
......@@ -553,6 +567,7 @@ void smf_app::handle_pdu_session_create_sm_context_request(
//Get necessary information
supi_t supi = smreq->req.get_supi();
std::string supi_prefix = smreq->req.get_supi_prefix();
supi64_t supi64 = smf_supi_to_u64(supi);
std::string dnn = smreq->req.get_dnn();
snssai_t snssai = smreq->req.get_snssai();
......@@ -624,8 +639,9 @@ void smf_app::handle_pdu_session_create_sm_context_request(
if (request_type.compare("INITIAL_REQUEST") != 0) {
Logger::smf_app().warn("Invalid request type (request type = %s)",
request_type.c_str());
//TODO:
//return
//"Existing PDU Session", AMF should use PDUSession_UpdateSMContext instead (see step 3, section 4.3.2.2.1 @ 3GPP TS 23.502 v16.0.0)
//ignore the message
return;
}
//TODO: For the moment, not support PDU session authentication and authorization by the external DN
......@@ -664,6 +680,7 @@ void smf_app::handle_pdu_session_create_sm_context_request(
"Create a new SMF context with SUPI " SUPI_64_FMT "", supi64);
sc = std::shared_ptr<smf_context>(new smf_context());
sc.get()->set_supi(supi);
sc.get()->set_supi_prefix(supi_prefix);
set_supi_2_smf_context(supi64, sc);
}
......@@ -684,41 +701,55 @@ void smf_app::handle_pdu_session_create_sm_context_request(
}
//Step 6. retrieve Session Management Subscription data from UDM if not available (step 4, section 4.3.2 3GPP TS 23.502)
//TODO: Test with UDM (TESTER)
std::string dnn_selection_mode = smreq->req.get_dnn_selection_mode();
if (not use_local_configuration_subscription_data(dnn_selection_mode)
&& not is_supi_dnn_snssai_subscription_data(supi, dnn, snssai)) {
//uses a dummy UDM to test this part
//if the Session Management Subscription data is not available, get from configuration file or UDM
if (not sc.get()->is_dnn_snssai_subscription_data(dnn, snssai)) {
Logger::smf_app().debug(
"Retrieve Session Management Subscription data from the UDM");
"The Session Management Subscription data is not available");
session_management_subscription *s = new session_management_subscription(
snssai);
std::shared_ptr<session_management_subscription> subscription =
std::shared_ptr<session_management_subscription>(s);
if (smf_n10_inst->get_sm_data(supi64, dnn, snssai, subscription)) {
//update dnn_context with subscription info
sc.get()->insert_dnn_subscription(snssai, subscription);
if (not use_local_configuration_subscription_data(dnn_selection_mode)) {
Logger::smf_app().debug(
"Retrieve Session Management Subscription data from the UDM");
if (smf_n10_inst->get_sm_data(supi64, dnn, snssai, subscription)) {
//update dnn_context with subscription info
sc.get()->insert_dnn_subscription(snssai, subscription);
} else {
// Cannot retrieve information from UDM, reject PDU session establishment
Logger::smf_app().warn(
"Received PDU_SESSION_CREATESMCONTEXT_REQUEST, couldn't retrieve the Session Management Subscription from UDM, ignore message!");
problem_details.setCause(
pdu_session_application_error_e2str[PDU_SESSION_APPLICATION_ERROR_SUBSCRIPTION_DENIED]);
smContextCreateError.setError(problem_details);
refToBinaryData.setContentId(N1_SM_CONTENT_ID);
smContextCreateError.setN1SmMsg(refToBinaryData);
//PDU Session Establishment Reject, with cause "29 User authentication or authorization failed"
smf_n1_n2_inst.create_n1_sm_container(
smreq->req,
PDU_SESSION_ESTABLISHMENT_REJECT,
n1_sm_message,
cause_value_5gsm_e::CAUSE_29_USER_AUTHENTICATION_OR_AUTHORIZATION_FAILED);
smf_app_inst->convert_string_2_hex(n1_sm_message, n1_sm_message_hex);
//Send response (PDU Session Establishment Reject) to AMF
smf_n11_inst->send_pdu_session_create_sm_context_response(
smreq->http_response, smContextCreateError,
Pistache::Http::Code::Forbidden, n1_sm_message_hex);
return;
}
} else {
// Cannot retrieve information from UDM, reject PDU session establishment
Logger::smf_app().warn(
"Received PDU_SESSION_CREATESMCONTEXT_REQUEST, couldn't retrieve the Session Management Subscription from UDM, ignore message!");
problem_details.setCause(
pdu_session_application_error_e2str[PDU_SESSION_APPLICATION_ERROR_SUBSCRIPTION_DENIED]);
smContextCreateError.setError(problem_details);
refToBinaryData.setContentId(N1_SM_CONTENT_ID);
smContextCreateError.setN1SmMsg(refToBinaryData);
//PDU Session Establishment Reject, with cause "29 User authentication or authorization failed"
smf_n1_n2_inst.create_n1_sm_container(
smreq->req,
PDU_SESSION_ESTABLISHMENT_REJECT,
n1_sm_message,
cause_value_5gsm_e::CAUSE_29_USER_AUTHENTICATION_OR_AUTHORIZATION_FAILED);
smf_app_inst->convert_string_2_hex(n1_sm_message, n1_sm_message_hex);
//Send response (PDU Session Establishment Reject) to AMF
smf_n11_inst->send_pdu_session_create_sm_context_response(
smreq->http_response, smContextCreateError,
Pistache::Http::Code::Forbidden, n1_sm_message_hex);
return;
//use local configuration
Logger::smf_app().debug(
"Retrieve Session Management Subscription data from local configuration");
if (get_session_management_subscription_data(supi64, dnn, snssai,
subscription)) {
//update dnn_context with subscription info
sc.get()->insert_dnn_subscription(snssai, subscription);
}
}
}
......@@ -916,10 +947,10 @@ void smf_app::handle_pdu_session_release_sm_context_request(
}
//------------------------------------------------------------------------------
void smf_app::trigger_pdu_session_modification(supi_t &supi, std::string &dnn,
pdu_session_id_t pdu_session_id,
snssai_t &snssai,
pfcp::qfi_t &qfi) {
void smf_app::trigger_pdu_session_modification(const supi_t &supi, const std::string &dnn,
const pdu_session_id_t pdu_session_id,
const snssai_t &snssai,
const pfcp::qfi_t &qfi) {
//SMF-requested session modification, see section 4.3.3.2@3GPP TS 23.502
//The SMF may decide to modify PDU Session. This procedure also may be
//triggered based on locally configured policy or triggered from the (R)AN (see clause 4.2.6 and clause 4.9.1).
......@@ -1025,26 +1056,26 @@ bool smf_app::scid_2_smf_context(const scid_t &scid,
bool smf_app::use_local_configuration_subscription_data(
const std::string &dnn_selection_mode) {
//TODO: should be implemented
return false; //get Session Management Subscription from UDM
return smf_cfg.local_configuration;
}
//------------------------------------------------------------------------------
bool smf_app::is_supi_dnn_snssai_subscription_data(supi_t &supi,
std::string &dnn,
snssai_t &snssai) {
bool smf_app::is_supi_dnn_snssai_subscription_data(const supi_t &supi,
const std::string &dnn,
const snssai_t &snssai) const {
//TODO: should be implemented
return false; //Session Management Subscription from UDM isn't available
}
//------------------------------------------------------------------------------
bool smf_app::is_create_sm_context_request_valid() {
bool smf_app::is_create_sm_context_request_valid() const {
//TODO: should be implemented
return true;
}
//---------------------------------------------------------------------------------------------
void smf_app::convert_string_2_hex(std::string &input_str,
void smf_app::convert_string_2_hex(const std::string &input_str,
std::string &output_str) {
Logger::smf_app().debug("Convert string to Hex");
unsigned char *data = (unsigned char*) malloc(input_str.length() + 1);
......@@ -1074,7 +1105,7 @@ void smf_app::convert_string_2_hex(std::string &input_str,
}
//---------------------------------------------------------------------------------------------
unsigned char* smf_app::format_string_as_hex(std::string &str) {
unsigned char* smf_app::format_string_as_hex(const std::string &str) {
unsigned int str_len = str.length();
char *data = (char*) malloc(str_len + 1);
memset(data, 0, str_len + 1);
......@@ -1214,7 +1245,7 @@ void smf_app::timer_t3591_timeout(timer_id_t timer_id, uint64_t arg2_user) {
}
//---------------------------------------------------------------------------------------------
n2_sm_info_type_e smf_app::n2_sm_info_type_str2e(std::string &n2_info_type) {
n2_sm_info_type_e smf_app::n2_sm_info_type_str2e(const std::string &n2_info_type) const {
std::size_t number_of_types = n2_sm_info_type_e2str.size();
for (auto i = 0; i < number_of_types; ++i) {
if (n2_info_type.compare(n2_sm_info_type_e2str[i]) == 0) {
......@@ -1223,3 +1254,74 @@ n2_sm_info_type_e smf_app::n2_sm_info_type_str2e(std::string &n2_info_type) {
}
}
bool smf_app::get_session_management_subscription_data(
const supi64_t &supi, const std::string &dnn, const snssai_t &snssai,
std::shared_ptr<session_management_subscription> subscription) {
Logger::smf_app().debug(
"Get Session Management Subscription from configuration file");
for (int i = 0; i < smf_cfg.num_session_management_subscription; i++) {
if ((0 == dnn.compare(smf_cfg.session_management_subscription[i].dnn))
and (snssai.sST
== smf_cfg.session_management_subscription[i].single_nssai.sST)) {
std::shared_ptr<dnn_configuration_t> dnn_configuration = std::make_shared<
dnn_configuration_t>();
//PDU Session Type
pdu_session_type_t pdu_session_type(
pdu_session_type_e::PDU_SESSION_TYPE_E_IPV4);
Logger::smf_app().debug(
"Default session type %s",
smf_cfg.session_management_subscription[i].session_type.c_str());
if (smf_cfg.session_management_subscription[i].session_type.compare(
"IPV4") == 0) {
pdu_session_type.pdu_session_type =
pdu_session_type_e::PDU_SESSION_TYPE_E_IPV4;
} else if (smf_cfg.session_management_subscription[i].session_type.compare(
"IPV6") == 0) {
pdu_session_type.pdu_session_type =
pdu_session_type_e::PDU_SESSION_TYPE_E_IPV6;
} else if (smf_cfg.session_management_subscription[i].session_type.compare(
"IPV4V6") == 0) {
pdu_session_type.pdu_session_type =
pdu_session_type_e::PDU_SESSION_TYPE_E_IPV4V6;
}
dnn_configuration->pdu_session_types.default_session_type =
pdu_session_type;
//Ssc_Mode
dnn_configuration->ssc_modes.default_ssc_mode.ssc_mode = smf_cfg
.session_management_subscription[i].ssc_mode;
//5gQosProfile
dnn_configuration->_5g_qos_profile._5qi = smf_cfg
.session_management_subscription[i].default_qos._5qi;
dnn_configuration->_5g_qos_profile.arp.priority_level = smf_cfg
.session_management_subscription[i].default_qos.priority_level;
dnn_configuration->_5g_qos_profile.arp.preempt_cap = smf_cfg
.session_management_subscription[i].default_qos.arp.preempt_cap;
dnn_configuration->_5g_qos_profile.arp.preempt_vuln = smf_cfg
.session_management_subscription[i].default_qos.arp.preempt_vuln;
dnn_configuration->_5g_qos_profile.priority_level = 1; //TODO: hardcoded
//session_ambr
dnn_configuration->session_ambr.uplink = smf_cfg
.session_management_subscription[i].session_ambr.uplink;
dnn_configuration->session_ambr.downlink = smf_cfg
.session_management_subscription[i].session_ambr.downlink;
Logger::smf_app().debug("Session AMBR Uplink %s, Downlink %s",
dnn_configuration->session_ambr.uplink.c_str(),
dnn_configuration->session_ambr.downlink.c_str());
subscription->insert_dnn_configuration(dnn, dnn_configuration);
return true;
}
}
return false;
}
......@@ -115,7 +115,7 @@ class smf_app {
mutable std::shared_mutex m_scid2smf_context;
/*
* Apply the config from the configuration file for APN pools
* Apply the config from the configuration file for DNN pools
* @param [const smf_config &cfg] cfg
* @return
*/
......@@ -392,16 +392,16 @@ class smf_app {
/*
* Trigger pdu session modification
* @param [supi_t &] supi
* @param [std::string &] dnn
* @param [pdu_session_id_t] pdu_session_id
* @param [snssai_t &] snssai
* @param [pfcp::qfi_t &] qfi
* @param [const supi_t &] supi
* @param [const std::string &] dnn
* @param [const pdu_session_id_t] pdu_session_id
* @param [const snssai_t &] snssai
* @param [const pfcp::qfi_t &] qfi
* @return void
*/
void trigger_pdu_session_modification(supi_t &supi, std::string &dnn,
pdu_session_id_t pdu_session_id,
snssai_t &snssai, pfcp::qfi_t &qfi);
void trigger_pdu_session_modification(const supi_t &supi, const std::string &dnn,
const pdu_session_id_t pdu_session_id,
const snssai_t &snssai, const pfcp::qfi_t &qfi);
/*
* Verify if SM Context is existed for this Supi
......@@ -412,7 +412,7 @@ class smf_app {
/*
* Create/Update SMF context with the corresponding supi
* @param [supi_t] supi
* @param [const supi_t&] supi
* @param [std::shared_ptr<smf_context>] sc Shared_ptr Pointer to an SMF context
* @return True if existed, otherwise false
*/
......@@ -428,7 +428,7 @@ class smf_app {
/*
* Check whether SMF uses local configuration instead of retrieving Session Management Data from UDM
* @param [std::string] dnn_selection_mode
* @param [const std::string&] dnn_selection_mode
* @return True if SMF uses the local configuration to check the validity of the UE request, False otherwise
*/
bool use_local_configuration_subscription_data(
......@@ -436,36 +436,49 @@ class smf_app {
/*
* Verify whether the Session Management Data is existed
* @param [supi_t] SUPI
* @param [std::string] DNN
* @param [snssai_t] S-NSSAI
* @param [const supi_t&] SUPI
* @param [const std::string&] DNN
* @param [const snssai_t&] S-NSSAI
* @return True if SMF uses the local configuration to check the validity of the UE request, False otherwise
*/
bool is_supi_dnn_snssai_subscription_data(supi_t &supi, std::string &dnn,
snssai_t &snssai);
bool is_supi_dnn_snssai_subscription_data(const supi_t &supi,
const std::string &dnn,
const snssai_t &snssai) const;
/*
* Get the Session Management Subscription data from local configuration
* @param [const supi_t &] SUPI
* @param [const std::string &] DNN
* @param [const snssai_t &] S-NSSAI
* @param [std::shared_ptr<session_management_subscription>] subscription: store subscription data if exist
* @return True if local configuration for this session management subscription exists, False otherwise
*/
bool get_session_management_subscription_data(
const supi64_t &supi, const std::string &dnn, const snssai_t &snssai,
std::shared_ptr<session_management_subscription> subscription);
/*
* Verify whether the UE request is valid according to the user subscription and with local policies
* @param [..]
* @return True if the request is valid, otherwise False
*/
bool is_create_sm_context_request_valid();
bool is_create_sm_context_request_valid() const;
/*
* Convert a string to hex representing this string
* @param [std::string&] input_str Input string
* @param [const std::string&] input_str Input string
* @param [std::string&] output_str String represents string in hex format
* @return void
*/
void convert_string_2_hex(std::string &input_str, std::string &output_str);
void convert_string_2_hex(const std::string &input_str,
std::string &output_str);
/*
* Represent a string as hex
* @param [std::string&] str: input string
* @param [std::string&] output_str String represents string in hex format
* @return void
* @param [const std::string&] str: input string
* @return String represents string in hex format
*/
unsigned char* format_string_as_hex(std::string &str);
unsigned char* format_string_as_hex(const std::string &str);
/*
* Update PDU session status
......@@ -478,10 +491,10 @@ class smf_app {
/*
* Convert N2 Info type representing by a string to n2_sm_info_type_e
* @param [std::string] n2_info_type
* @param [const std::string] n2_info_type
* @return representing of N2 info type in a form of emum
*/
n2_sm_info_type_e n2_sm_info_type_str2e(std::string &n2_info_type);
n2_sm_info_type_e n2_sm_info_type_str2e(const std::string &n2_info_type) const;
/*
* Update PDU session UpCnxState
......
......@@ -406,66 +406,66 @@ int smf_config::load(const string &config_file) {
num_paa6_pool += 1;
}
const Setting &apn_list_cfg = smf_cfg[SMF_CONFIG_STRING_APN_LIST];
count = apn_list_cfg.getLength();
int apn_idx = 0;
num_apn = 0;
const Setting &dnn_list_cfg = smf_cfg[SMF_CONFIG_STRING_DNN_LIST];
count = dnn_list_cfg.getLength();
int dnn_idx = 0;
num_dnn = 0;
for (int i = 0; i < count; i++) {
const Setting &apn_cfg = apn_list_cfg[i];
apn_cfg.lookupValue(SMF_CONFIG_STRING_APN_NI, astring);
apn[apn_idx].apn = astring;
apn[apn_idx].apn_label = EPC::Utility::apn_label(astring);
apn_cfg.lookupValue(SMF_CONFIG_STRING_PDN_TYPE, astring);
const Setting &dnn_cfg = dnn_list_cfg[i];
dnn_cfg.lookupValue(SMF_CONFIG_STRING_DNN_NI, astring);
dnn[dnn_idx].dnn = astring;
dnn[dnn_idx].dnn_label = EPC::Utility::dnn_label(astring);
dnn_cfg.lookupValue(SMF_CONFIG_STRING_PDN_TYPE, astring);
if (boost::iequals(astring, "IPv4")) {
apn[apn_idx].pdn_type.pdn_type = PDN_TYPE_E_IPV4;
dnn[dnn_idx].pdn_type.pdn_type = PDN_TYPE_E_IPV4;
} else if (boost::iequals(astring, "IPv6") == 0) {
apn[apn_idx].pdn_type.pdn_type = PDN_TYPE_E_IPV6;
dnn[dnn_idx].pdn_type.pdn_type = PDN_TYPE_E_IPV6;
} else if (boost::iequals(astring, "IPv4IPv6") == 0) {
apn[apn_idx].pdn_type.pdn_type = PDN_TYPE_E_IPV4V6;
dnn[dnn_idx].pdn_type.pdn_type = PDN_TYPE_E_IPV4V6;
} else if (boost::iequals(astring, "Non-IP") == 0) {
apn[apn_idx].pdn_type.pdn_type = PDN_TYPE_E_NON_IP;
dnn[dnn_idx].pdn_type.pdn_type = PDN_TYPE_E_NON_IP;
} else {
Logger::smf_app().error(
" " SMF_CONFIG_STRING_PDN_TYPE " in %d'th APN :%s", i + 1,
" " SMF_CONFIG_STRING_PDN_TYPE " in %d'th DNN :%s", i + 1,
astring.c_str());
throw("Error PDN_TYPE in config file");
}
apn_cfg.lookupValue(SMF_CONFIG_STRING_IPV4_POOL,
apn[apn_idx].pool_id_iv4);
apn_cfg.lookupValue(SMF_CONFIG_STRING_IPV6_POOL,
apn[apn_idx].pool_id_iv6);
dnn_cfg.lookupValue(SMF_CONFIG_STRING_IPV4_POOL,
dnn[dnn_idx].pool_id_iv4);
dnn_cfg.lookupValue(SMF_CONFIG_STRING_IPV6_POOL,
dnn[dnn_idx].pool_id_iv6);
if ((0 <= apn[apn_idx].pool_id_iv4)
&& (apn[apn_idx].pdn_type.pdn_type == PDN_TYPE_E_IPV6)) {
if ((0 <= dnn[dnn_idx].pool_id_iv4)
&& (dnn[dnn_idx].pdn_type.pdn_type == PDN_TYPE_E_IPV6)) {
Logger::smf_app().error(
"PDN_TYPE versus pool identifier %d 'th APN in config file", i + 1);
throw("PDN_TYPE versus pool identifier APN");
"PDN_TYPE versus pool identifier %d 'th DNN in config file", i + 1);
throw("PDN_TYPE versus pool identifier DNN");
}
if ((0 <= apn[apn_idx].pool_id_iv6)
&& (apn[apn_idx].pdn_type.pdn_type == PDN_TYPE_E_IPV4)) {
if ((0 <= dnn[dnn_idx].pool_id_iv6)
&& (dnn[dnn_idx].pdn_type.pdn_type == PDN_TYPE_E_IPV4)) {
Logger::smf_app().error(
"PDN_TYPE versus pool identifier %d 'th APN in config file", i + 1);
throw("PDN_TYPE versus pool identifier APN");
"PDN_TYPE versus pool identifier %d 'th DNN in config file", i + 1);
throw("PDN_TYPE versus pool identifier DNN");
}
if (((0 <= apn[apn_idx].pool_id_iv4) || (0 <= apn[apn_idx].pool_id_iv6))
&& (not boost::iequals(apn[apn_idx].apn, "none"))) {
if (((0 <= dnn[dnn_idx].pool_id_iv4) || (0 <= dnn[dnn_idx].pool_id_iv6))
&& (not boost::iequals(dnn[dnn_idx].dnn, "none"))) {
bool doublon = false;
for (int j = 0; j < apn_idx; j++) {
if (boost::iequals(apn[j].apn, apn[apn_idx].apn)) {
for (int j = 0; j < dnn_idx; j++) {
if (boost::iequals(dnn[j].dnn, dnn[dnn_idx].dnn)) {
doublon = true;
Logger::smf_app().info(
"%d'th APN %s already found in config file (%d 'th APN %s), bypassing",
i + 1, apn[apn_idx].apn.c_str(), j + 1, apn[j].apn.c_str());
"%d'th dnn %s already found in config file (%d 'th DNN %s), bypassing",
i + 1, dnn[dnn_idx].dnn.c_str(), j + 1, dnn[j].dnn.c_str());
}
}
if (not doublon) {
apn_idx++;
num_apn++;
dnn_idx++;
num_dnn++;
}
} else {
Logger::smf_app().error("Bypass %d'th APN %s in config file", i + 1,
apn[apn_idx].apn.c_str());
Logger::smf_app().error("Bypass %d'th DNN %s in config file", i + 1,
dnn[dnn_idx].dnn.c_str());
}
}
smf_cfg.lookupValue(SMF_CONFIG_STRING_DEFAULT_DNS_IPV4_ADDRESS, astring);
......@@ -559,6 +559,95 @@ int smf_config::load(const string &config_file) {
.c_str());
}
}
//Local configuration
num_session_management_subscription = 0;
const Setting &local_cfg = smf_cfg[SMF_CONFIG_STRING_LOCAL_CONFIGURATION];
string local_configuration_str = { };
local_cfg.lookupValue(SMF_CONFIG_STRING_USE_LOCAL_CONFIGURATION,
local_configuration_str);
if (boost::iequals(local_configuration_str, "yes")) {
local_configuration = true;
} else {
local_configuration = false;
}
const Setting &session_management_subscription_list_cfg =
local_cfg[SMF_CONFIG_STRING_SESSION_MANAGEMENT_SUBSCRIPTION_LIST];
count = session_management_subscription_list_cfg.getLength();
for (int i = 0; i < count; i++) {
const Setting &session_management_subscription_cfg =
session_management_subscription_list_cfg[i];
unsigned int nssai_sst = 0;
string nssai_sd = { };
string dnn = { };
string default_session_type = { };
unsigned int default_ssc_mode = 0;
unsigned int qos_profile_5qi = 0;
unsigned int qos_profile_priority_level = 0;
unsigned int qos_profile_arp_priority_level = 0;
string qos_profile_arp_preemptcap = { };
string qos_profile_arp_preemptvuln = { };
string session_ambr_ul = { };
string session_ambr_dl = { };
session_management_subscription_cfg.lookupValue(
SMF_CONFIG_STRING_NSSAI_SST,
nssai_sst);
session_management_subscription_cfg.lookupValue(
SMF_CONFIG_STRING_NSSAI_SD,
nssai_sd);
session_management_subscription_cfg.lookupValue(SMF_CONFIG_STRING_DNN,
dnn);
session_management_subscription_cfg.lookupValue(
SMF_CONFIG_STRING_DEFAULT_SESSION_TYPE,
default_session_type);
session_management_subscription_cfg.lookupValue(
SMF_CONFIG_STRING_DEFAULT_SSC_MODE,
default_ssc_mode);
session_management_subscription_cfg.lookupValue(
SMF_CONFIG_STRING_QOS_PROFILE_5QI,
qos_profile_5qi);
session_management_subscription_cfg.lookupValue(
SMF_CONFIG_STRING_QOS_PROFILE_PRIORITY_LEVEL,
qos_profile_priority_level);
session_management_subscription_cfg.lookupValue(
SMF_CONFIG_STRING_QOS_PROFILE_ARP_PRIORITY_LEVEL,
qos_profile_arp_priority_level);
session_management_subscription_cfg.lookupValue(
SMF_CONFIG_STRING_QOS_PROFILE_ARP_PREEMPTCAP,
qos_profile_arp_preemptcap);
session_management_subscription_cfg.lookupValue(
SMF_CONFIG_STRING_QOS_PROFILE_ARP_PREEMPTVULN,
qos_profile_arp_preemptvuln);
session_management_subscription_cfg.lookupValue(
SMF_CONFIG_STRING_SESSION_AMBR_UL,
session_ambr_ul);
session_management_subscription_cfg.lookupValue(
SMF_CONFIG_STRING_SESSION_AMBR_DL,
session_ambr_dl);
session_management_subscription[i].single_nssai.sST = nssai_sst;
session_management_subscription[i].single_nssai.sD = nssai_sd;
session_management_subscription[i].session_type = default_session_type;
session_management_subscription[i].dnn = dnn;
session_management_subscription[i].ssc_mode = default_ssc_mode;
session_management_subscription[i].default_qos._5qi = qos_profile_5qi;
session_management_subscription[i].default_qos.priority_level =
qos_profile_priority_level;
session_management_subscription[i].default_qos.arp.priority_level =
qos_profile_arp_priority_level;
session_management_subscription[i].default_qos.arp.preempt_cap =
qos_profile_arp_preemptcap;
session_management_subscription[i].default_qos.arp.preempt_vuln =
qos_profile_arp_preemptvuln;
session_management_subscription[i].session_ambr.downlink =
session_ambr_dl;
session_management_subscription[i].session_ambr.uplink = session_ambr_ul;
num_session_management_subscription++;
}
} catch (const SettingNotFoundException &nfex) {
Logger::smf_app().error("%s : %s", nfex.what(), nfex.getPath());
return RETURNerror ;
......@@ -623,8 +712,8 @@ void smf_config::display() {
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[apn[i].pool_id_iv4]));
std::string range_high(inet_ntoa(ue_pool_range_high[apn[i].pool_id_iv4]));
std::string range_low(inet_ntoa(ue_pool_range_low[dnn[i].pool_id_iv4]));
std::string range_high(inet_ntoa(ue_pool_range_high[dnn[i].pool_id_iv4]));
Logger::smf_app().info(" IPv4 pool %d ..........: %s - %s", i,
range_low.c_str(), range_high.c_str());
}
......@@ -648,23 +737,23 @@ void smf_config::display() {
Logger::smf_app().info(" Secondary DNS v6 .....: %s", str_addr6);
}
Logger::smf_app().info("- " SMF_CONFIG_STRING_APN_LIST ":");
for (int i = 0; i < num_apn; i++) {
Logger::smf_app().info(" APN %d:", i);
Logger::smf_app().info(" " SMF_CONFIG_STRING_APN_NI ": %s",
apn[i].apn.c_str());
Logger::smf_app().info("- " SMF_CONFIG_STRING_DNN_LIST ":");
for (int i = 0; i < num_dnn; i++) {
Logger::smf_app().info(" DNN %d:", i);
Logger::smf_app().info(" " SMF_CONFIG_STRING_DNN_NI ": %s",
dnn[i].dnn.c_str());
Logger::smf_app().info(" " SMF_CONFIG_STRING_PDN_TYPE ": %s",
apn[i].pdn_type.toString().c_str());
if (apn[i].pool_id_iv4 >= 0) {
std::string range_low(inet_ntoa(ue_pool_range_low[apn[i].pool_id_iv4]));
std::string range_high(inet_ntoa(ue_pool_range_high[apn[i].pool_id_iv4]));
dnn[i].pdn_type.toString().c_str());
if (dnn[i].pool_id_iv4 >= 0) {
std::string range_low(inet_ntoa(ue_pool_range_low[dnn[i].pool_id_iv4]));
std::string range_high(inet_ntoa(ue_pool_range_high[dnn[i].pool_id_iv4]));
Logger::smf_app().info(
" " SMF_CONFIG_STRING_IPV4_POOL ": %d ( %s - %s)",
apn[i].pool_id_iv4, range_low.c_str(), range_high.c_str());
dnn[i].pool_id_iv4, range_low.c_str(), range_high.c_str());
}
if (apn[i].pool_id_iv6 >= 0) {
if (dnn[i].pool_id_iv6 >= 0) {
Logger::smf_app().info(" " SMF_CONFIG_STRING_IPV6_POOL ": %d",
apn[i].pool_id_iv6);
dnn[i].pool_id_iv6);
}
}
......@@ -686,15 +775,56 @@ void smf_config::display() {
" Gnb Address ..........: %s",
inet_ntoa(*((struct in_addr*) &test_upf_cfg.gnb_addr4)));
if (local_configuration) {
Logger::smf_app().info(
"- " SMF_CONFIG_STRING_SESSION_MANAGEMENT_SUBSCRIPTION_LIST ":");
for (int i = 0; i < num_session_management_subscription; i++) {
Logger::smf_app().info(" Session Management Subscription Data %d:", i);
Logger::smf_app().info(
" " SMF_CONFIG_STRING_NSSAI_SST ": %d, " SMF_CONFIG_STRING_NSSAI_SD " %s",
session_management_subscription[i].single_nssai.sST,
session_management_subscription[i].single_nssai.sD.c_str());
Logger::smf_app().info(" " SMF_CONFIG_STRING_DNN ": %s",
session_management_subscription[i].dnn.c_str());
Logger::smf_app().info(
" " SMF_CONFIG_STRING_DEFAULT_SESSION_TYPE ": %s",
session_management_subscription[i].session_type.c_str());
Logger::smf_app().info(
" " SMF_CONFIG_STRING_DEFAULT_SSC_MODE ": %d",
session_management_subscription[i].ssc_mode);
Logger::smf_app().info(
" " SMF_CONFIG_STRING_QOS_PROFILE_5QI ": %d",
session_management_subscription[i].default_qos._5qi);
Logger::smf_app().info(
" " SMF_CONFIG_STRING_QOS_PROFILE_PRIORITY_LEVEL ": %d",
session_management_subscription[i].default_qos.priority_level);
Logger::smf_app().info(
" " SMF_CONFIG_STRING_QOS_PROFILE_ARP_PRIORITY_LEVEL ": %d",
session_management_subscription[i].default_qos.arp.priority_level);
Logger::smf_app().info(
" " SMF_CONFIG_STRING_QOS_PROFILE_ARP_PREEMPTCAP ": %s",
session_management_subscription[i].default_qos.arp.preempt_cap.c_str());
Logger::smf_app().info(
" " SMF_CONFIG_STRING_QOS_PROFILE_ARP_PREEMPTVULN ": %s",
session_management_subscription[i].default_qos.arp.preempt_vuln.c_str());
Logger::smf_app().info(
" " SMF_CONFIG_STRING_SESSION_AMBR_UL ": %s",
session_management_subscription[i].session_ambr.uplink.c_str());
Logger::smf_app().info(
" " SMF_CONFIG_STRING_SESSION_AMBR_DL ": %s",
session_management_subscription[i].session_ambr.downlink.c_str());
}
}
}
//------------------------------------------------------------------------------
bool smf_config::is_dotted_apn_handled(const string &apn,
bool smf_config::is_dotted_dnn_handled(const string &dnn,
const pdn_type_t &pdn_type) {
for (int i = 0; i < smf_cfg.num_apn; i++) {
if (0 == apn.compare(smf_cfg.apn[i].apn_label)) {
for (int i = 0; i < smf_cfg.num_dnn; i++) {
if (0 == dnn.compare(smf_cfg.dnn[i].dnn_label)) {
// TODO refine
if (pdn_type.pdn_type == smf_cfg.apn[i].pdn_type.pdn_type) {
if (pdn_type.pdn_type == smf_cfg.dnn[i].pdn_type.pdn_type) {
return true;
}
}
......@@ -744,18 +874,18 @@ smf_config::~smf_config() {
bool smf_config::is_dotted_dnn_handled(
const std::string &dnn, const pdu_session_type_t &pdn_session_type) {
Logger::smf_app().debug("Requested DNN: %s", dnn.c_str());
for (int i = 0; i < smf_cfg.num_apn; i++) {
for (int i = 0; i < smf_cfg.num_dnn; i++) {
Logger::smf_app().debug("DNN label: %s, dnn: %s",
smf_cfg.apn[i].apn_label.c_str(),
smf_cfg.apn[i].apn.c_str());
//if (0 == dnn.compare(smf_cfg.apn[i].apn_label)) {
if (0 == dnn.compare(smf_cfg.apn[i].apn)) {
smf_cfg.dnn[i].dnn_label.c_str(),
smf_cfg.dnn[i].dnn.c_str());
//if (0 == dnn.compare(smf_cfg.dnn[i].dnn_label)) {
if (0 == dnn.compare(smf_cfg.dnn[i].dnn)) {
Logger::smf_app().debug("DNN matched!");
Logger::smf_app().debug("PDU Session Type %d, PDN Type %d",
pdn_session_type.pdu_session_type,
smf_cfg.apn[i].pdn_type.pdn_type);
smf_cfg.dnn[i].pdn_type.pdn_type);
if (pdn_session_type.pdu_session_type
== smf_cfg.apn[i].pdn_type.pdn_type) {
== smf_cfg.dnn[i].pdn_type.pdn_type) {
return true;
}
}
......@@ -765,7 +895,7 @@ bool smf_config::is_dotted_dnn_handled(
//------------------------------------------------------------------------------
std::string smf_config::get_default_dnn() {
Logger::smf_app().debug("Default DNN: %s", smf_cfg.apn[0].apn.c_str());
return smf_cfg.apn[0].apn;
Logger::smf_app().debug("Default DNN: %s", smf_cfg.dnn[0].dnn.c_str());
return smf_cfg.dnn[0].dnn;
}
......@@ -55,8 +55,6 @@
#define SMF_CONFIG_STRING_INTERFACE_N4 "N4"
#define SMF_CONFIG_STRING_INTERFACE_SBI "SBI"
#define SMF_CONFIG_STRING_SMF_MASQUERADE_SGI "PGW_MASQUERADE_SGI"
#define SMF_CONFIG_STRING_UE_TCP_MSS_CLAMPING "UE_TCP_MSS_CLAMPING"
#define SMF_CONFIG_STRING_NAS_FORCE_PUSH_PCO "FORCE_PUSH_PROTOCOL_CONFIGURATION_OPTIONS"
#define SMF_CONFIG_STRING_IP_ADDRESS_POOL "IP_ADDRESS_POOL"
......@@ -79,18 +77,15 @@
#define SMF_CONFIG_STRING_INTERFACE_DISABLED "none"
#define SMF_CONFIG_STRING_APN_LIST "APN_LIST"
#define SMF_CONFIG_STRING_APN_NI "APN_NI"
#define SMF_CONFIG_STRING_DNN_LIST "DNN_LIST"
#define SMF_CONFIG_STRING_DNN_NI "DNN_NI"
#define SMF_CONFIG_STRING_PDN_TYPE "PDN_TYPE"
#define SMF_CONFIG_STRING_IPV4_POOL "IPV4_POOL"
#define SMF_CONFIG_STRING_IPV6_POOL "IPV6_POOL"
#define SMF_CONFIG_STRING_TCP_ECN_ENABLED "TCP_ECN_ENABLED"
#define SMF_CONFIG_STRING_AUTOMATIC_PUSH_DEDICATED_BEARER_PCC_RULE "AUTOMATIC_PUSH_DEDICATED_BEARER_PCC_RULE"
#define SMF_CONFIG_STRING_DEFAULT_BEARER_STATIC_PCC_RULE "DEFAULT_BEARER_STATIC_PCC_RULE"
#define SMF_CONFIG_STRING_PUSH_STATIC_PCC_RULES "PUSH_STATIC_PCC_RULES"
#define SMF_CONFIG_STRING_APN_AMBR_UL "APN_AMBR_UL"
#define SMF_CONFIG_STRING_APN_AMBR_DL "APN_AMBR_DL"
#define SMF_ABORT_ON_ERROR true
#define SMF_WARN_ON_ERROR false
......@@ -121,7 +116,23 @@
#define SMF_CONFIG_STRING_UPF_LIST "UPF_LIST"
#define SMF_CONFIG_STRING_UPF_IPV4_ADDRESS "IPV4_ADDRESS"
#define PGW_MAX_ALLOCATED_PDN_ADDRESSES 1024
#define SMF_CONFIG_STRING_LOCAL_CONFIGURATION "LOCAL_CONFIGURATION"
#define SMF_CONFIG_STRING_USE_LOCAL_CONFIGURATION "USE_LOCAL_CONFIGURATION"
#define SMF_CONFIG_STRING_SESSION_MANAGEMENT_SUBSCRIPTION_LIST "SESSION_MANAGEMENT_SUBSCRIPTION_LIST"
#define SMF_CONFIG_STRING_NSSAI_SST "NSSAI_SST"
#define SMF_CONFIG_STRING_NSSAI_SD "NSSAI_SD"
#define SMF_CONFIG_STRING_DNN "DNN"
#define SMF_CONFIG_STRING_DEFAULT_SESSION_TYPE "DEFAULT_SESSION_TYPE"
#define SMF_CONFIG_STRING_DEFAULT_SSC_MODE "DEFAULT_SSC_MODE"
#define SMF_CONFIG_STRING_QOS_PROFILE_5QI "QOS_PROFILE_5QI"
#define SMF_CONFIG_STRING_QOS_PROFILE_PRIORITY_LEVEL "QOS_PROFILE_PRIORITY_LEVEL"
#define SMF_CONFIG_STRING_QOS_PROFILE_ARP_PRIORITY_LEVEL "QOS_PROFILE_ARP_PRIORITY_LEVEL"
#define SMF_CONFIG_STRING_QOS_PROFILE_ARP_PREEMPTCAP "QOS_PROFILE_ARP_PREEMPTCAP"
#define SMF_CONFIG_STRING_QOS_PROFILE_ARP_PREEMPTVULN "QOS_PROFILE_ARP_PREEMPTVULN"
#define SMF_CONFIG_STRING_SESSION_AMBR_UL "SESSION_AMBR_UL"
#define SMF_CONFIG_STRING_SESSION_AMBR_DL "SESSION_AMBR_DL"
#define SMF_MAX_ALLOCATED_PDN_ADDRESSES 1024
namespace smf {
......@@ -172,29 +183,29 @@ class smf_config {
struct in6_addr default_dnsv6;
struct in6_addr default_dns_secv6;
#define PGW_NUM_APN_MAX 5
int num_apn;
#define SMF_NUM_DNN_MAX 5
int num_dnn;
struct {
std::string apn;
std::string apn_label;
std::string dnn;
std::string dnn_label;
int pool_id_iv4;
int pool_id_iv6;
pdn_type_t pdn_type;
} apn[PGW_NUM_APN_MAX];
} dnn[SMF_NUM_DNN_MAX];
int num_ue_pool;
#define PGW_NUM_UE_POOL_MAX 96
struct in_addr ue_pool_range_low[PGW_NUM_UE_POOL_MAX];
struct in_addr ue_pool_range_high[PGW_NUM_UE_POOL_MAX];
struct in_addr ue_pool_network[PGW_NUM_UE_POOL_MAX];
struct in_addr ue_pool_netmask[PGW_NUM_UE_POOL_MAX];
#define SMF_NUM_UE_POOL_MAX 96
struct in_addr ue_pool_range_low[SMF_NUM_UE_POOL_MAX];
struct in_addr ue_pool_range_high[SMF_NUM_UE_POOL_MAX];
struct in_addr ue_pool_network[SMF_NUM_UE_POOL_MAX];
struct in_addr ue_pool_netmask[SMF_NUM_UE_POOL_MAX];
//computed from config, UE IP adresses that matches ue_pool_network[]/ue_pool_netmask[] but do not match ue_pool_range_low[] - ue_pool_range_high[]
// The problem here is that OpenFlow do not deal with ip ranges but with netmasks
std::vector<struct in_addr> ue_pool_excluded[PGW_NUM_UE_POOL_MAX];
std::vector<struct in_addr> ue_pool_excluded[SMF_NUM_UE_POOL_MAX];
int num_paa6_pool;
struct in6_addr paa_pool6_prefix[PGW_NUM_UE_POOL_MAX];
uint8_t paa_pool6_prefix_len[PGW_NUM_UE_POOL_MAX];
struct in6_addr paa_pool6_prefix[SMF_NUM_UE_POOL_MAX];
uint8_t paa_pool6_prefix_len[SMF_NUM_UE_POOL_MAX];
bool force_push_pco;
uint ue_mtu;
......@@ -211,18 +222,31 @@ class smf_config {
std::vector<pfcp::node_id_t> upfs;
//Local configuration
bool local_configuration;
#define SMF_NUM_SESSION_MANAGEMENT_SUBSCRIPTION_MAX 5
struct {
snssai_t single_nssai;
std::string session_type;
std::string dnn;
uint8_t ssc_mode;
subscribed_default_qos_t default_qos;
session_ambr_t session_ambr;
} session_management_subscription[SMF_NUM_SESSION_MANAGEMENT_SUBSCRIPTION_MAX];
uint8_t num_session_management_subscription;
smf_config()
:
m_rw_lock(),
num_apn(0),
num_dnn(0),
pid_dir(),
instance(0),
n4(),
sbi(),
itti(),
upfs() {
for (int i = 0; i < PGW_NUM_APN_MAX; i++) {
apn[i] = { };
for (int i = 0; i < SMF_NUM_DNN_MAX; i++) {
dnn[i] = { };
}
default_dnsv4.s_addr = INADDR_ANY;
default_dns_secv4.s_addr = INADDR_ANY;
......@@ -231,7 +255,7 @@ class smf_config {
num_ue_pool = 0;
num_paa6_pool = 0;
for (int i = 0; i < PGW_NUM_UE_POOL_MAX; i++) {
for (int i = 0; i < SMF_NUM_UE_POOL_MAX; i++) {
ue_pool_range_low[i] = { };
ue_pool_range_high[i] = { };
ue_pool_network[i] = { };
......@@ -259,6 +283,9 @@ class smf_config {
amf_addr.ipv4_addr.s_addr = INADDR_ANY;
udm_addr.port = 80;
local_configuration = false;
num_session_management_subscription = 0;
}
;
~smf_config();
......@@ -273,11 +300,11 @@ class smf_config {
int load(const std::string &config_file);
int finalize();
void display();
bool is_dotted_apn_handled(const std::string &apn,
bool is_dotted_dnn_handled(const std::string &dnn,
const pdn_type_t &pdn_type);
int get_pfcp_node_id(pfcp::node_id_t &node_id);
int get_pfcp_fseid(pfcp::fseid_t &fseid);
bool is_dotted_dnn_handled(const std::string &apn,
bool is_dotted_dnn_handled(const std::string &dnn,
const pdu_session_type_t &pdn_session_type);
std::string get_default_dnn();
};
......
......@@ -43,11 +43,13 @@
#include "3gpp_29.502.h"
#include "3gpp_24.501.h"
#include "SmContextCreatedData.h"
#include "smf_pfcp_association.hpp"
extern "C" {
#include "Ngap_PDUSessionResourceSetupResponseTransfer.h"
#include "Ngap_PDUSessionResourceModifyResponseTransfer.h"
#include "Ngap_PDUSessionResourceReleaseResponseTransfer.h"
#include "Ngap_PDUSessionResourceSetupUnsuccessfulTransfer.h"
#include "Ngap_GTPTunnel.h"
#include "Ngap_AssociatedQosFlowItem.h"
#include "Ngap_QosFlowAddOrModifyResponseList.h"
......@@ -74,10 +76,12 @@ std::string smf_qos_flow::toString() const {
s.append("\tFQI:\t\t\t\t").append(std::to_string((uint8_t) qfi.qfi)).append(
"\n");
s.append("\tUL FTEID:\t\t").append(ul_fteid.toString()).append("\n");
s.append("\tDL FTEID:\t\t").append(dl_fteid.toString()).append("\n");
s.append("\tPDR ID UL:\t\t\t").append(std::to_string(pdr_id_ul.rule_id))
.append("\n");
s.append("\tPDR ID DL:\t\t\t").append(std::to_string(pdr_id_dl.rule_id))
.append("\n");
s.append("\tPrecedence:\t\t\t").append(std::to_string(precedence.precedence))
.append("\n");
if (far_id_ul.first) {
......@@ -269,7 +273,7 @@ void smf_pdu_session::remove_qos_flow(smf_qos_flow &flow) {
}
//------------------------------------------------------------------------------
void smf_pdu_session::deallocate_ressources(const std::string &apn) {
void smf_pdu_session::deallocate_ressources(const std::string &dnn) {
for (std::map<uint8_t, smf_qos_flow>::iterator it = qos_flows.begin();
it != qos_flows.end(); ++it) {
......@@ -281,7 +285,7 @@ void smf_pdu_session::deallocate_ressources(const std::string &apn) {
it->second.deallocate_ressources();
}
if (ipv4) {
paa_dynamic::get_instance().release_paa(apn, ipv4_address);
paa_dynamic::get_instance().release_paa(dnn, ipv4_address);
}
clear(); //including qos_flows.clear()
Logger::smf_app().info(
......@@ -290,8 +294,6 @@ void smf_pdu_session::deallocate_ressources(const std::string &apn) {
//------------------------------------------------------------------------------
void smf_pdu_session::generate_seid() {
// DO it simple now:
// seid = pgw_fteid_s5_s8_cp.teid_gre_key | (((uint64_t)smf_cfg.instance) << 32);
}
void smf_pdu_session::set_seid(const uint64_t &s) {
......@@ -335,6 +337,8 @@ void smf_pdu_session::release_qos_rule_id(const uint8_t &rule_id) {
//------------------------------------------------------------------------------
std::string smf_pdu_session::toString() const {
std::string s = { };
smf_qos_flow flow = { };
s.append("PDN CONNECTION:\n");
s.append("\tPDN type:\t\t\t").append(pdn_type.toString()).append("\n");
if (ipv4)
......@@ -343,9 +347,24 @@ std::string smf_pdu_session::toString() const {
if (ipv6)
s.append("\tPAA IPv6:\t\t\t").append(conv::toString(ipv6_address)).append(
"\n");
s.append("\tDefault QFI:\t\t\t").append(std::to_string(default_qfi.qfi))
.append("\n");
if (default_qfi.qfi) {
s.append("\tDefault QFI:\t\t\t").append(std::to_string(default_qfi.qfi))
.append("\n");
} else {
s.append("\tDefault QFI:\t\t\t").append("No QFI available").append("\n");
}
s.append("\tSEID:\t\t\t\t").append(std::to_string(seid)).append("\n");
if (default_qfi.qfi) {
s.append("Default ");
for (auto it : qos_flows) {
if (it.second.qfi == default_qfi.qfi) {
s.append(it.second.toString());
}
}
}
return s;
}
......@@ -415,7 +434,7 @@ bool smf_pdu_session::get_default_qos_rule(QOSRulesIE &qos_rule) const {
}
//------------------------------------------------------------------------------
bool smf_pdu_session::get_qos_rule(uint8_t rule_id,
bool smf_pdu_session::get_qos_rule(const uint8_t rule_id,
QOSRulesIE &qos_rule) const {
Logger::smf_app().info("Find QoS Rule with Rule Id %d", (uint8_t) rule_id);
if (qos_rules.count(rule_id) > 0) {
......@@ -437,23 +456,20 @@ void smf_pdu_session::update_qos_rule(const QOSRulesIE &qos_rule) {
qos_rules.insert(std::pair<uint8_t, QOSRulesIE>(rule_id, qos_rule));
//marked to be synchronised with UE
qos_rules_to_be_synchronised.push_back(rule_id);
Logger::smf_app().trace("smf_pdu_session::update_qos_rule(%d) success",
rule_id);
Logger::smf_app().trace("Update QoS rule (%d) success", rule_id);
} else {
Logger::smf_app().error(
"smf_pdu_session::update_qos_rule(%d) failed, rule does not existed",
rule_id);
"Update QoS Rule (%d) failed, rule does not existed", rule_id);
}
} else {
Logger::smf_app().error(
"smf_pdu_session::update_qos_rule(%d) failed, invalid Rule Id",
rule_id);
Logger::smf_app().error("Update QoS rule (%d) failed, invalid Rule Id",
rule_id);
}
}
//------------------------------------------------------------------------------
void smf_pdu_session::mark_qos_rule_to_be_synchronised(uint8_t rule_id) {
void smf_pdu_session::mark_qos_rule_to_be_synchronised(const uint8_t rule_id) {
if ((rule_id >= QOS_RULE_IDENTIFIER_FIRST )
and (rule_id <= QOS_RULE_IDENTIFIER_LAST )) {
......@@ -501,7 +517,8 @@ void smf_pdu_session::add_qos_rule(const QOSRulesIE &qos_rule) {
//------------------------------------------------------------------------------
void session_management_subscription::insert_dnn_configuration(
std::string dnn, std::shared_ptr<dnn_configuration_t> &dnn_configuration) {
const std::string &dnn,
std::shared_ptr<dnn_configuration_t> &dnn_configuration) {
dnn_configurations.insert(
std::pair<std::string, std::shared_ptr<dnn_configuration_t>>(
dnn, dnn_configuration));
......@@ -509,13 +526,24 @@ void session_management_subscription::insert_dnn_configuration(
//------------------------------------------------------------------------------
void session_management_subscription::find_dnn_configuration(
std::string dnn, std::shared_ptr<dnn_configuration_t> &dnn_configuration) {
const std::string &dnn,
std::shared_ptr<dnn_configuration_t> &dnn_configuration) const {
Logger::smf_app().info("Find DNN configuration with DNN %s", dnn.c_str());
if (dnn_configurations.count(dnn) > 0) {
dnn_configuration = dnn_configurations.at(dnn);
}
}
//------------------------------------------------------------------------------
bool session_management_subscription::dnn_configuration(
const std::string &dnn) const {
if (dnn_configurations.count(dnn) > 0) {
return true;
} else {
return false;
}
}
//------------------------------------------------------------------------------
void smf_context::insert_procedure(std::shared_ptr<smf_procedure> &sproc) {
std::unique_lock<std::recursive_mutex> lock(m_context);
......@@ -612,6 +640,156 @@ void smf_context::handle_itti_msg(itti_n4_session_deletion_response &sdresp) {
//------------------------------------------------------------------------------
void smf_context::handle_itti_msg(
std::shared_ptr<itti_n4_session_report_request> &req) {
pfcp::report_type_t report_type;
if (req->pfcp_ies.get(report_type)) {
pfcp::pdr_id_t pdr_id;
// Downlink Data Report
if (report_type.dldr) {
pfcp::downlink_data_report data_report;
if (req->pfcp_ies.get(data_report)) {
pfcp::pdr_id_t pdr_id;
if (data_report.get(pdr_id)) {
std::shared_ptr<dnn_context> sd = { };
std::shared_ptr<smf_pdu_session> sp = { };
pfcp::qfi_t qfi = { };
if (find_pdu_session(pdr_id, qfi, sd, sp)) {/*
downlink_data_report_procedure *proc =
new downlink_data_report_procedure(shared_from_this(), sp);
std::shared_ptr<smf_procedure> sproc =
std::shared_ptr<smf_procedure>(proc);
insert_procedure(sproc);
if (proc->run(pdr_id, qfi)) {
// error !
Logger::smf_app().info(
"Downlink Data Report Request procedure failed");
remove_procedure(proc);
}
*/
//Step 1. send N4 Data Report Ack to UPF
pfcp::node_id_t up_node_id = { };
if (not pfcp_associations::get_instance().select_up_node(
up_node_id, NODE_SELECTION_CRITERIA_MIN_PFCP_SESSIONS)) {
// TODO
Logger::smf_app().info("REMOTE_PEER_NOT_RESPONDING");
return;
}
itti_n4_session_report_response *n4_ser =
new itti_n4_session_report_response(TASK_SMF_APP, TASK_SMF_N4);
n4_ser->seid = req->seid;
n4_ser->trxn_id = req->trxn_id;
n4_ser->r_endpoint = endpoint(up_node_id.u1.ipv4_address,
pfcp::default_port);
std::shared_ptr<itti_n4_session_report_response> n4_report_ack =
std::shared_ptr<itti_n4_session_report_response>(n4_ser);
Logger::smf_app().info(
"Sending ITTI message %s to task TASK_SMF_N4",
n4_ser->get_msg_name());
int ret = itti_inst->send_msg(n4_report_ack);
if (RETURNok != ret) {
Logger::smf_app().error(
"Could not send ITTI message %s to task TASK_SMF_N4",
n4_ser->get_msg_name());
return;
}
//Step 2. Send N1N2MessageTranfer to AMF
pdu_session_report_response session_report_msg = { };
//set the required IEs
session_report_msg.set_supi(supi); //supi
session_report_msg.set_snssai(sd.get()->nssai); //s-nssai
session_report_msg.set_dnn(sd.get()->dnn_in_use); //dnn
session_report_msg.set_pdu_session_type(
sp.get()->get_pdn_type().pdn_type); //pdu session type
//get supi and put into URL
std::string supi_prefix = { };
get_supi_prefix(supi_prefix);
std::string supi_str = supi_prefix + "-" + smf_supi_to_string(supi);
std::string url = std::string(
inet_ntoa(*((struct in_addr*) &smf_cfg.amf_addr.ipv4_addr)))
+ ":" + std::to_string(smf_cfg.amf_addr.port)
+ fmt::format(NAMF_COMMUNICATION_N1N2_MESSAGE_TRANSFER_URL,
supi_str.c_str());
session_report_msg.set_amf_url(url);
//seid and trxn_id to be used in Failure indication
session_report_msg.set_seid(req->seid);
session_report_msg.set_trxn_id(req->trxn_id);
//QFIs, QoS profiles, CN Tunnel
smf_qos_flow flow = { };
sp.get()->get_qos_flow(qfi, flow);
//ADD QoS Flow to be updated
qos_flow_context_updated qcu = { };
qcu.set_qfi(qfi);
qcu.set_ul_fteid(flow.ul_fteid);
qcu.set_qos_profile(flow.qos_profile);
session_report_msg.add_qos_flow_context_updated(qcu);
// Create N2 SM Information: PDU Session Resource Setup Request Transfer IE
//N2 SM Information
smf_n1_n2 smf_n1_n2_inst = { };
std::string n2_sm_info, n2_sm_info_hex;
smf_n1_n2_inst.create_n2_sm_information(
session_report_msg, 1, n2_sm_info_type_e::PDU_RES_SETUP_REQ,
n2_sm_info);
smf_app_inst->convert_string_2_hex(n2_sm_info, n2_sm_info_hex);
session_report_msg.set_n2_sm_information(n2_sm_info_hex);
//Fill the json part
session_report_msg.n1n2_message_transfer_data["n2InfoContainer"]["n2InformationClass"] =
N1N2_MESSAGE_CLASS;
session_report_msg.n1n2_message_transfer_data["n2InfoContainer"]["smInfo"]["PduSessionId"] =
session_report_msg.get_pdu_session_id();
//N2InfoContent (section 6.1.6.2.27@3GPP TS 29.518)
session_report_msg.n1n2_message_transfer_data["n2InfoContainer"]["smInfo"]["n2InfoContent"]["ngapIeType"] =
"PDU_RES_SETUP_REQ"; //NGAP message type
session_report_msg.n1n2_message_transfer_data["n2InfoContainer"]["smInfo"]["n2InfoContent"]["ngapData"]["contentId"] =
N2_SM_CONTENT_ID; //NGAP part
session_report_msg.n1n2_message_transfer_data["n2InfoContainer"]["smInfo"]["sNssai"]["sst"] =
session_report_msg.get_snssai().sST;
session_report_msg.n1n2_message_transfer_data["n2InfoContainer"]["smInfo"]["sNssai"]["sd"] =
session_report_msg.get_snssai().sD;
itti_n11_session_report_request *itti_n11 =
new itti_n11_session_report_request(TASK_SMF_APP, TASK_SMF_N11);
std::shared_ptr<itti_n11_session_report_request> itti_n11_report =
std::shared_ptr<itti_n11_session_report_request>(itti_n11);
itti_n11_report->res = session_report_msg;
//send ITTI message to N11 interface to trigger N1N2MessageTransfer towards AMFs
Logger::smf_app().info(
"Sending ITTI message %s to task TASK_SMF_N11",
itti_n11_report->get_msg_name());
ret = itti_inst->send_msg(itti_n11_report);
if (RETURNok != ret) {
Logger::smf_app().error(
"Could not send ITTI message %s to task TASK_SMF_N11",
itti_n11_report->get_msg_name());
}
}
}
}
}
// Usage Report
if (report_type.usar) {
Logger::smf_app().debug("TODO PFCP_SESSION_REPORT_REQUEST/Usage Report");
}
// Error Indication Report
if (report_type.erir) {
Logger::smf_app().debug(
"TODO PFCP_SESSION_REPORT_REQUEST/Error Indication Report");
}
// User Plane Inactivity Report
if (report_type.upir) {
Logger::smf_app().debug(
"TODO PFCP_SESSION_REPORT_REQUEST/User Plane Inactivity Report");
}
}
}
//------------------------------------------------------------------------------
......@@ -859,8 +1037,6 @@ void smf_context::get_session_ambr(SessionAMBR &session_ambr,
void smf_context::get_session_ambr(
Ngap_PDUSessionAggregateMaximumBitRate_t &session_ambr,
const snssai_t &snssai, const std::string &dnn) {
Logger::smf_app().debug(
"Get AMBR info from the subscription information (DNN %s)", dnn.c_str());
std::shared_ptr<session_management_subscription> ss = { };
std::shared_ptr<dnn_configuration_t> sdc = { };
......@@ -881,9 +1057,9 @@ void smf_context::get_session_ambr(
if (nullptr != sdc.get()) {
Logger::smf_app().debug(
"Default AMBR info from the DNN configuration, downlink %s, uplink %s",
(sdc.get()->session_ambr).downlink.c_str(),
(sdc.get()->session_ambr).uplink.c_str());
"Default AMBR info from the DNN configuration, uplink %s, downlink %s",
(sdc.get()->session_ambr).uplink.c_str(),
(sdc.get()->session_ambr).downlink.c_str());
//Downlink
size_t leng_of_session_ambr_dl =
(sdc.get()->session_ambr).downlink.length();
......@@ -941,6 +1117,9 @@ void smf_context::get_session_ambr(
session_ambr.pDUSessionAggregateMaximumBitRateUL.buf);
}
Logger::smf_app().debug(
"Get AMBR info from the subscription information (DNN %s), uplink %d downlink %d",
dnn.c_str(), bit_rate_ul, bit_rate_dl);
}
//------------------------------------------------------------------------------
......@@ -1042,7 +1221,6 @@ void smf_context::handle_pdu_session_create_sm_context_request(
}
//pending session??
//Step 4. check if supi is authenticated
//TODO: if "Integrity Protection is required", check UE Integrity Protection Maximum Data Rate
//TODO: (Optional) Secondary authentication/authorization
......@@ -1354,13 +1532,6 @@ void smf_context::handle_pdu_session_update_sm_context_request(
return;
}
Logger::smf_app().debug(
"NAS header information, extended_protocol_discriminator %d, security_header_type:%d",
decoded_nas_msg.header.extended_protocol_discriminator,
decoded_nas_msg.header.security_header_type);
Logger::smf_app().debug("NAS header information, Message Type %d",
decoded_nas_msg.plain.sm.header.message_type);
uint8_t message_type = decoded_nas_msg.plain.sm.header.message_type;
switch (message_type) {
......@@ -1527,7 +1698,8 @@ void smf_context::handle_pdu_session_update_sm_context_request(
}
}
Logger::smf_app().debug("Add new QoS Flow with new QRI");
Logger::smf_app().debug("Add new QoS Flow with new QRI %d",
qos_rules_ie.qosruleidentifer);
//mark this rule to be synchronised with the UE
sp.get()->update_qos_rule(qos_rules_ie);
//Add new QoS flow
......@@ -1542,7 +1714,8 @@ void smf_context::handle_pdu_session_update_sm_context_request(
sm_context_resp_pending->res.add_qos_flow_context_updated(qcu);
} else { //update existing QRI
Logger::smf_app().debug("Update existing QRI");
Logger::smf_app().debug("Update existing QRI %d",
qos_rules_ie.qosruleidentifer);
qfi.qfi = qos_rules_ie.qosflowidentifer;
if (sp.get()->get_qos_flow(qfi, qos_flow)) {
sp.get()->update_qos_rule(qos_rules_ie);
......@@ -1893,7 +2066,7 @@ void smf_context::handle_pdu_session_update_sm_context_request(
}
//store AN Tunnel Info + list of accepted QFIs
fteid_t dl_teid;
fteid_t dl_teid = { };
memcpy(
&dl_teid.teid_gre_key,
decoded_msg->dLQosFlowPerTNLInformation.uPTransportLayerInformation
......@@ -1904,13 +2077,17 @@ void smf_context::handle_pdu_session_update_sm_context_request(
decoded_msg->dLQosFlowPerTNLInformation.uPTransportLayerInformation
.choice.gTPTunnel->transportLayerAddress.buf,
4);
Logger::smf_app().debug("DL GTP_F-TEID (AN F-TEID) " "0x%" PRIx32 " ",
htonl(dl_teid.teid_gre_key));
Logger::smf_app().debug("uPTransportLayerInformation (AN IP Addr) %s",
conv::toString(dl_teid.ipv4_address).c_str());
dl_teid.teid_gre_key = ntohl(dl_teid.teid_gre_key);
dl_teid.interface_type = S1_U_ENODEB_GTP_U;
dl_teid.v4 = 1; //Only V4 for now
smreq->req.set_dl_fteid(dl_teid);
Logger::smf_app().debug("DL GTP F-TEID (AN F-TEID) " "0x%" PRIx32 " ",
dl_teid.teid_gre_key);
Logger::smf_app().debug("uPTransportLayerInformation (AN IP Addr) %s",
conv::toString(dl_teid.ipv4_address).c_str());
for (int i = 0;
i
< decoded_msg->dLQosFlowPerTNLInformation.associatedQosFlowList
......@@ -1930,9 +2107,51 @@ void smf_context::handle_pdu_session_update_sm_context_request(
}
break;
//PDU Session Establishment procedure
//PDU Session Resource Setup Unsuccessful Transfer
case n2_sm_info_type_e::PDU_RES_SETUP_FAIL: {
Logger::smf_app().info(
"PDU Session Resource Setup Unsuccessful Transfer");
//Ngap_PDUSessionResourceSetupUnsuccessfulTransfer
std::shared_ptr<Ngap_PDUSessionResourceSetupUnsuccessfulTransfer_t> decoded_msg =
std::make_shared<Ngap_PDUSessionResourceSetupUnsuccessfulTransfer_t>();
int decode_status = smf_n1_n2_inst.decode_n2_sm_information(
decoded_msg, n2_sm_information);
if (decode_status == RETURNerror) {
Logger::smf_app().warn(
"Decode N2 SM (Ngap_PDUSessionResourceSetupUnsuccessfulTransfer) failed!");
problem_details.setCause(
pdu_session_application_error_e2str[PDU_SESSION_APPLICATION_ERROR_N2_SM_ERROR]);
smContextUpdateError.setError(problem_details);
smf_n11_inst->send_pdu_session_update_sm_context_response(
smreq->http_response, smContextUpdateError,
Pistache::Http::Code::Forbidden);
return;
}
//Logger::smf_app().info("PDU Session Resource Setup Unsuccessful Transfer cause %d",decoded_msg->cause );
problem_details.setCause(
pdu_session_application_error_e2str[PDU_SESSION_APPLICATION_ERROR_UE_NOT_RESPONDING]);
smContextUpdateError.setError(problem_details);
refToBinaryData.setContentId(N1_SM_CONTENT_ID);
smContextUpdateError.setN1SmMsg(refToBinaryData);
//PDU Session Establishment Reject, 24.501 cause "#26 Insufficient resources"
smf_n1_n2_inst.create_n1_sm_container(
smreq->req, PDU_SESSION_ESTABLISHMENT_REJECT, n1_sm_msg,
cause_value_5gsm_e::CAUSE_26_INSUFFICIENT_RESOURCES);
smf_app_inst->convert_string_2_hex(n1_sm_msg, n1_sm_msg_hex);
smf_n11_inst->send_pdu_session_update_sm_context_response(
smreq->http_response, smContextUpdateError,
Pistache::Http::Code::Forbidden, n1_sm_msg_hex);
//TODO: Need release established resources?
return;
}
break;
//PDU Session Modification procedure (UE-initiated, Section 4.3.3.2@3GPP TS 23.502 or SMF-Requested)(Step 2)
case n2_sm_info_type_e::PDU_RES_MOD_RSP: {
Logger::smf_app().info("PDU_RES_MOD_RSP");
Logger::smf_app().info(
"PDU Session Modification Procedure, processing N2 SM Information");
......@@ -1971,12 +2190,11 @@ void smf_context::handle_pdu_session_update_sm_context_request(
decoded_msg->dL_NGU_UP_TNLInformation->choice.gTPTunnel
->transportLayerAddress.buf,
4);
smreq->req.set_dl_fteid(dl_teid);
Logger::smf_app().debug("gTP_TEID " "0x%" PRIx32 " ",
htonl(dl_teid.teid_gre_key));
Logger::smf_app().debug("uPTransportLayerInformation IP Addr %s",
conv::toString(dl_teid.ipv4_address).c_str());
dl_teid.teid_gre_key = ntohl(dl_teid.teid_gre_key);
dl_teid.interface_type = S1_U_ENODEB_GTP_U;
dl_teid.v4 = 1; //Only v4 for now
smreq->req.set_dl_fteid(dl_teid);
//list of Qos Flows which have been successfully setup or modified
if (decoded_msg->qosFlowAddOrModifyResponseList) {
......@@ -2006,7 +2224,6 @@ void smf_context::handle_pdu_session_update_sm_context_request(
//PDU Session Release procedure (UE-initiated, Section 4.3.4.2@3GPP TS 23.502 or SMF-Requested)(Step 2)
case n2_sm_info_type_e::PDU_RES_REL_RSP: {
Logger::smf_app().info("PDU_RES_REL_RSP");
Logger::smf_app().info(
"PDU Session Release (UE-initiated), processing N2 SM Information");
......@@ -2397,6 +2614,20 @@ void smf_context::insert_dnn_subscription(
(uint8_t) snssai.sST);
}
//------------------------------------------------------------------------------
bool smf_context::is_dnn_snssai_subscription_data(const std::string &dnn,
const snssai_t &snssai) {
if (dnn_subscriptions.count((uint8_t) snssai.sST) > 0) {
std::shared_ptr<session_management_subscription> ss = dnn_subscriptions.at(
(uint8_t) snssai.sST);
if (ss.get()->dnn_configuration(dnn))
return true;
else
return false;
}
return false;
}
//------------------------------------------------------------------------------
bool smf_context::find_dnn_subscription(
const snssai_t &snssai,
......@@ -2454,7 +2685,7 @@ void smf_context::set_supi(const supi_t &s) {
}
//-----------------------------------------------------------------------------
std::size_t smf_context::get_number_dnn_contexts() {
std::size_t smf_context::get_number_dnn_contexts() const {
return dnns.size();
}
......@@ -2468,6 +2699,35 @@ scid_t smf_context::get_scid() const {
return scid;
}
//-----------------------------------------------------------------------------
void smf_context::get_supi_prefix(std::string &prefix) const {
prefix = supi_prefix;
}
//-----------------------------------------------------------------------------
void smf_context::set_supi_prefix(std::string const &prefix) {
supi_prefix = prefix;
}
//-----------------------------------------------------------------------------
bool smf_context::find_pdu_session(const pfcp::pdr_id_t &pdr_id,
pfcp::qfi_t &qfi,
std::shared_ptr<dnn_context> &sd,
std::shared_ptr<smf_pdu_session> &sp) {
for (auto it : dnns) {
for (auto session : it.get()->pdu_sessions) {
smf_qos_flow flow = { };
if (session->find_qos_flow(pdr_id, flow)) {
qfi.qfi = flow.qfi.qfi;
sp = session;
sd = it;
return true;
}
}
}
return false;
}
//------------------------------------------------------------------------------
bool dnn_context::find_pdu_session(
const uint32_t pdu_session_id,
......@@ -2490,7 +2750,7 @@ void dnn_context::insert_pdu_session(std::shared_ptr<smf_pdu_session> &sp) {
pdu_sessions.push_back(sp);
}
size_t dnn_context::get_number_pdu_sessions() {
size_t dnn_context::get_number_pdu_sessions() const {
return pdu_sessions.size();
}
......@@ -2500,8 +2760,6 @@ std::string dnn_context::toString() const {
s.append("DNN CONTEXT:\n");
s.append("\tIn use:\t\t\t\t").append(std::to_string(in_use)).append("\n");
s.append("\tDNN:\t\t\t\t").append(dnn_in_use).append("\n");
//s.append("\tAPN AMBR Bitrate Uplink:\t").append(std::to_string(apn_ambr.br_ul)).append("\n");
//s.append("\tAPN AMBR Bitrate Downlink:\t").append(std::to_string(apn_ambr.br_dl)).append("\n");
for (auto it : pdu_sessions) {
s.append(it->toString());
}
......
......@@ -258,10 +258,10 @@ class smf_pdu_session : public std::enable_shared_from_this<smf_pdu_session> {
upCnx_state_e get_upCnx_state() const;
// Called by GTPV2-C DELETE_SESSION_REQUEST
// deallocate_ressources is for releasing LTE resources prior to the deletion of objects
// deallocate_ressources is for releasing related-resources prior to the deletion of objects
// since shared_ptr is actually heavy used for handling objects, deletion of object instances cannot be always guaranteed
// when removing them from a collection, so that is why actually the deallocation of resources is not done in the destructor of objects.
void deallocate_ressources(const std::string &apn);
void deallocate_ressources(const std::string &dnn);
/*
* Represent PDU Session as string to be printed
......@@ -328,10 +328,10 @@ class smf_pdu_session : public std::enable_shared_from_this<smf_pdu_session> {
/*
* Mark a QoS Rule to be synchronised with UE
* @param [uint8_t ]: rule_id: QoS Rule ID to be synchronised with UE
* @param [const uint8_t ]: rule_id: QoS Rule ID to be synchronised with UE
* @return void
*/
void mark_qos_rule_to_be_synchronised(uint8_t rule_id);
void mark_qos_rule_to_be_synchronised(const uint8_t rule_id);
/*
* Get all QoS Rules to be synchronised with UE
......@@ -363,7 +363,7 @@ class smf_pdu_session : public std::enable_shared_from_this<smf_pdu_session> {
* @param [QOSRulesIE &] qos_rule
* @return bool: Return true if Rule exist, otherwise return false
*/
bool get_qos_rule(uint8_t rule_id, QOSRulesIE &qos_rule) const;
bool get_qos_rule(const uint8_t rule_id, QOSRulesIE &qos_rule) const;
/*
* Update QoS Rule
......@@ -412,7 +412,7 @@ class smf_pdu_session : public std::enable_shared_from_this<smf_pdu_session> {
timer_id_t timer_T3591;
timer_id_t timer_T3592;
pfcp::qfi_t default_qfi; //Default QFI for this session
pfcp::qfi_t default_qfi; //Default QFI for this session
std::map<uint8_t, smf_qos_flow> qos_flows; // QFI <-> QoS Flow
std::map<uint8_t, QOSRulesIE> qos_rules; // QRI <-> QoS Rules
std::vector<uint8_t> qos_rules_to_be_synchronised;
......@@ -441,7 +441,8 @@ class session_management_subscription {
* @return void
*/
void insert_dnn_configuration(
std::string dnn, std::shared_ptr<dnn_configuration_t> &dnn_configuration);
const std::string &dnn,
std::shared_ptr<dnn_configuration_t> &dnn_configuration);
/*
* Find a DNN configuration
......@@ -450,7 +451,15 @@ class session_management_subscription {
* @return void
*/
void find_dnn_configuration(
std::string dnn, std::shared_ptr<dnn_configuration_t> &dnn_configuration);
const std::string &dnn,
std::shared_ptr<dnn_configuration_t> &dnn_configuration) const;
/*
* Verify whether DNN configuration with a given DNN exist
* @param [std::string &] dnn
* @return bool: return true if the configuration exist, otherwise return false
*/
bool dnn_configuration(const std::string &dnn) const;
private:
snssai_t single_nssai;
......@@ -478,7 +487,6 @@ class dnn_context {
pdu_sessions(),
nssai(),
dnn_in_use(dnn) {
// apn_ambr = {0};
}
dnn_context(dnn_context &b) = delete;
......@@ -503,7 +511,7 @@ class dnn_context {
* @param void
* @return size_t: number of PDU sessions
*/
size_t get_number_pdu_sessions();
size_t get_number_pdu_sessions() const;
/*
* Represent DNN Context as a string object
......@@ -513,8 +521,7 @@ class dnn_context {
std::string toString() const;
bool in_use;
std::string dnn_in_use; // The APN currently used, as received from the SGW.
//ambr_t apn_ambr; // APN AMBR: The maximum aggregated uplink and downlink MBR values to be shared across all Non-GBR bearers, which are established for this APN.
std::string dnn_in_use; // The DNN currently used, as received from the AMF
snssai_t nssai;
std::vector<std::shared_ptr<smf_pdu_session>> pdu_sessions; //Store all PDU Sessions associated with this DNN context
mutable std::recursive_mutex m_context;
......@@ -528,12 +535,10 @@ class smf_context : public std::enable_shared_from_this<smf_context> {
smf_context()
:
m_context(),
imsi(),
imsi_unauthenticated_indicator(false),
pending_procedures(),
msisdn(),
dnn_subscriptions(),
scid(0) {
supi_prefix = { };
}
smf_context(smf_context &b) = delete;
......@@ -659,6 +664,14 @@ class smf_context : public std::enable_shared_from_this<smf_context> {
const snssai_t &snssai,
std::shared_ptr<session_management_subscription> &ss);
/*
* Verify whether a subscription data exist with a given dnn and snssai
* @param [const std::string &] dnn: DNN
* @param [const snssai_t&] snssai: single NSSAI
*@return bool: Return true if a subscription data corresponding with dnn and snssai exist, otherwise return false
*/
bool is_dnn_snssai_subscription_data(const std::string &dnn, const snssai_t &snssai);
/*
* Find a session management subscription from a SMF context
* @param [const snssai_t&] snssai
......@@ -704,7 +717,7 @@ class smf_context : public std::enable_shared_from_this<smf_context> {
* @param
* @return std::size_t: the number of contexts
*/
std::size_t get_number_dnn_contexts();
std::size_t get_number_dnn_contexts() const;
/*
* Set SM Context ID
......@@ -720,9 +733,25 @@ class smf_context : public std::enable_shared_from_this<smf_context> {
*/
scid_t get_scid() const;
/*
* Get Supi prefix
* @param [const std::string &] prefix: Supi prefix (e.g., imsi)
* @return void
*/
void get_supi_prefix(std::string &prefix) const;
/*
* Get Supi prefix
* @param [const std::string &] prefix: Supi prefix (e.g., imsi)
* @return void
*/
void set_supi_prefix(std::string const &value);
/*
* Get the default QoS Rule for all QFIs
* @param [QOSRulesIE] qos_rule
* @param [const uint8_t] pdu_session_type: PDU session type (e.g., Ipv4, Ipv6)
* @return void
*/
void get_default_qos_rule(QOSRulesIE &qos_rule, uint8_t pdu_session_type);
......@@ -758,17 +787,26 @@ class smf_context : public std::enable_shared_from_this<smf_context> {
void get_session_ambr(Ngap_PDUSessionAggregateMaximumBitRate_t &session_ambr,
const snssai_t &snssai, const std::string &dnn);
/*
* Find the PDU Session, QFI associated with a given PDR_ID
* @param [const pfcp::pdr_id_t &] pdr_id: PDR ID
* @param [pfcp::qfi_t &] qfi: QFI
* @param [std::shared_ptr<dnn_context> &] sd: pointer to the DNN context
* @param [std::shared_ptr<smf_pdu_session> &] sp: pointer to the PDU session
* @return bool: return true if found, otherwise return false
*/
bool find_pdu_session(const pfcp::pdr_id_t &pdr_id, pfcp::qfi_t &qfi,
std::shared_ptr<dnn_context> &sd,
std::shared_ptr<smf_pdu_session> &sp);
private:
std::vector<std::shared_ptr<dnn_context>> dnns;
imsi_t imsi; // IMSI (International Mobile Subscriber Identity) is the subscriber permanent identity.
bool imsi_unauthenticated_indicator; // This is an IMSI indicator to show the IMSI is unauthenticated.
// TO BE CHECKED me_identity_t me_identity; // Mobile Equipment Identity (e.g. IMEI/IMEISV).
msisdn_t msisdn; // The basic MSISDN of the UE. The presence is dictated by its storage in the HSS.
std::vector<std::shared_ptr<smf_procedure>> pending_procedures;
// snssai-sst <-> session management subscription
std::map<uint8_t, std::shared_ptr<session_management_subscription>> dnn_subscriptions;
supi_t supi;
scid_t scid; //SM Context ID
std::string supi_prefix;
scid_t scid; //SM Context ID
// Big recursive lock
mutable std::recursive_mutex m_context;
......
......@@ -78,7 +78,7 @@ pdu_session_msg_type_t pdu_session_msg::get_msg_type() const {
}
//-----------------------------------------------------------------------------
void pdu_session_msg::set_msg_type(pdu_session_msg_type_t const &msg_type) {
void pdu_session_msg::set_msg_type(const pdu_session_msg_type_t &msg_type) {
m_msg_type = msg_type;
}
......@@ -88,7 +88,7 @@ supi_t pdu_session_msg::get_supi() const {
}
//-----------------------------------------------------------------------------
void pdu_session_msg::set_supi(supi_t const &supi) {
void pdu_session_msg::set_supi(const supi_t &supi) {
m_supi = supi;
}
......@@ -98,7 +98,7 @@ std::string pdu_session_msg::get_supi_prefix() const {
}
//-----------------------------------------------------------------------------
void pdu_session_msg::set_supi_prefix(std::string const &prefix) {
void pdu_session_msg::set_supi_prefix(const std::string &prefix) {
m_supi_prefix = prefix;
}
......@@ -109,7 +109,7 @@ pdu_session_id_t pdu_session_msg::get_pdu_session_id() const {
//-----------------------------------------------------------------------------
void pdu_session_msg::set_pdu_session_id(
pdu_session_id_t const pdu_session_id) {
const pdu_session_id_t pdu_session_id) {
m_pdu_session_id = pdu_session_id;
}
......@@ -119,7 +119,7 @@ std::string pdu_session_msg::get_dnn() const {
}
//-----------------------------------------------------------------------------
void pdu_session_msg::set_dnn(std::string const &dnn) {
void pdu_session_msg::set_dnn(const std::string &dnn) {
m_dnn = dnn;
}
......@@ -129,12 +129,12 @@ snssai_t pdu_session_msg::get_snssai() const {
}
//-----------------------------------------------------------------------------
void pdu_session_msg::set_snssai(snssai_t const &snssai) {
void pdu_session_msg::set_snssai(const snssai_t &snssai) {
m_snssai = snssai;
}
//-----------------------------------------------------------------------------
void pdu_session_msg::set_api_root(std::string const &value) {
void pdu_session_msg::set_api_root(const std::string &value) {
m_api_root = value;
}
......@@ -148,7 +148,7 @@ uint8_t pdu_session_msg::get_pdu_session_type() const {
}
//-----------------------------------------------------------------------------
void pdu_session_msg::set_pdu_session_type(uint8_t const &pdu_session_type) {
void pdu_session_msg::set_pdu_session_type(const uint8_t &pdu_session_type) {
m_pdu_session_type = pdu_session_type;
}
......@@ -158,7 +158,7 @@ procedure_transaction_id_t pdu_session_msg::get_pti() const {
}
//-----------------------------------------------------------------------------
void pdu_session_msg::set_pti(procedure_transaction_id_t const &pti) {
void pdu_session_msg::set_pti(const procedure_transaction_id_t &pti) {
m_pti = pti;
}
......@@ -169,7 +169,7 @@ extended_protocol_discriminator_t pdu_session_create_sm_context::get_epd() const
//-----------------------------------------------------------------------------
void pdu_session_create_sm_context::set_epd(
extended_protocol_discriminator_t const &epd) {
const extended_protocol_discriminator_t &epd) {
m_epd = epd;
}
......@@ -180,7 +180,7 @@ uint8_t pdu_session_create_sm_context::get_message_type() const {
//-----------------------------------------------------------------------------
void pdu_session_create_sm_context::set_message_type(
uint8_t const &message_type) {
const uint8_t &message_type) {
m_message_type = message_type;
}
......@@ -202,7 +202,7 @@ std::string pdu_session_create_sm_context_request::get_serving_nf_id() const {
//-----------------------------------------------------------------------------
void pdu_session_create_sm_context_request::set_serving_nf_id(
std::string const &serving_nf_id) {
const std::string &serving_nf_id) {
m_serving_nf_id = serving_nf_id;
}
......@@ -213,13 +213,13 @@ std::string pdu_session_create_sm_context_request::get_request_type() const {
//-----------------------------------------------------------------------------
void pdu_session_create_sm_context_request::set_request_type(
std::string const &request_type) {
const std::string &request_type) {
m_request_type = request_type;
}
//-----------------------------------------------------------------------------
void pdu_session_create_sm_context_request::set_dnn_selection_mode(
std::string const &dnn_selection_mode) {
const std::string &dnn_selection_mode) {
m_dnn_selection_mode = dnn_selection_mode;
}
......@@ -277,7 +277,7 @@ std::string pdu_session_create_sm_context_response::get_n2_sm_information() cons
//-----------------------------------------------------------------------------
void pdu_session_create_sm_context_response::set_n2_sm_information(
std::string const &value) {
const std::string &value) {
m_n2_sm_information = value;
m_n2_sm_info_is_set = true;
}
......@@ -289,7 +289,7 @@ std::string pdu_session_create_sm_context_response::get_n1_sm_message() const {
//-----------------------------------------------------------------------------
void pdu_session_create_sm_context_response::set_n1_sm_message(
std::string const &value) {
const std::string &value) {
m_n1_sm_message = value;
m_n1_sm_msg_is_set = true;
}
......@@ -306,7 +306,7 @@ bool pdu_session_create_sm_context_response::n2_sm_info_is_set() const {
//-----------------------------------------------------------------------------
void pdu_session_create_sm_context_response::set_amf_url(
std::string const &value) {
const std::string &value) {
amf_url = value;
}
......@@ -322,7 +322,7 @@ std::string pdu_session_update_sm_context::get_n2_sm_information() const {
//-----------------------------------------------------------------------------
void pdu_session_update_sm_context::set_n2_sm_information(
std::string const &value) {
const std::string &value) {
m_n2_sm_information = value;
m_n2_sm_info_is_set = true;
}
......@@ -334,7 +334,7 @@ std::string pdu_session_update_sm_context::get_n2_sm_info_type() const {
//-----------------------------------------------------------------------------
void pdu_session_update_sm_context::set_n2_sm_info_type(
std::string const &value) {
const std::string &value) {
m_n2_sm_info_type = value;
m_n2_sm_info_is_set = true;
}
......@@ -346,7 +346,7 @@ std::string pdu_session_update_sm_context::get_n1_sm_message() const {
//-----------------------------------------------------------------------------
void pdu_session_update_sm_context::set_n1_sm_message(
std::string const &value) {
const std::string &value) {
m_n1_sm_message = value;
m_n1_sm_msg_is_set = true;
}
......@@ -362,12 +362,12 @@ bool pdu_session_update_sm_context::n2_sm_info_is_set() const {
}
//-----------------------------------------------------------------------------
void pdu_session_update_sm_context_request::add_qfi(pfcp::qfi_t const &qfi) {
void pdu_session_update_sm_context_request::add_qfi(const pfcp::qfi_t &qfi) {
qfis.push_back(qfi);
}
//-----------------------------------------------------------------------------
void pdu_session_update_sm_context_request::add_qfi(uint8_t const &q) {
void pdu_session_update_sm_context_request::add_qfi(const uint8_t &q) {
pfcp::qfi_t qfi(q);
qfis.push_back(qfi);
}
......@@ -381,7 +381,7 @@ void pdu_session_update_sm_context_request::get_qfis(
}
//-----------------------------------------------------------------------------
void pdu_session_update_sm_context_request::set_dl_fteid(fteid_t const &t) {
void pdu_session_update_sm_context_request::set_dl_fteid(const fteid_t &t) {
dl_fteid = t;
}
......@@ -392,7 +392,7 @@ void pdu_session_update_sm_context_request::get_dl_fteid(fteid_t &t) {
//-----------------------------------------------------------------------------
void pdu_session_update_sm_context_request::set_upCnx_state(
std::string const &value) {
const std::string &value) {
m_upCnx_state = value;
m_upCnx_state_is_set = true;
}
......@@ -404,7 +404,7 @@ bool pdu_session_update_sm_context_request::upCnx_state_is_set() const {
//-----------------------------------------------------------------------------
void pdu_session_update_sm_context_request::set_rat_type(
std::string const &value) {
const std::string &value) {
m_rat_type = value;
m_rat_type_is_set = true;
}
......@@ -416,7 +416,7 @@ bool pdu_session_update_sm_context_request::rat_type_is_set() const {
//-----------------------------------------------------------------------------
void pdu_session_update_sm_context_request::set_an_type(
std::string const &value) {
const std::string &value) {
m_an_type = value;
m_an_type_is_set = true;
}
......@@ -432,7 +432,7 @@ bool pdu_session_update_sm_context_request::release_is_set() const {
}
//-----------------------------------------------------------------------------
void pdu_session_update_sm_context_request::set_release(bool const value) {
void pdu_session_update_sm_context_request::set_release(bool value) {
m_release = value;
m_release_is_set = true;
}
......@@ -461,8 +461,7 @@ void pdu_session_update_sm_context_response::add_qos_flow_context_updated(
flow.qfi.qfi);
} else {
Logger::smf_app().error(
"Failed to add a QoS Flow Context (QFI %d), invalid QFI",
flow.qfi.qfi);
"Failed to add a QoS Flow Context (QFI %d), invalid QFI", flow.qfi.qfi);
}
}
......@@ -516,7 +515,7 @@ Pistache::Http::Code pdu_session_modification_network_requested::get_http_code()
//-----------------------------------------------------------------------------
void pdu_session_modification_network_requested::set_amf_url(
std::string const &value) {
const std::string &value) {
amf_url = value;
}
......@@ -527,12 +526,12 @@ std::string pdu_session_modification_network_requested::get_amf_url() const {
//-----------------------------------------------------------------------------
void pdu_session_modification_network_requested::add_qfi(
pfcp::qfi_t const &qfi) {
const pfcp::qfi_t &qfi) {
qfis.push_back(qfi);
}
//-----------------------------------------------------------------------------
void pdu_session_modification_network_requested::add_qfi(uint8_t const &q) {
void pdu_session_modification_network_requested::add_qfi(const uint8_t &q) {
pfcp::qfi_t qfi(q);
qfis.push_back(qfi);
}
......@@ -545,3 +544,120 @@ void pdu_session_modification_network_requested::get_qfis(
}
}
//-----------------------------------------------------------------------------
void pdu_session_report_response::set_amf_url(const std::string &value) {
amf_url = value;
}
//-----------------------------------------------------------------------------
std::string pdu_session_report_response::get_amf_url() const {
return amf_url;
}
//-----------------------------------------------------------------------------
void pdu_session_report_response::add_qos_flow_context_updated(
const qos_flow_context_updated &flow) {
if ((flow.qfi.qfi >= QOS_FLOW_IDENTIFIER_FIRST )
and (flow.qfi.qfi <= QOS_FLOW_IDENTIFIER_LAST )) {
qos_flow_context_updateds.erase(flow.qfi.qfi);
qos_flow_context_updateds.insert(
std::pair<uint8_t, qos_flow_context_updated>((uint8_t) flow.qfi.qfi,
flow));
Logger::smf_app().trace(
"A QoS Flow Context (QFI %d) has been added successfully",
flow.qfi.qfi);
} else {
Logger::smf_app().error(
"Failed to add a QoS Flow Context (QFI %d), invalid QFI", flow.qfi.qfi);
}
}
//-----------------------------------------------------------------------------
bool pdu_session_report_response::get_qos_flow_context_updated(
const pfcp::qfi_t &qfi, qos_flow_context_updated &flow) {
for (auto it : qos_flow_context_updateds) {
if (it.second.qfi == qfi) {
flow = it.second;
return true;
}
}
return false;
}
//-----------------------------------------------------------------------------
void pdu_session_report_response::get_all_qos_flow_context_updateds(
std::map<uint8_t, qos_flow_context_updated> &all_flows) {
for (auto it : qos_flow_context_updateds) {
all_flows.insert(
std::pair<uint8_t, qos_flow_context_updated>((uint8_t) it.first,
it.second));
}
}
//-----------------------------------------------------------------------------
std::string pdu_session_report_response::get_n2_sm_information() const {
return m_n2_sm_information;
}
//-----------------------------------------------------------------------------
void pdu_session_report_response::set_n2_sm_information(
const std::string &value) {
m_n2_sm_information = value;
m_n2_sm_info_is_set = true;
}
//-----------------------------------------------------------------------------
std::string pdu_session_report_response::get_n2_sm_info_type() const {
return m_n2_sm_info_type;
}
//-----------------------------------------------------------------------------
void pdu_session_report_response::set_n2_sm_info_type(
const std::string &value) {
m_n2_sm_info_type = value;
m_n2_sm_info_is_set = true;
}
//-----------------------------------------------------------------------------
std::string pdu_session_report_response::get_n1_sm_message() const {
return m_n1_sm_message;
}
//-----------------------------------------------------------------------------
void pdu_session_report_response::set_n1_sm_message(const std::string &value) {
m_n1_sm_message = value;
m_n1_sm_msg_is_set = true;
}
//-----------------------------------------------------------------------------
bool pdu_session_report_response::n1_sm_msg_is_set() const {
return m_n1_sm_msg_is_set;
}
//-----------------------------------------------------------------------------
bool pdu_session_report_response::n2_sm_info_is_set() const {
return m_n2_sm_info_is_set;
}
//-----------------------------------------------------------------------------
void pdu_session_report_response::set_seid(const seid_t &s) {
seid = s;
}
//-----------------------------------------------------------------------------
void pdu_session_report_response::set_trxn_id(const uint64_t &t) {
trxn_id = t;
}
//-----------------------------------------------------------------------------
seid_t pdu_session_report_response::get_seid() const {
return seid;
}
//-----------------------------------------------------------------------------
uint64_t pdu_session_report_response::get_trxn_id() const {
return trxn_id;
}
......@@ -124,23 +124,23 @@ class pdu_session_msg {
virtual ~pdu_session_msg() = default;
pdu_session_msg_type_t get_msg_type() const;
void set_msg_type(pdu_session_msg_type_t const &value);
void set_msg_type(const pdu_session_msg_type_t &value);
supi_t get_supi() const;
void set_supi(supi_t const &value);
void set_supi(const supi_t &value);
std::string get_supi_prefix() const;
void set_supi_prefix(std::string const &value);
void set_supi_prefix(const std::string &value);
pdu_session_id_t get_pdu_session_id() const;
void set_pdu_session_id(pdu_session_id_t const value);
void set_pdu_session_id(const pdu_session_id_t value);
std::string get_dnn() const;
void set_dnn(std::string const &value);
void set_dnn(const std::string &value);
snssai_t get_snssai() const;
void set_snssai(snssai_t const &value);
void set_api_root(std::string const &value);
void set_snssai(const snssai_t &value);
void set_api_root(const std::string &value);
std::string get_api_root() const;
uint8_t get_pdu_session_type() const;
void set_pdu_session_type(uint8_t const &pdu_session_type);
void set_pdu_session_type(const uint8_t &pdu_session_type);
procedure_transaction_id_t get_pti() const;
void set_pti(procedure_transaction_id_t const &pti);
void set_pti(const procedure_transaction_id_t &pti);
private:
pdu_session_msg_type_t m_msg_type;
......@@ -182,9 +182,9 @@ class pdu_session_create_sm_context : public pdu_session_msg {
}
extended_protocol_discriminator_t get_epd() const;
void set_epd(extended_protocol_discriminator_t const &epd);
void set_epd(const extended_protocol_discriminator_t &epd);
uint8_t get_message_type() const;
void set_message_type(uint8_t const &message_type);
void set_message_type(const uint8_t &message_type);
private:
extended_protocol_discriminator_t m_epd;
......@@ -210,12 +210,12 @@ class pdu_session_create_sm_context_request :
}
std::string get_n1_sm_message() const;
void set_n1_sm_message(std::string const &value);
void set_n1_sm_message(const std::string &value);
std::string get_serving_nf_id() const;
void set_serving_nf_id(std::string const &value);
void set_serving_nf_id(const std::string &value);
std::string get_request_type() const;
void set_request_type(std::string const &value);
void set_dnn_selection_mode(std::string const &value);
void set_request_type(const std::string &value);
void set_dnn_selection_mode(const std::string &value);
std::string get_dnn_selection_mode() const;
private:
......@@ -267,12 +267,12 @@ class pdu_session_create_sm_context_response :
void set_qos_flow_context(const qos_flow_context_updated &qos_flow);
qos_flow_context_updated get_qos_flow_context() const;
std::string get_n2_sm_information() const;
void set_n2_sm_information(std::string const &value);
void set_n2_sm_information(const std::string &value);
std::string get_n1_sm_message() const;
void set_n1_sm_message(std::string const &value);
void set_n1_sm_message(const std::string &value);
bool n1_sm_msg_is_set() const;
bool n2_sm_info_is_set() const;
void set_amf_url(std::string const &value);
void set_amf_url(const std::string &value);
std::string get_amf_url() const;
nlohmann::json n1n2_message_transfer_data; //N1N2MessageTransferReqData from oai::amf::model
......@@ -312,9 +312,9 @@ class pdu_session_update_sm_context : public pdu_session_msg {
std::string get_n2_sm_information() const;
void set_n2_sm_information(std::string const &value);
std::string get_n2_sm_info_type() const;
void set_n2_sm_info_type(std::string const &value);
void set_n2_sm_info_type(const std::string &value);
std::string get_n1_sm_message() const;
void set_n1_sm_message(std::string const &value);
void set_n1_sm_message(const std::string &value);
bool n1_sm_msg_is_set() const;
bool n2_sm_info_is_set() const;
......@@ -345,19 +345,19 @@ class pdu_session_update_sm_context_request :
}
;
void add_qfi(pfcp::qfi_t const &qfi);
void add_qfi(uint8_t const &qfi);
void add_qfi(const pfcp::qfi_t &qfi);
void add_qfi(const uint8_t &qfi);
void get_qfis(std::vector<pfcp::qfi_t> &q);
void set_dl_fteid(fteid_t const &t);
void set_dl_fteid(const fteid_t &t);
void get_dl_fteid(fteid_t &t);
void set_upCnx_state(std::string const &value);
void set_upCnx_state(const std::string &value);
bool upCnx_state_is_set() const;
void set_rat_type(std::string const &value);
void set_rat_type(const std::string &value);
bool rat_type_is_set() const;
void set_an_type(std::string const &value);
void set_an_type(const std::string &value);
bool an_type_is_set() const;
bool release_is_set() const;
void set_release(bool const value);
void set_release(bool value);
private:
std::vector<pfcp::qfi_t> qfis;
......@@ -456,10 +456,10 @@ class pdu_session_modification_network_requested :
void set_http_code(Pistache::Http::Code code);
Pistache::Http::Code get_http_code();
void set_amf_url(std::string const &value);
void set_amf_url(const std::string &value);
std::string get_amf_url() const;
void add_qfi(pfcp::qfi_t const &qfi);
void add_qfi(uint8_t const &qfi);
void add_qfi(const pfcp::qfi_t &qfi);
void add_qfi(const uint8_t &qfi);
void get_qfis(std::vector<pfcp::qfi_t> &q);
nlohmann::json n1n2_message_transfer_data; //N1N2MessageTransferReqData from oai::amf::model
......@@ -472,6 +472,65 @@ class pdu_session_modification_network_requested :
std::map<uint8_t, qos_flow_context_updated> qos_flow_context_updateds;
};
//---------------------------------------------------------------------------------------
class pdu_session_report_response : public pdu_session_msg {
public:
public:
pdu_session_report_response()
:
pdu_session_msg() {
m_n2_sm_info_is_set = false;
m_n1_sm_msg_is_set = false;
seid = 0;
trxn_id = 0;
}
;
pdu_session_report_response(pdu_session_msg_type_t msg_type)
:
pdu_session_msg(msg_type) {
m_n2_sm_info_is_set = false;
m_n1_sm_msg_is_set = false;
seid = 0;
trxn_id = 0;
}
;
void set_amf_url(std::string const &value);
std::string get_amf_url() const;
void add_qos_flow_context_updated(const qos_flow_context_updated &qos_flow);
bool get_qos_flow_context_updated(const pfcp::qfi_t &qfi,
qos_flow_context_updated &qos_flow);
void get_all_qos_flow_context_updateds(
std::map<uint8_t, qos_flow_context_updated> &all_flows);
std::string get_n2_sm_information() const;
void set_n2_sm_information(const std::string &value);
std::string get_n2_sm_info_type() const;
void set_n2_sm_info_type(const std::string &value);
std::string get_n1_sm_message() const;
void set_n1_sm_message(const std::string &value);
bool n1_sm_msg_is_set() const;
bool n2_sm_info_is_set() const;
void set_seid(const seid_t &s);
void set_trxn_id(const uint64_t &t);
seid_t get_seid() const;
uint64_t get_trxn_id() const;
nlohmann::json n1n2_message_transfer_data; //N1N2MessageTransferReqData from oai::amf::model
private:
supi_t m_supi;
std::string m_supi_prefix;
std::string amf_url;
std::map<uint8_t, qos_flow_context_updated> qos_flow_context_updateds;
std::string m_n1_sm_message;
bool m_n1_sm_msg_is_set;
std::string m_n2_sm_information;
bool m_n2_sm_info_is_set;
std::string m_n2_sm_info_type;
seid_t seid;
uint64_t trxn_id;
};
}
#endif
......@@ -101,7 +101,7 @@ smf_n10::smf_n10() {
//------------------------------------------------------------------------------
bool smf_n10::get_sm_data(
supi64_t &supi, std::string &dnn, snssai_t &snssai,
const supi64_t &supi, const std::string &dnn, const snssai_t &snssai,
std::shared_ptr<session_management_subscription> subscription) {
//retrieve a UE's Session Management Subscription Data (TS29503_Nudm_SDM.yaml: /{supi}/sm-data)
//use curl to send data for the moment
......@@ -114,7 +114,6 @@ bool smf_n10::get_sm_data(
headers = curl_slist_append(headers, "charsets: utf-8");
CURL *curl = curl_easy_init();
// std::string url = std::string(inet_ntoa (*((struct in_addr *)&smf_cfg.udm_addr.ipv4_addr))) + ":" + std::to_string(smf_cfg.udm_addr.port) + "/nudm-sdm/v2/" + std::to_string(supi) +"/sm-data";
std::string url = std::string(
inet_ntoa(*((struct in_addr*) &smf_cfg.udm_addr.ipv4_addr))) + ":"
+ std::to_string(smf_cfg.udm_addr.port)
......@@ -148,7 +147,6 @@ bool smf_n10::get_sm_data(
== http_response_codes_e::HTTP_RESPONSE_CODE_OK) {
Logger::smf_n10().debug("Got successful response from UDM, URL: %s ",
url.c_str());
//Logger::smf_n10().debug("[get_sm_data] Http Data from UDM: %s ", *httpData.get());
try {
jsonData = nlohmann::json::parse(*httpData.get());
//curl_easy_cleanup(curl);
......
......@@ -50,15 +50,15 @@ class smf_n10 {
/*
* Get SM subscription data from UDM
* @param [supi64_t &] supi
* @param [std::string &] dnn
* @param [snssai_t &] snssai
* @param [const supi64_t &] supi
* @param [const std::string &] dnn
* @param [const snssai_t &] snssai
* @param [std::shared_ptr<session_management_subscription>] subscription
* @return bool: True if successful, otherwise false
*
*/
bool get_sm_data(
supi64_t &supi, std::string &dnn, snssai_t &snssai,
const supi64_t &supi, const std::string &dnn, const snssai_t &snssai,
std::shared_ptr<session_management_subscription> subscription);
/*
......
......@@ -103,6 +103,12 @@ void smf_n11_task(void *args_p) {
shared_msg));
break;
case N11_SESSION_REPORT_RESPONSE:
//TODO
smf_n11_inst->send_n1n2_message_transfer_request(
std::static_pointer_cast<itti_n11_session_report_request>(
shared_msg));
break;
case TERMINATE:
if (itti_msg_terminate *terminate =
dynamic_cast<itti_msg_terminate*>(msg)) {
......@@ -139,7 +145,6 @@ void smf_n11::send_n1n2_message_transfer_request(
smf_n1_n2 smf_n1_n2_inst = { };
std::string n1_message = sm_context_res->res.get_n1_sm_message();
std::string json_part = sm_context_res->res.n1n2_message_transfer_data.dump();
std::string boundary = "----Boundary";
std::string body;
//add N2 content if available
......@@ -148,11 +153,11 @@ void smf_n11::send_n1n2_message_transfer_request(
if (n2_sm_found > 0) {
std::string n2_message = sm_context_res->res.get_n2_sm_information();
//prepare the body content for Curl
create_multipart_related_content(body, json_part, boundary, n1_message,
create_multipart_related_content(body, json_part, CURL_MIME_BOUNDARY, n1_message,
n2_message);
} else {
//prepare the body content for Curl
create_multipart_related_content(body, json_part, boundary, n1_message,
create_multipart_related_content(body, json_part, CURL_MIME_BOUNDARY, n1_message,
multipart_related_content_part_e::NAS);
}
......@@ -168,8 +173,9 @@ void smf_n11::send_n1n2_message_transfer_request(
CURLcode res = { };
struct curl_slist *headers = nullptr;
//headers = curl_slist_append(headers, "charsets: utf-8");
headers = curl_slist_append(
headers, "content-type: multipart/related; boundary=----Boundary"); //TODO: update Boundary
std::string content_type = "content-type: multipart/related; boundary="
+ std::string(CURL_MIME_BOUNDARY);
headers = curl_slist_append(headers, content_type.c_str());
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
curl_easy_setopt(curl, CURLOPT_URL,
sm_context_res->res.get_amf_url().c_str());
......@@ -210,6 +216,8 @@ void smf_n11::send_n1n2_message_transfer_request(
TASK_SMF_APP);
itti_msg->set_response_code(httpCode);
itti_msg->set_scid(sm_context_res->scid);
itti_msg->set_procedure_type(
session_management_procedures_type_e::PDU_SESSION_ESTABLISHMENT_UE_REQUESTED);
itti_msg->set_cause(response_data["cause"]);
if (sm_context_res->res.get_cause() == REQUEST_ACCEPTED) {
itti_msg->set_msg_type(PDU_SESSION_ESTABLISHMENT_ACCEPT);
......@@ -232,126 +240,6 @@ void smf_n11::send_n1n2_message_transfer_request(
curl_global_cleanup();
free_wrapper((void**) &data);
/*
//Curl MIME
//format string as hex
unsigned char *n1_msg_hex = smf_app_inst->format_string_as_hex(n1_message);
CURL *curl = curl_easy_init();
//N1N2MessageTransfer Notification URI??
std::string json_part = context_res_msg.n1n2_message_transfer_data.dump();
Logger::smf_n11().debug("Sending message to AMF....");
if (curl) {
CURLcode res = { };
struct curl_slist *headers = nullptr;
struct curl_slist *slist = nullptr;
curl_mime *mime;
curl_mime *alt;
curl_mimepart *part;
//headers = curl_slist_append(headers, "charsets: utf-8");
headers = curl_slist_append(headers, "content-type: multipart/related");
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
curl_easy_setopt(curl, CURLOPT_URL, context_res_msg.get_amf_url().c_str());
curl_easy_setopt(curl, CURLOPT_HTTPGET, 1);
curl_easy_setopt(curl, CURLOPT_TIMEOUT_MS, AMF_CURL_TIMEOUT_MS);
curl_easy_setopt(curl, CURLOPT_INTERFACE, smf_cfg.sbi.if_name.c_str());
mime = curl_mime_init(curl);
alt = curl_mime_init(curl);
//part with N1N2MessageTransferReqData (JsonData)
part = curl_mime_addpart(mime);
curl_mime_data(part, json_part.c_str(), CURL_ZERO_TERMINATED);
curl_mime_type(part, "application/json");
//N1 SM Container
Logger::smf_n11().debug(
"Add N1 SM Container (NAS) into the message: %s (bytes %d)",
context_res_msg.get_n1_sm_message().c_str(),
context_res_msg.get_n1_sm_message().length() / 2);
part = curl_mime_addpart(mime);
curl_mime_data(part, reinterpret_cast<const char*>(n1_msg_hex),
context_res_msg.get_n1_sm_message().length() / 2);
curl_mime_type(part, "application/vnd.3gpp.5gnas");
curl_mime_name(
part,
context_res_msg.n1n2_message_transfer_data["n1MessageContainer"]["n1MessageContent"]["contentId"]
.dump().c_str());
auto n2_sm_found = context_res_msg.n1n2_message_transfer_data.count(
"n2InfoContainer");
if (n2_sm_found > 0) {
std::string n2_message = context_res_msg.get_n2_sm_information();
unsigned char *n2_msg_hex = smf_app_inst->format_string_as_hex(
n2_message);
Logger::smf_n11().debug(
"Add N2 SM Information (NGAP) into the message: %s (bytes %d)",
n2_message.c_str(), n2_message.length() / 2);
part = curl_mime_addpart(mime);
curl_mime_data(part, reinterpret_cast<const char*>(n2_msg_hex), 80); //TODO: n2_message.length()/2 ISSUE need to be solved
curl_mime_type(part, "application/vnd.3gpp.ngap");
curl_mime_name(
part,
context_res_msg.n1n2_message_transfer_data["n2InfoContainer"]["smInfo"]["n2InfoContent"]["ngapData"]["contentId"]
.dump().c_str());
}
curl_easy_setopt(curl, CURLOPT_MIMEPOST, mime);
// Response information.
long httpCode = { 0 };
std::unique_ptr<std::string> httpData(new std::string());
// Hook up data handling function.
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, &callback);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, httpData.get());
res = curl_easy_perform(curl);
curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &httpCode);
//get cause from the response
json response_data = { };
try {
response_data = json::parse(*httpData.get());
} catch (json::exception &e) {
Logger::smf_n11().error("Could not get the cause from the response");
//Set the default Cause
response_data["cause"] = "504 Gateway Timeout";
}
Logger::smf_n11().debug("Response from AMF, Http Code: %d, cause %s",
httpCode, response_data["cause"].dump().c_str());
//send response to APP to process
itti_n11_n1n2_message_transfer_response_status *itti_msg =
new itti_n11_n1n2_message_transfer_response_status(TASK_SMF_N11,
TASK_SMF_APP);
itti_msg->set_response_code(httpCode);
itti_msg->set_scid(sm_context_res->scid);
itti_msg->set_cause(response_data["cause"]);
if (context_res_msg.get_cause() == REQUEST_ACCEPTED) {
itti_msg->set_msg_type(PDU_SESSION_ESTABLISHMENT_ACCEPT);
} else {
itti_msg->set_msg_type(PDU_SESSION_ESTABLISHMENT_REJECT);
}
std::shared_ptr<itti_n11_n1n2_message_transfer_response_status> i =
std::shared_ptr<itti_n11_n1n2_message_transfer_response_status>(
itti_msg);
int ret = itti_inst->send_msg(i);
if (RETURNok != ret) {
Logger::smf_n11().error(
"Could not send ITTI message %s to task TASK_SMF_APP",
i->get_msg_name());
}
curl_slist_free_all(headers);
curl_easy_cleanup(curl);
curl_mime_free(mime);
}
*/
}
//------------------------------------------------------------------------------
......@@ -364,7 +252,6 @@ void smf_n11::send_n1n2_message_transfer_request(
smf_n1_n2 smf_n1_n2_inst = { };
std::string n1_message = sm_context_res->msg.get_n1_sm_message();
std::string json_part = sm_context_res->msg.n1n2_message_transfer_data.dump();
std::string boundary = "----Boundary";
std::string body;
//add N2 content if available
......@@ -373,11 +260,11 @@ void smf_n11::send_n1n2_message_transfer_request(
if (n2_sm_found > 0) {
std::string n2_message = sm_context_res->msg.get_n2_sm_information();
//prepare the body content for Curl
create_multipart_related_content(body, json_part, boundary, n1_message,
create_multipart_related_content(body, json_part, CURL_MIME_BOUNDARY, n1_message,
n2_message);
} else {
//prepare the body content for Curl
create_multipart_related_content(body, json_part, boundary, n1_message,
create_multipart_related_content(body, json_part, CURL_MIME_BOUNDARY, n1_message,
multipart_related_content_part_e::NAS);
}
......@@ -393,8 +280,9 @@ void smf_n11::send_n1n2_message_transfer_request(
CURLcode res = { };
struct curl_slist *headers = nullptr;
//headers = curl_slist_append(headers, "charsets: utf-8");
headers = curl_slist_append(
headers, "content-type: multipart/related; boundary=----Boundary"); //TODO: update Boundary
std::string content_type = "content-type: multipart/related; boundary="
+ std::string(CURL_MIME_BOUNDARY);
headers = curl_slist_append(headers, content_type.c_str());
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
curl_easy_setopt(curl, CURLOPT_URL,
sm_context_res->msg.get_amf_url().c_str());
......@@ -423,8 +311,6 @@ void smf_n11::send_n1n2_message_transfer_request(
response_data = json::parse(*httpData.get());
} catch (json::exception &e) {
Logger::smf_n11().warn("Could not get the cause from the response");
//Set the default Cause
//response_data["cause"] = "504 Gateway Timeout";
}
Logger::smf_n11().debug("Response from AMF, Http Code: %d", httpCode);
......@@ -436,6 +322,108 @@ void smf_n11::send_n1n2_message_transfer_request(
}
//------------------------------------------------------------------------------
void smf_n11::send_n1n2_message_transfer_request(
std::shared_ptr<itti_n11_session_report_request> report_msg) {
Logger::smf_n11().debug(
"Send Communication_N1N2MessageTransfer to AMF (Network-initiated Service Request)");
smf_n1_n2 smf_n1_n2_inst = { };
std::string n2_message = report_msg->res.get_n2_sm_information();
std::string json_part = report_msg->res.n1n2_message_transfer_data.dump();
std::string body;
//add N1 content if available
auto n1_sm_found = report_msg->res.n1n2_message_transfer_data.count(
"n1MessageContainer");
if (n1_sm_found > 0) {
std::string n1_message = report_msg->res.get_n1_sm_message();
//prepare the body content for Curl
create_multipart_related_content(body, json_part, CURL_MIME_BOUNDARY, n1_message,
n2_message);
} else {
create_multipart_related_content(body, json_part, CURL_MIME_BOUNDARY, n2_message,
multipart_related_content_part_e::NGAP);
}
unsigned int str_len = body.length();
char *data = (char*) malloc(str_len + 1);
memset(data, 0, str_len + 1);
memcpy((void*) data, (void*) body.c_str(), str_len);
curl_global_init(CURL_GLOBAL_ALL);
CURL *curl = curl_easy_init();
if (curl) {
CURLcode res = { };
struct curl_slist *headers = nullptr;
//headers = curl_slist_append(headers, "charsets: utf-8");
std::string content_type = "content-type: multipart/related; boundary="
+ std::string(CURL_MIME_BOUNDARY);
headers = curl_slist_append(headers, content_type.c_str());
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
curl_easy_setopt(curl, CURLOPT_URL, report_msg->res.get_amf_url().c_str());
curl_easy_setopt(curl, CURLOPT_HTTPGET, 1);
curl_easy_setopt(curl, CURLOPT_TIMEOUT_MS, AMF_CURL_TIMEOUT_MS);
curl_easy_setopt(curl, CURLOPT_INTERFACE, smf_cfg.sbi.if_name.c_str());
// Response information.
long httpCode = { 0 };
std::unique_ptr<std::string> httpData(new std::string());
// Hook up data handling function
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, &callback);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, httpData.get());
curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, body.length());
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, data);
res = curl_easy_perform(curl);
curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &httpCode);
//get cause from the response
json response_data = { };
try {
response_data = json::parse(*httpData.get());
} catch (json::exception &e) {
Logger::smf_n11().warn("Could not get the cause from the response");
//Set the default Cause
response_data["cause"] = "504 Gateway Timeout";
}
Logger::smf_n11().debug("Response from AMF, Http Code: %d, cause %s",
httpCode, response_data["cause"].dump().c_str());
//send response to APP to process
itti_n11_n1n2_message_transfer_response_status *itti_msg =
new itti_n11_n1n2_message_transfer_response_status(TASK_SMF_N11,
TASK_SMF_APP);
itti_msg->set_response_code(httpCode);
itti_msg->set_procedure_type(
session_management_procedures_type_e::SERVICE_REQUEST_NETWORK_TRIGGERED);
itti_msg->set_cause(response_data["cause"]);
itti_msg->set_seid(report_msg->res.get_seid());
itti_msg->set_trxn_id(report_msg->res.get_trxn_id());
std::shared_ptr<itti_n11_n1n2_message_transfer_response_status> i =
std::shared_ptr<itti_n11_n1n2_message_transfer_response_status>(
itti_msg);
int ret = itti_inst->send_msg(i);
if (RETURNok != ret) {
Logger::smf_n11().error(
"Could not send ITTI message %s to task TASK_SMF_APP",
i->get_msg_name());
}
curl_slist_free_all(headers);
curl_easy_cleanup(curl);
}
curl_global_cleanup();
free_wrapper((void**) &data);
}
//------------------------------------------------------------------------------
void smf_n11::send_pdu_session_update_sm_context_response(
std::shared_ptr<itti_n11_update_sm_context_response> sm_context_res) {
......@@ -446,19 +434,18 @@ void smf_n11::send_pdu_session_update_sm_context_response(
case session_management_procedures_type_e::PDU_SESSION_TEST: {
Logger::smf_n11().debug("PDU_SESSION_TEST");
std::string boundary = "----Boundary";
std::string json_part =
sm_context_res->res.sm_context_updated_data.dump();
std::string n1_message = sm_context_res->res.get_n1_sm_message();
std::string n2_message = sm_context_res->res.get_n2_sm_information();
std::string body;
create_multipart_related_content(body, json_part, boundary, n1_message,
create_multipart_related_content(body, json_part, CURL_MIME_BOUNDARY, n1_message,
n2_message);
sm_context_res->http_response.headers()
.add<Pistache::Http::Header::ContentType>(
Pistache::Http::Mime::MediaType(
"multipart/related; boundary=" + boundary));
"multipart/related; boundary=" + std::string(CURL_MIME_BOUNDARY)));
sm_context_res->http_response.send(Pistache::Http::Code::Ok, body);
}
break;
......@@ -478,19 +465,18 @@ void smf_n11::send_pdu_session_update_sm_context_response(
case session_management_procedures_type_e::PDU_SESSION_MODIFICATION_UE_INITIATED_STEP1: {
Logger::smf_n11().info("PDU_SESSION_MODIFICATION_UE_INITIATED (step 1)");
std::string boundary = "----Boundary";
std::string json_part =
sm_context_res->res.sm_context_updated_data.dump();
std::string n1_message = sm_context_res->res.get_n1_sm_message();
std::string n2_message = sm_context_res->res.get_n2_sm_information();
std::string body;
create_multipart_related_content(body, json_part, boundary, n1_message,
create_multipart_related_content(body, json_part, CURL_MIME_BOUNDARY, n1_message,
n2_message);
sm_context_res->http_response.headers()
.add<Pistache::Http::Header::ContentType>(
Pistache::Http::Mime::MediaType(
"multipart/related; boundary=" + boundary));
"multipart/related; boundary=" + std::string(CURL_MIME_BOUNDARY)));
sm_context_res->http_response.send(Pistache::Http::Code::Ok, body);
}
......@@ -511,18 +497,17 @@ void smf_n11::send_pdu_session_update_sm_context_response(
case session_management_procedures_type_e::SERVICE_REQUEST_UE_TRIGGERED_STEP1: {
Logger::smf_n11().info("SERVICE_REQUEST_UE_TRIGGERED (step 1)");
std::string boundary = "----Boundary";
std::string json_part =
sm_context_res->res.sm_context_updated_data.dump();
std::string n2_message = sm_context_res->res.get_n2_sm_information();
std::string body;
create_multipart_related_content(body, json_part, boundary, n2_message,
create_multipart_related_content(body, json_part, CURL_MIME_BOUNDARY, n2_message,
multipart_related_content_part_e::NGAP);
sm_context_res->http_response.headers()
.add<Pistache::Http::Header::ContentType>(
Pistache::Http::Mime::MediaType(
"multipart/related; boundary=" + boundary));
"multipart/related; boundary=" + std::string(CURL_MIME_BOUNDARY)));
sm_context_res->http_response.send(Pistache::Http::Code::Ok, body);
}
......@@ -544,19 +529,18 @@ void smf_n11::send_pdu_session_update_sm_context_response(
case session_management_procedures_type_e::PDU_SESSION_RELEASE_UE_REQUESTED_STEP1: {
Logger::smf_n11().info("PDU_SESSION_RELEASE_UE_REQUESTED (step 1)");
std::string boundary = "----Boundary";
std::string json_part =
sm_context_res->res.sm_context_updated_data.dump();
std::string n1_message = sm_context_res->res.get_n1_sm_message();
std::string n2_message = sm_context_res->res.get_n2_sm_information();
std::string body;
create_multipart_related_content(body, json_part, boundary, n1_message,
create_multipart_related_content(body, json_part, CURL_MIME_BOUNDARY, n1_message,
n2_message);
sm_context_res->http_response.headers()
.add<Pistache::Http::Header::ContentType>(
Pistache::Http::Mime::MediaType(
"multipart/related; boundary=" + boundary));
"multipart/related; boundary=" + std::string(CURL_MIME_BOUNDARY)));
sm_context_res->http_response.send(Pistache::Http::Code::Ok, body);
}
break;
......@@ -583,7 +567,7 @@ void smf_n11::send_pdu_session_update_sm_context_response(
//------------------------------------------------------------------------------
void smf_n11::send_pdu_session_update_sm_context_response(
Pistache::Http::ResponseWriter &httpResponse,
oai::smf_server::model::SmContextUpdateError &smContextUpdateError,
const oai::smf_server::model::SmContextUpdateError &smContextUpdateError,
Pistache::Http::Code code) {
Logger::smf_n11().debug("Send PDUSession_UpdateSMContext Response to AMF.");
......@@ -597,57 +581,52 @@ void smf_n11::send_pdu_session_update_sm_context_response(
} else {
httpResponse.send(code);
}
}
//------------------------------------------------------------------------------
void smf_n11::send_pdu_session_update_sm_context_response(
Pistache::Http::ResponseWriter &httpResponse,
oai::smf_server::model::SmContextUpdateError &smContextUpdateError,
const oai::smf_server::model::SmContextUpdateError &smContextUpdateError,
Pistache::Http::Code code, std::string &n1_sm_msg) {
Logger::smf_n11().debug("Send PDUSession_UpdateSMContext Response to AMF.");
std::string boundary = "----Boundary";
nlohmann::json json_part = { };
to_json(json_part, smContextUpdateError);
std::string json_str = json_part.dump();
std::string body;
create_multipart_related_content(body, json_str, boundary, n1_sm_msg,
create_multipart_related_content(body, json_str, CURL_MIME_BOUNDARY, n1_sm_msg,
multipart_related_content_part_e::NAS);
httpResponse.headers().add<Pistache::Http::Header::ContentType>(
Pistache::Http::Mime::MediaType(
"multipart/related; boundary=" + boundary));
"multipart/related; boundary=" + std::string(CURL_MIME_BOUNDARY)));
httpResponse.send(code, body);
}
//------------------------------------------------------------------------------
void smf_n11::send_pdu_session_create_sm_context_response(
Pistache::Http::ResponseWriter &httpResponse,
oai::smf_server::model::SmContextCreateError &smContextCreateError,
const oai::smf_server::model::SmContextCreateError &smContextCreateError,
Pistache::Http::Code code, std::string &n1_sm_msg) {
Logger::smf_n11().debug("Send PDUSession_CreateSMContext Response to AMF.");
std::string boundary = "----Boundary";
nlohmann::json json_part = { };
to_json(json_part, smContextCreateError);
std::string json_str = json_part.dump();
std::string body;
create_multipart_related_content(body, json_str, boundary, n1_sm_msg,
create_multipart_related_content(body, json_str, CURL_MIME_BOUNDARY, n1_sm_msg,
multipart_related_content_part_e::NAS);
httpResponse.headers().add<Pistache::Http::Header::ContentType>(
Pistache::Http::Mime::MediaType(
"multipart/related; boundary=" + boundary));
"multipart/related; boundary=" + std::string(CURL_MIME_BOUNDARY)));
httpResponse.send(code, body);
}
//------------------------------------------------------------------------------
void smf_n11::send_pdu_session_update_sm_context_response(
Pistache::Http::ResponseWriter &httpResponse,
oai::smf_server::model::SmContextUpdatedData &smContextUpdatedData,
const oai::smf_server::model::SmContextUpdatedData &smContextUpdatedData,
Pistache::Http::Code code) {
Logger::smf_n11().debug("Send PDUSession_UpdateSMContext Response to AMF.");
nlohmann::json json_data = { };
......@@ -659,13 +638,12 @@ void smf_n11::send_pdu_session_update_sm_context_response(
} else {
httpResponse.send(code);
}
}
//------------------------------------------------------------------------------
void smf_n11::send_pdu_session_create_sm_context_response(
Pistache::Http::ResponseWriter &httpResponse,
oai::smf_server::model::SmContextCreatedData &smContextCreatedData,
const oai::smf_server::model::SmContextCreatedData &smContextCreatedData,
Pistache::Http::Code code) {
Logger::smf_n11().debug("Send PDUSession_CreateSMContext Response to AMF.");
nlohmann::json json_data = { };
......@@ -677,7 +655,6 @@ void smf_n11::send_pdu_session_create_sm_context_response(
} else {
httpResponse.send(code);
}
}
//------------------------------------------------------------------------------
......@@ -696,7 +673,7 @@ void smf_n11::send_pdu_session_release_sm_context_response(
//------------------------------------------------------------------------------
void smf_n11::send_pdu_session_release_sm_context_response(
Pistache::Http::ResponseWriter &httpResponse,
oai::smf_server::model::ProblemDetails &problem,
const oai::smf_server::model::ProblemDetails &problem,
Pistache::Http::Code code) {
Logger::smf_n11().debug("Send PDUSession_ReleaseSMContext Response to AMF.");
......@@ -713,10 +690,10 @@ void smf_n11::send_pdu_session_release_sm_context_response(
//------------------------------------------------------------------------------
void smf_n11::create_multipart_related_content(std::string &body,
std::string &json_part,
std::string &boundary,
std::string &n1_message,
std::string &n2_message) {
const std::string &json_part,
const std::string boundary,
const std::string &n1_message,
const std::string &n2_message) {
//format string as hex
unsigned char *n1_msg_hex = smf_app_inst->format_string_as_hex(n1_message);
......@@ -734,8 +711,6 @@ void smf_n11::create_multipart_related_content(std::string &body,
+ CRLF);
body.append(CRLF);
body.append(std::string((char*) n1_msg_hex, n1_message.length() / 2) + CRLF);
//body.append(n1_message + CRLF);
body.append("--" + boundary + CRLF);
body.append(
"Content-Type: application/vnd.3gpp.ngap" + CRLF + "Content-Id: n2SmMsg"
......@@ -747,8 +722,8 @@ void smf_n11::create_multipart_related_content(std::string &body,
//------------------------------------------------------------------------------
void smf_n11::create_multipart_related_content(
std::string &body, std::string &json_part, std::string &boundary,
std::string &message, multipart_related_content_part_e content_type) {
std::string &body, const std::string &json_part, const std::string boundary,
const std::string &message, const multipart_related_content_part_e content_type) {
//format string as hex
unsigned char *msg_hex = smf_app_inst->format_string_as_hex(message);
......
......@@ -67,6 +67,14 @@ class smf_n11 {
void send_n1n2_message_transfer_request(
std::shared_ptr<itti_nx_trigger_pdu_session_modification> sm_context_res);
/*
* Send N1N2 Message Transfer Request to AMF
* @param [std::shared_ptr<itti_n11_session_report_request>] n11_msg: Content of message to be sent
* @return void
*/
void send_n1n2_message_transfer_request(
std::shared_ptr<itti_n11_session_report_request> report_msg);
/*
* Send update session response to AMF
* @param [std::shared_ptr<itti_n11_update_sm_context_response> sm_context_res] sm_context_res
......@@ -86,75 +94,75 @@ class smf_n11 {
/*
* Send update session response to AMF
* @param [Pistache::Http::ResponseWriter] httpResponse
* @param [ oai::smf_server::model::SmContextUpdateError] SmContextUpdateError
* @param [const oai::smf_server::model::SmContextUpdateError] SmContextUpdateError
* @param [Pistache::Http::Code] code, response code
* @return void
*/
void send_pdu_session_update_sm_context_response(
Pistache::Http::ResponseWriter &httpResponse,
oai::smf_server::model::SmContextUpdateError &smContextUpdateError,
const oai::smf_server::model::SmContextUpdateError &smContextUpdateError,
Pistache::Http::Code code);
/*
* Send Update session response to AMF
* @param [Pistache::Http::ResponseWriter] httpResponse
* @param [ oai::smf_server::model::SmContextUpdatedData] smContextUpdatedData
* @param [const oai::smf_server::model::SmContextUpdatedData] smContextUpdatedData
* @param [Pistache::Http::Code] code, response code
* @return void
*/
void send_pdu_session_update_sm_context_response(
Pistache::Http::ResponseWriter &httpResponse,
oai::smf_server::model::SmContextUpdatedData &smContextUpdatedData,
const oai::smf_server::model::SmContextUpdatedData &smContextUpdatedData,
Pistache::Http::Code code);
/*
* Send create session response to AMF
* @param [Pistache::Http::ResponseWriter] httpResponse
* @param [ oai::smf_server::model::SmContextCreateError] smContextCreateError
* @param [const oai::smf_server::model::SmContextCreateError] smContextCreateError
* @param [Pistache::Http::Code] code, response code
* @return void
*/
void send_pdu_session_create_sm_context_response(
Pistache::Http::ResponseWriter &httpResponse,
oai::smf_server::model::SmContextCreateError &smContextCreateError,
const oai::smf_server::model::SmContextCreateError &smContextCreateError,
Pistache::Http::Code code);
/*
* Send create session response to AMF
* @param [Pistache::Http::ResponseWriter] httpResponse
* @param [ oai::smf_server::model::SmContextCreateError] smContextCreateError
* @param [const oai::smf_server::model::SmContextCreateError] smContextCreateError
* @param [Pistache::Http::Code] code, response code
* @param [std::string] n1_sm_msg, N1 SM message content
* @return void
*/
void send_pdu_session_create_sm_context_response(
Pistache::Http::ResponseWriter &httpResponse,
oai::smf_server::model::SmContextCreateError &smContextCreateError,
const oai::smf_server::model::SmContextCreateError &smContextCreateError,
Pistache::Http::Code code, std::string &n1_sm_msg);
/*
* Send update session response to AMF
* @param [Pistache::Http::ResponseWriter] httpResponse
* @param [ oai::smf_server::model::SmContextUpdateError] smContextUpdateError
* @param [const oai::smf_server::model::SmContextUpdateError] smContextUpdateError
* @param [Pistache::Http::Code] code, response code
* @param [std::string] n1_sm_msg, N1 SM message content
* @return void
*/
void send_pdu_session_update_sm_context_response(
Pistache::Http::ResponseWriter &httpResponse,
oai::smf_server::model::SmContextUpdateError &smContextUpdateError,
const oai::smf_server::model::SmContextUpdateError &smContextUpdateError,
Pistache::Http::Code code, std::string &n1_sm_msg);
/*
* Send create session response to AMF
* @param [Pistache::Http::ResponseWriter] httpResponse
* @param [ oai::smf_server::model::SmContextCreatedData] smContextCreatedData
* @param [const oai::smf_server::model::SmContextCreatedData] smContextCreatedData
* @param [Pistache::Http::Code] code, response code
* @return void
*/
void send_pdu_session_create_sm_context_response(
Pistache::Http::ResponseWriter &httpResponse,
oai::smf_server::model::SmContextCreatedData &smContextCreatedData,
const oai::smf_server::model::SmContextCreatedData &smContextCreatedData,
Pistache::Http::Code code);
/*
......@@ -169,13 +177,13 @@ class smf_n11 {
/*
* Send release session response to AMF
* @param [Pistache::Http::ResponseWriter] httpResponse
* @param [oai::smf_server::model::ProblemDetails] problem
* @param [const oai::smf_server::model::ProblemDetails] problem
* @param [Pistache::Http::Code] code, response code
* @return void
*/
void send_pdu_session_release_sm_context_response(
Pistache::Http::ResponseWriter &httpResponse,
oai::smf_server::model::ProblemDetails &problem,
const oai::smf_server::model::ProblemDetails &problem,
Pistache::Http::Code code);
/*
......@@ -188,10 +196,10 @@ class smf_n11 {
* @return void
*/
void create_multipart_related_content(std::string &body,
std::string &json_part,
std::string &boundary,
std::string &n1_message,
std::string &n2_message);
const std::string &json_part,
const std::string boundary,
const std::string &n1_message,
const std::string &n2_message);
/*
* Create HTTP body content for multipart/related message
......@@ -203,8 +211,8 @@ class smf_n11 {
* @return void
*/
void create_multipart_related_content(
std::string &body, std::string &json_part, std::string &boundary,
std::string &message, multipart_related_content_part_e content_type);
std::string &body, const std::string &json_part, const std::string boundary,
const std::string &message, const multipart_related_content_part_e content_type);
};
......
......@@ -415,8 +415,7 @@ void smf_n1_n2::create_n1_sm_container(pdu_session_msg &msg,
//1- PDU Session Update SM Context Response (PDU Session Modification UE-Initiated procedure - step 1)
//2- N1N2MessageTransfer Request (PDU Session Modification SMF-Requested, step 1 (from SMF to AMF)) ​
Logger::smf_app().debug(
"[Create N1 SM Message] PDU Session Modification Command");
Logger::smf_app().debug("PDU Session Modification Command");
//case 1 (case2: need to be verified?)
pdu_session_update_sm_context_response &sm_context_res =
static_cast<pdu_session_update_sm_context_response&>(msg);
......@@ -542,8 +541,7 @@ void smf_n1_n2::create_n1_sm_container(pdu_session_msg &msg,
//1 - PDU Session Update SM Context Response (PDU Session Release UE-Initiated, step 1)
//2 - N1N2MessageTransfer Request (PDU Session Release SMF-Requested, step 1)
Logger::smf_app().debug(
"[Create N1 SM Message] PDU Session Release Command");
Logger::smf_app().debug("PDU Session Release Command");
//case 1 (case2: need to be verified?)
pdu_session_update_sm_context_response &sm_context_res =
static_cast<pdu_session_update_sm_context_response&>(msg);
......@@ -567,9 +565,8 @@ void smf_n1_n2::create_n1_sm_container(pdu_session_msg &msg,
//_5GSMCongestionReattemptIndicator
// ExtendedProtocolConfigurationOptions
Logger::smf_app().debug("SM MSG, 5GSM Cause: 0x%x, %d",
sm_msg->pdu_session_release_command._5gsmcause,
static_cast<uint8_t>(sm_cause));
Logger::smf_app().debug("SM message, 5GSM Cause: 0x%x",
sm_msg->pdu_session_release_command._5gsmcause);
//Encode NAS message
bytes = nas_message_encode(data, &nas_msg,
......@@ -750,6 +747,13 @@ void smf_n1_n2::create_n2_sm_information(pdu_session_msg &msg,
pduSessionAggregateMaximumBitRate);
//UPTransportLayerInformation
fteid_t ul_fteid = { };
ul_fteid.interface_type = qos_flow.ul_fteid.interface_type;
ul_fteid.v4 = qos_flow.ul_fteid.v4;
ul_fteid.teid_gre_key = htonl(qos_flow.ul_fteid.teid_gre_key);
ul_fteid.ipv4_address = qos_flow.ul_fteid.ipv4_address;
Ngap_PDUSessionResourceSetupRequestTransferIEs_t *upTransportLayerInformation =
nullptr;
upTransportLayerInformation =
......@@ -774,7 +778,7 @@ void smf_n1_n2::create_n2_sm_information(pdu_session_msg &msg,
memcpy(
upTransportLayerInformation->value.choice.UPTransportLayerInformation
.choice.gTPTunnel->transportLayerAddress.buf,
&qos_flow.ul_fteid.ipv4_address, 4);
&ul_fteid.ipv4_address, 4);
upTransportLayerInformation->value.choice.UPTransportLayerInformation
.choice.gTPTunnel->transportLayerAddress.bits_unused = 0;
......@@ -786,7 +790,7 @@ void smf_n1_n2::create_n2_sm_information(pdu_session_msg &msg,
memcpy(
upTransportLayerInformation->value.choice.UPTransportLayerInformation
.choice.gTPTunnel->gTP_TEID.buf,
&qos_flow.ul_fteid.teid_gre_key, sizeof(struct in_addr));
&ul_fteid.teid_gre_key, sizeof(struct in_addr));
ASN_SEQUENCE_ADD(&ngap_IEs->protocolIEs.list,
upTransportLayerInformation);
......@@ -868,6 +872,10 @@ void smf_n1_n2::create_n2_sm_information(pdu_session_msg &msg,
ngap_QosFlowSetupRequestItem);
ASN_SEQUENCE_ADD(&ngap_IEs->protocolIEs.list, qosFlowSetupRequestList);
Logger::smf_app().info(
"QoS parameters: QFI %d, ARP priority level %d, qos_flow.qos_profile.arp.preempt_cap %s, qos_flow.qos_profile.arp.preempt_vuln %s",
qos_flow.qfi.qfi, qos_flow.qos_profile.arp.priority_level,qos_flow.qos_profile.arp.preempt_cap.c_str(), qos_flow.qos_profile.arp.preempt_vuln.c_str());
//encode
size_t buffer_size = BUF_LEN;
char *buffer = (char*) calloc(1, buffer_size);
......@@ -925,7 +933,7 @@ void smf_n1_n2::create_n2_sm_information(pdu_session_msg &msg,
//2 - N1N2MessageTransfer Request (PDU Session Modification procedure, SMF-requested, step 1)
Logger::smf_app().debug(
"[Create N2 SM Information] NGAP PDU Session Resource Modify Request Transfer");
"NGAP PDU Session Resource Modify Request Transfer");
pdu_session_update_sm_context_response &sm_context_res =
static_cast<pdu_session_update_sm_context_response&>(msg);
......@@ -935,16 +943,17 @@ void smf_n1_n2::create_n2_sm_information(pdu_session_msg &msg,
sm_context_res.get_all_qos_flow_context_updateds(qos_flows);
for (std::map<uint8_t, qos_flow_context_updated>::iterator it = qos_flows
.begin(); it != qos_flows.end(); ++it)
Logger::smf_app().debug("qos_flow_context_updated qfi %d", it->first);
Logger::smf_app().debug("QoS flow context to be updated with QFI %d",
it->first);
//TODO: support only 1 qos flow
qos_flow_context_updated qos_flow = qos_flows.begin()->second;
Logger::smf_app().debug(
"QoS Flow, UL gTP_TEID " "0x%" PRIx32 ", UL IP Address %s ",
"QoS Flow, UL F-TEID ID " "0x%" PRIx32 ", IP Address %s ",
qos_flow.ul_fteid.teid_gre_key,
conv::toString(qos_flow.ul_fteid.ipv4_address).c_str());
Logger::smf_app().debug(
"QoS Flow, DL gTP_TEID " "0x%" PRIx32 ", DL IP Address %s",
"QoS Flow, DL F-TEID ID" "0x%" PRIx32 ", IP Address %s",
qos_flow.dl_fteid.teid_gre_key,
conv::toString(qos_flow.dl_fteid.ipv4_address).c_str());
......@@ -994,6 +1003,18 @@ void smf_n1_n2::create_n2_sm_information(pdu_session_msg &msg,
//Ngap_UL_NGU_UP_TNLModifyList_t (included if the PDU Session modification was requested by the UE for a
//PDU Session that has no established User Plane resources)
fteid_t ul_fteid = { };
ul_fteid.interface_type = qos_flow.ul_fteid.interface_type;
ul_fteid.v4 = qos_flow.ul_fteid.v4;
ul_fteid.teid_gre_key = htonl(qos_flow.ul_fteid.teid_gre_key);
ul_fteid.ipv4_address = qos_flow.ul_fteid.ipv4_address;
fteid_t dl_fteid = { };
dl_fteid.interface_type = qos_flow.dl_fteid.interface_type;
dl_fteid.v4 = qos_flow.dl_fteid.v4;
dl_fteid.teid_gre_key = htonl(qos_flow.dl_fteid.teid_gre_key);
dl_fteid.ipv4_address = qos_flow.dl_fteid.ipv4_address;
Ngap_PDUSessionResourceModifyRequestTransferIEs_t *ul_NGU_UP_TNLModifyList =
nullptr;
ul_NGU_UP_TNLModifyList =
......@@ -1016,7 +1037,7 @@ void smf_n1_n2::create_n2_sm_information(pdu_session_msg &msg,
memcpy(
ngap_UL_NGU_UP_TNLModifyItem->uL_NGU_UP_TNLInformation.choice
.gTPTunnel->transportLayerAddress.buf,
&qos_flow.ul_fteid.ipv4_address, 4);
&ul_fteid.ipv4_address, 4);
ngap_UL_NGU_UP_TNLModifyItem->uL_NGU_UP_TNLInformation.choice.gTPTunnel
->transportLayerAddress.size = 4;
ngap_UL_NGU_UP_TNLModifyItem->uL_NGU_UP_TNLInformation.choice.gTPTunnel
......@@ -1030,7 +1051,7 @@ void smf_n1_n2::create_n2_sm_information(pdu_session_msg &msg,
memcpy(
ngap_UL_NGU_UP_TNLModifyItem->uL_NGU_UP_TNLInformation.choice
.gTPTunnel->gTP_TEID.buf,
&qos_flow.ul_fteid.teid_gre_key, sizeof(struct in_addr));
&ul_fteid.teid_gre_key, sizeof(struct in_addr));
ngap_UL_NGU_UP_TNLModifyItem->dL_NGU_UP_TNLInformation.present =
Ngap_UPTransportLayerInformation_PR_gTPTunnel;
......@@ -1041,7 +1062,7 @@ void smf_n1_n2::create_n2_sm_information(pdu_session_msg &msg,
memcpy(
ngap_UL_NGU_UP_TNLModifyItem->dL_NGU_UP_TNLInformation.choice
.gTPTunnel->transportLayerAddress.buf,
&qos_flow.dl_fteid.ipv4_address, 4);
&dl_fteid.ipv4_address, 4);
ngap_UL_NGU_UP_TNLModifyItem->dL_NGU_UP_TNLInformation.choice.gTPTunnel
->transportLayerAddress.size = 4;
ngap_UL_NGU_UP_TNLModifyItem->dL_NGU_UP_TNLInformation.choice.gTPTunnel
......@@ -1055,7 +1076,7 @@ void smf_n1_n2::create_n2_sm_information(pdu_session_msg &msg,
memcpy(
ngap_UL_NGU_UP_TNLModifyItem->dL_NGU_UP_TNLInformation.choice
.gTPTunnel->gTP_TEID.buf,
&qos_flow.dl_fteid.teid_gre_key, 4);
&dl_fteid.teid_gre_key, 4);
ASN_SEQUENCE_ADD(
&ul_NGU_UP_TNLModifyList->value.choice.UL_NGU_UP_TNLModifyList.list,
ngap_UL_NGU_UP_TNLModifyItem);
......@@ -1533,7 +1554,7 @@ void smf_n1_n2::create_n2_sm_information(pdu_session_msg &msg,
//------------------------------------------------------------------------------
int smf_n1_n2::decode_n1_sm_container(nas_message_t &nas_msg,
std::string &n1_sm_msg) {
const std::string &n1_sm_msg) {
Logger::smf_app().info("Decode NAS message from N1 SM Container.");
//step 1. Decode NAS message (for instance, ... only served as an example)
......@@ -1571,7 +1592,7 @@ int smf_n1_n2::decode_n1_sm_container(nas_message_t &nas_msg,
//---------------------------------------------------------------------------------------------
int smf_n1_n2::decode_n2_sm_information(
std::shared_ptr<Ngap_PDUSessionResourceSetupResponseTransfer_t> &ngap_IE,
std::string &n2_sm_info) {
const std::string &n2_sm_info) {
Logger::smf_app().info(
"Decode NGAP message (PDUSessionResourceSetupResponseTransfer) from N2 SM Information");
unsigned int data_len = n2_sm_info.length();
......@@ -1606,7 +1627,7 @@ int smf_n1_n2::decode_n2_sm_information(
//---------------------------------------------------------------------------------------------
int smf_n1_n2::decode_n2_sm_information(
std::shared_ptr<Ngap_PDUSessionResourceModifyResponseTransfer_t> &ngap_IE,
std::string &n2_sm_info) {
const std::string &n2_sm_info) {
Logger::smf_app().info(
"Decode NGAP message (Ngap_PDUSessionResourceModifyResponseTransfer) from N2 SM Information");
......@@ -1636,7 +1657,7 @@ int smf_n1_n2::decode_n2_sm_information(
//---------------------------------------------------------------------------------------------
int smf_n1_n2::decode_n2_sm_information(
std::shared_ptr<Ngap_PDUSessionResourceReleaseResponseTransfer_t> &ngap_IE,
std::string &n2_sm_info) {
const std::string &n2_sm_info) {
Logger::smf_app().info(
"Decode NGAP message (Ngap_PDUSessionResourceReleaseResponseTransfer) from N2 SM Information");
......@@ -1663,3 +1684,34 @@ int smf_n1_n2::decode_n2_sm_information(
}
//---------------------------------------------------------------------------------------------
int smf_n1_n2::decode_n2_sm_information(
std::shared_ptr<Ngap_PDUSessionResourceSetupUnsuccessfulTransfer_t> &ngap_IE,
const std::string &n2_sm_info) {
Logger::smf_app().info(
"Decode NGAP message (Ngap_PDUSessionResourceSetupUnsuccessfulTransfer) from N2 SM Information");
unsigned int data_len = n2_sm_info.length();
unsigned char *data = (unsigned char*) malloc(data_len + 1);
memset(data, 0, data_len + 1);
memcpy((void*) data, (void*) n2_sm_info.c_str(), data_len);
//Ngap_PDUSessionResourceSetupUnsuccessfulTransfer
asn_dec_rval_t rc = asn_decode(
nullptr, ATS_ALIGNED_CANONICAL_PER,
&asn_DEF_Ngap_PDUSessionResourceSetupUnsuccessfulTransfer,
(void**) &ngap_IE, (void*) data, data_len);
//free memory
free_wrapper((void**) &data);
if (rc.code != RC_OK) {
Logger::smf_app().warn("asn_decode failed with code %d", rc.code);
return RETURNerror ;
}
return RETURNok ;
}
......@@ -57,6 +57,7 @@ extern "C" {
#include "Ngap_PDUSessionResourceSetupResponseTransfer.h"
#include "Ngap_PDUSessionResourceModifyResponseTransfer.h"
#include "Ngap_PDUSessionResourceReleaseResponseTransfer.h"
#include "Ngap_PDUSessionResourceSetupUnsuccessfulTransfer.h"
}
namespace smf {
......@@ -97,20 +98,20 @@ class smf_n1_n2 {
/*
* Decode N1 SM Container into the NAS mesasge (using NAS lib)
* @param [nas_message_t&] nas_msg Store NAS message after decoded
* @param [std::string&] n1_sm_msg N1 SM Container from AMF
* @param [const std::string&] n1_sm_msg N1 SM Container
* @return status of the decode process
*/
int decode_n1_sm_container(nas_message_t &nas_msg, std::string &n1_sm_msg);
int decode_n1_sm_container(nas_message_t &nas_msg, const std::string &n1_sm_msg);
/*
* Decode N2 SM Information Ngap_PDUSessionResourceSetupResponseTransfer
* @param [std::shared_ptr<Ngap_PDUSessionResourceSetupResponseTransfer_t>&] ngap_IE Store decoded NGAP message
* @param [std::string&] n2_sm_info N2 SM Information
* @param [const std::string&] n2_sm_info N2 SM Information
* @return status of the decode process
*/
int decode_n2_sm_information(
std::shared_ptr<Ngap_PDUSessionResourceSetupResponseTransfer_t> &ngap_IE,
std::string &n2_sm_info);
const std::string &n2_sm_info);
/*
* Decode N2 SM Information Ngap_PDUSessionResourceModifyResponseTransfer_t
......@@ -120,7 +121,7 @@ class smf_n1_n2 {
*/
int decode_n2_sm_information(
std::shared_ptr<Ngap_PDUSessionResourceModifyResponseTransfer_t> &ngap_IE,
std::string &n2_sm_info);
const std::string &n2_sm_info);
/*
* Decode N2 SM Information Ngap_PDUSessionResourceReleaseResponseTransfer_t
......@@ -130,7 +131,18 @@ class smf_n1_n2 {
*/
int decode_n2_sm_information(
std::shared_ptr<Ngap_PDUSessionResourceReleaseResponseTransfer_t> &ngap_IE,
std::string &n2_sm_info);
const std::string &n2_sm_info);
/*
* Decode N2 SM Information Ngap_PDUSessionResourceSetupUnsuccessfulTransfer
* @param [std::shared_ptr<Ngap_PDUSessionResourceSetupUnsuccessfulTransfer_t>&] ngap_IE Store decoded NGAP message
* @param [std::string&] n2_sm_info N2 SM Information
* @return status of the decode process
*/
int decode_n2_sm_information(
std::shared_ptr<Ngap_PDUSessionResourceSetupUnsuccessfulTransfer_t> &ngap_IE,
const std::string &n2_sm_info);
};
......
......@@ -161,13 +161,13 @@ class ipv4_pool {
}
};
class apn_dynamic_pools {
class dnn_dynamic_pools {
public:
std::vector<uint32_t> ipv4_pool_ids;
std::vector<uint32_t> ipv6_pool_ids;
apn_dynamic_pools()
dnn_dynamic_pools()
:
ipv4_pool_ids(),
ipv6_pool_ids() {
......@@ -186,13 +186,13 @@ class paa_dynamic {
std::map<int32_t, ipv4_pool> ipv4_pools;
std::map<int32_t, ipv6_pool> ipv6_pools;
std::map<std::string, apn_dynamic_pools> apns;
std::map<std::string, dnn_dynamic_pools> dnns;
paa_dynamic()
:
ipv4_pools(),
ipv6_pools(),
apns() {
dnns() {
}
;
......@@ -205,7 +205,7 @@ class paa_dynamic {
paa_dynamic(paa_dynamic const&) = delete;
void operator=(paa_dynamic const&) = delete;
void add_pool(const std::string &apn_label, const int pool_id,
void add_pool(const std::string &dnn_label, const int pool_id,
const struct in_addr &first, const int range) {
if (pool_id >= 0) {
uint32_t uint32pool_id = uint32_t(pool_id);
......@@ -213,15 +213,15 @@ class paa_dynamic {
ipv4_pool pool(first, range);
ipv4_pools[uint32pool_id] = pool;
}
if (!apns.count(apn_label)) {
apn_dynamic_pools adp = { };
if (!dnns.count(dnn_label)) {
dnn_dynamic_pools adp = { };
adp.add_ipv4_pool_id(uint32pool_id);
apns[apn_label] = adp;
dnns[dnn_label] = adp;
}
}
}
void add_pool(const std::string &apn_label, const int pool_id,
void add_pool(const std::string &dnn_label, const int pool_id,
const struct in6_addr &prefix, const int prefix_len) {
if (pool_id >= 0) {
uint32_t uint32pool_id = uint32_t(pool_id);
......@@ -229,39 +229,39 @@ class paa_dynamic {
ipv6_pool pool(prefix, prefix_len);
ipv6_pools[uint32pool_id] = pool;
}
if (!apns.count(apn_label)) {
apn_dynamic_pools adp = { };
if (!dnns.count(dnn_label)) {
dnn_dynamic_pools adp = { };
adp.add_ipv6_pool_id(uint32pool_id);
apns[apn_label] = adp;
dnns[dnn_label] = adp;
}
}
}
bool get_free_paa(const std::string &apn_label, paa_t &paa) {
if (apns.count(apn_label)) {
apn_dynamic_pools &apn_pool = apns[apn_label];
bool get_free_paa(const std::string &dnn_label, paa_t &paa) {
if (dnns.count(dnn_label)) {
dnn_dynamic_pools &dnn_pool = dnns[dnn_label];
if (paa.pdn_type.pdn_type == PDN_TYPE_E_IPV4) {
for (std::vector<uint32_t>::const_iterator it4 = apn_pool.ipv4_pool_ids
.begin(); it4 != apn_pool.ipv4_pool_ids.end(); ++it4) {
for (std::vector<uint32_t>::const_iterator it4 = dnn_pool.ipv4_pool_ids
.begin(); it4 != dnn_pool.ipv4_pool_ids.end(); ++it4) {
if (ipv4_pools[*it4].alloc_address(paa.ipv4_address)) {
return true;
}
}
Logger::smf_app().warn("Could not get PAA PDN_TYPE_E_IPV4 for APN %s",
apn_label.c_str());
Logger::smf_app().warn("Could not get PAA PDN_TYPE_E_IPV4 for DNN %s",
dnn_label.c_str());
return false;
} else if (paa.pdn_type.pdn_type == PDN_TYPE_E_IPV4V6) {
bool success = false;
std::vector<uint32_t>::const_iterator it4 = { };
for (it4 = apn_pool.ipv4_pool_ids.begin();
it4 != apn_pool.ipv4_pool_ids.end(); ++it4) {
for (it4 = dnn_pool.ipv4_pool_ids.begin();
it4 != dnn_pool.ipv4_pool_ids.end(); ++it4) {
if (ipv4_pools[*it4].alloc_address(paa.ipv4_address)) {
success = true;
}
}
if (success) {
for (std::vector<uint32_t>::const_iterator it6 = apn_pool
.ipv6_pool_ids.begin(); it6 != apn_pool.ipv6_pool_ids.end();
for (std::vector<uint32_t>::const_iterator it6 = dnn_pool
.ipv6_pool_ids.begin(); it6 != dnn_pool.ipv6_pool_ids.end();
++it6) {
if (ipv6_pools[*it6].alloc_address(paa.ipv6_address)) {
return true;
......@@ -269,31 +269,31 @@ class paa_dynamic {
}
ipv4_pools[*it4].free_address(paa.ipv4_address);
}
Logger::smf_app().warn("Could not get PAA PDN_TYPE_E_IPV4V6 for APN %s",
apn_label.c_str());
Logger::smf_app().warn("Could not get PAA PDN_TYPE_E_IPV4V6 for DNN %s",
dnn_label.c_str());
return false;
} else if (paa.pdn_type.pdn_type == PDN_TYPE_E_IPV6) {
for (std::vector<uint32_t>::const_iterator it6 = apn_pool.ipv6_pool_ids
.begin(); it6 != apn_pool.ipv6_pool_ids.end(); ++it6) {
for (std::vector<uint32_t>::const_iterator it6 = dnn_pool.ipv6_pool_ids
.begin(); it6 != dnn_pool.ipv6_pool_ids.end(); ++it6) {
if (ipv6_pools[*it6].alloc_address(paa.ipv6_address)) {
return true;
}
}
Logger::smf_app().warn("Could not get PAA PDN_TYPE_E_IPV6 for APN %s",
apn_label.c_str());
Logger::smf_app().warn("Could not get PAA PDN_TYPE_E_IPV6 for DNN %s",
dnn_label.c_str());
return false;
}
}
Logger::smf_app().warn("Could not get PAA for APN %s", apn_label.c_str());
Logger::smf_app().warn("Could not get PAA for DNN %s", dnn_label.c_str());
return false;
}
bool release_paa(const std::string &apn_label, const paa_t &paa) {
if (apns.count(apn_label)) {
apn_dynamic_pools &apn_pool = apns[apn_label];
bool release_paa(const std::string &dnn_label, const paa_t &paa) {
if (dnns.count(dnn_label)) {
dnn_dynamic_pools &dnn_pool = dnns[dnn_label];
if (paa.pdn_type.pdn_type == PDN_TYPE_E_IPV4) {
for (std::vector<uint32_t>::const_iterator it4 = apn_pool.ipv4_pool_ids
.begin(); it4 != apn_pool.ipv4_pool_ids.end(); ++it4) {
for (std::vector<uint32_t>::const_iterator it4 = dnn_pool.ipv4_pool_ids
.begin(); it4 != dnn_pool.ipv4_pool_ids.end(); ++it4) {
if (ipv4_pools[*it4].free_address(paa.ipv4_address)) {
return true;
}
......@@ -302,8 +302,8 @@ class paa_dynamic {
} else if (paa.pdn_type.pdn_type == PDN_TYPE_E_IPV4V6) {
bool success = false;
std::vector<uint32_t>::const_iterator it4 = { };
for (it4 = apn_pool.ipv4_pool_ids.begin();
it4 != apn_pool.ipv4_pool_ids.end(); ++it4) {
for (it4 = dnn_pool.ipv4_pool_ids.begin();
it4 != dnn_pool.ipv4_pool_ids.end(); ++it4) {
if (ipv4_pools[*it4].free_address(paa.ipv4_address)) {
return true;
}
......@@ -313,24 +313,24 @@ class paa_dynamic {
return true;
}
}
Logger::smf_app().warn("Could not release PAA for APN %s",
apn_label.c_str());
Logger::smf_app().warn("Could not release PAA for DNN %s",
dnn_label.c_str());
return false;
}
bool release_paa(const std::string &apn_label,
bool release_paa(const std::string &dnn_label,
const struct in_addr &ipv4_address) {
if (apns.count(apn_label)) {
apn_dynamic_pools &apn_pool = apns[apn_label];
for (std::vector<uint32_t>::const_iterator it4 = apn_pool.ipv4_pool_ids
.begin(); it4 != apn_pool.ipv4_pool_ids.end(); ++it4) {
if (dnns.count(dnn_label)) {
dnn_dynamic_pools &dnn_pool = dnns[dnn_label];
for (std::vector<uint32_t>::const_iterator it4 = dnn_pool.ipv4_pool_ids
.begin(); it4 != dnn_pool.ipv4_pool_ids.end(); ++it4) {
if (ipv4_pools[*it4].free_address(ipv4_address)) {
return true;
}
}
}
Logger::smf_app().warn("Could not release PAA for APN %s",
apn_label.c_str());
Logger::smf_app().warn("Could not release PAA for DNN %s",
dnn_label.c_str());
return false;
}
......
......@@ -151,7 +151,7 @@ int session_create_sm_context_procedure::run(
pfcp::destination_interface_t destination_interface = { };
sps->generate_far_id(far_id);
apply_action.forw = 1;
apply_action.forw = 1; //forward the packets
//wys-test-add
pfcp::outer_header_creation_t outer_header_creation = { };
......@@ -662,13 +662,15 @@ int session_update_sm_context_procedure::run(
.s_addr;
update_forwarding_parameters.set(outer_header_creation);
update_far.set(update_forwarding_parameters);
apply_action.forw = 1;
apply_action.forw = 1; //forward the packets
//apply_action.nocp = 1; //notify the CP function about the arrival of a first DL packet
update_far.set(apply_action);
n4_ser->pfcp_ies.set(update_far);
send_n4 = true;
flow.far_id_dl.first = true;
flow.dl_fteid = dl_fteid;
} else {
Logger::smf_app().debug("Create FAR DL");
......@@ -691,7 +693,8 @@ int session_update_sm_context_procedure::run(
//pfcp::proxying_t proxying = {};
sps->generate_far_id(far_id);
apply_action.forw = 1;
apply_action.forw = 1; //forward the packets
//apply_action.nocp = 1; //notify the CP function about the arrival of a first DL packet
destination_interface.interface_value = pfcp::INTERFACE_VALUE_ACCESS; // ACCESS is for downlink, CORE for uplink
forwarding_parameters.set(destination_interface);
......@@ -713,6 +716,7 @@ int session_update_sm_context_procedure::run(
flow.far_id_dl.first = true;
flow.far_id_dl.second.far_id = far_id.far_id;
flow.dl_fteid = dl_fteid;
Logger::smf_app().debug("FAR DL ID " "0x%" PRIx32 " ", far_id.far_id);
}
......@@ -777,7 +781,7 @@ int session_update_sm_context_procedure::run(
pdr_id.rule_id);
} else {
Logger::smf_app().debug(
"Update FAR, PDR DL Rule Id " "0x%" PRIx16 ", 0x%" PRIx32 " ",
"Update FAR, PDR DL Rule Id " "0x%" PRIx16 ", FAR ID 0x%" PRIx32 " ",
flow.pdr_id_dl.rule_id, flow.far_id_dl.second.far_id);
/*
// Update FAR
......@@ -831,7 +835,9 @@ int session_update_sm_context_procedure::run(
}
// after a release flows
if (not flow.ul_fteid.is_zero()) {
}
if (not flow.dl_fteid.is_zero()) {
}
// may be modified
smf_qos_flow flow2 = flow;
......@@ -870,7 +876,7 @@ int session_update_sm_context_procedure::run(
far_id.far_id = flow.far_id_dl.second.far_id;
// apply_action.buff = 1;
pfcp::apply_action_t apply_action = { };
apply_action.nocp = 1;
apply_action.nocp = 1; //notify the CP function about the arrival of a first DL packet
far.set(far_id);
far.set(apply_action);
......@@ -967,63 +973,6 @@ void session_update_sm_context_procedure::handle_itti_msg(
.c_str());
switch (session_procedure_type) {
/*
case session_management_procedures_type_e::SERVICE_REQUEST_UE_TRIGGERED_STEP1: {
if (cause.cause_value == CAUSE_VALUE_REQUEST_ACCEPTED) {
Logger::smf_app().info(
"Service Request (step 1) accepted by UPF");
//delete AN Info
std::map<uint8_t, qos_flow_context_updated> qos_flow_context_to_be_updateds =
{ };
n11_triggered_pending->res.get_all_qos_flow_context_updateds(
qos_flow_context_to_be_updateds);
n11_triggered_pending->res.remove_all_qos_flow_context_updateds();
for (auto it : qos_flow_context_to_be_updateds)
Logger::smf_app().debug("QoS Flow context to be modified QFI %d",
it.first);
for (auto it : qos_flow_context_to_be_updateds) {
smf_qos_flow flow = { };
if (!sps->get_qos_flow(it.second.qfi, flow)) { //no QoS flow found
Logger::smf_app().error(
"Could not found any QoS flow with QFI %d",
it.first);
continue;
}
//if FAR DL exist -> remove it
if ((flow.far_id_dl.first) && (flow.far_id_dl.second.far_id)) {
Logger::smf_app().debug(
"FAR DL " "0x%" PRIx32 " has been removed",
flow.far_id_dl.second.far_id);
flow.far_id_dl.first = false;
flow.far_id_dl.second.far_id = 0;
}
//remove PDR DL if exist
if (flow.pdr_id_dl.rule_id) {
Logger::smf_app().debug(
"PDR DL " "0x%" PRIx16 " has been removed",
flow.pdr_id_dl.rule_id);
flow.pdr_id_dl.rule_id = 0;
}
// Update QoS Flow
smf_qos_flow flow2 = flow;
sps->add_qos_flow(flow2);
qos_flow_context_updated qcu = { };
qcu.set_cause(REQUEST_ACCEPTED);
qcu.set_qfi(pfcp::qfi_t(it.first));
qcu.set_ul_fteid(flow.ul_fteid);
qcu.set_qos_profile(flow.qos_profile);
n11_triggered_pending->res.add_qos_flow_context_updated(qcu);
}
}
}
break;
*/
case session_management_procedures_type_e::PDU_SESSION_ESTABLISHMENT_UE_REQUESTED:
case session_management_procedures_type_e::PDU_SESSION_MODIFICATION_SMF_REQUESTED:
case session_management_procedures_type_e::PDU_SESSION_MODIFICATION_AN_REQUESTED:
......@@ -1033,6 +982,9 @@ void session_update_sm_context_procedure::handle_itti_msg(
::fteid_t dl_fteid = { };
n11_trigger->req.get_dl_fteid(dl_fteid);
Logger::smf_app().debug("AN F-TEID ID" "0x%" PRIx32 ", IP Addr %s",
dl_fteid.teid_gre_key, conv::toString(dl_fteid.ipv4_address).c_str());
std::map<uint8_t, qos_flow_context_updated> qos_flow_context_to_be_updateds =
{ };
n11_triggered_pending->res.get_all_qos_flow_context_updateds(
......@@ -1193,10 +1145,6 @@ void session_update_sm_context_procedure::handle_itti_msg(
//FOR TESTING PURPOSE
case session_management_procedures_type_e::PDU_SESSION_TEST: {
//N1 SM: PDU Session Modification Command​
//N2 SM: PDU Session Resource Modify Request Transfer IE
//N1 SM
smf_n1_n2_inst.create_n1_sm_container(
n11_triggered_pending->res, PDU_SESSION_MODIFICATION_REQUEST,
......
......@@ -108,10 +108,6 @@ void create_multipart_related_content(std::string &body, std::string &json_part,
std::string &n1_message,
std::string &n2_message) {
//format string as hex
//unsigned char *n1_msg_hex = format_string_as_hex(n1_message);
//unsigned char *n2_msg_hex = format_string_as_hex(n2_message);
std::string CRLF = "\r\n";
body.append("--" + boundary + CRLF);
body.append("Content-Type: application/json" + CRLF);
......@@ -123,7 +119,6 @@ void create_multipart_related_content(std::string &body, std::string &json_part,
"Content-Type: application/vnd.3gpp.5gnas" + CRLF + "Content-Id: n1SmMsg"
+ CRLF);
body.append(CRLF);
//body.append(std::string((char*) n1_msg_hex, n1_message.length() / 2) + CRLF);
body.append(n1_message + CRLF);
body.append("--" + boundary + CRLF);
......@@ -131,7 +126,6 @@ void create_multipart_related_content(std::string &body, std::string &json_part,
"Content-Type: application/vnd.3gpp.ngap" + CRLF + "Content-Id: n2SmMsg"
+ CRLF);
body.append(CRLF);
//body.append(std::string((char*) n2_msg_hex, n2_message.length() / 2) + CRLF);
body.append(n2_message + CRLF);
body.append("--" + boundary + "--" + CRLF);
}
......@@ -141,9 +135,6 @@ void create_multipart_related_content(
std::string &body, std::string &json_part, std::string &boundary,
std::string &message, multipart_related_content_part_e content_type) {
//format string as hex
//unsigned char *msg_hex = format_string_as_hex(message);
std::string CRLF = "\r\n";
body.append("--" + boundary + CRLF);
body.append("Content-Type: application/json" + CRLF);
......@@ -161,7 +152,6 @@ void create_multipart_related_content(
+ CRLF);
}
body.append(CRLF);
//body.append(std::string((char*) msg_hex, message.length() / 2) + CRLF);
body.append(message + CRLF);
body.append("--" + boundary + "--" + CRLF);
}
......@@ -429,7 +419,6 @@ void send_pdu_session_modification_request_step1(std::string smf_ip_address) {
ENCODE_U8(buffer + size, 0x01, size); //QoS Rules
ENCODE_U8(buffer + size, 0x06, size); //QoS Rules
std::cout << "Buffer: " << std::endl;
for (int i = 0; i < size; i++) {
printf("%02x ", buffer[i]);
......@@ -1253,9 +1242,11 @@ int main(int argc, char *argv[]) {
usleep(200000);
//PDU Session Modification
send_pdu_session_modification_request_step1(smf_ip_address);
usleep(200000);
send_pdu_session_modification_request_step2(smf_ip_address);
usleep(200000);
send_pdu_session_modification_complete(smf_ip_address);
usleep(200000);
//PDU Session Release procedure
send_pdu_session_release_request(smf_ip_address);
usleep(200000);
......
/*
* https://github.com/iafonov/multipart-parser-c
*/
#include "../../utils/multipartparser.h"
#include <string.h>
#define CR '\r'
#define LF '\n'
#define SP ' '
#define HT '\t'
#define HYPHEN '-'
#define CALLBACK_NOTIFY(NAME) \
if (callbacks->on_##NAME != NULL) { \
if (callbacks->on_##NAME(parser) != 0) \
goto error; \
}
#define CALLBACK_DATA(NAME, P, S) \
if (callbacks->on_##NAME != NULL) { \
if (callbacks->on_##NAME(parser, P, S) != 0) \
goto error; \
}
enum state {
s_preamble,
s_preamble_hy_hy,
s_first_boundary,
s_header_field_start,
s_header_field,
s_header_value_start,
s_header_value,
s_header_value_cr,
s_headers_done,
s_data,
s_data_cr,
s_data_cr_lf,
s_data_cr_lf_hy,
s_data_boundary_start,
s_data_boundary,
s_data_boundary_done,
s_data_boundary_done_cr_lf,
s_data_boundary_done_hy_hy,
s_epilogue,
};
/* Header field name as defined by rfc 2616. Also lowercases them.
* field-name = token
* token = 1*<any CHAR except CTLs or tspecials>
* CTL = <any US-ASCII control character (octets 0 - 31) and DEL (127)>
* tspecials = "(" | ")" | "<" | ">" | "@"
* | "," | ";" | ":" | "\" | DQUOTE
* | "/" | "[" | "]" | "?" | "="
* | "{" | "}" | SP | HT
* DQUOTE = <US-ASCII double-quote mark (34)>
* SP = <US-ASCII SP, space (32)>
* HT = <US-ASCII HT, horizontal-tab (9)>
*/
static const char header_field_chars[256] = {
/* 0 nul 1 soh 2 stx 3 etx 4 eot 5 enq 6 ack 7 bel */
0, 0, 0, 0, 0, 0, 0, 0,
/* 8 bs 9 ht 10 nl 11 vt 12 np 13 cr 14 so 15 si */
0, 0, 0, 0, 0, 0, 0, 0,
/* 16 dle 17 dc1 18 dc2 19 dc3 20 dc4 21 nak 22 syn 23 etb */
0, 0, 0, 0, 0, 0, 0, 0,
/* 24 can 25 em 26 sub 27 esc 28 fs 29 gs 30 rs 31 us */
0, 0, 0, 0, 0, 0, 0, 0,
/* 32 sp 33 ! 34 " 35 # 36 $ 37 % 38 & 39 ' */
0, '!', 0, '#', '$', '%', '&', '\'',
/* 40 ( 41 ) 42 * 43 + 44 , 45 - 46 . 47 / */
0, 0, '*', '+', 0, '-', '.', 0,
/* 48 0 49 1 50 2 51 3 52 4 53 5 54 6 55 7 */
'0', '1', '2', '3', '4', '5', '6', '7',
/* 56 8 57 9 58 : 59 ; 60 < 61 = 62 > 63 ? */
'8', '9', 0, 0, 0, 0, 0, 0,
/* 64 @ 65 A 66 B 67 C 68 D 69 E 70 F 71 G */
0, 'A', 'B', 'C', 'D', 'E', 'F', 'G',
/* 72 H 73 I 74 J 75 K 76 L 77 M 78 N 79 O */
'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O',
/* 80 P 81 Q 82 R 83 S 84 T 85 U 86 V 87 W */
'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W',
/* 88 X 89 Y 90 Z 91 [ 92 \ 93 ] 94 ^ 95 _ */
'X', 'Y', 'Z', 0, 0, 0, '^', '_',
/* 96 ` 97 a 98 b 99 c 100 d 101 e 102 f 103 g */
'`', 'a', 'b', 'c', 'd', 'e', 'f', 'g',
/* 104 h 105 i 106 j 107 k 108 l 109 m 110 n 111 o */
'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o',
/* 112 p 113 q 114 r 115 s 116 t 117 u 118 v 119 w */
'p', 'q', 'r', 's', 't', 'u', 'v', 'w',
/* 120 x 121 y 122 z 123 { 124 | 125 } 126 ~ 127 del */
'x', 'y', 'z', 0, '|', 0, '~', 0
};
void multipartparser_init(multipartparser* parser, const char* boundary)
{
memset(parser, 0, sizeof(*parser));
//strncpy(parser->boundary, boundary, sizeof(parser->boundary));
strcpy(parser->boundary, boundary);
parser->boundary_length = strlen(parser->boundary);
parser->state = s_preamble;
}
void multipartparser_callbacks_init(multipartparser_callbacks* callbacks)
{
memset(callbacks, 0, sizeof(*callbacks));
}
size_t multipartparser_execute(multipartparser* parser,
multipartparser_callbacks* callbacks,
const char* data,
size_t size)
{
const char* mark;
const char* p;
unsigned char c;
for (p = data; p < data + size; ++p) {
c = *p;
reexecute:
switch (parser->state) {
case s_preamble:
if (c == HYPHEN)
parser->state = s_preamble_hy_hy;
// else ignore everything before first boundary
break;
case s_preamble_hy_hy:
if (c == HYPHEN)
parser->state = s_first_boundary;
else
parser->state = s_preamble;
break;
case s_first_boundary:
if (parser->index == parser->boundary_length) {
if (c != CR)
goto error;
parser->index++;
break;
}
if (parser->index == parser->boundary_length + 1) {
if (c != LF)
goto error;
CALLBACK_NOTIFY(body_begin);
CALLBACK_NOTIFY(part_begin);
parser->index = 0;
parser->state = s_header_field_start;
break;
}
if (c == parser->boundary[parser->index]) {
parser->index++;
break;
}
goto error;
case s_header_field_start:
if (c == CR) {
parser->state = s_headers_done;
break;
}
parser->state = s_header_field;
// fallthrough;
case s_header_field:
mark = p;
while (p != data + size) {
c = *p;
if (header_field_chars[c] == 0)
break;
++p;
}
if (p > mark) {
CALLBACK_DATA(header_field, mark, p - mark);
}
if (p == data + size) {
break;
}
if (c == ':') {
parser->state = s_header_value_start;
break;
}
goto error;
case s_header_value_start:
if (c == SP || c == HT) {
break;
}
parser->state = s_header_value;
// fallthrough;
case s_header_value:
mark = p;
while (p != data + size) {
c = *p;
if (c == CR) {
parser->state = s_header_value_cr;
break;
}
++p;
}
if (p > mark) {
CALLBACK_DATA(header_value, mark, p - mark);
}
break;
case s_header_value_cr:
if (c == LF) {
parser->state = s_header_field_start;
break;
}
goto error;
case s_headers_done:
if (c == LF) {
CALLBACK_NOTIFY(headers_complete);
parser->state = s_data;
break;
}
goto error;
case s_data:
mark = p;
while (p != data + size) {
c = *p;
if (c == CR) {
parser->state = s_data_cr;
break;
}
++p;
}
if (p > mark) {
CALLBACK_DATA(data, mark, p - mark);
}
break;
case s_data_cr:
if (c == LF) {
parser->state = s_data_cr_lf;
break;
}
CALLBACK_DATA(data, "\r", 1);
parser->state = s_data;
goto reexecute;
case s_data_cr_lf:
if (c == HYPHEN) {
parser->state = s_data_cr_lf_hy;
break;
}
CALLBACK_DATA(data, "\r\n", 2);
parser->state = s_data;
goto reexecute;
case s_data_cr_lf_hy:
if (c == HYPHEN) {
parser->state = s_data_boundary_start;
break;
}
CALLBACK_DATA(data, "\r\n-", 3);
parser->state = s_data;
goto reexecute;
case s_data_boundary_start:
parser->index = 0;
parser->state = s_data_boundary;
// fallthrough;
case s_data_boundary:
if (parser->index == parser->boundary_length) {
parser->index = 0;
parser->state = s_data_boundary_done;
goto reexecute;
}
if (c == parser->boundary[parser->index]) {
parser->index++;
break;
}
CALLBACK_DATA(data, parser->boundary, parser->index);
parser->state = s_data;
goto reexecute;
case s_data_boundary_done:
if (c == CR) {
parser->state = s_data_boundary_done_cr_lf;
break;
}
if (c == HYPHEN) {
parser->state = s_data_boundary_done_hy_hy;
break;
}
goto error;
case s_data_boundary_done_cr_lf:
if (c == LF) {
CALLBACK_NOTIFY(part_end);
CALLBACK_NOTIFY(part_begin);
parser->state = s_header_field_start;
break;
}
goto error;
case s_data_boundary_done_hy_hy:
if (c == HYPHEN) {
CALLBACK_NOTIFY(part_end);
CALLBACK_NOTIFY(body_end);
parser->state = s_epilogue;
break;
}
goto error;
case s_epilogue:
// Must be ignored according to rfc 1341.
break;
}
}
return size;
error:
return p - data;
}
/*
* https://github.com/iafonov/multipart-parser-c
*/
#ifndef MULTIPARTPARSER_H
#define MULTIPARTPARSER_H
#ifdef __cplusplus
extern "C" {
#endif
#include <stddef.h>
#include <stdint.h>
#include <sys/types.h>
typedef struct multipartparser multipartparser;
typedef struct multipartparser_callbacks multipartparser_callbacks;
typedef int (*multipart_cb) (multipartparser*);
typedef int (*multipart_data_cb) (multipartparser*, const char* data, size_t size);
struct multipartparser {
/** PRIVATE **/
char boundary[70];
int boundary_length;
int index;
uint16_t state;
/** PUBLIC **/
void* data;
};
struct multipartparser_callbacks {
multipart_cb on_body_begin;
multipart_cb on_part_begin;
multipart_data_cb on_header_field;
multipart_data_cb on_header_value;
multipart_cb on_headers_complete;
multipart_data_cb on_data;
multipart_cb on_part_end;
multipart_cb on_body_end;
};
void multipartparser_init(multipartparser* parser, const char* boundary);
void multipartparser_callbacks_init(multipartparser_callbacks* callbacks);
size_t multipartparser_execute(multipartparser* parser,
multipartparser_callbacks* callbacks,
const char* data,
size_t size);
#ifdef __cplusplus
}
#define BOUNDARY "----Boundary"
typedef struct part {
std::map<std::string,std::string> headers;
std::string body;
} part;
static multipartparser_callbacks g_callbacks;
static bool g_body_begin_called;
static std::string g_header_name;
static std::string g_header_value;
static std::list<part> g_parts;
static bool g_body_end_called;
static void init_globals()
{
g_body_begin_called = false;
g_header_name.clear();
g_header_value.clear();
g_parts.clear();
g_body_end_called = false;
}
static int on_body_begin(multipartparser* /*parser*/)
{
g_body_begin_called = true;
return 0;
}
static int on_part_begin(multipartparser* /*parser*/)
{
g_parts.push_back(part());
return 0;
}
static void on_header_done()
{
g_parts.back().headers[g_header_name] = g_header_value;
g_header_name.clear();
g_header_value.clear();
}
static int on_header_field(multipartparser* /*parser*/, const char* data, size_t size)
{
if (g_header_value.size() > 0)
on_header_done();
g_header_name.append(data, size);
return 0;
}
static int on_header_value(multipartparser* /*parser*/, const char* data, size_t size)
{
g_header_value.append(data, size);
return 0;
}
static int on_headers_complete(multipartparser* /*parser*/)
{
if (g_header_value.size() > 0)
on_header_done();
return 0;
}
static int on_data(multipartparser* /*parser*/, const char* data, size_t size)
{
std::string str;
//g_parts.back().body.append(data, size);
for(int i = 0;i < size; i++)
{
//printf("%02x ",data[i]);
str.push_back(data[i]);
}
g_parts.back().body.append(str);
return 0;
}
static int on_part_end(multipartparser* /*parser*/)
{
return 0;
}
static int on_body_end(multipartparser* /*parser*/)
{
g_body_end_called = true;
return 0;
}
#endif
#endif // MULTIPARTPARSER_H
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