mirror of https://github.com/PentHertz/srsLTE.git
Merge next into gtp_cleanup_sn. Fixed some conflicts.
This commit is contained in:
commit
d443604661
|
@ -75,7 +75,8 @@ option(ENABLE_HARDSIM "Enable support for SIM cards" ON)
|
|||
|
||||
option(BUILD_STATIC "Attempt to statically link external deps" OFF)
|
||||
option(RPATH "Enable RPATH" OFF)
|
||||
option(ENABLE_ASAN "Enable gcc address sanitizer" OFF)
|
||||
option(ENABLE_ASAN "Enable gcc/clang address sanitizer" OFF)
|
||||
option(ENABLE_MSAN "Enable clang memory sanitizer" OFF)
|
||||
|
||||
option(USE_LTE_RATES "Use standard LTE sampling rates" OFF)
|
||||
|
||||
|
@ -315,7 +316,6 @@ if(CMAKE_C_COMPILER_ID MATCHES "GNU" OR CMAKE_C_COMPILER_ID MATCHES "Clang")
|
|||
endif(HAVE_SSE)
|
||||
endif(NOT ${CMAKE_BUILD_TYPE} STREQUAL "Debug")
|
||||
|
||||
|
||||
if(${CMAKE_SYSTEM_PROCESSOR} MATCHES "arm")
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -mfpu=neon -march=native -DIS_ARM -DHAVE_NEON")
|
||||
message(STATUS "have ARM")
|
||||
|
@ -332,10 +332,21 @@ if(CMAKE_C_COMPILER_ID MATCHES "GNU" OR CMAKE_C_COMPILER_ID MATCHES "Clang")
|
|||
if(NOT WIN32)
|
||||
ADD_CXX_COMPILER_FLAG_IF_AVAILABLE(-fvisibility=hidden HAVE_VISIBILITY_HIDDEN)
|
||||
endif(NOT WIN32)
|
||||
if (ENABLE_ASAN)
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=address -fno-omit-frame-pointer")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=address -fno-omit-frame-pointer")
|
||||
endif (ENABLE_ASAN)
|
||||
|
||||
if (ENABLE_ASAN AND ENABLE_MSAN)
|
||||
message(FATAL_ERROR "ASAN and MSAN cannot be enabled at the same time.")
|
||||
endif (ENABLE_ASAN AND ENABLE_MSAN)
|
||||
|
||||
if (ENABLE_ASAN)
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=address -fno-omit-frame-pointer")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=address -fno-omit-frame-pointer")
|
||||
endif (ENABLE_ASAN)
|
||||
|
||||
if (ENABLE_MSAN AND CMAKE_C_COMPILER_ID MATCHES "Clang")
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=memory -fno-omit-frame-pointer -fPIE -pie")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=memory -fno-omit-frame-pointer -fPIE -pie")
|
||||
endif (ENABLE_MSAN AND CMAKE_C_COMPILER_ID MATCHES "Clang")
|
||||
|
||||
endif(CMAKE_C_COMPILER_ID MATCHES "GNU" OR CMAKE_C_COMPILER_ID MATCHES "Clang")
|
||||
|
||||
if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
|
||||
|
@ -359,7 +370,7 @@ if(NOT CLANG_TIDY_BIN)
|
|||
message(STATUS "clang-tidy not found.")
|
||||
else()
|
||||
message(STATUS "clang-tidy found: ${CLANG_TIDY_BIN}")
|
||||
set(DO_CLANG_TIDY "${CLANG_TIDY_BIN}" "-checks=*,-clang-analyzer-alpha.*")
|
||||
set(DO_CLANG_TIDY "${CLANG_TIDY_BIN}" "-checks=*,-clang-analyzer-alpha.*,-modernize-*,-cppcoreguidelines-pro-type-vararg,-cppcoreguidelines-pro-bounds-pointer-arithmetic,-cppcoreguidelines-pro-bounds-constant-array-index")
|
||||
endif()
|
||||
|
||||
|
||||
|
|
|
@ -150,9 +150,9 @@ inline void s1ap_plmn_to_mccmnc(uint32_t plmn, uint16_t *mcc, uint16_t *mnc)
|
|||
*mnc |= nibbles[4]; // MNC digit 3
|
||||
} else {
|
||||
// 3-digit MNC
|
||||
*mnc |= nibbles[5] << 8; // MNC digit 1
|
||||
*mnc |= nibbles[4] << 4; // MNC digit 2
|
||||
*mnc |= nibbles[2] ; // MNC digit 3
|
||||
*mnc |= nibbles[2] << 8; // MNC digit 1
|
||||
*mnc |= nibbles[5] << 4; // MNC digit 2
|
||||
*mnc |= nibbles[4] ; // MNC digit 3
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -177,9 +177,9 @@ inline void s1ap_mccmnc_to_plmn(uint16_t mcc, uint16_t mnc, uint32_t *plmn)
|
|||
nibbles[4] = (mnc & 0x000F); // MNC digit 3
|
||||
} else {
|
||||
// 3-digit MNC
|
||||
nibbles[5] = (mnc & 0x0F00) >> 8; // MNC digit 1
|
||||
nibbles[4] = (mnc & 0x00F0) >> 4; // MNC digit 2
|
||||
nibbles[2] = (mnc & 0x000F); // MNC digit 3
|
||||
nibbles[2] = (mnc & 0x0F00) >> 8; // MNC digit 1
|
||||
nibbles[5] = (mnc & 0x00F0) >> 4; // MNC digit 2
|
||||
nibbles[4] = (mnc & 0x000F); // MNC digit 3
|
||||
}
|
||||
|
||||
*plmn = 0x000000;
|
||||
|
|
|
@ -109,7 +109,6 @@ public:
|
|||
|
||||
myobj wait_pop() { // blocking pop
|
||||
myobj value;
|
||||
bzero(&value, sizeof(myobj));
|
||||
pop_(&value, true);
|
||||
return value;
|
||||
}
|
||||
|
@ -154,8 +153,8 @@ private:
|
|||
}
|
||||
if (value) {
|
||||
*value = q.front();
|
||||
q.pop();
|
||||
}
|
||||
q.pop();
|
||||
ret = true;
|
||||
if (mutexed_callback) {
|
||||
mutexed_callback->popping(*value);
|
||||
|
|
|
@ -59,10 +59,10 @@
|
|||
|
||||
#define ASYNC_DL_SCHED (HARQ_DELAY_MS <= 4)
|
||||
|
||||
// Cat 3 UE - Max number of DL-SCH transport block bits received within a TTI
|
||||
// Cat 4 UE - Max number of DL-SCH transport block bits received within a TTI
|
||||
// 3GPP 36.306 Table 4.1.1
|
||||
#define SRSLTE_MAX_BUFFER_SIZE_BITS 102048
|
||||
#define SRSLTE_MAX_BUFFER_SIZE_BYTES 12756
|
||||
#define SRSLTE_MAX_BUFFER_SIZE_BITS 150752
|
||||
#define SRSLTE_MAX_BUFFER_SIZE_BYTES (SRSLTE_MAX_BUFFER_SIZE_BITS/8)
|
||||
#define SRSLTE_BUFFER_HEADER_OFFSET 1020
|
||||
|
||||
#define SRSLTE_BUFFER_POOL_LOG_ENABLED
|
||||
|
@ -125,7 +125,7 @@ public:
|
|||
#ifdef ENABLE_TIMESTAMP
|
||||
timestamp_is_set = false;
|
||||
#endif
|
||||
msg = &buffer[SRSLTE_BUFFER_HEADER_OFFSET];
|
||||
msg = &buffer[SRSLTE_BUFFER_HEADER_OFFSET];
|
||||
next = NULL;
|
||||
#ifdef SRSLTE_BUFFER_POOL_LOG_ENABLED
|
||||
bzero(debug_name, SRSLTE_BUFFER_POOL_LOG_NAME_LEN);
|
||||
|
@ -134,6 +134,9 @@ public:
|
|||
byte_buffer_t(const byte_buffer_t& buf)
|
||||
{
|
||||
bzero(buffer, SRSLTE_MAX_BUFFER_SIZE_BYTES);
|
||||
msg = &buffer[SRSLTE_BUFFER_HEADER_OFFSET];
|
||||
next = NULL;
|
||||
// copy actual contents
|
||||
N_bytes = buf.N_bytes;
|
||||
memcpy(msg, buf.msg, N_bytes);
|
||||
}
|
||||
|
@ -143,6 +146,8 @@ public:
|
|||
if (&buf == this)
|
||||
return *this;
|
||||
bzero(buffer, SRSLTE_MAX_BUFFER_SIZE_BYTES);
|
||||
msg = &buffer[SRSLTE_BUFFER_HEADER_OFFSET];
|
||||
next = NULL;
|
||||
N_bytes = buf.N_bytes;
|
||||
memcpy(msg, buf.msg, N_bytes);
|
||||
return *this;
|
||||
|
|
|
@ -54,6 +54,7 @@ public:
|
|||
log_filter();
|
||||
log_filter(std::string layer);
|
||||
log_filter(std::string layer, logger *logger_, bool tti=false);
|
||||
~log_filter();
|
||||
|
||||
void init(std::string layer, logger *logger_, bool tti=false);
|
||||
|
||||
|
|
|
@ -48,14 +48,6 @@ typedef struct {
|
|||
float tx_rx_gain_offset;
|
||||
} srslte_rf_t;
|
||||
|
||||
typedef struct {
|
||||
float dc_gain;
|
||||
float dc_phase;
|
||||
float iq_i;
|
||||
float iq_q;
|
||||
} srslte_rf_cal_t;
|
||||
|
||||
|
||||
typedef struct {
|
||||
double min_tx_gain;
|
||||
double max_tx_gain;
|
||||
|
@ -96,10 +88,6 @@ SRSLTE_API int srslte_rf_start_gain_thread(srslte_rf_t *rf,
|
|||
|
||||
SRSLTE_API int srslte_rf_close(srslte_rf_t *h);
|
||||
|
||||
SRSLTE_API void srslte_rf_set_tx_cal(srslte_rf_t *h, srslte_rf_cal_t *cal);
|
||||
|
||||
SRSLTE_API void srslte_rf_set_rx_cal(srslte_rf_t *h, srslte_rf_cal_t *cal);
|
||||
|
||||
SRSLTE_API int srslte_rf_start_rx_stream(srslte_rf_t *h, bool now);
|
||||
|
||||
SRSLTE_API int srslte_rf_stop_rx_stream(srslte_rf_t *h);
|
||||
|
|
|
@ -33,17 +33,6 @@
|
|||
#ifndef SRSLTE_RADIO_H
|
||||
#define SRSLTE_RADIO_H
|
||||
|
||||
typedef struct {
|
||||
float tx_corr_dc_gain;
|
||||
float tx_corr_dc_phase;
|
||||
float tx_corr_iq_i;
|
||||
float tx_corr_iq_q;
|
||||
float rx_corr_dc_gain;
|
||||
float rx_corr_dc_phase;
|
||||
float rx_corr_iq_i;
|
||||
float rx_corr_iq_q;
|
||||
} rf_cal_t;
|
||||
|
||||
namespace srslte {
|
||||
|
||||
/* Interface to the RF frontend.
|
||||
|
@ -85,8 +74,6 @@ class radio {
|
|||
void set_tx_adv(int nsamples);
|
||||
void set_tx_adv_neg(bool tx_adv_is_neg);
|
||||
|
||||
void set_manual_calibration(rf_cal_t *calibration);
|
||||
|
||||
bool is_continuous_tx();
|
||||
void set_continuous_tx(bool enable);
|
||||
|
||||
|
|
|
@ -56,7 +56,7 @@ public:
|
|||
log *rlc_log_,
|
||||
mac_interface_timers *mac_timers_,
|
||||
uint32_t lcid_,
|
||||
int buffer_size = -1); // -1 to use default buffer sizes
|
||||
int buffer_size_ = -1); // -1 to use default buffer sizes
|
||||
void stop();
|
||||
|
||||
void get_metrics(rlc_metrics_t &m);
|
||||
|
@ -88,6 +88,7 @@ public:
|
|||
void add_bearer(uint32_t lcid, srslte_rlc_config_t cnfg);
|
||||
void add_bearer_mrb(uint32_t lcid);
|
||||
void del_bearer(uint32_t lcid);
|
||||
void del_bearer_mrb(uint32_t lcid);
|
||||
void change_lcid(uint32_t old_lcid, uint32_t new_lcid);
|
||||
|
||||
private:
|
||||
|
|
|
@ -69,14 +69,14 @@ struct rlc_amd_retx_t{
|
|||
class rlc_am : public rlc_common
|
||||
{
|
||||
public:
|
||||
rlc_am(uint32_t queue_len = 16);
|
||||
rlc_am(uint32_t queue_len = 128);
|
||||
~rlc_am();
|
||||
void init(log *rlc_entity_log_,
|
||||
void init(log *log_,
|
||||
uint32_t lcid_,
|
||||
srsue::pdcp_interface_rlc *pdcp_,
|
||||
srsue::rrc_interface_rlc *rrc_,
|
||||
mac_interface_timers *mac_timers);
|
||||
bool configure(srslte_rlc_config_t cnfg);
|
||||
mac_interface_timers *mac_timers_);
|
||||
bool configure(srslte_rlc_config_t cfg_);
|
||||
void reestablish();
|
||||
void stop();
|
||||
|
||||
|
@ -104,7 +104,7 @@ private:
|
|||
class rlc_am_tx : public timer_callback
|
||||
{
|
||||
public:
|
||||
rlc_am_tx(rlc_am *parent_, uint32_t queue_len);
|
||||
rlc_am_tx(rlc_am *parent_, uint32_t queue_len_);
|
||||
~rlc_am_tx();
|
||||
|
||||
void init();
|
||||
|
@ -139,6 +139,7 @@ private:
|
|||
|
||||
bool retx_queue_has_sn(uint32_t sn);
|
||||
int required_buffer_size(rlc_amd_retx_t retx);
|
||||
void retransmit_random_pdu();
|
||||
|
||||
// Timer checks
|
||||
bool status_prohibited;
|
||||
|
@ -224,7 +225,8 @@ private:
|
|||
void timer_expired(uint32_t timeout_id);
|
||||
|
||||
// Functions needed by Tx subclass to query rx state
|
||||
int get_status(rlc_status_pdu_t* status);
|
||||
int get_status_pdu_length();
|
||||
int get_status_pdu(rlc_status_pdu_t* status, const uint32_t nof_bytes);
|
||||
bool get_do_status();
|
||||
void reset_status(); // called when status PDU has been sent
|
||||
|
||||
|
@ -319,7 +321,8 @@ uint32_t rlc_am_packed_length(rlc_amd_retx_t retx);
|
|||
bool rlc_am_is_control_pdu(byte_buffer_t *pdu);
|
||||
bool rlc_am_is_control_pdu(uint8_t *payload);
|
||||
bool rlc_am_is_pdu_segment(uint8_t *payload);
|
||||
std::string rlc_am_to_string(rlc_status_pdu_t *status);
|
||||
std::string rlc_am_status_pdu_to_string(rlc_status_pdu_t *status);
|
||||
std::string rlc_amd_pdu_header_to_string(const rlc_amd_pdu_header_t &header);
|
||||
bool rlc_am_start_aligned(const uint8_t fi);
|
||||
bool rlc_am_end_aligned(const uint8_t fi);
|
||||
bool rlc_am_is_unaligned(const uint8_t fi);
|
||||
|
|
|
@ -39,6 +39,8 @@
|
|||
|
||||
namespace srslte {
|
||||
|
||||
#define RLC_UM_MAX_SDU_SIZE (2048-1) // Length of LI field is 11bits
|
||||
|
||||
struct rlc_umd_pdu_t{
|
||||
rlc_umd_pdu_header_t header;
|
||||
byte_buffer_t *buf;
|
||||
|
@ -48,7 +50,7 @@ class rlc_um
|
|||
:public rlc_common
|
||||
{
|
||||
public:
|
||||
rlc_um(uint32_t queue_len = 32);
|
||||
rlc_um(uint32_t queue_len = 128);
|
||||
~rlc_um();
|
||||
void init(log *rlc_entity_log_,
|
||||
uint32_t lcid_,
|
||||
|
@ -146,6 +148,7 @@ private:
|
|||
bool configure(srslte_rlc_config_t cfg, std::string rb_name);
|
||||
void handle_data_pdu(uint8_t *payload, uint32_t nof_bytes);
|
||||
void reassemble_rx_sdus();
|
||||
bool pdu_belongs_to_rx_sdu();
|
||||
bool inside_reordering_window(uint16_t sn);
|
||||
uint32_t get_num_rx_bytes();
|
||||
void reset_metrics();
|
||||
|
@ -213,6 +216,7 @@ private:
|
|||
uint32_t lcid;
|
||||
srslte_rlc_um_config_t cfg;
|
||||
std::string rb_name;
|
||||
byte_buffer_pool *pool;
|
||||
|
||||
std::string get_rb_name(srsue::rrc_interface_rlc *rrc, uint32_t lcid, bool is_mrb);
|
||||
};
|
||||
|
|
|
@ -59,6 +59,10 @@ log_filter::log_filter(std::string layer, logger *logger_, bool tti)
|
|||
init(layer, logger_, tti);
|
||||
}
|
||||
|
||||
log_filter::~log_filter()
|
||||
{
|
||||
}
|
||||
|
||||
void log_filter::init(std::string layer, logger *logger_, bool tti)
|
||||
{
|
||||
service_name = layer;
|
||||
|
|
|
@ -86,7 +86,7 @@ bool threads_new_rt_cpu(pthread_t *thread, void *(*start_routine) (void*), void
|
|||
#else
|
||||
// All threads have normal priority except prio_offset=0,1,2,3,4
|
||||
if (prio_offset >= 0 && prio_offset < 5) {
|
||||
param.sched_priority = 50;
|
||||
param.sched_priority = 50-prio_offset;
|
||||
pthread_attr_init(&attr);
|
||||
if (pthread_attr_setinheritsched(&attr, PTHREAD_EXPLICIT_SCHED)) {
|
||||
perror("pthread_attr_setinheritsched");
|
||||
|
|
|
@ -524,7 +524,6 @@ int srslte_pusch_encode(srslte_pusch_t *q, srslte_pusch_cfg_t *cfg, srslte_softb
|
|||
cfg->sf_idx, srslte_mod_string(cfg->grant.mcs.mod), rnti,
|
||||
cfg->grant.mcs.tbs, cfg->nbits.nof_re, cfg->nbits.nof_symb, cfg->nbits.nof_bits, cfg->rv);
|
||||
|
||||
bzero(q->q, cfg->nbits.nof_bits);
|
||||
if (srslte_ulsch_uci_encode(&q->ul_sch, cfg, softbuffer, data, uci_data, q->g, q->q)) {
|
||||
fprintf(stderr, "Error encoding TB\n");
|
||||
return SRSLTE_ERROR;
|
||||
|
@ -534,6 +533,10 @@ int srslte_pusch_encode(srslte_pusch_t *q, srslte_pusch_cfg_t *cfg, srslte_softb
|
|||
srslte_sequence_t *seq = get_user_sequence(q, rnti, cfg->sf_idx, cfg->nbits.nof_bits);
|
||||
|
||||
// Run scrambling
|
||||
if (!seq) {
|
||||
fprintf(stderr, "Error getting scrambling sequence\n");
|
||||
return SRSLTE_ERROR;
|
||||
}
|
||||
srslte_scrambling_bytes(seq, (uint8_t*) q->q, cfg->nbits.nof_bits);
|
||||
|
||||
// Correct UCI placeholder/repetition bits
|
||||
|
|
|
@ -402,23 +402,6 @@ double rf_blade_set_tx_freq(void *h, double freq)
|
|||
return freq;
|
||||
}
|
||||
|
||||
void rf_blade_set_tx_cal(void *h, srslte_rf_cal_t *cal) {
|
||||
rf_blade_handler_t *handler = (rf_blade_handler_t*) h;
|
||||
bladerf_set_correction(handler->dev, BLADERF_MODULE_TX, BLADERF_CORR_FPGA_PHASE, cal->dc_phase);
|
||||
bladerf_set_correction(handler->dev, BLADERF_MODULE_TX, BLADERF_CORR_FPGA_GAIN, cal->dc_gain);
|
||||
bladerf_set_correction(handler->dev, BLADERF_MODULE_TX, BLADERF_CORR_LMS_DCOFF_I, cal->iq_i);
|
||||
bladerf_set_correction(handler->dev, BLADERF_MODULE_TX, BLADERF_CORR_LMS_DCOFF_Q, cal->iq_q);
|
||||
}
|
||||
|
||||
void rf_blade_set_rx_cal(void *h, srslte_rf_cal_t *cal) {
|
||||
rf_blade_handler_t *handler = (rf_blade_handler_t*) h;
|
||||
bladerf_set_correction(handler->dev, BLADERF_MODULE_RX, BLADERF_CORR_FPGA_PHASE, cal->dc_phase);
|
||||
bladerf_set_correction(handler->dev, BLADERF_MODULE_RX, BLADERF_CORR_FPGA_GAIN, cal->dc_gain);
|
||||
bladerf_set_correction(handler->dev, BLADERF_MODULE_RX, BLADERF_CORR_LMS_DCOFF_I, cal->iq_i);
|
||||
bladerf_set_correction(handler->dev, BLADERF_MODULE_RX, BLADERF_CORR_LMS_DCOFF_Q, cal->iq_q);
|
||||
}
|
||||
|
||||
|
||||
static void timestamp_to_secs(uint32_t rate, uint64_t timestamp, time_t *secs, double *frac_secs) {
|
||||
double totalsecs = (double) timestamp/rate;
|
||||
time_t secs_i = (time_t) totalsecs;
|
||||
|
|
|
@ -40,10 +40,6 @@ SRSLTE_API char* rf_blade_devname(void *h);
|
|||
|
||||
SRSLTE_API int rf_blade_close(void *h);
|
||||
|
||||
SRSLTE_API void rf_blade_set_tx_cal(void *h, srslte_rf_cal_t *cal);
|
||||
|
||||
SRSLTE_API void rf_blade_set_rx_cal(void *h, srslte_rf_cal_t *cal);
|
||||
|
||||
SRSLTE_API int rf_blade_start_rx_stream(void *h, bool now);
|
||||
|
||||
SRSLTE_API int rf_blade_start_rx_stream_nsamples(void *h,
|
||||
|
|
|
@ -62,10 +62,6 @@ typedef struct {
|
|||
int (*srslte_rf_send_timed_multi)(void *h, void *data[4], int nsamples,
|
||||
time_t secs, double frac_secs, bool has_time_spec,
|
||||
bool blocking, bool is_start_of_burst, bool is_end_of_burst);
|
||||
void (*srslte_rf_set_tx_cal)(void *h, srslte_rf_cal_t *cal);
|
||||
|
||||
void (*srslte_rf_set_rx_cal)(void *h, srslte_rf_cal_t *cal);
|
||||
|
||||
} rf_dev_t;
|
||||
|
||||
/* Define implementation for UHD */
|
||||
|
@ -102,9 +98,7 @@ static rf_dev_t dev_uhd = {
|
|||
rf_uhd_recv_with_time,
|
||||
rf_uhd_recv_with_time_multi,
|
||||
rf_uhd_send_timed,
|
||||
.srslte_rf_send_timed_multi = rf_uhd_send_timed_multi,
|
||||
rf_uhd_set_tx_cal,
|
||||
rf_uhd_set_rx_cal
|
||||
.srslte_rf_send_timed_multi = rf_uhd_send_timed_multi
|
||||
};
|
||||
#endif
|
||||
|
||||
|
@ -142,9 +136,7 @@ static rf_dev_t dev_blade = {
|
|||
rf_blade_recv_with_time,
|
||||
rf_blade_recv_with_time_multi,
|
||||
rf_blade_send_timed,
|
||||
.srslte_rf_send_timed_multi = rf_blade_send_timed_multi,
|
||||
rf_blade_set_tx_cal,
|
||||
rf_blade_set_rx_cal
|
||||
.srslte_rf_send_timed_multi = rf_blade_send_timed_multi
|
||||
};
|
||||
#endif
|
||||
|
||||
|
@ -181,9 +173,7 @@ static rf_dev_t dev_soapy = {
|
|||
rf_soapy_recv_with_time,
|
||||
rf_soapy_recv_with_time_multi,
|
||||
rf_soapy_send_timed,
|
||||
.srslte_rf_send_timed_multi = rf_soapy_send_timed_multi,
|
||||
rf_soapy_set_tx_cal,
|
||||
rf_soapy_set_rx_cal
|
||||
.srslte_rf_send_timed_multi = rf_soapy_send_timed_multi
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -129,15 +129,6 @@ int srslte_rf_open_devname(srslte_rf_t *rf, char *devname, char *args, uint32_t
|
|||
return -1;
|
||||
}
|
||||
|
||||
void srslte_rf_set_tx_cal(srslte_rf_t *rf, srslte_rf_cal_t *cal) {
|
||||
return ((rf_dev_t*) rf->dev)->srslte_rf_set_tx_cal(rf->handler, cal);
|
||||
}
|
||||
|
||||
void srslte_rf_set_rx_cal(srslte_rf_t *rf, srslte_rf_cal_t *cal) {
|
||||
return ((rf_dev_t*) rf->dev)->srslte_rf_set_rx_cal(rf->handler, cal);
|
||||
}
|
||||
|
||||
|
||||
const char* srslte_rf_name(srslte_rf_t *rf) {
|
||||
return ((rf_dev_t*) rf->dev)->srslte_rf_devname(rf->handler);
|
||||
}
|
||||
|
|
|
@ -205,25 +205,18 @@ bool rf_soapy_rx_wait_lo_locked(void *h)
|
|||
return true;
|
||||
}
|
||||
|
||||
|
||||
void rf_soapy_set_tx_cal(void *h, srslte_rf_cal_t *cal)
|
||||
void rf_soapy_calibrate_tx(void *h)
|
||||
{
|
||||
rf_soapy_handler_t *handler = (rf_soapy_handler_t*) h;
|
||||
double actual_bw = SoapySDRDevice_getBandwidth(handler->device, SOAPY_SDR_TX, 0);
|
||||
char str_buf[25];
|
||||
snprintf(str_buf, sizeof(str_buf), "%f", actual_bw);
|
||||
str_buf[24] = 0;
|
||||
if (SoapySDRDevice_writeSetting(handler->device, "CALIBRATE_TX", str_buf)) {
|
||||
printf("Error calibrating Rx\n");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void rf_soapy_set_rx_cal(void *h, srslte_rf_cal_t *cal)
|
||||
{
|
||||
// not supported
|
||||
}
|
||||
|
||||
|
||||
int rf_soapy_start_rx_stream(void *h, bool now)
|
||||
{
|
||||
rf_soapy_handler_t *handler = (rf_soapy_handler_t*) h;
|
||||
|
|
|
@ -43,14 +43,12 @@ SRSLTE_API char* rf_soapy_devname(void *h);
|
|||
|
||||
SRSLTE_API int rf_soapy_close(void *h);
|
||||
|
||||
SRSLTE_API void rf_soapy_set_tx_cal(void *h, srslte_rf_cal_t *cal);
|
||||
|
||||
SRSLTE_API void rf_soapy_set_rx_cal(void *h, srslte_rf_cal_t *cal);
|
||||
|
||||
SRSLTE_API int rf_soapy_start_rx_stream(void *h, bool now);
|
||||
|
||||
SRSLTE_API int rf_soapy_stop_rx_stream(void *h);
|
||||
|
||||
SRSLTE_API void rf_soapy_calibrate_tx(void *h);
|
||||
|
||||
SRSLTE_API void rf_soapy_flush_buffer(void *h);
|
||||
|
||||
SRSLTE_API bool rf_soapy_has_rssi(void *h);
|
||||
|
|
|
@ -230,17 +230,6 @@ bool rf_uhd_rx_wait_lo_locked(void *h)
|
|||
return val;
|
||||
}
|
||||
|
||||
void rf_uhd_set_tx_cal(void *h, srslte_rf_cal_t *cal)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void rf_uhd_set_rx_cal(void *h, srslte_rf_cal_t *cal)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
int rf_uhd_start_rx_stream(void *h, bool now)
|
||||
{
|
||||
rf_uhd_handler_t *handler = (rf_uhd_handler_t*) h;
|
||||
|
|
|
@ -47,10 +47,6 @@ SRSLTE_API char* rf_uhd_devname(void *h);
|
|||
|
||||
SRSLTE_API int rf_uhd_close(void *h);
|
||||
|
||||
SRSLTE_API void rf_uhd_set_tx_cal(void *h, srslte_rf_cal_t *cal);
|
||||
|
||||
SRSLTE_API void rf_uhd_set_rx_cal(void *h, srslte_rf_cal_t *cal);
|
||||
|
||||
SRSLTE_API int rf_uhd_start_rx_stream(void *h,
|
||||
bool now);
|
||||
|
||||
|
|
|
@ -450,9 +450,9 @@ int srslte_ue_dl_cfg_grant(srslte_ue_dl_t *q, srslte_ra_dl_grant_t *grant, uint3
|
|||
}
|
||||
} else {
|
||||
if (grant->pinfo == 2) {
|
||||
ERROR("Not implemented codebook index (nof_tb=%d, pinfo=%d)", nof_tb, grant->pinfo);
|
||||
/* Not implemented */
|
||||
} else if (grant->pinfo > 2) {
|
||||
ERROR("Reserved codebook index (nof_tb=%d, pinfo=%d)", nof_tb, grant->pinfo);
|
||||
/* Reserved */
|
||||
}
|
||||
pmi = grant->pinfo % 2;
|
||||
}
|
||||
|
|
|
@ -97,16 +97,6 @@ void radio::reset()
|
|||
usleep(100000);
|
||||
}
|
||||
|
||||
void radio::set_manual_calibration(rf_cal_t* calibration)
|
||||
{
|
||||
srslte_rf_cal_t tx_cal;
|
||||
tx_cal.dc_gain = calibration->tx_corr_dc_gain;
|
||||
tx_cal.dc_phase = calibration->tx_corr_dc_phase;
|
||||
tx_cal.iq_i = calibration->tx_corr_iq_i;
|
||||
tx_cal.iq_q = calibration->tx_corr_iq_q;
|
||||
srslte_rf_set_tx_cal(&rf_device, &tx_cal);
|
||||
}
|
||||
|
||||
void radio::set_tx_rx_gain_offset(float offset) {
|
||||
srslte_rf_set_tx_rx_gain_offset(&rf_device, offset);
|
||||
}
|
||||
|
|
|
@ -22,3 +22,8 @@ file(GLOB SOURCES "*.cc")
|
|||
add_library(srslte_upper STATIC ${SOURCES})
|
||||
target_link_libraries(srslte_upper srslte_common srslte_asn1)
|
||||
install(TARGETS srslte_upper DESTINATION ${LIBRARY_DIR})
|
||||
|
||||
# Run clang-tidy if available
|
||||
if(CLANG_TIDY_BIN)
|
||||
set_target_properties(srslte_upper PROPERTIES CXX_CLANG_TIDY "${DO_CLANG_TIDY}")
|
||||
endif()
|
|
@ -42,6 +42,7 @@ rlc::rlc()
|
|||
mac_timers = NULL;
|
||||
ue = NULL;
|
||||
default_lcid = 0;
|
||||
buffer_size = 0;
|
||||
bzero(metrics_time, sizeof(metrics_time));
|
||||
pthread_rwlock_init(&rwlock, NULL);
|
||||
}
|
||||
|
@ -123,8 +124,8 @@ void rlc::get_metrics(rlc_metrics_t &m)
|
|||
m.ul_tput_mbps[it->first] = (it->second->get_num_tx_bytes()*8/static_cast<double>(1e6))/secs;
|
||||
rlc_log->info("LCID=%d, RX throughput: %4.6f Mbps. TX throughput: %4.6f Mbps.\n",
|
||||
it->first,
|
||||
(it->second->get_num_rx_bytes()*8/(double)1e6)/secs,
|
||||
(it->second->get_num_tx_bytes()*8/(double)1e6)/secs);
|
||||
(it->second->get_num_rx_bytes()*8/static_cast<double>(1e6))/secs,
|
||||
(it->second->get_num_tx_bytes()*8/static_cast<double>(1e6))/secs);
|
||||
}
|
||||
|
||||
// Add multicast metrics
|
||||
|
@ -279,7 +280,7 @@ uint32_t rlc::get_total_mch_buffer_state(uint32_t lcid)
|
|||
uint32_t ret = 0;
|
||||
|
||||
pthread_rwlock_rdlock(&rwlock);
|
||||
if (valid_lcid(lcid)) {
|
||||
if (valid_lcid_mrb(lcid)) {
|
||||
ret = rlc_array_mrb.at(lcid)->get_total_buffer_state();
|
||||
}
|
||||
pthread_rwlock_unlock(&rwlock);
|
||||
|
@ -305,7 +306,7 @@ int rlc::read_pdu_mch(uint32_t lcid, uint8_t *payload, uint32_t nof_bytes)
|
|||
uint32_t ret = 0;
|
||||
|
||||
pthread_rwlock_rdlock(&rwlock);
|
||||
if (valid_lcid(lcid)) {
|
||||
if (valid_lcid_mrb(lcid)) {
|
||||
ret = rlc_array_mrb.at(lcid)->read_pdu(payload, nof_bytes);
|
||||
}
|
||||
pthread_rwlock_unlock(&rwlock);
|
||||
|
@ -327,7 +328,7 @@ void rlc::write_pdu_bcch_bch(uint8_t *payload, uint32_t nof_bytes)
|
|||
{
|
||||
rlc_log->info_hex(payload, nof_bytes, "BCCH BCH message received.");
|
||||
byte_buffer_t *buf = pool_allocate;
|
||||
if (buf) {
|
||||
if (buf != NULL) {
|
||||
memcpy(buf->msg, payload, nof_bytes);
|
||||
buf->N_bytes = nof_bytes;
|
||||
buf->set_timestamp();
|
||||
|
@ -342,7 +343,7 @@ void rlc::write_pdu_bcch_dlsch(uint8_t *payload, uint32_t nof_bytes)
|
|||
{
|
||||
rlc_log->info_hex(payload, nof_bytes, "BCCH TXSCH message received.");
|
||||
byte_buffer_t *buf = pool_allocate;
|
||||
if (buf) {
|
||||
if (buf != NULL) {
|
||||
memcpy(buf->msg, payload, nof_bytes);
|
||||
buf->N_bytes = nof_bytes;
|
||||
buf->set_timestamp();
|
||||
|
@ -357,7 +358,7 @@ void rlc::write_pdu_pcch(uint8_t *payload, uint32_t nof_bytes)
|
|||
{
|
||||
rlc_log->info_hex(payload, nof_bytes, "PCCH message received.");
|
||||
byte_buffer_t *buf = pool_allocate;
|
||||
if (buf) {
|
||||
if (buf != NULL) {
|
||||
memcpy(buf->msg, payload, nof_bytes);
|
||||
buf->N_bytes = nof_bytes;
|
||||
buf->set_timestamp();
|
||||
|
@ -394,7 +395,7 @@ void rlc::add_bearer(uint32_t lcid)
|
|||
add_bearer(lcid, srslte_rlc_config_t());
|
||||
} else {
|
||||
// SRB1 and SRB2 are AM
|
||||
LIBLTE_RRC_RLC_CONFIG_STRUCT cnfg;
|
||||
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;
|
||||
|
@ -472,10 +473,10 @@ void rlc::add_bearer_mrb(uint32_t lcid)
|
|||
|
||||
if (not valid_lcid_mrb(lcid)) {
|
||||
rlc_entity = new rlc_um();
|
||||
if (rlc_entity) {
|
||||
if (rlc_entity != NULL) {
|
||||
// configure and add to array
|
||||
rlc_entity->init(rlc_log, lcid, pdcp, rrc, mac_timers);
|
||||
if (rlc_entity->configure(srslte_rlc_config_t::mch_config()) == false) {
|
||||
if (not rlc_entity->configure(srslte_rlc_config_t::mch_config())) {
|
||||
rlc_log->error("Error configuring RLC entity\n.");
|
||||
goto delete_and_exit;
|
||||
}
|
||||
|
@ -494,7 +495,7 @@ void rlc::add_bearer_mrb(uint32_t lcid)
|
|||
}
|
||||
|
||||
delete_and_exit:
|
||||
if (rlc_entity) {
|
||||
if (rlc_entity != NULL) {
|
||||
delete(rlc_entity);
|
||||
}
|
||||
|
||||
|
@ -507,7 +508,7 @@ void rlc::del_bearer(uint32_t lcid)
|
|||
{
|
||||
pthread_rwlock_wrlock(&rwlock);
|
||||
|
||||
if (valid_lcid_mrb(lcid)) {
|
||||
if (valid_lcid(lcid)) {
|
||||
rlc_map_t::iterator it = rlc_array.find(lcid);
|
||||
it->second->stop();
|
||||
delete(it->second);
|
||||
|
@ -521,6 +522,24 @@ void rlc::del_bearer(uint32_t lcid)
|
|||
}
|
||||
|
||||
|
||||
void rlc::del_bearer_mrb(uint32_t lcid)
|
||||
{
|
||||
pthread_rwlock_wrlock(&rwlock);
|
||||
|
||||
if (valid_lcid_mrb(lcid)) {
|
||||
rlc_map_t::iterator it = rlc_array_mrb.find(lcid);
|
||||
it->second->stop();
|
||||
delete(it->second);
|
||||
rlc_array_mrb.erase(it);
|
||||
rlc_log->warning("Deleted RLC MRB bearer %s\n", rrc->get_rb_name(lcid).c_str());
|
||||
} else {
|
||||
rlc_log->error("Can't delete bearer %s. Bearer doesn't exist.\n", rrc->get_rb_name(lcid).c_str());
|
||||
}
|
||||
|
||||
pthread_rwlock_unlock(&rwlock);
|
||||
}
|
||||
|
||||
|
||||
void rlc::change_lcid(uint32_t old_lcid, uint32_t new_lcid)
|
||||
{
|
||||
pthread_rwlock_wrlock(&rwlock);
|
||||
|
@ -577,4 +596,4 @@ bool rlc::valid_lcid_mrb(uint32_t lcid)
|
|||
return true;
|
||||
}
|
||||
|
||||
} // namespace srsue
|
||||
} // namespace srslte
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -37,6 +37,7 @@ namespace srslte {
|
|||
rlc_um::rlc_um(uint32_t queue_len)
|
||||
:lcid(0)
|
||||
,tx(queue_len)
|
||||
,pool(byte_buffer_pool::get_instance())
|
||||
,rrc(NULL)
|
||||
,log(NULL)
|
||||
{
|
||||
|
@ -150,6 +151,11 @@ uint32_t rlc_um::get_bearer()
|
|||
***************************************************************************/
|
||||
void rlc_um::write_sdu(byte_buffer_t *sdu, bool blocking)
|
||||
{
|
||||
if (sdu->N_bytes > RLC_UM_MAX_SDU_SIZE) {
|
||||
log->warning("Dropping too long SDU of size %d B (Max. size %d B).", sdu->N_bytes, RLC_UM_MAX_SDU_SIZE);
|
||||
pool->deallocate(sdu);
|
||||
}
|
||||
|
||||
if (blocking) {
|
||||
tx.write_sdu(sdu);
|
||||
} else {
|
||||
|
@ -399,7 +405,7 @@ int rlc_um::rlc_um_tx::build_data_pdu(uint8_t *payload, uint32_t nof_bytes)
|
|||
uint8_t *pdu_ptr = pdu->msg;
|
||||
|
||||
int head_len = rlc_um_packed_length(&header);
|
||||
int pdu_space = nof_bytes;
|
||||
int pdu_space = SRSLTE_MIN(nof_bytes, pdu->get_tailroom());;
|
||||
|
||||
if(pdu_space <= head_len + 1)
|
||||
{
|
||||
|
@ -430,7 +436,7 @@ int rlc_um::rlc_um_tx::build_data_pdu(uint8_t *payload, uint32_t nof_bytes)
|
|||
pool->deallocate(tx_sdu);
|
||||
tx_sdu = NULL;
|
||||
}
|
||||
pdu_space -= to_move;
|
||||
pdu_space -= SRSLTE_MIN(to_move, pdu->get_tailroom());
|
||||
header.fi |= RLC_FI_FIELD_NOT_START_ALIGNED; // First byte does not correspond to first byte of SDU
|
||||
}
|
||||
|
||||
|
@ -474,7 +480,7 @@ int rlc_um::rlc_um_tx::build_data_pdu(uint8_t *payload, uint32_t nof_bytes)
|
|||
memcpy(payload, pdu->msg, pdu->N_bytes);
|
||||
uint32_t ret = pdu->N_bytes;
|
||||
|
||||
log->info("%s Transmitting PDU SN=%d (%d B)\n", get_rb_name(), header.sn, pdu->N_bytes);
|
||||
log->info("%s Tx PDU SN=%d (%d B)\n", get_rb_name(), header.sn, pdu->N_bytes);
|
||||
pool->deallocate(pdu);
|
||||
|
||||
debug_state();
|
||||
|
@ -595,7 +601,7 @@ void rlc_um::rlc_um_rx::handle_data_pdu(uint8_t *payload, uint32_t nof_bytes)
|
|||
|
||||
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", get_rb_name(), header.sn);
|
||||
log->info_hex(payload, nof_bytes, "RX %s Rx data PDU SN: %d (%d B)", get_rb_name(), header.sn, nof_bytes);
|
||||
|
||||
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))
|
||||
|
@ -758,35 +764,29 @@ void rlc_um::rlc_um_rx::reassemble_rx_sdus()
|
|||
// Now update vr_ur until we reach an SN we haven't yet received
|
||||
while(rx_window.end() != rx_window.find(vr_ur)) {
|
||||
log->debug("Reassemble loop for vr_ur=%d\n", vr_ur);
|
||||
if ((vr_ur_in_rx_sdu+1)%cfg.rx_mod != vr_ur) {
|
||||
log->warning("PDU SN=%d lost, dropping remainder of %d\n", vr_ur_in_rx_sdu+1, vr_ur);
|
||||
|
||||
if (not pdu_belongs_to_rx_sdu()) {
|
||||
log->warning("PDU SN=%d lost, stop reassambling SDU (vr_ur_in_rx_sdu=%d)\n", vr_ur_in_rx_sdu+1, vr_ur_in_rx_sdu);
|
||||
pdu_lost = false; // Reset flag to not prevent reassembling of further segments
|
||||
rx_sdu->reset();
|
||||
}
|
||||
|
||||
// Handle any SDU segments
|
||||
for(uint32_t i=0; i<rx_window[vr_ur].header.N_li; i++) {
|
||||
int len = rx_window[vr_ur].header.li[i];
|
||||
log->debug("Handling SDU egment i=%d with len=%d of vr_ur=%d N_li=%d [%s]\n", i, len, vr_ur, rx_window[vr_ur].header.N_li, rlc_fi_field_text[rx_window[vr_ur].header.fi]);
|
||||
// Check if the first part of the PDU is a middle or end segment
|
||||
if (rx_sdu->N_bytes == 0 && i == 0 && !rlc_um_start_aligned(rx_window[vr_ur].header.fi)) {
|
||||
log->warning_hex(rx_window[vr_ur].buf->msg, len, "Dropping first part of SN %d due to lost start segment\n", vr_ur);
|
||||
log->warning_hex(rx_window[vr_ur].buf->msg, len, "Dropping first %d B of SN %d due to lost start segment\n", len, vr_ur);
|
||||
|
||||
// Advance data pointers and continue with next segment
|
||||
rx_window[vr_ur].buf->msg += len;
|
||||
rx_window[vr_ur].buf->N_bytes -= len;
|
||||
rx_sdu->reset();
|
||||
|
||||
// beginning of next SDU?
|
||||
if (rx_window[vr_ur].header.fi == RLC_FI_FIELD_NOT_START_OR_END_ALIGNED) {
|
||||
len = rx_window[vr_ur].buf->N_bytes;
|
||||
log->info_hex(rx_window[vr_ur].buf->msg, len, "Copying first %d bytes of new SDU\n", len);
|
||||
memcpy(rx_sdu->msg, rx_window[vr_ur].buf->msg, len);
|
||||
rx_sdu->N_bytes = len;
|
||||
rx_window[vr_ur].buf->msg += len;
|
||||
rx_window[vr_ur].buf->N_bytes -= len;
|
||||
log->info("Updating vr_ur_in_rx_sdu. old=%d, new=%d\n", vr_ur_in_rx_sdu, vr_ur);
|
||||
vr_ur_in_rx_sdu = vr_ur;
|
||||
goto clean_up_rx_window;
|
||||
}
|
||||
// Reset flag, it is safe to process all remaining segments of this PDU
|
||||
pdu_lost = false;
|
||||
continue;
|
||||
}
|
||||
|
||||
// Check available space in SDU
|
||||
|
@ -796,16 +796,22 @@ void rlc_um::rlc_um_rx::reassemble_rx_sdus()
|
|||
goto clean_up_rx_window;
|
||||
}
|
||||
|
||||
log->info_hex(rx_window[vr_ur].buf->msg, len, "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, cfg.rx_mod, (vr_ur_in_rx_sdu+1)%cfg.rx_mod);
|
||||
if (not pdu_belongs_to_rx_sdu()) {
|
||||
log->info_hex(rx_window[vr_ur].buf->msg, len, "Copying first %d bytes of new SDU\n", len);
|
||||
log->info("Updating vr_ur_in_rx_sdu. old=%d, new=%d\n", vr_ur_in_rx_sdu, vr_ur);
|
||||
vr_ur_in_rx_sdu = vr_ur;
|
||||
} else {
|
||||
log->info_hex(rx_window[vr_ur].buf->msg, len, "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, cfg.rx_mod, (vr_ur_in_rx_sdu+1)%cfg.rx_mod);
|
||||
}
|
||||
|
||||
memcpy(&rx_sdu->msg[rx_sdu->N_bytes], rx_window[vr_ur].buf->msg, len);
|
||||
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)%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 {
|
||||
vr_ur_in_rx_sdu = vr_ur;
|
||||
|
||||
if (not pdu_lost && pdu_belongs_to_rx_sdu()) {
|
||||
log->info_hex(rx_sdu->msg, rx_sdu->N_bytes, "%s Rx SDU vr_ur=%d, i=%d, (update vr_ur middle segments)", get_rb_name(), vr_ur, i);
|
||||
rx_sdu->set_timestamp();
|
||||
if(cfg.is_mrb){
|
||||
|
@ -818,6 +824,11 @@ void rlc_um::rlc_um_rx::reassemble_rx_sdus()
|
|||
log->error("Fatal Error: Couldn't allocate buffer in rlc_um::reassemble_rx_sdus().\n");
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
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);
|
||||
// Advance data pointers and continue with next segment
|
||||
rx_window[vr_ur].buf->msg += len;
|
||||
rx_window[vr_ur].buf->N_bytes -= len;
|
||||
}
|
||||
pdu_lost = false;
|
||||
}
|
||||
|
@ -833,8 +844,8 @@ void rlc_um::rlc_um_rx::reassemble_rx_sdus()
|
|||
rx_window[vr_ur].buf->N_bytes < SRSLTE_MAX_BUFFER_SIZE_BYTES &&
|
||||
rx_window[vr_ur].buf->N_bytes + rx_sdu->N_bytes < SRSLTE_MAX_BUFFER_SIZE_BYTES)
|
||||
{
|
||||
log->info_hex(rx_window[vr_ur].buf->msg, rx_window[vr_ur].buf->N_bytes, "Writing last segment in SDU buffer. Updating vr_ur=%d, Buffer size=%d, segment size=%d\n",
|
||||
vr_ur, rx_sdu->N_bytes, rx_window[vr_ur].buf->N_bytes);
|
||||
log->info_hex(rx_window[vr_ur].buf->msg, rx_window[vr_ur].buf->N_bytes, "Writing last segment in SDU buffer. Updating vr_ur=%d, vr_ur_in_rx_sdu=%d, Buffer size=%d, segment size=%d\n",
|
||||
vr_ur, vr_ur_in_rx_sdu, rx_sdu->N_bytes, rx_window[vr_ur].buf->N_bytes);
|
||||
memcpy(&rx_sdu->msg[rx_sdu->N_bytes], rx_window[vr_ur].buf->msg, rx_window[vr_ur].buf->N_bytes);
|
||||
rx_sdu->N_bytes += rx_window[vr_ur].buf->N_bytes;
|
||||
} else {
|
||||
|
@ -872,6 +883,18 @@ clean_up_rx_window:
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
// Only called when lock is hold
|
||||
bool rlc_um::rlc_um_rx::pdu_belongs_to_rx_sdu()
|
||||
{
|
||||
// return true if the currently received SDU
|
||||
if (((vr_ur_in_rx_sdu + 1)%cfg.rx_mod == vr_ur) || (vr_ur == vr_ur_in_rx_sdu)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
// Only called when lock is hold
|
||||
// 36.322 Section 5.1.2.2.1
|
||||
bool rlc_um::rlc_um_rx::inside_reordering_window(uint16_t sn)
|
||||
|
|
|
@ -34,7 +34,12 @@ add_executable(rlc_stress_test rlc_stress_test.cc)
|
|||
target_link_libraries(rlc_stress_test srslte_upper srslte_phy srslte_common ${Boost_LIBRARIES})
|
||||
add_test(rlc_am_stress_test rlc_stress_test --mode=AM --loglevel 1 --sdu_gen_delay 250)
|
||||
add_test(rlc_um_stress_test rlc_stress_test --mode=UM --loglevel 1)
|
||||
add_test(rlc_tm_stress_test rlc_stress_test --mode=TM --loglevel 1 --opp_sdu_ratio=1.0)
|
||||
add_test(rlc_tm_stress_test rlc_stress_test --mode=TM --loglevel 1 --random_opp=false)
|
||||
|
||||
# Run clang-tidy if available
|
||||
if(CLANG_TIDY_BIN)
|
||||
set_target_properties(rlc_stress_test PROPERTIES CXX_CLANG_TIDY "${DO_CLANG_TIDY}")
|
||||
endif()
|
||||
|
||||
add_executable(rlc_um_data_test rlc_um_data_test.cc)
|
||||
target_link_libraries(rlc_um_data_test srslte_upper srslte_phy srslte_common)
|
||||
|
|
|
@ -732,11 +732,11 @@ bool resegment_test_2()
|
|||
// Write the retx PDU to RLC2
|
||||
rlc2.write_pdu(retx1.msg, retx1.N_bytes);
|
||||
|
||||
assert(16 == rlc1.get_buffer_state());
|
||||
assert(18 == rlc1.get_buffer_state());
|
||||
|
||||
// Read the remaining segment
|
||||
byte_buffer_t retx2;
|
||||
retx2.N_bytes = rlc1.read_pdu(retx2.msg, 16); // 6 byte header + 10 data
|
||||
retx2.N_bytes = rlc1.read_pdu(retx2.msg, 18); // 6 byte header + 12 data
|
||||
|
||||
// Write the retx PDU to RLC2
|
||||
rlc2.write_pdu(retx2.msg, retx2.N_bytes);
|
||||
|
@ -867,7 +867,6 @@ bool resegment_test_3()
|
|||
|
||||
bool resegment_test_4()
|
||||
{
|
||||
|
||||
// SDUs: | 10 | 10 | 10 | 10 | 10 |
|
||||
// PDUs: | 5 | 5| 30 | 5 | 5|
|
||||
// Retx PDU segments: | 15 | 15 |
|
||||
|
@ -960,9 +959,11 @@ bool resegment_test_4()
|
|||
// Write the retx PDU to RLC2
|
||||
rlc2.write_pdu(retx1.msg, retx1.N_bytes);
|
||||
|
||||
assert(23 == rlc1.get_buffer_state());
|
||||
|
||||
// Read the remaining segment
|
||||
byte_buffer_t retx2;
|
||||
retx2.N_bytes = rlc1.read_pdu(retx2.msg, 21); // 6 byte header + 15 data
|
||||
retx2.N_bytes = rlc1.read_pdu(retx2.msg, 23); // 6 byte header + 18 data
|
||||
|
||||
// Write the retx PDU to RLC2
|
||||
rlc2.write_pdu(retx2.msg, retx2.N_bytes);
|
||||
|
@ -980,7 +981,6 @@ bool resegment_test_4()
|
|||
|
||||
bool resegment_test_5()
|
||||
{
|
||||
|
||||
// SDUs: | 10 | 10 | 10 | 10 | 10 |
|
||||
// PDUs: |2|3| 40 |3|2|
|
||||
// Retx PDU segments: | 20 | 20 |
|
||||
|
@ -1071,9 +1071,11 @@ bool resegment_test_5()
|
|||
// Write the retx PDU to RLC2
|
||||
rlc2.write_pdu(retx1.msg, retx1.N_bytes);
|
||||
|
||||
assert(31 == rlc1.get_buffer_state());
|
||||
|
||||
// Read the remaining segment
|
||||
byte_buffer_t retx2;
|
||||
retx2.N_bytes = rlc1.read_pdu(retx2.msg, 27); // 7 byte header + 20 data
|
||||
retx2.N_bytes = rlc1.read_pdu(retx2.msg, 34); // 7 byte header + 24 data
|
||||
|
||||
// Write the retx PDU to RLC2
|
||||
rlc2.write_pdu(retx2.msg, retx2.N_bytes);
|
||||
|
@ -1197,11 +1199,11 @@ bool resegment_test_6()
|
|||
// Write the retx PDU to RLC2
|
||||
rlc2.write_pdu(retx1.msg, retx1.N_bytes);
|
||||
|
||||
assert(155 == rlc1.get_buffer_state());
|
||||
assert(159 == rlc1.get_buffer_state());
|
||||
|
||||
// Read the remaining segment
|
||||
byte_buffer_t retx2;
|
||||
len = rlc1.read_pdu(retx2.msg, 157);
|
||||
len = rlc1.read_pdu(retx2.msg, 162);
|
||||
retx2.N_bytes = len;
|
||||
|
||||
// Write the retx PDU to RLC2
|
||||
|
@ -1216,6 +1218,7 @@ bool resegment_test_6()
|
|||
}
|
||||
for(int i=3;i<9;i++)
|
||||
{
|
||||
if (i >= tester.n_sdus) return -1;
|
||||
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;
|
||||
|
@ -1256,8 +1259,6 @@ bool resegment_test_7()
|
|||
rlc_am rlc1;
|
||||
rlc_am rlc2;
|
||||
|
||||
int len;
|
||||
|
||||
log1.set_level(srslte::LOG_LEVEL_DEBUG);
|
||||
log2.set_level(srslte::LOG_LEVEL_DEBUG);
|
||||
|
||||
|
@ -1302,7 +1303,14 @@ bool resegment_test_7()
|
|||
assert(pdu_bufs[i].N_bytes);
|
||||
}
|
||||
|
||||
assert(0 == rlc1.get_buffer_state());
|
||||
// Step timers until poll_retx timeout expires
|
||||
int cnt = 5;
|
||||
while (cnt--) {
|
||||
timers.step_all();
|
||||
}
|
||||
|
||||
// RLC should try to retx a random PDU because it needs to request a status from the receiver
|
||||
assert(0 != rlc1.get_buffer_state());
|
||||
|
||||
// Skip PDU with SN 2
|
||||
for(uint32_t i=0;i<N_PDU_BUFS;i++) {
|
||||
|
@ -1315,17 +1323,18 @@ bool resegment_test_7()
|
|||
}
|
||||
|
||||
// Step timers until reordering timeout expires
|
||||
int cnt = 5;
|
||||
cnt = 5;
|
||||
while (cnt--) {
|
||||
timers.step_all();
|
||||
}
|
||||
|
||||
assert(12 == rlc1.get_buffer_state());
|
||||
// RLC should try to retransmit a random PDU because it needs to re-request a status PDU from the receiver
|
||||
assert(0 != rlc1.get_buffer_state());
|
||||
|
||||
// first round of retx, forcing resegmentation
|
||||
byte_buffer_t retx[4];
|
||||
for (uint32_t i = 0; i < 4; i++) {
|
||||
assert(rlc1.get_buffer_state());
|
||||
assert(0 != rlc1.get_buffer_state());
|
||||
retx[i].N_bytes = rlc1.read_pdu(retx[i].msg, 7);
|
||||
assert(retx[i].N_bytes);
|
||||
|
||||
|
@ -1373,6 +1382,18 @@ bool resegment_test_7()
|
|||
timers.step_all();
|
||||
}
|
||||
|
||||
// Read status PDU from RLC2
|
||||
assert(rlc2.get_buffer_state());
|
||||
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 status again
|
||||
assert(0 == rlc1.get_buffer_state());
|
||||
assert(0 == rlc2.get_buffer_state());
|
||||
|
||||
// Check number of SDUs and their content
|
||||
|
@ -1441,11 +1462,11 @@ bool resegment_test_8()
|
|||
cnfg.ul_am_rlc.t_poll_retx = LIBLTE_RRC_T_POLL_RETRANSMIT_MS5;
|
||||
|
||||
if (not rlc1.configure(&cnfg)) {
|
||||
exit(-1);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (not rlc2.configure(&cnfg)) {
|
||||
exit(-1);
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Push 2 SDUs into RLC1
|
||||
|
@ -1487,7 +1508,8 @@ bool resegment_test_8()
|
|||
timers.step_all();
|
||||
}
|
||||
|
||||
assert(12 == rlc1.get_buffer_state());
|
||||
// what PDU to retransmit is random but it must not be zero
|
||||
assert(0 != rlc1.get_buffer_state());
|
||||
|
||||
// first round of retx, forcing resegmentation
|
||||
byte_buffer_t retx[4];
|
||||
|
|
|
@ -25,7 +25,7 @@
|
|||
*/
|
||||
|
||||
#include <iostream>
|
||||
#include <stdlib.h>
|
||||
#include <cstdlib>
|
||||
#include <pthread.h>
|
||||
#include "srslte/common/log_filter.h"
|
||||
#include "srslte/common/logger_stdout.h"
|
||||
|
@ -34,10 +34,9 @@
|
|||
#include "srslte/upper/rlc.h"
|
||||
#include <boost/program_options.hpp>
|
||||
#include <boost/program_options/parsers.hpp>
|
||||
#include <assert.h>
|
||||
#include <cassert>
|
||||
#include <srslte/upper/rlc_interface.h>
|
||||
|
||||
#define SDU_SIZE (1500)
|
||||
#define LOG_HEX_LIMIT (-1)
|
||||
|
||||
using namespace std;
|
||||
|
@ -47,6 +46,7 @@ namespace bpo = boost::program_options;
|
|||
|
||||
typedef struct {
|
||||
std::string mode;
|
||||
uint32_t sdu_size;
|
||||
uint32_t test_duration_sec;
|
||||
float error_rate;
|
||||
uint32_t sdu_gen_delay_usec;
|
||||
|
@ -55,8 +55,10 @@ typedef struct {
|
|||
uint32_t log_level;
|
||||
bool single_tx;
|
||||
bool write_pcap;
|
||||
float opp_sdu_ratio;
|
||||
uint32_t avg_opp_size;
|
||||
bool random_opp;
|
||||
bool zero_seed;
|
||||
bool pedantic;
|
||||
} stress_test_args_t;
|
||||
|
||||
void parse_args(stress_test_args_t *args, int argc, char *argv[]) {
|
||||
|
@ -73,15 +75,18 @@ void parse_args(stress_test_args_t *args, int argc, char *argv[]) {
|
|||
common.add_options()
|
||||
("mode", bpo::value<std::string>(&args->mode)->default_value("AM"), "Whether to test RLC acknowledged or unacknowledged mode (AM/UM)")
|
||||
("duration", bpo::value<uint32_t>(&args->test_duration_sec)->default_value(5), "Duration (sec)")
|
||||
("sdu_size", bpo::value<uint32_t>(&args->sdu_size)->default_value(1500), "Size of SDUs")
|
||||
("avg_opp_size", bpo::value<uint32_t>(&args->avg_opp_size)->default_value(1505), "Size of the MAC opportunity (if not random)")
|
||||
("random_opp", bpo::value<bool>(&args->random_opp)->default_value(true), "Whether to generate random MAC opportunities")
|
||||
("sdu_gen_delay", bpo::value<uint32_t>(&args->sdu_gen_delay_usec)->default_value(0), "SDU generation delay (usec)")
|
||||
("pdu_tx_delay", bpo::value<uint32_t>(&args->pdu_tx_delay_usec)->default_value(0), "Delay in MAC for transfering PDU from tx'ing RLC to rx'ing RLC (usec)")
|
||||
("error_rate", bpo::value<float>(&args->error_rate)->default_value(0.1), "Rate at which RLC PDUs are dropped")
|
||||
("opp_sdu_ratio", bpo::value<float>(&args->opp_sdu_ratio)->default_value(0.0), "Ratio between MAC opportunity and SDU size (0==random)")
|
||||
("reestablish", bpo::value<bool>(&args->reestablish)->default_value(false), "Mimic RLC reestablish during execution")
|
||||
("loglevel", bpo::value<uint32_t>(&args->log_level)->default_value(srslte::LOG_LEVEL_DEBUG), "Log level (1=Error,2=Warning,3=Info,4=Debug)")
|
||||
("singletx", bpo::value<bool>(&args->single_tx)->default_value(false), "If set to true, only one node is generating data")
|
||||
("pcap", bpo::value<bool>(&args->write_pcap)->default_value(false), "Whether to write all RLC PDU to PCAP file")
|
||||
("zeroseed", bpo::value<bool>(&args->zero_seed)->default_value(false), "Whether to initialize random seed to zero");
|
||||
("zeroseed", bpo::value<bool>(&args->zero_seed)->default_value(false), "Whether to initialize random seed to zero")
|
||||
("pedantic", bpo::value<bool>(&args->pedantic)->default_value(true), "Whether to perform strict SDU size checking at receiver");
|
||||
|
||||
// these options are allowed on the command line
|
||||
bpo::options_description cmdline_options;
|
||||
|
@ -93,7 +98,7 @@ void parse_args(stress_test_args_t *args, int argc, char *argv[]) {
|
|||
bpo::notify(vm);
|
||||
|
||||
// help option was given - print usage and exit
|
||||
if (vm.count("help")) {
|
||||
if (vm.count("help") > 0) {
|
||||
cout << "Usage: " << argv[0] << " [OPTIONS] config_file" << endl << endl;
|
||||
cout << common << endl << general << endl;
|
||||
exit(0);
|
||||
|
@ -110,19 +115,17 @@ class mac_dummy
|
|||
,public thread
|
||||
{
|
||||
public:
|
||||
mac_dummy(rlc_interface_mac *rlc1_, rlc_interface_mac *rlc2_, float fail_rate_, float opp_sdu_ratio_, int32_t pdu_tx_delay_usec_, uint32_t lcid_, rlc_pcap* pcap_ = NULL)
|
||||
mac_dummy(rlc_interface_mac *rlc1_, rlc_interface_mac *rlc2_, stress_test_args_t args_, uint32_t lcid_, rlc_pcap* pcap_ = NULL)
|
||||
:timers(8)
|
||||
,run_enable(true)
|
||||
,rlc1(rlc1_)
|
||||
,rlc2(rlc2_)
|
||||
,fail_rate(fail_rate_)
|
||||
,opp_sdu_ratio(opp_sdu_ratio_)
|
||||
,pdu_tx_delay_usec(pdu_tx_delay_usec_)
|
||||
,args(args_)
|
||||
,pcap(pcap_)
|
||||
,lcid(lcid_)
|
||||
,log("MAC ")
|
||||
{
|
||||
log.set_level(srslte::LOG_LEVEL_ERROR);
|
||||
log.set_level(static_cast<LOG_LEVEL_ENUM>(args.log_level));
|
||||
log.set_hex_limit(LOG_HEX_LIMIT);
|
||||
}
|
||||
|
||||
|
@ -155,14 +158,19 @@ private:
|
|||
exit(-1);
|
||||
}
|
||||
|
||||
float r = opp_sdu_ratio ? opp_sdu_ratio : (float)rand()/RAND_MAX;
|
||||
int opp_size = r*SDU_SIZE;
|
||||
float factor = 1.0;
|
||||
if (args.random_opp) {
|
||||
factor = 0.5 + static_cast<float>(rand())/RAND_MAX;
|
||||
}
|
||||
int opp_size = args.avg_opp_size * factor;
|
||||
uint32_t buf_state = tx_rlc->get_buffer_state(lcid);
|
||||
if (buf_state) {
|
||||
if (buf_state > 0) {
|
||||
int read = tx_rlc->read_pdu(lcid, pdu->msg, opp_size);
|
||||
pdu->N_bytes = read;
|
||||
if (pdu_tx_delay_usec) usleep(pdu_tx_delay_usec);
|
||||
if(((float)rand()/RAND_MAX > fail_rate) && read>0) {
|
||||
if (args.pdu_tx_delay_usec > 0) {
|
||||
usleep(args.pdu_tx_delay_usec);
|
||||
}
|
||||
if(((float)rand()/RAND_MAX > args.error_rate) && read>0) {
|
||||
rx_rlc->write_pdu(lcid, pdu->msg, pdu->N_bytes);
|
||||
if (is_dl) {
|
||||
pcap->write_dl_am_ccch(pdu->msg, pdu->N_bytes);
|
||||
|
@ -170,7 +178,7 @@ private:
|
|||
pcap->write_ul_am_ccch(pdu->msg, pdu->N_bytes);
|
||||
}
|
||||
} else {
|
||||
log.info_hex(pdu->msg, pdu->N_bytes, "Dropping RLC PDU (%d B)\n", pdu->N_bytes);
|
||||
log.warning_hex(pdu->msg, pdu->N_bytes, "Dropping RLC PDU (%d B)\n", pdu->N_bytes);
|
||||
}
|
||||
}
|
||||
byte_buffer_pool::get_instance()->deallocate(pdu);
|
||||
|
@ -194,9 +202,7 @@ private:
|
|||
rlc_interface_mac *rlc2;
|
||||
srslte::timers timers;
|
||||
bool run_enable;
|
||||
float fail_rate;
|
||||
float opp_sdu_ratio;
|
||||
uint32_t pdu_tx_delay_usec;
|
||||
stress_test_args_t args;
|
||||
rlc_pcap *pcap;
|
||||
uint32_t lcid;
|
||||
srslte::log_filter log;
|
||||
|
@ -209,13 +215,17 @@ class rlc_tester
|
|||
,public thread
|
||||
{
|
||||
public:
|
||||
rlc_tester(rlc_interface_pdcp *rlc_, std::string name_, uint32_t sdu_gen_delay_usec_, uint32_t lcid_){
|
||||
rlc = rlc_;
|
||||
run_enable = true;
|
||||
rx_pdus = 0;
|
||||
name = name_;
|
||||
sdu_gen_delay_usec = sdu_gen_delay_usec_;
|
||||
lcid = lcid_;
|
||||
rlc_tester(rlc_interface_pdcp *rlc_, std::string name_, stress_test_args_t args_, uint32_t lcid_)
|
||||
:log("Testr")
|
||||
,rlc(rlc_)
|
||||
,run_enable(true)
|
||||
,rx_pdus()
|
||||
,name(name_)
|
||||
,args(args_)
|
||||
,lcid(lcid_)
|
||||
{
|
||||
log.set_level(srslte::LOG_LEVEL_ERROR);
|
||||
log.set_hex_limit(LOG_HEX_LIMIT);
|
||||
}
|
||||
|
||||
void stop()
|
||||
|
@ -228,13 +238,14 @@ public:
|
|||
void write_pdu(uint32_t rx_lcid, byte_buffer_t *sdu)
|
||||
{
|
||||
assert(rx_lcid == lcid);
|
||||
if (sdu->N_bytes != SDU_SIZE) {
|
||||
srslte::log_filter log1("Testr");;
|
||||
log1.set_level(srslte::LOG_LEVEL_ERROR);
|
||||
log1.set_hex_limit(sdu->N_bytes);
|
||||
log1.error_hex(sdu->msg, sdu->N_bytes, "Received PDU with size %d, expected %d. Exiting.\n", sdu->N_bytes, SDU_SIZE);
|
||||
exit(-1);
|
||||
if (sdu->N_bytes != args.sdu_size) {
|
||||
log.error_hex(sdu->msg, sdu->N_bytes, "Received SDU with size %d, expected %d.\n", sdu->N_bytes, args.sdu_size);
|
||||
// exit if in pedantic mode or SDU is not a multiple of the expected size
|
||||
if (args.pedantic || sdu->N_bytes % args.sdu_size != 0) {
|
||||
exit(-1);
|
||||
}
|
||||
}
|
||||
|
||||
byte_buffer_pool::get_instance()->deallocate(sdu);
|
||||
rx_pdus++;
|
||||
}
|
||||
|
@ -254,29 +265,32 @@ private:
|
|||
uint8_t sn = 0;
|
||||
while(run_enable) {
|
||||
byte_buffer_t *pdu = byte_buffer_pool::get_instance()->allocate("rlc_tester::run_thread");
|
||||
if (!pdu) {
|
||||
if (pdu == NULL) {
|
||||
printf("Error: Could not allocate PDU in rlc_tester::run_thread\n\n\n");
|
||||
// backoff for a bit
|
||||
usleep(1000);
|
||||
continue;
|
||||
}
|
||||
for (uint32_t i = 0; i < SDU_SIZE; i++) {
|
||||
for (uint32_t i = 0; i < args.sdu_size; i++) {
|
||||
pdu->msg[i] = sn;
|
||||
}
|
||||
sn++;
|
||||
pdu->N_bytes = SDU_SIZE;
|
||||
pdu->N_bytes = args.sdu_size;
|
||||
rlc->write_sdu(lcid, pdu);
|
||||
if (sdu_gen_delay_usec) usleep(sdu_gen_delay_usec);
|
||||
if (args.sdu_gen_delay_usec > 0) {
|
||||
usleep(args.sdu_gen_delay_usec);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool run_enable;
|
||||
long rx_pdus;
|
||||
uint64_t rx_pdus;
|
||||
uint32_t lcid;
|
||||
srslte::log_filter log;
|
||||
|
||||
std::string name;
|
||||
|
||||
uint32_t sdu_gen_delay_usec;
|
||||
stress_test_args_t args;
|
||||
|
||||
rlc_interface_pdcp *rlc;
|
||||
};
|
||||
|
@ -285,8 +299,8 @@ void stress_test(stress_test_args_t args)
|
|||
{
|
||||
srslte::log_filter log1("RLC_1");
|
||||
srslte::log_filter log2("RLC_2");
|
||||
log1.set_level((LOG_LEVEL_ENUM)args.log_level);
|
||||
log2.set_level((LOG_LEVEL_ENUM)args.log_level);
|
||||
log1.set_level(static_cast<LOG_LEVEL_ENUM>(args.log_level));
|
||||
log2.set_level(static_cast<LOG_LEVEL_ENUM>(args.log_level));
|
||||
log1.set_hex_limit(LOG_HEX_LIMIT);
|
||||
log2.set_hex_limit(LOG_HEX_LIMIT);
|
||||
rlc_pcap pcap;
|
||||
|
@ -326,9 +340,9 @@ void stress_test(stress_test_args_t args)
|
|||
rlc rlc1;
|
||||
rlc rlc2;
|
||||
|
||||
rlc_tester tester1(&rlc1, "tester1", args.sdu_gen_delay_usec, lcid);
|
||||
rlc_tester tester2(&rlc2, "tester2", args.sdu_gen_delay_usec, lcid);
|
||||
mac_dummy mac(&rlc1, &rlc2, args.error_rate, args.opp_sdu_ratio, args.pdu_tx_delay_usec, lcid, &pcap);
|
||||
rlc_tester tester1(&rlc1, "tester1", args, lcid);
|
||||
rlc_tester tester2(&rlc2, "tester2", args, lcid);
|
||||
mac_dummy mac(&rlc1, &rlc2, args, lcid, &pcap);
|
||||
ue_interface ue;
|
||||
|
||||
rlc1.init(&tester1, &tester1, &ue, &log1, &mac, 0);
|
||||
|
@ -346,6 +360,10 @@ void stress_test(stress_test_args_t args)
|
|||
}
|
||||
mac.start();
|
||||
|
||||
if (args.test_duration_sec < 1) {
|
||||
args.test_duration_sec = 1;
|
||||
}
|
||||
|
||||
for (uint32_t i = 0; i < args.test_duration_sec; i++) {
|
||||
// if enabled, mimic reestablishment every second
|
||||
if (args.reestablish) {
|
||||
|
@ -355,39 +373,47 @@ void stress_test(stress_test_args_t args)
|
|||
usleep(1e6);
|
||||
}
|
||||
|
||||
printf("Test finished, tearing down ..\n");
|
||||
|
||||
// Stop RLC instances first to release blocking writers
|
||||
rlc1.stop();
|
||||
rlc2.stop();
|
||||
|
||||
printf("RLC entities stopped.\n");
|
||||
|
||||
// Stop upper layer writers
|
||||
tester1.stop();
|
||||
tester2.stop();
|
||||
|
||||
printf("Writers stopped.\n");
|
||||
|
||||
mac.stop();
|
||||
if (args.write_pcap) {
|
||||
pcap.close();
|
||||
}
|
||||
|
||||
rlc_metrics_t metrics;
|
||||
rlc_metrics_t metrics = {};
|
||||
rlc1.get_metrics(metrics);
|
||||
|
||||
printf("RLC1 received %d SDUs in %ds (%.2f PDU/s), Throughput: DL=%4.2f Mbps, UL=%4.2f Mbps\n",
|
||||
printf("RLC1 received %d SDUs in %ds (%.2f/s), Throughput: DL=%4.2f Mbps, UL=%4.2f Mbps\n",
|
||||
tester1.get_nof_rx_pdus(),
|
||||
args.test_duration_sec,
|
||||
(float)tester1.get_nof_rx_pdus()/args.test_duration_sec,
|
||||
static_cast<double>(tester1.get_nof_rx_pdus()/args.test_duration_sec),
|
||||
metrics.dl_tput_mbps[lcid],
|
||||
metrics.ul_tput_mbps[lcid]);
|
||||
|
||||
rlc2.get_metrics(metrics);
|
||||
printf("RLC2 received %d SDUs in %ds (%.2f PDU/s), Throughput: DL=%4.2f Mbps, UL=%4.2f Mbps\n",
|
||||
printf("RLC2 received %d SDUs in %ds (%.2f/s), Throughput: DL=%4.2f Mbps, UL=%4.2f Mbps\n",
|
||||
tester2.get_nof_rx_pdus(),
|
||||
args.test_duration_sec,
|
||||
(float)tester2.get_nof_rx_pdus()/args.test_duration_sec,
|
||||
static_cast<double>(tester2.get_nof_rx_pdus()/args.test_duration_sec),
|
||||
metrics.dl_tput_mbps[lcid],
|
||||
metrics.ul_tput_mbps[lcid]);
|
||||
}
|
||||
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
stress_test_args_t args;
|
||||
stress_test_args_t args = {};
|
||||
parse_args(&args, argc, argv);
|
||||
|
||||
if (args.zero_seed) {
|
||||
|
|
|
@ -162,21 +162,3 @@ nof_ctrl_symbols = 3
|
|||
#rrc_inactivity_timer = 60000
|
||||
#max_prach_offset_us = 30
|
||||
#enable_mbsfn = false
|
||||
|
||||
#####################################################################
|
||||
# Manual RF calibration
|
||||
#
|
||||
# Applies DC offset and IQ imbalance to TX and RX modules.
|
||||
# Currently this configuration is only used if the detected device is a bladeRF
|
||||
#
|
||||
# tx_corr_dc_gain: TX DC offset gain correction
|
||||
# tx_corr_dc_phase: TX DC offset phase correction
|
||||
# tx_corr_iq_i: TX IQ imbalance inphase correction
|
||||
# tx_corr_iq_q: TX IQ imbalance quadrature correction
|
||||
# same can be configured for rx_*
|
||||
#####################################################################
|
||||
[rf_calibration]
|
||||
tx_corr_dc_gain = 20
|
||||
tx_corr_dc_phase = 184
|
||||
tx_corr_iq_i = 19
|
||||
tx_corr_iq_q = 97
|
||||
|
|
|
@ -134,7 +134,6 @@ typedef struct {
|
|||
enb_args_t enb;
|
||||
enb_files_t enb_files;
|
||||
rf_args_t rf;
|
||||
rf_cal_t rf_cal;
|
||||
pcap_args_t pcap;
|
||||
log_args_t log;
|
||||
gui_args_t gui;
|
||||
|
@ -142,7 +141,7 @@ typedef struct {
|
|||
}all_args_t;
|
||||
|
||||
/*******************************************************************************
|
||||
Main UE class
|
||||
Main eNB class
|
||||
*******************************************************************************/
|
||||
|
||||
class enb
|
||||
|
@ -213,7 +212,7 @@ private:
|
|||
|
||||
bool check_srslte_version();
|
||||
int parse_sib1(std::string filename, LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_1_STRUCT *data);
|
||||
int parse_sib2(std::string filename, LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_2_STRUCT *data);
|
||||
int parse_sib2(std::string filename, LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_2_STRUCT *data, bool *mbsfn_section_present);
|
||||
int parse_sib3(std::string filename, LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_3_STRUCT *data);
|
||||
int parse_sib4(std::string filename, LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_4_STRUCT *data);
|
||||
int parse_sib9(std::string filename, LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_9_STRUCT *data);
|
||||
|
@ -222,7 +221,11 @@ private:
|
|||
int parse_rr(all_args_t *args, rrc_cfg_t *rrc_cfg);
|
||||
int parse_drb(all_args_t *args, rrc_cfg_t *rrc_cfg);
|
||||
bool sib_is_present(LIBLTE_RRC_SCHEDULING_INFO_STRUCT *sched_info, uint32_t nof_sched_info, LIBLTE_RRC_SIB_TYPE_ENUM sib_num);
|
||||
int parse_cell_cfg(all_args_t *args, srslte_cell_t *cell);
|
||||
int parse_cell_cfg(all_args_t *args, srslte_cell_t *cell);
|
||||
|
||||
std::string get_build_mode();
|
||||
std::string get_build_info();
|
||||
std::string get_build_string();
|
||||
};
|
||||
|
||||
} // namespace srsenb
|
||||
|
|
|
@ -83,9 +83,9 @@ private:
|
|||
const static int MAX_WORKERS = 4;
|
||||
const static int DEFAULT_WORKERS = 2;
|
||||
|
||||
const static int PRACH_WORKER_THREAD_PRIO = 80;
|
||||
const static int PRACH_WORKER_THREAD_PRIO = 3;
|
||||
const static int SF_RECV_THREAD_PRIO = 1;
|
||||
const static int WORKERS_THREAD_PRIO = 0;
|
||||
const static int WORKERS_THREAD_PRIO = 2;
|
||||
|
||||
srslte::radio *radio_handler;
|
||||
srslte::log *log_h;
|
||||
|
|
|
@ -182,39 +182,39 @@ public:
|
|||
bool running;
|
||||
void run_thread();
|
||||
};
|
||||
|
||||
|
||||
class ue
|
||||
{
|
||||
public:
|
||||
ue();
|
||||
public:
|
||||
ue();
|
||||
bool is_connected();
|
||||
bool is_idle();
|
||||
bool is_idle();
|
||||
bool is_timeout();
|
||||
void set_activity();
|
||||
|
||||
uint32_t rl_failure();
|
||||
|
||||
rrc_state_t get_state();
|
||||
|
||||
|
||||
void send_connection_setup(bool is_setup = true);
|
||||
void send_connection_reest();
|
||||
void send_connection_reest();
|
||||
void send_connection_release();
|
||||
void send_connection_reest_rej();
|
||||
void send_connection_reest_rej();
|
||||
void send_connection_reconf(srslte::byte_buffer_t *sdu);
|
||||
void send_connection_reconf_new_bearer(LIBLTE_S1AP_E_RABTOBESETUPLISTBEARERSUREQ_STRUCT *e);
|
||||
void send_connection_reconf_upd(srslte::byte_buffer_t *pdu);
|
||||
void send_connection_reconf_upd(srslte::byte_buffer_t *pdu);
|
||||
void send_security_mode_command();
|
||||
void send_ue_cap_enquiry();
|
||||
void parse_ul_dcch(uint32_t lcid, srslte::byte_buffer_t* pdu);
|
||||
|
||||
void handle_rrc_con_req(LIBLTE_RRC_CONNECTION_REQUEST_STRUCT *msg);
|
||||
void handle_rrc_con_reest_req(LIBLTE_RRC_CONNECTION_REESTABLISHMENT_REQUEST_STRUCT *msg);
|
||||
void handle_rrc_con_reest_req(LIBLTE_RRC_CONNECTION_REESTABLISHMENT_REQUEST_STRUCT *msg);
|
||||
void handle_rrc_con_setup_complete(LIBLTE_RRC_CONNECTION_SETUP_COMPLETE_STRUCT *msg, srslte::byte_buffer_t *pdu);
|
||||
void handle_rrc_reconf_complete(LIBLTE_RRC_CONNECTION_RECONFIGURATION_COMPLETE_STRUCT *msg, srslte::byte_buffer_t *pdu);
|
||||
void handle_security_mode_complete(LIBLTE_RRC_SECURITY_MODE_COMPLETE_STRUCT *msg);
|
||||
void handle_security_mode_failure(LIBLTE_RRC_SECURITY_MODE_FAILURE_STRUCT *msg);
|
||||
void handle_ue_cap_info(LIBLTE_RRC_UE_CAPABILITY_INFORMATION_STRUCT *msg);
|
||||
|
||||
|
||||
void set_bitrates(LIBLTE_S1AP_UEAGGREGATEMAXIMUMBITRATE_STRUCT *rates);
|
||||
void set_security_capabilities(LIBLTE_S1AP_UESECURITYCAPABILITIES_STRUCT *caps);
|
||||
void set_security_key(uint8_t* key, uint32_t length);
|
||||
|
@ -229,26 +229,26 @@ public:
|
|||
void notify_s1ap_ue_ctxt_setup_complete();
|
||||
void notify_s1ap_ue_erab_setup_response(LIBLTE_S1AP_E_RABTOBESETUPLISTBEARERSUREQ_STRUCT *e);
|
||||
|
||||
int sr_allocate(uint32_t period, uint32_t *I_sr, uint32_t *N_pucch_sr);
|
||||
void sr_get(uint32_t *I_sr, uint32_t *N_pucch_sr);
|
||||
int sr_allocate(uint32_t period, uint32_t *I_sr, uint32_t *N_pucch_sr);
|
||||
void sr_get(uint32_t *I_sr, uint32_t *N_pucch_sr);
|
||||
int sr_free();
|
||||
|
||||
int cqi_allocate(uint32_t period, uint32_t *pmi_idx, uint32_t *n_pucch);
|
||||
void cqi_get(uint32_t *pmi_idx, uint32_t *n_pucch);
|
||||
int cqi_free();
|
||||
|
||||
int cqi_allocate(uint32_t period, uint32_t *pmi_idx, uint32_t *n_pucch);
|
||||
void cqi_get(uint32_t *pmi_idx, uint32_t *n_pucch);
|
||||
int cqi_free();
|
||||
|
||||
void send_dl_ccch(LIBLTE_RRC_DL_CCCH_MSG_STRUCT *dl_ccch_msg);
|
||||
void send_dl_dcch(LIBLTE_RRC_DL_DCCH_MSG_STRUCT *dl_dcch_msg, srslte::byte_buffer_t *pdu = NULL);
|
||||
|
||||
uint16_t rnti;
|
||||
rrc *parent;
|
||||
|
||||
bool connect_notified;
|
||||
|
||||
|
||||
uint16_t rnti;
|
||||
rrc *parent;
|
||||
|
||||
bool connect_notified;
|
||||
|
||||
private:
|
||||
srslte::byte_buffer_pool *pool;
|
||||
|
||||
struct timeval t_last_activity;
|
||||
struct timeval t_last_activity;
|
||||
|
||||
LIBLTE_RRC_CON_REQ_EST_CAUSE_ENUM establishment_cause;
|
||||
|
||||
|
@ -260,10 +260,10 @@ public:
|
|||
uint32_t rlf_cnt;
|
||||
uint8_t transaction_id;
|
||||
rrc_state_t state;
|
||||
|
||||
|
||||
std::map<uint32_t, LIBLTE_RRC_SRB_TO_ADD_MOD_STRUCT> srbs;
|
||||
std::map<uint32_t, LIBLTE_RRC_DRB_TO_ADD_MOD_STRUCT> drbs;
|
||||
|
||||
|
||||
uint8_t k_enb[32]; // Provided by MME
|
||||
uint8_t k_rrc_enc[32];
|
||||
uint8_t k_rrc_int[32];
|
||||
|
@ -290,20 +290,21 @@ public:
|
|||
bool sr_allocated;
|
||||
uint32_t sr_N_pucch;
|
||||
uint32_t sr_I;
|
||||
uint32_t cqi_pucch;
|
||||
uint32_t cqi_idx;
|
||||
bool cqi_allocated;
|
||||
int cqi_sched_sf_idx;
|
||||
uint32_t cqi_pucch;
|
||||
uint32_t cqi_idx;
|
||||
bool cqi_allocated;
|
||||
int cqi_sched_sf_idx;
|
||||
int cqi_sched_prb_idx;
|
||||
int get_drbid_config(LIBLTE_RRC_DRB_TO_ADD_MOD_STRUCT *drb, int drbid);
|
||||
bool nas_pending;
|
||||
srslte::byte_buffer_t erab_info;
|
||||
};
|
||||
|
||||
|
||||
private:
|
||||
|
||||
};
|
||||
|
||||
|
||||
private:
|
||||
|
||||
std::map<uint16_t,ue> users;
|
||||
|
||||
|
||||
std::map<uint32_t, LIBLTE_S1AP_UEPAGINGID_STRUCT > pending_paging;
|
||||
|
||||
activity_monitor act_monitor;
|
||||
|
@ -362,7 +363,8 @@ private:
|
|||
typedef struct {
|
||||
uint32_t nof_users[100][80];
|
||||
} sr_sched_t;
|
||||
|
||||
|
||||
|
||||
sr_sched_t sr_sched;
|
||||
sr_sched_t cqi_sched;
|
||||
LIBLTE_RRC_MCCH_MSG_STRUCT mcch;
|
||||
|
|
|
@ -111,17 +111,6 @@ sib2 =
|
|||
additional_spectrum_emission = 1;
|
||||
};
|
||||
|
||||
mbsfnSubframeConfigList =
|
||||
{
|
||||
radioframeAllocationPeriod = "1";
|
||||
subframeAllocationNumFrames = "1";
|
||||
radioframeAllocationOffset = 0;
|
||||
subframeAllocation = 63;
|
||||
|
||||
};
|
||||
|
||||
mbsfnSubframeConfigListLength = 0;
|
||||
|
||||
time_alignment_timer = "INFINITY"; // use "sf500", "sf750", etc.
|
||||
};
|
||||
|
||||
|
|
|
@ -46,8 +46,8 @@ sib2 =
|
|||
{
|
||||
high_speed_flag = false;
|
||||
prach_config_index = 3;
|
||||
prach_freq_offset = 0;
|
||||
zero_correlation_zone_config = 11;
|
||||
prach_freq_offset = 2;
|
||||
zero_correlation_zone_config = 5;
|
||||
};
|
||||
};
|
||||
pdsch_cnfg =
|
||||
|
@ -111,8 +111,6 @@ sib2 =
|
|||
additional_spectrum_emission = 1;
|
||||
};
|
||||
|
||||
|
||||
|
||||
mbsfnSubframeConfigList =
|
||||
{
|
||||
radioframeAllocationPeriod = "1";
|
||||
|
@ -122,8 +120,6 @@ sib2 =
|
|||
|
||||
};
|
||||
|
||||
mbsfnSubframeConfigListLength = 1;
|
||||
|
||||
time_alignment_timer = "INFINITY"; // use "sf500", "sf750", etc.
|
||||
};
|
||||
|
||||
|
|
|
@ -26,6 +26,9 @@
|
|||
|
||||
#include <boost/algorithm/string.hpp>
|
||||
#include "srsenb/hdr/enb.h"
|
||||
#include "srslte/build_info.h"
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
|
||||
namespace srsenb {
|
||||
|
||||
|
@ -54,6 +57,9 @@ void enb::cleanup(void)
|
|||
}
|
||||
|
||||
enb::enb() : started(false) {
|
||||
// print build info
|
||||
std::cout << std::endl << get_build_string() << std::endl;
|
||||
|
||||
srslte_dft_load();
|
||||
pool = srslte::byte_buffer_pool::get_instance(ENB_POOL_SIZE);
|
||||
|
||||
|
@ -159,8 +165,6 @@ bool enb::init(all_args_t *args_)
|
|||
if (args->rf.burst_preamble.compare("auto")) {
|
||||
radio.set_burst_preamble(atof(args->rf.burst_preamble.c_str()));
|
||||
}
|
||||
|
||||
radio.set_manual_calibration(&args->rf_cal);
|
||||
|
||||
radio.set_rx_gain(args->rf.rx_gain);
|
||||
radio.set_tx_gain(args->rf.tx_gain);
|
||||
|
@ -342,4 +346,24 @@ srslte::LOG_LEVEL_ENUM enb::level(std::string l)
|
|||
}
|
||||
}
|
||||
|
||||
std::string enb::get_build_mode()
|
||||
{
|
||||
return std::string(srslte_get_build_mode());
|
||||
}
|
||||
|
||||
std::string enb::get_build_info()
|
||||
{
|
||||
if (std::string(srslte_get_build_info()) == "") {
|
||||
return std::string(srslte_get_version());
|
||||
}
|
||||
return std::string(srslte_get_build_info());
|
||||
}
|
||||
|
||||
std::string enb::get_build_string()
|
||||
{
|
||||
std::stringstream ss;
|
||||
ss << "Built in " << get_build_mode() << " mode using " << get_build_info() << "." << std::endl;
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
} // namespace srsenb
|
||||
|
|
|
@ -201,7 +201,7 @@ int enb::parse_sib1(std::string filename, LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_1_STRUC
|
|||
return parser::parse_section(filename, &sib1);
|
||||
}
|
||||
|
||||
int enb::parse_sib2(std::string filename, LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_2_STRUCT *data)
|
||||
int enb::parse_sib2(std::string filename, LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_2_STRUCT *data, bool *mbsfn_section_present)
|
||||
{
|
||||
parser::section sib2("sib2");
|
||||
|
||||
|
@ -214,12 +214,7 @@ int enb::parse_sib2(std::string filename, LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_2_STRUC
|
|||
parser::section mbsfnSubframeConfigList("mbsfnSubframeConfigList");
|
||||
sib2.add_subsection(&mbsfnSubframeConfigList);
|
||||
|
||||
bool mbsfn_present=false;
|
||||
mbsfnSubframeConfigList.set_optional(&mbsfn_present);
|
||||
|
||||
if (mbsfn_present) {
|
||||
data->mbsfn_subfr_cnfg_list_size = 1;
|
||||
}
|
||||
mbsfnSubframeConfigList.set_optional(mbsfn_section_present);
|
||||
|
||||
mbsfnSubframeConfigList.add_field(
|
||||
new parser::field<uint32>
|
||||
|
@ -876,11 +871,12 @@ int enb::parse_sibs(all_args_t *args, rrc_cfg_t *rrc_cfg, phy_cfg_t *phy_config_
|
|||
|
||||
// Generate SIB2
|
||||
bzero(sib2, sizeof(LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_2_STRUCT));
|
||||
if (parse_sib2(args->enb_files.sib_config, sib2)) {
|
||||
bool mbsfn_section_present = false;
|
||||
if (parse_sib2(args->enb_files.sib_config, sib2, &mbsfn_section_present)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
// SRS not yet supported
|
||||
// SRS not yet supported
|
||||
sib2->rr_config_common_sib.srs_ul_cnfg.present = false;
|
||||
if (sib2->ul_bw.present) {
|
||||
switch(args->enb.n_prb) {
|
||||
|
@ -907,8 +903,13 @@ int enb::parse_sibs(all_args_t *args, rrc_cfg_t *rrc_cfg, phy_cfg_t *phy_config_
|
|||
if (sib2->arfcn_value_eutra.present) {
|
||||
sib2->arfcn_value_eutra.value = args->rf.ul_earfcn;
|
||||
}
|
||||
|
||||
// Generate SIB3 if defined in mapping info
|
||||
|
||||
// Update MBSFN list counter. Only 1 supported
|
||||
if (mbsfn_section_present && args->expert.enable_mbsfn) {
|
||||
sib2->mbsfn_subfr_cnfg_list_size = 1;
|
||||
}
|
||||
|
||||
// Generate SIB3 if defined in mapping info
|
||||
if (sib_is_present(sib1->sched_info, sib1->N_sched_info, LIBLTE_RRC_SIB_TYPE_3)) {
|
||||
bzero(sib3, sizeof(LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_3_STRUCT));
|
||||
if (parse_sib3(args->enb_files.sib_config, sib3)) {
|
||||
|
|
|
@ -199,12 +199,6 @@ void parse_args(all_args_t *args, int argc, char* argv[]) {
|
|||
("expert.print_buffer_state",
|
||||
bpo::value<bool>(&args->expert.print_buffer_state)->default_value(false),
|
||||
"Prints on the console the buffer state every 10 seconds")
|
||||
|
||||
("rf_calibration.tx_corr_dc_gain", bpo::value<float>(&args->rf_cal.tx_corr_dc_gain)->default_value(0.0), "TX DC offset gain correction")
|
||||
("rf_calibration.tx_corr_dc_phase", bpo::value<float>(&args->rf_cal.tx_corr_dc_phase)->default_value(0.0), "TX DC offset phase correction")
|
||||
("rf_calibration.tx_corr_iq_i", bpo::value<float>(&args->rf_cal.tx_corr_iq_i)->default_value(0.0), "TX IQ imbalance inphase correction")
|
||||
("rf_calibration.tx_corr_iq_q", bpo::value<float>(&args->rf_cal.tx_corr_iq_q)->default_value(0.0), "TX IQ imbalance quadrature correction")
|
||||
|
||||
;
|
||||
|
||||
// Positional options - config file location
|
||||
|
|
|
@ -885,24 +885,25 @@ void rrc::activity_monitor::run_thread()
|
|||
*******************************************************************************/
|
||||
rrc::ue::ue()
|
||||
{
|
||||
parent = NULL;
|
||||
parent = NULL;
|
||||
set_activity();
|
||||
has_tmsi = false;
|
||||
connect_notified = false;
|
||||
transaction_id = 0;
|
||||
sr_allocated = false;
|
||||
sr_sched_sf_idx = 0;
|
||||
sr_sched_prb_idx = 0;
|
||||
sr_N_pucch = 0;
|
||||
sr_I = 0;
|
||||
cqi_allocated = false;
|
||||
cqi_pucch = 0;
|
||||
cqi_idx = 0;
|
||||
cqi_sched_sf_idx = 0;
|
||||
has_tmsi = false;
|
||||
connect_notified = false;
|
||||
transaction_id = 0;
|
||||
sr_allocated = false;
|
||||
sr_sched_sf_idx = 0;
|
||||
sr_sched_prb_idx = 0;
|
||||
sr_N_pucch = 0;
|
||||
sr_I = 0;
|
||||
cqi_allocated = false;
|
||||
cqi_pucch = 0;
|
||||
cqi_idx = 0;
|
||||
cqi_sched_sf_idx = 0;
|
||||
cqi_sched_prb_idx = 0;
|
||||
rlf_cnt = 0;
|
||||
state = RRC_STATE_IDLE;
|
||||
pool = srslte::byte_buffer_pool::get_instance();
|
||||
rlf_cnt = 0;
|
||||
nas_pending = false;
|
||||
state = RRC_STATE_IDLE;
|
||||
pool = srslte::byte_buffer_pool::get_instance();
|
||||
}
|
||||
|
||||
rrc_state_t rrc::ue::get_state()
|
||||
|
@ -1227,9 +1228,12 @@ void rrc::ue::setup_erab(uint8_t id, LIBLTE_S1AP_E_RABLEVELQOSPARAMETERS_STRUCT
|
|||
parent->gtpu->add_bearer(rnti, lcid, addr_, erabs[id].teid_out, &(erabs[id].teid_in));
|
||||
|
||||
if(nas_pdu) {
|
||||
nas_pending = true;
|
||||
memcpy(erab_info.buffer, nas_pdu->buffer, nas_pdu->n_octets);
|
||||
erab_info.N_bytes = nas_pdu->n_octets;
|
||||
parent->rrc_log->info_hex(erab_info.buffer, erab_info.N_bytes, "setup_erab nas_pdu -> erab_info rnti 0x%x", rnti);
|
||||
} else {
|
||||
nas_pending = false;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1666,18 +1670,23 @@ void rrc::ue::send_connection_reconf(srslte::byte_buffer_t *pdu)
|
|||
|
||||
// DRB1 has already been configured in GTPU through bearer setup
|
||||
|
||||
// Add NAS Attach accept
|
||||
conn_reconf->N_ded_info_nas = 1;
|
||||
// Add NAS Attach accept
|
||||
if(nas_pending){
|
||||
parent->rrc_log->debug("Adding NAS message to connection reconfiguration\n");
|
||||
conn_reconf->N_ded_info_nas = 1;
|
||||
|
||||
parent->rrc_log->info_hex(erab_info.buffer, erab_info.N_bytes, "connection_reconf erab_info -> nas_info rnti 0x%x\n", rnti);
|
||||
conn_reconf->ded_info_nas_list[0].N_bytes = erab_info.N_bytes;
|
||||
memcpy(conn_reconf->ded_info_nas_list[0].msg, erab_info.buffer, erab_info.N_bytes);
|
||||
|
||||
parent->rrc_log->info_hex(erab_info.buffer, erab_info.N_bytes, "connection_reconf erab_info -> nas_info rnti 0x%x\n", rnti);
|
||||
conn_reconf->ded_info_nas_list[0].N_bytes = erab_info.N_bytes;
|
||||
memcpy(conn_reconf->ded_info_nas_list[0].msg, erab_info.buffer, erab_info.N_bytes);
|
||||
} else {
|
||||
parent->rrc_log->debug("Not adding NAS message to connection reconfiguration\n");
|
||||
conn_reconf->N_ded_info_nas = 0;
|
||||
}
|
||||
// Reuse same PDU
|
||||
pdu->reset();
|
||||
|
||||
|
||||
send_dl_dcch(&dl_dcch_msg, pdu);
|
||||
|
||||
|
||||
state = RRC_STATE_WAIT_FOR_CON_RECONF_COMPLETE;
|
||||
}
|
||||
|
||||
|
|
|
@ -65,7 +65,7 @@ void s1ap_plmn_test()
|
|||
// 3-digit MNC test
|
||||
mnc = 0xF456;
|
||||
srslte::s1ap_mccmnc_to_plmn(mcc, mnc, &plmn);
|
||||
assert(plmn == 0x216354);
|
||||
assert(plmn == 0x214365);
|
||||
srslte::s1ap_plmn_to_mccmnc(plmn, &mcc, &mnc);
|
||||
assert(mcc == 0xF123);
|
||||
assert(mnc == 0xF456);
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
*
|
||||
*/
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include <fstream>
|
||||
#include <errno.h>
|
||||
#include <signal.h>
|
||||
|
@ -30,6 +31,7 @@
|
|||
#include "srslte/common/crash_handler.h"
|
||||
#include "srslte/common/bcd_helpers.h"
|
||||
#include "srslte/common/config_file.h"
|
||||
#include "srslte/build_info.h"
|
||||
#include "srsepc/hdr/mme/mme.h"
|
||||
#include "srsepc/hdr/hss/hss.h"
|
||||
#include "srsepc/hdr/spgw/spgw.h"
|
||||
|
@ -280,6 +282,26 @@ level(std::string l)
|
|||
}
|
||||
}
|
||||
|
||||
std::string get_build_mode()
|
||||
{
|
||||
return std::string(srslte_get_build_mode());
|
||||
}
|
||||
|
||||
std::string get_build_info()
|
||||
{
|
||||
if (std::string(srslte_get_build_info()) == "") {
|
||||
return std::string(srslte_get_version());
|
||||
}
|
||||
return std::string(srslte_get_build_info());
|
||||
}
|
||||
|
||||
std::string get_build_string()
|
||||
{
|
||||
std::stringstream ss;
|
||||
ss << "Built in " << get_build_mode() << " mode using " << get_build_info() << "." << std::endl;
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
int
|
||||
main (int argc,char * argv[] )
|
||||
{
|
||||
|
@ -287,6 +309,9 @@ main (int argc,char * argv[] )
|
|||
signal(SIGTERM, sig_int_handler);
|
||||
signal(SIGKILL, sig_int_handler);
|
||||
|
||||
// print build info
|
||||
cout << endl << get_build_string() << endl;
|
||||
|
||||
cout << endl <<"--- Software Radio Systems EPC ---" << endl << endl;
|
||||
srslte_debug_handle_crash(argc, argv);
|
||||
|
||||
|
|
|
@ -159,7 +159,7 @@ private:
|
|||
const static int DEFAULT_WORKERS = 2;
|
||||
|
||||
const static int SF_RECV_THREAD_PRIO = 1;
|
||||
const static int WORKERS_THREAD_PRIO = 0;
|
||||
const static int WORKERS_THREAD_PRIO = 2;
|
||||
|
||||
srslte::radio_multi *radio_handler;
|
||||
std::vector<srslte::log_filter*> log_vec;
|
||||
|
|
|
@ -122,7 +122,6 @@ typedef struct {
|
|||
|
||||
typedef struct {
|
||||
rf_args_t rf;
|
||||
rf_cal_t rf_cal;
|
||||
pcap_args_t pcap;
|
||||
trace_args_t trace;
|
||||
log_args_t log;
|
||||
|
|
|
@ -41,8 +41,15 @@ bsr_proc::bsr_proc()
|
|||
initiated = false;
|
||||
last_print = 0;
|
||||
next_tx_tti = 0;
|
||||
triggered_bsr_type=NONE;
|
||||
|
||||
triggered_bsr_type=NONE;
|
||||
|
||||
for (int i=0;i<MAX_LCID;i++) {
|
||||
lcg[i] = -1;
|
||||
priorities[i] = -1;
|
||||
last_pending_data[i] = 0;
|
||||
}
|
||||
lcg[0] = 0;
|
||||
priorities[0] = 99;
|
||||
}
|
||||
|
||||
void bsr_proc::init(rlc_interface_mac *rlc_, srslte::log* log_h_, mac_interface_rrc::mac_cfg_t *mac_cfg_, srslte::timers *timers_db_)
|
||||
|
@ -68,15 +75,8 @@ void bsr_proc::reset()
|
|||
|
||||
reset_sr = false;
|
||||
sr_is_sent = false;
|
||||
triggered_bsr_type = NONE;
|
||||
for (int i=0;i<MAX_LCID;i++) {
|
||||
lcg[i] = -1;
|
||||
priorities[i] = -1;
|
||||
last_pending_data[i] = 0;
|
||||
}
|
||||
lcg[0] = 0;
|
||||
priorities[0] = 99;
|
||||
next_tx_tti = 0;
|
||||
triggered_bsr_type = NONE;
|
||||
next_tx_tti = 0;
|
||||
}
|
||||
|
||||
/* Process Periodic BSR */
|
||||
|
|
|
@ -90,13 +90,11 @@ void parse_args(all_args_t *args, int argc, char *argv[]) {
|
|||
("nas.pass", bpo::value<string>(&args->nas.apn_pass)->default_value(""), "Password for CHAP authentication")
|
||||
("nas.force_imsi_attach", bpo::value<bool>(&args->nas.force_imsi_attach)->default_value(false), "Whether to always perform an IMSI attach")
|
||||
|
||||
|
||||
("pcap.enable", bpo::value<bool>(&args->pcap.enable)->default_value(false), "Enable MAC packet captures for wireshark")
|
||||
("pcap.filename", bpo::value<string>(&args->pcap.filename)->default_value("ue.pcap"), "MAC layer capture filename")
|
||||
("pcap.nas_enable", bpo::value<bool>(&args->pcap.nas_enable)->default_value(false), "Enable NAS packet captures for wireshark")
|
||||
("pcap.nas_filename", bpo::value<string>(&args->pcap.nas_filename)->default_value("ue_nas.pcap"), "NAS layer capture filename (useful when NAS encryption is enabled)")
|
||||
|
||||
|
||||
("trace.enable", bpo::value<bool>(&args->trace.enable)->default_value(false), "Enable PHY and radio timing traces")
|
||||
("trace.phy_filename", bpo::value<string>(&args->trace.phy_filename)->default_value("ue.phy_trace"),
|
||||
"PHY timing traces filename")
|
||||
|
@ -123,7 +121,6 @@ void parse_args(all_args_t *args, int argc, char *argv[]) {
|
|||
("log.usim_level", bpo::value<string>(&args->log.usim_level), "USIM log level")
|
||||
("log.usim_hex_limit", bpo::value<int>(&args->log.usim_hex_limit), "USIM log hex dump limit")
|
||||
|
||||
|
||||
("log.all_level", bpo::value<string>(&args->log.all_level)->default_value("info"), "ALL log level")
|
||||
("log.all_hex_limit", bpo::value<int>(&args->log.all_hex_limit)->default_value(32), "ALL log hex dump limit")
|
||||
|
||||
|
@ -309,16 +306,7 @@ void parse_args(all_args_t *args, int argc, char *argv[]) {
|
|||
|
||||
("expert.pdsch_8bit_decoder",
|
||||
bpo::value<bool>(&args->expert.phy.pdsch_8bit_decoder)->default_value(false),
|
||||
"Use 8-bit for LLR representation and turbo decoder trellis computation (Experimental)")
|
||||
|
||||
("rf_calibration.tx_corr_dc_gain", bpo::value<float>(&args->rf_cal.tx_corr_dc_gain)->default_value(0.0),
|
||||
"TX DC offset gain correction")
|
||||
("rf_calibration.tx_corr_dc_phase", bpo::value<float>(&args->rf_cal.tx_corr_dc_phase)->default_value(0.0),
|
||||
"TX DC offset phase correction")
|
||||
("rf_calibration.tx_corr_iq_i", bpo::value<float>(&args->rf_cal.tx_corr_iq_i)->default_value(0.0),
|
||||
"TX IQ imbalance inphase correction")
|
||||
("rf_calibration.tx_corr_iq_q", bpo::value<float>(&args->rf_cal.tx_corr_iq_q)->default_value(0.0),
|
||||
"TX IQ imbalance quadrature correction");
|
||||
"Use 8-bit for LLR representation and turbo decoder trellis computation (Experimental)");
|
||||
|
||||
// Positional options - config file location
|
||||
bpo::options_description position("Positional options");
|
||||
|
|
|
@ -53,6 +53,7 @@ phch_recv::phch_recv() {
|
|||
ul_freq = -1;
|
||||
bzero(&cell, sizeof(srslte_cell_t));
|
||||
bzero(&metrics, sizeof(sync_metrics_t));
|
||||
cellsearch_earfcn_index = 0;
|
||||
running = false;
|
||||
worker_com = NULL;
|
||||
}
|
||||
|
|
|
@ -61,6 +61,7 @@ phch_worker::phch_worker() : tr_exec(10240)
|
|||
chest_loop = NULL;
|
||||
|
||||
bzero(signal_buffer, sizeof(cf_t*)*SRSLTE_MAX_PORTS);
|
||||
ZERO_OBJECT(cell);
|
||||
|
||||
mem_initiated = false;
|
||||
cell_initiated = false;
|
||||
|
@ -1268,6 +1269,22 @@ void phch_worker::encode_pusch(srslte_ra_ul_grant_t *grant, uint8_t *payload, ui
|
|||
char timestr[64];
|
||||
timestr[0]='\0';
|
||||
|
||||
/* Check input values ranges */
|
||||
if (rnti == 0) {
|
||||
Warning("Encode PUSCH: Invalid RNTI (= 0)\n");
|
||||
return;
|
||||
} else if (rv > 3) {
|
||||
Warning("Encode PUSCH: Invalid RV (= %ud)\n", rv);
|
||||
return;
|
||||
} else if (payload == NULL) {
|
||||
Warning("Encode PUSCH: NULL payload\n");
|
||||
return;
|
||||
} else if (softbuffer == NULL) {
|
||||
Warning("Encode PUSCH: NULL softbuffer\n");
|
||||
return;
|
||||
}
|
||||
|
||||
/* Configure and encode */
|
||||
if (srslte_ue_ul_cfg_grant(&ue_ul, grant, TTI_TX(tti), rv, current_tx_nb)) {
|
||||
Error("Configuring UL grant\n");
|
||||
}
|
||||
|
|
|
@ -193,10 +193,7 @@ bool ue::init(all_args_t *args_) {
|
|||
radio.set_continuous_tx(args->rf.continuous_tx.compare("yes")?false:true);
|
||||
}
|
||||
|
||||
radio.set_manual_calibration(&args->rf_cal);
|
||||
|
||||
// Set PHY options
|
||||
|
||||
if (args->rf.tx_gain > 0) {
|
||||
args->expert.phy.ul_pwr_ctrl_en = false;
|
||||
} else {
|
||||
|
|
|
@ -308,30 +308,31 @@ void nas::write_pdu(uint32_t lcid, byte_buffer_t *pdu) {
|
|||
uint8 pd = 0;
|
||||
uint8 msg_type = 0;
|
||||
uint8 sec_hdr_type = 0;
|
||||
bool mac_valid = false;
|
||||
|
||||
nas_log->info_hex(pdu->msg, pdu->N_bytes, "DL %s PDU", rrc->get_rb_name(lcid).c_str());
|
||||
|
||||
// Parse the message security header
|
||||
liblte_mme_parse_msg_sec_header((LIBLTE_BYTE_MSG_STRUCT*)pdu, &pd, &sec_hdr_type);
|
||||
switch(sec_hdr_type)
|
||||
switch (sec_hdr_type)
|
||||
{
|
||||
case LIBLTE_MME_SECURITY_HDR_TYPE_PLAIN_NAS:
|
||||
case LIBLTE_MME_SECURITY_HDR_TYPE_INTEGRITY_WITH_NEW_EPS_SECURITY_CONTEXT:
|
||||
case LIBLTE_MME_SECURITY_HDR_TYPE_SERVICE_REQUEST:
|
||||
break;
|
||||
case LIBLTE_MME_SECURITY_HDR_TYPE_INTEGRITY:
|
||||
break;
|
||||
case LIBLTE_MME_SECURITY_HDR_TYPE_INTEGRITY_AND_CIPHERED:
|
||||
if((mac_valid = integrity_check(pdu))) {
|
||||
if((integrity_check(pdu))) {
|
||||
if (sec_hdr_type == LIBLTE_MME_SECURITY_HDR_TYPE_INTEGRITY_AND_CIPHERED) {
|
||||
cipher_decrypt(pdu);
|
||||
break;
|
||||
} else {
|
||||
nas_log->error("Not handling NAS message with integrity check error\n");
|
||||
pool->deallocate(pdu);
|
||||
return;
|
||||
}
|
||||
case LIBLTE_MME_SECURITY_HDR_TYPE_INTEGRITY_AND_CIPHERED_WITH_NEW_EPS_SECURITY_CONTEXT:
|
||||
break;
|
||||
} else {
|
||||
nas_log->error("Not handling NAS message with integrity check error\n");
|
||||
pool->deallocate(pdu);
|
||||
return;
|
||||
}
|
||||
case LIBLTE_MME_SECURITY_HDR_TYPE_INTEGRITY_AND_CIPHERED_WITH_NEW_EPS_SECURITY_CONTEXT:
|
||||
break;
|
||||
default:
|
||||
nas_log->error("Not handling NAS message with SEC_HDR_TYPE=%02X\n", sec_hdr_type);
|
||||
pool->deallocate(pdu);
|
||||
|
|
|
@ -51,7 +51,7 @@ uint8_t auth_request_pdu[] = { 0x07, 0x52, 0x01, 0x0c, 0x63, 0xa8, 0x54, 0x13, 0
|
|||
uint8_t sec_mode_command_pdu[] = { 0x37, 0x37, 0xc7, 0x67, 0xae, 0x00, 0x07, 0x5d, 0x02, 0x01,
|
||||
0x02, 0xe0, 0x60, 0xc1 };
|
||||
|
||||
uint8_t attach_accept_pdu[] = { 0x27, 0x0f, 0x4f, 0xb3, 0xef, 0x01, 0x07, 0x42, 0x01, 0x3e,
|
||||
uint8_t attach_accept_pdu[] = { 0x27, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x42, 0x01, 0x3e,
|
||||
0x06, 0x00, 0x00, 0xf1, 0x10, 0x00, 0x01, 0x00, 0x2a, 0x52,
|
||||
0x01, 0xc1, 0x01, 0x04, 0x1b, 0x07, 0x74, 0x65, 0x73, 0x74,
|
||||
0x31, 0x32, 0x33, 0x06, 0x6d, 0x6e, 0x63, 0x30, 0x30, 0x31,
|
||||
|
@ -60,7 +60,7 @@ uint8_t attach_accept_pdu[] = { 0x27, 0x0f, 0x4f, 0xb3, 0xef, 0x01, 0x07, 0x42,
|
|||
0x80, 0x50, 0x0b, 0xf6, 0x00, 0xf1, 0x10, 0x80, 0x01, 0x01,
|
||||
0x35, 0x16, 0x6d, 0xbc, 0x64, 0x01, 0x00 };
|
||||
|
||||
uint8_t esm_info_req_pdu[] = { 0x27, 0x1d, 0xbf, 0x7e, 0x05, 0x01, 0x02, 0x5a, 0xd9 };
|
||||
uint8_t esm_info_req_pdu[] = { 0x27, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x5a, 0xd9 };
|
||||
|
||||
uint16 mcc = 61441;
|
||||
uint16 mnc = 65281;
|
||||
|
@ -98,6 +98,7 @@ public:
|
|||
}
|
||||
std::string get_rb_name(uint32_t lcid) { return std::string("lcid"); }
|
||||
uint32_t get_last_sdu_len() { return last_sdu_len; }
|
||||
void reset() { last_sdu_len = 0; }
|
||||
|
||||
int plmn_search(srsue::rrc_interface_nas::found_plmn_t* found) {
|
||||
memcpy(found, &plmns, sizeof(found_plmn_t));
|
||||
|
@ -164,6 +165,7 @@ int security_command_test()
|
|||
|
||||
srsue::nas nas;
|
||||
srslte_nas_config_t cfg;
|
||||
ZERO_OBJECT(cfg);
|
||||
nas.init(&usim, &rrc_dummy, &gw, &nas_log, cfg);
|
||||
|
||||
// push auth request PDU to NAS to generate security context
|
||||
|
@ -218,6 +220,8 @@ int mme_attach_request_test()
|
|||
usim.init(&args, &usim_log);
|
||||
|
||||
srslte_nas_config_t nas_cfg;
|
||||
ZERO_OBJECT(nas_cfg);
|
||||
nas_cfg.force_imsi_attach = true;
|
||||
nas_cfg.apn = "test123";
|
||||
srsue::nas nas;
|
||||
nas.init(&usim, &rrc_dummy, &gw, &nas_log, nas_cfg);
|
||||
|
@ -226,6 +230,9 @@ int mme_attach_request_test()
|
|||
|
||||
// this will time out in the first place
|
||||
|
||||
// reset length of last received NAS PDU
|
||||
rrc_dummy.reset();
|
||||
|
||||
// finally push attach accept
|
||||
byte_buffer_t* tmp = byte_buffer_pool::get_instance()->allocate();
|
||||
memcpy(tmp->msg, attach_accept_pdu, sizeof(attach_accept_pdu));
|
||||
|
@ -278,9 +285,11 @@ int esm_info_request_test()
|
|||
|
||||
srsue::nas nas;
|
||||
srslte_nas_config_t cfg;
|
||||
ZERO_OBJECT(cfg);
|
||||
cfg.apn = "srslte";
|
||||
cfg.user = "srsuser";
|
||||
cfg.pass = "srspass";
|
||||
cfg.force_imsi_attach = true;
|
||||
nas.init(&usim, &rrc_dummy, &gw, &nas_log, cfg);
|
||||
|
||||
// push ESM info request PDU to NAS to generate response
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
# device_args: Arguments for the device driver. Options are "auto" or any string.
|
||||
# Default for UHD: "recv_frame_size=9232,send_frame_size=9232"
|
||||
# Default for bladeRF: ""
|
||||
# #time_adv_nsamples: Transmission time advance (in number of samples) to compensate for RF delay
|
||||
# time_adv_nsamples: Transmission time advance (in number of samples) to compensate for RF delay
|
||||
# from antenna to timestamp insertion.
|
||||
# Default "auto". B210 USRP: 100 samples, bladeRF: 27.
|
||||
# burst_preamble_us: Preamble length to transmit before start of burst.
|
||||
|
@ -249,21 +249,3 @@ enable = false
|
|||
#cfo_loop_pss_tol = 400
|
||||
#cfo_loop_ref_min = 0
|
||||
#cfo_loop_pss_conv = 20
|
||||
|
||||
#####################################################################
|
||||
# Manual RF calibration
|
||||
#
|
||||
# Applies DC offset and IQ imbalance to TX and RX modules.
|
||||
# Currently this configuration is only used if the detected device is a bladeRF
|
||||
#
|
||||
# tx_corr_dc_gain: TX DC offset gain correction
|
||||
# tx_corr_dc_phase: TX DC offset phase correction
|
||||
# tx_corr_iq_i: TX IQ imbalance inphase correction
|
||||
# tx_corr_iq_q: TX IQ imbalance quadrature correction
|
||||
# same can be configured for rx_*
|
||||
#####################################################################
|
||||
[rf_calibration]
|
||||
tx_corr_dc_gain = 20
|
||||
tx_corr_dc_phase = 184
|
||||
tx_corr_iq_i = 19
|
||||
tx_corr_iq_q = 97
|
||||
|
|
Loading…
Reference in New Issue