add radio_base/null classes

This commit is contained in:
Francisco Paisana 2020-06-16 12:08:34 +01:00
parent e26653c87f
commit f0874b780b
38 changed files with 542 additions and 163 deletions

View File

@ -342,7 +342,7 @@ private:
return 0;
}
void send_rx_data_ind(const uint32_t tti)
void send_rx_data_ind(const uint32_t tti_)
{
// MAC PDU for UL-SCH with IPv6 router solicitation
static uint8_t tv[] = {0x04, 0x38, 0x00, 0x80, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x08, 0x3a, 0xff, 0xfe,
@ -354,7 +354,7 @@ private:
rx_ind.header.type = basic_vnf_api::RX_DATA_IND;
rx_ind.header.msg_len = sizeof(rx_ind) - sizeof(basic_vnf_api::msg_header_t);
rx_ind.sfn = tti;
rx_ind.sfn = tti_;
rx_ind.t1 = 0;
rx_ind.nof_pdus = 1;
@ -377,7 +377,7 @@ private:
}
}
void send_dl_ind(uint32_t tti)
void send_dl_ind(uint32_t tti_)
{
#if PING_REQUEST_PDU
static uint8_t tv[] = {
@ -408,7 +408,7 @@ private:
dl_ind.header.type = basic_vnf_api::DL_IND;
dl_ind.header.msg_len = sizeof(dl_ind) - sizeof(basic_vnf_api::msg_header_t);
dl_ind.tti = tti;
dl_ind.tti = tti_;
dl_ind.t1 = 0;
dl_ind.nof_pdus = 1;

View File

@ -67,12 +67,8 @@ enum msg_type_t {
UL_IND, ///< For the UE for UL Data
MSG_TYPE_NITEMS
};
static const char* msg_type_text[MSG_TYPE_NITEMS] = {"SF Indication",
"DL_CONFIG.Request",
"TX.Request",
"RX_Data.indication"
"DL_Indication",
"UL_Indication"};
static const char* msg_type_text[MSG_TYPE_NITEMS] =
{"SF Indication", "DL_CONFIG.Request", "TX.Request", "RX_Data.indication", "DL_Indication", "UL_Indication"};
enum pdu_type_t { MAC_PBCH, PHY_PBCH, PDCCH, PDSCH, PUSCH };
struct msg_header_t {

View File

@ -23,6 +23,7 @@
#define SRSLTE_MAC_NR_PDU_H
#include "srslte/common/common.h"
#include "srslte/common/logmap.h"
#include <memory>
#include <stdint.h>
#include <vector>
@ -87,6 +88,7 @@ private:
uint8_t* sdu = nullptr;
mac_nr_sch_pdu* parent = nullptr;
srslte::log_ref log_h;
};
class mac_nr_sch_pdu

View File

@ -27,6 +27,8 @@
#include "srslte/common/log_filter.h"
#include "srslte/interfaces/radio_interfaces.h"
#include "srslte/phy/rf/rf.h"
#include "srslte/radio/radio_base.h"
#include "srslte/srslte.h"
#include <list>
#include <string>
@ -46,15 +48,16 @@ namespace srslte {
* rf driver object. In the current implementation, the mapping between N carriers and P antennas is sequentially, eg:
* [carrier_0_port_0, carrier_0_port_1, carrier_1_port_0, carrier_1_port_1, ..., carrier_N_port_N]
*/
class radio : public radio_interface_phy
class radio : public radio_interface_phy, public srslte::radio_base
{
public:
radio(srslte::log_filter* log_h);
radio(srslte::logger* logger_h);
virtual ~radio();
int init(const rf_args_t& args_, phy_interface_radio* phy_);
void stop();
int init(const rf_args_t& args_, phy_interface_radio* phy_);
void stop();
std::string get_type() override { return "radio"; }
// ==== PHY interface ===

View File

@ -0,0 +1,54 @@
/*
* Copyright 2013-2019 Software Radio Systems Limited
*
* This file is part of srsLTE.
*
* srsLTE is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of
* the License, or (at your option) any later version.
*
* srsLTE is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* A copy of the GNU Affero General Public License can be found in
* the LICENSE file in the top-level directory of this distribution
* and at http://www.gnu.org/licenses/.
*
*/
/******************************************************************************
* File: radio_base.h
* Description: Base class for all eNB/UE radios.
*****************************************************************************/
#ifndef SRSLTE_RADIO_BASE_H
#define SRSLTE_RADIO_BASE_H
#include "srslte/common/interfaces_common.h"
#include "srslte/common/logger.h"
#include "srslte/radio/radio_metrics.h"
namespace srslte {
class phy_interface_radio;
class radio_base
{
public:
radio_base(srslte::logger* logger_ = nullptr){};
virtual ~radio_base(){};
virtual std::string get_type() = 0;
virtual int init(const rf_args_t& args_, phy_interface_radio* phy_) = 0;
virtual void stop() = 0;
virtual bool get_metrics(rf_metrics_t* metrics) = 0;
};
} // namespace srslte
#endif // SRSLTE_RADIO_BASE_H

View File

@ -0,0 +1,133 @@
/*
* Copyright 2013-2019 Software Radio Systems Limited
*
* This file is part of srsLTE.
*
* srsLTE is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of
* the License, or (at your option) any later version.
*
* srsLTE is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* A copy of the GNU Affero General Public License can be found in
* the LICENSE file in the top-level directory of this distribution
* and at http://www.gnu.org/licenses/.
*
*/
/******************************************************************************
* File: radio_null.h
* Description: Dummy radio class
*****************************************************************************/
#ifndef SRSLTE_RADIO_NULL_H
#define SRSLTE_RADIO_NULL_H
#include "radio_base.h"
#include "srslte/common/logger.h"
#include "srslte/interfaces/radio_interfaces.h"
#include "srslte/phy/rf/rf.h"
#include "srslte/radio/radio.h"
#include "srslte/radio/radio_metrics.h"
namespace srslte {
class radio_null : public radio_base, public radio_interface_phy
{
public:
explicit radio_null(srslte::logger* logger_);
~radio_null() = default;
std::string get_type() override { return "null"; }
int init(const rf_args_t& args_, phy_interface_radio* phy_) override
{
log.init("RF ", logger);
log.set_level(args.log_level);
running = true;
return SRSLTE_SUCCESS;
}
void stop() override { running = false; }
bool get_metrics(rf_metrics_t* metrics) override
{
// do nothing
return true;
}
// radio_interface_phy
bool is_init() override { return running; }
void reset() override {}
bool is_continuous_tx() override { return false; }
bool tx(rf_buffer_interface& buffer, const rf_timestamp_interface& tx_time) override
{
log.info("%s\n", __PRETTY_FUNCTION__);
return true;
}
void tx_end() override { log.info("%s\n", __PRETTY_FUNCTION__); }
bool rx_now(rf_buffer_interface& buffer, rf_timestamp_interface& rxd_time) override
{
log.info("%s\n", __PRETTY_FUNCTION__);
return true;
}
void set_rx_gain(const float& gain) override { log.info("%s\n", __PRETTY_FUNCTION__); }
void set_rx_gain_th(const float& gain) override { log.info("%s\n", __PRETTY_FUNCTION__); }
float get_rx_gain() override
{
log.info("%s\n", __PRETTY_FUNCTION__);
return 0.0;
}
void set_tx_gain(const float& gain) override { log.info("%s\n", __PRETTY_FUNCTION__); }
void set_tx_freq(const uint32_t& channel_idx, const double& freq) override { log.info("%s\n", __PRETTY_FUNCTION__); }
void set_rx_freq(const uint32_t& channel_idx, const double& freq) override { log.info("%s\n", __PRETTY_FUNCTION__); }
double get_freq_offset() override
{
log.info("%s\n", __PRETTY_FUNCTION__);
return 0.0;
}
void set_tx_srate(const double& srate) override { log.info("%s\n", __PRETTY_FUNCTION__); }
void set_rx_srate(const double& srate) override { log.info("%s\n", __PRETTY_FUNCTION__); }
srslte_rf_info_t* get_info() override
{
log.info("%s\n", __PRETTY_FUNCTION__);
return nullptr;
}
bool get_is_start_of_burst() override { return true; }
void release_freq(const uint32_t& carrier_idx) override { log.info("%s\n", __PRETTY_FUNCTION__); }
void set_channel_rx_offset(uint32_t ch, int32_t offset_samples) override { log.info("%s\n", __PRETTY_FUNCTION__); }
protected:
rf_args_t args = {};
srslte::logger* logger = nullptr;
srslte::log_filter log;
bool running = false;
srslte::rf_metrics_t rf_metrics = {};
phy_interface_radio* phy = nullptr;
};
} // namespace srslte
#endif // SRSLTE_RADIO_NULL_H

View File

@ -72,7 +72,7 @@ private:
srslte::task_handler_interface* task_executor = nullptr;
srslte::log_ref pdcp_log;
std::map<uint16_t, std::unique_ptr<pdcp_entity_lte> > pdcp_array, pdcp_array_mrb;
std::map<uint16_t, std::unique_ptr<pdcp_entity_base> > pdcp_array, pdcp_array_mrb;
// cache valid lcids to be checked from separate thread
std::mutex cache_mutex;

View File

@ -114,10 +114,13 @@ public:
void config_security(as_security_config_t sec_cfg_);
// GW/SDAP/RRC interface
void write_sdu(unique_byte_buffer_t sdu, bool blocking);
virtual void write_sdu(unique_byte_buffer_t sdu, bool blocking) = 0;
// RLC interface
void write_pdu(unique_byte_buffer_t pdu);
virtual void write_pdu(unique_byte_buffer_t pdu) = 0;
virtual void get_bearer_state(pdcp_lte_state_t* state) = 0;
virtual void set_bearer_state(const pdcp_lte_state_t& state) = 0;
// COUNT, HFN and SN helpers
uint32_t HFN(uint32_t count);

View File

@ -50,23 +50,25 @@ public:
srsue::rrc_interface_pdcp* rrc_,
srsue::gw_interface_pdcp* gw_,
srslte::task_handler_interface* task_executor_,
srslte::log_ref log_);
~pdcp_entity_lte();
void init(uint32_t lcid_, pdcp_config_t cfg_);
void reset();
void reestablish();
srslte::log_ref log_,
uint32_t lcid_,
pdcp_config_t cfg_);
~pdcp_entity_lte() override;
void reset() override;
void reestablish() override;
// GW/RRC interface
void write_sdu(unique_byte_buffer_t sdu, bool blocking);
void get_bearer_state(pdcp_lte_state_t* state);
void set_bearer_state(const pdcp_lte_state_t& state);
void write_sdu(unique_byte_buffer_t sdu, bool blocking) override;
// RLC interface
void write_pdu(unique_byte_buffer_t pdu);
void write_pdu(unique_byte_buffer_t pdu) override;
// Config helpers
bool check_valid_config();
void get_bearer_state(pdcp_lte_state_t* state) override;
void set_bearer_state(const pdcp_lte_state_t& state) override;
private:
srsue::rlc_interface_pdcp* rlc = nullptr;
srsue::rrc_interface_pdcp* rrc = nullptr;

View File

@ -38,24 +38,25 @@ namespace srslte {
* NR PDCP Entity
* PDCP entity for 5G NR
***************************************************************************/
class pdcp_entity_nr : public pdcp_entity_base
class pdcp_entity_nr final : public pdcp_entity_base
{
public:
pdcp_entity_nr(srsue::rlc_interface_pdcp* rlc_,
srsue::rrc_interface_pdcp* rrc_,
srsue::gw_interface_pdcp* gw_,
srslte::task_handler_interface* task_executor_,
srslte::log_ref log_);
~pdcp_entity_nr();
void init(uint32_t lcid_, pdcp_config_t cfg_);
void reset();
void reestablish();
srslte::log_ref log_,
uint32_t lcid,
pdcp_config_t cfg_);
~pdcp_entity_nr() final;
void reset() final;
void reestablish() final;
// RRC interface
void write_sdu(unique_byte_buffer_t sdu, bool blocking);
void write_sdu(unique_byte_buffer_t sdu, bool blocking) final;
// RLC interface
void write_pdu(unique_byte_buffer_t pdu);
void write_pdu(unique_byte_buffer_t pdu) final;
// State variable setters (should be used only for testing)
void set_tx_next(uint32_t tx_next_) { tx_next = tx_next_; }
@ -63,12 +64,13 @@ public:
void set_rx_deliv(uint32_t rx_deliv_) { rx_deliv = rx_deliv_; }
void set_rx_reord(uint32_t rx_reord_) { rx_reord = rx_reord_; }
void get_bearer_state(pdcp_lte_state_t* state) override;
void set_bearer_state(const pdcp_lte_state_t& state) override;
// State variable getters (useful for testing)
uint32_t nof_discard_timers() { return discard_timers_map.size(); }
private:
bool initialized = false;
srsue::rlc_interface_pdcp* rlc = nullptr;
srsue::rrc_interface_pdcp* rrc = nullptr;
srsue::gw_interface_pdcp* gw = nullptr;

View File

@ -23,7 +23,7 @@
namespace srslte {
mac_nr_sch_subpdu::mac_nr_sch_subpdu(mac_nr_sch_pdu* parent_) : parent(parent_) {}
mac_nr_sch_subpdu::mac_nr_sch_subpdu(mac_nr_sch_pdu* parent_) : parent(parent_), log_h("MAC") {}
mac_nr_sch_subpdu::nr_lcid_sch_t mac_nr_sch_subpdu::get_type()
{
@ -78,7 +78,7 @@ int32_t mac_nr_sch_subpdu::read_subheader(const uint8_t* ptr)
}
sdu = (uint8_t*)ptr;
} else {
fprintf(stderr, "Invalid LCID (%d) in MAC PDU\n", lcid);
log_h->warning("Invalid LCID (%d) in MAC PDU\n", lcid);
return SRSLTE_ERROR;
}
return header_length;
@ -94,7 +94,7 @@ void mac_nr_sch_subpdu::set_sdu(const uint32_t lcid_, const uint8_t* payload_, c
F_bit = false;
sdu_length = sizeof_ce(lcid, parent->is_ulsch());
if (len_ != static_cast<uint32_t>(sdu_length)) {
fprintf(stderr, "Invalid SDU length of UL-SCH SDU (%d != %d)\n", len_, sdu_length);
log_h->warning("Invalid SDU length of UL-SCH SDU (%d != %d)\n", len_, sdu_length);
}
}
@ -133,7 +133,7 @@ uint32_t mac_nr_sch_subpdu::write_subpdu(const uint8_t* start_)
} else if (header_length == 1) {
// do nothing
} else {
fprintf(stderr, "Error while packing PDU. Unsupported header length (%d)\n", header_length);
log_h->warning("Error while packing PDU. Unsupported header length (%d)\n", header_length);
}
// copy SDU payload
@ -232,6 +232,12 @@ void mac_nr_sch_pdu::unpack(const uint8_t* payload, const uint32_t& len)
return;
}
offset += sch_pdu.get_total_length();
if (sch_pdu.get_lcid() == mac_nr_sch_subpdu::PADDING) {
// set SDU length to rest of PDU
sch_pdu.set_padding(len - offset + 1); // One byte for Padding header will be substracted again
// skip remaining bytes
offset = len;
}
subpdus.push_back(sch_pdu);
}
if (offset != len) {
@ -256,7 +262,8 @@ bool mac_nr_sch_pdu::is_ulsch()
void mac_nr_sch_pdu::init_tx(byte_buffer_t* buffer_, uint32_t pdu_len_, bool ulsch_)
{
buffer = buffer_;
buffer = buffer_;
subpdus.clear();
pdu_len = pdu_len_;
remaining_len = pdu_len_;
ulsch = ulsch_;

View File

@ -204,7 +204,7 @@ int main(int argc, char** argv)
}
for (uint32_t i = 0; i < snr_points; i++) {
frame_cnt = 0;
frame_cnt = 0;
errors_s = 0;
errors_c = 0;
errors_f = 0;

View File

@ -114,8 +114,8 @@ int rf_zmq_rx_open(rf_zmq_rx_t* q, rf_zmq_opts_t opts, void* zmq_ctx, char* sock
goto clean_exit;
}
q->socket_type = opts.socket_type;
q->sample_format = opts.sample_format;
q->frequency_mhz = opts.frequency_mhz;
q->sample_format = opts.sample_format;
q->frequency_mhz = opts.frequency_mhz;
q->fail_on_disconnect = opts.fail_on_disconnect;
if (opts.socket_type == ZMQ_SUB) {

View File

@ -19,7 +19,7 @@
#
if(RF_FOUND)
add_library(srslte_radio STATIC radio.cc channel_mapping.cc)
add_library(srslte_radio STATIC radio.cc radio_null.cc channel_mapping.cc)
target_link_libraries(srslte_radio srslte_rf)
endif(RF_FOUND)

View File

@ -0,0 +1,29 @@
/*
* Copyright 2013-2019 Software Radio Systems Limited
*
* This file is part of srsLTE.
*
* srsLTE is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of
* the License, or (at your option) any later version.
*
* srsLTE is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* A copy of the GNU Affero General Public License can be found in
* the LICENSE file in the top-level directory of this distribution
* and at http://www.gnu.org/licenses/.
*
*/
#include "srslte/radio/radio_null.h"
#include <mutex>
namespace srslte {
radio_null::radio_null(srslte::logger* logger_) : logger(logger_), radio_base(logger_) {}
} // namespace srslte

View File

@ -20,6 +20,7 @@
*/
#include "srslte/upper/pdcp.h"
#include "srslte/upper/pdcp_entity_nr.h"
namespace srslte {
@ -101,14 +102,17 @@ void pdcp::write_sdu_mch(uint32_t lcid, unique_byte_buffer_t sdu)
void pdcp::add_bearer(uint32_t lcid, pdcp_config_t cfg)
{
if (not valid_lcid(lcid)) {
if (not pdcp_array
.insert(std::make_pair(
lcid, std::unique_ptr<pdcp_entity_lte>(new pdcp_entity_lte(rlc, rrc, gw, task_executor, pdcp_log))))
.second) {
// create NR entity for 18bit SN length
std::unique_ptr<pdcp_entity_base> entity;
if (cfg.sn_len == srslte::PDCP_SN_LEN_18) {
entity.reset(new pdcp_entity_nr{rlc, rrc, gw, task_executor, pdcp_log, lcid, cfg});
} else {
entity.reset(new pdcp_entity_lte{rlc, rrc, gw, task_executor, pdcp_log, lcid, cfg});
}
if (not pdcp_array.insert(std::make_pair(lcid, std::move(entity))).second) {
pdcp_log->error("Error inserting PDCP entity in to array\n.");
return;
}
pdcp_array.at(lcid)->init(lcid, cfg);
pdcp_log->info("Add %s (lcid=%d, bearer_id=%d, sn_len=%dbits)\n",
rrc->get_rb_name(lcid).c_str(),
lcid,
@ -127,13 +131,13 @@ void pdcp::add_bearer_mrb(uint32_t lcid, pdcp_config_t cfg)
{
if (not valid_mch_lcid(lcid)) {
if (not pdcp_array_mrb
.insert(std::make_pair(
lcid, std::unique_ptr<pdcp_entity_lte>(new pdcp_entity_lte(rlc, rrc, gw, task_executor, pdcp_log))))
.insert(std::make_pair(lcid,
std::unique_ptr<pdcp_entity_lte>(
new pdcp_entity_lte(rlc, rrc, gw, task_executor, pdcp_log, lcid, cfg))))
.second) {
pdcp_log->error("Error inserting PDCP entity in to array\n.");
return;
}
pdcp_array_mrb.at(lcid)->init(lcid, cfg);
pdcp_log->info("Add %s (lcid=%d, bearer_id=%d, sn_len=%dbits)\n",
rrc->get_rb_name(lcid).c_str(),
lcid,
@ -163,9 +167,9 @@ void pdcp::change_lcid(uint32_t old_lcid, uint32_t new_lcid)
// make sure old LCID exists and new LCID is still free
if (valid_lcid(old_lcid) && not valid_lcid(new_lcid)) {
// insert old PDCP entity into new LCID
std::lock_guard<std::mutex> lock(cache_mutex);
auto it = pdcp_array.find(old_lcid);
std::unique_ptr<pdcp_entity_lte> pdcp_entity = std::move(it->second);
std::lock_guard<std::mutex> lock(cache_mutex);
auto it = pdcp_array.find(old_lcid);
std::unique_ptr<pdcp_entity_base> pdcp_entity = std::move(it->second);
if (not pdcp_array.insert(std::make_pair(new_lcid, std::move(pdcp_entity))).second) {
pdcp_log->error("Error inserting PDCP entity into array\n.");
return;

View File

@ -28,21 +28,17 @@ pdcp_entity_lte::pdcp_entity_lte(srsue::rlc_interface_pdcp* rlc_,
srsue::rrc_interface_pdcp* rrc_,
srsue::gw_interface_pdcp* gw_,
srslte::task_handler_interface* task_executor_,
srslte::log_ref log_) :
pdcp_entity_base(task_executor_, log_), rlc(rlc_), rrc(rrc_), gw(gw_)
{}
pdcp_entity_lte::~pdcp_entity_lte()
srslte::log_ref log_,
uint32_t lcid_,
pdcp_config_t cfg_) :
pdcp_entity_base(task_executor_, log_),
rlc(rlc_),
rrc(rrc_),
gw(gw_)
{
reset();
}
void pdcp_entity_lte::init(uint32_t lcid_, pdcp_config_t cfg_)
{
lcid = lcid_;
cfg = cfg_;
active = true;
lcid = lcid_;
cfg = cfg_;
active = true;
integrity_direction = DIRECTION_NONE;
encryption_direction = DIRECTION_NONE;
@ -72,6 +68,11 @@ void pdcp_entity_lte::init(uint32_t lcid_, pdcp_config_t cfg_)
}
}
pdcp_entity_lte::~pdcp_entity_lte()
{
reset();
}
// Reestablishment procedure: 36.323 5.2
void pdcp_entity_lte::reestablish()
{

View File

@ -28,18 +28,14 @@ pdcp_entity_nr::pdcp_entity_nr(srsue::rlc_interface_pdcp* rlc_,
srsue::rrc_interface_pdcp* rrc_,
srsue::gw_interface_pdcp* gw_,
srslte::task_handler_interface* task_executor_,
srslte::log_ref log_) :
srslte::log_ref log_,
uint32_t lcid_,
pdcp_config_t cfg_) :
pdcp_entity_base(task_executor_, log_),
rlc(rlc_),
rrc(rrc_),
gw(gw_),
reordering_fnc(new pdcp_entity_nr::reordering_callback(this))
{
}
pdcp_entity_nr::~pdcp_entity_nr() {}
void pdcp_entity_nr::init(uint32_t lcid_, pdcp_config_t cfg_)
{
lcid = lcid_;
cfg = cfg_;
@ -56,11 +52,10 @@ void pdcp_entity_nr::init(uint32_t lcid_, pdcp_config_t cfg_)
if (static_cast<uint32_t>(cfg.t_reordering) > 0) {
reordering_timer.set(static_cast<uint32_t>(cfg.t_reordering), *reordering_fnc);
}
// Mark entity as initialized
initialized = true;
}
pdcp_entity_nr::~pdcp_entity_nr() {}
// Reestablishment procedure: 38.323 5.2
void pdcp_entity_nr::reestablish()
{
@ -78,11 +73,6 @@ void pdcp_entity_nr::reset()
// SDAP/RRC interface
void pdcp_entity_nr::write_sdu(unique_byte_buffer_t sdu, bool blocking)
{
// Check initialization
if (not initialized) {
return;
}
// Log SDU
log->info_hex(sdu->msg,
sdu->N_bytes,
@ -136,11 +126,6 @@ void pdcp_entity_nr::write_sdu(unique_byte_buffer_t sdu, bool blocking)
// RLC interface
void pdcp_entity_nr::write_pdu(unique_byte_buffer_t pdu)
{
// Check initialization
if (not initialized) {
return;
}
// Log PDU
log->info_hex(pdu->msg,
pdu->N_bytes,
@ -276,7 +261,6 @@ void pdcp_entity_nr::reordering_callback::operator()(uint32_t timer_id)
parent->rx_reord = parent->rx_next;
parent->reordering_timer.run();
}
return;
}
// Discard Timer Callback (discardTimer)
@ -290,7 +274,16 @@ void pdcp_entity_nr::discard_callback::operator()(uint32_t timer_id)
// Remove timer from map
// NOTE: this will delete the callback. It *must* be the last instruction.
parent->discard_timers_map.erase(discard_sn);
return;
}
void pdcp_entity_nr::get_bearer_state(pdcp_lte_state_t* state)
{
// TODO
}
void pdcp_entity_nr::set_bearer_state(const pdcp_lte_state_t& state)
{
// TODO
}
} // namespace srslte

View File

@ -24,6 +24,6 @@ add_test(pdu_test pdu_test)
if (ENABLE_5GNR)
add_executable(mac_nr_pdu_test mac_nr_pdu_test.cc)
target_link_libraries(mac_nr_pdu_test srslte_phy srslte_common srslte_mac ${CMAKE_THREAD_LIBS_INIT})
target_link_libraries(mac_nr_pdu_test srslte_phy srslte_mac srslte_common ${CMAKE_THREAD_LIBS_INIT})
add_test(mac_nr_pdu_test mac_nr_pdu_test)
endif (ENABLE_5GNR)

View File

@ -68,11 +68,13 @@ srslte::pdcp_lte_state_t normal_init_state = {};
class pdcp_lte_test_helper
{
public:
pdcp_lte_test_helper(srslte::pdcp_config_t cfg, srslte::as_security_config_t sec_cfg, srslte::log_ref log) :
rlc(log), rrc(log), gw(log), pdcp(&rlc, &rrc, &gw, &stack, log)
pdcp_lte_test_helper(srslte::pdcp_config_t cfg, srslte::as_security_config_t sec_cfg_, srslte::log_ref log) :
rlc(log),
rrc(log),
gw(log),
pdcp(&rlc, &rrc, &gw, &stack, log, 0, cfg)
{
pdcp.init(0, cfg);
pdcp.config_security(sec_cfg);
pdcp.config_security(sec_cfg_);
pdcp.enable_integrity(srslte::DIRECTION_TXRX);
pdcp.enable_encryption(srslte::DIRECTION_TXRX);
}

View File

@ -96,14 +96,13 @@ pdcp_initial_state near_wraparound_init_state = {.tx_next = 4294967295,
class pdcp_nr_test_helper
{
public:
pdcp_nr_test_helper(srslte::pdcp_config_t cfg, srslte::as_security_config_t sec_cfg, srslte::log_ref log) :
pdcp_nr_test_helper(srslte::pdcp_config_t cfg, srslte::as_security_config_t sec_cfg_, srslte::log_ref log) :
rlc(log),
rrc(log),
gw(log),
pdcp(&rlc, &rrc, &gw, &stack, log)
pdcp(&rlc, &rrc, &gw, &stack, log, 0, cfg)
{
pdcp.init(0, cfg);
pdcp.config_security(sec_cfg);
pdcp.config_security(sec_cfg_);
pdcp.enable_integrity(srslte::DIRECTION_TXRX);
pdcp.enable_encryption(srslte::DIRECTION_TXRX);
}

View File

@ -141,7 +141,7 @@ private:
// eNB components
std::unique_ptr<enb_stack_base> stack = nullptr;
std::unique_ptr<srslte::radio> radio = nullptr;
std::unique_ptr<srslte::radio_base> radio = nullptr;
std::unique_ptr<enb_phy_base> phy = nullptr;
srslte::logger_stdout logger_stdout;

View File

@ -26,6 +26,7 @@
#include "srslte/common/common.h"
#include "srslte/common/logmap.h"
#include "srslte/interfaces/gnb_interfaces.h"
#include "srslte/interfaces/ue_interfaces.h"
namespace srsenb {
@ -33,7 +34,7 @@ class sdap final : public sdap_interface_pdcp_nr, public sdap_interface_gtpu_nr
{
public:
explicit sdap();
bool init(pdcp_interface_sdap_nr* pdcp_, gtpu_interface_sdap_nr* gtpu_);
bool init(pdcp_interface_sdap_nr* pdcp_, gtpu_interface_sdap_nr* gtpu_, srsue::gw_interface_pdcp* gw_);
void stop();
// Interface for PDCP
@ -43,9 +44,10 @@ public:
void write_sdu(uint16_t rnti, uint32_t lcid, srslte::unique_byte_buffer_t pdu) final;
private:
srslte::log_ref m_log{"SDAP"};
gtpu_interface_sdap_nr* m_gtpu = nullptr;
pdcp_interface_sdap_nr* m_pdcp = nullptr;
srslte::log_ref m_log{"SDAP"};
gtpu_interface_sdap_nr* m_gtpu = nullptr;
pdcp_interface_sdap_nr* m_pdcp = nullptr;
srsue::gw_interface_pdcp* m_gw = nullptr;
// state
bool running = false;

View File

@ -40,6 +40,11 @@ target_link_libraries(srsenb srsenb_phy
srsenb_upper
srsenb_mac
srsenb_rrc
srsgnb_phy
srsgnb_stack
srsgnb_upper
srsgnb_mac
srsgnb_rrc
srslte_common
srslte_mac
srslte_phy
@ -48,6 +53,8 @@ target_link_libraries(srsenb srsenb_phy
rrc_asn1
s1ap_asn1
enb_cfg_parser
rrc_nr_asn1
ngap_nr_asn1
${CMAKE_THREAD_LIBS_INIT}
${Boost_LIBRARIES}
${SEC_LIBRARIES}

View File

@ -20,9 +20,12 @@
*/
#include "srsenb/hdr/enb.h"
#include "srsenb/hdr/phy/vnf_phy_nr.h"
#include "srsenb/hdr/stack/enb_stack_lte.h"
#include "srsenb/hdr/stack/gnb_stack_nr.h"
#include "srsenb/src/enb_cfg_parser.h"
#include "srslte/build_info.h"
#include "srslte/radio/radio_null.h"
#include <iostream>
namespace srsenb {
@ -43,7 +46,7 @@ enb::~enb()
int enb::init(const all_args_t& args_, srslte::logger* logger_)
{
int ret = SRSLTE_SUCCESS;
logger = logger_;
logger = logger_;
// Init eNB log
srslte::logmap::set_default_logger(logger);
@ -62,49 +65,85 @@ int enb::init(const all_args_t& args_, srslte::logger* logger_)
pool->set_log(&pool_log);
// Create layers
std::unique_ptr<enb_stack_lte> lte_stack(new enb_stack_lte(logger));
if (!lte_stack) {
log->console("Error creating eNB stack.\n");
return SRSLTE_ERROR;
}
if (args.stack.type == "lte") {
std::unique_ptr<enb_stack_lte> lte_stack(new enb_stack_lte(logger));
if (!lte_stack) {
log->console("Error creating eNB stack.\n");
return SRSLTE_ERROR;
}
std::unique_ptr<srslte::radio> lte_radio = std::unique_ptr<srslte::radio>(new srslte::radio(logger));
if (!lte_radio) {
log->console("Error creating radio multi instance.\n");
return SRSLTE_ERROR;
}
std::unique_ptr<srslte::radio> lte_radio = std::unique_ptr<srslte::radio>(new srslte::radio(logger));
if (!lte_radio) {
log->console("Error creating radio multi instance.\n");
return SRSLTE_ERROR;
}
std::unique_ptr<srsenb::phy> lte_phy = std::unique_ptr<srsenb::phy>(new srsenb::phy(logger));
if (!lte_phy) {
log->console("Error creating LTE PHY instance.\n");
return SRSLTE_ERROR;
}
std::unique_ptr<srsenb::phy> lte_phy = std::unique_ptr<srsenb::phy>(new srsenb::phy(logger));
if (!lte_phy) {
log->console("Error creating LTE PHY instance.\n");
return SRSLTE_ERROR;
}
// Init Radio
if (lte_radio->init(args.rf, lte_phy.get())) {
log->console("Error initializing radio.\n");
ret = SRSLTE_ERROR;
}
// Init Radio
if (lte_radio->init(args.rf, lte_phy.get())) {
log->console("Error initializing radio.\n");
ret = SRSLTE_ERROR;
}
// Only Init PHY if radio couldn't be initialized
if (ret == SRSLTE_SUCCESS) {
if (lte_phy->init(args.phy, phy_cfg, lte_radio.get(), lte_stack.get())) {
// Only Init PHY if radio couldn't be initialized
if (ret == SRSLTE_SUCCESS) {
if (lte_phy->init(args.phy, phy_cfg, lte_radio.get(), lte_stack.get())) {
log->console("Error initializing PHY.\n");
ret = SRSLTE_ERROR;
}
}
// Only init Stack if both radio and PHY could be initialized
if (ret == SRSLTE_SUCCESS) {
if (lte_stack->init(args.stack, rrc_cfg, lte_phy.get())) {
log->console("Error initializing stack.\n");
ret = SRSLTE_ERROR;
}
}
stack = std::move(lte_stack);
phy = std::move(lte_phy);
radio = std::move(lte_radio);
} else if (args.stack.type == "nr") {
std::unique_ptr<srsenb::gnb_stack_nr> nr_stack(new srsenb::gnb_stack_nr(logger));
std::unique_ptr<srslte::radio_null> nr_radio(new srslte::radio_null(logger));
std::unique_ptr<srsenb::vnf_phy_nr> nr_phy(new srsenb::vnf_phy_nr(logger));
// Init layers
if (nr_radio->init(args.rf, nullptr)) {
log->console("Error initializing radio.\n");
return SRSLTE_ERROR;
}
// TODO: where do we put this?
srsenb::nr_phy_cfg_t nr_phy_cfg = {};
args.phy.vnf_args.type = "gnb";
if (nr_phy->init(args.phy, nr_phy_cfg, nr_stack.get())) {
log->console("Error initializing PHY.\n");
ret = SRSLTE_ERROR;
return SRSLTE_ERROR;
}
}
// Only init Stack if both radio and PHY could be initialized
if (ret == SRSLTE_SUCCESS) {
if (lte_stack->init(args.stack, rrc_cfg, lte_phy.get())) {
// Same here, where do we put this?
srsenb::rrc_nr_cfg_t rrc_nr_cfg = {};
rrc_nr_cfg.coreless = args.stack.coreless;
if (nr_stack->init(args.stack, rrc_nr_cfg, nr_phy.get())) {
log->console("Error initializing stack.\n");
ret = SRSLTE_ERROR;
return SRSLTE_ERROR;
}
}
stack = std::move(lte_stack);
phy = std::move(lte_phy);
radio = std::move(lte_radio);
stack = std::move(nr_stack);
phy = std::move(nr_phy);
radio = std::move(nr_radio);
}
started = true; // set to true in any case to allow stopping the eNB if an error happened

View File

@ -197,6 +197,23 @@ void parse_args(all_args_t* args, int argc, char* argv[])
("embms.m1u_multiaddr", bpo::value<string>(&args->stack.embms.m1u_multiaddr)->default_value("239.255.0.1"), "M1-U Multicast address the eNB joins.")
("embms.m1u_if_addr", bpo::value<string>(&args->stack.embms.m1u_if_addr)->default_value("127.0.1.201"), "IP address of the interface the eNB will listen for M1-U traffic.")
("embms.mcs", bpo::value<uint16_t>(&args->stack.embms.mcs)->default_value(20), "Modulation and Coding scheme of MBMS traffic.")
// NR section
("enb.stack", bpo::value<string>(&args->stack.type)->default_value("lte"), "Type of the upper stack [lte]")
// VNF params
("vnf.type", bpo::value<string>(&args->phy.vnf_args.type)->default_value("gnb"), "VNF instance type [gnb,ue]")
("vnf.addr", bpo::value<string>(&args->phy.vnf_args.bind_addr)->default_value("localhost"), "Address to bind VNF interface")
("vnf.port", bpo::value<uint16_t>(&args->phy.vnf_args.bind_port)->default_value(3333), "Bind port")
("log.vnf_level", bpo::value<string>(&args->phy.vnf_args.log_level), "VNF log level")
("log.vnf_hex_limit", bpo::value<int>(&args->phy.vnf_args.log_hex_limit), "VNF log hex dump limit")
// Arguments for coreless operation
("coreless.ip_devname", bpo::value<string>(&args->stack.coreless.gw_args.tun_dev_name)->default_value("tun0"), "Name of the TUN device")
("coreless.ip_address", bpo::value<string>(&args->stack.coreless.ip_addr)->default_value("192.168.1.1"), "IP address of the TUN device")
("coreless.ip_netmask", bpo::value<string>(&args->stack.coreless.gw_args.tun_dev_netmask)->default_value("255.255.255.0"), "Netmask of the TUN device")
("coreless.drb_lcid", bpo::value<uint8_t>(&args->stack.coreless.drb_lcid)->default_value(4), "LCID of the dummy DRB")
("coreless.rnti", bpo::value<uint16_t >(&args->stack.coreless.rnti)->default_value(1234), "RNTI of the dummy user")
;
// Positional options - config file location

View File

@ -29,5 +29,5 @@ target_link_libraries(srsenb_stack)
if(ENABLE_5GNR)
add_library(srsgnb_stack STATIC gnb_stack_nr.cc)
target_link_libraries(srsgnb_stack)
endif()
target_link_libraries(srsgnb_stack srsue_upper)
endif()

View File

@ -91,7 +91,7 @@ int gnb_stack_nr::init(const srsenb::stack_args_t& args_, const rrc_nr_cfg_t& rr
m_rrc->init(rrc_cfg_, phy, m_mac.get(), m_rlc.get(), m_pdcp.get(), nullptr, nullptr);
m_sdap->init(m_pdcp.get(), nullptr);
m_sdap->init(m_pdcp.get(), nullptr, m_gw.get());
m_gw->init(args.coreless.gw_args, logger, this);
char* err_str = nullptr;

View File

@ -25,10 +25,11 @@ namespace srsenb {
sdap::sdap() : m_log("SDAP") {}
bool sdap::init(pdcp_interface_sdap_nr* pdcp_, gtpu_interface_sdap_nr* gtpu_)
bool sdap::init(pdcp_interface_sdap_nr* pdcp_, gtpu_interface_sdap_nr* gtpu_, srsue::gw_interface_pdcp* gw_)
{
m_gtpu = gtpu_;
m_pdcp = pdcp_;
m_gw = gw_;
running = true;
return true;
@ -44,7 +45,11 @@ void sdap::stop()
void sdap::write_pdu(uint16_t rnti, uint32_t lcid, srslte::unique_byte_buffer_t pdu)
{
// for now just forwards it
m_gtpu->write_pdu(rnti, lcid, std::move(pdu));
if (m_gw) {
m_gw->write_pdu(lcid, std::move(pdu));
} else if (m_gtpu) {
m_gtpu->write_pdu(rnti, lcid, std::move(pdu));
}
}
void sdap::write_sdu(uint16_t rnti, uint32_t lcid, srslte::unique_byte_buffer_t pdu)
@ -52,4 +57,4 @@ void sdap::write_sdu(uint16_t rnti, uint32_t lcid, srslte::unique_byte_buffer_t
m_pdcp->write_sdu(rnti, lcid, std::move(pdu));
}
} // namespace srsenb
} // namespace srsenb

View File

@ -34,6 +34,8 @@ namespace srsue {
struct mac_nr_args_t {
srsue::pcap_args_t pcap;
// TODO: remove temp variable
uint32_t drb_lcid;
};
class mac_nr final : public mac_interface_phy_nr, public mac_interface_rrc_nr
@ -101,6 +103,9 @@ private:
mac_metrics_t metrics[SRSLTE_MAX_CARRIERS] = {};
/// Rx buffer
srslte::mac_nr_sch_pdu rx_pdu;
/// Tx buffer
srslte::mac_nr_sch_pdu tx_pdu;
srslte::unique_byte_buffer_t tx_buffer = nullptr;

View File

@ -84,8 +84,8 @@ public:
mac->sf_indication(tti);
return SRSLTE_SUCCESS;
}
void tb_decoded(const uint32_t cc_idx, mac_nr_grant_dl_t& grant) { mac->tb_decoded(cc_idx, grant); }
void new_grant_ul(const uint32_t cc_idx, const mac_nr_grant_ul_t& grant) { mac->new_grant_ul(cc_idx, grant); }
void tb_decoded(const uint32_t cc_idx, mac_nr_grant_dl_t& grant) final;
void new_grant_ul(const uint32_t cc_idx, const mac_nr_grant_ul_t& grant) final;
// Interface for GW
void write_sdu(uint32_t lcid, srslte::unique_byte_buffer_t sdu, bool blocking) final;
@ -144,4 +144,4 @@ private:
} // namespace srsue
#endif // SRSUE_UE_STACK_NR_H
#endif // SRSUE_UE_STACK_NR_H

View File

@ -110,7 +110,7 @@ public:
private:
// UE consists of a radio, a PHY and a stack element
std::unique_ptr<ue_phy_base> phy;
std::unique_ptr<srslte::radio> radio;
std::unique_ptr<srslte::radio_base> radio;
std::unique_ptr<ue_stack_base> stack;
std::unique_ptr<gw> gw_inst;

View File

@ -36,12 +36,17 @@ target_link_libraries(srsue srsue_phy
srsue_upper
srsue_mac
srsue_rrc
srsue_nr_stack
srsue_rrc_nr
srsue_mac_nr
srslte_common
srslte_mac
srslte_phy
srslte_radio
srslte_upper
rrc_asn1
rrc_nr_asn1
ngap_nr_asn1
${CMAKE_THREAD_LIBS_INIT}
${Boost_LIBRARIES})

View File

@ -408,7 +408,13 @@ static int parse_args(all_args_t* args, int argc, char* argv[])
("stack.have_tti_time_stats",
bpo::value<bool>(&args->stack.have_tti_time_stats)->default_value(true),
"Calculate TTI execution statistics");
"Calculate TTI execution statistics")
// NR params
("vnf.type", bpo::value<string>(&args->phy.vnf_args.type)->default_value("ue"), "VNF instance type [gnb,ue]")
("vnf.addr", bpo::value<string>(&args->phy.vnf_args.bind_addr)->default_value("localhost"), "Address to bind VNF interface")
("vnf.port", bpo::value<uint16_t>(&args->phy.vnf_args.bind_port)->default_value(3334), "Bind port")
;
// Positional options - config file location
bpo::options_description position("Positional options");

View File

@ -55,7 +55,7 @@ int mac_nr::init(const mac_nr_args_t& args_,
// Set up pcap
if (args.pcap.enable) {
pcap.reset(new srslte::mac_nr_pcap());
pcap->open(args.pcap.filename);
pcap->open(args.pcap.filename.c_str());
}
started = true;
@ -110,7 +110,7 @@ void mac_nr::bch_decoded_ok(uint32_t tti, srslte::unique_byte_buffer_t payload)
int mac_nr::sf_indication(const uint32_t tti)
{
run_tti(tti);
return SRSLTE_SUCCESS;
}
@ -173,7 +173,8 @@ void mac_nr::get_ul_data(const mac_nr_grant_ul_t& grant, phy_interface_stack_nr:
while (tx_pdu.get_remaing_len() >= MIN_RLC_PDU_LEN) {
// read RLC PDU
rlc_buffer->clear();
int pdu_len = rlc->read_pdu(4, rlc_buffer->msg, tx_pdu.get_remaing_len() - 2);
uint8_t* rd = rlc_buffer->msg;
int pdu_len = rlc->read_pdu(args.drb_lcid, rd, tx_pdu.get_remaing_len() - 2);
// Add SDU if RLC has something to tx
if (pdu_len > 0) {
@ -181,7 +182,7 @@ void mac_nr::get_ul_data(const mac_nr_grant_ul_t& grant, phy_interface_stack_nr:
log_h->info_hex(rlc_buffer->msg, rlc_buffer->N_bytes, "Read %d B from RLC\n", rlc_buffer->N_bytes);
// add to MAC PDU and pack
if (tx_pdu.add_sdu(4, rlc_buffer->msg, rlc_buffer->N_bytes) != SRSLTE_SUCCESS) {
if (tx_pdu.add_sdu(args.drb_lcid, rlc_buffer->msg, rlc_buffer->N_bytes) != SRSLTE_SUCCESS) {
log_h->error("Error packing MAC PDU\n");
}
}
@ -237,18 +238,32 @@ void mac_nr::get_metrics(mac_metrics_t m[SRSLTE_MAX_CARRIERS]) {}
*/
void mac_nr::process_pdus()
{
auto ret = stack_task_dispatch_queue.try_push([this]() {
while (started and not pdu_queue.empty()) {
srslte::unique_byte_buffer_t pdu = pdu_queue.wait_pop();
// TODO: delegate to demux class
handle_pdu(std::move(pdu));
}
});
while (started and not pdu_queue.empty()) {
srslte::unique_byte_buffer_t pdu = pdu_queue.wait_pop();
// TODO: delegate to demux class
handle_pdu(std::move(pdu));
}
}
void mac_nr::handle_pdu(srslte::unique_byte_buffer_t pdu)
{
log_h->info_hex(pdu->msg, pdu->N_bytes, "Handling MAC PDU (%d B)\n", pdu->N_bytes);
rx_pdu.init_rx();
rx_pdu.unpack(pdu->msg, pdu->N_bytes);
for (uint32_t i = 0; i < rx_pdu.get_num_subpdus(); ++i) {
srslte::mac_nr_sch_subpdu subpdu = rx_pdu.get_subpdu(i);
log_h->info("Handling subPDU %d/%d: lcid=%d, sdu_len=%d\n",
i,
rx_pdu.get_num_subpdus(),
subpdu.get_lcid(),
subpdu.get_sdu_length());
if (subpdu.get_lcid() == args.drb_lcid) {
rlc->write_pdu(subpdu.get_lcid(), subpdu.get_sdu(), subpdu.get_sdu_length());
}
}
}
} // namespace srsue

View File

@ -23,5 +23,5 @@ add_library(srsue_rrc STATIC ${SOURCES})
if(ENABLE_5GNR)
set(SOURCES rrc_nr.cc)
add_library(srsue_nr_rrc STATIC ${SOURCES})
add_library(srsue_rrc_nr STATIC ${SOURCES})
endif()

View File

@ -87,6 +87,7 @@ int ue_stack_nr::init(const stack_args_t& args_)
mac_nr_args_t mac_args = {};
mac_args.pcap = args.pcap;
mac_args.drb_lcid = 4;
mac->init(mac_args, phy, rlc.get(), &timers, this);
rlc->init(pdcp.get(), rrc.get(), &timers, 0 /* RB_ID_SRB0 */);
pdcp->init(rlc.get(), rrc.get(), gw);
@ -237,6 +238,18 @@ void ue_stack_nr::start_cell_select(const phy_interface_rrc_lte::phy_cell_t* cel
// not implemented
}
void ue_stack_nr::tb_decoded(const uint32_t cc_idx, mac_nr_grant_dl_t& grant)
{
pending_tasks.push(
mac_queue_id,
std::bind([this, cc_idx](mac_nr_grant_dl_t& grant) { mac->tb_decoded(cc_idx, grant); }, std::move(grant)));
}
void ue_stack_nr::new_grant_ul(const uint32_t cc_idx, const mac_nr_grant_ul_t& grant)
{
pending_tasks.push(mac_queue_id, [this, cc_idx, grant]() { mac->new_grant_ul(cc_idx, grant); });
}
/***************************
* Task Handling Interface
**************************/
@ -262,4 +275,4 @@ void ue_stack_nr::defer_task(srslte::move_task_t task)
deferred_stack_tasks.push_back(std::move(task));
}
} // namespace srsue
} // namespace srsue

View File

@ -23,9 +23,12 @@
#include "srslte/build_info.h"
#include "srslte/common/string_helpers.h"
#include "srslte/radio/radio.h"
#include "srslte/radio/radio_null.h"
#include "srslte/srslte.h"
#include "srsue/hdr/phy/phy.h"
#include "srsue/hdr/phy/vnf_phy_nr.h"
#include "srsue/hdr/stack/ue_stack_lte.h"
#include "srsue/hdr/stack/ue_stack_nr.h"
#include <algorithm>
#include <iostream>
#include <string>
@ -116,6 +119,38 @@ int ue::init(const all_args_t& args_, srslte::logger* logger_)
gw_inst = std::move(gw_ptr);
phy = std::move(lte_phy);
radio = std::move(lte_radio);
} else if (args.stack.type == "nr") {
std::unique_ptr<srsue::ue_stack_nr> nr_stack(new srsue::ue_stack_nr(logger));
std::unique_ptr<srslte::radio_null> nr_radio(new srslte::radio_null(logger));
std::unique_ptr<srsue::vnf_phy_nr> nr_phy(new srsue::vnf_phy_nr(logger));
std::unique_ptr<gw> gw_ptr(new gw());
// Init layers
if (nr_radio->init(args.rf, nullptr)) {
log.console("Error initializing radio.\n");
return SRSLTE_ERROR;
}
if (nr_phy->init(args.phy, nr_stack.get())) {
log.console("Error initializing PHY.\n");
return SRSLTE_ERROR;
}
if (nr_stack->init(args.stack, nr_phy.get(), gw_ptr.get())) {
log.console("Error initializing stack.\n");
return SRSLTE_ERROR;
}
if (gw_ptr->init(args.gw, logger, nr_stack.get())) {
log.console("Error initializing GW.\n");
return SRSLTE_ERROR;
}
// move ownership
stack = std::move(nr_stack);
gw_inst = std::move(gw_ptr);
phy = std::move(nr_phy);
radio = std::move(nr_radio);
} else {
log.console("Invalid stack type %s. Supported values are [lte].\n", args.stack.type.c_str());
ret = SRSLTE_ERROR;