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

Merge branch 'pdu_session_modification_v2.0' into 'develop'

Pdu session modification v2.0

See merge request oai/oai-cn5g-smf!10
parents a9abca49 acd67431
......@@ -6,21 +6,24 @@ The license information is distributed under LICENSE file in the same directory.
The OpenAirInterface CN SMF software is composed of the following parts:
openair-cn5g-smf
├── 3gpp-specs: Directory containing 3GPP specification files (YAML) used to implement SMF network function.
├── build: Build directory, contains targets and object files generated by compilation of network functions.
├── log: Directory containing build log files.
├── scripts: Directory containing scripts for building network functions
├── scripts: Directory containing scripts for building network functions.
└── smf: Directory containing CMakefile.txt and object files generated by compilation of SMF network function.
├── ci-scripts: Directory containing the script files for CI framework.
├── docs: Directory containing the documentation files.
├── etc: Directory containing the configuration file to be deployed for SMF.
└── src: Source files of SMF.
├── api-server: SMF services APIs.
├── common: Common header files
│   ├── msg: ITTI messages definitions.
│   └── utils: Common utilities.
├── gtpv1u: Generic GTPV1-U stack implementation
├── gtpv2c: Generic GTPV2-C stack implementation
├── itti: Inter task interface
├── nas: NAS protocol implememtation
├── mgap: NGAP protocol implememtation
├── gtpv1u: Generic GTPV1-U stack implementation.
├── gtpv2c: Generic GTPV2-C stack implementation.
├── itti: Inter task interface.
├── nas: NAS protocol implememtation.
├── ngap: NGAP protocol implememtation.
├── oai_smf: SMF main directory, contains the "main" CMakeLists.txt file.
├── pfcp: Generic PFCP stack implementation.
├── smf_app: SMF network functions procedures and contexts.
......
<table style="border-collapse: collapse; border: none;">
<tr style="border-collapse: collapse; border: none;">
<td style="border-collapse: collapse; border: none;">
<a href="http://www.openairinterface.org/">
<img src="./images/oai_final_logo.png" alt="" border=3 height=50 width=150>
</img>
</a>
</td>
<td style="border-collapse: collapse; border: none; vertical-align: center;">
<b><font size = "5">OpenAirInterface SMF Feature Set</font></b>
</td>
</tr>
</table>
**Table of Contents**
1. [5GC Service Based Architecture](#1-5gc-service-based-architecture)
2. [OAI SMF Available Interfaces](#2-oai-smf-available-interfaces)
3. [OAI SMF Feature List](#3-oai-smf-feature-list)
# 1. 5GC Service Based Architecture #
![5GC SBA](./images/5gc_sba.png)
# 2. OAI SMF Available Interfaces #
| **ID** | **Interface** | **Status** | **Comment** |
| ------ | ------------- | ------------------ | --------------------------------------------------------------------------|
| 1 | N4 | :heavy_check_mark: | between SMF and UPF (PFCP) |
| 2 | N7 | :x: | between SMF and PCF |
| 3 | N10 | :heavy_check_mark: | between SMF and UDM (Nudm_SubscriberDataManagement) |
| 4 | N11 | :heavy_check_mark: | between SMF and AMF (Nsmf_PDU_Session Services, Namf_N1N2MessageTransfer) |
| 5 | N16/16a | :x: | between SMFs |
# 3. OAI SMF Feature List #
Based on document **3GPP TS 23.501 v16.0.0 §6.2.2**.
| **ID** | **Classification** | **Status** | **Comments** |
| ------ | ------------------------------------------------------------------- | ------------------ | ------------------------------------------- |
| 1 | Session Management (Session Establishment/Modification/Release) | :heavy_check_mark: | |
| 2 | UE IP address allocation & management​ | :heavy_check_mark: | Only support static ipv4 address allocation |
| 3 | DHCPv4 (server and client) and DHCPv6 (server and client) function | :x: | |
| 4 | Respond to ARP requests and/or IPv6 Neighbour Solicitation requests | :x: | Local configuration in SMF |
| 5 | Selection of UPF function​ | :x: | |
| 6 | Configures traffic steering at UPF | :x: | |
| 7 | Termination of interfaces towards PCFs | :x: | |
| 8 | Lawful intercept | :x: | |
| 8 | Charging data collection and support of charging interfaces | :x: | |
| 10 | Termination of SM parts of NAS messages | :heavy_check_mark: | |
| 11 | Downlink Data Notification | :heavy_check_mark: | |
| 12 | Determine SSC mode of a session​ | :heavy_check_mark: | Only support SSC mode 1​ |
| 13 | Initiator of AN specific SM information, sent via AMF over N2 to AN | :heavy_check_mark: | |
| 14 | Support for Control Plane CIoT 5GS Optimisation | :x: | |
| 15 | Support of header compression. ​ | :x: | |
| 16 | Act as I-SMF in deployments | :x: | |
| 17 | Provisioning of external parameters | :x: | |
......@@ -89,12 +89,6 @@ SMF =
# Non standard feature, normally should be set to "no", but you may need to set to yes for UE that do not explicitly request a PDN address through NAS signalling
FORCE_PUSH_PROTOCOL_CONFIGURATION_OPTIONS = "no"; # STRING, {"yes", "no"}.
PCEF :
{
# Waiting for HSS APN-AMBR IE ...
APN_AMBR_UL = 500000; # Maximum UL bandwidth that can be used by non guaranteed bit rate traffic in Kbits/seconds.
APN_AMBR_DL = 500000; # Maximum DL bandwidth that can be used by non guaranteed bit rate traffic in Kbits/seconds.
};
AMF :
{
IPV4_ADDRESS="@AMF_IPV4_ADDRESS@";
......
......@@ -139,7 +139,7 @@ void IndividualSMContextApi::update_sm_context_handler(
Logger::smf_api_server().debug("");
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());
//find boundary
......@@ -174,7 +174,7 @@ void IndividualSMContextApi::update_sm_context_handler(
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().warn(
Logger::smf_api_server().debug(
"The received message can not be parsed properly!");
//TODO: fix this issue
//response.send(Pistache::Http::Code::Bad_Request, "");
......@@ -184,7 +184,7 @@ void IndividualSMContextApi::update_sm_context_handler(
free_wrapper((void**) &data);
uint8_t size = g_parts.size();
Logger::smf_api_server().debug("Number of g_parts %d", g_parts.size());
Logger::smf_api_server().debug("Number of MIME parts %d", g_parts.size());
part p0 = { };
part p1 = { };
......
......@@ -41,7 +41,6 @@
#include <map>
#include <string>
#include "logger.hpp"
#include "Helpers.h"
extern "C" {
......@@ -83,8 +82,9 @@ void SMContextsCollectionApi::post_sm_contexts_handler(
const Pistache::Rest::Request &request,
Pistache::Http::ResponseWriter response) {
Logger::smf_api_server().debug("");
Logger::smf_api_server().info(
"\nReceived 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
......@@ -120,7 +120,7 @@ void SMContextsCollectionApi::post_sm_contexts_handler(
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().warn(
Logger::smf_api_server().debug(
"The received message can not be parsed properly!");
//TODO: fix this issue
//response.send(Pistache::Http::Code::Bad_Request, "");
......@@ -130,7 +130,7 @@ void SMContextsCollectionApi::post_sm_contexts_handler(
free_wrapper((void**) &data);
uint8_t size = g_parts.size();
Logger::smf_api_server().debug("Number of g_parts %d", g_parts.size());
Logger::smf_api_server().debug("Number of MIME parts %d", g_parts.size());
//at least 2 parts for Json data and N1 (+ N2)
if (g_parts.size() < 2) {
response.send(Pistache::Http::Code::Bad_Request, "");
......
......@@ -58,7 +58,7 @@ void SMContextsCollectionApiImpl::post_sm_contexts(
const SmContextMessage &smContextMessage,
Pistache::Http::ResponseWriter &response) {
Logger::smf_api_server().info("PDU Session Create SM Context Request ...");
Logger::smf_api_server().info("PDU Session Create SM Context Request.");
//Assign the necessary informations to smf::pdu_session_create_sm_context_request
//and pass this message to SMF to handle this message
......@@ -88,18 +88,18 @@ void SMContextsCollectionApiImpl::post_sm_contexts(
sm_context_req_msg.set_supi(supi);
sm_context_req_msg.set_supi_prefix(supi_prefix);
Logger::smf_api_server().debug(
"SmContextCreateData, supi %s, prefix %s, imsi %s",
"SmContextCreateData, SUPI %s, SUPI Prefix %s, IMSI %s",
smContextCreateData.getSupi().c_str(), supi_prefix.c_str(),
supi_str.c_str());
//dnn
Logger::smf_api_server().debug("SmContextCreateData, dnn %s",
Logger::smf_api_server().debug("SmContextCreateData, DNN %s",
smContextCreateData.getDnn().c_str());
sm_context_req_msg.set_dnn(smContextCreateData.getDnn().c_str());
//S-Nssai
Logger::smf_api_server().debug(
"SmContextCreateData, S-NSSAI sst %d, sd %s",
"SmContextCreateData, S-NSSAI SST %d, SD %s",
smContextCreateData.getSNssai().getSst(),
smContextCreateData.getSNssai().getSd().c_str());
snssai_t snssai(smContextCreateData.getSNssai().getSst(),
......@@ -107,7 +107,7 @@ void SMContextsCollectionApiImpl::post_sm_contexts(
sm_context_req_msg.set_snssai(snssai);
//PDU session ID
Logger::smf_api_server().debug("SmContextCreateData, PDU SessionID %d",
Logger::smf_api_server().debug("SmContextCreateData, PDU Session ID %d",
smContextCreateData.getPduSessionId());
sm_context_req_msg.set_pdu_session_id(smContextCreateData.getPduSessionId());
......
......@@ -142,8 +142,7 @@ static const std::vector<std::string> session_management_procedures_type_e2str =
"PDU_SESSION_RELEASE_UE_REQUESTED_STEP2",
"PDU_SESSION_RELEASE_UE_REQUESTED_STEP3",
"PDU_SESSION_RELEASE_SMF_INITIATED",
"PDU_SESSION_RELEASE_AMF_INITIATED",
"PDU_SESSION_RELEASE_AN_INITIATED",
"PDU_SESSION_RELEASE_AMF_INITIATED", "PDU_SESSION_RELEASE_AN_INITIATED",
"PDU_SESSION_TEST"
};
......@@ -189,5 +188,9 @@ static const std::vector<std::string> multipart_related_content_part_e2str = {
//for CURL
#define AMF_CURL_TIMEOUT_MS 100L
#define AMF_NUMBER_RETRIES 3
#define UDM_CURL_TIMEOUT_MS 100L
#define UDM_NUMBER_RETRIES 3
//for N1N2
#define BUF_LEN 512
#endif
......@@ -331,14 +331,17 @@ static int _nas_message_header_encode(
//Security header type associated with a spare half octet;
ENCODE_U8(buffer + size, *((uint8_t* )(header) + 1), size);
//ENCODE_U8 (buffer+size,header->security_header_type,size);
#if DEBUG_IS_ON
printf("extended_protocol_discriminator %d, security_header_type %d \n",
header->extended_protocol_discriminator, header->security_header_type);
#endif
if (header->extended_protocol_discriminator
== EPD_5GS_MOBILITY_MANAGEMENT_MESSAGES) {
// header->extended_protocol_discriminator == EPD_5GS_SESSION_MANAGEMENT_MESSAGES) {
if (header->security_header_type != SECURITY_HEADER_TYPE_NOT_PROTECTED) {
#if DEBUG_IS_ON
printf("security_header_type != SECURITY_HEADER_TYPE_NOT_PROTECTED\n");
#endif
if (length < NAS_MESSAGE_SECURITY_HEADER_SIZE) {
/*
* The buffer is not big enough to contain security header
......@@ -357,7 +360,9 @@ static int _nas_message_header_encode(
*/
ENCODE_U8(buffer + size, header->sequence_number, size);
}
#if DEBUG_IS_ON
printf("security_header_type: SECURITY_HEADER_TYPE_NOT_PROTECTED\n");
#endif
}
return size;
//OAILOG_STREAM_HEX(OAILOG_LEVEL_DEBUG, LOG_NAS, "encode nas header Incoming NAS message: ", buffer, size)
......
......@@ -184,8 +184,9 @@ int encode_pdu_session_establishment_accept(
uint8_t *buffer, uint32_t len) {
uint32_t encoded = 0;
int encoded_result = 0;
#if DEBUG_IS_ON
printf("\nEncode PDU Session Establishment Accept\n");
#endif
// Check if we got a NULL pointer and if buffer length is >= minimum length expected for the message.
CHECK_PDU_POINTER_AND_LENGTH_ENCODER(
buffer, PDU_SESSION_ESTABLISHMENT_ACCEPT_MINIMUM_LENGTH, len);
......
......@@ -175,8 +175,9 @@ int fivegsm_msg_encode(SM_msg *msg, uint8_t *buffer, uint32_t len) {
buffer += header_result;
len -= header_result;
#if DEBUG_IS_ON
printf(", message type %d", msg->header.message_type);
#endif
switch (msg->header.message_type) {
case PDU_SESSION_ESTABLISHMENT_REQUEST:
encode_result = encode_pdu_session_establishment_request(
......
......@@ -8039,6 +8039,9 @@ public:
//--------
explicit pfcp_update_pdr_ie(const pfcp::update_pdr& b) : pfcp_grouped_ie(PFCP_IE_UPDATE_PDR){
tlv.set_length(0);
std::shared_ptr<pfcp_pdr_id_ie> sie(new pfcp_pdr_id_ie(b.pdr_id)); add_ie(sie);
if (b.far_id.first) {std::shared_ptr<pfcp_far_id_ie> sie(new pfcp_far_id_ie(b.far_id.second)); add_ie(sie);}
if (b.pdi.first) { std::shared_ptr<pfcp_pdi_ie> sie(new pfcp_pdi_ie(b.pdi.second)); add_ie(sie);}
}
//--------
pfcp_update_pdr_ie() : pfcp_grouped_ie(PFCP_IE_UPDATE_PDR){
......
This diff is collapsed.
This diff is collapsed.
......@@ -77,8 +77,6 @@ int smf_config::finalize() {
ue_pool_network[i].s_addr = htonl(network_hbo);
ue_pool_netmask[i].s_addr = htonl(netmask_hbo);
}
// "TODO"
//pgw_pcef_emulation_init(config_pP);
Logger::smf_app().info("Finalized config");
return 0;
}
......@@ -97,7 +95,8 @@ int smf_config::load_thread_sched_params(const Setting &thread_sched_params_cfg,
try {
std::string thread_rd_sched_policy;
thread_sched_params_cfg.lookupValue(
SMF_CONFIG_STRING_THREAD_RD_SCHED_POLICY, thread_rd_sched_policy);
SMF_CONFIG_STRING_THREAD_RD_SCHED_POLICY,
thread_rd_sched_policy);
util::trim(thread_rd_sched_policy);
if (boost::iequals(thread_rd_sched_policy, "SCHED_OTHER")) {
cfg.sched_policy = SCHED_OTHER;
......@@ -122,7 +121,8 @@ int smf_config::load_thread_sched_params(const Setting &thread_sched_params_cfg,
try {
thread_sched_params_cfg.lookupValue(
SMF_CONFIG_STRING_THREAD_RD_SCHED_PRIORITY, cfg.sched_priority);
SMF_CONFIG_STRING_THREAD_RD_SCHED_PRIORITY,
cfg.sched_priority);
if ((cfg.sched_priority > 99) || (cfg.sched_priority < 1)) {
Logger::smf_app().error(
"thread_rd_sched_priority: %d, must be in interval [1..99] in config file",
......@@ -332,7 +332,7 @@ int smf_config::load(const string &config_file) {
boost::token_compress_on);
if (ips.size() != 2) {
Logger::smf_app().error("Bad value %s : %s in config file %s",
SMF_CONFIG_STRING_IPV4_ADDRESS_RANGE_DELIMITER,
SMF_CONFIG_STRING_IPV4_ADDRESS_RANGE_DELIMITER,
ipv4_range.c_str(), config_file.c_str());
throw("Bad value %s : %s in config file %s", SMF_CONFIG_STRING_IPV4_ADDRESS_RANGE_DELIMITER, ipv4_range
.c_str(), config_file.c_str());
......@@ -382,8 +382,8 @@ int smf_config::load(const string &config_file) {
boost::token_compress_on);
if (ips6.size() != 2) {
Logger::smf_app().error("Bad value %s : %s in config file %s",
SMF_CONFIG_STRING_PREFIX, ipv6_prefix.c_str(),
config_file.c_str());
SMF_CONFIG_STRING_PREFIX,
ipv6_prefix.c_str(), config_file.c_str());
throw("Bad value %s : %s in config file %s", SMF_CONFIG_STRING_PREFIX, ipv6_prefix
.c_str(), config_file.c_str());
}
......@@ -507,19 +507,6 @@ int smf_config::load(const string &config_file) {
}
smf_cfg.lookupValue(SMF_CONFIG_STRING_UE_MTU, ue_mtu);
const Setting &pcef_cfg = smf_cfg[SMF_CONFIG_STRING_PCEF];
unsigned int apn_ambr = 0;
if (!(pcef_cfg.lookupValue(SMF_CONFIG_STRING_APN_AMBR_UL, apn_ambr))) {
Logger::smf_app().error(SMF_CONFIG_STRING_APN_AMBR_UL "failed");
throw(SMF_CONFIG_STRING_APN_AMBR_UL "failed");
}
pcef.apn_ambr_ul = apn_ambr;
if (!(pcef_cfg.lookupValue(SMF_CONFIG_STRING_APN_AMBR_DL, apn_ambr))) {
Logger::smf_app().error(SMF_CONFIG_STRING_APN_AMBR_DL "failed");
//throw (SMF_CONFIG_STRING_APN_AMBR_DL "failed");
}
pcef.apn_ambr_dl = apn_ambr;
const Setting &amf_cfg = smf_cfg[SMF_CONFIG_STRING_AMF];
struct in_addr amf_ipv4_addr;
unsigned int amf_port = 0;
......@@ -680,11 +667,7 @@ void smf_config::display() {
apn[i].pool_id_iv6);
}
}
Logger::smf_app().info("- PCEF support (in development)");
Logger::smf_app().info(" APN AMBR UL ..........: %lu (Kilo bits/s)",
pcef.apn_ambr_ul);
Logger::smf_app().info(" APN AMBR DL ..........: %lu (Kilo bits/s)",
pcef.apn_ambr_dl);
Logger::smf_app().info("- Helpers:");
Logger::smf_app().info(" Push PCO (DNS+MTU) ........: %s",
force_push_pco == 0 ? "false" : "true");
......@@ -760,15 +743,15 @@ smf_config::~smf_config() {
//------------------------------------------------------------------------------
bool smf_config::is_dotted_dnn_handled(
const std::string &dnn, const pdu_session_type_t &pdn_session_type) {
Logger::smf_app().debug("requested dnn: %s", dnn.c_str());
Logger::smf_app().debug("Requested DNN: %s", dnn.c_str());
for (int i = 0; i < smf_cfg.num_apn; i++) {
Logger::smf_app().debug("apn_label: %s, apn: %s",
Logger::smf_app().debug("DNN label: %s, dnn: %s",
smf_cfg.apn[i].apn_label.c_str(),
smf_cfg.apn[i].apn.c_str());
//if (0 == dnn.compare(smf_cfg.apn[i].apn_label)) {
if (0 == dnn.compare(smf_cfg.apn[i].apn)) {
Logger::smf_app().debug("DNN matched!");
Logger::smf_app().debug("pdu session type %d, pdn_type %d",
Logger::smf_app().debug("PDU Session Type %d, PDN Type %d",
pdn_session_type.pdu_session_type,
smf_cfg.apn[i].pdn_type.pdn_type);
if (pdn_session_type.pdu_session_type
......
......@@ -85,8 +85,6 @@
#define SMF_CONFIG_STRING_IPV4_POOL "IPV4_POOL"
#define SMF_CONFIG_STRING_IPV6_POOL "IPV6_POOL"
#define SMF_CONFIG_STRING_PCEF "PCEF"
#define SMF_CONFIG_STRING_PCEF_ENABLED "PCEF_ENABLED"
#define SMF_CONFIG_STRING_TCP_ECN_ENABLED "TCP_ECN_ENABLED"
#define SMF_CONFIG_STRING_AUTOMATIC_PUSH_DEDICATED_BEARER_PCC_RULE "AUTOMATIC_PUSH_DEDICATED_BEARER_PCC_RULE"
#define SMF_CONFIG_STRING_DEFAULT_BEARER_STATIC_PCC_RULE "DEFAULT_BEARER_STATIC_PCC_RULE"
......@@ -201,12 +199,6 @@ class smf_config {
bool force_push_pco;
uint ue_mtu;
struct {
bool tcp_ecn_enabled = false; // test for CoDel qdisc
unsigned int apn_ambr_ul;
unsigned int apn_ambr_dl;
} pcef;
struct {
struct in_addr ipv4_addr;
unsigned int port;
......@@ -222,7 +214,6 @@ class smf_config {
smf_config()
:
m_rw_lock(),
pcef(),
num_apn(0),
pid_dir(),
instance(0),
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
......@@ -39,9 +39,6 @@
#include "logger.hpp"
#include "smf_config.hpp"
#define UDM_CURL_TIMEOUT_MS 100L
#define UDM_NUMBER_RETRIES 3
using namespace smf;
using namespace std;
using json = nlohmann::json;
......@@ -102,11 +99,6 @@ smf_n10::smf_n10() {
Logger::smf_n10().startup("Started");
}
//------------------------------------------------------------------------------
void smf_n10::handle_receive_sm_data_notification() {
//TODO:
}
//------------------------------------------------------------------------------
bool smf_n10::get_sm_data(
supi64_t &supi, std::string &dnn, snssai_t &snssai,
......@@ -127,7 +119,7 @@ bool smf_n10::get_sm_data(
inet_ntoa(*((struct in_addr*) &smf_cfg.udm_addr.ipv4_addr))) + ":"
+ std::to_string(smf_cfg.udm_addr.port)
+ fmt::format(NUDM_SDM_GET_SM_DATA_URL, std::to_string(supi));
Logger::smf_n10().debug("[get_sm_data] UDM's URL: %s ", url.c_str());
Logger::smf_n10().debug("UDM's URL: %s ", url.c_str());
if (curl) {
CURLcode res = { };
......@@ -150,28 +142,24 @@ bool smf_n10::get_sm_data(
while (numRetries < UDM_NUMBER_RETRIES) {
res = curl_easy_perform(curl);
curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &httpCode);
Logger::smf_n10().debug("[get_sm_data] Response from UDM, Http Code: %d ",
httpCode);
Logger::smf_n10().debug("Response from UDM, HTTP Code: %d ", httpCode);
if (static_cast<http_response_codes_e>(httpCode)
== http_response_codes_e::HTTP_RESPONSE_CODE_OK) {
Logger::smf_n10().debug(
"[get_sm_data] Got successful response from UDM, URL: %s ",
url.c_str());
Logger::smf_n10().debug("Got successful response from UDM, URL: %s ",
url.c_str());
//Logger::smf_n10().debug("[get_sm_data] Http Data from UDM: %s ", *httpData.get());
try {
jsonData = nlohmann::json::parse(*httpData.get());
//curl_easy_cleanup(curl);
break;
} catch (json::exception &e) {
Logger::smf_n10().warn(
"[get_sm_data] Couldn't Parse json data from UDM");
Logger::smf_n10().warn("Could not parse json data from UDM");
}
numRetries++;
} else {
Logger::smf_n10().warn(
"[get_sm_data] Couldn't GET response from UDM, URL %s, retry ...",
url.c_str());
"Could not get response from UDM, URL %s, retry ...", url.c_str());
//retry
numRetries++;
}
......@@ -181,13 +169,12 @@ bool smf_n10::get_sm_data(
//process the response
if (!jsonData.empty()) {
Logger::smf_n10().debug("[get_sm_data] GET response from UDM %s",
jsonData.dump().c_str());
Logger::smf_n10().debug("Response from UDM %s", jsonData.dump().c_str());
//retrieve SessionManagementSubscription and store in the context
for (nlohmann::json::iterator it = jsonData["dnnConfigurations"].begin();
it != jsonData["dnnConfigurations"].end(); ++it) {
Logger::smf_n10().debug("[get_sm_data] DNN %s", it.key().c_str());
Logger::smf_n10().debug("DNN %s", it.key().c_str());
try {
std::shared_ptr<dnn_configuration_t> dnn_configuration =
std::make_shared<dnn_configuration_t>();
......@@ -196,7 +183,7 @@ bool smf_n10::get_sm_data(
pdu_session_type_e::PDU_SESSION_TYPE_E_IPV4);
std::string default_session_type =
it.value()["pduSessionTypes"]["defaultSessionType"];
Logger::smf_n10().debug("[get_sm_data] default_session_type %s",
Logger::smf_n10().debug("Default session type %s",
default_session_type.c_str());
if (default_session_type.compare("IPV4") == 0) {
pdu_session_type.pdu_session_type =
......@@ -214,7 +201,7 @@ bool smf_n10::get_sm_data(
//Ssc_Mode
ssc_mode_t ssc_mode(ssc_mode_e::SSC_MODE_1);
std::string default_ssc_mode = it.value()["sscModes"]["defaultSscMode"];
Logger::smf_n10().debug("[get_sm_data] defaultSscMode %s",
Logger::smf_n10().debug("Default SSC Mode %s",
default_ssc_mode.c_str());
if (default_ssc_mode.compare("SSC_MODE_1") == 0) {
dnn_configuration->ssc_modes.default_ssc_mode = ssc_mode_t(
......@@ -244,16 +231,14 @@ bool smf_n10::get_sm_data(
dnn_configuration->session_ambr.downlink =
it.value()["sessionAmbr"]["downlink"];
Logger::smf_n10().debug(
"[get_sm_data] sessionAmbr uplink %s, downlink %s",
"Session AMBR Uplink %s, Downlink %s",
dnn_configuration->session_ambr.uplink.c_str(),
dnn_configuration->session_ambr.downlink.c_str());
//sdc = std::shared_ptr<dnn_configuration_t> (dnn_configuration);
subscription->insert_dnn_configuration(it.key(), dnn_configuration);
} catch (nlohmann::json::exception &e) {
Logger::smf_n10().warn(
"[get_sm_data] exception message %s, exception id %d ", e.what(),
e.id);
Logger::smf_n10().warn("Exception message %s, exception id %d ",
e.what(), e.id);
return false;
}
}
......
......@@ -43,15 +43,30 @@ class smf_n10 {
std::thread::id thread_id;
std::thread thread;
void handle_receive_sm_data_notification();
public:
smf_n10();
smf_n10(smf_n10 const&) = delete;
void operator=(smf_n10 const&) = delete;
/*
* Get SM subscription data from UDM
* @param [supi64_t &] supi
* @param [std::string &] dnn
* @param [snssai_t &] snssai
* @param [std::shared_ptr<session_management_subscription>] subscription
* @return bool: True if successful, otherwise false
*
*/
bool get_sm_data(
supi64_t &supi, std::string &dnn, snssai_t &snssai,
std::shared_ptr<session_management_subscription> subscription);
/*
* Subscribe to be notify from UDM
* @param []
* @return void
*
*/
void subscribe_sm_data();
};
......
......@@ -97,6 +97,11 @@ void smf_n11_task(void *args_p) {
std::static_pointer_cast<
itti_n11_modify_session_request_smf_requested>(shared_msg));
break;
case NX_TRIGGER_SESSION_MODIFICATION:
smf_n11_inst->send_n1n2_message_transfer_request(
std::static_pointer_cast<itti_nx_trigger_pdu_session_modification>(
shared_msg));
break;
case TERMINATE:
if (itti_msg_terminate *terminate =
......@@ -349,10 +354,92 @@ void smf_n11::send_n1n2_message_transfer_request(
*/
}
//------------------------------------------------------------------------------
void smf_n11::send_n1n2_message_transfer_request(
std::shared_ptr<itti_nx_trigger_pdu_session_modification> sm_context_res) {
//Transfer N1/N2 message via AMF by using N_amf_Communication_N1N2MessageTransfer (see TS29518_Namf_Communication.yaml)
Logger::smf_n11().debug("Send Communication_N1N2MessageTransfer to AMF");
smf_n1_n2 smf_n1_n2_inst = { };
std::string n1_message = sm_context_res->msg.get_n1_sm_message();
std::string json_part = sm_context_res->msg.n1n2_message_transfer_data.dump();
std::string boundary = "----Boundary";
std::string body;
//add N2 content if available
auto n2_sm_found = sm_context_res->msg.n1n2_message_transfer_data.count(
"n2InfoContainer");
if (n2_sm_found > 0) {
std::string n2_message = sm_context_res->msg.get_n2_sm_information();
//prepare the body content for Curl
create_multipart_related_content(body, json_part, boundary, n1_message,
n2_message);
} else {
//prepare the body content for Curl
create_multipart_related_content(body, json_part, boundary, n1_message,
multipart_related_content_part_e::NAS);
}
unsigned int str_len = body.length();
char *data = (char*) malloc(str_len + 1);
memset(data, 0, str_len + 1);
memcpy((void*) data, (void*) body.c_str(), str_len);
curl_global_init(CURL_GLOBAL_ALL);
CURL *curl = curl_easy_init();
if (curl) {
CURLcode res = { };
struct curl_slist *headers = nullptr;
//headers = curl_slist_append(headers, "charsets: utf-8");
headers = curl_slist_append(
headers, "content-type: multipart/related; boundary=----Boundary"); //TODO: update Boundary
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
curl_easy_setopt(curl, CURLOPT_URL,
sm_context_res->msg.get_amf_url().c_str());
curl_easy_setopt(curl, CURLOPT_HTTPGET, 1);
curl_easy_setopt(curl, CURLOPT_TIMEOUT_MS, AMF_CURL_TIMEOUT_MS);
curl_easy_setopt(curl, CURLOPT_INTERFACE, smf_cfg.sbi.if_name.c_str());
// Response information.
long httpCode = { 0 };
std::unique_ptr<std::string> httpData(new std::string());
// Hook up data handling function
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, &callback);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, httpData.get());
curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, body.length());
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, data);
res = curl_easy_perform(curl);
curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &httpCode);
//get cause from the response
json response_data = { };
try {
response_data = json::parse(*httpData.get());
} catch (json::exception &e) {
Logger::smf_n11().warn("Could not get the cause from the response");
//Set the default Cause
//response_data["cause"] = "504 Gateway Timeout";
}
Logger::smf_n11().debug("Response from AMF, Http Code: %d", httpCode);
curl_slist_free_all(headers);
curl_easy_cleanup(curl);
}
curl_global_cleanup();
free_wrapper((void**) &data);
}
//------------------------------------------------------------------------------
void smf_n11::send_pdu_session_update_sm_context_response(
std::shared_ptr<itti_n11_update_sm_context_response> sm_context_res) {
Logger::smf_n11().debug("Send PDUSessionUpdateContextResponse to AMF ");
Logger::smf_n11().debug("Send PDUSession_UpdateSMContext Response to AMF.");
switch (sm_context_res->session_procedure_type) {
......@@ -499,8 +586,7 @@ void smf_n11::send_pdu_session_update_sm_context_response(
oai::smf_server::model::SmContextUpdateError &smContextUpdateError,
Pistache::Http::Code code) {
Logger::smf_n11().debug(
"[SMF N11] Send PDUSessionUpdateContextResponse to AMF!");
Logger::smf_n11().debug("Send PDUSession_UpdateSMContext Response to AMF.");
nlohmann::json json_data = { };
to_json(json_data, smContextUpdateError);
......@@ -519,8 +605,7 @@ void smf_n11::send_pdu_session_update_sm_context_response(
Pistache::Http::ResponseWriter &httpResponse,
oai::smf_server::model::SmContextUpdateError &smContextUpdateError,
Pistache::Http::Code code, std::string &n1_sm_msg) {
Logger::smf_n11().debug(
"[SMF N11] Send PDUSessionUpdateContextResponse to AMF!");
Logger::smf_n11().debug("Send PDUSession_UpdateSMContext Response to AMF.");
std::string boundary = "----Boundary";
nlohmann::json json_part = { };
......@@ -542,8 +627,7 @@ void smf_n11::send_pdu_session_create_sm_context_response(
Pistache::Http::ResponseWriter &httpResponse,
oai::smf_server::model::SmContextCreateError &smContextCreateError,
Pistache::Http::Code code, std::string &n1_sm_msg) {
Logger::smf_n11().debug(
"[SMF N11] Send PDUSessionCreateContextResponse to AMF!");
Logger::smf_n11().debug("Send PDUSession_CreateSMContext Response to AMF.");
std::string boundary = "----Boundary";
nlohmann::json json_part = { };
......@@ -565,8 +649,7 @@ void smf_n11::send_pdu_session_update_sm_context_response(
Pistache::Http::ResponseWriter &httpResponse,
oai::smf_server::model::SmContextUpdatedData &smContextUpdatedData,
Pistache::Http::Code code) {
Logger::smf_n11().debug(
"[SMF N11] Send PDUSessionUpdateContextResponse to AMF!");
Logger::smf_n11().debug("Send PDUSession_UpdateSMContext Response to AMF.");
nlohmann::json json_data = { };
to_json(json_data, smContextUpdatedData);
if (!json_data.empty()) {
......@@ -584,8 +667,7 @@ void smf_n11::send_pdu_session_create_sm_context_response(
Pistache::Http::ResponseWriter &httpResponse,
oai::smf_server::model::SmContextCreatedData &smContextCreatedData,
Pistache::Http::Code code) {
Logger::smf_n11().debug(
"[SMF N11] Send PDUSessionUpdateContextResponse to AMF!");
Logger::smf_n11().debug("Send PDUSession_CreateSMContext Response to AMF.");
nlohmann::json json_data = { };
to_json(json_data, smContextCreatedData);
if (!json_data.empty()) {
......@@ -607,8 +689,7 @@ void smf_n11::send_n1n2_message_transfer_request(
//------------------------------------------------------------------------------
void smf_n11::send_pdu_session_release_sm_context_response(
Pistache::Http::ResponseWriter &httpResponse, Pistache::Http::Code code) {
Logger::smf_n11().debug(
"[SMF N11] Send PDUSessionReleaseContextResponse to AMF!");
Logger::smf_n11().debug("Send PDUSession_ReleaseSMContext Response to AMF.");
httpResponse.send(code);
}
......@@ -618,8 +699,7 @@ void smf_n11::send_pdu_session_release_sm_context_response(
oai::smf_server::model::ProblemDetails &problem,
Pistache::Http::Code code) {
Logger::smf_n11().debug(
"[SMF N11] Send PDUSessionReleaseContextResponse to AMF!");
Logger::smf_n11().debug("Send PDUSession_ReleaseSMContext Response to AMF.");
nlohmann::json json_data = { };
to_json(json_data, problem);
if (!json_data.empty()) {
......
......@@ -46,8 +46,6 @@ class smf_n11 {
std::thread::id thread_id;
std::thread thread;
void handle_receive_sm_data_notification();
public:
smf_n11();
smf_n11(smf_n11 const&) = delete;
......@@ -56,24 +54,31 @@ class smf_n11 {
/*
* Send N1N2 Message Transfer Request to AMF
* @param [std::shared_ptr<itti_n11_create_sm_context_response>] sm_context_res: Content of message to be sent
*
* @return void
*/
void send_n1n2_message_transfer_request(
std::shared_ptr<itti_n11_create_sm_context_response> sm_context_res);
/*
* Send N1N2 Message Transfer Request to AMF
* @param [std::shared_ptr<itti_nx_trigger_pdu_session_modification>] sm_context_res: Content of message to be sent
* @return void
*/
void send_n1n2_message_transfer_request(
std::shared_ptr<itti_nx_trigger_pdu_session_modification> sm_context_res);
/*
* Send update session response to AMF
* @param [std::shared_ptr<itti_n11_update_sm_context_response> sm_context_res] sm_context_res
*
* @return void
*/
void send_pdu_session_update_sm_context_response(
std::shared_ptr<itti_n11_update_sm_context_response> sm_context_res);
/*
* Send N1N2 Message Transfer Request to AMF
* @param [std::shared_ptr<itti_n11_modify_session_request_smf_requested>] sm_context_mod: Content of message to be sent
*
* @return void
*/
void send_n1n2_message_transfer_request(
std::shared_ptr<itti_n11_modify_session_request_smf_requested> sm_context_mod);
......@@ -83,7 +88,7 @@ class smf_n11 {
* @param [Pistache::Http::ResponseWriter] httpResponse
* @param [ oai::smf_server::model::SmContextUpdateError] SmContextUpdateError
* @param [Pistache::Http::Code] code, response code
*
* @return void
*/
void send_pdu_session_update_sm_context_response(
Pistache::Http::ResponseWriter &httpResponse,
......@@ -95,7 +100,7 @@ class smf_n11 {
* @param [Pistache::Http::ResponseWriter] httpResponse
* @param [ oai::smf_server::model::SmContextUpdatedData] smContextUpdatedData
* @param [Pistache::Http::Code] code, response code
*
* @return void
*/
void send_pdu_session_update_sm_context_response(
Pistache::Http::ResponseWriter &httpResponse,
......@@ -107,7 +112,7 @@ class smf_n11 {
* @param [Pistache::Http::ResponseWriter] httpResponse
* @param [ oai::smf_server::model::SmContextCreateError] smContextCreateError
* @param [Pistache::Http::Code] code, response code
*
* @return void
*/
void send_pdu_session_create_sm_context_response(
Pistache::Http::ResponseWriter &httpResponse,
......@@ -120,7 +125,7 @@ class smf_n11 {
* @param [ oai::smf_server::model::SmContextCreateError] smContextCreateError
* @param [Pistache::Http::Code] code, response code
* @param [std::string] n1_sm_msg, N1 SM message content
*
* @return void
*/
void send_pdu_session_create_sm_context_response(
Pistache::Http::ResponseWriter &httpResponse,
......@@ -133,7 +138,7 @@ class smf_n11 {
* @param [ oai::smf_server::model::SmContextUpdateError] smContextUpdateError
* @param [Pistache::Http::Code] code, response code
* @param [std::string] n1_sm_msg, N1 SM message content
*
* @return void
*/
void send_pdu_session_update_sm_context_response(
Pistache::Http::ResponseWriter &httpResponse,
......@@ -145,7 +150,7 @@ class smf_n11 {
* @param [Pistache::Http::ResponseWriter] httpResponse
* @param [ oai::smf_server::model::SmContextCreatedData] smContextCreatedData
* @param [Pistache::Http::Code] code, response code
*
* @return void
*/
void send_pdu_session_create_sm_context_response(
Pistache::Http::ResponseWriter &httpResponse,
......@@ -156,7 +161,7 @@ class smf_n11 {
* Send release session response to AMF
* @param [Pistache::Http::ResponseWriter] httpResponse
* @param [Pistache::Http::Code] code, response code
*
* @return void
*/
void send_pdu_session_release_sm_context_response(
Pistache::Http::ResponseWriter &httpResponse, Pistache::Http::Code code);
......@@ -166,7 +171,7 @@ class smf_n11 {
* @param [Pistache::Http::ResponseWriter] httpResponse
* @param [oai::smf_server::model::ProblemDetails] problem
* @param [Pistache::Http::Code] code, response code
*
* @return void
*/
void send_pdu_session_release_sm_context_response(
Pistache::Http::ResponseWriter &httpResponse,
......@@ -180,7 +185,7 @@ class smf_n11 {
* @param [std::string] boundary: Boundary of multipart/related msg
* @param [std::string] n1_message: N1 (NAS) part
* @param [std::string] n2_message: N2 (NGAP) part
*
* @return void
*/
void create_multipart_related_content(std::string &body,
std::string &json_part,
......@@ -195,7 +200,7 @@ class smf_n11 {
* @param [std::string] boundary: Boundary of multipart/related msg
* @param [std::string] message: N1 (NAS) or N2 (NGAP) part
* @param [uint8_t] content_type: 1 for NAS content, else NGAP content
*
* @return void
*/
void create_multipart_related_content(
std::string &body, std::string &json_part, std::string &boundary,
......
This diff is collapsed.
This diff is collapsed.
......@@ -71,7 +71,6 @@ class smf_procedure {
virtual itti_msg_type_t get_procedure_type() {
return ITTI_MSG_TYPE_NONE;
}
//virtual void handle_itti_msg (itti_n4_session_establishment_response& resp) {}
virtual void handle_itti_msg(itti_n4_session_establishment_response &resp,
std::shared_ptr<smf::smf_context> pc) {
}
......@@ -81,7 +80,6 @@ class smf_procedure {
virtual void handle_itti_msg(itti_n4_session_deletion_response &resp,
std::shared_ptr<smf::smf_context> pc) {
}
//virtual void handle_itti_msg (itti_s5s8_downlink_data_notification_acknowledge& resp) {}
};
class smf_qos_flow;
......@@ -100,10 +98,7 @@ class n4_session_restore_procedure : public smf_procedure {
}
int run();
//void handle_itti_msg (itti_n4_session_establishment_response& resp);
//~n4_session_restore_procedure() {}
std::set<pfcp::fseid_t> pending_sessions;
std::set<pfcp::fseid_t> restored_sessions;
};
......@@ -121,10 +116,23 @@ class session_create_sm_context_procedure : public smf_procedure {
n11_trigger() {
}
/*
* Execute N11 Create SM Context Request procedure
* @param [itti_n11_create_sm_context_request] req
* @param [itti_n11_create_sm_context_response] resp
* @param [std::shared_ptr<smf::smf_context>] sc: smf context
* @return
*/
int run(std::shared_ptr<itti_n11_create_sm_context_request> req,
std::shared_ptr<itti_n11_create_sm_context_response> resp,
std::shared_ptr<smf::smf_context> sc);
/*
* Handle N4 Session Establishment Response from UPF
* @param [itti_n4_session_establishment_response] resp
* @param [std::shared_ptr<smf::smf_context>] sc smf context
* @return void
*/
void handle_itti_msg(itti_n4_session_establishment_response &resp,
std::shared_ptr<smf::smf_context> sc);
......@@ -149,11 +157,19 @@ class session_update_sm_context_procedure : public smf_procedure {
session_procedure_type() {
}
/*
* Execute N11 Update SM Context Request procedure
* @param [itti_n11_update_sm_context_request] req
* @param [itti_n11_update_sm_context_response] resp
* @param [std::shared_ptr<smf::smf_context>] sc: smf context
* @return
*/
int run(std::shared_ptr<itti_n11_update_sm_context_request> req,
std::shared_ptr<itti_n11_update_sm_context_response> resp,
std::shared_ptr<smf::smf_context> sc);
/*
* Handle N4 modification response from UPF
* Handle N4 Session Modification Response from UPF
* @param [itti_n4_session_modification_response] resp
* @param [std::shared_ptr<smf::smf_context>] sc smf context
* @return void
......@@ -170,7 +186,6 @@ class session_update_sm_context_procedure : public smf_procedure {
};
//------------------------------------------------------------------------------
class session_release_sm_context_procedure : public smf_procedure {
public:
......@@ -184,11 +199,19 @@ class session_release_sm_context_procedure : public smf_procedure {
n11_trigger() {
}
/*
* Execute N11 Release SM Context Request procedure
* @param [itti_n11_release_sm_context_request] req
* @param [itti_n11_release_sm_context_response] resp
* @param [std::shared_ptr<smf::smf_context>] sc: smf context
* @return
*/
int run(std::shared_ptr<itti_n11_release_sm_context_request> req,
std::shared_ptr<itti_n11_release_sm_context_response> resp,
std::shared_ptr<smf::smf_context> sc);
/*
* Handle N4 modification response from UPF
* Handle N4 Session Modification Response from UPF
* @param [itti_n4_session_modification_response] resp
* @param [std::shared_ptr<smf::smf_context>] sc smf context
* @return void
......
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