diff --git a/etc/smf.conf b/etc/smf.conf index 60dc214922f3ba2de7bb60da40d4e84642ce2f19..08a45a7dc42bf563560ca53a03846a7b63070832 100644 --- a/etc/smf.conf +++ b/etc/smf.conf @@ -73,8 +73,8 @@ SMF = APN_LIST = ( # IPV4_POOL, IPV6_POOL are index in IPV4_LIST, IPV6_LIST, PDN_TYPE choice in {IPv4, IPv6, IPv4v6} - {APN_NI = "carrier.com"; PDN_TYPE = "IPv4"; IPV4_POOL = 0; IPV6_POOL = -1}, - {APN_NI = "apn1"; PDN_TYPE = "IPv4"; IPV4_POOL = 1; IPV6_POOL = -1}, + {APN_NI = "default"; PDN_TYPE = "IPv4"; IPV4_POOL = 0; IPV6_POOL = -1}, + {APN_NI = "carrier.com"; PDN_TYPE = "IPv4"; IPV4_POOL = 1; IPV6_POOL = -1}, {APN_NI = "apn2"; PDN_TYPE = "IPv4"; IPV4_POOL = 2; IPV6_POOL = -1}, {APN_NI = "apn3"; PDN_TYPE = "IPv4"; IPV4_POOL = 3; IPV6_POOL = -1}, {APN_NI = "apn4"; PDN_TYPE = "IPv4"; IPV4_POOL = 4; IPV6_POOL = -1} diff --git a/src/api-server/impl/SMContextsCollectionApiImpl.cpp b/src/api-server/impl/SMContextsCollectionApiImpl.cpp index aba49d98e386c69c3b98614ca2ef06b33478e802..e6fa48c890ef0587d29fcc2d050967e39d4c9a85 100755 --- a/src/api-server/impl/SMContextsCollectionApiImpl.cpp +++ b/src/api-server/impl/SMContextsCollectionApiImpl.cpp @@ -103,7 +103,7 @@ void SMContextsCollectionApiImpl::post_sm_contexts( smContextCreateData.getSNssai().getSst(), smContextCreateData.getSNssai().getSd().c_str()); snssai_t snssai(smContextCreateData.getSNssai().getSst(), - smContextCreateData.getSNssai().getSd().c_str()); + smContextCreateData.getSNssai().getSd()); sm_context_req_msg.set_snssai(snssai); //PDU session ID diff --git a/src/smf_app/smf_app.cpp b/src/smf_app/smf_app.cpp index e5c2a61aaddc08f359c2e9a8f00ba5b4c926ebda..dedd3ea51345e6241eff7f6d6bb99d5bd3105b2f 100755 --- a/src/smf_app/smf_app.cpp +++ b/src/smf_app/smf_app.cpp @@ -459,7 +459,7 @@ void smf_app::handle_pdu_session_create_sm_context_request( oai::smf_server::model::SmContextCreateError smContextCreateError = { }; oai::smf_server::model::ProblemDetails problem_details = { }; oai::smf_server::model::RefToBinaryData refToBinaryData = { }; - std::string n1_sm_message, n1_sm_message_hex; //N1 SM container + std::string n1_sm_message, n1_sm_message_hex; smf_n1_n2 smf_n1_n2_inst = { }; nas_message_t decoded_nas_msg = { }; @@ -467,46 +467,37 @@ void smf_app::handle_pdu_session_create_sm_context_request( std::string n1_sm_msg = smreq->req.get_n1_sm_message(); memset(&decoded_nas_msg, 0, sizeof(nas_message_t)); - pdu_session_create_sm_context_request context_req_msg = smreq->req; - int decoder_rc = smf_n1_n2_inst.decode_n1_sm_container(decoded_nas_msg, n1_sm_msg); if (decoder_rc != RETURNok) { - //error, should send reply to AMF with error code!! + //error, send reply to AMF with PDU Session Establishment Reject Logger::smf_app().warn("N1 SM container cannot be decoded correctly!"); problem_details.setCause( pdu_session_application_error_e2str[PDU_SESSION_APPLICATION_ERROR_N1_SM_ERROR]); smContextCreateError.setError(problem_details); refToBinaryData.setContentId(N1_SM_CONTENT_ID); smContextCreateError.setN1SmMsg(refToBinaryData); - //PDU Session Establishment Reject - //24.501: response with a 5GSM STATUS message including cause "#95 Semantically incorrect message" smf_n1_n2_inst.create_n1_sm_container( - context_req_msg, PDU_SESSION_ESTABLISHMENT_REJECT, n1_sm_message, + smreq->req, PDU_SESSION_ESTABLISHMENT_REJECT, n1_sm_message, cause_value_5gsm_e::CAUSE_95_SEMANTICALLY_INCORRECT_MESSAGE); smf_app_inst->convert_string_2_hex(n1_sm_message, n1_sm_message_hex); - //Send response to AMF smf_n11_inst->send_pdu_session_create_sm_context_response( smreq->http_response, smContextCreateError, Pistache::Http::Code::Forbidden, n1_sm_message_hex); + return; } Logger::smf_app().debug( - "NAS header information: extended protocol discriminator %d, security headertype %d", + "NAS information: Extended Protocol Discriminator %d, Security Header Type %d, Message Type %d", decoded_nas_msg.header.extended_protocol_discriminator, - decoded_nas_msg.header.security_header_type); + decoded_nas_msg.header.security_header_type, + decoded_nas_msg.plain.sm.header.message_type); //Extended protocol discriminator (Mandatory) smreq->req.set_epd(decoded_nas_msg.header.extended_protocol_discriminator); - - //Message type (Mandatory) (PDU SESSION ESTABLISHMENT REQUEST message identity) - Logger::smf_app().debug("NAS header information, Message Type %d", - decoded_nas_msg.plain.sm.header.message_type); + //Message type (Mandatory) smreq->req.set_message_type(decoded_nas_msg.plain.sm.header.message_type); - - //Integrity protection maximum data rate (Mandatory) - //TODO: - + //TODO: Integrity protection maximum data rate (Mandatory) //PDU session type (Optional) smreq->req.set_pdu_session_type(PDU_SESSION_TYPE_E_IPV4); //set default value if (decoded_nas_msg.plain.sm.header.message_type @@ -535,8 +526,8 @@ void smf_app::handle_pdu_session_create_sm_context_request( uint8_t message_type = decoded_nas_msg.plain.sm.header.message_type; std::string request_type = smreq->req.get_request_type(); Logger::smf_app().info( - "Handle a PDU Session Create SM Context Request message from AMF, supi " SUPI_64_FMT ", dnn %s, snssai_sst %d", - supi64, dnn.c_str(), snssai.sST); + "Handle a PDU Session Create SM Context Request message from AMF, supi " SUPI_64_FMT ", dnn %s, snssai_sst %d, snssai_sd %s", + supi64, dnn.c_str(), snssai.sST, snssai.sD.c_str()); //If no DNN information from UE, set to default value if (dnn.length() == 0) { @@ -554,19 +545,17 @@ void smf_app::handle_pdu_session_create_sm_context_request( smContextCreateError.setError(problem_details); refToBinaryData.setContentId(N1_SM_CONTENT_ID); smContextCreateError.setN1SmMsg(refToBinaryData); - //PDU Session Establishment Reject - //(24.501 (section 7.3.1)) NAS N1 SM message: response with a 5GSM STATUS message including cause "#81 Invalid PTI value" + //PDU Session Establishment Reject including cause "#81 Invalid PTI value" (section 7.3.1 @3GPP TS 24.501) smf_n1_n2_inst.create_n1_sm_container( - context_req_msg, PDU_SESSION_ESTABLISHMENT_REJECT, n1_sm_message, + smreq->req, PDU_SESSION_ESTABLISHMENT_REJECT, n1_sm_message, cause_value_5gsm_e::CAUSE_81_INVALID_PTI_VALUE); smf_app_inst->convert_string_2_hex(n1_sm_message, n1_sm_message_hex); - //Send response to AMF smf_n11_inst->send_pdu_session_create_sm_context_response( smreq->http_response, smContextCreateError, Pistache::Http::Code::Forbidden, n1_sm_message_hex); + return; } - - context_req_msg.set_pti(pti); + smreq->req.set_pti(pti); //check pdu session id if ((pdu_session_id == PDU_SESSION_IDENTITY_UNASSIGNED ) @@ -589,12 +578,11 @@ void smf_app::handle_pdu_session_create_sm_context_request( //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." smf_n1_n2_inst.create_n1_sm_container( - context_req_msg, + smreq->req, PDU_SESSION_ESTABLISHMENT_REJECT, n1_sm_message, - cause_value_5gsm_e::CAUSE_98_MESSAGE_TYPE_NOT_COMPATIBLE_WITH_PROTOCOL_STATE); //TODO: should define 5GSM cause in 24.501 + 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); - //Send response to AMF smf_n11_inst->send_pdu_session_create_sm_context_response( smreq->http_response, smContextCreateError, Pistache::Http::Code::Forbidden, n1_sm_message_hex); @@ -625,10 +613,9 @@ void smf_app::handle_pdu_session_create_sm_context_request( smContextCreateError.setN1SmMsg(refToBinaryData); //PDU Session Establishment Reject, 24.501 cause "#27 Missing or unknown DNN" smf_n1_n2_inst.create_n1_sm_container( - context_req_msg, PDU_SESSION_ESTABLISHMENT_REJECT, n1_sm_message, + smreq->req, PDU_SESSION_ESTABLISHMENT_REJECT, n1_sm_message, cause_value_5gsm_e::CAUSE_27_MISSING_OR_UNKNOWN_DNN); smf_app_inst->convert_string_2_hex(n1_sm_message, n1_sm_message_hex); - //Send response to AMF smf_n11_inst->send_pdu_session_create_sm_context_response( smreq->http_response, smContextCreateError, Pistache::Http::Code::Forbidden, n1_sm_message_hex); @@ -683,8 +670,7 @@ void smf_app::handle_pdu_session_create_sm_context_request( //update dnn_context with subscription info sc.get()->insert_dnn_subscription(snssai, subscription); } else { - // Cannot retrieve information from UDM, - //Not accept to establish a PDU session + // Cannot retrieve information from UDM, reject PDU session establishment Logger::smf_app().warn( "Received PDU_SESSION_CREATESMCONTEXT_REQUEST, couldn't retrieve the Session Management Subscription from UDM, ignore message!"); problem_details.setCause( @@ -692,9 +678,9 @@ void smf_app::handle_pdu_session_create_sm_context_request( smContextCreateError.setError(problem_details); refToBinaryData.setContentId(N1_SM_CONTENT_ID); smContextCreateError.setN1SmMsg(refToBinaryData); - //PDU Session Establishment Reject, with cause "29 User authentication or authorization failed"? + //PDU Session Establishment Reject, with cause "29 User authentication or authorization failed" smf_n1_n2_inst.create_n1_sm_container( - context_req_msg, + smreq->req, PDU_SESSION_ESTABLISHMENT_REJECT, n1_sm_message, cause_value_5gsm_e::CAUSE_29_USER_AUTHENTICATION_OR_AUTHORIZATION_FAILED); @@ -723,8 +709,6 @@ void smf_app::handle_pdu_session_create_sm_context_request( Logger::smf_app().debug("Generated a SCID " SCID_FMT " ", scid); //Step 8. let the context handle the message - //in this step, SMF will send N4 Session Establishment/Modification to UPF (step 10a, section 4.3.2 3GPP 23.502) - //SMF, then, sends response to AMF sc.get()->handle_pdu_session_create_sm_context_request(smreq); } @@ -744,7 +728,6 @@ void smf_app::handle_pdu_session_update_sm_context_request( try { scid = std::stoi(smreq->scid); } catch (const std::exception &err) { - //TODO: send PDUSession_SMUpdateContext Response to AMF with CAUSE: invalid context Logger::smf_app().warn( "Received a PDU Session Update SM Context Request, couldn't retrieve the corresponding SMF context, ignore message!"); problem_details.setCause( @@ -772,19 +755,12 @@ void smf_app::handle_pdu_session_update_sm_context_request( return; } - supi_t supi = scf.get()->supi; - std::string dnn = scf.get()->dnn; - pdu_session_id_t pdu_session_id = scf.get()->pdu_session_id; - snssai_t nssai = scf.get()->nssai; - //Step 2. store supi, dnn, nssai in itti_n11_update_sm_context_request to be processed later on - supi64_t supi64 = smf_supi_to_u64(supi); - smreq->req.set_supi(supi); - smreq->req.set_dnn(dnn); - smreq->req.set_snssai(nssai); - smreq->req.set_pdu_session_id(pdu_session_id); - - pdu_session_update_sm_context_request context_req_msg = smreq->req; + supi64_t supi64 = smf_supi_to_u64(scf.get()->supi); + smreq->req.set_supi(scf.get()->supi); + smreq->req.set_dnn(scf.get()->dnn); + smreq->req.set_snssai(scf.get()->nssai); + smreq->req.set_pdu_session_id(scf.get()->pdu_session_id); //Step 2. find the smf context std::shared_ptr<smf_context> sc = { }; @@ -809,10 +785,9 @@ void smf_app::handle_pdu_session_update_sm_context_request( //get dnn context std::shared_ptr<dnn_context> sd = { }; - if (!sc.get()->find_dnn_context(scf.get()->nssai, dnn, sd)) { + if (!sc.get()->find_dnn_context(scf.get()->nssai, scf.get()->dnn, sd)) { if (nullptr == sd.get()) { - //Error, DNN context doesn't exist - // send PDUSession_SMUpdateContext Response to AMF + //Error, DNN context doesn't exist, send PDUSession_SMUpdateContext Response to AMF Logger::smf_app().warn( "Received PDU Session Update SM Context Request, couldn't retrieve the corresponding SMF context, ignore message!"); problem_details.setCause( diff --git a/src/smf_app/smf_context.cpp b/src/smf_app/smf_context.cpp index c9024fe7de18287aac1f25ea310abeac636fa127..c31ff26967f1171c612cd67f11bba7f3232f66f0 100644 --- a/src/smf_app/smf_context.cpp +++ b/src/smf_app/smf_context.cpp @@ -47,6 +47,7 @@ extern "C" { #include "Ngap_PDUSessionResourceSetupResponseTransfer.h" #include "Ngap_PDUSessionResourceModifyResponseTransfer.h" +#include "Ngap_PDUSessionResourceReleaseResponseTransfer.h" #include "Ngap_GTPTunnel.h" #include "Ngap_AssociatedQosFlowItem.h" #include "Ngap_QosFlowAddOrModifyResponseList.h" @@ -289,7 +290,7 @@ void smf_pdu_session::deallocate_ressources(const std::string &apn) { if (ipv4) { paa_dynamic::get_instance().release_paa(apn, ipv4_address); } - clear(); //including qos_flows.clear() + clear(); //including qos_flows.clear() Logger::smf_app().info( "Resources associated with this PDU Session have been released"); } @@ -826,7 +827,7 @@ void smf_context::handle_pdu_session_create_sm_context_request( std::shared_ptr<itti_n11_create_sm_context_request> smreq) { Logger::smf_app().info( "Handle a PDU Session Create SM Context Request message from AMF"); - pdu_session_create_sm_context_request sm_context_req_msg = smreq->req; + oai::smf_server::model::SmContextCreateError smContextCreateError = { }; oai::smf_server::model::ProblemDetails problem_details = { }; oai::smf_server::model::RefToBinaryData refToBinaryData = { }; @@ -835,12 +836,12 @@ void smf_context::handle_pdu_session_create_sm_context_request( bool request_accepted = true; //Step 1. get necessary information - std::string dnn = sm_context_req_msg.get_dnn(); - snssai_t snssai = sm_context_req_msg.get_snssai(); - std::string request_type = sm_context_req_msg.get_request_type(); - supi_t supi = sm_context_req_msg.get_supi(); + std::string dnn = smreq->req.get_dnn(); + snssai_t snssai = smreq->req.get_snssai(); + std::string request_type = smreq->req.get_request_type(); + supi_t supi = smreq->req.get_supi(); supi64_t supi64 = smf_supi_to_u64(supi); - uint32_t pdu_session_id = sm_context_req_msg.get_pdu_session_id(); + uint32_t pdu_session_id = smreq->req.get_pdu_session_id(); //Step 2. check the validity of the UE request, if valid send PDU Session Accept, otherwise send PDU Session Reject to AMF if (!verify_sm_context_request(smreq)) { @@ -852,9 +853,8 @@ void smf_context::handle_pdu_session_create_sm_context_request( smContextCreateError.setError(problem_details); refToBinaryData.setContentId(N1_SM_CONTENT_ID); smContextCreateError.setN1SmMsg(refToBinaryData); - //PDU Session Establishment Reject smf_n1_n2_inst.create_n1_sm_container( - sm_context_req_msg, + smreq->req, PDU_SESSION_ESTABLISHMENT_REJECT, n1_sm_message, cause_value_5gsm_e::CAUSE_29_USER_AUTHENTICATION_OR_AUTHORIZATION_FAILED); @@ -875,11 +875,14 @@ void smf_context::handle_pdu_session_create_sm_context_request( std::shared_ptr<itti_n11_create_sm_context_response> sm_context_resp_pending = std::shared_ptr<itti_n11_create_sm_context_response>(sm_context_resp); sm_context_resp->res.set_supi(supi); - sm_context_resp->res.set_supi_prefix(sm_context_req_msg.get_supi_prefix()); + sm_context_resp->res.set_supi_prefix(smreq->req.get_supi_prefix()); sm_context_resp->res.set_cause(REQUEST_ACCEPTED); sm_context_resp->res.set_pdu_session_id(pdu_session_id); sm_context_resp->res.set_snssai(snssai); sm_context_resp->res.set_dnn(dnn); + sm_context_resp->res.set_pdu_session_type( + smreq->req.get_pdu_session_type()); + sm_context_resp->res.set_pti(smreq->req.get_pti()); sm_context_resp->set_scid(smreq->scid); //Step 3. find pdu_session @@ -908,11 +911,10 @@ void smf_context::handle_pdu_session_create_sm_context_request( if (nullptr == sp.get()) { Logger::smf_app().debug("Create a new PDN connection!"); - //create a new pdu session sp = std::shared_ptr<smf_pdu_session>(new smf_pdu_session()); - sp.get()->pdn_type.pdn_type = sm_context_req_msg.get_pdu_session_type(); + sp.get()->pdn_type.pdn_type = smreq->req.get_pdu_session_type(); sp.get()->pdu_session_id = pdu_session_id; - sp.get()->amf_id = sm_context_req_msg.get_serving_nf_id(); //amf id + sp.get()->amf_id = smreq->req.get_serving_nf_id(); //amf id sd->insert_pdu_session(sp); } else { Logger::smf_app().debug("PDN connection is already existed!"); @@ -948,7 +950,6 @@ void smf_context::handle_pdu_session_create_sm_context_request( .ci_ip_address_allocation_via_nas_signalling = 0, .ci_ipv4_address_allocation_via_dhcpv4 = 0, .ci_ipv4_link_mtu_request = 0 }; - //smf_app_inst->process_pco_request(extended_protocol_options, pco_resp, pco_ids); //Step 7. Address allocation based on PDN type @@ -1014,7 +1015,7 @@ void smf_context::handle_pdu_session_create_sm_context_request( smContextCreateError.setN1SmMsg(refToBinaryData); //PDU Session Establishment Reject smf_n1_n2_inst.create_n1_sm_container( - sm_context_req_msg, PDU_SESSION_ESTABLISHMENT_REJECT, n1_sm_message, + smreq->req, PDU_SESSION_ESTABLISHMENT_REJECT, n1_sm_message, 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_n11_inst->send_pdu_session_create_sm_context_response( @@ -1050,10 +1051,9 @@ void smf_context::handle_pdu_session_create_sm_context_request( // std::string smContextRef = sm_context_req_msg.get_supi_prefix() + "-" + smf_supi_to_string(sm_context_req_msg.get_supi()); std::string smContextRef = std::to_string(smreq->scid); //headers: Location: contains the URI of the newly created resource, according to the structure: {apiRoot}/nsmf-pdusession/{apiVersion}/sm-contexts/{smContextRef} - std::string uri = sm_context_req_msg.get_api_root() + "/" + std::string uri = smreq->req.get_api_root() + "/" + smContextRef.c_str(); - //TODO: disable two following lines to test PDU SESSION ESTABLISHMENT ACCEPT sm_context_resp->http_response.headers() .add<Pistache::Http::Header::Location>(uri); smf_n11_inst->send_pdu_session_create_sm_context_response( @@ -1276,6 +1276,15 @@ void smf_context::handle_pdu_session_update_sm_context_request( */ //See section 6.4.2 - UE-requested PDU Session modification procedure@ 3GPP TS 24.501 + //PDU Session Identity + //check if the PDU Session Release Command is already sent for this message (see section 6.3.3.5 @3GPP TS 24.501) + if (sp.get()->get_pdu_session_status() == pdu_session_status_e::PDU_SESSION_INACTIVE_PENDING) { + //Ignore the message + Logger::smf_app().info("A PDU Session Release Command has been sent for this session (session ID %d), ignore the message!", + decoded_nas_msg.plain.sm.header.pdu_session_identity); + return; + } + //PTI Logger::smf_app().info( "PTI %d", @@ -1436,6 +1445,30 @@ void smf_context::handle_pdu_session_update_sm_context_request( != decoded_nas_msg.plain.sm.header.pdu_session_identity) { //TODO: PDU Session ID mismatch } + //Abnormal cases in network side (see section 6.4.3.6 @3GPP TS 24.501) + if (sp.get()->get_pdu_session_status() == pdu_session_status_e::PDU_SESSION_INACTIVE) { + Logger::smf_app().warn("PDU Session status: INACTIVE, send PDU Session Release Reject to UE!"); + problem_details.setCause( + pdu_session_application_error_e2str[PDU_SESSION_APPLICATION_ERROR_NETWORK_FAILURE]); //TODO: which cause? + smContextUpdateError.setError(problem_details); + refToBinaryData.setContentId(N1_SM_CONTENT_ID); + smContextUpdateError.setN1SmMsg(refToBinaryData); + smf_n1_n2_inst.create_n1_sm_container( + sm_context_req_msg, PDU_SESSION_RELEASE_REJECT, n1_sm_msg, + 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_n11_inst->send_pdu_session_update_sm_context_response( + smreq->http_response, smContextUpdateError, + Pistache::Http::Code::Forbidden, n1_sm_msg_hex); + } + //Abnormal cases in network side (see section 6.3.3.5 @3GPP TS 24.501) + if (sp.get()->get_pdu_session_status() == pdu_session_status_e::PDU_SESSION_INACTIVE_PENDING) { + //Ignore the message + Logger::smf_app().info("A PDU Session Release Command has been sent for this session (session ID %d), ignore the message!", + decoded_nas_msg.plain.sm.header.pdu_session_identity); + return; + } + //PTI Logger::smf_app().info( "PTI %d", @@ -1449,19 +1482,27 @@ void smf_context::handle_pdu_session_update_sm_context_request( //5GSM Cause //Extended Protocol Configuration Options - //Release the resources related to this PDU Session - //The SMF releases the IP address / Prefix(es) that were allocated to the PDU Session and releases the - //corresponding User Plane resources - - //SMF releases the IP address / Prefix(es) that were allocated to the PDU Session + //Release the resources related to this PDU Session (in Procedure) //find DNN context std::shared_ptr<dnn_context> sd = { }; - if ((!find_dnn_context(sm_context_req_msg.get_snssai(), sm_context_req_msg.get_dnn(), sd)) or (nullptr == sd.get())) { - //TODO: error cannot find the associated DNN context + Logger::smf_app().warn("Could not find the context for this PDU session"); + //create PDU Session Release Reject and send to UE + problem_details.setCause( + pdu_session_application_error_e2str[PDU_SESSION_APPLICATION_ERROR_CONTEXT_NOT_FOUND]); + smContextUpdateError.setError(problem_details); + refToBinaryData.setContentId(N1_SM_CONTENT_ID); + smContextUpdateError.setN1SmMsg(refToBinaryData); + smf_n1_n2_inst.create_n1_sm_container( + sm_context_req_msg, PDU_SESSION_RELEASE_REJECT, n1_sm_msg, + cause_value_5gsm_e::CAUSE_111_PROTOCOL_ERROR_UNSPECIFIED); + smf_app_inst->convert_string_2_hex(n1_sm_msg, n1_sm_msg_hex); + smf_n11_inst->send_pdu_session_update_sm_context_response( + smreq->http_response, smContextUpdateError, + Pistache::Http::Code::Forbidden, n1_sm_msg_hex); return; } @@ -1470,7 +1511,21 @@ void smf_context::handle_pdu_session_update_sm_context_request( if ((!sd.get()->find_pdu_session( sm_context_req_msg.get_pdu_session_id(), ss)) or (nullptr == ss.get())) { - //TODO: error cannot find the corresponding PDU Session + Logger::smf_app().warn("Could not find the context for this PDU session"); + //create PDU Session Release Reject and send to UE + problem_details.setCause( + pdu_session_application_error_e2str[PDU_SESSION_APPLICATION_ERROR_CONTEXT_NOT_FOUND]); + smContextUpdateError.setError(problem_details); + refToBinaryData.setContentId(N1_SM_CONTENT_ID); + smContextUpdateError.setN1SmMsg(refToBinaryData); + smf_n1_n2_inst.create_n1_sm_container( + sm_context_req_msg, PDU_SESSION_RELEASE_REJECT, n1_sm_msg, + 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_n11_inst->send_pdu_session_update_sm_context_response( + smreq->http_response, smContextUpdateError, + Pistache::Http::Code::Forbidden, n1_sm_msg_hex); + return; } //get the associated QoS flows: to be used for PFCP Session Modification procedure @@ -1482,8 +1537,6 @@ void smf_context::handle_pdu_session_update_sm_context_request( //need to update UPF accordingly update_upf = true; - - //TODO: } break; @@ -1522,8 +1575,7 @@ void smf_context::handle_pdu_session_update_sm_context_request( itti_inst->timer_remove(sp.get()->timer_T3592); //send response to AMF - //Verify, do we need this? - oai::smf_server::model::SmContextCreatedData smContextCreatedData; + oai::smf_server::model::SmContextCreatedData smContextCreatedData; //Verify, do we need this? smf_n11_inst->send_pdu_session_create_sm_context_response( smreq->http_response, smContextCreatedData, Pistache::Http::Code::Ok); @@ -1755,15 +1807,30 @@ void smf_context::handle_pdu_session_update_sm_context_request( procedure_type = session_management_procedures_type_e::PDU_SESSION_RELEASE_UE_REQUESTED_STEP2; //TODO: SMF does nothing (Step 7, section 4.3.4.2@3GPP TS 23.502) - //SMF send response to AMF - - //Verify, do we need this? - oai::smf_server::model::SmContextCreatedData smContextCreatedData; + //Ngap_PDUSessionResourceReleaseResponseTransfer + std::shared_ptr<Ngap_PDUSessionResourceReleaseResponseTransfer_t> decoded_msg = + std::make_shared<Ngap_PDUSessionResourceReleaseResponseTransfer_t>(); + int decode_status = smf_n1_n2_inst.decode_n2_sm_information( + decoded_msg, n2_sm_information); + if (decode_status == RETURNerror) { + Logger::smf_api_server().warn("asn_decode failed"); + //send error to AMF + Logger::smf_app().warn( + "Decode N2 SM (Ngap_PDUSessionResourceReleaseResponseTransfer) failed!"); + problem_details.setCause( + pdu_session_application_error_e2str[PDU_SESSION_APPLICATION_ERROR_N2_SM_ERROR]); + smContextUpdateError.setError(problem_details); + smf_n11_inst->send_pdu_session_update_sm_context_response( + smreq->http_response, smContextUpdateError, + Pistache::Http::Code::Forbidden); + return; + } + //SMF send response to AMF + oai::smf_server::model::SmContextCreatedData smContextCreatedData; //Verify, do we need this? smf_n11_inst->send_pdu_session_create_sm_context_response( smreq->http_response, smContextCreatedData, Pistache::Http::Code::Ok); - } break; @@ -1823,7 +1890,7 @@ void smf_context::handle_pdu_session_update_sm_context_request( smf_app_inst->convert_string_2_hex(n1_sm_msg, n1_sm_msg_hex); smf_n11_inst->send_pdu_session_update_sm_context_response( smreq->http_response, smContextUpdateError, - Pistache::Http::Code::Forbidden, n1_sm_msg_hex); + Pistache::Http::Code::Forbidden); return; } diff --git a/src/smf_app/smf_n11.cpp b/src/smf_app/smf_n11.cpp index 90b7d3eadd70668b61b51c3c685d04b33efebf00..f61b111e524e4e5747164aaf2ee4eb0ec2ce2b1c 100644 --- a/src/smf_app/smf_n11.cpp +++ b/src/smf_app/smf_n11.cpp @@ -44,6 +44,10 @@ #include "smf_config.hpp" #include "smf_n1_n2.hpp" +extern "C" { +#include "dynamic_memory_check.h" +} + using namespace Pistache::Http; using namespace Pistache::Http::Mime; @@ -124,152 +128,63 @@ void smf_n11::send_n1n2_message_transfer_request( std::shared_ptr<itti_n11_create_sm_context_response> sm_context_res) { //Transfer N1/N2 message via AMF by using N_amf_Communication_N1N2MessageTransfer (see TS29518_Namf_Communication.yaml) //TODO: use RestSDK for client, use curl to send data for the moment + Logger::smf_n11().debug("Send Communication_N1N2MessageTransfer to AMF"); smf_n1_n2 smf_n1_n2_inst = { }; + std::string n1_message = sm_context_res->res.get_n1_sm_message(); + std::string json_part = sm_context_res->res.n1n2_message_transfer_data.dump(); + std::string boundary = "----Boundary"; + std::string body; - pdu_session_create_sm_context_response context_res_msg = sm_context_res->res; - std::string n1_message = context_res_msg.get_n1_sm_message(); - - /* - ENABLE THIS TO TEST NAS PDU SESSION ESTABLISHMENT ACCEPT - Don't forget to disable Http_response in SMF CONTEXT - - std::string json_part = context_res_msg.n1n2_message_transfer_data.dump(); - std::string boundary = "----Boundary"; - std::string body; - - create_multipart_related_content(body, json_part, boundary, n1_message, multipart_related_content_part_e::NAS); - sm_context_res->http_response.headers().add<Pistache::Http::Header::ContentType>(Pistache::Http::Mime::MediaType("multipart/related; boundary=" + boundary)); - sm_context_res->http_response.send(Pistache::Http::Code::Ok, body); - */ - - /* - //format string as hex - unsigned char *msg_hex = smf_app_inst->format_string_as_hex(n1_message); - - string CRLF = "\r\n"; - body.append("--" + boundary + CRLF); - body.append("Content-Type: application/json" + CRLF); - body.append(CRLF); - body.append(json_part + CRLF); - - body.append("--" + boundary + CRLF); - //NAS - body.append("Content-Type: application/vnd.3gpp.5gnas"+ CRLF + "Content-Id: n1SmMsg" + CRLF); - - body.append(CRLF); - body.append(std::string((char *)msg_hex, n1_message.length()/2) + CRLF); - body.append("--" + boundary + "--" + CRLF); - - CURL *curl; - CURLcode res; - - - curl_global_init(CURL_GLOBAL_ALL); - - curl = curl_easy_init(); - if(curl) { - struct curl_slist *headers = nullptr; - //headers = curl_slist_append(headers, "charsets: utf-8"); - headers = curl_slist_append(headers, "content-type: multipart/related; boundary=----Boundary"); - curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers); - curl_easy_setopt(curl, CURLOPT_URL, context_res_msg.get_amf_url().c_str() ); - - curl_easy_setopt(curl, CURLOPT_HTTPGET,1); - curl_easy_setopt(curl, CURLOPT_TIMEOUT_MS, AMF_CURL_TIMEOUT_MS); - //curl_easy_setopt(curl, CURLOPT_INTERFACE, "eno1:sn11"); //Only for testing in all-in-one scenario - curl_easy_setopt(curl, CURLOPT_POSTFIELDS, body.c_str()); - - res = curl_easy_perform(curl); - - if(res != CURLE_OK) - fprintf(stderr, "curl_easy_perform() failed: %s\n", - curl_easy_strerror(res)); - - curl_easy_cleanup(curl); - } - curl_global_cleanup(); + //add N2 content if available + auto n2_sm_found = sm_context_res->res.n1n2_message_transfer_data.count( + "n2InfoContainer"); + if (n2_sm_found > 0) { + std::string n2_message = sm_context_res->res.get_n2_sm_information(); + //prepare the body content for Curl + create_multipart_related_content(body, json_part, boundary, n1_message, + n2_message); + } else { + //prepare the body content for Curl + create_multipart_related_content(body, json_part, boundary, n1_message, + multipart_related_content_part_e::NAS); + } - */ - - //format string as hex - unsigned char *n1_msg_hex = smf_app_inst->format_string_as_hex(n1_message); + unsigned int str_len = body.length(); + char *data = (char*) malloc(str_len + 1); + memset(data, 0, str_len + 1); + memcpy((void*) data, (void*) body.c_str(), str_len); + curl_global_init(CURL_GLOBAL_ALL); CURL *curl = curl_easy_init(); - //N1N2MessageTransfer Notification URI?? - std::string json_part = context_res_msg.n1n2_message_transfer_data.dump(); - - Logger::smf_n11().debug("Sending message to AMF...."); - if (curl) { CURLcode res = { }; struct curl_slist *headers = nullptr; - struct curl_slist *slist = nullptr; - curl_mime *mime; - curl_mime *alt; - curl_mimepart *part; - //headers = curl_slist_append(headers, "charsets: utf-8"); - headers = curl_slist_append(headers, "content-type: multipart/related"); + headers = curl_slist_append( + headers, "content-type: multipart/related; boundary=----Boundary"); //TODO: update Boundary curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers); - curl_easy_setopt(curl, CURLOPT_URL, context_res_msg.get_amf_url().c_str()); + curl_easy_setopt(curl, CURLOPT_URL, + sm_context_res->res.get_amf_url().c_str()); curl_easy_setopt(curl, CURLOPT_HTTPGET, 1); curl_easy_setopt(curl, CURLOPT_TIMEOUT_MS, AMF_CURL_TIMEOUT_MS); curl_easy_setopt(curl, CURLOPT_INTERFACE, smf_cfg.sbi.if_name.c_str()); - mime = curl_mime_init(curl); - alt = curl_mime_init(curl); - - //part with N1N2MessageTransferReqData (JsonData) - part = curl_mime_addpart(mime); - curl_mime_data(part, json_part.c_str(), CURL_ZERO_TERMINATED); - curl_mime_type(part, "application/json"); - - //N1 SM Container - Logger::smf_n11().debug( - "Add N1 SM Container (NAS) into the message: %s (bytes %d)", - context_res_msg.get_n1_sm_message().c_str(), - context_res_msg.get_n1_sm_message().length() / 2); - part = curl_mime_addpart(mime); - curl_mime_data(part, reinterpret_cast<const char*>(n1_msg_hex), - context_res_msg.get_n1_sm_message().length() / 2); - curl_mime_type(part, "application/vnd.3gpp.5gnas"); - curl_mime_name( - part, - context_res_msg.n1n2_message_transfer_data["n1MessageContainer"]["n1MessageContent"]["contentId"] - .dump().c_str()); - - auto n2_sm_found = context_res_msg.n1n2_message_transfer_data.count( - "n2InfoContainer"); - if (n2_sm_found > 0) { - std::string n2_message = context_res_msg.get_n2_sm_information(); - unsigned char *n2_msg_hex = smf_app_inst->format_string_as_hex( - n2_message); - Logger::smf_n11().debug( - "Add N2 SM Information (NGAP) into the message: %s (bytes %d)", - n2_message.c_str(), n2_message.length() / 2); - part = curl_mime_addpart(mime); - curl_mime_data(part, reinterpret_cast<const char*>(n2_msg_hex), 80); //TODO: n2_message.length()/2 ISSUE need to be solved - curl_mime_type(part, "application/vnd.3gpp.ngap"); - curl_mime_name( - part, - context_res_msg.n1n2_message_transfer_data["n2InfoContainer"]["smInfo"]["n2InfoContent"]["ngapData"]["contentId"] - .dump().c_str()); - } - - curl_easy_setopt(curl, CURLOPT_MIMEPOST, mime); - // Response information. long httpCode = { 0 }; std::unique_ptr<std::string> httpData(new std::string()); - // Hook up data handling function. + // Hook up data handling function curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, &callback); curl_easy_setopt(curl, CURLOPT_WRITEDATA, httpData.get()); + curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, body.length()); + curl_easy_setopt(curl, CURLOPT_POSTFIELDS, data); + res = curl_easy_perform(curl); + curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &httpCode); //get cause from the response @@ -277,7 +192,7 @@ void smf_n11::send_n1n2_message_transfer_request( try { response_data = json::parse(*httpData.get()); } catch (json::exception &e) { - Logger::smf_n11().error("Could not get the cause from the response"); + Logger::smf_n11().warn("Could not get the cause from the response"); //Set the default Cause response_data["cause"] = "504 Gateway Timeout"; } @@ -291,7 +206,7 @@ void smf_n11::send_n1n2_message_transfer_request( itti_msg->set_response_code(httpCode); itti_msg->set_scid(sm_context_res->scid); itti_msg->set_cause(response_data["cause"]); - if (context_res_msg.get_cause() == REQUEST_ACCEPTED) { + if (sm_context_res->res.get_cause() == REQUEST_ACCEPTED) { itti_msg->set_msg_type(PDU_SESSION_ESTABLISHMENT_ACCEPT); } else { itti_msg->set_msg_type(PDU_SESSION_ESTABLISHMENT_REJECT); @@ -308,9 +223,130 @@ void smf_n11::send_n1n2_message_transfer_request( curl_slist_free_all(headers); curl_easy_cleanup(curl); - curl_mime_free(mime); } + curl_global_cleanup(); + free_wrapper((void**) &data); + + /* + //Curl MIME + //format string as hex + unsigned char *n1_msg_hex = smf_app_inst->format_string_as_hex(n1_message); + + CURL *curl = curl_easy_init(); + //N1N2MessageTransfer Notification URI?? + std::string json_part = context_res_msg.n1n2_message_transfer_data.dump(); + + Logger::smf_n11().debug("Sending message to AMF...."); + + if (curl) { + CURLcode res = { }; + struct curl_slist *headers = nullptr; + struct curl_slist *slist = nullptr; + curl_mime *mime; + curl_mime *alt; + curl_mimepart *part; + + //headers = curl_slist_append(headers, "charsets: utf-8"); + headers = curl_slist_append(headers, "content-type: multipart/related"); + curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers); + curl_easy_setopt(curl, CURLOPT_URL, context_res_msg.get_amf_url().c_str()); + curl_easy_setopt(curl, CURLOPT_HTTPGET, 1); + curl_easy_setopt(curl, CURLOPT_TIMEOUT_MS, AMF_CURL_TIMEOUT_MS); + curl_easy_setopt(curl, CURLOPT_INTERFACE, smf_cfg.sbi.if_name.c_str()); + + mime = curl_mime_init(curl); + alt = curl_mime_init(curl); + + //part with N1N2MessageTransferReqData (JsonData) + part = curl_mime_addpart(mime); + curl_mime_data(part, json_part.c_str(), CURL_ZERO_TERMINATED); + curl_mime_type(part, "application/json"); + + //N1 SM Container + Logger::smf_n11().debug( + "Add N1 SM Container (NAS) into the message: %s (bytes %d)", + context_res_msg.get_n1_sm_message().c_str(), + context_res_msg.get_n1_sm_message().length() / 2); + part = curl_mime_addpart(mime); + curl_mime_data(part, reinterpret_cast<const char*>(n1_msg_hex), + context_res_msg.get_n1_sm_message().length() / 2); + curl_mime_type(part, "application/vnd.3gpp.5gnas"); + curl_mime_name( + part, + context_res_msg.n1n2_message_transfer_data["n1MessageContainer"]["n1MessageContent"]["contentId"] + .dump().c_str()); + + auto n2_sm_found = context_res_msg.n1n2_message_transfer_data.count( + "n2InfoContainer"); + if (n2_sm_found > 0) { + std::string n2_message = context_res_msg.get_n2_sm_information(); + unsigned char *n2_msg_hex = smf_app_inst->format_string_as_hex( + n2_message); + Logger::smf_n11().debug( + "Add N2 SM Information (NGAP) into the message: %s (bytes %d)", + n2_message.c_str(), n2_message.length() / 2); + part = curl_mime_addpart(mime); + curl_mime_data(part, reinterpret_cast<const char*>(n2_msg_hex), 80); //TODO: n2_message.length()/2 ISSUE need to be solved + curl_mime_type(part, "application/vnd.3gpp.ngap"); + curl_mime_name( + part, + context_res_msg.n1n2_message_transfer_data["n2InfoContainer"]["smInfo"]["n2InfoContent"]["ngapData"]["contentId"] + .dump().c_str()); + } + + curl_easy_setopt(curl, CURLOPT_MIMEPOST, mime); + + // Response information. + long httpCode = { 0 }; + std::unique_ptr<std::string> httpData(new std::string()); + + // Hook up data handling function. + curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, &callback); + curl_easy_setopt(curl, CURLOPT_WRITEDATA, httpData.get()); + + res = curl_easy_perform(curl); + curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &httpCode); + + //get cause from the response + json response_data = { }; + try { + response_data = json::parse(*httpData.get()); + } catch (json::exception &e) { + Logger::smf_n11().error("Could not get the cause from the response"); + //Set the default Cause + response_data["cause"] = "504 Gateway Timeout"; + } + Logger::smf_n11().debug("Response from AMF, Http Code: %d, cause %s", + httpCode, response_data["cause"].dump().c_str()); + + //send response to APP to process + itti_n11_n1n2_message_transfer_response_status *itti_msg = + new itti_n11_n1n2_message_transfer_response_status(TASK_SMF_N11, + TASK_SMF_APP); + itti_msg->set_response_code(httpCode); + itti_msg->set_scid(sm_context_res->scid); + itti_msg->set_cause(response_data["cause"]); + if (context_res_msg.get_cause() == REQUEST_ACCEPTED) { + itti_msg->set_msg_type(PDU_SESSION_ESTABLISHMENT_ACCEPT); + } else { + itti_msg->set_msg_type(PDU_SESSION_ESTABLISHMENT_REJECT); + } + std::shared_ptr<itti_n11_n1n2_message_transfer_response_status> i = + std::shared_ptr<itti_n11_n1n2_message_transfer_response_status>( + itti_msg); + int ret = itti_inst->send_msg(i); + if (RETURNok != ret) { + Logger::smf_n11().error( + "Could not send ITTI message %s to task TASK_SMF_APP", + i->get_msg_name()); + } + + curl_slist_free_all(headers); + curl_easy_cleanup(curl); + curl_mime_free(mime); + } + */ } //------------------------------------------------------------------------------ diff --git a/src/smf_app/smf_n1_n2.cpp b/src/smf_app/smf_n1_n2.cpp index 6cd7c99a5af264770acf1b11e8b60b8b16f30304..c93647e2c79760a63e1ebe76c032725d1f263490 100644 --- a/src/smf_app/smf_n1_n2.cpp +++ b/src/smf_app/smf_n1_n2.cpp @@ -109,7 +109,7 @@ void smf_n1_n2::create_n1_sm_container(pdu_session_msg &msg, //Extended Protocol Discriminator sm_msg->header.extended_protocol_discriminator = EPD_5GS_SESSION_MANAGEMENT_MESSAGES; - //Message Type + //PDU Session Identity sm_msg->header.pdu_session_identity = msg.get_pdu_session_id(); switch (n1_msg_type) { @@ -131,7 +131,6 @@ void smf_n1_n2::create_n1_sm_container(pdu_session_msg &msg, //get default QoS value qos_flow_context_updated qos_flow = { }; qos_flow = sm_context_res.get_qos_flow_context(); - //TODO: to be completed //get the default QoS profile and assign to the NAS message @@ -156,7 +155,7 @@ void smf_n1_n2::create_n1_sm_container(pdu_session_msg &msg, sm_msg->header.procedure_transaction_identity, sm_msg->header.message_type); - //Fill the content of PDU Session Establishment Request message + //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(); @@ -277,10 +276,12 @@ void smf_n1_n2::create_n1_sm_container(pdu_session_msg &msg, .get_snssai().sST; try { - sm_msg->pdu_session_establishment_accept.snssai.sd = std::stoi( - sm_context_res.get_snssai().sD); + 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()); + 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; } @@ -358,7 +359,7 @@ void smf_n1_n2::create_n1_sm_container(pdu_session_msg &msg, //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 + //PDU_SESSION_CREATE_SM_CONTEXT_RESPONSE or PDU_SESSION_CREATE_SM_CONTEXT_REQUEST Logger::smf_app().info( "PDU_SESSION_ESTABLISHMENT_REJECT, encode starting..."); @@ -386,7 +387,8 @@ void smf_n1_n2::create_n1_sm_container(pdu_session_msg &msg, sm_msg->pdu_session_establishment_reject._5gsmcause = static_cast<uint8_t>(sm_cause); //Presence - sm_msg->pdu_session_establishment_reject.presence = 0x00; + 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 = @@ -436,8 +438,6 @@ void smf_n1_n2::create_n1_sm_container(pdu_session_msg &msg, .is_ssc2_allowed, sm_msg->pdu_session_establishment_reject.allowedsscmode .is_ssc3_allowed); - //Logger::smf_app().debug("SM MSG, GPSR Timer3, unit: 0x%x, value: 0x%x",sm_msg->pdu_session_establishment_reject.gprstimer3.unit,sm_msg->pdu_session_establishment_reject.gprstimer3.timeValue); - //Logger::smf_app().debug("SM MSG, 5G SM Congestion Re-attempt Indicator: 0x%x",sm_msg->pdu_session_establishment_reject._5gsmcongestionreattemptindicator.abo); //Encode NAS message bytes = nas_message_encode(data, &nas_msg, @@ -455,7 +455,7 @@ void smf_n1_n2::create_n1_sm_container(pdu_session_msg &msg, break; case PDU_SESSION_MODIFICATION_COMMAND: { - //PDU Session Modification Command is included in the following msgs: + //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)) ​ @@ -469,19 +469,35 @@ void smf_n1_n2::create_n1_sm_container(pdu_session_msg &msg, "PDU_SESSION_MODIFICATION_COMMAND, encode starting..."); //Fill the content of PDU Session Establishment Request message with hardcoded values (to be completed) - //Message Type - sm_msg->header.message_type = PDU_SESSION_MODIFICATION_COMMAND; //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; //PDU Session Type sm_msg->pdu_session_modification_command.messagetype = sm_context_res .get_msg_type(); //Presence sm_msg->pdu_session_modification_command.presence = 0xff; //TODO: to be updated //5GSMCause - sm_msg->pdu_session_modification_command._5gsmcause = sm_context_res - .get_cause(); + sm_msg->pdu_session_modification_command._5gsmcause = + static_cast<uint8_t>(sm_cause); //sm_context_res.get_cause(); + + /* + ExtendedProtocolDiscriminator extendedprotocoldiscriminator; + PDUSessionIdentity pdusessionidentity; + ProcedureTransactionIdentity proceduretransactionidentity; + MessageType messagetype; + uint8_t presence; + _5GSMCause _5gsmcause; + SessionAMBR sessionambr; + GPRSTimer gprstimer; + AlwaysonPDUSessionIndication alwaysonpdusessionindication; + QOSRules qosrules; + MappedEPSBearerContexts mappedepsbearercontexts; + QOSFlowDescriptions qosflowdescriptions; + ExtendedProtocolConfigurationOptions extendedprotocolconfigurationoptions; + */ //SessionAMBR //TODO: get from subscription DB @@ -590,7 +606,6 @@ void smf_n1_n2::create_n1_sm_container(pdu_session_msg &msg, //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) - //TODO: to be completed Logger::smf_app().debug( "[Create N1 SM Message] PDU Session Release Command"); @@ -599,26 +614,68 @@ void smf_n1_n2::create_n1_sm_container(pdu_session_msg &msg, 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 (with hardcoded values) - //Message Type - sm_msg->header.message_type = PDU_SESSION_RELEASE_COMMAND; + //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; - //PDU Session Type - sm_msg->pdu_session_release_command.messagetype = sm_context_res - .get_msg_type(); + //Message Type + sm_msg->header.message_type = PDU_SESSION_RELEASE_COMMAND; //5GSMCause sm_msg->pdu_session_release_command._5gsmcause = - sm_context_res.get_cause(); + static_cast<uint8_t>(sm_cause); //sm_context_res.get_cause(); //Presence - sm_msg->pdu_session_modification_command.presence = 0x00; //TODO: to be updated - + 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 MSG, 5GSM Cause: 0x%x, %d", + sm_msg->pdu_session_release_command._5gsmcause, + static_cast<uint8_t>(sm_cause)); + + //Encode NAS message + bytes = nas_message_encode(data, &nas_msg, + sizeof(data)/*don't know the size*/, nullptr); + + Logger::smf_app().debug("Buffer Data: "); + for (int i = 0; i < bytes; i++) + printf("%02x ", data[i]); + printf(" (bytes %d)\n", bytes); + + 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); @@ -1505,3 +1562,33 @@ int smf_n1_n2::decode_n2_sm_information( } +//--------------------------------------------------------------------------------------------- +int smf_n1_n2::decode_n2_sm_information( + std::shared_ptr<Ngap_PDUSessionResourceReleaseResponseTransfer_t> &ngap_IE, + std::string &n2_sm_info) { + 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_api_server().warn("asn_decode failed with code %d", rc.code); + + return RETURNerror ; + } + return RETURNok ; + +} + diff --git a/src/smf_app/smf_n1_n2.hpp b/src/smf_app/smf_n1_n2.hpp index 8f38869971a9a37b077564515d2bcee00e90a7b1..e864c32a17e18f907f5c5510af1b95aea11f1f90 100644 --- a/src/smf_app/smf_n1_n2.hpp +++ b/src/smf_app/smf_n1_n2.hpp @@ -56,6 +56,7 @@ extern "C" { #include "Ngap_NGAP-PDU.h" #include "Ngap_PDUSessionResourceSetupResponseTransfer.h" #include "Ngap_PDUSessionResourceModifyResponseTransfer.h" +#include "Ngap_PDUSessionResourceReleaseResponseTransfer.h" } namespace smf { @@ -121,6 +122,16 @@ class smf_n1_n2 { std::shared_ptr<Ngap_PDUSessionResourceModifyResponseTransfer_t> &ngap_IE, std::string &n2_sm_info); + /* + * Decode N2 SM Information Ngap_PDUSessionResourceReleaseResponseTransfer_t + * @param [std::shared_ptr<Ngap_PDUSessionResourceReleaseResponseTransfer_t>&] ngap_IE Store decoded NGAP message + * @param [std::string&] n2_sm_info N2 SM Information + * @return status of the decode process + */ + int decode_n2_sm_information( + std::shared_ptr<Ngap_PDUSessionResourceReleaseResponseTransfer_t> &ngap_IE, + std::string &n2_sm_info); + }; } // namespace smf diff --git a/src/smf_app/smf_procedure.cpp b/src/smf_app/smf_procedure.cpp index 4b8ab3d32927cc64bb84796977a8e812e4307a56..bdbd1b809582a10a5df1fb5671aeca9de14cae8d 100644 --- a/src/smf_app/smf_procedure.cpp +++ b/src/smf_app/smf_procedure.cpp @@ -389,8 +389,7 @@ void session_create_sm_context_procedure::handle_itti_msg( Logger::smf_app().debug( "Prepare a PDU Session Establishment Accept message and send to UE"); smf_n1_n2_inst.create_n1_sm_container(n11_triggered_pending->res, - PDU_SESSION_ESTABLISHMENT_ACCEPT, - n1_sm_msg, + PDU_SESSION_ESTABLISHMENT_ACCEPT, n1_sm_msg, cause_value_5gsm_e::CAUSE_0_UNKNOWN); //TODO: need cause? 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); @@ -1100,6 +1099,7 @@ void session_update_sm_context_procedure::handle_itti_msg( 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); n11_triggered_pending->res.set_n1_sm_message(n1_sm_msg_hex); + //N2 SM Information smf_n1_n2_inst.create_n2_sm_information( n11_triggered_pending->res, 1, n2_sm_info_type_e::PDU_RES_REL_CMD, diff --git a/src/test/amf/amf-api-server.cpp b/src/test/amf/amf-api-server.cpp index e7702800f6c4f7a8f33876f1034e7f8ffba92331..0c5d85fc5890b3a7077b01117447071cb48f8ad3 100644 --- a/src/test/amf/amf-api-server.cpp +++ b/src/test/amf/amf-api-server.cpp @@ -127,6 +127,8 @@ int main(int argc, char* argv[]) { SubscriptionsCollectionDocumentApiImpl SubscriptionsCollectionDocumentApiserver(router); SubscriptionsCollectionDocumentApiserver.init(); + std::cout << "AMF server is listening on address: " << amf_ip_address.c_str() << std::endl; + httpEndpoint->setHandler(router->handler()); httpEndpoint->serve(); diff --git a/src/test/amf_client/amf-client.cpp b/src/test/amf_client/amf-client.cpp index 7e1126d829cde3a17810a939669e1b3855f14953..8f6e6536324e677bebe0e79de736521d8c72130b 100644 --- a/src/test/amf_client/amf-client.cpp +++ b/src/test/amf_client/amf-client.cpp @@ -1,18 +1,15 @@ - #include <curl/curl.h> #include <nlohmann/json.hpp> #include <iostream> #include <string> #include <unistd.h> +#include <stdexcept> + /* * To read content of the response from UDM */ -static std::size_t callback( - const char* in, - std::size_t size, - std::size_t num, - std::string* out) -{ +static std::size_t callback(const char *in, std::size_t size, std::size_t num, + std::string *out) { const std::size_t totalBytes(size * num); out->append(in, totalBytes); return totalBytes; @@ -22,35 +19,180 @@ static std::size_t callback( *(uint8_t*)(buffer) = value; \ size += sizeof(uint8_t) -void send_pdu_session_establishment_request(std::string smf_ip_address) -{ - std::cout << "[AMF N11] PDU Session Establishment Request (SM Context Create)"<<std::endl; +static const char hex_to_ascii_table[16] = { '0', '1', '2', '3', '4', '5', '6', + '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f', }; + +static const signed char ascii_to_hex_table[0x100] = { -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -1, -1, -1, -1, -1, -1, -1, + 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 10, 11, 12, 13, 14, 15, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1 }; + +int ascii_to_hex(uint8_t *dst, const char *h) { + const unsigned char *hex = (const unsigned char*) h; + unsigned i = 0; + + for (;;) { + int high, low; + + while (*hex && isspace(*hex)) + hex++; + + if (!*hex) + return 1; + + high = ascii_to_hex_table[*hex++]; + + if (high < 0) + return 0; + + while (*hex && isspace(*hex)) + hex++; + + if (!*hex) + return 0; + + low = ascii_to_hex_table[*hex++]; + + if (low < 0) + return 0; + + dst[i++] = (high << 4) | low; + } +} + +enum class multipart_related_content_part_e { + JSON = 0, + NAS = 1, + NGAP = 2 +}; + +//------------------------------------------------------------------------------ +unsigned char* format_string_as_hex(std::string str) { + unsigned int str_len = str.length(); + char *data = (char*) malloc(str_len + 1); + memset(data, 0, str_len + 1); + memcpy((void*) data, (void*) str.c_str(), str_len); + + unsigned char *data_hex = (uint8_t*) malloc(str_len / 2 + 1); + ascii_to_hex(data_hex, (const char*) data); + + std::cout << "[Format string as Hex] Input string" << str.c_str() << "(" + << str_len << " bytes)" << std::endl; + std::cout << "Data (formatted):" << std::endl; + + for (int i = 0; i < str_len / 2; i++) + printf(" %02x ", data_hex[i]); + printf("\n"); + + //free memory + free(data); + + return data_hex; + +} + +//------------------------------------------------------------------------------ +void create_multipart_related_content(std::string &body, std::string &json_part, + std::string &boundary, + std::string &n1_message, + std::string &n2_message) { + + //format string as hex + //unsigned char *n1_msg_hex = format_string_as_hex(n1_message); + //unsigned char *n2_msg_hex = format_string_as_hex(n2_message); + + std::string CRLF = "\r\n"; + body.append("--" + boundary + CRLF); + body.append("Content-Type: application/json" + CRLF); + body.append(CRLF); + body.append(json_part + CRLF); + + body.append("--" + boundary + CRLF); + body.append( + "Content-Type: application/vnd.3gpp.5gnas" + CRLF + "Content-Id: n1SmMsg" + + CRLF); + body.append(CRLF); + //body.append(std::string((char*) n1_msg_hex, n1_message.length() / 2) + CRLF); + body.append(n1_message + CRLF); + + body.append("--" + boundary + CRLF); + body.append( + "Content-Type: application/vnd.3gpp.ngap" + CRLF + "Content-Id: n2SmMsg" + + CRLF); + body.append(CRLF); + //body.append(std::string((char*) n2_msg_hex, n2_message.length() / 2) + CRLF); + body.append(n2_message + CRLF); + body.append("--" + boundary + "--" + CRLF); +} + +//------------------------------------------------------------------------------ +void create_multipart_related_content( + std::string &body, std::string &json_part, std::string &boundary, + std::string &message, multipart_related_content_part_e content_type) { + + //format string as hex + //unsigned char *msg_hex = format_string_as_hex(message); + + std::string CRLF = "\r\n"; + body.append("--" + boundary + CRLF); + body.append("Content-Type: application/json" + CRLF); + body.append(CRLF); + body.append(json_part + CRLF); + + body.append("--" + boundary + CRLF); + if (content_type == multipart_related_content_part_e::NAS) { //NAS + body.append( + "Content-Type: application/vnd.3gpp.5gnas" + CRLF + + "Content-Id: n1SmMsg" + CRLF); + } else if (content_type == multipart_related_content_part_e::NGAP) { //NGAP + body.append( + "Content-Type: application/vnd.3gpp.ngap" + CRLF + "Content-Id: n2SmMsg" + + CRLF); + } + body.append(CRLF); + //body.append(std::string((char*) msg_hex, message.length() / 2) + CRLF); + body.append(message + CRLF); + body.append("--" + boundary + "--" + CRLF); +} + +//------------------------------------------------------------------------------ +void send_pdu_session_establishment_request(std::string smf_ip_address) { + std::cout << "[AMF N11] PDU Session Establishment Request (SM Context Create)" + << std::endl; nlohmann::json pdu_session_establishment_request; - //encode - // PDU Session Establishment Request + //encode PDU Session Establishment Request /* - 0000 2e 01 01 c1 ff ff 91 00 00 00 00 00 00 00 00 00 + 0000 2e 01 01 c1 ff ff 91 00 00 00 00 00 00 00 00 00 */ size_t buffer_size = 128; - char *buffer = (char *)calloc(1,buffer_size); - int size = 0; - ENCODE_U8 (buffer, 0x2e , size); //ExtendedProtocolDiscriminator - ENCODE_U8 (buffer+size, 0x01 , size); //PDUSessionIdentity - ENCODE_U8 (buffer+size, 0x01 , size); //ProcedureTransactionIdentity - ENCODE_U8 (buffer+size, 0xc1 , size); //MessageType - PDU_SESSION_ESTABLISHMENT_REQUEST - ENCODE_U8 (buffer+size, 0xff , size); //Integrity Protection Maximum Data Rate - ENCODE_U8 (buffer+size, 0xff , size); //Integrity Protection Maximum Data Rate - ENCODE_U8 (buffer+size, 0x91 , size); //01 PDU Session Type - Ipv4 - - std::cout << "Buffer: "<<std::endl; - for(int i=0;i<size;i++) - { + char *buffer = (char*) calloc(1, buffer_size); + int size = 0; + ENCODE_U8(buffer, 0x2e, size); //ExtendedProtocolDiscriminator + ENCODE_U8(buffer + size, 0x01, size); //PDUSessionIdentity + ENCODE_U8(buffer + size, 0x01, size); //ProcedureTransactionIdentity + ENCODE_U8(buffer + size, 0xc1, size); //MessageType - PDU_SESSION_ESTABLISHMENT_REQUEST + ENCODE_U8(buffer + size, 0xff, size); //Integrity Protection Maximum Data Rate + ENCODE_U8(buffer + size, 0xff, size); //Integrity Protection Maximum Data Rate + ENCODE_U8(buffer + size, 0x91, size); //01 PDU Session Type - Ipv4 + + std::cout << "Buffer: " << std::endl; + for (int i = 0; i < size; i++) { printf("%02x ", buffer[i]); } - std::cout << "Buffer: "<<std::endl; + std::cout << "Buffer: " << std::endl; - //Fill Json part std::string url = std::string("http://"); url.append(smf_ip_address); url.append(std::string("/nsmf-pdusession/v2/sm-contexts")); @@ -59,7 +201,7 @@ void send_pdu_session_establishment_request(std::string smf_ip_address) pdu_session_establishment_request["supi"] = "imsi-200000000000001"; pdu_session_establishment_request["pei"] = "imei-200000000000001"; pdu_session_establishment_request["gpsi"] = "msisdn-200000000001"; - pdu_session_establishment_request["dnn"] = "carrier.com"; + pdu_session_establishment_request["dnn"] = "default"; pdu_session_establishment_request["sNssai"]["sst"] = 222; pdu_session_establishment_request["sNssai"]["sd"] = "0000D4"; pdu_session_establishment_request["pduSessionId"] = 1; @@ -68,499 +210,463 @@ void send_pdu_session_establishment_request(std::string smf_ip_address) pdu_session_establishment_request["servingNetwork"]["mcc"] = "234"; pdu_session_establishment_request["servingNetwork"]["mnc"] = "067"; pdu_session_establishment_request["anType"] = "3GPP_ACCESS"; - pdu_session_establishment_request["smContextStatusUri"] = "smContextStatusUri"; - pdu_session_establishment_request["n1SmMsg"]["contentId"] = "n1SmMsg"; // NAS + pdu_session_establishment_request["smContextStatusUri"] = + "smContextStatusUri"; + pdu_session_establishment_request["n1SmMsg"]["contentId"] = "n1SmMsg"; // NAS + std::string body; + std::string boundary = "----Boundary"; + std::string json_part = pdu_session_establishment_request.dump(); + std::string n1_msg(reinterpret_cast<const char*>(buffer), size); - CURL *curl = curl_easy_init(); + create_multipart_related_content(body, json_part, boundary, n1_msg, + multipart_related_content_part_e::NAS); - std::string json_part = pdu_session_establishment_request.dump(); + unsigned char *data = (unsigned char*) malloc(body.length() + 1); + memset(data, 0, body.length() + 1); + memcpy((void*) data, (void*) body.c_str(), body.length()); - std::cout<< "Sending message to SMF....\n"; - if(curl) { - CURLcode res; - struct curl_slist *headers = nullptr; - struct curl_slist *slist = nullptr; - curl_mime *mime; - curl_mime *alt; - curl_mimepart *part; + curl_global_init(CURL_GLOBAL_ALL); + CURL *curl = curl = curl_easy_init(); + if (curl) { + CURLcode res = { }; + struct curl_slist *headers = nullptr; //headers = curl_slist_append(headers, "charsets: utf-8"); - headers = curl_slist_append(headers, "content-type: multipart/related"); + headers = curl_slist_append( + headers, "content-type: multipart/related; boundary=----Boundary"); curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers); curl_easy_setopt(curl, CURLOPT_URL, url.c_str()); - curl_easy_setopt(curl, CURLOPT_HTTPGET,1); + curl_easy_setopt(curl, CURLOPT_HTTPGET, 1); curl_easy_setopt(curl, CURLOPT_TIMEOUT_MS, 100L); - //curl_easy_setopt(curl, CURLOPT_INTERFACE, "eno1:amf"); //hardcoded - - mime = curl_mime_init(curl); - alt = curl_mime_init(curl); - - //part with N1N2MessageTransferReqData (JsonData) - part = curl_mime_addpart(mime); - curl_mime_data(part, json_part.c_str(), CURL_ZERO_TERMINATED); - curl_mime_type(part, "application/json"); - - part = curl_mime_addpart(mime); - //curl_mime_data(part, reinterpret_cast<const char*>(n1_msg_hex), CURL_ZERO_TERMINATED); - curl_mime_data(part, reinterpret_cast<const char*>(buffer), size); - curl_mime_type(part, "application/vnd.3gpp.5gnas"); - curl_mime_name (part, "n1SmMsg"); - - curl_easy_setopt(curl, CURLOPT_MIMEPOST, mime); + //curl_easy_setopt(curl, CURLOPT_INTERFACE, "eno1:amf"); //hardcoded // Response information. - long httpCode(0); + long httpCode = { 0 }; std::unique_ptr<std::string> httpData(new std::string()); - // Hook up data handling function. curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, &callback); curl_easy_setopt(curl, CURLOPT_WRITEDATA, httpData.get()); + curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, body.length()); + curl_easy_setopt(curl, CURLOPT_POSTFIELDS, data); + res = curl_easy_perform(curl); + curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &httpCode); //get cause from the response nlohmann::json response_data; - try{ + try { response_data = nlohmann::json::parse(*httpData.get()); - } catch (nlohmann::json::exception& e){ - std::cout << "Could not get the cause from the response" <<std::endl; - + } catch (nlohmann::json::exception &e) { + std::cout << "Could not get json data from the response" << std::endl; } - std::cout << "[AMF N11] PDU session establishment request, response from SMF, Http Code " << httpCode <<std::endl; + std::cout + << "[AMF N11] PDU session establishment request, response from SMF, Http Code " + << httpCode << std::endl; - curl_slist_free_all(headers); curl_easy_cleanup(curl); - curl_mime_free(mime); } + curl_global_cleanup(); + free(buffer); } - -void send_pdu_session_update_sm_context_establishment(std::string smf_ip_address) -{ - std::cout << "[AMF N11] PDU Session Establishment Request (SM Context Update)"<<std::endl; +//------------------------------------------------------------------------------ +void send_pdu_session_update_sm_context_establishment( + std::string smf_ip_address) { + std::cout << "[AMF N11] PDU Session Establishment Request (SM Context Update)" + << std::endl; nlohmann::json pdu_session_update_request; - - //encode - //PDU Session Resource Setup Response Transfer IE + //encode PDU Session Resource Setup Response Transfer IE /* - 00 03 e0 ac 0a 05 01 00 00 00 01 00 3c + 00 03 e0 ac 0a 05 01 00 00 00 01 00 3c */ size_t buffer_size = 128; - char *buffer = (char *)calloc(1,buffer_size); - int size = 0; - ENCODE_U8 (buffer, 0x00 , size); - ENCODE_U8 (buffer+size, 0x03 , size); - ENCODE_U8 (buffer+size, 0xe0 , size); - ENCODE_U8 (buffer+size, 0xac , size); //uPTransportLayerInformation IP Addr 172.10.5.1: 172. - ENCODE_U8 (buffer+size, 0x0a , size); //10 - ENCODE_U8 (buffer+size, 0x05 , size); //.5 - ENCODE_U8 (buffer+size, 0x01 , size); //.1 - ENCODE_U8 (buffer+size, 0x00 , size); //gTP_TEID 00 00 00 01: 00 - ENCODE_U8 (buffer+size, 0x00 , size); //00 - ENCODE_U8 (buffer+size, 0x00 , size); //00 - ENCODE_U8 (buffer+size, 0x01 , size); //01 - ENCODE_U8 (buffer+size, 0x00 , size); //Associated QoS Flow 00 3c - ENCODE_U8 (buffer+size, 0x3c , size); //QFI: 60 - - std::cout << "Buffer: "<<std::endl; - for(int i=0;i<2;i++) - { + char *buffer = (char*) calloc(1, buffer_size); + int size = 0; + ENCODE_U8(buffer, 0x00, size); + ENCODE_U8(buffer + size, 0x03, size); + ENCODE_U8(buffer + size, 0xe0, size); + ENCODE_U8(buffer + size, 0xac, size); //uPTransportLayerInformation IP Addr 172.10.5.1: 172. + ENCODE_U8(buffer + size, 0x0a, size); //10 + ENCODE_U8(buffer + size, 0x05, size); //.5 + ENCODE_U8(buffer + size, 0x01, size); //.1 + ENCODE_U8(buffer + size, 0x00, size); //gTP_TEID 00 00 00 01: 00 + ENCODE_U8(buffer + size, 0x00, size); //00 + ENCODE_U8(buffer + size, 0x00, size); //00 + ENCODE_U8(buffer + size, 0x01, size); //01 + ENCODE_U8(buffer + size, 0x00, size); //Associated QoS Flow 00 3c + ENCODE_U8(buffer + size, 0x3c, size); //QFI: 60 + + std::cout << "Buffer: " << std::endl; + for (int i = 0; i < size; i++) { printf("%02x ", buffer[i]); } - std::cout << "Buffer: "<<std::endl; + std::cout << "Buffer: " << std::endl; - //Fill Json part std::string url = std::string("http://"); url.append(smf_ip_address); url.append(std::string("/nsmf-pdusession/v2/sm-contexts/1/modify")); //Fill the json part pdu_session_update_request["n2SmInfoType"] = "PDU_RES_SETUP_RSP"; - pdu_session_update_request["n2SmInfo"]["contentId"] = "n2SmMsg"; //NGAP + pdu_session_update_request["n2SmInfo"]["contentId"] = "n2SmMsg"; //NGAP - CURL *curl = curl_easy_init(); + //pdu_session_update_request["n2InfoContainer"]["n2InformationClass"] = "SM"; + //pdu_session_update_request["n2InfoContainer"]["smInfo"]["n2InfoContent"]["ngapData"]["contentId"] = "n2SmMsg"; + // pdu_session_update_request["n2InfoContainer"]["smInfo"]["n2InfoContent"]["ngapIeType"] = + // "PDU_RES_SETUP_RSP"; //NGAP message + std::string body; + std::string boundary = "----Boundary"; std::string json_part = pdu_session_update_request.dump(); + std::string n2_msg(reinterpret_cast<const char*>(buffer), size); - std::cout<< "Sending message to SMF....\n"; - if(curl) { + create_multipart_related_content(body, json_part, boundary, n2_msg, + multipart_related_content_part_e::NGAP); - CURLcode res; - struct curl_slist *headers = nullptr; - struct curl_slist *slist = nullptr; - curl_mime *mime; - curl_mime *alt; - curl_mimepart *part; + unsigned char *data = (unsigned char*) malloc(body.length() + 1); + memset(data, 0, body.length() + 1); + memcpy((void*) data, (void*) body.c_str(), body.length()); + + curl_global_init(CURL_GLOBAL_ALL); + CURL *curl = curl = curl_easy_init(); - headers = curl_slist_append(headers, "charsets: utf-8"); - headers = curl_slist_append(headers, "content-type: multipart/related"); + if (curl) { + CURLcode res = { }; + struct curl_slist *headers = nullptr; + //headers = curl_slist_append(headers, "charsets: utf-8"); + headers = curl_slist_append( + headers, "content-type: multipart/related; boundary=----Boundary"); curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers); curl_easy_setopt(curl, CURLOPT_URL, url.c_str()); - curl_easy_setopt(curl, CURLOPT_HTTPGET,1); + curl_easy_setopt(curl, CURLOPT_HTTPGET, 1); curl_easy_setopt(curl, CURLOPT_TIMEOUT_MS, 100L); - //curl_easy_setopt(curl, CURLOPT_INTERFACE, "eno1:amf"); //hardcoded - - - mime = curl_mime_init(curl); - alt = curl_mime_init(curl); - - //part with N1N2MessageTransferReqData (JsonData) - part = curl_mime_addpart(mime); - curl_mime_data(part, json_part.c_str(), CURL_ZERO_TERMINATED); - curl_mime_type(part, "application/json"); - - part = curl_mime_addpart(mime); - curl_mime_data(part, reinterpret_cast<const char*>(buffer), size); - - curl_mime_type(part, "application/vnd.3gpp.ngap"); - curl_mime_name (part, "n2SmMsg"); - - curl_easy_setopt(curl, CURLOPT_MIMEPOST, mime); + //curl_easy_setopt(curl, CURLOPT_INTERFACE, "eno1:amf"); //hardcoded // Response information. - long httpCode(0); + long httpCode = { 0 }; std::unique_ptr<std::string> httpData(new std::string()); - // Hook up data handling function. curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, &callback); curl_easy_setopt(curl, CURLOPT_WRITEDATA, httpData.get()); + curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, body.length()); + curl_easy_setopt(curl, CURLOPT_POSTFIELDS, data); + res = curl_easy_perform(curl); + curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &httpCode); //get cause from the response nlohmann::json response_data; - try{ + try { response_data = nlohmann::json::parse(*httpData.get()); - } catch (nlohmann::json::exception& e){ - std::cout << "Could not get the cause from the response" <<std::endl; + } catch (nlohmann::json::exception &e) { + std::cout << "Could not get json data from the response" << std::endl; //Set the default Cause response_data["cause"] = "504 Gateway Timeout"; + } - std::cout << "[AMF N11] PDU Session Establishment Request, response from SMF, Http Code " << httpCode << " cause "<< response_data["cause"].dump().c_str()<<std::endl; + std::cout + << "[AMF N11] PDU Session Establishment Request, response from SMF, Http Code " + << httpCode << " cause " << response_data["cause"].dump().c_str() + << std::endl; - curl_slist_free_all(headers); curl_easy_cleanup(curl); - curl_mime_free(mime); } + curl_global_cleanup(); + free(buffer); } +//------------------------------------------------------------------------------ +void send_pdu_session_release_request(std::string smf_ip_address) { -void send_pdu_session_release_request(std::string smf_ip_address) -{ - std::cout << "[AMF N11] PDU Session Release Request (SM Context Update)"<<std::endl; + std::cout << "[AMF N11] PDU Session Release Request (SM Context Update)" + << std::endl; nlohmann::json pdu_session_release_request; - //encode + //encode PDU Session Release Request /* - 0000 2e 01 01 d1 00 00 00 00 00 00 00 00 00 00 00 00 + 0000 2e 01 01 d1 00 00 00 00 00 00 00 00 00 00 00 00 */ size_t buffer_size = 128; - char *buffer = (char *)calloc(1,buffer_size); - int size = 0; - ENCODE_U8 (buffer, 0x2e , size); //ExtendedProtocolDiscriminator - ENCODE_U8 (buffer+size, 0x01 , size); //PDUSessionIdentity - ENCODE_U8 (buffer+size, 0x01 , size); //ProcedureTransactionIdentity - ENCODE_U8 (buffer+size, 0xd1 , size); //MessageType - ENCODE_U8 (buffer+size, 0x00 , size); //presence - - std::cout << "Buffer: "<<std::endl; - for(int i=0;i<size;i++) - { + char *buffer = (char*) calloc(1, buffer_size); + int size = 0; + ENCODE_U8(buffer, 0x2e, size); //ExtendedProtocolDiscriminator + ENCODE_U8(buffer + size, 0x01, size); //PDUSessionIdentity + ENCODE_U8(buffer + size, 0x01, size); //ProcedureTransactionIdentity + ENCODE_U8(buffer + size, 0xd1, size); //MessageType + ENCODE_U8(buffer + size, 0x00, size); //presence + + std::cout << "Buffer: " << std::endl; + for (int i = 0; i < size; i++) { printf("%02x ", buffer[i]); } - std::cout << "Buffer: "<<std::endl; + std::cout << "Buffer: " << std::endl; - //Fill Json part std::string url = std::string("http://"); url.append(smf_ip_address); url.append(std::string("/nsmf-pdusession/v2/sm-contexts/1/modify")); //Fill the json part - pdu_session_release_request["cause"] = "INSUFFICIENT_UP_RESOURCES"; //need to be updated - pdu_session_release_request["n1SmMsg"]["contentId"] = "n1SmMsg"; // NAS - - CURL *curl = curl_easy_init(); + pdu_session_release_request["cause"] = "INSUFFICIENT_UP_RESOURCES"; //need to be updated + pdu_session_release_request["n1SmMsg"]["contentId"] = "n1SmMsg"; // NAS + std::string body; + std::string boundary = "----Boundary"; std::string json_part = pdu_session_release_request.dump(); + std::string n1_msg(reinterpret_cast<const char*>(buffer), size); - std::cout<< "Sending message to SMF....\n"; - if(curl) { - CURLcode res; - struct curl_slist *headers = nullptr; - struct curl_slist *slist = nullptr; - curl_mime *mime; - curl_mime *alt; - curl_mimepart *part; + create_multipart_related_content(body, json_part, boundary, n1_msg, + multipart_related_content_part_e::NAS); + unsigned char *data = (unsigned char*) malloc(body.length() + 1); + memset(data, 0, body.length() + 1); + memcpy((void*) data, (void*) body.c_str(), body.length()); + + curl_global_init(CURL_GLOBAL_ALL); + CURL *curl = curl = curl_easy_init(); + + if (curl) { + CURLcode res = { }; + struct curl_slist *headers = nullptr; //headers = curl_slist_append(headers, "charsets: utf-8"); - headers = curl_slist_append(headers, "content-type: multipart/related"); + headers = curl_slist_append( + headers, "content-type: multipart/related; boundary=----Boundary"); curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers); curl_easy_setopt(curl, CURLOPT_URL, url.c_str()); - curl_easy_setopt(curl, CURLOPT_HTTPGET,1); + curl_easy_setopt(curl, CURLOPT_HTTPGET, 1); curl_easy_setopt(curl, CURLOPT_TIMEOUT_MS, 100L); - //curl_easy_setopt(curl, CURLOPT_INTERFACE, "eno1:amf"); //hardcoded - - mime = curl_mime_init(curl); - alt = curl_mime_init(curl); - - //part with N1N2MessageTransferReqData (JsonData) - part = curl_mime_addpart(mime); - curl_mime_data(part, json_part.c_str(), CURL_ZERO_TERMINATED); - curl_mime_type(part, "application/json"); - - part = curl_mime_addpart(mime); - //curl_mime_data(part, reinterpret_cast<const char*>(n1_msg_hex), CURL_ZERO_TERMINATED); - curl_mime_data(part, reinterpret_cast<const char*>(buffer), size); - curl_mime_type(part, "application/vnd.3gpp.5gnas"); - //curl_mime_name (part, "n1SmMsg"); - - curl_easy_setopt(curl, CURLOPT_MIMEPOST, mime); + //curl_easy_setopt(curl, CURLOPT_INTERFACE, "eno1:amf"); //hardcoded // Response information. - long httpCode(0); + long httpCode = { 0 }; std::unique_ptr<std::string> httpData(new std::string()); - // Hook up data handling function. curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, &callback); curl_easy_setopt(curl, CURLOPT_WRITEDATA, httpData.get()); + curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, body.length()); + curl_easy_setopt(curl, CURLOPT_POSTFIELDS, data); + res = curl_easy_perform(curl); + curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &httpCode); //get cause from the response nlohmann::json response_data; - try{ + try { response_data = nlohmann::json::parse(*httpData.get()); - } catch (nlohmann::json::exception& e){ - std::cout << "Could not get the cause from the response" <<std::endl; - + } catch (nlohmann::json::exception &e) { + std::cout << "Could not get json data from the response" << std::endl; } - std::cout << "[AMF N11] PDU Session Release Request, response from SMF, Http Code " << httpCode <<std::endl; + std::cout + << "[AMF N11] PDU Session Release Request, response from SMF, Http Code " + << httpCode << std::endl; - curl_slist_free_all(headers); curl_easy_cleanup(curl); - curl_mime_free(mime); } + curl_global_cleanup(); + free(buffer); } -void send_pdu_session_release_resource_release_ack(std::string smf_ip_address) -{ - std::cout << "[AMF N11] PDU Session Release Ack (Update SM Context): N2 SM - Resource Release Ack"<<std::endl; +//------------------------------------------------------------------------------ +void send_pdu_session_release_resource_release_ack( + std::string smf_ip_address) { + + std::cout + << "[AMF N11] PDU Session Release Ack (Update SM Context): N2 SM - Resource Release Ack" + << std::endl; nlohmann::json pdu_session_release_ack; - //encode + //encode PDU Session Resource Release Response Transfer IE size_t buffer_size = 128; - char *buffer = (char *)calloc(1,buffer_size); - int size = 0; - ENCODE_U8 (buffer, 0x00 , size); - + char *buffer = (char*) calloc(1, buffer_size); + int size = 0; + ENCODE_U8(buffer, 0x00, size); - std::cout << "Buffer: "<<std::endl; - for(int i=0;i<size;i++) - { + std::cout << "Buffer: " << std::endl; + for (int i = 0; i < size; i++) { printf("%02x ", buffer[i]); } - std::cout << "Buffer: "<<std::endl; + std::cout << "Buffer: " << std::endl; - //Fill Json part std::string url = std::string("http://"); url.append(smf_ip_address); url.append(std::string("/nsmf-pdusession/v2/sm-contexts/1/modify")); - //Fill the json part - //Fill the json part pdu_session_release_ack["n2SmInfoType"] = "PDU_RES_REL_RSP"; - pdu_session_release_ack["n2SmInfo"]["contentId"] = "n2SmMsg"; //NGAP - - CURL *curl = curl_easy_init(); + pdu_session_release_ack["n2SmInfo"]["contentId"] = "n2SmMsg"; //NGAP + std::string body; + std::string boundary = "----Boundary"; std::string json_part = pdu_session_release_ack.dump(); + std::string n2_msg(reinterpret_cast<const char*>(buffer), size); - std::cout<< "Sending message to SMF....\n"; - if(curl) { - CURLcode res; - struct curl_slist *headers = nullptr; - struct curl_slist *slist = nullptr; - curl_mime *mime; - curl_mime *alt; - curl_mimepart *part; + create_multipart_related_content(body, json_part, boundary, n2_msg, + multipart_related_content_part_e::NGAP); + + unsigned char *data = (unsigned char*) malloc(body.length() + 1); + memset(data, 0, body.length() + 1); + memcpy((void*) data, (void*) body.c_str(), body.length()); + curl_global_init(CURL_GLOBAL_ALL); + CURL *curl = curl = curl_easy_init(); + + if (curl) { + CURLcode res = { }; + struct curl_slist *headers = nullptr; //headers = curl_slist_append(headers, "charsets: utf-8"); - headers = curl_slist_append(headers, "content-type: multipart/related"); + headers = curl_slist_append( + headers, "content-type: multipart/related; boundary=----Boundary"); curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers); curl_easy_setopt(curl, CURLOPT_URL, url.c_str()); - curl_easy_setopt(curl, CURLOPT_HTTPGET,1); + curl_easy_setopt(curl, CURLOPT_HTTPGET, 1); curl_easy_setopt(curl, CURLOPT_TIMEOUT_MS, 100L); - //curl_easy_setopt(curl, CURLOPT_INTERFACE, "eno1:amf"); //hardcoded - - mime = curl_mime_init(curl); - alt = curl_mime_init(curl); - - //part with N1N2MessageTransferReqData (JsonData) - part = curl_mime_addpart(mime); - curl_mime_data(part, json_part.c_str(), CURL_ZERO_TERMINATED); - curl_mime_type(part, "application/json"); - - part = curl_mime_addpart(mime); - //curl_mime_data(part, reinterpret_cast<const char*>(n1_msg_hex), CURL_ZERO_TERMINATED); - curl_mime_data(part, reinterpret_cast<const char*>(buffer), size); - curl_mime_type(part, "application/vnd.3gpp.ngap"); - curl_mime_name (part, "n2SmMsg"); - - curl_easy_setopt(curl, CURLOPT_MIMEPOST, mime); + //curl_easy_setopt(curl, CURLOPT_INTERFACE, "eno1:amf"); //hardcoded // Response information. - long httpCode(0); + long httpCode = { 0 }; std::unique_ptr<std::string> httpData(new std::string()); - // Hook up data handling function. curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, &callback); curl_easy_setopt(curl, CURLOPT_WRITEDATA, httpData.get()); + curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, body.length()); + curl_easy_setopt(curl, CURLOPT_POSTFIELDS, data); + res = curl_easy_perform(curl); + curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &httpCode); //get cause from the response nlohmann::json response_data; - try{ + try { response_data = nlohmann::json::parse(*httpData.get()); - } catch (nlohmann::json::exception& e){ - std::cout << "Could not get the cause from the response" <<std::endl; + } catch (nlohmann::json::exception &e) { + std::cout << "Could not get json data from the response" << std::endl; } - std::cout << "[AMF N11] PDU Session Release Ack, response from SMF, Http Code " << httpCode <<std::endl; + std::cout + << "[AMF N11] PDU Session Establishment Request, response from SMF, Http Code " + << httpCode << std::endl; - curl_slist_free_all(headers); curl_easy_cleanup(curl); - curl_mime_free(mime); } + curl_global_cleanup(); + free(buffer); } +//------------------------------------------------------------------------------ +void send_pdu_session_release_complete(std::string smf_ip_address) { - -void send_pdu_session_release_complete(std::string smf_ip_address) -{ - std::cout << "[AMF N11] PDU Session Release Complete (Update SM Context): N1 SM - PDU Session Release Complete"<<std::endl; + std::cout + << "[AMF N11] PDU Session Release Complete (Update SM Context): N1 SM - PDU Session Release Complete" + << std::endl; nlohmann::json pdu_session_release_complete; - //encode + //encode PDU Session Release Complete /* - 0000 2e 01 01 c1 d4 00 00 00 00 00 00 00 00 00 00 00 + 0000 2e 01 01 c1 d4 00 00 00 00 00 00 00 00 00 00 00 */ size_t buffer_size = 128; - char *buffer = (char *)calloc(1,buffer_size); - int size = 0; - ENCODE_U8 (buffer, 0x2e , size); //ExtendedProtocolDiscriminator - ENCODE_U8 (buffer+size, 0x01 , size); //PDUSessionIdentity - ENCODE_U8 (buffer+size, 0x01 , size); //ProcedureTransactionIdentity - ENCODE_U8 (buffer+size, 0xd4 , size); //MessageType - ENCODE_U8 (buffer+size, 0x00 , size); //Cause - ENCODE_U8 (buffer+size, 0x00 , size); //Extended protocol configuration options - - - std::cout << "Buffer: "<<std::endl; - for(int i=0;i<size;i++) - { + char *buffer = (char*) calloc(1, buffer_size); + int size = 0; + ENCODE_U8(buffer, 0x2e, size); //ExtendedProtocolDiscriminator + ENCODE_U8(buffer + size, 0x01, size); //PDUSessionIdentity + ENCODE_U8(buffer + size, 0x01, size); //ProcedureTransactionIdentity + ENCODE_U8(buffer + size, 0xd4, size); //MessageType + ENCODE_U8(buffer + size, 0x00, size); //Cause + ENCODE_U8(buffer + size, 0x00, size); //Extended protocol configuration options + + std::cout << "Buffer: " << std::endl; + for (int i = 0; i < size; i++) { printf("%02x ", buffer[i]); } - std::cout << "Buffer: "<<std::endl; + std::cout << "Buffer: " << std::endl; - //Fill Json part std::string url = std::string("http://"); url.append(smf_ip_address); url.append(std::string("/nsmf-pdusession/v2/sm-contexts/1/modify")); //Fill the json part - pdu_session_release_complete["cause"] = "INSUFFICIENT_UP_RESOURCES"; //need to be updated - pdu_session_release_complete["n1SmMsg"]["contentId"] = "n1SmMsg"; // NAS + pdu_session_release_complete["cause"] = "INSUFFICIENT_UP_RESOURCES"; //need to be updated + pdu_session_release_complete["n1SmMsg"]["contentId"] = "n1SmMsg"; // NAS - //pdu_session_release_complete["n1MessageContainer"]["n1MessageClass"] = "SM"; - //pdu_session_release_complete["n1MessageContainer"]["n1MessageContent"]["contentId"] = "n1SmMsg"; + std::string body; + std::string boundary = "----Boundary"; + std::string json_part = pdu_session_release_complete.dump(); + std::string n1_msg(reinterpret_cast<const char*>(buffer), size); + create_multipart_related_content(body, json_part, boundary, n1_msg, + multipart_related_content_part_e::NAS); - CURL *curl = curl_easy_init(); + unsigned char *data = (unsigned char*) malloc(body.length() + 1); + memset(data, 0, body.length() + 1); + memcpy((void*) data, (void*) body.c_str(), body.length()); - std::string json_part = pdu_session_release_complete.dump(); + curl_global_init(CURL_GLOBAL_ALL); + CURL *curl = curl = curl_easy_init(); - std::cout<< "Sending message to SMF....\n"; - if(curl) { - CURLcode res; + if (curl) { + CURLcode res = { }; struct curl_slist *headers = nullptr; - struct curl_slist *slist = nullptr; - curl_mime *mime; - curl_mime *alt; - curl_mimepart *part; - //headers = curl_slist_append(headers, "charsets: utf-8"); - headers = curl_slist_append(headers, "content-type: multipart/related"); + headers = curl_slist_append( + headers, "content-type: multipart/related; boundary=----Boundary"); curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers); curl_easy_setopt(curl, CURLOPT_URL, url.c_str()); - curl_easy_setopt(curl, CURLOPT_HTTPGET,1); + curl_easy_setopt(curl, CURLOPT_HTTPGET, 1); curl_easy_setopt(curl, CURLOPT_TIMEOUT_MS, 100L); - //curl_easy_setopt(curl, CURLOPT_INTERFACE, "eno1:amf"); //hardcoded - - mime = curl_mime_init(curl); - alt = curl_mime_init(curl); - - //part with N1N2MessageTransferReqData (JsonData) - part = curl_mime_addpart(mime); - curl_mime_data(part, json_part.c_str(), CURL_ZERO_TERMINATED); - curl_mime_type(part, "application/json"); - - part = curl_mime_addpart(mime); - //curl_mime_data(part, reinterpret_cast<const char*>(n1_msg_hex), CURL_ZERO_TERMINATED); - curl_mime_data(part, reinterpret_cast<const char*>(buffer), size); - curl_mime_type(part, "application/vnd.3gpp.5gnas"); - curl_mime_name (part, "n1SmMsg"); - - curl_easy_setopt(curl, CURLOPT_MIMEPOST, mime); + //curl_easy_setopt(curl, CURLOPT_INTERFACE, "eno1:amf"); //hardcoded // Response information. - long httpCode(0); + long httpCode = { 0 }; std::unique_ptr<std::string> httpData(new std::string()); - // Hook up data handling function. curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, &callback); curl_easy_setopt(curl, CURLOPT_WRITEDATA, httpData.get()); + curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, body.length()); + curl_easy_setopt(curl, CURLOPT_POSTFIELDS, data); + res = curl_easy_perform(curl); + curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &httpCode); //get cause from the response nlohmann::json response_data; - try{ + try { response_data = nlohmann::json::parse(*httpData.get()); - } catch (nlohmann::json::exception& e){ - std::cout << "Could not get the cause from the response" <<std::endl; - + } catch (nlohmann::json::exception &e) { + std::cout << "Could not get json data from the response" << std::endl; } - std::cout << "[AMF N11] PDU Session Release Complete, response from SMF, Http Code " << httpCode <<std::endl; + std::cout + << "[AMF N11] PDU Session Release Complete, response from SMF, Http Code " + << httpCode << std::endl; - curl_slist_free_all(headers); curl_easy_cleanup(curl); - curl_mime_free(mime); } + curl_global_cleanup(); + free(buffer); } - - -int main(int argc, char* argv[]) -{ +//------------------------------------------------------------------------------ +int main(int argc, char *argv[]) { std::string smf_ip_address; if ((argc != 1) && (argc != 3)) { - std::cout << "Error: Usage is " <<std::endl; - std::cout << " " << argv[0] << " [ -i www.xxx.yy.zz ]" <<std::endl; + std::cout << "Error: Usage is " << std::endl; + std::cout << " " << argv[0] << " [ -i www.xxx.yy.zz ]" << std::endl; return -1; } @@ -569,15 +675,15 @@ int main(int argc, char* argv[]) } else { int opt = 0; while ((opt = getopt(argc, argv, "i:")) != -1) { - switch(opt) { - case 'i': - smf_ip_address.append(optarg); - break; - default: - std::cout << "Error: Usage is " <<std::endl; - std::cout << " " << argv[0] << " [ -i www.xxx.yy.zz ]" <<std::endl; - return -1; - break; + switch (opt) { + case 'i': + smf_ip_address.append(optarg); + break; + default: + std::cout << "Error: Usage is " << std::endl; + std::cout << " " << argv[0] << " [ -i www.xxx.yy.zz ]" << std::endl; + return -1; + break; } } } diff --git a/src/test/inputs/apitest.json b/src/test/inputs/apitest.json deleted file mode 100644 index 6eb49c51f530c78a521b34a89da93c75f123eb63..0000000000000000000000000000000000000000 --- a/src/test/inputs/apitest.json +++ /dev/null @@ -1,45 +0,0 @@ -{ -"jsonData": { - "supi": "208931234561000", - "pei": "pei", - "gpsi": "gpsi", - "pduSessionId": 5, - "dnn": "default", - "sNssai": {"sst":1, "sd":123}, - "hplmnSnssai": {"sst":1, "sd": 345}, - "servingNfId": "", - "guami": {"plmnId": {"mcc": "122", "mnc":"13"}, "amfId":"2"}, - "serviceName": "", - "servingNetwork": {"mcc": "122", "mnc":"13"}, - "requestType": 1, - "anType": "", - "secondAnType": "", - "ratType": "", - "presenceInLadn": "", - "ueTimeZone": "", - "smContextStatusUri": "", - "hSmfUri": "", - "additionalHsmfUri": [], - "oldPduSessionId": 1, - "pduSessionsActivateList": [1,2], - "ueEpsPdnConnection": "", - "hoState": "", - "pcfId": "", - "nrfUi": "", - "supportedFeatures": "", - "selMode": "VERIFIED", - "udmGroupId": "", - "routingIndicator": "", - "epsBearerCtxStatus": "", - "cpCiotEnabled": true, - "invokeNef": true, - "maPduIndication": false, - "smContextRef": "", - "n2SmInfo": {"contentId":"n2SmInfo"}, - "n1SmMsg": {"contentId":"n1SmMsg"} - }, - "binaryDataN1SmMessage":"2e031fc100ff93a2390f616263646566406768696a6b2e6c6d", - "binaryDataN1SmMessage_full":"00 00 00 00 00 00 00 00 00 00 00 00 08 00 45 02 00 55 00 01 40 00 40 84 3c 25 7f 00 00 01 7f 00 00 01 df b0 96 0c ea 4c f5 4b 00 00 00 00 00 03 00 35 20 bc ec 86 00 00 00 00 00 00 00 00 00 0f 40 21 00 00 01 00 26 00 1a 19 2e 03 1f c1 00 ff 93 a2 39 0f 61 62 63 64 65 66 40 67 68 69 6a 6b 2e 6c 6d" -} - - diff --git a/src/test/inputs/apitest_full.json b/src/test/inputs/apitest_full.json deleted file mode 100644 index 8dfc2f38925dc816c2840bfe5199313994aed456..0000000000000000000000000000000000000000 --- a/src/test/inputs/apitest_full.json +++ /dev/null @@ -1,52 +0,0 @@ -{ -"jsonData": { - "supi": "supi", - "pei": "pei", - "gpsi": "gpsi", - "pduSessionId": 1, - "dnn": "dnn", - "sNssai": {"sst":1, "sd":"sd"}, - "hplmnSnssai": {"sst":1, "sd":"sd"}, - "servingNfId": "", - "guami": {"plmnId": {"mcc": "122", "mnc":"13"}, "amfId":"2"}, - "serviceName": "", - "servingNetwork": {"mcc": "122", "mnc":"13"}, - "requestType": "", - "anType": "", - "secondAnType": "", - "ratType": "", - "presenceInLadn": "", - "ueLocation": "", - "ueTimeZone": "", - "addUeLocation": "", - "smContextStatusUri": "", - "hSmfUri": "", - "additionalHsmfUri": [], - "oldPduSessionId": "", - "pduSessionsActivateList": [1,2], - "ueEpsPdnConnection": "", - "hoState": "", - "pcfId": "", - "nrfUi": "", - "supportedFeatures": "", - "selMode": "", - "backupAmfInfo": [], - "traceData": "", - "udmGroupId": "", - "routingIndicator": "", - "epsInterworkingInd": "", - "indirectForwardingFlag": "", - "targetId": "", - "epsBearerCtxStatus": "", - "cpCiotEnabled": "", - "invokeNef": "", - "maPduIndication": "", - "smContextRef": "", - "n2SmInfo": "", - "n1SmMsg": {"contentId":"contentId"} - }, - "binaryDataN1SmMessage":"binaryDataN1SmMessage", - "binaryDataN2SmInformation": "binaryDataN2SmInformation" -} - - diff --git a/src/test/inputs/pdu_session_create_request.hex b/src/test/inputs/pdu_session_create_request.hex deleted file mode 100644 index 5b6c8a0b8af66698e0b6f1173ba3bbc4ca30bfea..0000000000000000000000000000000000000000 --- a/src/test/inputs/pdu_session_create_request.hex +++ /dev/null @@ -1,13 +0,0 @@ -00000 00 00 00 00 00 00 00 00 -00008 00 00 00 00 08 00 45 02 -00010 00 55 00 01 40 00 40 84 -00018 3c 25 7f 00 00 01 7f 00 -00020 00 01 df b0 96 0c ea 4c -00028 f5 4b 00 00 00 00 00 03 -00030 00 35 20 bc ec 86 00 00 -00038 00 00 00 00 00 00 00 0f -00040 40 21 00 00 01 00 26 00 -00048 1a 19 2e 03 1f c1 00 ff -00050 93 a2 39 0f 61 62 63 64 -00058 65 66 40 67 68 69 6a 6b -00060 2e 6c 6d diff --git a/src/test/inputs/session_management_subscription.json b/src/test/inputs/session_management_subscription.json deleted file mode 100644 index 82a2c783d89b67d6aec86b28dde2ad039cb58124..0000000000000000000000000000000000000000 --- a/src/test/inputs/session_management_subscription.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "singleNssai": {"sst":1, "sd":123}, - "dnnConfigurations": { - "default": { - "pduSessionTypes": {"defaultSessionType": "IPV4"} , - "sscModes": {"defaultSscMode": "SSC_MODE_1"} , - "5gQosProfile": {"5qi": 12345, "arp": {"priorityLevel": 1 , "preemptCap": "NOT_PREEMPT" , "preemptVuln": "NOT_PREEMPTABLE"} }, - "sessionAmbr": {"uplink": "10Mbps", "downlink":"11Mbps"} - } - } -} diff --git a/src/test/udm/impl/SessionManagementSubscriptionDataRetrievalApiImpl.cpp b/src/test/udm/impl/SessionManagementSubscriptionDataRetrievalApiImpl.cpp index 309899aa84108d72d1b7df255bf2f8d290c39abb..894e7865f70379fd1082e9d6bc7864277dde6e59 100644 --- a/src/test/udm/impl/SessionManagementSubscriptionDataRetrievalApiImpl.cpp +++ b/src/test/udm/impl/SessionManagementSubscriptionDataRetrievalApiImpl.cpp @@ -44,14 +44,23 @@ void SessionManagementSubscriptionDataRetrievalApiImpl::get_sm_data(const std::s nlohmann::json jsonData; jsonData["singleNssai"]["sst"] = 222; jsonData["singleNssai"]["sd"] = 123; - jsonData["dnnConfigurations"]["carrier.com"]["pduSessionTypes"]["defaultSessionType"] = "IPV4"; - jsonData["dnnConfigurations"]["carrier.com"]["sscModes"]["defaultSscMode"] = "SSC_MODE_1"; - jsonData["dnnConfigurations"]["carrier.com"]["5gQosProfile"]["5qi"] = 60; - jsonData["dnnConfigurations"]["carrier.com"]["5gQosProfile"]["arp"]["priorityLevel"] = 1; - jsonData["dnnConfigurations"]["carrier.com"]["5gQosProfile"]["arp"]["preemptCap"] = "NOT_PREEMPT"; - jsonData["dnnConfigurations"]["carrier.com"]["5gQosProfile"]["arp"]["preemptVuln"] = "NOT_PREEMPTABLE"; - jsonData["dnnConfigurations"]["carrier.com"]["sessionAmbr"]["uplink"] = "10Mbps"; - jsonData["dnnConfigurations"]["carrier.com"]["sessionAmbr"]["downlink"] = "11Mbps"; + jsonData["dnnConfigurations"]["default"]["pduSessionTypes"]["defaultSessionType"] = "IPV4"; + jsonData["dnnConfigurations"]["default"]["sscModes"]["defaultSscMode"] = "SSC_MODE_1"; + jsonData["dnnConfigurations"]["default"]["5gQosProfile"]["5qi"] = 60; + jsonData["dnnConfigurations"]["default"]["5gQosProfile"]["arp"]["priorityLevel"] = 1; + jsonData["dnnConfigurations"]["default"]["5gQosProfile"]["arp"]["preemptCap"] = "NOT_PREEMPT"; + jsonData["dnnConfigurations"]["default"]["5gQosProfile"]["arp"]["preemptVuln"] = "NOT_PREEMPTABLE"; + jsonData["dnnConfigurations"]["default"]["sessionAmbr"]["uplink"] = "20Mbps"; + jsonData["dnnConfigurations"]["default"]["sessionAmbr"]["downlink"] = "22Mbps"; + + jsonData["dnnConfigurations"]["carrier.com"]["pduSessionTypes"]["defaultSessionType"] = "IPV4"; + jsonData["dnnConfigurations"]["carrier.com"]["sscModes"]["defaultSscMode"] = "SSC_MODE_1"; + jsonData["dnnConfigurations"]["carrier.com"]["5gQosProfile"]["5qi"] = 61; + jsonData["dnnConfigurations"]["carrier.com"]["5gQosProfile"]["arp"]["priorityLevel"] = 1; + jsonData["dnnConfigurations"]["carrier.com"]["5gQosProfile"]["arp"]["preemptCap"] = "NOT_PREEMPT"; + jsonData["dnnConfigurations"]["carrier.com"]["5gQosProfile"]["arp"]["preemptVuln"] = "NOT_PREEMPTABLE"; + jsonData["dnnConfigurations"]["carrier.com"]["sessionAmbr"]["uplink"] = "10Mbps"; + jsonData["dnnConfigurations"]["carrier.com"]["sessionAmbr"]["downlink"] = "11Mbps"; /* SessionManagementSubscriptionData subscriptionData; diff --git a/src/test/udm/udm-api-server.cpp b/src/test/udm/udm-api-server.cpp index 844e65f1c0fdb3adc5a8ebfae32a4ea8b273fdbd..7700bf4956f689cf17d05db43685b850dad388ac 100644 --- a/src/test/udm/udm-api-server.cpp +++ b/src/test/udm/udm-api-server.cpp @@ -117,7 +117,6 @@ int main(int argc, char* argv[]) { opts.flags(Pistache::Tcp::Options::ReuseAddr); opts.maxPayload(PISTACHE_SERVER_MAX_PAYLOAD); httpEndpoint->init(opts); - AccessAndMobilitySubscriptionDataRetrievalApiImpl AccessAndMobilitySubscriptionDataRetrievalApiserver(router); AccessAndMobilitySubscriptionDataRetrievalApiserver.init(); @@ -160,9 +159,12 @@ int main(int argc, char* argv[]) { UEContextInSMSFDataRetrievalApiImpl UEContextInSMSFDataRetrievalApiserver(router); UEContextInSMSFDataRetrievalApiserver.init(); + std::cout << "UDM is listening on address: " << udm_ip_address.c_str() << std::endl; + httpEndpoint->setHandler(router->handler()); httpEndpoint->serve(); + httpEndpoint->shutdown(); }