diff --git a/lib/include/srslte/common/common.h b/lib/include/srslte/common/common.h index 5f13ab214..ad88d9dcc 100644 --- a/lib/include/srslte/common/common.h +++ b/lib/include/srslte/common/common.h @@ -83,32 +83,6 @@ static const char error_text[ERROR_N_ITEMS][20] = { "None", "Can't start", "Already started"}; -typedef enum{ - RB_ID_SRB0 = 0, - RB_ID_SRB1, - RB_ID_SRB2, - RB_ID_DRB1, - RB_ID_DRB2, - RB_ID_DRB3, - RB_ID_DRB4, - RB_ID_DRB5, - RB_ID_DRB6, - RB_ID_DRB7, - RB_ID_DRB8, - RB_ID_N_ITEMS, -}rb_id_t; -static const char rb_id_text[RB_ID_N_ITEMS][20] = { "SRB0", - "SRB1", - "SRB2", - "DRB1", - "DRB2", - "DRB3", - "DRB4", - "DRB5", - "DRB6", - "DRB7", - "DRB8"}; - /****************************************************************************** * Byte and Bit buffers * diff --git a/lib/include/srslte/common/interfaces_common.h b/lib/include/srslte/common/interfaces_common.h index 76025a64f..d919d9fe5 100644 --- a/lib/include/srslte/common/interfaces_common.h +++ b/lib/include/srslte/common/interfaces_common.h @@ -28,9 +28,43 @@ #define INTERFACE_COMMON_H #include "srslte/common/timers.h" +#include "srslte/common/security.h" +#include "srslte/asn1/liblte_rrc.h" + namespace srslte { +class srslte_nas_config_t +{ +public: + srslte_nas_config_t(uint32_t lcid_ = 0) + :lcid(lcid_) + {} + + uint32_t lcid; +}; + + +class srslte_pdcp_config_t +{ +public: + srslte_pdcp_config_t(bool is_control_ = false, bool is_data_ = false, uint8_t direction_ = SECURITY_DIRECTION_UPLINK) + :direction(direction_) + ,is_control(is_control_) + ,is_data(is_data_) + ,do_security(false) + ,sn_len(12) {} + + uint8_t direction; + bool is_control; + bool is_data; + bool do_security; + uint8_t sn_len; + + // TODO: Support the following configurations + // bool do_rohc; +}; + class mac_interface_timers { public: diff --git a/lib/include/srslte/common/timers.h b/lib/include/srslte/common/timers.h index 56e40e152..377df7b1d 100644 --- a/lib/include/srslte/common/timers.h +++ b/lib/include/srslte/common/timers.h @@ -97,11 +97,13 @@ public: bool running; }; - timers(uint32_t nof_timers_) : timer_list(nof_timers_) { + timers(uint32_t nof_timers_) : timer_list(nof_timers_),used_timers(nof_timers_) { nof_timers = nof_timers_; next_timer = 0; + nof_used_timers = 0; for (uint32_t i=0;i 0 && i < nof_timers) { + used_timers[i] = false; + nof_used_timers--; + } else { + fprintf(stderr, "Error releasing timer: nof_used_timers=%d, nof_timers=%d\n", nof_used_timers, nof_timers); + } + } uint32_t get_unique_id() { - if (next_timer == nof_timers){ - printf("No more unique timer ids (Only %d timers available)\n", nof_timers); - next_timer = 0; + if (nof_used_timers >= nof_timers) { + fprintf(stderr, "Error getting uinque timer id: no more timers available\n"); + return 0; + } else { + while(used_timers[next_timer]) { + next_timer++; + if (next_timer >= nof_timers) { + next_timer=0; + } + } + used_timers[next_timer] = true; + nof_used_timers++; + return next_timer; } - return next_timer++; } private: - uint32_t nof_timers; uint32_t next_timer; - std::vector timer_list; + uint32_t nof_used_timers; + uint32_t nof_timers; + std::vector timer_list; + std::vector used_timers; }; } // namespace srslte diff --git a/lib/include/srslte/interfaces/enb_interfaces.h b/lib/include/srslte/interfaces/enb_interfaces.h index 8806ded58..ed2478896 100644 --- a/lib/include/srslte/interfaces/enb_interfaces.h +++ b/lib/include/srslte/interfaces/enb_interfaces.h @@ -28,7 +28,9 @@ #include "srslte/common/common.h" #include "srslte/common/security.h" +#include "srslte/common/interfaces_common.h" #include "srslte/interfaces/sched_interface.h" +#include "srslte/upper/rlc_interface.h" #include "srslte/asn1/liblte_rrc.h" #include "srslte/asn1/liblte_s1ap.h" @@ -156,7 +158,7 @@ public: virtual void add_user(uint16_t rnti) = 0; virtual void rem_user(uint16_t rnti) = 0; virtual void add_bearer(uint16_t rnti, uint32_t lcid) = 0; - virtual void add_bearer(uint16_t rnti, uint32_t lcid, LIBLTE_RRC_RLC_CONFIG_STRUCT *cnfg) = 0; + virtual void add_bearer(uint16_t rnti, uint32_t lcid, srslte::srslte_rlc_config_t cnfg) = 0; }; // PDCP interface for GTPU @@ -174,7 +176,7 @@ public: virtual void add_user(uint16_t rnti) = 0; virtual void rem_user(uint16_t rnti) = 0; virtual void write_sdu(uint16_t rnti, uint32_t lcid, srslte::byte_buffer_t *sdu) = 0; - virtual void add_bearer(uint16_t rnti, uint32_t lcid, LIBLTE_RRC_PDCP_CONFIG_STRUCT *cnfg=NULL) = 0; + virtual void add_bearer(uint16_t rnti, uint32_t lcid, srslte::srslte_pdcp_config_t cnfg) = 0; virtual void config_security(uint16_t rnti, uint32_t lcid, uint8_t *k_rrc_enc_, diff --git a/lib/include/srslte/interfaces/sched_interface.h b/lib/include/srslte/interfaces/sched_interface.h index 63ab92121..a717b4293 100644 --- a/lib/include/srslte/interfaces/sched_interface.h +++ b/lib/include/srslte/interfaces/sched_interface.h @@ -94,7 +94,8 @@ public: typedef struct { int priority; int bsd; - int pbr; + int pbr; + int group; enum {IDLE = 0, UL, DL, BOTH} direction; } ue_bearer_cfg_t; @@ -231,7 +232,7 @@ public: /* UL information */ virtual int ul_crc_info(uint32_t tti, uint16_t rnti, bool crc) = 0; virtual int ul_sr_info(uint32_t tti, uint16_t rnti) = 0; - virtual int ul_bsr(uint16_t rnti, uint32_t lcid, uint32_t bsr) = 0; + virtual int ul_bsr(uint16_t rnti, uint32_t lcid, uint32_t bsr, bool set_value = true) = 0; virtual int ul_recv_len(uint16_t rnti, uint32_t lcid, uint32_t len) = 0; virtual int ul_phr(uint16_t rnti, int phr) = 0; virtual int ul_cqi_info(uint32_t tti, uint16_t rnti, uint32_t cqi, uint32_t ul_ch_code) = 0; diff --git a/lib/include/srslte/interfaces/ue_interfaces.h b/lib/include/srslte/interfaces/ue_interfaces.h index 62b2a7ef7..81ed67b74 100644 --- a/lib/include/srslte/interfaces/ue_interfaces.h +++ b/lib/include/srslte/interfaces/ue_interfaces.h @@ -39,6 +39,7 @@ #include "srslte/common/interfaces_common.h" #include "srslte/common/common.h" #include "srslte/common/security.h" +#include "srslte/upper/rlc_interface.h" namespace srsue { @@ -104,11 +105,16 @@ public: }; // RRC interface for MAC -class rrc_interface_mac +class rrc_interface_mac_common +{ +public: + virtual void ra_problem() = 0; +}; + +class rrc_interface_mac : public rrc_interface_mac_common { public: virtual void release_pucch_srs() = 0; - virtual void ra_problem() = 0; }; // RRC interface for PHY @@ -127,6 +133,7 @@ public: virtual uint16_t get_mcc() = 0; virtual uint16_t get_mnc() = 0; virtual void enable_capabilities() = 0; + virtual std::string get_rb_name(uint32_t lcid) = 0; }; // RRC interface for GW @@ -146,6 +153,7 @@ public: virtual void write_pdu_bcch_bch(srslte::byte_buffer_t *pdu) = 0; virtual void write_pdu_bcch_dlsch(srslte::byte_buffer_t *pdu) = 0; virtual void write_pdu_pcch(srslte::byte_buffer_t *pdu) = 0; + virtual std::string get_rb_name(uint32_t lcid) = 0; }; // RRC interface for RLC @@ -153,6 +161,7 @@ class rrc_interface_rlc { public: virtual void max_retx_attempted() = 0; + virtual std::string get_rb_name(uint32_t lcid) = 0; }; // PDCP interface for GW @@ -168,7 +177,7 @@ class pdcp_interface_rrc public: virtual void reset() = 0; virtual void write_sdu(uint32_t lcid, srslte::byte_buffer_t *sdu) = 0; - virtual void add_bearer(uint32_t lcid, LIBLTE_RRC_PDCP_CONFIG_STRUCT *cnfg=NULL) = 0; + virtual void add_bearer(uint32_t lcid, srslte::srslte_pdcp_config_t cnfg = srslte::srslte_pdcp_config_t()) = 0; virtual void config_security(uint32_t lcid, uint8_t *k_rrc_enc_, uint8_t *k_rrc_int_, @@ -193,7 +202,7 @@ class rlc_interface_rrc public: virtual void reset() = 0; virtual void add_bearer(uint32_t lcid) = 0; - virtual void add_bearer(uint32_t lcid, LIBLTE_RRC_RLC_CONFIG_STRUCT *cnfg) = 0; + virtual void add_bearer(uint32_t lcid, srslte::srslte_rlc_config_t cnfg) = 0; }; // RLC interface for PDCP @@ -230,6 +239,31 @@ public: }; +//BSR interface for MUX +class bsr_interface_mux +{ +public: + typedef enum { + LONG_BSR, + SHORT_BSR, + TRUNC_BSR + } bsr_format_t; + + typedef struct { + bsr_format_t format; + uint32_t buff_size[4]; + } bsr_t; + + /* MUX calls BSR to check if it can fit a BSR into PDU */ + virtual bool need_to_send_bsr_on_ul_grant(uint32_t grant_size, bsr_t *bsr) = 0; + + /* MUX calls BSR to let it generate a padding BSR if there is space in PDU */ + virtual bool generate_padding_bsr(uint32_t nof_padding_bytes, bsr_t *bsr) = 0; + + /* MAX calls BSR to set the Tx TTI */ + virtual void set_tx_tti(uint32_t tti) = 0; +}; + /** MAC interface * @@ -275,6 +309,7 @@ public: uint32_t rv; uint16_t rnti; uint32_t current_tx_nb; + int32_t tti_offset; // relative offset between grant and UL tx/HARQ rx srslte_softbuffer_tx_t *softbuffer; srslte_phy_grant_t phy_grant; uint8_t *payload_ptr; @@ -309,9 +344,27 @@ public: }; +/* Interface RRC -> MAC shared between different RATs */ +class mac_interface_rrc_common +{ +public: + // Class to handle UE specific RNTIs between RRC and MAC + typedef struct { + uint16_t crnti; + uint16_t temp_rnti; + uint16_t tpc_rnti; + uint16_t sps_rnti; + uint64_t contention_id; + } ue_rnti_t; + + typedef struct { + uint32_t max_harq_msg3_tx; + uint32_t max_harq_tx; + } ul_harq_params_t; +}; /* Interface RRC -> MAC */ -class mac_interface_rrc +class mac_interface_rrc : public mac_interface_rrc_common { public: @@ -319,19 +372,10 @@ public: LIBLTE_RRC_MAC_MAIN_CONFIG_STRUCT main; LIBLTE_RRC_RACH_CONFIG_COMMON_STRUCT rach; LIBLTE_RRC_SCHEDULING_REQUEST_CONFIG_STRUCT sr; + ul_harq_params_t ul_harq_params; uint32_t prach_config_index; } mac_cfg_t; - - // Class to handle UE specific RNTIs between RRC and MAC - typedef struct { - uint16_t crnti; - uint16_t temp_rnti; - uint16_t tpc_rnti; - uint16_t sps_rnti; - uint64_t contention_id; - } ue_rnti_t; - /* Instructs the MAC to start receiving BCCH */ virtual void bcch_start_rx() = 0; virtual void bcch_stop_rx() = 0; @@ -391,46 +435,51 @@ typedef struct { float estimator_fil_w; bool rssi_sensor_enabled; } phy_args_t; - -/* Interface MAC -> PHY */ -class phy_interface_mac + + +/* RAT agnostic Interface MAC -> PHY */ +class phy_interface_mac_common { public: - /* Configure PRACH using parameters written by RRC */ - virtual void configure_prach_params() = 0; - /* Start synchronization with strongest cell in the current carrier frequency */ - virtual void sync_start() = 0; + virtual void sync_start() = 0; virtual void sync_stop() = 0; - + /* Sets a C-RNTI allowing the PHY to pregenerate signals if necessary */ - virtual void set_crnti(uint16_t rnti) = 0; - + virtual void set_crnti(uint16_t rnti) = 0; + + /* Time advance commands */ + virtual void set_timeadv_rar(uint32_t ta_cmd) = 0; + virtual void set_timeadv(uint32_t ta_cmd) = 0; + + /* Sets RAR grant payload */ + virtual void set_rar_grant(uint32_t tti, uint8_t grant_payload[SRSLTE_RAR_GRANT_LEN]) = 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 : public phy_interface_mac_common +{ +public: + /* Configure PRACH using parameters written by RRC */ + virtual void configure_prach_params() = 0; + virtual void prach_send(uint32_t preamble_idx, int allowed_subframe, float target_power_dbm) = 0; virtual int prach_tx_tti() = 0; /* Indicates the transmission of a SR signal in the next opportunity */ virtual void sr_send() = 0; virtual int sr_last_tx_tti() = 0; - - /* Time advance commands */ - virtual void set_timeadv_rar(uint32_t ta_cmd) = 0; - virtual void set_timeadv(uint32_t ta_cmd) = 0; - - /* Sets RAR grant payload */ - virtual void set_rar_grant(uint32_t tti, uint8_t grant_payload[SRSLTE_RAR_GRANT_LEN]) = 0; /* Instruct the PHY to decode PDCCH with the CRC scrambled with given RNTI */ virtual void pdcch_ul_search(srslte_rnti_type_t rnti_type, uint16_t rnti, int tti_start = -1, int tti_end = -1) = 0; virtual void pdcch_dl_search(srslte_rnti_type_t rnti_type, uint16_t rnti, int tti_start = -1, int tti_end = -1) = 0; virtual void pdcch_ul_search_reset() = 0; virtual void pdcch_dl_search_reset() = 0; - - virtual uint32_t get_current_tti() = 0; - - virtual float get_phr() = 0; - virtual float get_pathloss_db() = 0; - }; class phy_interface_rrc diff --git a/lib/include/srslte/phy/common/phy_common.h b/lib/include/srslte/phy/common/phy_common.h index efd498c86..65dc2319c 100644 --- a/lib/include/srslte/phy/common/phy_common.h +++ b/lib/include/srslte/phy/common/phy_common.h @@ -242,6 +242,9 @@ SRSLTE_API uint32_t srslte_N_ta_new_rar(uint32_t ta); SRSLTE_API uint32_t srslte_N_ta_new(uint32_t N_ta_old, uint32_t ta); +SRSLTE_API float srslte_coderate(uint32_t tbs, + uint32_t nof_re); + SRSLTE_API char *srslte_cp_string(srslte_cp_t cp); SRSLTE_API char *srslte_mod_string(srslte_mod_t mod); diff --git a/lib/include/srslte/phy/fec/turbodecoder_simd.h b/lib/include/srslte/phy/fec/turbodecoder_simd.h index 7ca3914ca..d7bc284d2 100644 --- a/lib/include/srslte/phy/fec/turbodecoder_simd.h +++ b/lib/include/srslte/phy/fec/turbodecoder_simd.h @@ -48,13 +48,13 @@ // The constant SRSLTE_TDEC_NPAR defines the maximum number of parallel CB supported by all SIMD decoders #ifdef ENABLE_SIMD_INTER #include "srslte/phy/fec/turbodecoder_simd_inter.h" - #if LV_HAVE_AVX2 + #ifdef LV_HAVE_AVX2 #define SRSLTE_TDEC_NPAR_INTRA 2 #else #define SRSLTE_TDEC_NPAR_INTRA 1 #endif #else - #if LV_HAVE_AVX2 + #ifdef LV_HAVE_AVX2 #define SRSLTE_TDEC_NPAR 2 #else #define SRSLTE_TDEC_NPAR 1 diff --git a/lib/include/srslte/phy/phch/pdsch.h b/lib/include/srslte/phy/phch/pdsch.h index ad01c4ef8..a73129444 100644 --- a/lib/include/srslte/phy/phch/pdsch.h +++ b/lib/include/srslte/phy/phch/pdsch.h @@ -93,10 +93,7 @@ SRSLTE_API int srslte_pdsch_set_rnti(srslte_pdsch_t *q, SRSLTE_API void srslte_pdsch_free_rnti(srslte_pdsch_t *q, uint16_t rnti); -SRSLTE_API float srslte_pdsch_coderate(uint32_t tbs, - uint32_t nof_re); - -SRSLTE_API int srslte_pdsch_cfg(srslte_pdsch_cfg_t *cfg, +SRSLTE_API int srslte_pdsch_cfg(srslte_pdsch_cfg_t *cfg, srslte_cell_t cell, srslte_ra_dl_grant_t *grant, uint32_t cfi, diff --git a/lib/include/srslte/phy/phch/pucch.h b/lib/include/srslte/phy/phch/pucch.h index 56d512418..da0b5b81e 100644 --- a/lib/include/srslte/phy/phch/pucch.h +++ b/lib/include/srslte/phy/phch/pucch.h @@ -108,7 +108,6 @@ typedef struct SRSLTE_API { bool group_hopping_en; float threshold_format1; - float threshold_format1a; float last_corr; uint32_t last_n_prb; uint32_t last_n_pucch; @@ -125,9 +124,8 @@ SRSLTE_API bool srslte_pucch_set_cfg(srslte_pucch_t* q, srslte_pucch_cfg_t* cfg, bool group_hopping_en); -SRSLTE_API void srslte_pucch_set_threshold(srslte_pucch_t *q, - float format1, - float format1a); +SRSLTE_API void srslte_pucch_set_threshold(srslte_pucch_t *q, + float format1_threshold); SRSLTE_API int srslte_pucch_set_crnti(srslte_pucch_t *q, uint16_t c_rnti); diff --git a/lib/include/srslte/phy/utils/vector.h b/lib/include/srslte/phy/utils/vector.h index 74cd60172..d203ff390 100644 --- a/lib/include/srslte/phy/utils/vector.h +++ b/lib/include/srslte/phy/utils/vector.h @@ -152,6 +152,9 @@ SRSLTE_API void srslte_vec_conj_cc(cf_t *x, cf_t *y, uint32_t len); /* average vector power */ SRSLTE_API float srslte_vec_avg_power_cf(cf_t *x, uint32_t len); +/* Correlation between complex vectors x and y */ +SRSLTE_API float srslte_vec_corr_ccc(cf_t *x, cf_t *y, uint32_t len); + /* return the index of the maximum value in the vector */ SRSLTE_API uint32_t srslte_vec_max_fi(float *x, uint32_t len); SRSLTE_API uint32_t srslte_vec_max_abs_ci(cf_t *x, uint32_t len); diff --git a/lib/include/srslte/upper/gw.h b/lib/include/srslte/upper/gw.h index a01413829..ce5936b71 100644 --- a/lib/include/srslte/upper/gw.h +++ b/lib/include/srslte/upper/gw.h @@ -46,7 +46,7 @@ class gw { public: gw(); - void init(srsue::pdcp_interface_gw *pdcp_, srsue::rrc_interface_gw *rrc_, srsue::ue_interface *ue_, log *gw_log_); + void init(srsue::pdcp_interface_gw *pdcp_, srsue::rrc_interface_gw *rrc_, srsue::ue_interface *ue_, log *gw_log_, uint32_t lcid_); void stop(); void get_metrics(gw_metrics_t &m); @@ -56,11 +56,11 @@ public: // NAS interface error_t setup_if_addr(uint32_t ip_addr, char *err_str); - + private: - - static const int GW_THREAD_PRIO = 7; - + + static const int GW_THREAD_PRIO = 7; + srsue::pdcp_interface_gw *pdcp; srsue::rrc_interface_gw *rrc; srsue::ue_interface *ue; @@ -73,6 +73,7 @@ private: struct ifreq ifr; int32 sock; bool if_up; + uint32_t lcid; long ul_tput_bytes; long dl_tput_bytes; diff --git a/lib/include/srslte/upper/pdcp.h b/lib/include/srslte/upper/pdcp.h index 857806810..abdbeeaea 100644 --- a/lib/include/srslte/upper/pdcp.h +++ b/lib/include/srslte/upper/pdcp.h @@ -46,13 +46,14 @@ public: srsue::rrc_interface_pdcp *rrc_, srsue::gw_interface_pdcp *gw_, log *pdcp_log_, + uint32_t lcid_, uint8_t direction_); void stop(); // RRC interface void reset(); void write_sdu(uint32_t lcid, byte_buffer_t *sdu); - void add_bearer(uint32_t lcid, LIBLTE_RRC_PDCP_CONFIG_STRUCT *cnfg = NULL); + void add_bearer(uint32_t lcid, srslte_pdcp_config_t cnfg = srslte_pdcp_config_t()); void config_security(uint32_t lcid, uint8_t *k_rrc_enc, uint8_t *k_rrc_int, @@ -72,6 +73,7 @@ private: log *pdcp_log; pdcp_entity pdcp_array[SRSLTE_N_RADIO_BEARERS]; + uint32_t lcid; // default LCID that is maintained active by PDCP instance uint8_t direction; bool valid_lcid(uint32_t lcid); diff --git a/lib/include/srslte/upper/pdcp_entity.h b/lib/include/srslte/upper/pdcp_entity.h index 2c1c988a0..0ff005d07 100644 --- a/lib/include/srslte/upper/pdcp_entity.h +++ b/lib/include/srslte/upper/pdcp_entity.h @@ -67,9 +67,7 @@ public: srsue::gw_interface_pdcp *gw_, srslte::log *log_, uint32_t lcid_, - uint8_t direction_, - LIBLTE_RRC_PDCP_CONFIG_STRUCT *cnfg = NULL - ); + srslte_pdcp_config_t cfg_); void reset(); bool is_active(); @@ -94,12 +92,7 @@ private: bool active; uint32_t lcid; - bool do_security; - u_int8_t direction; - - uint8_t sn_len; - // TODO: Support the following configurations - // bool do_rohc; + srslte_pdcp_config_t cfg; uint32_t rx_count; uint32_t tx_count; diff --git a/lib/include/srslte/upper/rlc.h b/lib/include/srslte/upper/rlc.h index 9d7f7ff39..349a7952d 100644 --- a/lib/include/srslte/upper/rlc.h +++ b/lib/include/srslte/upper/rlc.h @@ -34,6 +34,7 @@ #include "srslte/common/msg_queue.h" #include "srslte/upper/rlc_entity.h" #include "srslte/upper/rlc_metrics.h" +#include "srslte/upper/rlc_common.h" namespace srslte { @@ -55,13 +56,15 @@ public: srsue::rrc_interface_rlc *rrc_, srsue::ue_interface *ue_, log *rlc_log_, - mac_interface_timers *mac_timers_); + mac_interface_timers *mac_timers_, + uint32_t lcid_); void stop(); void get_metrics(rlc_metrics_t &m); // PDCP interface void write_sdu(uint32_t lcid, byte_buffer_t *sdu); + std::string get_rb_name(uint32_t lcid); // MAC interface uint32_t get_buffer_state(uint32_t lcid); @@ -74,8 +77,9 @@ public: // RRC interface void reset(); + void empty_queue(); void add_bearer(uint32_t lcid); - void add_bearer(uint32_t lcid, LIBLTE_RRC_RLC_CONFIG_STRUCT *cnfg); + void add_bearer(uint32_t lcid, srslte_rlc_config_t cnfg); private: void reset_metrics(); @@ -87,6 +91,7 @@ private: srslte::mac_interface_timers *mac_timers; srsue::ue_interface *ue; srslte::rlc_entity rlc_array[SRSLTE_N_RADIO_BEARERS]; + uint32_t default_lcid; long ul_tput_bytes[SRSLTE_N_RADIO_BEARERS]; long dl_tput_bytes[SRSLTE_N_RADIO_BEARERS]; diff --git a/lib/include/srslte/upper/rlc_am.h b/lib/include/srslte/upper/rlc_am.h index 5fcf31c94..a92c9a0ad 100644 --- a/lib/include/srslte/upper/rlc_am.h +++ b/lib/include/srslte/upper/rlc_am.h @@ -76,7 +76,7 @@ public: srsue::pdcp_interface_rlc *pdcp_, srsue::rrc_interface_rlc *rrc_, mac_interface_timers *mac_timers); - void configure(LIBLTE_RRC_RLC_CONFIG_STRUCT *cnfg); + void configure(srslte_rlc_config_t cnfg); void reset(); void empty_queue(); @@ -128,15 +128,7 @@ private: * Ref: 3GPP TS 36.322 v10.0.0 Section 7 ***************************************************************************/ - // TX configs - int32_t t_poll_retx; // Poll retx timeout (ms) - int32_t poll_pdu; // Insert poll bit after this many PDUs - int32_t poll_byte; // Insert poll bit after this much data (KB) - uint32_t max_retx_thresh; // Max number of retx - - // RX configs - int32_t t_reordering; // Timer used by rx to detect PDU loss (ms) - int32_t t_status_prohibit; // Timer used by rx to prohibit tx of status PDU (ms) + srslte_rlc_am_config_t cfg; /**************************************************************************** * State variables and counters diff --git a/lib/include/srslte/upper/rlc_common.h b/lib/include/srslte/upper/rlc_common.h index 0c545b60f..c68e3e6f3 100644 --- a/lib/include/srslte/upper/rlc_common.h +++ b/lib/include/srslte/upper/rlc_common.h @@ -27,6 +27,8 @@ #ifndef RLC_COMMON_H #define RLC_COMMON_H +#include "srslte/upper/rlc_interface.h" + namespace srslte { /**************************************************************************** @@ -66,14 +68,6 @@ typedef enum{ static const char rlc_dc_field_text[RLC_DC_FIELD_N_ITEMS][20] = {"Control PDU", "Data PDU"}; -typedef enum{ - RLC_UMD_SN_SIZE_5_BITS = 0, - RLC_UMD_SN_SIZE_10_BITS, - RLC_UMD_SN_SIZE_N_ITEMS, -}rlc_umd_sn_size_t; -static const char rlc_umd_sn_size_text[RLC_UMD_SN_SIZE_N_ITEMS][20] = {"5 bits", "10 bits"}; -static const uint16_t rlc_umd_sn_size_num[RLC_UMD_SN_SIZE_N_ITEMS] = {5, 10}; - // UMD PDU Header typedef struct{ uint8_t fi; // Framing info @@ -162,7 +156,7 @@ public: srsue::pdcp_interface_rlc *pdcp_, srsue::rrc_interface_rlc *rrc_, srslte::mac_interface_timers *mac_timers_) = 0; - virtual void configure(LIBLTE_RRC_RLC_CONFIG_STRUCT *cnfg) = 0; + virtual void configure(srslte_rlc_config_t cnfg) = 0; virtual void reset() = 0; virtual void empty_queue() = 0; diff --git a/lib/include/srslte/upper/rlc_entity.h b/lib/include/srslte/upper/rlc_entity.h index cf09c19d2..651af72fb 100644 --- a/lib/include/srslte/upper/rlc_entity.h +++ b/lib/include/srslte/upper/rlc_entity.h @@ -54,8 +54,9 @@ public: srsue::rrc_interface_rlc *rrc_, mac_interface_timers *mac_timers_); - void configure(LIBLTE_RRC_RLC_CONFIG_STRUCT *cnfg); + void configure(srslte_rlc_config_t cnfg); void reset(); + void empty_queue(); bool active(); rlc_mode_t get_mode(); diff --git a/lib/include/srslte/upper/rlc_interface.h b/lib/include/srslte/upper/rlc_interface.h new file mode 100644 index 000000000..feddac1cc --- /dev/null +++ b/lib/include/srslte/upper/rlc_interface.h @@ -0,0 +1,126 @@ +/** + * + * \section COPYRIGHT + * + * Copyright 2013-2015 Software Radio Systems Limited + * + * \section LICENSE + * + * This file is part of the srsUE library. + * + * srsUE 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. + * + * srsUE 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/. + * + */ + +#ifndef RLC_INTERFACE_H +#define RLC_INTERFACE_H + +// for custom constructors +#include "srslte/asn1/liblte_rrc.h" + +namespace srslte { + + +typedef enum{ + RLC_UMD_SN_SIZE_5_BITS = 0, + RLC_UMD_SN_SIZE_10_BITS, + RLC_UMD_SN_SIZE_N_ITEMS, +}rlc_umd_sn_size_t; +static const char rlc_umd_sn_size_text[RLC_UMD_SN_SIZE_N_ITEMS][20] = {"5 bits", "10 bits"}; +static const uint16_t rlc_umd_sn_size_num[RLC_UMD_SN_SIZE_N_ITEMS] = {5, 10}; + + +typedef struct { + /**************************************************************************** + * Configurable parameters + * Ref: 3GPP TS 36.322 v10.0.0 Section 7 + ***************************************************************************/ + + // TX configs + int32_t t_poll_retx; // Poll retx timeout (ms) + int32_t poll_pdu; // Insert poll bit after this many PDUs + int32_t poll_byte; // Insert poll bit after this much data (KB) + uint32_t max_retx_thresh; // Max number of retx + + // RX configs + int32_t t_reordering; // Timer used by rx to detect PDU loss (ms) + int32_t t_status_prohibit; // Timer used by rx to prohibit tx of status PDU (ms) +} srslte_rlc_am_config_t; + + +typedef struct { + /**************************************************************************** + * Configurable parameters + * Ref: 3GPP TS 36.322 v10.0.0 Section 7 + ***************************************************************************/ + + int32_t t_reordering; // Timer used by rx to detect PDU loss (ms) + rlc_umd_sn_size_t tx_sn_field_length; // Number of bits used for tx (UL) sequence number + rlc_umd_sn_size_t rx_sn_field_length; // Number of bits used for rx (DL) sequence number + + uint32_t rx_window_size; + uint32_t rx_mod; // Rx counter modulus + uint32_t tx_mod; // Tx counter modulus +} srslte_rlc_um_config_t; + + +class srslte_rlc_config_t +{ +public: + LIBLTE_RRC_RLC_MODE_ENUM rlc_mode; + srslte_rlc_am_config_t am; + srslte_rlc_um_config_t um; + + // Constructor based on liblte's RLC config + srslte_rlc_config_t(LIBLTE_RRC_RLC_CONFIG_STRUCT *cnfg) : rlc_mode(cnfg->rlc_mode), am(), um() + { + switch(rlc_mode) + { + case LIBLTE_RRC_RLC_MODE_AM: + am.t_poll_retx = liblte_rrc_t_poll_retransmit_num[cnfg->ul_am_rlc.t_poll_retx]; + am.poll_pdu = liblte_rrc_poll_pdu_num[cnfg->ul_am_rlc.poll_pdu]; + am.poll_byte = liblte_rrc_poll_byte_num[cnfg->ul_am_rlc.poll_byte]*1000; // KB + am.max_retx_thresh = liblte_rrc_max_retx_threshold_num[cnfg->ul_am_rlc.max_retx_thresh]; + am.t_reordering = liblte_rrc_t_reordering_num[cnfg->dl_am_rlc.t_reordering]; + am.t_status_prohibit = liblte_rrc_t_status_prohibit_num[cnfg->dl_am_rlc.t_status_prohibit]; + break; + case LIBLTE_RRC_RLC_MODE_UM_BI: + um.t_reordering = liblte_rrc_t_reordering_num[cnfg->dl_um_bi_rlc.t_reordering]; + um.rx_sn_field_length = (rlc_umd_sn_size_t)cnfg->dl_um_bi_rlc.sn_field_len; + um.rx_window_size = (RLC_UMD_SN_SIZE_5_BITS == um.rx_sn_field_length) ? 16 : 512; + um.rx_mod = (RLC_UMD_SN_SIZE_5_BITS == um.rx_sn_field_length) ? 32 : 1024; + um.tx_sn_field_length = (rlc_umd_sn_size_t)cnfg->ul_um_bi_rlc.sn_field_len; + um.tx_mod = (RLC_UMD_SN_SIZE_5_BITS == um.tx_sn_field_length) ? 32 : 1024; + break; + case LIBLTE_RRC_RLC_MODE_UM_UNI_UL: + um.tx_sn_field_length = (rlc_umd_sn_size_t)cnfg->ul_um_uni_rlc.sn_field_len; + um.tx_mod = (RLC_UMD_SN_SIZE_5_BITS == um.tx_sn_field_length) ? 32 : 1024; + break; + case LIBLTE_RRC_RLC_MODE_UM_UNI_DL: + um.t_reordering = liblte_rrc_t_reordering_num[cnfg->dl_um_uni_rlc.t_reordering]; + um.rx_sn_field_length = (rlc_umd_sn_size_t)cnfg->dl_um_uni_rlc.sn_field_len; + um.rx_window_size = (RLC_UMD_SN_SIZE_5_BITS == um.rx_sn_field_length) ? 16 : 512; + um.rx_mod = (RLC_UMD_SN_SIZE_5_BITS == um.rx_sn_field_length) ? 32 : 1024; + break; + default: + // Handle default case + break; + } + } +}; + +} // namespace srslte + +#endif // RLC_INTERFACE_H diff --git a/lib/include/srslte/upper/rlc_tm.h b/lib/include/srslte/upper/rlc_tm.h index d8034cd38..def968a92 100644 --- a/lib/include/srslte/upper/rlc_tm.h +++ b/lib/include/srslte/upper/rlc_tm.h @@ -46,7 +46,7 @@ public: srsue::pdcp_interface_rlc *pdcp_, srsue::rrc_interface_rlc *rrc_, mac_interface_timers *mac_timers); - void configure(LIBLTE_RRC_RLC_CONFIG_STRUCT *cnfg); + void configure(srslte_rlc_config_t cnfg); void reset(); void empty_queue(); diff --git a/lib/include/srslte/upper/rlc_um.h b/lib/include/srslte/upper/rlc_um.h index 8e95dcb71..4325bd029 100644 --- a/lib/include/srslte/upper/rlc_um.h +++ b/lib/include/srslte/upper/rlc_um.h @@ -56,7 +56,7 @@ public: srsue::pdcp_interface_rlc *pdcp_, srsue::rrc_interface_rlc *rrc_, mac_interface_timers *mac_timers_); - void configure(LIBLTE_RRC_RLC_CONFIG_STRUCT *cnfg); + void configure(srslte_rlc_config_t cnfg); void reset(); void empty_queue(); @@ -92,9 +92,6 @@ private: // Rx window std::map rx_window; - uint32_t rx_window_size; - uint32_t rx_mod; // Rx counter modulus - uint32_t tx_mod; // Tx counter modulus // RX SDU buffers byte_buffer_t *rx_sdu; @@ -108,9 +105,7 @@ private: * Ref: 3GPP TS 36.322 v10.0.0 Section 7 ***************************************************************************/ - int32_t t_reordering; // Timer used by rx to detect PDU loss (ms) - rlc_umd_sn_size_t tx_sn_field_length; // Number of bits used for tx (UL) sequence number - rlc_umd_sn_size_t rx_sn_field_length; // Number of bits used for rx (DL) sequence number + srslte_rlc_um_config_t cfg; /**************************************************************************** * State variables and counters diff --git a/lib/src/asn1/liblte_rrc.cc b/lib/src/asn1/liblte_rrc.cc index 3bfa4a540..e4621994e 100644 --- a/lib/src/asn1/liblte_rrc.cc +++ b/lib/src/asn1/liblte_rrc.cc @@ -2006,6 +2006,7 @@ LIBLTE_ERROR_ENUM liblte_rrc_pack_meas_object_eutra_ie(LIBLTE_RRC_MEAS_OBJECT_EU liblte_value_2_bits(0, ie_ptr, 1); // Optional indicators + liblte_value_2_bits(meas_obj_eutra->offset_freq_not_default, ie_ptr, 1); liblte_value_2_bits(meas_obj_eutra->cells_to_remove_list_present, ie_ptr, 1); if(0 != meas_obj_eutra->N_cells_to_add_mod) { @@ -2035,7 +2036,10 @@ LIBLTE_ERROR_ENUM liblte_rrc_pack_meas_object_eutra_ie(LIBLTE_RRC_MEAS_OBJECT_EU liblte_rrc_pack_neigh_cell_config_ie(meas_obj_eutra->neigh_cell_cnfg, ie_ptr); // Offset Freq - liblte_rrc_pack_q_offset_range_ie(meas_obj_eutra->offset_freq, ie_ptr); + if(meas_obj_eutra->offset_freq_not_default) + { + liblte_rrc_pack_q_offset_range_ie(meas_obj_eutra->offset_freq, ie_ptr); + } // Cells To Remove List if(meas_obj_eutra->cells_to_remove_list_present) @@ -2329,6 +2333,9 @@ LIBLTE_ERROR_ENUM liblte_rrc_pack_meas_object_to_add_mod_list_ie(LIBLTE_RRC_MEAS // Meas Object ID liblte_rrc_pack_meas_object_id_ie(list->meas_obj_list[i].meas_obj_id, ie_ptr); + // Meas Object Choice Extension + liblte_value_2_bits(0, ie_ptr, 1); // Choice from before extension marker + // Meas Object Choice liblte_value_2_bits(list->meas_obj_list[i].meas_obj_type, ie_ptr, 2); diff --git a/lib/src/common/pdu.cc b/lib/src/common/pdu.cc index c54636fcd..57bc07043 100644 --- a/lib/src/common/pdu.cc +++ b/lib/src/common/pdu.cc @@ -33,7 +33,7 @@ // Table 6.1.3.1-1 Buffer size levels for BSR static uint32_t btable[64] = { - 0, 5, 10, 12, 14, 17, 19, 22, 26, 31, 36, 42, 49, 57, 67, 78, 91, 107, 125, 146, 171, 200, 234, 274, 321, 376, 440, 515, 603, 706, 826, 967, 1132, + 0, 1, 10, 12, 14, 17, 19, 22, 26, 31, 36, 42, 49, 57, 67, 78, 91, 107, 125, 146, 171, 200, 234, 274, 321, 376, 440, 515, 603, 706, 826, 967, 1132, 1326, 1552, 1817, 2127, 2490, 2915, 3413, 3995, 4667, 5476, 6411, 7505, 8787, 10287, 12043, 14099, 16507, 19325, 22624, 26487, 31009, 36304, 42502, 49759, 58255, 68201, 79846, 93479, 109439, 128125, 150000}; @@ -428,12 +428,16 @@ int sch_subh::get_bsr(uint32_t buff_size[4]) buff_size[2] = (payload[1]&0x0F) << 4 | (payload[1]&0xC0) >> 6; buff_size[3] = (payload[2]&0x3F); } else { - uint32_t nonzero_lcg = (payload[0]&0xc0) >> 6; + nonzero_lcg = (payload[0]&0xc0) >> 6; buff_size[nonzero_lcg%4] = payload[0]&0x3f; } for (int i=0;i<4;i++) { if (buff_size[i]) { - buff_size[i] = btable[buff_size[i]%64]; + if (buff_size[i]<63) { + buff_size[i] = btable[1+buff_size[i]]; + } else { + buff_size[i] = btable[63]; + } } } return nonzero_lcg; diff --git a/lib/src/phy/common/phy_common.c b/lib/src/phy/common/phy_common.c index 8386ae18b..76dc0366f 100644 --- a/lib/src/phy/common/phy_common.c +++ b/lib/src/phy/common/phy_common.c @@ -178,6 +178,11 @@ uint32_t srslte_N_ta_new(uint32_t N_ta_old, uint32_t ta) { } } +float srslte_coderate(uint32_t tbs, uint32_t nof_re) +{ + return (float) (tbs + 24)/(nof_re); +} + /* Returns the new time advance as indicated by the random access response * as specified in Section 4.2.3 of 36.213 */ uint32_t srslte_N_ta_new_rar(uint32_t ta) { diff --git a/lib/src/phy/enb/enb_ul.c b/lib/src/phy/enb/enb_ul.c index 9c294ac43..9d773d6d5 100644 --- a/lib/src/phy/enb/enb_ul.c +++ b/lib/src/phy/enb/enb_ul.c @@ -91,7 +91,7 @@ int srslte_enb_ul_init(srslte_enb_ul_t *q, srslte_cell_t cell, srslte_prach_set_detect_factor(&q->prach, 60); } - srslte_pucch_set_threshold(&q->pucch, 0.5, 0.5); + srslte_pucch_set_threshold(&q->pucch, 0.8); if (srslte_chest_ul_init(&q->chest, cell)) { fprintf(stderr, "Error initiating channel estimator\n"); diff --git a/lib/src/phy/fec/turbodecoder_gen.c b/lib/src/phy/fec/turbodecoder_gen.c index 396d94caa..649c3363a 100644 --- a/lib/src/phy/fec/turbodecoder_gen.c +++ b/lib/src/phy/fec/turbodecoder_gen.c @@ -328,6 +328,9 @@ void srslte_tdec_gen_iteration(srslte_tdec_gen_t * h, float * input, uint32_t lo } else { fprintf(stderr, "Error CB index not set (call srslte_tdec_gen_reset() first\n"); } + + // Increase number of iterations + h->n_iter++; } int srslte_tdec_gen_reset(srslte_tdec_gen_t * h, uint32_t long_cb) @@ -339,6 +342,7 @@ int srslte_tdec_gen_reset(srslte_tdec_gen_t * h, uint32_t long_cb) } memset(h->w, 0, sizeof(float) * long_cb); h->current_cbidx = srslte_cbsegm_cbindex(long_cb); + h->current_cb_len = long_cb; if (h->current_cbidx < 0) { fprintf(stderr, "Invalid CB length %d\n", long_cb); return -1; diff --git a/lib/src/phy/phch/pdsch.c b/lib/src/phy/phch/pdsch.c index 9b6128c64..a31e98c77 100644 --- a/lib/src/phy/phch/pdsch.c +++ b/lib/src/phy/phch/pdsch.c @@ -58,12 +58,7 @@ extern int indices[100000]; extern int indices_ptr; #endif -float srslte_pdsch_coderate(uint32_t tbs, uint32_t nof_re) -{ - return (float) (tbs + 24)/(nof_re); -} - -int srslte_pdsch_cp(srslte_pdsch_t *q, cf_t *input, cf_t *output, srslte_ra_dl_grant_t *grant, uint32_t lstart_grant, uint32_t nsubframe, bool put) +int srslte_pdsch_cp(srslte_pdsch_t *q, cf_t *input, cf_t *output, srslte_ra_dl_grant_t *grant, uint32_t lstart_grant, uint32_t nsubframe, bool put) { uint32_t s, n, l, lp, lstart, lend, nof_refs; bool is_pbch, is_sss; diff --git a/lib/src/phy/phch/pucch.c b/lib/src/phy/phch/pucch.c index 6a889b89c..928a51019 100644 --- a/lib/src/phy/phch/pucch.c +++ b/lib/src/phy/phch/pucch.c @@ -214,15 +214,15 @@ uint32_t srslte_pucch_get_npucch(uint32_t n_cce, srslte_pucch_format_t format, b { uint32_t n_pucch = 0; if (has_scheduling_request) { - n_pucch = pucch_sched->n_pucch_sr; + n_pucch = pucch_sched->n_pucch_sr; } else if (format < SRSLTE_PUCCH_FORMAT_2) { if (pucch_sched->sps_enabled) { n_pucch = pucch_sched->n_pucch_1[pucch_sched->tpc_for_pucch%4]; } else { - n_pucch = n_cce + pucch_sched->N_pucch_1; + n_pucch = n_cce + pucch_sched->N_pucch_1; } } else { - n_pucch = pucch_sched->n_pucch_2; + n_pucch = pucch_sched->n_pucch_2; } return n_pucch; } @@ -411,9 +411,8 @@ static int pucch_get(srslte_pucch_t *q, srslte_pucch_format_t format, uint32_t n return pucch_cp(q, format, n_pucch, input, z, true); } -void srslte_pucch_set_threshold(srslte_pucch_t *q, float format1, float format1a) { - q->threshold_format1 = format1; - q->threshold_format1a = format1a; +void srslte_pucch_set_threshold(srslte_pucch_t *q, float format1_threshold) { + q->threshold_format1 = format1_threshold; } /** Initializes the PDCCH transmitter and receiver */ @@ -452,6 +451,8 @@ int srslte_pucch_init(srslte_pucch_t *q, srslte_cell_t cell) { q->z_tmp = srslte_vec_malloc(sizeof(cf_t)*SRSLTE_PUCCH_MAX_SYMBOLS); q->ce = srslte_vec_malloc(sizeof(cf_t)*SRSLTE_PUCCH_MAX_SYMBOLS); + q->threshold_format1 = 0.8; + ret = SRSLTE_SUCCESS; } return ret; @@ -612,6 +613,10 @@ static int uci_mod_bits(srslte_pucch_t *q, srslte_pucch_format_t format, uint8_t // Declare this here, since we can not include refsignal_ul.h void srslte_refsignal_r_uv_arg_1prb(float *arg, uint32_t u); + +float tmp_alpha; +uint32_t tmp_noc, tmp_nprime, tmp_woc; + static int pucch_encode_(srslte_pucch_t* q, srslte_pucch_format_t format, uint32_t n_pucch, uint32_t sf_idx, uint16_t rnti, uint8_t bits[SRSLTE_PUCCH_MAX_BITS], cf_t z[SRSLTE_PUCCH_MAX_SYMBOLS], bool signal_only) @@ -655,8 +660,14 @@ static int pucch_encode_(srslte_pucch_t* q, srslte_pucch_format_t format, if (n_prime_ns%2) { S_ns = M_PI/2; } - DEBUG("PUCCH d_0: %.1f+%.1fi, alpha: %.1f, n_oc: %d, n_prime_ns: %d, n_rb_2=%d\n", + DEBUG("PUCCH d_0: %.1f+%.1fi, alpha: %.1f, n_oc: %d, n_prime_ns: %d, n_rb_2=%d\n", __real__ q->d[0], __imag__ q->d[0], alpha, n_oc, n_prime_ns, q->pucch_cfg.n_rb_2); + + tmp_alpha = alpha; + tmp_noc = n_oc; + tmp_nprime = n_prime_ns; + tmp_woc = w_n_oc[N_sf_widx][n_oc%3][m]; + for (uint32_t n=0;nd[0]*cexpf(I*(w_n_oc[N_sf_widx][n_oc%3][m]+q->tmp_arg[n]+alpha*n+S_ns)); @@ -767,7 +778,7 @@ int srslte_pucch_decode(srslte_pucch_t* q, srslte_pucch_format_t format, case SRSLTE_PUCCH_FORMAT_1: bzero(bits, SRSLTE_PUCCH_MAX_BITS*sizeof(uint8_t)); pucch_encode(q, format, n_pucch, sf_idx, rnti, bits, q->z_tmp); - corr = crealf(srslte_vec_dot_prod_conj_ccc(q->z, q->z_tmp, nof_re))/nof_re; + corr = srslte_vec_corr_ccc(q->z, q->z_tmp, nof_re); if (corr >= q->threshold_format1) { ret = 1; } else { @@ -778,11 +789,11 @@ int srslte_pucch_decode(srslte_pucch_t* q, srslte_pucch_format_t format, break; case SRSLTE_PUCCH_FORMAT_1A: bzero(bits, SRSLTE_PUCCH_MAX_BITS*sizeof(uint8_t)); - ret = 0; + ret = 0; for (int b=0;b<2;b++) { - bits[0] = b; + bits[0] = b; pucch_encode(q, format, n_pucch, sf_idx, rnti, bits, q->z_tmp); - corr = crealf(srslte_vec_dot_prod_conj_ccc(q->z, q->z_tmp, nof_re))/nof_re; + corr = srslte_vec_corr_ccc(q->z, q->z_tmp, nof_re); if (corr > corr_max) { corr_max = corr; b_max = b; @@ -790,7 +801,7 @@ int srslte_pucch_decode(srslte_pucch_t* q, srslte_pucch_format_t format, if (corr_max > q->threshold_format1) { // check with format1 in case ack+sr because ack only is binary ret = 1; } - DEBUG("format1a b=%d, corr=%f, nof_re=%d, th=%f\n", b, corr, nof_re, q->threshold_format1a); + DEBUG("format1a b=%d, corr=%f, nof_re=%d\n", b, corr, nof_re); } q->last_corr = corr_max; bits[0] = b_max; diff --git a/lib/src/phy/phch/uci.c b/lib/src/phy/phch/uci.c index 821e5be5f..5bf40cc17 100644 --- a/lib/src/phy/phch/uci.c +++ b/lib/src/phy/phch/uci.c @@ -380,7 +380,7 @@ int decode_cqi_long(srslte_uci_cqi_pusch_t *q, int16_t *q_bits, uint32_t Q, ret = srslte_crc_checksum(&q->crc, q->tmp_cqi, nof_bits + 8); if (ret == 0) { memcpy(data, q->tmp_cqi, nof_bits*sizeof(uint8_t)); - ret = 1; + ret = 1; } else { ret = 0; } diff --git a/lib/src/phy/rf/rf_soapy_imp.c b/lib/src/phy/rf/rf_soapy_imp.c index 8fcf57c24..31649af69 100644 --- a/lib/src/phy/rf/rf_soapy_imp.c +++ b/lib/src/phy/rf/rf_soapy_imp.c @@ -43,9 +43,15 @@ typedef struct { SoapySDRRange *ranges; SoapySDRStream *rxStream; SoapySDRStream *txStream; + bool tx_stream_active; + bool rx_stream_active; } rf_soapy_handler_t; +cf_t zero_mem[64*1024]; + + + int soapy_error(void *h) { return 0; @@ -82,6 +88,7 @@ void rf_soapy_register_error_handler(void *notused, srslte_rf_error_handler_t ne } + char* rf_soapy_devname(void* h) { return "soapy"; @@ -110,10 +117,11 @@ void rf_soapy_set_rx_cal(void *h, srslte_rf_cal_t *cal) int rf_soapy_start_rx_stream(void *h) { rf_soapy_handler_t *handler = (rf_soapy_handler_t*) h; - - if (SoapySDRDevice_activateStream(handler->device, handler->rxStream, 0, 0, 0) != 0) - return SRSLTE_ERROR; - + if(handler->rx_stream_active == false){ + if(SoapySDRDevice_activateStream(handler->device, handler->rxStream, 0, 0, 0) != 0) + return SRSLTE_ERROR; + handler->rx_stream_active = true; + } return SRSLTE_SUCCESS; } @@ -121,14 +129,11 @@ int rf_soapy_start_rx_stream(void *h) int rf_soapy_start_tx_stream(void *h) { rf_soapy_handler_t *handler = (rf_soapy_handler_t*) h; - if (SoapySDRDevice_setupStream(handler->device, &(handler->txStream), SOAPY_SDR_TX, SOAPY_SDR_CF32, NULL, 0, NULL) != 0) { - printf("setupStream fail: %s\n", SoapySDRDevice_lastError()); - return SRSLTE_ERROR; - } - - if(SoapySDRDevice_activateStream(handler->device, handler->txStream, 0, 0, 0) != 0) - return SRSLTE_ERROR; - + if(handler->tx_stream_active == false){ + if(SoapySDRDevice_activateStream(handler->device, handler->txStream, 0, 0, 0) != 0) + return SRSLTE_ERROR; + handler->tx_stream_active = true; + } return SRSLTE_SUCCESS; } @@ -138,7 +143,8 @@ int rf_soapy_stop_rx_stream(void *h) rf_soapy_handler_t *handler = (rf_soapy_handler_t*) h; if (SoapySDRDevice_deactivateStream(handler->device, handler->rxStream, 0, 0) != 0) return SRSLTE_ERROR; - + + handler->rx_stream_active = false; return SRSLTE_SUCCESS; } @@ -149,6 +155,8 @@ int rf_soapy_stop_tx_stream(void *h) if(SoapySDRDevice_deactivateStream(handler->device, handler->txStream, 0, 0) != 0) return SRSLTE_ERROR; + + handler->tx_stream_active = false; return SRSLTE_SUCCESS; } @@ -210,12 +218,26 @@ int rf_soapy_open_multi(char *args, void **h, uint32_t nof_rx_antennas) bzero(handler, sizeof(rf_soapy_handler_t)); *h = handler; handler->device = sdr; - - if (SoapySDRDevice_setupStream(handler->device, &(handler->rxStream), SOAPY_SDR_RX, SOAPY_SDR_CF32, NULL, 0, NULL) != 0) { - printf("setupStream fail: %s\n", SoapySDRDevice_lastError()); - return SRSLTE_ERROR; + handler->tx_stream_active = false; + handler->rx_stream_active = false; + + + if(SoapySDRDevice_getNumChannels(handler->device,SOAPY_SDR_RX) > 0){ + printf("setting up RX stream\n"); + if(SoapySDRDevice_setupStream(handler->device, &(handler->rxStream), SOAPY_SDR_RX, SOAPY_SDR_CF32, NULL, 0, NULL) != 0) { + printf("Rx setupStream fail: %s\n", SoapySDRDevice_lastError()); + return SRSLTE_ERROR; + } } - + + if(SoapySDRDevice_getNumChannels(handler->device,SOAPY_SDR_TX) > 0){ + printf("setting up TX stream\n"); + if (SoapySDRDevice_setupStream(handler->device, &(handler->txStream), SOAPY_SDR_TX, SOAPY_SDR_CF32, NULL, 0, NULL) != 0) { + printf("Tx setupStream fail: %s\n", SoapySDRDevice_lastError()); + return SRSLTE_ERROR; + } + } + return SRSLTE_SUCCESS; } @@ -300,7 +322,7 @@ double rf_soapy_set_tx_gain(void *h, double gain) printf("setGain fail: %s\n", SoapySDRDevice_lastError()); return SRSLTE_ERROR; } - return rf_soapy_get_rx_gain(h); + return rf_soapy_get_tx_gain(h); } @@ -338,7 +360,7 @@ double rf_soapy_set_tx_freq(void *h, double freq) printf("setFrequency fail: %s\n", SoapySDRDevice_lastError()); return SRSLTE_ERROR; } - return SoapySDRDevice_getFrequency(handler->device, SOAPY_SDR_RX, 0); + return SoapySDRDevice_getFrequency(handler->device, SOAPY_SDR_TX, 0); } @@ -355,10 +377,7 @@ int rf_soapy_recv_with_time_multi(void *h, double *frac_secs) { rf_soapy_handler_t *handler = (rf_soapy_handler_t*) h; - //void *buffs[] = {buff}; //array of buffers - int flags; //flags set by receive operation - int num_channels = 1; // temp int trials = 0; @@ -368,16 +387,14 @@ int rf_soapy_recv_with_time_multi(void *h, do { size_t rx_samples = nsamples; - if (rx_samples > nsamples - n) - { + if (rx_samples > nsamples - n){ rx_samples = nsamples - n; } void *buffs_ptr[4]; - for (int i=0; idevice, handler->rxStream, buffs_ptr , rx_samples, &flags, &timeNs, 1000000); if(ret < 0) { // continue when getting overflows @@ -413,23 +430,49 @@ int rf_soapy_recv_with_time(void *h, int rf_soapy_send_timed(void *h, - void *data, - int nsamples, - time_t secs, - double frac_secs, - bool has_time_spec, - bool blocking, - bool is_start_of_burst, - bool is_end_of_burst) -{ - int flags; - long long timeNs; - rf_soapy_handler_t *handler = (rf_soapy_handler_t*) h; - timeNs = secs * 1000000000; - timeNs = timeNs + (frac_secs * 1000000000); - int ret = SoapySDRDevice_writeStream(handler->device, handler->txStream, data, nsamples, &flags, timeNs, 100000); - if(ret != nsamples) - return SRSLTE_ERROR; - - return ret; + void *data, + int nsamples, + time_t secs, + double frac_secs, + bool has_time_spec, + bool blocking, + bool is_start_of_burst, + bool is_end_of_burst) +{ + + int flags; + long long timeNs; + int trials = 0; + int ret = 0; + rf_soapy_handler_t *handler = (rf_soapy_handler_t*) h; + timeNs = secs * 1000000000; + timeNs = timeNs + (frac_secs * 1000000000); + int n = 0; + + if(!handler->tx_stream_active){ + rf_soapy_start_tx_stream(h); + } + + + cf_t *data_c = (cf_t*) data; + do{ + size_t tx_samples = nsamples; + if (tx_samples > nsamples - n) { + tx_samples = nsamples - n; + } + void *buff = (void*) &data_c[n]; + const void *buffs_ptr[1] = {buff}; + ret = SoapySDRDevice_writeStream(handler->device, handler->txStream, buffs_ptr, tx_samples, &flags, timeNs, 10000); + if(ret < 0) + return SRSLTE_ERROR; + + n += ret; + trials++; + }while (n < nsamples && trials < 100); + + if(ret != nsamples) + return SRSLTE_ERROR; + + return ret; + } diff --git a/lib/src/phy/rf/rf_uhd_imp.c b/lib/src/phy/rf/rf_uhd_imp.c index 319093994..3a047ceba 100644 --- a/lib/src/phy/rf/rf_uhd_imp.c +++ b/lib/src/phy/rf/rf_uhd_imp.c @@ -328,7 +328,7 @@ int rf_uhd_open_multi(char *args, void **h, uint32_t nof_rx_antennas) if (args[0]=='\0') { if (find_string(devices_str, "type=b200") && !strstr(args, "recv_frame_size")) { // If B200 is available, use it - args = "type=b200"; + args = "type=b200,master_clock_rate=30.72e6"; handler->devname = DEVNAME_B200; } else if (find_string(devices_str, "type=x300")) { // Else if X300 is available, set master clock rate now (can't be changed later) @@ -344,6 +344,8 @@ int rf_uhd_open_multi(char *args, void **h, uint32_t nof_rx_antennas) handler->dynamic_rate = false; handler->devname = DEVNAME_X300; } else if (strstr(args, "type=b200")) { + snprintf(args2, sizeof(args2), "%s,master_clock_rate=30.72e6", args); + args = args2; handler->devname = DEVNAME_B200; } } @@ -399,7 +401,11 @@ int rf_uhd_open_multi(char *args, void **h, uint32_t nof_rx_antennas) }; handler->nof_rx_channels = nof_rx_antennas; - handler->nof_tx_channels = 1; + handler->nof_tx_channels = 1; + + /* Set default rate to avoid decimation warnings */ + uhd_usrp_set_rx_rate(handler->usrp, 1.92e6, 0); + uhd_usrp_set_tx_rate(handler->usrp, 1.92e6, 0); /* Initialize rx and tx stremers */ uhd_rx_streamer_make(&handler->rx_stream); diff --git a/lib/src/phy/ue/ue_cell_search.c b/lib/src/phy/ue/ue_cell_search.c index f8c38a1bb..f7d244387 100644 --- a/lib/src/phy/ue/ue_cell_search.c +++ b/lib/src/phy/ue/ue_cell_search.c @@ -95,7 +95,7 @@ int srslte_ue_cellsearch_init_multi(srslte_ue_cellsearch_t * q, uint32_t max_fra { int ret = SRSLTE_ERROR_INVALID_INPUTS; - if (q != NULL) { + if (q != NULL && nof_rx_antennas > 0) { ret = SRSLTE_ERROR; srslte_cell_t cell; diff --git a/lib/src/phy/utils/vector.c b/lib/src/phy/utils/vector.c index 2a2001ae3..ed6dfa989 100644 --- a/lib/src/phy/utils/vector.c +++ b/lib/src/phy/utils/vector.c @@ -656,6 +656,15 @@ float srslte_vec_avg_power_cf(cf_t *x, uint32_t len) { return crealf(srslte_vec_dot_prod_conj_ccc(x,x,len)) / len; } +// Correlation assumes zero-mean x and y +float srslte_vec_corr_ccc(cf_t *x, cf_t *y, uint32_t len) { +// return crealf(srslte_vec_dot_prod_conj_ccc(x,y,len)) / len; + float s_x = crealf(srslte_vec_dot_prod_conj_ccc(x, x, len))/len; + float s_y = crealf(srslte_vec_dot_prod_conj_ccc(y, y, len))/len; + float cov = crealf(srslte_vec_dot_prod_conj_ccc(x, y, len))/len; + return cov/(sqrt(s_x*s_y)); +} + // PSS (disabled and using abs_square ) void srslte_vec_abs_cf(cf_t *x, float *abs, uint32_t len) { int i; diff --git a/lib/src/radio/radio.cc b/lib/src/radio/radio.cc index bc74660b0..872fdda7e 100644 --- a/lib/src/radio/radio.cc +++ b/lib/src/radio/radio.cc @@ -333,7 +333,7 @@ void radio::set_tx_srate(float srate) } else if (srate_khz == 15.36e3) { nsamples = 131; } else if (srate_khz == 23.04e3) { - nsamples = 175; + nsamples = 150; } else { /* Interpolate from known values */ printf("\nWarning TX/RX time offset for sampling rate %.0f KHz not calibrated. Using interpolated value\n\n", cur_tx_srate); @@ -353,7 +353,7 @@ void radio::set_tx_srate(float srate) } else if (srate_khz == 15.36e3) { nsamples = 86; } else if (srate_khz == 23.04e3) { - nsamples = 119; + nsamples = 110; } else { /* Interpolate from known values */ printf("\nWarning TX/RX time offset for sampling rate %.0f KHz not calibrated. Using interpolated value\n\n", cur_tx_srate); diff --git a/lib/src/upper/gw.cc b/lib/src/upper/gw.cc index beb003c51..685803a4d 100644 --- a/lib/src/upper/gw.cc +++ b/lib/src/upper/gw.cc @@ -44,13 +44,14 @@ gw::gw() :if_up(false) {} -void gw::init(srsue::pdcp_interface_gw *pdcp_, srsue::rrc_interface_gw *rrc_, srsue::ue_interface *ue_, log *gw_log_) +void gw::init(srsue::pdcp_interface_gw *pdcp_, srsue::rrc_interface_gw *rrc_, srsue::ue_interface *ue_, log *gw_log_, uint32_t lcid_) { pool = byte_buffer_pool::get_instance(); pdcp = pdcp_; rrc = rrc_; ue = ue_; gw_log = gw_log_; + lcid = lcid_; run_enable = true; gettimeofday(&metrics_time[1], NULL); @@ -261,7 +262,7 @@ void gw::run_thread() // Send PDU directly to PDCP pdu->set_timestamp(); ul_tput_bytes += pdu->N_bytes; - pdcp->write_sdu(RB_ID_DRB1, pdu); + pdcp->write_sdu(lcid, pdu); do { pdu = pool_allocate; diff --git a/lib/src/upper/pdcp.cc b/lib/src/upper/pdcp.cc index e729118ce..5f4afbd62 100644 --- a/lib/src/upper/pdcp.cc +++ b/lib/src/upper/pdcp.cc @@ -32,15 +32,22 @@ namespace srslte { pdcp::pdcp() {} -void pdcp::init(srsue::rlc_interface_pdcp *rlc_, srsue::rrc_interface_pdcp *rrc_, srsue::gw_interface_pdcp *gw_, log *pdcp_log_, uint8_t direction_) +void pdcp::init(srsue::rlc_interface_pdcp *rlc_, srsue::rrc_interface_pdcp *rrc_, srsue::gw_interface_pdcp *gw_, log *pdcp_log_, uint32_t lcid_, uint8_t direction_) { rlc = rlc_; rrc = rrc_; gw = gw_; pdcp_log = pdcp_log_; + lcid = lcid_; direction = direction_; - pdcp_array[0].init(rlc, rrc, gw, pdcp_log, RB_ID_SRB0, direction); // SRB0 + // Default config + srslte_pdcp_config_t cnfg; + cnfg.is_control = false; + cnfg.is_data = false; + cnfg.direction = direction_; + + pdcp_array[0].init(rlc, rrc, gw, pdcp_log, lcid, cnfg); } void pdcp::stop() @@ -52,7 +59,7 @@ void pdcp::reset() pdcp_array[i].reset(); } - pdcp_array[0].init(rlc, rrc, gw, pdcp_log, RB_ID_SRB0, direction); // SRB0 + pdcp_array[0].init(rlc, rrc, gw, pdcp_log, lcid, direction); } /******************************************************************************* @@ -64,17 +71,17 @@ void pdcp::write_sdu(uint32_t lcid, byte_buffer_t *sdu) pdcp_array[lcid].write_sdu(sdu); } -void pdcp::add_bearer(uint32_t lcid, LIBLTE_RRC_PDCP_CONFIG_STRUCT *cnfg) +void pdcp::add_bearer(uint32_t lcid, srslte_pdcp_config_t cfg) { - if(lcid < 0 || lcid >= SRSLTE_N_RADIO_BEARERS) { + if(lcid >= SRSLTE_N_RADIO_BEARERS) { pdcp_log->error("Radio bearer id must be in [0:%d] - %d\n", SRSLTE_N_RADIO_BEARERS, lcid); return; } if (!pdcp_array[lcid].is_active()) { - pdcp_array[lcid].init(rlc, rrc, gw, pdcp_log, lcid, direction, cnfg); - pdcp_log->info("Added bearer %s\n", rb_id_text[lcid]); + pdcp_array[lcid].init(rlc, rrc, gw, pdcp_log, lcid, cfg); + pdcp_log->info("Added bearer %s\n", rrc->get_rb_name(lcid).c_str()); } else { - pdcp_log->warning("Bearer %s already configured. Reconfiguration not supported\n", rb_id_text[lcid]); + pdcp_log->warning("Bearer %s already configured. Reconfiguration not supported\n", rrc->get_rb_name(lcid).c_str()); } } @@ -116,7 +123,7 @@ void pdcp::write_pdu_pcch(byte_buffer_t *sdu) *******************************************************************************/ bool pdcp::valid_lcid(uint32_t lcid) { - if(lcid < 0 || lcid >= SRSLTE_N_RADIO_BEARERS) { + if(lcid >= SRSLTE_N_RADIO_BEARERS) { pdcp_log->error("Radio bearer id must be in [0:%d] - %d", SRSLTE_N_RADIO_BEARERS, lcid); return false; } diff --git a/lib/src/upper/pdcp_entity.cc b/lib/src/upper/pdcp_entity.cc index 23fe8768d..9f658a577 100644 --- a/lib/src/upper/pdcp_entity.cc +++ b/lib/src/upper/pdcp_entity.cc @@ -34,8 +34,6 @@ pdcp_entity::pdcp_entity() :active(false) ,tx_count(0) ,rx_count(0) - ,do_security(false) - ,sn_len(12) { pool = byte_buffer_pool::get_instance(); } @@ -45,38 +43,27 @@ void pdcp_entity::init(srsue::rlc_interface_pdcp *rlc_, srsue::gw_interface_pdcp *gw_, srslte::log *log_, uint32_t lcid_, - u_int8_t direction_, - LIBLTE_RRC_PDCP_CONFIG_STRUCT *cnfg) + srslte_pdcp_config_t cfg_) { rlc = rlc_; rrc = rrc_; gw = gw_; log = log_; lcid = lcid_; - direction = direction_; + cfg = cfg_; active = true; tx_count = 0; rx_count = 0; - do_security = false; - if(cnfg) - { - if(cnfg->rlc_um_pdcp_sn_size_present) { - if(LIBLTE_RRC_PDCP_SN_SIZE_7_BITS == cnfg->rlc_um_pdcp_sn_size) { - sn_len = 7; - } - } - // TODO: handle remainder of cnfg - } - log->debug("Init %s\n", rb_id_text[lcid]); + log->debug("Init %s\n", rrc->get_rb_name(lcid).c_str()); } void pdcp_entity::reset() { active = false; if(log) - log->debug("Reset %s\n", rb_id_text[lcid]); + log->debug("Reset %s\n", rrc->get_rb_name(lcid).c_str()); } bool pdcp_entity::is_active() @@ -87,44 +74,32 @@ bool pdcp_entity::is_active() // RRC interface void pdcp_entity::write_sdu(byte_buffer_t *sdu) { - log->info_hex(sdu->msg, sdu->N_bytes, "TX %s SDU, do_security = %s", rb_id_text[lcid], (do_security)?"true":"false"); + log->info_hex(sdu->msg, sdu->N_bytes, "TX %s SDU, do_security = %s", rrc->get_rb_name(lcid).c_str(), (cfg.do_security)?"true":"false"); - // Handle SRB messages - switch(lcid) - { - case RB_ID_SRB0: - rlc->write_sdu(lcid, sdu); - break; - case RB_ID_SRB1: // Intentional fall-through - case RB_ID_SRB2: + if (cfg.is_control) { pdcp_pack_control_pdu(tx_count, sdu); - if(do_security) + if(cfg.do_security) { integrity_generate(&k_rrc_int[16], tx_count, lcid-1, - direction, + cfg.direction, sdu->msg, sdu->N_bytes-4, &sdu->msg[sdu->N_bytes-4]); } tx_count++; - rlc->write_sdu(lcid, sdu); - - break; } - // Handle DRB messages - if(lcid >= RB_ID_DRB1) - { - if(12 == sn_len) - { + if (cfg.is_data) { + if(12 == cfg.sn_len) { pdcp_pack_data_pdu_long_sn(tx_count++, sdu); } else { pdcp_pack_data_pdu_short_sn(tx_count++, sdu); } - rlc->write_sdu(lcid, sdu); } + + rlc->write_sdu(lcid, sdu); } void pdcp_entity::config_security(uint8_t *k_rrc_enc_, @@ -132,7 +107,7 @@ void pdcp_entity::config_security(uint8_t *k_rrc_enc_, CIPHERING_ALGORITHM_ID_ENUM cipher_algo_, INTEGRITY_ALGORITHM_ID_ENUM integ_algo_) { - do_security = true; + cfg.do_security = true; for(int i=0; i<32; i++) { k_rrc_enc[i] = k_rrc_enc_[i]; @@ -145,37 +120,32 @@ void pdcp_entity::config_security(uint8_t *k_rrc_enc_, // RLC interface void pdcp_entity::write_pdu(byte_buffer_t *pdu) { - // Handle SRB messages - switch(lcid) - { - case RB_ID_SRB0: - // Simply pass on to RRC - log->info_hex(pdu->msg, pdu->N_bytes, "RX %s PDU", rb_id_text[lcid]); - rrc->write_pdu(RB_ID_SRB0, pdu); - break; - case RB_ID_SRB1: // Intentional fall-through - case RB_ID_SRB2: - uint32_t sn; - log->info_hex(pdu->msg, pdu->N_bytes, "RX %s PDU", rb_id_text[lcid]); - pdcp_unpack_control_pdu(pdu, &sn); - log->info_hex(pdu->msg, pdu->N_bytes, "RX %s SDU SN: %d", - rb_id_text[lcid], sn); - rrc->write_pdu(lcid, pdu); - break; - } - // Handle DRB messages - if(lcid >= RB_ID_DRB1) - { + + + + + if (cfg.is_data) { uint32_t sn; - if(12 == sn_len) + if(12 == cfg.sn_len) { pdcp_unpack_data_pdu_long_sn(pdu, &sn); } else { pdcp_unpack_data_pdu_short_sn(pdu, &sn); } - log->info_hex(pdu->msg, pdu->N_bytes, "RX %s PDU: %d", rb_id_text[lcid], sn); + log->info_hex(pdu->msg, pdu->N_bytes, "RX %s PDU: %d", rrc->get_rb_name(lcid).c_str(), sn); gw->write_pdu(lcid, pdu); + } else { + if (cfg.is_control) { + uint32_t sn; + pdcp_unpack_control_pdu(pdu, &sn); + log->info_hex(pdu->msg, pdu->N_bytes, "RX %s SDU SN: %d", + rrc->get_rb_name(lcid).c_str(), sn); + } else { + log->info_hex(pdu->msg, pdu->N_bytes, "RX %s PDU", rrc->get_rb_name(lcid).c_str()); + } + // pass to RRC + rrc->write_pdu(lcid, pdu); } } diff --git a/lib/src/upper/rlc.cc b/lib/src/upper/rlc.cc index becb15c37..0cc551a1f 100644 --- a/lib/src/upper/rlc.cc +++ b/lib/src/upper/rlc.cc @@ -41,18 +41,20 @@ void rlc::init(srsue::pdcp_interface_rlc *pdcp_, srsue::rrc_interface_rlc *rrc_, srsue::ue_interface *ue_, log *rlc_log_, - mac_interface_timers *mac_timers_) + mac_interface_timers *mac_timers_, + uint32_t lcid_) { pdcp = pdcp_; rrc = rrc_; ue = ue_; rlc_log = rlc_log_; mac_timers = mac_timers_; + default_lcid = lcid_; gettimeofday(&metrics_time[1], NULL); reset_metrics(); - rlc_array[0].init(RLC_MODE_TM, rlc_log, RB_ID_SRB0, pdcp, rrc, mac_timers); // SRB0 + rlc_array[0].init(RLC_MODE_TM, rlc_log, default_lcid, pdcp, rrc, mac_timers); // SRB0 } void rlc::reset_metrics() @@ -97,7 +99,15 @@ void rlc::reset() rlc_array[i].reset(); } - rlc_array[0].init(RLC_MODE_TM, rlc_log, RB_ID_SRB0, pdcp, rrc, mac_timers); // SRB0 + rlc_array[0].init(RLC_MODE_TM, rlc_log, default_lcid, pdcp, rrc, mac_timers); // SRB0 +} + +void rlc::empty_queue() +{ + for(uint32_t i=0; iget_rb_name(lcid); +} + /******************************************************************************* MAC interface *******************************************************************************/ @@ -186,11 +201,10 @@ void rlc::write_pdu_pcch(uint8_t *payload, uint32_t nof_bytes) *******************************************************************************/ void rlc::add_bearer(uint32_t lcid) { - // No config provided - use defaults for lcid - LIBLTE_RRC_RLC_CONFIG_STRUCT cnfg; - if(RB_ID_SRB1 == lcid || RB_ID_SRB2 == lcid) - { + // No config provided - use defaults for SRB1 and SRB2 + if(lcid < 3) { if (!rlc_array[lcid].active()) { + LIBLTE_RRC_RLC_CONFIG_STRUCT cnfg; cnfg.rlc_mode = LIBLTE_RRC_RLC_MODE_AM; cnfg.ul_am_rlc.t_poll_retx = LIBLTE_RRC_T_POLL_RETRANSMIT_MS45; cnfg.ul_am_rlc.poll_pdu = LIBLTE_RRC_POLL_PDU_INFINITY; @@ -198,28 +212,27 @@ void rlc::add_bearer(uint32_t lcid) cnfg.ul_am_rlc.max_retx_thresh = LIBLTE_RRC_MAX_RETX_THRESHOLD_T4; cnfg.dl_am_rlc.t_reordering = LIBLTE_RRC_T_REORDERING_MS35; cnfg.dl_am_rlc.t_status_prohibit = LIBLTE_RRC_T_STATUS_PROHIBIT_MS0; - add_bearer(lcid, &cnfg); + add_bearer(lcid, srslte_rlc_config_t(&cnfg)); } else { - rlc_log->warning("Bearer %s already configured. Reconfiguration not supported\n", rb_id_text[lcid]); + rlc_log->warning("Bearer %s already configured. Reconfiguration not supported\n", get_rb_name(lcid).c_str()); } }else{ - rlc_log->error("Radio bearer %s does not support default RLC configuration.", - rb_id_text[lcid]); + rlc_log->error("Radio bearer %s does not support default RLC configuration.\n", + get_rb_name(lcid).c_str()); } } -void rlc::add_bearer(uint32_t lcid, LIBLTE_RRC_RLC_CONFIG_STRUCT *cnfg) +void rlc::add_bearer(uint32_t lcid, srslte_rlc_config_t cnfg) { if(lcid < 0 || lcid >= SRSLTE_N_RADIO_BEARERS) { rlc_log->error("Radio bearer id must be in [0:%d] - %d\n", SRSLTE_N_RADIO_BEARERS, lcid); return; } - - + if (!rlc_array[lcid].active()) { rlc_log->info("Adding radio bearer %s with mode %s\n", - rb_id_text[lcid], liblte_rrc_rlc_mode_text[cnfg->rlc_mode]); - switch(cnfg->rlc_mode) + get_rb_name(lcid).c_str(), liblte_rrc_rlc_mode_text[cnfg.rlc_mode]); + switch(cnfg.rlc_mode) { case LIBLTE_RRC_RLC_MODE_AM: rlc_array[lcid].init(RLC_MODE_AM, rlc_log, lcid, pdcp, rrc, mac_timers); @@ -238,7 +251,7 @@ void rlc::add_bearer(uint32_t lcid, LIBLTE_RRC_RLC_CONFIG_STRUCT *cnfg) return; } } else { - rlc_log->warning("Bearer %s already created.\n", rb_id_text[lcid]); + rlc_log->warning("Bearer %s already created.\n", get_rb_name(lcid).c_str()); } rlc_array[lcid].configure(cnfg); diff --git a/lib/src/upper/rlc_am.cc b/lib/src/upper/rlc_am.cc index 416a141c8..f0055a534 100644 --- a/lib/src/upper/rlc_am.cc +++ b/lib/src/upper/rlc_am.cc @@ -74,20 +74,13 @@ void rlc_am::init(srslte::log *log_, rrc = rrc_; } -void rlc_am::configure(LIBLTE_RRC_RLC_CONFIG_STRUCT *cnfg) +void rlc_am::configure(srslte_rlc_config_t cfg_) { - t_poll_retx = liblte_rrc_t_poll_retransmit_num[cnfg->ul_am_rlc.t_poll_retx]; - poll_pdu = liblte_rrc_poll_pdu_num[cnfg->ul_am_rlc.poll_pdu]; - poll_byte = liblte_rrc_poll_byte_num[cnfg->ul_am_rlc.poll_byte]*1000; // KB - max_retx_thresh = liblte_rrc_max_retx_threshold_num[cnfg->ul_am_rlc.max_retx_thresh]; - - t_reordering = liblte_rrc_t_reordering_num[cnfg->dl_am_rlc.t_reordering]; - t_status_prohibit = liblte_rrc_t_status_prohibit_num[cnfg->dl_am_rlc.t_status_prohibit]; - + cfg = cfg_.am; log->info("%s configured: t_poll_retx=%d, poll_pdu=%d, poll_byte=%d, max_retx_thresh=%d, " "t_reordering=%d, t_status_prohibit=%d\n", - rb_id_text[lcid], t_poll_retx, poll_pdu, poll_byte, max_retx_thresh, - t_reordering, t_status_prohibit); + rrc->get_rb_name(lcid).c_str(), cfg.t_poll_retx, cfg.poll_pdu, cfg.poll_byte, cfg.max_retx_thresh, + cfg.t_reordering, cfg.t_status_prohibit); } @@ -176,7 +169,7 @@ uint32_t rlc_am::get_bearer() void rlc_am::write_sdu(byte_buffer_t *sdu) { - log->info_hex(sdu->msg, sdu->N_bytes, "%s Tx SDU", rb_id_text[lcid]); + log->info_hex(sdu->msg, sdu->N_bytes, "%s Tx SDU", rrc->get_rb_name(lcid).c_str()); tx_sdu_queue.write(sdu); } @@ -347,7 +340,7 @@ void rlc_am::check_reordering_timeout() if(reordering_timeout.is_running() && reordering_timeout.expired()) { reordering_timeout.reset(); - log->debug("%s reordering timeout expiry - updating vr_ms\n", rb_id_text[lcid]); + log->debug("%s reordering timeout expiry - updating vr_ms\n", rrc->get_rb_name(lcid).c_str()); // 36.322 v10 Section 5.1.3.2.4 vr_ms = vr_x; @@ -362,7 +355,7 @@ void rlc_am::check_reordering_timeout() if(RX_MOD_BASE(vr_h) > RX_MOD_BASE(vr_ms)) { - reordering_timeout.start(t_reordering); + reordering_timeout.start(cfg.t_reordering); vr_x = vr_h; } @@ -376,9 +369,9 @@ void rlc_am::check_reordering_timeout() bool rlc_am::poll_required() { - if(poll_pdu > 0 && pdu_without_poll > (uint32_t)poll_pdu) + if(cfg.poll_pdu > 0 && pdu_without_poll > (uint32_t)cfg.poll_pdu) return true; - if(poll_byte > 0 && byte_without_poll > (uint32_t)poll_byte) + if(cfg.poll_byte > 0 && byte_without_poll > (uint32_t)cfg.poll_byte) return true; if(poll_retx()) return true; @@ -409,18 +402,18 @@ int rlc_am::build_status_pdu(uint8_t *payload, uint32_t nof_bytes) if(pdu_len > 0 && nof_bytes >= (uint32_t)pdu_len) { log->info("%s Tx status PDU - %s\n", - rb_id_text[lcid], rlc_am_to_string(&status).c_str()); + rrc->get_rb_name(lcid).c_str(), rlc_am_to_string(&status).c_str()); do_status = false; poll_received = false; - if(t_status_prohibit > 0) - status_prohibit_timeout.start(t_status_prohibit); + if(cfg.t_status_prohibit > 0) + status_prohibit_timeout.start(cfg.t_status_prohibit); debug_state(); return rlc_am_write_status_pdu(&status, payload); }else{ log->warning("%s Cannot tx status PDU - %d bytes available, %d bytes required\n", - rb_id_text[lcid], nof_bytes, pdu_len); + rrc->get_rb_name(lcid).c_str(), nof_bytes, pdu_len); return 0; } } @@ -437,7 +430,7 @@ int rlc_am::build_retx_pdu(uint8_t *payload, uint32_t nof_bytes) // Is resegmentation needed? if(retx.is_segment || required_buffer_size(retx) > (int)nof_bytes) { - log->debug("%s build_retx_pdu - resegmentation required\n", rb_id_text[lcid]); + log->debug("%s build_retx_pdu - resegmentation required\n", rrc->get_rb_name(lcid).c_str()); return build_segment(payload, nof_bytes, retx); } @@ -450,7 +443,7 @@ int rlc_am::build_retx_pdu(uint8_t *payload, uint32_t nof_bytes) poll_sn = vt_s; pdu_without_poll = 0; byte_without_poll = 0; - poll_retx_timeout.start(t_poll_retx); + poll_retx_timeout.start(cfg.t_poll_retx); } uint8_t *ptr = payload; @@ -459,10 +452,10 @@ int rlc_am::build_retx_pdu(uint8_t *payload, uint32_t nof_bytes) retx_queue.pop_front(); tx_window[retx.sn].retx_count++; - if(tx_window[retx.sn].retx_count >= max_retx_thresh) + if(tx_window[retx.sn].retx_count >= cfg.max_retx_thresh) rrc->max_retx_attempted(); log->info("%s Retx PDU scheduled for tx. SN: %d, retx count: %d\n", - rb_id_text[lcid], retx.sn, tx_window[retx.sn].retx_count); + rrc->get_rb_name(lcid).c_str(), retx.sn, tx_window[retx.sn].retx_count); debug_state(); return (ptr-payload) + tx_window[retx.sn].buf->N_bytes; @@ -495,7 +488,7 @@ int rlc_am::build_segment(uint8_t *payload, uint32_t nof_bytes, rlc_amd_retx_t r if(nof_bytes <= head_len) { log->warning("%s Cannot build a PDU segment - %d bytes available, %d bytes required for header\n", - rb_id_text[lcid], nof_bytes, head_len); + rrc->get_rb_name(lcid).c_str(), nof_bytes, head_len); return 0; } pdu_space = nof_bytes-head_len; @@ -561,15 +554,15 @@ int rlc_am::build_segment(uint8_t *payload, uint32_t nof_bytes, rlc_amd_retx_t r memcpy(ptr, data, len); log->info("%s Retx PDU segment scheduled for tx. SN: %d, SO: %d\n", - rb_id_text[lcid], retx.sn, retx.so_start); + rrc->get_rb_name(lcid).c_str(), retx.sn, retx.so_start); debug_state(); int pdu_len = (ptr-payload) + len; if(pdu_len > (int)nof_bytes) { log->error("%s Retx PDU segment length error. Available: %d, Used: %d\n", - rb_id_text[lcid], nof_bytes, pdu_len); + rrc->get_rb_name(lcid).c_str(), nof_bytes, pdu_len); log->debug("%s Retx PDU segment length error. Header len: %d, Payload len: %d, N_li: %d\n", - rb_id_text[lcid], (ptr-payload), len, new_header.N_li); + rrc->get_rb_name(lcid).c_str(), (ptr-payload), len, new_header.N_li); } return pdu_len; @@ -617,13 +610,13 @@ int rlc_am::build_data_pdu(uint8_t *payload, uint32_t nof_bytes) if(pdu_space <= head_len) { log->warning("%s Cannot build a PDU - %d bytes available, %d bytes required for header\n", - rb_id_text[lcid], nof_bytes, head_len); + rrc->get_rb_name(lcid).c_str(), nof_bytes, head_len); pool->deallocate(pdu); return 0; } log->debug("%s Building PDU - pdu_space: %d, head_len: %d \n", - rb_id_text[lcid], pdu_space, head_len); + rrc->get_rb_name(lcid).c_str(), pdu_space, head_len); // Check for SDU segment if(tx_sdu) @@ -638,7 +631,7 @@ int rlc_am::build_data_pdu(uint8_t *payload, uint32_t nof_bytes) if(tx_sdu->N_bytes == 0) { log->info("%s Complete SDU scheduled for tx. Stack latency: %ld us\n", - rb_id_text[lcid], tx_sdu->get_latency_us()); + rrc->get_rb_name(lcid).c_str(), tx_sdu->get_latency_us()); pool->deallocate(tx_sdu); tx_sdu = NULL; } @@ -649,7 +642,7 @@ int rlc_am::build_data_pdu(uint8_t *payload, uint32_t nof_bytes) header.fi |= RLC_FI_FIELD_NOT_START_ALIGNED; // First byte does not correspond to first byte of SDU log->debug("%s Building PDU - added SDU segment (len:%d) - pdu_space: %d, head_len: %d \n", - rb_id_text[lcid], to_move, pdu_space, head_len); + rrc->get_rb_name(lcid).c_str(), to_move, pdu_space, head_len); } // Pull SDUs from queue @@ -673,7 +666,7 @@ int rlc_am::build_data_pdu(uint8_t *payload, uint32_t nof_bytes) if(tx_sdu->N_bytes == 0) { log->info("%s Complete SDU scheduled for tx. Stack latency: %ld us\n", - rb_id_text[lcid], tx_sdu->get_latency_us()); + rrc->get_rb_name(lcid).c_str(), tx_sdu->get_latency_us()); pool->deallocate(tx_sdu); tx_sdu = NULL; } @@ -683,7 +676,7 @@ int rlc_am::build_data_pdu(uint8_t *payload, uint32_t nof_bytes) pdu_space = 0; log->debug("%s Building PDU - added SDU segment (len:%d) - pdu_space: %d, head_len: %d \n", - rb_id_text[lcid], to_move, pdu_space, head_len); + rrc->get_rb_name(lcid).c_str(), to_move, pdu_space, head_len); } if(tx_sdu) @@ -692,22 +685,22 @@ int rlc_am::build_data_pdu(uint8_t *payload, uint32_t nof_bytes) // Set Poll bit pdu_without_poll++; byte_without_poll += (pdu->N_bytes + head_len); - log->debug("%s pdu_without_poll: %d\n", rb_id_text[lcid], pdu_without_poll); - log->debug("%s byte_without_poll: %d\n", rb_id_text[lcid], byte_without_poll); + log->debug("%s pdu_without_poll: %d\n", rrc->get_rb_name(lcid).c_str(), pdu_without_poll); + log->debug("%s byte_without_poll: %d\n", rrc->get_rb_name(lcid).c_str(), byte_without_poll); if(poll_required()) { - log->debug("%s setting poll bit to request status\n", rb_id_text[lcid]); + log->debug("%s setting poll bit to request status\n", rrc->get_rb_name(lcid).c_str()); header.p = 1; poll_sn = vt_s; pdu_without_poll = 0; byte_without_poll = 0; - poll_retx_timeout.start(t_poll_retx); + poll_retx_timeout.start(cfg.t_poll_retx); } // Set SN header.sn = vt_s; vt_s = (vt_s + 1)%MOD; - log->info("%s PDU scheduled for tx. SN: %d\n", rb_id_text[lcid], header.sn); + log->info("%s PDU scheduled for tx. SN: %d\n", rrc->get_rb_name(lcid).c_str(), header.sn); // Place PDU in tx_window, write header and TX tx_window[header.sn].buf = pdu; @@ -728,26 +721,26 @@ void rlc_am::handle_data_pdu(uint8_t *payload, uint32_t nof_bytes, rlc_amd_pdu_h std::map::iterator it; log->info_hex(payload, nof_bytes, "%s Rx data PDU SN: %d", - rb_id_text[lcid], header.sn); + rrc->get_rb_name(lcid).c_str(), header.sn); if(!inside_rx_window(header.sn)) { if(header.p) { - log->info("%s Status packet requested through polling bit\n", rb_id_text[lcid]); + log->info("%s Status packet requested through polling bit\n", rrc->get_rb_name(lcid).c_str()); do_status = true; } log->info("%s SN: %d outside rx window [%d:%d] - discarding\n", - rb_id_text[lcid], header.sn, vr_r, vr_mr); + rrc->get_rb_name(lcid).c_str(), header.sn, vr_r, vr_mr); return; } it = rx_window.find(header.sn); if(rx_window.end() != it) { if(header.p) { - log->info("%s Status packet requested through polling bit\n", rb_id_text[lcid]); + log->info("%s Status packet requested through polling bit\n", rrc->get_rb_name(lcid).c_str()); do_status = true; } log->info("%s Discarding duplicate SN: %d\n", - rb_id_text[lcid], header.sn); + rrc->get_rb_name(lcid).c_str(), header.sn); return; } @@ -780,7 +773,7 @@ void rlc_am::handle_data_pdu(uint8_t *payload, uint32_t nof_bytes, rlc_amd_pdu_h // Check poll bit if(header.p) { - log->info("%s Status packet requested through polling bit\n", rb_id_text[lcid]); + log->info("%s Status packet requested through polling bit\n", rrc->get_rb_name(lcid).c_str()); poll_received = true; // 36.322 v10 Section 5.2.3 @@ -812,7 +805,7 @@ void rlc_am::handle_data_pdu(uint8_t *payload, uint32_t nof_bytes, rlc_amd_pdu_h { if(RX_MOD_BASE(vr_h) > RX_MOD_BASE(vr_r)) { - reordering_timeout.start(t_reordering); + reordering_timeout.start(cfg.t_reordering); vr_x = vr_h; } } @@ -825,16 +818,16 @@ void rlc_am::handle_data_pdu_segment(uint8_t *payload, uint32_t nof_bytes, rlc_a std::map::iterator it; log->info_hex(payload, nof_bytes, "%s Rx data PDU segment. SN: %d, SO: %d", - rb_id_text[lcid], header.sn, header.so); + rrc->get_rb_name(lcid).c_str(), header.sn, header.so); // Check inside rx window if(!inside_rx_window(header.sn)) { if(header.p) { - log->info("%s Status packet requested through polling bit\n", rb_id_text[lcid]); + log->info("%s Status packet requested through polling bit\n", rrc->get_rb_name(lcid).c_str()); do_status = true; } log->info("%s SN: %d outside rx window [%d:%d] - discarding\n", - rb_id_text[lcid], header.sn, vr_r, vr_mr); + rrc->get_rb_name(lcid).c_str(), header.sn, vr_r, vr_mr); return; } @@ -853,7 +846,7 @@ void rlc_am::handle_data_pdu_segment(uint8_t *payload, uint32_t nof_bytes, rlc_a if(rx_segments.end() != it) { if(header.p) { - log->info("%s Status packet requested through polling bit\n", rb_id_text[lcid]); + log->info("%s Status packet requested through polling bit\n", rrc->get_rb_name(lcid).c_str()); do_status = true; } @@ -883,7 +876,7 @@ void rlc_am::handle_data_pdu_segment(uint8_t *payload, uint32_t nof_bytes, rlc_a // Check poll bit if(header.p) { - log->info("%s Status packet requested through polling bit\n", rb_id_text[lcid]); + log->info("%s Status packet requested through polling bit\n", rrc->get_rb_name(lcid).c_str()); poll_received = true; // 36.322 v10 Section 5.2.3 @@ -901,12 +894,12 @@ void rlc_am::handle_data_pdu_segment(uint8_t *payload, uint32_t nof_bytes, rlc_a void rlc_am::handle_control_pdu(uint8_t *payload, uint32_t nof_bytes) { - log->info_hex(payload, nof_bytes, "%s Rx control PDU", rb_id_text[lcid]); + log->info_hex(payload, nof_bytes, "%s Rx control PDU", rrc->get_rb_name(lcid).c_str()); rlc_status_pdu_t status; rlc_am_read_status_pdu(payload, nof_bytes, &status); - log->info("%s Rx Status PDU: %s\n", rb_id_text[lcid], rlc_am_to_string(&status).c_str()); + log->info("%s Rx Status PDU: %s\n", rrc->get_rb_name(lcid).c_str(), rlc_am_to_string(&status).c_str()); poll_retx_timeout.reset(); @@ -944,7 +937,7 @@ void rlc_am::handle_control_pdu(uint8_t *payload, uint32_t nof_bytes) } } else { log->warning("%s invalid segment NACK received for SN %d. so_start: %d, so_end: %d, N_bytes: %d\n", - rb_id_text[lcid], i, status.nacks[j].so_start, status.nacks[j].so_end, it->second.buf->N_bytes); + rrc->get_rb_name(lcid).c_str(), i, status.nacks[j].so_start, status.nacks[j].so_end, it->second.buf->N_bytes); } } @@ -998,7 +991,7 @@ void rlc_am::reassemble_rx_sdus() rx_sdu->N_bytes += len; rx_window[vr_r].buf->msg += len; rx_window[vr_r].buf->N_bytes -= len; - log->info_hex(rx_sdu->msg, rx_sdu->N_bytes, "%s Rx SDU", rb_id_text[lcid]); + log->info_hex(rx_sdu->msg, rx_sdu->N_bytes, "%s Rx SDU", rrc->get_rb_name(lcid).c_str()); rx_sdu->set_timestamp(); pdcp->write_pdu(lcid, rx_sdu); rx_sdu = pool_allocate; @@ -1014,7 +1007,7 @@ void rlc_am::reassemble_rx_sdus() rx_sdu->N_bytes += rx_window[vr_r].buf->N_bytes; if(rlc_am_end_aligned(rx_window[vr_r].header.fi)) { - log->info_hex(rx_sdu->msg, rx_sdu->N_bytes, "%s Rx SDU", rb_id_text[lcid]); + log->info_hex(rx_sdu->msg, rx_sdu->N_bytes, "%s Rx SDU", rrc->get_rb_name(lcid).c_str()); rx_sdu->set_timestamp(); pdcp->write_pdu(lcid, rx_sdu); rx_sdu = pool_allocate; @@ -1058,7 +1051,7 @@ void rlc_am::debug_state() { log->debug("%s vt_a = %d, vt_ms = %d, vt_s = %d, poll_sn = %d " "vr_r = %d, vr_mr = %d, vr_x = %d, vr_ms = %d, vr_h = %d\n", - rb_id_text[lcid], vt_a, vt_ms, vt_s, poll_sn, + rrc->get_rb_name(lcid).c_str(), vt_a, vt_ms, vt_s, poll_sn, vr_r, vr_mr, vr_x, vr_ms, vr_h); } diff --git a/lib/src/upper/rlc_entity.cc b/lib/src/upper/rlc_entity.cc index ace991b10..247bf4409 100644 --- a/lib/src/upper/rlc_entity.cc +++ b/lib/src/upper/rlc_entity.cc @@ -64,7 +64,7 @@ void rlc_entity::init(rlc_mode_t mode, rlc->init(rlc_entity_log_, lcid_, pdcp_, rrc_, mac_timers_); } -void rlc_entity::configure(LIBLTE_RRC_RLC_CONFIG_STRUCT *cnfg) +void rlc_entity::configure(srslte_rlc_config_t cnfg) { if(rlc) rlc->configure(cnfg); @@ -76,6 +76,12 @@ void rlc_entity::reset() rlc = NULL; } + +void rlc_entity::empty_queue() +{ + rlc->empty_queue(); +} + bool rlc_entity::active() { return (rlc != NULL); diff --git a/lib/src/upper/rlc_tm.cc b/lib/src/upper/rlc_tm.cc index a515a77a5..e3bef0a99 100644 --- a/lib/src/upper/rlc_tm.cc +++ b/lib/src/upper/rlc_tm.cc @@ -46,7 +46,7 @@ void rlc_tm::init(srslte::log *log_, rrc = rrc_; } -void rlc_tm::configure(LIBLTE_RRC_RLC_CONFIG_STRUCT *cnfg) +void rlc_tm::configure(srslte_rlc_config_t cnfg) { log->error("Attempted to configure TM RLC entity"); } @@ -79,7 +79,7 @@ uint32_t rlc_tm::get_bearer() // PDCP interface void rlc_tm::write_sdu(byte_buffer_t *sdu) { - log->info_hex(sdu->msg, sdu->N_bytes, "%s Tx SDU", rb_id_text[lcid]); + log->info_hex(sdu->msg, sdu->N_bytes, "%s Tx SDU", rrc->get_rb_name(lcid).c_str()); ul_queue.write(sdu); } @@ -99,7 +99,7 @@ int rlc_tm::read_pdu(uint8_t *payload, uint32_t nof_bytes) uint32_t pdu_size = ul_queue.size_tail_bytes(); if(pdu_size > nof_bytes) { - log->error("TX %s PDU size larger than MAC opportunity\n", rb_id_text[lcid]); + log->error("TX %s PDU size larger than MAC opportunity\n", rrc->get_rb_name(lcid).c_str()); return 0; } byte_buffer_t *buf; @@ -107,13 +107,13 @@ int rlc_tm::read_pdu(uint8_t *payload, uint32_t nof_bytes) pdu_size = buf->N_bytes; memcpy(payload, buf->msg, buf->N_bytes); log->info("%s Complete SDU scheduled for tx. Stack latency: %ld us\n", - rb_id_text[lcid], buf->get_latency_us()); + rrc->get_rb_name(lcid).c_str(), buf->get_latency_us()); pool->deallocate(buf); - log->info_hex(payload, pdu_size, "TX %s, %s PDU", rb_id_text[lcid], rlc_mode_text[RLC_MODE_TM]); + log->info_hex(payload, pdu_size, "TX %s, %s PDU", rrc->get_rb_name(lcid).c_str(), rlc_mode_text[RLC_MODE_TM]); return pdu_size; } -void rlc_tm:: write_pdu(uint8_t *payload, uint32_t nof_bytes) +void rlc_tm::write_pdu(uint8_t *payload, uint32_t nof_bytes) { byte_buffer_t *buf = pool_allocate; memcpy(buf->msg, payload, nof_bytes); diff --git a/lib/src/upper/rlc_um.cc b/lib/src/upper/rlc_um.cc index 78fc0a68b..3d6bb9553 100644 --- a/lib/src/upper/rlc_um.cc +++ b/lib/src/upper/rlc_um.cc @@ -27,7 +27,7 @@ #include "srslte/upper/rlc_um.h" -#define RX_MOD_BASE(x) (x-vr_uh-rx_window_size)%rx_mod +#define RX_MOD_BASE(x) (x-vr_uh-cfg.rx_window_size)%cfg.rx_mod namespace srslte { @@ -65,41 +65,28 @@ void rlc_um::init(srslte::log *log_, reordering_timeout_id = mac_timers->get_unique_id(); } -void rlc_um::configure(LIBLTE_RRC_RLC_CONFIG_STRUCT *cnfg) +void rlc_um::configure(srslte_rlc_config_t cnfg_) { - switch(cnfg->rlc_mode) + cfg = cnfg_.um; + + switch(cnfg_.rlc_mode) { case LIBLTE_RRC_RLC_MODE_UM_BI: - t_reordering = liblte_rrc_t_reordering_num[cnfg->dl_um_bi_rlc.t_reordering]; - rx_sn_field_length = (rlc_umd_sn_size_t)cnfg->dl_um_bi_rlc.sn_field_len; - rx_window_size = (RLC_UMD_SN_SIZE_5_BITS == rx_sn_field_length) ? 16 : 512; - rx_mod = (RLC_UMD_SN_SIZE_5_BITS == rx_sn_field_length) ? 32 : 1024; - tx_sn_field_length = (rlc_umd_sn_size_t)cnfg->ul_um_bi_rlc.sn_field_len; - tx_mod = (RLC_UMD_SN_SIZE_5_BITS == tx_sn_field_length) ? 32 : 1024; log->info("%s configured in %s mode: " "t_reordering=%d ms, rx_sn_field_length=%u bits, tx_sn_field_length=%u bits\n", - rb_id_text[lcid], liblte_rrc_rlc_mode_text[cnfg->rlc_mode], - t_reordering, - rlc_umd_sn_size_num[rx_sn_field_length], - rlc_umd_sn_size_num[tx_sn_field_length]); + rrc->get_rb_name(lcid).c_str(), liblte_rrc_rlc_mode_text[cnfg_.rlc_mode], + cfg.t_reordering, rlc_umd_sn_size_num[cfg.rx_sn_field_length], rlc_umd_sn_size_num[cfg.rx_sn_field_length]); break; case LIBLTE_RRC_RLC_MODE_UM_UNI_UL: - tx_sn_field_length = (rlc_umd_sn_size_t)cnfg->ul_um_uni_rlc.sn_field_len; - tx_mod = (RLC_UMD_SN_SIZE_5_BITS == tx_sn_field_length) ? 32 : 1024; log->info("%s configured in %s mode: tx_sn_field_length=%u bits\n", - rb_id_text[lcid], liblte_rrc_rlc_mode_text[cnfg->rlc_mode], - rlc_umd_sn_size_num[tx_sn_field_length]); + rrc->get_rb_name(lcid).c_str(), liblte_rrc_rlc_mode_text[cnfg_.rlc_mode], + rlc_umd_sn_size_num[cfg.rx_sn_field_length]); break; case LIBLTE_RRC_RLC_MODE_UM_UNI_DL: - t_reordering = liblte_rrc_t_reordering_num[cnfg->dl_um_uni_rlc.t_reordering]; - rx_sn_field_length = (rlc_umd_sn_size_t)cnfg->dl_um_uni_rlc.sn_field_len; - rx_window_size = (RLC_UMD_SN_SIZE_5_BITS == rx_sn_field_length) ? 16 : 512; - rx_mod = (RLC_UMD_SN_SIZE_5_BITS == rx_sn_field_length) ? 32 : 1024; log->info("%s configured in %s mode: " "t_reordering=%d ms, rx_sn_field_length=%u bits\n", - rb_id_text[lcid], liblte_rrc_rlc_mode_text[cnfg->rlc_mode], - liblte_rrc_t_reordering_num[t_reordering], - rlc_umd_sn_size_num[rx_sn_field_length]); + rrc->get_rb_name(lcid).c_str(), liblte_rrc_rlc_mode_text[cnfg_.rlc_mode], + cfg.t_reordering, rlc_umd_sn_size_num[cfg.rx_sn_field_length]); break; default: log->error("RLC configuration mode not recognized\n"); @@ -159,7 +146,7 @@ uint32_t rlc_um::get_bearer() void rlc_um::write_sdu(byte_buffer_t *sdu) { - log->info_hex(sdu->msg, sdu->N_bytes, "%s Tx SDU", rb_id_text[lcid]); + log->info_hex(sdu->msg, sdu->N_bytes, "%s Tx SDU", rrc->get_rb_name(lcid).c_str()); tx_sdu_queue.write(sdu); } @@ -222,14 +209,14 @@ void rlc_um::timer_expired(uint32_t timeout_id) // 36.322 v10 Section 5.1.2.2.4 log->info("%s reordering timeout expiry - updating vr_ur and reassembling\n", - rb_id_text[lcid]); + rrc->get_rb_name(lcid).c_str()); log->warning("Lost PDU SN: %d\n", vr_ur); pdu_lost = true; rx_sdu->reset(); while(RX_MOD_BASE(vr_ur) < RX_MOD_BASE(vr_ux)) { - vr_ur = (vr_ur + 1)%rx_mod; + vr_ur = (vr_ur + 1)%cfg.rx_mod; log->debug("Entering Reassemble from timeout id=%d\n", timeout_id); reassemble_rx_sdus(); log->debug("Finished reassemble from timeout id=%d\n", timeout_id); @@ -237,7 +224,7 @@ void rlc_um::timer_expired(uint32_t timeout_id) mac_timers->get(reordering_timeout_id)->stop(); if(RX_MOD_BASE(vr_uh) > RX_MOD_BASE(vr_ur)) { - mac_timers->get(reordering_timeout_id)->set(this, t_reordering); + mac_timers->get(reordering_timeout_id)->set(this, cfg.t_reordering); mac_timers->get(reordering_timeout_id)->run(); vr_ux = vr_uh; } @@ -274,7 +261,7 @@ int rlc_um::build_data_pdu(uint8_t *payload, uint32_t nof_bytes) header.fi = RLC_FI_FIELD_START_AND_END_ALIGNED; header.sn = vt_us; header.N_li = 0; - header.sn_size = tx_sn_field_length; + header.sn_size = cfg.tx_sn_field_length; uint32_t to_move = 0; uint32_t last_li = 0; @@ -286,7 +273,7 @@ int rlc_um::build_data_pdu(uint8_t *payload, uint32_t nof_bytes) if(pdu_space <= head_len) { log->warning("%s Cannot build a PDU - %d bytes available, %d bytes required for header\n", - rb_id_text[lcid], nof_bytes, head_len); + rrc->get_rb_name(lcid).c_str(), nof_bytes, head_len); return 0; } @@ -296,7 +283,7 @@ int rlc_um::build_data_pdu(uint8_t *payload, uint32_t nof_bytes) uint32_t space = pdu_space-head_len; to_move = space >= tx_sdu->N_bytes ? tx_sdu->N_bytes : space; log->debug("%s adding remainder of SDU segment - %d bytes of %d remaining\n", - rb_id_text[lcid], to_move, tx_sdu->N_bytes); + rrc->get_rb_name(lcid).c_str(), to_move, tx_sdu->N_bytes); memcpy(pdu_ptr, tx_sdu->msg, to_move); last_li = to_move; pdu_ptr += to_move; @@ -306,7 +293,7 @@ int rlc_um::build_data_pdu(uint8_t *payload, uint32_t nof_bytes) if(tx_sdu->N_bytes == 0) { log->info("%s Complete SDU scheduled for tx. Stack latency: %ld us\n", - rb_id_text[lcid], tx_sdu->get_latency_us()); + rrc->get_rb_name(lcid).c_str(), tx_sdu->get_latency_us()); pool->deallocate(tx_sdu); tx_sdu = NULL; } @@ -325,7 +312,7 @@ int rlc_um::build_data_pdu(uint8_t *payload, uint32_t nof_bytes) uint32_t space = pdu_space-head_len; to_move = space >= tx_sdu->N_bytes ? tx_sdu->N_bytes : space; log->debug("%s adding new SDU segment - %d bytes of %d remaining\n", - rb_id_text[lcid], to_move, tx_sdu->N_bytes); + rrc->get_rb_name(lcid).c_str(), to_move, tx_sdu->N_bytes); memcpy(pdu_ptr, tx_sdu->msg, to_move); last_li = to_move; pdu_ptr += to_move; @@ -335,7 +322,7 @@ int rlc_um::build_data_pdu(uint8_t *payload, uint32_t nof_bytes) if(tx_sdu->N_bytes == 0) { log->info("%s Complete SDU scheduled for tx. Stack latency: %ld us\n", - rb_id_text[lcid], tx_sdu->get_latency_us()); + rrc->get_rb_name(lcid).c_str(), tx_sdu->get_latency_us()); pool->deallocate(tx_sdu); tx_sdu = NULL; } @@ -347,14 +334,14 @@ int rlc_um::build_data_pdu(uint8_t *payload, uint32_t nof_bytes) // Set SN header.sn = vt_us; - vt_us = (vt_us + 1)%tx_mod; + vt_us = (vt_us + 1)%cfg.tx_mod; // Add header and TX - log->debug("%s packing PDU with length %d\n", rb_id_text[lcid], pdu->N_bytes); + log->debug("%s packing PDU with length %d\n", rrc->get_rb_name(lcid).c_str(), pdu->N_bytes); rlc_um_write_data_pdu_header(&header, pdu); memcpy(payload, pdu->msg, pdu->N_bytes); uint32_t ret = pdu->N_bytes; - log->debug("%sreturning length %d\n", rb_id_text[lcid], pdu->N_bytes); + log->debug("%sreturning length %d\n", rrc->get_rb_name(lcid).c_str(), pdu->N_bytes); pool->deallocate(pdu); debug_state(); @@ -365,23 +352,23 @@ void rlc_um::handle_data_pdu(uint8_t *payload, uint32_t nof_bytes) { std::map::iterator it; rlc_umd_pdu_header_t header; - rlc_um_read_data_pdu_header(payload, nof_bytes, rx_sn_field_length, &header); + rlc_um_read_data_pdu_header(payload, nof_bytes, cfg.rx_sn_field_length, &header); log->info_hex(payload, nof_bytes, "RX %s Rx data PDU SN: %d", - rb_id_text[lcid], header.sn); + rrc->get_rb_name(lcid).c_str(), header.sn); - if(RX_MOD_BASE(header.sn) >= RX_MOD_BASE(vr_uh-rx_window_size) && + if(RX_MOD_BASE(header.sn) >= RX_MOD_BASE(vr_uh-cfg.rx_window_size) && RX_MOD_BASE(header.sn) < RX_MOD_BASE(vr_ur)) { log->info("%s SN: %d outside rx window [%d:%d] - discarding\n", - rb_id_text[lcid], header.sn, vr_ur, vr_uh); + rrc->get_rb_name(lcid).c_str(), header.sn, vr_ur, vr_uh); return; } it = rx_window.find(header.sn); if(rx_window.end() != it) { log->info("%s Discarding duplicate SN: %d\n", - rb_id_text[lcid], header.sn); + rrc->get_rb_name(lcid).c_str(), header.sn); return; } @@ -403,7 +390,7 @@ void rlc_um::handle_data_pdu(uint8_t *payload, uint32_t nof_bytes) // Update vr_uh if(!inside_reordering_window(header.sn)) - vr_uh = (header.sn + 1)%rx_mod; + vr_uh = (header.sn + 1)%cfg.rx_mod; // Reassemble and deliver SDUs, while updating vr_ur log->debug("Entering Reassemble from received PDU\n"); @@ -423,7 +410,7 @@ void rlc_um::handle_data_pdu(uint8_t *payload, uint32_t nof_bytes) { if(RX_MOD_BASE(vr_uh) > RX_MOD_BASE(vr_ur)) { - mac_timers->get(reordering_timeout_id)->set(this, t_reordering); + mac_timers->get(reordering_timeout_id)->set(this, cfg.t_reordering); mac_timers->get(reordering_timeout_id)->run(); vr_ux = vr_uh; } @@ -452,11 +439,11 @@ void rlc_um::reassemble_rx_sdus() rx_sdu->N_bytes += len; rx_window[vr_ur].buf->msg += len; rx_window[vr_ur].buf->N_bytes -= len; - if((pdu_lost && !rlc_um_start_aligned(rx_window[vr_ur].header.fi)) || (vr_ur != ((vr_ur_in_rx_sdu+1)%rx_mod))) { + if((pdu_lost && !rlc_um_start_aligned(rx_window[vr_ur].header.fi)) || (vr_ur != ((vr_ur_in_rx_sdu+1)%cfg.rx_mod))) { log->warning("Dropping remainder of lost PDU (lower edge middle segments, vr_ur=%d, vr_ur_in_rx_sdu=%d)\n", vr_ur, vr_ur_in_rx_sdu); rx_sdu->reset(); } else { - log->info_hex(rx_sdu->msg, rx_sdu->N_bytes, "%s Rx SDU vr_ur=%d, i=%d (lower edge middle segments)", rb_id_text[lcid], vr_ur, i); + log->info_hex(rx_sdu->msg, rx_sdu->N_bytes, "%s Rx SDU vr_ur=%d, i=%d (lower edge middle segments)", rrc->get_rb_name(lcid).c_str(), vr_ur, i); rx_sdu->set_timestamp(); pdcp->write_pdu(lcid, rx_sdu); rx_sdu = pool_allocate; @@ -476,7 +463,7 @@ void rlc_um::reassemble_rx_sdus() log->warning("Dropping remainder of lost PDU (lower edge last segments)\n"); rx_sdu->reset(); } else { - log->info_hex(rx_sdu->msg, rx_sdu->N_bytes, "%s Rx SDU vr_ur=%d (lower edge last segments)", rb_id_text[lcid], vr_ur); + log->info_hex(rx_sdu->msg, rx_sdu->N_bytes, "%s Rx SDU vr_ur=%d (lower edge last segments)", rrc->get_rb_name(lcid).c_str(), vr_ur); rx_sdu->set_timestamp(); pdcp->write_pdu(lcid, rx_sdu); rx_sdu = pool_allocate; @@ -489,7 +476,7 @@ void rlc_um::reassemble_rx_sdus() rx_window.erase(vr_ur); } - vr_ur = (vr_ur + 1)%rx_mod; + vr_ur = (vr_ur + 1)%cfg.rx_mod; } @@ -502,15 +489,15 @@ void rlc_um::reassemble_rx_sdus() int len = rx_window[vr_ur].header.li[i]; memcpy(&rx_sdu->msg[rx_sdu->N_bytes], rx_window[vr_ur].buf->msg, len); log->debug("Concatenating %d bytes in to current length %d. rx_window remaining bytes=%d, vr_ur_in_rx_sdu=%d, vr_ur=%d, rx_mod=%d, last_mod=%d\n", - len, rx_sdu->N_bytes, rx_window[vr_ur].buf->N_bytes, vr_ur_in_rx_sdu, vr_ur, rx_mod, (vr_ur_in_rx_sdu+1)%rx_mod); + len, rx_sdu->N_bytes, rx_window[vr_ur].buf->N_bytes, vr_ur_in_rx_sdu, vr_ur, cfg.rx_mod, (vr_ur_in_rx_sdu+1)%cfg.rx_mod); rx_sdu->N_bytes += len; rx_window[vr_ur].buf->msg += len; rx_window[vr_ur].buf->N_bytes -= len; - if((pdu_lost && !rlc_um_start_aligned(rx_window[vr_ur].header.fi)) || (vr_ur != ((vr_ur_in_rx_sdu+1)%rx_mod))) { + if((pdu_lost && !rlc_um_start_aligned(rx_window[vr_ur].header.fi)) || (vr_ur != ((vr_ur_in_rx_sdu+1)%cfg.rx_mod))) { log->warning("Dropping remainder of lost PDU (update vr_ur middle segments, vr_ur=%d, vr_ur_in_rx_sdu=%d)\n", vr_ur, vr_ur_in_rx_sdu); rx_sdu->reset(); } else { - log->info_hex(rx_sdu->msg, rx_sdu->N_bytes, "%s Rx SDU vr_ur=%d, i=%d, (update vr_ur middle segments)", rb_id_text[lcid], vr_ur, i); + log->info_hex(rx_sdu->msg, rx_sdu->N_bytes, "%s Rx SDU vr_ur=%d, i=%d, (update vr_ur middle segments)", rrc->get_rb_name(lcid).c_str(), vr_ur, i); rx_sdu->set_timestamp(); pdcp->write_pdu(lcid, rx_sdu); rx_sdu = pool_allocate; @@ -530,7 +517,7 @@ void rlc_um::reassemble_rx_sdus() log->warning("Dropping remainder of lost PDU (update vr_ur last segments)\n"); rx_sdu->reset(); } else { - log->info_hex(rx_sdu->msg, rx_sdu->N_bytes, "%s Rx SDU vr_ur=%d (update vr_ur last segments)", rb_id_text[lcid], vr_ur); + log->info_hex(rx_sdu->msg, rx_sdu->N_bytes, "%s Rx SDU vr_ur=%d (update vr_ur last segments)", rrc->get_rb_name(lcid).c_str(), vr_ur); rx_sdu->set_timestamp(); pdcp->write_pdu(lcid, rx_sdu); rx_sdu = pool_allocate; @@ -542,13 +529,13 @@ void rlc_um::reassemble_rx_sdus() pool->deallocate(rx_window[vr_ur].buf); rx_window.erase(vr_ur); - vr_ur = (vr_ur + 1)%rx_mod; + vr_ur = (vr_ur + 1)%cfg.rx_mod; } } bool rlc_um::inside_reordering_window(uint16_t sn) { - if(RX_MOD_BASE(sn) >= RX_MOD_BASE(vr_uh-rx_window_size) && + if(RX_MOD_BASE(sn) >= RX_MOD_BASE(vr_uh-cfg.rx_window_size) && RX_MOD_BASE(sn) < RX_MOD_BASE(vr_uh)) { return true; @@ -560,7 +547,7 @@ bool rlc_um::inside_reordering_window(uint16_t sn) void rlc_um::debug_state() { log->debug("%s vt_us = %d, vr_ur = %d, vr_ux = %d, vr_uh = %d \n", - rb_id_text[lcid], vt_us, vr_ur, vr_ux, vr_uh); + rrc->get_rb_name(lcid).c_str(), vt_us, vr_ur, vr_ux, vr_uh); } diff --git a/lib/test/upper/rlc_am_test.cc b/lib/test/upper/rlc_am_test.cc index dfe62905e..c7ab2aa74 100644 --- a/lib/test/upper/rlc_am_test.cc +++ b/lib/test/upper/rlc_am_test.cc @@ -67,6 +67,7 @@ public: // RRC interface void max_retx_attempted(){} + std::string get_rb_name(uint32_t lcid) { return std::string(""); } byte_buffer_t *sdus[10]; int n_sdus; @@ -101,6 +102,7 @@ void basic_test() cnfg.ul_am_rlc.max_retx_thresh = LIBLTE_RRC_MAX_RETX_THRESHOLD_T4; cnfg.ul_am_rlc.poll_byte = LIBLTE_RRC_POLL_BYTE_KB25; cnfg.ul_am_rlc.poll_pdu = LIBLTE_RRC_POLL_PDU_P4; + cnfg.ul_am_rlc.t_poll_retx = LIBLTE_RRC_T_POLL_RETRANSMIT_MS5; rlc1.configure(&cnfg); rlc2.configure(&cnfg); @@ -180,6 +182,7 @@ void concat_test() cnfg.ul_am_rlc.max_retx_thresh = LIBLTE_RRC_MAX_RETX_THRESHOLD_T4; cnfg.ul_am_rlc.poll_byte = LIBLTE_RRC_POLL_BYTE_KB25; cnfg.ul_am_rlc.poll_pdu = LIBLTE_RRC_POLL_PDU_P4; + cnfg.ul_am_rlc.t_poll_retx = LIBLTE_RRC_T_POLL_RETRANSMIT_MS5; rlc1.configure(&cnfg); rlc2.configure(&cnfg); @@ -244,6 +247,7 @@ void segment_test() cnfg.ul_am_rlc.max_retx_thresh = LIBLTE_RRC_MAX_RETX_THRESHOLD_T4; cnfg.ul_am_rlc.poll_byte = LIBLTE_RRC_POLL_BYTE_KB25; cnfg.ul_am_rlc.poll_pdu = LIBLTE_RRC_POLL_PDU_P4; + cnfg.ul_am_rlc.t_poll_retx = LIBLTE_RRC_T_POLL_RETRANSMIT_MS5; rlc1.configure(&cnfg); rlc2.configure(&cnfg); @@ -326,6 +330,7 @@ void retx_test() cnfg.ul_am_rlc.max_retx_thresh = LIBLTE_RRC_MAX_RETX_THRESHOLD_T4; cnfg.ul_am_rlc.poll_byte = LIBLTE_RRC_POLL_BYTE_KB25; cnfg.ul_am_rlc.poll_pdu = LIBLTE_RRC_POLL_PDU_P4; + cnfg.ul_am_rlc.t_poll_retx = LIBLTE_RRC_T_POLL_RETRANSMIT_MS5; rlc1.configure(&cnfg); rlc2.configure(&cnfg); @@ -422,6 +427,7 @@ void resegment_test_1() cnfg.ul_am_rlc.max_retx_thresh = LIBLTE_RRC_MAX_RETX_THRESHOLD_T4; cnfg.ul_am_rlc.poll_byte = LIBLTE_RRC_POLL_BYTE_KB25; cnfg.ul_am_rlc.poll_pdu = LIBLTE_RRC_POLL_PDU_P4; + cnfg.ul_am_rlc.t_poll_retx = LIBLTE_RRC_T_POLL_RETRANSMIT_MS5; rlc1.configure(&cnfg); rlc2.configure(&cnfg); @@ -531,6 +537,7 @@ void resegment_test_2() cnfg.ul_am_rlc.max_retx_thresh = LIBLTE_RRC_MAX_RETX_THRESHOLD_T4; cnfg.ul_am_rlc.poll_byte = LIBLTE_RRC_POLL_BYTE_KB25; cnfg.ul_am_rlc.poll_pdu = LIBLTE_RRC_POLL_PDU_P4; + cnfg.ul_am_rlc.t_poll_retx = LIBLTE_RRC_T_POLL_RETRANSMIT_MS5; rlc1.configure(&cnfg); rlc2.configure(&cnfg); @@ -637,6 +644,7 @@ void resegment_test_3() cnfg.ul_am_rlc.max_retx_thresh = LIBLTE_RRC_MAX_RETX_THRESHOLD_T4; cnfg.ul_am_rlc.poll_byte = LIBLTE_RRC_POLL_BYTE_KB25; cnfg.ul_am_rlc.poll_pdu = LIBLTE_RRC_POLL_PDU_P4; + cnfg.ul_am_rlc.t_poll_retx = LIBLTE_RRC_T_POLL_RETRANSMIT_MS5; rlc1.configure(&cnfg); rlc2.configure(&cnfg); @@ -739,6 +747,7 @@ void resegment_test_4() cnfg.ul_am_rlc.max_retx_thresh = LIBLTE_RRC_MAX_RETX_THRESHOLD_T4; cnfg.ul_am_rlc.poll_byte = LIBLTE_RRC_POLL_BYTE_KB25; cnfg.ul_am_rlc.poll_pdu = LIBLTE_RRC_POLL_PDU_P4; + cnfg.ul_am_rlc.t_poll_retx = LIBLTE_RRC_T_POLL_RETRANSMIT_MS5; rlc1.configure(&cnfg); rlc2.configure(&cnfg); @@ -841,6 +850,7 @@ void resegment_test_5() cnfg.ul_am_rlc.max_retx_thresh = LIBLTE_RRC_MAX_RETX_THRESHOLD_T4; cnfg.ul_am_rlc.poll_byte = LIBLTE_RRC_POLL_BYTE_KB25; cnfg.ul_am_rlc.poll_pdu = LIBLTE_RRC_POLL_PDU_P4; + cnfg.ul_am_rlc.t_poll_retx = LIBLTE_RRC_T_POLL_RETRANSMIT_MS5; rlc1.configure(&cnfg); rlc2.configure(&cnfg); @@ -942,6 +952,7 @@ void resegment_test_6() cnfg.ul_am_rlc.max_retx_thresh = LIBLTE_RRC_MAX_RETX_THRESHOLD_T4; cnfg.ul_am_rlc.poll_byte = LIBLTE_RRC_POLL_BYTE_KB25; cnfg.ul_am_rlc.poll_pdu = LIBLTE_RRC_POLL_PDU_P4; + cnfg.ul_am_rlc.t_poll_retx = LIBLTE_RRC_T_POLL_RETRANSMIT_MS5; rlc1.configure(&cnfg); rlc2.configure(&cnfg); diff --git a/lib/test/upper/rlc_um_test.cc b/lib/test/upper/rlc_um_test.cc index 491d816cc..739c9ebf8 100644 --- a/lib/test/upper/rlc_um_test.cc +++ b/lib/test/upper/rlc_um_test.cc @@ -71,6 +71,7 @@ public: // RRC interface void max_retx_attempted(){} + std::string get_rb_name(uint32_t lcid) { return std::string(""); } byte_buffer_t *sdus[5]; int n_sdus; diff --git a/srsenb/drb.conf.example b/srsenb/drb.conf.example index 4a2eab0d6..0f8e83372 100644 --- a/srsenb/drb.conf.example +++ b/srsenb/drb.conf.example @@ -15,14 +15,14 @@ qci_config = ( }; dl_um = { sn_field_length = 10; - t_reordering = 80; + t_reordering = 45; }; }; logical_channel_config = { - priority = 11; + priority = 13; prioritized_bit_rate = -1; bucket_size_duration = 100; - log_chan_group = 3; + log_chan_group = 2; }; }, { diff --git a/srsenb/enb.conf.example b/srsenb/enb.conf.example index cfba64a30..7446df122 100644 --- a/srsenb/enb.conf.example +++ b/srsenb/enb.conf.example @@ -57,8 +57,8 @@ drb_config = drb.conf ##################################################################### [rf] dl_earfcn = 3400 -tx_gain = 70 -rx_gain = 50 +tx_gain = 80 +rx_gain = 60 #device_name = auto #device_args = auto @@ -121,7 +121,7 @@ enable = false #pdsch_mcs = -1 #pdsch_max_mcs = -1 #pusch_mcs = -1 -pusch_max_mcs = 16 +#pusch_max_mcs = -1 nof_ctrl_symbols = 2 ##################################################################### @@ -141,9 +141,9 @@ nof_ctrl_symbols = 2 #pdsch_max_its = 4 #nof_phy_threads = 2 #pregenerate_signals = false -#tx_amplitude = 0.8 +#tx_amplitude = 0.6 #link_failure_nof_err = 50 -#rrc_inactivity_timer = 30000 +#rrc_inactivity_timer = 10000 #max_prach_offset_us = 30 ##################################################################### diff --git a/srsenb/hdr/mac/scheduler.h b/srsenb/hdr/mac/scheduler.h index 74ca8cc95..66f8998c1 100644 --- a/srsenb/hdr/mac/scheduler.h +++ b/srsenb/hdr/mac/scheduler.h @@ -108,7 +108,7 @@ public: int ul_crc_info(uint32_t tti, uint16_t rnti, bool crc); int ul_sr_info(uint32_t tti, uint16_t rnti); - int ul_bsr(uint16_t rnti, uint32_t lcid, uint32_t bsr); + int ul_bsr(uint16_t rnti, uint32_t lcid, uint32_t bsr, bool set_value = true); int ul_recv_len(uint16_t rnti, uint32_t lcid, uint32_t len); int ul_phr(uint16_t rnti, int phr); int ul_cqi_info(uint32_t tti, uint16_t rnti, uint32_t cqi, uint32_t ul_ch_code); diff --git a/srsenb/hdr/mac/scheduler_harq.h b/srsenb/hdr/mac/scheduler_harq.h index 9a38306ae..2e09136f9 100644 --- a/srsenb/hdr/mac/scheduler_harq.h +++ b/srsenb/hdr/mac/scheduler_harq.h @@ -104,7 +104,8 @@ public: void set_alloc(ul_alloc_t alloc); void same_alloc(); bool is_adaptive_retx(); - + + void reset_pending_data(); bool has_pending_ack(); uint32_t get_pending_data(); diff --git a/srsenb/hdr/mac/scheduler_ue.h b/srsenb/hdr/mac/scheduler_ue.h index fa38b2396..b95e5dda2 100644 --- a/srsenb/hdr/mac/scheduler_ue.h +++ b/srsenb/hdr/mac/scheduler_ue.h @@ -62,7 +62,7 @@ public: void rem_bearer(uint32_t lc_id); void dl_buffer_state(uint8_t lc_id, uint32_t tx_queue, uint32_t retx_queue); - void ul_buffer_state(uint8_t lc_id, uint32_t bsr); + void ul_buffer_state(uint8_t lc_id, uint32_t bsr, bool set_value = true); void ul_phr(int phr); void mac_buffer_state(uint32_t ce_code); void ul_recv_len(uint32_t lcid, uint32_t len); @@ -114,8 +114,10 @@ public: uint32_t get_max_retx(); bool get_pucch_sched(uint32_t current_tti, uint32_t prb_idx[2], uint32_t *L); - bool pucch_sr_collision(uint32_t current_tti, uint32_t n_cce); - + bool pucch_sr_collision(uint32_t current_tti, uint32_t n_cce); + + uint32_t get_pending_ul_old_data(); + private: typedef struct { @@ -126,12 +128,13 @@ private: } ue_bearer_t; bool is_sr_triggered(); - uint32_t get_pending_ul_old_data(); - int alloc_pdu(int tbs, sched_interface::dl_sched_pdu_t* pdu); + int alloc_pdu(int tbs, sched_interface::dl_sched_pdu_t* pdu); static uint32_t format1_count_prb(uint32_t bitmask, uint32_t cell_nof_prb); - static int cqi_to_tbs(uint32_t cqi, uint32_t nof_prb, uint32_t nof_re, uint32_t max_mcs, uint32_t *mcs); - static int alloc_tbs(uint32_t cqi, uint32_t nof_prb, uint32_t nof_re, uint32_t req_bytes, uint32_t max_mcs, int *mcs); + static int cqi_to_tbs(uint32_t cqi, uint32_t nof_prb, uint32_t nof_re, uint32_t max_mcs, uint32_t max_Qm, uint32_t *mcs); + int alloc_tbs_dl(uint32_t nof_prb, uint32_t nof_re, uint32_t req_bytes, int *mcs); + int alloc_tbs_ul(uint32_t nof_prb, uint32_t nof_re, uint32_t req_bytes, int *mcs); + int alloc_tbs(uint32_t nof_prb, uint32_t nof_re, uint32_t req_bytes, bool is_ul, int *mcs); static bool bearer_is_ul(ue_bearer_t *lch); static bool bearer_is_dl(ue_bearer_t *lch); diff --git a/srsenb/hdr/mac/ue.h b/srsenb/hdr/mac/ue.h index bb3597a04..b98b07f9d 100644 --- a/srsenb/hdr/mac/ue.h +++ b/srsenb/hdr/mac/ue.h @@ -58,6 +58,10 @@ public: } virtual ~ue() { + for (int i=0;i lc_groups[4]; mac_metrics_t metrics; diff --git a/srsenb/hdr/upper/common_enb.h b/srsenb/hdr/upper/common_enb.h index 9f15b69ae..d04869c54 100644 --- a/srsenb/hdr/upper/common_enb.h +++ b/srsenb/hdr/upper/common_enb.h @@ -43,6 +43,32 @@ namespace srsenb { #define SRSENB_N_DRB 8 #define SRSENB_N_RADIO_BEARERS 11 +typedef enum{ + RB_ID_SRB0 = 0, + RB_ID_SRB1, + RB_ID_SRB2, + RB_ID_DRB1, + RB_ID_DRB2, + RB_ID_DRB3, + RB_ID_DRB4, + RB_ID_DRB5, + RB_ID_DRB6, + RB_ID_DRB7, + RB_ID_DRB8, + RB_ID_N_ITEMS, +}rb_id_t; +static const char rb_id_text[RB_ID_N_ITEMS][20] = { "SRB0", + "SRB1", + "SRB2", + "DRB1", + "DRB2", + "DRB3", + "DRB4", + "DRB5", + "DRB6", + "DRB7", + "DRB8"}; + // Cat 3 UE - Max number of DL-SCH transport block bits received within a TTI // 3GPP 36.306 Table 4.1.1 #define SRSENB_MAX_BUFFER_SIZE_BITS 102048 diff --git a/srsenb/hdr/upper/pdcp.h b/srsenb/hdr/upper/pdcp.h index 44c59b8e6..228490312 100644 --- a/srsenb/hdr/upper/pdcp.h +++ b/srsenb/hdr/upper/pdcp.h @@ -51,7 +51,7 @@ public: void add_user(uint16_t rnti); void rem_user(uint16_t rnti); void write_sdu(uint16_t rnti, uint32_t lcid, srslte::byte_buffer_t *sdu); - void add_bearer(uint16_t rnti, uint32_t lcid, LIBLTE_RRC_PDCP_CONFIG_STRUCT *cnfg=NULL); + void add_bearer(uint16_t rnti, uint32_t lcid, srslte::srslte_pdcp_config_t cnfg); void config_security(uint16_t rnti, uint32_t lcid, uint8_t *k_rrc_enc_, @@ -89,6 +89,7 @@ private: void write_pdu_bcch_bch(srslte::byte_buffer_t *pdu); void write_pdu_bcch_dlsch(srslte::byte_buffer_t *pdu); void write_pdu_pcch(srslte::byte_buffer_t *pdu); + std::string get_rb_name(uint32_t lcid); }; class user_interface diff --git a/srsenb/hdr/upper/rlc.h b/srsenb/hdr/upper/rlc.h index c979f6af8..abbf99516 100644 --- a/srsenb/hdr/upper/rlc.h +++ b/srsenb/hdr/upper/rlc.h @@ -50,10 +50,11 @@ public: void add_user(uint16_t rnti); void rem_user(uint16_t rnti); void add_bearer(uint16_t rnti, uint32_t lcid); - void add_bearer(uint16_t rnti, uint32_t lcid, LIBLTE_RRC_RLC_CONFIG_STRUCT *cnfg); + void add_bearer(uint16_t rnti, uint32_t lcid, srslte::srslte_rlc_config_t cnfg); // rlc_interface_pdcp void write_sdu(uint16_t rnti, uint32_t lcid, srslte::byte_buffer_t *sdu); + std::string get_rb_name(uint32_t lcid); // rlc_interface_mac int read_pdu(uint16_t rnti, uint32_t lcid, uint8_t *payload, uint32_t nof_bytes); @@ -73,6 +74,7 @@ private: void write_pdu_bcch_dlsch(srslte::byte_buffer_t *sdu); void write_pdu_pcch(srslte::byte_buffer_t *sdu); void max_retx_attempted(); + std::string get_rb_name(uint32_t lcid); uint16_t rnti; srsenb::pdcp_interface_rlc *pdcp; diff --git a/srsenb/rr.conf.example b/srsenb/rr.conf.example index 33a625359..af6dcf2c1 100644 --- a/srsenb/rr.conf.example +++ b/srsenb/rr.conf.example @@ -9,7 +9,7 @@ mac_cnfg = ulsch_cnfg = { max_harq_tx = 4; - periodic_bsr_timer = 5; // in ms + periodic_bsr_timer = 40; // in ms retx_bsr_timer = 320; // in ms }; @@ -28,7 +28,7 @@ phy_cnfg = { beta_offset_ack_idx = 10; beta_offset_ri_idx = 5; - beta_offset_cqi_idx = 5; + beta_offset_cqi_idx = 10; }; // PUCCH-SR resources are scheduled on time-frequeny domain first, then multiplexed in the same resource. diff --git a/srsenb/sib.conf.example b/srsenb/sib.conf.example index 1ccfe5465..f23d18981 100644 --- a/srsenb/sib.conf.example +++ b/srsenb/sib.conf.example @@ -23,9 +23,9 @@ sib2 = rach_cnfg = { num_ra_preambles = 52; - preamble_init_rx_target_pwr = -108; + preamble_init_rx_target_pwr = -104; pwr_ramping_step = 6; // in dB - preamble_trans_max = 7; + preamble_trans_max = 10; ra_resp_win_size = 10; // in ms mac_con_res_timer = 64; // in ms max_harq_msg3_tx = 4; @@ -53,14 +53,14 @@ sib2 = pdsch_cnfg = { p_b = 0; - rs_power = -4; + rs_power = 20; }; pusch_cnfg = { n_sb = 1; hopping_mode = "inter-subframe"; pusch_hopping_offset = 2; - enable_64_qam = false; + enable_64_qam = false; // 64QAM PUSCH is not currently enabled ul_rs = { cyclic_shift = 0; @@ -71,25 +71,25 @@ sib2 = }; pucch_cnfg = { - delta_pucch_shift = 1; - n_rb_cqi = 1; + delta_pucch_shift = 2; + n_rb_cqi = 2; n_cs_an = 0; - n1_pucch_an = 2; + n1_pucch_an = 12; }; ul_pwr_ctrl = { - p0_nominal_pusch = -108; - alpha = 1.0; - p0_nominal_pucch = -88; + p0_nominal_pusch = -85; + alpha = 0.7; + p0_nominal_pucch = -107; delta_flist_pucch = { - format_1 = 2; + format_1 = 0; format_1b = 3; - format_2 = 0; - format_2a = 0; - format_2b = 0; + format_2 = 1; + format_2a = 2; + format_2b = 2; }; - delta_preamble_msg3 = 4; + delta_preamble_msg3 = 8; }; ul_cp_length = "Normal"; }; diff --git a/srsenb/src/CMakeLists.txt b/srsenb/src/CMakeLists.txt index a83e974a8..ef66c03a8 100644 --- a/srsenb/src/CMakeLists.txt +++ b/srsenb/src/CMakeLists.txt @@ -44,3 +44,5 @@ if (NOT ${BUILDENB_CMD} STREQUAL "") else(NOT ${BUILDENB_CMD} STREQUAL "") message(STATUS "No post-build-ENB command defined") endif (NOT ${BUILDENB_CMD} STREQUAL "") + +install(TARGETS srsenb DESTINATION ${RUNTIME_DIR}) diff --git a/srsenb/src/mac/mac.cc b/srsenb/src/mac/mac.cc index 8bf88a662..fb2c3110e 100644 --- a/srsenb/src/mac/mac.cc +++ b/srsenb/src/mac/mac.cc @@ -33,6 +33,7 @@ #include #include #include +#include #include "srslte/common/log.h" #include "mac/mac.h" @@ -163,7 +164,9 @@ int mac::rlc_buffer_state(uint16_t rnti, uint32_t lc_id, uint32_t tx_queue, uint int mac::bearer_ue_cfg(uint16_t rnti, uint32_t lc_id, sched_interface::ue_bearer_cfg_t* cfg) { - if (ue_db.count(rnti)) { + if (ue_db.count(rnti)) { + // configure BSR group in UE + ue_db[rnti]->set_lcg(lc_id, (uint32_t) cfg->group); return scheduler.bearer_ue_cfg(rnti, lc_id, cfg); } else { Error("User rnti=0x%x not found\n", rnti); @@ -259,7 +262,7 @@ void mac::rl_failure(uint16_t rnti) if (ue_db.count(rnti)) { uint32_t nof_fails = ue_db[rnti]->rl_failure(); if (nof_fails >= (uint32_t) args.link_failure_nof_err && args.link_failure_nof_err > 0) { - Info("Detected PUSCH failure for rnti=0x%x\n", rnti); + Info("Detected Uplink failure for rnti=0x%x\n", rnti); rrc_h->rl_failure(rnti); ue_db[rnti]->rl_failure_reset(); } @@ -384,7 +387,7 @@ int mac::rach_detected(uint32_t tti, uint32_t preamble_idx, uint32_t time_adv) } // Save RA info pending_rars[ra_id].preamble_idx = preamble_idx; - pending_rars[ra_id].ta_cmd = time_adv; + pending_rars[ra_id].ta_cmd = 2*time_adv; pending_rars[ra_id].temp_crnti = last_rnti; // Add new user to the scheduler so that it can RX/TX SRB0 diff --git a/srsenb/src/mac/scheduler.cc b/srsenb/src/mac/scheduler.cc index 5a9a8a6e5..12a7ea1cc 100644 --- a/srsenb/src/mac/scheduler.cc +++ b/srsenb/src/mac/scheduler.cc @@ -302,12 +302,12 @@ int sched::ul_cqi_info(uint32_t tti, uint16_t rnti, uint32_t cqi, uint32_t ul_ch return ret; } -int sched::ul_bsr(uint16_t rnti, uint32_t lcid, uint32_t bsr) +int sched::ul_bsr(uint16_t rnti, uint32_t lcid, uint32_t bsr, bool set_value) { pthread_mutex_lock(&mutex); int ret = 0; if (ue_db.count(rnti)) { - ue_db[rnti].ul_buffer_state(lcid, bsr); + ue_db[rnti].ul_buffer_state(lcid, bsr, set_value); } else { Error("User rnti=0x%x not found\n", rnti); ret = -1; @@ -792,13 +792,13 @@ int sched::ul_sched(uint32_t tti, srsenb::sched_interface::ul_sched_res_t* sched user->unset_sr(); } - log_h->info("SCHED: %s %s rnti=0x%x, pid=%d, dci=%d,%d, grant=%d,%d, n_rtx=%d, tbs=%d, bsr=%d (%d)\n", + log_h->info("SCHED: %s %s rnti=0x%x, pid=%d, dci=%d,%d, grant=%d,%d, n_rtx=%d, tbs=%d, bsr=%d (%d-%d)\n", is_rar?"RAR":"UL", is_newtx?"tx":"retx", rnti, h->get_id(), sched_result->pusch[nof_dci_elems].dci_location.L, sched_result->pusch[nof_dci_elems].dci_location.ncce, alloc.RB_start, alloc.L, h->nof_retx(), sched_result->pusch[nof_dci_elems].tbs, - user->get_pending_ul_new_data(current_tti),pending_data_before); + user->get_pending_ul_new_data(current_tti),pending_data_before, user->get_pending_ul_old_data()); nof_dci_elems++; } else { @@ -812,8 +812,16 @@ int sched::ul_sched(uint32_t tti, srsenb::sched_interface::ul_sched_res_t* sched } } } - } - + } + + // Update pending data counters after this TTI + for(std::map::iterator iter=ue_db.begin(); iter!=ue_db.end(); ++iter) { + sched_ue *user = (sched_ue *) &iter->second; + uint16_t rnti = (uint16_t) iter->first; + + user->get_ul_harq(current_tti)->reset_pending_data(); + } + sched_result->nof_dci_elems = nof_dci_elems; sched_result->nof_phich_elems = nof_phich_elems; diff --git a/srsenb/src/mac/scheduler_harq.cc b/srsenb/src/mac/scheduler_harq.cc index 4651b5533..009872153 100644 --- a/srsenb/src/mac/scheduler_harq.cc +++ b/srsenb/src/mac/scheduler_harq.cc @@ -98,7 +98,7 @@ bool harq_proc::get_ack() void harq_proc::set_ack(bool ack_) { ack = ack_; - ack_received = true; + ack_received = true; log_h->debug("ACK=%d received pid=%d, n_rtx=%d, max_retx=%d\n", ack_, id, n_rtx, max_retx); if (n_rtx >= max_retx) { Warning("SCHED: discarting TB pid=%d, tti=%d, maximum number of retx exceeded (%d)\n", id, tti, max_retx); @@ -229,13 +229,22 @@ bool ul_harq_proc::has_pending_ack() active = false; } if (!active) { - pending_data = 0; - need_ack = false; + need_ack = false; } return ret; } -uint32_t ul_harq_proc::get_pending_data() + + +void ul_harq_proc::reset_pending_data() +{ + if (!active) { + pending_data = 0; + } +} + + + uint32_t ul_harq_proc::get_pending_data() { return pending_data; } diff --git a/srsenb/src/mac/scheduler_ue.cc b/srsenb/src/mac/scheduler_ue.cc index 178fe6446..21aa61b19 100644 --- a/srsenb/src/mac/scheduler_ue.cc +++ b/srsenb/src/mac/scheduler_ue.cc @@ -26,6 +26,8 @@ #include #include +#include +#include #include "srslte/srslte.h" #include "srslte/common/pdu.h" @@ -163,12 +165,17 @@ void sched_ue::phy_config_enabled(uint32_t tti, bool enabled) phy_config_dedicated_enabled = enabled; } -void sched_ue::ul_buffer_state(uint8_t lc_id, uint32_t bsr) +void sched_ue::ul_buffer_state(uint8_t lc_id, uint32_t bsr, bool set_value) { if (lc_id < sched_interface::MAX_LC) { - lch[lc_id].bsr = bsr; - Debug("SCHED: UL lcid=%d buffer_state=%d\n", lc_id, bsr); - } + if (set_value) { + lch[lc_id].bsr = bsr; + } else { + lch[lc_id].bsr += bsr; + } + } + Debug("SCHED: bsr=%d, lcid=%d, bsr={%d,%d,%d,%d}\n", bsr, lc_id, + lch[0].bsr, lch[1].bsr, lch[2].bsr, lch[3].bsr); } void sched_ue::ul_phr(int phr) @@ -230,7 +237,8 @@ bool sched_ue::get_pucch_sched(uint32_t current_tti, uint32_t prb_idx[2], uint32 if (!phy_config_dedicated_enabled) { return false; } - srslte_pucch_sched_t pucch_sched; + srslte_pucch_sched_t pucch_sched; + pucch_sched.sps_enabled = false; pucch_sched.n_pucch_sr = cfg.sr_N_pucch; pucch_sched.n_pucch_2 = cfg.n_pucch_cqi; pucch_sched.N_pucch_1 = cfg.pucch_cfg.n1_pucch_an; @@ -239,7 +247,7 @@ bool sched_ue::get_pucch_sched(uint32_t current_tti, uint32_t prb_idx[2], uint32 // First check if it has pending ACKs for (int i=0;i 0 && coderate >= max_coderate); + coderate = srslte_coderate(tbs, nof_re); + Qm = SRSLTE_MIN(max_Qm, srslte_mod_bits_x_symbol(srslte_ra_mod_from_mcs(sel_mcs))); + eff_coderate = coderate/Qm; + } while((sel_mcs > 0 && coderate > max_coderate) || eff_coderate > 0.930); if (mcs) { *mcs = (uint32_t) sel_mcs; } return tbs; } -/* In this scheduler we tend to use all the available bandwidth and select the MCS +int sched_ue::alloc_tbs_dl(uint32_t nof_prb, + uint32_t nof_re, + uint32_t req_bytes, + int *mcs) +{ + return alloc_tbs(nof_prb, nof_re, req_bytes, false, mcs); +} + +int sched_ue::alloc_tbs_ul(uint32_t nof_prb, + uint32_t nof_re, + uint32_t req_bytes, + int *mcs) +{ + return alloc_tbs(nof_prb, nof_re, req_bytes, true, mcs); +} + + /* In this scheduler we tend to use all the available bandwidth and select the MCS * that approximates the minimum between the capacity and the requested rate */ -int sched_ue::alloc_tbs(uint32_t cqi, - uint32_t nof_prb, - uint32_t nof_re, - uint32_t req_bytes, - uint32_t max_mcs, - int *mcs) -{ - uint32_t sel_mcs = 0; - int tbs = cqi_to_tbs(cqi, nof_prb, nof_re, max_mcs, &sel_mcs)/8; +int sched_ue::alloc_tbs(uint32_t nof_prb, + uint32_t nof_re, + uint32_t req_bytes, + bool is_ul, + int *mcs) +{ + uint32_t sel_mcs = 0; + + uint32_t cqi = is_ul?ul_cqi:dl_cqi; + uint32_t max_mcs = is_ul?max_mcs_ul:max_mcs_dl; + uint32_t max_Qm = is_ul?4:6; // Allow 16-QAM in PUSCH Only + + int tbs = cqi_to_tbs(cqi, nof_prb, nof_re, max_mcs, max_Qm, &sel_mcs)/8; /* If less bytes are requested, lower the MCS */ if (tbs > (int) req_bytes && req_bytes > 0) { diff --git a/srsenb/src/mac/ue.cc b/srsenb/src/mac/ue.cc index cae9b6899..0b9776918 100644 --- a/srsenb/src/mac/ue.cc +++ b/srsenb/src/mac/ue.cc @@ -58,8 +58,14 @@ void ue::config(uint16_t rnti_, uint32_t nof_prb, sched_interface *sched_, rrc_i for(int i=0;iwrite_ul_crnti(pdu, nof_bytes, rnti, true, last_tti); } + + uint32_t lcid_most_data = 0; + int most_data = -99; while(mac_msg_ul.next()) { assert(mac_msg_ul.get()); - if (mac_msg_ul.get()->is_sdu()) - { + if (mac_msg_ul.get()->is_sdu()) { // Route logical channel - log_h->debug_hex(mac_msg_ul.get()->get_sdu_ptr(), mac_msg_ul.get()->get_payload_size(), - "PDU: rnti=0x%x, lcid=%d, %d bytes\n", - rnti, mac_msg_ul.get()->get_sdu_lcid(), mac_msg_ul.get()->get_payload_size()); - - + log_h->debug_hex(mac_msg_ul.get()->get_sdu_ptr(), mac_msg_ul.get()->get_payload_size(), + "PDU: rnti=0x%x, lcid=%d, %d bytes\n", + rnti, mac_msg_ul.get()->get_sdu_lcid(), mac_msg_ul.get()->get_payload_size()); + + /* In some cases, an uplink transmission with only CQI has all zeros and gets routed to RRC * Compute the checksum if lcid=0 and avoid routing in that case */ - bool route_pdu = true; + bool route_pdu = true; if (mac_msg_ul.get()->get_sdu_lcid() == 0) { uint8_t *x = mac_msg_ul.get()->get_sdu_ptr(); - uint32_t sum = 0; - for (uint32_t i=0;iget_payload_size();i++) { + uint32_t sum = 0; + for (uint32_t i = 0; i < mac_msg_ul.get()->get_payload_size(); i++) { sum += x[i]; } if (sum == 0) { - route_pdu = false; + route_pdu = false; Warning("Received all zero PDU\n"); } } - + if (route_pdu) { - rlc->write_pdu(rnti, - mac_msg_ul.get()->get_sdu_lcid(), - mac_msg_ul.get()->get_sdu_ptr(), - mac_msg_ul.get()->get_payload_size()); + rlc->write_pdu(rnti, + mac_msg_ul.get()->get_sdu_lcid(), + mac_msg_ul.get()->get_sdu_ptr(), + mac_msg_ul.get()->get_payload_size()); } - + // Indicate scheduler to update BSR counters sched->ul_recv_len(rnti, mac_msg_ul.get()->get_sdu_lcid(), mac_msg_ul.get()->get_payload_size()); - + + if ((int) mac_msg_ul.get()->get_payload_size() > most_data) { + most_data = (int) mac_msg_ul.get()->get_payload_size(); + lcid_most_data = mac_msg_ul.get()->get_sdu_lcid(); + } + // Save contention resolution if lcid == 0 if (mac_msg_ul.get()->get_sdu_lcid() == 0 && route_pdu) { - uint32_t nbytes = srslte::sch_subh::MAC_CE_CONTRES_LEN; + uint32_t nbytes = srslte::sch_subh::MAC_CE_CONTRES_LEN; if (mac_msg_ul.get()->get_payload_size() >= nbytes) { - uint8_t *ue_cri_ptr = (uint8_t*) &conres_id; - uint8_t *pkt_ptr = mac_msg_ul.get()->get_sdu_ptr(); // Warning here: we want to include the - for (uint32_t i=0;iget_sdu_ptr(); // Warning here: we want to include the + for (uint32_t i = 0; i < nbytes; i++) { + ue_cri_ptr[nbytes - i - 1] = pkt_ptr[i]; } } else { Error("Received CCCH UL message of invalid size=%d bytes\n", mac_msg_ul.get()->get_payload_size()); } - } - } else { - // Process MAC Control Element - if (!process_ce(mac_msg_ul.get())) { - Warning("Received Subheader with invalid or unkonwn LCID\n"); } } - } + } + mac_msg_ul.reset(); + + /* Process CE after all SDUs because we need to update BSR after */ + bool bsr_received = false; + while(mac_msg_ul.next()) { + assert(mac_msg_ul.get()); + if (!mac_msg_ul.get()->is_sdu()) { + // Process MAC Control Element + bsr_received |= process_ce(mac_msg_ul.get()); + } + } + + // If BSR is not received means that new data has arrived and there is no space for BSR transmission + if (!bsr_received && lcid_most_data > 2) { + // Add BSR to the LCID for which most data was received + sched->ul_bsr(rnti, lcid_most_data, 256, false); // false adds BSR instead of setting + Debug("BSR not received. Giving extra grant\n"); + } Debug("MAC PDU processed\n"); @@ -220,9 +255,10 @@ void ue::push_pdu(uint32_t tti, uint32_t len) bool ue::process_ce(srslte::sch_subh *subh) { uint32_t buff_size[4] = {0, 0, 0, 0}; - uint32_t idx = 0; - float phr = 0; - uint16_t old_rnti = 0; + float phr = 0; + int idx = 0; + uint16_t old_rnti = 0; + bool is_bsr = false; switch(subh->ce_type()) { case srslte::sch_subh::PHR_REPORT: phr = subh->get_phr(); @@ -241,23 +277,26 @@ bool ue::process_ce(srslte::sch_subh *subh) { } break; case srslte::sch_subh::TRUNC_BSR: - case srslte::sch_subh::SHORT_BSR: - case srslte::sch_subh::LONG_BSR: + case srslte::sch_subh::SHORT_BSR: idx = subh->get_bsr(buff_size); - if (idx > 0) { - // Indicate BSR to scheduler - sched->ul_bsr(rnti, idx, buff_size[idx]); - Info("CE: Received BSR rnti=0x%x, lcid=%d, value=%d\n", rnti, idx, buff_size[idx]); - } else if (idx == 0) { - // TODO: map lcid group to lcid - for (int i=0;i<4;i++) { - sched->ul_bsr(rnti, i, buff_size[i]); + for (uint32_t i=0;iul_bsr(rnti, lc_groups[idx][i], buff_size[idx]); + } + Info("CE: Received %s BSR rnti=0x%x, lcg=%d, value=%d\n", + subh->ce_type()==srslte::sch_subh::SHORT_BSR?"Short":"Trunc", rnti, idx, buff_size[idx]); + is_bsr = true; + break; + case srslte::sch_subh::LONG_BSR: + subh->get_bsr(buff_size); + for (int idx=0;idx<4;idx++) { + for (uint32_t i=0;iul_bsr(rnti, lc_groups[idx][i], buff_size[idx]); } - Info("CE: Received Long BSR rnti=0x%x, value=%d,%d,%d,%d\n", rnti, - buff_size[0], buff_size[1], buff_size[2], buff_size[3]); - } else { - printf("Error!\n"); } + is_bsr = true; + Info("CE: Received Long BSR rnti=0x%x, value=%d,%d,%d,%d\n", rnti, + buff_size[0], buff_size[1], buff_size[2], buff_size[3]); break; case srslte::sch_subh::PADDING: Debug("CE: Received padding for rnti=0x%x\n", rnti); @@ -266,7 +305,7 @@ bool ue::process_ce(srslte::sch_subh *subh) { Error("CE: Invalid lcid=0x%x\n", subh->ce_type()); break; } - return true; + return is_bsr; } diff --git a/srsenb/src/main.cc b/srsenb/src/main.cc index 92669ba69..1e337b3ba 100644 --- a/srsenb/src/main.cc +++ b/srsenb/src/main.cc @@ -130,7 +130,7 @@ void parse_args(all_args_t *args, int argc, char* argv[]) { bpo::value(&args->expert.mac.sched.pusch_mcs)->default_value(-1), "Optional fixed PUSCH MCS (ignores reported CQIs if specified)") ("scheduler.pusch_max_mcs", - bpo::value(&args->expert.mac.sched.pusch_max_mcs)->default_value(16), + bpo::value(&args->expert.mac.sched.pusch_max_mcs)->default_value(-1), "Optional PUSCH MCS limit") ("scheduler.nof_ctrl_symbols", bpo::value(&args->expert.mac.sched.nof_ctrl_symbols)->default_value(3), @@ -152,7 +152,7 @@ void parse_args(all_args_t *args, int argc, char* argv[]) { "Maximum number of turbo decoder iterations") ("expert.tx_amplitude", - bpo::value(&args->expert.phy.tx_amplitude)->default_value(0.8), + bpo::value(&args->expert.phy.tx_amplitude)->default_value(0.6), "Transmit amplitude factor") ("expert.nof_phy_threads", @@ -176,7 +176,7 @@ void parse_args(all_args_t *args, int argc, char* argv[]) { "Chooses the coefficients for the 3-tap channel estimator centered filter.") ("expert.rrc_inactivity_timer", - bpo::value(&args->expert.rrc_inactivity_timer)->default_value(30000), + bpo::value(&args->expert.rrc_inactivity_timer)->default_value(10000), "Inactivity timer in ms") diff --git a/srsenb/src/phy/phch_worker.cc b/srsenb/src/phy/phch_worker.cc index eca637635..f10ebdfa8 100644 --- a/srsenb/src/phy/phch_worker.cc +++ b/srsenb/src/phy/phch_worker.cc @@ -49,6 +49,8 @@ using namespace std; #ifdef ENABLE_GUI #include "srsgui/srsgui.h" #include +#include + void init_plots(srsenb::phch_worker *worker); pthread_t plot_thread; sem_t plot_sem; @@ -109,7 +111,7 @@ void phch_worker::init(phch_common* phy_, srslte::log *log_h_) return; } - srslte_pucch_set_threshold(&enb_ul.pucch, 0.8, 0.5); + srslte_pucch_set_threshold(&enb_ul.pucch, 0.8); srslte_sch_set_max_noi(&enb_ul.pusch.ul_sch, phy->params.pusch_max_its); srslte_enb_dl_set_amp(&enb_dl, phy->params.tx_amplitude); @@ -178,8 +180,8 @@ void phch_worker::set_config_dedicated(uint16_t rnti, srslte_enb_ul_cfg_ue(&enb_ul, rnti, uci_cfg, pucch_sched, srs_cfg); ue_db[rnti].I_sr = I_sr; - ue_db[rnti].I_sr_en = true; - + ue_db[rnti].I_sr_en = true; + if (pucch_cqi) { ue_db[rnti].pmi_idx = pmi_idx; ue_db[rnti].cqi_en = true; @@ -355,7 +357,6 @@ int phch_worker::decode_pusch(srslte_enb_ul_pusch_t *grants, uint32_t nof_pusch, } if (cqi_enabled) { uci_data.uci_cqi_len = srslte_cqi_size(&cqi_value); - Info("cqi enabled len=%d\n", uci_data.uci_cqi_len); } // mark this tti as having an ul grant to avoid pucch @@ -364,7 +365,11 @@ int phch_worker::decode_pusch(srslte_enb_ul_pusch_t *grants, uint32_t nof_pusch, srslte_ra_ul_grant_t phy_grant; int res = -1; if (!srslte_ra_ul_dci_to_grant(&grants[i].grant, enb_ul.cell.nof_prb, n_rb_ho, &phy_grant, tti%8)) { - res = srslte_enb_ul_get_pusch(&enb_ul, &phy_grant, grants[i].softbuffer, + if (phy_grant.mcs.mod == SRSLTE_MOD_64QAM) { + phy_grant.mcs.mod = SRSLTE_MOD_16QAM; + } + phy_grant.Qm = SRSLTE_MIN(phy_grant.Qm, 4); + res = srslte_enb_ul_get_pusch(&enb_ul, &phy_grant, grants[i].softbuffer, rnti, grants[i].rv_idx, grants[i].current_tx_nb, grants[i].data, @@ -415,7 +420,7 @@ int phch_worker::decode_pusch(srslte_enb_ul_pusch_t *grants, uint32_t nof_pusch, } */ log_h->info_hex(grants[i].data, phy_grant.mcs.tbs/8, - "PUSCH: rnti=0x%x, prb=(%d,%d), tbs=%d, mcs=%d, rv=%d, snr=%.1f dB, n_iter=%d, crc=%s%s%s%s\n", + "PUSCH: rnti=0x%x, prb=(%d,%d), tbs=%d, mcs=%d, rv=%d, snr=%.1f dB, n_iter=%d, crc=%s%s%s%s\n", rnti, phy_grant.n_prb[0], phy_grant.n_prb[0]+phy_grant.L_prb, phy_grant.mcs.tbs/8, phy_grant.mcs.idx, grants[i].grant.rv_idx, snr_db, diff --git a/srsenb/src/upper/pdcp.cc b/srsenb/src/upper/pdcp.cc index 772184fbd..027f04909 100644 --- a/srsenb/src/upper/pdcp.cc +++ b/srsenb/src/upper/pdcp.cc @@ -25,6 +25,7 @@ */ #include "upper/pdcp.h" +#include "upper/common_enb.h" namespace srsenb { @@ -50,7 +51,7 @@ void pdcp::add_user(uint16_t rnti) { if (users.count(rnti) == 0) { srslte::pdcp *obj = new srslte::pdcp; - obj->init(&users[rnti].rlc_itf, &users[rnti].rrc_itf, &users[rnti].gtpu_itf, log_h, SECURITY_DIRECTION_DOWNLINK); + obj->init(&users[rnti].rlc_itf, &users[rnti].rrc_itf, &users[rnti].gtpu_itf, log_h, RB_ID_SRB0, SECURITY_DIRECTION_DOWNLINK); users[rnti].rlc_itf.rnti = rnti; users[rnti].gtpu_itf.rnti = rnti; users[rnti].rrc_itf.rnti = rnti; @@ -72,14 +73,13 @@ void pdcp::rem_user(uint16_t rnti) } } -void pdcp::add_bearer(uint16_t rnti, uint32_t lcid, LIBLTE_RRC_PDCP_CONFIG_STRUCT* cnfg) +void pdcp::add_bearer(uint16_t rnti, uint32_t lcid, srslte::srslte_pdcp_config_t cfg) { if (users.count(rnti)) { - users[rnti].pdcp->add_bearer(lcid, cnfg); + users[rnti].pdcp->add_bearer(lcid, cfg); } } - void pdcp::reset(uint16_t rnti) { if (users.count(rnti)) { @@ -143,6 +143,10 @@ void pdcp::user_interface_rrc::write_pdu_pcch(srslte::byte_buffer_t* pdu) { fprintf(stderr, "Error: Received PCCH from ue=%d\n", rnti); } - - + +std::string pdcp::user_interface_rrc::get_rb_name(uint32_t lcid) +{ + return std::string(rb_id_text[lcid]); +} + } diff --git a/srsenb/src/upper/rlc.cc b/srsenb/src/upper/rlc.cc index 1af7a76de..6147597e3 100644 --- a/srsenb/src/upper/rlc.cc +++ b/srsenb/src/upper/rlc.cc @@ -25,6 +25,7 @@ */ #include "upper/rlc.h" +#include "upper/common_enb.h" namespace srsenb { @@ -53,7 +54,7 @@ void rlc::add_user(uint16_t rnti) { if (users.count(rnti) == 0) { srslte::rlc *obj = new srslte::rlc; - obj->init(&users[rnti], &users[rnti], &users[rnti], log_h, mac_timers); + obj->init(&users[rnti], &users[rnti], &users[rnti], log_h, mac_timers, RB_ID_SRB0); users[rnti].rnti = rnti; users[rnti].pdcp = pdcp; users[rnti].rrc = rrc; @@ -82,11 +83,11 @@ void rlc::reset(uint16_t rnti) void rlc::clear_buffer(uint16_t rnti) { if (users.count(rnti)) { - log_h->info("Clearing buffer rnti=0x%x\n", rnti); - users[rnti].rlc->reset(); + users[rnti].rlc->empty_queue(); for (int i=0;irlc_buffer_state(rnti, i, 0, 0); } + log_h->info("Cleared buffer rnti=0x%x\n", rnti); } } @@ -97,7 +98,7 @@ void rlc::add_bearer(uint16_t rnti, uint32_t lcid) } } -void rlc::add_bearer(uint16_t rnti, uint32_t lcid, LIBLTE_RRC_RLC_CONFIG_STRUCT* cnfg) +void rlc::add_bearer(uint16_t rnti, uint32_t lcid, srslte::srslte_rlc_config_t cnfg) { if (users.count(rnti)) { users[rnti].rlc->add_bearer(lcid, cnfg); @@ -184,4 +185,9 @@ void rlc::user_interface::write_pdu_pcch(srslte::byte_buffer_t* sdu) fprintf(stderr, "Error: Received PCCH from ue=%d\n", rnti); } +std::string rlc::user_interface::get_rb_name(uint32_t lcid) +{ + return std::string(rb_id_text[lcid]); +} + } diff --git a/srsenb/src/upper/rrc.cc b/srsenb/src/upper/rrc.cc index 259fac714..03ea65f2c 100644 --- a/srsenb/src/upper/rrc.cc +++ b/srsenb/src/upper/rrc.cc @@ -24,13 +24,13 @@ * */ +#include +#include #include "srslte/asn1/liblte_mme.h" #include "upper/rrc.h" -using srslte::rb_id_text; using srslte::byte_buffer_t; using srslte::bit_buffer_t; -using srslte::rb_id_t; namespace srsenb { @@ -314,12 +314,11 @@ void rrc::release_complete(uint16_t rnti) if (!users[rnti].is_idle()) { rlc->clear_buffer(rnti); users[rnti].send_connection_release(); - // There is no RRCReleaseComplete message from UE thus sleep to enable all retx in PHY +50% - usleep(1.5*8*1e3*cfg.mac_cnfg.ulsch_cnfg.max_harq_tx); + // There is no RRCReleaseComplete message from UE thus wait ~100 subframes for tx + usleep(100000); } rem_user(rnti); } else { - rrc_log->error("Received ReleaseComplete for unknown rnti=0x%x\n", rnti); } } @@ -439,7 +438,7 @@ void rrc::add_paging_id(uint32_t ueid, LIBLTE_S1AP_UEPAGINGID_STRUCT UEPagingID) // Described in Section 7 of 36.304 bool rrc::is_paging_opportunity(uint32_t tti, uint32_t *payload_len) { - int sf_pattern[4][3] = {{9, 4, 0}, {-1, 9, 4}, {-1, -1, 5}, {-1, -1, 9}}; + int sf_pattern[4][4] = {{9, 4, -1, 0}, {-1, 9, -1, 4}, {-1, -1, -1, 5}, {-1, -1, -1, 9}}; if (pending_paging.empty()) { return false; @@ -468,7 +467,7 @@ bool rrc::is_paging_opportunity(uint32_t tti, uint32_t *payload_len) if ((sfn % T) == (T/N) * (ueid % N)) { - int sf_idx = sf_pattern[i_s%4][(Ns-1)%3]; + int sf_idx = sf_pattern[i_s%4][(Ns-1)%4]; if (sf_idx < 0) { rrc_log->error("SF pattern is N/A for Ns=%d, i_s=%d, imsi_decimal=%d\n", Ns, i_s, ueid); } else if ((uint32_t) sf_idx == (tti%10)) { @@ -607,11 +606,11 @@ void rrc::run_thread() } switch(p.lcid) { - case srslte::RB_ID_SRB0: + case RB_ID_SRB0: parse_ul_ccch(p.rnti, p.pdu); break; - case srslte::RB_ID_SRB1: - case srslte::RB_ID_SRB2: + case RB_ID_SRB1: + case RB_ID_SRB2: parse_ul_dcch(p.rnti, p.lcid, p.pdu); break; case LCID_REM_USER: @@ -919,7 +918,7 @@ void rrc::ue::set_security_key(uint8_t* key, uint32_t length) k_up_enc, k_up_int); - parent->configure_security(rnti, srslte::RB_ID_SRB1, + parent->configure_security(rnti, RB_ID_SRB1, k_rrc_enc, k_rrc_int, k_up_enc, k_up_int, cipher_algo, integ_algo); @@ -1156,9 +1155,14 @@ void rrc::ue::send_connection_setup(bool is_setup) // Configure MAC parent->mac->ue_cfg(rnti, &sched_cfg); - // Configure SRB1 in RLC and PDCP + // Configure SRB1 in RLC parent->rlc->add_bearer(rnti, 1); - parent->pdcp->add_bearer(rnti, 1); + + // Configure SRB1 in PDCP + srslte::srslte_pdcp_config_t pdcp_cnfg; + pdcp_cnfg.is_control = true; + pdcp_cnfg.direction = SECURITY_DIRECTION_DOWNLINK; + parent->pdcp->add_bearer(rnti, 1, pdcp_cnfg); // Configure PHY layer parent->phy->set_config_dedicated(rnti, phy_cfg); @@ -1170,7 +1174,6 @@ void rrc::ue::send_connection_setup(bool is_setup) rr_cfg->sps_cnfg_present = false; send_dl_ccch(&dl_ccch_msg); - } @@ -1309,17 +1312,34 @@ void rrc::ue::send_connection_reconf(srslte::byte_buffer_t *pdu) // Add SRB2 and DRB1 to the scheduler srsenb::sched_interface::ue_bearer_cfg_t bearer_cfg; bearer_cfg.direction = srsenb::sched_interface::ue_bearer_cfg_t::BOTH; + bearer_cfg.group = 0; parent->mac->bearer_ue_cfg(rnti, 2, &bearer_cfg); + bearer_cfg.group = conn_reconf->rr_cnfg_ded.drb_to_add_mod_list[0].lc_cnfg.ul_specific_params.log_chan_group; parent->mac->bearer_ue_cfg(rnti, 3, &bearer_cfg); // Configure SRB2 in RLC and PDCP parent->rlc->add_bearer(rnti, 2); - parent->pdcp->add_bearer(rnti, 2); - + + // Configure SRB2 in PDCP + srslte::srslte_pdcp_config_t pdcp_cnfg; + pdcp_cnfg.direction = SECURITY_DIRECTION_DOWNLINK; + pdcp_cnfg.is_control = true; + pdcp_cnfg.is_data = false; + parent->pdcp->add_bearer(rnti, 2, pdcp_cnfg); + // Configure DRB1 in RLC parent->rlc->add_bearer(rnti, 3, &conn_reconf->rr_cnfg_ded.drb_to_add_mod_list[0].rlc_cnfg); + // Configure DRB1 in PDCP - parent->pdcp->add_bearer(rnti, 3, &conn_reconf->rr_cnfg_ded.drb_to_add_mod_list[0].pdcp_cnfg); + pdcp_cnfg.is_control = false; + pdcp_cnfg.is_data = true; + if (conn_reconf->rr_cnfg_ded.drb_to_add_mod_list[0].pdcp_cnfg.rlc_um_pdcp_sn_size_present) { + if(LIBLTE_RRC_PDCP_SN_SIZE_7_BITS == conn_reconf->rr_cnfg_ded.drb_to_add_mod_list[0].pdcp_cnfg.rlc_um_pdcp_sn_size) { + pdcp_cnfg.sn_len = 7; + } + } + parent->pdcp->add_bearer(rnti, 3, pdcp_cnfg); + // DRB1 has already been configured in GTPU through bearer setup // Add NAS Attach accept @@ -1432,7 +1452,7 @@ void rrc::ue::send_dl_ccch(LIBLTE_RRC_DL_CCCH_MSG_STRUCT *dl_ccch_msg) rnti, liblte_rrc_dl_ccch_msg_type_text[dl_ccch_msg->msg_type]); - parent->pdcp->write_sdu(rnti, srslte::RB_ID_SRB0, pdu); + parent->pdcp->write_sdu(rnti, RB_ID_SRB0, pdu); } else { parent->rrc_log->error("Allocating pdu\n"); @@ -1453,7 +1473,7 @@ void rrc::ue::send_dl_dcch(LIBLTE_RRC_DL_DCCH_MSG_STRUCT *dl_dcch_msg, byte_buff rnti, liblte_rrc_dl_dcch_msg_type_text[dl_dcch_msg->msg_type]); - parent->pdcp->write_sdu(rnti, srslte::RB_ID_SRB1, pdu); + parent->pdcp->write_sdu(rnti, RB_ID_SRB1, pdu); } else { parent->rrc_log->error("Allocating pdu\n"); diff --git a/srsenb/src/upper/s1ap.cc b/srsenb/src/upper/s1ap.cc index 032a6018f..eba9186e7 100644 --- a/srsenb/src/upper/s1ap.cc +++ b/srsenb/src/upper/s1ap.cc @@ -173,7 +173,7 @@ void s1ap::build_tai_cgi() void s1ap::initial_ue(uint16_t rnti, srslte::byte_buffer_t *pdu) { ue_ctxt_map[rnti].eNB_UE_S1AP_ID = next_eNB_UE_S1AP_ID++; - ue_ctxt_map[rnti].stream_id = next_ue_stream_id++; + ue_ctxt_map[rnti].stream_id = 1; ue_ctxt_map[rnti].release_requested = false; enbid_to_rnti_map[ue_ctxt_map[rnti].eNB_UE_S1AP_ID] = rnti; send_initialuemessage(rnti, pdu, false); @@ -182,7 +182,7 @@ void s1ap::initial_ue(uint16_t rnti, srslte::byte_buffer_t *pdu) void s1ap::initial_ue(uint16_t rnti, srslte::byte_buffer_t *pdu, uint32_t m_tmsi, uint8_t mmec) { ue_ctxt_map[rnti].eNB_UE_S1AP_ID = next_eNB_UE_S1AP_ID++; - ue_ctxt_map[rnti].stream_id = next_ue_stream_id++; + ue_ctxt_map[rnti].stream_id = 1; ue_ctxt_map[rnti].release_requested = false; enbid_to_rnti_map[ue_ctxt_map[rnti].eNB_UE_S1AP_ID] = rnti; send_initialuemessage(rnti, pdu, true, m_tmsi, mmec); @@ -594,7 +594,7 @@ bool s1ap::handle_uectxtreleasecommand(LIBLTE_S1AP_MESSAGE_UECONTEXTRELEASECOMMA s1ap_log->warning("Not handling S1AP message extension\n"); } - uint16_t rnti; + uint16_t rnti = 0; if(msg->UE_S1AP_IDs.choice_type == LIBLTE_S1AP_UE_S1AP_IDS_CHOICE_UE_S1AP_ID_PAIR) { if(msg->UE_S1AP_IDs.choice.uE_S1AP_ID_pair.ext) { diff --git a/srsenb/test/upper/ip_test.cc b/srsenb/test/upper/ip_test.cc index 41c430f29..2b789cf27 100644 --- a/srsenb/test/upper/ip_test.cc +++ b/srsenb/test/upper/ip_test.cc @@ -155,6 +155,7 @@ public: void set_activity_user(uint16_t rnti) {} bool is_paging_opportunity(uint32_t tti, uint32_t *payload_len) {return false;} void read_pdu_pcch(uint8_t* payload, uint32_t buffer_size) {} + std::string get_rb_name(uint32_t lcid) { return std::string("lcid"); } void write_pdu(uint32_t lcid, srslte::byte_buffer_t *sdu) { @@ -566,7 +567,7 @@ int main(int argc, char *argv[]) my_phy.init(&phy_args, &phy_cfg, &my_radio, &my_mac, &log_phy); my_mac.init(&mac_args, &mac_cfg.cell, &my_phy, &my_tester, &my_tester, &log_mac); - my_rlc.init(&my_tester, &my_tester, &my_tester, &log_rlc, &my_mac); + my_rlc.init(&my_tester, &my_tester, &my_tester, &log_rlc, &my_mac, 0 /* SRB0 */); my_tester.init(&my_rlc, &my_mac, &my_phy, &log_tester, prog_args.ip_address); if (prog_args.enable_gui) { diff --git a/srsue/hdr/mac/demux.h b/srsue/hdr/mac/demux.h index 773181220..2f38a4dfc 100644 --- a/srsue/hdr/mac/demux.h +++ b/srsue/hdr/mac/demux.h @@ -41,8 +41,8 @@ namespace srsue { class demux : public srslte::pdu_queue::process_callback { public: - demux(); - void init(phy_interface_mac* phy_h_, rlc_interface_mac *rlc, srslte::log* log_h_, srslte::timers* timers_db_); + demux(uint8_t nof_harq_proc_); + void init(phy_interface_mac_common* phy_h_, rlc_interface_mac *rlc, srslte::log* log_h_, srslte::timers* timers_db_); bool process_pdus(); uint8_t* request_buffer(uint32_t pid, uint32_t len); @@ -57,7 +57,6 @@ public: void process_pdu(uint8_t *pdu, uint32_t nof_bytes, uint32_t tstamp); private: - const static int NOF_HARQ_PID = 8; const static int MAX_PDU_LEN = 150*1024/8; // ~ 150 Mbps const static int NOF_BUFFER_PDUS = 64; // Number of PDU buffers per HARQ pid uint8_t bcch_buffer[1024]; // BCCH PID has a dedicated buffer @@ -73,10 +72,11 @@ private: bool is_uecrid_successful; - phy_interface_mac *phy_h; - srslte::log *log_h; - srslte::timers *timers_db; - rlc_interface_mac *rlc; + phy_interface_mac_common *phy_h; + srslte::log *log_h; + srslte::timers *timers_db; + rlc_interface_mac *rlc; + uint8_t nof_harq_proc; // Buffer of PDUs srslte::pdu_queue pdus; diff --git a/srsue/hdr/mac/dl_harq.h b/srsue/hdr/mac/dl_harq.h index e64e204c6..809ecd151 100644 --- a/srsue/hdr/mac/dl_harq.h +++ b/srsue/hdr/mac/dl_harq.h @@ -27,9 +27,15 @@ #ifndef DL_HARQ_H #define DL_HARQ_H +#define Error(fmt, ...) log_h->error_line(__FILE__, __LINE__, fmt, ##__VA_ARGS__) +#define Warning(fmt, ...) log_h->warning_line(__FILE__, __LINE__, fmt, ##__VA_ARGS__) +#define Info(fmt, ...) log_h->info_line(__FILE__, __LINE__, fmt, ##__VA_ARGS__) +#define Debug(fmt, ...) log_h->debug_line(__FILE__, __LINE__, fmt, ##__VA_ARGS__) + #include "srslte/common/log.h" #include "srslte/common/timers.h" #include "mac/demux.h" +#include "mac/mac_common.h" #include "mac/dl_sps.h" #include "srslte/common/mac_pcap.h" @@ -39,79 +45,314 @@ namespace srsue { - + +template class dl_harq_entity { public: - const static uint32_t NOF_HARQ_PROC = 8; - const static uint32_t HARQ_BCCH_PID = NOF_HARQ_PROC; - - dl_harq_entity(); - bool init(srslte::log *log_h_, mac_interface_rrc::mac_cfg_t *mac_cfg, srslte::timers *timers_, demux *demux_unit); - + const static uint32_t HARQ_BCCH_PID = N; + dl_harq_entity() : proc(N+1) + { + pcap = NULL; + } + + bool init(srslte::log *log_h_, srslte::timers *timers_, demux *demux_unit_) + { + timers_db = timers_; + demux_unit = demux_unit_; + si_window_start = 0; + log_h = log_h_; + for (uint32_t i=0;iMAC interface for DL processes **************************/ - void new_grant_dl(mac_interface_phy::mac_grant_t grant, mac_interface_phy::tb_action_dl_t *action); - void tb_decoded(bool ack, srslte_rnti_type_t rnti_type, uint32_t harq_pid); - - - void reset(); - void start_pcap(srslte::mac_pcap* pcap); - int get_current_tbs(uint32_t harq_pid); + void new_grant_dl(Tgrant grant, Taction *action) + { + if (grant.rnti_type != SRSLTE_RNTI_SPS) { + uint32_t harq_pid; + // Set BCCH PID for SI RNTI + if (grant.rnti_type == SRSLTE_RNTI_SI) { + harq_pid = HARQ_BCCH_PID; + } else { + harq_pid = grant.pid%N; + } + if (grant.rnti_type == SRSLTE_RNTI_TEMP && last_temporal_crnti != grant.rnti) { + grant.ndi = true; + Info("Set NDI=1 for Temp-RNTI DL grant\n"); + last_temporal_crnti = grant.rnti; + } + if (grant.rnti_type == SRSLTE_RNTI_USER && proc[harq_pid].is_sps()) { + grant.ndi = true; + Info("Set NDI=1 for C-RNTI DL grant\n"); + } + proc[harq_pid].new_grant_dl(grant, action); + } else { + /* This is for SPS scheduling */ + uint32_t harq_pid = get_harq_sps_pid(grant.tti)%N; + if (grant.ndi) { + grant.ndi = false; + proc[harq_pid].new_grant_dl(grant, action); + } else { + if (grant.is_sps_release) { + dl_sps_assig.clear(); + if (timers_db->get(TIME_ALIGNMENT)->is_running()) { + //phy_h->send_sps_ack(); + Warning("PHY Send SPS ACK not implemented\n"); + } + } else { + Error("SPS not implemented\n"); + //dl_sps_assig.reset(grant.tti, grant); + //grant.ndi = true; + //procs[harq_pid].save_grant(); + } + } + } + } + + + void tb_decoded(bool ack, srslte_rnti_type_t rnti_type, uint32_t harq_pid) + { + if (rnti_type == SRSLTE_RNTI_SI) { + proc[N].tb_decoded(ack); + } else { + proc[harq_pid%N].tb_decoded(ack); + } + } + + + void reset() + { + for (uint32_t i=0;ilog_h; + return true; + } + } + + void reset() + { + ack = false; + payload_buffer_ptr = NULL; + bzero(&cur_grant, sizeof(Tgrant)); + if (is_initiated) { + srslte_softbuffer_rx_reset(&softbuffer); + } + } - private: - bool calc_is_new_transmission(mac_interface_phy::mac_grant_t grant); + void new_grant_dl(Tgrant grant, Taction *action) + { + // Compute RV for BCCH when not specified in PDCCH format + if (pid == HARQ_BCCH_PID && grant.rv == -1) { + uint32_t k; + if ((grant.tti/10)%2 == 0 && grant.tti%10 == 5) { // This is SIB1, k is different + k = (grant.tti/20)%4; + grant.rv = ((uint32_t) ceilf((float)1.5*k))%4; + } else if (grant.rv == -1) { + k = (grant.tti-harq_entity->si_window_start)%4; + grant.rv = ((uint32_t) ceilf((float)1.5*k))%4; + } + } + calc_is_new_transmission(grant); + if (is_new_transmission) { + ack = false; + srslte_softbuffer_rx_reset_tbs(&softbuffer, cur_grant.n_bytes*8); + n_retx = 0; + } + + // Save grant + grant.last_ndi = cur_grant.ndi; + grant.last_tti = cur_grant.tti; + memcpy(&cur_grant, &grant, sizeof(Tgrant)); + + // Fill action structure + bzero(action, sizeof(Taction)); + action->default_ack = ack; + action->generate_ack = true; + action->decode_enabled = false; + + // If data has not yet been successfully decoded + if (ack == false) { + + // Instruct the PHY To combine the received data and attempt to decode it + payload_buffer_ptr = harq_entity->demux_unit->request_buffer(pid, cur_grant.n_bytes); + action->payload_ptr = payload_buffer_ptr; + if (!action->payload_ptr) { + action->decode_enabled = false; + Error("Can't get a buffer for TBS=%d\n", cur_grant.n_bytes); + return; + } + action->decode_enabled = true; + action->rv = cur_grant.rv; + action->rnti = cur_grant.rnti; + action->softbuffer = &softbuffer; + memcpy(&action->phy_grant, &cur_grant.phy_grant, sizeof(Tphygrant)); + n_retx++; + + } else { + Warning("DL PID %d: Received duplicate TB. Discarting and retransmitting ACK\n", pid); + } + + if (pid == HARQ_BCCH_PID || harq_entity->timers_db->get(TIME_ALIGNMENT)->is_expired()) { + // Do not generate ACK + Debug("Not generating ACK\n"); + action->generate_ack = false; + } else { + if (cur_grant.rnti_type == SRSLTE_RNTI_TEMP && ack == false) { + // Postpone ACK after contention resolution is resolved + action->generate_ack_callback = harq_entity->generate_ack_callback; + action->generate_ack_callback_arg = harq_entity->demux_unit; + Debug("ACK pending contention resolution\n"); + } else { + Debug("Generating ACK\n"); + } + } + } + void tb_decoded(bool ack_) + { + ack = ack_; + if (ack == true) { + if (pid == HARQ_BCCH_PID) { + if (harq_entity->pcap) { + harq_entity->pcap->write_dl_sirnti(payload_buffer_ptr, cur_grant.n_bytes, ack, cur_grant.tti); + } + Debug("Delivering PDU=%d bytes to Dissassemble and Demux unit (BCCH)\n", cur_grant.n_bytes); + harq_entity->demux_unit->push_pdu(pid, payload_buffer_ptr, cur_grant.n_bytes, cur_grant.tti); + } else { + if (harq_entity->pcap) { + harq_entity->pcap->write_dl_crnti(payload_buffer_ptr, cur_grant.n_bytes, cur_grant.rnti, ack, cur_grant.tti); + } + if (ack) { + if (cur_grant.rnti_type == SRSLTE_RNTI_TEMP) { + Debug("Delivering PDU=%d bytes to Dissassemble and Demux unit (Temporal C-RNTI)\n", cur_grant.n_bytes); + harq_entity->demux_unit->push_pdu_temp_crnti(payload_buffer_ptr, cur_grant.n_bytes); + } else { + Debug("Delivering PDU=%d bytes to Dissassemble and Demux unit\n", cur_grant.n_bytes); + harq_entity->demux_unit->push_pdu(pid, payload_buffer_ptr, cur_grant.n_bytes, cur_grant.tti); + + // Compute average number of retransmissions per packet + harq_entity->average_retx = SRSLTE_VEC_CMA((float) n_retx, harq_entity->average_retx, harq_entity->nof_pkts++); + } + } + } + } else { + harq_entity->demux_unit->deallocate(payload_buffer_ptr); + } + + Info("DL %d: %s tbs=%d, rv=%d, ack=%s, ndi=%d (%d), tti=%d (%d)\n", + pid, is_new_transmission?"newTX":"reTX ", + cur_grant.n_bytes, cur_grant.rv, ack?"OK":"KO", + cur_grant.ndi, cur_grant.last_ndi, cur_grant.tti, cur_grant.last_tti); + + if (ack && pid == HARQ_BCCH_PID) { + reset(); + } + } + + bool is_sps() { return false; } + + int get_current_tbs() { return cur_grant.n_bytes*8; } + + private: + bool calc_is_new_transmission(Tgrant grant) + { + bool is_new_tb = true; + if ((srslte_tti_interval(grant.tti, cur_grant.tti) <= 8 && (grant.n_bytes == cur_grant.n_bytes)) || + pid == HARQ_BCCH_PID) + { + is_new_tb = false; + } + + if ((grant.ndi != cur_grant.ndi && !is_new_tb) || // NDI toggled for same TB + is_new_tb || // is new TB + (pid == HARQ_BCCH_PID && grant.rv == 0)) // Broadcast PID and 1st TX (RV=0) + { + is_new_transmission = true; + Debug("Set HARQ for new transmission\n"); + } else { + is_new_transmission = false; + Debug("Set HARQ for retransmission\n"); + } + + return is_new_transmission; + } + bool is_initiated; dl_harq_entity *harq_entity; srslte::log *log_h; - bool is_new_transmission; + bool is_new_transmission; uint32_t pid; uint8_t *payload_buffer_ptr; bool ack; - uint32_t n_retx; + uint32_t n_retx; - mac_interface_phy::mac_grant_t cur_grant; + Tgrant cur_grant; srslte_softbuffer_rx_t softbuffer; - }; - static bool generate_ack_callback(void *arg); + + // Private members of dl_harq_entity + + static bool generate_ack_callback(void *arg) + { + demux *demux_unit = (demux*) arg; + return demux_unit->get_uecrid_successful(); + } - uint32_t get_harq_sps_pid(uint32_t tti); + uint32_t get_harq_sps_pid(uint32_t tti) { return 0; } dl_sps dl_sps_assig; - dl_harq_process proc[NOF_HARQ_PROC+1]; + + std::vector proc; srslte::timers *timers_db; - mac_interface_rrc::mac_cfg_t *mac_cfg; demux *demux_unit; srslte::log *log_h; srslte::mac_pcap *pcap; uint16_t last_temporal_crnti; - int si_window_start; + int si_window_start; - float average_retx; + float average_retx; uint64_t nof_pkts; }; diff --git a/srsue/hdr/mac/mac.h b/srsue/hdr/mac/mac.h index f6f22f334..660f7fbba 100644 --- a/srsue/hdr/mac/mac.h +++ b/srsue/hdr/mac/mac.h @@ -98,17 +98,6 @@ public: u_int32_t get_unique_id(); uint32_t get_current_tti(); - - enum { - HARQ_RTT, - TIME_ALIGNMENT, - CONTENTION_TIMER, - BSR_TIMER_PERIODIC, - BSR_TIMER_RETX, - PHR_TIMER_PERIODIC, - PHR_TIMER_PROHIBIT, - NOF_MAC_TIMERS - } mac_timers_t; static const int MAC_NOF_UPPER_TIMERS = 20; @@ -117,6 +106,7 @@ private: static const int MAC_MAIN_THREAD_PRIO = 5; static const int MAC_PDU_THREAD_PRIO = 6; + static const int MAC_NOF_HARQ_PROC = 8; // Interaction with PHY srslte::tti_sync_cv ttisync; @@ -141,9 +131,9 @@ private: mux mux_unit; demux demux_unit; - /* DL/UL HARQ */ - dl_harq_entity dl_harq; - ul_harq_entity ul_harq; + /* DL/UL HARQ */ + dl_harq_entity dl_harq; + ul_harq_entity ul_harq; /* MAC Uplink-related Procedures */ ra_proc ra_procedure; diff --git a/srsue/hdr/mac/mac_common.h b/srsue/hdr/mac/mac_common.h new file mode 100644 index 000000000..d40d179eb --- /dev/null +++ b/srsue/hdr/mac/mac_common.h @@ -0,0 +1,45 @@ +/** + * + * \section COPYRIGHT + * + * Copyright 2013-2015 Software Radio Systems Limited + * + * \section LICENSE + * + * This file is part of the srsUE library. + * + * srsUE 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. + * + * srsUE 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/. + * + */ + +#ifndef MAC_COMMON_H +#define MAC_COMMON_H + +namespace srsue { + +typedef enum { + HARQ_RTT, + TIME_ALIGNMENT, + CONTENTION_TIMER, + BSR_TIMER_PERIODIC, + BSR_TIMER_RETX, + PHR_TIMER_PERIODIC, + PHR_TIMER_PROHIBIT, + NOF_MAC_TIMERS +} mac_timers_t; + +} // namespace srsue + +#endif // MAC_COMMON_H diff --git a/srsue/hdr/mac/mux.h b/srsue/hdr/mac/mux.h index db98ebe78..1167af752 100644 --- a/srsue/hdr/mac/mux.h +++ b/srsue/hdr/mac/mux.h @@ -55,9 +55,9 @@ namespace srsue { class mux { public: - mux(); + mux(uint8_t nof_harq_proc_); void reset(); - void init(rlc_interface_mac *rlc, srslte::log *log_h, bsr_proc *bsr_procedure, phr_proc *phr_procedure_); + void init(rlc_interface_mac *rlc, srslte::log *log_h, bsr_interface_mux *bsr_procedure, phr_proc *phr_procedure_); bool is_pending_any_sdu(); bool is_pending_sdu(uint32_t lcid); @@ -87,16 +87,17 @@ private: std::vector lch; // Keep track of the PIDs that transmitted BSR reports - bool pid_has_bsr[MAX_HARQ_PROC]; + std::vector pid_has_bsr; // Mutex for exclusive access pthread_mutex_t mutex; srslte::log *log_h; rlc_interface_mac *rlc; - bsr_proc *bsr_procedure; + bsr_interface_mux *bsr_procedure; phr_proc *phr_procedure; uint16_t pending_crnti_ce; + uint8_t nof_harq_proc; /* Msg3 Buffer */ static const uint32_t MSG3_BUFF_SZ = 128; @@ -105,9 +106,6 @@ private: /* PDU Buffer */ srslte::sch_pdu pdu_msg; bool msg3_has_been_transmitted; - - - }; } // namespace srsue diff --git a/srsue/hdr/mac/proc_bsr.h b/srsue/hdr/mac/proc_bsr.h index bbfaa1c90..21f278e29 100644 --- a/srsue/hdr/mac/proc_bsr.h +++ b/srsue/hdr/mac/proc_bsr.h @@ -37,7 +37,7 @@ namespace srsue { -class bsr_proc : public srslte::timer_callback +class bsr_proc : public srslte::timer_callback, public bsr_interface_mux { public: bsr_proc(); @@ -48,18 +48,6 @@ public: void set_priority(uint32_t lcid, uint32_t priority); void timer_expired(uint32_t timer_id); uint32_t get_buffer_state(); - - typedef enum { - LONG_BSR, - SHORT_BSR, - TRUNC_BSR - } bsr_format_t; - - typedef struct { - bsr_format_t format; - uint32_t buff_size[4]; - } bsr_t; - bool need_to_send_bsr_on_ul_grant(uint32_t grant_size, bsr_t *bsr); bool generate_padding_bsr(uint32_t nof_padding_bytes, bsr_t *bsr); bool need_to_send_sr(uint32_t tti); diff --git a/srsue/hdr/mac/ul_harq.h b/srsue/hdr/mac/ul_harq.h index cea469e33..2ef1ed2b6 100644 --- a/srsue/hdr/mac/ul_harq.h +++ b/srsue/hdr/mac/ul_harq.h @@ -27,78 +27,268 @@ #ifndef ULHARQ_H #define ULHARQ_H +#define Error(fmt, ...) log_h->error_line(__FILE__, __LINE__, fmt, ##__VA_ARGS__) +#define Warning(fmt, ...) log_h->warning_line(__FILE__, __LINE__, fmt, ##__VA_ARGS__) +#define Info(fmt, ...) log_h->info_line(__FILE__, __LINE__, fmt, ##__VA_ARGS__) +#define Debug(fmt, ...) log_h->debug_line(__FILE__, __LINE__, fmt, ##__VA_ARGS__) + #include "srslte/interfaces/ue_interfaces.h" #include "srslte/common/log.h" #include "mac/mux.h" +#include "mac/mac_common.h" #include "mac/ul_sps.h" #include "srslte/common/mac_pcap.h" #include "srslte/common/timers.h" +#include "srslte/common/interfaces_common.h" /* Uplink HARQ entity as defined in 5.4.2 of 36.321 */ - - namespace srsue { - + +template class ul_harq_entity { public: - - const static uint32_t NOF_HARQ_PROC = 8; - static uint32_t pidof(uint32_t tti); + static uint32_t pidof(uint32_t tti) + { + return (uint32_t) tti%N; + } - ul_harq_entity() { + ul_harq_entity() : proc(N) + { pcap = NULL; timers_db = NULL; mux_unit = NULL; log_h = NULL; - mac_cfg = NULL; + params = NULL; rntis = NULL; average_retx = 0; - nof_pkts = 0; + nof_pkts = 0; + } + + bool init(srslte::log *log_h_, + mac_interface_rrc_common::ue_rnti_t *rntis_, + mac_interface_rrc_common::ul_harq_params_t *params_, + srslte::timers* timers_db_, + mux *mux_unit_) + { + log_h = log_h_; + mux_unit = mux_unit_; + params = params_; + rntis = rntis_; + timers_db = timers_db_; + for (uint32_t i=0;iMAC interface for UL processes **************************/ - void new_grant_ul(mac_interface_phy::mac_grant_t grant, mac_interface_phy::tb_action_ul_t *action); - void new_grant_ul_ack(mac_interface_phy::mac_grant_t grant, bool ack, mac_interface_phy::tb_action_ul_t *action); - void harq_recv(uint32_t tti, bool ack, mac_interface_phy::tb_action_ul_t *action); + void new_grant_ul(Tgrant grant, Taction *action) + { + if (grant.rnti_type == SRSLTE_RNTI_USER || + grant.rnti_type == SRSLTE_RNTI_TEMP || + grant.rnti_type == SRSLTE_RNTI_RAR) + { + if (grant.rnti_type == SRSLTE_RNTI_USER && proc[pidof(grant.tti)].is_sps()) { + grant.ndi = true; + } + run_tti(grant.tti, &grant, action); + } else if (grant.rnti_type == SRSLTE_RNTI_SPS) { + if (grant.ndi) { + grant.ndi = proc[pidof(grant.tti)].get_ndi(); + run_tti(grant.tti, &grant, action); + } else { + Info("Not implemented\n"); + } + } + } - int get_current_tbs(uint32_t tti); + void new_grant_ul_ack(Tgrant grant, bool ack, Taction *action) + { + set_ack(grant.tti, ack, action); + new_grant_ul(grant, action); + } + + void harq_recv(uint32_t tti, bool ack, Taction *action) + { + set_ack(tti, ack, action); + run_tti(tti, NULL, action); + } + + int get_current_tbs(uint32_t tti) + { + int tti_harq = (int) tti-4; + if (tti_harq < 0) { + tti_harq += 10240; + } + uint32_t pid_harq = pidof(tti_harq); + return proc[pid_harq].get_current_tbs(); + } - float get_average_retx(); + float get_average_retx() + { + return average_retx; + } -private: - +private: class ul_harq_process { public: - ul_harq_process(); - bool init(uint32_t pid, ul_harq_entity *parent); - void reset(); - void reset_ndi(); + ul_harq_process() + { + current_tx_nb = 0; + current_irv = 0; + is_initiated = false; + is_grant_configured = false; + tti_last_tx = 0; + bzero(&cur_grant, sizeof(Tgrant)); + } + + bool init(uint32_t pid_, ul_harq_entity *parent) + { + if (srslte_softbuffer_tx_init(&softbuffer, 110)) { + fprintf(stderr, "Error initiating soft buffer\n"); + return false; + } else { + is_initiated = true; + harq_entity = parent; + log_h = harq_entity->log_h; + pid = pid_; + payload_buffer = (uint8_t*) srslte_vec_malloc(payload_buffer_len*sizeof(uint8_t)); + if (!payload_buffer) { + Error("Allocating memory\n"); + return false; + } + pdu_ptr = payload_buffer; + return true; + } + } + + void reset() + { + current_tx_nb = 0; + current_irv = 0; + tti_last_tx = 0; + is_grant_configured = false; + bzero(&cur_grant, sizeof(Tgrant)); + } + + void reset_ndi() { ndi = false; } - void run_tti(uint32_t tti, mac_interface_phy::mac_grant_t *grant, mac_interface_phy::tb_action_ul_t* action); + void run_tti(uint32_t tti_tx, Tgrant *grant, Taction* action) + { + uint32_t max_retx; + if (is_msg3) { + max_retx = harq_entity->params->max_harq_msg3_tx; + } else { + max_retx = harq_entity->params->max_harq_tx; + } - uint32_t get_rv(); - bool has_grant(); + // Receive and route HARQ feedbacks + if (grant) { + if ((!(grant->rnti_type == SRSLTE_RNTI_TEMP) && grant->ndi != get_ndi()) || + (grant->rnti_type == SRSLTE_RNTI_USER && !has_grant()) || + grant->is_from_rar) + { + // New transmission - void set_harq_feedback(bool ack); - bool get_ndi(); - bool is_sps(); - uint32_t last_tx_tti(); - uint32_t get_nof_retx(); - int get_current_tbs(); + // Uplink grant in a RAR + if (grant->is_from_rar) { + Debug("Getting Msg3 buffer payload, grant size=%d bytes\n", grant->n_bytes); + pdu_ptr = harq_entity->mux_unit->msg3_get(payload_buffer, grant->n_bytes); + if (pdu_ptr) { + generate_new_tx(tti_tx, true, grant, action); + } else { + Warning("UL RAR grant available but no Msg3 on buffer\n"); + } + + // Normal UL grant + } else { + // Request a MAC PDU from the Multiplexing & Assemble Unit + pdu_ptr = harq_entity->mux_unit->pdu_get(payload_buffer, grant->n_bytes, tti_tx, pid); + if (pdu_ptr) { + generate_new_tx(tti_tx, false, grant, action); + } else { + Warning("Uplink grant but no MAC PDU in Multiplex Unit buffer\n"); + } + } + } else { + // Adaptive Re-TX + if (current_tx_nb >= max_retx) { + Info("UL %d: Maximum number of ReTX reached (%d). Discarting TB.\n", pid, max_retx); + reset(); + action->expect_ack = false; + } else { + generate_retx(tti_tx, grant, action); + } + } + } else if (has_grant()) { + // Non-Adaptive Re-Tx + if (current_tx_nb >= max_retx) { + Info("UL %d: Maximum number of ReTX reached (%d). Discarting TB.\n", pid, max_retx); + reset(); + action->expect_ack = false; + } else { + generate_retx(tti_tx, action); + } + } + if (harq_entity->pcap && grant) { + if (grant->is_from_rar) { + grant->rnti = harq_entity->rntis->temp_rnti; + } + harq_entity->pcap->write_ul_crnti(pdu_ptr, grant->n_bytes, grant->rnti, get_nof_retx(), tti_tx); + } + } + + void set_harq_feedback(bool ack) + { + harq_feedback = ack; + // UL packet successfully delivered + if (ack) { + Info("UL %d: HARQ = ACK for UL transmission. Discarting TB.\n", pid); + reset(); + } else { + Info("UL %d: HARQ = NACK for UL transmission\n", pid); + } + } + + uint32_t get_rv() + { + int rv_of_irv[4] = {0, 2, 3, 1}; + return rv_of_irv[current_irv%4]; + } + + bool has_grant() { return is_grant_configured; } + bool get_ndi() { return ndi; } + bool is_sps() { return false; } + uint32_t last_tx_tti() { return tti_last_tx; } + uint32_t get_nof_retx() { return current_tx_nb; } + int get_current_tbs() { return cur_grant.n_bytes*8; } private: - mac_interface_phy::mac_grant_t cur_grant; + Tgrant cur_grant; uint32_t pid; uint32_t current_tx_nb; @@ -118,28 +308,109 @@ private: uint8_t *payload_buffer; uint8_t *pdu_ptr; - void generate_retx(uint32_t tti_tx, mac_interface_phy::tb_action_ul_t *action); - void generate_retx(uint32_t tti_tx, mac_interface_phy::mac_grant_t *grant, - mac_interface_phy::tb_action_ul_t *action); - void generate_new_tx(uint32_t tti_tx, bool is_msg3, mac_interface_phy::mac_grant_t *grant, - mac_interface_phy::tb_action_ul_t *action); - void generate_tx(uint32_t tti_tx, mac_interface_phy::tb_action_ul_t *action); + void generate_retx(uint32_t tti_tx, Taction *action) + { + generate_retx(tti_tx, NULL, action); + } + + // Retransmission with or w/o grant (Section 5.4.2.2) + void generate_retx(uint32_t tti_tx, Tgrant *grant, + Taction *action) + { + int irv_of_rv[4] = {0, 3, 1, 2}; + if (grant) { + // HARQ entity requests an adaptive transmission + if (grant->rv) { + current_irv = irv_of_rv[grant->rv%4]; + } + memcpy(&cur_grant, grant, sizeof(Tgrant)); + harq_feedback = false; + Info("UL %d: Adaptive retx=%d, RV=%d, TBS=%d\n", + pid, current_tx_nb, get_rv(), grant->n_bytes); + generate_tx(tti_tx, action); + } else { + Info("UL %d: Non-Adaptive retx=%d, RV=%d, TBS=%d\n", + pid, current_tx_nb, get_rv(), cur_grant.n_bytes); + // HARQ entity requests a non-adaptive transmission + if (!harq_feedback) { + generate_tx(tti_tx, action); + } + } + + // On every Msg3 retransmission, restart mac-ContentionResolutionTimer as defined in Section 5.1.5 + if (is_msg3) { + harq_entity->timers_db->get(CONTENTION_TIMER)->reset(); + } + + harq_entity->mux_unit->pusch_retx(tti_tx, pid); + } + + // New transmission (Section 5.4.2.2) + void generate_new_tx(uint32_t tti_tx, bool is_msg3_, Tgrant *grant, Taction *action) + { + if (grant) { + // Compute average number of retransmissions per packet considering previous packet + harq_entity->average_retx = SRSLTE_VEC_CMA((float) current_tx_nb, harq_entity->average_retx, harq_entity->nof_pkts++); + memcpy(&cur_grant, grant, sizeof(Tgrant)); + harq_feedback = false; + is_grant_configured = true; + current_tx_nb = 0; + current_irv = 0; + is_msg3 = is_msg3_; + Info("UL %d: New TX%s, RV=%d, TBS=%d, RNTI=%d\n", + pid, is_msg3?" for Msg3":"", get_rv(), cur_grant.n_bytes, cur_grant.rnti); + generate_tx(tti_tx, action); + } + } + + // Transmission of pending frame (Section 5.4.2.2) + void generate_tx(uint32_t tti_tx, Taction *action) + { + action->current_tx_nb = current_tx_nb; + current_tx_nb++; + action->expect_ack = true; + action->rnti = is_msg3?harq_entity->rntis->temp_rnti:cur_grant.rnti; + action->rv = cur_grant.rv>0?cur_grant.rv:get_rv(); + action->softbuffer = &softbuffer; + action->tx_enabled = true; + action->payload_ptr = pdu_ptr; + memcpy(&action->phy_grant, &cur_grant.phy_grant, sizeof(Tphygrant)); + + current_irv = (current_irv+1)%4; + tti_last_tx = tti_tx; + } }; - - void run_tti(uint32_t tti, mac_interface_phy::mac_grant_t *grant, mac_interface_phy::tb_action_ul_t* action); - void set_ack(uint32_t tti, bool ack); + // Implements Section 5.4.2.1 + // Called with UL grant + void run_tti(uint32_t tti, Tgrant *grant, Taction* action) + { + uint32_t tti_tx = (tti+action->tti_offset)%10240; + proc[pidof(tti_tx)].run_tti(tti_tx, grant, action); + } + + void set_ack(uint32_t tti, bool ack, Taction *action) + { + int tti_harq = (int) tti - action->tti_offset; + if (tti_harq < 0) { + tti_harq += 10240; + } + uint32_t pid_harq = pidof(tti_harq); + if (proc[pid_harq].has_grant() && (proc[pid_harq].last_tx_tti() <= (uint32_t)tti_harq)) { + proc[pid_harq].set_harq_feedback(ack); + } + } ul_sps ul_sps_assig; srslte::timers *timers_db; mux *mux_unit; - ul_harq_process proc[NOF_HARQ_PROC]; + std::vector proc; srslte::log *log_h; srslte::mac_pcap *pcap; - mac_interface_rrc::ue_rnti_t *rntis; - mac_interface_rrc::mac_cfg_t *mac_cfg; + mac_interface_rrc_common::ue_rnti_t *rntis; + mac_interface_rrc_common::ul_harq_params_t *params; float average_retx; uint64_t nof_pkts; diff --git a/srsue/hdr/ue.h b/srsue/hdr/ue.h index 6fb593d55..c69dbddeb 100644 --- a/srsue/hdr/ue.h +++ b/srsue/hdr/ue.h @@ -37,6 +37,7 @@ #include #include +#include "ue_base.h" #include "srslte/radio/radio_multi.h" #include "phy/phy.h" #include "mac/mac.h" @@ -56,89 +57,15 @@ namespace srsue { -/******************************************************************************* - UE Parameters -*******************************************************************************/ - -typedef struct { - float dl_freq; - float ul_freq; - float rx_gain; - float tx_gain; - uint32_t nof_rx_ant; - std::string device_name; - std::string device_args; - std::string time_adv_nsamples; - std::string burst_preamble; -}rf_args_t; - -typedef struct { - bool enable; - std::string filename; -}pcap_args_t; - -typedef struct { - bool enable; - std::string phy_filename; - std::string radio_filename; -}trace_args_t; - -typedef struct { - std::string phy_level; - std::string mac_level; - std::string rlc_level; - std::string pdcp_level; - std::string rrc_level; - std::string gw_level; - std::string nas_level; - std::string usim_level; - std::string all_level; - int phy_hex_limit; - int mac_hex_limit; - int rlc_hex_limit; - int pdcp_hex_limit; - int rrc_hex_limit; - int gw_hex_limit; - int nas_hex_limit; - int usim_hex_limit; - int all_hex_limit; - std::string filename; -}log_args_t; - -typedef struct { - bool enable; -}gui_args_t; - -typedef struct { - phy_args_t phy; - float metrics_period_secs; - bool pregenerate_signals; - int ue_cateogry; - -}expert_args_t; - -typedef struct { - rf_args_t rf; - rf_cal_t rf_cal; - pcap_args_t pcap; - trace_args_t trace; - log_args_t log; - gui_args_t gui; - usim_args_t usim; - expert_args_t expert; -}all_args_t; - /******************************************************************************* Main UE class *******************************************************************************/ class ue - :public ue_interface - ,public ue_metrics_interface + :public ue_base { public: - static ue* get_instance(void); - static void cleanup(void); + ue(); bool init(all_args_t *args_); void stop(); @@ -158,8 +85,6 @@ public: private: - static ue *instance; - ue(); virtual ~ue(); srslte::radio_multi radio; @@ -189,8 +114,6 @@ private: all_args_t *args; bool started; rf_metrics_t rf_metrics; - - srslte::LOG_LEVEL_ENUM level(std::string l); bool check_srslte_version(); }; diff --git a/srsue/hdr/ue_base.h b/srsue/hdr/ue_base.h new file mode 100644 index 000000000..06c3f3e24 --- /dev/null +++ b/srsue/hdr/ue_base.h @@ -0,0 +1,164 @@ +/** + * + * \section COPYRIGHT + * + * Copyright 2013-2015 Software Radio Systems Limited + * + * \section LICENSE + * + * This file is part of the srsUE library. + * + * srsUE 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. + * + * srsUE 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: ue_base.h + * Description: Base class for UEs. + *****************************************************************************/ + +#ifndef UE_BASE_H +#define UE_BASE_H + +#include +#include +#include +#include "srslte/radio/radio_multi.h" +#include "phy/phy.h" +#include "upper/usim.h" +#include "srslte/interfaces/ue_interfaces.h" + +#include "srslte/common/logger.h" +#include "srslte/common/log_filter.h" + +#include "ue_metrics_interface.h" + +namespace srsue { + +/******************************************************************************* + UE Parameters +*******************************************************************************/ + +typedef struct { + float dl_freq; + float ul_freq; + float rx_gain; + float tx_gain; + uint32_t nof_rx_ant; + std::string device_name; + std::string device_args; + std::string time_adv_nsamples; + std::string burst_preamble; +}rf_args_t; + +typedef struct { + bool enable; + std::string filename; +}pcap_args_t; + +typedef struct { + bool enable; + std::string phy_filename; + std::string radio_filename; +}trace_args_t; + +typedef struct { + std::string phy_level; + std::string mac_level; + std::string rlc_level; + std::string pdcp_level; + std::string rrc_level; + std::string gw_level; + std::string nas_level; + std::string usim_level; + std::string all_level; + int phy_hex_limit; + int mac_hex_limit; + int rlc_hex_limit; + int pdcp_hex_limit; + int rrc_hex_limit; + int gw_hex_limit; + int nas_hex_limit; + int usim_hex_limit; + int all_hex_limit; + std::string filename; +}log_args_t; + +typedef struct { + bool enable; +}gui_args_t; + +typedef struct { + phy_args_t phy; + float metrics_period_secs; + bool pregenerate_signals; + std::string ue_cateogry; +}expert_args_t; + +typedef struct { + rf_args_t rf; + rf_cal_t rf_cal; + pcap_args_t pcap; + trace_args_t trace; + log_args_t log; + gui_args_t gui; + usim_args_t usim; + expert_args_t expert; +}all_args_t; + +typedef enum { + LTE = 0, + SRSUE_INSTANCE_TYPE_NITEMS +} srsue_instance_type_t; +static const char srsue_instance_type_text[SRSUE_INSTANCE_TYPE_NITEMS][10] = { "LTE" }; + + +/******************************************************************************* + Main UE class +*******************************************************************************/ + +class ue_base + :public ue_interface + ,public ue_metrics_interface +{ +public: + ue_base() {} + virtual ~ue_base() {} + + static ue_base* get_instance(srsue_instance_type_t type); + + void cleanup(void); + + virtual bool init(all_args_t *args_) = 0; + virtual void stop() = 0; + virtual bool is_attached() = 0; + virtual void start_plot() = 0; + + void handle_rf_msg(srslte_rf_error_t error); + + // UE metrics interface + virtual bool get_metrics(ue_metrics_t &m) = 0; + + virtual void pregenerate_signals(bool enable) = 0; + + srslte::log_filter rf_log; + rf_metrics_t rf_metrics; + srslte::LOG_LEVEL_ENUM level(std::string l); +}; + +} // namespace srsue + +#endif // UE_BASE_H + diff --git a/srsue/hdr/upper/nas.h b/srsue/hdr/upper/nas.h index 5e3a8b098..32afd52bb 100644 --- a/srsue/hdr/upper/nas.h +++ b/srsue/hdr/upper/nas.h @@ -65,7 +65,8 @@ public: void init(usim_interface_nas *usim_, rrc_interface_nas *rrc_, gw_interface_nas *gw_, - srslte::log *nas_log_); + srslte::log *nas_log_, + srslte::srslte_nas_config_t cfg_); void stop(); emm_state_t get_state(); @@ -83,6 +84,7 @@ private: rrc_interface_nas *rrc; usim_interface_nas *usim; gw_interface_nas *gw; + srslte::srslte_nas_config_t cfg; emm_state_t state; diff --git a/srsue/hdr/upper/rrc.h b/srsue/hdr/upper/rrc.h index cc1a22fd1..c758622fb 100644 --- a/srsue/hdr/upper/rrc.h +++ b/srsue/hdr/upper/rrc.h @@ -29,6 +29,7 @@ #include "pthread.h" +#include "rrc_common.h" #include "srslte/common/buffer_pool.h" #include "srslte/common/log.h" #include "srslte/common/common.h" @@ -41,24 +42,6 @@ using srslte::byte_buffer_t; namespace srsue { -// RRC states (3GPP 36.331 v10.0.0) -typedef enum{ - RRC_STATE_IDLE = 0, - RRC_STATE_SIB1_SEARCH, - RRC_STATE_SIB2_SEARCH, - RRC_STATE_WAIT_FOR_CON_SETUP, - RRC_STATE_COMPLETING_SETUP, - RRC_STATE_RRC_CONNECTED, - RRC_STATE_N_ITEMS, -}rrc_state_t; -static const char rrc_state_text[RRC_STATE_N_ITEMS][100] = {"IDLE", - "SIB1_SEARCH", - "SIB2_SEARCH", - "WAIT FOR CON SETUP", - "COMPLETING SETUP", - "RRC CONNECTED"}; - - class rrc :public rrc_interface_nas ,public rrc_interface_phy @@ -161,6 +144,23 @@ private: void write_pdu_bcch_dlsch(byte_buffer_t *pdu); void write_pdu_pcch(byte_buffer_t *pdu); + // Radio bearers + typedef enum{ + RB_ID_SRB0 = 0, + RB_ID_SRB1, + RB_ID_SRB2, + RB_ID_DRB1, + RB_ID_DRB2, + RB_ID_DRB3, + RB_ID_DRB4, + RB_ID_DRB5, + RB_ID_DRB6, + RB_ID_DRB7, + RB_ID_DRB8 + } rb_id_t; + std::map bearers; + std::string get_rb_name(uint32_t lcid) { return bearers.at(lcid); } + // RLC interface void max_retx_attempted(); @@ -202,6 +202,7 @@ private: void set_phy_default(); void set_mac_default(); void set_rrc_default(); + void set_bearers(); }; diff --git a/srsue/hdr/upper/rrc_common.h b/srsue/hdr/upper/rrc_common.h new file mode 100644 index 000000000..692a20cb3 --- /dev/null +++ b/srsue/hdr/upper/rrc_common.h @@ -0,0 +1,52 @@ +/** + * + * \section COPYRIGHT + * + * Copyright 2013-2015 Software Radio Systems Limited + * + * \section LICENSE + * + * This file is part of the srsUE library. + * + * srsUE 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. + * + * srsUE 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/. + * + */ + +#ifndef RRC_COMMON_H +#define RRC_COMMON_H + +namespace srsue { + +// RRC states (3GPP 36.331 v10.0.0) +typedef enum{ + RRC_STATE_IDLE = 0, + RRC_STATE_SIB1_SEARCH, + RRC_STATE_SIB2_SEARCH, + RRC_STATE_WAIT_FOR_CON_SETUP, + RRC_STATE_COMPLETING_SETUP, + RRC_STATE_RRC_CONNECTED, + RRC_STATE_N_ITEMS, +}rrc_state_t; +static const char rrc_state_text[RRC_STATE_N_ITEMS][100] = {"IDLE", + "SIB1_SEARCH", + "SIB2_SEARCH", + "WAIT FOR CON SETUP", + "COMPLETING SETUP", + "RRC CONNECTED"}; + +} // namespace srsue + + +#endif // RRC_COMMON_H diff --git a/srsue/src/CMakeLists.txt b/srsue/src/CMakeLists.txt index 4b2a7e282..5c6000f63 100644 --- a/srsue/src/CMakeLists.txt +++ b/srsue/src/CMakeLists.txt @@ -31,7 +31,7 @@ if (RPATH) set(CMAKE_BUILD_WITH_INSTALL_RPATH TRUE) endif (RPATH) -add_executable(srsue main.cc ue.cc metrics_stdout.cc) +add_executable(srsue main.cc ue_base.cc ue.cc metrics_stdout.cc) target_link_libraries(srsue srsue_mac srsue_phy srsue_upper @@ -57,3 +57,5 @@ if (NOT ${BUILDUE_CMD} STREQUAL "") else(NOT ${BUILDUE_CMD} STREQUAL "") message(STATUS "No post-build-UE command defined") endif (NOT ${BUILDUE_CMD} STREQUAL "") + +install(TARGETS srsue DESTINATION ${RUNTIME_DIR}) diff --git a/srsue/src/mac/demux.cc b/srsue/src/mac/demux.cc index c7c73a14b..4fcb402fc 100644 --- a/srsue/src/mac/demux.cc +++ b/srsue/src/mac/demux.cc @@ -36,11 +36,11 @@ namespace srsue { -demux::demux() : mac_msg(20), pending_mac_msg(20) +demux::demux(uint8_t nof_harq_proc_) : mac_msg(20), pending_mac_msg(20), nof_harq_proc(nof_harq_proc_) { } -void demux::init(phy_interface_mac* phy_h_, rlc_interface_mac *rlc_, srslte::log* log_h_, srslte::timers* timers_db_) +void demux::init(phy_interface_mac_common* phy_h_, rlc_interface_mac *rlc_, srslte::log* log_h_, srslte::timers* timers_db_) { phy_h = phy_h_; log_h = log_h_; @@ -68,9 +68,9 @@ void demux::deallocate(uint8_t* payload_buffer_ptr) uint8_t* demux::request_buffer(uint32_t pid, uint32_t len) { uint8_t *buff = NULL; - if (pid < NOF_HARQ_PID) { + if (pid < nof_harq_proc) { return pdus.request(len); - } else if (pid == NOF_HARQ_PID) { + } else if (pid == nof_harq_proc) { buff = bcch_buffer; } else { Error("Requested buffer for invalid PID=%d\n", pid); @@ -119,9 +119,9 @@ void demux::push_pdu_temp_crnti(uint8_t *buff, uint32_t nof_bytes) */ void demux::push_pdu(uint32_t pid, uint8_t *buff, uint32_t nof_bytes, uint32_t tstamp) { - if (pid < NOF_HARQ_PID) { + if (pid < nof_harq_proc) { return pdus.push(buff, nof_bytes, tstamp); - } else if (pid == NOF_HARQ_PID) { + } else if (pid == nof_harq_proc) { /* Demultiplexing of MAC PDU associated with SI-RNTI. The PDU passes through * the MAC in transparent mode. * Warning: In this case function sends the message to RLC now, since SI blocks do not @@ -190,8 +190,8 @@ bool demux::process_ce(srslte::sch_subh *subh) { Info("Received TA=%d\n", subh->get_ta_cmd()); // Start or restart timeAlignmentTimer - timers_db->get(mac::TIME_ALIGNMENT)->reset(); - timers_db->get(mac::TIME_ALIGNMENT)->run(); + timers_db->get(TIME_ALIGNMENT)->reset(); + timers_db->get(TIME_ALIGNMENT)->run(); break; case srslte::sch_subh::PADDING: break; diff --git a/srsue/src/mac/dl_harq.cc b/srsue/src/mac/dl_harq.cc deleted file mode 100644 index 685224786..000000000 --- a/srsue/src/mac/dl_harq.cc +++ /dev/null @@ -1,337 +0,0 @@ -/** - * - * \section COPYRIGHT - * - * Copyright 2013-2015 Software Radio Systems Limited - * - * \section LICENSE - * - * This file is part of the srsUE library. - * - * srsUE 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. - * - * srsUE 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/. - * - */ - -#define Error(fmt, ...) log_h->error_line(__FILE__, __LINE__, fmt, ##__VA_ARGS__) -#define Warning(fmt, ...) log_h->warning_line(__FILE__, __LINE__, fmt, ##__VA_ARGS__) -#define Info(fmt, ...) log_h->info_line(__FILE__, __LINE__, fmt, ##__VA_ARGS__) -#define Debug(fmt, ...) log_h->debug_line(__FILE__, __LINE__, fmt, ##__VA_ARGS__) - -#include "mac/mac.h" -#include "mac/dl_harq.h" - - -namespace srsue { - - - /*********************************************************** - * - * HARQ ENTITY - * - *********************************************************/ - -dl_harq_entity::dl_harq_entity() -{ - pcap = NULL; -} - -bool dl_harq_entity::init(srslte::log* log_h_, mac_interface_rrc::mac_cfg_t *mac_cfg_, srslte::timers* timers_, demux *demux_unit_) -{ - timers_db = timers_; - demux_unit = demux_unit_; - mac_cfg = mac_cfg_; - si_window_start = 0; - log_h = log_h_; - for (uint32_t i=0;iget(mac::TIME_ALIGNMENT)->is_running()) { - //phy_h->send_sps_ack(); - Warning("PHY Send SPS ACK not implemented\n"); - } - } else { - Error("SPS not implemented\n"); - //dl_sps_assig.reset(grant.tti, grant); - //grant.ndi = true; - //procs[harq_pid].save_grant(); - } - } - } -} - -void dl_harq_entity::tb_decoded(bool ack, srslte_rnti_type_t rnti_type, uint32_t harq_pid) -{ - if (rnti_type == SRSLTE_RNTI_SI) { - proc[NOF_HARQ_PROC].tb_decoded(ack); - } else { - proc[harq_pid%NOF_HARQ_PROC].tb_decoded(ack); - } -} - -int dl_harq_entity::get_current_tbs(uint32_t harq_pid) -{ - return proc[harq_pid%NOF_HARQ_PROC].get_current_tbs(); -} - - -bool dl_harq_entity::generate_ack_callback(void *arg) -{ - demux *demux_unit = (demux*) arg; - return demux_unit->get_uecrid_successful(); -} - -void dl_harq_entity::set_si_window_start(int si_window_start_) -{ - si_window_start = si_window_start_; -} - -float dl_harq_entity::get_average_retx() -{ - return average_retx; -} - - /*********************************************************** - * - * HARQ PROCESS - * - *********************************************************/ - -dl_harq_entity::dl_harq_process::dl_harq_process() { - is_initiated = false; - ack = false; - bzero(&cur_grant, sizeof(mac_interface_phy::mac_grant_t)); -} - -void dl_harq_entity::dl_harq_process::reset() { - ack = false; - payload_buffer_ptr = NULL; - bzero(&cur_grant, sizeof(mac_interface_phy::mac_grant_t)); - if (is_initiated) { - srslte_softbuffer_rx_reset(&softbuffer); - } -} - -bool dl_harq_entity::dl_harq_process::init(uint32_t pid_, dl_harq_entity *parent) { - if (srslte_softbuffer_rx_init(&softbuffer, 110)) { - Error("Error initiating soft buffer\n"); - return false; - } else { - pid = pid_; - is_initiated = true; - harq_entity = parent; - log_h = harq_entity->log_h; - return true; - } -} - -bool dl_harq_entity::dl_harq_process::is_sps() -{ - return false; -} - -bool dl_harq_entity::dl_harq_process::calc_is_new_transmission(mac_interface_phy::mac_grant_t grant) { - - bool is_new_tb = true; - if ((srslte_tti_interval(grant.tti, cur_grant.tti) <= 8 && (grant.n_bytes == cur_grant.n_bytes)) || - pid == HARQ_BCCH_PID) - { - is_new_tb = false; - } - - if ((grant.ndi != cur_grant.ndi && !is_new_tb) || // NDI toggled for same TB - is_new_tb || // is new TB - (pid == HARQ_BCCH_PID && grant.rv == 0)) // Broadcast PID and 1st TX (RV=0) - { - is_new_transmission = true; - Debug("Set HARQ for new transmission\n"); - } else { - is_new_transmission = false; - Debug("Set HARQ for retransmission\n"); - } - - return is_new_transmission; -} - -void dl_harq_entity::dl_harq_process::new_grant_dl(mac_interface_phy::mac_grant_t grant, mac_interface_phy::tb_action_dl_t* action) -{ - // Compute RV for BCCH when not specified in PDCCH format - if (pid == HARQ_BCCH_PID && grant.rv == -1) { - uint32_t k; - if ((grant.tti/10)%2 == 0 && grant.tti%10 == 5) { // This is SIB1, k is different - k = (grant.tti/20)%4; - grant.rv = ((uint32_t) ceilf((float)1.5*k))%4; - } else if (grant.rv == -1) { - k = (grant.tti-harq_entity->si_window_start)%4; - grant.rv = ((uint32_t) ceilf((float)1.5*k))%4; - } - } - calc_is_new_transmission(grant); - if (is_new_transmission) { - ack = false; - srslte_softbuffer_rx_reset_tbs(&softbuffer, cur_grant.n_bytes*8); - n_retx = 0; - } - - // Save grant - grant.last_ndi = cur_grant.ndi; - grant.last_tti = cur_grant.tti; - memcpy(&cur_grant, &grant, sizeof(mac_interface_phy::mac_grant_t)); - - // Fill action structure - bzero(action, sizeof(mac_interface_phy::tb_action_dl_t)); - action->default_ack = ack; - action->generate_ack = true; - action->decode_enabled = false; - - // If data has not yet been successfully decoded - if (ack == false) { - - // Instruct the PHY To combine the received data and attempt to decode it - payload_buffer_ptr = harq_entity->demux_unit->request_buffer(pid, cur_grant.n_bytes); - action->payload_ptr = payload_buffer_ptr; - if (!action->payload_ptr) { - action->decode_enabled = false; - Error("Can't get a buffer for TBS=%d\n", cur_grant.n_bytes); - return; - } - action->decode_enabled = true; - action->rv = cur_grant.rv; - action->rnti = cur_grant.rnti; - action->softbuffer = &softbuffer; - memcpy(&action->phy_grant, &cur_grant.phy_grant, sizeof(srslte_phy_grant_t)); - n_retx++; - - } else { - Warning("DL PID %d: Received duplicate TB. Discarting and retransmitting ACK\n", pid); - } - - if (pid == HARQ_BCCH_PID || harq_entity->timers_db->get(mac::TIME_ALIGNMENT)->is_expired()) { - // Do not generate ACK - Debug("Not generating ACK\n"); - action->generate_ack = false; - } else { - if (cur_grant.rnti_type == SRSLTE_RNTI_TEMP && ack == false) { - // Postpone ACK after contention resolution is resolved - action->generate_ack_callback = harq_entity->generate_ack_callback; - action->generate_ack_callback_arg = harq_entity->demux_unit; - Debug("ACK pending contention resolution\n"); - } else { - Debug("Generating ACK\n"); - } - } -} - -int dl_harq_entity::dl_harq_process::get_current_tbs() -{ - return cur_grant.n_bytes*8; -} - -void dl_harq_entity::dl_harq_process::tb_decoded(bool ack_) -{ - ack = ack_; - if (ack == true) { - if (pid == HARQ_BCCH_PID) { - if (harq_entity->pcap) { - harq_entity->pcap->write_dl_sirnti(payload_buffer_ptr, cur_grant.n_bytes, ack, cur_grant.tti); - } - Debug("Delivering PDU=%d bytes to Dissassemble and Demux unit (BCCH)\n", cur_grant.n_bytes); - harq_entity->demux_unit->push_pdu(pid, payload_buffer_ptr, cur_grant.n_bytes, cur_grant.tti); - } else { - if (harq_entity->pcap) { - harq_entity->pcap->write_dl_crnti(payload_buffer_ptr, cur_grant.n_bytes, cur_grant.rnti, ack, cur_grant.tti); - } - if (ack) { - if (cur_grant.rnti_type == SRSLTE_RNTI_TEMP) { - Debug("Delivering PDU=%d bytes to Dissassemble and Demux unit (Temporal C-RNTI)\n", cur_grant.n_bytes); - harq_entity->demux_unit->push_pdu_temp_crnti(payload_buffer_ptr, cur_grant.n_bytes); - } else { - Debug("Delivering PDU=%d bytes to Dissassemble and Demux unit\n", cur_grant.n_bytes); - harq_entity->demux_unit->push_pdu(pid, payload_buffer_ptr, cur_grant.n_bytes, cur_grant.tti); - - // Compute average number of retransmissions per packet - harq_entity->average_retx = SRSLTE_VEC_CMA((float) n_retx, harq_entity->average_retx, harq_entity->nof_pkts++); - } - } - } - } else { - harq_entity->demux_unit->deallocate(payload_buffer_ptr); - } - - Info("DL %d: %s tbs=%d, rv=%d, ack=%s, ndi=%d (%d), tti=%d (%d)\n", - pid, is_new_transmission?"newTX":"reTX ", - cur_grant.n_bytes, cur_grant.rv, ack?"OK":"KO", - cur_grant.ndi, cur_grant.last_ndi, cur_grant.tti, cur_grant.last_tti); - - if (ack && pid == HARQ_BCCH_PID) { - reset(); - } -} - - - -} diff --git a/srsue/src/mac/mac.cc b/srsue/src/mac/mac.cc index f583dd2df..e1426780e 100644 --- a/srsue/src/mac/mac.cc +++ b/srsue/src/mac/mac.cc @@ -42,7 +42,9 @@ namespace srsue { mac::mac() : ttisync(10240), - timers_db((uint32_t) NOF_MAC_TIMERS), + timers_db((uint32_t) NOF_MAC_TIMERS), + mux_unit(MAC_NOF_HARQ_PROC), + demux_unit(MAC_NOF_HARQ_PROC), pdu_process_thread(&demux_unit) { started = false; @@ -66,13 +68,13 @@ bool mac::init(phy_interface_mac *phy, rlc_interface_mac *rlc, rrc_interface_mac srslte_softbuffer_rx_init(&pch_softbuffer, 100); bsr_procedure.init( rlc_h, log_h, &config, &timers_db); - phr_procedure.init(phy_h, log_h, &config, &timers_db); - mux_unit.init ( rlc_h, log_h, &bsr_procedure, &phr_procedure); - demux_unit.init (phy_h, rlc_h, log_h, &timers_db); - ra_procedure.init (phy_h, rrc, log_h, &uernti, &config, &timers_db, &mux_unit, &demux_unit); + phr_procedure.init(phy_h, log_h, &config, &timers_db); + mux_unit.init ( rlc_h, log_h, &bsr_procedure, &phr_procedure); + demux_unit.init (phy_h, rlc_h, log_h, &timers_db); + ra_procedure.init (phy_h, rrc, log_h, &uernti, &config, &timers_db, &mux_unit, &demux_unit); sr_procedure.init (phy_h, rrc, log_h, &config); - ul_harq.init ( log_h, &uernti, &config, &timers_db, &mux_unit); - dl_harq.init ( log_h, &config, &timers_db, &demux_unit); + ul_harq.init ( log_h, &uernti, &config.ul_harq_params, &timers_db, &mux_unit); + dl_harq.init ( log_h, &timers_db, &demux_unit); reset(); @@ -308,7 +310,7 @@ void mac::new_grant_ul(mac_interface_phy::mac_grant_t grant, mac_interface_phy:: /* Start PHR Periodic timer on first UL grant */ if (is_first_ul_grant) { is_first_ul_grant = false; - timers_db.get(mac::PHR_TIMER_PERIODIC)->run(); + timers_db.get(PHR_TIMER_PERIODIC)->run(); } if (grant.rnti_type == SRSLTE_RNTI_USER && ra_procedure.is_contention_resolution()) { ra_procedure.pdcch_to_crnti(true); diff --git a/srsue/src/mac/mux.cc b/srsue/src/mac/mux.cc index 58ba3d57f..5ab58fb50 100644 --- a/srsue/src/mac/mux.cc +++ b/srsue/src/mac/mux.cc @@ -37,7 +37,7 @@ namespace srsue { -mux::mux() : pdu_msg(MAX_NOF_SUBHEADERS) +mux::mux(uint8_t nof_harq_proc_) : pdu_msg(MAX_NOF_SUBHEADERS), pid_has_bsr(nof_harq_proc_), nof_harq_proc(nof_harq_proc_) { pthread_mutex_init(&mutex, NULL); @@ -51,7 +51,7 @@ mux::mux() : pdu_msg(MAX_NOF_SUBHEADERS) msg3_flush(); } -void mux::init(rlc_interface_mac *rlc_, srslte::log *log_h_, bsr_proc *bsr_procedure_, phr_proc *phr_procedure_) +void mux::init(rlc_interface_mac *rlc_, srslte::log *log_h_, bsr_interface_mux *bsr_procedure_, phr_proc *phr_procedure_) { log_h = log_h_; rlc = rlc_; @@ -141,7 +141,7 @@ srslte::sch_subh::cetype bsr_format_convert(bsr_proc::bsr_format_t format) { void mux::pusch_retx(uint32_t tx_tti, uint32_t pid) { - if (pid_has_bsr[pid%MAX_HARQ_PROC]) { + if (pid_has_bsr[pid%nof_harq_proc]) { bsr_procedure->set_tx_tti(tx_tti); } } @@ -189,13 +189,17 @@ uint8_t* mux::pdu_get(uint8_t *payload, uint32_t pdu_sz, uint32_t tx_tti, uint32 bsr_is_inserted = true; } } + // MAC control element for PHR - float phr_value; - if (phr_procedure->generate_phr_on_ul_grant(&phr_value)) { - if (pdu_msg.new_subh()) { - pdu_msg.get()->set_phr(phr_value); + if (phr_procedure) { + float phr_value; + if (phr_procedure->generate_phr_on_ul_grant(&phr_value)) { + if (pdu_msg.new_subh()) { + pdu_msg.get()->set_phr(phr_value); + } } } + // Update buffer states for all logical channels int sdu_space = pdu_msg.get_sdu_space(); for (uint32_t i=0;iset_tx_tti(tx_tti); } diff --git a/srsue/src/mac/proc_bsr.cc b/srsue/src/mac/proc_bsr.cc index d93b7f0f4..3117eeffc 100644 --- a/srsue/src/mac/proc_bsr.cc +++ b/srsue/src/mac/proc_bsr.cc @@ -57,10 +57,10 @@ void bsr_proc::init(rlc_interface_mac *rlc_, srslte::log* log_h_, mac_interface_ void bsr_proc::reset() { - timers_db->get(mac::BSR_TIMER_PERIODIC)->stop(); - timers_db->get(mac::BSR_TIMER_PERIODIC)->reset(); - timers_db->get(mac::BSR_TIMER_RETX)->stop(); - timers_db->get(mac::BSR_TIMER_RETX)->reset(); + timers_db->get(BSR_TIMER_PERIODIC)->stop(); + timers_db->get(BSR_TIMER_PERIODIC)->reset(); + timers_db->get(BSR_TIMER_RETX)->stop(); + timers_db->get(BSR_TIMER_RETX)->reset(); reset_sr = false; sr_is_sent = false; @@ -78,14 +78,14 @@ void bsr_proc::reset() /* Process Periodic BSR */ void bsr_proc::timer_expired(uint32_t timer_id) { switch(timer_id) { - case mac::BSR_TIMER_PERIODIC: + case BSR_TIMER_PERIODIC: if (triggered_bsr_type == NONE) { // Check condition 4 in Sec 5.4.5 triggered_bsr_type = PERIODIC; Debug("BSR: Triggering Periodic BSR\n"); } break; - case mac::BSR_TIMER_RETX: + case BSR_TIMER_RETX: // Enable reTx of SR only if periodic timer is not infinity int periodic = liblte_rrc_periodic_bsr_timer_num[mac_cfg->main.ulsch_cnfg.periodic_bsr_timer]; if (periodic >= 0) { @@ -222,17 +222,17 @@ void bsr_proc::step(uint32_t tti) } int periodic = liblte_rrc_periodic_bsr_timer_num[mac_cfg->main.ulsch_cnfg.periodic_bsr_timer]; - if (periodic > 0 && (uint32_t)periodic != timers_db->get(mac::BSR_TIMER_PERIODIC)->get_timeout()) + if (periodic > 0 && (uint32_t)periodic != timers_db->get(BSR_TIMER_PERIODIC)->get_timeout()) { - timers_db->get(mac::BSR_TIMER_PERIODIC)->set(this, periodic); - timers_db->get(mac::BSR_TIMER_PERIODIC)->run(); + timers_db->get(BSR_TIMER_PERIODIC)->set(this, periodic); + timers_db->get(BSR_TIMER_PERIODIC)->run(); Info("BSR: Configured timer periodic %d ms\n", periodic); } int retx = liblte_rrc_retransmission_bsr_timer_num[mac_cfg->main.ulsch_cnfg.retx_bsr_timer]; - if (retx > 0 && (uint32_t)retx != timers_db->get(mac::BSR_TIMER_RETX)->get_timeout()) + if (retx > 0 && (uint32_t)retx != timers_db->get(BSR_TIMER_RETX)->get_timeout()) { - timers_db->get(mac::BSR_TIMER_RETX)->set(this, retx); - timers_db->get(mac::BSR_TIMER_RETX)->run(); + timers_db->get(BSR_TIMER_RETX)->set(this, retx); + timers_db->get(BSR_TIMER_RETX)->run(); Info("BSR: Configured timer reTX %d ms\n", retx); } @@ -309,18 +309,18 @@ bool bsr_proc::need_to_send_bsr_on_ul_grant(uint32_t grant_size, bsr_t *bsr) grant_size, total_data, bsr_sz); ret = true; } - if (timers_db->get(mac::BSR_TIMER_PERIODIC)->get_timeout() && bsr->format != TRUNC_BSR) { - timers_db->get(mac::BSR_TIMER_PERIODIC)->reset(); - timers_db->get(mac::BSR_TIMER_PERIODIC)->run(); + if (timers_db->get(BSR_TIMER_PERIODIC)->get_timeout() && bsr->format != TRUNC_BSR) { + timers_db->get(BSR_TIMER_PERIODIC)->reset(); + timers_db->get(BSR_TIMER_PERIODIC)->run(); } } // Cancel all triggered BSR and SR triggered_bsr_type = NONE; reset_sr = true; // Restart or Start ReTX timer - if (timers_db->get(mac::BSR_TIMER_RETX)->get_timeout()) { - timers_db->get(mac::BSR_TIMER_RETX)->reset(); - timers_db->get(mac::BSR_TIMER_RETX)->run(); + if (timers_db->get(BSR_TIMER_RETX)->get_timeout()) { + timers_db->get(BSR_TIMER_RETX)->reset(); + timers_db->get(BSR_TIMER_RETX)->run(); } return ret; } @@ -340,9 +340,9 @@ bool bsr_proc::generate_padding_bsr(uint32_t nof_padding_bytes, bsr_t *bsr) bsr_type_tostring(triggered_bsr_type), bsr_format_tostring(bsr->format), bsr->buff_size[0], bsr->buff_size[1], bsr->buff_size[2], bsr->buff_size[3]); - if (timers_db->get(mac::BSR_TIMER_PERIODIC)->get_timeout() && bsr->format != TRUNC_BSR) { - timers_db->get(mac::BSR_TIMER_PERIODIC)->reset(); - timers_db->get(mac::BSR_TIMER_PERIODIC)->run(); + if (timers_db->get(BSR_TIMER_PERIODIC)->get_timeout() && bsr->format != TRUNC_BSR) { + timers_db->get(BSR_TIMER_PERIODIC)->reset(); + timers_db->get(BSR_TIMER_PERIODIC)->run(); } } diff --git a/srsue/src/mac/proc_phr.cc b/srsue/src/mac/proc_phr.cc index b432f1c06..11828f306 100644 --- a/srsue/src/mac/proc_phr.cc +++ b/srsue/src/mac/proc_phr.cc @@ -76,13 +76,13 @@ bool phr_proc::pathloss_changed() { /* Trigger PHR when timers exire */ void phr_proc::timer_expired(uint32_t timer_id) { switch(timer_id) { - case mac::PHR_TIMER_PERIODIC: - timers_db->get(mac::PHR_TIMER_PERIODIC)->reset(); - timers_db->get(mac::PHR_TIMER_PERIODIC)->run(); + case PHR_TIMER_PERIODIC: + timers_db->get(PHR_TIMER_PERIODIC)->reset(); + timers_db->get(PHR_TIMER_PERIODIC)->run(); Debug("PHR: Triggered by timer periodic (timer expired).\n"); phr_is_triggered = true; break; - case mac::PHR_TIMER_PROHIBIT: + case PHR_TIMER_PROHIBIT: int pathloss_db = liblte_rrc_dl_pathloss_change_num[mac_cfg->main.phr_cnfg.dl_pathloss_change]; if (pathloss_changed()) { Info("PHR: Triggered by pathloss difference. cur_pathloss_db=%f (timer expired)\n", last_pathloss_db); @@ -105,8 +105,8 @@ void phr_proc::step(uint32_t tti) if (timer_periodic != cfg_timer_periodic && cfg_timer_periodic > 0) { timer_periodic = cfg_timer_periodic; - timers_db->get(mac::PHR_TIMER_PERIODIC)->set(this, timer_periodic); - timers_db->get(mac::PHR_TIMER_PERIODIC)->run(); + timers_db->get(PHR_TIMER_PERIODIC)->set(this, timer_periodic); + timers_db->get(PHR_TIMER_PERIODIC)->run(); phr_is_triggered = true; Info("PHR: Configured timer periodic %d ms\n", timer_periodic); } @@ -118,12 +118,12 @@ void phr_proc::step(uint32_t tti) if (timer_prohibit != cfg_timer_prohibit && cfg_timer_prohibit > 0) { timer_prohibit = cfg_timer_prohibit; - timers_db->get(mac::PHR_TIMER_PROHIBIT)->set(this, timer_prohibit); - timers_db->get(mac::PHR_TIMER_PROHIBIT)->run(); + timers_db->get(PHR_TIMER_PROHIBIT)->set(this, timer_prohibit); + timers_db->get(PHR_TIMER_PROHIBIT)->run(); Info("PHR: Configured timer prohibit %d ms\n", timer_prohibit); phr_is_triggered = true; } - if (pathloss_changed() && timers_db->get(mac::PHR_TIMER_PROHIBIT)->is_expired()) + if (pathloss_changed() && timers_db->get(PHR_TIMER_PROHIBIT)->is_expired()) { Info("PHR: Triggered by pathloss difference. cur_pathloss_db=%f\n", last_pathloss_db); phr_is_triggered = true; @@ -140,10 +140,10 @@ bool phr_proc::generate_phr_on_ul_grant(float *phr) Debug("PHR: Generating PHR=%f\n", phr?*phr:0.0); - timers_db->get(mac::PHR_TIMER_PERIODIC)->reset(); - timers_db->get(mac::PHR_TIMER_PROHIBIT)->reset(); - timers_db->get(mac::PHR_TIMER_PERIODIC)->run(); - timers_db->get(mac::PHR_TIMER_PROHIBIT)->run(); + timers_db->get(PHR_TIMER_PERIODIC)->reset(); + timers_db->get(PHR_TIMER_PROHIBIT)->reset(); + timers_db->get(PHR_TIMER_PERIODIC)->run(); + timers_db->get(PHR_TIMER_PROHIBIT)->run(); phr_is_triggered = false; diff --git a/srsue/src/mac/proc_ra.cc b/srsue/src/mac/proc_ra.cc index 495c9945f..73b51d61c 100644 --- a/srsue/src/mac/proc_ra.cc +++ b/srsue/src/mac/proc_ra.cc @@ -115,7 +115,7 @@ void ra_proc::read_params() { delta_preamble_db = delta_preamble_db_table[configIndex%5]; if (contentionResolutionTimer > 0) { - timers_db->get(mac::CONTENTION_TIMER)->set(this, contentionResolutionTimer); + timers_db->get(CONTENTION_TIMER)->set(this, contentionResolutionTimer); } } @@ -165,14 +165,14 @@ void ra_proc::process_timeadv_cmd(uint32_t ta) { if (preambleIndex == 0) { // Preamble not selected by UE MAC phy_h->set_timeadv_rar(ta); - timers_db->get(mac::TIME_ALIGNMENT)->reset(); - timers_db->get(mac::TIME_ALIGNMENT)->run(); + timers_db->get(TIME_ALIGNMENT)->reset(); + timers_db->get(TIME_ALIGNMENT)->run(); Debug("Applying RAR TA CMD %d\n", ta); } else { // Preamble selected by UE MAC - if (!timers_db->get(mac::TIME_ALIGNMENT)->is_running()) { + if (!timers_db->get(TIME_ALIGNMENT)->is_running()) { phy_h->set_timeadv_rar(ta); - timers_db->get(mac::TIME_ALIGNMENT)->run(); + timers_db->get(TIME_ALIGNMENT)->run(); Debug("Applying RAR TA CMD %d\n", ta); } else { // Ignore TA CMD @@ -355,8 +355,8 @@ void ra_proc::tb_decoded_ok() { state = CONTENTION_RESOLUTION; // Start contention resolution timer - timers_db->get(mac::CONTENTION_TIMER)->reset(); - timers_db->get(mac::CONTENTION_TIMER)->run(); + timers_db->get(CONTENTION_TIMER)->reset(); + timers_db->get(CONTENTION_TIMER)->run(); } } else { rDebug("Found RAR for preamble %d\n", rar_pdu_msg.get()->get_rapid()); @@ -417,7 +417,7 @@ bool ra_proc::contention_resolution_id_received(uint64_t rx_contention_id) { rDebug("MAC PDU Contains Contention Resolution ID CE\n"); // MAC PDU successfully decoded and contains MAC CE contention Id - timers_db->get(mac::CONTENTION_TIMER)->stop(); + timers_db->get(CONTENTION_TIMER)->stop(); if (transmitted_contention_id == rx_contention_id) { @@ -453,7 +453,7 @@ void ra_proc::step_contention_resolution() { (started_by_pdcch && pdcch_to_crnti_received != PDCCH_CRNTI_NOT_RECEIVED)) { rDebug("PDCCH for C-RNTI received\n"); - timers_db->get(mac::CONTENTION_TIMER)->stop(); + timers_db->get(CONTENTION_TIMER)->stop(); rntis->temp_rnti = 0; state = COMPLETION; } @@ -559,7 +559,7 @@ void ra_proc::pdcch_to_crnti(bool contains_uplink_grant) { void ra_proc::harq_retx() { - timers_db->get(mac::CONTENTION_TIMER)->reset(); + timers_db->get(CONTENTION_TIMER)->reset(); } } diff --git a/srsue/src/mac/ul_harq.cc b/srsue/src/mac/ul_harq.cc deleted file mode 100644 index da28d62b3..000000000 --- a/srsue/src/mac/ul_harq.cc +++ /dev/null @@ -1,394 +0,0 @@ -/** - * - * \section COPYRIGHT - * - * Copyright 2013-2015 Software Radio Systems Limited - * - * \section LICENSE - * - * This file is part of the srsUE library. - * - * srsUE 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. - * - * srsUE 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/. - * - */ - -#define Error(fmt, ...) log_h->error_line(__FILE__, __LINE__, fmt, ##__VA_ARGS__) -#define Warning(fmt, ...) log_h->warning_line(__FILE__, __LINE__, fmt, ##__VA_ARGS__) -#define Info(fmt, ...) log_h->info_line(__FILE__, __LINE__, fmt, ##__VA_ARGS__) -#define Debug(fmt, ...) log_h->debug_line(__FILE__, __LINE__, fmt, ##__VA_ARGS__) - -#include "srslte/common/log.h" -#include "mac/mac.h" -#include "mac/ul_harq.h" - - - namespace srsue { - - /*********************************************************** - * - * HARQ ENTITY - * - *********************************************************/ - -bool ul_harq_entity::init(srslte::log *log_h_, - mac_interface_rrc::ue_rnti_t *rntis_, - mac_interface_rrc::mac_cfg_t *mac_cfg_, - srslte::timers *timers_db_, - mux *mux_unit_) { - log_h = log_h_; - mux_unit = mux_unit_; - mac_cfg = mac_cfg_; - rntis = rntis_; - timers_db = timers_db_; - for (uint32_t i=0;ilog_h; - pid = pid_; - payload_buffer = (uint8_t*) srslte_vec_malloc(payload_buffer_len*sizeof(uint8_t)); - if (!payload_buffer) { - Error("Allocating memory\n"); - return false; - } - pdu_ptr = payload_buffer; - return true; - } -} - -void ul_harq_entity::ul_harq_process::run_tti(uint32_t tti_tx, mac_interface_phy::mac_grant_t* grant, mac_interface_phy::tb_action_ul_t* action) -{ - - - uint32_t max_retx; - if (is_msg3) { - max_retx = harq_entity->mac_cfg->rach.max_harq_msg3_tx; - } else { - max_retx = liblte_rrc_max_harq_tx_num[harq_entity->mac_cfg->main.ulsch_cnfg.max_harq_tx]; - } - - - // Receive and route HARQ feedbacks - if (grant) { - if ((!(grant->rnti_type == SRSLTE_RNTI_TEMP) && grant->ndi != get_ndi()) || - (grant->rnti_type == SRSLTE_RNTI_USER && !has_grant()) || - grant->is_from_rar) - { - // New transmission - - // Uplink grant in a RAR - if (grant->is_from_rar) { - Debug("Getting Msg3 buffer payload, grant size=%d bytes\n", grant->n_bytes); - pdu_ptr = harq_entity->mux_unit->msg3_get(payload_buffer, grant->n_bytes); - if (pdu_ptr) { - generate_new_tx(tti_tx, true, grant, action); - } else { - Warning("UL RAR grant available but no Msg3 on buffer\n"); - } - - // Normal UL grant - } else { - // Request a MAC PDU from the Multiplexing & Assemble Unit - pdu_ptr = harq_entity->mux_unit->pdu_get(payload_buffer, grant->n_bytes, tti_tx, pid); - if (pdu_ptr) { - generate_new_tx(tti_tx, false, grant, action); - } else { - Warning("Uplink grant but no MAC PDU in Multiplex Unit buffer\n"); - } - } - } else { - // Adaptive Re-TX - if (current_tx_nb >= max_retx) { - Info("UL %d: Maximum number of ReTX reached (%d). Discarting TB.\n", pid, max_retx); - reset(); - action->expect_ack = false; - } else { - generate_retx(tti_tx, grant, action); - } - } - } else if (has_grant()) { - // Non-Adaptive Re-Tx - if (current_tx_nb >= max_retx) { - Info("UL %d: Maximum number of ReTX reached (%d). Discarting TB.\n", pid, max_retx); - reset(); - action->expect_ack = false; - } else { - generate_retx(tti_tx, action); - } - } - if (harq_entity->pcap && grant) { - if (grant->is_from_rar) { - grant->rnti = harq_entity->rntis->temp_rnti; - } - harq_entity->pcap->write_ul_crnti(pdu_ptr, grant->n_bytes, grant->rnti, get_nof_retx(), tti_tx); - } - - - -} - -int ul_harq_entity::ul_harq_process::get_current_tbs() -{ - return cur_grant.n_bytes*8; -} - -void ul_harq_entity::ul_harq_process::generate_retx(uint32_t tti_tx, mac_interface_phy::tb_action_ul_t *action) -{ - generate_retx(tti_tx, NULL, action); -} - -// Retransmission with or w/o grant (Section 5.4.2.2) -void ul_harq_entity::ul_harq_process::generate_retx(uint32_t tti_tx, mac_interface_phy::mac_grant_t *grant, - mac_interface_phy::tb_action_ul_t *action) -{ - if (grant) { - // HARQ entity requests an adaptive transmission - if (grant->rv) { - current_irv = irv_of_rv[grant->rv%4]; - } - memcpy(&cur_grant, grant, sizeof(mac_interface_phy::mac_grant_t)); - harq_feedback = false; - Info("UL %d: Adaptive retx=%d, RV=%d, TBS=%d\n", - pid, current_tx_nb, get_rv(), grant->n_bytes); - generate_tx(tti_tx, action); - } else { - Info("UL %d: Non-Adaptive retx=%d, RV=%d, TBS=%d\n", - pid, current_tx_nb, get_rv(), cur_grant.n_bytes); - // HARQ entity requests a non-adaptive transmission - if (!harq_feedback) { - generate_tx(tti_tx, action); - } - } - - // On every Msg3 retransmission, restart mac-ContentionResolutionTimer as defined in Section 5.1.5 - if (is_msg3) { - harq_entity->timers_db->get(mac::CONTENTION_TIMER)->reset(); - } - - harq_entity->mux_unit->pusch_retx(tti_tx, pid); -} - -// New transmission (Section 5.4.2.2) -void ul_harq_entity::ul_harq_process::generate_new_tx(uint32_t tti_tx, bool is_msg3_, - mac_interface_phy::mac_grant_t *grant, - mac_interface_phy::tb_action_ul_t *action) -{ - if (grant) { - - // Compute average number of retransmissions per packet considering previous packet - harq_entity->average_retx = SRSLTE_VEC_CMA((float) current_tx_nb, harq_entity->average_retx, harq_entity->nof_pkts++); - - - memcpy(&cur_grant, grant, sizeof(mac_interface_phy::mac_grant_t)); - harq_feedback = false; - is_grant_configured = true; - current_tx_nb = 0; - current_irv = 0; - is_msg3 = is_msg3_; - Info("UL %d: New TX%s, RV=%d, TBS=%d, RNTI=%d\n", - pid, is_msg3?" for Msg3":"", get_rv(), cur_grant.n_bytes, cur_grant.rnti); - generate_tx(tti_tx, action); - } -} - -// Transmission of pending frame (Section 5.4.2.2) -void ul_harq_entity::ul_harq_process::generate_tx(uint32_t tti_tx, mac_interface_phy::tb_action_ul_t *action) -{ - action->current_tx_nb = current_tx_nb; - current_tx_nb++; - action->expect_ack = true; - action->rnti = is_msg3?harq_entity->rntis->temp_rnti:cur_grant.rnti; - action->rv = cur_grant.rv>0?cur_grant.rv:get_rv(); - action->softbuffer = &softbuffer; - action->tx_enabled = true; - action->payload_ptr = pdu_ptr; - memcpy(&action->phy_grant, &cur_grant.phy_grant, sizeof(srslte_phy_grant_t)); - - current_irv = (current_irv+1)%4; - tti_last_tx = tti_tx; -} - -bool ul_harq_entity::ul_harq_process::is_sps() -{ - return false; -} - -uint32_t ul_harq_entity::ul_harq_process::last_tx_tti() -{ - return tti_last_tx; -} - -uint32_t ul_harq_entity::ul_harq_process::get_nof_retx() -{ - return current_tx_nb; -} - -} diff --git a/srsue/src/main.cc b/srsue/src/main.cc index f114c0606..16e0cb59f 100644 --- a/srsue/src/main.cc +++ b/srsue/src/main.cc @@ -126,7 +126,7 @@ void parse_args(all_args_t *args, int argc, char *argv[]) { "index of the core used by the sync thread") ("expert.ue_category", - bpo::value(&args->expert.ue_cateogry)->default_value(4), + bpo::value(&args->expert.ue_cateogry)->default_value("4"), "UE Category (1 to 5)") ("expert.metrics_period_secs", @@ -342,18 +342,26 @@ void *input_loop(void *m) { return NULL; } -int main(int argc, char *argv[]) { +int main(int argc, char *argv[]) +{ signal(SIGINT, sig_int_handler); all_args_t args; - metrics_stdout metrics; - ue *ue = ue::get_instance(); + parse_args(&args, argc, argv); - cout << "--- Software Radio Systems LTE UE ---" << endl << endl; - parse_args(&args, argc, argv); + srsue_instance_type_t type = LTE; + ue_base *ue = ue_base::get_instance(type); + if (!ue) { + cout << "Error creating UE instance." << endl << endl; + exit(1); + } + + cout << "--- Software Radio Systems " << srsue_instance_type_text[type] << " UE ---" << endl << endl; if (!ue->init(&args)) { exit(1); } + + metrics_stdout metrics; metrics.init(ue, args.expert.metrics_period_secs); pthread_t input; diff --git a/srsue/src/phy/phch_worker.cc b/srsue/src/phy/phch_worker.cc index 14de9b51a..c2796e2ad 100644 --- a/srsue/src/phy/phch_worker.cc +++ b/srsue/src/phy/phch_worker.cc @@ -240,6 +240,9 @@ void phch_worker::work_imp() set_uci_periodic_cqi(); } + /* TTI offset for UL is always 4 for LTE */ + ul_action.tti_offset = 4; + /* Send UL grant or HARQ information (from PHICH) to MAC */ if (ul_grant_available && ul_ack_available) { phy->mac->new_grant_ul_ack(ul_mac_grant, ul_ack, &ul_action); diff --git a/srsue/src/phy/phy.cc b/srsue/src/phy/phy.cc index cf673cce6..dea66346b 100644 --- a/srsue/src/phy/phy.cc +++ b/srsue/src/phy/phy.cc @@ -59,6 +59,7 @@ phy::phy() : workers_pool(MAX_WORKERS), void phy::set_default_args(phy_args_t *args) { + args->nof_rx_ant = 1; args->ul_pwr_ctrl_en = false; args->prach_gain = -1; args->cqi_max = -1; diff --git a/srsue/src/ue.cc b/srsue/src/ue.cc index 97f59c15e..0110a1a14 100644 --- a/srsue/src/ue.cc +++ b/srsue/src/ue.cc @@ -26,7 +26,6 @@ #include "ue.h" -//#include "srslte_version_check.h" #include "srslte/srslte.h" #include #include @@ -38,28 +37,6 @@ using namespace srslte; namespace srsue{ -ue* ue::instance = NULL; -pthread_mutex_t ue_instance_mutex = PTHREAD_MUTEX_INITIALIZER; - -ue* ue::get_instance(void) -{ - pthread_mutex_lock(&ue_instance_mutex); - if(NULL == instance) { - instance = new ue(); - } - pthread_mutex_unlock(&ue_instance_mutex); - return(instance); -} -void ue::cleanup(void) -{ - pthread_mutex_lock(&ue_instance_mutex); - if(NULL != instance) { - delete instance; - instance = NULL; - } - pthread_mutex_unlock(&ue_instance_mutex); -} - ue::ue() :started(false) { @@ -184,14 +161,15 @@ bool ue::init(all_args_t *args_) phy_log.console("Setting frequency: DL=%.1f Mhz, UL=%.1f MHz\n", args->rf.dl_freq/1e6, args->rf.ul_freq/1e6); mac.init(&phy, &rlc, &rrc, &mac_log); - rlc.init(&pdcp, &rrc, this, &rlc_log, &mac); - pdcp.init(&rlc, &rrc, &gw, &pdcp_log, SECURITY_DIRECTION_UPLINK); + rlc.init(&pdcp, &rrc, this, &rlc_log, &mac, 0 /* RB_ID_SRB0 */); + + pdcp.init(&rlc, &rrc, &gw, &pdcp_log, 0 /* RB_ID_SRB0 */, SECURITY_DIRECTION_UPLINK); + rrc.init(&phy, &mac, &rlc, &pdcp, &nas, &usim, &mac, &rrc_log); + rrc.set_ue_category(atoi(args->expert.ue_cateogry.c_str())); - rrc.set_ue_category(args->expert.ue_cateogry); - - nas.init(&usim, &rrc, &gw, &nas_log); - gw.init(&pdcp, &rrc, this, &gw_log); + nas.init(&usim, &rrc, &gw, &nas_log, 1 /* RB_ID_SRB1 */); + gw.init(&pdcp, &rrc, this, &gw_log, 3 /* RB_ID_DRB1 */); usim.init(&args->usim, &usim_log); started = true; @@ -271,49 +249,8 @@ bool ue::get_metrics(ue_metrics_t &m) void ue::rf_msg(srslte_rf_error_t error) { - ue *u = ue::get_instance(); - u->handle_rf_msg(error); -} - -void ue::handle_rf_msg(srslte_rf_error_t error) -{ - if(error.type == srslte_rf_error_t::SRSLTE_RF_ERROR_OVERFLOW) { - rf_metrics.rf_o++; - rf_metrics.rf_error = true; - rf_log.warning("Overflow\n"); - }else if(error.type == srslte_rf_error_t::SRSLTE_RF_ERROR_UNDERFLOW) { - rf_metrics.rf_u++; - rf_metrics.rf_error = true; - rf_log.warning("Underflow\n"); - } else if(error.type == srslte_rf_error_t::SRSLTE_RF_ERROR_LATE) { - rf_metrics.rf_l++; - rf_metrics.rf_error = true; - rf_log.warning("Late\n"); - } else if (error.type == srslte_rf_error_t::SRSLTE_RF_ERROR_OTHER) { - std::string str(error.msg); - str.erase(std::remove(str.begin(), str.end(), '\n'), str.end()); - str.erase(std::remove(str.begin(), str.end(), '\r'), str.end()); - str.push_back('\n'); - rf_log.info(str); - } -} - -srslte::LOG_LEVEL_ENUM ue::level(std::string l) -{ - std::transform(l.begin(), l.end(), l.begin(), ::toupper); - if("NONE" == l){ - return srslte::LOG_LEVEL_NONE; - }else if("ERROR" == l){ - return srslte::LOG_LEVEL_ERROR; - }else if("WARNING" == l){ - return srslte::LOG_LEVEL_WARNING; - }else if("INFO" == l){ - return srslte::LOG_LEVEL_INFO; - }else if("DEBUG" == l){ - return srslte::LOG_LEVEL_DEBUG; - }else{ - return srslte::LOG_LEVEL_NONE; - } + ue_base *ue = ue_base::get_instance(LTE); + ue->handle_rf_msg(error); } } // namespace srsue diff --git a/srsue/src/ue_base.cc b/srsue/src/ue_base.cc new file mode 100644 index 000000000..61cbafb2c --- /dev/null +++ b/srsue/src/ue_base.cc @@ -0,0 +1,111 @@ +/** + * + * \section COPYRIGHT + * + * Copyright 2013-2015 Software Radio Systems Limited + * + * \section LICENSE + * + * This file is part of the srsUE library. + * + * srsUE 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. + * + * srsUE 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 "ue_base.h" +#include "ue.h" +#include "srslte/srslte.h" +#include +#include +#include +#include +#include + +using namespace srslte; + +namespace srsue{ + +static ue_base* instance = NULL; +pthread_mutex_t ue_instance_mutex = PTHREAD_MUTEX_INITIALIZER; + +ue_base* ue_base::get_instance(srsue_instance_type_t type) +{ + pthread_mutex_lock(&ue_instance_mutex); + if(NULL == instance) { + switch (type) { + case LTE: + instance = new ue(); + break; + default: + perror("Unknown UE type.\n"); + } + } + pthread_mutex_unlock(&ue_instance_mutex); + return(instance); +} + +void ue_base::cleanup(void) +{ + pthread_mutex_lock(&ue_instance_mutex); + if(NULL != instance) { + delete instance; + instance = NULL; + } + pthread_mutex_unlock(&ue_instance_mutex); +} + +void ue_base::handle_rf_msg(srslte_rf_error_t error) +{ + if(error.type == srslte_rf_error_t::SRSLTE_RF_ERROR_OVERFLOW) { + rf_metrics.rf_o++; + rf_metrics.rf_error = true; + rf_log.warning("Overflow\n"); + }else if(error.type == srslte_rf_error_t::SRSLTE_RF_ERROR_UNDERFLOW) { + rf_metrics.rf_u++; + rf_metrics.rf_error = true; + rf_log.warning("Underflow\n"); + } else if(error.type == srslte_rf_error_t::SRSLTE_RF_ERROR_LATE) { + rf_metrics.rf_l++; + rf_metrics.rf_error = true; + rf_log.warning("Late\n"); + } else if (error.type == srslte_rf_error_t::SRSLTE_RF_ERROR_OTHER) { + std::string str(error.msg); + str.erase(std::remove(str.begin(), str.end(), '\n'), str.end()); + str.erase(std::remove(str.begin(), str.end(), '\r'), str.end()); + str.push_back('\n'); + rf_log.info(str); + } +} + +srslte::LOG_LEVEL_ENUM ue_base::level(std::string l) +{ + std::transform(l.begin(), l.end(), l.begin(), ::toupper); + if("NONE" == l){ + return srslte::LOG_LEVEL_NONE; + }else if("ERROR" == l){ + return srslte::LOG_LEVEL_ERROR; + }else if("WARNING" == l){ + return srslte::LOG_LEVEL_WARNING; + }else if("INFO" == l){ + return srslte::LOG_LEVEL_INFO; + }else if("DEBUG" == l){ + return srslte::LOG_LEVEL_DEBUG; + }else{ + return srslte::LOG_LEVEL_NONE; + } +} + +} // namespace srsue diff --git a/srsue/src/upper/nas.cc b/srsue/src/upper/nas.cc index 15dc154ae..1595a2cec 100644 --- a/srsue/src/upper/nas.cc +++ b/srsue/src/upper/nas.cc @@ -43,13 +43,15 @@ nas::nas() void nas::init(usim_interface_nas *usim_, rrc_interface_nas *rrc_, gw_interface_nas *gw_, - srslte::log *nas_log_) + srslte::log *nas_log_, + srslte::srslte_nas_config_t cfg_) { pool = byte_buffer_pool::get_instance(); usim = usim_; rrc = rrc_; gw = gw_; nas_log = nas_log_; + cfg = cfg_; } void nas::stop() @@ -85,7 +87,7 @@ void nas::write_pdu(uint32_t lcid, byte_buffer_t *pdu) uint8 pd; uint8 msg_type; - nas_log->info_hex(pdu->msg, pdu->N_bytes, "DL %s PDU", rb_id_text[lcid]); + nas_log->info_hex(pdu->msg, pdu->N_bytes, "DL %s PDU", rrc->get_rb_name(lcid).c_str()); // Parse the message liblte_mme_parse_msg_header((LIBLTE_BYTE_MSG_STRUCT*)pdu, &pd, &msg_type); @@ -492,8 +494,8 @@ void nas::parse_security_mode_command(uint32_t lcid, byte_buffer_t *pdu) pdu->N_bytes-5, &pdu->msg[1]); nas_log->info("Sending Security Mode Complete nas_count_ul=%d, RB=%s\n", - count_ul, - rb_id_text[lcid]); + count_ul, + rrc->get_rb_name(lcid).c_str()); success = true; } } @@ -572,7 +574,7 @@ void nas::send_attach_request() liblte_mme_pack_attach_request_msg(&attach_req, (LIBLTE_BYTE_MSG_STRUCT*)msg); nas_log->info("Sending attach request\n"); - rrc->write_sdu(RB_ID_SRB1, msg); + rrc->write_sdu(cfg.lcid, msg); } void nas::gen_pdn_connectivity_request(LIBLTE_BYTE_MSG_STRUCT *msg) @@ -614,7 +616,7 @@ void nas::send_service_request() uint8_t mac[4]; integrity_generate(&k_nas_int[16], count_ul, - RB_ID_SRB1-1, + cfg.lcid-1, SECURITY_DIRECTION_UPLINK, &msg->msg[0], 2, @@ -625,7 +627,7 @@ void nas::send_service_request() msg->msg[3] = mac[3]; msg->N_bytes++; nas_log->info("Sending service request\n"); - rrc->write_sdu(RB_ID_SRB1, msg); + rrc->write_sdu(cfg.lcid, msg); } void nas::send_esm_information_response(){} diff --git a/srsue/src/upper/rrc.cc b/srsue/src/upper/rrc.cc index a1805a1e9..291024c05 100644 --- a/srsue/src/upper/rrc.cc +++ b/srsue/src/upper/rrc.cc @@ -27,11 +27,13 @@ #include #include +#include #include "upper/rrc.h" #include "srslte/phy/utils/bit.h" #include "srslte/common/security.h" #include "srslte/common/bcd_helpers.h" +#include "boost/assign.hpp" #define TIMEOUT_RESYNC_REESTABLISH 100 @@ -42,7 +44,9 @@ namespace srsue{ rrc::rrc() :state(RRC_STATE_IDLE) ,drb_up(false) -{} +{ + set_bearers(); +} static void liblte_rrc_handler(void *ctx, char *str) { rrc *r = (rrc*) ctx; @@ -75,7 +79,14 @@ void rrc::init(phy_interface_rrc *phy_, nas = nas_; usim = usim_; rrc_log = rrc_log_; + + // Use MAC timers mac_timers = mac_timers_; + t301 = mac_timers->get_unique_id(); + t310 = mac_timers->get_unique_id(); + t311 = mac_timers->get_unique_id(); + safe_reset_timer = mac_timers->get_unique_id(); + pthread_mutex_init(&mutex, NULL); @@ -116,7 +127,7 @@ void rrc::set_ue_category(int category) void rrc::write_sdu(uint32_t lcid, byte_buffer_t *sdu) { - rrc_log->info_hex(sdu->msg, sdu->N_bytes, "RX %s SDU", rb_id_text[lcid]); + rrc_log->info_hex(sdu->msg, sdu->N_bytes, "RX %s SDU", bearers.at(lcid).c_str()); switch(state) { @@ -227,7 +238,7 @@ bool rrc::have_drb() void rrc::write_pdu(uint32_t lcid, byte_buffer_t *pdu) { - rrc_log->info_hex(pdu->msg, pdu->N_bytes, "TX %s PDU", rb_id_text[lcid]); + rrc_log->info_hex(pdu->msg, pdu->N_bytes, "TX %s PDU", bearers.at(lcid).c_str()); rrc_log->info("TX PDU Stack latency: %ld us\n", pdu->get_latency_us()); switch(lcid) @@ -793,7 +804,7 @@ void rrc::parse_dl_dcch(uint32_t lcid, byte_buffer_t *pdu) liblte_rrc_unpack_dl_dcch_msg((LIBLTE_BIT_MSG_STRUCT*)&bit_buf, &dl_dcch_msg); rrc_log->info("%s - Received %s\n", - rb_id_text[lcid], + bearers.at(lcid).c_str(), liblte_rrc_dl_dcch_msg_type_text[dl_dcch_msg.msg_type]); // Reset and reuse pdu buffer if possible @@ -989,7 +1000,8 @@ void rrc::apply_sib2_configs() mac->get_config(&cfg); cfg.main.time_alignment_timer = sib2.time_alignment_timer; memcpy(&cfg.rach, &sib2.rr_config_common_sib.rach_cnfg, sizeof(LIBLTE_RRC_RACH_CONFIG_COMMON_STRUCT)); - cfg.prach_config_index = sib2.rr_config_common_sib.prach_cnfg.root_sequence_index; + cfg.prach_config_index = sib2.rr_config_common_sib.prach_cnfg.root_sequence_index; + cfg.ul_harq_params.max_harq_msg3_tx = cfg.rach.max_harq_msg3_tx; mac->set_config(&cfg); rrc_log->info("Set RACH ConfigCommon: NofPreambles=%d, ResponseWindow=%d, ContentionResolutionTimer=%d ms\n", @@ -1080,8 +1092,11 @@ void rrc::apply_phy_config_dedicated(LIBLTE_RRC_PHYSICAL_CONFIG_DEDICATED_STRUCT current_cfg->ul_pwr_ctrl_ded.accumulation_en = true; current_cfg->ul_pwr_ctrl_ded.p0_ue_pucch = 0; current_cfg->ul_pwr_ctrl_ded.p_srs_offset = 7; - current_cfg->ul_pwr_ctrl_ded.filter_coeff = LIBLTE_RRC_FILTER_COEFFICIENT_FC4; - current_cfg->ul_pwr_ctrl_ded.filter_coeff_present = true; + } + if (phy_cnfg->ul_pwr_ctrl_ded.filter_coeff_present) { + current_cfg->ul_pwr_ctrl_ded.filter_coeff = phy_cnfg->ul_pwr_ctrl_ded.filter_coeff; + } else { + current_cfg->ul_pwr_ctrl_ded.filter_coeff = LIBLTE_RRC_FILTER_COEFFICIENT_FC4; } if(phy_cnfg->tpc_pdcch_cnfg_pucch_present) { memcpy(¤t_cfg->tpc_pdcch_cnfg_pucch, &phy_cnfg->tpc_pdcch_cnfg_pucch, sizeof(LIBLTE_RRC_TPC_PDCCH_CONFIG_STRUCT)); @@ -1218,7 +1233,13 @@ void rrc::apply_mac_config_dedicated(LIBLTE_RRC_MAC_MAIN_CONFIG_STRUCT *mac_cnfg } // Setup MAC configuration - mac->set_config_main(&default_cfg); + mac->set_config_main(&default_cfg); + + // Update UL HARQ config + mac_interface_rrc::mac_cfg_t cfg; + mac->get_config(&cfg); + cfg.ul_harq_params.max_harq_tx = liblte_rrc_max_harq_tx_num[default_cfg.ulsch_cnfg.max_harq_tx]; + mac->set_config(&cfg); rrc_log->info("Set MAC main config: harq-MaxReTX=%d, bsr-TimerReTX=%d, bsr-TimerPeriodic=%d\n", liblte_rrc_max_harq_tx_num[default_cfg.ulsch_cnfg.max_harq_tx], @@ -1319,9 +1340,10 @@ void rrc::handle_rrc_con_reconfig(uint32_t lcid, LIBLTE_RRC_CONNECTION_RECONFIGU void rrc::add_srb(LIBLTE_RRC_SRB_TO_ADD_MOD_STRUCT *srb_cnfg) { // Setup PDCP - pdcp->add_bearer(srb_cnfg->srb_id); - if(RB_ID_SRB2 == srb_cnfg->srb_id) + pdcp->add_bearer(srb_cnfg->srb_id, srslte_pdcp_config_t(true)); // Set PDCP config control flag + if(RB_ID_SRB2 == srb_cnfg->srb_id) { pdcp->config_security(srb_cnfg->srb_id, k_rrc_enc, k_rrc_int, cipher_algo, integ_algo); + } // Setup RLC if(srb_cnfg->rlc_cnfg_present) @@ -1330,7 +1352,7 @@ void rrc::add_srb(LIBLTE_RRC_SRB_TO_ADD_MOD_STRUCT *srb_cnfg) { rlc->add_bearer(srb_cnfg->srb_id); }else{ - rlc->add_bearer(srb_cnfg->srb_id, &srb_cnfg->rlc_explicit_cnfg); + rlc->add_bearer(srb_cnfg->srb_id, srslte_rlc_config_t(&srb_cnfg->rlc_explicit_cnfg)); } } @@ -1365,7 +1387,7 @@ void rrc::add_srb(LIBLTE_RRC_SRB_TO_ADD_MOD_STRUCT *srb_cnfg) } srbs[srb_cnfg->srb_id] = *srb_cnfg; - rrc_log->info("Added radio bearer %s\n", rb_id_text[srb_cnfg->srb_id]); + rrc_log->info("Added radio bearer %s\n", bearers.at(srb_cnfg->srb_id).c_str()); } void rrc::add_drb(LIBLTE_RRC_DRB_TO_ADD_MOD_STRUCT *drb_cnfg) @@ -1387,11 +1409,18 @@ void rrc::add_drb(LIBLTE_RRC_DRB_TO_ADD_MOD_STRUCT *drb_cnfg) } // Setup PDCP - pdcp->add_bearer(lcid, &drb_cnfg->pdcp_cnfg); + srslte_pdcp_config_t pdcp_cfg; + pdcp_cfg.is_data = true; + if (drb_cnfg->pdcp_cnfg.rlc_um_pdcp_sn_size_present) { + if (LIBLTE_RRC_PDCP_SN_SIZE_7_BITS == drb_cnfg->pdcp_cnfg.rlc_um_pdcp_sn_size) { + pdcp_cfg.sn_len = 7; + } + } + pdcp->add_bearer(lcid, pdcp_cfg); // TODO: setup PDCP security (using k_up_enc) // Setup RLC - rlc->add_bearer(lcid, &drb_cnfg->rlc_cnfg); + rlc->add_bearer(lcid, srslte_rlc_config_t(&drb_cnfg->rlc_cnfg)); // Setup MAC uint8_t log_chan_group = 0; @@ -1419,7 +1448,7 @@ void rrc::add_drb(LIBLTE_RRC_DRB_TO_ADD_MOD_STRUCT *drb_cnfg) drbs[lcid] = *drb_cnfg; drb_up = true; - rrc_log->info("Added radio bearer %s\n", rb_id_text[lcid]); + rrc_log->info("Added radio bearer %s\n", bearers.at(lcid).c_str()); } void rrc::release_drb(uint8_t lcid) @@ -1470,13 +1499,24 @@ void rrc::set_mac_default() void rrc::set_rrc_default() { N310 = 1; N311 = 1; - t301 = mac_timers->get_unique_id(); - t310 = mac_timers->get_unique_id(); - t311 = mac_timers->get_unique_id(); - safe_reset_timer = mac_timers->get_unique_id(); mac_timers->get(t310)->set(this, 1000); mac_timers->get(t311)->set(this, 1000); mac_timers->get(safe_reset_timer)->set(this, 10); } +void rrc::set_bearers() +{ + boost::assign::insert(bearers) (RB_ID_SRB0, "SRB0") + (RB_ID_SRB1, "SRB1") + (RB_ID_SRB2, "SRB2") + (RB_ID_DRB1, "DRB1") + (RB_ID_DRB2, "DRB2") + (RB_ID_DRB3, "DRB3") + (RB_ID_DRB4, "DRB4") + (RB_ID_DRB5, "DRB5") + (RB_ID_DRB6, "DRB6") + (RB_ID_DRB7, "DRB7") + (RB_ID_DRB8, "DRB8"); +} + } // namespace srsue diff --git a/srsue/test/mac/mac_test.cc b/srsue/test/mac/mac_test.cc index cb2ad2945..368a7f35e 100644 --- a/srsue/test/mac/mac_test.cc +++ b/srsue/test/mac/mac_test.cc @@ -458,7 +458,9 @@ int main(int argc, char *argv[]) } // Init Radio and PHY - radio.init(); + if (!radio.init()) { + exit(1); + } phy.init(&radio, &mac, NULL, &phy_log); if (prog_args.rf_rx_gain > 0 && prog_args.rf_tx_gain > 0) { radio.set_rx_gain(prog_args.rf_rx_gain); diff --git a/srsue/test/phy/ue_itf_test_prach.cc b/srsue/test/phy/ue_itf_test_prach.cc index 76adcacdf..30d3e9f3d 100644 --- a/srsue/test/phy/ue_itf_test_prach.cc +++ b/srsue/test/phy/ue_itf_test_prach.cc @@ -199,6 +199,14 @@ srslte_softbuffer_tx_t softbuffer_tx; uint16_t temp_c_rnti; + +class rrc_dummy : public srsue::rrc_interface_phy +{ +public: + void in_sync() {}; + void out_of_sync() {}; +}; + /******** MAC Interface implementation */ class testmac : public srsue::mac_interface_phy { @@ -326,7 +334,8 @@ private: testmac my_mac; -srslte::radio_multi radio; +srslte::radio_multi radio; +rrc_dummy rrc_dummy; int main(int argc, char *argv[]) { @@ -336,7 +345,7 @@ int main(int argc, char *argv[]) // Init Radio and PHY radio.init(); - my_phy.init(&radio, &my_mac, NULL, &log); + my_phy.init(&radio, &my_mac, &rrc_dummy, &log); if (prog_args.rf_rx_gain > 0 && prog_args.rf_tx_gain > 0) { radio.set_rx_gain(prog_args.rf_rx_gain); radio.set_tx_gain(prog_args.rf_tx_gain); diff --git a/srsue/test/phy/ue_itf_test_sib1.cc b/srsue/test/phy/ue_itf_test_sib1.cc index 10e78b23a..803c5ff11 100644 --- a/srsue/test/phy/ue_itf_test_sib1.cc +++ b/srsue/test/phy/ue_itf_test_sib1.cc @@ -90,6 +90,13 @@ uint32_t total_oks=0; uint8_t payload[1024]; srslte_softbuffer_rx_t softbuffer; +class rrc_dummy : public srsue::rrc_interface_phy +{ +public: + void in_sync() {}; + void out_of_sync() {}; +}; + /******** MAC Interface implementation */ class testmac : public srsue::mac_interface_phy { @@ -147,7 +154,7 @@ public: testmac my_mac; srslte::radio_multi radio; - +rrc_dummy rrc_dummy; @@ -159,7 +166,7 @@ int main(int argc, char *argv[]) // Init Radio and PHY radio.init(); - my_phy.init(&radio, &my_mac, NULL, &log); + my_phy.init(&radio, &my_mac, &rrc_dummy, &log); if (prog_args.rf_gain > 0) { radio.set_rx_gain(prog_args.rf_gain); } else { diff --git a/srsue/test/upper/ip_test.cc b/srsue/test/upper/ip_test.cc index 93021cd2b..afed88ebc 100644 --- a/srsue/test/upper/ip_test.cc +++ b/srsue/test/upper/ip_test.cc @@ -269,6 +269,7 @@ public: } void write_pdu_pcch(srslte::byte_buffer_t *sdu) {} void max_retx_attempted(){} + std::string get_rb_name(uint32_t lcid) { return std::string("rb"); } void in_sync() {}; void out_of_sync() {}; @@ -543,7 +544,7 @@ int main(int argc, char *argv[]) my_phy.init(&my_radio, &my_mac, &my_tester, &log_phy, NULL); my_mac.init(&my_phy, &rlc, &my_tester, &log_mac); - rlc.init(&my_tester, &my_tester, &my_tester, &log_rlc, &my_mac); + rlc.init(&my_tester, &my_tester, &my_tester, &log_rlc, &my_mac, 0 /* SRB0 */); my_tester.init(&my_phy, &my_mac, &rlc, &log_tester, prog_args.ip_address); diff --git a/srsue/ue.conf.example b/srsue/ue.conf.example index 90d974859..532bb9849 100644 --- a/srsue/ue.conf.example +++ b/srsue/ue.conf.example @@ -23,10 +23,10 @@ [rf] dl_freq = 2685000000 ul_freq = 2565000000 -tx_gain = 70 -rx_gain = 50 +tx_gain = 80 +rx_gain = 60 -#nof_rx_ant = 1 +nof_rx_ant = 2 #device_name = auto #device_args = auto #time_adv_nsamples = auto