Add 5G NAS infrastructure

This commit is contained in:
David Rupprecht 2021-07-09 10:12:31 +02:00 committed by David Rupprecht
parent 505225d845
commit fb92118bb7
13 changed files with 808 additions and 3 deletions

View File

@ -39,6 +39,17 @@ public:
virtual bool connection_request_completed(bool outcome) = 0;
};
class nas_5g_interface_rrc_nr
{
public:
};
class nas_5g_interface_procedures
{
public:
virtual int send_registration_request() = 0;
};
} // namespace srsue
#endif // SRSRAN_UE_NAS_INTERFACES_H

View File

@ -113,6 +113,10 @@ public:
virtual bool is_config_pending() = 0;
};
class rrc_nr_interface_nas_5g
{
public:
};
} // namespace srsue
#endif // SRSRAN_UE_RRC_INTERFACES_H

View File

@ -0,0 +1,98 @@
/**
*
* \section COPYRIGHT
*
* Copyright 2013-2021 Software Radio Systems Limited
*
* By using this file, you agree to the terms and conditions set
* forth in the LICENSE file which can be found at the top level of
* the distribution.
*
*/
#ifndef SRSUE_NAS_5G_H
#define SRSUE_NAS_5G_H
#include "nas_base.h"
#include "srsran/common/buffer_pool.h"
#include "srsran/common/common.h"
#include "srsran/common/nas_pcap.h"
#include "srsran/common/security.h"
#include "srsran/common/stack_procedure.h"
#include "srsran/common/task_scheduler.h"
#include "srsran/interfaces/ue_gw_interfaces.h"
#include "srsran/interfaces/ue_nas_interfaces.h"
#include "srsran/interfaces/ue_rrc_interfaces.h"
#include "srsran/interfaces/ue_usim_interfaces.h"
#include "srsran/srslog/srslog.h"
#include "srsue/hdr/stack/upper/nas_5gmm_state.h"
#include "srsue/hdr/stack/upper/nas_config.h"
using srsran::byte_buffer_t;
namespace srsue {
class nas_5g : public nas_base, public nas_5g_interface_rrc_nr, public nas_5g_interface_procedures
{
public:
explicit nas_5g(srsran::task_sched_handle task_sched_);
virtual ~nas_5g();
int init(usim_interface_nas* usim_, rrc_nr_interface_nas_5g* rrc_nr_, gw_interface_nas* gw_, const nas_args_t& cfg_);
void stop();
void run_tti();
// Stack+RRC interface
bool is_registered();
// timer callback
void timer_expired(uint32_t timeout_id);
// Stack interface
int switch_on();
int switch_off();
int enable_data();
int disable_data();
int start_service_request();
private:
rrc_nr_interface_nas_5g* rrc_nr = nullptr;
usim_interface_nas* usim = nullptr;
gw_interface_nas* gw = nullptr;
bool running = false;
nas_args_t cfg = {};
mm5g_state_t state = {};
// Security
bool ia5g_caps[8] = {};
bool ea5g_caps[8] = {};
// timers
srsran::task_sched_handle task_sched;
srsran::timer_handler::unique_timer t3502; // started when registration failure and the attempt counter is equal to 5
srsran::timer_handler::unique_timer t3510; // started when transmission of REGISTRATION REQUEST message. ON EXPIRY:
// start T3511 or T3502 as specified in subclause 5.5.1.2.7
srsran::timer_handler::unique_timer t3511; // started when registration failure due to lower layer failure
srsran::timer_handler::unique_timer t3521; // started when detach request is sent
srsran::timer_handler::unique_timer reregistration_timer; // started to trigger delayed re-attach
// Values according to TS 24.501 Sec 10.2
const uint32_t t3502_duration_ms = 12 * 60 * 1000; // 12m
const uint32_t t3510_duration_ms = 15 * 1000; // 15s
const uint32_t t3511_duration_ms = 10 * 1000; // 10s
const uint32_t t3521_duration_ms = 15 * 1000; // 15s
const uint32_t reregistration_timer_duration_ms = 2 * 1000; // 2s (arbitrarily chosen to delay re-attach)
srsran::proc_manager_list_t callbacks;
// Procedures
// Forward declartion
class registration_procedure;
srsran::proc_t<registration_procedure> registration_proc;
int send_registration_request();
};
} // namespace srsue
#endif

View File

@ -0,0 +1,40 @@
/**
*
* \section COPYRIGHT
*
* Copyright 2013-2021 Software Radio Systems Limited
*
* By using this file, you agree to the terms and conditions set
* forth in the LICENSE file which can be found at the top level of
* the distribution.
*
*/
#ifndef SRSUE_NAS_5G_PROCEDURES_H_
#define SRSUE_NAS_5G_PROCEDURES_H_
#include "srsue/hdr/stack/upper/nas_5g.h"
namespace srsue {
/**
* @brief 5G NAS registration procedure
*
* Specified in 24 501 V16.7.0
* 5GMM specific procedures
* 5.5.1 Registration procedure
*/
class nas_5g::registration_procedure
{
public:
explicit registration_procedure(nas_5g_interface_procedures* parent_nas_);
srsran::proc_outcome_t init();
srsran::proc_outcome_t step();
static const char* name() { return "Registration Procedure"; }
private:
nas_5g_interface_procedures* parent_nas;
};
} // namespace srsue
#endif // SRSUE_NAS_5G_PROCEDURES_H_

View File

@ -0,0 +1,88 @@
/**
*
* \section COPYRIGHT
*
* Copyright 2013-2021 Software Radio Systems Limited
*
* By using this file, you agree to the terms and conditions set
* forth in the LICENSE file which can be found at the top level of
* the distribution.
*
*/
#ifndef SRSUE_NR_NAS_MM5G_STATE_H
#define SRSUE_NR_NAS_MM5G_STATE_H
#include "srsran/srslog/srslog.h"
#include <atomic>
#include <string>
namespace srsue {
// 5GMM states (3GPP 24.501 v16.07.0)
class mm5g_state_t
{
public:
enum class state_t {
null = 0,
deregistered,
registered_initiated,
registered,
deregistered_initiated,
service_request_initiated,
};
// 5GMM-DEREGISTERED sub-states (3GPP 24.501 v16.07.0)
enum class deregistered_substate_t {
null = 0, // This should be used when not in mm5g-DEREGISTERED
normal_service,
limited_service,
attempting_to_registration,
plmn_search,
no_supi,
no_cell_available,
e_call_inactive,
initial_registration_needed,
};
// 5GMM-DEREGISTERED sub-states (3GPP 24.501 v16.07.0)
enum class registered_substate_t {
null = 0, // This should be used when not in mm5g-REGISTERED
normal_service,
non_allowed_service,
attempting_registration_update,
limited_service,
plmn_search,
no_cell_available,
update_needed,
};
// FSM setters
void set_null();
void set_deregistered(deregistered_substate_t substate);
void set_deregistered_initiated();
void set_registered(registered_substate_t substate);
void set_registered_initiated();
void set_service_request_initiated();
// FSM getters
state_t get_state() { return state; }
deregistered_substate_t get_deregistered_substate() { return deregistered_substate; }
registered_substate_t get_registered_substate() { return registered_substate; }
// Text Helpers
const std::string get_full_state_text();
private:
std::atomic<state_t> state{state_t::null};
deregistered_substate_t deregistered_substate = deregistered_substate_t::null;
registered_substate_t registered_substate = registered_substate_t::null;
srslog::basic_logger& logger = srslog::fetch_basic_logger("NAS-5G");
};
const char* mm5g_state_text(mm5g_state_t::state_t type);
const char* mm5g_deregistered_substate_text(mm5g_state_t::deregistered_substate_t type);
const char* mm5g_registered_substate_text(mm5g_state_t::registered_substate_t type);
} // namespace srsue
#endif

View File

@ -34,6 +34,8 @@ public:
bool force_imsi_attach;
std::string eia;
std::string eea;
std::string ia5g;
std::string ea5g;
nas_sim_args_t sim;
};

View File

@ -22,6 +22,7 @@
#include "srsran/test/ue_test_interfaces.h"
#include "srsue/hdr/stack/upper/gw.h"
#include "srsue/hdr/stack/upper/nas.h"
#include "srsue/hdr/stack/upper/nas_5g.h"
#include "srsue/hdr/stack/upper/usim.h"
#include "srsue/hdr/stack/upper/usim_base.h"
@ -122,6 +123,26 @@ private:
bool is_connected_flag = false;
};
class rrc_nr_dummy : public rrc_nr_interface_nas_5g
{
public:
rrc_nr_dummy() : last_sdu_len(0)
{
plmns[0].plmn_id.from_number(mcc, mnc);
plmns[0].tac = 0xffff;
}
void init(nas_5g* nas_5g_) { nas_5g_ptr = nas_5g_; }
void write_sdu(unique_byte_buffer_t sdu)
{
last_sdu_len = sdu->N_bytes;
// printf("NAS generated SDU (len=%d):\n", sdu->N_bytes);
}
private:
nas_5g* nas_5g_ptr;
uint32_t last_sdu_len;
nas_interface_rrc::found_plmn_t plmns[nas_interface_rrc::MAX_FOUND_PLMNS];
};
template <typename T>
class test_stack_dummy : public srsue::stack_test_dummy, public stack_interface_gw, public thread
{
@ -132,7 +153,11 @@ public:
nas = nas_;
start(-1);
}
bool switch_on() { nas->switch_on(); return true; }
bool switch_on()
{
nas->switch_on();
return true;
}
void write_sdu(uint32_t lcid, srsran::unique_byte_buffer_t sdu) { pdcp->write_sdu(lcid, std::move(sdu)); }
bool has_active_radio_bearer(uint32_t eps_bearer_id) { return true; }

View File

@ -8,7 +8,7 @@
add_subdirectory(test)
set(SOURCES nas.cc nas_emm_state.cc nas_idle_procedures.cc gw.cc usim_base.cc usim.cc tft_packet_filter.cc nas_base.cc)
set(SOURCES nas.cc nas_emm_state.cc nas_idle_procedures.cc gw.cc usim_base.cc usim.cc tft_packet_filter.cc nas_base.cc nas_5g_procedures.cc nas_5g.cc nas_5gmm_state.cc)
if(HAVE_PCSC)
list(APPEND SOURCES "pcsc_usim.cc")
@ -17,6 +17,8 @@ endif(HAVE_PCSC)
add_library(srsue_upper STATIC ${SOURCES})
target_link_libraries(srsue_upper ${ATOMIC_LIBS} srsran_asn1)
target_link_libraries(srsue_upper nas_5g_msg)
if(HAVE_PCSC)
target_link_libraries(srsue_upper ${PCSCLITE_LIBRARY})
endif(HAVE_PCSC)

View File

@ -0,0 +1,236 @@
/**
*
* \section COPYRIGHT
*
* Copyright 2013-2021 Software Radio Systems Limited
*
* By using this file, you agree to the terms and conditions set
* forth in the LICENSE file which can be found at the top level of
* the distribution.
*
*/
#include "srsue/hdr/stack/upper/nas_5g.h"
#include "srsran/asn1/nas_5g_ies.h"
#include "srsran/asn1/nas_5g_msg.h"
#include "srsran/common/bcd_helpers.h"
#include "srsran/common/security.h"
#include "srsran/common/standard_streams.h"
#include "srsran/common/string_helpers.h"
#include "srsran/interfaces/ue_gw_interfaces.h"
#include "srsran/interfaces/ue_rrc_interfaces.h"
#include "srsran/interfaces/ue_usim_interfaces.h"
#include "srsue/hdr/stack/upper/nas_5g_procedures.h"
#include <fstream>
#include <iomanip>
#include <iostream>
#include <unistd.h>
using namespace srsran;
using namespace srsran::nas_5g;
namespace srsue {
/*********************************************************************
* NAS 5G (NR)
********************************************************************/
nas_5g::nas_5g(srsran::task_sched_handle task_sched_) :
nas_base("NAS-5G"),
task_sched(task_sched_),
t3502(task_sched_.get_unique_timer()),
t3510(task_sched_.get_unique_timer()),
t3511(task_sched_.get_unique_timer()),
t3521(task_sched_.get_unique_timer()),
reregistration_timer(task_sched_.get_unique_timer()),
registration_proc(this)
{
// Configure timers
t3502.set(t3502_duration_ms, [this](uint32_t tid) { timer_expired(tid); });
t3510.set(t3510_duration_ms, [this](uint32_t tid) { timer_expired(tid); });
t3511.set(t3511_duration_ms, [this](uint32_t tid) { timer_expired(tid); });
t3521.set(t3521_duration_ms, [this](uint32_t tid) { timer_expired(tid); });
reregistration_timer.set(reregistration_timer_duration_ms, [this](uint32_t tid) { timer_expired(tid); });
}
nas_5g::~nas_5g() {}
void nas_5g::stop()
{
running = false;
}
int nas_5g::init(usim_interface_nas* usim_,
rrc_nr_interface_nas_5g* rrc_nr_,
gw_interface_nas* gw_,
const nas_args_t& cfg_)
{
usim = usim_;
rrc_nr = rrc_nr_;
gw = gw_;
cfg = cfg_;
// parse and sanity check EIA list
if (parse_security_algorithm_list(cfg_.ia5g, ia5g_caps) != SRSRAN_SUCCESS) {
logger.warning("Failed to parse integrity algorithm list: Defaulting to 5G-EI1-128, 5G-EI2-128, 5G-EI3-128");
ia5g_caps[0] = false;
ia5g_caps[1] = true;
ia5g_caps[2] = true;
ia5g_caps[3] = true;
}
// parse and sanity check EEA list
if (parse_security_algorithm_list(cfg_.ea5g, ea5g_caps) != SRSRAN_SUCCESS) {
logger.warning(
"Failed to parse encryption algorithm list: Defaulting to 5G-EA0, 5G-EA1-128, 5G-EA2-128, 5G-EA3-128");
ea5g_caps[0] = true;
ea5g_caps[1] = true;
ea5g_caps[2] = true;
ea5g_caps[3] = true;
}
running = true;
return SRSRAN_SUCCESS;
}
void nas_5g::run_tti()
{
// Process PLMN selection ongoing procedures
callbacks.run();
// Transmit intiating messages if necessary
switch (state.get_state()) {
case mm5g_state_t::state_t::deregistered:
// TODO Make sure cell selection is finished after transitioning from another state (if required)
// Make sure the RRC is finished transitioning to RRC Idle
if (reregistration_timer.is_running()) {
logger.debug("Waiting for re-attach timer to expire to attach again.");
return;
}
switch (state.get_deregistered_substate()) {
case mm5g_state_t::deregistered_substate_t::plmn_search:
case mm5g_state_t::deregistered_substate_t::normal_service:
case mm5g_state_t::deregistered_substate_t::initial_registration_needed:
registration_proc.launch();
break;
case mm5g_state_t::deregistered_substate_t::attempting_to_registration:
case mm5g_state_t::deregistered_substate_t::no_supi:
case mm5g_state_t::deregistered_substate_t::no_cell_available:
case mm5g_state_t::deregistered_substate_t::e_call_inactive:
logger.debug("Attempting to registration (not implemented) %s", state.get_full_state_text().c_str());
default:
break;
}
case mm5g_state_t::state_t::registered:
break;
case mm5g_state_t::state_t::deregistered_initiated:
logger.debug("UE detaching...");
break;
default:
break;
}
}
/*******************************************************************************
* Senders
******************************************************************************/
int nas_5g::send_registration_request()
{
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 request");
nas_5gs_msg nas_msg;
registration_request_t& reg_req = nas_msg.set_registration_request();
reg_req.registration_type_5gs.follow_on_request_bit =
registration_type_5gs_t::follow_on_request_bit_type_::options::no_follow_on_request_pending;
reg_req.registration_type_5gs.registration_type =
registration_type_5gs_t::registration_type_type_::options::initial_registration;
mobile_identity_5gs_t::suci_s& suci = reg_req.mobile_identity_5gs.set_suci();
suci.supi_format = mobile_identity_5gs_t::suci_s::supi_format_type_::options::imsi;
mcc_to_bytes(0x0, suci.mcc.data());
uint8_t mnc_len;
mnc_to_bytes(0x0, suci.mnc.data(), &mnc_len);
suci.scheme_output.resize(15);
usim->get_imsi_vec(suci.scheme_output.data(), 15);
logger.info("Requesting IMSI attach (IMSI=%s)", usim->get_imsi_str().c_str());
if (nas_msg.pack(pdu) != SRSASN_SUCCESS) {
logger.error("Failed to pack registration request");
return SRSRAN_ERROR;
}
if (pcap != nullptr) {
pcap->write_nas(pdu.get()->msg, pdu.get()->N_bytes);
}
// start T3510
logger.debug("Starting T3410. Timeout in %d ms.", t3510.duration());
t3510.run();
state.set_registered_initiated();
return SRSRAN_SUCCESS;
}
/*******************************************************************************
* 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;
}
} // namespace srsue

View File

@ -0,0 +1,38 @@
/**
*
* \section COPYRIGHT
*
* Copyright 2013-2021 Software Radio Systems Limited
*
* By using this file, you agree to the terms and conditions set
* forth in the LICENSE file which can be found at the top level of
* the distribution.
*
*/
#include "srsue/hdr/stack/upper/nas_5g_procedures.h"
#include <fstream>
#include <iomanip>
#include <iostream>
#include <unistd.h>
using namespace srsran;
namespace srsue {
nas_5g::registration_procedure::registration_procedure(nas_5g_interface_procedures* parent_nas_) :
parent_nas(parent_nas_)
{}
srsran::proc_outcome_t nas_5g::registration_procedure::init()
{
parent_nas->send_registration_request();
return srsran::proc_outcome_t::yield;
}
srsran::proc_outcome_t nas_5g::registration_procedure::step()
{
return srsran::proc_outcome_t::success;
}
} // namespace srsue

View File

@ -0,0 +1,149 @@
/**
*
* \section COPYRIGHT
*
* Copyright 2013-2021 Software Radio Systems Limited
*
* By using this file, you agree to the terms and conditions set
* forth in the LICENSE file which can be found at the top level of
* the distribution.
*
*/
#include "srsue/hdr/stack/upper/nas_5gmm_state.h"
namespace srsue {
// FSM setters
void mm5g_state_t::set_null()
{
state = state_t::null;
deregistered_substate = deregistered_substate_t::null;
registered_substate = registered_substate_t::null;
logger.debug("Changed to mm5g state: %s", get_full_state_text().c_str());
}
void mm5g_state_t::set_deregistered(deregistered_substate_t substate)
{
state = state_t::deregistered;
deregistered_substate = substate;
registered_substate = registered_substate_t::null;
logger.debug("Changed to mm5g state: %s", get_full_state_text().c_str());
}
void mm5g_state_t::set_deregistered_initiated()
{
state = state_t::deregistered_initiated;
deregistered_substate = deregistered_substate_t::null;
registered_substate = registered_substate_t::null;
logger.debug("Changed to mm5g state: %s", get_full_state_text().c_str());
}
void mm5g_state_t::set_registered(registered_substate_t substate)
{
state = state_t::registered;
deregistered_substate = deregistered_substate_t::null;
registered_substate = substate;
logger.debug("Changed to mm5g state: %s", get_full_state_text().c_str());
}
void mm5g_state_t::set_registered_initiated()
{
state = state_t::registered_initiated;
deregistered_substate = deregistered_substate_t::null;
registered_substate = registered_substate_t::null;
logger.debug("Changed to mm5g state: %s", get_full_state_text().c_str());
}
void mm5g_state_t::set_service_request_initiated()
{
state = state_t::service_request_initiated;
deregistered_substate = deregistered_substate_t::null;
registered_substate = registered_substate_t::null;
logger.debug("Changed to mm5g state: %s", get_full_state_text().c_str());
}
const std::string mm5g_state_t::get_full_state_text()
{
if (state == state_t::deregistered) {
return mm5g_state_text(state) + std::string(", with substate ") +
mm5g_deregistered_substate_text(deregistered_substate);
} else if (state == state_t::registered) {
return mm5g_state_text(state) + std::string(", with substate ") +
mm5g_registered_substate_text(registered_substate);
} else {
return mm5g_state_text(state);
}
return std::string("Invalid State");
}
/*
* Logging helper functions
*/
const char* mm5g_state_text(mm5g_state_t::state_t type)
{
switch (type) {
case mm5g_state_t::state_t::null:
return "NULL";
case mm5g_state_t::state_t::deregistered:
return "DEREGISTERED";
case mm5g_state_t::state_t::registered_initiated:
return "REGISTERED-INITIATED";
case mm5g_state_t::state_t::registered:
return "REGISTERED";
case mm5g_state_t::state_t::deregistered_initiated:
return "DEREGISTERED-INITIATED";
case mm5g_state_t::state_t::service_request_initiated:
return "SERVICE-REQUEST-INITIATED";
}
return "INVALID";
}
const char* mm5g_deregistered_substate_text(mm5g_state_t::deregistered_substate_t type)
{
switch (type) {
case mm5g_state_t::deregistered_substate_t::null:
return "NULL";
case mm5g_state_t::deregistered_substate_t::normal_service:
return "NORMAL-SERVICE";
case mm5g_state_t::deregistered_substate_t::limited_service:
return "LIMITED-SERVICE";
case mm5g_state_t::deregistered_substate_t::attempting_to_registration:
return "ATTEMPTING-TO-REGISTRATION";
case mm5g_state_t::deregistered_substate_t::plmn_search:
return "PLMN-SEARCH";
case mm5g_state_t::deregistered_substate_t::no_supi:
return "NO-SUPI";
case mm5g_state_t::deregistered_substate_t::no_cell_available:
return "NO-CELL-AVAILABLE";
case mm5g_state_t::deregistered_substate_t::e_call_inactive:
return "eCALL-INACTIVE";
case mm5g_state_t::deregistered_substate_t::initial_registration_needed:
return "ATTACH-NEEDED";
}
return "INVALID";
}
const char* mm5g_registered_substate_text(mm5g_state_t::registered_substate_t type)
{
switch (type) {
case mm5g_state_t::registered_substate_t::null:
return "NULL";
case mm5g_state_t::registered_substate_t::normal_service:
return "NORMAL-SERVICE";
case mm5g_state_t::registered_substate_t::non_allowed_service:
return "NON-ALLOWED-SERVICE";
case mm5g_state_t::registered_substate_t::attempting_registration_update:
return "ATTEMPTING-REGISTRATION-UPDATE";
case mm5g_state_t::registered_substate_t::limited_service:
return "LIMITED-SERVICE";
case mm5g_state_t::registered_substate_t::plmn_search:
return "PLMN-SEARCH";
case mm5g_state_t::registered_substate_t::no_cell_available:
return "NO-CELL-AVAILABLE";
case mm5g_state_t::registered_substate_t::update_needed:
return "UPDATE-NEEDED";
}
return "INVALID";
}
} // namespace srsue

View File

@ -19,6 +19,10 @@ add_executable(nas_test nas_test.cc)
target_link_libraries(nas_test srsue_upper srsran_common srsran_phy rrc_asn1 srsran_asn1)
add_test(nas_test nas_test)
add_executable(nas_5g_test nas_5g_test.cc)
target_link_libraries(nas_5g_test srsue_upper srsran_phy rrc_asn1)
add_test(nas_5g_test nas_5g_test)
add_executable(gw_test gw_test.cc)
target_link_libraries(gw_test srsue_upper srsran_common srsran_phy)
add_test(gw_test gw_test)

View File

@ -0,0 +1,108 @@
/**
*
* \section COPYRIGHT
*
* Copyright 2013-2021 Software Radio Systems Limited
*
* By using this file, you agree to the terms and conditions set
* forth in the LICENSE file which can be found at the top level of
* the distribution.
*
*/
#include "srsran/common/bcd_helpers.h"
#include "srsran/common/test_common.h"
#include "srsran/common/tsan_options.h"
#include "srsran/interfaces/ue_pdcp_interfaces.h"
#include "srsran/srslog/srslog.h"
#include "srsran/test/ue_test_interfaces.h"
#include "srsue/hdr/stack/upper/gw.h"
#include "srsue/hdr/stack/upper/nas_5g.h"
#include "srsue/hdr/stack/upper/test/nas_test_common.h"
using namespace srsue;
using namespace srsran;
#define HAVE_PCAP 0
int amf_attach_request_test(srsran::nas_pcap* pcap)
{
int ret = SRSRAN_ERROR;
rrc_nr_dummy rrc_nr_dummy;
pdcp_dummy pdcp_dummy;
srsue::usim usim(srslog::fetch_basic_logger("USIM"));
usim_args_t args;
args.mode = "soft";
args.algo = "xor";
args.imei = "353490069873319";
args.imsi = "001010123456789";
args.k = "00112233445566778899aabbccddeeff";
args.op = "63BFA50EE6523365FF14C1F45F88737D";
usim.init(&args);
nas_args_t nas_cfg;
nas_cfg.force_imsi_attach = true;
nas_cfg.apn_name = "test123";
nas_cfg.ia5g = "0,1,2,3";
nas_cfg.ea5g = "0,1,2,3";
test_stack_dummy<srsue::nas_5g> stack(&pdcp_dummy);
srsue::nas_5g nas_5g(&stack.task_sched);
srsue::gw gw;
if (pcap != nullptr) {
nas_5g.start_pcap(pcap);
}
gw_args_t gw_args;
gw_args.tun_dev_name = "tun0";
gw_args.log.gw_level = "debug";
gw_args.log.gw_hex_limit = 100000;
gw.init(gw_args, &stack);
stack.init(&nas_5g);
nas_5g.init(&usim, &rrc_nr_dummy, &gw, nas_cfg);
rrc_nr_dummy.init(&nas_5g);
// trigger test
stack.switch_on();
stack.stop();
gw.stop();
ret = SRSRAN_SUCCESS;
return ret;
}
int main(int argc, char** argv)
{
// Setup logging.
auto& rrc_logger = srslog::fetch_basic_logger("RRC", false);
rrc_logger.set_level(srslog::basic_levels::debug);
rrc_logger.set_hex_dump_max_size(100000);
auto& nas_logger = srslog::fetch_basic_logger("NAS", false);
nas_logger.set_level(srslog::basic_levels::debug);
nas_logger.set_hex_dump_max_size(100000);
auto& usim_logger = srslog::fetch_basic_logger("USIM", false);
usim_logger.set_level(srslog::basic_levels::debug);
usim_logger.set_hex_dump_max_size(100000);
auto& gw_logger = srslog::fetch_basic_logger("GW", false);
gw_logger.set_level(srslog::basic_levels::debug);
gw_logger.set_hex_dump_max_size(100000);
// Start the log backend.
srslog::init();
#if HAVE_PCAP
srsran::nas_pcap pcap;
pcap.open("nas_5g_test.pcap", 0, srsran::srsran_rat_t::nr);
TESTASSERT(amf_attach_request_test(&pcap) == SRSRAN_SUCCESS);
pcap.close();
#else
TESTASSERT(amf_attach_request_test(nullptr) == SRSRAN_SUCCESS);
#endif // HAVE_PCAP
return SRSRAN_SUCCESS;
}