mirror of https://github.com/pvnis/srsRAN_4G.git
commit
d290fe9714
@ -0,0 +1,125 @@
|
|||||||
|
/**
|
||||||
|
*
|
||||||
|
* \section COPYRIGHT
|
||||||
|
*
|
||||||
|
* Copyright 2013-2020 Software Radio Systems Limited
|
||||||
|
*
|
||||||
|
* By using this file, you agree to the terms and conditions set
|
||||||
|
* forth in the LICENSE file which can be found at the top level of
|
||||||
|
* the distribution.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef SRSLTE_MAC_PCAP_BASE_H
|
||||||
|
#define SRSLTE_MAC_PCAP_BASE_H
|
||||||
|
|
||||||
|
#include "srslte/common/block_queue.h"
|
||||||
|
#include "srslte/common/buffer_pool.h"
|
||||||
|
#include "srslte/common/common.h"
|
||||||
|
#include "srslte/common/pcap.h"
|
||||||
|
#include "srslte/common/threads.h"
|
||||||
|
#include "srslte/srslog/srslog.h"
|
||||||
|
#include <mutex>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <thread>
|
||||||
|
|
||||||
|
namespace srslte {
|
||||||
|
class mac_pcap_base : protected srslte::thread
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
mac_pcap_base();
|
||||||
|
~mac_pcap_base();
|
||||||
|
void enable(bool enable);
|
||||||
|
virtual uint32_t close() = 0;
|
||||||
|
|
||||||
|
void set_ue_id(uint16_t ue_id);
|
||||||
|
|
||||||
|
// EUTRA
|
||||||
|
void
|
||||||
|
write_ul_crnti(uint8_t* pdu, uint32_t pdu_len_bytes, uint16_t crnti, uint32_t reTX, uint32_t tti, uint8_t cc_idx);
|
||||||
|
void write_dl_crnti(uint8_t* pdu, uint32_t pdu_len_bytes, uint16_t crnti, bool crc_ok, uint32_t tti, uint8_t cc_idx);
|
||||||
|
void write_dl_ranti(uint8_t* pdu, uint32_t pdu_len_bytes, uint16_t ranti, bool crc_ok, uint32_t tti, uint8_t cc_idx);
|
||||||
|
|
||||||
|
void write_ul_crnti(uint8_t* pdu,
|
||||||
|
uint32_t pdu_len_bytes,
|
||||||
|
uint16_t crnti,
|
||||||
|
uint16_t ue_id,
|
||||||
|
uint32_t reTX,
|
||||||
|
uint32_t tti,
|
||||||
|
uint8_t cc_idx);
|
||||||
|
|
||||||
|
void write_dl_crnti(uint8_t* pdu,
|
||||||
|
uint32_t pdu_len_bytes,
|
||||||
|
uint16_t crnti,
|
||||||
|
uint16_t ue_id,
|
||||||
|
bool crc_ok,
|
||||||
|
uint32_t tti,
|
||||||
|
uint8_t cc_idx);
|
||||||
|
|
||||||
|
// SI and BCH only for DL
|
||||||
|
void write_dl_sirnti(uint8_t* pdu, uint32_t pdu_len_bytes, bool crc_ok, uint32_t tti, uint8_t cc_idx);
|
||||||
|
void write_dl_bch(uint8_t* pdu, uint32_t pdu_len_bytes, bool crc_ok, uint32_t tti, uint8_t cc_idx);
|
||||||
|
void write_dl_pch(uint8_t* pdu, uint32_t pdu_len_bytes, bool crc_ok, uint32_t tti, uint8_t cc_idx);
|
||||||
|
void write_dl_mch(uint8_t* pdu, uint32_t pdu_len_bytes, bool crc_ok, uint32_t tti, uint8_t cc_idx);
|
||||||
|
|
||||||
|
void write_ul_rrc_pdu(const uint8_t* input, const int32_t input_len);
|
||||||
|
|
||||||
|
// Sidelink
|
||||||
|
void write_sl_crnti(uint8_t* pdu, uint32_t pdu_len_bytes, uint16_t rnti, uint32_t reTX, uint32_t tti, uint8_t cc_idx);
|
||||||
|
|
||||||
|
// NR
|
||||||
|
void write_dl_crnti_nr(uint8_t* pdu, uint32_t pdu_len_bytes, uint16_t crnti, uint8_t harqid, uint32_t tti);
|
||||||
|
void write_ul_crnti_nr(uint8_t* pdu, uint32_t pdu_len_bytes, uint16_t rnti, uint8_t harqid, uint32_t tti);
|
||||||
|
void write_dl_ra_rnti_nr(uint8_t* pdu, uint32_t pdu_len_bytes, uint16_t rnti, uint8_t harqid, uint32_t tti);
|
||||||
|
void write_dl_bch_nr(uint8_t* pdu, uint32_t pdu_len_bytes, uint16_t rnti, uint8_t harqid, uint32_t tti);
|
||||||
|
void write_dl_pch_nr(uint8_t* pdu, uint32_t pdu_len_bytes, uint16_t rnti, uint8_t harqid, uint32_t tti);
|
||||||
|
void write_dl_si_rnti_nr(uint8_t* pdu, uint32_t pdu_len_bytes, uint16_t rnti, uint8_t harqid, uint32_t tti);
|
||||||
|
|
||||||
|
// NR for enb with different ue_id
|
||||||
|
// clang-format off
|
||||||
|
void write_dl_crnti_nr(uint8_t* pdu, uint32_t pdu_len_bytes, uint16_t crnti, uint16_t ue_id, uint8_t harqid, uint32_t tti);
|
||||||
|
void write_ul_crnti_nr(uint8_t* pdu, uint32_t pdu_len_bytes, uint16_t rnti, uint16_t ue_id, uint8_t harqid, uint32_t tti);
|
||||||
|
// clang-format on
|
||||||
|
|
||||||
|
protected:
|
||||||
|
typedef struct {
|
||||||
|
// Different PCAP context for both RATs
|
||||||
|
srslte::srslte_rat_t rat;
|
||||||
|
MAC_Context_Info_t context;
|
||||||
|
mac_nr_context_info_t context_nr;
|
||||||
|
unique_byte_buffer_t pdu;
|
||||||
|
} pcap_pdu_t;
|
||||||
|
|
||||||
|
virtual void write_pdu(pcap_pdu_t& pdu) = 0;
|
||||||
|
void run_thread() final;
|
||||||
|
|
||||||
|
std::mutex mutex;
|
||||||
|
srslog::basic_logger& logger;
|
||||||
|
bool running = false;
|
||||||
|
block_queue<pcap_pdu_t> queue;
|
||||||
|
uint16_t ue_id = 0;
|
||||||
|
|
||||||
|
private:
|
||||||
|
void pack_and_queue(uint8_t* payload,
|
||||||
|
uint32_t payload_len,
|
||||||
|
uint16_t ue_id,
|
||||||
|
uint32_t reTX,
|
||||||
|
bool crc_ok,
|
||||||
|
uint8_t cc_idx,
|
||||||
|
uint32_t tti,
|
||||||
|
uint16_t crnti_,
|
||||||
|
uint8_t direction,
|
||||||
|
uint8_t rnti_type);
|
||||||
|
void pack_and_queue_nr(uint8_t* payload,
|
||||||
|
uint32_t payload_len,
|
||||||
|
uint32_t tti,
|
||||||
|
uint16_t crnti,
|
||||||
|
uint16_t ue_id,
|
||||||
|
uint8_t harqid,
|
||||||
|
uint8_t direction,
|
||||||
|
uint8_t rnti_type);
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace srslte
|
||||||
|
|
||||||
|
#endif // SRSLTE_MAC_PCAP_BASE_H
|
@ -0,0 +1,44 @@
|
|||||||
|
/**
|
||||||
|
*
|
||||||
|
* \section COPYRIGHT
|
||||||
|
*
|
||||||
|
* Copyright 2013-2020 Software Radio Systems Limited
|
||||||
|
*
|
||||||
|
* By using this file, you agree to the terms and conditions set
|
||||||
|
* forth in the LICENSE file which can be found at the top level of
|
||||||
|
* the distribution.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef SRSLTE_MAC_PCAP_NET_H
|
||||||
|
#define SRSLTE_MAC_PCAP_NET_H
|
||||||
|
|
||||||
|
#include "srslte/common/common.h"
|
||||||
|
#include "srslte/common/mac_pcap_base.h"
|
||||||
|
#include "srslte/common/network_utils.h"
|
||||||
|
#include "srslte/srslte.h"
|
||||||
|
|
||||||
|
namespace srslte {
|
||||||
|
class mac_pcap_net : public mac_pcap_base
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
mac_pcap_net();
|
||||||
|
~mac_pcap_net();
|
||||||
|
uint32_t open(std::string client_ip_addr_,
|
||||||
|
std::string bind_addr_str = "0.0.0.0",
|
||||||
|
uint16_t client_udp_port_ = 5847,
|
||||||
|
uint16_t bind_udp_port_ = 5687,
|
||||||
|
uint32_t ue_id_ = 0);
|
||||||
|
uint32_t close();
|
||||||
|
|
||||||
|
private:
|
||||||
|
void write_pdu(srslte::mac_pcap_base::pcap_pdu_t& pdu);
|
||||||
|
void write_mac_lte_pdu_to_net(srslte::mac_pcap_base::pcap_pdu_t& pdu);
|
||||||
|
void write_mac_nr_pdu_to_net(srslte::mac_pcap_base::pcap_pdu_t& pdu);
|
||||||
|
|
||||||
|
srslte::socket_handler_t socket;
|
||||||
|
struct sockaddr_in client_addr;
|
||||||
|
};
|
||||||
|
} // namespace srslte
|
||||||
|
|
||||||
|
#endif // SRSLTE_MAC_PCAP_NET_H
|
@ -0,0 +1,67 @@
|
|||||||
|
/**
|
||||||
|
*
|
||||||
|
* \section COPYRIGHT
|
||||||
|
*
|
||||||
|
* Copyright 2013-2020 Software Radio Systems Limited
|
||||||
|
*
|
||||||
|
* By using this file, you agree to the terms and conditions set
|
||||||
|
* forth in the LICENSE file which can be found at the top level of
|
||||||
|
* the distribution.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef SRSLTE_UE_GW_INTERFACES_H
|
||||||
|
#define SRSLTE_UE_GW_INTERFACES_H
|
||||||
|
|
||||||
|
#include "srslte/asn1/liblte_mme.h"
|
||||||
|
|
||||||
|
namespace srsue {
|
||||||
|
|
||||||
|
class gw_interface_nas
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
virtual int setup_if_addr(uint32_t eps_bearer_id,
|
||||||
|
uint32_t lcid,
|
||||||
|
uint8_t pdn_type,
|
||||||
|
uint32_t ip_addr,
|
||||||
|
uint8_t* ipv6_if_id,
|
||||||
|
char* err_str) = 0;
|
||||||
|
virtual int apply_traffic_flow_template(const uint8_t& eps_bearer_id,
|
||||||
|
const uint8_t& lcid,
|
||||||
|
const LIBLTE_MME_TRAFFIC_FLOW_TEMPLATE_STRUCT* tft) = 0;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
TEST_LOOP_INACTIVE = 0,
|
||||||
|
TEST_LOOP_MODE_A_ACTIVE,
|
||||||
|
TEST_LOOP_MODE_B_ACTIVE,
|
||||||
|
TEST_LOOP_MODE_C_ACTIVE
|
||||||
|
} test_loop_mode_state_t;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Updates the test loop mode. The IP delay parameter is only valid for Mode B.
|
||||||
|
* @param mode
|
||||||
|
* @param ip_pdu_delay_ms The PDU delay in ms
|
||||||
|
*/
|
||||||
|
virtual void set_test_loop_mode(const test_loop_mode_state_t mode, const uint32_t ip_pdu_delay_ms = 0) = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
class gw_interface_rrc
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
virtual void add_mch_port(uint32_t lcid, uint32_t port) = 0;
|
||||||
|
virtual int update_lcid(uint32_t eps_bearer_id, uint32_t new_lcid) = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
class gw_interface_pdcp
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
virtual void write_pdu(uint32_t lcid, srslte::unique_byte_buffer_t pdu) = 0;
|
||||||
|
virtual void write_pdu_mch(uint32_t lcid, srslte::unique_byte_buffer_t pdu) = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
class gw_interface_stack : public gw_interface_nas, public gw_interface_rrc, public gw_interface_pdcp
|
||||||
|
{};
|
||||||
|
|
||||||
|
} // namespace srsue
|
||||||
|
|
||||||
|
#endif // SRSLTE_UE_GW_INTERFACES_H
|
@ -0,0 +1,151 @@
|
|||||||
|
/**
|
||||||
|
*
|
||||||
|
* \section COPYRIGHT
|
||||||
|
*
|
||||||
|
* Copyright 2013-2020 Software Radio Systems Limited
|
||||||
|
*
|
||||||
|
* By using this file, you agree to the terms and conditions set
|
||||||
|
* forth in the LICENSE file which can be found at the top level of
|
||||||
|
* the distribution.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef SRSLTE_UE_MAC_INTERFACES_H
|
||||||
|
#define SRSLTE_UE_MAC_INTERFACES_H
|
||||||
|
|
||||||
|
#include "mac_interface_types.h"
|
||||||
|
|
||||||
|
namespace srsue {
|
||||||
|
|
||||||
|
class mac_interface_phy_lte
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
typedef struct {
|
||||||
|
uint32_t nof_mbsfn_services;
|
||||||
|
} mac_phy_cfg_mbsfn_t;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uint32_t tbs;
|
||||||
|
bool ndi;
|
||||||
|
bool ndi_present;
|
||||||
|
int rv;
|
||||||
|
} mac_tb_t;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
mac_tb_t tb[SRSLTE_MAX_TB];
|
||||||
|
uint32_t pid;
|
||||||
|
uint16_t rnti;
|
||||||
|
bool is_sps_release;
|
||||||
|
uint32_t tti;
|
||||||
|
} mac_grant_dl_t;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
mac_tb_t tb;
|
||||||
|
uint32_t pid;
|
||||||
|
uint16_t rnti;
|
||||||
|
bool phich_available;
|
||||||
|
bool hi_value;
|
||||||
|
bool is_rar;
|
||||||
|
uint32_t tti_tx;
|
||||||
|
} mac_grant_ul_t;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
bool enabled;
|
||||||
|
uint32_t rv;
|
||||||
|
uint8_t* payload;
|
||||||
|
union {
|
||||||
|
srslte_softbuffer_rx_t* rx;
|
||||||
|
srslte_softbuffer_tx_t* tx;
|
||||||
|
} softbuffer;
|
||||||
|
} tb_action_t;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
tb_action_t tb[SRSLTE_MAX_TB];
|
||||||
|
|
||||||
|
bool generate_ack;
|
||||||
|
} tb_action_dl_t;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
tb_action_t tb;
|
||||||
|
uint32_t current_tx_nb;
|
||||||
|
bool expect_ack;
|
||||||
|
bool is_rar;
|
||||||
|
} tb_action_ul_t;
|
||||||
|
|
||||||
|
/* Query the MAC for the current RNTI to look for
|
||||||
|
*/
|
||||||
|
virtual uint16_t get_dl_sched_rnti(uint32_t tti) = 0;
|
||||||
|
virtual uint16_t get_ul_sched_rnti(uint32_t tti) = 0;
|
||||||
|
|
||||||
|
/* Indicate reception of UL dci.
|
||||||
|
* payload_ptr points to memory where MAC PDU must be written by MAC layer */
|
||||||
|
virtual void new_grant_ul(uint32_t cc_idx, mac_grant_ul_t grant, tb_action_ul_t* action) = 0;
|
||||||
|
|
||||||
|
/* Indicate reception of DL dci. */
|
||||||
|
virtual void new_grant_dl(uint32_t cc_idx, mac_grant_dl_t grant, tb_action_dl_t* action) = 0;
|
||||||
|
|
||||||
|
/* Indicate successful decoding of PDSCH AND PCH TB. */
|
||||||
|
virtual void tb_decoded(uint32_t cc_idx, mac_grant_dl_t grant, bool ack[SRSLTE_MAX_CODEWORDS]) = 0;
|
||||||
|
|
||||||
|
/* Indicate successful decoding of BCH TB through PBCH */
|
||||||
|
virtual void bch_decoded_ok(uint32_t cc_idx, uint8_t* payload, uint32_t len) = 0;
|
||||||
|
|
||||||
|
/* Indicate successful decoding of MCH TB through PMCH */
|
||||||
|
virtual void mch_decoded(uint32_t len, bool crc) = 0;
|
||||||
|
|
||||||
|
/* Obtain action for a new MCH subframe. */
|
||||||
|
virtual void new_mch_dl(const srslte_pdsch_grant_t& phy_grant, tb_action_dl_t* action) = 0;
|
||||||
|
|
||||||
|
/* Communicate the number of mbsfn services available */
|
||||||
|
virtual void set_mbsfn_config(uint32_t nof_mbsfn_services) = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
class mac_interface_rrc_common
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
// Class to handle UE specific RNTIs between RRC and MAC
|
||||||
|
typedef struct {
|
||||||
|
uint16_t crnti;
|
||||||
|
uint16_t rar_rnti;
|
||||||
|
uint16_t temp_rnti;
|
||||||
|
uint16_t tpc_rnti;
|
||||||
|
uint16_t sps_rnti;
|
||||||
|
uint64_t contention_id;
|
||||||
|
} ue_rnti_t;
|
||||||
|
};
|
||||||
|
|
||||||
|
class mac_interface_rrc : public mac_interface_rrc_common
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
/* Instructs the MAC to start receiving BCCH */
|
||||||
|
virtual void bcch_start_rx(int si_window_start, int si_window_length) = 0;
|
||||||
|
virtual void bcch_stop_rx() = 0;
|
||||||
|
|
||||||
|
/* Instructs the MAC to start receiving PCCH */
|
||||||
|
virtual void pcch_start_rx() = 0;
|
||||||
|
|
||||||
|
/* RRC configures a logical channel */
|
||||||
|
virtual void setup_lcid(uint32_t lcid, uint32_t lcg, uint32_t priority, int PBR_x_tti, uint32_t BSD) = 0;
|
||||||
|
|
||||||
|
/* Instructs the MAC to start receiving an MCH */
|
||||||
|
virtual void mch_start_rx(uint32_t lcid) = 0;
|
||||||
|
|
||||||
|
/* Set entire MAC config */
|
||||||
|
virtual void set_config(srslte::mac_cfg_t& mac_cfg) = 0;
|
||||||
|
|
||||||
|
/* Update SR config only for PUCCH release */
|
||||||
|
virtual void set_config(srslte::sr_cfg_t& sr_cfg) = 0;
|
||||||
|
|
||||||
|
virtual void set_rach_ded_cfg(uint32_t preamble_index, uint32_t prach_mask) = 0;
|
||||||
|
|
||||||
|
virtual void get_rntis(ue_rnti_t* rntis) = 0;
|
||||||
|
virtual void set_contention_id(uint64_t uecri) = 0;
|
||||||
|
virtual void set_ho_rnti(uint16_t crnti, uint16_t target_pci) = 0;
|
||||||
|
|
||||||
|
virtual void reconfiguration(const uint32_t& cc_idx, const bool& enable) = 0;
|
||||||
|
virtual void reset() = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace srsue
|
||||||
|
|
||||||
|
#endif // SRSLTE_UE_MAC_INTERFACES_H
|
@ -0,0 +1,44 @@
|
|||||||
|
/**
|
||||||
|
*
|
||||||
|
* \section COPYRIGHT
|
||||||
|
*
|
||||||
|
* Copyright 2013-2020 Software Radio Systems Limited
|
||||||
|
*
|
||||||
|
* By using this file, you agree to the terms and conditions set
|
||||||
|
* forth in the LICENSE file which can be found at the top level of
|
||||||
|
* the distribution.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef SRSLTE_UE_NAS_INTERFACES_H
|
||||||
|
#define SRSLTE_UE_NAS_INTERFACES_H
|
||||||
|
|
||||||
|
#include "srslte/interfaces/rrc_interface_types.h"
|
||||||
|
|
||||||
|
namespace srsue {
|
||||||
|
|
||||||
|
class nas_interface_rrc
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
const static int MAX_FOUND_PLMNS = 16;
|
||||||
|
struct found_plmn_t {
|
||||||
|
srslte::plmn_id_t plmn_id;
|
||||||
|
uint16_t tac;
|
||||||
|
};
|
||||||
|
|
||||||
|
virtual void left_rrc_connected() = 0;
|
||||||
|
virtual void set_barring(srslte::barring_t barring) = 0;
|
||||||
|
virtual bool paging(srslte::s_tmsi_t* ue_identity) = 0;
|
||||||
|
virtual bool is_registered() = 0;
|
||||||
|
virtual void write_pdu(uint32_t lcid, srslte::unique_byte_buffer_t pdu) = 0;
|
||||||
|
virtual uint32_t get_k_enb_count() = 0;
|
||||||
|
virtual bool get_k_asme(uint8_t* k_asme_, uint32_t n) = 0;
|
||||||
|
virtual uint32_t get_ipv4_addr() = 0;
|
||||||
|
virtual bool get_ipv6_addr(uint8_t* ipv6_addr) = 0;
|
||||||
|
virtual void plmn_search_completed(const found_plmn_t found_plmns[MAX_FOUND_PLMNS], int nof_plmns) = 0;
|
||||||
|
virtual bool connection_request_completed(bool outcome) = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace srsue
|
||||||
|
|
||||||
|
#endif // SRSLTE_UE_NAS_INTERFACES_H
|
@ -0,0 +1,68 @@
|
|||||||
|
/**
|
||||||
|
*
|
||||||
|
* \section COPYRIGHT
|
||||||
|
*
|
||||||
|
* Copyright 2013-2020 Software Radio Systems Limited
|
||||||
|
*
|
||||||
|
* By using this file, you agree to the terms and conditions set
|
||||||
|
* forth in the LICENSE file which can be found at the top level of
|
||||||
|
* the distribution.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef SRSLTE_UE_PDCP_INTERFACES_H
|
||||||
|
#define SRSLTE_UE_PDCP_INTERFACES_H
|
||||||
|
|
||||||
|
#include "pdcp_interface_types.h"
|
||||||
|
|
||||||
|
namespace srsue {
|
||||||
|
|
||||||
|
class pdcp_interface_rrc
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
virtual void reestablish() = 0;
|
||||||
|
virtual void reestablish(uint32_t lcid) = 0;
|
||||||
|
virtual void reset() = 0;
|
||||||
|
virtual void write_sdu(uint32_t lcid, srslte::unique_byte_buffer_t sdu, int sn = -1) = 0;
|
||||||
|
virtual void add_bearer(uint32_t lcid, srslte::pdcp_config_t cnfg) = 0;
|
||||||
|
virtual void change_lcid(uint32_t old_lcid, uint32_t new_lcid) = 0;
|
||||||
|
virtual void config_security(uint32_t lcid, srslte::as_security_config_t sec_cfg) = 0;
|
||||||
|
virtual void config_security_all(srslte::as_security_config_t sec_cfg) = 0;
|
||||||
|
virtual void enable_integrity(uint32_t lcid, srslte::srslte_direction_t direction) = 0;
|
||||||
|
virtual void enable_encryption(uint32_t lcid,
|
||||||
|
srslte::srslte_direction_t direction = srslte::srslte_direction_t::DIRECTION_TXRX) = 0;
|
||||||
|
virtual void send_status_report() = 0;
|
||||||
|
virtual void send_status_report(uint32_t lcid) = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
class pdcp_interface_rlc
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
/* RLC calls PDCP to push a PDCP PDU. */
|
||||||
|
virtual void write_pdu(uint32_t lcid, srslte::unique_byte_buffer_t sdu) = 0;
|
||||||
|
virtual void write_pdu_bcch_bch(srslte::unique_byte_buffer_t sdu) = 0;
|
||||||
|
virtual void write_pdu_bcch_dlsch(srslte::unique_byte_buffer_t sdu) = 0;
|
||||||
|
virtual void write_pdu_pcch(srslte::unique_byte_buffer_t sdu) = 0;
|
||||||
|
virtual void write_pdu_mch(uint32_t lcid, srslte::unique_byte_buffer_t sdu) = 0;
|
||||||
|
virtual void notify_delivery(uint32_t lcid, const std::vector<uint32_t>& pdcp_sn) = 0;
|
||||||
|
virtual void notify_failure(uint32_t lcid, const std::vector<uint32_t>& pdcp_sn) = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
class pdcp_interface_gw
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
virtual void write_sdu(uint32_t lcid, srslte::unique_byte_buffer_t sdu) = 0;
|
||||||
|
virtual bool is_lcid_enabled(uint32_t lcid) = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
// STACK interface for GW
|
||||||
|
class stack_interface_gw : public pdcp_interface_gw
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
virtual bool is_registered() = 0;
|
||||||
|
virtual bool start_service_request() = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace srsue
|
||||||
|
|
||||||
|
#endif // SRSLTE_UE_PDCP_INTERFACES_H
|
@ -0,0 +1,174 @@
|
|||||||
|
/**
|
||||||
|
*
|
||||||
|
* \section COPYRIGHT
|
||||||
|
*
|
||||||
|
* Copyright 2013-2020 Software Radio Systems Limited
|
||||||
|
*
|
||||||
|
* By using this file, you agree to the terms and conditions set
|
||||||
|
* forth in the LICENSE file which can be found at the top level of
|
||||||
|
* the distribution.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef SRSLTE_UE_PHY_INTERFACES_H
|
||||||
|
#define SRSLTE_UE_PHY_INTERFACES_H
|
||||||
|
|
||||||
|
#include "srslte/srslte.h"
|
||||||
|
|
||||||
|
#include "phy_interface_types.h"
|
||||||
|
#include "rrc_interface_types.h"
|
||||||
|
#include "srslte/common/interfaces_common.h"
|
||||||
|
#include "srslte/phy/channel/channel.h"
|
||||||
|
|
||||||
|
#include <map>
|
||||||
|
#include <set>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
namespace srsue {
|
||||||
|
|
||||||
|
struct phy_args_t {
|
||||||
|
std::string type = "lte";
|
||||||
|
srslte::phy_log_args_t log;
|
||||||
|
|
||||||
|
std::string dl_earfcn = "3400"; // comma-separated list of DL EARFCNs
|
||||||
|
std::string ul_earfcn = ""; // comma-separated list of UL EARFCNs
|
||||||
|
std::vector<uint32_t> dl_earfcn_list = {3400}; // vectorized version of dl_earfcn that gets populated during init
|
||||||
|
std::map<uint32_t, uint32_t> ul_earfcn_map; // Map linking DL EARFCN and UL EARFCN
|
||||||
|
|
||||||
|
std::string dl_nr_arfcn = "632628"; // comma-separated list of DL NR ARFCNs
|
||||||
|
std::vector<uint32_t> dl_nr_arfcn_list = {
|
||||||
|
632628}; // vectorized version of dl_nr_arfcn that gets populated during init
|
||||||
|
|
||||||
|
float dl_freq = -1.0f;
|
||||||
|
float ul_freq = -1.0f;
|
||||||
|
|
||||||
|
bool ul_pwr_ctrl_en = false;
|
||||||
|
float prach_gain = -1;
|
||||||
|
uint32_t pdsch_max_its = 8;
|
||||||
|
bool meas_evm = false;
|
||||||
|
uint32_t nof_phy_threads = 3;
|
||||||
|
|
||||||
|
int worker_cpu_mask = -1;
|
||||||
|
int sync_cpu_affinity = -1;
|
||||||
|
|
||||||
|
uint32_t nof_lte_carriers = 1;
|
||||||
|
uint32_t nof_nr_carriers = 0;
|
||||||
|
uint32_t nr_nof_prb = 50;
|
||||||
|
double nr_freq_hz = 2630e6;
|
||||||
|
uint32_t nof_rx_ant = 1;
|
||||||
|
std::string equalizer_mode = "mmse";
|
||||||
|
int cqi_max = 15;
|
||||||
|
int cqi_fixed = -1;
|
||||||
|
float snr_ema_coeff = 0.1f;
|
||||||
|
std::string snr_estim_alg = "refs";
|
||||||
|
bool agc_enable = true;
|
||||||
|
bool correct_sync_error = false;
|
||||||
|
bool cfo_is_doppler = false;
|
||||||
|
bool cfo_integer_enabled = false;
|
||||||
|
float cfo_correct_tol_hz = 1.0f;
|
||||||
|
float cfo_pss_ema = DEFAULT_CFO_EMA_TRACK;
|
||||||
|
float cfo_loop_bw_pss = DEFAULT_CFO_BW_PSS;
|
||||||
|
float cfo_loop_bw_ref = DEFAULT_CFO_BW_REF;
|
||||||
|
float cfo_loop_ref_min = DEFAULT_CFO_REF_MIN;
|
||||||
|
float cfo_loop_pss_tol = DEFAULT_CFO_PSS_MIN;
|
||||||
|
float sfo_ema = DEFAULT_SFO_EMA_COEFF;
|
||||||
|
uint32_t sfo_correct_period = DEFAULT_SAMPLE_OFFSET_CORRECT_PERIOD;
|
||||||
|
uint32_t cfo_loop_pss_conv = DEFAULT_PSS_STABLE_TIMEOUT;
|
||||||
|
uint32_t cfo_ref_mask = 1023;
|
||||||
|
bool interpolate_subframe_enabled = false;
|
||||||
|
bool estimator_fil_auto = false;
|
||||||
|
float estimator_fil_stddev = 1.0f;
|
||||||
|
uint32_t estimator_fil_order = 4;
|
||||||
|
float snr_to_cqi_offset = 0.0f;
|
||||||
|
std::string sss_algorithm = "full";
|
||||||
|
float rx_gain_offset = 62;
|
||||||
|
bool pdsch_csi_enabled = true;
|
||||||
|
bool pdsch_8bit_decoder = false;
|
||||||
|
uint32_t intra_freq_meas_len_ms = 20;
|
||||||
|
uint32_t intra_freq_meas_period_ms = 200;
|
||||||
|
float force_ul_amplitude = 0.0f;
|
||||||
|
|
||||||
|
float in_sync_rsrp_dbm_th = -130.0f;
|
||||||
|
float in_sync_snr_db_th = 1.0f;
|
||||||
|
uint32_t nof_in_sync_events = 10;
|
||||||
|
uint32_t nof_out_of_sync_events = 20;
|
||||||
|
|
||||||
|
srslte::channel::args_t dl_channel_args;
|
||||||
|
srslte::channel::args_t ul_channel_args;
|
||||||
|
|
||||||
|
srslte::vnf_args_t vnf_args;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* RAT agnostic Interface MAC -> PHY */
|
||||||
|
class phy_interface_mac_common
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
/* Time advance commands */
|
||||||
|
virtual void set_timeadv_rar(uint32_t ta_cmd) = 0;
|
||||||
|
virtual void set_timeadv(uint32_t ta_cmd) = 0;
|
||||||
|
|
||||||
|
/* Activate / Disactivate SCell*/
|
||||||
|
virtual void set_activation_deactivation_scell(uint32_t cmd, uint32_t tti) = 0;
|
||||||
|
|
||||||
|
/* Sets RAR dci payload */
|
||||||
|
virtual void set_rar_grant(uint8_t grant_payload[SRSLTE_RAR_GRANT_LEN], uint16_t rnti) = 0;
|
||||||
|
|
||||||
|
virtual uint32_t get_current_tti() = 0;
|
||||||
|
|
||||||
|
virtual float get_phr() = 0;
|
||||||
|
virtual float get_pathloss_db() = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Interface MAC -> PHY */
|
||||||
|
class phy_interface_mac_lte : public phy_interface_mac_common
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
typedef struct {
|
||||||
|
bool is_transmitted;
|
||||||
|
uint32_t tti_ra;
|
||||||
|
uint32_t f_id;
|
||||||
|
uint32_t preamble_format;
|
||||||
|
} prach_info_t;
|
||||||
|
|
||||||
|
virtual void
|
||||||
|
prach_send(uint32_t preamble_idx, int allowed_subframe, float target_power_dbm, float ta_base_sec = 0.0f) = 0;
|
||||||
|
virtual prach_info_t prach_get_info() = 0;
|
||||||
|
|
||||||
|
/* Indicates the transmission of a SR signal in the next opportunity */
|
||||||
|
virtual void sr_send() = 0;
|
||||||
|
virtual int sr_last_tx_tti() = 0;
|
||||||
|
|
||||||
|
virtual void set_mch_period_stop(uint32_t stop) = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
class phy_interface_rrc_lte
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
virtual bool set_config(srslte::phy_cfg_t config, uint32_t cc_idx = 0) = 0;
|
||||||
|
virtual bool set_scell(srslte_cell_t cell_info, uint32_t cc_idx, uint32_t earfcn) = 0;
|
||||||
|
virtual void set_config_tdd(srslte_tdd_config_t& tdd_config) = 0;
|
||||||
|
virtual void set_config_mbsfn_sib2(srslte::mbsfn_sf_cfg_t* cfg_list, uint32_t nof_cfgs) = 0;
|
||||||
|
virtual void set_config_mbsfn_sib13(const srslte::sib13_t& sib13) = 0;
|
||||||
|
virtual void set_config_mbsfn_mcch(const srslte::mcch_msg_t& mcch) = 0;
|
||||||
|
|
||||||
|
virtual void deactivate_scells() = 0;
|
||||||
|
|
||||||
|
/* Measurements interface */
|
||||||
|
virtual void set_cells_to_meas(uint32_t earfcn, const std::set<uint32_t>& pci) = 0;
|
||||||
|
virtual void meas_stop() = 0;
|
||||||
|
|
||||||
|
/* Cell search and selection procedures */
|
||||||
|
virtual bool cell_search() = 0;
|
||||||
|
virtual bool cell_select(phy_cell_t cell) = 0;
|
||||||
|
virtual bool cell_is_camping() = 0;
|
||||||
|
|
||||||
|
virtual void enable_pregen_signals(bool enable) = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Combined interface for stack (MAC and RRC) to access PHY
|
||||||
|
class phy_interface_stack_lte : public phy_interface_mac_lte, public phy_interface_rrc_lte
|
||||||
|
{};
|
||||||
|
|
||||||
|
} // namespace srsue
|
||||||
|
|
||||||
|
#endif // SRSLTE_UE_PHY_INTERFACES_H
|
@ -0,0 +1,83 @@
|
|||||||
|
/**
|
||||||
|
*
|
||||||
|
* \section COPYRIGHT
|
||||||
|
*
|
||||||
|
* Copyright 2013-2020 Software Radio Systems Limited
|
||||||
|
*
|
||||||
|
* By using this file, you agree to the terms and conditions set
|
||||||
|
* forth in the LICENSE file which can be found at the top level of
|
||||||
|
* the distribution.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef SRSLTE_UE_RLC_INTERFACES_H
|
||||||
|
#define SRSLTE_UE_RLC_INTERFACES_H
|
||||||
|
|
||||||
|
#include "srslte/common/interfaces_common.h"
|
||||||
|
#include "srslte/interfaces/rlc_interface_types.h"
|
||||||
|
|
||||||
|
namespace srsue {
|
||||||
|
|
||||||
|
class rlc_interface_rrc
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
virtual void reset() = 0;
|
||||||
|
virtual void reestablish() = 0;
|
||||||
|
virtual void reestablish(uint32_t lcid) = 0;
|
||||||
|
virtual void add_bearer(uint32_t lcid, const srslte::rlc_config_t& cnfg) = 0;
|
||||||
|
virtual void add_bearer_mrb(uint32_t lcid) = 0;
|
||||||
|
virtual void del_bearer(uint32_t lcid) = 0;
|
||||||
|
virtual void suspend_bearer(uint32_t lcid) = 0;
|
||||||
|
virtual void resume_bearer(uint32_t lcid) = 0;
|
||||||
|
virtual void change_lcid(uint32_t old_lcid, uint32_t new_lcid) = 0;
|
||||||
|
virtual bool has_bearer(uint32_t lcid) = 0;
|
||||||
|
virtual bool has_data(const uint32_t lcid) = 0;
|
||||||
|
virtual bool is_suspended(const uint32_t lcid) = 0;
|
||||||
|
virtual void write_sdu(uint32_t lcid, srslte::unique_byte_buffer_t sdu) = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
class rlc_interface_pdcp
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
///< PDCP calls RLC to push an RLC SDU. SDU gets placed into the buffer
|
||||||
|
///< MAC pulls RLC PDUs according to TB size
|
||||||
|
virtual void write_sdu(uint32_t lcid, srslte::unique_byte_buffer_t sdu) = 0;
|
||||||
|
|
||||||
|
///< Indicate RLC that a certain SN can be discarded
|
||||||
|
virtual void discard_sdu(uint32_t lcid, uint32_t discard_sn) = 0;
|
||||||
|
|
||||||
|
///< Helper to query RLC mode
|
||||||
|
virtual bool rb_is_um(uint32_t lcid) = 0;
|
||||||
|
|
||||||
|
///< Allow PDCP to query SDU queue status
|
||||||
|
virtual bool sdu_queue_is_full(uint32_t lcid) = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
class rlc_interface_mac : public srslte::read_pdu_interface
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
/* MAC calls has_data() to query whether a logical channel has data to transmit (without
|
||||||
|
* knowing how much. This function should return quickly. */
|
||||||
|
virtual bool has_data_locked(const uint32_t lcid) = 0;
|
||||||
|
|
||||||
|
/* MAC calls RLC to get the buffer state for a logical channel. */
|
||||||
|
virtual uint32_t get_buffer_state(const uint32_t lcid) = 0;
|
||||||
|
|
||||||
|
const static int MAX_PDU_SEGMENTS = 20;
|
||||||
|
|
||||||
|
/* MAC calls RLC to get RLC segment of nof_bytes length.
|
||||||
|
* Segmentation happens in this function. RLC PDU is stored in payload. */
|
||||||
|
virtual int read_pdu(uint32_t lcid, uint8_t* payload, uint32_t nof_bytes) = 0;
|
||||||
|
|
||||||
|
/* MAC calls RLC to push an RLC PDU. This function is called from an independent MAC thread.
|
||||||
|
* PDU gets placed into the buffer and higher layer thread gets notified. */
|
||||||
|
virtual void write_pdu(uint32_t lcid, uint8_t* payload, uint32_t nof_bytes) = 0;
|
||||||
|
virtual void write_pdu_bcch_bch(srslte::unique_byte_buffer_t payload) = 0;
|
||||||
|
virtual void write_pdu_bcch_dlsch(uint8_t* payload, uint32_t nof_bytes) = 0;
|
||||||
|
virtual void write_pdu_pcch(srslte::unique_byte_buffer_t payload) = 0;
|
||||||
|
virtual void write_pdu_mch(uint32_t lcid, uint8_t* payload, uint32_t nof_bytes) = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace srsue
|
||||||
|
|
||||||
|
#endif // SRSLTE_UE_RLC_INTERFACES_H
|
@ -0,0 +1,120 @@
|
|||||||
|
/**
|
||||||
|
*
|
||||||
|
* \section COPYRIGHT
|
||||||
|
*
|
||||||
|
* Copyright 2013-2020 Software Radio Systems Limited
|
||||||
|
*
|
||||||
|
* By using this file, you agree to the terms and conditions set
|
||||||
|
* forth in the LICENSE file which can be found at the top level of
|
||||||
|
* the distribution.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef SRSLTE_UE_RRC_INTERFACES_H
|
||||||
|
#define SRSLTE_UE_RRC_INTERFACES_H
|
||||||
|
|
||||||
|
#include "phy_interface_types.h"
|
||||||
|
#include "rrc_interface_types.h"
|
||||||
|
#include "srslte/asn1/asn1_utils.h"
|
||||||
|
#include "srslte/common/byte_buffer.h"
|
||||||
|
#include "srslte/common/tti_point.h"
|
||||||
|
|
||||||
|
namespace srsue {
|
||||||
|
|
||||||
|
class rrc_interface_mac_common
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
virtual void ra_problem() = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
class rrc_interface_mac : public rrc_interface_mac_common
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
virtual void ra_completed() = 0;
|
||||||
|
virtual void release_pucch_srs() = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
class rrc_eutra_interface_rrc_nr
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
virtual void new_cell_meas_nr(const std::vector<phy_meas_nr_t>& meas) = 0;
|
||||||
|
virtual void nr_rrc_con_reconfig_complete(bool status) = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
class rrc_interface_phy_lte
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
virtual void in_sync() = 0;
|
||||||
|
virtual void out_of_sync() = 0;
|
||||||
|
virtual void new_cell_meas(const std::vector<phy_meas_t>& meas) = 0;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
enum { CELL_FOUND = 0, CELL_NOT_FOUND, ERROR } found;
|
||||||
|
enum { MORE_FREQS = 0, NO_MORE_FREQS } last_freq;
|
||||||
|
} cell_search_ret_t;
|
||||||
|
|
||||||
|
virtual void cell_search_complete(cell_search_ret_t ret, phy_cell_t found_cell) = 0;
|
||||||
|
virtual void cell_select_complete(bool status) = 0;
|
||||||
|
virtual void set_config_complete(bool status) = 0;
|
||||||
|
virtual void set_scell_complete(bool status) = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
class rrc_interface_nas
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
virtual ~rrc_interface_nas() = default;
|
||||||
|
virtual void write_sdu(srslte::unique_byte_buffer_t sdu) = 0;
|
||||||
|
virtual uint16_t get_mcc() = 0;
|
||||||
|
virtual uint16_t get_mnc() = 0;
|
||||||
|
virtual void enable_capabilities() = 0;
|
||||||
|
virtual bool plmn_search() = 0;
|
||||||
|
virtual void plmn_select(srslte::plmn_id_t plmn_id) = 0;
|
||||||
|
virtual bool connection_request(srslte::establishment_cause_t cause,
|
||||||
|
srslte::unique_byte_buffer_t dedicatedInfoNAS) = 0;
|
||||||
|
virtual void set_ue_identity(srslte::s_tmsi_t s_tmsi) = 0;
|
||||||
|
virtual bool is_connected() = 0;
|
||||||
|
virtual void paging_completed(bool outcome) = 0;
|
||||||
|
virtual std::string get_rb_name(uint32_t lcid) = 0;
|
||||||
|
virtual uint32_t get_lcid_for_eps_bearer(const uint32_t& eps_bearer_id) = 0;
|
||||||
|
virtual bool has_nr_dc() = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
class rrc_interface_pdcp
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
virtual void write_pdu(uint32_t lcid, srslte::unique_byte_buffer_t pdu) = 0;
|
||||||
|
virtual void write_pdu_bcch_bch(srslte::unique_byte_buffer_t pdu) = 0;
|
||||||
|
virtual void write_pdu_bcch_dlsch(srslte::unique_byte_buffer_t pdu) = 0;
|
||||||
|
virtual void write_pdu_pcch(srslte::unique_byte_buffer_t pdu) = 0;
|
||||||
|
virtual void write_pdu_mch(uint32_t lcid, srslte::unique_byte_buffer_t pdu) = 0;
|
||||||
|
virtual std::string get_rb_name(uint32_t lcid) = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
class rrc_interface_rlc
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
virtual void max_retx_attempted() = 0;
|
||||||
|
virtual std::string get_rb_name(uint32_t lcid) = 0;
|
||||||
|
virtual void write_pdu(uint32_t lcid, srslte::unique_byte_buffer_t pdu) = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
class rrc_nr_interface_rrc
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
virtual void get_eutra_nr_capabilities(srslte::byte_buffer_t* eutra_nr_caps) = 0;
|
||||||
|
virtual void get_nr_capabilities(srslte::byte_buffer_t* nr_cap) = 0;
|
||||||
|
virtual void phy_set_cells_to_meas(uint32_t carrier_freq_r15) = 0;
|
||||||
|
virtual void phy_meas_stop() = 0;
|
||||||
|
virtual bool rrc_reconfiguration(bool endc_release_and_add_r15,
|
||||||
|
bool nr_secondary_cell_group_cfg_r15_present,
|
||||||
|
asn1::dyn_octstring nr_secondary_cell_group_cfg_r15,
|
||||||
|
bool sk_counter_r15_present,
|
||||||
|
uint32_t sk_counter_r15,
|
||||||
|
bool nr_radio_bearer_cfg1_r15_present,
|
||||||
|
asn1::dyn_octstring nr_radio_bearer_cfg1_r15) = 0;
|
||||||
|
virtual bool is_config_pending() = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace srsue
|
||||||
|
|
||||||
|
#endif // SRSLTE_UE_RRC_INTERFACES_H
|
@ -0,0 +1,65 @@
|
|||||||
|
/**
|
||||||
|
*
|
||||||
|
* \section COPYRIGHT
|
||||||
|
*
|
||||||
|
* Copyright 2013-2020 Software Radio Systems Limited
|
||||||
|
*
|
||||||
|
* By using this file, you agree to the terms and conditions set
|
||||||
|
* forth in the LICENSE file which can be found at the top level of
|
||||||
|
* the distribution.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef SRSLTE_UE_USIM_INTERFACES_H
|
||||||
|
#define SRSLTE_UE_USIM_INTERFACES_H
|
||||||
|
|
||||||
|
#include "rrc_interface_types.h"
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
namespace srsue {
|
||||||
|
|
||||||
|
enum auth_result_t { AUTH_OK, AUTH_FAILED, AUTH_SYNCH_FAILURE };
|
||||||
|
|
||||||
|
// USIM interface for NAS
|
||||||
|
class usim_interface_nas
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
virtual std::string get_imsi_str() = 0;
|
||||||
|
virtual std::string get_imei_str() = 0;
|
||||||
|
virtual bool get_imsi_vec(uint8_t* imsi_, uint32_t n) = 0;
|
||||||
|
virtual bool get_imei_vec(uint8_t* imei_, uint32_t n) = 0;
|
||||||
|
virtual bool get_home_plmn_id(srslte::plmn_id_t* home_plmn_id) = 0;
|
||||||
|
virtual auth_result_t generate_authentication_response(uint8_t* rand,
|
||||||
|
uint8_t* autn_enb,
|
||||||
|
uint16_t mcc,
|
||||||
|
uint16_t mnc,
|
||||||
|
uint8_t* res,
|
||||||
|
int* res_len,
|
||||||
|
uint8_t* k_asme) = 0;
|
||||||
|
virtual void generate_nas_keys(uint8_t* k_asme,
|
||||||
|
uint8_t* k_nas_enc,
|
||||||
|
uint8_t* k_nas_int,
|
||||||
|
srslte::CIPHERING_ALGORITHM_ID_ENUM cipher_algo,
|
||||||
|
srslte::INTEGRITY_ALGORITHM_ID_ENUM integ_algo) = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
// USIM interface for RRC
|
||||||
|
class usim_interface_rrc
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
virtual void generate_as_keys(uint8_t* k_asme, uint32_t count_ul, srslte::as_security_config_t* sec_cfg) = 0;
|
||||||
|
virtual void generate_as_keys_ho(uint32_t pci, uint32_t earfcn, int ncc, srslte::as_security_config_t* sec_cfg) = 0;
|
||||||
|
virtual void store_keys_before_ho(const srslte::as_security_config_t& as_cfg) = 0;
|
||||||
|
virtual void restore_keys_from_failed_ho(srslte::as_security_config_t* as_cfg) = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
class usim_interface_rrc_nr
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
virtual void generate_nr_context(uint16_t sk_counter, srslte::as_security_config_t* sec_cfg) = 0;
|
||||||
|
virtual void update_nr_context(srslte::as_security_config_t* sec_cfg) = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace srsue
|
||||||
|
|
||||||
|
#endif // SRSLTE_UE_USIM_INTERFACES_H
|
@ -0,0 +1,69 @@
|
|||||||
|
/**
|
||||||
|
*
|
||||||
|
* \section COPYRIGHT
|
||||||
|
*
|
||||||
|
* Copyright 2013-2020 Software Radio Systems Limited
|
||||||
|
*
|
||||||
|
* By using this file, you agree to the terms and conditions set
|
||||||
|
* forth in the LICENSE file which can be found at the top level of
|
||||||
|
* the distribution.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef SRSLTE_CSI_NR_H
|
||||||
|
#define SRSLTE_CSI_NR_H
|
||||||
|
|
||||||
|
#include "uci_cfg_nr.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Fills Uplink Control Information data with triggered reports for the given slot
|
||||||
|
* @param cfg CSI report configuration
|
||||||
|
* @param slot_idx Slot index within the radio frame
|
||||||
|
* @param measurements CSI measurements
|
||||||
|
* @param[out] uci_data Uplink Control Information data
|
||||||
|
* @return The number CSI reports for transmission if the provided data is valid, SRSLTE_ERROR code otherwise
|
||||||
|
*/
|
||||||
|
SRSLTE_API int srslte_csi_generate_reports(const srslte_csi_hl_cfg_t* cfg,
|
||||||
|
uint32_t slot_idx,
|
||||||
|
const srslte_csi_measurements_t measurements[SRSLTE_CSI_MAX_NOF_RESOURCES],
|
||||||
|
srslte_csi_report_cfg_t report_cfg[SRSLTE_CSI_MAX_NOF_REPORT],
|
||||||
|
srslte_csi_report_value_t report_value[SRSLTE_CSI_MAX_NOF_REPORT]);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Compute number of CSI bits necessary to transmit all the CSI reports for a PUCCH transmission
|
||||||
|
* @param report_list Provides the CSI report list
|
||||||
|
* @param nof_reports Number of CSI reports in the list
|
||||||
|
* @return The number of bits if the provided list is valid, SRSLTE_ERROR code otherwise
|
||||||
|
*/
|
||||||
|
SRSLTE_API int srslte_csi_nof_bits(const srslte_csi_report_cfg_t* report_list, uint32_t nof_reports);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Pack CSI part 1 bits for a PUCCH transmission
|
||||||
|
* @param report_list Provides the CSI report list
|
||||||
|
* @param nof_reports Number of CSI reports in the list
|
||||||
|
* @param o_csi1 CSI bits
|
||||||
|
* @param max_o_csi1 Maximum number of CSI bits
|
||||||
|
* @return number of packed bits if provided data is valid, SRSLTE_ERROR code otherwise
|
||||||
|
*/
|
||||||
|
SRSLTE_API int srslte_csi_part1_pack(const srslte_csi_report_cfg_t* report_cfg,
|
||||||
|
const srslte_csi_report_value_t* report_value,
|
||||||
|
uint32_t nof_reports,
|
||||||
|
uint8_t* o_csi1,
|
||||||
|
uint32_t max_o_csi1);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Converts to string a given list of CSI reports
|
||||||
|
* @param report_cfg Report configuration list
|
||||||
|
* @param report_value Report value list
|
||||||
|
* @param nof_reports Number of reports
|
||||||
|
* @param str String pointer
|
||||||
|
* @param str_len Maximum string length
|
||||||
|
* @return Number of used characters
|
||||||
|
*/
|
||||||
|
SRSLTE_API uint32_t srslte_csi_str(const srslte_csi_report_cfg_t* report_cfg,
|
||||||
|
const srslte_csi_report_value_t* report_value,
|
||||||
|
uint32_t nof_reports,
|
||||||
|
char* str,
|
||||||
|
uint32_t str_len);
|
||||||
|
|
||||||
|
#endif // SRSLTE_CSI_NR_H
|
@ -0,0 +1,165 @@
|
|||||||
|
/**
|
||||||
|
*
|
||||||
|
* \section COPYRIGHT
|
||||||
|
*
|
||||||
|
* Copyright 2013-2020 Software Radio Systems Limited
|
||||||
|
*
|
||||||
|
* By using this file, you agree to the terms and conditions set
|
||||||
|
* forth in the LICENSE file which can be found at the top level of
|
||||||
|
* the distribution.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef SRSLTE_CSI_CFG_H
|
||||||
|
#define SRSLTE_CSI_CFG_H
|
||||||
|
|
||||||
|
#include "pucch_cfg_nr.h"
|
||||||
|
#include "srslte/config.h"
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Maximum number of CSI report configurations defined in TS 38.331 maxNrofCSI-ReportConfigurations
|
||||||
|
*/
|
||||||
|
#define SRSLTE_CSI_MAX_NOF_REPORT 48
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Maximum number of CSI-RS resources defined in TS 38.331 maxNrofCSI-ResourceConfigurations
|
||||||
|
*/
|
||||||
|
#define SRSLTE_CSI_MAX_NOF_RESOURCES 112
|
||||||
|
/**
|
||||||
|
* @brief CSI report types defined in TS 38.331 CSI-ReportConfig
|
||||||
|
*/
|
||||||
|
typedef enum SRSLTE_API {
|
||||||
|
SRSLTE_CSI_REPORT_TYPE_NONE = 0,
|
||||||
|
SRSLTE_CSI_REPORT_TYPE_PERIODIC,
|
||||||
|
SRSLTE_CSI_REPORT_TYPE_SEMI_PERSISTENT_ON_PUCCH,
|
||||||
|
SRSLTE_CSI_REPORT_TYPE_SEMI_PERSISTENT_ON_PUSCH,
|
||||||
|
SRSLTE_CSI_REPORT_TYPE_APERIODIC,
|
||||||
|
} srslte_csi_report_type_t;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief CSI report quantities defined in TS 38.331 CSI-ReportConfig
|
||||||
|
*/
|
||||||
|
typedef enum SRSLTE_API {
|
||||||
|
SRSLTE_CSI_REPORT_QUANTITY_NONE = 0,
|
||||||
|
SRSLTE_CSI_REPORT_QUANTITY_CRI_RI_PMI_CQI,
|
||||||
|
SRSLTE_CSI_REPORT_QUANTITY_CRI_RI_I1,
|
||||||
|
SRSLTE_CSI_REPORT_QUANTITY_CRI_RI_I1_CQI,
|
||||||
|
SRSLTE_CSI_REPORT_QUANTITY_CRI_RI_CQI,
|
||||||
|
SRSLTE_CSI_REPORT_QUANTITY_CRI_RSRP,
|
||||||
|
SRSLTE_CSI_REPORT_QUANTITY_SSB_INDEX_RSRP,
|
||||||
|
SRSLTE_CSI_REPORT_QUANTITY_CRI_RI_LI_PMI_CQI
|
||||||
|
} srslte_csi_report_quantity_t;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief CSI report frequency configuration defined in TS 38.331 CSI-ReportConfig
|
||||||
|
*/
|
||||||
|
typedef enum SRSLTE_API {
|
||||||
|
SRSLTE_CSI_REPORT_FREQ_WIDEBAND = 0,
|
||||||
|
SRSLTE_CSI_REPORT_FREQ_SUBBAND
|
||||||
|
} srslte_csi_report_freq_t;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief CQI table selection
|
||||||
|
*/
|
||||||
|
typedef enum SRSLTE_API {
|
||||||
|
SRSLTE_CSI_CQI_TABLE_1 = 0,
|
||||||
|
SRSLTE_CSI_CQI_TABLE_2,
|
||||||
|
SRSLTE_CSI_CQI_TABLE_3,
|
||||||
|
} srslte_csi_cqi_table_t;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief CSI periodic report configuration from upper layers
|
||||||
|
* @remark Described in TS 38.331 CSI-ReportConfig
|
||||||
|
*/
|
||||||
|
typedef struct SRSLTE_API {
|
||||||
|
uint32_t period; ///< Period in slots
|
||||||
|
uint32_t offset; ///< Offset from beginning of the period in slots
|
||||||
|
srslte_pucch_nr_resource_t resource; ///< PUCCH resource to use for reporting
|
||||||
|
} srslte_csi_periodic_report_cfg_t;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief CSI report configuration from higher layers
|
||||||
|
*/
|
||||||
|
typedef struct SRSLTE_API {
|
||||||
|
uint32_t channel_meas_id; ///< Channel measurement resource identifier
|
||||||
|
uint32_t interf_meas_id; ///< Interference measurement resource identifier
|
||||||
|
bool interf_meas_present; ///< Indicates if interference measurement identifier is present
|
||||||
|
srslte_csi_report_type_t type; ///< CSI report type (none, periodic, semiPersistentOnPUCCH, ...)
|
||||||
|
union {
|
||||||
|
void* none; ///< Reserved, no configured
|
||||||
|
srslte_csi_periodic_report_cfg_t periodic; ///< Used for periodic reporting
|
||||||
|
// ... add here other types
|
||||||
|
};
|
||||||
|
srslte_csi_report_quantity_t quantity; ///< Report quantity
|
||||||
|
srslte_csi_cqi_table_t cqi_table; ///< CQI table selection
|
||||||
|
srslte_csi_report_freq_t freq_cfg; ///< Determine whether it is wideband or subband
|
||||||
|
} srslte_csi_hl_report_cfg_t;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief General CSI configuration provided by higher layers
|
||||||
|
*/
|
||||||
|
typedef struct SRSLTE_API {
|
||||||
|
srslte_csi_hl_report_cfg_t reports[SRSLTE_CSI_MAX_NOF_REPORT]; ///< CSI report configuration
|
||||||
|
// ... add here physical CSI measurement sets
|
||||||
|
} srslte_csi_hl_cfg_t;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Generic measurement structure
|
||||||
|
*/
|
||||||
|
typedef struct SRSLTE_API {
|
||||||
|
uint32_t cri; ///< CSI-RS Resource Indicator
|
||||||
|
float wideband_rsrp_dBm; ///< Measured NZP-CSI-RS RSRP (Ignore for IM-CSI-RS)
|
||||||
|
float wideband_epre_dBm; ///< Measured EPRE
|
||||||
|
float wideband_snr_db; ///< SNR calculated from NZP-CSI-RS RSRP and EPRE (Ignore for IM-CSI-RS)
|
||||||
|
|
||||||
|
// Resource set context
|
||||||
|
uint32_t nof_ports; ///< Number of antenna ports
|
||||||
|
uint32_t K_csi_rs; ///< Number of CSI-RS in the corresponding resource set
|
||||||
|
} srslte_csi_measurements_t;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief CSI report configuration
|
||||||
|
*/
|
||||||
|
typedef struct SRSLTE_API {
|
||||||
|
srslte_csi_report_type_t type; ///< CSI report type (none, periodic, semiPersistentOnPUCCH, ...)
|
||||||
|
srslte_csi_report_quantity_t quantity; ///< Report quantity
|
||||||
|
srslte_pucch_nr_resource_t pucch_resource; ///< PUCCH resource to use for periodic reporting
|
||||||
|
srslte_csi_report_freq_t freq_cfg; ///< Determine whether it is wideband or subband
|
||||||
|
|
||||||
|
// Resource set context
|
||||||
|
uint32_t nof_ports; ///< Number of antenna ports
|
||||||
|
uint32_t K_csi_rs; ///< Number of CSI-RS in the corresponding resource set
|
||||||
|
} srslte_csi_report_cfg_t;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Wideband CSI report values
|
||||||
|
*/
|
||||||
|
typedef struct SRSLTE_API {
|
||||||
|
uint32_t ri;
|
||||||
|
uint32_t pmi;
|
||||||
|
uint32_t cqi;
|
||||||
|
} srslte_csi_report_wideband_cri_ri_pmi_cqi_t;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Unified CSI report values
|
||||||
|
*/
|
||||||
|
typedef struct SRSLTE_API {
|
||||||
|
uint32_t cri; ///< CSI-RS Resource Indicator
|
||||||
|
union {
|
||||||
|
void* none;
|
||||||
|
srslte_csi_report_wideband_cri_ri_pmi_cqi_t wideband_cri_ri_pmi_cqi;
|
||||||
|
};
|
||||||
|
bool valid; ///< Used by receiver only
|
||||||
|
} srslte_csi_report_value_t;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Complete report configuration and value
|
||||||
|
*/
|
||||||
|
typedef struct SRSLTE_API {
|
||||||
|
srslte_csi_report_cfg_t cfg[SRSLTE_CSI_MAX_NOF_REPORT]; ///< Configuration ready for encoding
|
||||||
|
srslte_csi_report_value_t value[SRSLTE_CSI_MAX_NOF_REPORT]; ///< Quantified values
|
||||||
|
uint32_t nof_reports; ///< Total number of reports to transmit
|
||||||
|
} srslte_csi_reports_t;
|
||||||
|
|
||||||
|
#endif // SRSLTE_CSI_CFG_H
|
@ -0,0 +1,33 @@
|
|||||||
|
/**
|
||||||
|
*
|
||||||
|
* \section COPYRIGHT
|
||||||
|
*
|
||||||
|
* Copyright 2013-2020 Software Radio Systems Limited
|
||||||
|
*
|
||||||
|
* By using this file, you agree to the terms and conditions set
|
||||||
|
* forth in the LICENSE file which can be found at the top level of
|
||||||
|
* the distribution.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef SRSLTE_SYS_METRICS_H
|
||||||
|
#define SRSLTE_SYS_METRICS_H
|
||||||
|
|
||||||
|
#include <cstdint>
|
||||||
|
|
||||||
|
namespace srslte {
|
||||||
|
|
||||||
|
/// Metrics of cpu usage, memory consumption and number of thread used by the process.
|
||||||
|
struct sys_metrics_t {
|
||||||
|
uint32_t process_realmem_kB = 0;
|
||||||
|
uint32_t process_virtualmem_kB = 0;
|
||||||
|
float process_realmem = -1.f;
|
||||||
|
float process_virtualmem = -1.f;
|
||||||
|
uint32_t thread_count = 0;
|
||||||
|
float process_cpu_usage = -1.f;
|
||||||
|
float system_mem = -1.f;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace srslte
|
||||||
|
|
||||||
|
#endif // SRSLTE_SYS_METRICS_H
|
@ -0,0 +1,66 @@
|
|||||||
|
/**
|
||||||
|
*
|
||||||
|
* \section COPYRIGHT
|
||||||
|
*
|
||||||
|
* Copyright 2013-2020 Software Radio Systems Limited
|
||||||
|
*
|
||||||
|
* By using this file, you agree to the terms and conditions set
|
||||||
|
* forth in the LICENSE file which can be found at the top level of
|
||||||
|
* the distribution.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef SRSLTE_SYS_METRICS_PROCESSOR_H
|
||||||
|
#define SRSLTE_SYS_METRICS_PROCESSOR_H
|
||||||
|
|
||||||
|
#include "srslte/system/sys_metrics.h"
|
||||||
|
#include <chrono>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
namespace srslte {
|
||||||
|
|
||||||
|
/// Process information from the system to create sys_metrics_t. The information is processed from the /proc/ system.
|
||||||
|
class sys_metrics_processor
|
||||||
|
{
|
||||||
|
/// Helper class used to parse the information from the /proc/[pid]/stats.
|
||||||
|
struct proc_stats_info {
|
||||||
|
proc_stats_info();
|
||||||
|
|
||||||
|
// Initialize the variables that will be used.
|
||||||
|
int32_t num_threads = 0;
|
||||||
|
uint32_t utime = 0;
|
||||||
|
uint32_t stime = 0;
|
||||||
|
|
||||||
|
// Rest of the information of the stats file.
|
||||||
|
int32_t pid, ppid, pgrp, session, tty_nr, tpgid, exit_signal, processor, exit_code, cutime, cstime, priority, nice,
|
||||||
|
itrealvalue, rss, cguest_time;
|
||||||
|
uint32_t minflt, cminflt, majflt, cmajflt, vsize, rsslim, startcode, endcode, startstack, kstkesp, kstkeip, signal,
|
||||||
|
blocked, sigignore, sigcatch, wchan, nswap, cnswap, guest_time, start_data, end_data, start_brk, arg_start,
|
||||||
|
arg_end, env_start, env_end, flags, rt_priority, policy;
|
||||||
|
uint64_t starttime, delaycct_blkio_ticks;
|
||||||
|
uint8_t state;
|
||||||
|
std::string comm;
|
||||||
|
};
|
||||||
|
|
||||||
|
public:
|
||||||
|
/// Measures and returns the system metrics.
|
||||||
|
sys_metrics_t get_metrics();
|
||||||
|
|
||||||
|
private:
|
||||||
|
/// Calculates and returns the cpu usage in %. current_query is the most recent proc_stats_info, and
|
||||||
|
/// delta_time_in_seconds is the elapsed time between the last measure and current in seconds. NOTE: Returns -1.0f on
|
||||||
|
/// error.
|
||||||
|
float calculate_cpu_usage(const proc_stats_info& current_query, float delta_time_in_seconds) const;
|
||||||
|
|
||||||
|
/// Calculate the memory parameters and writes them in metrics.
|
||||||
|
/// NOTE: on error, metrics memory parameters are set to 0.
|
||||||
|
void calculate_mem_usage(sys_metrics_t& metrics) const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
proc_stats_info last_query = {};
|
||||||
|
std::chrono::time_point<std::chrono::steady_clock> last_query_time = std::chrono::steady_clock::now();
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace srslte
|
||||||
|
|
||||||
|
#endif // SRSLTE_SYS_METRICS_PROCESSOR_H
|
@ -0,0 +1,336 @@
|
|||||||
|
/**
|
||||||
|
*
|
||||||
|
* \section COPYRIGHT
|
||||||
|
*
|
||||||
|
* Copyright 2013-2020 Software Radio Systems Limited
|
||||||
|
*
|
||||||
|
* By using this file, you agree to the terms and conditions set
|
||||||
|
* forth in the LICENSE file which can be found at the top level of
|
||||||
|
* the distribution.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "srslte/common/mac_pcap_base.h"
|
||||||
|
#include "srslte/config.h"
|
||||||
|
#include "srslte/phy/common/phy_common.h"
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
namespace srslte {
|
||||||
|
|
||||||
|
mac_pcap_base::mac_pcap_base() : logger(srslog::fetch_basic_logger("MAC")), thread("PCAP_WRITER_MAC") {}
|
||||||
|
|
||||||
|
mac_pcap_base::~mac_pcap_base() {}
|
||||||
|
|
||||||
|
void mac_pcap_base::enable(bool enable_)
|
||||||
|
{
|
||||||
|
std::lock_guard<std::mutex> lock(mutex);
|
||||||
|
running = enable_;
|
||||||
|
}
|
||||||
|
|
||||||
|
void mac_pcap_base::set_ue_id(uint16_t ue_id_)
|
||||||
|
{
|
||||||
|
std::lock_guard<std::mutex> lock(mutex);
|
||||||
|
ue_id = ue_id_;
|
||||||
|
}
|
||||||
|
|
||||||
|
void mac_pcap_base::run_thread()
|
||||||
|
{
|
||||||
|
// blocking write until stopped
|
||||||
|
while (running) {
|
||||||
|
pcap_pdu_t pdu = queue.wait_pop();
|
||||||
|
{
|
||||||
|
std::lock_guard<std::mutex> lock(mutex);
|
||||||
|
write_pdu(pdu);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// write remainder of queue
|
||||||
|
std::lock_guard<std::mutex> lock(mutex);
|
||||||
|
pcap_pdu_t pdu = {};
|
||||||
|
while (queue.try_pop(&pdu)) {
|
||||||
|
write_pdu(pdu);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Function called from PHY worker context, locking not needed as PDU queue is thread-safe
|
||||||
|
void mac_pcap_base::pack_and_queue(uint8_t* payload,
|
||||||
|
uint32_t payload_len,
|
||||||
|
uint16_t ue_id,
|
||||||
|
uint32_t reTX,
|
||||||
|
bool crc_ok,
|
||||||
|
uint8_t cc_idx,
|
||||||
|
uint32_t tti,
|
||||||
|
uint16_t crnti,
|
||||||
|
uint8_t direction,
|
||||||
|
uint8_t rnti_type)
|
||||||
|
{
|
||||||
|
if (running && payload != nullptr) {
|
||||||
|
pcap_pdu_t pdu = {};
|
||||||
|
pdu.rat = srslte::srslte_rat_t::lte;
|
||||||
|
pdu.context.radioType = FDD_RADIO;
|
||||||
|
pdu.context.direction = direction;
|
||||||
|
pdu.context.rntiType = rnti_type;
|
||||||
|
pdu.context.rnti = crnti;
|
||||||
|
pdu.context.ueid = ue_id;
|
||||||
|
pdu.context.isRetx = (uint8_t)reTX;
|
||||||
|
pdu.context.crcStatusOK = crc_ok;
|
||||||
|
pdu.context.cc_idx = cc_idx;
|
||||||
|
pdu.context.sysFrameNumber = (uint16_t)(tti / 10);
|
||||||
|
pdu.context.subFrameNumber = (uint16_t)(tti % 10);
|
||||||
|
|
||||||
|
// try to allocate PDU buffer
|
||||||
|
pdu.pdu = srslte::make_byte_buffer();
|
||||||
|
if (pdu.pdu != nullptr && pdu.pdu->get_tailroom() >= payload_len) {
|
||||||
|
// copy payload into PDU buffer
|
||||||
|
memcpy(pdu.pdu->msg, payload, payload_len);
|
||||||
|
pdu.pdu->N_bytes = payload_len;
|
||||||
|
queue.push(std::move(pdu));
|
||||||
|
} else {
|
||||||
|
logger.info("Dropping PDU in PCAP. No buffer available or not enough space (pdu_len=%d).", payload_len);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Function called from PHY worker context, locking not needed as PDU queue is thread-safe
|
||||||
|
void mac_pcap_base::pack_and_queue_nr(uint8_t* payload,
|
||||||
|
uint32_t payload_len,
|
||||||
|
uint32_t tti,
|
||||||
|
uint16_t crnti,
|
||||||
|
uint16_t ue_id,
|
||||||
|
uint8_t harqid,
|
||||||
|
uint8_t direction,
|
||||||
|
uint8_t rnti_type)
|
||||||
|
{
|
||||||
|
if (running && payload != nullptr) {
|
||||||
|
pcap_pdu_t pdu = {};
|
||||||
|
pdu.rat = srslte_rat_t::nr;
|
||||||
|
pdu.context_nr.radioType = FDD_RADIO;
|
||||||
|
pdu.context_nr.direction = direction;
|
||||||
|
pdu.context_nr.rntiType = rnti_type;
|
||||||
|
pdu.context_nr.rnti = crnti;
|
||||||
|
pdu.context_nr.ueid = ue_id;
|
||||||
|
pdu.context_nr.harqid = harqid;
|
||||||
|
pdu.context_nr.system_frame_number = tti / 10;
|
||||||
|
pdu.context_nr.sub_frame_number = tti % 10;
|
||||||
|
|
||||||
|
// try to allocate PDU buffer
|
||||||
|
pdu.pdu = srslte::make_byte_buffer();
|
||||||
|
if (pdu.pdu != nullptr && pdu.pdu->get_tailroom() >= payload_len) {
|
||||||
|
// copy payload into PDU buffer
|
||||||
|
memcpy(pdu.pdu->msg, payload, payload_len);
|
||||||
|
pdu.pdu->N_bytes = payload_len;
|
||||||
|
queue.push(std::move(pdu));
|
||||||
|
} else {
|
||||||
|
logger.info("Dropping PDU in NR PCAP. No buffer available or not enough space (pdu_len=%d).", payload_len);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void mac_pcap_base::write_dl_crnti(uint8_t* pdu,
|
||||||
|
uint32_t pdu_len_bytes,
|
||||||
|
uint16_t rnti,
|
||||||
|
bool crc_ok,
|
||||||
|
uint32_t tti,
|
||||||
|
uint8_t cc_idx)
|
||||||
|
{
|
||||||
|
pack_and_queue(pdu, pdu_len_bytes, ue_id, 0, crc_ok, cc_idx, tti, rnti, DIRECTION_DOWNLINK, C_RNTI);
|
||||||
|
}
|
||||||
|
void mac_pcap_base::write_dl_ranti(uint8_t* pdu,
|
||||||
|
uint32_t pdu_len_bytes,
|
||||||
|
uint16_t rnti,
|
||||||
|
bool crc_ok,
|
||||||
|
uint32_t tti,
|
||||||
|
uint8_t cc_idx)
|
||||||
|
{
|
||||||
|
pack_and_queue(pdu, pdu_len_bytes, ue_id, 0, crc_ok, cc_idx, tti, rnti, DIRECTION_DOWNLINK, RA_RNTI);
|
||||||
|
}
|
||||||
|
void mac_pcap_base::write_ul_crnti(uint8_t* pdu,
|
||||||
|
uint32_t pdu_len_bytes,
|
||||||
|
uint16_t rnti,
|
||||||
|
uint32_t reTX,
|
||||||
|
uint32_t tti,
|
||||||
|
uint8_t cc_idx)
|
||||||
|
{
|
||||||
|
pack_and_queue(pdu, pdu_len_bytes, ue_id, reTX, true, cc_idx, tti, rnti, DIRECTION_UPLINK, C_RNTI);
|
||||||
|
}
|
||||||
|
|
||||||
|
void mac_pcap_base::write_ul_crnti(uint8_t* pdu,
|
||||||
|
uint32_t pdu_len_bytes,
|
||||||
|
uint16_t rnti,
|
||||||
|
uint16_t ue_id,
|
||||||
|
uint32_t reTX,
|
||||||
|
uint32_t tti,
|
||||||
|
uint8_t cc_idx)
|
||||||
|
{
|
||||||
|
pack_and_queue(pdu, pdu_len_bytes, ue_id, reTX, true, cc_idx, tti, rnti, DIRECTION_UPLINK, C_RNTI);
|
||||||
|
}
|
||||||
|
|
||||||
|
void mac_pcap_base::write_dl_crnti(uint8_t* pdu,
|
||||||
|
uint32_t pdu_len_bytes,
|
||||||
|
uint16_t rnti,
|
||||||
|
uint16_t ue_id,
|
||||||
|
bool crc_ok,
|
||||||
|
uint32_t tti,
|
||||||
|
uint8_t cc_idx)
|
||||||
|
{
|
||||||
|
pack_and_queue(pdu, pdu_len_bytes, ue_id, 0, crc_ok, cc_idx, tti, rnti, DIRECTION_DOWNLINK, C_RNTI);
|
||||||
|
}
|
||||||
|
|
||||||
|
void mac_pcap_base::write_sl_crnti(uint8_t* pdu,
|
||||||
|
uint32_t pdu_len_bytes,
|
||||||
|
uint16_t rnti,
|
||||||
|
uint32_t reTX,
|
||||||
|
uint32_t tti,
|
||||||
|
uint8_t cc_idx)
|
||||||
|
{
|
||||||
|
pack_and_queue(pdu, pdu_len_bytes, ue_id, reTX, true, cc_idx, tti, rnti, DIRECTION_UPLINK, SL_RNTI);
|
||||||
|
}
|
||||||
|
|
||||||
|
void mac_pcap_base::write_dl_bch(uint8_t* pdu, uint32_t pdu_len_bytes, bool crc_ok, uint32_t tti, uint8_t cc_idx)
|
||||||
|
{
|
||||||
|
pack_and_queue(pdu, pdu_len_bytes, ue_id, 0, crc_ok, cc_idx, tti, 0, DIRECTION_DOWNLINK, NO_RNTI);
|
||||||
|
}
|
||||||
|
void mac_pcap_base::write_dl_pch(uint8_t* pdu, uint32_t pdu_len_bytes, bool crc_ok, uint32_t tti, uint8_t cc_idx)
|
||||||
|
{
|
||||||
|
pack_and_queue(pdu, pdu_len_bytes, ue_id, 0, crc_ok, cc_idx, tti, SRSLTE_PRNTI, DIRECTION_DOWNLINK, P_RNTI);
|
||||||
|
}
|
||||||
|
void mac_pcap_base::write_dl_mch(uint8_t* pdu, uint32_t pdu_len_bytes, bool crc_ok, uint32_t tti, uint8_t cc_idx)
|
||||||
|
{
|
||||||
|
pack_and_queue(pdu, pdu_len_bytes, ue_id, 0, crc_ok, cc_idx, tti, SRSLTE_MRNTI, DIRECTION_DOWNLINK, M_RNTI);
|
||||||
|
}
|
||||||
|
void mac_pcap_base::write_dl_sirnti(uint8_t* pdu, uint32_t pdu_len_bytes, bool crc_ok, uint32_t tti, uint8_t cc_idx)
|
||||||
|
{
|
||||||
|
pack_and_queue(pdu, pdu_len_bytes, ue_id, 0, crc_ok, cc_idx, tti, SRSLTE_SIRNTI, DIRECTION_DOWNLINK, SI_RNTI);
|
||||||
|
}
|
||||||
|
|
||||||
|
void mac_pcap_base::write_dl_crnti_nr(uint8_t* pdu, uint32_t pdu_len_bytes, uint16_t rnti, uint8_t harqid, uint32_t tti)
|
||||||
|
{
|
||||||
|
pack_and_queue_nr(pdu, pdu_len_bytes, tti, rnti, ue_id, harqid, DIRECTION_DOWNLINK, C_RNTI);
|
||||||
|
}
|
||||||
|
|
||||||
|
void mac_pcap_base::write_dl_crnti_nr(uint8_t* pdu,
|
||||||
|
uint32_t pdu_len_bytes,
|
||||||
|
uint16_t crnti,
|
||||||
|
uint16_t ue_id,
|
||||||
|
uint8_t harqid,
|
||||||
|
uint32_t tti)
|
||||||
|
{
|
||||||
|
pack_and_queue_nr(pdu, pdu_len_bytes, tti, crnti, ue_id, harqid, DIRECTION_DOWNLINK, C_RNTI);
|
||||||
|
}
|
||||||
|
|
||||||
|
void mac_pcap_base::write_ul_crnti_nr(uint8_t* pdu, uint32_t pdu_len_bytes, uint16_t rnti, uint8_t harqid, uint32_t tti)
|
||||||
|
{
|
||||||
|
pack_and_queue_nr(pdu, pdu_len_bytes, tti, rnti, ue_id, harqid, DIRECTION_UPLINK, C_RNTI);
|
||||||
|
}
|
||||||
|
|
||||||
|
void mac_pcap_base::write_ul_crnti_nr(uint8_t* pdu,
|
||||||
|
uint32_t pdu_len_bytes,
|
||||||
|
uint16_t rnti,
|
||||||
|
uint16_t ue_id,
|
||||||
|
uint8_t harqid,
|
||||||
|
uint32_t tti)
|
||||||
|
{
|
||||||
|
pack_and_queue_nr(pdu, pdu_len_bytes, tti, rnti, ue_id, harqid, DIRECTION_UPLINK, C_RNTI);
|
||||||
|
}
|
||||||
|
|
||||||
|
void mac_pcap_base::write_dl_ra_rnti_nr(uint8_t* pdu,
|
||||||
|
uint32_t pdu_len_bytes,
|
||||||
|
uint16_t rnti,
|
||||||
|
uint8_t harqid,
|
||||||
|
uint32_t tti)
|
||||||
|
{
|
||||||
|
pack_and_queue_nr(pdu, pdu_len_bytes, tti, rnti, ue_id, harqid, DIRECTION_DOWNLINK, RA_RNTI);
|
||||||
|
}
|
||||||
|
|
||||||
|
void mac_pcap_base::write_dl_bch_nr(uint8_t* pdu, uint32_t pdu_len_bytes, uint16_t rnti, uint8_t harqid, uint32_t tti)
|
||||||
|
{
|
||||||
|
pack_and_queue_nr(pdu, pdu_len_bytes, tti, rnti, ue_id, harqid, DIRECTION_DOWNLINK, NO_RNTI);
|
||||||
|
}
|
||||||
|
|
||||||
|
void mac_pcap_base::write_dl_pch_nr(uint8_t* pdu, uint32_t pdu_len_bytes, uint16_t rnti, uint8_t harqid, uint32_t tti)
|
||||||
|
{
|
||||||
|
pack_and_queue_nr(pdu, pdu_len_bytes, tti, rnti, ue_id, harqid, DIRECTION_DOWNLINK, P_RNTI);
|
||||||
|
}
|
||||||
|
|
||||||
|
void mac_pcap_base::write_dl_si_rnti_nr(uint8_t* pdu,
|
||||||
|
uint32_t pdu_len_bytes,
|
||||||
|
uint16_t rnti,
|
||||||
|
uint8_t harqid,
|
||||||
|
uint32_t tti)
|
||||||
|
{
|
||||||
|
pack_and_queue_nr(pdu, pdu_len_bytes, tti, rnti, ue_id, harqid, DIRECTION_DOWNLINK, SI_RNTI);
|
||||||
|
}
|
||||||
|
|
||||||
|
void mac_pcap_base::write_ul_rrc_pdu(const uint8_t* input, const int32_t input_len)
|
||||||
|
{
|
||||||
|
uint8_t pdu[1024];
|
||||||
|
bzero(pdu, sizeof(pdu));
|
||||||
|
|
||||||
|
// Size is limited by PDU buffer and MAC subheader (format 1 < 128 B)
|
||||||
|
if (input_len > 128 - 7) {
|
||||||
|
logger.error("PDU too large.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// MAC PDU Header (Short BSR) (1:54) (Padding:remainder) [3 subheaders]
|
||||||
|
// Sub-header (lcid=Short BSR)
|
||||||
|
// 0... .... = SCH reserved bit: 0x0
|
||||||
|
// .0.. .... = Format2: Data length is < 32768 bytes
|
||||||
|
// ..1. .... = Extension: 0x1
|
||||||
|
// ...1 1101 = LCID: Short BSR (0x1d)
|
||||||
|
// Sub-header (lcid=1, length=54)
|
||||||
|
// 0... .... = SCH reserved bit: 0x0
|
||||||
|
// .0.. .... = Format2: Data length is < 32768 bytes
|
||||||
|
// ..1. .... = Extension: 0x1
|
||||||
|
// ...0 0001 = LCID: 1 (0x01)
|
||||||
|
// 0... .... = Format: Data length is < 128 bytes
|
||||||
|
// .011 0110 = Length: 54 (Will be dynamically updated)
|
||||||
|
// Sub-header (lcid=Padding, length is remainder)
|
||||||
|
// 0... .... = SCH reserved bit: 0x0
|
||||||
|
// .0.. .... = Format2: Data length is < 32768 bytes
|
||||||
|
// ..0. .... = Extension: 0x0
|
||||||
|
// ...1 1111 = LCID: Padding (0x1f)
|
||||||
|
uint8_t mac_hdr[] = {0x3D, 0x21, 0x36, 0x1F, 0x0C};
|
||||||
|
|
||||||
|
// Update MAC length
|
||||||
|
mac_hdr[2] = input_len + 7; // rlc_hdr (2) + pdcp_hdr (1) + MAC (4)
|
||||||
|
|
||||||
|
// AM Header (P) sn=4
|
||||||
|
// 1... .... = Frame type: Data PDU (0x1)
|
||||||
|
// .0.. .... = Re-segmentation Flag: AMD PDU (0x0)
|
||||||
|
// ..1. .... = Polling Bit: Status report is requested (0x1)
|
||||||
|
// ...0 0... = Framing Info: First byte begins a RLC SDU and last byte ends a RLC SDU (0x0)
|
||||||
|
// .... .0.. = Extension: Data field follows from the octet following the fixed part of the header (0x0)
|
||||||
|
// .... ..00 0000 0100 = Sequence Number: 4
|
||||||
|
uint8_t rlc_hdr[] = {0xA0, 0x04};
|
||||||
|
|
||||||
|
// PDCP-LTE sn=3
|
||||||
|
// 000. .... = Reserved: 0
|
||||||
|
// ...0 0011 = Seq Num: 3
|
||||||
|
uint8_t pdcp_hdr[] = {0x03};
|
||||||
|
|
||||||
|
uint8_t* pdu_ptr = pdu;
|
||||||
|
|
||||||
|
memcpy(pdu_ptr, mac_hdr, sizeof(mac_hdr));
|
||||||
|
pdu_ptr += sizeof(mac_hdr);
|
||||||
|
memcpy(pdu_ptr, rlc_hdr, sizeof(rlc_hdr));
|
||||||
|
pdu_ptr += sizeof(rlc_hdr);
|
||||||
|
memcpy(pdu_ptr, pdcp_hdr, sizeof(pdcp_hdr));
|
||||||
|
pdu_ptr += sizeof(pdcp_hdr);
|
||||||
|
memcpy(pdu_ptr, input, input_len);
|
||||||
|
pdu_ptr += input_len;
|
||||||
|
|
||||||
|
// MAC
|
||||||
|
uint8_t pad = 0x00;
|
||||||
|
for (uint32_t i = 0; i < 4; i++) {
|
||||||
|
memcpy(pdu_ptr, &pad, 1);
|
||||||
|
pdu_ptr += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Pad
|
||||||
|
memcpy(pdu_ptr, &pad, 1);
|
||||||
|
pdu_ptr += 1;
|
||||||
|
|
||||||
|
write_ul_crnti(pdu, pdu_ptr - pdu, 14931, true, 0, 0);
|
||||||
|
}
|
||||||
|
} // namespace srslte
|
@ -0,0 +1,170 @@
|
|||||||
|
/**
|
||||||
|
*
|
||||||
|
* \section COPYRIGHT
|
||||||
|
*
|
||||||
|
* Copyright 2013-2020 Software Radio Systems Limited
|
||||||
|
*
|
||||||
|
* By using this file, you agree to the terms and conditions set
|
||||||
|
* forth in the LICENSE file which can be found at the top level of
|
||||||
|
* the distribution.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "srslte/common/mac_pcap_net.h"
|
||||||
|
|
||||||
|
namespace srslte {
|
||||||
|
|
||||||
|
mac_pcap_net::mac_pcap_net() : mac_pcap_base() {}
|
||||||
|
|
||||||
|
mac_pcap_net::~mac_pcap_net()
|
||||||
|
{
|
||||||
|
close();
|
||||||
|
}
|
||||||
|
uint32_t mac_pcap_net::open(std::string client_ip_addr_,
|
||||||
|
std::string bind_addr_str,
|
||||||
|
uint16_t client_udp_port_,
|
||||||
|
uint16_t bind_udp_port_,
|
||||||
|
uint32_t ue_id_)
|
||||||
|
{
|
||||||
|
std::lock_guard<std::mutex> lock(mutex);
|
||||||
|
|
||||||
|
if (socket.is_init()) {
|
||||||
|
logger.error("PCAP socket writer for %s already running. Close first.", bind_addr_str.c_str());
|
||||||
|
return SRSLTE_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (not socket.open_socket(
|
||||||
|
net_utils::addr_family::ipv4, net_utils::socket_type::datagram, net_utils::protocol_type::UDP)) {
|
||||||
|
logger.error("Couldn't open socket %s to write PCAP", bind_addr_str.c_str());
|
||||||
|
return SRSLTE_ERROR;
|
||||||
|
}
|
||||||
|
if (not socket.bind_addr(bind_addr_str.c_str(), bind_udp_port_)) {
|
||||||
|
socket.reset();
|
||||||
|
logger.error("Couldn't bind socket %s to write PCAP", bind_addr_str.c_str());
|
||||||
|
return SRSLTE_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
logger.info("Sending MAC PCAP frames to %s:%d (from %s:%d)",
|
||||||
|
client_ip_addr_.c_str(),
|
||||||
|
client_udp_port_,
|
||||||
|
bind_addr_str.c_str(),
|
||||||
|
bind_udp_port_);
|
||||||
|
client_addr.sin_family = AF_INET;
|
||||||
|
client_addr.sin_addr.s_addr = inet_addr(client_ip_addr_.c_str());
|
||||||
|
client_addr.sin_port = htons(client_udp_port_);
|
||||||
|
running = true;
|
||||||
|
ue_id = ue_id_;
|
||||||
|
// start writer thread
|
||||||
|
start();
|
||||||
|
|
||||||
|
return SRSLTE_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t mac_pcap_net::close()
|
||||||
|
{
|
||||||
|
{
|
||||||
|
std::lock_guard<std::mutex> lock(mutex);
|
||||||
|
if (running == false || socket.is_init() == false) {
|
||||||
|
return SRSLTE_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
// tell writer thread to stop
|
||||||
|
running = false;
|
||||||
|
pcap_pdu_t pdu = {};
|
||||||
|
queue.push(std::move(pdu));
|
||||||
|
}
|
||||||
|
|
||||||
|
wait_thread_finish();
|
||||||
|
// close socket handle
|
||||||
|
if (socket.is_init()) {
|
||||||
|
std::lock_guard<std::mutex> lock(mutex);
|
||||||
|
socket.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
return SRSLTE_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
void mac_pcap_net::write_pdu(pcap_pdu_t& pdu)
|
||||||
|
{
|
||||||
|
if (pdu.pdu != nullptr && socket.is_init()) {
|
||||||
|
switch (pdu.rat) {
|
||||||
|
case srslte_rat_t::lte:
|
||||||
|
write_mac_lte_pdu_to_net(pdu);
|
||||||
|
break;
|
||||||
|
case srslte_rat_t::nr:
|
||||||
|
write_mac_nr_pdu_to_net(pdu);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
logger.error("Error writing PDU to PCAP socket. Unsupported RAT selected.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void mac_pcap_net::write_mac_lte_pdu_to_net(pcap_pdu_t& pdu)
|
||||||
|
{
|
||||||
|
int bytes_sent;
|
||||||
|
uint32_t offset = 0;
|
||||||
|
uint8_t buffer[PCAP_CONTEXT_HEADER_MAX];
|
||||||
|
|
||||||
|
// MAC_LTE_START_STRING for UDP heuristics
|
||||||
|
memcpy(buffer + offset, MAC_LTE_START_STRING, strlen(MAC_LTE_START_STRING));
|
||||||
|
offset += strlen(MAC_LTE_START_STRING);
|
||||||
|
|
||||||
|
offset += LTE_PCAP_PACK_MAC_CONTEXT_TO_BUFFER(&pdu.context, buffer + offset, PCAP_CONTEXT_HEADER_MAX);
|
||||||
|
|
||||||
|
if (pdu.pdu.get()->get_headroom() < offset) {
|
||||||
|
logger.error("PDU headroom is to small for adding context buffer");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
pdu.pdu.get()->msg -= offset;
|
||||||
|
memcpy(pdu.pdu.get()->msg, buffer, offset);
|
||||||
|
pdu.pdu.get()->N_bytes += offset;
|
||||||
|
|
||||||
|
bytes_sent = sendto(socket.get_socket(),
|
||||||
|
pdu.pdu.get()->msg,
|
||||||
|
pdu.pdu.get()->N_bytes,
|
||||||
|
0,
|
||||||
|
(const struct sockaddr*)&client_addr,
|
||||||
|
sizeof(client_addr));
|
||||||
|
|
||||||
|
if ((int)pdu.pdu.get()->N_bytes != bytes_sent || bytes_sent < 0) {
|
||||||
|
logger.error(
|
||||||
|
"Sending UDP packet mismatches %d != %d (err %s)", pdu.pdu.get()->N_bytes, bytes_sent, strerror(errno));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void mac_pcap_net::write_mac_nr_pdu_to_net(pcap_pdu_t& pdu)
|
||||||
|
{
|
||||||
|
int bytes_sent;
|
||||||
|
uint32_t offset = 0;
|
||||||
|
uint8_t buffer[PCAP_CONTEXT_HEADER_MAX];
|
||||||
|
|
||||||
|
// MAC_LTE_START_STRING for UDP heuristics
|
||||||
|
memcpy(buffer + offset, MAC_LTE_START_STRING, strlen(MAC_LTE_START_STRING));
|
||||||
|
offset += strlen(MAC_LTE_START_STRING);
|
||||||
|
|
||||||
|
offset += NR_PCAP_PACK_MAC_CONTEXT_TO_BUFFER(&pdu.context_nr, buffer + offset, PCAP_CONTEXT_HEADER_MAX);
|
||||||
|
|
||||||
|
if (pdu.pdu.get()->get_headroom() < offset) {
|
||||||
|
logger.error("PDU headroom is to small for adding context buffer");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
pdu.pdu.get()->msg -= offset;
|
||||||
|
memcpy(pdu.pdu.get()->msg, buffer, offset);
|
||||||
|
pdu.pdu.get()->N_bytes += offset;
|
||||||
|
|
||||||
|
bytes_sent = sendto(socket.get_socket(),
|
||||||
|
pdu.pdu.get()->msg,
|
||||||
|
pdu.pdu.get()->N_bytes,
|
||||||
|
0,
|
||||||
|
(const struct sockaddr*)&client_addr,
|
||||||
|
sizeof(client_addr));
|
||||||
|
|
||||||
|
if ((int)pdu.pdu.get()->N_bytes != bytes_sent || bytes_sent < 0) {
|
||||||
|
logger.error(
|
||||||
|
"Sending UDP packet mismatches %d != %d (err %s)", pdu.pdu.get()->N_bytes, bytes_sent, strerror(errno));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} // namespace srslte
|
@ -0,0 +1,221 @@
|
|||||||
|
/**
|
||||||
|
*
|
||||||
|
* \section COPYRIGHT
|
||||||
|
*
|
||||||
|
* Copyright 2013-2020 Software Radio Systems Limited
|
||||||
|
*
|
||||||
|
* By using this file, you agree to the terms and conditions set
|
||||||
|
* forth in the LICENSE file which can be found at the top level of
|
||||||
|
* the distribution.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
#include "srslte/phy/phch/csi.h"
|
||||||
|
#include "srslte/phy/utils/bit.h"
|
||||||
|
#include "srslte/phy/utils/debug.h"
|
||||||
|
#include <math.h>
|
||||||
|
|
||||||
|
#define CSI_WIDEBAND_CSI_NOF_BITS 4
|
||||||
|
|
||||||
|
/// Implements SNRI to CQI conversion
|
||||||
|
uint32_t csi_snri_db_to_cqi(srslte_csi_cqi_table_t table, float snri_db)
|
||||||
|
{
|
||||||
|
return 6;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Implements CSI report triggers
|
||||||
|
static bool csi_report_trigger(const srslte_csi_hl_report_cfg_t* cfg, uint32_t slot_idx)
|
||||||
|
{
|
||||||
|
switch (cfg->type) {
|
||||||
|
case SRSLTE_CSI_REPORT_TYPE_PERIODIC:
|
||||||
|
return (slot_idx + cfg->periodic.period - cfg->periodic.offset) % cfg->periodic.period == 0;
|
||||||
|
default:; // Do nothing
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void csi_wideband_cri_ri_pmi_cqi_quantify(const srslte_csi_hl_report_cfg_t* cfg,
|
||||||
|
const srslte_csi_measurements_t* channel_meas,
|
||||||
|
const srslte_csi_measurements_t* interf_meas,
|
||||||
|
srslte_csi_report_cfg_t* report_cfg,
|
||||||
|
srslte_csi_report_value_t* report_value)
|
||||||
|
{
|
||||||
|
// Take SNR by default
|
||||||
|
float wideband_sinr_db = channel_meas->wideband_snr_db;
|
||||||
|
|
||||||
|
// If interference is provided, use the channel RSRP and interference EPRE to calculate the SINR
|
||||||
|
if (interf_meas != NULL) {
|
||||||
|
wideband_sinr_db = channel_meas->wideband_rsrp_dBm - interf_meas->wideband_epre_dBm;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fill report configuration
|
||||||
|
report_cfg->type = cfg->type;
|
||||||
|
report_cfg->quantity = SRSLTE_CSI_REPORT_QUANTITY_CRI_RI_PMI_CQI;
|
||||||
|
report_cfg->freq_cfg = SRSLTE_CSI_REPORT_FREQ_WIDEBAND;
|
||||||
|
report_cfg->nof_ports = channel_meas->nof_ports;
|
||||||
|
report_cfg->K_csi_rs = channel_meas->K_csi_rs;
|
||||||
|
|
||||||
|
// Save PUCCH resource only if periodic type
|
||||||
|
if (cfg->type == SRSLTE_CSI_REPORT_TYPE_PERIODIC) {
|
||||||
|
report_cfg->pucch_resource = cfg->periodic.resource;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fill quantified values
|
||||||
|
report_value->wideband_cri_ri_pmi_cqi.cqi = csi_snri_db_to_cqi(cfg->cqi_table, wideband_sinr_db);
|
||||||
|
report_value->wideband_cri_ri_pmi_cqi.ri = 0;
|
||||||
|
report_value->wideband_cri_ri_pmi_cqi.pmi = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint32_t csi_wideband_cri_ri_pmi_cqi_nof_bits(const srslte_csi_report_cfg_t* cfg)
|
||||||
|
{
|
||||||
|
// Compute number of bits for CRI
|
||||||
|
uint32_t nof_bits_cri = 0;
|
||||||
|
if (cfg->K_csi_rs > 0) {
|
||||||
|
nof_bits_cri = (uint32_t)ceilf(log2f((float)cfg->K_csi_rs));
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (cfg->nof_ports) {
|
||||||
|
case 1:
|
||||||
|
return CSI_WIDEBAND_CSI_NOF_BITS + nof_bits_cri;
|
||||||
|
default:
|
||||||
|
ERROR("Invalid or not implemented number of ports (%d)", cfg->nof_ports);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int csi_wideband_cri_ri_pmi_cqi_pack(const srslte_csi_report_cfg_t* cfg,
|
||||||
|
const srslte_csi_report_value_t* value,
|
||||||
|
uint8_t* o_csi1)
|
||||||
|
{
|
||||||
|
// Compute number of bits for CRI
|
||||||
|
uint32_t nof_bits_cri = 0;
|
||||||
|
if (cfg->K_csi_rs > 0) {
|
||||||
|
nof_bits_cri = (uint32_t)ceilf(log2f((float)cfg->K_csi_rs));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Write wideband CQI
|
||||||
|
srslte_bit_unpack(value->wideband_cri_ri_pmi_cqi.cqi, &o_csi1, CSI_WIDEBAND_CSI_NOF_BITS);
|
||||||
|
|
||||||
|
// Compute number of bits for CRI and write
|
||||||
|
srslte_bit_unpack(value->cri, &o_csi1, nof_bits_cri);
|
||||||
|
|
||||||
|
return nof_bits_cri + CSI_WIDEBAND_CSI_NOF_BITS;
|
||||||
|
}
|
||||||
|
|
||||||
|
int srslte_csi_generate_reports(const srslte_csi_hl_cfg_t* cfg,
|
||||||
|
uint32_t slot_idx,
|
||||||
|
const srslte_csi_measurements_t measurements[SRSLTE_CSI_MAX_NOF_RESOURCES],
|
||||||
|
srslte_csi_report_cfg_t report_cfg[SRSLTE_CSI_MAX_NOF_REPORT],
|
||||||
|
srslte_csi_report_value_t report_value[SRSLTE_CSI_MAX_NOF_REPORT])
|
||||||
|
{
|
||||||
|
uint32_t count = 0;
|
||||||
|
|
||||||
|
// Check inputs
|
||||||
|
if (cfg == NULL || measurements == NULL || report_cfg == NULL || report_value == NULL) {
|
||||||
|
return SRSLTE_ERROR_INVALID_INPUTS;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Iterate every possible configured CSI report
|
||||||
|
for (uint32_t i = 0; i < SRSLTE_CSI_MAX_NOF_REPORT; i++) {
|
||||||
|
// Skip if report is not configured or triggered
|
||||||
|
if (!csi_report_trigger(&cfg->reports[i], slot_idx)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Select channel measurement
|
||||||
|
if (cfg->reports->channel_meas_id >= SRSLTE_CSI_MAX_NOF_RESOURCES) {
|
||||||
|
ERROR("Channel measurement ID (%d) is out of range", cfg->reports->channel_meas_id);
|
||||||
|
return SRSLTE_ERROR;
|
||||||
|
}
|
||||||
|
const srslte_csi_measurements_t* channel_meas = &measurements[cfg->reports->channel_meas_id];
|
||||||
|
|
||||||
|
// Select interference measurement
|
||||||
|
const srslte_csi_measurements_t* interf_meas = NULL;
|
||||||
|
if (cfg->reports->interf_meas_present) {
|
||||||
|
if (cfg->reports->interf_meas_id >= SRSLTE_CSI_MAX_NOF_RESOURCES) {
|
||||||
|
ERROR("Interference measurement ID (%d) is out of range", cfg->reports->interf_meas_id);
|
||||||
|
return SRSLTE_ERROR;
|
||||||
|
}
|
||||||
|
interf_meas = &measurements[cfg->reports->interf_meas_id];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Quantify measurements according to frequency and quantity configuration
|
||||||
|
if (cfg->reports->freq_cfg == SRSLTE_CSI_REPORT_FREQ_WIDEBAND &&
|
||||||
|
cfg->reports->quantity == SRSLTE_CSI_REPORT_QUANTITY_CRI_RI_PMI_CQI) {
|
||||||
|
csi_wideband_cri_ri_pmi_cqi_quantify(
|
||||||
|
&cfg->reports[i], channel_meas, interf_meas, &report_cfg[count], &report_value[count]);
|
||||||
|
count++;
|
||||||
|
} else {
|
||||||
|
; // Ignore other types
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return (int)count;
|
||||||
|
}
|
||||||
|
|
||||||
|
int srslte_csi_nof_bits(const srslte_csi_report_cfg_t* report_list, uint32_t nof_reports)
|
||||||
|
{
|
||||||
|
uint32_t count = 0;
|
||||||
|
|
||||||
|
// Check input pointer
|
||||||
|
if (report_list == NULL) {
|
||||||
|
return SRSLTE_ERROR_INVALID_INPUTS;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Iterate all report configurations
|
||||||
|
for (uint32_t i = 0; i < nof_reports; i++) {
|
||||||
|
const srslte_csi_report_cfg_t* report = &report_list[i];
|
||||||
|
if (report->quantity && report->quantity == SRSLTE_CSI_REPORT_QUANTITY_CRI_RI_PMI_CQI) {
|
||||||
|
count += csi_wideband_cri_ri_pmi_cqi_nof_bits(report);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return (int)count;
|
||||||
|
}
|
||||||
|
|
||||||
|
int srslte_csi_part1_pack(const srslte_csi_report_cfg_t* report_cfg,
|
||||||
|
const srslte_csi_report_value_t* report_value,
|
||||||
|
uint32_t nof_reports,
|
||||||
|
uint8_t* o_csi1,
|
||||||
|
uint32_t max_o_csi1)
|
||||||
|
{
|
||||||
|
uint32_t count = 0;
|
||||||
|
|
||||||
|
if (report_cfg == NULL || report_value == NULL || o_csi1 == NULL) {
|
||||||
|
return SRSLTE_ERROR_INVALID_INPUTS;
|
||||||
|
}
|
||||||
|
|
||||||
|
int n = srslte_csi_nof_bits(report_cfg, nof_reports);
|
||||||
|
if (n > (int)max_o_csi1) {
|
||||||
|
ERROR("The maximum number of CSI bits (%d) is not enough to accommodate %d bits", max_o_csi1, n);
|
||||||
|
return SRSLTE_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (uint32_t i = 0; i < nof_reports && count < max_o_csi1; i++) {
|
||||||
|
if (report_cfg[i].freq_cfg == SRSLTE_CSI_REPORT_FREQ_WIDEBAND &&
|
||||||
|
report_cfg[i].quantity == SRSLTE_CSI_REPORT_QUANTITY_CRI_RI_PMI_CQI) {
|
||||||
|
count += csi_wideband_cri_ri_pmi_cqi_pack(&report_cfg[i], &report_value[i], &o_csi1[count]);
|
||||||
|
} else {
|
||||||
|
ERROR("CSI frequency (%d) and quantity (%d) combination is not implemented",
|
||||||
|
report_cfg[i].freq_cfg,
|
||||||
|
report_cfg[i].quantity);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return (int)count;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t srslte_csi_str(const srslte_csi_report_cfg_t* report_cfg,
|
||||||
|
const srslte_csi_report_value_t* report_value,
|
||||||
|
uint32_t nof_reports,
|
||||||
|
char* str,
|
||||||
|
uint32_t str_len)
|
||||||
|
{
|
||||||
|
uint32_t len = 0;
|
||||||
|
for (uint32_t i = 0; i < nof_reports; i++) {
|
||||||
|
if (report_cfg[i].freq_cfg == SRSLTE_CSI_REPORT_FREQ_WIDEBAND &&
|
||||||
|
report_cfg[i].quantity == SRSLTE_CSI_REPORT_QUANTITY_CRI_RI_PMI_CQI) {
|
||||||
|
len = srslte_print_check(str, str_len, len, ", cqi=%d", report_value[i].wideband_cri_ri_pmi_cqi.cqi);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return len;
|
||||||
|
}
|
@ -0,0 +1,15 @@
|
|||||||
|
#
|
||||||
|
# Copyright 2013-2021 Software Radio Systems Limited
|
||||||
|
#
|
||||||
|
# By using this file, you agree to the terms and conditions set
|
||||||
|
# forth in the LICENSE file which can be found at the top level of
|
||||||
|
# the distribution.
|
||||||
|
#
|
||||||
|
|
||||||
|
set(SOURCES
|
||||||
|
sys_metrics_processor.cc)
|
||||||
|
|
||||||
|
find_package(Threads REQUIRED)
|
||||||
|
|
||||||
|
add_library(system STATIC ${SOURCES})
|
||||||
|
target_link_libraries(system "${CMAKE_THREAD_LIBS_INIT}")
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue