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 ((nframes%100) == 0 || rx_gain_offset == 0) {
if (srslte_rf_has_rssi(&rf)) { 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 { } else {
rx_gain_offset = srslte_rf_get_rx_gain(&rf); 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, uint32_t earfcn,
uint8 *k_enb_star); 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 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_enc,
uint8 *k_nas_int); uint8 *k_nas_int);
/********************************************************************* /*********************************************************************
Name: liblte_security_generate_k_rrc Name: liblte_security_generate_k_rrc

@ -81,6 +81,10 @@ uint8_t security_generate_k_enb_star( uint8_t *k_enb,
uint32_t earfcn, uint32_t earfcn,
uint8_t *k_enb_star); 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, uint8_t security_generate_k_nas( uint8_t *k_asme,
CIPHERING_ALGORITHM_ID_ENUM enc_alg_id, CIPHERING_ALGORITHM_ID_ENUM enc_alg_id,
INTEGRITY_ALGORITHM_ID_ENUM int_alg_id, INTEGRITY_ALGORITHM_ID_ENUM int_alg_id,

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

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

@ -335,6 +335,34 @@ LIBLTE_ERROR_ENUM liblte_security_generate_k_enb_star(uint8 *k_enb,
return (err); 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 Name: liblte_security_generate_k_nas

@ -72,6 +72,15 @@ uint8_t security_generate_k_enb_star( uint8_t *k_enb,
k_enb_star); 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, uint8_t security_generate_k_nas( uint8_t *k_asme,
CIPHERING_ALGORITHM_ID_ENUM enc_alg_id, CIPHERING_ALGORITHM_ID_ENUM enc_alg_id,
INTEGRITY_ALGORITHM_ID_ENUM int_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); 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 // 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; peak_pos = 0 ;//peak_pos + q->decimate*(2);// replace 2 with q->filter_size -2;
} }
if (peak_pos < 0) { if (peak_pos < 0) {
@ -591,7 +590,7 @@ 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))) { 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) { if (q->mean_cfo2_isunset) {
@ -600,8 +599,6 @@ srslte_sync_find_ret_t srslte_sync_find(srslte_sync_t *q, cf_t *input, uint32_t
} else { } else {
q->mean_cfo2 = SRSLTE_VEC_EMA(cfo2, q->mean_cfo2, q->cfo_ema_alpha); q->mean_cfo2 = SRSLTE_VEC_EMA(cfo2, q->mean_cfo2, q->cfo_ema_alpha);
} }
} else {
ret = SRSLTE_SYNC_FOUND_NOSPACE;
} }
} }
} else { } 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) 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 */ /* Run FFT for all subframe data */
for (int j=0;j<q->nof_rx_antennas;j++) { for (int j=0;j<q->nof_rx_antennas;j++) {

@ -682,6 +682,7 @@ 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; q->sf_idx = (q->sf_idx + q->nof_recv_sf) % 10;
#ifndef DO_CFO_IN_SYNC #ifndef DO_CFO_IN_SYNC
if (q->correct_cfo) {
/* We found that CP-based correction performs better in low SNR than PSS-based. /* We found that CP-based correction performs better in low SNR than PSS-based.
* *
* Estimate, average and correct here instead of inside sync object * Estimate, average and correct here instead of inside sync object
@ -695,6 +696,7 @@ int srslte_ue_sync_zerocopy_multi(srslte_ue_sync_t *q, cf_t *input_buffer[SRSLTE
q->mean_cfo = SRSLTE_VEC_EMA(q->cfo, q->mean_cfo, q->cfo_ema_alpha); 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 #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++; 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; break;
} }

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

@ -167,7 +167,7 @@ private:
void set_cell(srslte_cell_t cell); void set_cell(srslte_cell_t cell);
ret_code run_subframe(uint32_t sf_idx); 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_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 rsrp();
float rsrq(); float rsrq();
float snr(); float snr();
@ -205,6 +205,7 @@ private:
srslte::log *log_h; srslte::log *log_h;
srslte_sync_t sync_find; srslte_sync_t sync_find;
uint32_t current_fft_sz;
measure measure_p; measure measure_p;
}; };

@ -205,8 +205,10 @@ private:
LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_13_STRUCT sib13; LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_13_STRUCT sib13;
} cell_t; } 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; cell_t *current_cell;
void add_new_cell(uint32_t earfcn, srslte_cell_t phy_cell, float rsrp);
typedef enum { typedef enum {
SI_ACQUIRE_IDLE = 0, SI_ACQUIRE_IDLE = 0,
@ -353,7 +355,6 @@ private:
float Qqualmin; float Qqualmin;
float Qqualminoffset; float Qqualminoffset;
float s_intrasearchP; float s_intrasearchP;
float s_intrasearchQ;
float q_hyst; float q_hyst;
float threshservinglow; float threshservinglow;

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

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

@ -52,6 +52,7 @@ phch_recv::phch_recv() {
ul_freq = -1; ul_freq = -1;
bzero(&cell, sizeof(srslte_cell_t)); bzero(&cell, sizeof(srslte_cell_t));
running = false; running = false;
worker_com = NULL;
} }
void phch_recv::init(srslte::radio_multi *_radio_handler, mac_interface_phy *_mac, rrc_interface_phy *_rrc, void phch_recv::init(srslte::radio_multi *_radio_handler, mac_interface_phy *_mac, rrc_interface_phy *_rrc,
@ -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); int sync_res = srslte_ue_sync_zerocopy_multi(ue_sync, buffer);
if (sync_res == 1) { if (sync_res == 1) {
log_h->info("SYNC: CFO=%.1f KHz\n", srslte_ue_sync_get_cfo(ue_sync));
return run_subframe(sf_idx); return run_subframe(sf_idx);
} else { } else {
log_h->error("SYNC: Measuring RSRP: Sync error\n"); log_h->error("SYNC: Measuring RSRP: Sync error\n");
@ -1034,20 +1036,63 @@ 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, phch_recv::measure::ret_code phch_recv::measure::run_multiple_subframes(cf_t *input_buffer,
uint32_t offset,
uint32_t sf_idx, uint32_t sf_idx,
uint32_t nof_sf) uint32_t max_sf)
{ {
uint32_t sf_len = SRSLTE_SF_LEN_PRB(current_prb); uint32_t sf_len = SRSLTE_SF_LEN_PRB(current_prb);
ret_code ret = IDLE; ret_code ret = IDLE;
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++) { for (uint32_t i=0;i<nof_sf;i++) {
memcpy(buffer[0], &input_buffer[i*sf_len], sizeof(cf_t)*sf_len); memcpy(buffer[0], &input_buffer[offset+i*sf_len], sizeof(cf_t)*sf_len);
ret = run_subframe((sf_idx+i)%10); ret = run_subframe((sf_idx+i)%10);
if (ret != IDLE) { if (ret != IDLE) {
return ret; return ret;
} }
} }
}
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); 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"); fprintf(stderr, "Error initiating sync_find\n");
return; return;
} }
srslte_sync_cp_en(&sync_find, false); 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_cfo_ema_alpha(&sync_find, 0.8);
srslte_sync_set_threshold(&sync_find, 1.2); srslte_sync_set_threshold(&sync_find, 1.2);
srslte_sync_set_em_alpha(&sync_find, 0.0);
reset(); reset();
} }
void phch_recv::scell_recv::reset() void phch_recv::scell_recv::reset()
{ {
current_fft_sz = 0;
measure_p.reset(); 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); uint32_t sf_len = SRSLTE_SF_LEN(fft_sz);
if (fft_sz != current_fft_sz) {
if (srslte_sync_resize(&sync_find, nof_sf*sf_len, 5*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"); fprintf(stderr, "Error resizing sync\n");
return SRSLTE_ERROR; return SRSLTE_ERROR;
} }
current_fft_sz = fft_sz;
}
srslte_sync_reset(&sync_find);
int nof_cells = 0; int nof_cells = 0;
uint32_t peak_idx = 0; uint32_t peak_idx = 0;
uint32_t sf_idx = 0; uint32_t sf_idx = 0;
uint32_t cell_id = 0; uint32_t cell_id = 0;
uint32_t rem_sf = 0;
int offset = 0;
srslte_cell_t found_cell; 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); measure_p.set_rx_gain_offset(rx_gain_offset);
for (uint32_t n_id_2=0;n_id_2<3;n_id_2++) { 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); 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); srslte_sync_find_ret_t sync_res = srslte_sync_find(&sync_find, input_buffer, 0, &peak_idx);
switch(sync_res) { switch(sync_res) {
@ -1160,6 +1212,7 @@ int phch_recv::scell_recv::find_cells(cf_t *input_buffer, float rx_gain_offset,
case SRSLTE_SYNC_FOUND: case SRSLTE_SYNC_FOUND:
sf_idx = srslte_sync_get_sf_idx(&sync_find); sf_idx = srslte_sync_get_sf_idx(&sync_find);
cell_id = srslte_sync_get_cell_id(&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); peak_idx, n_id_2, cell_id, sf_idx);
@ -1167,27 +1220,21 @@ int phch_recv::scell_recv::find_cells(cf_t *input_buffer, float rx_gain_offset,
found_cell.nof_ports = 1; // Use port 0 only for measurement found_cell.nof_ports = 1; // Use port 0 only for measurement
measure_p.set_cell(found_cell); measure_p.set_cell(found_cell);
offset = peak_idx-sf_len/2; //printf("cell_id=%d, correcting cfo=%f Hz\n", cell_id, 15000*sync_find.mean_cfo2);
if (offset < 0) { //srslte_cfo_correct(&sync_find.cfocorr, input_buffer, input_buffer, -sync_find.mean_cfo2 / sync_find.fft_size);
offset += sf_len;
sf_idx ++;
}
rem_sf = (sf_len*nof_sf - offset)/sf_len; switch(measure_p.run_multiple_subframes(input_buffer, peak_idx, sf_idx, nof_sf)) {
switch(measure_p.run_multiple_subframes(&input_buffer[offset], sf_idx, rem_sf)) {
case measure::MEASURE_OK: case measure::MEASURE_OK:
cells[nof_cells].pci = found_cell.id; cells[nof_cells].pci = found_cell.id;
cells[nof_cells].rsrp = measure_p.rsrp(); cells[nof_cells].rsrp = measure_p.rsrp();
cells[nof_cells].rsrq = measure_p.rsrq(); cells[nof_cells].rsrq = measure_p.rsrq();
cells[nof_cells].offset = offset; cells[nof_cells].offset = peak_idx;
nof_cells++; nof_cells++;
break; break;
case measure::ERROR: case measure::ERROR:
Error("Measuring neighbour cell\n"); Error("Measuring neighbour cell\n");
return SRSLTE_ERROR; return SRSLTE_ERROR;
default: default:
printf("torna idle\n");
break; break;
} }
break; break;
@ -1212,8 +1259,10 @@ int phch_recv::scell_recv::find_cells(cf_t *input_buffer, float rx_gain_offset,
void phch_recv::meas_reset() { void phch_recv::meas_reset() {
// Stop all measurements // Stop all measurements
intra_freq_meas.clear_cells(); intra_freq_meas.clear_cells();
if (worker_com) {
worker_com->pcell_meas_enabled = false; worker_com->pcell_meas_enabled = false;
} }
}
int phch_recv::meas_start(uint32_t earfcn, int pci) { int phch_recv::meas_start(uint32_t earfcn, int pci) {
if (earfcn == current_earfcn) { if (earfcn == current_earfcn) {
@ -1318,12 +1367,12 @@ void phch_recv::intra_measure::write(uint32_t tti, cf_t *data, uint32_t nsamples
receiving = true; receiving = true;
receive_cnt = 0; receive_cnt = 0;
measure_tti = tti; measure_tti = tti;
srslte_ringbuffer_reset(&ring_buffer);
} }
if (receiving == true) { if (receiving == true) {
if (srslte_ringbuffer_write(&ring_buffer, data, nsamples*sizeof(cf_t)) < (int) (nsamples*sizeof(cf_t))) { if (srslte_ringbuffer_write(&ring_buffer, data, nsamples*sizeof(cf_t)) < (int) (nsamples*sizeof(cf_t))) {
Warning("Error writing to ringbuffer\n"); Warning("Error writing to ringbuffer\n");
receiving = false; receiving = false;
srslte_ringbuffer_reset(&ring_buffer);
} else { } else {
receive_cnt++; receive_cnt++;
if (receive_cnt == CAPTURE_LEN_SF) { if (receive_cnt == CAPTURE_LEN_SF) {
@ -1345,11 +1394,10 @@ void phch_recv::intra_measure::run_thread()
if (running) { 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)); 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); int found_cells = scell.find_cells(search_buffer, common->rx_gain_offset, primary_cell, CAPTURE_LEN_SF, info);
receiving = false; receiving = false;
srslte_ringbuffer_reset(&ring_buffer);
for (int i=0;i<found_cells;i++) { 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); 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 */ /* 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 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) { 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"); log_h->debug("SYNC: Sending in-sync to RRC\n");
} else { } else {
phy->rrc->out_of_sync(); 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))); 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 #endif
uint8_t dummy[2] = {0,0}; 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, (tti+HARQ_DELAY_MS)%10240,
grant->n_prb[0], grant->n_prb[0]+grant->L_prb, grant->n_prb[0], grant->n_prb[0]+grant->L_prb,
grant->mcs.tbs/8, grant->mcs.idx, rv, 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) { if (tti== 0 || phy->rx_gain_offset == 0) {
float rx_gain_offset = 0; float rx_gain_offset = 0;
if (phy->get_radio()->has_rssi() && phy->args->rssi_sensor_enabled) { if (phy->get_radio()->has_rssi() && phy->args->rssi_sensor_enabled) {
float rssi_all_signal = srslte_chest_dl_get_rssi(&ue_dl.chest); float rssi_all_signal = 30+10*log10(srslte_vec_avg_power_cf(signal_buffer[0],SRSLTE_SF_LEN(srslte_symbol_sz(cell.nof_prb))));
if (rssi_all_signal) { rx_gain_offset = 30+rssi_all_signal-phy->get_radio()->get_rssi();
rx_gain_offset = 10*log10(rssi_all_signal)-phy->get_radio()->get_rssi();
} else {
rx_gain_offset = 0;
}
} else { } else {
rx_gain_offset = phy->get_radio()->get_rx_gain(); rx_gain_offset = phy->get_radio()->get_rx_gain();
} }
if (phy->rx_gain_offset) { 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 { } else {
phy->rx_gain_offset = rx_gain_offset; phy->rx_gain_offset = rx_gain_offset;
} }
} }
// Average RSRQ // Average RSRQ
float cur_rsrq = 10*log10(srslte_chest_dl_get_rsrq(&ue_dl.chest)); float rsrq_db = 10*log10(srslte_chest_dl_get_rsrq(&ue_dl.chest));
if (isnormal(cur_rsrq)) { if (isnormal(rsrq_db)) {
phy->avg_rsrq_db = SRSLTE_VEC_EMA(phy->avg_rsrq_db, cur_rsrq, snr_ema_coeff); phy->avg_rsrq_db = SRSLTE_VEC_EMA(rsrq_db, phy->avg_rsrq_db, snr_ema_coeff);
} }
// Average RSRP // Average RSRP
float cur_rsrp = srslte_chest_dl_get_rsrp(&ue_dl.chest); float rsrp_lin = srslte_chest_dl_get_rsrp(&ue_dl.chest);
if (isnormal(cur_rsrp)) { if (isnormal(rsrp_lin)) {
phy->avg_rsrp = SRSLTE_VEC_EMA(phy->avg_rsrp, cur_rsrp, snr_ema_coeff); phy->avg_rsrp = SRSLTE_VEC_EMA(rsrp_lin, phy->avg_rsrp, snr_ema_coeff);
} }
/* Correct absolute power measurements by RX gain offset */ /* 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 rsrp_dbm = 10*log10(rsrp_lin) + 30 - phy->rx_gain_offset;
float rssi = 10*log10(srslte_chest_dl_get_rssi(&ue_dl.chest)) + 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 // Serving cell measurements are averaged over DEFAULT_MEAS_PERIOD_MS then sent to RRC
if (isnormal(rsrp)) { if (isnormal(rsrp_dbm)) {
if (!phy->avg_rsrp_db) { if (!phy->avg_rsrp_dbm) {
phy->avg_rsrp_db = rsrp; phy->avg_rsrp_dbm= rsrp_dbm;
} else { } 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) { 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 // Compute PL
float tx_crs_power = phy->config->common.pdsch_cnfg.rs_power; 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 // Average noise
float cur_noise = srslte_chest_dl_get_noise_estimate(&ue_dl.chest); 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) { if (!phy->avg_noise) {
phy->avg_noise = cur_noise; phy->avg_noise = cur_noise;
} else { } 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 // Store metrics
dl_metrics.n = phy->avg_noise; 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.rsrq = phy->avg_rsrq_db;
dl_metrics.rssi = rssi; dl_metrics.rssi = rssi_db;
dl_metrics.pathloss = phy->pathloss; dl_metrics.pathloss = phy->pathloss;
dl_metrics.sinr = phy->avg_snr_db; dl_metrics.sinr = phy->avg_snr_db;
dl_metrics.turbo_iters = srslte_pdsch_last_noi(&ue_dl.pdsch); 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; state = RRC_STATE_IDLE;
si_acquire_state = SI_ACQUIRE_IDLE; si_acquire_state = SI_ACQUIRE_IDLE;
bzero(known_cells, MAX_KNOWN_CELLS*sizeof(cell_t));
thread_running = true; thread_running = true;
start(); start();
@ -433,7 +435,7 @@ void rrc::plmn_select(LIBLTE_RRC_PLMN_IDENTITY_STRUCT plmn_id) {
} }
void rrc::select_next_cell_in_plmn() { 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++) { 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 || 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) { 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) { void rrc::cell_found(uint32_t earfcn, srslte_cell_t phy_cell, float rsrp) {
// find if cell_id-earfcn combination already exists // 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) { if (earfcn == known_cells[i].earfcn && phy_cell.id == known_cells[i].phy_cell.id) {
current_cell = &known_cells[i]; current_cell = &known_cells[i];
current_cell->rsrp = rsrp; 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 // add to list of known cells
cell_t cell; add_new_cell(earfcn, phy_cell, rsrp);
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();
si_acquire_state = SI_ACQUIRE_SIB1; 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); 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 // PHY indicates that has gone through all known EARFCN
void rrc::earfcn_end() { void rrc::earfcn_end() {
rrc_log->debug("Finished searching cells in EARFCN set while in state %s\n", rrc_state_text[state]); 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) { 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) { if (earfcn == known_cells[i].earfcn && pci == known_cells[i].phy_cell.id) {
known_cells[i].rsrp = rsrp; known_cells[i].rsrp = rsrp;
return; return;
} }
} }
rrc_log->info("Added neighbour cell earfcn=%d, pci=%d, rsrp=%f\n", earfcn, pci, rsrp); rrc_log->info("Added neighbour cell earfcn=%d, pci=%d, rsrp=%f\n", earfcn, pci, rsrp);
cell_t c;
bzero(&c, sizeof(cell_t)); srslte_cell_t cell;
c.earfcn = earfcn; cell = current_cell->phy_cell;
c.rsrp = rsrp; cell.id = pci;
memcpy(&c.phy_cell, &current_cell->phy_cell, sizeof(srslte_cell_t)); add_new_cell(earfcn, cell, rsrp);
c.phy_cell.id = pci;
known_cells.push_back(c);
} }
// Cell reselection in IDLE Section 5.2.4 of 36.304 // 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 // 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 // UE may not perform intra-frequency measurements
phy->meas_reset(); phy->meas_reset();
} else { } else {
@ -900,9 +908,7 @@ void rrc::ho_prepare() {
apply_rr_config_common_dl(&mob_reconf.mob_ctrl_info.rr_cnfg_common); apply_rr_config_common_dl(&mob_reconf.mob_ctrl_info.rr_cnfg_common);
bool found = false; bool found = false;
for (uint32_t i = 0; i < known_cells.size(); i++) { for (uint32_t i = 0; i < MAX_KNOWN_CELLS && known_cells[i].earfcn; 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);
if (known_cells[i].earfcn == phy->get_current_earfcn() && if (known_cells[i].earfcn == phy->get_current_earfcn() &&
known_cells[i].phy_cell.id == mob_reconf.mob_ctrl_info.target_pci) { 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); 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(); 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(), 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); 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); pdcp->config_security(1, k_rrc_enc, k_rrc_int, cipher_algo, integ_algo);
send_rrc_con_reconfig_complete(NULL); 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) { 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->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 // store mobilityControlInfo
memcpy(&mob_reconf, reconfig, sizeof(LIBLTE_RRC_CONNECTION_RECONFIGURATION_STRUCT)); memcpy(&mob_reconf, reconfig, sizeof(LIBLTE_RRC_CONNECTION_RECONFIGURATION_STRUCT));
@ -1126,6 +1138,21 @@ void rrc::handle_sib3()
{ {
rrc_log->info("SIB3 received\n"); 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) 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}; float values[NOF_MEASUREMENTS] = {rsrp, rsrq};
// This indicates serving cell // This indicates serving cell
if (earfcn == 0) { 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); L3_filter(&pcell_measurement, values);
} else { } else {
// Add to known cells // Add to known cells
parent->add_neighbour_cell(earfcn, pci, rsrp); 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 // 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) { for(std::map<uint32_t, meas_t>::iterator iter=active.begin(); iter!=active.end(); ++iter) {
meas_t *m = &iter->second; meas_t *m = &iter->second;

@ -244,6 +244,8 @@ void usim::generate_as_keys(uint8_t *k_asme,
count_ul, count_ul,
k_enb); k_enb);
memcpy(this->k_asme, k_asme, 32);
// Generate K_rrc_enc and K_rrc_int // Generate K_rrc_enc and K_rrc_int
security_generate_k_rrc( k_enb, security_generate_k_rrc( k_enb,
cipher_algo, cipher_algo,
@ -257,10 +259,13 @@ void usim::generate_as_keys(uint8_t *k_asme,
integ_algo, integ_algo,
k_up_enc, k_up_enc,
k_up_int); k_up_int);
current_ncc = 0;
} }
void usim::generate_as_keys_ho(uint32_t pci, void usim::generate_as_keys_ho(uint32_t pci,
uint32_t earfcn, uint32_t earfcn,
int ncc,
uint8_t *k_rrc_enc, uint8_t *k_rrc_enc,
uint8_t *k_rrc_int, uint8_t *k_rrc_int,
uint8_t *k_up_enc, uint8_t *k_up_enc,
@ -268,13 +273,39 @@ void usim::generate_as_keys_ho(uint32_t pci,
CIPHERING_ALGORITHM_ID_ENUM cipher_algo, CIPHERING_ALGORITHM_ID_ENUM cipher_algo,
INTEGRITY_ALGORITHM_ID_ENUM integ_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 // Generate K_enb
security_generate_k_enb_star( k_enb, security_generate_k_enb_star( enb_star_key,
pci, pci,
earfcn, earfcn,
k_enb_star); k_enb_star);
// K_enb becomes K_enb*
memcpy(k_enb, k_enb_star, 32); memcpy(k_enb, k_enb_star, 32);
// Generate K_rrc_enc and K_rrc_int // Generate K_rrc_enc and K_rrc_int

Loading…
Cancel
Save