srsue/extnas: derive abstract 'nas_base' class from 'nas'
This is the first step towards the goal of having an external NAS interface. The new 'nas_base' class becomes a parent of 'nas', combining all interfaces and the basic (common) API. The 'ue_stack_lte' now holds a unique_ptr of type 'srsue::nas_base', so the underlying NAS implementation (built-in or external) can be choosen at run-time depending on configuration. The implementation specific configuration now needs to be passed to the constructor instead, not to the init() method as was before.
This commit is contained in:
parent
d56863ff4e
commit
2b1ded220e
|
@ -174,8 +174,10 @@ private:
|
|||
srslte::rlc rlc;
|
||||
srslte::pdcp pdcp;
|
||||
srsue::rrc rrc;
|
||||
srsue::nas nas;
|
||||
std::unique_ptr<usim_base> usim;
|
||||
|
||||
// NAS implementation (built-in or external)
|
||||
std::unique_ptr<srsue::nas_base> nas;
|
||||
};
|
||||
|
||||
} // namespace srsue
|
||||
|
|
|
@ -38,15 +38,43 @@ using srslte::byte_buffer_t;
|
|||
|
||||
namespace srsue {
|
||||
|
||||
class nas : public nas_interface_rrc, public nas_interface_ue, public srslte::timer_callback
|
||||
class nas_base : public nas_interface_rrc, public nas_interface_ue, public srslte::timer_callback
|
||||
{
|
||||
public:
|
||||
explicit nas(srslte::task_sched_handle task_sched_);
|
||||
virtual ~nas() = default;
|
||||
void init(usim_interface_nas* usim_, rrc_interface_nas* rrc_, gw_interface_nas* gw_, const nas_args_t& args_);
|
||||
void stop();
|
||||
explicit nas_base(srslte::task_sched_handle task_sched_, const char *log_name_);
|
||||
virtual ~nas_base() = default;
|
||||
|
||||
virtual void init(usim_interface_nas* usim_, rrc_interface_nas* rrc_, gw_interface_nas* gw_) = 0;
|
||||
virtual void get_metrics(nas_metrics_t* m) = 0;
|
||||
virtual void stop() = 0;
|
||||
|
||||
void start_pcap(srslte::nas_pcap* pcap_);
|
||||
void run_tti();
|
||||
|
||||
protected:
|
||||
srslte::byte_buffer_pool* pool = nullptr;
|
||||
rrc_interface_nas* rrc = nullptr;
|
||||
usim_interface_nas* usim = nullptr;
|
||||
gw_interface_nas* gw = nullptr;
|
||||
|
||||
// Task handler
|
||||
srslte::task_sched_handle task_sched;
|
||||
srslte::proc_manager_list_t callbacks;
|
||||
|
||||
// Logging reference
|
||||
srslte::log_ref nas_log;
|
||||
|
||||
// PCAP
|
||||
srslte::nas_pcap* pcap = nullptr;
|
||||
};
|
||||
|
||||
class nas : public nas_base
|
||||
{
|
||||
public:
|
||||
nas(srslte::task_sched_handle task_sched_, const nas_args_t& cfg_);
|
||||
void init(usim_interface_nas* usim_, rrc_interface_nas* rrc_, gw_interface_nas* gw_);
|
||||
void stop();
|
||||
|
||||
void get_metrics(nas_metrics_t* m);
|
||||
emm_state_t get_state();
|
||||
|
||||
|
@ -72,16 +100,7 @@ public:
|
|||
// timer callback
|
||||
void timer_expired(uint32_t timeout_id) override;
|
||||
|
||||
// PCAP
|
||||
void start_pcap(srslte::nas_pcap* pcap_);
|
||||
|
||||
private:
|
||||
srslte::byte_buffer_pool* pool = nullptr;
|
||||
srslte::log_ref nas_log;
|
||||
rrc_interface_nas* rrc = nullptr;
|
||||
usim_interface_nas* usim = nullptr;
|
||||
gw_interface_nas* gw = nullptr;
|
||||
|
||||
nas_args_t cfg = { };
|
||||
|
||||
emm_state_t state = EMM_STATE_DEREGISTERED;
|
||||
|
@ -135,7 +154,6 @@ private:
|
|||
uint8_t transaction_id = 0;
|
||||
|
||||
// timers
|
||||
srslte::task_sched_handle task_sched;
|
||||
srslte::timer_handler::unique_timer t3402; // started when attach attempt counter reached 5
|
||||
srslte::timer_handler::unique_timer t3410; // started when attach request is sent, on expiry, start t3411
|
||||
srslte::timer_handler::unique_timer t3411; // started when attach failed
|
||||
|
@ -317,7 +335,6 @@ private:
|
|||
nas* nas_ptr;
|
||||
enum class state_t { plmn_search, rrc_connect } state = state_t::plmn_search;
|
||||
};
|
||||
srslte::proc_manager_list_t callbacks;
|
||||
srslte::proc_t<plmn_search_proc> plmn_searcher;
|
||||
srslte::proc_t<rrc_connect_proc> rrc_connector;
|
||||
|
||||
|
|
|
@ -37,11 +37,11 @@ ue_stack_lte::ue_stack_lte() :
|
|||
logger(nullptr),
|
||||
usim(nullptr),
|
||||
phy(nullptr),
|
||||
nas(nullptr),
|
||||
rlc("RLC"),
|
||||
mac("MAC", &task_sched),
|
||||
rrc(this, &task_sched),
|
||||
pdcp(&task_sched, "PDCP"),
|
||||
nas(&task_sched),
|
||||
thread("STACK"),
|
||||
task_sched(512, 2, 64),
|
||||
tti_tprof("tti_tprof", "STCK", TTI_STAT_PERIOD)
|
||||
|
@ -103,6 +103,11 @@ int ue_stack_lte::init(const stack_args_t& args_, srslte::logger* logger_)
|
|||
nas_log->set_level(args.log.nas_level);
|
||||
nas_log->set_hex_limit(args.log.nas_hex_limit);
|
||||
|
||||
// Should we use the built-in NAS implementation
|
||||
// TODO: or provide an external interface (RRCTL)?
|
||||
std::unique_ptr<srsue::nas> nas_impl(new srsue::nas(&task_sched, args.nas));
|
||||
nas = std::move(nas_impl);
|
||||
|
||||
// Set up pcap
|
||||
if (args.pcap.enable) {
|
||||
mac_pcap.open(args.pcap.filename.c_str());
|
||||
|
@ -110,7 +115,7 @@ int ue_stack_lte::init(const stack_args_t& args_, srslte::logger* logger_)
|
|||
}
|
||||
if (args.pcap.nas_enable) {
|
||||
nas_pcap.open(args.pcap.nas_filename.c_str());
|
||||
nas.start_pcap(&nas_pcap);
|
||||
nas->start_pcap(&nas_pcap);
|
||||
}
|
||||
|
||||
// Init USIM first to allow early exit in case reader couldn't be found
|
||||
|
@ -126,8 +131,8 @@ int ue_stack_lte::init(const stack_args_t& args_, srslte::logger* logger_)
|
|||
mac.init(phy, &rlc, &rrc);
|
||||
rlc.init(&pdcp, &rrc, task_sched.get_timer_handler(), 0 /* RB_ID_SRB0 */);
|
||||
pdcp.init(&rlc, &rrc, gw);
|
||||
nas.init(usim.get(), &rrc, gw, args.nas);
|
||||
rrc.init(phy, &mac, &rlc, &pdcp, &nas, usim.get(), gw, args.rrc);
|
||||
nas->init(usim.get(), &rrc, gw);
|
||||
rrc.init(phy, &mac, &rlc, &pdcp, nas.get(), usim.get(), gw, args.rrc);
|
||||
|
||||
running = true;
|
||||
start(STACK_MAIN_THREAD_PRIO);
|
||||
|
@ -148,7 +153,7 @@ void ue_stack_lte::stop_impl()
|
|||
running = false;
|
||||
|
||||
usim->stop();
|
||||
nas.stop();
|
||||
nas->stop();
|
||||
rrc.stop();
|
||||
|
||||
rlc.stop();
|
||||
|
@ -166,7 +171,7 @@ void ue_stack_lte::stop_impl()
|
|||
bool ue_stack_lte::switch_on()
|
||||
{
|
||||
if (running) {
|
||||
ue_task_queue.try_push([this]() { nas.start_attach_proc(nullptr, srslte::establishment_cause_t::mo_sig); });
|
||||
ue_task_queue.try_push([this]() { nas->start_attach_proc(nullptr, srslte::establishment_cause_t::mo_sig); });
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
@ -175,7 +180,7 @@ bool ue_stack_lte::switch_on()
|
|||
bool ue_stack_lte::switch_off()
|
||||
{
|
||||
// generate detach request with switch-off flag
|
||||
nas.detach_request(true);
|
||||
nas->detach_request(true);
|
||||
|
||||
// wait for max. 5s for it to be sent (according to TS 24.301 Sec 25.5.2.2)
|
||||
int cnt = 0, timeout_ms = 5000;
|
||||
|
@ -202,7 +207,7 @@ bool ue_stack_lte::disable_data()
|
|||
{
|
||||
// generate detach request
|
||||
srslte::console("Turning on airplane mode.\n");
|
||||
return nas.detach_request(false);
|
||||
return nas->detach_request(false);
|
||||
}
|
||||
|
||||
bool ue_stack_lte::get_metrics(stack_metrics_t* metrics)
|
||||
|
@ -212,7 +217,7 @@ bool ue_stack_lte::get_metrics(stack_metrics_t* metrics)
|
|||
stack_metrics_t metrics{};
|
||||
mac.get_metrics(metrics.mac);
|
||||
rlc.get_metrics(metrics.rlc);
|
||||
nas.get_metrics(&metrics.nas);
|
||||
nas->get_metrics(&metrics.nas);
|
||||
rrc.get_metrics(metrics.rrc);
|
||||
pending_stack_metrics.push(metrics);
|
||||
});
|
||||
|
@ -313,7 +318,7 @@ void ue_stack_lte::run_tti_impl(uint32_t tti, uint32_t tti_jump)
|
|||
task_sched.tic();
|
||||
}
|
||||
rrc.run_tti();
|
||||
nas.run_tti();
|
||||
nas->run_tti();
|
||||
|
||||
if (args.have_tti_time_stats) {
|
||||
std::chrono::nanoseconds dur = tti_tprof.stop();
|
||||
|
|
|
@ -235,20 +235,25 @@ proc_outcome_t nas::rrc_connect_proc::react(nas::rrc_connect_proc::connection_re
|
|||
* NAS
|
||||
********************************************************************/
|
||||
|
||||
nas::nas(srslte::task_sched_handle task_sched_) :
|
||||
nas_base::nas_base(srslte::task_sched_handle task_sched_, const char *log_name_) :
|
||||
pool(byte_buffer_pool::get_instance()),
|
||||
task_sched(task_sched_),
|
||||
nas_log{log_name_}
|
||||
{}
|
||||
|
||||
nas::nas(srslte::task_sched_handle task_sched_, const nas_args_t& cfg_) :
|
||||
nas_base::nas_base(task_sched_, "NAS"),
|
||||
cfg(cfg_),
|
||||
plmn_searcher(this),
|
||||
rrc_connector(this),
|
||||
task_sched(task_sched_),
|
||||
t3402(task_sched_.get_unique_timer()),
|
||||
t3410(task_sched_.get_unique_timer()),
|
||||
t3411(task_sched_.get_unique_timer()),
|
||||
t3421(task_sched_.get_unique_timer()),
|
||||
reattach_timer(task_sched_.get_unique_timer()),
|
||||
nas_log{"NAS"}
|
||||
reattach_timer(task_sched_.get_unique_timer())
|
||||
{}
|
||||
|
||||
void nas::init(usim_interface_nas* usim_, rrc_interface_nas* rrc_, gw_interface_nas* gw_, const nas_args_t& cfg_)
|
||||
void nas::init(usim_interface_nas* usim_, rrc_interface_nas* rrc_, gw_interface_nas* gw_)
|
||||
{
|
||||
usim = usim_;
|
||||
rrc = rrc_;
|
||||
|
@ -262,7 +267,7 @@ void nas::init(usim_interface_nas* usim_, rrc_interface_nas* rrc_, gw_interface_
|
|||
|
||||
// parse and sanity check EIA list
|
||||
std::vector<uint8_t> cap_list;
|
||||
srslte::string_parse_list(cfg_.eia, ',', cap_list);
|
||||
srslte::string_parse_list(cfg.eia, ',', cap_list);
|
||||
if (cap_list.empty()) {
|
||||
nas_log->error("Empty EIA list. Select at least one EIA algorithm.\n");
|
||||
}
|
||||
|
@ -275,7 +280,7 @@ void nas::init(usim_interface_nas* usim_, rrc_interface_nas* rrc_, gw_interface_
|
|||
}
|
||||
|
||||
// parse and sanity check EEA list
|
||||
srslte::string_parse_list(cfg_.eea, ',', cap_list);
|
||||
srslte::string_parse_list(cfg.eea, ',', cap_list);
|
||||
if (cap_list.empty()) {
|
||||
nas_log->error("Empty EEA list. Select at least one EEA algorithm.\n");
|
||||
}
|
||||
|
@ -287,8 +292,6 @@ void nas::init(usim_interface_nas* usim_, rrc_interface_nas* rrc_, gw_interface_
|
|||
}
|
||||
}
|
||||
|
||||
cfg = cfg_;
|
||||
|
||||
if ((read_ctxt_file(&ctxt))) {
|
||||
usim->generate_nas_keys(ctxt.k_asme, k_nas_enc, k_nas_int, ctxt.cipher_algo, ctxt.integ_algo);
|
||||
nas_log->debug_hex(k_nas_enc, 32, "NAS encryption key - k_nas_enc");
|
||||
|
@ -326,7 +329,7 @@ emm_state_t nas::get_state()
|
|||
return state;
|
||||
}
|
||||
|
||||
void nas::run_tti()
|
||||
void nas_base::run_tti()
|
||||
{
|
||||
callbacks.run();
|
||||
}
|
||||
|
@ -756,7 +759,7 @@ bool nas::get_ipv6_addr(uint8_t* ipv6_addr)
|
|||
PCAP
|
||||
*******************************************************************************/
|
||||
|
||||
void nas::start_pcap(srslte::nas_pcap* pcap_)
|
||||
void nas_base::start_pcap(srslte::nas_pcap* pcap_)
|
||||
{
|
||||
pcap = pcap_;
|
||||
}
|
||||
|
|
|
@ -231,11 +231,11 @@ int security_command_test()
|
|||
usim.init(&args);
|
||||
|
||||
{
|
||||
srsue::nas nas(&stack.task_sched);
|
||||
nas_args_t cfg;
|
||||
cfg.eia = "1,2,3";
|
||||
cfg.eea = "0,1,2,3";
|
||||
nas.init(&usim, &rrc_dummy, &gw, cfg);
|
||||
srsue::nas nas(&stack.task_sched, cfg);
|
||||
nas.init(&usim, &rrc_dummy, &gw);
|
||||
rrc_dummy.init(&nas);
|
||||
|
||||
// push auth request PDU to NAS to generate security context
|
||||
|
@ -299,10 +299,10 @@ int mme_attach_request_test()
|
|||
nas_cfg.apn_name = "test123";
|
||||
|
||||
test_stack_dummy stack(&pdcp_dummy);
|
||||
srsue::nas nas(&stack.task_sched);
|
||||
srsue::nas nas(&stack.task_sched, nas_cfg);
|
||||
srsue::gw gw;
|
||||
|
||||
nas.init(&usim, &rrc_dummy, &gw, nas_cfg);
|
||||
nas.init(&usim, &rrc_dummy, &gw);
|
||||
rrc_dummy.init(&nas);
|
||||
|
||||
gw_args_t gw_args;
|
||||
|
@ -377,13 +377,13 @@ int esm_info_request_test()
|
|||
pool = byte_buffer_pool::get_instance();
|
||||
|
||||
{
|
||||
srsue::nas nas(&stack.task_sched);
|
||||
nas_args_t cfg;
|
||||
cfg.apn_name = "srslte";
|
||||
cfg.apn_user = "srsuser";
|
||||
cfg.apn_pass = "srspass";
|
||||
cfg.force_imsi_attach = true;
|
||||
nas.init(&usim, &rrc_dummy, &gw, cfg);
|
||||
srsue::nas nas(&stack.task_sched, cfg);
|
||||
nas.init(&usim, &rrc_dummy, &gw);
|
||||
|
||||
// push ESM info request PDU to NAS to generate response
|
||||
unique_byte_buffer_t tmp = srslte::allocate_unique_buffer(*pool, true);
|
||||
|
@ -427,10 +427,10 @@ int dedicated_eps_bearer_test()
|
|||
|
||||
srslte::byte_buffer_pool* pool = byte_buffer_pool::get_instance();
|
||||
|
||||
srsue::nas nas(&stack.task_sched);
|
||||
nas_args_t cfg = {};
|
||||
cfg.force_imsi_attach = true; // make sure we get a fresh security context
|
||||
nas.init(&usim, &rrc_dummy, &gw, cfg);
|
||||
srsue::nas nas(&stack.task_sched, cfg);
|
||||
nas.init(&usim, &rrc_dummy, &gw);
|
||||
|
||||
// push dedicated EPS bearer PDU to NAS
|
||||
unique_byte_buffer_t tmp = srslte::allocate_unique_buffer(*pool, true);
|
||||
|
|
|
@ -173,7 +173,7 @@ public:
|
|||
class nas_test : public srsue::nas
|
||||
{
|
||||
public:
|
||||
nas_test(srslte::task_sched_handle t) : srsue::nas(t) {}
|
||||
nas_test(srslte::task_sched_handle t) : srsue::nas(t, {}) {}
|
||||
bool is_attached() override { return false; }
|
||||
};
|
||||
|
||||
|
|
Loading…
Reference in New Issue