From 3712983308d9ff29d6063bc42896936242fc0065 Mon Sep 17 00:00:00 2001 From: David Rupprecht Date: Mon, 23 Aug 2021 15:28:39 +0200 Subject: [PATCH] Added PDU Session est request --- .../srsran/interfaces/ue_nas_interfaces.h | 23 + srsenb/hdr/stack/ngap/ngap.h | 2 +- srsenb/hdr/stack/ngap/ngap_ue.h | 3 + srsenb/hdr/stack/ngap/ngap_ue_proc.h | 17 + srsenb/src/stack/ngap/ngap.cc | 14 +- srsenb/src/stack/ngap/ngap_ue.cc | 12 +- srsenb/src/stack/ngap/ngap_ue_proc.cc | 37 + srsue/hdr/stack/upper/nas.h | 2 - srsue/hdr/stack/upper/nas_5g.h | 55 +- srsue/hdr/stack/upper/nas_5g_procedures.h | 26 + srsue/hdr/stack/upper/nas_base.h | 2 + srsue/hdr/stack/upper/nas_config.h | 6 +- srsue/src/stack/upper/nas_5g.cc | 745 ++++++++++++------ srsue/src/stack/upper/nas_5g_procedures.cc | 49 ++ 14 files changed, 740 insertions(+), 253 deletions(-) diff --git a/lib/include/srsran/interfaces/ue_nas_interfaces.h b/lib/include/srsran/interfaces/ue_nas_interfaces.h index 4bbe3dfba..75459dd22 100644 --- a/lib/include/srsran/interfaces/ue_nas_interfaces.h +++ b/lib/include/srsran/interfaces/ue_nas_interfaces.h @@ -13,10 +13,26 @@ #ifndef SRSRAN_UE_NAS_INTERFACES_H #define SRSRAN_UE_NAS_INTERFACES_H +#include "srsran/asn1/nas_5g_ies.h" #include "srsran/interfaces/rrc_interface_types.h" namespace srsue { +enum apn_types { + ipv4 = 0b001, + ipv6 = 0b010, + ipv4v6 = 0b011, + unstructured = 0b100, + ethernet = 0b101, +}; +class pdu_session_cfg_t +{ +public: + std::string apn_name; + apn_types apn_type; + std::string apn_user; + std::string apn_pass; +}; class nas_interface_rrc { public: @@ -49,6 +65,13 @@ class nas_5g_interface_procedures { public: virtual int send_registration_request() = 0; + virtual int send_pdu_session_establishment_request(uint32_t transaction_identity, + uint16_t pdu_session_id, + const pdu_session_cfg_t& pdu_session) = 0; + virtual int + add_pdu_session(uint16_t pdu_session_id, uint16_t pdu_session_type, srsran::nas_5g::pdu_address_t pdu_address) = 0; + + virtual uint32_t allocate_next_proc_trans_id() = 0; }; } // namespace srsue diff --git a/srsenb/hdr/stack/ngap/ngap.h b/srsenb/hdr/stack/ngap/ngap.h index 3aa3b0f39..5e1112b56 100644 --- a/srsenb/hdr/stack/ngap/ngap.h +++ b/srsenb/hdr/stack/ngap/ngap.h @@ -125,7 +125,7 @@ private: // TS 38.413 - Section 9.2.2.1 - Initial Context Setup Request bool handle_initial_ctxt_setup_request(const asn1::ngap_nr::init_context_setup_request_s& msg); // TS 38.413 - Section 9.2.1.1 - PDU Session Resource Setup Request - bool handle_pdu_session_resource_setup_request(const asn1::ngap_nr::pdu_session_res_setup_request_s& msg); + bool handle_ue_pdu_session_res_setup_request(const asn1::ngap_nr::pdu_session_res_setup_request_s& msg); class user_list { diff --git a/srsenb/hdr/stack/ngap/ngap_ue.h b/srsenb/hdr/stack/ngap/ngap_ue.h index 77bbc626e..cbf2550a3 100644 --- a/srsenb/hdr/stack/ngap/ngap_ue.h +++ b/srsenb/hdr/stack/ngap/ngap_ue.h @@ -39,6 +39,8 @@ public: bool handle_initial_ctxt_setup_request(const asn1::ngap_nr::init_context_setup_request_s& msg); // TS 38.413 - Section 9.2.2.5 - UE Context Release Command bool handle_ue_ctxt_release_cmd(const asn1::ngap_nr::ue_context_release_cmd_s& msg); + // TS 38.413 - Section 9.2.1.1 - PDU Session Resource Setup Request + bool handle_pdu_session_res_setup_request(const asn1::ngap_nr::pdu_session_res_setup_request_s& msg); bool was_uectxtrelease_requested() const { return release_requested; } void ue_ctxt_setup_complete(); @@ -60,6 +62,7 @@ private: // procedures srsran::proc_t initial_context_setup_proc; srsran::proc_t ue_context_release_proc; + srsran::proc_t ue_pdu_session_res_setup_proc; }; } // namespace srsenb diff --git a/srsenb/hdr/stack/ngap/ngap_ue_proc.h b/srsenb/hdr/stack/ngap/ngap_ue_proc.h index eeb13c5b6..a549a24d3 100644 --- a/srsenb/hdr/stack/ngap/ngap_ue_proc.h +++ b/srsenb/hdr/stack/ngap/ngap_ue_proc.h @@ -79,6 +79,23 @@ private: ngap_interface_ngap_proc* parent; }; +class ngap_ue_pdu_session_res_setup_proc +{ +public: + explicit ngap_ue_pdu_session_res_setup_proc(ngap_interface_ngap_proc* parent_, + rrc_interface_ngap_nr* rrc_, + ngap_ue_ctxt_t* ue_ctxt); + srsran::proc_outcome_t init(const asn1::ngap_nr::pdu_session_res_setup_request_s& msg); + srsran::proc_outcome_t step(); + static const char* name() { return "UE PDU Session Resource Setup"; } + +private: + ngap_ue_ctxt_t* ue_ctxt; + ngap_interface_ngap_proc* parent; + rrc_interface_ngap_nr* rrc = nullptr; + srslog::basic_logger& logger; +}; + } // namespace srsenb #endif \ No newline at end of file diff --git a/srsenb/src/stack/ngap/ngap.cc b/srsenb/src/stack/ngap/ngap.cc index 0f99b1973..9d99e8d3a 100644 --- a/srsenb/src/stack/ngap/ngap.cc +++ b/srsenb/src/stack/ngap/ngap.cc @@ -414,6 +414,8 @@ bool ngap::handle_initiating_message(const asn1::ngap_nr::init_msg_s& msg) return handle_initial_ctxt_setup_request(msg.value.init_context_setup_request()); case ngap_elem_procs_o::init_msg_c::types_opts::ue_context_release_cmd: return handle_ue_ctxt_release_cmd(msg.value.ue_context_release_cmd()); + case ngap_elem_procs_o::init_msg_c::types_opts::pdu_session_res_setup_request: + return handle_ue_pdu_session_res_setup_request(msg.value.pdu_session_res_setup_request()); default: logger.error("Unhandled initiating message: %s", msg.value.type().to_string()); } @@ -532,10 +534,16 @@ bool ngap::handle_ue_ctxt_release_cmd(const asn1::ngap_nr::ue_context_release_cm return true; } -bool ngap::handle_pdu_session_resource_setup_request(const asn1::ngap_nr::pdu_session_res_setup_request_s& msg) +bool ngap::handle_ue_pdu_session_res_setup_request(const asn1::ngap_nr::pdu_session_res_setup_request_s& msg) { - // TODO - logger.warning("Not implemented yet"); + ue* u = + handle_ngapmsg_ue_id(msg.protocol_ies.ran_ue_ngap_id.value.value, msg.protocol_ies.amf_ue_ngap_id.value.value); + if (u == nullptr) { + logger.warning("Can not find UE"); + return false; + } + + u->handle_pdu_session_res_setup_request(msg); return true; } diff --git a/srsenb/src/stack/ngap/ngap_ue.cc b/srsenb/src/stack/ngap/ngap_ue.cc index ac988ca45..26a115c10 100644 --- a/srsenb/src/stack/ngap/ngap_ue.cc +++ b/srsenb/src/stack/ngap/ngap_ue.cc @@ -27,7 +27,8 @@ ngap::ue::ue(ngap* ngap_ptr_, rrc_interface_ngap_nr* rrc_ptr_, srslog::basic_log logger(logger_), ngap_ptr(ngap_ptr_), initial_context_setup_proc(this, rrc_ptr_, &ctxt), - ue_context_release_proc(this, rrc_ptr_, &ctxt) + ue_context_release_proc(this, rrc_ptr_, &ctxt), + ue_pdu_session_res_setup_proc(this, rrc_ptr_, &ctxt) { ctxt.ran_ue_ngap_id = ngap_ptr->next_gnb_ue_ngap_id++; gettimeofday(&ctxt.init_timestamp, nullptr); @@ -202,4 +203,13 @@ bool ngap::ue::handle_ue_ctxt_release_cmd(const asn1::ngap_nr::ue_context_releas return true; } +bool ngap::ue::handle_pdu_session_res_setup_request(const asn1::ngap_nr::pdu_session_res_setup_request_s& msg) +{ + if (not ue_pdu_session_res_setup_proc.launch(msg)) { + logger.error("Failed to start UE PDU Session Resource Setup Procedure"); + return false; + } + return true; +} + } // namespace srsenb \ No newline at end of file diff --git a/srsenb/src/stack/ngap/ngap_ue_proc.cc b/srsenb/src/stack/ngap/ngap_ue_proc.cc index 52b0812b3..739698d84 100644 --- a/srsenb/src/stack/ngap/ngap_ue_proc.cc +++ b/srsenb/src/stack/ngap/ngap_ue_proc.cc @@ -89,4 +89,41 @@ proc_outcome_t ngap_ue_ue_context_release_proc::step() return proc_outcome_t::success; } +ngap_ue_pdu_session_res_setup_proc::ngap_ue_pdu_session_res_setup_proc(ngap_interface_ngap_proc* parent_, + rrc_interface_ngap_nr* rrc_, + ngap_ue_ctxt_t* ue_ctxt_) : + logger(srslog::fetch_basic_logger("NGAP UE")) +{ + parent = parent_; + rrc = rrc_; + ue_ctxt = ue_ctxt_; +} + +proc_outcome_t ngap_ue_pdu_session_res_setup_proc::init(const asn1::ngap_nr::pdu_session_res_setup_request_s& msg) +{ + if (msg.protocol_ies.pdu_session_res_setup_list_su_req.value.size() != 1) { + logger.error("Not handling multiple su requests"); + return proc_outcome_t::error; + } + asn1::ngap_nr::pdu_session_res_setup_item_su_req_s su_req = + msg.protocol_ies.pdu_session_res_setup_list_su_req.value[0]; + + if (su_req.pdu_session_nas_pdu_present) { + srsran::unique_byte_buffer_t pdu = srsran::make_byte_buffer(); + if (pdu == nullptr) { + logger.error("Fatal Error: Couldn't allocate buffer in ngap_ue_initial_context_setup_proc::init()."); + return proc_outcome_t::error; + } + memcpy(pdu->msg, su_req.pdu_session_nas_pdu.data(), su_req.pdu_session_nas_pdu.size()); + pdu->N_bytes = su_req.pdu_session_nas_pdu.size(); + rrc->write_dl_info(ue_ctxt->rnti, std::move(pdu)); + } + return proc_outcome_t::yield; +} + +proc_outcome_t ngap_ue_pdu_session_res_setup_proc::step() +{ + return proc_outcome_t::success; +} + } // namespace srsenb \ No newline at end of file diff --git a/srsue/hdr/stack/upper/nas.h b/srsue/hdr/stack/upper/nas.h index 42d643b63..010e5978f 100644 --- a/srsue/hdr/stack/upper/nas.h +++ b/srsue/hdr/stack/upper/nas.h @@ -263,8 +263,6 @@ private: srsran::proc_manager_list_t callbacks; srsran::proc_t plmn_searcher; - - const std::string gw_setup_failure_str = "Failed to setup/configure GW interface"; }; } // namespace srsue diff --git a/srsue/hdr/stack/upper/nas_5g.h b/srsue/hdr/stack/upper/nas_5g.h index 2124f5aea..4e68275e9 100644 --- a/srsue/hdr/stack/upper/nas_5g.h +++ b/srsue/hdr/stack/upper/nas_5g.h @@ -33,6 +33,9 @@ using srsran::byte_buffer_t; +#define MAX_PDU_SESSIONS 15 +#define MAX_TRANS_ID 255 + namespace srsue { /** @@ -72,7 +75,7 @@ private: bool running = false; - bool initial_sec_command = false; + bool initial_sec_command = false; srsran::nas_5g::mobile_identity_5gs_t::guti_5g_s guti_5g; srsran::nas_5g::nas_5gs_msg initial_registration_request_stored; @@ -110,20 +113,25 @@ private: // Procedures // Forward declartion class registration_procedure; + class pdu_session_establishment_procedure; - srsran::proc_t registration_proc; + srsran::proc_t registration_proc; + srsran::proc_t pdu_session_establishment_proc; // Message sender - int send_registration_request(); - int send_authentication_response(const uint8_t res[16]); - int send_security_mode_reject(const srsran::nas_5g::cause_5gmm_t::cause_5gmm_type_::options cause); - int send_authentication_failure(const srsran::nas_5g::cause_5gmm_t::cause_5gmm_type_::options cause, - const uint8_t* auth_fail_param); - int send_security_mode_complete(const srsran::nas_5g::security_mode_command_t& security_mode_command); - int send_registration_complete(); + int send_registration_request(); + int send_authentication_response(const uint8_t res[16]); + int send_security_mode_reject(const srsran::nas_5g::cause_5gmm_t::cause_5gmm_type_::options cause); + int send_authentication_failure(const srsran::nas_5g::cause_5gmm_t::cause_5gmm_type_::options cause, + const uint8_t* auth_fail_param); + int send_security_mode_complete(const srsran::nas_5g::security_mode_command_t& security_mode_command); + int send_registration_complete(); + int send_pdu_session_establishment_request(uint32_t transaction_identity, + uint16_t pdu_session_id, + const pdu_session_cfg_t& pdu_session); void fill_security_caps(srsran::nas_5g::ue_security_capability_t& sec_caps); - int apply_security_config(srsran::unique_byte_buffer_t& pdu, uint8_t sec_hdr_type); + int apply_security_config(srsran::unique_byte_buffer_t& pdu, uint8_t sec_hdr_type); // message handler int handle_registration_accept(srsran::nas_5g::registration_accept_t& registration_accept); @@ -138,6 +146,33 @@ private: srsran::nas_5g::deregistration_accept_ue_terminated_t& deregistration_accept_ue_terminated); int handle_deregistration_request_ue_terminated( srsran::nas_5g::deregistration_request_ue_terminated_t& deregistration_request_ue_terminated); + int handle_dl_nas_transport(srsran::nas_5g::dl_nas_transport_t& dl_nas_transport); + + // message handler container + int handle_n1_sm_information(std::vector payload_container_contents); + + // Transaction ID management + std::array pdu_trans_ids; + uint32_t allocate_next_proc_trans_id(); + void release_proc_trans_id(uint32_t proc_id); + + int trigger_pdu_session_est(); + + // PDU Session Management + int add_pdu_session(uint16_t pdu_session_id, uint16_t pdu_session_type, srsran::nas_5g::pdu_address_t pdu_address); + int init_pdu_sessions(std::vector pdu_session_cfgs); + int configure_pdu_session(uint16_t pdu_session_id); + bool unestablished_pdu_sessions(); + int get_unestablished_pdu_session(uint16_t& pdu_session_id, pdu_session_cfg_t& pdu_session_cfg); + + struct pdu_session_t { + bool configured; + bool established; + uint16_t pdu_session_id; + pdu_session_cfg_t pdu_session_cfg; + }; + + std::array pdu_sessions; }; } // namespace srsue #endif \ No newline at end of file diff --git a/srsue/hdr/stack/upper/nas_5g_procedures.h b/srsue/hdr/stack/upper/nas_5g_procedures.h index 9d6b08e3a..742189cf7 100644 --- a/srsue/hdr/stack/upper/nas_5g_procedures.h +++ b/srsue/hdr/stack/upper/nas_5g_procedures.h @@ -36,6 +36,32 @@ public: private: nas_5g_interface_procedures* parent_nas; }; + +/** + * @brief 5G NAS (5GSM) UE-requested PDU session establishment procedure + * + * Specified in 24 501 V16.7.0 + * UE-requested 5GSM procedures + * 6.4.1 UE-requested PDU session establishment procedure + */ +class nas_5g::pdu_session_establishment_procedure +{ +public: + explicit pdu_session_establishment_procedure(nas_5g_interface_procedures* parent_nas_, srslog::basic_logger& logger_); + srsran::proc_outcome_t init(const uint16_t pdu_session_id, const pdu_session_cfg_t pdu_session); + srsran::proc_outcome_t react(const srsran::nas_5g::pdu_session_establishment_accept_t& pdu_session_est_accept); + srsran::proc_outcome_t react(const srsran::nas_5g::pdu_session_establishment_reject_t& pdu_session_est_reject); + srsran::proc_outcome_t step(); + srsran::proc_outcome_t then(); + static const char* name() { return "PDU Session Establishment Procedure"; } + +private: + srslog::basic_logger& logger; + nas_5g_interface_procedures* parent_nas; + uint32_t transaction_identity = 0; + uint16_t pdu_session_id = 0; +}; + } // namespace srsue #endif // SRSUE_NAS_5G_PROCEDURES_H_ \ No newline at end of file diff --git a/srsue/hdr/stack/upper/nas_base.h b/srsue/hdr/stack/upper/nas_base.h index 5688482d8..00b719548 100644 --- a/srsue/hdr/stack/upper/nas_base.h +++ b/srsue/hdr/stack/upper/nas_base.h @@ -73,6 +73,8 @@ protected: uint32_t mac_offset = 0; uint32_t seq_offset = 0; uint32_t bearer_id = 0; + + const std::string gw_setup_failure_str = "Failed to setup/configure GW interface"; }; } // namespace srsue diff --git a/srsue/hdr/stack/upper/nas_config.h b/srsue/hdr/stack/upper/nas_config.h index 179b0f7fa..c0444725b 100644 --- a/srsue/hdr/stack/upper/nas_config.h +++ b/srsue/hdr/stack/upper/nas_config.h @@ -13,6 +13,7 @@ #ifndef SRSUE_NAS_CONFIG_H #define SRSUE_NAS_CONFIG_H +#include "srsran/interfaces/ue_nas_interfaces.h" #include namespace srsue { @@ -34,9 +35,12 @@ public: bool force_imsi_attach; std::string eia; std::string eea; + nas_sim_args_t sim; + + // 5G args std::string ia5g; std::string ea5g; - nas_sim_args_t sim; + std::vector pdu_session_cfgs; }; } // namespace srsue diff --git a/srsue/src/stack/upper/nas_5g.cc b/srsue/src/stack/upper/nas_5g.cc index 2d13272b6..c6a66bfcd 100644 --- a/srsue/src/stack/upper/nas_5g.cc +++ b/srsue/src/stack/upper/nas_5g.cc @@ -49,7 +49,8 @@ nas_5g::nas_5g(srslog::basic_logger& logger_, srsran::task_sched_handle task_sch t3521(task_sched_.get_unique_timer()), reregistration_timer(task_sched_.get_unique_timer()), registration_proc(this), - state(logger_) + state(logger_), + pdu_session_establishment_proc(this, logger_) { // Configure timers t3502.set(t3502_duration_ms, [this](uint32_t tid) { timer_expired(tid); }); @@ -95,6 +96,10 @@ int nas_5g::init(usim_interface_nas* usim_, ea5g_caps[3] = true; } + if (init_pdu_sessions(cfg.pdu_session_cfgs) != SRSRAN_SUCCESS) { + logger.warning("Failure while configuring pdu sessions"); + } + running = true; return SRSRAN_SUCCESS; } @@ -137,6 +142,94 @@ void nas_5g::run_tti() } } +int nas_5g::write_pdu(srsran::unique_byte_buffer_t pdu) +{ + logger.info(pdu->msg, pdu->N_bytes, "DL PDU (length %d)", pdu->N_bytes); + + nas_5gs_msg nas_msg; + + if (nas_msg.unpack_outer_hdr(pdu) != SRSRAN_SUCCESS) { + logger.error("Unable to unpack outer NAS header"); + return SRSRAN_ERROR; + } + + switch (nas_msg.hdr.security_header_type) { + case nas_5gs_hdr::security_header_type_opts::plain_5gs_nas_message: + break; + case nas_5gs_hdr::security_header_type_opts::integrity_protected: + if (integrity_check(pdu.get()) == false) { + logger.error("Not handling NAS message with integrity check error"); + return SRSRAN_ERROR; + } + break; + case nas_5gs_hdr::security_header_type_opts::integrity_protected_and_ciphered: + if (integrity_check(pdu.get()) == false) { + logger.error("Not handling NAS message with integrity check error"); + return SRSRAN_ERROR; + } else { + cipher_decrypt(pdu.get()); + } + break; + case nas_5gs_hdr::security_header_type_opts::integrity_protected_with_new_5G_nas_context: + break; + case nas_5gs_hdr::security_header_type_opts::integrity_protected_and_ciphered_with_new_5G_nas_context: + return SRSRAN_ERROR; + default: + logger.error("Not handling NAS message with unkown security header"); + break; + } + + if (pcap != nullptr) { + pcap->write_nas(pdu->msg, pdu->N_bytes); + } + + logger.info(pdu->msg, pdu->N_bytes, "Decrypted DL PDU (length %d)", pdu->N_bytes); + + // Parse the message header + if (nas_msg.unpack(pdu) != SRSRAN_SUCCESS) { + logger.error("Unable to unpack complete NAS pdu"); + return SRSRAN_ERROR; + } + + switch (nas_msg.hdr.message_type) { + case msg_opts::options::registration_accept: + handle_registration_accept(nas_msg.registration_accept()); + break; + case msg_opts::options::registration_reject: + handle_registration_reject(nas_msg.registration_reject()); + break; + case msg_opts::options::authentication_request: + handle_authentication_request(nas_msg.authentication_request()); + break; + case msg_opts::options::identity_request: + handle_identity_request(nas_msg.identity_request()); + break; + case msg_opts::options::security_mode_command: + handle_security_mode_command(nas_msg.security_mode_command(), std::move(pdu)); + break; + case msg_opts::options::service_accept: + handle_service_accept(nas_msg.service_accept()); + break; + case msg_opts::options::service_reject: + handle_service_reject(nas_msg.service_reject()); + break; + case msg_opts::options::deregistration_accept_ue_terminated: + handle_deregistration_accept_ue_terminated(nas_msg.deregistration_accept_ue_terminated()); + break; + case msg_opts::options::deregistration_request_ue_terminated: + handle_deregistration_request_ue_terminated(nas_msg.deregistration_request_ue_terminated()); + break; + case msg_opts::options::dl_nas_transport: + handle_dl_nas_transport(nas_msg.dl_nas_transport()); + break; + default: + logger.error( + "Not handling NAS message type: %s (0x%02x)", nas_msg.hdr.message_type.to_string(), nas_msg.hdr.message_type); + break; + } + return SRSRAN_SUCCESS; +} + /******************************************************************************* * Senders ******************************************************************************/ @@ -199,6 +292,34 @@ int nas_5g::send_registration_request() return SRSRAN_SUCCESS; } +int nas_5g::send_registration_complete() +{ + unique_byte_buffer_t pdu = srsran::make_byte_buffer(); + if (!pdu) { + logger.error("Couldn't allocate PDU in %s().", __FUNCTION__); + return SRSRAN_ERROR; + } + + logger.info("Generating Registration Complete"); + + nas_5gs_msg nas_msg; + registration_complete_t& reg_comp = nas_msg.set_registration_complete(); + + if (nas_msg.pack(pdu) != SRSASN_SUCCESS) { + logger.error("Failed to pack registration complete."); + return SRSRAN_ERROR; + } + + if (pcap != nullptr) { + pcap->write_nas(pdu.get()->msg, pdu.get()->N_bytes); + } + + logger.info("Sending Registration Complete"); + rrc_nr->write_sdu(std::move(pdu)); + + return SRSRAN_SUCCESS; +} + int nas_5g::send_authentication_response(const uint8_t res[16]) { unique_byte_buffer_t pdu = srsran::make_byte_buffer(); @@ -224,11 +345,6 @@ int nas_5g::send_authentication_response(const uint8_t res[16]) pcap->write_nas(pdu.get()->msg, pdu.get()->N_bytes); } - // if (apply_security_config(pdu, current_sec_hdr) != SRSASN_SUCCESS) { - // logger.error("Error applying NAS security."); - // return SRSRAN_ERROR; - // } - logger.info("Sending Authentication Response"); rrc_nr->write_sdu(std::move(pdu)); @@ -261,16 +377,6 @@ int nas_5g::send_security_mode_reject(const cause_5gmm_t::cause_5gmm_type_::opti return SRSRAN_SUCCESS; } -void copy_msg_to_buffer(unique_byte_buffer_t& pdu, const_byte_span msg) -{ - pdu = srsran::make_byte_buffer(); - if (pdu == nullptr) { - srslog::fetch_basic_logger("ALL").error("Couldn't allocate PDU in %s().", __FUNCTION__); - return; - } - memcpy(pdu->msg, msg.data(), msg.size()); - pdu->N_bytes = msg.size(); -} int nas_5g::send_security_mode_complete(const srsran::nas_5g::security_mode_command_t& security_mode_command) { @@ -339,7 +445,7 @@ int nas_5g::send_security_mode_complete(const srsran::nas_5g::security_mode_comm logger.info("Sending Security Mode Complete"); rrc_nr->write_sdu(std::move(pdu)); - ctxt.rx_count++; + ctxt.tx_count++; return SRSRAN_SUCCESS; } @@ -371,7 +477,30 @@ int nas_5g::send_authentication_failure(const cause_5gmm_t::cause_5gmm_type_::op return SRSRAN_SUCCESS; } -int nas_5g::send_registration_complete() +uint32_t nas_5g::allocate_next_proc_trans_id() +{ + uint32_t i = 0; + for (auto pdu_trans_id : pdu_trans_ids) { + i++; + if (pdu_trans_id == false) { + pdu_trans_id = true; + } + } + // TODO if Trans ID exhausted + return i; +} + +void nas_5g::release_proc_trans_id(uint32_t proc_id) +{ + if (proc_id < MAX_TRANS_ID) { + pdu_trans_ids[proc_id] = false; + } + return; +} + +int nas_5g::send_pdu_session_establishment_request(uint32_t transaction_identity, + uint16_t pdu_session_id, + const pdu_session_cfg_t& pdu_session_cfg) { unique_byte_buffer_t pdu = srsran::make_byte_buffer(); if (!pdu) { @@ -379,13 +508,64 @@ int nas_5g::send_registration_complete() return SRSRAN_ERROR; } - logger.info("Generating Registration Complete"); + logger.info("Generating PDU Session Establishment Request"); - nas_5gs_msg nas_msg; - registration_complete_t& reg_comp = nas_msg.set_registration_complete(); + nas_5gs_msg nas_msg; + nas_msg.hdr.pdu_session_identity = pdu_session_id; + nas_msg.hdr.procedure_transaction_identity = transaction_identity; - if (nas_msg.pack(pdu) != SRSASN_SUCCESS) { - logger.error("Failed to pack registration complete."); + pdu_session_establishment_request_t& pdu_ses_est_req = nas_msg.set_pdu_session_establishment_request(); + pdu_ses_est_req.integrity_protection_maximum_data_rate.max_data_rate_upip_downlink = + integrity_protection_maximum_data_rate_t::max_data_rate_UPIP_downlink_type_::options::full_data_rate; + pdu_ses_est_req.integrity_protection_maximum_data_rate.max_data_rate_upip_uplink = + integrity_protection_maximum_data_rate_t::max_data_rate_UPIP_uplink_type_::options::full_data_rate; + + pdu_ses_est_req.pdu_session_type_present = true; + pdu_ses_est_req.pdu_session_type.pdu_session_type_value = + static_cast(pdu_session_cfg.apn_type); + + pdu_ses_est_req.ssc_mode_present = true; + pdu_ses_est_req.ssc_mode.ssc_mode_value = ssc_mode_t::SSC_mode_value_type_::options::ssc_mode_1; + + // TODO set the capability and extended protocol configuration + pdu_ses_est_req.capability_5gsm_present = false; + pdu_ses_est_req.extended_protocol_configuration_options_present = false; + + // Build up the Envelope for the PDU session request + nas_5gs_msg env_nas_msg; + env_nas_msg.hdr.security_header_type = nas_5gs_hdr::security_header_type_opts::integrity_protected_and_ciphered; + + // TODO move that seq number setting to the security part + env_nas_msg.hdr.sequence_number = ctxt.tx_count; + + ul_nas_transport_t& ul_nas_msg = env_nas_msg.set_ul_nas_transport(); + ul_nas_msg.payload_container_type.payload_container_type.value = + payload_container_type_t::Payload_container_type_type_::options::n1_sm_information; + + // Pack the pdu session est request into the envelope + if (nas_msg.pack(ul_nas_msg.payload_container.payload_container_contents) != SRSASN_SUCCESS) { + logger.error("Failed to pack PDU Session Establishment Request."); + return SRSRAN_ERROR; + } + + ul_nas_msg.pdu_session_id_present = true; + ul_nas_msg.pdu_session_id.pdu_session_identity_2_value = pdu_session_id; + + ul_nas_msg.request_type_present = true; + ul_nas_msg.request_type.request_type_value = request_type_t::Request_type_value_type_::options::initial_request; + + ul_nas_msg.s_nssai_present = true; + ul_nas_msg.s_nssai.type = s_nssai_t::SST_type_::options::sst; + ul_nas_msg.s_nssai.sst = 1; + + ul_nas_msg.dnn_present = true; + ul_nas_msg.dnn.dnn_value.resize(pdu_session_cfg.apn_name.size() + 1); + ul_nas_msg.dnn.dnn_value.data()[0] = static_cast(pdu_session_cfg.apn_name.size()); + + memcpy(ul_nas_msg.dnn.dnn_value.data() + 1, pdu_session_cfg.apn_name.data(), pdu_session_cfg.apn_name.size()); + + if (env_nas_msg.pack(pdu) != SRSASN_SUCCESS) { + logger.error("Failed to pack UL NAS transport."); return SRSRAN_ERROR; } @@ -393,235 +573,55 @@ int nas_5g::send_registration_complete() pcap->write_nas(pdu.get()->msg, pdu.get()->N_bytes); } - logger.info("Sending Registration Complete"); + cipher_encrypt(pdu.get()); + integrity_generate(&k_nas_int[16], + ctxt.tx_count, + SECURITY_DIRECTION_UPLINK, + &pdu->msg[SEQ_5G_OFFSET], + pdu->N_bytes - SEQ_5G_OFFSET, + &pdu->msg[MAC_5G_OFFSET]); + + logger.info("Sending PDU Session Establishment Complete in UL NAS transport."); rrc_nr->write_sdu(std::move(pdu)); return SRSRAN_SUCCESS; } -int nas_5g::write_pdu(srsran::unique_byte_buffer_t pdu) +// Message handler +int nas_5g::handle_registration_accept(registration_accept_t& registration_accept) { - logger.info(pdu->msg, pdu->N_bytes, "DL PDU (length %d)", pdu->N_bytes); - - nas_5gs_msg nas_msg; - - if (nas_msg.unpack_outer_hdr(pdu) != SRSRAN_SUCCESS) { - logger.error("Unable to unpack outer NAS header"); + if (state.get_state() != mm5g_state_t::state_t::registered_initiated) { + logger.warning("Not compatibale with current state %s", state.get_full_state_text()); return SRSRAN_ERROR; } - switch (nas_msg.hdr.security_header_type) { - case nas_5gs_hdr::security_header_type_opts::plain_5gs_nas_message: - break; - case nas_5gs_hdr::security_header_type_opts::integrity_protected: - if (integrity_check(pdu.get()) == false) { - logger.error("Not handling NAS message with integrity check error"); - return SRSRAN_ERROR; - } - break; - case nas_5gs_hdr::security_header_type_opts::integrity_protected_and_ciphered: - if (integrity_check(pdu.get()) == false) { - logger.error("Not handling NAS message with integrity check error"); - return SRSRAN_ERROR; - } else { - cipher_decrypt(pdu.get()); - } - break; - case nas_5gs_hdr::security_header_type_opts::integrity_protected_with_new_5G_nas_context: - break; - case nas_5gs_hdr::security_header_type_opts::integrity_protected_and_ciphered_with_new_5G_nas_context: - return SRSRAN_ERROR; - default: - logger.error("Not handling NAS message with unkown security header"); - break; - } - - if (pcap != nullptr) { - pcap->write_nas(pdu->msg, pdu->N_bytes); + bool send_reg_complete = false; + logger.info("Handling Registration Accept"); + if (registration_accept.guti_5g_present) { + guti_5g = registration_accept.guti_5g.guti_5g(); + send_reg_complete = true; } - logger.info(pdu->msg, pdu->N_bytes, "Decrypted DL PDU (length %d)", pdu->N_bytes); + // TODO: reset counters and everything what is needed by the specification + t3521.set(registration_accept.t3512_value.timer_value); + registration_proc.run(); + state.set_registered(mm5g_state_t::registered_substate_t::normal_service); - // Parse the message header - if (nas_msg.unpack(pdu) != SRSRAN_SUCCESS) { - logger.error("Unable to unpack complete NAS pdu"); - return SRSRAN_ERROR; + if (send_reg_complete == true) { + send_registration_complete(); } + // TODO: use the state machine to trigger that transition + trigger_pdu_session_est(); + return SRSRAN_SUCCESS; +} - switch (nas_msg.hdr.message_type) { - case msg_opts::options::registration_accept: - handle_registration_accept(nas_msg.registration_accept()); - break; - case msg_opts::options::registration_reject: - handle_registration_reject(nas_msg.registration_reject()); - break; - case msg_opts::options::authentication_request: - handle_authentication_request(nas_msg.authentication_request()); - break; - case msg_opts::options::identity_request: - handle_identity_request(nas_msg.identity_request()); - break; - case msg_opts::options::security_mode_command: - handle_security_mode_command(nas_msg.security_mode_command(), std::move(pdu)); - break; - case msg_opts::options::service_accept: - handle_service_accept(nas_msg.service_accept()); - break; - case msg_opts::options::service_reject: - handle_service_reject(nas_msg.service_reject()); - break; - case msg_opts::options::deregistration_accept_ue_terminated: - handle_deregistration_accept_ue_terminated(nas_msg.deregistration_accept_ue_terminated()); - break; - case msg_opts::options::deregistration_request_ue_terminated: - handle_deregistration_request_ue_terminated(nas_msg.deregistration_request_ue_terminated()); - break; - default: - logger.error( - "Not handling NAS message type: %s (0x%02x)", nas_msg.hdr.message_type.to_string(), nas_msg.hdr.message_type); - break; - } +int nas_5g::handle_registration_reject(registration_reject_t& registration_reject) +{ + logger.info("Handling Registration Reject"); return SRSRAN_SUCCESS; } -void nas_5g::fill_security_caps(srsran::nas_5g::ue_security_capability_t& sec_caps) -{ - if (ia5g_caps[0] == true) { - sec_caps.ia0_5g_supported = true; - } - if (ia5g_caps[1] == true) { - sec_caps.ia1_128_5g_supported = true; - } - if (ia5g_caps[2] == true) { - sec_caps.ia2_128_5g_supported = true; - } - if (ia5g_caps[3] == true) { - sec_caps.ia3_128_5g_supported = true; - } - if (ia5g_caps[4] == true) { - sec_caps.ia4_5g_supported = true; - } - if (ia5g_caps[5] == true) { - sec_caps.ia5_5g_supported = true; - } - if (ia5g_caps[6] == true) { - sec_caps.ia6_5g_supported = true; - } - if (ia5g_caps[7] == true) { - sec_caps.ia7_5g_supported = true; - } - - if (ea5g_caps[0] == true) { - sec_caps.ea0_5g_supported = true; - } - if (ea5g_caps[1] == true) { - sec_caps.ea1_128_5g_supported = true; - } - if (ea5g_caps[2] == true) { - sec_caps.ea2_128_5g_supported = true; - } - if (ea5g_caps[3] == true) { - sec_caps.ea3_128_5g_supported = true; - } - if (ea5g_caps[4] == true) { - sec_caps.ea4_5g_supported = true; - } - if (ea5g_caps[5] == true) { - sec_caps.ea5_5g_supported = true; - } - if (ea5g_caps[6] == true) { - sec_caps.ea6_5g_supported = true; - } - if (ea5g_caps[7] == true) { - sec_caps.ea7_5g_supported = true; - } -} -/******************************************************************************* - * UE Stack and RRC common Interface - ******************************************************************************/ -bool nas_5g::is_registered() -{ - return state.get_state() == mm5g_state_t::state_t::registered; -} - -/******************************************************************************* - * NAS Timers - ******************************************************************************/ -void nas_5g::timer_expired(uint32_t timeout_id) -{ - // TODO -} - -/******************************************************************************* - * UE Stack Interface - ******************************************************************************/ -int nas_5g::switch_on() -{ - logger.info("Switching on"); - state.set_deregistered(mm5g_state_t::deregistered_substate_t::plmn_search); - return SRSRAN_SUCCESS; -} - -int nas_5g::switch_off() -{ - logger.info("Switching off"); - // TODO - return SRSRAN_SUCCESS; -} - -int nas_5g::enable_data() -{ - logger.info("Enabling data services"); - return switch_on(); -} - -int nas_5g::disable_data() -{ - logger.info("Disabling data services"); - // TODO - return SRSRAN_SUCCESS; -} - -int nas_5g::start_service_request() -{ - logger.info("Service Request"); - // TODO - return SRSRAN_SUCCESS; -} - -// Message handler - -int nas_5g::handle_registration_accept(registration_accept_t& registration_accept) -{ - if (state.get_state() != mm5g_state_t::state_t::registered_initiated) { - logger.warning("Not compatibale with current state %s", state.get_full_state_text()); - return SRSRAN_ERROR; - } - - bool send_reg_complete = false; - logger.info("Handling Registration Accept"); - if (registration_accept.guti_5g_present) { - guti_5g = registration_accept.guti_5g.guti_5g(); - send_reg_complete = true; - } - - if (send_reg_complete == true) { - send_registration_complete(); - } - - // TODO: reset counters and everything what is needed by the specification - t3521.set(registration_accept.t3512_value.timer_value); - registration_proc.run(); - state.set_registered(mm5g_state_t::registered_substate_t::normal_service); - return SRSRAN_SUCCESS; -} - -int nas_5g::handle_registration_reject(registration_reject_t& registration_reject) -{ - logger.info("Handling Registration Reject"); - return SRSRAN_SUCCESS; -} -int nas_5g::handle_authentication_request(authentication_request_t& authentication_request) +int nas_5g::handle_authentication_request(authentication_request_t& authentication_request) { logger.info("Handling Registration Request"); @@ -742,12 +742,14 @@ int nas_5g::handle_security_mode_command(security_mode_command_t& security_m ctxt.rx_count++; return SRSRAN_SUCCESS; } + int nas_5g::handle_deregistration_accept_ue_terminated( deregistration_accept_ue_terminated_t& deregistration_accept_ue_terminated) { logger.info("Handling Deregistration Accept UE Terminated"); return SRSRAN_SUCCESS; } + int nas_5g::handle_deregistration_request_ue_terminated( deregistration_request_ue_terminated_t& deregistration_request_ue_terminated) { @@ -755,4 +757,277 @@ int nas_5g::handle_deregistration_request_ue_terminated( return SRSRAN_SUCCESS; } +int nas_5g::handle_dl_nas_transport(srsran::nas_5g::dl_nas_transport_t& dl_nas_transport) +{ + logger.info("Handling DL NAS transport"); + switch (dl_nas_transport.payload_container_type.payload_container_type) { + case payload_container_type_t::Payload_container_type_type_::options::n1_sm_information: + return handle_n1_sm_information(dl_nas_transport.payload_container.payload_container_contents); + break; + default: + logger.warning("Not handling payload container %x", + dl_nas_transport.payload_container_type.payload_container_type.value); + break; + } + return SRSRAN_SUCCESS; +} + +int nas_5g::handle_n1_sm_information(std::vector payload_container_contents) +{ + logger.info(payload_container_contents.data(), + payload_container_contents.size(), + "Payload contents (length %d)", + payload_container_contents.size()); + + nas_5gs_msg nas_msg; + nas_msg.unpack(payload_container_contents); + + switch (nas_msg.hdr.message_type) { + case msg_opts::options::pdu_session_establishment_accept: + pdu_session_establishment_proc.trigger(nas_msg.pdu_session_establishment_accept()); + break; + case msg_opts::options::pdu_session_establishment_reject: + pdu_session_establishment_proc.trigger(nas_msg.pdu_session_establishment_reject()); + break; + default: + logger.error( + "Not handling NAS message type: %s (0x%02x)", nas_msg.hdr.message_type.to_string(), nas_msg.hdr.message_type); + break; + } + return SRSRAN_SUCCESS; +} + +/******************************************************************************* + * NAS Timers + ******************************************************************************/ +void nas_5g::timer_expired(uint32_t timeout_id) +{ + // TODO +} + +/******************************************************************************* + * UE Stack & RRC Interface + ******************************************************************************/ +bool nas_5g::is_registered() +{ + return state.get_state() == mm5g_state_t::state_t::registered; +} + +int nas_5g::switch_on() +{ + logger.info("Switching on"); + state.set_deregistered(mm5g_state_t::deregistered_substate_t::plmn_search); + return SRSRAN_SUCCESS; +} + +int nas_5g::switch_off() +{ + logger.info("Switching off"); + // TODO + return SRSRAN_SUCCESS; +} + +int nas_5g::enable_data() +{ + logger.info("Enabling data services"); + return switch_on(); +} + +int nas_5g::disable_data() +{ + logger.info("Disabling data services"); + // TODO + return SRSRAN_SUCCESS; +} + +int nas_5g::start_service_request() +{ + logger.info("Service Request"); + // TODO + return SRSRAN_SUCCESS; +} + +/******************************************************************************* + * Helpers + ******************************************************************************/ + +void nas_5g::fill_security_caps(srsran::nas_5g::ue_security_capability_t& sec_caps) +{ + if (ia5g_caps[0] == true) { + sec_caps.ia0_5g_supported = true; + } + if (ia5g_caps[1] == true) { + sec_caps.ia1_128_5g_supported = true; + } + if (ia5g_caps[2] == true) { + sec_caps.ia2_128_5g_supported = true; + } + if (ia5g_caps[3] == true) { + sec_caps.ia3_128_5g_supported = true; + } + if (ia5g_caps[4] == true) { + sec_caps.ia4_5g_supported = true; + } + if (ia5g_caps[5] == true) { + sec_caps.ia5_5g_supported = true; + } + if (ia5g_caps[6] == true) { + sec_caps.ia6_5g_supported = true; + } + if (ia5g_caps[7] == true) { + sec_caps.ia7_5g_supported = true; + } + + if (ea5g_caps[0] == true) { + sec_caps.ea0_5g_supported = true; + } + if (ea5g_caps[1] == true) { + sec_caps.ea1_128_5g_supported = true; + } + if (ea5g_caps[2] == true) { + sec_caps.ea2_128_5g_supported = true; + } + if (ea5g_caps[3] == true) { + sec_caps.ea3_128_5g_supported = true; + } + if (ea5g_caps[4] == true) { + sec_caps.ea4_5g_supported = true; + } + if (ea5g_caps[5] == true) { + sec_caps.ea5_5g_supported = true; + } + if (ea5g_caps[6] == true) { + sec_caps.ea6_5g_supported = true; + } + if (ea5g_caps[7] == true) { + sec_caps.ea7_5g_supported = true; + } +} + +/******************************************************************************* + * Helpers for Session Management + ******************************************************************************/ + +int nas_5g::trigger_pdu_session_est() +{ + if (unestablished_pdu_sessions() == true) { + pdu_session_cfg_t pdu_session_cfg; + uint16_t pdu_session_id; + get_unestablished_pdu_session(pdu_session_id, pdu_session_cfg); + pdu_session_establishment_proc.launch(pdu_session_id, pdu_session_cfg); + } + return SRSRAN_SUCCESS; +} + +int nas_5g::init_pdu_sessions(std::vector pdu_session_cfgs) +{ + uint16_t i = 0; + for (auto pdu_session_cfg : pdu_session_cfgs) { + pdu_sessions[i].configured = true; + pdu_sessions[i].pdu_session_id = i + 1; + pdu_sessions[i].pdu_session_cfg = pdu_session_cfg; + } + return SRSRAN_SUCCESS; +} + +int nas_5g::configure_pdu_session(uint16_t pdu_session_id) +{ + for (auto pdu_session : pdu_sessions) { + if (pdu_session.pdu_session_id == pdu_session_id) { + pdu_session.established = true; + } + } + return SRSRAN_SUCCESS; +} + +bool nas_5g::unestablished_pdu_sessions() +{ + for (auto pdu_session : pdu_sessions) { + if (pdu_session.configured == true && pdu_session.established == false) { + return true; + } + } + return false; +} + +int nas_5g::get_unestablished_pdu_session(uint16_t& pdu_session_id, pdu_session_cfg_t& pdu_session_cfg) +{ + for (auto pdu_session : pdu_sessions) { + if (pdu_session.configured == true && pdu_session.established == false) { + pdu_session_id = pdu_session.pdu_session_id; + pdu_session_cfg = pdu_session.pdu_session_cfg; + } + } + return SRSRAN_SUCCESS; +} + +int nas_5g::add_pdu_session(uint16_t pdu_session_id, + uint16_t pdu_session_type, + srsran::nas_5g::pdu_address_t pdu_address) +{ + char* err_str = nullptr; + + // Copy IPv4 + uint32_t ip_addr = 0; + + ip_addr |= pdu_address.ipv4.data()[0] << 24u; + ip_addr |= pdu_address.ipv4.data()[1] << 16u; + ip_addr |= pdu_address.ipv4.data()[2] << 8u; + ip_addr |= pdu_address.ipv4.data()[3]; + + // Copy IPv6 + uint8_t ipv6_if_id[8] = {}; + memcpy(ipv6_if_id, pdu_address.ipv6.data(), 8); + + if (!(pdu_session_type == LIBLTE_MME_PDN_TYPE_IPV4V6 || pdu_session_type == LIBLTE_MME_PDN_TYPE_IPV4 || + pdu_session_type == LIBLTE_MME_PDN_TYPE_IPV6)) { + logger.warning("PDU session typed expected to be of IPV4 or IPV6 or IPV4V6"); + return SRSRAN_ERROR; + } + + if (gw->setup_if_addr(pdu_session_id, pdu_session_type, ip_addr, ipv6_if_id, err_str)) { + logger.error("%s - %s", gw_setup_failure_str.c_str(), err_str ? err_str : ""); + srsran::console("%s\n", gw_setup_failure_str.c_str()); + return SRSRAN_ERROR; + } + + if (pdu_session_type == LIBLTE_MME_PDN_TYPE_IPV4V6 || pdu_session_type == LIBLTE_MME_PDN_TYPE_IPV4) { + logger.info("PDU Session Establishment successful. IP: %u.%u.%u.%u", + pdu_address.ipv4.data()[0], + pdu_address.ipv4.data()[1], + pdu_address.ipv4.data()[2], + pdu_address.ipv4.data()[3]); + + srsran::console("PDU Session Establishment successful. IP: %u.%u.%u.%u\n", + pdu_address.ipv4.data()[0], + pdu_address.ipv4.data()[1], + pdu_address.ipv4.data()[2], + pdu_address.ipv4.data()[3]); + } + + if (pdu_session_type == LIBLTE_MME_PDN_TYPE_IPV4V6 || pdu_session_type == LIBLTE_MME_PDN_TYPE_IPV6) { + logger.info("PDU Session Establishment successful. IPv6 interface id: %02x%02x:%02x%02x:%02x%02x:%02x%02x", + pdu_address.ipv6.data()[0], + pdu_address.ipv6.data()[1], + pdu_address.ipv6.data()[2], + pdu_address.ipv6.data()[3], + pdu_address.ipv6.data()[4], + pdu_address.ipv6.data()[5], + pdu_address.ipv6.data()[6], + pdu_address.ipv6.data()[7]); + + srsran::console("PDU Session Establishment successful. IPv6 interface id: %02x%02x:%02x%02x:%02x%02x:%02x%02x\n", + pdu_address.ipv6.data()[0], + pdu_address.ipv6.data()[1], + pdu_address.ipv6.data()[2], + pdu_address.ipv6.data()[3], + pdu_address.ipv6.data()[4], + pdu_address.ipv6.data()[5], + pdu_address.ipv6.data()[6], + pdu_address.ipv6.data()[7]); + } + + return SRSRAN_SUCCESS; +} + } // namespace srsue \ No newline at end of file diff --git a/srsue/src/stack/upper/nas_5g_procedures.cc b/srsue/src/stack/upper/nas_5g_procedures.cc index 577095cc4..2ce2281af 100644 --- a/srsue/src/stack/upper/nas_5g_procedures.cc +++ b/srsue/src/stack/upper/nas_5g_procedures.cc @@ -35,5 +35,54 @@ srsran::proc_outcome_t nas_5g::registration_procedure::step() return srsran::proc_outcome_t::success; } +// PDU Sessions Establishment Procedure +nas_5g::pdu_session_establishment_procedure::pdu_session_establishment_procedure( + nas_5g_interface_procedures* parent_nas_, + srslog::basic_logger& logger_) : + logger(logger_), parent_nas(parent_nas_) +{} + +srsran::proc_outcome_t nas_5g::pdu_session_establishment_procedure::init(const uint16_t pdu_session_id_, + const pdu_session_cfg_t pdu_session_cfg) +{ + // Get PDU transaction identity + transaction_identity = parent_nas->allocate_next_proc_trans_id(); + pdu_session_id = pdu_session_id_; + parent_nas->send_pdu_session_establishment_request(transaction_identity, pdu_session_id, pdu_session_cfg); + + return srsran::proc_outcome_t::yield; +} + +srsran::proc_outcome_t nas_5g::pdu_session_establishment_procedure::react( + const srsran::nas_5g::pdu_session_establishment_accept_t& pdu_session_est_accept) +{ + // TODO check the pdu session values + if (pdu_session_est_accept.dnn_present == false) { + logger.warning("Expected DNN in PDU session establishment accept"); + return proc_outcome_t::error; + } + if (pdu_session_est_accept.pdu_address_present == false) { + logger.warning("Expected PDU Address in PDU session establishment accept"); + return proc_outcome_t::error; + } + if (parent_nas->add_pdu_session(pdu_session_id, + pdu_session_est_accept.selected_pdu_session_type.pdu_session_type_value, + pdu_session_est_accept.pdu_address) != SRSRAN_SUCCESS) { + logger.warning("Adding PDU session failed\n"); + return srsran::proc_outcome_t::error; + } + return srsran::proc_outcome_t::success; +} + +srsran::proc_outcome_t nas_5g::pdu_session_establishment_procedure::react( + const srsran::nas_5g::pdu_session_establishment_reject_t& session_est_reject) +{ + return srsran::proc_outcome_t::success; +} + +srsran::proc_outcome_t nas_5g::pdu_session_establishment_procedure::step() +{ + return srsran::proc_outcome_t::success; +} } // namespace srsue \ No newline at end of file