S1/X2 handover tested and working

master
Ismael Gomez 7 years ago
parent cfbea7a6c1
commit 3a0ab02264

@ -369,7 +369,7 @@ int main(int argc, char **argv) {
if ((nframes%100) == 0 || rx_gain_offset == 0) {
if (srslte_rf_has_rssi(&rf)) {
rx_gain_offset = 10*log10(rssi*1000)-srslte_rf_get_rssi(&rf);
rx_gain_offset = 30+10*log10(rssi*1000)-srslte_rf_get_rssi(&rf);
} else {
rx_gain_offset = srslte_rf_get_rx_gain(&rf);
}

@ -91,6 +91,10 @@ LIBLTE_ERROR_ENUM liblte_security_generate_k_enb_star(uint8 *k_enb,
uint32_t earfcn,
uint8 *k_enb_star);
LIBLTE_ERROR_ENUM liblte_security_generate_nh( uint8_t *k_asme,
uint8_t *sync,
uint8_t *nh);
/*********************************************************************
Name: liblte_security_generate_k_nas
@ -126,6 +130,8 @@ LIBLTE_ERROR_ENUM liblte_security_generate_k_nas(uint8
uint8 *k_nas_enc,
uint8 *k_nas_int);
/*********************************************************************
Name: liblte_security_generate_k_rrc

@ -81,6 +81,10 @@ uint8_t security_generate_k_enb_star( uint8_t *k_enb,
uint32_t earfcn,
uint8_t *k_enb_star);
uint8_t security_generate_nh( uint8_t *k_asme,
uint8_t *sync,
uint8_t *nh);
uint8_t security_generate_k_nas( uint8_t *k_asme,
CIPHERING_ALGORITHM_ID_ENUM enc_alg_id,
INTEGRITY_ALGORITHM_ID_ENUM int_alg_id,

@ -85,6 +85,7 @@ public:
srslte::INTEGRITY_ALGORITHM_ID_ENUM integ_algo) = 0;
virtual void generate_as_keys_ho(uint32_t pci,
uint32_t earfcn,
int ncc,
uint8_t *k_rrc_enc,
uint8_t *k_rrc_int,
uint8_t *k_up_enc,

@ -75,6 +75,7 @@ typedef struct SRSLTE_API {
uint32_t frame_size;
uint32_t max_offset;
bool enable_cfo_corr;
bool enable_cfo_pss;
bool mean_cfo2_isunset;
bool mean_cfo_isunset;
float mean_cfo;

@ -335,6 +335,34 @@ LIBLTE_ERROR_ENUM liblte_security_generate_k_enb_star(uint8 *k_enb,
return (err);
}
LIBLTE_ERROR_ENUM liblte_security_generate_nh( uint8_t *k_asme,
uint8_t *sync,
uint8_t *nh)
{
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
uint8 s[35];
if (k_asme != NULL &&
sync != NULL &&
nh != NULL)
{
// Construct S
s[0] = 0x12; // FC
for (int i=0;i<32;i++) {
s[1+i] = sync[i];
}
s[33] = 0x00; // First byte of L0
s[34] = 0x20, // Second byte of L0
// Derive NH
sha256(k_asme, 32, s, 35, nh, 0);
err = LIBLTE_SUCCESS;
}
return (err);
}
/*********************************************************************
Name: liblte_security_generate_k_nas

@ -72,6 +72,15 @@ uint8_t security_generate_k_enb_star( uint8_t *k_enb,
k_enb_star);
}
uint8_t security_generate_nh( uint8_t *k_asme,
uint8_t *sync,
uint8_t *nh)
{
return liblte_security_generate_nh( k_asme,
sync,
nh);
}
uint8_t security_generate_k_nas( uint8_t *k_asme,
CIPHERING_ALGORITHM_ID_ENUM enc_alg_id,
INTEGRITY_ALGORITHM_ID_ENUM int_alg_id,

@ -554,8 +554,7 @@ srslte_sync_find_ret_t srslte_sync_find(srslte_sync_t *q, cf_t *input, uint32_t
peak_pos = srslte_pss_synch_find_pss(&q->pss, &input_cfo[find_offset], &q->peak_value);
// this compensates for the constant time shift caused by the low pass filter
if(q->decimate && peak_pos < 0)
{
if(q->decimate && peak_pos < 0) {
peak_pos = 0 ;//peak_pos + q->decimate*(2);// replace 2 with q->filter_size -2;
}
if (peak_pos < 0) {
@ -591,17 +590,15 @@ srslte_sync_find_ret_t srslte_sync_find(srslte_sync_t *q, cf_t *input, uint32_t
}
}
if (q->enable_cfo_corr) {
if (q->enable_cfo_pss) {
if (peak_pos + find_offset >= 2*(q->fft_size + SRSLTE_CP_LEN_EXT(q->fft_size))) {
float cfo2 = srslte_pss_synch_cfo_compute(&q->pss, &input[find_offset + peak_pos - q->fft_size]);
float cfo2 = srslte_pss_synch_cfo_compute(&q->pss, &input[find_offset + peak_pos - q->fft_size]);
if (q->mean_cfo2_isunset) {
q->mean_cfo2 = cfo2;
q->mean_cfo2_isunset = true;
} else {
q->mean_cfo2 = SRSLTE_VEC_EMA(cfo2, q->mean_cfo2, q->cfo_ema_alpha);
}
} else {
ret = SRSLTE_SYNC_FOUND_NOSPACE;
}
}
} else {

@ -401,7 +401,7 @@ int srslte_ue_dl_decode_fft_estimate_mbsfn(srslte_ue_dl_t *q, uint32_t sf_idx, u
int srslte_ue_dl_decode_fft_estimate_noguru(srslte_ue_dl_t *q, cf_t *input[SRSLTE_MAX_PORTS], uint32_t sf_idx, uint32_t *cfi)
{
if (input && q && cfi && sf_idx < SRSLTE_NSUBFRAMES_X_FRAME) {
if (input && q && sf_idx < SRSLTE_NSUBFRAMES_X_FRAME) {
/* Run FFT for all subframe data */
for (int j=0;j<q->nof_rx_antennas;j++) {

@ -682,19 +682,21 @@ int srslte_ue_sync_zerocopy_multi(srslte_ue_sync_t *q, cf_t *input_buffer[SRSLTE
q->sf_idx = (q->sf_idx + q->nof_recv_sf) % 10;
#ifndef DO_CFO_IN_SYNC
/* We found that CP-based correction performs better in low SNR than PSS-based.
*
* Estimate, average and correct here instead of inside sync object
*/
q->cfo = srslte_sync_cfo_estimate(&q->strack, input_buffer[0], 0);
if (q->mean_cfo_isunset) {
q->mean_cfo = q->cfo;
q->mean_cfo_isunset = false;
} else {
/* compute exponential moving average CFO */
q->mean_cfo = SRSLTE_VEC_EMA(q->cfo, q->mean_cfo, q->cfo_ema_alpha);
if (q->correct_cfo) {
/* We found that CP-based correction performs better in low SNR than PSS-based.
*
* Estimate, average and correct here instead of inside sync object
*/
q->cfo = srslte_sync_cfo_estimate(&q->strack, input_buffer[0], 0);
if (q->mean_cfo_isunset) {
q->mean_cfo = q->cfo;
q->mean_cfo_isunset = false;
} else {
/* compute exponential moving average CFO */
q->mean_cfo = SRSLTE_VEC_EMA(q->cfo, q->mean_cfo, q->cfo_ema_alpha);
}
srslte_cfo_correct(&q->strack.cfocorr2, input_buffer[0], input_buffer[0], -q->mean_cfo / q->fft_size);
}
srslte_cfo_correct(&q->strack.cfocorr2, input_buffer[0], input_buffer[0], -q->mean_cfo / q->fft_size);
#endif
@ -754,14 +756,6 @@ int srslte_ue_sync_zerocopy_multi(srslte_ue_sync_t *q, cf_t *input_buffer[SRSLTE
q->frame_total_cnt++;
}
if (q->correct_cfo) {
for (int i=0;i<q->nof_rx_antennas;i++) {
srslte_cfo_correct(&q->strack.cfocorr,
input_buffer[i],
input_buffer[i],
-srslte_sync_get_cfo(&q->strack) / q->fft_size);
}
}
break;
}

@ -51,20 +51,19 @@ namespace srsue {
phy_args_t *args;
rrc_interface_phy *rrc;
mac_interface_phy *mac;
srslte_ue_ul_t ue_ul;
/* Power control variables */
float pathloss;
float cur_pathloss;
float p0_preamble;
float cur_radio_power;
float cur_pusch_power;
float avg_rsrp_db;
float avg_rsrp;
float avg_rsrp_dbm;
float avg_rsrq_db;
float rx_gain_offset;
float avg_snr_db;
float avg_noise;
float avg_rsrp;
bool pcell_meas_enabled;
uint32_t pcell_report_period;

@ -167,7 +167,7 @@ private:
void set_cell(srslte_cell_t cell);
ret_code run_subframe(uint32_t sf_idx);
ret_code run_subframe_sync(srslte_ue_sync_t *ue_sync, uint32_t sf_idx);
ret_code run_multiple_subframes(cf_t *buffer, uint32_t sf_idx, uint32_t nof_sf);
ret_code run_multiple_subframes(cf_t *buffer, uint32_t offset, uint32_t sf_idx, uint32_t nof_sf);
float rsrp();
float rsrq();
float snr();
@ -205,6 +205,7 @@ private:
srslte::log *log_h;
srslte_sync_t sync_find;
uint32_t current_fft_sz;
measure measure_p;
};

@ -205,8 +205,10 @@ private:
LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_13_STRUCT sib13;
} cell_t;
std::vector<cell_t> known_cells;
const static int MAX_KNOWN_CELLS = 64;
cell_t known_cells[MAX_KNOWN_CELLS];
cell_t *current_cell;
void add_new_cell(uint32_t earfcn, srslte_cell_t phy_cell, float rsrp);
typedef enum {
SI_ACQUIRE_IDLE = 0,
@ -353,7 +355,6 @@ private:
float Qqualmin;
float Qqualminoffset;
float s_intrasearchP;
float s_intrasearchQ;
float q_hyst;
float threshservinglow;

@ -92,6 +92,7 @@ public:
void generate_as_keys_ho(uint32_t pci,
uint32_t earfcn,
int ncc,
uint8_t *k_rrc_enc,
uint8_t *k_rrc_int,
uint8_t *k_up_enc,
@ -137,9 +138,13 @@ private:
uint8_t ak[6];
uint8_t mac[8];
uint8_t autn[16];
uint8_t k_asme[32];
uint8_t nh[32];
uint8_t k_enb[32];
uint8_t k_enb_star[32];
uint32_t current_ncc;
bool initiated;
};

@ -385,7 +385,6 @@ void mac::set_ho_rnti(uint16_t crnti, uint16_t target_pci) {
phy_h->pdcch_ul_search_reset();
uernti.crnti = crnti;
if (pcap) {
printf("set_ue_id=%d\n", target_pci);
pcap->set_ue_id(target_pci);
}
}

@ -52,6 +52,7 @@ phch_recv::phch_recv() {
ul_freq = -1;
bzero(&cell, sizeof(srslte_cell_t));
running = false;
worker_com = NULL;
}
void phch_recv::init(srslte::radio_multi *_radio_handler, mac_interface_phy *_mac, rrc_interface_phy *_rrc,
@ -976,7 +977,7 @@ void phch_recv::measure::init(cf_t *buffer[SRSLTE_MAX_PORTS], srslte::log *log_h
for (int i=0;i<SRSLTE_MAX_PORTS;i++) {
this->buffer[i] = buffer[i];
}
if (srslte_ue_dl_init(&ue_dl, this->buffer, SRSLTE_MAX_PRB, nof_rx_antennas)) {
Error("SYNC: Initiating ue_dl_measure\n");
return;
@ -1024,6 +1025,7 @@ phch_recv::measure::ret_code phch_recv::measure::run_subframe_sync(srslte_ue_syn
{
int sync_res = srslte_ue_sync_zerocopy_multi(ue_sync, buffer);
if (sync_res == 1) {
log_h->info("SYNC: CFO=%.1f KHz\n", srslte_ue_sync_get_cfo(ue_sync));
return run_subframe(sf_idx);
} else {
log_h->error("SYNC: Measuring RSRP: Sync error\n");
@ -1034,18 +1036,61 @@ phch_recv::measure::ret_code phch_recv::measure::run_subframe_sync(srslte_ue_syn
}
phch_recv::measure::ret_code phch_recv::measure::run_multiple_subframes(cf_t *input_buffer,
uint32_t offset,
uint32_t sf_idx,
uint32_t nof_sf)
uint32_t max_sf)
{
uint32_t sf_len = SRSLTE_SF_LEN_PRB(current_prb);
ret_code ret = IDLE;
for (uint32_t i=0;i<nof_sf;i++) {
memcpy(buffer[0], &input_buffer[i*sf_len], sizeof(cf_t)*sf_len);
ret = run_subframe((sf_idx+i)%10);
if (ret != IDLE) {
return ret;
offset = offset-sf_len/2;
if (offset < 0) {
offset += sf_len;
sf_idx ++;
}
float max_rsrp = -99;
int best_test_offset = 0;
int test_offset = 0;
bool found_best = false;
// Fine-tune offset using RS
for (uint32_t n=0;n<5;n++) {
test_offset = offset-2+n;
if (test_offset >= 0) {
cf_t *buf_m[SRSLTE_MAX_PORTS];
buf_m[0] = &input_buffer[test_offset];
uint32_t cfi;
if (srslte_ue_dl_decode_fft_estimate_noguru(&ue_dl, buf_m, sf_idx, &cfi)) {
Error("MEAS: Measuring RSRP: Estimating channel\n");
return ERROR;
}
float rsrp = srslte_chest_dl_get_rsrp(&ue_dl.chest);
if (rsrp > max_rsrp) {
max_rsrp = rsrp;
best_test_offset = test_offset;
found_best = true;
}
}
}
offset = found_best?best_test_offset:offset;
if (offset >= 0 && offset < sf_len*max_sf) {
uint32_t nof_sf = (sf_len*max_sf - offset)/sf_len;
Info("INTRA: fine-tuning offset: %d, found_best=%d, rem_sf=%d\n", offset, found_best, nof_sf);
for (uint32_t i=0;i<nof_sf;i++) {
memcpy(buffer[0], &input_buffer[offset+i*sf_len], sizeof(cf_t)*sf_len);
ret = run_subframe((sf_idx+i)%10);
if (ret != IDLE) {
return ret;
}
}
}
return ret;
@ -1107,49 +1152,56 @@ void phch_recv::scell_recv::init(srslte::log *log_h)
measure_p.init(sf_buffer, log_h, 1, DEFAULT_MEASUREMENT_LEN);
if(srslte_sync_init(&sync_find, 15*max_sf_size, 5*max_sf_size, max_fft_sz)) {
if(srslte_sync_init(&sync_find, 5*max_sf_size, 5*max_sf_size, max_fft_sz)) {
fprintf(stderr, "Error initiating sync_find\n");
return;
}
srslte_sync_cp_en(&sync_find, false);
srslte_sync_set_cfo_enable(&sync_find, false);
srslte_sync_set_cfo_ema_alpha(&sync_find, 0.8);
srslte_sync_set_threshold(&sync_find, 1.2);
srslte_sync_set_em_alpha(&sync_find, 0.0);
reset();
}
void phch_recv::scell_recv::reset()
{
current_fft_sz = 0;
measure_p.reset();
}
int phch_recv::scell_recv::find_cells(cf_t *input_buffer, float rx_gain_offset, srslte_cell_t current_cell, uint32_t nof_sf, cell_info_t cells[MAX_CELLS])
int phch_recv::scell_recv::find_cells(cf_t *input_buffer, float rx_gain_offset, srslte_cell_t cell, uint32_t nof_sf, cell_info_t cells[MAX_CELLS])
{
uint32_t fft_sz = srslte_symbol_sz(current_cell.nof_prb);
uint32_t fft_sz = srslte_symbol_sz(cell.nof_prb);
uint32_t sf_len = SRSLTE_SF_LEN(fft_sz);
if (srslte_sync_resize(&sync_find, nof_sf*sf_len, 5*sf_len, fft_sz)) {
fprintf(stderr, "Error resizing sync\n");
return SRSLTE_ERROR;
if (fft_sz != current_fft_sz) {
if (srslte_sync_resize(&sync_find, nof_sf*sf_len, 5*sf_len, fft_sz)) {
fprintf(stderr, "Error resizing sync\n");
return SRSLTE_ERROR;
}
current_fft_sz = fft_sz;
}
srslte_sync_reset(&sync_find);
int nof_cells = 0;
uint32_t peak_idx = 0;
uint32_t sf_idx = 0;
uint32_t cell_id = 0;
uint32_t rem_sf = 0;
int offset = 0;
srslte_cell_t found_cell;
memcpy(&found_cell, &current_cell, sizeof(srslte_cell_t));
memcpy(&found_cell, &cell, sizeof(srslte_cell_t));
measure_p.set_rx_gain_offset(rx_gain_offset);
for (uint32_t n_id_2=0;n_id_2<3;n_id_2++) {
if (current_cell.id%3 != n_id_2) {
if (cell.id%3 != n_id_2) {
srslte_sync_set_N_id_2(&sync_find, n_id_2);
sync_find.enable_cfo_pss = true;
srslte_sync_find_ret_t sync_res = srslte_sync_find(&sync_find, input_buffer, 0, &peak_idx);
switch(sync_res) {
@ -1160,34 +1212,29 @@ int phch_recv::scell_recv::find_cells(cf_t *input_buffer, float rx_gain_offset,
case SRSLTE_SYNC_FOUND:
sf_idx = srslte_sync_get_sf_idx(&sync_find);
cell_id = srslte_sync_get_cell_id(&sync_find);
Info("INTRA: found peak_idx=%d, n_id_2=%d, cell_id=%d, sf=%d\n",
Info("INTRA: found peak_idx=%d, n_id_2=%d, cell_id=%d, sf=%d\n",
peak_idx, n_id_2, cell_id, sf_idx);
found_cell.id = cell_id;
found_cell.nof_ports = 1; // Use port 0 only for measurement
measure_p.set_cell(found_cell);
offset = peak_idx-sf_len/2;
if (offset < 0) {
offset += sf_len;
sf_idx ++;
}
rem_sf = (sf_len*nof_sf - offset)/sf_len;
//printf("cell_id=%d, correcting cfo=%f Hz\n", cell_id, 15000*sync_find.mean_cfo2);
//srslte_cfo_correct(&sync_find.cfocorr, input_buffer, input_buffer, -sync_find.mean_cfo2 / sync_find.fft_size);
switch(measure_p.run_multiple_subframes(&input_buffer[offset], sf_idx, rem_sf)) {
switch(measure_p.run_multiple_subframes(input_buffer, peak_idx, sf_idx, nof_sf)) {
case measure::MEASURE_OK:
cells[nof_cells].pci = found_cell.id;
cells[nof_cells].rsrp = measure_p.rsrp();
cells[nof_cells].rsrq = measure_p.rsrq();
cells[nof_cells].offset = offset;
cells[nof_cells].offset = peak_idx;
nof_cells++;
break;
case measure::ERROR:
Error("Measuring neighbour cell\n");
return SRSLTE_ERROR;
default:
printf("torna idle\n");
break;
}
break;
@ -1212,7 +1259,9 @@ int phch_recv::scell_recv::find_cells(cf_t *input_buffer, float rx_gain_offset,
void phch_recv::meas_reset() {
// Stop all measurements
intra_freq_meas.clear_cells();
worker_com->pcell_meas_enabled = false;
if (worker_com) {
worker_com->pcell_meas_enabled = false;
}
}
int phch_recv::meas_start(uint32_t earfcn, int pci) {
@ -1223,7 +1272,7 @@ int phch_recv::meas_start(uint32_t earfcn, int pci) {
}
return 0;
} else {
Warning("INTRA: Inter-frequency measurements not supported (current EARFCN=%d, requested measurement for %d)\n",
Warning("INTRA: Inter-frequency measurements not supported (current EARFCN=%d, requested measurement for %d)\n",
current_earfcn, earfcn);
return -1;
}
@ -1234,7 +1283,7 @@ int phch_recv::meas_stop(uint32_t earfcn, int pci) {
intra_freq_meas.rem_cell(pci);
return 0;
} else {
Warning("INTRA: Inter-frequency measurements not supported (current EARFCN=%d, requested stop measurement for %d)\n",
Warning("INTRA: Inter-frequency measurements not supported (current EARFCN=%d, requested stop measurement for %d)\n",
current_earfcn, earfcn);
}
return -1;
@ -1283,9 +1332,9 @@ void phch_recv::intra_measure::add_cell(int pci) {
if (std::find(active_pci.begin(), active_pci.end(), pci) == active_pci.end()) {
active_pci.push_back(pci);
receive_enabled = true;
Info("INTRA: Starting intra-frequency measurement for pci=%d\n", pci);
Info("INTRA: Starting intra-frequency measurement for pci=%d\n", pci);
} else {
Warning("INTRA: Requested to start already existing intra-frequency measurement for PCI=%d\n", pci);
Warning("INTRA: Requested to start already existing intra-frequency measurement for PCI=%d\n", pci);
}
}
@ -1306,9 +1355,9 @@ void phch_recv::intra_measure::rem_cell(int pci) {
if (active_pci.size() == 0) {
receive_enabled = false;
}
Info("INTRA: Stopping intra-frequency measurement for pci=%d. Number of cells: %d\n", pci, active_pci.size());
Info("INTRA: Stopping intra-frequency measurement for pci=%d. Number of cells: %d\n", pci, active_pci.size());
} else {
Warning("INTRA: Requested to stop non-existing intra-frequency measurement for PCI=%d\n", pci);
Warning("INTRA: Requested to stop non-existing intra-frequency measurement for PCI=%d\n", pci);
}
}
@ -1318,12 +1367,12 @@ void phch_recv::intra_measure::write(uint32_t tti, cf_t *data, uint32_t nsamples
receiving = true;
receive_cnt = 0;
measure_tti = tti;
srslte_ringbuffer_reset(&ring_buffer);
}
if (receiving == true) {
if (srslte_ringbuffer_write(&ring_buffer, data, nsamples*sizeof(cf_t)) < (int) (nsamples*sizeof(cf_t))) {
Warning("Error writing to ringbuffer\n");
receiving = false;
srslte_ringbuffer_reset(&ring_buffer);
} else {
receive_cnt++;
if (receive_cnt == CAPTURE_LEN_SF) {
@ -1343,13 +1392,12 @@ void phch_recv::intra_measure::run_thread()
}
if (running) {
Info("INTRA: Running intra-frequency measurements\n");
Info("INTRA: Running intra-frequency measurements\n");
// Read 5 ms data from buffer
// Read 15 ms data from buffer
srslte_ringbuffer_read(&ring_buffer, search_buffer, CAPTURE_LEN_SF*current_sflen*sizeof(cf_t));
int found_cells = scell.find_cells(search_buffer, common->rx_gain_offset, primary_cell, CAPTURE_LEN_SF, info);
receiving = false;
srslte_ringbuffer_reset(&ring_buffer);
for (int i=0;i<found_cells;i++) {
rrc->new_phy_meas(info[i].rsrp, info[i].rsrq, measure_tti, current_earfcn, info[i].pci);

@ -221,7 +221,7 @@ void phch_worker::work_imp()
/* Do FFT and extract PDCCH LLR, or quit if no actions are required in this subframe */
bool chest_ok = extract_fft_and_pdcch_llr();
bool snr_th_ok = 10*log10(srslte_chest_dl_get_snr(&ue_dl.chest))>1.0;
bool snr_th_ok = 10*log10(srslte_chest_dl_get_snr(&ue_dl.chest))>-10.0;
if (chest_ok && snr_th_ok) {
@ -381,7 +381,7 @@ void phch_worker::work_imp()
log_h->debug("SYNC: Sending in-sync to RRC\n");
} else {
phy->rrc->out_of_sync();
log_h->debug("SNR=%.1f dB under threshold. Sending out-of-sync to RRC\n",
log_h->info("SNR=%.1f dB under threshold. Sending out-of-sync to RRC\n",
10*log10(srslte_chest_dl_get_snr(&ue_dl.chest)));
}
}
@ -974,7 +974,7 @@ void phch_worker::encode_pusch(srslte_ra_ul_grant_t *grant, uint8_t *payload, ui
#endif
uint8_t dummy[2] = {0,0};
log_h->info_hex(payload?payload:dummy, payload?grant->mcs.tbs/8:1,"PUSCH: tti_tx=%d, alloc=(%d,%d), tbs=%d, mcs=%d, rv=%d, ack=%s, ri=%s, cfo=%.1f KHz%s\n",
log_h->info("PUSCH: tti_tx=%d, alloc=(%d,%d), tbs=%d, mcs=%d, rv=%d, ack=%s, ri=%s, cfo=%.1f KHz%s\n",
(tti+HARQ_DELAY_MS)%10240,
grant->n_prb[0], grant->n_prb[0]+grant->L_prb,
grant->mcs.tbs/8, grant->mcs.idx, rv,
@ -1244,52 +1244,49 @@ void phch_worker::update_measurements()
if (tti== 0 || phy->rx_gain_offset == 0) {
float rx_gain_offset = 0;
if (phy->get_radio()->has_rssi() && phy->args->rssi_sensor_enabled) {
float rssi_all_signal = srslte_chest_dl_get_rssi(&ue_dl.chest);
if (rssi_all_signal) {
rx_gain_offset = 10*log10(rssi_all_signal)-phy->get_radio()->get_rssi();
} else {
rx_gain_offset = 0;
}
float rssi_all_signal = 30+10*log10(srslte_vec_avg_power_cf(signal_buffer[0],SRSLTE_SF_LEN(srslte_symbol_sz(cell.nof_prb))));
rx_gain_offset = 30+rssi_all_signal-phy->get_radio()->get_rssi();
} else {
rx_gain_offset = phy->get_radio()->get_rx_gain();
}
if (phy->rx_gain_offset) {
phy->rx_gain_offset = SRSLTE_VEC_EMA(phy->rx_gain_offset, rx_gain_offset, 0.5);
phy->rx_gain_offset = SRSLTE_VEC_EMA(rx_gain_offset, phy->rx_gain_offset, 0.5);
} else {
phy->rx_gain_offset = rx_gain_offset;
}
}
// Average RSRQ
float cur_rsrq = 10*log10(srslte_chest_dl_get_rsrq(&ue_dl.chest));
if (isnormal(cur_rsrq)) {
phy->avg_rsrq_db = SRSLTE_VEC_EMA(phy->avg_rsrq_db, cur_rsrq, snr_ema_coeff);
float rsrq_db = 10*log10(srslte_chest_dl_get_rsrq(&ue_dl.chest));
if (isnormal(rsrq_db)) {
phy->avg_rsrq_db = SRSLTE_VEC_EMA(rsrq_db, phy->avg_rsrq_db, snr_ema_coeff);
}
// Average RSRP
float cur_rsrp = srslte_chest_dl_get_rsrp(&ue_dl.chest);
if (isnormal(cur_rsrp)) {
phy->avg_rsrp = SRSLTE_VEC_EMA(phy->avg_rsrp, cur_rsrp, snr_ema_coeff);
float rsrp_lin = srslte_chest_dl_get_rsrp(&ue_dl.chest);
if (isnormal(rsrp_lin)) {
phy->avg_rsrp = SRSLTE_VEC_EMA(rsrp_lin, phy->avg_rsrp, snr_ema_coeff);
}
/* Correct absolute power measurements by RX gain offset */
float rsrp = 10*log10(srslte_chest_dl_get_rsrp(&ue_dl.chest)) + 30 - phy->rx_gain_offset;
float rssi = 10*log10(srslte_chest_dl_get_rssi(&ue_dl.chest)) + 30 - phy->rx_gain_offset;
float rsrp_dbm = 10*log10(rsrp_lin) + 30 - phy->rx_gain_offset;
float rssi_db = 10*log10(srslte_chest_dl_get_rssi(&ue_dl.chest)) + 30 - phy->rx_gain_offset;
// Serving cell measurements are averaged over DEFAULT_MEAS_PERIOD_MS then sent to RRC
if (isnormal(rsrp)) {
if (!phy->avg_rsrp_db) {
phy->avg_rsrp_db = rsrp;
if (isnormal(rsrp_dbm)) {
if (!phy->avg_rsrp_dbm) {
phy->avg_rsrp_dbm= rsrp_dbm;
} else {
phy->avg_rsrp_db = SRSLTE_VEC_EMA(phy->avg_rsrp_db, rsrp, 0.8);
phy->avg_rsrp_dbm = SRSLTE_VEC_EMA(rsrp_dbm, phy->avg_rsrp_dbm, snr_ema_coeff);
}
if ((tti%phy->pcell_report_period) == 0 && phy->pcell_meas_enabled) {
phy->rrc->new_phy_meas(phy->avg_rsrp_db, phy->avg_rsrq_db, tti);
phy->rrc->new_phy_meas(phy->avg_rsrp_dbm, phy->avg_rsrq_db, tti);
}
}
// Compute PL
float tx_crs_power = phy->config->common.pdsch_cnfg.rs_power;
phy->pathloss = tx_crs_power - phy->avg_rsrp_db;
phy->pathloss = tx_crs_power - phy->avg_rsrp_dbm;
// Average noise
float cur_noise = srslte_chest_dl_get_noise_estimate(&ue_dl.chest);
@ -1297,7 +1294,7 @@ void phch_worker::update_measurements()
if (!phy->avg_noise) {
phy->avg_noise = cur_noise;
} else {
phy->avg_noise = SRSLTE_VEC_EMA(phy->avg_noise, cur_noise, snr_ema_coeff);
phy->avg_noise = SRSLTE_VEC_EMA(cur_noise, phy->avg_noise, snr_ema_coeff);
}
}
@ -1306,9 +1303,9 @@ void phch_worker::update_measurements()
// Store metrics
dl_metrics.n = phy->avg_noise;
dl_metrics.rsrp = phy->avg_rsrp_db;
dl_metrics.rsrp = phy->avg_rsrp_dbm;
dl_metrics.rsrq = phy->avg_rsrq_db;
dl_metrics.rssi = rssi;
dl_metrics.rssi = rssi_db;
dl_metrics.pathloss = phy->pathloss;
dl_metrics.sinr = phy->avg_snr_db;
dl_metrics.turbo_iters = srslte_pdsch_last_noi(&ue_dl.pdsch);

@ -89,6 +89,8 @@ void rrc::init(phy_interface_rrc *phy_,
state = RRC_STATE_IDLE;
si_acquire_state = SI_ACQUIRE_IDLE;
bzero(known_cells, MAX_KNOWN_CELLS*sizeof(cell_t));
thread_running = true;
start();
@ -433,7 +435,7 @@ void rrc::plmn_select(LIBLTE_RRC_PLMN_IDENTITY_STRUCT plmn_id) {
}
void rrc::select_next_cell_in_plmn() {
for (uint32_t i = last_selected_cell + 1; i < known_cells.size(); i++) {
for (uint32_t i = last_selected_cell + 1; i < MAX_KNOWN_CELLS && known_cells[i].earfcn; i++) {
for (uint32_t j = 0; j < known_cells[i].sib1.N_plmn_ids; j++) {
if (known_cells[i].sib1.plmn_id[j].id.mcc == selected_plmn_id.mcc ||
known_cells[i].sib1.plmn_id[j].id.mnc == selected_plmn_id.mnc) {
@ -476,7 +478,7 @@ void rrc::new_phy_meas(float rsrp, float rsrq, uint32_t tti, uint32_t earfcn, ui
void rrc::cell_found(uint32_t earfcn, srslte_cell_t phy_cell, float rsrp) {
// find if cell_id-earfcn combination already exists
for (uint32_t i = 0; i < known_cells.size(); i++) {
for (uint32_t i = 0; i < MAX_KNOWN_CELLS && known_cells[i].earfcn; i++) {
if (earfcn == known_cells[i].earfcn && phy_cell.id == known_cells[i].phy_cell.id) {
current_cell = &known_cells[i];
current_cell->rsrp = rsrp;
@ -497,17 +499,7 @@ void rrc::cell_found(uint32_t earfcn, srslte_cell_t phy_cell, float rsrp) {
}
}
// add to list of known cells
cell_t cell;
cell.phy_cell = phy_cell;
cell.rsrp = rsrp;
cell.earfcn = earfcn;
cell.has_valid_sib1 = false;
cell.has_valid_sib2 = false;
cell.has_valid_sib3 = false;
known_cells.push_back(cell);
// save current cell
current_cell = &known_cells.back();
add_new_cell(earfcn, phy_cell, rsrp);
si_acquire_state = SI_ACQUIRE_SIB1;
@ -516,6 +508,24 @@ void rrc::cell_found(uint32_t earfcn, srslte_cell_t phy_cell, float rsrp) {
current_cell->earfcn, current_cell->rsrp, current_cell);
}
void rrc::add_new_cell(uint32_t earfcn, srslte_cell_t phy_cell, float rsrp) {
int i=0;
while(i<MAX_KNOWN_CELLS && known_cells[i].earfcn) {
i++;
}
if (i==MAX_KNOWN_CELLS) {
rrc_log->error("Can't add more cells\n");
return;
}
current_cell = &known_cells[i];
current_cell->phy_cell = phy_cell;
current_cell->rsrp = rsrp;
current_cell->earfcn = earfcn;
current_cell->has_valid_sib1 = false;
current_cell->has_valid_sib2 = false;
current_cell->has_valid_sib3 = false;
}
// PHY indicates that has gone through all known EARFCN
void rrc::earfcn_end() {
rrc_log->debug("Finished searching cells in EARFCN set while in state %s\n", rrc_state_text[state]);
@ -527,20 +537,18 @@ void rrc::earfcn_end() {
}
void rrc::add_neighbour_cell(uint32_t earfcn, uint32_t pci, float rsrp) {
for (uint32_t i = 0; i < known_cells.size(); i++) {
for (uint32_t i = 0; i < MAX_KNOWN_CELLS && known_cells[i].earfcn; i++) {
if (earfcn == known_cells[i].earfcn && pci == known_cells[i].phy_cell.id) {
known_cells[i].rsrp = rsrp;
return;
}
}
rrc_log->info("Added neighbour cell earfcn=%d, pci=%d, rsrp=%f\n", earfcn, pci, rsrp);
cell_t c;
bzero(&c, sizeof(cell_t));
c.earfcn = earfcn;
c.rsrp = rsrp;
memcpy(&c.phy_cell, &current_cell->phy_cell, sizeof(srslte_cell_t));
c.phy_cell.id = pci;
known_cells.push_back(c);
srslte_cell_t cell;
cell = current_cell->phy_cell;
cell.id = pci;
add_new_cell(earfcn, cell, rsrp);
}
// Cell reselection in IDLE Section 5.2.4 of 36.304
@ -548,7 +556,7 @@ void rrc::cell_reselection_eval(float rsrp, float rsrq)
{
// Intra-frequency cell-reselection criteria
if (get_srxlev(rsrp) > cell_resel_cfg.s_intrasearchP && get_squal(rsrq) > cell_resel_cfg.s_intrasearchQ) {
if (get_srxlev(rsrp) > cell_resel_cfg.s_intrasearchP) {
// UE may not perform intra-frequency measurements
phy->meas_reset();
} else {
@ -900,9 +908,7 @@ void rrc::ho_prepare() {
apply_rr_config_common_dl(&mob_reconf.mob_ctrl_info.rr_cnfg_common);
bool found = false;
for (uint32_t i = 0; i < known_cells.size(); i++) {
rrc_log->info("cell[%d]=%d:%d, cur_earfcn=%d\n", i, known_cells[i].earfcn, known_cells[i].phy_cell.id,
current_cell->earfcn);
for (uint32_t i = 0; i < MAX_KNOWN_CELLS && known_cells[i].earfcn; i++) {
if (known_cells[i].earfcn == phy->get_current_earfcn() &&
known_cells[i].phy_cell.id == mob_reconf.mob_ctrl_info.target_pci) {
rrc_log->info("Selecting new cell pci=%d\n", known_cells[i].phy_cell.id);
@ -925,8 +931,13 @@ void rrc::ho_prepare() {
mac->start_cont_ho();
}
printf("ncc=%d\n", mob_reconf.sec_cnfg_ho.intra_lte.next_hop_chaining_count);
int ncc = -1;
if (mob_reconf.sec_cnfg_ho_present) {
ncc = mob_reconf.sec_cnfg_ho.intra_lte.next_hop_chaining_count;
}
usim->generate_as_keys_ho(mob_reconf.mob_ctrl_info.target_pci, phy->get_current_earfcn(),
ncc,
k_rrc_enc, k_rrc_int, k_up_enc, k_up_int, cipher_algo, integ_algo);
pdcp->config_security(1, k_rrc_enc, k_rrc_int, cipher_algo, integ_algo);
send_rrc_con_reconfig_complete(NULL);
@ -968,7 +979,8 @@ void rrc::handle_rrc_con_reconfig(uint32_t lcid, LIBLTE_RRC_CONNECTION_RECONFIGU
if (reconfig->mob_ctrl_info_present) {
rrc_log->info("Received HO command to target PCell=%d\n", reconfig->mob_ctrl_info.target_pci);
rrc_log->console("Received HO command to target PCell=%d\n", reconfig->mob_ctrl_info.target_pci);
rrc_log->console("Received HO command to target PCell=%d, NCC=%d\n",
reconfig->mob_ctrl_info.target_pci, reconfig->sec_cnfg_ho.intra_lte.next_hop_chaining_count);
// store mobilityControlInfo
memcpy(&mob_reconf, reconfig, sizeof(LIBLTE_RRC_CONNECTION_RECONFIGURATION_STRUCT));
@ -1126,6 +1138,21 @@ void rrc::handle_sib3()
{
rrc_log->info("SIB3 received\n");
LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_3_STRUCT *sib3 = &current_cell->sib3;
// cellReselectionInfoCommon
cell_resel_cfg.q_hyst = liblte_rrc_q_hyst_num[sib3->q_hyst];
// cellReselectionServingFreqInfo
cell_resel_cfg.threshservinglow = 2*sib3->thresh_serving_low;
// intraFreqCellReselectionInfo
cell_resel_cfg.Qrxlevmin = 2*sib3->q_rx_lev_min;
if (sib3->s_intra_search_present) {
cell_resel_cfg.s_intrasearchP = 2*sib3->s_intra_search;
} else {
cell_resel_cfg.s_intrasearchP = INFINITY;
}
}
@ -2055,16 +2082,19 @@ void rrc::rrc_meas::L3_filter(meas_value_t *value, float values[NOF_MEASUREMENTS
void rrc::rrc_meas::new_phy_meas(uint32_t earfcn, uint32_t pci, float rsrp, float rsrq, uint32_t tti)
{
log_h->info("MEAS: New measurement earfcn=%d, pci=%d, rsrp=%f, rsrq=%f, tti=%d\n", earfcn, pci, rsrp, rsrq, tti);
float values[NOF_MEASUREMENTS] = {rsrp, rsrq};
// This indicates serving cell
if (earfcn == 0) {
log_h->info("MEAS: New measurement serving cell, rsrp=%f, rsrq=%f, tti=%d\n", rsrp, rsrq, tti);
L3_filter(&pcell_measurement, values);
} else {
// Add to known cells
parent->add_neighbour_cell(earfcn, pci, rsrp);
log_h->info("MEAS: New measurement earfcn=%d, pci=%d, rsrp=%f, rsrq=%f, tti=%d\n", earfcn, pci, rsrp, rsrq, tti);
// Save PHY measurement for all active measurements whose earfcn/pci matches
for(std::map<uint32_t, meas_t>::iterator iter=active.begin(); iter!=active.end(); ++iter) {
meas_t *m = &iter->second;

@ -244,6 +244,8 @@ void usim::generate_as_keys(uint8_t *k_asme,
count_ul,
k_enb);
memcpy(this->k_asme, k_asme, 32);
// Generate K_rrc_enc and K_rrc_int
security_generate_k_rrc( k_enb,
cipher_algo,
@ -257,10 +259,13 @@ void usim::generate_as_keys(uint8_t *k_asme,
integ_algo,
k_up_enc,
k_up_int);
current_ncc = 0;
}
void usim::generate_as_keys_ho(uint32_t pci,
uint32_t earfcn,
int ncc,
uint8_t *k_rrc_enc,
uint8_t *k_rrc_int,
uint8_t *k_up_enc,
@ -268,13 +273,39 @@ void usim::generate_as_keys_ho(uint32_t pci,
CIPHERING_ALGORITHM_ID_ENUM cipher_algo,
INTEGRITY_ALGORITHM_ID_ENUM integ_algo)
{
uint8_t *enb_star_key = k_enb;
if (ncc < 0) {
ncc = current_ncc;
}
// Generate successive NH
while(current_ncc != (uint32_t) ncc) {
uint8_t *sync = NULL;
if (current_ncc) {
sync = nh;
} else {
sync = k_enb;
}
// Generate NH
security_generate_nh(k_asme,
sync,
nh);
current_ncc++;
if (current_ncc == 7) {
current_ncc = 0;
}
enb_star_key = nh;
}
// Generate K_enb
security_generate_k_enb_star( k_enb,
security_generate_k_enb_star( enb_star_key,
pci,
earfcn,
k_enb_star);
// K_enb becomes K_enb*
memcpy(k_enb, k_enb_star, 32);
// Generate K_rrc_enc and K_rrc_int

Loading…
Cancel
Save