mirror of https://github.com/PentHertz/srsLTE.git
add radio_base/null classes
This commit is contained in:
parent
e26653c87f
commit
f0874b780b
|
@ -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;
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 ===
|
||||
|
||||
|
|
|
@ -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
|
|
@ -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
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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_;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
|
@ -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
|
|
@ -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;
|
||||
|
|
|
@ -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()
|
||||
{
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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}
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
target_link_libraries(srsgnb_stack srsue_upper)
|
||||
endif()
|
|
@ -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;
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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})
|
||||
|
||||
|
|
|
@ -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");
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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
|
||||
**************************/
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in New Issue