Improved stability after radio link failure and radio transport error

This commit is contained in:
Ismael Gomez 2017-09-18 18:34:33 +02:00
parent fcbcf1ec7b
commit 4a86967530
9 changed files with 123 additions and 47 deletions

View File

@ -98,6 +98,7 @@ class nas_interface_rrc
{
public:
virtual bool is_attached() = 0;
virtual bool is_attaching() = 0;
virtual void notify_connection_setup() = 0;
virtual void write_pdu(uint32_t lcid, srslte::byte_buffer_t *pdu) = 0;
virtual uint32_t get_ul_count() = 0;
@ -532,6 +533,7 @@ public:
/* Is the PHY downlink synchronized? */
virtual bool sync_status() = 0;
virtual void sync_reset() = 0;
/* Configure UL using parameters written with set_param() */
virtual void configure_ul_params(bool pregen_disabled = false) = 0;

View File

@ -54,7 +54,7 @@ public:
void set_earfcn(std::vector<uint32_t> earfcn);
bool stop_sync();
void reset_sync();
void cell_search_start();
void cell_search_stop();
void cell_search_next(bool reset = false);
@ -73,12 +73,16 @@ private:
std::vector<uint32_t> earfcn;
void reset();
void radio_error();
bool wait_radio_reset();
void set_ue_sync_opts(srslte_ue_sync_t *q);
void run_thread();
void set_sampling_rate();
bool set_frequency();
void resync_sfn();
bool stop_sync();
void cell_search_inc();
@ -89,6 +93,8 @@ private:
void start_rx();
bool radio_is_rx;
bool radio_is_resetting;
bool running;
srslte::radio_multi *radio_h;
@ -152,7 +158,6 @@ private:
float measure_rsrp;
srslte_ue_dl_t ue_dl_measure;
const static int RSRP_MEASURE_NOF_FRAMES = 5;
int cell_sync_sfn();

View File

@ -79,6 +79,7 @@ public:
/********** RRC INTERFACE ********************/
void reset();
void sync_reset();
void configure_ul_params(bool pregen_disabled = false);
void cell_search_start();
void cell_search_stop();

View File

@ -86,6 +86,7 @@ public:
uint32_t get_ul_count();
bool is_attached();
bool is_attaching();
bool get_s_tmsi(LIBLTE_RRC_S_TMSI_STRUCT *s_tmsi);

View File

@ -79,15 +79,7 @@ void phch_recv:: init(srslte::radio_multi *_radio_handler, mac_interface_phy *_
prach_buffer = _prach_buffer;
nof_rx_antennas = nof_rx_antennas_;
tx_mutex_cnt = 0;
running = true;
phy_state = IDLE;
time_adv_sec = 0;
cell_is_set = false;
sync_sfn_cnt = 0;
srate_mode = SRATE_NONE;
cell_search_in_progress = false;
current_earfcn = 0;
reset();
for (uint32_t i = 0; i < nof_rx_antennas; i++) {
sf_buffer[i] = (cf_t *) srslte_vec_malloc(sizeof(cf_t) * 3 * SRSLTE_SF_LEN_PRB(100));
@ -157,6 +149,37 @@ void phch_recv::stop() {
wait_thread_finish();
}
void phch_recv::reset() {
tx_mutex_cnt = 0;
running = true;
phy_state = IDLE;
time_adv_sec = 0;
cell_is_set = false;
sync_sfn_cnt = 0;
srate_mode = SRATE_NONE;
cell_search_in_progress = false;
current_earfcn = 0;
radio_is_resetting = false;
}
void phch_recv::radio_error() {
log_h->error("SYNC: Receiving from radio.\n");
phy_state = IDLE;
radio_is_resetting=true;
radio_h->reset();
reset();
radio_is_resetting=false;
}
bool phch_recv::wait_radio_reset() {
int cnt=0;
while(cnt < 20 && radio_is_resetting) {
sleep(1);
cnt++;
}
return radio_is_resetting;
}
void phch_recv::set_agc_enable(bool enable) {
do_agc = enable;
}
@ -394,6 +417,9 @@ int phch_recv::cell_meas_rsrp() {
}
void phch_recv::resync_sfn() {
wait_radio_reset();
stop_rx();
start_rx();
srslte_ue_mib_reset(&ue_mib);
@ -407,6 +433,9 @@ void phch_recv::set_earfcn(std::vector<uint32_t> earfcn) {
}
bool phch_recv::stop_sync() {
wait_radio_reset();
if (phy_state == IDLE && is_in_idle) {
return true;
} else {
@ -421,6 +450,16 @@ bool phch_recv::stop_sync() {
}
}
void phch_recv::reset_sync() {
wait_radio_reset();
Info("SYNC: Resetting sync\n");
srslte_ue_sync_reset(&ue_mib_sync.ue_sync);
srslte_ue_sync_reset(&ue_sync);
resync_sfn();
}
void phch_recv::cell_search_inc()
{
cur_earfcn_index++;
@ -540,17 +579,20 @@ bool phch_recv::set_frequency()
void phch_recv::set_sampling_rate()
{
float srate = (float) srslte_sampling_freq_hz(cell.nof_prb);
if (srate != -1) {
Info("SYNC: Setting sampling rate %.2f MHz\n", srate/1000000);
Info("SYNC: Setting sampling rate %.2f MHz\n", srate/1000000);
if (30720 % ((int) srate / 1000) == 0) {
radio_h->set_master_clock_rate(30.72e6);
if (30720 % ((int) srate / 1000) == 0) {
radio_h->set_master_clock_rate(30.72e6);
} else {
radio_h->set_master_clock_rate(23.04e6);
}
srate_mode = SRATE_CAMP;
radio_h->set_rx_srate(srate);
radio_h->set_tx_srate(srate);
} else {
radio_h->set_master_clock_rate(23.04e6);
Error("Error setting sampling rate for cell with %d PRBs\n", cell.nof_prb);
}
srate_mode = SRATE_CAMP;
radio_h->set_rx_srate(srate);
radio_h->set_tx_srate(srate);
}
void phch_recv::run_thread() {
@ -585,9 +627,8 @@ void phch_recv::run_thread() {
}
break;
default:
log_h->error("SYNC: Receiving frorm radio.\n");
phy_state = IDLE;
radio_h->reset();
radio_error();
break;
}
}
break;
@ -610,9 +651,7 @@ void phch_recv::run_thread() {
case 0:
break;
default:
log_h->error("SYNC: Receiving frorm radio.\n");
phy_state = IDLE;
radio_h->reset();
radio_error();
break;
}
sync_sfn_cnt++;
@ -632,9 +671,8 @@ void phch_recv::run_thread() {
case 0:
break;
default:
log_h->error("SYNC: Receiving frorm radio.\n");
phy_state = IDLE;
radio_h->reset();
radio_error();
break;
}
break;
case CELL_CAMP:
@ -694,9 +732,8 @@ void phch_recv::run_thread() {
worker_com->reset_ul();
break;
default:
log_h->error("SYNC: Receiving from radio.\n");
phy_state = IDLE;
radio_h->reset();
radio_error();
break;
}
} else {
// wait_worker() only returns NULL if it's being closed. Quit now to avoid unnecessary loops here

View File

@ -242,6 +242,10 @@ void phy::cell_search_next()
sf_recv.cell_search_next();
}
void phy::sync_reset() {
sf_recv.reset_sync();
}
bool phy::cell_select(uint32_t earfcn, srslte_cell_t phy_cell)
{
return sf_recv.cell_select(earfcn, phy_cell);

View File

@ -232,8 +232,10 @@ void gw::run_thread()
int32 N_bytes;
srslte::byte_buffer_t *pdu = pool_allocate;
const static uint32_t ATTACH_TIMEOUT_MS = 2000;
const static uint32_t ATTACH_TIMEOUT_MS = 10000;
const static uint32_t ATTACH_MAX_ATTEMPTS = 3;
uint32_t attach_cnt = 0;
uint32_t attach_attempts = 0;
gw_log->info("GW IP packet receiver thread run_enable\n");
@ -260,10 +262,11 @@ void gw::run_thread()
{
gw_log->info_hex(pdu->msg, pdu->N_bytes, "TX PDU");
while(run_enable && !pdcp->is_drb_enabled(lcid)) {
while(run_enable && !pdcp->is_drb_enabled(lcid) && attach_attempts < ATTACH_MAX_ATTEMPTS) {
if (attach_cnt == 0) {
gw_log->info("LCID=%d not active, requesting NAS attach\n", lcid);
gw_log->info("LCID=%d not active, requesting NAS attach (%d/%d)\n", lcid, attach_attempts, ATTACH_MAX_ATTEMPTS);
nas->attach_request();
attach_attempts++;
}
attach_cnt++;
if (attach_cnt == ATTACH_TIMEOUT_MS) {
@ -271,6 +274,12 @@ void gw::run_thread()
}
usleep(1000);
}
if (attach_attempts == ATTACH_MAX_ATTEMPTS) {
gw_log->warning("LCID=%d was not active after %d attempts\n", lcid, ATTACH_MAX_ATTEMPTS);
}
attach_attempts = 0;
attach_cnt = 0;
if (!run_enable) {
@ -278,18 +287,20 @@ void gw::run_thread()
}
// Send PDU directly to PDCP
pdu->set_timestamp();
ul_tput_bytes += pdu->N_bytes;
pdcp->write_sdu(lcid, pdu);
if (pdcp->is_drb_enabled(lcid)) {
pdu->set_timestamp();
ul_tput_bytes += pdu->N_bytes;
pdcp->write_sdu(lcid, pdu);
do {
pdu = pool_allocate;
if (!pdu) {
printf("Not enough buffers in pool\n");
usleep(100000);
}
} while(!pdu);
idx = 0;
do {
pdu = pool_allocate;
if (!pdu) {
printf("Not enough buffers in pool\n");
usleep(100000);
}
} while(!pdu);
idx = 0;
}
}else{
idx += N_bytes;
}

View File

@ -121,6 +121,10 @@ bool nas::is_attached() {
return state == EMM_STATE_REGISTERED;
}
bool nas::is_attaching() {
return state == EMM_STATE_REGISTERED_INITIATED;
}
void nas::notify_connection_setup() {
nas_log->debug("State = %s\n", emm_state_text[state]);
if (EMM_STATE_REGISTERED_INITIATED == state) {

View File

@ -154,13 +154,22 @@ void rrc::run_thread() {
case RRC_STATE_IDLE:
// If camping on the cell, it will receive SI and paging from PLMN
if (phy->sync_status()) {
// If attempting to attach, reselect cell
if (nas->is_attaching()) {
sleep(1);
rrc_log->info("RRC IDLE: NAS is attaching and camping on cell, reselecting...\n");
plmn_select(selected_plmn_id);
}
// If not camping on a cell
} else {
// If NAS is attached, perform cell reselection on current PLMN
if (nas->is_attached()) {
rrc_log->info("RRC IDLE: NAS is attached, PHY not synchronized. Re-selecting cell...\n");
plmn_select(selected_plmn_id);
} else if (nas->is_attaching()) {
sleep(1);
rrc_log->info("RRC IDLE: NAS is attaching, searching again PLMN\n");
plmn_search();
}
// If not attached, PLMN selection will be triggered from higher layers
}
@ -358,6 +367,7 @@ void rrc::plmn_select(LIBLTE_RRC_PLMN_IDENTITY_STRUCT plmn_id) {
if (phy->sync_status() && selected_plmn_id.mcc == plmn_id.mcc && selected_plmn_id.mnc == plmn_id.mnc) {
rrc_log->info("Already camping on selected PLMN, connecting...\n");
state = RRC_STATE_CELL_SELECTING;
select_cell_timeout = 0;
} else {
rrc_log->info("PLMN %s selected\n", plmn_id_to_c_str(plmn_id).c_str());
// Sort cells according to RSRP
@ -495,6 +505,7 @@ void rrc::in_sync() {
void rrc::radio_link_failure() {
// TODO: Generate and store failure report
phy->sync_reset();
rrc_log->warning("Detected Radio-Link Failure\n");
rrc_log->console("Warning: Detected Radio-Link Failure\n");
if (state != RRC_STATE_CONNECTED) {
@ -681,7 +692,7 @@ void rrc::send_con_restablish_request() {
rrc_log->debug("Setting UE contention resolution ID: %d\n", uecri);
mac->set_contention_id(uecri);
rrc_log->info("Sending RRC Connection Resetablishment Request on SRB0\n");
rrc_log->info("Sending RRC Connection Reestablishment Request on SRB0\n");
pdcp->write_sdu(RB_ID_SRB0, pdcp_buf);
}