mirror of https://github.com/PentHertz/srsLTE.git
Merge branch 'next' of github.com:softwareradiosystems/srsLTE into next
This commit is contained in:
commit
243a7708d4
|
@ -100,109 +100,204 @@ public:
|
|||
|
||||
private:
|
||||
|
||||
byte_buffer_pool *pool;
|
||||
srslte::log *log;
|
||||
uint32_t lcid;
|
||||
srsue::pdcp_interface_rlc *pdcp;
|
||||
// Transmitter sub-class
|
||||
class rlc_am_tx : public timer_callback
|
||||
{
|
||||
public:
|
||||
rlc_am_tx(rlc_am *parent_, uint32_t queue_len);
|
||||
~rlc_am_tx();
|
||||
|
||||
void init();
|
||||
bool configure(srslte_rlc_am_config_t cfg_);
|
||||
|
||||
void empty_queue();
|
||||
void reestablish();
|
||||
void stop();
|
||||
|
||||
void write_sdu(byte_buffer_t *sdu, bool blocking);
|
||||
int read_pdu(uint8_t *payload, uint32_t nof_bytes);
|
||||
|
||||
uint32_t get_buffer_state();
|
||||
uint32_t get_total_buffer_state();
|
||||
uint32_t get_num_tx_bytes();
|
||||
void reset_metrics();
|
||||
|
||||
// Timeout callback interface
|
||||
void timer_expired(uint32_t timeout_id);
|
||||
|
||||
// Interface for Rx subclass
|
||||
void handle_control_pdu(uint8_t *payload, uint32_t nof_bytes);
|
||||
|
||||
private:
|
||||
|
||||
int build_status_pdu(uint8_t *payload, uint32_t nof_bytes);
|
||||
int build_retx_pdu(uint8_t *payload, uint32_t nof_bytes);
|
||||
int build_segment(uint8_t *payload, uint32_t nof_bytes, rlc_amd_retx_t retx);
|
||||
int build_data_pdu(uint8_t *payload, uint32_t nof_bytes);
|
||||
|
||||
void debug_state();
|
||||
|
||||
bool retx_queue_has_sn(uint32_t sn);
|
||||
int required_buffer_size(rlc_amd_retx_t retx);
|
||||
|
||||
// Timer checks
|
||||
bool status_prohibited;
|
||||
|
||||
// Helpers
|
||||
bool poll_required();
|
||||
bool do_status();
|
||||
|
||||
rlc_am *parent;
|
||||
byte_buffer_pool *pool;
|
||||
srslte::log *log;
|
||||
|
||||
/****************************************************************************
|
||||
* Configurable parameters
|
||||
* Ref: 3GPP TS 36.322 v10.0.0 Section 7
|
||||
***************************************************************************/
|
||||
|
||||
srslte_rlc_am_config_t cfg;
|
||||
|
||||
// TX SDU buffers
|
||||
rlc_tx_queue tx_sdu_queue;
|
||||
byte_buffer_t *tx_sdu;;
|
||||
|
||||
bool tx_enabled;
|
||||
|
||||
/****************************************************************************
|
||||
* State variables and counters
|
||||
* Ref: 3GPP TS 36.322 v10.0.0 Section 7
|
||||
***************************************************************************/
|
||||
|
||||
// Tx state variables
|
||||
uint32_t vt_a; // ACK state. SN of next PDU in sequence to be ACKed. Low edge of tx window.
|
||||
uint32_t vt_ms; // Max send state. High edge of tx window. vt_a + window_size.
|
||||
uint32_t vt_s; // Send state. SN to be assigned for next PDU.
|
||||
uint32_t poll_sn; // Poll send state. SN of most recent PDU txed with poll bit set.
|
||||
|
||||
// Tx counters
|
||||
uint32_t pdu_without_poll;
|
||||
uint32_t byte_without_poll;
|
||||
|
||||
rlc_status_pdu_t tx_status;
|
||||
|
||||
/****************************************************************************
|
||||
* Timers
|
||||
* Ref: 3GPP TS 36.322 v10.0.0 Section 7
|
||||
***************************************************************************/
|
||||
|
||||
srslte::timers::timer *poll_retx_timer;
|
||||
uint32_t poll_retx_timer_id;
|
||||
|
||||
srslte::timers::timer *status_prohibit_timer;
|
||||
uint32_t status_prohibit_timer_id;
|
||||
|
||||
// Tx windows
|
||||
std::map<uint32_t, rlc_amd_tx_pdu_t> tx_window;
|
||||
std::deque<rlc_amd_retx_t> retx_queue;
|
||||
|
||||
// Mutexes
|
||||
pthread_mutex_t mutex;
|
||||
|
||||
// Metrics
|
||||
uint32_t num_tx_bytes;
|
||||
};
|
||||
|
||||
// Receiver sub-class
|
||||
class rlc_am_rx : public timer_callback
|
||||
{
|
||||
public:
|
||||
rlc_am_rx(rlc_am* parent_);
|
||||
~rlc_am_rx();
|
||||
|
||||
void init();
|
||||
bool configure(srslte_rlc_am_config_t cfg_);
|
||||
void reestablish();
|
||||
void stop();
|
||||
|
||||
void write_pdu(uint8_t *payload, uint32_t nof_bytes);
|
||||
|
||||
uint32_t get_num_rx_bytes();
|
||||
void reset_metrics();
|
||||
|
||||
// Timeout callback interface
|
||||
void timer_expired(uint32_t timeout_id);
|
||||
|
||||
// Functions needed by Tx subclass to query rx state
|
||||
int get_status(rlc_status_pdu_t* status);
|
||||
bool get_do_status();
|
||||
void reset_status(); // called when status PDU has been sent
|
||||
|
||||
private:
|
||||
void handle_data_pdu(uint8_t *payload, uint32_t nof_bytes, rlc_amd_pdu_header_t &header);
|
||||
void handle_data_pdu_segment(uint8_t *payload, uint32_t nof_bytes, rlc_amd_pdu_header_t &header);
|
||||
void reassemble_rx_sdus();
|
||||
bool inside_rx_window(uint16_t sn);
|
||||
void debug_state();
|
||||
void print_rx_segments();
|
||||
bool add_segment_and_check(rlc_amd_rx_pdu_segments_t *pdu, rlc_amd_rx_pdu_t *segment);
|
||||
|
||||
rlc_am *parent;
|
||||
byte_buffer_pool *pool;
|
||||
srslte::log *log;
|
||||
|
||||
/****************************************************************************
|
||||
* Configurable parameters
|
||||
* Ref: 3GPP TS 36.322 v10.0.0 Section 7
|
||||
***************************************************************************/
|
||||
srslte_rlc_am_config_t cfg;
|
||||
|
||||
// RX SDU buffers
|
||||
byte_buffer_t *rx_sdu;
|
||||
|
||||
/****************************************************************************
|
||||
* State variables and counters
|
||||
* Ref: 3GPP TS 36.322 v10.0.0 Section 7
|
||||
***************************************************************************/
|
||||
|
||||
// Rx state variables
|
||||
uint32_t vr_r; // Receive state. SN following last in-sequence received PDU. Low edge of rx window
|
||||
uint32_t vr_mr; // Max acceptable receive state. High edge of rx window. vr_r + window size.
|
||||
uint32_t vr_x; // t_reordering state. SN following PDU which triggered t_reordering.
|
||||
uint32_t vr_ms; // Max status tx state. Highest possible value of SN for ACK_SN in status PDU.
|
||||
uint32_t vr_h; // Highest rx state. SN following PDU with highest SN among rxed PDUs.
|
||||
|
||||
// Mutexes
|
||||
pthread_mutex_t mutex;
|
||||
|
||||
// Rx windows
|
||||
std::map<uint32_t, rlc_amd_rx_pdu_t> rx_window;
|
||||
std::map<uint32_t, rlc_amd_rx_pdu_segments_t> rx_segments;
|
||||
|
||||
// Metrics
|
||||
uint32_t num_rx_bytes;
|
||||
|
||||
bool poll_received;
|
||||
bool do_status;
|
||||
|
||||
/****************************************************************************
|
||||
* Timers
|
||||
* Ref: 3GPP TS 36.322 v10.0.0 Section 7
|
||||
***************************************************************************/
|
||||
|
||||
srslte::timers::timer *reordering_timer;
|
||||
uint32_t reordering_timer_id;
|
||||
};
|
||||
|
||||
// Rx and Tx objects
|
||||
rlc_am_tx tx;
|
||||
rlc_am_rx rx;
|
||||
|
||||
// Common variables needed/provided by parent class
|
||||
srsue::rrc_interface_rlc *rrc;
|
||||
|
||||
// TX SDU buffers
|
||||
rlc_tx_queue tx_sdu_queue;
|
||||
byte_buffer_t *tx_sdu;
|
||||
|
||||
// PDU being resegmented
|
||||
rlc_amd_tx_pdu_t tx_pdu_segments;
|
||||
|
||||
// Tx and Rx windows
|
||||
std::map<uint32_t, rlc_amd_tx_pdu_t> tx_window;
|
||||
std::deque<rlc_amd_retx_t> retx_queue;
|
||||
std::map<uint32_t, rlc_amd_rx_pdu_t> rx_window;
|
||||
std::map<uint32_t, rlc_amd_rx_pdu_segments_t> rx_segments;
|
||||
|
||||
// RX SDU buffers
|
||||
byte_buffer_t *rx_sdu;
|
||||
|
||||
// Mutexes
|
||||
pthread_mutex_t mutex;
|
||||
|
||||
bool tx_enabled;
|
||||
bool poll_received;
|
||||
bool do_status;
|
||||
rlc_status_pdu_t status;
|
||||
|
||||
// Metrics
|
||||
uint32_t num_tx_bytes;
|
||||
uint32_t num_rx_bytes;
|
||||
|
||||
/****************************************************************************
|
||||
* Configurable parameters
|
||||
* Ref: 3GPP TS 36.322 v10.0.0 Section 7
|
||||
***************************************************************************/
|
||||
|
||||
srslte_rlc_am_config_t cfg;
|
||||
|
||||
/****************************************************************************
|
||||
* State variables and counters
|
||||
* Ref: 3GPP TS 36.322 v10.0.0 Section 7
|
||||
***************************************************************************/
|
||||
|
||||
// Tx state variables
|
||||
uint32_t vt_a; // ACK state. SN of next PDU in sequence to be ACKed. Low edge of tx window.
|
||||
uint32_t vt_ms; // Max send state. High edge of tx window. vt_a + window_size.
|
||||
uint32_t vt_s; // Send state. SN to be assigned for next PDU.
|
||||
uint32_t poll_sn; // Poll send state. SN of most recent PDU txed with poll bit set.
|
||||
|
||||
// Tx counters
|
||||
uint32_t pdu_without_poll;
|
||||
uint32_t byte_without_poll;
|
||||
|
||||
// Rx state variables
|
||||
uint32_t vr_r; // Receive state. SN following last in-sequence received PDU. Low edge of rx window
|
||||
uint32_t vr_mr; // Max acceptable receive state. High edge of rx window. vr_r + window size.
|
||||
uint32_t vr_x; // t_reordering state. SN following PDU which triggered t_reordering.
|
||||
uint32_t vr_ms; // Max status tx state. Highest possible value of SN for ACK_SN in status PDU.
|
||||
uint32_t vr_h; // Highest rx state. SN following PDU with highest SN among rxed PDUs.
|
||||
|
||||
/****************************************************************************
|
||||
* Timers
|
||||
* Ref: 3GPP TS 36.322 v10.0.0 Section 7
|
||||
***************************************************************************/
|
||||
timeout poll_retx_timeout;
|
||||
timeout reordering_timeout;
|
||||
timeout status_prohibit_timeout;
|
||||
|
||||
static const int reordering_timeout_id = 1;
|
||||
srslte::log *log;
|
||||
srsue::pdcp_interface_rlc *pdcp;
|
||||
mac_interface_timers *mac_timers;
|
||||
uint32_t lcid;
|
||||
srslte_rlc_am_config_t cfg;
|
||||
std::string rb_name;
|
||||
|
||||
static const int poll_periodicity = 8; // After how many data PDUs a status PDU shall be requested
|
||||
|
||||
// Timer checks
|
||||
bool status_prohibited();
|
||||
bool poll_retx();
|
||||
void check_reordering_timeout();
|
||||
|
||||
// Helpers
|
||||
bool poll_required();
|
||||
|
||||
int prepare_status();
|
||||
int build_status_pdu(uint8_t *payload, uint32_t nof_bytes);
|
||||
int build_retx_pdu(uint8_t *payload, uint32_t nof_bytes);
|
||||
int build_segment(uint8_t *payload, uint32_t nof_bytes, rlc_amd_retx_t retx);
|
||||
int build_data_pdu(uint8_t *payload, uint32_t nof_bytes);
|
||||
|
||||
void handle_data_pdu(uint8_t *payload, uint32_t nof_bytes, rlc_amd_pdu_header_t &header);
|
||||
void handle_data_pdu_segment(uint8_t *payload, uint32_t nof_bytes, rlc_amd_pdu_header_t &header);
|
||||
void handle_control_pdu(uint8_t *payload, uint32_t nof_bytes);
|
||||
|
||||
void reassemble_rx_sdus();
|
||||
|
||||
bool inside_tx_window(uint16_t sn);
|
||||
bool inside_rx_window(uint16_t sn);
|
||||
void debug_state();
|
||||
void print_rx_segments();
|
||||
|
||||
bool add_segment_and_check(rlc_amd_rx_pdu_segments_t *pdu, rlc_amd_rx_pdu_t *segment);
|
||||
int required_buffer_size(rlc_amd_retx_t retx);
|
||||
bool retx_queue_has_sn(uint32_t sn);
|
||||
};
|
||||
|
||||
/****************************************************************************
|
||||
|
|
|
@ -417,7 +417,8 @@ int srslte_enb_dl_put_pdcch_dl(srslte_enb_dl_t *q, srslte_ra_dl_dci_t *grant,
|
|||
srslte_dci_format_t format, srslte_dci_location_t location,
|
||||
uint16_t rnti, uint32_t sf_idx)
|
||||
{
|
||||
srslte_dci_msg_t dci_msg = {};
|
||||
srslte_dci_msg_t dci_msg;
|
||||
bzero(&dci_msg, sizeof(dci_msg));
|
||||
|
||||
bool rnti_is_user = true;
|
||||
if (rnti == SRSLTE_SIRNTI || rnti == SRSLTE_PRNTI || (rnti >= SRSLTE_RARNTI_START && rnti <= SRSLTE_RARNTI_END)) {
|
||||
|
@ -439,7 +440,8 @@ int srslte_enb_dl_put_pdcch_ul(srslte_enb_dl_t *q, srslte_ra_ul_dci_t *grant,
|
|||
srslte_dci_location_t location,
|
||||
uint16_t rnti, uint32_t sf_idx)
|
||||
{
|
||||
srslte_dci_msg_t dci_msg = {};
|
||||
srslte_dci_msg_t dci_msg;
|
||||
bzero(&dci_msg, sizeof(dci_msg));
|
||||
|
||||
srslte_dci_msg_pack_pusch(grant, &dci_msg, q->cell.nof_prb);
|
||||
if (srslte_pdcch_encode(&q->pdcch, &dci_msg, location, rnti, q->sf_symbols, sf_idx, q->cfi)) {
|
||||
|
|
|
@ -97,7 +97,8 @@ int main(int argc, char **argv) {
|
|||
}
|
||||
|
||||
/* Create CRC for Transport Block, it is not currently used but it is required */
|
||||
srslte_crc_t crc_tb = {};
|
||||
srslte_crc_t crc_tb;
|
||||
bzero(&crc_tb, sizeof(crc_tb));
|
||||
if (srslte_crc_init(&crc_tb, SRSLTE_LTE_CRC24A, 24)) {
|
||||
printf("error initialising CRC\n");
|
||||
exit(-1);
|
||||
|
|
|
@ -60,6 +60,8 @@ bool verbose = false;
|
|||
|
||||
#define TEST(X, CODE) static bool test_##X (char *func_name, double *timing, uint32_t block_size) {\
|
||||
struct timeval start, end;\
|
||||
bzero(&start, sizeof(start));\
|
||||
bzero(&end, sizeof(end));\
|
||||
float mse = 0.0f;\
|
||||
bool passed;\
|
||||
strncpy(func_name, #X, 32);\
|
||||
|
@ -781,7 +783,8 @@ TEST(srslte_vec_apply_cfo,
|
|||
)
|
||||
|
||||
TEST(srslte_cfo_correct,
|
||||
srslte_cfo_t srslte_cfo = {0};
|
||||
srslte_cfo_t srslte_cfo;
|
||||
bzero(&srslte_cfo, sizeof(srslte_cfo));
|
||||
MALLOC(cf_t, x);
|
||||
MALLOC(cf_t, z);
|
||||
|
||||
|
@ -807,7 +810,8 @@ TEST(srslte_cfo_correct,
|
|||
)
|
||||
|
||||
TEST(srslte_cfo_correct_change,
|
||||
srslte_cfo_t srslte_cfo = {0};
|
||||
srslte_cfo_t srslte_cfo;
|
||||
bzero(&srslte_cfo, sizeof(srslte_cfo));
|
||||
MALLOC(cf_t, x);
|
||||
MALLOC(cf_t, z);
|
||||
|
||||
|
|
|
@ -129,7 +129,9 @@ int main(int argc, char **argv)
|
|||
{
|
||||
int ret = SRSLTE_ERROR;
|
||||
srslte::radio_multi *radio_h = NULL;
|
||||
srslte_timestamp_t ts_rx = {}, ts_tx = {};
|
||||
srslte_timestamp_t ts_rx, ts_tx;
|
||||
bzero(&ts_rx, sizeof(ts_rx));
|
||||
bzero(&ts_tx, sizeof(ts_tx));
|
||||
|
||||
signal(SIGINT, sig_int_handler);
|
||||
|
||||
|
|
|
@ -440,7 +440,7 @@ void rlc::add_bearer(uint32_t lcid, srslte_rlc_config_t cnfg)
|
|||
rlc_log->error("Error instantiating RLC\n");
|
||||
goto delete_and_exit;
|
||||
}
|
||||
rlc_log->warning("Added radio bearer %s with mode %s\n", rrc->get_rb_name(lcid).c_str(), liblte_rrc_rlc_mode_text[cnfg.rlc_mode]);
|
||||
rlc_log->warning("Added radio bearer %s in %s\n", rrc->get_rb_name(lcid).c_str(), rlc_mode_text[cnfg.rlc_mode]);
|
||||
goto unlock_and_exit;
|
||||
} else {
|
||||
rlc_log->warning("Bearer %s already created.\n", rrc->get_rb_name(lcid).c_str());
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -75,13 +75,13 @@ bool rlc_um::configure(srslte_rlc_config_t cnfg_)
|
|||
return false;
|
||||
}
|
||||
|
||||
log->warning("%s configured in %s mode: t_reordering=%d ms, rx_sn_field_length=%u bits, tx_sn_field_length=%u bits\n",
|
||||
rb_name.c_str(), 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]);
|
||||
|
||||
// store config
|
||||
cfg = cnfg_.um;
|
||||
|
||||
log->warning("%s configured in %s mode: ft_reordering=%d ms, rx_sn_field_length=%u bits, tx_sn_field_length=%u bits\n",
|
||||
rb_name.c_str(), 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]);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -149,7 +149,6 @@ void rlc_um::write_sdu(byte_buffer_t *sdu, bool blocking)
|
|||
} else {
|
||||
tx.try_write_sdu(sdu);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
|
@ -199,7 +198,7 @@ void rlc_um::reset_metrics()
|
|||
|
||||
std::string rlc_um::get_rb_name(srsue::rrc_interface_rlc *rrc, uint32_t lcid, bool is_mrb)
|
||||
{
|
||||
if(is_mrb) {
|
||||
if (is_mrb) {
|
||||
std::stringstream ss;
|
||||
ss << "MRB" << lcid;
|
||||
return ss.str();
|
||||
|
|
|
@ -190,8 +190,8 @@ uint32_t prbset_to_bitmask() {
|
|||
int main(int argc, char **argv) {
|
||||
struct timeval t[3] = {};
|
||||
size_t tx_nof_bits = 0, rx_nof_bits = 0;
|
||||
srslte_enb_dl_t enb_dl = {};
|
||||
srslte_ue_dl_t ue_dl = {};
|
||||
srslte_enb_dl_t enb_dl;
|
||||
srslte_ue_dl_t ue_dl;
|
||||
srslte_softbuffer_tx_t *softbuffer_tx[SRSLTE_MAX_TB] = {};
|
||||
srslte_softbuffer_rx_t *softbuffer_rx[SRSLTE_MAX_TB] = {};
|
||||
uint8_t *data_tx[SRSLTE_MAX_TB] = {};
|
||||
|
@ -206,6 +206,9 @@ int main(int argc, char **argv) {
|
|||
|
||||
cf_t *signal_buffer[SRSLTE_MAX_PORTS] = {NULL};
|
||||
|
||||
bzero(&enb_dl, sizeof(enb_dl));
|
||||
bzero(&ue_dl, sizeof(ue_dl));
|
||||
|
||||
/*
|
||||
* Allocate Memory
|
||||
*/
|
||||
|
@ -304,9 +307,12 @@ int main(int argc, char **argv) {
|
|||
/*
|
||||
* Run eNodeB
|
||||
*/
|
||||
srslte_ra_dl_dci_t dci = {};
|
||||
srslte_ra_dl_dci_t dci;
|
||||
srslte_dci_format_t dci_format = SRSLTE_DCI_FORMAT1A;
|
||||
srslte_ra_dl_grant_t grant = {};
|
||||
srslte_ra_dl_grant_t grant;
|
||||
|
||||
bzero(&dci, sizeof(dci));
|
||||
bzero(&grant, sizeof(grant));
|
||||
|
||||
prbset_num = (int) ceilf((float) cell.nof_prb / srslte_ra_type0_P(cell.nof_prb));
|
||||
last_prbset_num = prbset_num;
|
||||
|
|
|
@ -42,15 +42,21 @@ class mac_dummy_timers
|
|||
:public srslte::mac_interface_timers
|
||||
{
|
||||
public:
|
||||
srslte::timers::timer* timer_get(uint32_t timer_id)
|
||||
{
|
||||
return &t;
|
||||
mac_dummy_timers() : timers(8) {}
|
||||
srslte::timers::timer* timer_get(uint32_t timer_id) {
|
||||
return timers.get(timer_id);
|
||||
}
|
||||
void timer_release_id(uint32_t timer_id) {
|
||||
timers.release_id(timer_id);
|
||||
}
|
||||
uint32_t timer_get_unique_id() {
|
||||
return timers.get_unique_id();
|
||||
}
|
||||
void step_all() {
|
||||
timers.step_all();
|
||||
}
|
||||
uint32_t timer_get_unique_id(){return 0;}
|
||||
void timer_release_id(uint32_t id){}
|
||||
|
||||
private:
|
||||
srslte::timers::timer t;
|
||||
srslte::timers timers;
|
||||
};
|
||||
|
||||
class rlc_am_tester
|
||||
|
@ -135,7 +141,7 @@ private:
|
|||
bool running;
|
||||
};
|
||||
|
||||
void basic_test()
|
||||
bool basic_test()
|
||||
{
|
||||
srslte::log_filter log1("RLC_AM_1");
|
||||
srslte::log_filter log2("RLC_AM_2");
|
||||
|
@ -166,8 +172,13 @@ void basic_test()
|
|||
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);
|
||||
if (not rlc1.configure(&cnfg)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (not rlc2.configure(&cnfg)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Push 5 SDUs into RLC1
|
||||
byte_buffer_t sdu_bufs[NBUFS];
|
||||
|
@ -215,11 +226,17 @@ void basic_test()
|
|||
}
|
||||
|
||||
// Check statistics
|
||||
assert(rlc1.get_num_tx_bytes() == rlc2.get_num_rx_bytes());
|
||||
assert(rlc2.get_num_tx_bytes() == rlc1.get_num_rx_bytes());
|
||||
if (rlc1.get_num_tx_bytes() != rlc2.get_num_rx_bytes()) {
|
||||
return -1;
|
||||
}
|
||||
if (rlc2.get_num_tx_bytes() != rlc1.get_num_rx_bytes()) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void concat_test()
|
||||
bool concat_test()
|
||||
{
|
||||
srslte::log_filter log1("RLC_AM_1");
|
||||
srslte::log_filter log2("RLC_AM_2");
|
||||
|
@ -250,8 +267,13 @@ void concat_test()
|
|||
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);
|
||||
if (not rlc1.configure(&cnfg)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (not rlc2.configure(&cnfg)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Push 5 SDUs into RLC1
|
||||
byte_buffer_t sdu_bufs[NBUFS];
|
||||
|
@ -284,11 +306,17 @@ void concat_test()
|
|||
}
|
||||
|
||||
// check statistics
|
||||
assert(rlc1.get_num_tx_bytes() == rlc2.get_num_rx_bytes());
|
||||
assert(rlc2.get_num_tx_bytes() == rlc1.get_num_rx_bytes());
|
||||
if (rlc1.get_num_tx_bytes() != rlc2.get_num_rx_bytes()) {
|
||||
return -1;
|
||||
}
|
||||
if (rlc2.get_num_tx_bytes() != rlc1.get_num_rx_bytes()) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void segment_test()
|
||||
bool segment_test()
|
||||
{
|
||||
srslte::log_filter log1("RLC_AM_1");
|
||||
srslte::log_filter log2("RLC_AM_2");
|
||||
|
@ -319,8 +347,13 @@ void segment_test()
|
|||
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);
|
||||
if (not rlc1.configure(&cnfg)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (not rlc2.configure(&cnfg)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Push 5 SDUs into RLC1
|
||||
byte_buffer_t sdu_bufs[NBUFS];
|
||||
|
@ -370,11 +403,17 @@ void segment_test()
|
|||
assert(tester.sdus[i]->msg[j] == j);
|
||||
}
|
||||
|
||||
assert(rlc1.get_num_tx_bytes() == rlc2.get_num_rx_bytes());
|
||||
assert(rlc2.get_num_tx_bytes() == rlc1.get_num_rx_bytes());
|
||||
if (rlc1.get_num_tx_bytes() != rlc2.get_num_rx_bytes()) {
|
||||
return -1;
|
||||
}
|
||||
if (rlc2.get_num_tx_bytes() != rlc1.get_num_rx_bytes()) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void retx_test()
|
||||
bool retx_test()
|
||||
{
|
||||
srslte::log_filter log1("RLC_AM_1");
|
||||
srslte::log_filter log2("RLC_AM_2");
|
||||
|
@ -405,8 +444,13 @@ void retx_test()
|
|||
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);
|
||||
if (not rlc1.configure(&cnfg)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (not rlc2.configure(&cnfg)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Push 5 SDUs into RLC1
|
||||
byte_buffer_t sdu_bufs[NBUFS];
|
||||
|
@ -436,8 +480,11 @@ void retx_test()
|
|||
rlc2.write_pdu(pdu_bufs[i].msg, pdu_bufs[i].N_bytes);
|
||||
}
|
||||
|
||||
// Sleep to let reordering timeout expire
|
||||
usleep(10000);
|
||||
// Step timers until reordering timeout expires
|
||||
int cnt = 5;
|
||||
while (cnt--) {
|
||||
timers.step_all();
|
||||
}
|
||||
|
||||
assert(4 == rlc2.get_buffer_state());
|
||||
|
||||
|
@ -462,12 +509,14 @@ void retx_test()
|
|||
assert(tester.n_sdus == 5);
|
||||
for(int i=0; i<tester.n_sdus; i++)
|
||||
{
|
||||
assert(tester.sdus[i]->N_bytes == 1);
|
||||
assert(*(tester.sdus[i]->msg) == i);
|
||||
if (tester.sdus[i]->N_bytes != 1) return -1;
|
||||
if (*(tester.sdus[i]->msg) != i) return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void resegment_test_1()
|
||||
bool resegment_test_1()
|
||||
{
|
||||
// SDUs: | 10 | 10 | 10 | 10 | 10 |
|
||||
// PDUs: | 10 | 10 | 10 | 10 | 10 |
|
||||
|
@ -502,8 +551,13 @@ void resegment_test_1()
|
|||
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);
|
||||
if (not rlc1.configure(&cnfg)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (not rlc2.configure(&cnfg)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Push 5 SDUs into RLC1
|
||||
byte_buffer_t sdu_bufs[NBUFS];
|
||||
|
@ -534,8 +588,11 @@ void resegment_test_1()
|
|||
rlc2.write_pdu(pdu_bufs[i].msg, pdu_bufs[i].N_bytes);
|
||||
}
|
||||
|
||||
// Sleep to let reordering timeout expire
|
||||
usleep(10000);
|
||||
// Step timers until reordering timeout expires
|
||||
int cnt = 5;
|
||||
while (cnt--) {
|
||||
timers.step_all();
|
||||
}
|
||||
|
||||
assert(4 == rlc2.get_buffer_state());
|
||||
|
||||
|
@ -570,13 +627,15 @@ void resegment_test_1()
|
|||
assert(tester.n_sdus == 5);
|
||||
for(int i=0; i<tester.n_sdus; i++)
|
||||
{
|
||||
assert(tester.sdus[i]->N_bytes == 10);
|
||||
if (tester.sdus[i]->N_bytes != 10) return -1;
|
||||
for(int j=0;j<10;j++)
|
||||
assert(tester.sdus[i]->msg[j] == j);
|
||||
if (tester.sdus[i]->msg[j] != j) return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void resegment_test_2()
|
||||
bool resegment_test_2()
|
||||
{
|
||||
|
||||
// SDUs: | 10 | 10 | 10 | 10 | 10 |
|
||||
|
@ -612,8 +671,13 @@ void resegment_test_2()
|
|||
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);
|
||||
if (not rlc1.configure(&cnfg)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (not rlc2.configure(&cnfg)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Push 5 SDUs into RLC1
|
||||
byte_buffer_t sdu_bufs[NBUFS];
|
||||
|
@ -644,8 +708,11 @@ void resegment_test_2()
|
|||
rlc2.write_pdu(pdu_bufs[i].msg, pdu_bufs[i].N_bytes);
|
||||
}
|
||||
|
||||
// Sleep to let reordering timeout expire
|
||||
usleep(10000);
|
||||
// Step timers until reordering timeout expires
|
||||
int cnt = 5;
|
||||
while (cnt--) {
|
||||
timers.step_all();
|
||||
}
|
||||
|
||||
assert(4 == rlc2.get_buffer_state());
|
||||
|
||||
|
@ -677,13 +744,15 @@ void resegment_test_2()
|
|||
assert(tester.n_sdus == 5);
|
||||
for(int i=0; i<tester.n_sdus; i++)
|
||||
{
|
||||
assert(tester.sdus[i]->N_bytes == 10);
|
||||
if (tester.sdus[i]->N_bytes != 10) return -1;
|
||||
for(int j=0;j<10;j++)
|
||||
assert(tester.sdus[i]->msg[j] == j);
|
||||
if (tester.sdus[i]->msg[j] != j) return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void resegment_test_3()
|
||||
bool resegment_test_3()
|
||||
{
|
||||
|
||||
// SDUs: | 10 | 10 | 10 | 10 | 10 |
|
||||
|
@ -719,8 +788,13 @@ void resegment_test_3()
|
|||
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);
|
||||
if (not rlc1.configure(&cnfg)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (not rlc2.configure(&cnfg)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Push 5 SDUs into RLC1
|
||||
byte_buffer_t sdu_bufs[NBUFS];
|
||||
|
@ -751,8 +825,11 @@ void resegment_test_3()
|
|||
rlc2.write_pdu(pdu_bufs[i].msg, pdu_bufs[i].N_bytes);
|
||||
}
|
||||
|
||||
// Sleep to let reordering timeout expire
|
||||
usleep(10000);
|
||||
// Step timers until reordering timeout expires
|
||||
int cnt = 5;
|
||||
while (cnt--) {
|
||||
timers.step_all();
|
||||
}
|
||||
|
||||
assert(4 == rlc2.get_buffer_state());
|
||||
|
||||
|
@ -780,13 +857,15 @@ void resegment_test_3()
|
|||
assert(tester.n_sdus == 5);
|
||||
for(int i=0; i<tester.n_sdus; i++)
|
||||
{
|
||||
assert(tester.sdus[i]->N_bytes == 10);
|
||||
if (tester.sdus[i]->N_bytes != 10) return -1;
|
||||
for(int j=0;j<10;j++)
|
||||
assert(tester.sdus[i]->msg[j] == j);
|
||||
if (tester.sdus[i]->msg[j] != j) return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void resegment_test_4()
|
||||
bool resegment_test_4()
|
||||
{
|
||||
|
||||
// SDUs: | 10 | 10 | 10 | 10 | 10 |
|
||||
|
@ -822,8 +901,13 @@ void resegment_test_4()
|
|||
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);
|
||||
if (not rlc1.configure(&cnfg)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (not rlc2.configure(&cnfg)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Push 5 SDUs into RLC1
|
||||
byte_buffer_t sdu_bufs[NBUFS];
|
||||
|
@ -854,8 +938,11 @@ void resegment_test_4()
|
|||
rlc2.write_pdu(pdu_bufs[i].msg, pdu_bufs[i].N_bytes);
|
||||
}
|
||||
|
||||
// Sleep to let reordering timeout expire
|
||||
usleep(10000);
|
||||
// Step timers until reordering timeout expires
|
||||
int cnt = 5;
|
||||
while (cnt--) {
|
||||
timers.step_all();
|
||||
}
|
||||
|
||||
assert(4 == rlc2.get_buffer_state());
|
||||
|
||||
|
@ -883,13 +970,15 @@ void resegment_test_4()
|
|||
assert(tester.n_sdus == 5);
|
||||
for(int i=0; i<tester.n_sdus; i++)
|
||||
{
|
||||
assert(tester.sdus[i]->N_bytes == 10);
|
||||
if (tester.sdus[i]->N_bytes != 10) return -1;
|
||||
for(int j=0;j<10;j++)
|
||||
assert(tester.sdus[i]->msg[j] == j);
|
||||
if (tester.sdus[i]->msg[j] != j) return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void resegment_test_5()
|
||||
bool resegment_test_5()
|
||||
{
|
||||
|
||||
// SDUs: | 10 | 10 | 10 | 10 | 10 |
|
||||
|
@ -908,8 +997,6 @@ void resegment_test_5()
|
|||
rlc_am rlc1;
|
||||
rlc_am rlc2;
|
||||
|
||||
int len;
|
||||
|
||||
log1.set_level(srslte::LOG_LEVEL_DEBUG);
|
||||
log2.set_level(srslte::LOG_LEVEL_DEBUG);
|
||||
|
||||
|
@ -925,8 +1012,13 @@ void resegment_test_5()
|
|||
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);
|
||||
if (not rlc1.configure(&cnfg)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (not rlc2.configure(&cnfg)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Push 5 SDUs into RLC1
|
||||
byte_buffer_t sdu_bufs[NBUFS];
|
||||
|
@ -957,8 +1049,11 @@ void resegment_test_5()
|
|||
rlc2.write_pdu(pdu_bufs[i].msg, pdu_bufs[i].N_bytes);
|
||||
}
|
||||
|
||||
// Sleep to let reordering timeout expire
|
||||
usleep(10000);
|
||||
// Step timers until reordering timeout expires
|
||||
int cnt = 5;
|
||||
while (cnt--) {
|
||||
timers.step_all();
|
||||
}
|
||||
|
||||
assert(4 == rlc2.get_buffer_state());
|
||||
|
||||
|
@ -986,13 +1081,15 @@ void resegment_test_5()
|
|||
assert(tester.n_sdus == 5);
|
||||
for(int i=0; i<tester.n_sdus; i++)
|
||||
{
|
||||
assert(tester.sdus[i]->N_bytes == 10);
|
||||
if (tester.sdus[i]->N_bytes != 10) return -1;
|
||||
for(int j=0;j<10;j++)
|
||||
assert(tester.sdus[i]->msg[j] == j);
|
||||
if (tester.sdus[i]->msg[j] != j) return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void resegment_test_6()
|
||||
bool resegment_test_6()
|
||||
{
|
||||
// SDUs: |10|10|10| 54 | 54 | 54 | 54 | 54 | 54 |
|
||||
// PDUs: |10|10|10| 270 | 54 |
|
||||
|
@ -1027,8 +1124,13 @@ void resegment_test_6()
|
|||
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);
|
||||
if (not rlc1.configure(&cnfg)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (not rlc2.configure(&cnfg)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Push SDUs into RLC1
|
||||
byte_buffer_t sdu_bufs[9];
|
||||
|
@ -1069,8 +1171,11 @@ void resegment_test_6()
|
|||
rlc2.write_pdu(pdu_bufs[i].msg, pdu_bufs[i].N_bytes);
|
||||
}
|
||||
|
||||
// Sleep to let reordering timeout expire
|
||||
usleep(10000);
|
||||
// Step timers until reordering timeout expires
|
||||
int cnt = 5;
|
||||
while (cnt--) {
|
||||
timers.step_all();
|
||||
}
|
||||
|
||||
assert(4 == rlc2.get_buffer_state());
|
||||
|
||||
|
@ -1111,14 +1216,17 @@ void resegment_test_6()
|
|||
}
|
||||
for(int i=3;i<9;i++)
|
||||
{
|
||||
assert(tester.sdus[i]->N_bytes == 54);
|
||||
for(int j=0;j<54;j++)
|
||||
assert(tester.sdus[i]->msg[j] == j);
|
||||
if(tester.sdus[i]->N_bytes != 54) return -1;
|
||||
for(int j=0;j<54;j++) {
|
||||
if (tester.sdus[i]->msg[j] != j) return -1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Retransmission of PDU segments of the same size
|
||||
void resegment_test_7()
|
||||
bool resegment_test_7()
|
||||
{
|
||||
// SDUs: | 30 | 30 |
|
||||
// PDUs: | 13 | 13 | 11 | 13 | 10 |
|
||||
|
@ -1165,8 +1273,13 @@ void resegment_test_7()
|
|||
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);
|
||||
if (not rlc1.configure(&cnfg)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (not rlc2.configure(&cnfg)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Push 2 SDUs into RLC1
|
||||
byte_buffer_t sdu_bufs[N_SDU_BUFS];
|
||||
|
@ -1201,8 +1314,11 @@ void resegment_test_7()
|
|||
}
|
||||
}
|
||||
|
||||
// Sleep to let reordering timeout expire
|
||||
usleep(10000);
|
||||
// Step timers until reordering timeout expires
|
||||
int cnt = 5;
|
||||
while (cnt--) {
|
||||
timers.step_all();
|
||||
}
|
||||
|
||||
assert(12 == rlc1.get_buffer_state());
|
||||
|
||||
|
@ -1222,8 +1338,6 @@ void resegment_test_7()
|
|||
}
|
||||
}
|
||||
|
||||
usleep(10000);
|
||||
|
||||
// Read status PDU from RLC2
|
||||
assert(rlc2.get_buffer_state());
|
||||
byte_buffer_t status_buf;
|
||||
|
@ -1237,7 +1351,6 @@ void resegment_test_7()
|
|||
|
||||
assert(15 == rlc1.get_buffer_state());
|
||||
|
||||
|
||||
// second round of retx, forcing resegmentation
|
||||
byte_buffer_t retx2[4];
|
||||
for (uint32_t i = 0; i < 4; i++) {
|
||||
|
@ -1253,26 +1366,35 @@ void resegment_test_7()
|
|||
|
||||
// check buffer states
|
||||
assert(0 == rlc1.get_buffer_state());
|
||||
|
||||
// Step timers until poll_retx timeout expires
|
||||
cnt = 5;
|
||||
while (cnt--) {
|
||||
timers.step_all();
|
||||
}
|
||||
|
||||
assert(0 == rlc2.get_buffer_state());
|
||||
|
||||
// Check number of SDUs and their content
|
||||
assert(tester.n_sdus == N_SDU_BUFS);
|
||||
for(int i=0; i<tester.n_sdus; i++)
|
||||
{
|
||||
assert(tester.sdus[i]->N_bytes == sdu_size);
|
||||
if (tester.sdus[i]->N_bytes != sdu_size) return -1;
|
||||
for(uint32_t j=0;j<N_SDU_BUFS;j++) {
|
||||
assert(tester.sdus[i]->msg[j] == i);
|
||||
if (tester.sdus[i]->msg[j] != i) return -1;
|
||||
}
|
||||
}
|
||||
|
||||
#if HAVE_PCAP
|
||||
pcap.close();
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
// Retransmission of PDU segments with different size
|
||||
void resegment_test_8()
|
||||
bool resegment_test_8()
|
||||
{
|
||||
// SDUs: | 30 | 30 |
|
||||
// PDUs: | 15 | 15 | 15 | 15 | 15 |
|
||||
|
@ -1318,8 +1440,13 @@ void resegment_test_8()
|
|||
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);
|
||||
if (not rlc1.configure(&cnfg)) {
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
if (not rlc2.configure(&cnfg)) {
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
// Push 2 SDUs into RLC1
|
||||
byte_buffer_t sdu_bufs[N_SDU_BUFS];
|
||||
|
@ -1354,8 +1481,11 @@ void resegment_test_8()
|
|||
}
|
||||
}
|
||||
|
||||
// Sleep to let reordering timeout expire
|
||||
usleep(10000);
|
||||
// Step timers until reordering timeout expires
|
||||
int cnt = 5;
|
||||
while (cnt--) {
|
||||
timers.step_all();
|
||||
}
|
||||
|
||||
assert(12 == rlc1.get_buffer_state());
|
||||
|
||||
|
@ -1375,7 +1505,11 @@ void resegment_test_8()
|
|||
}
|
||||
}
|
||||
|
||||
usleep(20000);
|
||||
// Step timers until reordering timeout expires
|
||||
cnt = 7;
|
||||
while (cnt--) {
|
||||
timers.step_all();
|
||||
}
|
||||
|
||||
// Read status PDU from RLC2
|
||||
assert(rlc2.get_buffer_state());
|
||||
|
@ -1402,27 +1536,41 @@ void resegment_test_8()
|
|||
#endif
|
||||
}
|
||||
|
||||
// get BSR from RLC2
|
||||
status_buf.N_bytes = rlc2.read_pdu(status_buf.msg, 10); // 10 bytes is enough to hold the status
|
||||
|
||||
// Write status PDU to RLC1
|
||||
rlc1.write_pdu(status_buf.msg, status_buf.N_bytes);
|
||||
#if HAVE_PCAP
|
||||
pcap.write_ul_am_ccch(status_buf.msg, status_buf.N_bytes);
|
||||
#endif
|
||||
|
||||
// check buffer states
|
||||
assert(0 == rlc1.get_buffer_state());
|
||||
assert(0 == rlc2.get_buffer_state());
|
||||
if (rlc1.get_buffer_state() != 0) {
|
||||
return -1;
|
||||
};
|
||||
if (rlc2.get_buffer_state() != 0) {
|
||||
return -1;
|
||||
};
|
||||
|
||||
// Check number of SDUs and their content
|
||||
assert(tester.n_sdus == N_SDU_BUFS);
|
||||
for(int i=0; i<tester.n_sdus; i++)
|
||||
{
|
||||
assert(tester.sdus[i]->N_bytes == sdu_size);
|
||||
for(int i=0; i<tester.n_sdus; i++) {
|
||||
if (tester.sdus[i]->N_bytes != sdu_size) return -1;
|
||||
for(uint32_t j=0;j<N_SDU_BUFS;j++) {
|
||||
assert(tester.sdus[i]->msg[j] == i);
|
||||
if (tester.sdus[i]->msg[j] != i) return -1;
|
||||
}
|
||||
}
|
||||
|
||||
#if HAVE_PCAP
|
||||
pcap.close();
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void reset_test()
|
||||
bool reset_test()
|
||||
{
|
||||
srslte::log_filter log1("RLC_AM_1");
|
||||
srslte::log_filter log2("RLC_AM_2");
|
||||
|
@ -1449,7 +1597,9 @@ void reset_test()
|
|||
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);
|
||||
if (not rlc1.configure(&cnfg)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Push 1 SDU of size 10 into RLC1
|
||||
byte_buffer_t sdu_buf;
|
||||
|
@ -1473,10 +1623,14 @@ void reset_test()
|
|||
len = rlc1.read_pdu(pdu_bufs.msg, 100);
|
||||
pdu_bufs.N_bytes = len;
|
||||
|
||||
assert(0 == rlc1.get_buffer_state());
|
||||
if (0 != rlc1.get_buffer_state()) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void stop_test()
|
||||
bool stop_test()
|
||||
{
|
||||
srslte::log_filter log1("RLC_AM_1");
|
||||
log1.set_level(srslte::LOG_LEVEL_DEBUG);
|
||||
|
@ -1499,7 +1653,9 @@ void stop_test()
|
|||
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);
|
||||
if (not rlc1.configure(&cnfg)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
// start thread reading
|
||||
ul_writer writer(&rlc1);
|
||||
|
@ -1510,48 +1666,93 @@ void stop_test()
|
|||
|
||||
// stop RLC1
|
||||
rlc1.stop();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
basic_test();
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
if (basic_test()) {
|
||||
printf("basic_test failed\n");
|
||||
exit(-1);
|
||||
};
|
||||
byte_buffer_pool::get_instance()->cleanup();
|
||||
|
||||
concat_test();
|
||||
if (concat_test()) {
|
||||
printf("concat_test failed\n");
|
||||
exit(-1);
|
||||
};
|
||||
byte_buffer_pool::get_instance()->cleanup();
|
||||
|
||||
segment_test();
|
||||
if (segment_test()) {
|
||||
printf("segment_test failed\n");
|
||||
exit(-1);
|
||||
};
|
||||
byte_buffer_pool::get_instance()->cleanup();
|
||||
|
||||
retx_test();
|
||||
if (retx_test()) {
|
||||
printf("retx_test failed\n");
|
||||
exit(-1);
|
||||
};
|
||||
byte_buffer_pool::get_instance()->cleanup();
|
||||
|
||||
resegment_test_1();
|
||||
if (resegment_test_1()) {
|
||||
printf("resegment_test_1 failed\n");
|
||||
exit(-1);
|
||||
};
|
||||
byte_buffer_pool::get_instance()->cleanup();
|
||||
|
||||
resegment_test_2();
|
||||
if (resegment_test_2()) {
|
||||
printf("resegment_test_2 failed\n");
|
||||
exit(-1);
|
||||
};
|
||||
byte_buffer_pool::get_instance()->cleanup();
|
||||
|
||||
resegment_test_3();
|
||||
if (resegment_test_3()) {
|
||||
printf("resegment_test_3 failed\n");
|
||||
exit(-1);
|
||||
};
|
||||
byte_buffer_pool::get_instance()->cleanup();
|
||||
|
||||
resegment_test_4();
|
||||
if (resegment_test_4()) {
|
||||
printf("resegment_test_4 failed\n");
|
||||
exit(-1);
|
||||
};
|
||||
byte_buffer_pool::get_instance()->cleanup();
|
||||
|
||||
resegment_test_5();
|
||||
if (resegment_test_5()) {
|
||||
printf("resegment_test_5 failed\n");
|
||||
exit(-1);
|
||||
};
|
||||
byte_buffer_pool::get_instance()->cleanup();
|
||||
|
||||
resegment_test_6();
|
||||
if (resegment_test_6()) {
|
||||
printf("resegment_test_6 failed\n");
|
||||
exit(-1);
|
||||
};
|
||||
byte_buffer_pool::get_instance()->cleanup();
|
||||
|
||||
resegment_test_7();
|
||||
if (resegment_test_7()) {
|
||||
printf("resegment_test_7 failed\n");
|
||||
exit(-1);
|
||||
};
|
||||
byte_buffer_pool::get_instance()->cleanup();
|
||||
|
||||
resegment_test_8();
|
||||
if (resegment_test_8()) {
|
||||
printf("resegment_test_8 failed\n");
|
||||
exit(-1);
|
||||
};
|
||||
byte_buffer_pool::get_instance()->cleanup();
|
||||
|
||||
reset_test();
|
||||
if (reset_test()) {
|
||||
printf("reset_test failed\n");
|
||||
exit(-1);
|
||||
};
|
||||
byte_buffer_pool::get_instance()->cleanup();
|
||||
|
||||
stop_test();
|
||||
|
||||
if (stop_test()) {
|
||||
printf("stop_test failed\n");
|
||||
exit(-1);
|
||||
};
|
||||
byte_buffer_pool::get_instance()->cleanup();
|
||||
}
|
||||
|
|
|
@ -28,6 +28,7 @@
|
|||
#define SRSENB_PHCH_COMMON_H
|
||||
|
||||
#include <map>
|
||||
#include <semaphore.h>
|
||||
#include "srslte/interfaces/enb_interfaces.h"
|
||||
#include "srslte/interfaces/enb_metrics_interface.h"
|
||||
#include "srslte/common/gen_mch_tables.h"
|
||||
|
@ -36,6 +37,7 @@
|
|||
#include "srslte/common/thread_pool.h"
|
||||
#include "srslte/radio/radio.h"
|
||||
#include <string.h>
|
||||
|
||||
namespace srsenb {
|
||||
|
||||
typedef struct {
|
||||
|
@ -73,29 +75,16 @@ class phch_common
|
|||
{
|
||||
public:
|
||||
|
||||
|
||||
phch_common(uint32_t max_mutex_) : tx_mutex(max_mutex_) {
|
||||
nof_mutex = 0;
|
||||
max_mutex = max_mutex_;
|
||||
params.max_prach_offset_us = 20;
|
||||
radio = NULL;
|
||||
mac = NULL;
|
||||
is_first_tx = false;
|
||||
is_first_of_burst = false;
|
||||
pdsch_p_b = 0;
|
||||
nof_workers = 0;
|
||||
bzero(&pusch_cfg, sizeof(pusch_cfg));
|
||||
bzero(&hopping_cfg, sizeof(hopping_cfg));
|
||||
bzero(&pucch_cfg, sizeof(pucch_cfg));
|
||||
bzero(&ul_grants, sizeof(ul_grants));
|
||||
}
|
||||
|
||||
|
||||
phch_common(uint32_t nof_workers);
|
||||
~phch_common();
|
||||
|
||||
void set_nof_workers(uint32_t nof_workers);
|
||||
|
||||
bool init(srslte_cell_t *cell, srslte::radio *radio_handler, mac_interface_phy *mac);
|
||||
void reset();
|
||||
void stop();
|
||||
|
||||
void set_nof_mutex(uint32_t nof_mutex);
|
||||
|
||||
void worker_end(uint32_t tx_mutex_cnt, cf_t *buffer[SRSLTE_MAX_PORTS], uint32_t nof_samples, srslte_timestamp_t tx_time);
|
||||
|
||||
// Common objects
|
||||
|
@ -148,13 +137,12 @@ public:
|
|||
|
||||
|
||||
private:
|
||||
std::vector<pthread_mutex_t> tx_mutex;
|
||||
std::vector<sem_t> tx_sem;
|
||||
bool is_first_tx;
|
||||
bool is_first_of_burst;
|
||||
|
||||
uint32_t nof_workers;
|
||||
uint32_t nof_mutex;
|
||||
uint32_t max_mutex;
|
||||
uint32_t max_workers;
|
||||
|
||||
pthread_mutex_t user_mutex;
|
||||
|
||||
|
|
|
@ -46,7 +46,7 @@ public:
|
|||
void reset();
|
||||
|
||||
cf_t *get_buffer_rx(uint32_t antenna_idx);
|
||||
void set_time(uint32_t tti, uint32_t tx_mutex_cnt, srslte_timestamp_t tx_time);
|
||||
void set_time(uint32_t tti, uint32_t tx_worker_cnt, srslte_timestamp_t tx_time);
|
||||
|
||||
int add_rnti(uint16_t rnti);
|
||||
void rem_rnti(uint16_t rnti);
|
||||
|
@ -93,8 +93,9 @@ private:
|
|||
cf_t *signal_buffer_rx[SRSLTE_MAX_PORTS];
|
||||
cf_t *signal_buffer_tx[SRSLTE_MAX_PORTS];
|
||||
uint32_t tti_rx, tti_tx_dl, tti_tx_ul;
|
||||
uint32_t sf_rx, sf_tx, tx_mutex_cnt;
|
||||
uint32_t sf_rx, sf_tx;
|
||||
uint32_t t_rx, t_tx_dl, t_tx_ul;
|
||||
uint32_t tx_worker_cnt;
|
||||
srslte_enb_dl_t enb_dl;
|
||||
srslte_enb_ul_t enb_ul;
|
||||
srslte_softbuffer_tx_t temp_mbsfn_softbuffer;
|
||||
|
|
|
@ -50,8 +50,6 @@ public:
|
|||
uint32_t prio);
|
||||
void stop();
|
||||
|
||||
const static int MUTEX_X_WORKER = 4;
|
||||
|
||||
private:
|
||||
|
||||
void run_thread();
|
||||
|
@ -61,12 +59,12 @@ private:
|
|||
srslte::thread_pool *workers_pool;
|
||||
prach_worker *prach;
|
||||
phch_common *worker_com;
|
||||
|
||||
uint32_t tx_mutex_cnt;
|
||||
uint32_t nof_tx_mutex;
|
||||
|
||||
|
||||
// Main system TTI counter
|
||||
uint32_t tti;
|
||||
uint32_t tti;
|
||||
|
||||
uint32_t tx_worker_cnt;
|
||||
uint32_t nof_workers;
|
||||
|
||||
bool running;
|
||||
};
|
||||
|
|
|
@ -41,9 +41,35 @@ using namespace std;
|
|||
|
||||
namespace srsenb {
|
||||
|
||||
void phch_common::set_nof_mutex(uint32_t nof_mutex_) {
|
||||
nof_mutex = nof_mutex_;
|
||||
assert(nof_mutex <= max_mutex);
|
||||
phch_common::phch_common(uint32_t max_workers) : tx_sem(max_workers)
|
||||
{
|
||||
this->nof_workers = nof_workers;
|
||||
params.max_prach_offset_us = 20;
|
||||
radio = NULL;
|
||||
mac = NULL;
|
||||
is_first_tx = false;
|
||||
is_first_of_burst = false;
|
||||
pdsch_p_b = 0;
|
||||
this->max_workers = max_workers;
|
||||
bzero(&pusch_cfg, sizeof(pusch_cfg));
|
||||
bzero(&hopping_cfg, sizeof(hopping_cfg));
|
||||
bzero(&pucch_cfg, sizeof(pucch_cfg));
|
||||
bzero(&ul_grants, sizeof(ul_grants));
|
||||
|
||||
for (uint32_t i=0;i<max_workers;i++) {
|
||||
sem_init(&tx_sem[i], 0, 0); // All semaphores start blocked
|
||||
}
|
||||
}
|
||||
|
||||
phch_common::~phch_common() {
|
||||
for (uint32_t i=0;i<max_workers;i++) {
|
||||
sem_destroy(&tx_sem[i]);
|
||||
}
|
||||
}
|
||||
|
||||
void phch_common::set_nof_workers(uint32_t nof_workers)
|
||||
{
|
||||
this->nof_workers = nof_workers;
|
||||
}
|
||||
|
||||
void phch_common::reset() {
|
||||
|
@ -61,35 +87,42 @@ bool phch_common::init(srslte_cell_t *cell_, srslte::radio* radio_h_, mac_interf
|
|||
|
||||
is_first_of_burst = true;
|
||||
is_first_tx = true;
|
||||
for (uint32_t i=0;i<max_mutex;i++) {
|
||||
pthread_mutex_init(&tx_mutex[i], NULL);
|
||||
}
|
||||
reset();
|
||||
reset();
|
||||
return true;
|
||||
}
|
||||
|
||||
void phch_common::stop() {
|
||||
for (uint32_t i=0;i<nof_mutex;i++) {
|
||||
pthread_mutex_trylock(&tx_mutex[i]);
|
||||
pthread_mutex_unlock(&tx_mutex[i]);
|
||||
for (uint32_t i=0;i<max_workers;i++) {
|
||||
sem_post(&tx_sem[i]);
|
||||
}
|
||||
}
|
||||
|
||||
void phch_common::worker_end(uint32_t tx_mutex_cnt, cf_t* buffer[SRSLTE_MAX_PORTS], uint32_t nof_samples, srslte_timestamp_t tx_time)
|
||||
/* The transmission of UL subframes must be in sequence. The correct sequence is guaranteed by a chain of N semaphores,
|
||||
* one per TTI%nof_workers. Each threads waits for the semaphore for the current thread and after transmission allows
|
||||
* next TTI to be transmitted
|
||||
*
|
||||
* Each worker uses this function to indicate that all processing is done and data is ready for transmission or
|
||||
* there is no transmission at all (tx_enable). In that case, the end of burst message will be sent to the radio
|
||||
*/
|
||||
void phch_common::worker_end(uint32_t tti, cf_t* buffer[SRSLTE_MAX_PORTS], uint32_t nof_samples, srslte_timestamp_t tx_time)
|
||||
{
|
||||
|
||||
// Wait previous TTIs to be transmitted
|
||||
// This variable is not protected but it is very unlikely that 2 threads arrive here simultaneously since at the beginning
|
||||
// there is no workload and threads are separated by 1 ms
|
||||
if (is_first_tx) {
|
||||
is_first_tx = false;
|
||||
} else {
|
||||
pthread_mutex_lock(&tx_mutex[tx_mutex_cnt%nof_mutex]);
|
||||
is_first_tx = false;
|
||||
// Allow my own transmission if I'm the first to transmit
|
||||
sem_post(&tx_sem[tti%nof_workers]);
|
||||
}
|
||||
|
||||
radio->set_tti(tx_mutex_cnt);
|
||||
// Wait for the green light to transmit in the current TTI
|
||||
sem_wait(&tx_sem[tti%nof_workers]);
|
||||
|
||||
radio->set_tti(tti);
|
||||
radio->tx((void **) buffer, nof_samples, tx_time);
|
||||
|
||||
// Trigger next transmission
|
||||
pthread_mutex_unlock(&tx_mutex[(tx_mutex_cnt+1)%nof_mutex]);
|
||||
|
||||
// Allow next TTI to transmit
|
||||
sem_post(&tx_sem[(tti+1)%nof_workers]);
|
||||
|
||||
// Trigger MAC clock
|
||||
mac->tti_clock();
|
||||
|
|
|
@ -206,7 +206,7 @@ cf_t* phch_worker::get_buffer_rx(uint32_t antenna_idx)
|
|||
return signal_buffer_rx[antenna_idx];
|
||||
}
|
||||
|
||||
void phch_worker::set_time(uint32_t tti_, uint32_t tx_mutex_cnt_, srslte_timestamp_t tx_time_)
|
||||
void phch_worker::set_time(uint32_t tti_, uint32_t tx_worker_cnt_, srslte_timestamp_t tx_time_)
|
||||
{
|
||||
tti_rx = tti_;
|
||||
tti_tx_dl = TTI_TX(tti_rx);
|
||||
|
@ -219,7 +219,7 @@ void phch_worker::set_time(uint32_t tti_, uint32_t tx_mutex_cnt_, srslte_timesta
|
|||
t_rx = TTIMOD(tti_rx);
|
||||
t_tx_ul = TTIMOD(tti_tx_ul);
|
||||
|
||||
tx_mutex_cnt = tx_mutex_cnt_;
|
||||
tx_worker_cnt = tx_worker_cnt_;
|
||||
memcpy(&tx_time, &tx_time_, sizeof(srslte_timestamp_t));
|
||||
}
|
||||
|
||||
|
@ -483,7 +483,7 @@ void phch_worker::work_imp()
|
|||
pthread_mutex_unlock(&mutex);
|
||||
|
||||
Debug("Sending to radio\n");
|
||||
phy->worker_end(tx_mutex_cnt, signal_buffer_tx, SRSLTE_SF_LEN_PRB(phy->cell.nof_prb), tx_time);
|
||||
phy->worker_end(tx_worker_cnt, signal_buffer_tx, SRSLTE_SF_LEN_PRB(phy->cell.nof_prb), tx_time);
|
||||
|
||||
is_worker_running = false;
|
||||
|
||||
|
|
|
@ -48,7 +48,7 @@ namespace srsenb {
|
|||
|
||||
phy::phy() : workers_pool(MAX_WORKERS),
|
||||
workers(MAX_WORKERS),
|
||||
workers_common(txrx::MUTEX_X_WORKER*MAX_WORKERS),
|
||||
workers_common(MAX_WORKERS),
|
||||
nof_workers(0)
|
||||
{
|
||||
radio_handler = NULL;
|
||||
|
@ -141,10 +141,10 @@ bool phy::init(phy_args_t *args,
|
|||
void phy::stop()
|
||||
{
|
||||
tx_rx.stop();
|
||||
workers_common.stop();
|
||||
for (uint32_t i=0;i<nof_workers;i++) {
|
||||
workers[i].stop();
|
||||
}
|
||||
workers_common.stop();
|
||||
workers_pool.stop();
|
||||
prach.stop();
|
||||
}
|
||||
|
|
|
@ -42,7 +42,7 @@ using namespace std;
|
|||
|
||||
namespace srsenb {
|
||||
|
||||
txrx::txrx() : tx_mutex_cnt(0), nof_tx_mutex(0), tti(0) {
|
||||
txrx::txrx() : tx_worker_cnt(0), nof_workers(0), tti(0) {
|
||||
running = false;
|
||||
radio_h = NULL;
|
||||
log_h = NULL;
|
||||
|
@ -58,11 +58,11 @@ bool txrx::init(srslte::radio* radio_h_, srslte::thread_pool* workers_pool_, phc
|
|||
workers_pool = workers_pool_;
|
||||
worker_com = worker_com_;
|
||||
prach = prach_;
|
||||
tx_mutex_cnt = 0;
|
||||
tx_worker_cnt = 0;
|
||||
running = true;
|
||||
|
||||
nof_tx_mutex = MUTEX_X_WORKER*workers_pool->get_nof_workers();
|
||||
worker_com->set_nof_mutex(nof_tx_mutex);
|
||||
nof_workers = workers_pool->get_nof_workers();
|
||||
worker_com->set_nof_workers(nof_workers);
|
||||
|
||||
start(prio_);
|
||||
return true;
|
||||
|
@ -126,12 +126,12 @@ void txrx::run_thread()
|
|||
srslte_timestamp_add(&tx_time, 0, HARQ_DELAY_MS*1e-3);
|
||||
|
||||
Debug("Settting TTI=%d, tx_mutex=%d, tx_time=%ld:%f to worker %d\n",
|
||||
tti, tx_mutex_cnt,
|
||||
tti, tx_worker_cnt,
|
||||
tx_time.full_secs, tx_time.frac_secs,
|
||||
worker->get_id());
|
||||
|
||||
worker->set_time(tti, tx_mutex_cnt, tx_time);
|
||||
tx_mutex_cnt = (tx_mutex_cnt+1)%nof_tx_mutex;
|
||||
worker->set_time(tti, tx_worker_cnt, tx_time);
|
||||
tx_worker_cnt = (tx_worker_cnt+1)%nof_workers;
|
||||
|
||||
// Trigger phy worker execution
|
||||
workers_pool->start_worker(worker);
|
||||
|
|
|
@ -33,6 +33,7 @@
|
|||
#include <pthread.h>
|
||||
#include <string.h>
|
||||
#include <vector>
|
||||
#include <semaphore.h>
|
||||
#include "srslte/srslte.h"
|
||||
#include "srslte/interfaces/ue_interfaces.h"
|
||||
#include "srslte/radio/radio.h"
|
||||
|
@ -116,7 +117,8 @@ typedef struct {
|
|||
uint8_t last_ri;
|
||||
uint8_t last_pmi;
|
||||
|
||||
phch_common(uint32_t max_mutex = 3);
|
||||
phch_common(uint32_t max_workers);
|
||||
~phch_common();
|
||||
void init(phy_interface_rrc::phy_cfg_t *config,
|
||||
phy_args_t *args,
|
||||
srslte::log *_log,
|
||||
|
@ -144,8 +146,7 @@ typedef struct {
|
|||
|
||||
void worker_end(uint32_t tti, bool tx_enable, cf_t *buffer, uint32_t nof_samples, srslte_timestamp_t tx_time);
|
||||
|
||||
void set_nof_mutex(uint32_t nof_mutex);
|
||||
|
||||
void set_nof_workers(uint32_t nof_workers);
|
||||
bool sr_enabled;
|
||||
int sr_last_tx_tti;
|
||||
|
||||
|
@ -179,7 +180,9 @@ typedef struct {
|
|||
|
||||
|
||||
|
||||
std::vector<pthread_mutex_t> tx_mutex;
|
||||
std::vector<sem_t> tx_sem;
|
||||
uint32_t nof_workers;
|
||||
uint32_t max_workers;
|
||||
|
||||
bool is_first_of_burst;
|
||||
srslte::radio *radio_h;
|
||||
|
@ -208,10 +211,6 @@ typedef struct {
|
|||
|
||||
bool is_first_tx;
|
||||
|
||||
uint32_t nof_workers;
|
||||
uint32_t nof_mutex;
|
||||
uint32_t max_mutex;
|
||||
|
||||
srslte_cell_t cell;
|
||||
|
||||
dl_metrics_t dl_metrics;
|
||||
|
|
|
@ -83,7 +83,6 @@ public:
|
|||
void force_freq(float dl_freq, float ul_freq);
|
||||
|
||||
// Other functions
|
||||
const static int MUTEX_X_WORKER = 4;
|
||||
double set_rx_gain(double gain);
|
||||
int radio_recv_fnc(cf_t *data[SRSLTE_MAX_PORTS], uint32_t nsamples, srslte_timestamp_t *rx_time);
|
||||
int scell_recv_fnc(cf_t *data[SRSLTE_MAX_PORTS], uint32_t nsamples, srslte_timestamp_t *rx_time);
|
||||
|
@ -438,9 +437,9 @@ private:
|
|||
float time_adv_sec, next_time_adv_sec;
|
||||
uint32_t tti;
|
||||
bool do_agc;
|
||||
|
||||
uint32_t nof_tx_mutex;
|
||||
uint32_t tx_mutex_cnt;
|
||||
|
||||
uint32_t tx_worker_cnt;
|
||||
uint32_t nof_workers;
|
||||
|
||||
float ul_dl_factor;
|
||||
int current_earfcn;
|
||||
|
|
|
@ -52,7 +52,7 @@ public:
|
|||
|
||||
/* Functions used by main PHY thread */
|
||||
cf_t* get_buffer(uint32_t antenna_idx);
|
||||
void set_tti(uint32_t tti, uint32_t tx_tti);
|
||||
void set_tti(uint32_t tti, uint32_t tx_worker_cnt);
|
||||
void set_tx_time(srslte_timestamp_t tx_time, uint32_t next_offset);
|
||||
void set_prach(cf_t *prach_ptr, float prach_power);
|
||||
void set_cfo(float cfo);
|
||||
|
|
|
@ -39,15 +39,14 @@ namespace srsue {
|
|||
|
||||
cf_t zeros[50000];
|
||||
|
||||
phch_common::phch_common(uint32_t max_mutex_) : tx_mutex(max_mutex_)
|
||||
phch_common::phch_common(uint32_t max_workers) : tx_sem(max_workers)
|
||||
{
|
||||
config = NULL;
|
||||
args = NULL;
|
||||
log_h = NULL;
|
||||
radio_h = NULL;
|
||||
mac = NULL;
|
||||
max_mutex = max_mutex_;
|
||||
nof_mutex = 0;
|
||||
mac = NULL;
|
||||
this->max_workers = max_workers;
|
||||
rx_gain_offset = 0;
|
||||
last_ri = 0;
|
||||
last_pmi = 0;
|
||||
|
@ -65,17 +64,28 @@ phch_common::phch_common(uint32_t max_mutex_) : tx_mutex(max_mutex_)
|
|||
|
||||
bzero(zeros, 50000*sizeof(cf_t));
|
||||
|
||||
// FIXME: This is an ugly fix to avoid the TX filters to empty
|
||||
/*
|
||||
for (int i=0;i<50000;i++) {
|
||||
zeros[i] = 0.01*cexpf(((float) i/50000)*0.1*_Complex_I);
|
||||
}*/
|
||||
for (uint32_t i=0;i<max_workers;i++) {
|
||||
sem_init(&tx_sem[i], 0, 0); // All semaphores start blocked
|
||||
}
|
||||
|
||||
reset();
|
||||
|
||||
sib13_configured = false;
|
||||
mcch_configured = false;
|
||||
}
|
||||
|
||||
phch_common::~phch_common() {
|
||||
for (uint32_t i=0;i<max_workers;i++) {
|
||||
sem_post(&tx_sem[i]);
|
||||
}
|
||||
for (uint32_t i=0;i<max_workers;i++) {
|
||||
sem_destroy(&tx_sem[i]);
|
||||
}
|
||||
}
|
||||
|
||||
void phch_common::set_nof_workers(uint32_t nof_workers) {
|
||||
this->nof_workers = nof_workers;
|
||||
}
|
||||
|
||||
void phch_common::init(phy_interface_rrc::phy_cfg_t *_config, phy_args_t *_args, srslte::log *_log, srslte::radio *_radio, rrc_interface_phy *_rrc, mac_interface_phy *_mac)
|
||||
{
|
||||
|
@ -87,15 +97,6 @@ void phch_common::init(phy_interface_rrc::phy_cfg_t *_config, phy_args_t *_args,
|
|||
args = _args;
|
||||
is_first_tx = true;
|
||||
sr_last_tx_tti = -1;
|
||||
|
||||
for (uint32_t i=0;i<nof_mutex;i++) {
|
||||
pthread_mutex_init(&tx_mutex[i], NULL);
|
||||
}
|
||||
}
|
||||
|
||||
void phch_common::set_nof_mutex(uint32_t nof_mutex_) {
|
||||
nof_mutex = nof_mutex_;
|
||||
assert(nof_mutex <= max_mutex);
|
||||
}
|
||||
|
||||
bool phch_common::ul_rnti_active(uint32_t tti) {
|
||||
|
@ -231,23 +232,30 @@ bool phch_common::is_any_pending_ack() {
|
|||
return false;
|
||||
}
|
||||
|
||||
/* The transmisison of UL subframes must be in sequence. Each worker uses this function to indicate
|
||||
* that all processing is done and data is ready for transmission or there is no transmission at all (tx_enable).
|
||||
* In that case, the end of burst message will be send to the radio
|
||||
/* The transmission of UL subframes must be in sequence. The correct sequence is guaranteed by a chain of N semaphores,
|
||||
* one per TTI%max_workers. Each threads waits for the semaphore for the current thread and after transmission allows
|
||||
* next TTI to be transmitted
|
||||
*
|
||||
* Each worker uses this function to indicate that all processing is done and data is ready for transmission or
|
||||
* there is no transmission at all (tx_enable). In that case, the end of burst message will be sent to the radio
|
||||
*/
|
||||
void phch_common::worker_end(uint32_t tti, bool tx_enable,
|
||||
cf_t *buffer, uint32_t nof_samples,
|
||||
srslte_timestamp_t tx_time)
|
||||
srslte_timestamp_t tx_time)
|
||||
{
|
||||
|
||||
// Wait previous TTIs to be transmitted
|
||||
// This variable is not protected but it is very unlikely that 2 threads arrive here simultaneously since at the beginning
|
||||
// there is no workload and threads are separated by 1 ms
|
||||
if (is_first_tx) {
|
||||
is_first_tx = false;
|
||||
} else {
|
||||
pthread_mutex_lock(&tx_mutex[tti%nof_mutex]);
|
||||
is_first_tx = false;
|
||||
// Allow my own transmission if I'm the first to transmit
|
||||
sem_post(&tx_sem[tti%nof_workers]);
|
||||
}
|
||||
|
||||
radio_h->set_tti(tti);
|
||||
// Wait for the green light to transmit in the current TTI
|
||||
sem_wait(&tx_sem[tti%nof_workers]);
|
||||
|
||||
radio_h->set_tti(tti);
|
||||
if (tx_enable) {
|
||||
radio_h->tx_single(buffer, nof_samples, tx_time);
|
||||
is_first_of_burst = false;
|
||||
|
@ -263,8 +271,9 @@ void phch_common::worker_end(uint32_t tti, bool tx_enable,
|
|||
}
|
||||
}
|
||||
}
|
||||
// Trigger next transmission
|
||||
pthread_mutex_unlock(&tx_mutex[(tti+1)%nof_mutex]);
|
||||
|
||||
// Allow next TTI to transmit
|
||||
sem_post(&tx_sem[(tti+1)%nof_workers]);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -81,8 +81,8 @@ void phch_recv::init(srslte::radio_multi *_radio_handler, mac_interface_phy *_ma
|
|||
return;
|
||||
}
|
||||
|
||||
nof_tx_mutex = MUTEX_X_WORKER * workers_pool->get_nof_workers();
|
||||
worker_com->set_nof_mutex(nof_tx_mutex);
|
||||
nof_workers = workers_pool->get_nof_workers();
|
||||
worker_com->set_nof_workers(nof_workers);
|
||||
|
||||
// Initialize cell searcher
|
||||
search_p.init(sf_buffer, log_h, nof_rx_antennas, this);
|
||||
|
@ -128,7 +128,7 @@ void phch_recv::reset()
|
|||
radio_overflow_return = false;
|
||||
in_sync_cnt = 0;
|
||||
out_of_sync_cnt = 0;
|
||||
tx_mutex_cnt = 0;
|
||||
tx_worker_cnt = 0;
|
||||
time_adv_sec = 0;
|
||||
next_offset = 0;
|
||||
srate_mode = SRATE_NONE;
|
||||
|
@ -454,13 +454,13 @@ void phch_recv::run_thread()
|
|||
|
||||
worker->set_prach(prach_ptr?&prach_ptr[prach_sf_cnt*SRSLTE_SF_LEN_PRB(cell.nof_prb)]:NULL, prach_power);
|
||||
worker->set_cfo(get_tx_cfo());
|
||||
worker->set_tti(tti, tx_mutex_cnt);
|
||||
worker->set_tti(tti, tx_worker_cnt);
|
||||
worker->set_tx_time(tx_time, next_offset);
|
||||
next_offset = 0;
|
||||
if (next_time_adv_sec != time_adv_sec) {
|
||||
time_adv_sec = next_time_adv_sec;
|
||||
}
|
||||
tx_mutex_cnt = (tx_mutex_cnt+1) % nof_tx_mutex;
|
||||
tx_worker_cnt = (tx_worker_cnt+1) % nof_workers;
|
||||
|
||||
// Advance/reset prach subframe pointer
|
||||
if (prach_ptr) {
|
||||
|
|
|
@ -193,10 +193,10 @@ cf_t* phch_worker::get_buffer(uint32_t antenna_idx)
|
|||
return signal_buffer[antenna_idx];
|
||||
}
|
||||
|
||||
void phch_worker::set_tti(uint32_t tti_, uint32_t tx_tti_)
|
||||
void phch_worker::set_tti(uint32_t tti_, uint32_t tx_worker_cnt)
|
||||
{
|
||||
tti = tti_;
|
||||
tx_tti = tx_tti_;
|
||||
tti = tti_;
|
||||
tx_tti = tx_worker_cnt;
|
||||
log_h->step(tti);
|
||||
if (log_phy_lib_h) {
|
||||
log_phy_lib_h->step(tti);
|
||||
|
|
|
@ -52,7 +52,7 @@ namespace srsue {
|
|||
|
||||
phy::phy() : workers_pool(MAX_WORKERS),
|
||||
workers(MAX_WORKERS),
|
||||
workers_common(phch_recv::MUTEX_X_WORKER*MAX_WORKERS),nof_coworkers(0)
|
||||
workers_common(MAX_WORKERS),nof_coworkers(0)
|
||||
{
|
||||
}
|
||||
|
||||
|
|
|
@ -1176,7 +1176,8 @@ void nas::send_detach_request(bool switch_off)
|
|||
return;
|
||||
}
|
||||
|
||||
LIBLTE_MME_DETACH_REQUEST_MSG_STRUCT detach_request = {};
|
||||
LIBLTE_MME_DETACH_REQUEST_MSG_STRUCT detach_request;
|
||||
bzero(&detach_request, sizeof(detach_request));
|
||||
if (switch_off) {
|
||||
detach_request.detach_type.switch_off = 1;
|
||||
detach_request.detach_type.type_of_detach = LIBLTE_MME_SO_FLAG_SWITCH_OFF;
|
||||
|
|
|
@ -64,7 +64,7 @@ int pcsc_usim::init(usim_args_t *args, srslte::log *log_)
|
|||
log->error("Error reading IMSI from SIM.\n");
|
||||
return ret;
|
||||
}
|
||||
imsi_str = tmp;
|
||||
imsi_str.assign(tmp, tmp_len);
|
||||
|
||||
// Check extracted IMSI and convert
|
||||
if(15 == imsi_str.length()) {
|
||||
|
|
|
@ -729,10 +729,10 @@ uint32_t rrc::sib_start_tti(uint32_t tti, uint32_t period, uint32_t offset, uint
|
|||
*/
|
||||
bool rrc::si_acquire(uint32_t sib_index)
|
||||
{
|
||||
uint32_t tti;
|
||||
uint32_t tti = 0;
|
||||
uint32_t si_win_start=0, si_win_len=0;
|
||||
uint16_t period;
|
||||
uint32_t sched_index;
|
||||
uint16_t period = 0;
|
||||
uint32_t sched_index = 0;
|
||||
uint32_t x, sf, offset;
|
||||
|
||||
uint32_t last_win_start = 0;
|
||||
|
|
Loading…
Reference in New Issue