Commit 2aec7a14 authored by Tien-Thinh Nguyen's avatar Tien-Thinh Nguyen

Merge branch 'separate_n1_n2' into 'develop'

Separate n1 n2

See merge request oai/cn5g/oai-cn5g-smf!25
parents 4620a1e2 aff44ff8
...@@ -62,6 +62,8 @@ void Logger::_init(const char *app, const bool log_stdout, ...@@ -62,6 +62,8 @@ void Logger::_init(const char *app, const bool log_stdout,
m_udp = new _Logger("udp ", m_sinks, ss.str().c_str()); m_udp = new _Logger("udp ", m_sinks, ss.str().c_str());
m_pfcp = new _Logger("pfcp ", m_sinks, ss.str().c_str()); m_pfcp = new _Logger("pfcp ", m_sinks, ss.str().c_str());
m_pfcp_switch = new _Logger("pfcp_sw ", m_sinks, ss.str().c_str()); m_pfcp_switch = new _Logger("pfcp_sw ", m_sinks, ss.str().c_str());
m_smf_n1 = new _Logger("smf_n1 ", m_sinks, ss.str().c_str());
m_smf_n2 = new _Logger("smf_n2 ", m_sinks, ss.str().c_str());
m_smf_n4 = new _Logger("smf_n4 ", m_sinks, ss.str().c_str()); m_smf_n4 = new _Logger("smf_n4 ", m_sinks, ss.str().c_str());
m_smf_n10 = new _Logger("smf_n10 ", m_sinks, ss.str().c_str()); m_smf_n10 = new _Logger("smf_n10 ", m_sinks, ss.str().c_str());
m_smf_n11 = new _Logger("smf_n11 ", m_sinks, ss.str().c_str()); m_smf_n11 = new _Logger("smf_n11 ", m_sinks, ss.str().c_str());
......
...@@ -107,6 +107,13 @@ class Logger { ...@@ -107,6 +107,13 @@ class Logger {
static _Logger& pfcp_switch() { static _Logger& pfcp_switch() {
return *singleton().m_pfcp_switch; return *singleton().m_pfcp_switch;
} }
static _Logger& smf_n1() {
return *singleton().m_smf_n1;
}
static _Logger& smf_n2() {
return *singleton().m_smf_n2;
}
static _Logger& smf_n4() { static _Logger& smf_n4() {
return *singleton().m_smf_n4; return *singleton().m_smf_n4;
} }
...@@ -146,6 +153,8 @@ class Logger { ...@@ -146,6 +153,8 @@ class Logger {
_Logger *m_udp; _Logger *m_udp;
_Logger *m_pfcp; _Logger *m_pfcp;
_Logger *m_pfcp_switch; _Logger *m_pfcp_switch;
_Logger *m_smf_n1;
_Logger *m_smf_n2;
_Logger *m_smf_n4; _Logger *m_smf_n4;
_Logger *m_smf_n10; _Logger *m_smf_n10;
_Logger *m_smf_n11; _Logger *m_smf_n11;
......
...@@ -49,7 +49,8 @@ add_library (SMF STATIC ...@@ -49,7 +49,8 @@ add_library (SMF STATIC
smf_app.cpp smf_app.cpp
smf_config.cpp smf_config.cpp
smf_context.cpp smf_context.cpp
smf_n1_n2.cpp smf_n1.cpp
smf_n2.cpp
smf_pfcp_association.cpp smf_pfcp_association.cpp
smf_pco.cpp smf_pco.cpp
smf_procedure.cpp smf_procedure.cpp
......
...@@ -44,7 +44,7 @@ ...@@ -44,7 +44,7 @@
#include "3gpp_24.007.h" #include "3gpp_24.007.h"
#include "smf.h" #include "smf.h"
#include "3gpp_24.501.h" #include "3gpp_24.501.h"
#include "smf_n1_n2.hpp" #include "smf_n1.hpp"
#include "smf_paa_dynamic.hpp" #include "smf_paa_dynamic.hpp"
#include "smf_n4.hpp" #include "smf_n4.hpp"
#include "smf_n10.hpp" #include "smf_n10.hpp"
...@@ -548,7 +548,7 @@ void smf_app::handle_pdu_session_create_sm_context_request( ...@@ -548,7 +548,7 @@ void smf_app::handle_pdu_session_create_sm_context_request(
oai::smf_server::model::ProblemDetails problem_details = { }; oai::smf_server::model::ProblemDetails problem_details = { };
oai::smf_server::model::RefToBinaryData refToBinaryData = { }; oai::smf_server::model::RefToBinaryData refToBinaryData = { };
std::string n1_sm_message, n1_sm_message_hex; std::string n1_sm_message, n1_sm_message_hex;
smf_n1_n2 smf_n1_n2_inst = { }; smf_n1 smf_n1_inst = { };
nas_message_t decoded_nas_msg = { }; nas_message_t decoded_nas_msg = { };
cause_value_5gsm_e cause_n1 = { cause_value_5gsm_e::CAUSE_0_UNKNOWN }; cause_value_5gsm_e cause_n1 = { cause_value_5gsm_e::CAUSE_0_UNKNOWN };
pdu_session_type_t pdu_session_type = { .pdu_session_type = pdu_session_type_t pdu_session_type = { .pdu_session_type =
...@@ -557,7 +557,7 @@ void smf_app::handle_pdu_session_create_sm_context_request( ...@@ -557,7 +557,7 @@ void smf_app::handle_pdu_session_create_sm_context_request(
//Step 1. Decode NAS and get the necessary information //Step 1. Decode NAS and get the necessary information
std::string n1_sm_msg = smreq->req.get_n1_sm_message(); std::string n1_sm_msg = smreq->req.get_n1_sm_message();
int decoder_rc = smf_n1_n2_inst.decode_n1_sm_container(decoded_nas_msg, int decoder_rc = smf_n1_inst.decode_n1_sm_container(decoded_nas_msg,
n1_sm_msg); n1_sm_msg);
if (decoder_rc != RETURNok) { if (decoder_rc != RETURNok) {
//error, send reply to AMF with PDU Session Establishment Reject //error, send reply to AMF with PDU Session Establishment Reject
...@@ -567,9 +567,9 @@ void smf_app::handle_pdu_session_create_sm_context_request( ...@@ -567,9 +567,9 @@ void smf_app::handle_pdu_session_create_sm_context_request(
smContextCreateError.setError(problem_details); smContextCreateError.setError(problem_details);
refToBinaryData.setContentId(N1_SM_CONTENT_ID); refToBinaryData.setContentId(N1_SM_CONTENT_ID);
smContextCreateError.setN1SmMsg(refToBinaryData); smContextCreateError.setN1SmMsg(refToBinaryData);
if (smf_n1_n2_inst.create_n1_sm_container( if (smf_n1_inst.create_n1_pdu_session_establishment_reject(
smreq->req, PDU_SESSION_ESTABLISHMENT_REJECT, n1_sm_message, smreq->req, n1_sm_message,
cause_value_5gsm_e::CAUSE_95_SEMANTICALLY_INCORRECT_MESSAGE)) { cause_value_5gsm_e::CAUSE_95_SEMANTICALLY_INCORRECT_MESSAGE)) {
smf_app_inst->convert_string_2_hex(n1_sm_message, n1_sm_message_hex); smf_app_inst->convert_string_2_hex(n1_sm_message, n1_sm_message_hex);
//trigger to send reply to AMF //trigger to send reply to AMF
trigger_http_response(http_status_code_e::HTTP_STATUS_CODE_403_FORBIDDEN, trigger_http_response(http_status_code_e::HTTP_STATUS_CODE_403_FORBIDDEN,
...@@ -625,9 +625,8 @@ void smf_app::handle_pdu_session_create_sm_context_request( ...@@ -625,9 +625,8 @@ void smf_app::handle_pdu_session_create_sm_context_request(
refToBinaryData.setContentId(N1_SM_CONTENT_ID); refToBinaryData.setContentId(N1_SM_CONTENT_ID);
smContextCreateError.setN1SmMsg(refToBinaryData); smContextCreateError.setN1SmMsg(refToBinaryData);
//PDU Session Establishment Reject //PDU Session Establishment Reject
if (smf_n1_n2_inst.create_n1_sm_container(smreq->req, if (smf_n1_inst.create_n1_pdu_session_establishment_reject(smreq->req,
PDU_SESSION_ESTABLISHMENT_REJECT, n1_sm_message, cause_n1)) {
n1_sm_message, cause_n1)) {
smf_app_inst->convert_string_2_hex(n1_sm_message, n1_sm_message_hex); smf_app_inst->convert_string_2_hex(n1_sm_message, n1_sm_message_hex);
//trigger to send reply to AMF //trigger to send reply to AMF
trigger_http_response(http_status_code_e::HTTP_STATUS_CODE_403_FORBIDDEN, trigger_http_response(http_status_code_e::HTTP_STATUS_CODE_403_FORBIDDEN,
...@@ -677,9 +676,9 @@ void smf_app::handle_pdu_session_create_sm_context_request( ...@@ -677,9 +676,9 @@ void smf_app::handle_pdu_session_create_sm_context_request(
refToBinaryData.setContentId(N1_SM_CONTENT_ID); refToBinaryData.setContentId(N1_SM_CONTENT_ID);
smContextCreateError.setN1SmMsg(refToBinaryData); smContextCreateError.setN1SmMsg(refToBinaryData);
//PDU Session Establishment Reject including cause "#81 Invalid PTI value" (section 7.3.1 @3GPP TS 24.501) //PDU Session Establishment Reject including cause "#81 Invalid PTI value" (section 7.3.1 @3GPP TS 24.501)
if (smf_n1_n2_inst.create_n1_sm_container( if (smf_n1_inst.create_n1_pdu_session_establishment_reject(
smreq->req, PDU_SESSION_ESTABLISHMENT_REJECT, n1_sm_message, smreq->req, n1_sm_message,
cause_value_5gsm_e::CAUSE_81_INVALID_PTI_VALUE)) { cause_value_5gsm_e::CAUSE_81_INVALID_PTI_VALUE)) {
smf_app_inst->convert_string_2_hex(n1_sm_message, n1_sm_message_hex); smf_app_inst->convert_string_2_hex(n1_sm_message, n1_sm_message_hex);
//trigger to send reply to AMF //trigger to send reply to AMF
trigger_http_response(http_status_code_e::HTTP_STATUS_CODE_403_FORBIDDEN, trigger_http_response(http_status_code_e::HTTP_STATUS_CODE_403_FORBIDDEN,
...@@ -717,12 +716,10 @@ void smf_app::handle_pdu_session_create_sm_context_request( ...@@ -717,12 +716,10 @@ void smf_app::handle_pdu_session_create_sm_context_request(
smContextCreateError.setN1SmMsg(refToBinaryData); smContextCreateError.setN1SmMsg(refToBinaryData);
//PDU Session Establishment Reject //PDU Session Establishment Reject
//(24.501 (section 7.4)) implementation dependent->do similar to UE: response with a 5GSM STATUS message including cause "#98 message type not compatible with protocol state." //(24.501 (section 7.4)) implementation dependent->do similar to UE: response with a 5GSM STATUS message including cause "#98 message type not compatible with protocol state."
if (smf_n1_n2_inst.create_n1_sm_container( if (smf_n1_inst.create_n1_pdu_session_establishment_reject(
smreq->req, smreq->req,
PDU_SESSION_ESTABLISHMENT_REJECT, n1_sm_message,
n1_sm_message, cause_value_5gsm_e::CAUSE_98_MESSAGE_TYPE_NOT_COMPATIBLE_WITH_PROTOCOL_STATE)) {
cause_value_5gsm_e::CAUSE_98_MESSAGE_TYPE_NOT_COMPATIBLE_WITH_PROTOCOL_STATE)) {
smf_app_inst->convert_string_2_hex(n1_sm_message, n1_sm_message_hex); smf_app_inst->convert_string_2_hex(n1_sm_message, n1_sm_message_hex);
//trigger to send reply to AMF //trigger to send reply to AMF
trigger_http_response(http_status_code_e::HTTP_STATUS_CODE_403_FORBIDDEN, trigger_http_response(http_status_code_e::HTTP_STATUS_CODE_403_FORBIDDEN,
...@@ -759,9 +756,9 @@ void smf_app::handle_pdu_session_create_sm_context_request( ...@@ -759,9 +756,9 @@ void smf_app::handle_pdu_session_create_sm_context_request(
refToBinaryData.setContentId(N1_SM_CONTENT_ID); refToBinaryData.setContentId(N1_SM_CONTENT_ID);
smContextCreateError.setN1SmMsg(refToBinaryData); smContextCreateError.setN1SmMsg(refToBinaryData);
//PDU Session Establishment Reject, 24.501 cause "#27 Missing or unknown DNN" //PDU Session Establishment Reject, 24.501 cause "#27 Missing or unknown DNN"
if (smf_n1_n2_inst.create_n1_sm_container( if (smf_n1_inst.create_n1_pdu_session_establishment_reject(
smreq->req, PDU_SESSION_ESTABLISHMENT_REJECT, n1_sm_message, smreq->req, n1_sm_message,
cause_value_5gsm_e::CAUSE_27_MISSING_OR_UNKNOWN_DNN)) { cause_value_5gsm_e::CAUSE_27_MISSING_OR_UNKNOWN_DNN)) {
smf_app_inst->convert_string_2_hex(n1_sm_message, n1_sm_message_hex); smf_app_inst->convert_string_2_hex(n1_sm_message, n1_sm_message_hex);
//trigger to send reply to AMF //trigger to send reply to AMF
trigger_http_response(http_status_code_e::HTTP_STATUS_CODE_403_FORBIDDEN, trigger_http_response(http_status_code_e::HTTP_STATUS_CODE_403_FORBIDDEN,
...@@ -851,12 +848,11 @@ void smf_app::handle_pdu_session_create_sm_context_request( ...@@ -851,12 +848,11 @@ void smf_app::handle_pdu_session_create_sm_context_request(
refToBinaryData.setContentId(N1_SM_CONTENT_ID); refToBinaryData.setContentId(N1_SM_CONTENT_ID);
smContextCreateError.setN1SmMsg(refToBinaryData); smContextCreateError.setN1SmMsg(refToBinaryData);
//PDU Session Establishment Reject, with cause "29 User authentication or authorization failed" //PDU Session Establishment Reject, with cause "29 User authentication or authorization failed"
if (smf_n1_n2_inst.create_n1_sm_container( if (smf_n1_inst.create_n1_pdu_session_establishment_reject(
smreq->req, smreq->req,
PDU_SESSION_ESTABLISHMENT_REJECT,
n1_sm_message, n1_sm_message,
cause_value_5gsm_e::CAUSE_29_USER_AUTHENTICATION_OR_AUTHORIZATION_FAILED)) { cause_value_5gsm_e::CAUSE_29_USER_AUTHENTICATION_OR_AUTHORIZATION_FAILED)) {
smf_app_inst->convert_string_2_hex(n1_sm_message, n1_sm_message_hex); smf_app_inst->convert_string_2_hex(n1_sm_message, n1_sm_message_hex);
//trigger to send reply to AMF //trigger to send reply to AMF
trigger_http_response( trigger_http_response(
http_status_code_e::HTTP_STATUS_CODE_403_FORBIDDEN, http_status_code_e::HTTP_STATUS_CODE_403_FORBIDDEN,
......
...@@ -36,7 +36,8 @@ ...@@ -36,7 +36,8 @@
#include "smf_app.hpp" #include "smf_app.hpp"
#include "smf_n11.hpp" #include "smf_n11.hpp"
#include "smf_config.hpp" #include "smf_config.hpp"
#include "smf_n1_n2.hpp" #include "smf_n1.hpp"
#include "smf_n2.hpp"
#include "smf_paa_dynamic.hpp" #include "smf_paa_dynamic.hpp"
#include "smf_procedure.hpp" #include "smf_procedure.hpp"
#include "ProblemDetails.h" #include "ProblemDetails.h"
...@@ -728,11 +729,12 @@ void smf_context::handle_itti_msg( ...@@ -728,11 +729,12 @@ void smf_context::handle_itti_msg(
// Create N2 SM Information: PDU Session Resource Setup Request Transfer IE // Create N2 SM Information: PDU Session Resource Setup Request Transfer IE
//N2 SM Information //N2 SM Information
smf_n1_n2 smf_n1_n2_inst = { }; smf_n2 smf_n2_inst = { };
std::string n2_sm_info, n2_sm_info_hex; std::string n2_sm_info, n2_sm_info_hex;
smf_n1_n2_inst.create_n2_sm_information( smf_n2_inst.create_n2_pdu_session_resource_setup_request_transfer(
session_report_msg, 1, n2_sm_info_type_e::PDU_RES_SETUP_REQ, session_report_msg, n2_sm_info_type_e::PDU_RES_SETUP_REQ,
n2_sm_info); n2_sm_info);
smf_app_inst->convert_string_2_hex(n2_sm_info, n2_sm_info_hex); smf_app_inst->convert_string_2_hex(n2_sm_info, n2_sm_info_hex);
session_report_msg.set_n2_sm_information(n2_sm_info_hex); session_report_msg.set_n2_sm_information(n2_sm_info_hex);
...@@ -1130,7 +1132,7 @@ void smf_context::handle_pdu_session_create_sm_context_request( ...@@ -1130,7 +1132,7 @@ void smf_context::handle_pdu_session_create_sm_context_request(
oai::smf_server::model::ProblemDetails problem_details = { }; oai::smf_server::model::ProblemDetails problem_details = { };
oai::smf_server::model::RefToBinaryData refToBinaryData = { }; oai::smf_server::model::RefToBinaryData refToBinaryData = { };
std::string n1_sm_message, n1_sm_msg_hex; std::string n1_sm_message, n1_sm_msg_hex;
smf_n1_n2 smf_n1_n2_inst = { }; smf_n1 smf_n1_inst = { };
bool request_accepted = true; bool request_accepted = true;
//Step 1. get necessary information //Step 1. get necessary information
...@@ -1151,12 +1153,10 @@ void smf_context::handle_pdu_session_create_sm_context_request( ...@@ -1151,12 +1153,10 @@ void smf_context::handle_pdu_session_create_sm_context_request(
smContextCreateError.setError(problem_details); smContextCreateError.setError(problem_details);
refToBinaryData.setContentId(N1_SM_CONTENT_ID); refToBinaryData.setContentId(N1_SM_CONTENT_ID);
smContextCreateError.setN1SmMsg(refToBinaryData); smContextCreateError.setN1SmMsg(refToBinaryData);
if (smf_n1_n2_inst.create_n1_sm_container( if (smf_n1_inst.create_n1_pdu_session_establishment_reject(
smreq->req, smreq->req,
PDU_SESSION_ESTABLISHMENT_REJECT,
n1_sm_message, n1_sm_message,
cause_value_5gsm_e::CAUSE_29_USER_AUTHENTICATION_OR_AUTHORIZATION_FAILED)) { cause_value_5gsm_e::CAUSE_29_USER_AUTHENTICATION_OR_AUTHORIZATION_FAILED)) {
smf_app_inst->convert_string_2_hex(n1_sm_message, n1_sm_msg_hex); smf_app_inst->convert_string_2_hex(n1_sm_message, n1_sm_msg_hex);
//trigger to send reply to AMF //trigger to send reply to AMF
smf_app_inst->trigger_http_response( smf_app_inst->trigger_http_response(
...@@ -1328,9 +1328,9 @@ void smf_context::handle_pdu_session_create_sm_context_request( ...@@ -1328,9 +1328,9 @@ void smf_context::handle_pdu_session_create_sm_context_request(
refToBinaryData.setContentId(N1_SM_CONTENT_ID); refToBinaryData.setContentId(N1_SM_CONTENT_ID);
smContextCreateError.setN1SmMsg(refToBinaryData); smContextCreateError.setN1SmMsg(refToBinaryData);
//PDU Session Establishment Reject //PDU Session Establishment Reject
if (smf_n1_n2_inst.create_n1_sm_container( if (smf_n1_inst.create_n1_pdu_session_establishment_reject(
smreq->req, PDU_SESSION_ESTABLISHMENT_REJECT, n1_sm_message, smreq->req, n1_sm_message,
cause_value_5gsm_e::CAUSE_28_UNKNOWN_PDU_SESSION_TYPE)) { cause_value_5gsm_e::CAUSE_28_UNKNOWN_PDU_SESSION_TYPE)) {
smf_app_inst->convert_string_2_hex(n1_sm_message, n1_sm_msg_hex); smf_app_inst->convert_string_2_hex(n1_sm_message, n1_sm_msg_hex);
//trigger to send reply to AMF //trigger to send reply to AMF
smf_app_inst->trigger_http_response( smf_app_inst->trigger_http_response(
...@@ -1449,9 +1449,8 @@ void smf_context::handle_pdu_session_create_sm_context_request( ...@@ -1449,9 +1449,8 @@ void smf_context::handle_pdu_session_create_sm_context_request(
if (sm_context_resp->res.get_cause() == NO_RESOURCES_AVAILABLE) { if (sm_context_resp->res.get_cause() == NO_RESOURCES_AVAILABLE) {
cause_n1 = cause_value_5gsm_e::CAUSE_26_INSUFFICIENT_RESOURCES; cause_n1 = cause_value_5gsm_e::CAUSE_26_INSUFFICIENT_RESOURCES;
} }
smf_n1_n2_inst.create_n1_sm_container(sm_context_resp_pending->res, smf_n1_inst.create_n1_pdu_session_establishment_reject(sm_context_resp_pending->res,
PDU_SESSION_ESTABLISHMENT_REJECT, n1_sm_message, cause_n1);
n1_sm_message, cause_n1);
smf_app_inst->convert_string_2_hex(n1_sm_message, n1_sm_msg_hex); smf_app_inst->convert_string_2_hex(n1_sm_message, n1_sm_msg_hex);
sm_context_resp_pending->res.set_n1_sm_message(n1_sm_msg_hex); sm_context_resp_pending->res.set_n1_sm_message(n1_sm_msg_hex);
...@@ -1498,7 +1497,8 @@ void smf_context::handle_pdu_session_update_sm_context_request( ...@@ -1498,7 +1497,8 @@ void smf_context::handle_pdu_session_update_sm_context_request(
"Handle a PDU Session Update SM Context Request message from an AMF (HTTP version %d)", "Handle a PDU Session Update SM Context Request message from an AMF (HTTP version %d)",
smreq->http_version); smreq->http_version);
pdu_session_update_sm_context_request sm_context_req_msg = smreq->req; pdu_session_update_sm_context_request sm_context_req_msg = smreq->req;
smf_n1_n2 smf_n1_n2_inst = { }; smf_n1 smf_n1_inst = { };
smf_n2 smf_n2_inst = { };
oai::smf_server::model::SmContextUpdateError smContextUpdateError = { }; oai::smf_server::model::SmContextUpdateError smContextUpdateError = { };
oai::smf_server::model::SmContextUpdatedData smContextUpdatedData = { }; oai::smf_server::model::SmContextUpdatedData smContextUpdatedData = { };
oai::smf_server::model::ProblemDetails problem_details = { }; oai::smf_server::model::ProblemDetails problem_details = { };
...@@ -1560,7 +1560,7 @@ void smf_context::handle_pdu_session_update_sm_context_request( ...@@ -1560,7 +1560,7 @@ void smf_context::handle_pdu_session_update_sm_context_request(
n1_sm_msg = sm_context_req_msg.get_n1_sm_message(); n1_sm_msg = sm_context_req_msg.get_n1_sm_message();
memset(&decoded_nas_msg, 0, sizeof(nas_message_t)); memset(&decoded_nas_msg, 0, sizeof(nas_message_t));
int decoder_rc = smf_n1_n2_inst.decode_n1_sm_container(decoded_nas_msg, int decoder_rc = smf_n1_inst.decode_n1_sm_container(decoded_nas_msg,
n1_sm_msg); n1_sm_msg);
if (decoder_rc != RETURNok) { if (decoder_rc != RETURNok) {
//error, send reply to AMF with error code!! //error, send reply to AMF with error code!!
...@@ -1788,12 +1788,11 @@ void smf_context::handle_pdu_session_update_sm_context_request( ...@@ -1788,12 +1788,11 @@ void smf_context::handle_pdu_session_update_sm_context_request(
std::string n1_sm_msg_to_be_created, n1_sm_msg_hex_to_be_created; std::string n1_sm_msg_to_be_created, n1_sm_msg_hex_to_be_created;
std::string n2_sm_info_to_be_created, n2_sm_info_hex_to_be_created; std::string n2_sm_info_to_be_created, n2_sm_info_hex_to_be_created;
//N1 SM (PDU Session Modification Command) //N1 SM (PDU Session Modification Command)
if (not smf_n1_n2_inst.create_n1_sm_container( if (not smf_n1_inst.create_n1_pdu_session_modification_command(
n11_sm_context_resp->res, PDU_SESSION_MODIFICATION_COMMAND, n11_sm_context_resp->res, n1_sm_msg_to_be_created, cause_value_5gsm_e::CAUSE_0_UNKNOWN) or //TODO: need cause?
n1_sm_msg_to_be_created, cause_value_5gsm_e::CAUSE_0_UNKNOWN) or //TODO: need cause?
//N2 SM (PDU Session Resource Modify Request Transfer IE) //N2 SM (PDU Session Resource Modify Request Transfer IE)
not smf_n1_n2_inst.create_n2_sm_information( not smf_n2_inst.create_n2_pdu_session_resource_modify_request_transfer(
n11_sm_context_resp->res, 1, n2_sm_info_type_e::PDU_RES_MOD_REQ, n11_sm_context_resp->res, n2_sm_info_type_e::PDU_RES_MOD_REQ,
n2_sm_info_to_be_created)) { n2_sm_info_to_be_created)) {
smf_app_inst->trigger_http_response( smf_app_inst->trigger_http_response(
http_status_code_e::HTTP_STATUS_CODE_500_INTERNAL_SERVER_ERROR, http_status_code_e::HTTP_STATUS_CODE_500_INTERNAL_SERVER_ERROR,
...@@ -1953,10 +1952,9 @@ void smf_context::handle_pdu_session_update_sm_context_request( ...@@ -1953,10 +1952,9 @@ void smf_context::handle_pdu_session_update_sm_context_request(
smContextUpdateError.setError(problem_details); smContextUpdateError.setError(problem_details);
refToBinaryData.setContentId(N1_SM_CONTENT_ID); refToBinaryData.setContentId(N1_SM_CONTENT_ID);
smContextUpdateError.setN1SmMsg(refToBinaryData); smContextUpdateError.setN1SmMsg(refToBinaryData);
if (smf_n1_n2_inst.create_n1_sm_container( if (smf_n1_inst.create_n1_pdu_session_release_reject(
sm_context_req_msg, PDU_SESSION_RELEASE_REJECT, n1_sm_msg, sm_context_req_msg, n1_sm_msg,
cause_value_5gsm_e::CAUSE_43_INVALID_PDU_SESSION_IDENTITY)) { cause_value_5gsm_e::CAUSE_43_INVALID_PDU_SESSION_IDENTITY)) {
smf_app_inst->convert_string_2_hex(n1_sm_msg, n1_sm_msg_hex); smf_app_inst->convert_string_2_hex(n1_sm_msg, n1_sm_msg_hex);
//trigger to send reply to AMF //trigger to send reply to AMF
smf_app_inst->trigger_http_response( smf_app_inst->trigger_http_response(
...@@ -2105,7 +2103,7 @@ void smf_context::handle_pdu_session_update_sm_context_request( ...@@ -2105,7 +2103,7 @@ void smf_context::handle_pdu_session_update_sm_context_request(
//Ngap_PDUSessionResourceSetupResponseTransfer //Ngap_PDUSessionResourceSetupResponseTransfer
std::shared_ptr<Ngap_PDUSessionResourceSetupResponseTransfer_t> decoded_msg = std::shared_ptr<Ngap_PDUSessionResourceSetupResponseTransfer_t> decoded_msg =
std::make_shared<Ngap_PDUSessionResourceSetupResponseTransfer_t>(); std::make_shared<Ngap_PDUSessionResourceSetupResponseTransfer_t>();
int decode_status = smf_n1_n2_inst.decode_n2_sm_information( int decode_status = smf_n2_inst.decode_n2_sm_information(
decoded_msg, n2_sm_information); decoded_msg, n2_sm_information);
if (decode_status == RETURNerror) { if (decode_status == RETURNerror) {
//error, send error to AMF //error, send error to AMF
...@@ -2118,10 +2116,9 @@ void smf_context::handle_pdu_session_update_sm_context_request( ...@@ -2118,10 +2116,9 @@ void smf_context::handle_pdu_session_update_sm_context_request(
smContextUpdateError.setN1SmMsg(refToBinaryData); smContextUpdateError.setN1SmMsg(refToBinaryData);
//PDU Session Establishment Reject //PDU Session Establishment Reject
//24.501: response with a 5GSM STATUS message including cause "#95 Semantically incorrect message" //24.501: response with a 5GSM STATUS message including cause "#95 Semantically incorrect message"
if (smf_n1_n2_inst.create_n1_sm_container( if (smf_n1_inst.create_n1_pdu_session_establishment_reject(
sm_context_req_msg, PDU_SESSION_ESTABLISHMENT_REJECT, n1_sm_msg, sm_context_req_msg, n1_sm_msg,
cause_value_5gsm_e::CAUSE_95_SEMANTICALLY_INCORRECT_MESSAGE)) { cause_value_5gsm_e::CAUSE_95_SEMANTICALLY_INCORRECT_MESSAGE)) {
smf_app_inst->convert_string_2_hex(n1_sm_msg, n1_sm_msg_hex); //TODO: need N1SM? smf_app_inst->convert_string_2_hex(n1_sm_msg, n1_sm_msg_hex); //TODO: need N1SM?
//trigger to send reply to AMF //trigger to send reply to AMF
smf_app_inst->trigger_http_response( smf_app_inst->trigger_http_response(
...@@ -2186,7 +2183,7 @@ void smf_context::handle_pdu_session_update_sm_context_request( ...@@ -2186,7 +2183,7 @@ void smf_context::handle_pdu_session_update_sm_context_request(
//Ngap_PDUSessionResourceSetupUnsuccessfulTransfer //Ngap_PDUSessionResourceSetupUnsuccessfulTransfer
std::shared_ptr<Ngap_PDUSessionResourceSetupUnsuccessfulTransfer_t> decoded_msg = std::shared_ptr<Ngap_PDUSessionResourceSetupUnsuccessfulTransfer_t> decoded_msg =
std::make_shared<Ngap_PDUSessionResourceSetupUnsuccessfulTransfer_t>(); std::make_shared<Ngap_PDUSessionResourceSetupUnsuccessfulTransfer_t>();
int decode_status = smf_n1_n2_inst.decode_n2_sm_information( int decode_status = smf_n2_inst.decode_n2_sm_information(
decoded_msg, n2_sm_information); decoded_msg, n2_sm_information);
if (decode_status == RETURNerror) { if (decode_status == RETURNerror) {
...@@ -2210,9 +2207,9 @@ void smf_context::handle_pdu_session_update_sm_context_request( ...@@ -2210,9 +2207,9 @@ void smf_context::handle_pdu_session_update_sm_context_request(
refToBinaryData.setContentId(N1_SM_CONTENT_ID); refToBinaryData.setContentId(N1_SM_CONTENT_ID);
smContextUpdateError.setN1SmMsg(refToBinaryData); smContextUpdateError.setN1SmMsg(refToBinaryData);
//PDU Session Establishment Reject, 24.501 cause "#26 Insufficient resources" //PDU Session Establishment Reject, 24.501 cause "#26 Insufficient resources"
if (smf_n1_n2_inst.create_n1_sm_container( if (smf_n1_inst.create_n1_pdu_session_establishment_reject(
smreq->req, PDU_SESSION_ESTABLISHMENT_REJECT, n1_sm_msg, smreq->req, n1_sm_msg,
cause_value_5gsm_e::CAUSE_26_INSUFFICIENT_RESOURCES)) { cause_value_5gsm_e::CAUSE_26_INSUFFICIENT_RESOURCES)) {
smf_app_inst->convert_string_2_hex(n1_sm_msg, n1_sm_msg_hex); smf_app_inst->convert_string_2_hex(n1_sm_msg, n1_sm_msg_hex);
//trigger to send reply to AMF //trigger to send reply to AMF
smf_app_inst->trigger_http_response( smf_app_inst->trigger_http_response(
...@@ -2238,7 +2235,7 @@ void smf_context::handle_pdu_session_update_sm_context_request( ...@@ -2238,7 +2235,7 @@ void smf_context::handle_pdu_session_update_sm_context_request(
//Ngap_PDUSessionResourceModifyResponseTransfer //Ngap_PDUSessionResourceModifyResponseTransfer
std::shared_ptr<Ngap_PDUSessionResourceModifyResponseTransfer_t> decoded_msg = std::shared_ptr<Ngap_PDUSessionResourceModifyResponseTransfer_t> decoded_msg =
std::make_shared<Ngap_PDUSessionResourceModifyResponseTransfer_t>(); std::make_shared<Ngap_PDUSessionResourceModifyResponseTransfer_t>();
int decode_status = smf_n1_n2_inst.decode_n2_sm_information( int decode_status = smf_n2_inst.decode_n2_sm_information(
decoded_msg, n2_sm_information); decoded_msg, n2_sm_information);
if (decode_status == RETURNerror) { if (decode_status == RETURNerror) {
...@@ -2311,7 +2308,7 @@ void smf_context::handle_pdu_session_update_sm_context_request( ...@@ -2311,7 +2308,7 @@ void smf_context::handle_pdu_session_update_sm_context_request(
//Ngap_PDUSessionResourceReleaseResponseTransfer //Ngap_PDUSessionResourceReleaseResponseTransfer
std::shared_ptr<Ngap_PDUSessionResourceReleaseResponseTransfer_t> decoded_msg = std::shared_ptr<Ngap_PDUSessionResourceReleaseResponseTransfer_t> decoded_msg =
std::make_shared<Ngap_PDUSessionResourceReleaseResponseTransfer_t>(); std::make_shared<Ngap_PDUSessionResourceReleaseResponseTransfer_t>();
int decode_status = smf_n1_n2_inst.decode_n2_sm_information( int decode_status = smf_n2_inst.decode_n2_sm_information(
decoded_msg, n2_sm_information); decoded_msg, n2_sm_information);
if (decode_status == RETURNerror) { if (decode_status == RETURNerror) {
Logger::smf_app().warn( Logger::smf_app().warn(
...@@ -2369,9 +2366,10 @@ void smf_context::handle_pdu_session_update_sm_context_request( ...@@ -2369,9 +2366,10 @@ void smf_context::handle_pdu_session_update_sm_context_request(
// Create N2 SM Information: PDU Session Resource Setup Request Transfer IE // Create N2 SM Information: PDU Session Resource Setup Request Transfer IE
//N2 SM Information //N2 SM Information
smf_n1_n2_inst.create_n2_sm_information( smf_n2_inst.create_n2_pdu_session_resource_setup_request_transfer(
sm_context_resp_pending->res, 1, n2_sm_info_type_e::PDU_RES_SETUP_REQ, sm_context_resp_pending->res, n2_sm_info_type_e::PDU_RES_SETUP_REQ,
n2_sm_info); n2_sm_info);
smf_app_inst->convert_string_2_hex(n2_sm_info, n2_sm_info_hex); smf_app_inst->convert_string_2_hex(n2_sm_info, n2_sm_info_hex);
sm_context_resp_pending->res.set_n2_sm_information(n2_sm_info_hex); sm_context_resp_pending->res.set_n2_sm_information(n2_sm_info_hex);
...@@ -2443,8 +2441,8 @@ void smf_context::handle_pdu_session_update_sm_context_request( ...@@ -2443,8 +2441,8 @@ void smf_context::handle_pdu_session_update_sm_context_request(
refToBinaryData.setContentId(N1_SM_CONTENT_ID); refToBinaryData.setContentId(N1_SM_CONTENT_ID);
smContextUpdateError.setN1SmMsg(refToBinaryData); smContextUpdateError.setN1SmMsg(refToBinaryData);
//PDU Session Establishment Reject //PDU Session Establishment Reject
if (smf_n1_n2_inst.create_n1_sm_container( if (smf_n1_inst.create_n1_pdu_session_establishment_reject(
sm_context_req_msg, PDU_SESSION_ESTABLISHMENT_REJECT, n1_sm_msg, sm_context_req_msg, n1_sm_msg,
cause_value_5gsm_e::CAUSE_38_NETWORK_FAILURE)) { cause_value_5gsm_e::CAUSE_38_NETWORK_FAILURE)) {
smf_app_inst->convert_string_2_hex(n1_sm_msg, n1_sm_msg_hex); smf_app_inst->convert_string_2_hex(n1_sm_msg, n1_sm_msg_hex);
//trigger to send reply to AMF //trigger to send reply to AMF
...@@ -2575,7 +2573,8 @@ void smf_context::handle_pdu_session_modification_network_requested( ...@@ -2575,7 +2573,8 @@ void smf_context::handle_pdu_session_modification_network_requested(
Logger::smf_app().info( Logger::smf_app().info(
"Handle a PDU Session Modification Request (SMF-Requested)"); "Handle a PDU Session Modification Request (SMF-Requested)");
smf_n1_n2 smf_n1_n2_inst = { }; smf_n1 smf_n1_inst = { };
smf_n2 smf_n2_inst = { };
oai::smf_server::model::SmContextUpdateError smContextUpdateError = { }; oai::smf_server::model::SmContextUpdateError smContextUpdateError = { };
oai::smf_server::model::SmContextUpdatedData smContextUpdatedData = { }; oai::smf_server::model::SmContextUpdatedData smContextUpdatedData = { };
oai::smf_server::model::ProblemDetails problem_details = { }; oai::smf_server::model::ProblemDetails problem_details = { };
...@@ -2630,15 +2629,14 @@ void smf_context::handle_pdu_session_modification_network_requested( ...@@ -2630,15 +2629,14 @@ void smf_context::handle_pdu_session_modification_network_requested(
//TODO: handle encode N1, N2 failure //TODO: handle encode N1, N2 failure
//N1: PDU_SESSION_MODIFICATION_COMMAND //N1: PDU_SESSION_MODIFICATION_COMMAND
smf_n1_n2_inst.create_n1_sm_container(itti_msg->msg, smf_n1_inst.create_n1_pdu_session_modification_command(itti_msg->msg,
PDU_SESSION_MODIFICATION_COMMAND,
n1_sm_msg, n1_sm_msg,
cause_value_5gsm_e::CAUSE_0_UNKNOWN); cause_value_5gsm_e::CAUSE_0_UNKNOWN);
smf_app_inst->convert_string_2_hex(n1_sm_msg, n1_sm_msg_hex); smf_app_inst->convert_string_2_hex(n1_sm_msg, n1_sm_msg_hex);
itti_msg->msg.set_n1_sm_message(n1_sm_msg_hex); itti_msg->msg.set_n1_sm_message(n1_sm_msg_hex);
//N2: PDU Session Resource Modify Response Transfer //N2: PDU Session Resource Modify Response Transfer
smf_n1_n2_inst.create_n2_sm_information(itti_msg->msg, 1, smf_n2_inst.create_n2_pdu_session_resource_modify_request_transfer(itti_msg->msg,
n2_sm_info_type_e::PDU_RES_MOD_REQ, n2_sm_info_type_e::PDU_RES_MOD_REQ,
n2_sm_info); n2_sm_info);
......
/*
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The OpenAirInterface Software Alliance licenses this file to You under
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
* except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.openairinterface.org/?page_id=698
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*-------------------------------------------------------------------------------
* For more information about the OpenAirInterface (OAI) Software Alliance:
* contact@openairinterface.org
*/
/*! \file smf_n1.cpp
\brief
\author Tien-Thinh NGUYEN, Keliang DU
\company Eurecom
\date 2019
\email: tien-thinh.nguyen@eurecom.fr
*/
#include "smf_n1.hpp"
#include "string.hpp"
#include <stdexcept>
#include <arpa/inet.h>
#include "smf.h"
#include "smf_app.hpp"
extern "C" {
#include "dynamic_memory_check.h"
#include "nas_message.h"
}
using namespace smf;
extern smf_app *smf_app_inst;
//-----------------------------------------------------------------------------------------------------
bool smf_n1::create_n1_pdu_session_establishment_accept(pdu_session_create_sm_context_response &sm_context_res,
std::string &nas_msg_str,
cause_value_5gsm_e sm_cause) {
Logger::smf_app().info("Create N1 SM Container, PDU Session Establishment Accept");
int bytes = { 0 };
unsigned char data[BUF_LEN] = { '\0' };
nas_message_t nas_msg = { };
bool result = false;
nas_msg.header.extended_protocol_discriminator = EPD_5GS_SESSION_MANAGEMENT_MESSAGES;
nas_msg.header.security_header_type = SECURITY_HEADER_TYPE_NOT_PROTECTED;
//nas_msg.header.sequence_number = 0xfe;
//nas_msg.header.message_authentication_code = 0xffee;
SM_msg *sm_msg = &nas_msg.plain.sm;
//Fill the content of SM header
//Extended Protocol Discriminator
sm_msg->header.extended_protocol_discriminator = EPD_5GS_SESSION_MANAGEMENT_MESSAGES;
//PDU Session Identity
sm_msg->header.pdu_session_identity = sm_context_res.get_pdu_session_id();
//get default QoS value
qos_flow_context_updated qos_flow = { };
qos_flow = sm_context_res.get_qos_flow_context();
//check the QoS Flow
if ((qos_flow.qfi.qfi < QOS_FLOW_IDENTIFIER_FIRST ) or (qos_flow.qfi.qfi > QOS_FLOW_IDENTIFIER_LAST )) {
//error
Logger::smf_app().error("Incorrect QFI %d", qos_flow.qfi.qfi);
return false;
}
Logger::smf_app().info("PDU_SESSION_ESTABLISHMENT_ACCEPT, encode starting...");
//Fill the rest of SM header
//PTI
sm_msg->header.procedure_transaction_identity = sm_context_res.get_pti().procedure_transaction_id;
//Message Type
sm_msg->header.message_type = PDU_SESSION_ESTABLISHMENT_ACCEPT;
Logger::smf_app().debug("SM header, Extended Protocol Discriminator 0x%x, PDU Session Identity %d, Procedure Transaction Identity: %d, Message Type: %d", sm_msg->header.extended_protocol_discriminator, sm_msg->header.pdu_session_identity, sm_msg->header.procedure_transaction_identity,
sm_msg->header.message_type);
//Fill the content of PDU Session Establishment Accept message
//PDU Session Type
sm_msg->pdu_session_establishment_accept._pdusessiontype.pdu_session_type_value = sm_context_res.get_pdu_session_type();
Logger::smf_app().debug("PDU Session Type: %d", sm_msg->pdu_session_establishment_accept._pdusessiontype.pdu_session_type_value);
//SSC Mode
sm_msg->pdu_session_establishment_accept.sscmode.ssc_mode_value = SSC_MODE_1; //TODO: get from sm_context_res
Logger::smf_app().debug("SSC Mode: %d", sm_msg->pdu_session_establishment_accept.sscmode.ssc_mode_value);
//authorized QoS rules of the PDU session: QOSRules (Section 6.2.5@3GPP TS 24.501)
//(Section 6.4.1.3@3GPP TS 24.501 V16.1.0) Make sure that the number of the packet filters used in the authorized QoS rules of the PDU Session does not
// exceed the maximum number of packet filters supported by the UE for the PDU session
if (qos_flow.qos_rules.size() > 0) {
sm_msg->pdu_session_establishment_accept.qosrules.lengthofqosrulesie = qos_flow.qos_rules.size();
sm_msg->pdu_session_establishment_accept.qosrules.qosrulesie = (QOSRulesIE*) calloc(qos_flow.qos_rules.size(), sizeof(QOSRulesIE));
int i = 0;
for (auto rule : qos_flow.qos_rules) {
sm_msg->pdu_session_establishment_accept.qosrules.qosrulesie[i].qosruleidentifer = rule.second.qosruleidentifer;
memcpy(&sm_msg->pdu_session_establishment_accept.qosrules.qosrulesie[i], &rule.second, sizeof(QOSRulesIE));
i++;
}
}
//SessionAMBR
Logger::smf_app().debug("Get default values for Session-AMBR");
//TODO: get from subscription DB
supi_t supi = sm_context_res.get_supi();
supi64_t supi64 = smf_supi_to_u64(supi);
std::shared_ptr<smf_context> sc = { };
if (smf_app_inst->is_supi_2_smf_context(supi64)) {
Logger::smf_app().debug("Get SMF context with SUPI " SUPI_64_FMT "",
supi64);
sc = smf_app_inst->supi_2_smf_context(supi64);
sc.get()->get_session_ambr(sm_msg->pdu_session_establishment_accept.sessionambr, sm_context_res.get_snssai(), sm_context_res.get_dnn());
} else {
Logger::smf_app().warn(
"SMF context with SUPI " SUPI_64_FMT " does not exist!", supi64);
//free memory
if (qos_flow.qos_rules.size() > 0) {
free_wrapper((void**) &sm_msg->pdu_session_establishment_accept.qosrules.qosrulesie);
}
return false;
}
//Presence
sm_msg->pdu_session_establishment_accept.presence = 0xffff; //TODO: To be updated
//_5GSMCause
sm_msg->pdu_session_establishment_accept._5gsmcause = static_cast<uint8_t>(sm_cause);
Logger::smf_app().debug("5GSM Cause: %d", sm_msg->pdu_session_establishment_accept._5gsmcause);
//PDUAddress
paa_t paa = sm_context_res.get_paa();
unsigned char bitStream_pdu_address_information[4];
bitStream_pdu_address_information[0] = (uint8_t)((paa.ipv4_address.s_addr) & 0x000000ff);
bitStream_pdu_address_information[1] = (uint8_t)(((paa.ipv4_address.s_addr) & 0x0000ff00) >> 8);
bitStream_pdu_address_information[2] = (uint8_t)(((paa.ipv4_address.s_addr) & 0x00ff0000) >> 16);
bitStream_pdu_address_information[3] = (uint8_t)(((paa.ipv4_address.s_addr) & 0xff000000) >> 24);
sm_msg->pdu_session_establishment_accept.pduaddress.pdu_address_information = bfromcstralloc(4, "\0");
sm_msg->pdu_session_establishment_accept.pduaddress.pdu_address_information->slen = 4;
memcpy(sm_msg->pdu_session_establishment_accept.pduaddress.pdu_address_information->data, bitStream_pdu_address_information, sizeof(bitStream_pdu_address_information));
sm_msg->pdu_session_establishment_accept.pduaddress.pdu_session_type_value = static_cast<uint8_t>(PDU_SESSION_TYPE_E_IPV4);
Logger::smf_app().debug("UE Address %s", conv::toString(paa.ipv4_address).c_str());
//GPRSTimer
//sm_msg->pdu_session_establishment_accept.gprstimer.unit = GPRSTIMER_VALUE_IS_INCREMENTED_IN_MULTIPLES_OF_2_SECONDS;
//sm_msg->pdu_session_establishment_accept.gprstimer.timeValue = 0;
//SNSSAI
sm_msg->pdu_session_establishment_accept.snssai.len = SST_AND_SD_LENGTH;
sm_msg->pdu_session_establishment_accept.snssai.sst = sm_context_res.get_snssai().sST;
try {
sm_msg->pdu_session_establishment_accept.snssai.sd = std::stoul(sm_context_res.get_snssai().sD, nullptr, 16);
} catch (const std::exception &e) {
Logger::smf_app().warn("Error when converting from string to int for snssai.SD, error: %s", e.what());
//"no SD value associated with the SST"
sm_msg->pdu_session_establishment_accept.snssai.sd = 0xFFFFFF;
}
Logger::smf_app().debug("SNSSAI SST %d, SD %#0x", sm_msg->pdu_session_establishment_accept.snssai.sst, sm_msg->pdu_session_establishment_accept.snssai.sd);
//AlwaysonPDUSessionIndication
//sm_msg->pdu_session_establishment_accept.alwaysonpdusessionindication.apsi_indication = ALWAYSON_PDU_SESSION_REQUIRED;
//MappedEPSBearerContexts mappedepsbearercontexts;
//EAPMessage
//authorized QoS flow descriptions IE: QoSFlowDescritions
//TODO: we may not need this IE (see section 6.4.1.3 @3GPP TS 24.501)
if (smf_app_inst->is_supi_2_smf_context(supi64)) {
Logger::smf_app().debug("Get SMF context with SUPI " SUPI_64_FMT "",
supi64);
sc = smf_app_inst->supi_2_smf_context(supi64);
sm_msg->pdu_session_establishment_accept.qosflowdescriptions.qosflowdescriptionsnumber = 1;
sm_msg->pdu_session_establishment_accept.qosflowdescriptions.qosflowdescriptionscontents = (QOSFlowDescriptionsContents*) calloc(1, sizeof(QOSFlowDescriptionsContents));
sc.get()->get_default_qos_flow_description(sm_msg->pdu_session_establishment_accept.qosflowdescriptions.qosflowdescriptionscontents[0], sm_context_res.get_pdu_session_type(), qos_flow.qfi);
}
//ExtendedProtocolConfigurationOptions
//DNN
sm_msg->pdu_session_establishment_accept.dnn = bfromcstralloc(sm_context_res.get_dnn().length(), "\0");
sm_msg->pdu_session_establishment_accept.dnn->slen = sm_context_res.get_dnn().length();
memcpy((void*) sm_msg->pdu_session_establishment_accept.dnn->data, (void*) sm_context_res.get_dnn().c_str(), sm_context_res.get_dnn().length());
std::string dnn_str((char*) sm_msg->pdu_session_establishment_accept.dnn->data, sm_msg->pdu_session_establishment_accept.dnn->slen);
Logger::smf_app().debug("DNN %s", dnn_str.c_str());
Logger::smf_app().info("Encode PDU Session Establishment Accept");
//Encode NAS message
bytes = nas_message_encode(data, &nas_msg, sizeof(data)/*don't know the size*/, nullptr);
#if DEBUG_IS_ON
Logger::smf_app().debug("Buffer Data: ");
for (int i = 0; i < bytes; i++)
printf("%02x ", data[i]);
printf(" (bytes %d)\n", bytes);
#endif
if (bytes > 0) {
std::string n1Message((char*) data, bytes);
nas_msg_str = n1Message;
result = true;
} else {
result = false;
}
//free memory
if (qos_flow.qos_rules.size() > 0) {
free_wrapper((void**) &sm_msg->pdu_session_establishment_accept.qosrules.qosrulesie);
}
free_wrapper((void**) &sm_msg->pdu_session_establishment_accept.qosflowdescriptions.qosflowdescriptionscontents);
return result;
}
//-----------------------------------------------------------------------------------------------------
bool smf_n1::create_n1_pdu_session_establishment_reject(pdu_session_msg &msg,
std::string &nas_msg_str,
cause_value_5gsm_e sm_cause) {
Logger::smf_app().info("Create N1 SM Container, PDU Session Establishment Reject");
int bytes = { 0 };
unsigned char data[BUF_LEN] = { '\0' };
nas_message_t nas_msg = { };
bool result = false;
nas_msg.header.extended_protocol_discriminator = EPD_5GS_SESSION_MANAGEMENT_MESSAGES;
nas_msg.header.security_header_type = SECURITY_HEADER_TYPE_NOT_PROTECTED;
//nas_msg.header.sequence_number = 0xfe;
//nas_msg.header.message_authentication_code = 0xffee;
SM_msg *sm_msg = &nas_msg.plain.sm;
//Fill the content of SM header
//Extended Protocol Discriminator
sm_msg->header.extended_protocol_discriminator = EPD_5GS_SESSION_MANAGEMENT_MESSAGES;
//PDU Session Identity
sm_msg->header.pdu_session_identity = msg.get_pdu_session_id();
//PDU Session Establishment Reject is included in the following messages:
//1 - PDU Session Create SM Context Response (PDU Session Establishment procedure - reject)
//2 - N1N2MessageTransfer Request (PDU Session Establishment procedure - reject)
//3- PDU Session Update SM Context Response (PDU Session Establishment procedure - reject)​
//PDU_SESSION_CREATE_SM_CONTEXT_RESPONSE or PDU_SESSION_CREATE_SM_CONTEXT_REQUEST
Logger::smf_app().info("PDU_SESSION_ESTABLISHMENT_REJECT, encode starting...");
//Fill the content of PDU Session Establishment Reject message
//PDU Session ID
sm_msg->header.pdu_session_identity = msg.get_pdu_session_id();
//PTI
sm_msg->header.procedure_transaction_identity = msg.get_pti().procedure_transaction_id;
//Message Type
sm_msg->header.message_type = PDU_SESSION_ESTABLISHMENT_REJECT;
Logger::smf_app().debug("NAS header, Extended Protocol Discriminator 0x%x, Security Header Type: 0x%x", nas_msg.header.extended_protocol_discriminator, nas_msg.header.security_header_type);
Logger::smf_app().debug("SM header, PDU Session Identity 0x%x, Procedure Transaction Identity 0x%x, Message Type 0x%x", sm_msg->header.pdu_session_identity, sm_msg->header.procedure_transaction_identity, sm_msg->header.message_type);
//5GSM Cause
sm_msg->pdu_session_establishment_reject._5gsmcause = static_cast<uint8_t>(sm_cause);
//Presence
sm_msg->pdu_session_establishment_reject.presence =
PDU_SESSION_ESTABLISHMENT_REJECT_ALLOWED_SSC_MODE_PRESENCE; //Should be updated according to the following IEs
/*
//GPRSTimer3
sm_msg->pdu_session_establishment_reject.gprstimer3.unit =
GPRSTIMER3_VALUE_IS_INCREMENTED_IN_MULTIPLES_OF_1_HOUR;
sm_msg->pdu_session_establishment_reject.gprstimer3.timeValue = 0;
*/
//AllowedSSCMode
sm_msg->pdu_session_establishment_reject.allowedsscmode.is_ssc1_allowed =
SSC_MODE1_ALLOWED;
sm_msg->pdu_session_establishment_reject.allowedsscmode.is_ssc2_allowed =
SSC_MODE2_NOT_ALLOWED;
sm_msg->pdu_session_establishment_reject.allowedsscmode.is_ssc3_allowed =
SSC_MODE3_NOT_ALLOWED;
/*
//EAPMessage
unsigned char bitStream_eapmessage[2] = {0x01,0x02};
bstring eapmessage_tmp = bfromcstralloc(2, "\0");
eapmessage_tmp->slen = 2;
memcpy(eapmessage_tmp->data,bitStream_eapmessage,sizeof(bitStream_eapmessage));
sm_msg->pdu_session_establishment_reject.eapmessage = bfromcstralloc(2, "\0");
sm_msg->pdu_session_establishment_reject.eapmessage->slen = 2;
//ExtendedProtocolConfigurationOptions
unsigned char bitStream_extendedprotocolconfigurationoptions[4];
bitStream_extendedprotocolconfigurationoptions[0] = 0x12;
bitStream_extendedprotocolconfigurationoptions[1] = 0x13;
bitStream_extendedprotocolconfigurationoptions[2] = 0x14;
bitStream_extendedprotocolconfigurationoptions[3] = 0x15;
bstring extendedprotocolconfigurationoptions_tmp = bfromcstralloc(4, "\0");
extendedprotocolconfigurationoptions_tmp->slen = 4;
memcpy(extendedprotocolconfigurationoptions_tmp->data,bitStream_extendedprotocolconfigurationoptions,sizeof(bitStream_extendedprotocolconfigurationoptions));
sm_msg->pdu_session_establishment_reject.extendedprotocolconfigurationoptions = extendedprotocolconfigurationoptions_tmp;
//5GSM CongestionReattemptIndicator
sm_msg->pdu_session_establishment_reject._5gsmcongestionreattemptindicator.abo = THE_BACKOFF_TIMER_IS_APPLIED_IN_ALL_PLMNS;
*/
Logger::smf_app().debug("SM MSG, 5GSM Cause: 0x%x", sm_msg->pdu_session_establishment_reject._5gsmcause);
Logger::smf_app().debug("SM MSG, Allowed SSC Mode, SSC1 allowed 0x%x, SSC2 allowed 0x%x, SSC3 allowed 0x%x", sm_msg->pdu_session_establishment_reject.allowedsscmode.is_ssc1_allowed, sm_msg->pdu_session_establishment_reject.allowedsscmode.is_ssc2_allowed,
sm_msg->pdu_session_establishment_reject.allowedsscmode.is_ssc3_allowed);
//Encode NAS message
bytes = nas_message_encode(data, &nas_msg, sizeof(data)/*don't know the size*/, nullptr);
#if DEBUG_IS_ON
Logger::smf_app().debug("Buffer Data: ");
for (int i = 0; i < bytes; i++)
printf("%02x ", data[i]);
printf(" (bytes %d)\n", bytes);
#endif
if (bytes > 0) {
std::string n1Message((char*) data, bytes);
nas_msg_str = n1Message;
result = true;
} else {
result = false;
}
return result;
}
//-----------------------------------------------------------------------------------------------------
//For testing purpose
bool smf_n1::create_n1_pdu_session_modification_request(pdu_session_update_sm_context_response &msg,
std::string &nas_msg_str,
cause_value_5gsm_e sm_cause) {
//TODO:
Logger::smf_app().info("Create N1 SM Container, PDU Session Modification Request");
return true;
}
//-----------------------------------------------------------------------------------------------------
bool smf_n1::create_n1_pdu_session_modification_command(pdu_session_update_sm_context_response &sm_context_res,
std::string &nas_msg_str,
cause_value_5gsm_e sm_cause) {
Logger::smf_app().info("Create N1 SM Container, PDU Session Modification Command (pdu_session_update_sm_context_response)");
int bytes = { 0 };
unsigned char data[BUF_LEN] = { '\0' };
nas_message_t nas_msg = { };
bool result = false;
nas_msg.header.extended_protocol_discriminator = EPD_5GS_SESSION_MANAGEMENT_MESSAGES;
nas_msg.header.security_header_type = SECURITY_HEADER_TYPE_NOT_PROTECTED;
//nas_msg.header.sequence_number = 0xfe;
//nas_msg.header.message_authentication_code = 0xffee;
SM_msg *sm_msg = &nas_msg.plain.sm;
//Fill the content of SM header
//Extended Protocol Discriminator
sm_msg->header.extended_protocol_discriminator = EPD_5GS_SESSION_MANAGEMENT_MESSAGES;
//PDU Session Identity
sm_msg->header.pdu_session_identity = sm_context_res.get_pdu_session_id();
Logger::smf_app().debug("PDU Session Modification Command");
Logger::smf_app().info("PDU_SESSION_MODIFICATION_COMMAND, encode starting...");
//Get the SMF_PDU_Session
std::shared_ptr<smf_context> sc = { };
std::shared_ptr<dnn_context> sd = { };
std::shared_ptr<smf_pdu_session> sp = { };
supi_t supi = sm_context_res.get_supi();
supi64_t supi64 = smf_supi_to_u64(supi);
if (smf_app_inst->is_supi_2_smf_context(supi64)) {
Logger::smf_app().debug("Get SMF context with SUPI " SUPI_64_FMT "",
supi64);
sc = smf_app_inst->supi_2_smf_context(supi64);
} else {
Logger::smf_app().warn(
"SMF context with SUPI " SUPI_64_FMT " does not exist!", supi64);
return false;
}
bool find_dnn = sc.get()->find_dnn_context(sm_context_res.get_snssai(), sm_context_res.get_dnn(), sd);
bool find_pdu = false;
if (find_dnn) {
find_pdu = sd.get()->find_pdu_session(sm_context_res.get_pdu_session_id(), sp);
}
if (!find_dnn or !find_pdu) {
//error
Logger::smf_app().warn("DNN or PDU session context does not exist!");
return false;
}
//PTI
sm_msg->header.procedure_transaction_identity = sm_context_res.get_pti().procedure_transaction_id;
//Message Type
sm_msg->header.message_type = PDU_SESSION_MODIFICATION_COMMAND;
//Presence
sm_msg->pdu_session_modification_command.presence = 0xff; //TODO: to be updated
//5GSMCause
sm_msg->pdu_session_modification_command._5gsmcause = static_cast<uint8_t>(sm_cause);
//SessionAMBR (default)
sc.get()->get_session_ambr(sm_msg->pdu_session_modification_command.sessionambr, sm_context_res.get_snssai(), sm_context_res.get_dnn());
//TODO: GPRSTimer
//TODO: AlwaysonPDUSessionIndication
//QOSRules
//Get the authorized QoS Rules
std::vector<QOSRulesIE> qos_rules;
sp.get()->get_qos_rules_to_be_synchronised(qos_rules);
if (qos_rules.size() == 0) {
return false;
}
sm_msg->pdu_session_modification_command.qosrules.lengthofqosrulesie = qos_rules.size();
sm_msg->pdu_session_modification_command.qosrules.qosrulesie = (QOSRulesIE*) calloc(qos_rules.size(), sizeof(QOSRulesIE));
for (int i = 0; i < qos_rules.size(); i++) {
Logger::smf_app().debug("QoS Rule to be updated (Id %d)", qos_rules[i].qosruleidentifer);
//sm_msg->pdu_session_modification_command.qosrules.qosrulesie[i] = qos_rules[i];
memcpy(&sm_msg->pdu_session_modification_command.qosrules.qosrulesie[i], &qos_rules[i], sizeof(QOSRulesIE));
}
//MappedEPSBearerContexts
//TODO:
//QOSFlowDescriptions, TODO: get authorized QoS flow descriptions IE
if (smf_app_inst->is_supi_2_smf_context(supi64)) {
Logger::smf_app().debug("Get SMF context with SUPI " SUPI_64_FMT "",
supi64);
sc = smf_app_inst->supi_2_smf_context(supi64);
sm_msg->pdu_session_modification_command.qosflowdescriptions.qosflowdescriptionsnumber = 1;
sm_msg->pdu_session_modification_command.qosflowdescriptions.qosflowdescriptionscontents = (QOSFlowDescriptionsContents*) calloc(1, sizeof(QOSFlowDescriptionsContents));
sc.get()->get_default_qos_flow_description(sm_msg->pdu_session_modification_command.qosflowdescriptions.qosflowdescriptionscontents[0], sm_context_res.get_pdu_session_type(), qos_rules[0].qosflowidentifer);
}
//Encode NAS message
bytes = nas_message_encode(data, &nas_msg, sizeof(data)/*don't know the size*/, nullptr);
#if DEBUG_IS_ON
Logger::smf_app().debug("Buffer Data: ");
for (int i = 0; i < bytes; i++)
printf("%02x ", data[i]);
printf(" (bytes %d)\n", bytes);
#endif
if (bytes > 0 ){
std::string n1Message((char*) data, bytes);
nas_msg_str = n1Message;
result = true;
} else {
result = false;
}
//free memory
free_wrapper((void**) &sm_msg->pdu_session_modification_command.qosrules.qosrulesie);
free_wrapper((void**) &sm_msg->pdu_session_modification_command.qosflowdescriptions.qosflowdescriptionscontents);
return result;
}
//-----------------------------------------------------------------------------------------------------
bool smf_n1::create_n1_pdu_session_modification_command(pdu_session_modification_network_requested &msg,
std::string &nas_msg_str,
cause_value_5gsm_e sm_cause) {
Logger::smf_app().info("Create N1 SM Container, PDU Session Modification Command (pdu_session_modification_network_requested)");
int bytes = { 0 };
unsigned char data[BUF_LEN] = { '\0' };
nas_message_t nas_msg = { };
bool result = false;
nas_msg.header.extended_protocol_discriminator = EPD_5GS_SESSION_MANAGEMENT_MESSAGES;
nas_msg.header.security_header_type = SECURITY_HEADER_TYPE_NOT_PROTECTED;
//nas_msg.header.sequence_number = 0xfe;
//nas_msg.header.message_authentication_code = 0xffee;
SM_msg *sm_msg = &nas_msg.plain.sm;
//Fill the content of SM header
//Extended Protocol Discriminator
sm_msg->header.extended_protocol_discriminator = EPD_5GS_SESSION_MANAGEMENT_MESSAGES;
//PDU Session Identity
sm_msg->header.pdu_session_identity = msg.get_pdu_session_id();
Logger::smf_app().debug("PDU Session Modification Command");
Logger::smf_app().info("PDU_SESSION_MODIFICATION_COMMAND, encode starting...");
//Get the SMF_PDU_Session
std::shared_ptr<smf_context> sc = { };
std::shared_ptr<dnn_context> sd = { };
std::shared_ptr<smf_pdu_session> sp = { };
supi_t supi = msg.get_supi();
supi64_t supi64 = smf_supi_to_u64(supi);
if (smf_app_inst->is_supi_2_smf_context(supi64)) {
Logger::smf_app().debug("Get SMF context with SUPI " SUPI_64_FMT "",
supi64);
sc = smf_app_inst->supi_2_smf_context(supi64);
} else {
Logger::smf_app().warn(
"SMF context with SUPI " SUPI_64_FMT " does not exist!", supi64);
return false;
}
bool find_dnn = sc.get()->find_dnn_context(msg.get_snssai(), msg.get_dnn(), sd);
bool find_pdu = false;
if (find_dnn) {
find_pdu = sd.get()->find_pdu_session(msg.get_pdu_session_id(), sp);
}
if (!find_dnn or !find_pdu) {
//error
Logger::smf_app().warn("DNN or PDU session context does not exist!");
return false;
}
//PTI
sm_msg->header.procedure_transaction_identity = msg.get_pti().procedure_transaction_id;
//Message Type
sm_msg->header.message_type = PDU_SESSION_MODIFICATION_COMMAND;
//Presence
sm_msg->pdu_session_modification_command.presence = 0xff; //TODO: to be updated
//5GSMCause
sm_msg->pdu_session_modification_command._5gsmcause = static_cast<uint8_t>(sm_cause);
//SessionAMBR (default)
sc.get()->get_session_ambr(sm_msg->pdu_session_modification_command.sessionambr, msg.get_snssai(), msg.get_dnn());
//TODO: GPRSTimer
//TODO: AlwaysonPDUSessionIndication
//QOSRules
//Get the authorized QoS Rules
std::vector<QOSRulesIE> qos_rules;
sp.get()->get_qos_rules_to_be_synchronised(qos_rules);
if (qos_rules.size() == 0) {
return false;
}
sm_msg->pdu_session_modification_command.qosrules.lengthofqosrulesie = qos_rules.size();
sm_msg->pdu_session_modification_command.qosrules.qosrulesie = (QOSRulesIE*) calloc(qos_rules.size(), sizeof(QOSRulesIE));
for (int i = 0; i < qos_rules.size(); i++) {
Logger::smf_app().debug("QoS Rule to be updated (Id %d)", qos_rules[i].qosruleidentifer);
//sm_msg->pdu_session_modification_command.qosrules.qosrulesie[i] = qos_rules[i];
memcpy(&sm_msg->pdu_session_modification_command.qosrules.qosrulesie[i], &qos_rules[i], sizeof(QOSRulesIE));
}
//MappedEPSBearerContexts
//TODO:
//QOSFlowDescriptions, TODO: get authorized QoS flow descriptions IE
if (smf_app_inst->is_supi_2_smf_context(supi64)) {
Logger::smf_app().debug("Get SMF context with SUPI " SUPI_64_FMT "",
supi64);
sc = smf_app_inst->supi_2_smf_context(supi64);
sm_msg->pdu_session_modification_command.qosflowdescriptions.qosflowdescriptionsnumber = 1;
sm_msg->pdu_session_modification_command.qosflowdescriptions.qosflowdescriptionscontents = (QOSFlowDescriptionsContents*) calloc(1, sizeof(QOSFlowDescriptionsContents));
sc.get()->get_default_qos_flow_description(sm_msg->pdu_session_modification_command.qosflowdescriptions.qosflowdescriptionscontents[0], msg.get_pdu_session_type(), qos_rules[0].qosflowidentifer);
}
//Encode NAS message
bytes = nas_message_encode(data, &nas_msg, sizeof(data)/*don't know the size*/, nullptr);
#if DEBUG_IS_ON
Logger::smf_app().debug("Buffer Data: ");
for (int i = 0; i < bytes; i++)
printf("%02x ", data[i]);
printf(" (bytes %d)\n", bytes);
#endif
if (bytes > 0){
std::string n1Message((char*) data, bytes);
nas_msg_str = n1Message;
result = true;
} else {
result = false;
}
//free memory
free_wrapper((void**) &sm_msg->pdu_session_modification_command.qosrules.qosrulesie);
free_wrapper((void**) &sm_msg->pdu_session_modification_command.qosflowdescriptions.qosflowdescriptionscontents);
return result;
}
//-----------------------------------------------------------------------------------------------------
bool smf_n1::create_n1_pdu_session_release_reject(pdu_session_update_sm_context_request &sm_context_res,
std::string &nas_msg_str,
cause_value_5gsm_e sm_cause) {
Logger::smf_app().info("Create N1 SM Container, PDU Session Release Reject");
int bytes = { 0 };
unsigned char data[BUF_LEN] = { '\0' };
nas_message_t nas_msg = { };
nas_msg.header.extended_protocol_discriminator = EPD_5GS_SESSION_MANAGEMENT_MESSAGES;
nas_msg.header.security_header_type = SECURITY_HEADER_TYPE_NOT_PROTECTED;
//nas_msg.header.sequence_number = 0xfe;
//nas_msg.header.message_authentication_code = 0xffee;
SM_msg *sm_msg = &nas_msg.plain.sm;
//Fill the content of SM header
//Extended Protocol Discriminator
sm_msg->header.extended_protocol_discriminator = EPD_5GS_SESSION_MANAGEMENT_MESSAGES;
//PDU Session Identity
sm_msg->header.pdu_session_identity = sm_context_res.get_pdu_session_id();
//Fill the content of PDU Session Release Reject
//PDU Session ID
sm_msg->header.pdu_session_identity = sm_context_res.get_pdu_session_id();
//PTI
sm_msg->header.procedure_transaction_identity = sm_context_res.get_pti().procedure_transaction_id;
//Message Type
sm_msg->header.message_type = PDU_SESSION_RELEASE_REJECT;
//5GSMCause
sm_msg->pdu_session_release_reject._5gsmcause = static_cast<uint8_t>(sm_cause); //sm_context_res.get_cause();
//Presence
sm_msg->pdu_session_release_command.presence = 0x00; //TODO: to be updated when adding the following IE
//Extended protocol configuration options
//Encode NAS message
bytes = nas_message_encode(data, &nas_msg, sizeof(data)/*don't know the size*/, nullptr);
#if DEBUG_IS_ON
Logger::smf_app().debug("Buffer Data: ");
for (int i = 0; i < bytes; i++)
printf("%02x ", data[i]);
printf(" (bytes %d)\n", bytes);
#endif
if (bytes > 0) {
std::string n1Message((char*) data, bytes);
nas_msg_str = n1Message;
return true;
} else {
return false;
}
}
//-----------------------------------------------------------------------------------------------------
bool smf_n1::create_n1_pdu_session_release_command(pdu_session_update_sm_context_response &sm_context_res,
std::string &nas_msg_str,
cause_value_5gsm_e sm_cause) {
Logger::smf_app().info("Create N1 SM Container, PDU Session Release Command (pdu_session_update_sm_context_response)");
int bytes = { 0 };
unsigned char data[BUF_LEN] = { '\0' };
nas_message_t nas_msg = { };
nas_msg.header.extended_protocol_discriminator = EPD_5GS_SESSION_MANAGEMENT_MESSAGES;
nas_msg.header.security_header_type = SECURITY_HEADER_TYPE_NOT_PROTECTED;
//nas_msg.header.sequence_number = 0xfe;
//nas_msg.header.message_authentication_code = 0xffee;
SM_msg *sm_msg = &nas_msg.plain.sm;
//Fill the content of SM header
//Extended Protocol Discriminator
sm_msg->header.extended_protocol_discriminator = EPD_5GS_SESSION_MANAGEMENT_MESSAGES;
//PDU Session Identity
sm_msg->header.pdu_session_identity = sm_context_res.get_pdu_session_id();
Logger::smf_app().info("PDU_SESSION_RELEASE_COMMAND, encode starting...");
//Fill the content of PDU Session Release Command
//PDU Session ID
sm_msg->header.pdu_session_identity = sm_context_res.get_pdu_session_id();
//PTI
sm_msg->header.procedure_transaction_identity = sm_context_res.get_pti().procedure_transaction_id;
//Message Type
sm_msg->header.message_type = PDU_SESSION_RELEASE_COMMAND;
//5GSMCause
sm_msg->pdu_session_release_command._5gsmcause = static_cast<uint8_t>(sm_cause); //sm_context_res.get_cause();
//Presence
sm_msg->pdu_session_release_command.presence = 0x00; //TODO: to be updated when adding the following IEs
//GPRSTimer3
//EAPMessage
//_5GSMCongestionReattemptIndicator
// ExtendedProtocolConfigurationOptions
Logger::smf_app().debug("SM message, 5GSM Cause: 0x%x", sm_msg->pdu_session_release_command._5gsmcause);
//Encode NAS message
bytes = nas_message_encode(data, &nas_msg, sizeof(data)/*don't know the size*/, nullptr);
#if DEBUG_IS_ON
Logger::smf_app().debug("Buffer Data: ");
for (int i = 0; i < bytes; i++)
printf("%02x ", data[i]);
printf(" (bytes %d)\n", bytes);
#endif
if (bytes > 0){
std::string n1Message((char*) data, bytes);
nas_msg_str = n1Message;
return true;
} else {
return false;
}
}
//-----------------------------------------------------------------------------------------------------
bool create_n1_pdu_session_release_command(pdu_session_modification_network_requested &msg,
std::string &nas_msg_str,
cause_value_5gsm_e sm_cause) {
Logger::smf_app().info("Create N1 SM Container, PDU Session Release Command (pdu_session_modification_network_requested)");
//TODO:
return true;
}
//------------------------------------------------------------------------------
int smf_n1::decode_n1_sm_container(nas_message_t &nas_msg,
const std::string &n1_sm_msg) {
Logger::smf_app().info("Decode NAS message from N1 SM Container.");
//step 1. Decode NAS message (for instance, ... only served as an example)
nas_message_decode_status_t decode_status = { 0 };
int decoder_rc = RETURNok;
unsigned int data_len = n1_sm_msg.length();
unsigned char *data = (unsigned char*) malloc(data_len + 1);
memset(data, 0, data_len + 1);
memcpy((void*) data, (void*) n1_sm_msg.c_str(), data_len);
#if DEBUG_IS_ON
printf("Content: ");
for (int i = 0; i < data_len; i++)
printf(" %02x ", data[i]);
printf("\n");
#endif
//decode the NAS message (using NAS lib)
decoder_rc = nas_message_decode(data, &nas_msg, data_len, nullptr,
&decode_status);
Logger::smf_app().debug(
"NAS message, Extended Protocol Discriminator 0x%x, PDU Session Identity 0x%x, Procedure Transaction Identity 0x%x, Message Type 0x%x",
nas_msg.plain.sm.header.extended_protocol_discriminator,
nas_msg.plain.sm.header.pdu_session_identity,
nas_msg.plain.sm.header.procedure_transaction_identity,
nas_msg.plain.sm.header.message_type);
//free memory
free_wrapper((void**) &data);
return decoder_rc;
}
/*
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The OpenAirInterface Software Alliance licenses this file to You under
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
* except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.openairinterface.org/?page_id=698
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*-------------------------------------------------------------------------------
* For more information about the OpenAirInterface (OAI) Software Alliance:
* contact@openairinterface.org
*/
/*! \file smf_n1.hpp
* \brief
\author Tien-Thinh NGUYEN
\company Eurecom
\date 2019
\email: tien-thinh.nguyen@eurecom.fr
*/
#ifndef FILE_SMF_N1_HPP_SEEN
#define FILE_SMF_N1_HPP_SEEN
#include <string>
#include "smf.h"
#include "smf_context.hpp"
#include "smf_msg.hpp"
#include "3gpp_29.502.h"
extern "C" {
#include "nas_message.h"
}
namespace smf {
class smf_n1 {
private:
public:
smf_n1() {
}
;
smf_n1(smf_n1 const&) = delete;
void operator=(smf_n1 const&) = delete;
/*
* Create N1 SM Container: PDU Session Establishment Accept
* @param [pdu_session_create_sm_context_response] sm_context_res: include necessary information for encoding NGAP msg
* @param [std::string&] ngap_msg_str store the created NGAP message in form of string
* @param [uint8_t] sm_cause store NAS Cause
* @return boolean: True if the NGAP message has been created successfully, otherwise return false
*
*/
bool create_n1_pdu_session_establishment_accept(pdu_session_create_sm_context_response &sm_context_res,
std::string &nas_msg_str,
cause_value_5gsm_e sm_cause);
/*
* Create N1 SM Container: PDU Session Establishment Reject
* @param [pdu_session_msg] msg: include necessary information for encoding NGAP msg
* @param [std::string&] ngap_msg_str store the created NGAP message in form of string
* @param [uint8_t] sm_cause store NAS Cause
* @return boolean: True if the NGAP message has been created successfully, otherwise return false
*
*/
bool create_n1_pdu_session_establishment_reject(pdu_session_msg &msg,
std::string &nas_msg_str,
cause_value_5gsm_e sm_cause);
//TODO: separate into 4 functions (verify if necessary)
/*
bool create_n1_pdu_session_establishment_accept(pdu_session_create_sm_context_response &sm_context_res,
std::string &nas_msg_str,
cause_value_5gsm_e sm_cause);
bool create_n1_pdu_session_establishment_reject(pdu_session_create_sm_context_request &msg, uint8_t msg_type,
std::string &nas_msg_str,
cause_value_5gsm_e sm_cause);
bool create_n1_pdu_session_establishment_reject(pdu_session_update_sm_context_response &msg, uint8_t msg_type,
std::string &nas_msg_str,
cause_value_5gsm_e sm_cause);
bool create_n1_pdu_session_establishment_reject(pdu_session_update_sm_context_request &msg, uint8_t msg_type,
std::string &nas_msg_str,
cause_value_5gsm_e sm_cause);
*/
//For testing purpose
bool create_n1_pdu_session_modification_request(pdu_session_update_sm_context_response &msg,
std::string &nas_msg_str,
cause_value_5gsm_e sm_cause);
/*
* Create N1 SM Container: PDU Session Modification Command
* Included in PDU Session Update SM Context Response (PDU Session Modification UE-Initiated procedure - step 1)
* @param [pdu_session_msg] msg: include necessary information for encoding NGAP msg
* @param [std::string&] ngap_msg_str store the created NGAP message in form of string
* @param [uint8_t] sm_cause store NAS Cause
* @return boolean: True if the NGAP message has been created successfully, otherwise return false
*
*/
bool create_n1_pdu_session_modification_command(pdu_session_update_sm_context_response &msg,
std::string &nas_msg_str,
cause_value_5gsm_e sm_cause);
/*
* Create N1 SM Container: PDU Session Modification Command
* Included in N1N2MessageTransfer Request (PDU Session Modification SMF-Requested, step 1 (from SMF to AMF))
* @param [pdu_session_msg] msg: include necessary information for encoding NGAP msg
* @param [std::string&] ngap_msg_str store the created NGAP message in form of string
* @param [uint8_t] sm_cause store NAS Cause
* @return boolean: True if the NGAP message has been created successfully, otherwise return false
*
*/
bool create_n1_pdu_session_modification_command(pdu_session_modification_network_requested &msg,
std::string &nas_msg_str,
cause_value_5gsm_e sm_cause);
/*
* Create N1 SM Container: PDU Session Release Reject
* Included in PDU Session Update SM Context Response (PDU Session Release UE-Initiated, step 1)
* @param [pdu_session_msg] msg: include necessary information for encoding NGAP msg
* @param [std::string&] ngap_msg_str store the created NGAP message in form of string
* @param [uint8_t] sm_cause store NAS Cause
* @return boolean: True if the NGAP message has been created successfully, otherwise return false
*
*/
bool create_n1_pdu_session_release_reject(pdu_session_update_sm_context_request &sm_context_res,
std::string &nas_msg_str,
cause_value_5gsm_e sm_cause);
/*
* Create N1 SM Container: PDU Session Release Command
* Included in PDU Session Update SM Context Response (PDU Session Release UE-Initiated, step 1)
* @param [pdu_session_msg] msg: include necessary information for encoding NGAP msg
* @param [std::string&] ngap_msg_str store the created NGAP message in form of string
* @param [uint8_t] sm_cause store NAS Cause
* @return boolean: True if the NGAP message has been created successfully, otherwise return false
*
*/
bool create_n1_pdu_session_release_command(pdu_session_update_sm_context_response &msg,
std::string &nas_msg_str,
cause_value_5gsm_e sm_cause);
/*
* Create N1 SM Container: PDU Session Release Command
* Included in N1N2MessageTransfer Request (PDU Session Release SMF-Requested, step 1)
* @param [pdu_session_msg] msg: include necessary information for encoding NGAP msg
* @param [std::string&] ngap_msg_str store the created NGAP message in form of string
* @param [uint8_t] sm_cause store NAS Cause
* @return boolean: True if the NGAP message has been created successfully, otherwise return false
*
*/
bool create_n1_pdu_session_release_command(pdu_session_modification_network_requested &msg,
std::string &nas_msg_str,
cause_value_5gsm_e sm_cause);
/*
* Decode N1 SM Container into the NAS mesasge (using NAS lib)
* @param [nas_message_t&] nas_msg Store NAS message after decoded
* @param [const std::string&] n1_sm_msg N1 SM Container
* @return status of the decode process
*/
int decode_n1_sm_container(nas_message_t &nas_msg, const std::string &n1_sm_msg);
};
} // namespace smf
#endif /* FILE_SMF_N1_HPP_SEEN */
...@@ -42,7 +42,6 @@ ...@@ -42,7 +42,6 @@
#include "logger.hpp" #include "logger.hpp"
#include "smf_app.hpp" #include "smf_app.hpp"
#include "smf_config.hpp" #include "smf_config.hpp"
#include "smf_n1_n2.hpp"
#include "mime_parser.hpp" #include "mime_parser.hpp"
extern "C" { extern "C" {
...@@ -129,7 +128,6 @@ void smf_n11::send_n1n2_message_transfer_request( ...@@ -129,7 +128,6 @@ void smf_n11::send_n1n2_message_transfer_request(
Logger::smf_n11().debug("Send Communication_N1N2MessageTransfer to AMF (HTTP version %d)", sm_context_res->http_version); Logger::smf_n11().debug("Send Communication_N1N2MessageTransfer to AMF (HTTP version %d)", sm_context_res->http_version);
mime_parser parser = {}; mime_parser parser = {};
smf_n1_n2 smf_n1_n2_inst = { };
std::string n1_message = sm_context_res->res.get_n1_sm_message(); std::string n1_message = sm_context_res->res.get_n1_sm_message();
nlohmann::json json_data = {}; nlohmann::json json_data = {};
std::string body; std::string body;
...@@ -248,7 +246,6 @@ void smf_n11::send_n1n2_message_transfer_request( ...@@ -248,7 +246,6 @@ void smf_n11::send_n1n2_message_transfer_request(
mime_parser parser = {}; mime_parser parser = {};
std::string body; std::string body;
smf_n1_n2 smf_n1_n2_inst = { };
nlohmann::json json_data = {}; nlohmann::json json_data = {};
std::string json_part; std::string json_part;
std::string n1_message = sm_session_modification->msg.get_n1_sm_message(); std::string n1_message = sm_session_modification->msg.get_n1_sm_message();
...@@ -337,7 +334,6 @@ void smf_n11::send_n1n2_message_transfer_request( ...@@ -337,7 +334,6 @@ void smf_n11::send_n1n2_message_transfer_request(
"Send Communication_N1N2MessageTransfer to AMF (Network-initiated Service Request)"); "Send Communication_N1N2MessageTransfer to AMF (Network-initiated Service Request)");
mime_parser parser = {}; mime_parser parser = {};
smf_n1_n2 smf_n1_n2_inst = { };
std::string n2_message = report_msg->res.get_n2_sm_information(); std::string n2_message = report_msg->res.get_n2_sm_information();
nlohmann::json json_data = {}; nlohmann::json json_data = {};
std::string body; std::string body;
......
/*
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The OpenAirInterface Software Alliance licenses this file to You under
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
* except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.openairinterface.org/?page_id=698
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*-------------------------------------------------------------------------------
* For more information about the OpenAirInterface (OAI) Software Alliance:
* contact@openairinterface.org
*/
/*! \file smf_n1_n2.cpp
\brief
\author Tien-Thinh NGUYEN, Keliang DU
\company Eurecom
\date 2019
\email: tien-thinh.nguyen@eurecom.fr
*/
#include "smf_n1_n2.hpp"
#include "string.hpp"
#include <stdexcept>
#include <curl/curl.h>
#include <nlohmann/json.hpp>
#include <pistache/http.h>
#include <pistache/mime.h>
#include <arpa/inet.h>
#include "smf.h"
extern "C" {
#include "dynamic_memory_check.h"
#include "nas_message.h"
#include "Ngap_NGAP-PDU.h"
#include "Ngap_ProtocolIE-Field.h"
#include "Ngap_ProcedureCode.h"
#include "Ngap_Criticality.h"
#include "Ngap_PDUSessionResourceSetupRequestTransfer.h"
#include "Ngap_PDUSessionResourceSetupResponseTransfer.h"
#include "Ngap_QosFlowSetupRequestItem.h"
#include "Ngap_GTPTunnel.h"
#include "Ngap_NonDynamic5QIDescriptor.h"
#include "Ngap_Dynamic5QIDescriptor.h"
#include "Ngap_AssociatedQosFlowItem.h"
#include "Ngap_PDUSessionResourceModifyRequestTransfer.h"
#include "Ngap_UL-NGU-UP-TNLModifyItem.h"
#include "Ngap_QosFlowAddOrModifyRequestItem.h"
#include "Ngap_PDUSessionResourceReleaseCommandTransfer.h"
#include "Ngap_PDUSessionResourceReleaseResponseTransfer.h"
#include "Ngap_QosFlowAddOrModifyResponseItem.h"
#include "Ngap_QosFlowAddOrModifyResponseList.h"
}
using namespace Pistache::Http;
using namespace Pistache::Http::Mime;
using namespace smf;
extern smf_app *smf_app_inst;
//-----------------------------------------------------------------------------------------------------
bool smf_n1_n2::create_n1_sm_container(pdu_session_msg &msg,
uint8_t n1_msg_type,
std::string &nas_msg_str,
cause_value_5gsm_e sm_cause) {
Logger::smf_app().info("Create N1 SM Container, n1 message type %d",
n1_msg_type);
int bytes = { 0 };
unsigned char data[BUF_LEN] = { '\0' };
nas_message_t nas_msg = { };
nas_msg.header.extended_protocol_discriminator =
EPD_5GS_SESSION_MANAGEMENT_MESSAGES;
nas_msg.header.security_header_type = SECURITY_HEADER_TYPE_NOT_PROTECTED;
//nas_msg.header.sequence_number = 0xfe;
//nas_msg.header.message_authentication_code = 0xffee;
SM_msg *sm_msg = &nas_msg.plain.sm;
//Fill the content of SM header
//Extended Protocol Discriminator
sm_msg->header.extended_protocol_discriminator =
EPD_5GS_SESSION_MANAGEMENT_MESSAGES;
//PDU Session Identity
sm_msg->header.pdu_session_identity = msg.get_pdu_session_id();
//Depending on message type, encode N1 message accordingly
switch (n1_msg_type) {
//PDU Session Establishment Accept
case PDU_SESSION_ESTABLISHMENT_ACCEPT: {
//PDU Session Establishment Accept is including in the N1N2MessageTransfer Request sent from SMF to AMF (PDU Session Establishment procedure)
if (msg.get_msg_type() != PDU_SESSION_CREATE_SM_CONTEXT_RESPONSE) {
Logger::smf_app().error(
"Cannot create an PDU Session Establishment Accept for this message (type %d)",
msg.get_msg_type());
return false;
}
pdu_session_create_sm_context_response &sm_context_res =
static_cast<pdu_session_create_sm_context_response&>(msg);
//get default QoS value
qos_flow_context_updated qos_flow = { };
qos_flow = sm_context_res.get_qos_flow_context();
//check the QoS Flow
if ((qos_flow.qfi.qfi < QOS_FLOW_IDENTIFIER_FIRST )
or (qos_flow.qfi.qfi > QOS_FLOW_IDENTIFIER_LAST )) {
//error
Logger::smf_app().error("Incorrect QFI %d", qos_flow.qfi.qfi);
return false;
}
Logger::smf_app().info(
"PDU_SESSION_ESTABLISHMENT_ACCEPT, encode starting...");
//Fill the rest of SM header
//PTI
sm_msg->header.procedure_transaction_identity = sm_context_res.get_pti()
.procedure_transaction_id;
//Message Type
sm_msg->header.message_type = PDU_SESSION_ESTABLISHMENT_ACCEPT;
Logger::smf_app().debug(
"SM header, Extended Protocol Discriminator 0x%x, PDU Session Identity %d, Procedure Transaction Identity: %d, Message Type: %d",
sm_msg->header.extended_protocol_discriminator,
sm_msg->header.pdu_session_identity,
sm_msg->header.procedure_transaction_identity,
sm_msg->header.message_type);
//Fill the content of PDU Session Establishment Accept message
//PDU Session Type
sm_msg->pdu_session_establishment_accept._pdusessiontype
.pdu_session_type_value = sm_context_res.get_pdu_session_type();
Logger::smf_app().debug(
"PDU Session Type: %d",
sm_msg->pdu_session_establishment_accept._pdusessiontype
.pdu_session_type_value);
//SSC Mode
sm_msg->pdu_session_establishment_accept.sscmode.ssc_mode_value =
SSC_MODE_1; //TODO: get from sm_context_res
Logger::smf_app().debug(
"SSC Mode: %d",
sm_msg->pdu_session_establishment_accept.sscmode.ssc_mode_value);
//authorized QoS rules of the PDU session: QOSRules (Section 6.2.5@3GPP TS 24.501)
//(Section 6.4.1.3@3GPP TS 24.501 V16.1.0) Make sure that the number of the packet filters used in the authorized QoS rules of the PDU Session does not
// exceed the maximum number of packet filters supported by the UE for the PDU session
if (qos_flow.qos_rules.size() > 0) {
sm_msg->pdu_session_establishment_accept.qosrules.lengthofqosrulesie =
qos_flow.qos_rules.size();
sm_msg->pdu_session_establishment_accept.qosrules.qosrulesie =
(QOSRulesIE*) calloc(qos_flow.qos_rules.size(), sizeof(QOSRulesIE));
int i = 0;
for (auto rule : qos_flow.qos_rules) {
sm_msg->pdu_session_establishment_accept.qosrules.qosrulesie[i]
.qosruleidentifer = rule.second.qosruleidentifer;
memcpy(
&sm_msg->pdu_session_establishment_accept.qosrules.qosrulesie[i],
&rule.second, sizeof(QOSRulesIE));
i++;
}
}
//SessionAMBR
Logger::smf_app().debug("Get default values for Session-AMBR");
//TODO: get from subscription DB
supi_t supi = sm_context_res.get_supi();
supi64_t supi64 = smf_supi_to_u64(supi);
std::shared_ptr<smf_context> sc = { };
if (smf_app_inst->is_supi_2_smf_context(supi64)) {
Logger::smf_app().debug("Get SMF context with SUPI " SUPI_64_FMT "",
supi64);
sc = smf_app_inst->supi_2_smf_context(supi64);
sc.get()->get_session_ambr(
sm_msg->pdu_session_establishment_accept.sessionambr,
sm_context_res.get_snssai(), sm_context_res.get_dnn());
} else {
Logger::smf_app().warn(
"SMF context with SUPI " SUPI_64_FMT " does not exist!", supi64);
return false;
}
//Presence
sm_msg->pdu_session_establishment_accept.presence = 0xffff; //TODO: To be updated
//_5GSMCause
sm_msg->pdu_session_establishment_accept._5gsmcause =
static_cast<uint8_t>(sm_cause);
Logger::smf_app().debug(
"5GSM Cause: %d",
sm_msg->pdu_session_establishment_accept._5gsmcause);
//PDUAddress
paa_t paa = sm_context_res.get_paa();
unsigned char bitStream_pdu_address_information[4];
bitStream_pdu_address_information[0] =
(uint8_t) ((paa.ipv4_address.s_addr) & 0x000000ff);
bitStream_pdu_address_information[1] = (uint8_t) (((paa.ipv4_address
.s_addr) & 0x0000ff00) >> 8);
bitStream_pdu_address_information[2] = (uint8_t) (((paa.ipv4_address
.s_addr) & 0x00ff0000) >> 16);
bitStream_pdu_address_information[3] = (uint8_t) (((paa.ipv4_address
.s_addr) & 0xff000000) >> 24);
sm_msg->pdu_session_establishment_accept.pduaddress
.pdu_address_information = bfromcstralloc(4, "\0");
sm_msg->pdu_session_establishment_accept.pduaddress
.pdu_address_information->slen = 4;
memcpy(
sm_msg->pdu_session_establishment_accept.pduaddress
.pdu_address_information->data,
bitStream_pdu_address_information,
sizeof(bitStream_pdu_address_information));
sm_msg->pdu_session_establishment_accept.pduaddress.pdu_session_type_value =
static_cast<uint8_t>(PDU_SESSION_TYPE_E_IPV4);
Logger::smf_app().debug("UE Address %s",
conv::toString(paa.ipv4_address).c_str());
//GPRSTimer
//sm_msg->pdu_session_establishment_accept.gprstimer.unit = GPRSTIMER_VALUE_IS_INCREMENTED_IN_MULTIPLES_OF_2_SECONDS;
//sm_msg->pdu_session_establishment_accept.gprstimer.timeValue = 0;
//SNSSAI
sm_msg->pdu_session_establishment_accept.snssai.len = SST_AND_SD_LENGTH;
sm_msg->pdu_session_establishment_accept.snssai.sst = sm_context_res
.get_snssai().sST;
try {
sm_msg->pdu_session_establishment_accept.snssai.sd = std::stoul(
sm_context_res.get_snssai().sD, nullptr, 16);
} catch (const std::exception &e) {
Logger::smf_app().warn(
"Error when converting from string to int for snssai.SD, error: %s",
e.what());
//"no SD value associated with the SST"
sm_msg->pdu_session_establishment_accept.snssai.sd = 0xFFFFFF;
}
Logger::smf_app().debug(
"SNSSAI SST %d, SD %#0x",
sm_msg->pdu_session_establishment_accept.snssai.sst,
sm_msg->pdu_session_establishment_accept.snssai.sd);
//AlwaysonPDUSessionIndication
//sm_msg->pdu_session_establishment_accept.alwaysonpdusessionindication.apsi_indication = ALWAYSON_PDU_SESSION_REQUIRED;
//MappedEPSBearerContexts mappedepsbearercontexts;
//EAPMessage
//authorized QoS flow descriptions IE: QoSFlowDescritions
//TODO: we may not need this IE (see section 6.4.1.3 @3GPP TS 24.501)
if (smf_app_inst->is_supi_2_smf_context(supi64)) {
Logger::smf_app().debug("Get SMF context with SUPI " SUPI_64_FMT "",
supi64);
sc = smf_app_inst->supi_2_smf_context(supi64);
sm_msg->pdu_session_establishment_accept.qosflowdescriptions
.qosflowdescriptionsnumber = 1;
sm_msg->pdu_session_establishment_accept.qosflowdescriptions
.qosflowdescriptionscontents =
(QOSFlowDescriptionsContents*) calloc(
1, sizeof(QOSFlowDescriptionsContents));
sc.get()->get_default_qos_flow_description(
sm_msg->pdu_session_establishment_accept.qosflowdescriptions
.qosflowdescriptionscontents[0],
sm_context_res.get_pdu_session_type(), qos_flow.qfi);
}
//ExtendedProtocolConfigurationOptions
//DNN
sm_msg->pdu_session_establishment_accept.dnn = bfromcstralloc(
sm_context_res.get_dnn().length(), "\0");
sm_msg->pdu_session_establishment_accept.dnn->slen = sm_context_res
.get_dnn().length();
memcpy((void*) sm_msg->pdu_session_establishment_accept.dnn->data,
(void*) sm_context_res.get_dnn().c_str(),
sm_context_res.get_dnn().length());
std::string dnn_str(
(char*) sm_msg->pdu_session_establishment_accept.dnn->data,
sm_msg->pdu_session_establishment_accept.dnn->slen);
Logger::smf_app().debug("DNN %s", dnn_str.c_str());
Logger::smf_app().info("Encode PDU Session Establishment Accept");
//Encode NAS message
bytes = nas_message_encode(data, &nas_msg,
sizeof(data)/*don't know the size*/, nullptr);
#if DEBUG_IS_ON
Logger::smf_app().debug("Buffer Data: ");
for (int i = 0; i < bytes; i++)
printf("%02x ", data[i]);
printf(" (bytes %d)\n", bytes);
#endif
std::string n1Message((char*) data, bytes);
nas_msg_str = n1Message;
//free memory
if (qos_flow.qos_rules.size() > 0) {
free_wrapper(
(void**) &sm_msg->pdu_session_establishment_accept.qosrules
.qosrulesie);
}
free_wrapper(
(void**) &sm_msg->pdu_session_establishment_accept.qosflowdescriptions
.qosflowdescriptionscontents);
}
break;
case PDU_SESSION_ESTABLISHMENT_REJECT: {
//PDU Session Establishment Reject is included in the following messages:
//1 - PDU Session Create SM Context Response (PDU Session Establishment procedure - reject)
//2 - N1N2MessageTransfer Request (PDU Session Establishment procedure - reject)
//3- PDU Session Update SM Context Response (PDU Session Establishment procedure - reject)​
//PDU_SESSION_CREATE_SM_CONTEXT_RESPONSE or PDU_SESSION_CREATE_SM_CONTEXT_REQUEST
Logger::smf_app().info(
"PDU_SESSION_ESTABLISHMENT_REJECT, encode starting...");
//Fill the content of PDU Session Establishment Reject message
//PDU Session ID
sm_msg->header.pdu_session_identity = msg.get_pdu_session_id();
//PTI
sm_msg->header.procedure_transaction_identity = msg.get_pti()
.procedure_transaction_id;
//Message Type
sm_msg->header.message_type = PDU_SESSION_ESTABLISHMENT_REJECT;
Logger::smf_app().debug(
"NAS header, Extended Protocol Discriminator 0x%x, Security Header Type: 0x%x",
nas_msg.header.extended_protocol_discriminator,
nas_msg.header.security_header_type);
Logger::smf_app().debug(
"SM header, PDU Session Identity 0x%x, Procedure Transaction Identity 0x%x, Message Type 0x%x",
sm_msg->header.pdu_session_identity,
sm_msg->header.procedure_transaction_identity,
sm_msg->header.message_type);
//5GSM Cause
sm_msg->pdu_session_establishment_reject._5gsmcause =
static_cast<uint8_t>(sm_cause);
//Presence
sm_msg->pdu_session_establishment_reject.presence =
PDU_SESSION_ESTABLISHMENT_REJECT_ALLOWED_SSC_MODE_PRESENCE; //Should be updated according to the following IEs
/*
//GPRSTimer3
sm_msg->pdu_session_establishment_reject.gprstimer3.unit =
GPRSTIMER3_VALUE_IS_INCREMENTED_IN_MULTIPLES_OF_1_HOUR;
sm_msg->pdu_session_establishment_reject.gprstimer3.timeValue = 0;
*/
//AllowedSSCMode
sm_msg->pdu_session_establishment_reject.allowedsscmode.is_ssc1_allowed =
SSC_MODE1_ALLOWED;
sm_msg->pdu_session_establishment_reject.allowedsscmode.is_ssc2_allowed =
SSC_MODE2_NOT_ALLOWED;
sm_msg->pdu_session_establishment_reject.allowedsscmode.is_ssc3_allowed =
SSC_MODE3_NOT_ALLOWED;
/*
//EAPMessage
unsigned char bitStream_eapmessage[2] = {0x01,0x02};
bstring eapmessage_tmp = bfromcstralloc(2, "\0");
eapmessage_tmp->slen = 2;
memcpy(eapmessage_tmp->data,bitStream_eapmessage,sizeof(bitStream_eapmessage));
sm_msg->pdu_session_establishment_reject.eapmessage = bfromcstralloc(2, "\0");
sm_msg->pdu_session_establishment_reject.eapmessage->slen = 2;
//ExtendedProtocolConfigurationOptions
unsigned char bitStream_extendedprotocolconfigurationoptions[4];
bitStream_extendedprotocolconfigurationoptions[0] = 0x12;
bitStream_extendedprotocolconfigurationoptions[1] = 0x13;
bitStream_extendedprotocolconfigurationoptions[2] = 0x14;
bitStream_extendedprotocolconfigurationoptions[3] = 0x15;
bstring extendedprotocolconfigurationoptions_tmp = bfromcstralloc(4, "\0");
extendedprotocolconfigurationoptions_tmp->slen = 4;
memcpy(extendedprotocolconfigurationoptions_tmp->data,bitStream_extendedprotocolconfigurationoptions,sizeof(bitStream_extendedprotocolconfigurationoptions));
sm_msg->pdu_session_establishment_reject.extendedprotocolconfigurationoptions = extendedprotocolconfigurationoptions_tmp;
//5GSM CongestionReattemptIndicator
sm_msg->pdu_session_establishment_reject._5gsmcongestionreattemptindicator.abo = THE_BACKOFF_TIMER_IS_APPLIED_IN_ALL_PLMNS;
*/
Logger::smf_app().debug(
"SM MSG, 5GSM Cause: 0x%x",
sm_msg->pdu_session_establishment_reject._5gsmcause);
Logger::smf_app().debug(
"SM MSG, Allowed SSC Mode, SSC1 allowed 0x%x, SSC2 allowed 0x%x, SSC3 allowed 0x%x",
sm_msg->pdu_session_establishment_reject.allowedsscmode
.is_ssc1_allowed,
sm_msg->pdu_session_establishment_reject.allowedsscmode
.is_ssc2_allowed,
sm_msg->pdu_session_establishment_reject.allowedsscmode
.is_ssc3_allowed);
//Encode NAS message
bytes = nas_message_encode(data, &nas_msg,
sizeof(data)/*don't know the size*/, nullptr);
#if DEBUG_IS_ON
Logger::smf_app().debug("Buffer Data: ");
for (int i = 0; i < bytes; i++)
printf("%02x ", data[i]);
printf(" (bytes %d)\n", bytes);
#endif
std::string n1Message((char*) data, bytes);
nas_msg_str = n1Message;
}
break;
case PDU_SESSION_MODIFICATION_COMMAND: {
//PDU Session Modification Command is included in the following messages:
//1- PDU Session Update SM Context Response (PDU Session Modification UE-Initiated procedure - step 1)
//2- N1N2MessageTransfer Request (PDU Session Modification SMF-Requested, step 1 (from SMF to AMF)) ​
Logger::smf_app().debug("PDU Session Modification Command");
//case 1 (case2: need to be verified?)
pdu_session_update_sm_context_response &sm_context_res =
static_cast<pdu_session_update_sm_context_response&>(msg);
Logger::smf_app().info(
"PDU_SESSION_MODIFICATION_COMMAND, encode starting...");
//Get the SMF_PDU_Session
std::shared_ptr<smf_context> sc = { };
std::shared_ptr<dnn_context> sd = { };
std::shared_ptr<smf_pdu_session> sp = { };
supi_t supi = sm_context_res.get_supi();
supi64_t supi64 = smf_supi_to_u64(supi);
if (smf_app_inst->is_supi_2_smf_context(supi64)) {
Logger::smf_app().debug("Get SMF context with SUPI " SUPI_64_FMT "",
supi64);
sc = smf_app_inst->supi_2_smf_context(supi64);
} else {
Logger::smf_app().warn(
"SMF context with SUPI " SUPI_64_FMT " does not exist!", supi64);
return false;
}
bool find_dnn = sc.get()->find_dnn_context(sm_context_res.get_snssai(),
sm_context_res.get_dnn(), sd);
bool find_pdu = false;
if (find_dnn) {
find_pdu = sd.get()->find_pdu_session(
sm_context_res.get_pdu_session_id(), sp);
}
if (!find_dnn or !find_pdu) {
//error
Logger::smf_app().warn("DNN or PDU session context does not exist!");
return false;
}
//PTI
sm_msg->header.procedure_transaction_identity = sm_context_res.get_pti()
.procedure_transaction_id;
//Message Type
sm_msg->header.message_type = PDU_SESSION_MODIFICATION_COMMAND;
//Presence
sm_msg->pdu_session_modification_command.presence = 0xff; //TODO: to be updated
//5GSMCause
sm_msg->pdu_session_modification_command._5gsmcause =
static_cast<uint8_t>(sm_cause);
//SessionAMBR (default)
sc.get()->get_session_ambr(
sm_msg->pdu_session_modification_command.sessionambr,
sm_context_res.get_snssai(), sm_context_res.get_dnn());
//TODO: GPRSTimer
//TODO: AlwaysonPDUSessionIndication
//QOSRules
//Get the authorized QoS Rules
std::vector<QOSRulesIE> qos_rules;
sp.get()->get_qos_rules_to_be_synchronised(qos_rules);
if (qos_rules.size() == 0) {
return false;
}
sm_msg->pdu_session_modification_command.qosrules.lengthofqosrulesie =
qos_rules.size();
sm_msg->pdu_session_modification_command.qosrules.qosrulesie =
(QOSRulesIE*) calloc(qos_rules.size(), sizeof(QOSRulesIE));
for (int i = 0; i < qos_rules.size(); i++) {
Logger::smf_app().debug("QoS Rule to be updated (Id %d)",
qos_rules[i].qosruleidentifer);
//sm_msg->pdu_session_modification_command.qosrules.qosrulesie[i] = qos_rules[i];
memcpy(&sm_msg->pdu_session_modification_command.qosrules.qosrulesie[i],
&qos_rules[i], sizeof(QOSRulesIE));
}
//MappedEPSBearerContexts
//TODO:
//QOSFlowDescriptions, TODO: get authorized QoS flow descriptions IE
if (smf_app_inst->is_supi_2_smf_context(supi64)) {
Logger::smf_app().debug("Get SMF context with SUPI " SUPI_64_FMT "",
supi64);
sc = smf_app_inst->supi_2_smf_context(supi64);
sm_msg->pdu_session_modification_command.qosflowdescriptions
.qosflowdescriptionsnumber = 1;
sm_msg->pdu_session_modification_command.qosflowdescriptions
.qosflowdescriptionscontents =
(QOSFlowDescriptionsContents*) calloc(
1, sizeof(QOSFlowDescriptionsContents));
sc.get()->get_default_qos_flow_description(
sm_msg->pdu_session_modification_command.qosflowdescriptions
.qosflowdescriptionscontents[0],
sm_context_res.get_pdu_session_type(),
qos_rules[0].qosflowidentifer);
}
//Encode NAS message
bytes = nas_message_encode(data, &nas_msg,
sizeof(data)/*don't know the size*/, nullptr);
#if DEBUG_IS_ON
Logger::smf_app().debug("Buffer Data: ");
for (int i = 0; i < bytes; i++)
printf("%02x ", data[i]);
printf(" (bytes %d)\n", bytes);
#endif
std::string n1Message((char*) data, bytes);
nas_msg_str = n1Message;
//free memory
free_wrapper(
(void**) &sm_msg->pdu_session_modification_command.qosrules.qosrulesie);
free_wrapper(
(void**) &sm_msg->pdu_session_modification_command.qosflowdescriptions
.qosflowdescriptionscontents);
}
break;
//PDU Session Release UE-Initiated (section 4.3.4@3GPP TS 23.502, step 1)
case PDU_SESSION_RELEASE_COMMAND: {
//this IE is included in the following message
//1 - PDU Session Update SM Context Response (PDU Session Release UE-Initiated, step 1)
//2 - N1N2MessageTransfer Request (PDU Session Release SMF-Requested, step 1)
Logger::smf_app().debug("PDU Session Release Command");
//case 1 (case2: need to be verified?)
pdu_session_update_sm_context_response &sm_context_res =
static_cast<pdu_session_update_sm_context_response&>(msg);
Logger::smf_app().info("PDU_SESSION_RELEASE_COMMAND, encode starting...");
//Fill the content of PDU Session Release Command
//PDU Session ID
sm_msg->header.pdu_session_identity = sm_context_res.get_pdu_session_id();
//PTI
sm_msg->header.procedure_transaction_identity = sm_context_res.get_pti()
.procedure_transaction_id;
//Message Type
sm_msg->header.message_type = PDU_SESSION_RELEASE_COMMAND;
//5GSMCause
sm_msg->pdu_session_release_command._5gsmcause =
static_cast<uint8_t>(sm_cause); //sm_context_res.get_cause();
//Presence
sm_msg->pdu_session_release_command.presence = 0x00; //TODO: to be updated when adding the following IEs
//GPRSTimer3
//EAPMessage
//_5GSMCongestionReattemptIndicator
// ExtendedProtocolConfigurationOptions
Logger::smf_app().debug("SM message, 5GSM Cause: 0x%x",
sm_msg->pdu_session_release_command._5gsmcause);
//Encode NAS message
bytes = nas_message_encode(data, &nas_msg,
sizeof(data)/*don't know the size*/, nullptr);
#if DEBUG_IS_ON
Logger::smf_app().debug("Buffer Data: ");
for (int i = 0; i < bytes; i++)
printf("%02x ", data[i]);
printf(" (bytes %d)\n", bytes);
#endif
std::string n1Message((char*) data, bytes);
nas_msg_str = n1Message;
}
break;
case PDU_SESSION_RELEASE_REJECT: {
//This IE is included in the PDU Session Update SM Context Response (PDU Session Release UE-Initiated, step 1)
Logger::smf_app().debug(
"[Create N1 SM Message] PDU Session Release Reject");
Logger::smf_app().info("PDU_SESSION_RELEASE_REJECT, encode starting...");
pdu_session_update_sm_context_response &sm_context_res =
static_cast<pdu_session_update_sm_context_response&>(msg);
//Fill the content of PDU Session Release Reject
//PDU Session ID
sm_msg->header.pdu_session_identity = sm_context_res.get_pdu_session_id();
//PTI
sm_msg->header.procedure_transaction_identity = sm_context_res.get_pti()
.procedure_transaction_id;
//Message Type
sm_msg->header.message_type = PDU_SESSION_RELEASE_REJECT;
//5GSMCause
sm_msg->pdu_session_release_reject._5gsmcause =
static_cast<uint8_t>(sm_cause); //sm_context_res.get_cause();
//Presence
sm_msg->pdu_session_release_command.presence = 0x00; //TODO: to be updated when adding the following IE
//Extended protocol configuration options
//Encode NAS message
bytes = nas_message_encode(data, &nas_msg,
sizeof(data)/*don't know the size*/, nullptr);
#if DEBUG_IS_ON
Logger::smf_app().debug("Buffer Data: ");
for (int i = 0; i < bytes; i++)
printf("%02x ", data[i]);
printf(" (bytes %d)\n", bytes);
#endif
std::string n1Message((char*) data, bytes);
nas_msg_str = n1Message;
}
break;
default: {
Logger::smf_app().debug("Unknown PDU Session Type");
//TODO:
}
} //end Switch
}
//------------------------------------------------------------------------------
bool smf_n1_n2::create_n2_sm_information(pdu_session_msg &msg,
uint8_t ngap_msg_type,
n2_sm_info_type_e ngap_ie_type,
std::string &ngap_msg_str) {
Logger::smf_app().info(
"Create N2 SM Information, NGAP message type %d, IE type %d",
ngap_msg_type, ngap_ie_type);
switch (ngap_ie_type) {
//PDU Session Resource Setup Request Transfer
case n2_sm_info_type_e::PDU_RES_SETUP_REQ: {
//PDU Session Resource Setup Request Transfer
//This IE is included in the following messages:
//1 - N1N2MessageTransfer Request (Accept, PDU Session Establishment procedure - UE initiated) (PDU Session Create SM Context)
//2 - PDU Session Update SM Context Response​ (Service Request, step 2)
Logger::smf_app().info("PDU Session Resource Setup Request Transfer");
Ngap_PDUSessionResourceSetupRequestTransfer_t *ngap_IEs = nullptr;
ngap_IEs = (Ngap_PDUSessionResourceSetupRequestTransfer_t*) calloc(
1, sizeof(Ngap_PDUSessionResourceSetupRequestTransfer_t));
qos_flow_context_updated qos_flow = { };
switch (msg.get_msg_type()) {
//Case 1: in N1N2MessageTransfer Request
case PDU_SESSION_CREATE_SM_CONTEXT_RESPONSE: {
pdu_session_create_sm_context_response &sm_context_res =
static_cast<pdu_session_create_sm_context_response&>(msg);
//get default QoS value
qos_flow = sm_context_res.get_qos_flow_context();
Logger::smf_app().debug(
"UL F-TEID, TEID " "0x%" PRIx32 ", IP Address %s",
qos_flow.ul_fteid.teid_gre_key,
conv::toString(qos_flow.ul_fteid.ipv4_address).c_str());
Logger::smf_app().info(
"QoS parameters: QFI %d, Priority level %d, ARP priority level %d",
qos_flow.qfi.qfi, qos_flow.qos_profile.priority_level,
qos_flow.qos_profile.arp.priority_level);
}
break;
//Case 2: in PDU Session Update SM Context Response​ (Service Request, step 2)​
case PDU_SESSION_UPDATE_SM_CONTEXT_RESPONSE: {
pdu_session_update_sm_context_response &sm_context_res =
static_cast<pdu_session_update_sm_context_response&>(msg);
//get default QoS value
std::map<uint8_t, qos_flow_context_updated> qos_flows = { };
sm_context_res.get_all_qos_flow_context_updateds(qos_flows);
for (std::map<uint8_t, qos_flow_context_updated>::iterator it =
qos_flows.begin(); it != qos_flows.end(); ++it)
Logger::smf_app().debug("QoS Flow context to be updated QFI %d",
it->first);
if (qos_flows.empty()) {
free_wrapper((void**) &ngap_IEs);
return false;
}
//TODO: support only 1 qos flow
qos_flow = qos_flows.begin()->second;
Logger::smf_app().debug(
"UL F-TEID, TEID " "0x%" PRIx32 ", IP Address %s",
qos_flow.ul_fteid.teid_gre_key,
conv::toString(qos_flow.ul_fteid.ipv4_address).c_str());
Logger::smf_app().info(
"QoS parameters: QFI %d, Priority level %d, ARP priority level %d",
qos_flow.qfi.qfi, qos_flow.qos_profile.priority_level,
qos_flow.qos_profile.arp.priority_level);
}
break;
default:
Logger::smf_app().warn("Unknown message type: %d \n",
msg.get_msg_type());
//TODO:
free_wrapper((void**) &ngap_IEs);
return false;
}
//check the QoS Flow
if ((qos_flow.qfi.qfi < QOS_FLOW_IDENTIFIER_FIRST )
or (qos_flow.qfi.qfi > QOS_FLOW_IDENTIFIER_LAST )) {
//error
Logger::smf_app().error("Incorrect QFI %d", qos_flow.qfi.qfi);
free_wrapper((void**) &ngap_IEs);
return false;
}
//PDUSessionAggregateMaximumBitRate
Ngap_PDUSessionResourceSetupRequestTransferIEs_t *pduSessionAggregateMaximumBitRate =
nullptr;
pduSessionAggregateMaximumBitRate =
(Ngap_PDUSessionResourceSetupRequestTransferIEs_t*) calloc(
1, sizeof(Ngap_PDUSessionResourceSetupRequestTransferIEs_t));
pduSessionAggregateMaximumBitRate->id =
Ngap_ProtocolIE_ID_id_PDUSessionAggregateMaximumBitRate;
pduSessionAggregateMaximumBitRate->criticality = Ngap_Criticality_reject;
pduSessionAggregateMaximumBitRate->value.present =
Ngap_PDUSessionResourceSetupRequestTransferIEs__value_PR_PDUSessionAggregateMaximumBitRate;
asn_set_empty(&ngap_IEs->protocolIEs.list);
//SessionAMBR
supi_t supi = msg.get_supi();
supi64_t supi64 = smf_supi_to_u64(supi);
std::shared_ptr<smf_context> sc = { };
if (smf_app_inst->is_supi_2_smf_context(supi64)) {
Logger::smf_app().debug("Get SMF context with SUPI " SUPI_64_FMT "",
supi64);
sc = smf_app_inst->supi_2_smf_context(supi64);
sc.get()->get_session_ambr(
pduSessionAggregateMaximumBitRate->value.choice
.PDUSessionAggregateMaximumBitRate,
msg.get_snssai(), msg.get_dnn());
} else {
Logger::smf_app().warn(
"SMF context with SUPI " SUPI_64_FMT " does not exist!", supi64);
return false;
}
ASN_SEQUENCE_ADD(&ngap_IEs->protocolIEs.list,
pduSessionAggregateMaximumBitRate);
//UPTransportLayerInformation
fteid_t ul_fteid = { };
ul_fteid.interface_type = qos_flow.ul_fteid.interface_type;
ul_fteid.v4 = qos_flow.ul_fteid.v4;
ul_fteid.teid_gre_key = htonl(qos_flow.ul_fteid.teid_gre_key);
ul_fteid.ipv4_address = qos_flow.ul_fteid.ipv4_address;
Ngap_PDUSessionResourceSetupRequestTransferIEs_t *upTransportLayerInformation =
nullptr;
upTransportLayerInformation =
(Ngap_PDUSessionResourceSetupRequestTransferIEs_t*) calloc(
1, sizeof(Ngap_PDUSessionResourceSetupRequestTransferIEs_t));
upTransportLayerInformation->id =
Ngap_ProtocolIE_ID_id_UL_NGU_UP_TNLInformation;
upTransportLayerInformation->criticality = Ngap_Criticality_reject;
upTransportLayerInformation->value.present =
Ngap_PDUSessionResourceSetupRequestTransferIEs__value_PR_UPTransportLayerInformation;
upTransportLayerInformation->value.choice.UPTransportLayerInformation
.present = Ngap_UPTransportLayerInformation_PR_gTPTunnel;
upTransportLayerInformation->value.choice.UPTransportLayerInformation
.choice.gTPTunnel = (Ngap_GTPTunnel_t*) calloc(
1, sizeof(Ngap_GTPTunnel_t));
upTransportLayerInformation->value.choice.UPTransportLayerInformation
.choice.gTPTunnel->transportLayerAddress.size = 4;
upTransportLayerInformation->value.choice.UPTransportLayerInformation
.choice.gTPTunnel->transportLayerAddress.buf = (uint8_t*) calloc(
4, sizeof(uint8_t));
memcpy(
upTransportLayerInformation->value.choice.UPTransportLayerInformation
.choice.gTPTunnel->transportLayerAddress.buf,
&ul_fteid.ipv4_address, 4);
upTransportLayerInformation->value.choice.UPTransportLayerInformation
.choice.gTPTunnel->transportLayerAddress.bits_unused = 0;
upTransportLayerInformation->value.choice.UPTransportLayerInformation
.choice.gTPTunnel->gTP_TEID.size = sizeof(struct in_addr);
upTransportLayerInformation->value.choice.UPTransportLayerInformation
.choice.gTPTunnel->gTP_TEID.buf = (uint8_t*) calloc(
sizeof(struct in_addr), sizeof(uint8_t));
memcpy(
upTransportLayerInformation->value.choice.UPTransportLayerInformation
.choice.gTPTunnel->gTP_TEID.buf,
&ul_fteid.teid_gre_key, sizeof(struct in_addr));
ASN_SEQUENCE_ADD(&ngap_IEs->protocolIEs.list,
upTransportLayerInformation);
//DataForwardingNotPossible
//TODO:
//PDUSessionType
Ngap_PDUSessionResourceSetupRequestTransferIEs_t *pduSessionType = nullptr;
pduSessionType =
(Ngap_PDUSessionResourceSetupRequestTransferIEs_t*) calloc(
1, sizeof(Ngap_PDUSessionResourceSetupRequestTransferIEs_t));
pduSessionType->id = Ngap_ProtocolIE_ID_id_PDUSessionType;
pduSessionType->criticality = Ngap_Criticality_reject;
pduSessionType->value.present =
Ngap_PDUSessionResourceSetupRequestTransferIEs__value_PR_PDUSessionType;
pduSessionType->value.choice.PDUSessionType = msg.get_pdu_session_type()
- 1; //TODO: dirty code, difference between Ngap_PDUSessionType_ipv4 vs pdu_session_type_e::PDU_SESSION_TYPE_E_IPV4 (TS 38.413 vs TS 24.501)
ASN_SEQUENCE_ADD(&ngap_IEs->protocolIEs.list, pduSessionType);
Logger::smf_app().debug("PDU Session Type: %d ",
msg.get_pdu_session_type());
//SecurityIndication
//TODO: should get from UDM
// Ngap_PDUSessionResourceSetupRequestTransferIEs_t *securityIndication = nullptr;
// securityIndication = (Ngap_PDUSessionResourceSetupRequestTransferIEs_t *) calloc(1, sizeof(Ngap_PDUSessionResourceSetupRequestTransferIEs_t));
// securityIndication->value.choice.SecurityIndication.integrityProtectionIndication = Ngap_IntegrityProtectionIndication_not_needed;
// securityIndication->value.choice.SecurityIndication.confidentialityProtectionIndication = Ngap_ConfidentialityProtectionIndication_not_needed;
//NetworkInstance
//TODO:
//QosFlowSetupRequestList
Ngap_PDUSessionResourceSetupRequestTransferIEs_t *qosFlowSetupRequestList =
nullptr;
qosFlowSetupRequestList =
(Ngap_PDUSessionResourceSetupRequestTransferIEs_t*) calloc(
1, sizeof(Ngap_PDUSessionResourceSetupRequestTransferIEs_t));
qosFlowSetupRequestList->id =
Ngap_ProtocolIE_ID_id_QosFlowSetupRequestList;
qosFlowSetupRequestList->criticality = Ngap_Criticality_reject;
qosFlowSetupRequestList->value.present =
Ngap_PDUSessionResourceSetupRequestTransferIEs__value_PR_QosFlowSetupRequestList;
Ngap_QosFlowSetupRequestItem_t *ngap_QosFlowSetupRequestItem = nullptr;
ngap_QosFlowSetupRequestItem = (Ngap_QosFlowSetupRequestItem_t*) calloc(
1, sizeof(Ngap_QosFlowSetupRequestItem_t));
ngap_QosFlowSetupRequestItem->qosFlowIdentifier = (uint8_t) qos_flow.qfi
.qfi;
ngap_QosFlowSetupRequestItem->qosFlowLevelQosParameters.qosCharacteristics
.present = Ngap_QosCharacteristics_PR_nonDynamic5QI;
ngap_QosFlowSetupRequestItem->qosFlowLevelQosParameters.qosCharacteristics
.choice.nonDynamic5QI = (Ngap_NonDynamic5QIDescriptor_t*) (calloc(
1, sizeof(Ngap_NonDynamic5QIDescriptor_t)));
ngap_QosFlowSetupRequestItem->qosFlowLevelQosParameters.qosCharacteristics
.choice.nonDynamic5QI->fiveQI = (uint8_t) qos_flow.qfi.qfi;
ngap_QosFlowSetupRequestItem->qosFlowLevelQosParameters
.allocationAndRetentionPriority.priorityLevelARP = qos_flow
.qos_profile.arp.priority_level;
if (qos_flow.qos_profile.arp.preempt_cap.compare("NOT_PREEMPT") == 0) {
ngap_QosFlowSetupRequestItem->qosFlowLevelQosParameters
.allocationAndRetentionPriority.pre_emptionCapability =
Ngap_Pre_emptionCapability_shall_not_trigger_pre_emption;
} else {
ngap_QosFlowSetupRequestItem->qosFlowLevelQosParameters
.allocationAndRetentionPriority.pre_emptionCapability =
Ngap_Pre_emptionCapability_may_trigger_pre_emption;
}
if (qos_flow.qos_profile.arp.preempt_vuln.compare("NOT_PREEMPTABLE")
== 0) {
ngap_QosFlowSetupRequestItem->qosFlowLevelQosParameters
.allocationAndRetentionPriority.pre_emptionVulnerability =
Ngap_Pre_emptionVulnerability_not_pre_emptable;
} else {
ngap_QosFlowSetupRequestItem->qosFlowLevelQosParameters
.allocationAndRetentionPriority.pre_emptionVulnerability =
Ngap_Pre_emptionVulnerability_pre_emptable;
}
asn_set_empty(
&qosFlowSetupRequestList->value.choice.QosFlowSetupRequestList.list);
ASN_SEQUENCE_ADD(
&qosFlowSetupRequestList->value.choice.QosFlowSetupRequestList.list,
ngap_QosFlowSetupRequestItem);
ASN_SEQUENCE_ADD(&ngap_IEs->protocolIEs.list, qosFlowSetupRequestList);
Logger::smf_app().info(
"QoS parameters: QFI %d, ARP priority level %d, qos_flow.qos_profile.arp.preempt_cap %s, qos_flow.qos_profile.arp.preempt_vuln %s",
qos_flow.qfi.qfi, qos_flow.qos_profile.arp.priority_level,
qos_flow.qos_profile.arp.preempt_cap.c_str(),
qos_flow.qos_profile.arp.preempt_vuln.c_str());
//encode
size_t buffer_size = BUF_LEN;
char *buffer = (char*) calloc(1, buffer_size);
ssize_t encoded_size = aper_encode_to_new_buffer(
&asn_DEF_Ngap_PDUSessionResourceSetupRequestTransfer, nullptr,
ngap_IEs, (void**) &buffer);
if (encoded_size < 0) {
Logger::smf_app().warn(
"NGAP PDU Session Resource Setup Request Transfer encode failed (encode size %d)",
encoded_size);
return false;
}
#if DEBUG_IS_ON
Logger::smf_app().debug("N2 SM buffer data: ");
for (int i = 0; i < encoded_size; i++)
printf("%02x ", (char) buffer[i]);
printf(" (%d bytes)\n", (int) encoded_size);
#endif
std::string ngap_message((char*) buffer, encoded_size);
ngap_msg_str = ngap_message;
//free memory
free_wrapper((void**) &pduSessionAggregateMaximumBitRate);
free_wrapper(
(void**) &upTransportLayerInformation->value.choice
.UPTransportLayerInformation.choice.gTPTunnel
->transportLayerAddress.buf);
free_wrapper(
(void**) &upTransportLayerInformation->value.choice
.UPTransportLayerInformation.choice.gTPTunnel->gTP_TEID.buf);
free_wrapper(
(void**) &upTransportLayerInformation->value.choice
.UPTransportLayerInformation.choice.gTPTunnel);
free_wrapper((void**) &upTransportLayerInformation);
free_wrapper((void**) &pduSessionType);
free_wrapper((void**) &qosFlowSetupRequestList);
free_wrapper(
(void**) &ngap_QosFlowSetupRequestItem->qosFlowLevelQosParameters
.qosCharacteristics.choice.nonDynamic5QI);
free_wrapper((void**) &ngap_QosFlowSetupRequestItem);
free_wrapper((void**) &ngap_IEs);
free_wrapper((void**) &buffer);
}
break;
//PDU Session Resource Modify Request Transfer IE
case n2_sm_info_type_e::PDU_RES_MOD_REQ: {
//PDU Session Resource Modify Request Transfer IE​
//This IE is included in the following messages (PDU Session SM Context Update):
//1 - PDU Session Update SM Context Response (PDU Session Modification procedure, UE-initiated, step 1)
//2 - N1N2MessageTransfer Request (PDU Session Modification procedure, SMF-requested, step 1)
Logger::smf_app().debug(
"NGAP PDU Session Resource Modify Request Transfer");
pdu_session_update_sm_context_response &sm_context_res =
static_cast<pdu_session_update_sm_context_response&>(msg);
//get default QoS info
std::map<uint8_t, qos_flow_context_updated> qos_flows = { };
sm_context_res.get_all_qos_flow_context_updateds(qos_flows);
for (std::map<uint8_t, qos_flow_context_updated>::iterator it = qos_flows
.begin(); it != qos_flows.end(); ++it)
Logger::smf_app().debug("QoS flow context to be updated with QFI %d",
it->first);
//TODO: support only 1 qos flow
qos_flow_context_updated qos_flow = qos_flows.begin()->second;
//check the QoS Flow
if ((qos_flow.qfi.qfi < QOS_FLOW_IDENTIFIER_FIRST )
or (qos_flow.qfi.qfi > QOS_FLOW_IDENTIFIER_LAST )) {
//error
Logger::smf_app().error("Incorrect QFI %d", qos_flow.qfi.qfi);
return false;
}
Logger::smf_app().debug(
"QoS Flow, UL F-TEID ID " "0x%" PRIx32 ", IP Address %s ",
qos_flow.ul_fteid.teid_gre_key,
conv::toString(qos_flow.ul_fteid.ipv4_address).c_str());
Logger::smf_app().debug(
"QoS Flow, DL F-TEID ID" "0x%" PRIx32 ", IP Address %s",
qos_flow.dl_fteid.teid_gre_key,
conv::toString(qos_flow.dl_fteid.ipv4_address).c_str());
Ngap_PDUSessionResourceModifyRequestTransfer_t *ngap_IEs = nullptr;
ngap_IEs = (Ngap_PDUSessionResourceModifyRequestTransfer_t*) calloc(
1, sizeof(Ngap_PDUSessionResourceModifyRequestTransfer_t));
/*
Ngap_PDUSessionAggregateMaximumBitRate_t PDUSessionAggregateMaximumBitRate;
Ngap_UL_NGU_UP_TNLModifyList_t UL_NGU_UP_TNLModifyList;
Ngap_NetworkInstance_t NetworkInstance;
Ngap_QosFlowAddOrModifyRequestList_t QosFlowAddOrModifyRequestList;
Ngap_QosFlowListWithCause_t QosFlowListWithCause;
Ngap_UPTransportLayerInformationList_t UPTransportLayerInformationList;
*/
//PDUSessionAggregateMaximumBitRate
Ngap_PDUSessionResourceModifyRequestTransferIEs_t *pduSessionAggregateMaximumBitRate =
nullptr;
pduSessionAggregateMaximumBitRate =
(Ngap_PDUSessionResourceModifyRequestTransferIEs_t*) calloc(
1, sizeof(Ngap_PDUSessionResourceModifyRequestTransferIEs_t));
pduSessionAggregateMaximumBitRate->id =
Ngap_ProtocolIE_ID_id_PDUSessionAggregateMaximumBitRate;
pduSessionAggregateMaximumBitRate->criticality = Ngap_Criticality_reject;
pduSessionAggregateMaximumBitRate->value.present =
Ngap_PDUSessionResourceModifyRequestTransferIEs__value_PR_PDUSessionAggregateMaximumBitRate;
supi_t supi = sm_context_res.get_supi();
supi64_t supi64 = smf_supi_to_u64(supi);
std::shared_ptr<smf_context> sc = { };
if (smf_app_inst->is_supi_2_smf_context(supi64)) {
Logger::smf_app().debug("Get SMF context with SUPI " SUPI_64_FMT "",
supi64);
sc = smf_app_inst->supi_2_smf_context(supi64);
sc.get()->get_session_ambr(
pduSessionAggregateMaximumBitRate->value.choice
.PDUSessionAggregateMaximumBitRate,
sm_context_res.get_snssai(), sm_context_res.get_dnn());
} else {
Logger::smf_app().warn(
"SMF context with SUPI " SUPI_64_FMT " does not exist!", supi64);
//TODO:
}
ASN_SEQUENCE_ADD(&ngap_IEs->protocolIEs.list,
pduSessionAggregateMaximumBitRate);
//Ngap_UL_NGU_UP_TNLModifyList_t (included if the PDU Session modification was requested by the UE for a
//PDU Session that has no established User Plane resources)
fteid_t ul_fteid = { };
ul_fteid.interface_type = qos_flow.ul_fteid.interface_type;
ul_fteid.v4 = qos_flow.ul_fteid.v4;
ul_fteid.teid_gre_key = htonl(qos_flow.ul_fteid.teid_gre_key);
ul_fteid.ipv4_address = qos_flow.ul_fteid.ipv4_address;
fteid_t dl_fteid = { };
dl_fteid.interface_type = qos_flow.dl_fteid.interface_type;
dl_fteid.v4 = qos_flow.dl_fteid.v4;
dl_fteid.teid_gre_key = htonl(qos_flow.dl_fteid.teid_gre_key);
dl_fteid.ipv4_address = qos_flow.dl_fteid.ipv4_address;
Ngap_PDUSessionResourceModifyRequestTransferIEs_t *ul_NGU_UP_TNLModifyList =
nullptr;
ul_NGU_UP_TNLModifyList =
(Ngap_PDUSessionResourceModifyRequestTransferIEs_t*) calloc(
1, sizeof(Ngap_PDUSessionResourceModifyRequestTransferIEs_t));
ul_NGU_UP_TNLModifyList->id =
Ngap_ProtocolIE_ID_id_UL_NGU_UP_TNLModifyList;
ul_NGU_UP_TNLModifyList->criticality = Ngap_Criticality_reject;
ul_NGU_UP_TNLModifyList->value.present =
Ngap_PDUSessionResourceModifyRequestTransferIEs__value_PR_UL_NGU_UP_TNLModifyList;
Ngap_UL_NGU_UP_TNLModifyItem_t *ngap_UL_NGU_UP_TNLModifyItem = nullptr;
ngap_UL_NGU_UP_TNLModifyItem = (Ngap_UL_NGU_UP_TNLModifyItem_t*) calloc(
1, sizeof(Ngap_UL_NGU_UP_TNLModifyItem_t));
ngap_UL_NGU_UP_TNLModifyItem->uL_NGU_UP_TNLInformation.present =
Ngap_UPTransportLayerInformation_PR_gTPTunnel;
ngap_UL_NGU_UP_TNLModifyItem->uL_NGU_UP_TNLInformation.choice.gTPTunnel =
(Ngap_GTPTunnel_t*) calloc(1, sizeof(Ngap_GTPTunnel_t));
ngap_UL_NGU_UP_TNLModifyItem->uL_NGU_UP_TNLInformation.choice.gTPTunnel
->transportLayerAddress.buf = (uint8_t*) calloc(4, sizeof(uint8_t));
memcpy(
ngap_UL_NGU_UP_TNLModifyItem->uL_NGU_UP_TNLInformation.choice
.gTPTunnel->transportLayerAddress.buf,
&ul_fteid.ipv4_address, 4);
ngap_UL_NGU_UP_TNLModifyItem->uL_NGU_UP_TNLInformation.choice.gTPTunnel
->transportLayerAddress.size = 4;
ngap_UL_NGU_UP_TNLModifyItem->uL_NGU_UP_TNLInformation.choice.gTPTunnel
->transportLayerAddress.bits_unused = 0;
ngap_UL_NGU_UP_TNLModifyItem->uL_NGU_UP_TNLInformation.choice.gTPTunnel
->gTP_TEID.size = sizeof(struct in_addr);
ngap_UL_NGU_UP_TNLModifyItem->uL_NGU_UP_TNLInformation.choice.gTPTunnel
->gTP_TEID.buf = (uint8_t*) calloc(sizeof(struct in_addr),
sizeof(uint8_t));
memcpy(
ngap_UL_NGU_UP_TNLModifyItem->uL_NGU_UP_TNLInformation.choice
.gTPTunnel->gTP_TEID.buf,
&ul_fteid.teid_gre_key, sizeof(struct in_addr));
ngap_UL_NGU_UP_TNLModifyItem->dL_NGU_UP_TNLInformation.present =
Ngap_UPTransportLayerInformation_PR_gTPTunnel;
ngap_UL_NGU_UP_TNLModifyItem->dL_NGU_UP_TNLInformation.choice.gTPTunnel =
(Ngap_GTPTunnel_t*) calloc(1, sizeof(Ngap_GTPTunnel_t));
ngap_UL_NGU_UP_TNLModifyItem->dL_NGU_UP_TNLInformation.choice.gTPTunnel
->transportLayerAddress.buf = (uint8_t*) calloc(4, sizeof(uint8_t));
memcpy(
ngap_UL_NGU_UP_TNLModifyItem->dL_NGU_UP_TNLInformation.choice
.gTPTunnel->transportLayerAddress.buf,
&dl_fteid.ipv4_address, 4);
ngap_UL_NGU_UP_TNLModifyItem->dL_NGU_UP_TNLInformation.choice.gTPTunnel
->transportLayerAddress.size = 4;
ngap_UL_NGU_UP_TNLModifyItem->dL_NGU_UP_TNLInformation.choice.gTPTunnel
->transportLayerAddress.bits_unused = 0;
ngap_UL_NGU_UP_TNLModifyItem->dL_NGU_UP_TNLInformation.choice.gTPTunnel
->gTP_TEID.size = sizeof(struct in_addr);
ngap_UL_NGU_UP_TNLModifyItem->dL_NGU_UP_TNLInformation.choice.gTPTunnel
->gTP_TEID.buf = (uint8_t*) calloc(sizeof(struct in_addr),
sizeof(uint8_t));
memcpy(
ngap_UL_NGU_UP_TNLModifyItem->dL_NGU_UP_TNLInformation.choice
.gTPTunnel->gTP_TEID.buf,
&dl_fteid.teid_gre_key, 4);
ASN_SEQUENCE_ADD(
&ul_NGU_UP_TNLModifyList->value.choice.UL_NGU_UP_TNLModifyList.list,
ngap_UL_NGU_UP_TNLModifyItem);
ASN_SEQUENCE_ADD(&ngap_IEs->protocolIEs.list, ul_NGU_UP_TNLModifyList);
//Ngap_NetworkInstance_t
//TODO
//Ngap_QosFlowAddOrModifyRequestList_t
//TODO: to be completed
Ngap_PDUSessionResourceModifyRequestTransferIEs_t *qosFlowAddOrModifyRequestList =
nullptr;
qosFlowAddOrModifyRequestList =
(Ngap_PDUSessionResourceModifyRequestTransferIEs_t*) calloc(
1, sizeof(Ngap_PDUSessionResourceModifyRequestTransferIEs_t));
qosFlowAddOrModifyRequestList->id =
Ngap_ProtocolIE_ID_id_QosFlowAddOrModifyRequestList;
qosFlowAddOrModifyRequestList->criticality = Ngap_Criticality_reject;
qosFlowAddOrModifyRequestList->value.present =
Ngap_PDUSessionResourceModifyRequestTransferIEs__value_PR_QosFlowAddOrModifyRequestList;
Ngap_QosFlowAddOrModifyRequestItem *ngap_QosFlowAddOrModifyRequestItem =
nullptr;
ngap_QosFlowAddOrModifyRequestItem =
(Ngap_QosFlowAddOrModifyRequestItem*) calloc(
1, sizeof(Ngap_QosFlowAddOrModifyRequestItem));
ngap_QosFlowAddOrModifyRequestItem->qosFlowIdentifier = qos_flow.qfi.qfi;
ngap_QosFlowAddOrModifyRequestItem->qosFlowLevelQosParameters =
(struct Ngap_QosFlowLevelQosParameters*) calloc(
1, sizeof(struct Ngap_QosFlowLevelQosParameters));
ngap_QosFlowAddOrModifyRequestItem->qosFlowLevelQosParameters
->qosCharacteristics.present =
Ngap_QosCharacteristics_PR_nonDynamic5QI;
ngap_QosFlowAddOrModifyRequestItem->qosFlowLevelQosParameters
->qosCharacteristics.choice.nonDynamic5QI =
(Ngap_NonDynamic5QIDescriptor_t*) (calloc(
1, sizeof(Ngap_NonDynamic5QIDescriptor_t)));
ngap_QosFlowAddOrModifyRequestItem->qosFlowLevelQosParameters
->qosCharacteristics.choice.nonDynamic5QI->fiveQI = qos_flow.qfi.qfi;
ngap_QosFlowAddOrModifyRequestItem->qosFlowLevelQosParameters
->allocationAndRetentionPriority.priorityLevelARP = qos_flow
.qos_profile.priority_level;
if (qos_flow.qos_profile.arp.preempt_cap.compare("NOT_PREEMPT") == 0) {
ngap_QosFlowAddOrModifyRequestItem->qosFlowLevelQosParameters
->allocationAndRetentionPriority.pre_emptionCapability =
Ngap_Pre_emptionCapability_shall_not_trigger_pre_emption;
} else {
ngap_QosFlowAddOrModifyRequestItem->qosFlowLevelQosParameters
->allocationAndRetentionPriority.pre_emptionCapability =
Ngap_Pre_emptionCapability_may_trigger_pre_emption;
}
if (qos_flow.qos_profile.arp.preempt_vuln.compare("NOT_PREEMPTABLE")
== 0) {
ngap_QosFlowAddOrModifyRequestItem->qosFlowLevelQosParameters
->allocationAndRetentionPriority.pre_emptionVulnerability =
Ngap_Pre_emptionVulnerability_not_pre_emptable;
} else {
ngap_QosFlowAddOrModifyRequestItem->qosFlowLevelQosParameters
->allocationAndRetentionPriority.pre_emptionVulnerability =
Ngap_Pre_emptionVulnerability_pre_emptable;
}
ASN_SEQUENCE_ADD(
&qosFlowAddOrModifyRequestList->value.choice
.QosFlowAddOrModifyRequestList.list,
ngap_QosFlowAddOrModifyRequestItem);
//Ngap_E_RAB_ID_t *e_RAB_ID; //optional
ASN_SEQUENCE_ADD(&ngap_IEs->protocolIEs.list,
qosFlowAddOrModifyRequestList);
//Ngap_QosFlowList_t - QoS to release list??
//TODO
//Ngap_UPTransportLayerInformation_t
//TODO
//encode
size_t buffer_size = BUF_LEN;
char *buffer = (char*) calloc(1, buffer_size);
ssize_t encoded_size = aper_encode_to_new_buffer(
&asn_DEF_Ngap_PDUSessionResourceModifyRequestTransfer, nullptr,
ngap_IEs, (void**) &buffer);
if (encoded_size < 0) {
Logger::smf_app().warn(
"NGAP PDU Session Resource Modify Request Transfer encode failed (encoded size %d)",
encoded_size);
return false;
}
#if DEBUG_IS_ON
Logger::smf_app().debug("N2 SM buffer data: ");
for (int i = 0; i < encoded_size; i++)
printf("%02x ", (char) buffer[i]);
printf(" (%d bytes)\n", (int) encoded_size);
#endif
std::string ngap_message((char*) buffer, encoded_size);
ngap_msg_str = ngap_message;
//free memory
free_wrapper((void**) &pduSessionAggregateMaximumBitRate);
free_wrapper(
(void**) &ngap_UL_NGU_UP_TNLModifyItem->uL_NGU_UP_TNLInformation
.choice.gTPTunnel->transportLayerAddress.buf);
free_wrapper(
(void**) &ngap_UL_NGU_UP_TNLModifyItem->uL_NGU_UP_TNLInformation
.choice.gTPTunnel->gTP_TEID.buf);
free_wrapper(
(void**) &ngap_UL_NGU_UP_TNLModifyItem->dL_NGU_UP_TNLInformation
.choice.gTPTunnel->transportLayerAddress.buf);
free_wrapper(
(void**) &ngap_UL_NGU_UP_TNLModifyItem->dL_NGU_UP_TNLInformation
.choice.gTPTunnel->gTP_TEID.buf);
free_wrapper((void**) &ngap_UL_NGU_UP_TNLModifyItem);
free_wrapper((void**) &ul_NGU_UP_TNLModifyList);
free_wrapper(
(void**) &ngap_QosFlowAddOrModifyRequestItem
->qosFlowLevelQosParameters->qosCharacteristics.choice
.nonDynamic5QI);
free_wrapper(
(void**) &ngap_QosFlowAddOrModifyRequestItem
->qosFlowLevelQosParameters);
free_wrapper((void**) &ngap_QosFlowAddOrModifyRequestItem);
free_wrapper((void**) &qosFlowAddOrModifyRequestList);
free_wrapper((void**) &ngap_IEs);
free_wrapper((void**) &buffer);
}
break;
case n2_sm_info_type_e::PDU_RES_SETUP_RSP: {
//PDU Session Resource Setup Response Transfer for testing purpose
Logger::smf_app().debug(
"[Create N2 SM Information] NGAP PDU Session Resource Setup Response Transfer");
// Ngap_QosFlowPerTNLInformation_t qosFlowPerTNLInformation;
// struct Ngap_QosFlowPerTNLInformation *additionalQosFlowPerTNLInformation; /* OPTIONAL */
// struct Ngap_SecurityResult *securityResult; /* OPTIONAL */
// struct Ngap_QosFlowList *qosFlowFailedToSetupList; /* OPTIONAL */
// struct Ngap_ProtocolExtensionContainer *iE_Extensions; /* OPTIONAL */
Ngap_PDUSessionResourceSetupResponseTransfer_t *ngap_resource_response_transfer =
nullptr;
ngap_resource_response_transfer =
(Ngap_PDUSessionResourceSetupResponseTransfer_t*) calloc(
1, sizeof(Ngap_PDUSessionResourceSetupResponseTransfer_t));
ngap_resource_response_transfer->dLQosFlowPerTNLInformation
.uPTransportLayerInformation.present =
Ngap_UPTransportLayerInformation_PR_gTPTunnel;
ngap_resource_response_transfer->dLQosFlowPerTNLInformation
.uPTransportLayerInformation.choice.gTPTunnel =
(Ngap_GTPTunnel_t*) calloc(1, sizeof(Ngap_GTPTunnel_t));
ngap_resource_response_transfer->dLQosFlowPerTNLInformation
.uPTransportLayerInformation.choice.gTPTunnel->transportLayerAddress
.size = 4;
ngap_resource_response_transfer->dLQosFlowPerTNLInformation
.uPTransportLayerInformation.choice.gTPTunnel->transportLayerAddress
.buf = (uint8_t*) calloc(4, sizeof(uint8_t));
ngap_resource_response_transfer->dLQosFlowPerTNLInformation
.uPTransportLayerInformation.choice.gTPTunnel->transportLayerAddress
.buf[0] = 0xc0;
ngap_resource_response_transfer->dLQosFlowPerTNLInformation
.uPTransportLayerInformation.choice.gTPTunnel->transportLayerAddress
.buf[1] = 0xa8;
ngap_resource_response_transfer->dLQosFlowPerTNLInformation
.uPTransportLayerInformation.choice.gTPTunnel->transportLayerAddress
.buf[2] = 0xf8;
ngap_resource_response_transfer->dLQosFlowPerTNLInformation
.uPTransportLayerInformation.choice.gTPTunnel->transportLayerAddress
.buf[3] = 0x9f;
ngap_resource_response_transfer->dLQosFlowPerTNLInformation
.uPTransportLayerInformation.choice.gTPTunnel->transportLayerAddress
.bits_unused = 0;
ngap_resource_response_transfer->dLQosFlowPerTNLInformation
.uPTransportLayerInformation.choice.gTPTunnel->gTP_TEID.size =
sizeof(struct in_addr);
ngap_resource_response_transfer->dLQosFlowPerTNLInformation
.uPTransportLayerInformation.choice.gTPTunnel->gTP_TEID.buf =
(uint8_t*) calloc(sizeof(struct in_addr), sizeof(uint8_t));
ngap_resource_response_transfer->dLQosFlowPerTNLInformation
.uPTransportLayerInformation.choice.gTPTunnel->gTP_TEID.buf[0] = 0x00;
ngap_resource_response_transfer->dLQosFlowPerTNLInformation
.uPTransportLayerInformation.choice.gTPTunnel->gTP_TEID.buf[1] = 0x00;
ngap_resource_response_transfer->dLQosFlowPerTNLInformation
.uPTransportLayerInformation.choice.gTPTunnel->gTP_TEID.buf[2] = 0x00;
ngap_resource_response_transfer->dLQosFlowPerTNLInformation
.uPTransportLayerInformation.choice.gTPTunnel->gTP_TEID.buf[3] = 0x01;
Ngap_AssociatedQosFlowItem_t *qos_flow_item = nullptr;
qos_flow_item = (Ngap_AssociatedQosFlowItem_t*) calloc(
1, sizeof(Ngap_AssociatedQosFlowItem_t));
qos_flow_item->qosFlowIdentifier = 60;
ASN_SEQUENCE_ADD(
&ngap_resource_response_transfer->dLQosFlowPerTNLInformation
.associatedQosFlowList.list,
qos_flow_item);
//encode
size_t buffer_size = BUF_LEN;
char *buffer = (char*) calloc(1, buffer_size);
ssize_t encoded_size = aper_encode_to_new_buffer(
&asn_DEF_Ngap_PDUSessionResourceSetupResponseTransfer, nullptr,
ngap_resource_response_transfer, (void**) &buffer);
if (encoded_size < 0) {
Logger::smf_app().warn(
"NGAP PDU Session Resource Setup Response Transfer encode failed (encoded size %d)",
encoded_size);
return false;
}
#if DEBUG_IS_ON
Logger::smf_app().debug("N2 SM buffer data: ");
for (int i = 0; i < encoded_size; i++)
printf("%02x ", (char) buffer[i]);
Logger::smf_app().debug(" (%d bytes) \n", encoded_size);
#endif
std::string ngap_message((char*) buffer, encoded_size);
ngap_msg_str = ngap_message;
//free memory
free_wrapper(
(void**) &ngap_resource_response_transfer->dLQosFlowPerTNLInformation
.uPTransportLayerInformation.choice.gTPTunnel
->transportLayerAddress.buf);
free_wrapper(
(void**) &ngap_resource_response_transfer->dLQosFlowPerTNLInformation
.uPTransportLayerInformation.choice.gTPTunnel->gTP_TEID.buf);
free_wrapper(
(void**) &ngap_resource_response_transfer->dLQosFlowPerTNLInformation
.uPTransportLayerInformation.choice.gTPTunnel);
free_wrapper((void**) &ngap_resource_response_transfer);
free_wrapper((void**) &qos_flow_item);
free_wrapper((void**) &buffer);
}
break;
case n2_sm_info_type_e::PDU_RES_MOD_RSP: {
//PDU Session Resource Modify Response Transfer IE for testing purpose
Logger::smf_app().debug(
"[Create N2 SM Information] NGAP PDU Session Resource Modify Response Transfer");
//struct Ngap_UPTransportLayerInformation *dL_NGU_UP_TNLInformation; /* OPTIONAL */
//struct Ngap_UPTransportLayerInformation *uL_NGU_UP_TNLInformation; /* OPTIONAL */
//struct Ngap_QosFlowAddOrModifyResponseList *qosFlowAddOrModifyResponseList; /* OPTIONAL */
//struct Ngap_QosFlowPerTNLInformationList *additionalDLQosFlowPerTNLInformation; /* OPTIONAL */
// struct Ngap_QosFlowListWithCause *qosFlowFailedToAddOrModifyList; /* OPTIONAL */
Ngap_PDUSessionResourceModifyResponseTransfer_t *ngap_resource_response_transfer =
nullptr;
ngap_resource_response_transfer =
(Ngap_PDUSessionResourceModifyResponseTransfer_t*) calloc(
1, sizeof(Ngap_PDUSessionResourceModifyResponseTransfer_t));
ngap_resource_response_transfer->dL_NGU_UP_TNLInformation =
(Ngap_UPTransportLayerInformation*) calloc(
1, sizeof(Ngap_UPTransportLayerInformation));
ngap_resource_response_transfer->dL_NGU_UP_TNLInformation->present =
Ngap_UPTransportLayerInformation_PR_gTPTunnel;
ngap_resource_response_transfer->dL_NGU_UP_TNLInformation->choice
.gTPTunnel = (Ngap_GTPTunnel_t*) calloc(1, sizeof(Ngap_GTPTunnel_t));
ngap_resource_response_transfer->dL_NGU_UP_TNLInformation->choice
.gTPTunnel->transportLayerAddress.size = 4;
ngap_resource_response_transfer->dL_NGU_UP_TNLInformation->choice
.gTPTunnel->transportLayerAddress.buf = (uint8_t*) calloc(
4, sizeof(uint8_t));
ngap_resource_response_transfer->dL_NGU_UP_TNLInformation->choice
.gTPTunnel->transportLayerAddress.buf[0] = 0xc0;
ngap_resource_response_transfer->dL_NGU_UP_TNLInformation->choice
.gTPTunnel->transportLayerAddress.buf[1] = 0xa8;
ngap_resource_response_transfer->dL_NGU_UP_TNLInformation->choice
.gTPTunnel->transportLayerAddress.buf[2] = 0xf8;
ngap_resource_response_transfer->dL_NGU_UP_TNLInformation->choice
.gTPTunnel->transportLayerAddress.buf[3] = 0x9f;
ngap_resource_response_transfer->dL_NGU_UP_TNLInformation->choice
.gTPTunnel->transportLayerAddress.bits_unused = 0;
ngap_resource_response_transfer->dL_NGU_UP_TNLInformation->choice
.gTPTunnel->gTP_TEID.size = 4;
ngap_resource_response_transfer->dL_NGU_UP_TNLInformation->choice
.gTPTunnel->gTP_TEID.buf = (uint8_t*) calloc(4, sizeof(uint8_t));
ngap_resource_response_transfer->dL_NGU_UP_TNLInformation->choice
.gTPTunnel->gTP_TEID.buf[0] = 0x00;
ngap_resource_response_transfer->dL_NGU_UP_TNLInformation->choice
.gTPTunnel->gTP_TEID.buf[1] = 0x00;
ngap_resource_response_transfer->dL_NGU_UP_TNLInformation->choice
.gTPTunnel->gTP_TEID.buf[2] = 0x00;
ngap_resource_response_transfer->dL_NGU_UP_TNLInformation->choice
.gTPTunnel->gTP_TEID.buf[3] = 0x01;
ngap_resource_response_transfer->qosFlowAddOrModifyResponseList =
(Ngap_QosFlowAddOrModifyResponseList_t*) calloc(
1, sizeof(Ngap_QosFlowAddOrModifyResponseList_t));
Ngap_QosFlowAddOrModifyResponseItem *qosFlowAddOrModifyResponseItem =
nullptr;
qosFlowAddOrModifyResponseItem =
(Ngap_QosFlowAddOrModifyResponseItem*) calloc(
1, sizeof(Ngap_QosFlowAddOrModifyResponseItem));
qosFlowAddOrModifyResponseItem->qosFlowIdentifier = 60;
ASN_SEQUENCE_ADD(
&ngap_resource_response_transfer->qosFlowAddOrModifyResponseList->list,
qosFlowAddOrModifyResponseItem);
//encode
size_t buffer_size = BUF_LEN;
char *buffer = (char*) calloc(1, buffer_size);
ssize_t encoded_size = aper_encode_to_new_buffer(
&asn_DEF_Ngap_PDUSessionResourceModifyResponseTransfer, nullptr,
ngap_resource_response_transfer, (void**) &buffer);
if (encoded_size < 0) {
Logger::smf_app().warn(
" NGAP PDU Session Resource Modify Response Transfer encode failed (encoded size %d)",
encoded_size);
return false;
}
#if DEBUG_IS_ON
Logger::smf_app().debug("N2 SM buffer data: ");
for (int i = 0; i < encoded_size; i++)
printf("%02x ", (char) buffer[i]);
Logger::smf_app().debug(" (%d bytes) \n", encoded_size);
#endif
std::string ngap_message((char*) buffer, encoded_size);
ngap_msg_str = ngap_message;
//free memory
free_wrapper(
(void**) &ngap_resource_response_transfer->dL_NGU_UP_TNLInformation
->choice.gTPTunnel->transportLayerAddress.buf);
free_wrapper(
(void**) &ngap_resource_response_transfer->dL_NGU_UP_TNLInformation
->choice.gTPTunnel->gTP_TEID.buf);
free_wrapper(
(void**) &ngap_resource_response_transfer->dL_NGU_UP_TNLInformation
->choice.gTPTunnel);
free_wrapper((void**) &qosFlowAddOrModifyResponseItem);
free_wrapper(
(void**) &ngap_resource_response_transfer
->qosFlowAddOrModifyResponseList);
free_wrapper((void**) &ngap_resource_response_transfer);
free_wrapper((void**) &buffer);
}
break;
//PDU Session Resource Release Command Transfer
case n2_sm_info_type_e::PDU_RES_REL_CMD: {
//PDU Session Resource Release Command Transfer IE
//This IE is included in the following messages:
//1 - PDU Session Update SM Context Response (PDU Session Release UE-Initiated: section 4.3.4@3GPP TS 23.502, step 1)
//2 - N1N2MessageTransfer Request​ (PDU Session Release SMF-Requested, step 1)
Ngap_PDUSessionResourceReleaseCommandTransfer_t *ngap_resource_release_command_transfer =
nullptr;
ngap_resource_release_command_transfer =
(Ngap_PDUSessionResourceReleaseCommandTransfer_t*) calloc(
1, sizeof(Ngap_PDUSessionResourceReleaseCommandTransfer_t));
//TODO: To be completed, here's an example
/*
typedef struct Ngap_Cause {
Ngap_Cause_PR present;
union Ngap_Cause_u {
Ngap_CauseRadioNetwork_t radioNetwork;
Ngap_CauseTransport_t transport;
Ngap_CauseNas_t nas;
Ngap_CauseProtocol_t protocol;
Ngap_CauseMisc_t misc;
struct Ngap_ProtocolIE_SingleContainer *choice_Extensions;
} choice;
asn_struct_ctx_t _asn_ctx;
} Ngap_Cause_t;
*/
ngap_resource_release_command_transfer->cause.present =
Ngap_Cause_PR_radioNetwork;
ngap_resource_release_command_transfer->cause.choice.radioNetwork = 1;
//encode
size_t buffer_size = BUF_LEN;
char *buffer = (char*) calloc(1, buffer_size);
ssize_t encoded_size = aper_encode_to_new_buffer(
&asn_DEF_Ngap_PDUSessionResourceReleaseCommandTransfer, nullptr,
ngap_resource_release_command_transfer, (void**) &buffer);
if (encoded_size < 0) {
Logger::smf_app().warn(
"NGAP PDU Session Release Command encode failed (encoded size %d)",
encoded_size);
return false;
}
#if DEBUG_IS_ON
Logger::smf_app().debug("N2 SM buffer data: ");
for (int i = 0; i < encoded_size; i++)
printf("%02x ", (char) buffer[i]);
Logger::smf_app().debug(" (%d bytes) \n", encoded_size);
#endif
std::string ngap_message((char*) buffer, encoded_size);
ngap_msg_str = ngap_message;
//free memory
free_wrapper((void**) &ngap_resource_release_command_transfer);
free_wrapper((void**) &buffer);
}
break;
//PDU Session Resource Release Response Transfer
//FOR TESTING PURPOSE ONLY!!
case n2_sm_info_type_e::PDU_RES_REL_RSP: {
//PDU Session Resource Release Response Transfer IE
//This IE is included in:
//1 - PDU Session Update SM Context Request (PDU Session Release UE-Initiated, step 2 - UPLINK)
Ngap_PDUSessionResourceReleaseResponseTransfer_t *ngap_resource_release_response_transfer =
nullptr;
ngap_resource_release_response_transfer =
(Ngap_PDUSessionResourceReleaseResponseTransfer_t*) calloc(
1, sizeof(Ngap_PDUSessionResourceReleaseResponseTransfer_t));
//TODO: To be completed, here's an example
//encode
size_t buffer_size = BUF_LEN;
char *buffer = (char*) calloc(1, buffer_size);
ssize_t encoded_size = aper_encode_to_new_buffer(
&asn_DEF_Ngap_PDUSessionResourceReleaseResponseTransfer, nullptr,
ngap_resource_release_response_transfer, (void**) &buffer);
if (encoded_size < 0) {
Logger::smf_app().warn(
"NGAP PDU Session Release Command encode failed (encoded size %d)",
encoded_size);
return false;
}
#if DEBUG_IS_ON
Logger::smf_app().debug("N2 SM buffer data: ");
for (int i = 0; i < encoded_size; i++)
printf("%02x ", (char) buffer[i]);
Logger::smf_app().debug(" (%d bytes) \n", encoded_size);
#endif
std::string ngap_message((char*) buffer, encoded_size);
ngap_msg_str = ngap_message;
//free memory
free_wrapper((void**) &ngap_resource_release_response_transfer);
free_wrapper((void**) &buffer);
}
break;
default:
Logger::smf_app().warn("Unknown NGAP IE type: %s \n",
n2_sm_info_type_e2str[(uint8_t) ngap_ie_type]);
}
}
//------------------------------------------------------------------------------
int smf_n1_n2::decode_n1_sm_container(nas_message_t &nas_msg,
const std::string &n1_sm_msg) {
Logger::smf_app().info("Decode NAS message from N1 SM Container.");
//step 1. Decode NAS message (for instance, ... only served as an example)
nas_message_decode_status_t decode_status = { 0 };
int decoder_rc = RETURNok;
unsigned int data_len = n1_sm_msg.length();
unsigned char *data = (unsigned char*) malloc(data_len + 1);
memset(data, 0, data_len + 1);
memcpy((void*) data, (void*) n1_sm_msg.c_str(), data_len);
#if DEBUG_IS_ON
printf("Content: ");
for (int i = 0; i < data_len; i++)
printf(" %02x ", data[i]);
printf("\n");
#endif
//decode the NAS message (using NAS lib)
decoder_rc = nas_message_decode(data, &nas_msg, data_len, nullptr,
&decode_status);
Logger::smf_app().debug(
"NAS message, Extended Protocol Discriminator 0x%x, PDU Session Identity 0x%x, Procedure Transaction Identity 0x%x, Message Type 0x%x",
nas_msg.plain.sm.header.extended_protocol_discriminator,
nas_msg.plain.sm.header.pdu_session_identity,
nas_msg.plain.sm.header.procedure_transaction_identity,
nas_msg.plain.sm.header.message_type);
//free memory
free_wrapper((void**) &data);
return decoder_rc;
}
//---------------------------------------------------------------------------------------------
int smf_n1_n2::decode_n2_sm_information(
std::shared_ptr<Ngap_PDUSessionResourceSetupResponseTransfer_t> &ngap_IE,
const std::string &n2_sm_info) {
Logger::smf_app().info(
"Decode NGAP message (PDUSessionResourceSetupResponseTransfer) from N2 SM Information");
unsigned int data_len = n2_sm_info.length();
unsigned char *data = (unsigned char*) malloc(data_len + 1);
memset(data, 0, data_len + 1);
memcpy((void*) data, (void*) n2_sm_info.c_str(), data_len);
#if DEBUG_IS_ON
printf("Content: ");
for (int i = 0; i < data_len; i++)
printf(" %02x ", data[i]);
printf("\n");
#endif
//PDUSessionResourceSetupResponseTransfer
asn_dec_rval_t rc = asn_decode(
nullptr, ATS_ALIGNED_CANONICAL_PER,
&asn_DEF_Ngap_PDUSessionResourceSetupResponseTransfer, (void**) &ngap_IE,
(void*) data, data_len);
//free memory
free_wrapper((void**) &data);
if (rc.code != RC_OK) {
Logger::smf_app().warn("asn_decode failed with code %d", rc.code);
return RETURNerror ;
}
return RETURNok ;
}
//---------------------------------------------------------------------------------------------
int smf_n1_n2::decode_n2_sm_information(
std::shared_ptr<Ngap_PDUSessionResourceModifyResponseTransfer_t> &ngap_IE,
const std::string &n2_sm_info) {
Logger::smf_app().info(
"Decode NGAP message (Ngap_PDUSessionResourceModifyResponseTransfer) from N2 SM Information");
unsigned int data_len = n2_sm_info.length();
unsigned char *data = (unsigned char*) malloc(data_len + 1);
memset(data, 0, data_len + 1);
memcpy((void*) data, (void*) n2_sm_info.c_str(), data_len);
//Ngap_PDUSessionResourceModifyResponseTransfer
asn_dec_rval_t rc = asn_decode(
nullptr, ATS_ALIGNED_CANONICAL_PER,
&asn_DEF_Ngap_PDUSessionResourceModifyResponseTransfer, (void**) &ngap_IE,
(void*) data, data_len);
//free memory
free_wrapper((void**) &data);
if (rc.code != RC_OK) {
Logger::smf_app().warn("asn_decode failed with code %d", rc.code);
return RETURNerror ;
}
return RETURNok ;
}
//---------------------------------------------------------------------------------------------
int smf_n1_n2::decode_n2_sm_information(
std::shared_ptr<Ngap_PDUSessionResourceReleaseResponseTransfer_t> &ngap_IE,
const std::string &n2_sm_info) {
Logger::smf_app().info(
"Decode NGAP message (Ngap_PDUSessionResourceReleaseResponseTransfer) from N2 SM Information");
unsigned int data_len = n2_sm_info.length();
unsigned char *data = (unsigned char*) malloc(data_len + 1);
memset(data, 0, data_len + 1);
memcpy((void*) data, (void*) n2_sm_info.c_str(), data_len);
//Ngap_PDUSessionResourceModifyResponseTransfer
asn_dec_rval_t rc = asn_decode(
nullptr, ATS_ALIGNED_CANONICAL_PER,
&asn_DEF_Ngap_PDUSessionResourceReleaseResponseTransfer,
(void**) &ngap_IE, (void*) data, data_len);
//free memory
free_wrapper((void**) &data);
if (rc.code != RC_OK) {
Logger::smf_app().warn("asn_decode failed with code %d", rc.code);
return RETURNerror ;
}
return RETURNok ;
}
//---------------------------------------------------------------------------------------------
int smf_n1_n2::decode_n2_sm_information(
std::shared_ptr<Ngap_PDUSessionResourceSetupUnsuccessfulTransfer_t> &ngap_IE,
const std::string &n2_sm_info) {
Logger::smf_app().info(
"Decode NGAP message (Ngap_PDUSessionResourceSetupUnsuccessfulTransfer) from N2 SM Information");
unsigned int data_len = n2_sm_info.length();
unsigned char *data = (unsigned char*) malloc(data_len + 1);
memset(data, 0, data_len + 1);
memcpy((void*) data, (void*) n2_sm_info.c_str(), data_len);
//Ngap_PDUSessionResourceSetupUnsuccessfulTransfer
asn_dec_rval_t rc = asn_decode(
nullptr, ATS_ALIGNED_CANONICAL_PER,
&asn_DEF_Ngap_PDUSessionResourceSetupUnsuccessfulTransfer,
(void**) &ngap_IE, (void*) data, data_len);
//free memory
free_wrapper((void**) &data);
if (rc.code != RC_OK) {
Logger::smf_app().warn("asn_decode failed with code %d", rc.code);
return RETURNerror ;
}
return RETURNok ;
}
/*
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The OpenAirInterface Software Alliance licenses this file to You under
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
* except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.openairinterface.org/?page_id=698
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*-------------------------------------------------------------------------------
* For more information about the OpenAirInterface (OAI) Software Alliance:
* contact@openairinterface.org
*/
/*! \file smf_n2.cpp
\brief
\author Tien-Thinh NGUYEN, Keliang DU
\company Eurecom
\date 2019
\email: tien-thinh.nguyen@eurecom.fr
*/
#include "smf_n2.hpp"
#include "string.hpp"
#include <stdexcept>
#include <arpa/inet.h>
#include "smf.h"
extern "C" {
#include "dynamic_memory_check.h"
#include "Ngap_NGAP-PDU.h"
#include "Ngap_ProtocolIE-Field.h"
#include "Ngap_ProcedureCode.h"
#include "Ngap_Criticality.h"
#include "Ngap_PDUSessionResourceSetupRequestTransfer.h"
#include "Ngap_PDUSessionResourceSetupResponseTransfer.h"
#include "Ngap_QosFlowSetupRequestItem.h"
#include "Ngap_GTPTunnel.h"
#include "Ngap_NonDynamic5QIDescriptor.h"
#include "Ngap_Dynamic5QIDescriptor.h"
#include "Ngap_AssociatedQosFlowItem.h"
#include "Ngap_PDUSessionResourceModifyRequestTransfer.h"
#include "Ngap_UL-NGU-UP-TNLModifyItem.h"
#include "Ngap_QosFlowAddOrModifyRequestItem.h"
#include "Ngap_PDUSessionResourceReleaseCommandTransfer.h"
#include "Ngap_PDUSessionResourceReleaseResponseTransfer.h"
#include "Ngap_QosFlowAddOrModifyResponseItem.h"
#include "Ngap_QosFlowAddOrModifyResponseList.h"
}
using namespace smf;
extern smf_app *smf_app_inst;
//------------------------------------------------------------------------------
bool smf_n2::create_n2_pdu_session_resource_setup_request_transfer(pdu_session_create_sm_context_response &sm_context_res,
n2_sm_info_type_e ngap_info_type,
std::string &ngap_msg_str) {
Logger::smf_n2().info("Create N2 SM Information, PDU Session Resource Setup Request Transfer");
bool result = false;
Ngap_PDUSessionResourceSetupRequestTransfer_t *ngap_IEs = nullptr;
ngap_IEs = (Ngap_PDUSessionResourceSetupRequestTransfer_t*) calloc(
1, sizeof(Ngap_PDUSessionResourceSetupRequestTransfer_t));
qos_flow_context_updated qos_flow = { };
//get default QoS value
qos_flow = sm_context_res.get_qos_flow_context();
Logger::smf_n2().debug(
"UL F-TEID, TEID " "0x%" PRIx32 ", IP Address %s",
qos_flow.ul_fteid.teid_gre_key,
conv::toString(qos_flow.ul_fteid.ipv4_address).c_str());
Logger::smf_n2().info(
"QoS parameters: QFI %d, Priority level %d, ARP priority level %d",
qos_flow.qfi.qfi, qos_flow.qos_profile.priority_level,
qos_flow.qos_profile.arp.priority_level);
//check the QoS Flow
if ((qos_flow.qfi.qfi < QOS_FLOW_IDENTIFIER_FIRST )
or (qos_flow.qfi.qfi > QOS_FLOW_IDENTIFIER_LAST )) {
//error
Logger::smf_n2().error("Incorrect QFI %d", qos_flow.qfi.qfi);
free_wrapper((void**) &ngap_IEs);
return false;
}
//PDUSessionAggregateMaximumBitRate
Ngap_PDUSessionResourceSetupRequestTransferIEs_t *pduSessionAggregateMaximumBitRate =
nullptr;
pduSessionAggregateMaximumBitRate =
(Ngap_PDUSessionResourceSetupRequestTransferIEs_t*) calloc(
1, sizeof(Ngap_PDUSessionResourceSetupRequestTransferIEs_t));
pduSessionAggregateMaximumBitRate->id =
Ngap_ProtocolIE_ID_id_PDUSessionAggregateMaximumBitRate;
pduSessionAggregateMaximumBitRate->criticality = Ngap_Criticality_reject;
pduSessionAggregateMaximumBitRate->value.present =
Ngap_PDUSessionResourceSetupRequestTransferIEs__value_PR_PDUSessionAggregateMaximumBitRate;
asn_set_empty(&ngap_IEs->protocolIEs.list);
//SessionAMBR
supi_t supi = sm_context_res.get_supi();
supi64_t supi64 = smf_supi_to_u64(supi);
std::shared_ptr<smf_context> sc = { };
if (smf_app_inst->is_supi_2_smf_context(supi64)) {
Logger::smf_n2().debug("Get SMF context with SUPI " SUPI_64_FMT "",
supi64);
sc = smf_app_inst->supi_2_smf_context(supi64);
sc.get()->get_session_ambr(
pduSessionAggregateMaximumBitRate->value.choice
.PDUSessionAggregateMaximumBitRate,
sm_context_res.get_snssai(), sm_context_res.get_dnn());
} else {
Logger::smf_n2().warn(
"SMF context with SUPI " SUPI_64_FMT " does not exist!", supi64);
free_wrapper((void**) &pduSessionAggregateMaximumBitRate);
return false;
}
ASN_SEQUENCE_ADD(&ngap_IEs->protocolIEs.list,
pduSessionAggregateMaximumBitRate);
//UPTransportLayerInformation
fteid_t ul_fteid = { };
ul_fteid.interface_type = qos_flow.ul_fteid.interface_type;
ul_fteid.v4 = qos_flow.ul_fteid.v4;
ul_fteid.teid_gre_key = htonl(qos_flow.ul_fteid.teid_gre_key);
ul_fteid.ipv4_address = qos_flow.ul_fteid.ipv4_address;
Ngap_PDUSessionResourceSetupRequestTransferIEs_t *upTransportLayerInformation =
nullptr;
upTransportLayerInformation =
(Ngap_PDUSessionResourceSetupRequestTransferIEs_t*) calloc(
1, sizeof(Ngap_PDUSessionResourceSetupRequestTransferIEs_t));
upTransportLayerInformation->id =
Ngap_ProtocolIE_ID_id_UL_NGU_UP_TNLInformation;
upTransportLayerInformation->criticality = Ngap_Criticality_reject;
upTransportLayerInformation->value.present =
Ngap_PDUSessionResourceSetupRequestTransferIEs__value_PR_UPTransportLayerInformation;
upTransportLayerInformation->value.choice.UPTransportLayerInformation
.present = Ngap_UPTransportLayerInformation_PR_gTPTunnel;
upTransportLayerInformation->value.choice.UPTransportLayerInformation
.choice.gTPTunnel = (Ngap_GTPTunnel_t*) calloc(
1, sizeof(Ngap_GTPTunnel_t));
upTransportLayerInformation->value.choice.UPTransportLayerInformation
.choice.gTPTunnel->transportLayerAddress.size = 4;
upTransportLayerInformation->value.choice.UPTransportLayerInformation
.choice.gTPTunnel->transportLayerAddress.buf = (uint8_t*) calloc(
4, sizeof(uint8_t));
memcpy(
upTransportLayerInformation->value.choice.UPTransportLayerInformation
.choice.gTPTunnel->transportLayerAddress.buf,
&ul_fteid.ipv4_address, 4);
upTransportLayerInformation->value.choice.UPTransportLayerInformation
.choice.gTPTunnel->transportLayerAddress.bits_unused = 0;
upTransportLayerInformation->value.choice.UPTransportLayerInformation
.choice.gTPTunnel->gTP_TEID.size = sizeof(struct in_addr);
upTransportLayerInformation->value.choice.UPTransportLayerInformation
.choice.gTPTunnel->gTP_TEID.buf = (uint8_t*) calloc(
sizeof(struct in_addr), sizeof(uint8_t));
memcpy(
upTransportLayerInformation->value.choice.UPTransportLayerInformation
.choice.gTPTunnel->gTP_TEID.buf,
&ul_fteid.teid_gre_key, sizeof(struct in_addr));
ASN_SEQUENCE_ADD(&ngap_IEs->protocolIEs.list,
upTransportLayerInformation);
//DataForwardingNotPossible
//TODO:
//PDUSessionType
Ngap_PDUSessionResourceSetupRequestTransferIEs_t *pduSessionType = nullptr;
pduSessionType =
(Ngap_PDUSessionResourceSetupRequestTransferIEs_t*) calloc(
1, sizeof(Ngap_PDUSessionResourceSetupRequestTransferIEs_t));
pduSessionType->id = Ngap_ProtocolIE_ID_id_PDUSessionType;
pduSessionType->criticality = Ngap_Criticality_reject;
pduSessionType->value.present =
Ngap_PDUSessionResourceSetupRequestTransferIEs__value_PR_PDUSessionType;
pduSessionType->value.choice.PDUSessionType = sm_context_res.get_pdu_session_type()
- 1; //TODO: dirty code, difference between Ngap_PDUSessionType_ipv4 vs pdu_session_type_e::PDU_SESSION_TYPE_E_IPV4 (TS 38.413 vs TS 24.501)
ASN_SEQUENCE_ADD(&ngap_IEs->protocolIEs.list, pduSessionType);
Logger::smf_n2().debug("PDU Session Type: %d ",
sm_context_res.get_pdu_session_type());
//SecurityIndication
//TODO: should get from UDM
// Ngap_PDUSessionResourceSetupRequestTransferIEs_t *securityIndication = nullptr;
// securityIndication = (Ngap_PDUSessionResourceSetupRequestTransferIEs_t *) calloc(1, sizeof(Ngap_PDUSessionResourceSetupRequestTransferIEs_t));
// securityIndication->value.choice.SecurityIndication.integrityProtectionIndication = Ngap_IntegrityProtectionIndication_not_needed;
// securityIndication->value.choice.SecurityIndication.confidentialityProtectionIndication = Ngap_ConfidentialityProtectionIndication_not_needed;
//NetworkInstance
//TODO:
//QosFlowSetupRequestList
Ngap_PDUSessionResourceSetupRequestTransferIEs_t *qosFlowSetupRequestList =
nullptr;
qosFlowSetupRequestList =
(Ngap_PDUSessionResourceSetupRequestTransferIEs_t*) calloc(
1, sizeof(Ngap_PDUSessionResourceSetupRequestTransferIEs_t));
qosFlowSetupRequestList->id =
Ngap_ProtocolIE_ID_id_QosFlowSetupRequestList;
qosFlowSetupRequestList->criticality = Ngap_Criticality_reject;
qosFlowSetupRequestList->value.present =
Ngap_PDUSessionResourceSetupRequestTransferIEs__value_PR_QosFlowSetupRequestList;
Ngap_QosFlowSetupRequestItem_t *ngap_QosFlowSetupRequestItem = nullptr;
ngap_QosFlowSetupRequestItem = (Ngap_QosFlowSetupRequestItem_t*) calloc(
1, sizeof(Ngap_QosFlowSetupRequestItem_t));
ngap_QosFlowSetupRequestItem->qosFlowIdentifier = (uint8_t) qos_flow.qfi
.qfi;
ngap_QosFlowSetupRequestItem->qosFlowLevelQosParameters.qosCharacteristics
.present = Ngap_QosCharacteristics_PR_nonDynamic5QI;
ngap_QosFlowSetupRequestItem->qosFlowLevelQosParameters.qosCharacteristics
.choice.nonDynamic5QI = (Ngap_NonDynamic5QIDescriptor_t*) (calloc(
1, sizeof(Ngap_NonDynamic5QIDescriptor_t)));
ngap_QosFlowSetupRequestItem->qosFlowLevelQosParameters.qosCharacteristics
.choice.nonDynamic5QI->fiveQI = (uint8_t) qos_flow.qfi.qfi;
ngap_QosFlowSetupRequestItem->qosFlowLevelQosParameters
.allocationAndRetentionPriority.priorityLevelARP = qos_flow
.qos_profile.arp.priority_level;
if (qos_flow.qos_profile.arp.preempt_cap.compare("NOT_PREEMPT") == 0) {
ngap_QosFlowSetupRequestItem->qosFlowLevelQosParameters
.allocationAndRetentionPriority.pre_emptionCapability =
Ngap_Pre_emptionCapability_shall_not_trigger_pre_emption;
} else {
ngap_QosFlowSetupRequestItem->qosFlowLevelQosParameters
.allocationAndRetentionPriority.pre_emptionCapability =
Ngap_Pre_emptionCapability_may_trigger_pre_emption;
}
if (qos_flow.qos_profile.arp.preempt_vuln.compare("NOT_PREEMPTABLE")
== 0) {
ngap_QosFlowSetupRequestItem->qosFlowLevelQosParameters
.allocationAndRetentionPriority.pre_emptionVulnerability =
Ngap_Pre_emptionVulnerability_not_pre_emptable;
} else {
ngap_QosFlowSetupRequestItem->qosFlowLevelQosParameters
.allocationAndRetentionPriority.pre_emptionVulnerability =
Ngap_Pre_emptionVulnerability_pre_emptable;
}
asn_set_empty(
&qosFlowSetupRequestList->value.choice.QosFlowSetupRequestList.list);
ASN_SEQUENCE_ADD(
&qosFlowSetupRequestList->value.choice.QosFlowSetupRequestList.list,
ngap_QosFlowSetupRequestItem);
ASN_SEQUENCE_ADD(&ngap_IEs->protocolIEs.list, qosFlowSetupRequestList);
Logger::smf_n2().info(
"QoS parameters: QFI %d, ARP priority level %d, qos_flow.qos_profile.arp.preempt_cap %s, qos_flow.qos_profile.arp.preempt_vuln %s",
qos_flow.qfi.qfi, qos_flow.qos_profile.arp.priority_level,
qos_flow.qos_profile.arp.preempt_cap.c_str(),
qos_flow.qos_profile.arp.preempt_vuln.c_str());
//encode
size_t buffer_size = BUF_LEN;
char *buffer = (char*) calloc(1, buffer_size);
ssize_t encoded_size = aper_encode_to_new_buffer(
&asn_DEF_Ngap_PDUSessionResourceSetupRequestTransfer, nullptr,
ngap_IEs, (void**) &buffer);
if (encoded_size < 0) {
Logger::smf_n2().warn(
"NGAP PDU Session Resource Setup Request Transfer encode failed (encode size %d)",
encoded_size);
result = false;
} else {
#if DEBUG_IS_ON
Logger::smf_n2().debug("N2 SM buffer data: ");
for (int i = 0; i < encoded_size; i++)
printf("%02x ", (char) buffer[i]);
printf(" (%d bytes)\n", (int) encoded_size);
#endif
std::string ngap_message((char*) buffer, encoded_size);
ngap_msg_str = ngap_message;
result = true;
}
//free memory
free_wrapper((void**) &pduSessionAggregateMaximumBitRate);
free_wrapper(
(void**) &upTransportLayerInformation->value.choice
.UPTransportLayerInformation.choice.gTPTunnel
->transportLayerAddress.buf);
free_wrapper(
(void**) &upTransportLayerInformation->value.choice
.UPTransportLayerInformation.choice.gTPTunnel->gTP_TEID.buf);
free_wrapper(
(void**) &upTransportLayerInformation->value.choice
.UPTransportLayerInformation.choice.gTPTunnel);
free_wrapper((void**) &upTransportLayerInformation);
free_wrapper((void**) &pduSessionType);
free_wrapper((void**) &qosFlowSetupRequestList);
free_wrapper(
(void**) &ngap_QosFlowSetupRequestItem->qosFlowLevelQosParameters
.qosCharacteristics.choice.nonDynamic5QI);
free_wrapper((void**) &ngap_QosFlowSetupRequestItem);
free_wrapper((void**) &ngap_IEs);
free_wrapper((void**) &buffer);
return result;
}
//------------------------------------------------------------------------------
bool smf_n2::create_n2_pdu_session_resource_setup_request_transfer(pdu_session_update_sm_context_response &sm_context_res,
n2_sm_info_type_e ngap_info_type,
std::string &ngap_msg_str) {
Logger::smf_n2().info("Create N2 SM Information, PDU Session Resource Setup Request Transfer");
bool result = false;
Ngap_PDUSessionResourceSetupRequestTransfer_t *ngap_IEs = nullptr;
ngap_IEs = (Ngap_PDUSessionResourceSetupRequestTransfer_t*) calloc(
1, sizeof(Ngap_PDUSessionResourceSetupRequestTransfer_t));
qos_flow_context_updated qos_flow = { };
//get default QoS value
std::map<uint8_t, qos_flow_context_updated> qos_flows = { };
sm_context_res.get_all_qos_flow_context_updateds(qos_flows);
for (std::map<uint8_t, qos_flow_context_updated>::iterator it =
qos_flows.begin(); it != qos_flows.end(); ++it)
Logger::smf_n2().debug("QoS Flow context to be updated QFI %d",
it->first);
if (qos_flows.empty()) {
free_wrapper((void**) &ngap_IEs);
return false;
}
//TODO: support only 1 qos flow
qos_flow = qos_flows.begin()->second;
Logger::smf_n2().debug(
"UL F-TEID, TEID " "0x%" PRIx32 ", IP Address %s",
qos_flow.ul_fteid.teid_gre_key,
conv::toString(qos_flow.ul_fteid.ipv4_address).c_str());
Logger::smf_n2().info(
"QoS parameters: QFI %d, Priority level %d, ARP priority level %d",
qos_flow.qfi.qfi, qos_flow.qos_profile.priority_level,
qos_flow.qos_profile.arp.priority_level);
//check the QoS Flow
if ((qos_flow.qfi.qfi < QOS_FLOW_IDENTIFIER_FIRST )
or (qos_flow.qfi.qfi > QOS_FLOW_IDENTIFIER_LAST )) {
//error
Logger::smf_n2().error("Incorrect QFI %d", qos_flow.qfi.qfi);
free_wrapper((void**) &ngap_IEs);
return false;
}
//PDUSessionAggregateMaximumBitRate
Ngap_PDUSessionResourceSetupRequestTransferIEs_t *pduSessionAggregateMaximumBitRate =
nullptr;
pduSessionAggregateMaximumBitRate =
(Ngap_PDUSessionResourceSetupRequestTransferIEs_t*) calloc(
1, sizeof(Ngap_PDUSessionResourceSetupRequestTransferIEs_t));
pduSessionAggregateMaximumBitRate->id =
Ngap_ProtocolIE_ID_id_PDUSessionAggregateMaximumBitRate;
pduSessionAggregateMaximumBitRate->criticality = Ngap_Criticality_reject;
pduSessionAggregateMaximumBitRate->value.present =
Ngap_PDUSessionResourceSetupRequestTransferIEs__value_PR_PDUSessionAggregateMaximumBitRate;
asn_set_empty(&ngap_IEs->protocolIEs.list);
//SessionAMBR
supi_t supi = sm_context_res.get_supi();
supi64_t supi64 = smf_supi_to_u64(supi);
std::shared_ptr<smf_context> sc = { };
if (smf_app_inst->is_supi_2_smf_context(supi64)) {
Logger::smf_n2().debug("Get SMF context with SUPI " SUPI_64_FMT "",
supi64);
sc = smf_app_inst->supi_2_smf_context(supi64);
sc.get()->get_session_ambr(
pduSessionAggregateMaximumBitRate->value.choice
.PDUSessionAggregateMaximumBitRate,
sm_context_res.get_snssai(), sm_context_res.get_dnn());
} else {
Logger::smf_n2().warn(
"SMF context with SUPI " SUPI_64_FMT " does not exist!", supi64);
free_wrapper((void**) &pduSessionAggregateMaximumBitRate);
return false;
}
ASN_SEQUENCE_ADD(&ngap_IEs->protocolIEs.list,
pduSessionAggregateMaximumBitRate);
//UPTransportLayerInformation
fteid_t ul_fteid = { };
ul_fteid.interface_type = qos_flow.ul_fteid.interface_type;
ul_fteid.v4 = qos_flow.ul_fteid.v4;
ul_fteid.teid_gre_key = htonl(qos_flow.ul_fteid.teid_gre_key);
ul_fteid.ipv4_address = qos_flow.ul_fteid.ipv4_address;
Ngap_PDUSessionResourceSetupRequestTransferIEs_t *upTransportLayerInformation =
nullptr;
upTransportLayerInformation =
(Ngap_PDUSessionResourceSetupRequestTransferIEs_t*) calloc(
1, sizeof(Ngap_PDUSessionResourceSetupRequestTransferIEs_t));
upTransportLayerInformation->id =
Ngap_ProtocolIE_ID_id_UL_NGU_UP_TNLInformation;
upTransportLayerInformation->criticality = Ngap_Criticality_reject;
upTransportLayerInformation->value.present =
Ngap_PDUSessionResourceSetupRequestTransferIEs__value_PR_UPTransportLayerInformation;
upTransportLayerInformation->value.choice.UPTransportLayerInformation
.present = Ngap_UPTransportLayerInformation_PR_gTPTunnel;
upTransportLayerInformation->value.choice.UPTransportLayerInformation
.choice.gTPTunnel = (Ngap_GTPTunnel_t*) calloc(
1, sizeof(Ngap_GTPTunnel_t));
upTransportLayerInformation->value.choice.UPTransportLayerInformation
.choice.gTPTunnel->transportLayerAddress.size = 4;
upTransportLayerInformation->value.choice.UPTransportLayerInformation
.choice.gTPTunnel->transportLayerAddress.buf = (uint8_t*) calloc(
4, sizeof(uint8_t));
memcpy(
upTransportLayerInformation->value.choice.UPTransportLayerInformation
.choice.gTPTunnel->transportLayerAddress.buf,
&ul_fteid.ipv4_address, 4);
upTransportLayerInformation->value.choice.UPTransportLayerInformation
.choice.gTPTunnel->transportLayerAddress.bits_unused = 0;
upTransportLayerInformation->value.choice.UPTransportLayerInformation
.choice.gTPTunnel->gTP_TEID.size = sizeof(struct in_addr);
upTransportLayerInformation->value.choice.UPTransportLayerInformation
.choice.gTPTunnel->gTP_TEID.buf = (uint8_t*) calloc(
sizeof(struct in_addr), sizeof(uint8_t));
memcpy(
upTransportLayerInformation->value.choice.UPTransportLayerInformation
.choice.gTPTunnel->gTP_TEID.buf,
&ul_fteid.teid_gre_key, sizeof(struct in_addr));
ASN_SEQUENCE_ADD(&ngap_IEs->protocolIEs.list,
upTransportLayerInformation);
//DataForwardingNotPossible
//TODO:
//PDUSessionType
Ngap_PDUSessionResourceSetupRequestTransferIEs_t *pduSessionType = nullptr;
pduSessionType =
(Ngap_PDUSessionResourceSetupRequestTransferIEs_t*) calloc(
1, sizeof(Ngap_PDUSessionResourceSetupRequestTransferIEs_t));
pduSessionType->id = Ngap_ProtocolIE_ID_id_PDUSessionType;
pduSessionType->criticality = Ngap_Criticality_reject;
pduSessionType->value.present =
Ngap_PDUSessionResourceSetupRequestTransferIEs__value_PR_PDUSessionType;
pduSessionType->value.choice.PDUSessionType = sm_context_res.get_pdu_session_type()
- 1; //TODO: dirty code, difference between Ngap_PDUSessionType_ipv4 vs pdu_session_type_e::PDU_SESSION_TYPE_E_IPV4 (TS 38.413 vs TS 24.501)
ASN_SEQUENCE_ADD(&ngap_IEs->protocolIEs.list, pduSessionType);
Logger::smf_n2().debug("PDU Session Type: %d ",
sm_context_res.get_pdu_session_type());
//SecurityIndication
//TODO: should get from UDM
// Ngap_PDUSessionResourceSetupRequestTransferIEs_t *securityIndication = nullptr;
// securityIndication = (Ngap_PDUSessionResourceSetupRequestTransferIEs_t *) calloc(1, sizeof(Ngap_PDUSessionResourceSetupRequestTransferIEs_t));
// securityIndication->value.choice.SecurityIndication.integrityProtectionIndication = Ngap_IntegrityProtectionIndication_not_needed;
// securityIndication->value.choice.SecurityIndication.confidentialityProtectionIndication = Ngap_ConfidentialityProtectionIndication_not_needed;
//NetworkInstance
//TODO:
//QosFlowSetupRequestList
Ngap_PDUSessionResourceSetupRequestTransferIEs_t *qosFlowSetupRequestList =
nullptr;
qosFlowSetupRequestList =
(Ngap_PDUSessionResourceSetupRequestTransferIEs_t*) calloc(
1, sizeof(Ngap_PDUSessionResourceSetupRequestTransferIEs_t));
qosFlowSetupRequestList->id =
Ngap_ProtocolIE_ID_id_QosFlowSetupRequestList;
qosFlowSetupRequestList->criticality = Ngap_Criticality_reject;
qosFlowSetupRequestList->value.present =
Ngap_PDUSessionResourceSetupRequestTransferIEs__value_PR_QosFlowSetupRequestList;
Ngap_QosFlowSetupRequestItem_t *ngap_QosFlowSetupRequestItem = nullptr;
ngap_QosFlowSetupRequestItem = (Ngap_QosFlowSetupRequestItem_t*) calloc(
1, sizeof(Ngap_QosFlowSetupRequestItem_t));
ngap_QosFlowSetupRequestItem->qosFlowIdentifier = (uint8_t) qos_flow.qfi
.qfi;
ngap_QosFlowSetupRequestItem->qosFlowLevelQosParameters.qosCharacteristics
.present = Ngap_QosCharacteristics_PR_nonDynamic5QI;
ngap_QosFlowSetupRequestItem->qosFlowLevelQosParameters.qosCharacteristics
.choice.nonDynamic5QI = (Ngap_NonDynamic5QIDescriptor_t*) (calloc(
1, sizeof(Ngap_NonDynamic5QIDescriptor_t)));
ngap_QosFlowSetupRequestItem->qosFlowLevelQosParameters.qosCharacteristics
.choice.nonDynamic5QI->fiveQI = (uint8_t) qos_flow.qfi.qfi;
ngap_QosFlowSetupRequestItem->qosFlowLevelQosParameters
.allocationAndRetentionPriority.priorityLevelARP = qos_flow
.qos_profile.arp.priority_level;
if (qos_flow.qos_profile.arp.preempt_cap.compare("NOT_PREEMPT") == 0) {
ngap_QosFlowSetupRequestItem->qosFlowLevelQosParameters
.allocationAndRetentionPriority.pre_emptionCapability =
Ngap_Pre_emptionCapability_shall_not_trigger_pre_emption;
} else {
ngap_QosFlowSetupRequestItem->qosFlowLevelQosParameters
.allocationAndRetentionPriority.pre_emptionCapability =
Ngap_Pre_emptionCapability_may_trigger_pre_emption;
}
if (qos_flow.qos_profile.arp.preempt_vuln.compare("NOT_PREEMPTABLE")
== 0) {
ngap_QosFlowSetupRequestItem->qosFlowLevelQosParameters
.allocationAndRetentionPriority.pre_emptionVulnerability =
Ngap_Pre_emptionVulnerability_not_pre_emptable;
} else {
ngap_QosFlowSetupRequestItem->qosFlowLevelQosParameters
.allocationAndRetentionPriority.pre_emptionVulnerability =
Ngap_Pre_emptionVulnerability_pre_emptable;
}
asn_set_empty(
&qosFlowSetupRequestList->value.choice.QosFlowSetupRequestList.list);
ASN_SEQUENCE_ADD(
&qosFlowSetupRequestList->value.choice.QosFlowSetupRequestList.list,
ngap_QosFlowSetupRequestItem);
ASN_SEQUENCE_ADD(&ngap_IEs->protocolIEs.list, qosFlowSetupRequestList);
Logger::smf_n2().info(
"QoS parameters: QFI %d, ARP priority level %d, qos_flow.qos_profile.arp.preempt_cap %s, qos_flow.qos_profile.arp.preempt_vuln %s",
qos_flow.qfi.qfi, qos_flow.qos_profile.arp.priority_level,
qos_flow.qos_profile.arp.preempt_cap.c_str(),
qos_flow.qos_profile.arp.preempt_vuln.c_str());
//encode
size_t buffer_size = BUF_LEN;
char *buffer = (char*) calloc(1, buffer_size);
ssize_t encoded_size = aper_encode_to_new_buffer(
&asn_DEF_Ngap_PDUSessionResourceSetupRequestTransfer, nullptr,
ngap_IEs, (void**) &buffer);
if (encoded_size < 0) {
Logger::smf_n2().warn(
"NGAP PDU Session Resource Setup Request Transfer encode failed (encode size %d)",
encoded_size);
result = false;
} else {
#if DEBUG_IS_ON
Logger::smf_n2().debug("N2 SM buffer data: ");
for (int i = 0; i < encoded_size; i++)
printf("%02x ", (char) buffer[i]);
printf(" (%d bytes)\n", (int) encoded_size);
#endif
std::string ngap_message((char*) buffer, encoded_size);
ngap_msg_str = ngap_message;
result = true;
}
//free memory
free_wrapper((void**) &pduSessionAggregateMaximumBitRate);
free_wrapper(
(void**) &upTransportLayerInformation->value.choice
.UPTransportLayerInformation.choice.gTPTunnel
->transportLayerAddress.buf);
free_wrapper(
(void**) &upTransportLayerInformation->value.choice
.UPTransportLayerInformation.choice.gTPTunnel->gTP_TEID.buf);
free_wrapper(
(void**) &upTransportLayerInformation->value.choice
.UPTransportLayerInformation.choice.gTPTunnel);
free_wrapper((void**) &upTransportLayerInformation);
free_wrapper((void**) &pduSessionType);
free_wrapper((void**) &qosFlowSetupRequestList);
free_wrapper(
(void**) &ngap_QosFlowSetupRequestItem->qosFlowLevelQosParameters
.qosCharacteristics.choice.nonDynamic5QI);
free_wrapper((void**) &ngap_QosFlowSetupRequestItem);
free_wrapper((void**) &ngap_IEs);
free_wrapper((void**) &buffer);
return result;
}
//------------------------------------------------------------------------------
bool smf_n2::create_n2_pdu_session_resource_modify_request_transfer(pdu_session_update_sm_context_response &sm_context_res,
n2_sm_info_type_e ngap_info_type,
std::string &ngap_msg_str) {
Logger::smf_n2().debug("Create N2 SM Information: NGAP PDU Session Resource Modify Request Transfer");
bool result = false;
//get default QoS info
std::map<uint8_t, qos_flow_context_updated> qos_flows = { };
sm_context_res.get_all_qos_flow_context_updateds(qos_flows);
for (std::map<uint8_t, qos_flow_context_updated>::iterator it = qos_flows
.begin(); it != qos_flows.end(); ++it)
Logger::smf_n2().debug("QoS flow context to be updated with QFI %d",
it->first);
//TODO: support only 1 qos flow
qos_flow_context_updated qos_flow = qos_flows.begin()->second;
//check the QoS Flow
if ((qos_flow.qfi.qfi < QOS_FLOW_IDENTIFIER_FIRST )
or (qos_flow.qfi.qfi > QOS_FLOW_IDENTIFIER_LAST )) {
//error
Logger::smf_n2().error("Incorrect QFI %d", qos_flow.qfi.qfi);
return false;
}
Logger::smf_n2().debug(
"QoS Flow, UL F-TEID ID " "0x%" PRIx32 ", IP Address %s ",
qos_flow.ul_fteid.teid_gre_key,
conv::toString(qos_flow.ul_fteid.ipv4_address).c_str());
Logger::smf_n2().debug(
"QoS Flow, DL F-TEID ID" "0x%" PRIx32 ", IP Address %s",
qos_flow.dl_fteid.teid_gre_key,
conv::toString(qos_flow.dl_fteid.ipv4_address).c_str());
Ngap_PDUSessionResourceModifyRequestTransfer_t *ngap_IEs = nullptr;
ngap_IEs = (Ngap_PDUSessionResourceModifyRequestTransfer_t*) calloc(
1, sizeof(Ngap_PDUSessionResourceModifyRequestTransfer_t));
//PDUSessionAggregateMaximumBitRate
Ngap_PDUSessionResourceModifyRequestTransferIEs_t *pduSessionAggregateMaximumBitRate =
nullptr;
pduSessionAggregateMaximumBitRate =
(Ngap_PDUSessionResourceModifyRequestTransferIEs_t*) calloc(
1, sizeof(Ngap_PDUSessionResourceModifyRequestTransferIEs_t));
pduSessionAggregateMaximumBitRate->id =
Ngap_ProtocolIE_ID_id_PDUSessionAggregateMaximumBitRate;
pduSessionAggregateMaximumBitRate->criticality = Ngap_Criticality_reject;
pduSessionAggregateMaximumBitRate->value.present =
Ngap_PDUSessionResourceModifyRequestTransferIEs__value_PR_PDUSessionAggregateMaximumBitRate;
supi_t supi = sm_context_res.get_supi();
supi64_t supi64 = smf_supi_to_u64(supi);
std::shared_ptr<smf_context> sc = { };
if (smf_app_inst->is_supi_2_smf_context(supi64)) {
Logger::smf_n2().debug("Get SMF context with SUPI " SUPI_64_FMT "",
supi64);
sc = smf_app_inst->supi_2_smf_context(supi64);
sc.get()->get_session_ambr(
pduSessionAggregateMaximumBitRate->value.choice
.PDUSessionAggregateMaximumBitRate,
sm_context_res.get_snssai(), sm_context_res.get_dnn());
} else {
Logger::smf_n2().warn(
"SMF context with SUPI " SUPI_64_FMT " does not exist!", supi64);
//TODO:
}
ASN_SEQUENCE_ADD(&ngap_IEs->protocolIEs.list,
pduSessionAggregateMaximumBitRate);
//Ngap_UL_NGU_UP_TNLModifyList_t (included if the PDU Session modification was requested by the UE for a
//PDU Session that has no established User Plane resources)
fteid_t ul_fteid = { };
ul_fteid.interface_type = qos_flow.ul_fteid.interface_type;
ul_fteid.v4 = qos_flow.ul_fteid.v4;
ul_fteid.teid_gre_key = htonl(qos_flow.ul_fteid.teid_gre_key);
ul_fteid.ipv4_address = qos_flow.ul_fteid.ipv4_address;
fteid_t dl_fteid = { };
dl_fteid.interface_type = qos_flow.dl_fteid.interface_type;
dl_fteid.v4 = qos_flow.dl_fteid.v4;
dl_fteid.teid_gre_key = htonl(qos_flow.dl_fteid.teid_gre_key);
dl_fteid.ipv4_address = qos_flow.dl_fteid.ipv4_address;
Ngap_PDUSessionResourceModifyRequestTransferIEs_t *ul_NGU_UP_TNLModifyList =
nullptr;
ul_NGU_UP_TNLModifyList =
(Ngap_PDUSessionResourceModifyRequestTransferIEs_t*) calloc(
1, sizeof(Ngap_PDUSessionResourceModifyRequestTransferIEs_t));
ul_NGU_UP_TNLModifyList->id =
Ngap_ProtocolIE_ID_id_UL_NGU_UP_TNLModifyList;
ul_NGU_UP_TNLModifyList->criticality = Ngap_Criticality_reject;
ul_NGU_UP_TNLModifyList->value.present =
Ngap_PDUSessionResourceModifyRequestTransferIEs__value_PR_UL_NGU_UP_TNLModifyList;
Ngap_UL_NGU_UP_TNLModifyItem_t *ngap_UL_NGU_UP_TNLModifyItem = nullptr;
ngap_UL_NGU_UP_TNLModifyItem = (Ngap_UL_NGU_UP_TNLModifyItem_t*) calloc(
1, sizeof(Ngap_UL_NGU_UP_TNLModifyItem_t));
ngap_UL_NGU_UP_TNLModifyItem->uL_NGU_UP_TNLInformation.present =
Ngap_UPTransportLayerInformation_PR_gTPTunnel;
ngap_UL_NGU_UP_TNLModifyItem->uL_NGU_UP_TNLInformation.choice.gTPTunnel =
(Ngap_GTPTunnel_t*) calloc(1, sizeof(Ngap_GTPTunnel_t));
ngap_UL_NGU_UP_TNLModifyItem->uL_NGU_UP_TNLInformation.choice.gTPTunnel
->transportLayerAddress.buf = (uint8_t*) calloc(4, sizeof(uint8_t));
memcpy(
ngap_UL_NGU_UP_TNLModifyItem->uL_NGU_UP_TNLInformation.choice
.gTPTunnel->transportLayerAddress.buf,
&ul_fteid.ipv4_address, 4);
ngap_UL_NGU_UP_TNLModifyItem->uL_NGU_UP_TNLInformation.choice.gTPTunnel
->transportLayerAddress.size = 4;
ngap_UL_NGU_UP_TNLModifyItem->uL_NGU_UP_TNLInformation.choice.gTPTunnel
->transportLayerAddress.bits_unused = 0;
ngap_UL_NGU_UP_TNLModifyItem->uL_NGU_UP_TNLInformation.choice.gTPTunnel
->gTP_TEID.size = sizeof(struct in_addr);
ngap_UL_NGU_UP_TNLModifyItem->uL_NGU_UP_TNLInformation.choice.gTPTunnel
->gTP_TEID.buf = (uint8_t*) calloc(sizeof(struct in_addr),
sizeof(uint8_t));
memcpy(
ngap_UL_NGU_UP_TNLModifyItem->uL_NGU_UP_TNLInformation.choice
.gTPTunnel->gTP_TEID.buf,
&ul_fteid.teid_gre_key, sizeof(struct in_addr));
ngap_UL_NGU_UP_TNLModifyItem->dL_NGU_UP_TNLInformation.present =
Ngap_UPTransportLayerInformation_PR_gTPTunnel;
ngap_UL_NGU_UP_TNLModifyItem->dL_NGU_UP_TNLInformation.choice.gTPTunnel =
(Ngap_GTPTunnel_t*) calloc(1, sizeof(Ngap_GTPTunnel_t));
ngap_UL_NGU_UP_TNLModifyItem->dL_NGU_UP_TNLInformation.choice.gTPTunnel
->transportLayerAddress.buf = (uint8_t*) calloc(4, sizeof(uint8_t));
memcpy(
ngap_UL_NGU_UP_TNLModifyItem->dL_NGU_UP_TNLInformation.choice
.gTPTunnel->transportLayerAddress.buf,
&dl_fteid.ipv4_address, 4);
ngap_UL_NGU_UP_TNLModifyItem->dL_NGU_UP_TNLInformation.choice.gTPTunnel
->transportLayerAddress.size = 4;
ngap_UL_NGU_UP_TNLModifyItem->dL_NGU_UP_TNLInformation.choice.gTPTunnel
->transportLayerAddress.bits_unused = 0;
ngap_UL_NGU_UP_TNLModifyItem->dL_NGU_UP_TNLInformation.choice.gTPTunnel
->gTP_TEID.size = sizeof(struct in_addr);
ngap_UL_NGU_UP_TNLModifyItem->dL_NGU_UP_TNLInformation.choice.gTPTunnel
->gTP_TEID.buf = (uint8_t*) calloc(sizeof(struct in_addr),
sizeof(uint8_t));
memcpy(
ngap_UL_NGU_UP_TNLModifyItem->dL_NGU_UP_TNLInformation.choice
.gTPTunnel->gTP_TEID.buf,
&dl_fteid.teid_gre_key, 4);
ASN_SEQUENCE_ADD(
&ul_NGU_UP_TNLModifyList->value.choice.UL_NGU_UP_TNLModifyList.list,
ngap_UL_NGU_UP_TNLModifyItem);
ASN_SEQUENCE_ADD(&ngap_IEs->protocolIEs.list, ul_NGU_UP_TNLModifyList);
//Ngap_NetworkInstance_t
//TODO
//Ngap_QosFlowAddOrModifyRequestList_t
//TODO: to be completed
Ngap_PDUSessionResourceModifyRequestTransferIEs_t *qosFlowAddOrModifyRequestList =
nullptr;
qosFlowAddOrModifyRequestList =
(Ngap_PDUSessionResourceModifyRequestTransferIEs_t*) calloc(
1, sizeof(Ngap_PDUSessionResourceModifyRequestTransferIEs_t));
qosFlowAddOrModifyRequestList->id =
Ngap_ProtocolIE_ID_id_QosFlowAddOrModifyRequestList;
qosFlowAddOrModifyRequestList->criticality = Ngap_Criticality_reject;
qosFlowAddOrModifyRequestList->value.present =
Ngap_PDUSessionResourceModifyRequestTransferIEs__value_PR_QosFlowAddOrModifyRequestList;
Ngap_QosFlowAddOrModifyRequestItem *ngap_QosFlowAddOrModifyRequestItem =
nullptr;
ngap_QosFlowAddOrModifyRequestItem =
(Ngap_QosFlowAddOrModifyRequestItem*) calloc(
1, sizeof(Ngap_QosFlowAddOrModifyRequestItem));
ngap_QosFlowAddOrModifyRequestItem->qosFlowIdentifier = qos_flow.qfi.qfi;
ngap_QosFlowAddOrModifyRequestItem->qosFlowLevelQosParameters =
(struct Ngap_QosFlowLevelQosParameters*) calloc(
1, sizeof(struct Ngap_QosFlowLevelQosParameters));
ngap_QosFlowAddOrModifyRequestItem->qosFlowLevelQosParameters
->qosCharacteristics.present =
Ngap_QosCharacteristics_PR_nonDynamic5QI;
ngap_QosFlowAddOrModifyRequestItem->qosFlowLevelQosParameters
->qosCharacteristics.choice.nonDynamic5QI =
(Ngap_NonDynamic5QIDescriptor_t*) (calloc(
1, sizeof(Ngap_NonDynamic5QIDescriptor_t)));
ngap_QosFlowAddOrModifyRequestItem->qosFlowLevelQosParameters
->qosCharacteristics.choice.nonDynamic5QI->fiveQI = qos_flow.qfi.qfi;
ngap_QosFlowAddOrModifyRequestItem->qosFlowLevelQosParameters
->allocationAndRetentionPriority.priorityLevelARP = qos_flow
.qos_profile.priority_level;
if (qos_flow.qos_profile.arp.preempt_cap.compare("NOT_PREEMPT") == 0) {
ngap_QosFlowAddOrModifyRequestItem->qosFlowLevelQosParameters
->allocationAndRetentionPriority.pre_emptionCapability =
Ngap_Pre_emptionCapability_shall_not_trigger_pre_emption;
} else {
ngap_QosFlowAddOrModifyRequestItem->qosFlowLevelQosParameters
->allocationAndRetentionPriority.pre_emptionCapability =
Ngap_Pre_emptionCapability_may_trigger_pre_emption;
}
if (qos_flow.qos_profile.arp.preempt_vuln.compare("NOT_PREEMPTABLE")
== 0) {
ngap_QosFlowAddOrModifyRequestItem->qosFlowLevelQosParameters
->allocationAndRetentionPriority.pre_emptionVulnerability =
Ngap_Pre_emptionVulnerability_not_pre_emptable;
} else {
ngap_QosFlowAddOrModifyRequestItem->qosFlowLevelQosParameters
->allocationAndRetentionPriority.pre_emptionVulnerability =
Ngap_Pre_emptionVulnerability_pre_emptable;
}
ASN_SEQUENCE_ADD(
&qosFlowAddOrModifyRequestList->value.choice
.QosFlowAddOrModifyRequestList.list,
ngap_QosFlowAddOrModifyRequestItem);
//Ngap_E_RAB_ID_t *e_RAB_ID; //optional
ASN_SEQUENCE_ADD(&ngap_IEs->protocolIEs.list,
qosFlowAddOrModifyRequestList);
//Ngap_QosFlowList_t - QoS to release list??
//TODO
//Ngap_UPTransportLayerInformation_t
//TODO
//encode
size_t buffer_size = BUF_LEN;
char *buffer = (char*) calloc(1, buffer_size);
ssize_t encoded_size = aper_encode_to_new_buffer(
&asn_DEF_Ngap_PDUSessionResourceModifyRequestTransfer, nullptr,
ngap_IEs, (void**) &buffer);
if (encoded_size < 0) {
Logger::smf_n2().warn(
"NGAP PDU Session Resource Modify Request Transfer encode failed (encoded size %d)",
encoded_size);
result = false;
} else {
#if DEBUG_IS_ON
Logger::smf_n2().debug("N2 SM buffer data: ");
for (int i = 0; i < encoded_size; i++)
printf("%02x ", (char) buffer[i]);
printf(" (%d bytes)\n", (int) encoded_size);
#endif
std::string ngap_message((char*) buffer, encoded_size);
ngap_msg_str = ngap_message;
result = true;
}
//free memory
free_wrapper((void**) &pduSessionAggregateMaximumBitRate);
free_wrapper(
(void**) &ngap_UL_NGU_UP_TNLModifyItem->uL_NGU_UP_TNLInformation
.choice.gTPTunnel->transportLayerAddress.buf);
free_wrapper(
(void**) &ngap_UL_NGU_UP_TNLModifyItem->uL_NGU_UP_TNLInformation
.choice.gTPTunnel->gTP_TEID.buf);
free_wrapper(
(void**) &ngap_UL_NGU_UP_TNLModifyItem->dL_NGU_UP_TNLInformation
.choice.gTPTunnel->transportLayerAddress.buf);
free_wrapper(
(void**) &ngap_UL_NGU_UP_TNLModifyItem->dL_NGU_UP_TNLInformation
.choice.gTPTunnel->gTP_TEID.buf);
free_wrapper((void**) &ngap_UL_NGU_UP_TNLModifyItem);
free_wrapper((void**) &ul_NGU_UP_TNLModifyList);
free_wrapper(
(void**) &ngap_QosFlowAddOrModifyRequestItem
->qosFlowLevelQosParameters->qosCharacteristics.choice
.nonDynamic5QI);
free_wrapper(
(void**) &ngap_QosFlowAddOrModifyRequestItem
->qosFlowLevelQosParameters);
free_wrapper((void**) &ngap_QosFlowAddOrModifyRequestItem);
free_wrapper((void**) &qosFlowAddOrModifyRequestList);
free_wrapper((void**) &ngap_IEs);
free_wrapper((void**) &buffer);
return result;
}
//------------------------------------------------------------------------------
bool smf_n2::create_n2_pdu_session_resource_release_command_transfer(pdu_session_update_sm_context_response &sm_context_res,
n2_sm_info_type_e ngap_info_type,
std::string &ngap_msg_str) {
Logger::smf_n2().debug("Create N2 SM Information: NGAP PDU Session Resource Release Command Transfer IE");
bool result = false;
Ngap_PDUSessionResourceReleaseCommandTransfer_t *ngap_resource_release_command_transfer =
nullptr;
ngap_resource_release_command_transfer =
(Ngap_PDUSessionResourceReleaseCommandTransfer_t*) calloc(
1, sizeof(Ngap_PDUSessionResourceReleaseCommandTransfer_t));
//TODO: To be completed, here's an example
/*
typedef struct Ngap_Cause {
Ngap_Cause_PR present;
union Ngap_Cause_u {
Ngap_CauseRadioNetwork_t radioNetwork;
Ngap_CauseTransport_t transport;
Ngap_CauseNas_t nas;
Ngap_CauseProtocol_t protocol;
Ngap_CauseMisc_t misc;
struct Ngap_ProtocolIE_SingleContainer *choice_Extensions;
} choice;
asn_struct_ctx_t _asn_ctx;
} Ngap_Cause_t;
*/
ngap_resource_release_command_transfer->cause.present =
Ngap_Cause_PR_radioNetwork;
ngap_resource_release_command_transfer->cause.choice.radioNetwork = 1;
//encode
size_t buffer_size = BUF_LEN;
char *buffer = (char*) calloc(1, buffer_size);
ssize_t encoded_size = aper_encode_to_new_buffer(
&asn_DEF_Ngap_PDUSessionResourceReleaseCommandTransfer, nullptr,
ngap_resource_release_command_transfer, (void**) &buffer);
if (encoded_size < 0) {
Logger::smf_n2().warn(
"NGAP PDU Session Release Command encode failed (encoded size %d)",
encoded_size);
result = false;
} else {
#if DEBUG_IS_ON
Logger::smf_n2().debug("N2 SM buffer data: ");
for (int i = 0; i < encoded_size; i++)
printf("%02x ", (char) buffer[i]);
Logger::smf_n2().debug(" (%d bytes) \n", encoded_size);
#endif
std::string ngap_message((char*) buffer, encoded_size);
ngap_msg_str = ngap_message;
result = true;
}
//free memory
free_wrapper((void**) &ngap_resource_release_command_transfer);
free_wrapper((void**) &buffer);
return result;
}
//------------------------------------------------------------------------------
bool smf_n2::create_n2_pdu_session_resource_setup_request_transfer(pdu_session_report_response &msg,
n2_sm_info_type_e ngap_info_type,
std::string &ngap_msg_str) {
Logger::smf_n2().debug("Create N2 SM Information: NGAP PDU Session Resource Setup Request Transfer IE");
//TODO:
return true;
}
//------------------------------------------------------------------------------
bool smf_n2::create_n2_pdu_session_resource_modify_request_transfer(pdu_session_modification_network_requested &msg,
n2_sm_info_type_e ngap_info_type,
std::string &ngap_msg_str) {
Logger::smf_n2().debug("Create N2 SM Information: NGAP PDU Session Resource Modify Request Transfer IE");
//TODO:
return true;
}
//------------------------------------------------------------------------------
bool smf_n2::create_n2_pdu_session_resource_modify_response_transfer(pdu_session_update_sm_context_response &sm_context_res, n2_sm_info_type_e ngap_info_type,
std::string &ngap_msg_str) {
//PDU Session Resource Modify Response Transfer IE for testing purpose
Logger::smf_n2().debug("Create N2 SM Information: NGAP PDU Session Resource Modify Response Transfer IE");
bool result = false;
//struct Ngap_UPTransportLayerInformation *dL_NGU_UP_TNLInformation; /* OPTIONAL */
//struct Ngap_UPTransportLayerInformation *uL_NGU_UP_TNLInformation; /* OPTIONAL */
//struct Ngap_QosFlowAddOrModifyResponseList *qosFlowAddOrModifyResponseList; /* OPTIONAL */
//struct Ngap_QosFlowPerTNLInformationList *additionalDLQosFlowPerTNLInformation; /* OPTIONAL */
// struct Ngap_QosFlowListWithCause *qosFlowFailedToAddOrModifyList; /* OPTIONAL */
Ngap_PDUSessionResourceModifyResponseTransfer_t *ngap_resource_response_transfer =
nullptr;
ngap_resource_response_transfer =
(Ngap_PDUSessionResourceModifyResponseTransfer_t*) calloc(
1, sizeof(Ngap_PDUSessionResourceModifyResponseTransfer_t));
ngap_resource_response_transfer->dL_NGU_UP_TNLInformation =
(Ngap_UPTransportLayerInformation*) calloc(
1, sizeof(Ngap_UPTransportLayerInformation));
ngap_resource_response_transfer->dL_NGU_UP_TNLInformation->present =
Ngap_UPTransportLayerInformation_PR_gTPTunnel;
ngap_resource_response_transfer->dL_NGU_UP_TNLInformation->choice
.gTPTunnel = (Ngap_GTPTunnel_t*) calloc(1, sizeof(Ngap_GTPTunnel_t));
ngap_resource_response_transfer->dL_NGU_UP_TNLInformation->choice
.gTPTunnel->transportLayerAddress.size = 4;
ngap_resource_response_transfer->dL_NGU_UP_TNLInformation->choice
.gTPTunnel->transportLayerAddress.buf = (uint8_t*) calloc(
4, sizeof(uint8_t));
ngap_resource_response_transfer->dL_NGU_UP_TNLInformation->choice
.gTPTunnel->transportLayerAddress.buf[0] = 0xc0;
ngap_resource_response_transfer->dL_NGU_UP_TNLInformation->choice
.gTPTunnel->transportLayerAddress.buf[1] = 0xa8;
ngap_resource_response_transfer->dL_NGU_UP_TNLInformation->choice
.gTPTunnel->transportLayerAddress.buf[2] = 0xf8;
ngap_resource_response_transfer->dL_NGU_UP_TNLInformation->choice
.gTPTunnel->transportLayerAddress.buf[3] = 0x9f;
ngap_resource_response_transfer->dL_NGU_UP_TNLInformation->choice
.gTPTunnel->transportLayerAddress.bits_unused = 0;
ngap_resource_response_transfer->dL_NGU_UP_TNLInformation->choice
.gTPTunnel->gTP_TEID.size = 4;
ngap_resource_response_transfer->dL_NGU_UP_TNLInformation->choice
.gTPTunnel->gTP_TEID.buf = (uint8_t*) calloc(4, sizeof(uint8_t));
ngap_resource_response_transfer->dL_NGU_UP_TNLInformation->choice
.gTPTunnel->gTP_TEID.buf[0] = 0x00;
ngap_resource_response_transfer->dL_NGU_UP_TNLInformation->choice
.gTPTunnel->gTP_TEID.buf[1] = 0x00;
ngap_resource_response_transfer->dL_NGU_UP_TNLInformation->choice
.gTPTunnel->gTP_TEID.buf[2] = 0x00;
ngap_resource_response_transfer->dL_NGU_UP_TNLInformation->choice
.gTPTunnel->gTP_TEID.buf[3] = 0x01;
ngap_resource_response_transfer->qosFlowAddOrModifyResponseList =
(Ngap_QosFlowAddOrModifyResponseList_t*) calloc(
1, sizeof(Ngap_QosFlowAddOrModifyResponseList_t));
Ngap_QosFlowAddOrModifyResponseItem *qosFlowAddOrModifyResponseItem =
nullptr;
qosFlowAddOrModifyResponseItem =
(Ngap_QosFlowAddOrModifyResponseItem*) calloc(
1, sizeof(Ngap_QosFlowAddOrModifyResponseItem));
qosFlowAddOrModifyResponseItem->qosFlowIdentifier = 60;
ASN_SEQUENCE_ADD(
&ngap_resource_response_transfer->qosFlowAddOrModifyResponseList->list,
qosFlowAddOrModifyResponseItem);
//encode
size_t buffer_size = BUF_LEN;
char *buffer = (char*) calloc(1, buffer_size);
ssize_t encoded_size = aper_encode_to_new_buffer(
&asn_DEF_Ngap_PDUSessionResourceModifyResponseTransfer, nullptr,
ngap_resource_response_transfer, (void**) &buffer);
if (encoded_size < 0) {
Logger::smf_n2().warn(
" NGAP PDU Session Resource Modify Response Transfer encode failed (encoded size %d)",
encoded_size);
result = false;
} else {
#if DEBUG_IS_ON
Logger::smf_n2().debug("N2 SM buffer data: ");
for (int i = 0; i < encoded_size; i++)
printf("%02x ", (char) buffer[i]);
Logger::smf_n2().debug(" (%d bytes) \n", encoded_size);
#endif
std::string ngap_message((char*) buffer, encoded_size);
ngap_msg_str = ngap_message;
result = true;
}
//free memory
free_wrapper(
(void**) &ngap_resource_response_transfer->dL_NGU_UP_TNLInformation
->choice.gTPTunnel->transportLayerAddress.buf);
free_wrapper(
(void**) &ngap_resource_response_transfer->dL_NGU_UP_TNLInformation
->choice.gTPTunnel->gTP_TEID.buf);
free_wrapper(
(void**) &ngap_resource_response_transfer->dL_NGU_UP_TNLInformation
->choice.gTPTunnel);
free_wrapper((void**) &qosFlowAddOrModifyResponseItem);
free_wrapper(
(void**) &ngap_resource_response_transfer
->qosFlowAddOrModifyResponseList);
free_wrapper((void**) &ngap_resource_response_transfer);
free_wrapper((void**) &buffer);
return result;
}
//------------------------------------------------------------------------------
/*
bool smf_n2::create_n2_pdu_session_resource_modify_response_transfer(pdu_session_modification_network_requested &msg,
n2_sm_info_type_e ngap_info_type,
std::string &ngap_msg_str) {
//TODO:
}
*/
//---------------------------------------------------------------------------------------------
int smf_n2::decode_n2_sm_information(
std::shared_ptr<Ngap_PDUSessionResourceSetupResponseTransfer_t> &ngap_IE,
const std::string &n2_sm_info) {
Logger::smf_n2().info(
"Decode NGAP message (PDUSessionResourceSetupResponseTransfer) from N2 SM Information");
unsigned int data_len = n2_sm_info.length();
unsigned char *data = (unsigned char*) malloc(data_len + 1);
memset(data, 0, data_len + 1);
memcpy((void*) data, (void*) n2_sm_info.c_str(), data_len);
#if DEBUG_IS_ON
printf("Content: ");
for (int i = 0; i < data_len; i++)
printf(" %02x ", data[i]);
printf("\n");
#endif
//PDUSessionResourceSetupResponseTransfer
asn_dec_rval_t rc = asn_decode(
nullptr, ATS_ALIGNED_CANONICAL_PER,
&asn_DEF_Ngap_PDUSessionResourceSetupResponseTransfer, (void**) &ngap_IE,
(void*) data, data_len);
//free memory
free_wrapper((void**) &data);
if (rc.code != RC_OK) {
Logger::smf_n2().warn("asn_decode failed with code %d", rc.code);
return RETURNerror ;
}
return RETURNok ;
}
//---------------------------------------------------------------------------------------------
int smf_n2::decode_n2_sm_information(
std::shared_ptr<Ngap_PDUSessionResourceModifyResponseTransfer_t> &ngap_IE,
const std::string &n2_sm_info) {
Logger::smf_n2().info(
"Decode NGAP message (Ngap_PDUSessionResourceModifyResponseTransfer) from N2 SM Information");
unsigned int data_len = n2_sm_info.length();
unsigned char *data = (unsigned char*) malloc(data_len + 1);
memset(data, 0, data_len + 1);
memcpy((void*) data, (void*) n2_sm_info.c_str(), data_len);
//Ngap_PDUSessionResourceModifyResponseTransfer
asn_dec_rval_t rc = asn_decode(
nullptr, ATS_ALIGNED_CANONICAL_PER,
&asn_DEF_Ngap_PDUSessionResourceModifyResponseTransfer, (void**) &ngap_IE,
(void*) data, data_len);
//free memory
free_wrapper((void**) &data);
if (rc.code != RC_OK) {
Logger::smf_n2().warn("asn_decode failed with code %d", rc.code);
return RETURNerror ;
}
return RETURNok ;
}
//---------------------------------------------------------------------------------------------
int smf_n2::decode_n2_sm_information(
std::shared_ptr<Ngap_PDUSessionResourceReleaseResponseTransfer_t> &ngap_IE,
const std::string &n2_sm_info) {
Logger::smf_n2().info(
"Decode NGAP message (Ngap_PDUSessionResourceReleaseResponseTransfer) from N2 SM Information");
unsigned int data_len = n2_sm_info.length();
unsigned char *data = (unsigned char*) malloc(data_len + 1);
memset(data, 0, data_len + 1);
memcpy((void*) data, (void*) n2_sm_info.c_str(), data_len);
//Ngap_PDUSessionResourceModifyResponseTransfer
asn_dec_rval_t rc = asn_decode(
nullptr, ATS_ALIGNED_CANONICAL_PER,
&asn_DEF_Ngap_PDUSessionResourceReleaseResponseTransfer,
(void**) &ngap_IE, (void*) data, data_len);
//free memory
free_wrapper((void**) &data);
if (rc.code != RC_OK) {
Logger::smf_n2().warn("asn_decode failed with code %d", rc.code);
return RETURNerror ;
}
return RETURNok ;
}
//---------------------------------------------------------------------------------------------
int smf_n2::decode_n2_sm_information(
std::shared_ptr<Ngap_PDUSessionResourceSetupUnsuccessfulTransfer_t> &ngap_IE,
const std::string &n2_sm_info) {
Logger::smf_n2().info(
"Decode NGAP message (Ngap_PDUSessionResourceSetupUnsuccessfulTransfer) from N2 SM Information");
unsigned int data_len = n2_sm_info.length();
unsigned char *data = (unsigned char*) malloc(data_len + 1);
memset(data, 0, data_len + 1);
memcpy((void*) data, (void*) n2_sm_info.c_str(), data_len);
//Ngap_PDUSessionResourceSetupUnsuccessfulTransfer
asn_dec_rval_t rc = asn_decode(
nullptr, ATS_ALIGNED_CANONICAL_PER,
&asn_DEF_Ngap_PDUSessionResourceSetupUnsuccessfulTransfer,
(void**) &ngap_IE, (void*) data, data_len);
//free memory
free_wrapper((void**) &data);
if (rc.code != RC_OK) {
Logger::smf_n2().warn("asn_decode failed with code %d", rc.code);
return RETURNerror ;
}
return RETURNok ;
}
...@@ -19,7 +19,7 @@ ...@@ -19,7 +19,7 @@
* contact@openairinterface.org * contact@openairinterface.org
*/ */
/*! \file smf_n1_n2.hpp /*! \file smf_n2.hpp
* \brief * \brief
\author Tien-Thinh NGUYEN \author Tien-Thinh NGUYEN
\company Eurecom \company Eurecom
...@@ -27,24 +27,12 @@ ...@@ -27,24 +27,12 @@
\email: tien-thinh.nguyen@eurecom.fr \email: tien-thinh.nguyen@eurecom.fr
*/ */
#ifndef FILE_SMF_N1_N2_HPP_SEEN #ifndef FILE_SMF_N2_HPP_SEEN
#define FILE_SMF_N1_N2_HPP_SEEN #define FILE_SMF_N2_HPP_SEEN
#include <map>
#include <set>
#include <shared_mutex>
#include <string> #include <string>
#include <thread>
#include "pistache/endpoint.h"
#include "pistache/http.h"
#include "pistache/router.h"
#include "smf.h" #include "smf.h"
#include "3gpp_29.274.h"
#include "itti_msg_n4.hpp"
#include "itti_msg_n11.hpp"
#include "smf_context.hpp"
#include "smf_pco.hpp"
#include "smf_msg.hpp" #include "smf_msg.hpp"
#include "smf_app.hpp" #include "smf_app.hpp"
#include "3gpp_29.502.h" #include "3gpp_29.502.h"
...@@ -52,8 +40,6 @@ ...@@ -52,8 +40,6 @@
#include "SmContextCreateError.h" #include "SmContextCreateError.h"
extern "C" { extern "C" {
#include "nas_message.h"
#include "Ngap_NGAP-PDU.h"
#include "Ngap_PDUSessionResourceSetupResponseTransfer.h" #include "Ngap_PDUSessionResourceSetupResponseTransfer.h"
#include "Ngap_PDUSessionResourceModifyResponseTransfer.h" #include "Ngap_PDUSessionResourceModifyResponseTransfer.h"
#include "Ngap_PDUSessionResourceReleaseResponseTransfer.h" #include "Ngap_PDUSessionResourceReleaseResponseTransfer.h"
...@@ -62,47 +48,98 @@ extern "C" { ...@@ -62,47 +48,98 @@ extern "C" {
namespace smf { namespace smf {
class smf_n1_n2 { class smf_n2 {
private: private:
public: public:
smf_n1_n2() { smf_n2() {
} }
; ;
smf_n1_n2(smf_n1_n2 const&) = delete; smf_n2(smf_n2 const&) = delete;
void operator=(smf_n1_n2 const&) = delete; void operator=(smf_n2 const&) = delete;
/* /*
* Create N1 SM Container to send to AMF (using NAS lib) * Create N2 SM Information: PDU Session Resource Setup Request Transfer
* @param [pdu_session_msg&] msg * This IE is included in N1N2MessageTransfer Request (Accept, PDU Session Establishment procedure - UE initiated)
* @param [uint8_t] msg_type Type of N1 message * @param [pdu_session_create_sm_context_response] sm_context_res: include necessary information for encoding NGAP msg
* @param [std::string&] nas_msg_str store NAS message in form of string * @param [std::string&] ngap_msg_str store the created NGAP message in form of string
* @param [uint8_t] sm_cause store NAS Cause * @return boolean: True if the NGAP message has been created successfully, otherwise return false
* @return boolean: True if the NAS message has been created successfully, otherwise return false *
*/ */
bool create_n1_sm_container(pdu_session_msg &msg, uint8_t msg_type, bool create_n2_pdu_session_resource_setup_request_transfer(pdu_session_create_sm_context_response &sm_context_res, n2_sm_info_type_e ngap_info_type,
std::string &nas_msg_str, std::string &ngap_msg_str);
cause_value_5gsm_e sm_cause);
/* /*
* Create N2 SM Information to send to AMF (using NAS lib) * Create N2 SM Information: PDU Session Resource Setup Request Transfer
* @param [std::shared_ptr<itti_n11_create_sm_context_response>] sm_context_res * This IE is included in PDU Session Update SM Context Response​ (Service Request, step 2)
* @param [uint8_t] msg_type Type of N2 message * @param [pdu_session_update_sm_context_response] sm_context_res: include necessary information for encoding NGAP msg
* @param [std::string&] ngap_msg_str store NGAP message in form of string * @param [std::string&] ngap_msg_str store the created NGAP message in form of string
* @return boolean: True if the NGAP message has been created successfully, otherwise return false * @return boolean: True if the NGAP message has been created successfully, otherwise return false
* *
*/ */
bool create_n2_sm_information(pdu_session_msg &msg, uint8_t ngap_msg_type, bool create_n2_pdu_session_resource_setup_request_transfer(pdu_session_update_sm_context_response &sm_context_res, n2_sm_info_type_e ngap_info_type,
n2_sm_info_type_e ngap_ie_type, std::string &ngap_msg_str);
std::string &ngap_msg_str);
/*
* Create N2 SM Information: PDU Session Resource Setup Request Transfer
* This IE is included in N1N2MessageTranfer (N4 Data Report)
* @param [pdu_session_report_response] msg: include necessary information for encoding NGAP msg
* @param [std::string&] ngap_msg_str store the created NGAP message in form of string
* @return boolean: True if the NGAP message has been created successfully, otherwise return false
*
*/
bool create_n2_pdu_session_resource_setup_request_transfer(pdu_session_report_response &msg, n2_sm_info_type_e ngap_info_type,
std::string &ngap_msg_str);
/*
* Create N2 SM Information: PDU Session Resource Modify Request Transfer IE
* This IE is included in PDU Session Update SM Context Response (PDU Session Modification procedure, UE-initiated, step 1)
* @param [pdu_session_update_sm_context_response] sm_context_res: include necessary information for encoding NGAP msg
* @param [std::string&] ngap_msg_str store the created NGAP message in form of string
* @return boolean: True if the NGAP message has been created successfully, otherwise return false
*
*/
bool create_n2_pdu_session_resource_modify_request_transfer(pdu_session_update_sm_context_response &sm_context_res, n2_sm_info_type_e ngap_info_type,
std::string &ngap_msg_str);
/* /*
* Decode N1 SM Container into the NAS mesasge (using NAS lib) * Create N2 SM Information: PDU Session Resource Modify Request Transfer IE
* @param [nas_message_t&] nas_msg Store NAS message after decoded * This IE is included in N1N2MessageTransfer Request (PDU Session Modification procedure, SMF-requested, step 1)
* @param [const std::string&] n1_sm_msg N1 SM Container * @param [pdu_session_update_sm_context_response] sm_context_res: include necessary information for encoding NGAP msg
* @return status of the decode process * @param [std::string&] ngap_msg_str store the created NGAP message in form of string
* @return boolean: True if the NGAP message has been created successfully, otherwise return false
*
*/ */
int decode_n1_sm_container(nas_message_t &nas_msg, const std::string &n1_sm_msg); bool create_n2_pdu_session_resource_modify_request_transfer(pdu_session_modification_network_requested &msg, n2_sm_info_type_e ngap_info_type,
std::string &ngap_msg_str);
/*
* Create N2 SM Information: PDU Session Resource Modify Response Transfer IE
*
* @param [pdu_session_update_sm_context_response] sm_context_res: include necessary information for encoding NGAP msg
* @param [std::string&] ngap_msg_str store the created NGAP message in form of string
* @return boolean: True if the NGAP message has been created successfully, otherwise return false
*
*/
bool create_n2_pdu_session_resource_modify_response_transfer(pdu_session_update_sm_context_response &sm_context_res, n2_sm_info_type_e ngap_info_type,
std::string &ngap_msg_str);
// bool create_n2_pdu_session_resource_modify_response_transfer(pdu_session_modification_network_requested &msg, n2_sm_info_type_e ngap_info_type,
// std::string &ngap_msg_str);
/*
* Create N2 SM Information: PDU Session Resource Release Command Transfer IE
* This IE is included in the following messages:
* PDU Session Update SM Context Response (PDU Session Release UE-Initiated: section 4.3.4@3GPP TS 23.502, step 1)
* N1N2MessageTransfer Request​ (PDU Session Release SMF-Requested, step 1)
* @param [pdu_session_update_sm_context_response] sm_context_res: include necessary information for encoding NGAP msg
* @param [std::string&] ngap_msg_str store the created NGAP message in form of string
* @return boolean: True if the NGAP message has been created successfully, otherwise return false
*
*/
bool create_n2_pdu_session_resource_release_command_transfer(pdu_session_update_sm_context_response &sm_context_res, n2_sm_info_type_e ngap_info_type,
std::string &ngap_msg_str);
/* /*
* Decode N2 SM Information Ngap_PDUSessionResourceSetupResponseTransfer * Decode N2 SM Information Ngap_PDUSessionResourceSetupResponseTransfer
...@@ -144,9 +181,8 @@ class smf_n1_n2 { ...@@ -144,9 +181,8 @@ class smf_n1_n2 {
std::shared_ptr<Ngap_PDUSessionResourceSetupUnsuccessfulTransfer_t> &ngap_IE, std::shared_ptr<Ngap_PDUSessionResourceSetupUnsuccessfulTransfer_t> &ngap_IE,
const std::string &n2_sm_info); const std::string &n2_sm_info);
}; };
} // namespace smf } // namespace smf
#endif /* FILE_SMF_N1_N2_HPP_SEEN */ #endif /* FILE_SMF_N2_HPP_SEEN */
...@@ -43,7 +43,8 @@ ...@@ -43,7 +43,8 @@
#include "smf_config.hpp" #include "smf_config.hpp"
#include "smf_pfcp_association.hpp" #include "smf_pfcp_association.hpp"
#include "smf_context.hpp" #include "smf_context.hpp"
#include "smf_n1_n2.hpp" #include "smf_n1.hpp"
#include "smf_n2.hpp"
#include "smf_n11.hpp" #include "smf_n11.hpp"
#include "SmContextCreatedData.h" #include "SmContextCreatedData.h"
...@@ -370,7 +371,8 @@ void session_create_sm_context_procedure::handle_itti_msg( ...@@ -370,7 +371,8 @@ void session_create_sm_context_procedure::handle_itti_msg(
//fill content for N1N2MessageTransfer (including N1, N2 SM) //fill content for N1N2MessageTransfer (including N1, N2 SM)
// Create N1 SM container & N2 SM Information // Create N1 SM container & N2 SM Information
smf_n1_n2 smf_n1_n2_inst = { }; smf_n1 smf_n1_inst = { };
smf_n2 smf_n2_inst = { };
std::string n1_sm_msg, n1_sm_msg_hex; std::string n1_sm_msg, n1_sm_msg_hex;
std::string n2_sm_info, n2_sm_info_hex; std::string n2_sm_info, n2_sm_info_hex;
...@@ -386,9 +388,8 @@ void session_create_sm_context_procedure::handle_itti_msg( ...@@ -386,9 +388,8 @@ void session_create_sm_context_procedure::handle_itti_msg(
cause_value_5gsm_e::CAUSE_50_PDU_SESSION_TYPE_IPV4_ONLY_ALLOWED; cause_value_5gsm_e::CAUSE_50_PDU_SESSION_TYPE_IPV4_ONLY_ALLOWED;
} }
smf_n1_n2_inst.create_n1_sm_container(n11_triggered_pending->res, smf_n1_inst.create_n1_pdu_session_establishment_reject(n11_triggered_pending->res,
PDU_SESSION_ESTABLISHMENT_REJECT, n1_sm_msg, cause_n1);
n1_sm_msg, cause_n1);
smf_app_inst->convert_string_2_hex(n1_sm_msg, n1_sm_msg_hex); smf_app_inst->convert_string_2_hex(n1_sm_msg, n1_sm_msg_hex);
n11_triggered_pending->res.set_n1_sm_message(n1_sm_msg_hex); n11_triggered_pending->res.set_n1_sm_message(n1_sm_msg_hex);
...@@ -404,15 +405,15 @@ void session_create_sm_context_procedure::handle_itti_msg( ...@@ -404,15 +405,15 @@ void session_create_sm_context_procedure::handle_itti_msg(
cause_value_5gsm_e::CAUSE_50_PDU_SESSION_TYPE_IPV4_ONLY_ALLOWED; cause_value_5gsm_e::CAUSE_50_PDU_SESSION_TYPE_IPV4_ONLY_ALLOWED;
} }
smf_n1_n2_inst.create_n1_sm_container(n11_triggered_pending->res, smf_n1_inst.create_n1_pdu_session_establishment_accept(n11_triggered_pending->res,
PDU_SESSION_ESTABLISHMENT_ACCEPT, n1_sm_msg, cause_n1);
n1_sm_msg, cause_n1);
smf_app_inst->convert_string_2_hex(n1_sm_msg, n1_sm_msg_hex); smf_app_inst->convert_string_2_hex(n1_sm_msg, n1_sm_msg_hex);
n11_triggered_pending->res.set_n1_sm_message(n1_sm_msg_hex); n11_triggered_pending->res.set_n1_sm_message(n1_sm_msg_hex);
//N2 SM Information (Step 11, section 4.3.2.2.1 @ 3GPP TS 23.502): PDUSessionRessourceSetupRequestTransfer IE //N2 SM Information (Step 11, section 4.3.2.2.1 @ 3GPP TS 23.502): PDUSessionRessourceSetupRequestTransfer IE
smf_n1_n2_inst.create_n2_sm_information( smf_n2_inst.create_n2_pdu_session_resource_setup_request_transfer(
n11_triggered_pending->res, 1, n2_sm_info_type_e::PDU_RES_SETUP_REQ, n11_triggered_pending->res, n2_sm_info_type_e::PDU_RES_SETUP_REQ,
n2_sm_info); n2_sm_info);
smf_app_inst->convert_string_2_hex(n2_sm_info, n2_sm_info_hex); smf_app_inst->convert_string_2_hex(n2_sm_info, n2_sm_info_hex);
n11_triggered_pending->res.set_n2_sm_information(n2_sm_info_hex); n11_triggered_pending->res.set_n2_sm_information(n2_sm_info_hex);
} }
...@@ -864,7 +865,8 @@ void session_update_sm_context_procedure::handle_itti_msg( ...@@ -864,7 +865,8 @@ void session_update_sm_context_procedure::handle_itti_msg(
itti_n4_session_modification_response &resp, itti_n4_session_modification_response &resp,
std::shared_ptr<smf::smf_context> sc) { std::shared_ptr<smf::smf_context> sc) {
smf_n1_n2 smf_n1_n2_inst = { }; smf_n1 smf_n1_inst = { };
smf_n2 smf_n2_inst = { };
std::string n1_sm_msg, n1_sm_msg_hex; std::string n1_sm_msg, n1_sm_msg_hex;
std::string n2_sm_info, n2_sm_info_hex; std::string n2_sm_info, n2_sm_info_hex;
...@@ -1055,14 +1057,13 @@ void session_update_sm_context_procedure::handle_itti_msg( ...@@ -1055,14 +1057,13 @@ 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 //N1 SM
smf_n1_n2_inst.create_n1_sm_container( smf_n1_inst.create_n1_pdu_session_modification_request(
n11_triggered_pending->res, PDU_SESSION_MODIFICATION_REQUEST, n11_triggered_pending->res, n1_sm_msg, cause_value_5gsm_e::CAUSE_0_UNKNOWN);
n1_sm_msg, cause_value_5gsm_e::CAUSE_0_UNKNOWN);
smf_app_inst->convert_string_2_hex(n1_sm_msg, n1_sm_msg_hex); smf_app_inst->convert_string_2_hex(n1_sm_msg, n1_sm_msg_hex);
n11_triggered_pending->res.set_n1_sm_message(n1_sm_msg_hex); n11_triggered_pending->res.set_n1_sm_message(n1_sm_msg_hex);
//N2 SM Information //N2 SM Information
smf_n1_n2_inst.create_n2_sm_information( smf_n2_inst.create_n2_pdu_session_resource_modify_response_transfer(
n11_triggered_pending->res, 1, n2_sm_info_type_e::PDU_RES_MOD_RSP, n11_triggered_pending->res, n2_sm_info_type_e::PDU_RES_MOD_RSP,
n2_sm_info); n2_sm_info);
smf_app_inst->convert_string_2_hex(n2_sm_info, n2_sm_info_hex); smf_app_inst->convert_string_2_hex(n2_sm_info, n2_sm_info_hex);
n11_triggered_pending->res.set_n2_sm_information(n2_sm_info_hex); n11_triggered_pending->res.set_n2_sm_information(n2_sm_info_hex);
...@@ -1096,9 +1097,10 @@ void session_update_sm_context_procedure::handle_itti_msg( ...@@ -1096,9 +1097,10 @@ void session_update_sm_context_procedure::handle_itti_msg(
// Create N2 SM Information: PDU Session Resource Setup Request Transfer IE // Create N2 SM Information: PDU Session Resource Setup Request Transfer IE
//N2 SM Information //N2 SM Information
smf_n1_n2_inst.create_n2_sm_information( smf_n2_inst.create_n2_pdu_session_resource_setup_request_transfer(
n11_triggered_pending->res, 1, n2_sm_info_type_e::PDU_RES_SETUP_REQ, n11_triggered_pending->res, n2_sm_info_type_e::PDU_RES_SETUP_REQ,
n2_sm_info); n2_sm_info);
smf_app_inst->convert_string_2_hex(n2_sm_info, n2_sm_info_hex); smf_app_inst->convert_string_2_hex(n2_sm_info, n2_sm_info_hex);
n11_triggered_pending->res.set_n2_sm_information(n2_sm_info_hex); n11_triggered_pending->res.set_n2_sm_information(n2_sm_info_hex);
...@@ -1156,8 +1158,8 @@ void session_update_sm_context_procedure::handle_itti_msg( ...@@ -1156,8 +1158,8 @@ void session_update_sm_context_procedure::handle_itti_msg(
Logger::smf_app().info("PDU Session Release UE-initiated (Step 1))"); Logger::smf_app().info("PDU Session Release UE-initiated (Step 1))");
//N1 SM //N1 SM
smf_n1_n2_inst.create_n1_sm_container( smf_n1_inst.create_n1_pdu_session_release_command(
n11_triggered_pending->res, PDU_SESSION_RELEASE_COMMAND, n1_sm_msg, n11_triggered_pending->res, n1_sm_msg,
cause_value_5gsm_e::CAUSE_26_INSUFFICIENT_RESOURCES); //TODO: check Cause cause_value_5gsm_e::CAUSE_26_INSUFFICIENT_RESOURCES); //TODO: check Cause
smf_app_inst->convert_string_2_hex(n1_sm_msg, n1_sm_msg_hex); smf_app_inst->convert_string_2_hex(n1_sm_msg, n1_sm_msg_hex);
n11_triggered_pending->res.set_n1_sm_message(n1_sm_msg_hex); n11_triggered_pending->res.set_n1_sm_message(n1_sm_msg_hex);
...@@ -1165,8 +1167,8 @@ void session_update_sm_context_procedure::handle_itti_msg( ...@@ -1165,8 +1167,8 @@ void session_update_sm_context_procedure::handle_itti_msg(
//include N2 SM Resource Release Request only when User Plane connection is activated //include N2 SM Resource Release Request only when User Plane connection is activated
if (sps->get_upCnx_state() == upCnx_state_e::UPCNX_STATE_ACTIVATED) { if (sps->get_upCnx_state() == upCnx_state_e::UPCNX_STATE_ACTIVATED) {
//N2 SM Information //N2 SM Information
smf_n1_n2_inst.create_n2_sm_information( smf_n2_inst.create_n2_pdu_session_resource_release_command_transfer(
n11_triggered_pending->res, 1, n2_sm_info_type_e::PDU_RES_REL_CMD, n11_triggered_pending->res, n2_sm_info_type_e::PDU_RES_REL_CMD,
n2_sm_info); n2_sm_info);
smf_app_inst->convert_string_2_hex(n2_sm_info, n2_sm_info_hex); smf_app_inst->convert_string_2_hex(n2_sm_info, n2_sm_info_hex);
n11_triggered_pending->res.set_n2_sm_information(n2_sm_info_hex); n11_triggered_pending->res.set_n2_sm_information(n2_sm_info_hex);
......
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