diff --git a/lib/include/srslte/common/basic_pnf.h b/lib/include/srslte/common/basic_pnf.h index cbebebaf3..c4c28ceb8 100644 --- a/lib/include/srslte/common/basic_pnf.h +++ b/lib/include/srslte/common/basic_pnf.h @@ -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; diff --git a/lib/include/srslte/common/basic_vnf_api.h b/lib/include/srslte/common/basic_vnf_api.h index 7637575b5..ea6d91456 100644 --- a/lib/include/srslte/common/basic_vnf_api.h +++ b/lib/include/srslte/common/basic_vnf_api.h @@ -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 { diff --git a/lib/include/srslte/mac/mac_nr_pdu.h b/lib/include/srslte/mac/mac_nr_pdu.h index 185c791a5..94bff4caa 100644 --- a/lib/include/srslte/mac/mac_nr_pdu.h +++ b/lib/include/srslte/mac/mac_nr_pdu.h @@ -23,6 +23,7 @@ #define SRSLTE_MAC_NR_PDU_H #include "srslte/common/common.h" +#include "srslte/common/logmap.h" #include #include #include @@ -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 diff --git a/lib/include/srslte/radio/radio.h b/lib/include/srslte/radio/radio.h index 424995727..ad44e63d7 100644 --- a/lib/include/srslte/radio/radio.h +++ b/lib/include/srslte/radio/radio.h @@ -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 #include @@ -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 === diff --git a/lib/include/srslte/radio/radio_base.h b/lib/include/srslte/radio/radio_base.h new file mode 100644 index 000000000..b431e2648 --- /dev/null +++ b/lib/include/srslte/radio/radio_base.h @@ -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 diff --git a/lib/include/srslte/radio/radio_null.h b/lib/include/srslte/radio/radio_null.h new file mode 100644 index 000000000..2eadcd6f9 --- /dev/null +++ b/lib/include/srslte/radio/radio_null.h @@ -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 diff --git a/lib/include/srslte/upper/pdcp.h b/lib/include/srslte/upper/pdcp.h index e18f74f84..5a823c52f 100644 --- a/lib/include/srslte/upper/pdcp.h +++ b/lib/include/srslte/upper/pdcp.h @@ -72,7 +72,7 @@ private: srslte::task_handler_interface* task_executor = nullptr; srslte::log_ref pdcp_log; - std::map > pdcp_array, pdcp_array_mrb; + std::map > pdcp_array, pdcp_array_mrb; // cache valid lcids to be checked from separate thread std::mutex cache_mutex; diff --git a/lib/include/srslte/upper/pdcp_entity_base.h b/lib/include/srslte/upper/pdcp_entity_base.h index 426477766..476a51b2d 100644 --- a/lib/include/srslte/upper/pdcp_entity_base.h +++ b/lib/include/srslte/upper/pdcp_entity_base.h @@ -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); diff --git a/lib/include/srslte/upper/pdcp_entity_lte.h b/lib/include/srslte/upper/pdcp_entity_lte.h index 668b90905..e7079d7f0 100644 --- a/lib/include/srslte/upper/pdcp_entity_lte.h +++ b/lib/include/srslte/upper/pdcp_entity_lte.h @@ -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; diff --git a/lib/include/srslte/upper/pdcp_entity_nr.h b/lib/include/srslte/upper/pdcp_entity_nr.h index e4e3f5282..f98a00ac3 100644 --- a/lib/include/srslte/upper/pdcp_entity_nr.h +++ b/lib/include/srslte/upper/pdcp_entity_nr.h @@ -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; diff --git a/lib/src/mac/mac_nr_pdu.cc b/lib/src/mac/mac_nr_pdu.cc index 4a8ebe990..0c992d1b1 100644 --- a/lib/src/mac/mac_nr_pdu.cc +++ b/lib/src/mac/mac_nr_pdu.cc @@ -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(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_; diff --git a/lib/src/phy/fec/test/viterbi_test.c b/lib/src/phy/fec/test/viterbi_test.c index 9e4c18c1e..812917419 100644 --- a/lib/src/phy/fec/test/viterbi_test.c +++ b/lib/src/phy/fec/test/viterbi_test.c @@ -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; diff --git a/lib/src/phy/rf/rf_zmq_imp_rx.c b/lib/src/phy/rf/rf_zmq_imp_rx.c index ebd3fd5a2..0e73ce010 100644 --- a/lib/src/phy/rf/rf_zmq_imp_rx.c +++ b/lib/src/phy/rf/rf_zmq_imp_rx.c @@ -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) { diff --git a/lib/src/radio/CMakeLists.txt b/lib/src/radio/CMakeLists.txt index 3d4a0fa3a..a3c9a1dbf 100644 --- a/lib/src/radio/CMakeLists.txt +++ b/lib/src/radio/CMakeLists.txt @@ -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) diff --git a/lib/src/radio/radio_null.cc b/lib/src/radio/radio_null.cc new file mode 100644 index 000000000..97cc00dcc --- /dev/null +++ b/lib/src/radio/radio_null.cc @@ -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 + +namespace srslte { + +radio_null::radio_null(srslte::logger* logger_) : logger(logger_), radio_base(logger_) {} + +} // namespace srslte diff --git a/lib/src/upper/pdcp.cc b/lib/src/upper/pdcp.cc index ed41e6ba5..39deda91f 100644 --- a/lib/src/upper/pdcp.cc +++ b/lib/src/upper/pdcp.cc @@ -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(new pdcp_entity_lte(rlc, rrc, gw, task_executor, pdcp_log)))) - .second) { + // create NR entity for 18bit SN length + std::unique_ptr 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(new pdcp_entity_lte(rlc, rrc, gw, task_executor, pdcp_log)))) + .insert(std::make_pair(lcid, + std::unique_ptr( + 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 lock(cache_mutex); - auto it = pdcp_array.find(old_lcid); - std::unique_ptr pdcp_entity = std::move(it->second); + std::lock_guard lock(cache_mutex); + auto it = pdcp_array.find(old_lcid); + std::unique_ptr 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; diff --git a/lib/src/upper/pdcp_entity_lte.cc b/lib/src/upper/pdcp_entity_lte.cc index b44358d98..5fba49ebc 100644 --- a/lib/src/upper/pdcp_entity_lte.cc +++ b/lib/src/upper/pdcp_entity_lte.cc @@ -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() -{ - reset(); -} - -void pdcp_entity_lte::init(uint32_t lcid_, pdcp_config_t cfg_) + srslte::log_ref log_, + uint32_t lcid_, + pdcp_config_t cfg_) : + pdcp_entity_base(task_executor_, log_), + rlc(rlc_), + rrc(rrc_), + gw(gw_) { - 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() { diff --git a/lib/src/upper/pdcp_entity_nr.cc b/lib/src/upper/pdcp_entity_nr.cc index 76a109aa9..bb72e8689 100644 --- a/lib/src/upper/pdcp_entity_nr.cc +++ b/lib/src/upper/pdcp_entity_nr.cc @@ -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(cfg.t_reordering) > 0) { reordering_timer.set(static_cast(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 diff --git a/lib/test/mac/CMakeLists.txt b/lib/test/mac/CMakeLists.txt index b7c10c394..d800435b3 100644 --- a/lib/test/mac/CMakeLists.txt +++ b/lib/test/mac/CMakeLists.txt @@ -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) diff --git a/lib/test/upper/pdcp_lte_test.h b/lib/test/upper/pdcp_lte_test.h index 350bca7b6..e015428f2 100644 --- a/lib/test/upper/pdcp_lte_test.h +++ b/lib/test/upper/pdcp_lte_test.h @@ -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); } diff --git a/lib/test/upper/pdcp_nr_test.h b/lib/test/upper/pdcp_nr_test.h index d38450c30..36f2ba9b6 100644 --- a/lib/test/upper/pdcp_nr_test.h +++ b/lib/test/upper/pdcp_nr_test.h @@ -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); } diff --git a/srsenb/hdr/enb.h b/srsenb/hdr/enb.h index 489265567..0ab840cb2 100644 --- a/srsenb/hdr/enb.h +++ b/srsenb/hdr/enb.h @@ -141,7 +141,7 @@ private: // eNB components std::unique_ptr stack = nullptr; - std::unique_ptr radio = nullptr; + std::unique_ptr radio = nullptr; std::unique_ptr phy = nullptr; srslte::logger_stdout logger_stdout; diff --git a/srsenb/hdr/stack/upper/sdap.h b/srsenb/hdr/stack/upper/sdap.h index aaea69556..3bf9775e6 100644 --- a/srsenb/hdr/stack/upper/sdap.h +++ b/srsenb/hdr/stack/upper/sdap.h @@ -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; diff --git a/srsenb/src/CMakeLists.txt b/srsenb/src/CMakeLists.txt index 68d3459e2..430ee7b90 100644 --- a/srsenb/src/CMakeLists.txt +++ b/srsenb/src/CMakeLists.txt @@ -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} diff --git a/srsenb/src/enb.cc b/srsenb/src/enb.cc index bf3dc3c40..7cace5718 100644 --- a/srsenb/src/enb.cc +++ b/srsenb/src/enb.cc @@ -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 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 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 lte_stack(new enb_stack_lte(logger)); + if (!lte_stack) { + log->console("Error creating eNB stack.\n"); + return SRSLTE_ERROR; + } - std::unique_ptr lte_radio = std::unique_ptr(new srslte::radio(logger)); - if (!lte_radio) { - log->console("Error creating radio multi instance.\n"); - return SRSLTE_ERROR; - } + std::unique_ptr lte_radio = std::unique_ptr(new srslte::radio(logger)); + if (!lte_radio) { + log->console("Error creating radio multi instance.\n"); + return SRSLTE_ERROR; + } - std::unique_ptr lte_phy = std::unique_ptr(new srsenb::phy(logger)); - if (!lte_phy) { - log->console("Error creating LTE PHY instance.\n"); - return SRSLTE_ERROR; - } + std::unique_ptr lte_phy = std::unique_ptr(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 nr_stack(new srsenb::gnb_stack_nr(logger)); + std::unique_ptr nr_radio(new srslte::radio_null(logger)); + std::unique_ptr 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 diff --git a/srsenb/src/main.cc b/srsenb/src/main.cc index 73c706007..7548ce6fd 100644 --- a/srsenb/src/main.cc +++ b/srsenb/src/main.cc @@ -197,6 +197,23 @@ void parse_args(all_args_t* args, int argc, char* argv[]) ("embms.m1u_multiaddr", bpo::value(&args->stack.embms.m1u_multiaddr)->default_value("239.255.0.1"), "M1-U Multicast address the eNB joins.") ("embms.m1u_if_addr", bpo::value(&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(&args->stack.embms.mcs)->default_value(20), "Modulation and Coding scheme of MBMS traffic.") + + // NR section + ("enb.stack", bpo::value(&args->stack.type)->default_value("lte"), "Type of the upper stack [lte]") + + // VNF params + ("vnf.type", bpo::value(&args->phy.vnf_args.type)->default_value("gnb"), "VNF instance type [gnb,ue]") + ("vnf.addr", bpo::value(&args->phy.vnf_args.bind_addr)->default_value("localhost"), "Address to bind VNF interface") + ("vnf.port", bpo::value(&args->phy.vnf_args.bind_port)->default_value(3333), "Bind port") + ("log.vnf_level", bpo::value(&args->phy.vnf_args.log_level), "VNF log level") + ("log.vnf_hex_limit", bpo::value(&args->phy.vnf_args.log_hex_limit), "VNF log hex dump limit") + + // Arguments for coreless operation + ("coreless.ip_devname", bpo::value(&args->stack.coreless.gw_args.tun_dev_name)->default_value("tun0"), "Name of the TUN device") + ("coreless.ip_address", bpo::value(&args->stack.coreless.ip_addr)->default_value("192.168.1.1"), "IP address of the TUN device") + ("coreless.ip_netmask", bpo::value(&args->stack.coreless.gw_args.tun_dev_netmask)->default_value("255.255.255.0"), "Netmask of the TUN device") + ("coreless.drb_lcid", bpo::value(&args->stack.coreless.drb_lcid)->default_value(4), "LCID of the dummy DRB") + ("coreless.rnti", bpo::value(&args->stack.coreless.rnti)->default_value(1234), "RNTI of the dummy user") ; // Positional options - config file location diff --git a/srsenb/src/stack/CMakeLists.txt b/srsenb/src/stack/CMakeLists.txt index 9310ed98d..7cbd2ac84 100644 --- a/srsenb/src/stack/CMakeLists.txt +++ b/srsenb/src/stack/CMakeLists.txt @@ -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() \ No newline at end of file + target_link_libraries(srsgnb_stack srsue_upper) +endif() diff --git a/srsenb/src/stack/gnb_stack_nr.cc b/srsenb/src/stack/gnb_stack_nr.cc index 02e367003..ec1ebfc70 100644 --- a/srsenb/src/stack/gnb_stack_nr.cc +++ b/srsenb/src/stack/gnb_stack_nr.cc @@ -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; diff --git a/srsenb/src/stack/upper/sdap.cc b/srsenb/src/stack/upper/sdap.cc index 3933854de..69fcb64ac 100644 --- a/srsenb/src/stack/upper/sdap.cc +++ b/srsenb/src/stack/upper/sdap.cc @@ -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 \ No newline at end of file +} // namespace srsenb diff --git a/srsue/hdr/stack/mac/mac_nr.h b/srsue/hdr/stack/mac/mac_nr.h index a5d782c61..187816142 100644 --- a/srsue/hdr/stack/mac/mac_nr.h +++ b/srsue/hdr/stack/mac/mac_nr.h @@ -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; diff --git a/srsue/hdr/stack/ue_stack_nr.h b/srsue/hdr/stack/ue_stack_nr.h index 6710f3f1a..1c9ef387e 100644 --- a/srsue/hdr/stack/ue_stack_nr.h +++ b/srsue/hdr/stack/ue_stack_nr.h @@ -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 \ No newline at end of file +#endif // SRSUE_UE_STACK_NR_H diff --git a/srsue/hdr/ue.h b/srsue/hdr/ue.h index a4afd8d99..06482d7d6 100644 --- a/srsue/hdr/ue.h +++ b/srsue/hdr/ue.h @@ -110,7 +110,7 @@ public: private: // UE consists of a radio, a PHY and a stack element std::unique_ptr phy; - std::unique_ptr radio; + std::unique_ptr radio; std::unique_ptr stack; std::unique_ptr gw_inst; diff --git a/srsue/src/CMakeLists.txt b/srsue/src/CMakeLists.txt index ace316f74..044fc27b7 100644 --- a/srsue/src/CMakeLists.txt +++ b/srsue/src/CMakeLists.txt @@ -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}) diff --git a/srsue/src/main.cc b/srsue/src/main.cc index 140ddf21a..806fa70e9 100644 --- a/srsue/src/main.cc +++ b/srsue/src/main.cc @@ -408,7 +408,13 @@ static int parse_args(all_args_t* args, int argc, char* argv[]) ("stack.have_tti_time_stats", bpo::value(&args->stack.have_tti_time_stats)->default_value(true), - "Calculate TTI execution statistics"); + "Calculate TTI execution statistics") + + // NR params + ("vnf.type", bpo::value(&args->phy.vnf_args.type)->default_value("ue"), "VNF instance type [gnb,ue]") + ("vnf.addr", bpo::value(&args->phy.vnf_args.bind_addr)->default_value("localhost"), "Address to bind VNF interface") + ("vnf.port", bpo::value(&args->phy.vnf_args.bind_port)->default_value(3334), "Bind port") + ; // Positional options - config file location bpo::options_description position("Positional options"); diff --git a/srsue/src/stack/mac/mac_nr.cc b/srsue/src/stack/mac/mac_nr.cc index 17571cca2..56ff8b321 100644 --- a/srsue/src/stack/mac/mac_nr.cc +++ b/srsue/src/stack/mac/mac_nr.cc @@ -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 diff --git a/srsue/src/stack/rrc/CMakeLists.txt b/srsue/src/stack/rrc/CMakeLists.txt index 9a73c1600..1e5391fab 100644 --- a/srsue/src/stack/rrc/CMakeLists.txt +++ b/srsue/src/stack/rrc/CMakeLists.txt @@ -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() diff --git a/srsue/src/stack/ue_stack_nr.cc b/srsue/src/stack/ue_stack_nr.cc index a4804f026..b77370a1b 100644 --- a/srsue/src/stack/ue_stack_nr.cc +++ b/srsue/src/stack/ue_stack_nr.cc @@ -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 \ No newline at end of file +} // namespace srsue diff --git a/srsue/src/ue.cc b/srsue/src/ue.cc index a8faa40ea..02b2b3ce2 100644 --- a/srsue/src/ue.cc +++ b/srsue/src/ue.cc @@ -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 #include #include @@ -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 nr_stack(new srsue::ue_stack_nr(logger)); + std::unique_ptr nr_radio(new srslte::radio_null(logger)); + std::unique_ptr nr_phy(new srsue::vnf_phy_nr(logger)); + std::unique_ptr 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;