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 = ...@@ -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} # 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}, {DNN_NI = "default"; PDN_TYPE = "IPv4"; IPV4_POOL = 0; IPV6_POOL = -1},
{APN_NI = "carrier.com"; PDN_TYPE = "IPv4"; IPV4_POOL = 1; IPV6_POOL = -1}, {DNN_NI = "carrier.com"; PDN_TYPE = "IPv4"; IPV4_POOL = 1; IPV6_POOL = -1},
{APN_NI = "apn2"; PDN_TYPE = "IPv4"; IPV4_POOL = 2; IPV6_POOL = -1}, {DNN_NI = "apn2"; PDN_TYPE = "IPv4"; IPV4_POOL = 2; IPV6_POOL = -1},
{APN_NI = "apn3"; PDN_TYPE = "IPv4"; IPV4_POOL = 3; IPV6_POOL = -1}, {DNN_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 = "apn4"; PDN_TYPE = "IPv4"; IPV4_POOL = 4; IPV6_POOL = -1}
); );
# DNS address communicated to UEs # DNS address communicated to UEs
...@@ -97,12 +97,26 @@ SMF = ...@@ -97,12 +97,26 @@ SMF =
UDM : UDM :
{ {
IPV4_ADDRESS="@UDM_IPV4_ADDRESS@"; IPV4_ADDRESS="@UDM_IPV4_ADDRESS@";
PORT = @UDM_PORT@; #should be removed (default 80) PORT = @UDM_PORT@; #should be removed (default 80)
}; };
UPF_LIST = ( UPF_LIST = (
{IPV4_ADDRESS="@UPF_IPV4_ADDRESS@" ;} {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 @@ ...@@ -43,10 +43,7 @@
#include "logger.hpp" #include "logger.hpp"
#include "Helpers.h" #include "Helpers.h"
extern "C" { #include "simple_parser.hpp"
#include "multipartparser.h"
#include "dynamic_memory_check.h"
}
namespace oai { namespace oai {
namespace smf_server { namespace smf_server {
...@@ -141,91 +138,39 @@ void IndividualSMContextApi::update_sm_context_handler( ...@@ -141,91 +138,39 @@ void IndividualSMContextApi::update_sm_context_handler(
Logger::smf_api_server().info( Logger::smf_api_server().info(
"Received a SM context update request from AMF."); "Received a SM context update request from AMF.");
Logger::smf_api_server().debug("Request body: %s\n", request.body().c_str()); 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 = { }; SmContextUpdateMessage smContextUpdateMessage = { };
//step 1. use multipartparser to decode the request //simple parser
multipartparser_callbacks_init(&g_callbacks); simple_parser sp = { };
g_callbacks.on_body_begin = &on_body_begin; sp.parse(request.body());
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); std::vector<mime_part> parts = { };
sp.get_mime_parts(parts);
uint8_t size = g_parts.size(); uint8_t size = parts.size();
Logger::smf_api_server().debug("Number of MIME parts %d", g_parts.size()); Logger::smf_api_server().debug("Number of MIME parts %d", 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());
}
// Getting the body param // Getting the body param
SmContextUpdateData smContextUpdateData = { }; SmContextUpdateData smContextUpdateData = { };
try { try {
if (size > 0) { 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 { } else {
nlohmann::json::parse(request.body().c_str()).get_to(smContextUpdateData); nlohmann::json::parse(request.body().c_str()).get_to(smContextUpdateData);
} }
smContextUpdateMessage.setJsonData(smContextUpdateData); smContextUpdateMessage.setJsonData(smContextUpdateData);
if (size > 1) { for (int i = 1; i < size; i++) {
if (smContextUpdateData.n2SmInfoIsSet()) { if (parts[i].content_type.compare("application/vnd.3gpp.5gnas") == 0) {
//N2 SM (for Session establishment, or for session modification) smContextUpdateMessage.setBinaryDataN1SmMessage(parts[i].body);
Logger::smf_api_server().debug("N2 SM information is set");
smContextUpdateMessage.setBinaryDataN2SmInformation(p1.body);
}
if (smContextUpdateData.n1SmMsgIsSet()) {
//N1 SM (for session modification, UE-initiated)
Logger::smf_api_server().debug("N1 SM message is set"); 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 // Getting the path params
auto smContextRef = request.param(":smContextRef").as<std::string>(); auto smContextRef = request.param(":smContextRef").as<std::string>();
this->update_sm_context(smContextRef, smContextUpdateMessage, response); this->update_sm_context(smContextRef, smContextUpdateMessage, response);
......
...@@ -43,8 +43,9 @@ ...@@ -43,8 +43,9 @@
#include "logger.hpp" #include "logger.hpp"
#include "Helpers.h" #include "Helpers.h"
#include "simple_parser.hpp"
extern "C" { extern "C" {
#include "multipartparser.h"
#include "dynamic_memory_check.h" #include "dynamic_memory_check.h"
} }
...@@ -85,77 +86,34 @@ void SMContextsCollectionApi::post_sm_contexts_handler( ...@@ -85,77 +86,34 @@ void SMContextsCollectionApi::post_sm_contexts_handler(
Logger::smf_api_server().debug(""); Logger::smf_api_server().debug("");
Logger::smf_api_server().info( Logger::smf_api_server().info(
"Received a SM context create request from AMF."); "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 = { }; SmContextMessage smContextMessage = { };
SmContextCreateData smContextCreateData = { }; SmContextCreateData smContextCreateData = { };
//step 1. use multipartparser to decode the request //simple parser
multipartparser_callbacks_init(&g_callbacks); simple_parser sp = { };
g_callbacks.on_body_begin = &on_body_begin; sp.parse(request.body());
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);
uint8_t size = g_parts.size(); std::vector<mime_part> parts = { };
Logger::smf_api_server().debug("Number of MIME parts %d", g_parts.size()); 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) //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, ""); response.send(Pistache::Http::Code::Bad_Request, "");
return; 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 //step 2. process the request
try { 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.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); this->post_sm_contexts(smContextMessage, response);
} catch (nlohmann::detail::exception &e) { } catch (nlohmann::detail::exception &e) {
//send a 400 error //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 { ...@@ -300,7 +300,11 @@ class itti_n11_n1n2_message_transfer_response_status : public itti_n11_msg {
dest), dest),
scid(0), scid(0),
response_code(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( itti_n11_n1n2_message_transfer_response_status(
const itti_n11_n1n2_message_transfer_response_status &i) 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 { ...@@ -308,7 +312,10 @@ class itti_n11_n1n2_message_transfer_response_status : public itti_n11_msg {
itti_n11_msg(i), itti_n11_msg(i),
scid(i.scid), scid(i.scid),
response_code(i.response_code), 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( itti_n11_n1n2_message_transfer_response_status(
const itti_n11_n1n2_message_transfer_response_status &i, 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 { ...@@ -317,7 +324,10 @@ class itti_n11_n1n2_message_transfer_response_status : public itti_n11_msg {
itti_n11_msg(i, orig, dest), itti_n11_msg(i, orig, dest),
scid(i.scid), scid(i.scid),
response_code(i.response_code), 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() { const char* get_msg_name() {
return "N11_SESSION_N1N2_MESSAGE_TRANSFER_RESPONSE_STATUS"; return "N11_SESSION_N1N2_MESSAGE_TRANSFER_RESPONSE_STATUS";
...@@ -339,10 +349,28 @@ class itti_n11_n1n2_message_transfer_response_status : public itti_n11_msg { ...@@ -339,10 +349,28 @@ class itti_n11_n1n2_message_transfer_response_status : public itti_n11_msg {
msg_type = type; 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 scid_t scid; //SM Context ID
int16_t response_code; int16_t response_code;
std::string cause; std::string cause;
uint8_t msg_type; 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 { ...@@ -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 { class itti_n11_release_sm_context_response : public itti_n11_msg {
public: public:
itti_n11_release_sm_context_response(const task_id_t orig, itti_n11_release_sm_context_response(const task_id_t orig,
const task_id_t dest, const task_id_t dest,
Pistache::Http::ResponseWriter &response) Pistache::Http::ResponseWriter &response)
: :
itti_n11_msg(N11_SESSION_RELEASE_SM_CONTEXT_RESPONSE, orig, dest), itti_n11_msg(N11_SESSION_RELEASE_SM_CONTEXT_RESPONSE, orig, dest),
http_response(response.clone()), http_response(response.clone()),
...@@ -427,5 +455,30 @@ class itti_n11_release_sm_context_response : public itti_n11_msg { ...@@ -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_ */ #endif /* ITTI_MSG_N11_HPP_INCLUDED_ */
...@@ -705,4 +705,33 @@ class itti_n4_session_report_response : public itti_n4_msg { ...@@ -705,4 +705,33 @@ class itti_n4_session_report_response : public itti_n4_msg {
pfcp::pfcp_session_report_response pfcp_ies; 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_ */ #endif /* ITTI_MSG_N4_HPP_INCLUDED_ */
...@@ -28,7 +28,6 @@ ...@@ -28,7 +28,6 @@
typedef uint64_t supi64_t; typedef uint64_t supi64_t;
#define SUPI_64_FMT "%" SCNu64 #define SUPI_64_FMT "%" SCNu64
//typedef imsi_t supi_t;
#define SUPI_DIGITS_MAX 15 #define SUPI_DIGITS_MAX 15
...@@ -110,22 +109,23 @@ enum class http_response_codes_e { ...@@ -110,22 +109,23 @@ enum class http_response_codes_e {
//From 23.502 //From 23.502
enum class session_management_procedures_type_e { enum class session_management_procedures_type_e {
PDU_SESSION_ESTABLISHMENT_UE_REQUESTED = 0, PROCEDURE_TYPE_UNKNOWN = 0,
SERVICE_REQUEST_UE_TRIGGERED_STEP1 = 1, PDU_SESSION_ESTABLISHMENT_UE_REQUESTED = 1,
SERVICE_REQUEST_UE_TRIGGERED_STEP2 = 2, SERVICE_REQUEST_UE_TRIGGERED_STEP1 = 2,
SERVICE_REQUEST_NETWORK_TRIGGERED = 3, SERVICE_REQUEST_UE_TRIGGERED_STEP2 = 3,
PDU_SESSION_MODIFICATION_UE_INITIATED_STEP1 = 4, SERVICE_REQUEST_NETWORK_TRIGGERED = 4,
PDU_SESSION_MODIFICATION_UE_INITIATED_STEP2 = 5, PDU_SESSION_MODIFICATION_UE_INITIATED_STEP1 = 5,
PDU_SESSION_MODIFICATION_UE_INITIATED_STEP3 = 6, PDU_SESSION_MODIFICATION_UE_INITIATED_STEP2 = 6,
PDU_SESSION_MODIFICATION_SMF_REQUESTED = 7, PDU_SESSION_MODIFICATION_UE_INITIATED_STEP3 = 7,
PDU_SESSION_MODIFICATION_AN_REQUESTED = 8, PDU_SESSION_MODIFICATION_SMF_REQUESTED = 8,
PDU_SESSION_RELEASE_UE_REQUESTED_STEP1 = 9, PDU_SESSION_MODIFICATION_AN_REQUESTED = 9,
PDU_SESSION_RELEASE_UE_REQUESTED_STEP2 = 10, PDU_SESSION_RELEASE_UE_REQUESTED_STEP1 = 10,
PDU_SESSION_RELEASE_UE_REQUESTED_STEP3 = 11, PDU_SESSION_RELEASE_UE_REQUESTED_STEP2 = 11,
PDU_SESSION_RELEASE_SMF_INITIATED = 12, PDU_SESSION_RELEASE_UE_REQUESTED_STEP3 = 12,
PDU_SESSION_RELEASE_AMF_INITIATED = 13, PDU_SESSION_RELEASE_SMF_INITIATED = 13,
PDU_SESSION_RELEASE_AN_INITIATED = 14, PDU_SESSION_RELEASE_AMF_INITIATED = 14,
PDU_SESSION_TEST = 15 PDU_SESSION_RELEASE_AN_INITIATED = 15,
PDU_SESSION_TEST = 16
}; };
static const std::vector<std::string> session_management_procedures_type_e2str = 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 = { ...@@ -191,6 +191,12 @@ static const std::vector<std::string> multipart_related_content_part_e2str = {
#define AMF_NUMBER_RETRIES 3 #define AMF_NUMBER_RETRIES 3
#define UDM_CURL_TIMEOUT_MS 100L #define UDM_CURL_TIMEOUT_MS 100L
#define UDM_NUMBER_RETRIES 3 #define UDM_NUMBER_RETRIES 3
constexpr auto CURL_MIME_BOUNDARY = "----Boundary";
//for N1N2 //for N1N2
#define BUF_LEN 512 #define BUF_LEN 512
//for PFCP
constexpr uint64_t SECONDS_SINCE_FIRST_EPOCH = 2208988800;
#endif #endif
...@@ -36,6 +36,7 @@ set(CN_UTILS_SRC STATIC ...@@ -36,6 +36,7 @@ set(CN_UTILS_SRC STATIC
${CMAKE_CURRENT_SOURCE_DIR}/pid_file.cpp ${CMAKE_CURRENT_SOURCE_DIR}/pid_file.cpp
${CMAKE_CURRENT_SOURCE_DIR}/string.cpp ${CMAKE_CURRENT_SOURCE_DIR}/string.cpp
${CMAKE_CURRENT_SOURCE_DIR}/thread_sched.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) { ...@@ -363,62 +363,62 @@ std::string Utility::epc(const unsigned char *plmnid) {
return epc(mnc, mcc); 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) { const char *mcc) {
std::string s; std::string s;
// '(.+)\.apn\.epc\.mnc(\d{3})\.mcc(\d{3})\.3gppnetworks\.org$' // '(.+)\.dnn\.epc\.mnc(\d{3})\.mcc(\d{3})\.3gppnetworks\.org$'
s.append(apnoi).append(".apn.epc.").APPEND_MNC( mnc ).APPEND_MCC( mcc ). s.append(apnoi).append(".dnn.epc.").APPEND_MNC( mnc ).APPEND_MCC( mcc ).
APPEND_3GPPNETWORK; APPEND_3GPPNETWORK;
return s; 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); 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; std::string s;
// '(.+)\.apn\.mnc(\d{3})\.mcc(\d{3})\.gprs$'} // '(.+)\.dnn\.mnc(\d{3})\.mcc(\d{3})\.gprs$'}
s.append(apnoi).append(".apn.").APPEND_MNC( mnc ).APPEND_MCC( mcc ).append( s.append(apnoi).append(".dnn.").APPEND_MNC( mnc ).APPEND_MCC( mcc ).append(
"gprs"); "gprs");
return s; 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); PARSE_PLMNID(plmnid);
return apn(apnoi, mnc, mcc); return dnn(apnoi, mnc, mcc);
} }
std::string Utility::apn_label(const std::string &apn) { std::string Utility::dnn_label(const std::string &dnn) {
std::string apn_label = { }; std::string dnn_label = { };
bool to_count = true; bool to_count = true;
uint8_t counted = 0; uint8_t counted = 0;
int index = 0; int index = 0;
apn_label.push_back('?'); dnn_label.push_back('?');
for (int i = 0; i < apn.length(); ++i) { for (int i = 0; i < dnn.length(); ++i) {
if (isalnum(apn[i]) || (apn[i] == '-')) { if (isalnum(dnn[i]) || (dnn[i] == '-')) {
apn_label.push_back(apn[i]); dnn_label.push_back(dnn[i]);
counted++; counted++;
} else if (apn[i] == '.') { } else if (dnn[i] == '.') {
apn_label.push_back('?'); dnn_label.push_back('?');
if (to_count) { // always true if (to_count) { // always true
apn_label[index] = counted; dnn_label[index] = counted;
} }
to_count = true; to_count = true;
counted = 0; counted = 0;
index = apn_label.length() - 1; index = dnn_label.length() - 1;
} }
} }
if (to_count) { if (to_count) {
apn_label[index] = counted; dnn_label[index] = counted;
} }
return apn_label; return dnn_label;
} }
...@@ -336,12 +336,12 @@ class Utility { ...@@ -336,12 +336,12 @@ class Utility {
const unsigned char *plmnid); const unsigned char *plmnid);
static std::string epc(const char *mnc, const char *mcc); static std::string epc(const char *mnc, const char *mcc);
static std::string epc(const unsigned char *plmnid); 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); const char *mcc);
static std::string apn_fqdn(const char *apnoi, const unsigned char *plmnid); static std::string dnn_fqdn(const char *apnoi, const unsigned char *plmnid);
static std::string apn(const char *apnoi, const char *mnc, const char *mcc); static std::string dnn(const char *apnoi, const char *mnc, const char *mcc);
static std::string apn(const char *apnoi, const unsigned char *plmnid); static std::string dnn(const char *apnoi, const unsigned char *plmnid);
static std::string apn_label(const std::string &apn); static std::string dnn_label(const std::string &dnn);
static AppServiceEnum getAppService(const std::string &s); static AppServiceEnum getAppService(const std::string &s);
static AppProtocolEnum getAppProtocol(const std::string &p); 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) ...@@ -28,6 +28,5 @@ include_directories(${SRC_TOP_DIR}/common/msg)
include_directories(${SRC_TOP_DIR}/common/utils) include_directories(${SRC_TOP_DIR}/common/utils)
include_directories(${SRC_TOP_DIR}/gtpv2c) include_directories(${SRC_TOP_DIR}/gtpv2c)
include_directories(${SRC_TOP_DIR}/itti) 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}/udp)
include_directories(${SRC_TOP_DIR}/../build/ext/spdlog/include) include_directories(${SRC_TOP_DIR}/../build/ext/spdlog/include)
...@@ -116,6 +116,7 @@ typedef enum { ...@@ -116,6 +116,7 @@ typedef enum {
N11_SESSION_N1N2_MESSAGE_TRANSFER_RESPONSE_STATUS, N11_SESSION_N1N2_MESSAGE_TRANSFER_RESPONSE_STATUS,
N11_SESSION_RELEASE_SM_CONTEXT_REQUEST, N11_SESSION_RELEASE_SM_CONTEXT_REQUEST,
N11_SESSION_RELEASE_SM_CONTEXT_RESPONSE, N11_SESSION_RELEASE_SM_CONTEXT_RESPONSE,
N11_SESSION_REPORT_RESPONSE,
NX_TRIGGER_SESSION_MODIFICATION, NX_TRIGGER_SESSION_MODIFICATION,
UDP_INIT, UDP_INIT,
UDP_DATA_REQ, UDP_DATA_REQ,
......
This diff is collapsed.
...@@ -115,7 +115,7 @@ class smf_app { ...@@ -115,7 +115,7 @@ class smf_app {
mutable std::shared_mutex m_scid2smf_context; 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 * @param [const smf_config &cfg] cfg
* @return * @return
*/ */
...@@ -392,16 +392,16 @@ class smf_app { ...@@ -392,16 +392,16 @@ class smf_app {
/* /*
* Trigger pdu session modification * Trigger pdu session modification
* @param [supi_t &] supi * @param [const supi_t &] supi
* @param [std::string &] dnn * @param [const std::string &] dnn
* @param [pdu_session_id_t] pdu_session_id * @param [const pdu_session_id_t] pdu_session_id
* @param [snssai_t &] snssai * @param [const snssai_t &] snssai
* @param [pfcp::qfi_t &] qfi * @param [const pfcp::qfi_t &] qfi
* @return void * @return void
*/ */
void trigger_pdu_session_modification(supi_t &supi, std::string &dnn, void trigger_pdu_session_modification(const supi_t &supi, const std::string &dnn,
pdu_session_id_t pdu_session_id, const pdu_session_id_t pdu_session_id,
snssai_t &snssai, pfcp::qfi_t &qfi); const snssai_t &snssai, const pfcp::qfi_t &qfi);
/* /*
* Verify if SM Context is existed for this Supi * Verify if SM Context is existed for this Supi
...@@ -412,7 +412,7 @@ class smf_app { ...@@ -412,7 +412,7 @@ class smf_app {
/* /*
* Create/Update SMF context with the corresponding supi * 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 * @param [std::shared_ptr<smf_context>] sc Shared_ptr Pointer to an SMF context
* @return True if existed, otherwise false * @return True if existed, otherwise false
*/ */
...@@ -428,7 +428,7 @@ class smf_app { ...@@ -428,7 +428,7 @@ class smf_app {
/* /*
* Check whether SMF uses local configuration instead of retrieving Session Management Data from UDM * 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 * @return True if SMF uses the local configuration to check the validity of the UE request, False otherwise
*/ */
bool use_local_configuration_subscription_data( bool use_local_configuration_subscription_data(
...@@ -436,36 +436,49 @@ class smf_app { ...@@ -436,36 +436,49 @@ class smf_app {
/* /*
* Verify whether the Session Management Data is existed * Verify whether the Session Management Data is existed
* @param [supi_t] SUPI * @param [const supi_t&] SUPI
* @param [std::string] DNN * @param [const std::string&] DNN
* @param [snssai_t] S-NSSAI * @param [const snssai_t&] S-NSSAI
* @return True if SMF uses the local configuration to check the validity of the UE request, False otherwise * @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, bool is_supi_dnn_snssai_subscription_data(const supi_t &supi,
snssai_t &snssai); 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 * Verify whether the UE request is valid according to the user subscription and with local policies
* @param [..] * @param [..]
* @return True if the request is valid, otherwise False * @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 * 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 * @param [std::string&] output_str String represents string in hex format
* @return void * @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 * Represent a string as hex
* @param [std::string&] str: input string * @param [const std::string&] str: input string
* @param [std::string&] output_str String represents string in hex format * @return String represents string in hex format
* @return void
*/ */
unsigned char* format_string_as_hex(std::string &str); unsigned char* format_string_as_hex(const std::string &str);
/* /*
* Update PDU session status * Update PDU session status
...@@ -478,10 +491,10 @@ class smf_app { ...@@ -478,10 +491,10 @@ class smf_app {
/* /*
* Convert N2 Info type representing by a string to n2_sm_info_type_e * 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 * @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 * Update PDU session UpCnxState
......
This diff is collapsed.
...@@ -55,8 +55,6 @@ ...@@ -55,8 +55,6 @@
#define SMF_CONFIG_STRING_INTERFACE_N4 "N4" #define SMF_CONFIG_STRING_INTERFACE_N4 "N4"
#define SMF_CONFIG_STRING_INTERFACE_SBI "SBI" #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_NAS_FORCE_PUSH_PCO "FORCE_PUSH_PROTOCOL_CONFIGURATION_OPTIONS"
#define SMF_CONFIG_STRING_IP_ADDRESS_POOL "IP_ADDRESS_POOL" #define SMF_CONFIG_STRING_IP_ADDRESS_POOL "IP_ADDRESS_POOL"
...@@ -79,18 +77,15 @@ ...@@ -79,18 +77,15 @@
#define SMF_CONFIG_STRING_INTERFACE_DISABLED "none" #define SMF_CONFIG_STRING_INTERFACE_DISABLED "none"
#define SMF_CONFIG_STRING_APN_LIST "APN_LIST" #define SMF_CONFIG_STRING_DNN_LIST "DNN_LIST"
#define SMF_CONFIG_STRING_APN_NI "APN_NI" #define SMF_CONFIG_STRING_DNN_NI "DNN_NI"
#define SMF_CONFIG_STRING_PDN_TYPE "PDN_TYPE" #define SMF_CONFIG_STRING_PDN_TYPE "PDN_TYPE"
#define SMF_CONFIG_STRING_IPV4_POOL "IPV4_POOL" #define SMF_CONFIG_STRING_IPV4_POOL "IPV4_POOL"
#define SMF_CONFIG_STRING_IPV6_POOL "IPV6_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_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_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_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_ABORT_ON_ERROR true
#define SMF_WARN_ON_ERROR false #define SMF_WARN_ON_ERROR false
...@@ -121,7 +116,23 @@ ...@@ -121,7 +116,23 @@
#define SMF_CONFIG_STRING_UPF_LIST "UPF_LIST" #define SMF_CONFIG_STRING_UPF_LIST "UPF_LIST"
#define SMF_CONFIG_STRING_UPF_IPV4_ADDRESS "IPV4_ADDRESS" #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 { namespace smf {
...@@ -172,29 +183,29 @@ class smf_config { ...@@ -172,29 +183,29 @@ class smf_config {
struct in6_addr default_dnsv6; struct in6_addr default_dnsv6;
struct in6_addr default_dns_secv6; struct in6_addr default_dns_secv6;
#define PGW_NUM_APN_MAX 5 #define SMF_NUM_DNN_MAX 5
int num_apn; int num_dnn;
struct { struct {
std::string apn; std::string dnn;
std::string apn_label; std::string dnn_label;
int pool_id_iv4; int pool_id_iv4;
int pool_id_iv6; int pool_id_iv6;
pdn_type_t pdn_type; pdn_type_t pdn_type;
} apn[PGW_NUM_APN_MAX]; } dnn[SMF_NUM_DNN_MAX];
int num_ue_pool; int num_ue_pool;
#define PGW_NUM_UE_POOL_MAX 96 #define SMF_NUM_UE_POOL_MAX 96
struct in_addr ue_pool_range_low[PGW_NUM_UE_POOL_MAX]; struct in_addr ue_pool_range_low[SMF_NUM_UE_POOL_MAX];
struct in_addr ue_pool_range_high[PGW_NUM_UE_POOL_MAX]; struct in_addr ue_pool_range_high[SMF_NUM_UE_POOL_MAX];
struct in_addr ue_pool_network[PGW_NUM_UE_POOL_MAX]; struct in_addr ue_pool_network[SMF_NUM_UE_POOL_MAX];
struct in_addr ue_pool_netmask[PGW_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[] //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 // 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; int num_paa6_pool;
struct in6_addr paa_pool6_prefix[PGW_NUM_UE_POOL_MAX]; struct in6_addr paa_pool6_prefix[SMF_NUM_UE_POOL_MAX];
uint8_t paa_pool6_prefix_len[PGW_NUM_UE_POOL_MAX]; uint8_t paa_pool6_prefix_len[SMF_NUM_UE_POOL_MAX];
bool force_push_pco; bool force_push_pco;
uint ue_mtu; uint ue_mtu;
...@@ -211,18 +222,31 @@ class smf_config { ...@@ -211,18 +222,31 @@ class smf_config {
std::vector<pfcp::node_id_t> upfs; 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() smf_config()
: :
m_rw_lock(), m_rw_lock(),
num_apn(0), num_dnn(0),
pid_dir(), pid_dir(),
instance(0), instance(0),
n4(), n4(),
sbi(), sbi(),
itti(), itti(),
upfs() { upfs() {
for (int i = 0; i < PGW_NUM_APN_MAX; i++) { for (int i = 0; i < SMF_NUM_DNN_MAX; i++) {
apn[i] = { }; dnn[i] = { };
} }
default_dnsv4.s_addr = INADDR_ANY; default_dnsv4.s_addr = INADDR_ANY;
default_dns_secv4.s_addr = INADDR_ANY; default_dns_secv4.s_addr = INADDR_ANY;
...@@ -231,7 +255,7 @@ class smf_config { ...@@ -231,7 +255,7 @@ class smf_config {
num_ue_pool = 0; num_ue_pool = 0;
num_paa6_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_low[i] = { };
ue_pool_range_high[i] = { }; ue_pool_range_high[i] = { };
ue_pool_network[i] = { }; ue_pool_network[i] = { };
...@@ -259,6 +283,9 @@ class smf_config { ...@@ -259,6 +283,9 @@ class smf_config {
amf_addr.ipv4_addr.s_addr = INADDR_ANY; amf_addr.ipv4_addr.s_addr = INADDR_ANY;
udm_addr.port = 80; udm_addr.port = 80;
local_configuration = false;
num_session_management_subscription = 0;
} }
; ;
~smf_config(); ~smf_config();
...@@ -273,11 +300,11 @@ class smf_config { ...@@ -273,11 +300,11 @@ class smf_config {
int load(const std::string &config_file); int load(const std::string &config_file);
int finalize(); int finalize();
void display(); 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); const pdn_type_t &pdn_type);
int get_pfcp_node_id(pfcp::node_id_t &node_id); int get_pfcp_node_id(pfcp::node_id_t &node_id);
int get_pfcp_fseid(pfcp::fseid_t &fseid); 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); const pdu_session_type_t &pdn_session_type);
std::string get_default_dnn(); std::string get_default_dnn();
}; };
......
This diff is collapsed.
...@@ -258,10 +258,10 @@ class smf_pdu_session : public std::enable_shared_from_this<smf_pdu_session> { ...@@ -258,10 +258,10 @@ class smf_pdu_session : public std::enable_shared_from_this<smf_pdu_session> {
upCnx_state_e get_upCnx_state() const; upCnx_state_e get_upCnx_state() const;
// Called by GTPV2-C DELETE_SESSION_REQUEST // 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 // 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. // 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 * 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> { ...@@ -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 * 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 * @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 * 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> { ...@@ -363,7 +363,7 @@ class smf_pdu_session : public std::enable_shared_from_this<smf_pdu_session> {
* @param [QOSRulesIE &] qos_rule * @param [QOSRulesIE &] qos_rule
* @return bool: Return true if Rule exist, otherwise return false * @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 * Update QoS Rule
...@@ -412,7 +412,7 @@ class smf_pdu_session : public std::enable_shared_from_this<smf_pdu_session> { ...@@ -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_T3591;
timer_id_t timer_T3592; 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, smf_qos_flow> qos_flows; // QFI <-> QoS Flow
std::map<uint8_t, QOSRulesIE> qos_rules; // QRI <-> QoS Rules std::map<uint8_t, QOSRulesIE> qos_rules; // QRI <-> QoS Rules
std::vector<uint8_t> qos_rules_to_be_synchronised; std::vector<uint8_t> qos_rules_to_be_synchronised;
...@@ -441,7 +441,8 @@ class session_management_subscription { ...@@ -441,7 +441,8 @@ class session_management_subscription {
* @return void * @return void
*/ */
void insert_dnn_configuration( 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 * Find a DNN configuration
...@@ -450,7 +451,15 @@ class session_management_subscription { ...@@ -450,7 +451,15 @@ class session_management_subscription {
* @return void * @return void
*/ */
void find_dnn_configuration( 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: private:
snssai_t single_nssai; snssai_t single_nssai;
...@@ -478,7 +487,6 @@ class dnn_context { ...@@ -478,7 +487,6 @@ class dnn_context {
pdu_sessions(), pdu_sessions(),
nssai(), nssai(),
dnn_in_use(dnn) { dnn_in_use(dnn) {
// apn_ambr = {0};
} }
dnn_context(dnn_context &b) = delete; dnn_context(dnn_context &b) = delete;
...@@ -503,7 +511,7 @@ class dnn_context { ...@@ -503,7 +511,7 @@ class dnn_context {
* @param void * @param void
* @return size_t: number of PDU sessions * @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 * Represent DNN Context as a string object
...@@ -513,8 +521,7 @@ class dnn_context { ...@@ -513,8 +521,7 @@ class dnn_context {
std::string toString() const; std::string toString() const;
bool in_use; bool in_use;
std::string dnn_in_use; // The APN currently used, as received from the SGW. std::string dnn_in_use; // The DNN currently used, as received from the AMF
//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.
snssai_t nssai; snssai_t nssai;
std::vector<std::shared_ptr<smf_pdu_session>> pdu_sessions; //Store all PDU Sessions associated with this DNN context 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; mutable std::recursive_mutex m_context;
...@@ -528,12 +535,10 @@ class smf_context : public std::enable_shared_from_this<smf_context> { ...@@ -528,12 +535,10 @@ class smf_context : public std::enable_shared_from_this<smf_context> {
smf_context() smf_context()
: :
m_context(), m_context(),
imsi(),
imsi_unauthenticated_indicator(false),
pending_procedures(), pending_procedures(),
msisdn(),
dnn_subscriptions(), dnn_subscriptions(),
scid(0) { scid(0) {
supi_prefix = { };
} }
smf_context(smf_context &b) = delete; smf_context(smf_context &b) = delete;
...@@ -659,6 +664,14 @@ class smf_context : public std::enable_shared_from_this<smf_context> { ...@@ -659,6 +664,14 @@ class smf_context : public std::enable_shared_from_this<smf_context> {
const snssai_t &snssai, const snssai_t &snssai,
std::shared_ptr<session_management_subscription> &ss); 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 * Find a session management subscription from a SMF context
* @param [const snssai_t&] snssai * @param [const snssai_t&] snssai
...@@ -704,7 +717,7 @@ class smf_context : public std::enable_shared_from_this<smf_context> { ...@@ -704,7 +717,7 @@ class smf_context : public std::enable_shared_from_this<smf_context> {
* @param * @param
* @return std::size_t: the number of contexts * @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 * Set SM Context ID
...@@ -720,9 +733,25 @@ class smf_context : public std::enable_shared_from_this<smf_context> { ...@@ -720,9 +733,25 @@ class smf_context : public std::enable_shared_from_this<smf_context> {
*/ */
scid_t get_scid() const; 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 * Get the default QoS Rule for all QFIs
* @param [QOSRulesIE] qos_rule * @param [QOSRulesIE] qos_rule
* @param [const uint8_t] pdu_session_type: PDU session type (e.g., Ipv4, Ipv6)
* @return void * @return void
*/ */
void get_default_qos_rule(QOSRulesIE &qos_rule, uint8_t pdu_session_type); 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> { ...@@ -758,17 +787,26 @@ class smf_context : public std::enable_shared_from_this<smf_context> {
void get_session_ambr(Ngap_PDUSessionAggregateMaximumBitRate_t &session_ambr, void get_session_ambr(Ngap_PDUSessionAggregateMaximumBitRate_t &session_ambr,
const snssai_t &snssai, const std::string &dnn); 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: private:
std::vector<std::shared_ptr<dnn_context>> dnns; 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; std::vector<std::shared_ptr<smf_procedure>> pending_procedures;
// snssai-sst <-> session management subscription // snssai-sst <-> session management subscription
std::map<uint8_t, std::shared_ptr<session_management_subscription>> dnn_subscriptions; std::map<uint8_t, std::shared_ptr<session_management_subscription>> dnn_subscriptions;
supi_t supi; supi_t supi;
scid_t scid; //SM Context ID std::string supi_prefix;
scid_t scid; //SM Context ID
// Big recursive lock // Big recursive lock
mutable std::recursive_mutex m_context; mutable std::recursive_mutex m_context;
......
This diff is collapsed.
...@@ -124,23 +124,23 @@ class pdu_session_msg { ...@@ -124,23 +124,23 @@ class pdu_session_msg {
virtual ~pdu_session_msg() = default; virtual ~pdu_session_msg() = default;
pdu_session_msg_type_t get_msg_type() const; 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; 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; 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; 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; std::string get_dnn() const;
void set_dnn(std::string const &value); void set_dnn(const std::string &value);
snssai_t get_snssai() const; snssai_t get_snssai() const;
void set_snssai(snssai_t const &value); void set_snssai(const snssai_t &value);
void set_api_root(std::string const &value); void set_api_root(const std::string &value);
std::string get_api_root() const; std::string get_api_root() const;
uint8_t get_pdu_session_type() 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; 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: private:
pdu_session_msg_type_t m_msg_type; pdu_session_msg_type_t m_msg_type;
...@@ -182,9 +182,9 @@ class pdu_session_create_sm_context : public pdu_session_msg { ...@@ -182,9 +182,9 @@ class pdu_session_create_sm_context : public pdu_session_msg {
} }
extended_protocol_discriminator_t get_epd() const; 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; 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: private:
extended_protocol_discriminator_t m_epd; extended_protocol_discriminator_t m_epd;
...@@ -210,12 +210,12 @@ class pdu_session_create_sm_context_request : ...@@ -210,12 +210,12 @@ class pdu_session_create_sm_context_request :
} }
std::string get_n1_sm_message() const; 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; 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; std::string get_request_type() const;
void set_request_type(std::string const &value); void set_request_type(const std::string &value);
void set_dnn_selection_mode(std::string const &value); void set_dnn_selection_mode(const std::string &value);
std::string get_dnn_selection_mode() const; std::string get_dnn_selection_mode() const;
private: private:
...@@ -267,12 +267,12 @@ class pdu_session_create_sm_context_response : ...@@ -267,12 +267,12 @@ class pdu_session_create_sm_context_response :
void set_qos_flow_context(const qos_flow_context_updated &qos_flow); void set_qos_flow_context(const qos_flow_context_updated &qos_flow);
qos_flow_context_updated get_qos_flow_context() const; qos_flow_context_updated get_qos_flow_context() const;
std::string get_n2_sm_information() 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; 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 n1_sm_msg_is_set() const;
bool n2_sm_info_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; std::string get_amf_url() const;
nlohmann::json n1n2_message_transfer_data; //N1N2MessageTransferReqData from oai::amf::model 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 { ...@@ -312,9 +312,9 @@ class pdu_session_update_sm_context : public pdu_session_msg {
std::string get_n2_sm_information() const; std::string get_n2_sm_information() const;
void set_n2_sm_information(std::string const &value); void set_n2_sm_information(std::string const &value);
std::string get_n2_sm_info_type() const; 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; 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 n1_sm_msg_is_set() const;
bool n2_sm_info_is_set() const; bool n2_sm_info_is_set() const;
...@@ -345,19 +345,19 @@ class pdu_session_update_sm_context_request : ...@@ -345,19 +345,19 @@ class pdu_session_update_sm_context_request :
} }
; ;
void add_qfi(pfcp::qfi_t const &qfi); void add_qfi(const pfcp::qfi_t &qfi);
void add_qfi(uint8_t const &qfi); void add_qfi(const uint8_t &qfi);
void get_qfis(std::vector<pfcp::qfi_t> &q); 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 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; 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; 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 an_type_is_set() const;
bool release_is_set() const; bool release_is_set() const;
void set_release(bool const value); void set_release(bool value);
private: private:
std::vector<pfcp::qfi_t> qfis; std::vector<pfcp::qfi_t> qfis;
...@@ -456,10 +456,10 @@ class pdu_session_modification_network_requested : ...@@ -456,10 +456,10 @@ class pdu_session_modification_network_requested :
void set_http_code(Pistache::Http::Code code); void set_http_code(Pistache::Http::Code code);
Pistache::Http::Code get_http_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; std::string get_amf_url() const;
void add_qfi(pfcp::qfi_t const &qfi); void add_qfi(const pfcp::qfi_t &qfi);
void add_qfi(uint8_t const &qfi); void add_qfi(const uint8_t &qfi);
void get_qfis(std::vector<pfcp::qfi_t> &q); void get_qfis(std::vector<pfcp::qfi_t> &q);
nlohmann::json n1n2_message_transfer_data; //N1N2MessageTransferReqData from oai::amf::model nlohmann::json n1n2_message_transfer_data; //N1N2MessageTransferReqData from oai::amf::model
...@@ -472,6 +472,65 @@ class pdu_session_modification_network_requested : ...@@ -472,6 +472,65 @@ class pdu_session_modification_network_requested :
std::map<uint8_t, qos_flow_context_updated> qos_flow_context_updateds; 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 #endif
...@@ -101,7 +101,7 @@ smf_n10::smf_n10() { ...@@ -101,7 +101,7 @@ smf_n10::smf_n10() {
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
bool smf_n10::get_sm_data( 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) { std::shared_ptr<session_management_subscription> subscription) {
//retrieve a UE's Session Management Subscription Data (TS29503_Nudm_SDM.yaml: /{supi}/sm-data) //retrieve a UE's Session Management Subscription Data (TS29503_Nudm_SDM.yaml: /{supi}/sm-data)
//use curl to send data for the moment //use curl to send data for the moment
...@@ -114,7 +114,6 @@ bool smf_n10::get_sm_data( ...@@ -114,7 +114,6 @@ bool smf_n10::get_sm_data(
headers = curl_slist_append(headers, "charsets: utf-8"); headers = curl_slist_append(headers, "charsets: utf-8");
CURL *curl = curl_easy_init(); 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( std::string url = std::string(
inet_ntoa(*((struct in_addr*) &smf_cfg.udm_addr.ipv4_addr))) + ":" inet_ntoa(*((struct in_addr*) &smf_cfg.udm_addr.ipv4_addr))) + ":"
+ std::to_string(smf_cfg.udm_addr.port) + std::to_string(smf_cfg.udm_addr.port)
...@@ -148,7 +147,6 @@ bool smf_n10::get_sm_data( ...@@ -148,7 +147,6 @@ bool smf_n10::get_sm_data(
== http_response_codes_e::HTTP_RESPONSE_CODE_OK) { == http_response_codes_e::HTTP_RESPONSE_CODE_OK) {
Logger::smf_n10().debug("Got successful response from UDM, URL: %s ", Logger::smf_n10().debug("Got successful response from UDM, URL: %s ",
url.c_str()); url.c_str());
//Logger::smf_n10().debug("[get_sm_data] Http Data from UDM: %s ", *httpData.get());
try { try {
jsonData = nlohmann::json::parse(*httpData.get()); jsonData = nlohmann::json::parse(*httpData.get());
//curl_easy_cleanup(curl); //curl_easy_cleanup(curl);
......
...@@ -50,15 +50,15 @@ class smf_n10 { ...@@ -50,15 +50,15 @@ class smf_n10 {
/* /*
* Get SM subscription data from UDM * Get SM subscription data from UDM
* @param [supi64_t &] supi * @param [const supi64_t &] supi
* @param [std::string &] dnn * @param [const std::string &] dnn
* @param [snssai_t &] snssai * @param [const snssai_t &] snssai
* @param [std::shared_ptr<session_management_subscription>] subscription * @param [std::shared_ptr<session_management_subscription>] subscription
* @return bool: True if successful, otherwise false * @return bool: True if successful, otherwise false
* *
*/ */
bool get_sm_data( 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); std::shared_ptr<session_management_subscription> subscription);
/* /*
......
This diff is collapsed.
...@@ -67,6 +67,14 @@ class smf_n11 { ...@@ -67,6 +67,14 @@ class smf_n11 {
void send_n1n2_message_transfer_request( void send_n1n2_message_transfer_request(
std::shared_ptr<itti_nx_trigger_pdu_session_modification> sm_context_res); 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 * Send update session response to AMF
* @param [std::shared_ptr<itti_n11_update_sm_context_response> sm_context_res] sm_context_res * @param [std::shared_ptr<itti_n11_update_sm_context_response> sm_context_res] sm_context_res
...@@ -86,75 +94,75 @@ class smf_n11 { ...@@ -86,75 +94,75 @@ class smf_n11 {
/* /*
* Send update session response to AMF * Send update session response to AMF
* @param [Pistache::Http::ResponseWriter] httpResponse * @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 [Pistache::Http::Code] code, response code
* @return void * @return void
*/ */
void send_pdu_session_update_sm_context_response( void send_pdu_session_update_sm_context_response(
Pistache::Http::ResponseWriter &httpResponse, Pistache::Http::ResponseWriter &httpResponse,
oai::smf_server::model::SmContextUpdateError &smContextUpdateError, const oai::smf_server::model::SmContextUpdateError &smContextUpdateError,
Pistache::Http::Code code); Pistache::Http::Code code);
/* /*
* Send Update session response to AMF * Send Update session response to AMF
* @param [Pistache::Http::ResponseWriter] httpResponse * @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 * @param [Pistache::Http::Code] code, response code
* @return void * @return void
*/ */
void send_pdu_session_update_sm_context_response( void send_pdu_session_update_sm_context_response(
Pistache::Http::ResponseWriter &httpResponse, Pistache::Http::ResponseWriter &httpResponse,
oai::smf_server::model::SmContextUpdatedData &smContextUpdatedData, const oai::smf_server::model::SmContextUpdatedData &smContextUpdatedData,
Pistache::Http::Code code); Pistache::Http::Code code);
/* /*
* Send create session response to AMF * Send create session response to AMF
* @param [Pistache::Http::ResponseWriter] httpResponse * @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 [Pistache::Http::Code] code, response code
* @return void * @return void
*/ */
void send_pdu_session_create_sm_context_response( void send_pdu_session_create_sm_context_response(
Pistache::Http::ResponseWriter &httpResponse, Pistache::Http::ResponseWriter &httpResponse,
oai::smf_server::model::SmContextCreateError &smContextCreateError, const oai::smf_server::model::SmContextCreateError &smContextCreateError,
Pistache::Http::Code code); Pistache::Http::Code code);
/* /*
* Send create session response to AMF * Send create session response to AMF
* @param [Pistache::Http::ResponseWriter] httpResponse * @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 [Pistache::Http::Code] code, response code
* @param [std::string] n1_sm_msg, N1 SM message content * @param [std::string] n1_sm_msg, N1 SM message content
* @return void * @return void
*/ */
void send_pdu_session_create_sm_context_response( void send_pdu_session_create_sm_context_response(
Pistache::Http::ResponseWriter &httpResponse, 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); Pistache::Http::Code code, std::string &n1_sm_msg);
/* /*
* Send update session response to AMF * Send update session response to AMF
* @param [Pistache::Http::ResponseWriter] httpResponse * @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 [Pistache::Http::Code] code, response code
* @param [std::string] n1_sm_msg, N1 SM message content * @param [std::string] n1_sm_msg, N1 SM message content
* @return void * @return void
*/ */
void send_pdu_session_update_sm_context_response( void send_pdu_session_update_sm_context_response(
Pistache::Http::ResponseWriter &httpResponse, 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); Pistache::Http::Code code, std::string &n1_sm_msg);
/* /*
* Send create session response to AMF * Send create session response to AMF
* @param [Pistache::Http::ResponseWriter] httpResponse * @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 * @param [Pistache::Http::Code] code, response code
* @return void * @return void
*/ */
void send_pdu_session_create_sm_context_response( void send_pdu_session_create_sm_context_response(
Pistache::Http::ResponseWriter &httpResponse, Pistache::Http::ResponseWriter &httpResponse,
oai::smf_server::model::SmContextCreatedData &smContextCreatedData, const oai::smf_server::model::SmContextCreatedData &smContextCreatedData,
Pistache::Http::Code code); Pistache::Http::Code code);
/* /*
...@@ -169,13 +177,13 @@ class smf_n11 { ...@@ -169,13 +177,13 @@ class smf_n11 {
/* /*
* Send release session response to AMF * Send release session response to AMF
* @param [Pistache::Http::ResponseWriter] httpResponse * @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 * @param [Pistache::Http::Code] code, response code
* @return void * @return void
*/ */
void send_pdu_session_release_sm_context_response( void send_pdu_session_release_sm_context_response(
Pistache::Http::ResponseWriter &httpResponse, Pistache::Http::ResponseWriter &httpResponse,
oai::smf_server::model::ProblemDetails &problem, const oai::smf_server::model::ProblemDetails &problem,
Pistache::Http::Code code); Pistache::Http::Code code);
/* /*
...@@ -188,10 +196,10 @@ class smf_n11 { ...@@ -188,10 +196,10 @@ class smf_n11 {
* @return void * @return void
*/ */
void create_multipart_related_content(std::string &body, void create_multipart_related_content(std::string &body,
std::string &json_part, const std::string &json_part,
std::string &boundary, const std::string boundary,
std::string &n1_message, const std::string &n1_message,
std::string &n2_message); const std::string &n2_message);
/* /*
* Create HTTP body content for multipart/related message * Create HTTP body content for multipart/related message
...@@ -203,8 +211,8 @@ class smf_n11 { ...@@ -203,8 +211,8 @@ class smf_n11 {
* @return void * @return void
*/ */
void create_multipart_related_content( void create_multipart_related_content(
std::string &body, std::string &json_part, std::string &boundary, std::string &body, const std::string &json_part, const std::string boundary,
std::string &message, multipart_related_content_part_e content_type); const std::string &message, const multipart_related_content_part_e content_type);
}; };
......
This diff is collapsed.
...@@ -57,6 +57,7 @@ extern "C" { ...@@ -57,6 +57,7 @@ extern "C" {
#include "Ngap_PDUSessionResourceSetupResponseTransfer.h" #include "Ngap_PDUSessionResourceSetupResponseTransfer.h"
#include "Ngap_PDUSessionResourceModifyResponseTransfer.h" #include "Ngap_PDUSessionResourceModifyResponseTransfer.h"
#include "Ngap_PDUSessionResourceReleaseResponseTransfer.h" #include "Ngap_PDUSessionResourceReleaseResponseTransfer.h"
#include "Ngap_PDUSessionResourceSetupUnsuccessfulTransfer.h"
} }
namespace smf { namespace smf {
...@@ -97,20 +98,20 @@ class smf_n1_n2 { ...@@ -97,20 +98,20 @@ class smf_n1_n2 {
/* /*
* Decode N1 SM Container into the NAS mesasge (using NAS lib) * Decode N1 SM Container into the NAS mesasge (using NAS lib)
* @param [nas_message_t&] nas_msg Store NAS message after decoded * @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 * @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 * Decode N2 SM Information Ngap_PDUSessionResourceSetupResponseTransfer
* @param [std::shared_ptr<Ngap_PDUSessionResourceSetupResponseTransfer_t>&] ngap_IE Store decoded NGAP message * @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 * @return status of the decode process
*/ */
int decode_n2_sm_information( int decode_n2_sm_information(
std::shared_ptr<Ngap_PDUSessionResourceSetupResponseTransfer_t> &ngap_IE, 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 * Decode N2 SM Information Ngap_PDUSessionResourceModifyResponseTransfer_t
...@@ -120,7 +121,7 @@ class smf_n1_n2 { ...@@ -120,7 +121,7 @@ class smf_n1_n2 {
*/ */
int decode_n2_sm_information( int decode_n2_sm_information(
std::shared_ptr<Ngap_PDUSessionResourceModifyResponseTransfer_t> &ngap_IE, 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 * Decode N2 SM Information Ngap_PDUSessionResourceReleaseResponseTransfer_t
...@@ -130,7 +131,18 @@ class smf_n1_n2 { ...@@ -130,7 +131,18 @@ class smf_n1_n2 {
*/ */
int decode_n2_sm_information( int decode_n2_sm_information(
std::shared_ptr<Ngap_PDUSessionResourceReleaseResponseTransfer_t> &ngap_IE, 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 { ...@@ -161,13 +161,13 @@ class ipv4_pool {
} }
}; };
class apn_dynamic_pools { class dnn_dynamic_pools {
public: public:
std::vector<uint32_t> ipv4_pool_ids; std::vector<uint32_t> ipv4_pool_ids;
std::vector<uint32_t> ipv6_pool_ids; std::vector<uint32_t> ipv6_pool_ids;
apn_dynamic_pools() dnn_dynamic_pools()
: :
ipv4_pool_ids(), ipv4_pool_ids(),
ipv6_pool_ids() { ipv6_pool_ids() {
...@@ -186,13 +186,13 @@ class paa_dynamic { ...@@ -186,13 +186,13 @@ class paa_dynamic {
std::map<int32_t, ipv4_pool> ipv4_pools; std::map<int32_t, ipv4_pool> ipv4_pools;
std::map<int32_t, ipv6_pool> ipv6_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() paa_dynamic()
: :
ipv4_pools(), ipv4_pools(),
ipv6_pools(), ipv6_pools(),
apns() { dnns() {
} }
; ;
...@@ -205,7 +205,7 @@ class paa_dynamic { ...@@ -205,7 +205,7 @@ class paa_dynamic {
paa_dynamic(paa_dynamic const&) = delete; paa_dynamic(paa_dynamic const&) = delete;
void operator=(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) { const struct in_addr &first, const int range) {
if (pool_id >= 0) { if (pool_id >= 0) {
uint32_t uint32pool_id = uint32_t(pool_id); uint32_t uint32pool_id = uint32_t(pool_id);
...@@ -213,15 +213,15 @@ class paa_dynamic { ...@@ -213,15 +213,15 @@ class paa_dynamic {
ipv4_pool pool(first, range); ipv4_pool pool(first, range);
ipv4_pools[uint32pool_id] = pool; ipv4_pools[uint32pool_id] = pool;
} }
if (!apns.count(apn_label)) { if (!dnns.count(dnn_label)) {
apn_dynamic_pools adp = { }; dnn_dynamic_pools adp = { };
adp.add_ipv4_pool_id(uint32pool_id); 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) { const struct in6_addr &prefix, const int prefix_len) {
if (pool_id >= 0) { if (pool_id >= 0) {
uint32_t uint32pool_id = uint32_t(pool_id); uint32_t uint32pool_id = uint32_t(pool_id);
...@@ -229,39 +229,39 @@ class paa_dynamic { ...@@ -229,39 +229,39 @@ class paa_dynamic {
ipv6_pool pool(prefix, prefix_len); ipv6_pool pool(prefix, prefix_len);
ipv6_pools[uint32pool_id] = pool; ipv6_pools[uint32pool_id] = pool;
} }
if (!apns.count(apn_label)) { if (!dnns.count(dnn_label)) {
apn_dynamic_pools adp = { }; dnn_dynamic_pools adp = { };
adp.add_ipv6_pool_id(uint32pool_id); 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) { bool get_free_paa(const std::string &dnn_label, paa_t &paa) {
if (apns.count(apn_label)) { if (dnns.count(dnn_label)) {
apn_dynamic_pools &apn_pool = apns[apn_label]; dnn_dynamic_pools &dnn_pool = dnns[dnn_label];
if (paa.pdn_type.pdn_type == PDN_TYPE_E_IPV4) { if (paa.pdn_type.pdn_type == PDN_TYPE_E_IPV4) {
for (std::vector<uint32_t>::const_iterator it4 = apn_pool.ipv4_pool_ids for (std::vector<uint32_t>::const_iterator it4 = dnn_pool.ipv4_pool_ids
.begin(); it4 != apn_pool.ipv4_pool_ids.end(); ++it4) { .begin(); it4 != dnn_pool.ipv4_pool_ids.end(); ++it4) {
if (ipv4_pools[*it4].alloc_address(paa.ipv4_address)) { if (ipv4_pools[*it4].alloc_address(paa.ipv4_address)) {
return true; return true;
} }
} }
Logger::smf_app().warn("Could not get PAA PDN_TYPE_E_IPV4 for APN %s", Logger::smf_app().warn("Could not get PAA PDN_TYPE_E_IPV4 for DNN %s",
apn_label.c_str()); dnn_label.c_str());
return false; return false;
} else if (paa.pdn_type.pdn_type == PDN_TYPE_E_IPV4V6) { } else if (paa.pdn_type.pdn_type == PDN_TYPE_E_IPV4V6) {
bool success = false; bool success = false;
std::vector<uint32_t>::const_iterator it4 = { }; std::vector<uint32_t>::const_iterator it4 = { };
for (it4 = apn_pool.ipv4_pool_ids.begin(); for (it4 = dnn_pool.ipv4_pool_ids.begin();
it4 != apn_pool.ipv4_pool_ids.end(); ++it4) { it4 != dnn_pool.ipv4_pool_ids.end(); ++it4) {
if (ipv4_pools[*it4].alloc_address(paa.ipv4_address)) { if (ipv4_pools[*it4].alloc_address(paa.ipv4_address)) {
success = true; success = true;
} }
} }
if (success) { if (success) {
for (std::vector<uint32_t>::const_iterator it6 = apn_pool for (std::vector<uint32_t>::const_iterator it6 = dnn_pool
.ipv6_pool_ids.begin(); it6 != apn_pool.ipv6_pool_ids.end(); .ipv6_pool_ids.begin(); it6 != dnn_pool.ipv6_pool_ids.end();
++it6) { ++it6) {
if (ipv6_pools[*it6].alloc_address(paa.ipv6_address)) { if (ipv6_pools[*it6].alloc_address(paa.ipv6_address)) {
return true; return true;
...@@ -269,31 +269,31 @@ class paa_dynamic { ...@@ -269,31 +269,31 @@ class paa_dynamic {
} }
ipv4_pools[*it4].free_address(paa.ipv4_address); ipv4_pools[*it4].free_address(paa.ipv4_address);
} }
Logger::smf_app().warn("Could not get PAA PDN_TYPE_E_IPV4V6 for APN %s", Logger::smf_app().warn("Could not get PAA PDN_TYPE_E_IPV4V6 for DNN %s",
apn_label.c_str()); dnn_label.c_str());
return false; return false;
} else if (paa.pdn_type.pdn_type == PDN_TYPE_E_IPV6) { } else if (paa.pdn_type.pdn_type == PDN_TYPE_E_IPV6) {
for (std::vector<uint32_t>::const_iterator it6 = apn_pool.ipv6_pool_ids for (std::vector<uint32_t>::const_iterator it6 = dnn_pool.ipv6_pool_ids
.begin(); it6 != apn_pool.ipv6_pool_ids.end(); ++it6) { .begin(); it6 != dnn_pool.ipv6_pool_ids.end(); ++it6) {
if (ipv6_pools[*it6].alloc_address(paa.ipv6_address)) { if (ipv6_pools[*it6].alloc_address(paa.ipv6_address)) {
return true; return true;
} }
} }
Logger::smf_app().warn("Could not get PAA PDN_TYPE_E_IPV6 for APN %s", Logger::smf_app().warn("Could not get PAA PDN_TYPE_E_IPV6 for DNN %s",
apn_label.c_str()); dnn_label.c_str());
return false; 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; return false;
} }
bool release_paa(const std::string &apn_label, const paa_t &paa) { bool release_paa(const std::string &dnn_label, const paa_t &paa) {
if (apns.count(apn_label)) { if (dnns.count(dnn_label)) {
apn_dynamic_pools &apn_pool = apns[apn_label]; dnn_dynamic_pools &dnn_pool = dnns[dnn_label];
if (paa.pdn_type.pdn_type == PDN_TYPE_E_IPV4) { if (paa.pdn_type.pdn_type == PDN_TYPE_E_IPV4) {
for (std::vector<uint32_t>::const_iterator it4 = apn_pool.ipv4_pool_ids for (std::vector<uint32_t>::const_iterator it4 = dnn_pool.ipv4_pool_ids
.begin(); it4 != apn_pool.ipv4_pool_ids.end(); ++it4) { .begin(); it4 != dnn_pool.ipv4_pool_ids.end(); ++it4) {
if (ipv4_pools[*it4].free_address(paa.ipv4_address)) { if (ipv4_pools[*it4].free_address(paa.ipv4_address)) {
return true; return true;
} }
...@@ -302,8 +302,8 @@ class paa_dynamic { ...@@ -302,8 +302,8 @@ class paa_dynamic {
} else if (paa.pdn_type.pdn_type == PDN_TYPE_E_IPV4V6) { } else if (paa.pdn_type.pdn_type == PDN_TYPE_E_IPV4V6) {
bool success = false; bool success = false;
std::vector<uint32_t>::const_iterator it4 = { }; std::vector<uint32_t>::const_iterator it4 = { };
for (it4 = apn_pool.ipv4_pool_ids.begin(); for (it4 = dnn_pool.ipv4_pool_ids.begin();
it4 != apn_pool.ipv4_pool_ids.end(); ++it4) { it4 != dnn_pool.ipv4_pool_ids.end(); ++it4) {
if (ipv4_pools[*it4].free_address(paa.ipv4_address)) { if (ipv4_pools[*it4].free_address(paa.ipv4_address)) {
return true; return true;
} }
...@@ -313,24 +313,24 @@ class paa_dynamic { ...@@ -313,24 +313,24 @@ class paa_dynamic {
return true; return true;
} }
} }
Logger::smf_app().warn("Could not release PAA for APN %s", Logger::smf_app().warn("Could not release PAA for DNN %s",
apn_label.c_str()); dnn_label.c_str());
return false; return false;
} }
bool release_paa(const std::string &apn_label, bool release_paa(const std::string &dnn_label,
const struct in_addr &ipv4_address) { const struct in_addr &ipv4_address) {
if (apns.count(apn_label)) { if (dnns.count(dnn_label)) {
apn_dynamic_pools &apn_pool = apns[apn_label]; dnn_dynamic_pools &dnn_pool = dnns[dnn_label];
for (std::vector<uint32_t>::const_iterator it4 = apn_pool.ipv4_pool_ids for (std::vector<uint32_t>::const_iterator it4 = dnn_pool.ipv4_pool_ids
.begin(); it4 != apn_pool.ipv4_pool_ids.end(); ++it4) { .begin(); it4 != dnn_pool.ipv4_pool_ids.end(); ++it4) {
if (ipv4_pools[*it4].free_address(ipv4_address)) { if (ipv4_pools[*it4].free_address(ipv4_address)) {
return true; return true;
} }
} }
} }
Logger::smf_app().warn("Could not release PAA for APN %s", Logger::smf_app().warn("Could not release PAA for DNN %s",
apn_label.c_str()); dnn_label.c_str());
return false; return false;
} }
......
...@@ -151,7 +151,7 @@ int session_create_sm_context_procedure::run( ...@@ -151,7 +151,7 @@ int session_create_sm_context_procedure::run(
pfcp::destination_interface_t destination_interface = { }; pfcp::destination_interface_t destination_interface = { };
sps->generate_far_id(far_id); sps->generate_far_id(far_id);
apply_action.forw = 1; apply_action.forw = 1; //forward the packets
//wys-test-add //wys-test-add
pfcp::outer_header_creation_t outer_header_creation = { }; pfcp::outer_header_creation_t outer_header_creation = { };
...@@ -662,13 +662,15 @@ int session_update_sm_context_procedure::run( ...@@ -662,13 +662,15 @@ int session_update_sm_context_procedure::run(
.s_addr; .s_addr;
update_forwarding_parameters.set(outer_header_creation); update_forwarding_parameters.set(outer_header_creation);
update_far.set(update_forwarding_parameters); 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); update_far.set(apply_action);
n4_ser->pfcp_ies.set(update_far); n4_ser->pfcp_ies.set(update_far);
send_n4 = true; send_n4 = true;
flow.far_id_dl.first = true; flow.far_id_dl.first = true;
flow.dl_fteid = dl_fteid;
} else { } else {
Logger::smf_app().debug("Create FAR DL"); Logger::smf_app().debug("Create FAR DL");
...@@ -691,7 +693,8 @@ int session_update_sm_context_procedure::run( ...@@ -691,7 +693,8 @@ int session_update_sm_context_procedure::run(
//pfcp::proxying_t proxying = {}; //pfcp::proxying_t proxying = {};
sps->generate_far_id(far_id); 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 destination_interface.interface_value = pfcp::INTERFACE_VALUE_ACCESS; // ACCESS is for downlink, CORE for uplink
forwarding_parameters.set(destination_interface); forwarding_parameters.set(destination_interface);
...@@ -713,6 +716,7 @@ int session_update_sm_context_procedure::run( ...@@ -713,6 +716,7 @@ int session_update_sm_context_procedure::run(
flow.far_id_dl.first = true; flow.far_id_dl.first = true;
flow.far_id_dl.second.far_id = far_id.far_id; 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); Logger::smf_app().debug("FAR DL ID " "0x%" PRIx32 " ", far_id.far_id);
} }
...@@ -777,7 +781,7 @@ int session_update_sm_context_procedure::run( ...@@ -777,7 +781,7 @@ int session_update_sm_context_procedure::run(
pdr_id.rule_id); pdr_id.rule_id);
} else { } else {
Logger::smf_app().debug( 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); flow.pdr_id_dl.rule_id, flow.far_id_dl.second.far_id);
/* /*
// Update FAR // Update FAR
...@@ -831,7 +835,9 @@ int session_update_sm_context_procedure::run( ...@@ -831,7 +835,9 @@ int session_update_sm_context_procedure::run(
} }
// after a release flows // after a release flows
if (not flow.ul_fteid.is_zero()) { if (not flow.ul_fteid.is_zero()) {
}
if (not flow.dl_fteid.is_zero()) {
} }
// may be modified // may be modified
smf_qos_flow flow2 = flow; smf_qos_flow flow2 = flow;
...@@ -870,7 +876,7 @@ int session_update_sm_context_procedure::run( ...@@ -870,7 +876,7 @@ int session_update_sm_context_procedure::run(
far_id.far_id = flow.far_id_dl.second.far_id; far_id.far_id = flow.far_id_dl.second.far_id;
// apply_action.buff = 1; // apply_action.buff = 1;
pfcp::apply_action_t apply_action = { }; 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(far_id);
far.set(apply_action); far.set(apply_action);
...@@ -967,63 +973,6 @@ void session_update_sm_context_procedure::handle_itti_msg( ...@@ -967,63 +973,6 @@ void session_update_sm_context_procedure::handle_itti_msg(
.c_str()); .c_str());
switch (session_procedure_type) { 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_ESTABLISHMENT_UE_REQUESTED:
case session_management_procedures_type_e::PDU_SESSION_MODIFICATION_SMF_REQUESTED: case session_management_procedures_type_e::PDU_SESSION_MODIFICATION_SMF_REQUESTED:
case session_management_procedures_type_e::PDU_SESSION_MODIFICATION_AN_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( ...@@ -1033,6 +982,9 @@ void session_update_sm_context_procedure::handle_itti_msg(
::fteid_t dl_fteid = { }; ::fteid_t dl_fteid = { };
n11_trigger->req.get_dl_fteid(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 = std::map<uint8_t, qos_flow_context_updated> qos_flow_context_to_be_updateds =
{ }; { };
n11_triggered_pending->res.get_all_qos_flow_context_updateds( n11_triggered_pending->res.get_all_qos_flow_context_updateds(
...@@ -1193,10 +1145,6 @@ void session_update_sm_context_procedure::handle_itti_msg( ...@@ -1193,10 +1145,6 @@ void session_update_sm_context_procedure::handle_itti_msg(
//FOR TESTING PURPOSE //FOR TESTING PURPOSE
case session_management_procedures_type_e::PDU_SESSION_TEST: { 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 //N1 SM
smf_n1_n2_inst.create_n1_sm_container( smf_n1_n2_inst.create_n1_sm_container(
n11_triggered_pending->res, PDU_SESSION_MODIFICATION_REQUEST, n11_triggered_pending->res, PDU_SESSION_MODIFICATION_REQUEST,
......
...@@ -108,10 +108,6 @@ void create_multipart_related_content(std::string &body, std::string &json_part, ...@@ -108,10 +108,6 @@ void create_multipart_related_content(std::string &body, std::string &json_part,
std::string &n1_message, std::string &n1_message,
std::string &n2_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"; std::string CRLF = "\r\n";
body.append("--" + boundary + CRLF); body.append("--" + boundary + CRLF);
body.append("Content-Type: application/json" + CRLF); body.append("Content-Type: application/json" + CRLF);
...@@ -123,7 +119,6 @@ void create_multipart_related_content(std::string &body, std::string &json_part, ...@@ -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" "Content-Type: application/vnd.3gpp.5gnas" + CRLF + "Content-Id: n1SmMsg"
+ CRLF); + CRLF);
body.append(CRLF); body.append(CRLF);
//body.append(std::string((char*) n1_msg_hex, n1_message.length() / 2) + CRLF);
body.append(n1_message + CRLF); body.append(n1_message + CRLF);
body.append("--" + boundary + CRLF); body.append("--" + boundary + CRLF);
...@@ -131,7 +126,6 @@ void create_multipart_related_content(std::string &body, std::string &json_part, ...@@ -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" "Content-Type: application/vnd.3gpp.ngap" + CRLF + "Content-Id: n2SmMsg"
+ CRLF); + CRLF);
body.append(CRLF); body.append(CRLF);
//body.append(std::string((char*) n2_msg_hex, n2_message.length() / 2) + CRLF);
body.append(n2_message + CRLF); body.append(n2_message + CRLF);
body.append("--" + boundary + "--" + CRLF); body.append("--" + boundary + "--" + CRLF);
} }
...@@ -141,9 +135,6 @@ void create_multipart_related_content( ...@@ -141,9 +135,6 @@ void create_multipart_related_content(
std::string &body, std::string &json_part, std::string &boundary, std::string &body, std::string &json_part, std::string &boundary,
std::string &message, multipart_related_content_part_e content_type) { 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"; std::string CRLF = "\r\n";
body.append("--" + boundary + CRLF); body.append("--" + boundary + CRLF);
body.append("Content-Type: application/json" + CRLF); body.append("Content-Type: application/json" + CRLF);
...@@ -161,7 +152,6 @@ void create_multipart_related_content( ...@@ -161,7 +152,6 @@ void create_multipart_related_content(
+ CRLF); + CRLF);
} }
body.append(CRLF); body.append(CRLF);
//body.append(std::string((char*) msg_hex, message.length() / 2) + CRLF);
body.append(message + CRLF); body.append(message + CRLF);
body.append("--" + boundary + "--" + CRLF); body.append("--" + boundary + "--" + CRLF);
} }
...@@ -429,7 +419,6 @@ void send_pdu_session_modification_request_step1(std::string smf_ip_address) { ...@@ -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, 0x01, size); //QoS Rules
ENCODE_U8(buffer + size, 0x06, size); //QoS Rules ENCODE_U8(buffer + size, 0x06, size); //QoS Rules
std::cout << "Buffer: " << std::endl; std::cout << "Buffer: " << std::endl;
for (int i = 0; i < size; i++) { for (int i = 0; i < size; i++) {
printf("%02x ", buffer[i]); printf("%02x ", buffer[i]);
...@@ -1253,9 +1242,11 @@ int main(int argc, char *argv[]) { ...@@ -1253,9 +1242,11 @@ int main(int argc, char *argv[]) {
usleep(200000); usleep(200000);
//PDU Session Modification //PDU Session Modification
send_pdu_session_modification_request_step1(smf_ip_address); send_pdu_session_modification_request_step1(smf_ip_address);
usleep(200000);
send_pdu_session_modification_request_step2(smf_ip_address); send_pdu_session_modification_request_step2(smf_ip_address);
usleep(200000);
send_pdu_session_modification_complete(smf_ip_address); send_pdu_session_modification_complete(smf_ip_address);
usleep(200000);
//PDU Session Release procedure //PDU Session Release procedure
send_pdu_session_release_request(smf_ip_address); send_pdu_session_release_request(smf_ip_address);
usleep(200000); usleep(200000);
......
This diff is collapsed.
/*
* 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