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::rlc rlc;
|
||||||
srslte::pdcp pdcp;
|
srslte::pdcp pdcp;
|
||||||
srsue::rrc rrc;
|
srsue::rrc rrc;
|
||||||
srsue::nas nas;
|
|
||||||
std::unique_ptr<usim_base> usim;
|
std::unique_ptr<usim_base> usim;
|
||||||
|
|
||||||
|
// NAS implementation (built-in or external)
|
||||||
|
std::unique_ptr<srsue::nas_base> nas;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace srsue
|
} // namespace srsue
|
||||||
|
|
|
@ -38,15 +38,43 @@ using srslte::byte_buffer_t;
|
||||||
|
|
||||||
namespace srsue {
|
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:
|
public:
|
||||||
explicit nas(srslte::task_sched_handle task_sched_);
|
explicit nas_base(srslte::task_sched_handle task_sched_, const char *log_name_);
|
||||||
virtual ~nas() = default;
|
virtual ~nas_base() = default;
|
||||||
void init(usim_interface_nas* usim_, rrc_interface_nas* rrc_, gw_interface_nas* gw_, const nas_args_t& args_);
|
|
||||||
void stop();
|
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();
|
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);
|
void get_metrics(nas_metrics_t* m);
|
||||||
emm_state_t get_state();
|
emm_state_t get_state();
|
||||||
|
|
||||||
|
@ -72,16 +100,7 @@ public:
|
||||||
// timer callback
|
// timer callback
|
||||||
void timer_expired(uint32_t timeout_id) override;
|
void timer_expired(uint32_t timeout_id) override;
|
||||||
|
|
||||||
// PCAP
|
|
||||||
void start_pcap(srslte::nas_pcap* pcap_);
|
|
||||||
|
|
||||||
private:
|
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 = { };
|
nas_args_t cfg = { };
|
||||||
|
|
||||||
emm_state_t state = EMM_STATE_DEREGISTERED;
|
emm_state_t state = EMM_STATE_DEREGISTERED;
|
||||||
|
@ -135,7 +154,6 @@ private:
|
||||||
uint8_t transaction_id = 0;
|
uint8_t transaction_id = 0;
|
||||||
|
|
||||||
// timers
|
// 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 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 t3410; // started when attach request is sent, on expiry, start t3411
|
||||||
srslte::timer_handler::unique_timer t3411; // started when attach failed
|
srslte::timer_handler::unique_timer t3411; // started when attach failed
|
||||||
|
@ -317,7 +335,6 @@ private:
|
||||||
nas* nas_ptr;
|
nas* nas_ptr;
|
||||||
enum class state_t { plmn_search, rrc_connect } state = state_t::plmn_search;
|
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<plmn_search_proc> plmn_searcher;
|
||||||
srslte::proc_t<rrc_connect_proc> rrc_connector;
|
srslte::proc_t<rrc_connect_proc> rrc_connector;
|
||||||
|
|
||||||
|
|
|
@ -37,11 +37,11 @@ ue_stack_lte::ue_stack_lte() :
|
||||||
logger(nullptr),
|
logger(nullptr),
|
||||||
usim(nullptr),
|
usim(nullptr),
|
||||||
phy(nullptr),
|
phy(nullptr),
|
||||||
|
nas(nullptr),
|
||||||
rlc("RLC"),
|
rlc("RLC"),
|
||||||
mac("MAC", &task_sched),
|
mac("MAC", &task_sched),
|
||||||
rrc(this, &task_sched),
|
rrc(this, &task_sched),
|
||||||
pdcp(&task_sched, "PDCP"),
|
pdcp(&task_sched, "PDCP"),
|
||||||
nas(&task_sched),
|
|
||||||
thread("STACK"),
|
thread("STACK"),
|
||||||
task_sched(512, 2, 64),
|
task_sched(512, 2, 64),
|
||||||
tti_tprof("tti_tprof", "STCK", TTI_STAT_PERIOD)
|
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_level(args.log.nas_level);
|
||||||
nas_log->set_hex_limit(args.log.nas_hex_limit);
|
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
|
// Set up pcap
|
||||||
if (args.pcap.enable) {
|
if (args.pcap.enable) {
|
||||||
mac_pcap.open(args.pcap.filename.c_str());
|
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) {
|
if (args.pcap.nas_enable) {
|
||||||
nas_pcap.open(args.pcap.nas_filename.c_str());
|
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
|
// 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);
|
mac.init(phy, &rlc, &rrc);
|
||||||
rlc.init(&pdcp, &rrc, task_sched.get_timer_handler(), 0 /* RB_ID_SRB0 */);
|
rlc.init(&pdcp, &rrc, task_sched.get_timer_handler(), 0 /* RB_ID_SRB0 */);
|
||||||
pdcp.init(&rlc, &rrc, gw);
|
pdcp.init(&rlc, &rrc, gw);
|
||||||
nas.init(usim.get(), &rrc, gw, args.nas);
|
nas->init(usim.get(), &rrc, gw);
|
||||||
rrc.init(phy, &mac, &rlc, &pdcp, &nas, usim.get(), gw, args.rrc);
|
rrc.init(phy, &mac, &rlc, &pdcp, nas.get(), usim.get(), gw, args.rrc);
|
||||||
|
|
||||||
running = true;
|
running = true;
|
||||||
start(STACK_MAIN_THREAD_PRIO);
|
start(STACK_MAIN_THREAD_PRIO);
|
||||||
|
@ -148,7 +153,7 @@ void ue_stack_lte::stop_impl()
|
||||||
running = false;
|
running = false;
|
||||||
|
|
||||||
usim->stop();
|
usim->stop();
|
||||||
nas.stop();
|
nas->stop();
|
||||||
rrc.stop();
|
rrc.stop();
|
||||||
|
|
||||||
rlc.stop();
|
rlc.stop();
|
||||||
|
@ -166,7 +171,7 @@ void ue_stack_lte::stop_impl()
|
||||||
bool ue_stack_lte::switch_on()
|
bool ue_stack_lte::switch_on()
|
||||||
{
|
{
|
||||||
if (running) {
|
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 true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
@ -175,7 +180,7 @@ bool ue_stack_lte::switch_on()
|
||||||
bool ue_stack_lte::switch_off()
|
bool ue_stack_lte::switch_off()
|
||||||
{
|
{
|
||||||
// generate detach request with switch-off flag
|
// 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)
|
// 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;
|
int cnt = 0, timeout_ms = 5000;
|
||||||
|
@ -202,7 +207,7 @@ bool ue_stack_lte::disable_data()
|
||||||
{
|
{
|
||||||
// generate detach request
|
// generate detach request
|
||||||
srslte::console("Turning on airplane mode.\n");
|
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)
|
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{};
|
stack_metrics_t metrics{};
|
||||||
mac.get_metrics(metrics.mac);
|
mac.get_metrics(metrics.mac);
|
||||||
rlc.get_metrics(metrics.rlc);
|
rlc.get_metrics(metrics.rlc);
|
||||||
nas.get_metrics(&metrics.nas);
|
nas->get_metrics(&metrics.nas);
|
||||||
rrc.get_metrics(metrics.rrc);
|
rrc.get_metrics(metrics.rrc);
|
||||||
pending_stack_metrics.push(metrics);
|
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();
|
task_sched.tic();
|
||||||
}
|
}
|
||||||
rrc.run_tti();
|
rrc.run_tti();
|
||||||
nas.run_tti();
|
nas->run_tti();
|
||||||
|
|
||||||
if (args.have_tti_time_stats) {
|
if (args.have_tti_time_stats) {
|
||||||
std::chrono::nanoseconds dur = tti_tprof.stop();
|
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::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()),
|
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),
|
plmn_searcher(this),
|
||||||
rrc_connector(this),
|
rrc_connector(this),
|
||||||
task_sched(task_sched_),
|
|
||||||
t3402(task_sched_.get_unique_timer()),
|
t3402(task_sched_.get_unique_timer()),
|
||||||
t3410(task_sched_.get_unique_timer()),
|
t3410(task_sched_.get_unique_timer()),
|
||||||
t3411(task_sched_.get_unique_timer()),
|
t3411(task_sched_.get_unique_timer()),
|
||||||
t3421(task_sched_.get_unique_timer()),
|
t3421(task_sched_.get_unique_timer()),
|
||||||
reattach_timer(task_sched_.get_unique_timer()),
|
reattach_timer(task_sched_.get_unique_timer())
|
||||||
nas_log{"NAS"}
|
|
||||||
{}
|
{}
|
||||||
|
|
||||||
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_;
|
usim = usim_;
|
||||||
rrc = rrc_;
|
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
|
// parse and sanity check EIA list
|
||||||
std::vector<uint8_t> cap_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()) {
|
if (cap_list.empty()) {
|
||||||
nas_log->error("Empty EIA list. Select at least one EIA algorithm.\n");
|
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
|
// 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()) {
|
if (cap_list.empty()) {
|
||||||
nas_log->error("Empty EEA list. Select at least one EEA algorithm.\n");
|
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))) {
|
if ((read_ctxt_file(&ctxt))) {
|
||||||
usim->generate_nas_keys(ctxt.k_asme, k_nas_enc, k_nas_int, ctxt.cipher_algo, ctxt.integ_algo);
|
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");
|
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;
|
return state;
|
||||||
}
|
}
|
||||||
|
|
||||||
void nas::run_tti()
|
void nas_base::run_tti()
|
||||||
{
|
{
|
||||||
callbacks.run();
|
callbacks.run();
|
||||||
}
|
}
|
||||||
|
@ -756,7 +759,7 @@ bool nas::get_ipv6_addr(uint8_t* ipv6_addr)
|
||||||
PCAP
|
PCAP
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
|
|
||||||
void nas::start_pcap(srslte::nas_pcap* pcap_)
|
void nas_base::start_pcap(srslte::nas_pcap* pcap_)
|
||||||
{
|
{
|
||||||
pcap = pcap_;
|
pcap = pcap_;
|
||||||
}
|
}
|
||||||
|
|
|
@ -231,11 +231,11 @@ int security_command_test()
|
||||||
usim.init(&args);
|
usim.init(&args);
|
||||||
|
|
||||||
{
|
{
|
||||||
srsue::nas nas(&stack.task_sched);
|
|
||||||
nas_args_t cfg;
|
nas_args_t cfg;
|
||||||
cfg.eia = "1,2,3";
|
cfg.eia = "1,2,3";
|
||||||
cfg.eea = "0,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);
|
rrc_dummy.init(&nas);
|
||||||
|
|
||||||
// push auth request PDU to NAS to generate security context
|
// push auth request PDU to NAS to generate security context
|
||||||
|
@ -299,10 +299,10 @@ int mme_attach_request_test()
|
||||||
nas_cfg.apn_name = "test123";
|
nas_cfg.apn_name = "test123";
|
||||||
|
|
||||||
test_stack_dummy stack(&pdcp_dummy);
|
test_stack_dummy stack(&pdcp_dummy);
|
||||||
srsue::nas nas(&stack.task_sched);
|
srsue::nas nas(&stack.task_sched, nas_cfg);
|
||||||
srsue::gw gw;
|
srsue::gw gw;
|
||||||
|
|
||||||
nas.init(&usim, &rrc_dummy, &gw, nas_cfg);
|
nas.init(&usim, &rrc_dummy, &gw);
|
||||||
rrc_dummy.init(&nas);
|
rrc_dummy.init(&nas);
|
||||||
|
|
||||||
gw_args_t gw_args;
|
gw_args_t gw_args;
|
||||||
|
@ -377,13 +377,13 @@ int esm_info_request_test()
|
||||||
pool = byte_buffer_pool::get_instance();
|
pool = byte_buffer_pool::get_instance();
|
||||||
|
|
||||||
{
|
{
|
||||||
srsue::nas nas(&stack.task_sched);
|
|
||||||
nas_args_t cfg;
|
nas_args_t cfg;
|
||||||
cfg.apn_name = "srslte";
|
cfg.apn_name = "srslte";
|
||||||
cfg.apn_user = "srsuser";
|
cfg.apn_user = "srsuser";
|
||||||
cfg.apn_pass = "srspass";
|
cfg.apn_pass = "srspass";
|
||||||
cfg.force_imsi_attach = true;
|
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
|
// push ESM info request PDU to NAS to generate response
|
||||||
unique_byte_buffer_t tmp = srslte::allocate_unique_buffer(*pool, true);
|
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();
|
srslte::byte_buffer_pool* pool = byte_buffer_pool::get_instance();
|
||||||
|
|
||||||
srsue::nas nas(&stack.task_sched);
|
|
||||||
nas_args_t cfg = {};
|
nas_args_t cfg = {};
|
||||||
cfg.force_imsi_attach = true; // make sure we get a fresh security context
|
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
|
// push dedicated EPS bearer PDU to NAS
|
||||||
unique_byte_buffer_t tmp = srslte::allocate_unique_buffer(*pool, true);
|
unique_byte_buffer_t tmp = srslte::allocate_unique_buffer(*pool, true);
|
||||||
|
|
|
@ -173,7 +173,7 @@ public:
|
||||||
class nas_test : public srsue::nas
|
class nas_test : public srsue::nas
|
||||||
{
|
{
|
||||||
public:
|
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; }
|
bool is_attached() override { return false; }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue