X2 (constant NCC) working

master
Ismael Gomez 7 years ago
parent 12d8b373c7
commit 408545dab8

@ -293,7 +293,7 @@ int main(int argc, char **argv) {
return -1;
}
srslte_rf_start_rx_stream(&rf);
srslte_rf_start_rx_stream(&rf, false);
float rx_gain_offset = 0;

@ -219,7 +219,7 @@ int main(int argc, char **argv) {
INFO("Setting sampling frequency %.2f MHz for PSS search\n", SRSLTE_CS_SAMP_FREQ/1000000);
srslte_rf_set_rx_srate(&rf, SRSLTE_CS_SAMP_FREQ);
INFO("Starting receiver...\n", 0);
srslte_rf_start_rx_stream(&rf);
srslte_rf_start_rx_stream(&rf, false);
n = srslte_ue_cellsearch_scan(&cs, found_cells, NULL);
if (n < 0) {

@ -552,7 +552,7 @@ int main(int argc, char **argv) {
#ifndef DISABLE_RF
if (!prog_args.input_file_name) {
srslte_rf_start_rx_stream(&rf);
srslte_rf_start_rx_stream(&rf, false);
}
#endif

@ -153,7 +153,7 @@ int main(int argc, char **argv) {
printf("Correctly RX rate: %.2f MHz\n", srate*1e-6);
srslte_rf_rx_wait_lo_locked(&rf);
srslte_rf_start_rx_stream(&rf);
srslte_rf_start_rx_stream(&rf, false);
while((sample_count < nof_samples || nof_samples == -1)

@ -158,7 +158,7 @@ int main(int argc, char **argv) {
exit(-1);
}
srslte_rf_rx_wait_lo_locked(&rf);
srslte_rf_start_rx_stream(&rf);
srslte_rf_start_rx_stream(&rf, false);
cell.cp = SRSLTE_CP_NORM;
cell.id = N_id_2;

@ -175,7 +175,7 @@ int main(int argc, char **argv) {
srslte_timestamp_t tstamp;
srslte_rf_start_rx_stream(&rf);
srslte_rf_start_rx_stream(&rf, false);
uint32_t nframe=0;

@ -2684,6 +2684,7 @@ typedef enum{
}LIBLTE_RRC_T304_ENUM;
static const char liblte_rrc_t304_text[LIBLTE_RRC_T304_N_ITEMS][20] = { "50", "100", "150", "200",
"500", "1000", "2000", "SPARE"};
static const int32 liblte_rrc_t304_num[LIBLTE_RRC_T304_N_ITEMS] = {50, 100, 150, 200, 500, 1000, 2000, -1};
// Structs
typedef struct{
uint8 p_b;

@ -86,6 +86,11 @@ LIBLTE_ERROR_ENUM liblte_security_generate_k_enb(uint8 *k_asme,
uint32 nas_count,
uint8 *k_enb);
LIBLTE_ERROR_ENUM liblte_security_generate_k_enb_star(uint8 *k_enb,
uint32 pci,
uint32_t earfcn,
uint8 *k_enb_star);
/*********************************************************************
Name: liblte_security_generate_k_nas

@ -39,6 +39,9 @@ public:
void enable(bool en);
void open(const char *filename, uint32_t ue_id = 0);
void close();
void set_ue_id(uint16_t ue_id);
void write_ul_crnti(uint8_t *pdu, uint32_t pdu_len_bytes, uint16_t crnti, uint32_t reTX, uint32_t tti);
void write_dl_crnti(uint8_t *pdu, uint32_t pdu_len_bytes, uint16_t crnti, bool crc_ok, uint32_t tti);
void write_dl_ranti(uint8_t *pdu, uint32_t pdu_len_bytes, uint16_t ranti, bool crc_ok, uint32_t tti);

@ -76,6 +76,11 @@ uint8_t security_generate_k_enb( uint8_t *k_asme,
uint32_t nas_count,
uint8_t *k_enb);
uint8_t security_generate_k_enb_star( uint8_t *k_enb,
uint32_t pci,
uint32_t earfcn,
uint8_t *k_enb_star);
uint8_t security_generate_k_nas( uint8_t *k_asme,
CIPHERING_ALGORITHM_ID_ENUM enc_alg_id,
INTEGRITY_ALGORITHM_ID_ENUM int_alg_id,

@ -147,6 +147,7 @@ public:
/* PDCP calls RLC to push an RLC SDU. SDU gets placed into the RLC buffer and MAC pulls
* RLC PDUs according to TB size. */
virtual void write_sdu(uint16_t rnti, uint32_t lcid, srslte::byte_buffer_t *sdu) = 0;
virtual bool rb_is_um(uint16_t rnti, uint32_t lcid) = 0;
};
// RLC interface for RRC

@ -78,6 +78,14 @@ public:
uint8_t *k_up_int,
srslte::CIPHERING_ALGORITHM_ID_ENUM cipher_algo,
srslte::INTEGRITY_ALGORITHM_ID_ENUM integ_algo) = 0;
virtual void generate_as_keys_ho(uint32_t pci,
uint32_t earfcn,
uint8_t *k_rrc_enc,
uint8_t *k_rrc_int,
uint8_t *k_up_enc,
uint8_t *k_up_int,
srslte::CIPHERING_ALGORITHM_ID_ENUM cipher_algo,
srslte::INTEGRITY_ALGORITHM_ID_ENUM integ_algo) = 0;
};
// GW interface for NAS
@ -133,6 +141,7 @@ public:
class rrc_interface_mac : public rrc_interface_mac_common
{
public:
virtual void ho_ra_completed(bool ra_successful) = 0;
virtual void release_pucch_srs() = 0;
virtual void run_tti(uint32_t tti) = 0;
};
@ -192,6 +201,7 @@ public:
class pdcp_interface_rrc
{
public:
virtual void reestablish() = 0;
virtual void reset() = 0;
virtual void write_sdu(uint32_t lcid, srslte::byte_buffer_t *sdu) = 0;
virtual void add_bearer(uint32_t lcid, srslte::srslte_pdcp_config_t cnfg = srslte::srslte_pdcp_config_t()) = 0;
@ -218,6 +228,7 @@ class rlc_interface_rrc
{
public:
virtual void reset() = 0;
virtual void reestablish() = 0;
virtual void add_bearer(uint32_t lcid) = 0;
virtual void add_bearer(uint32_t lcid, srslte::srslte_rlc_config_t cnfg) = 0;
};
@ -229,6 +240,7 @@ public:
/* PDCP calls RLC to push an RLC SDU. SDU gets placed into the RLC buffer and MAC pulls
* RLC PDUs according to TB size. */
virtual void write_sdu(uint32_t lcid, srslte::byte_buffer_t *sdu) = 0;
virtual bool rb_is_um(uint32_t lcid) = 0;
};
//RLC interface for MAC
@ -417,10 +429,14 @@ public:
virtual void get_rntis(ue_rnti_t *rntis) = 0;
virtual void set_contention_id(uint64_t uecri) = 0;
virtual void set_ho_rnti(uint16_t crnti, uint16_t target_pci) = 0;
virtual void start_noncont_ho(uint32_t preamble_index, uint32_t prach_mask) = 0;
virtual void start_cont_ho() = 0;
virtual void reconfiguration() = 0;
virtual void reset() = 0;
virtual void wait_uplink() = 0;
};
@ -541,6 +557,7 @@ public:
virtual void cell_search_stop() = 0;
virtual void cell_search_next() = 0;
virtual bool cell_select(uint32_t earfcn, srslte_cell_t cell) = 0;
virtual bool cell_handover(srslte_cell_t cell) = 0;
/* Is the PHY downlink synchronized? */
virtual bool sync_status() = 0;

@ -95,7 +95,7 @@ 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);
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);

@ -117,7 +117,7 @@ namespace srslte {
void start_trace();
void write_trace(std::string filename);
void start_rx();
void start_rx(bool now = false);
void stop_rx();
void set_tti(uint32_t tti);

@ -54,6 +54,7 @@ public:
bool is_drb_enabled(uint32_t lcid);
// RRC interface
void reestablish();
void reset();
void write_sdu(uint32_t lcid, byte_buffer_t *sdu);
void add_bearer(uint32_t lcid, srslte_pdcp_config_t cnfg = srslte_pdcp_config_t());

@ -69,6 +69,7 @@ public:
uint32_t lcid_,
srslte_pdcp_config_t cfg_);
void reset();
void reestablish();
bool is_active();
@ -94,8 +95,8 @@ private:
uint32_t lcid;
srslte_pdcp_config_t cfg;
uint32_t rx_count;
uint32_t tx_count;
uint32_t tx_sn;
uint8_t k_rrc_enc[32];
uint8_t k_rrc_int[32];

@ -64,6 +64,7 @@ public:
// PDCP interface
void write_sdu(uint32_t lcid, byte_buffer_t *sdu);
bool rb_is_um(uint32_t lcid);
std::string get_rb_name(uint32_t lcid);
// MAC interface
@ -76,6 +77,7 @@ public:
void write_pdu_pcch(uint8_t *payload, uint32_t nof_bytes);
// RRC interface
void reestablish();
void reset();
void empty_queue();
void add_bearer(uint32_t lcid);

@ -78,6 +78,7 @@ public:
mac_interface_timers *mac_timers);
void configure(srslte_rlc_config_t cnfg);
void reset();
void reestablish();
void stop();
void empty_queue();

@ -56,6 +56,7 @@ public:
void configure(srslte_rlc_config_t cnfg);
void reset();
void reestablish();
void stop();
void empty_queue();
bool active();

@ -298,6 +298,43 @@ LIBLTE_ERROR_ENUM liblte_security_generate_k_enb(uint8 *k_asme,
return(err);
}
/*********************************************************************
Name: liblte_security_generate_k_enb_star
Description: Generate the security key Kenb*.
Document Reference: 33.401 v10.0.0 Annex A.5
*********************************************************************/
LIBLTE_ERROR_ENUM liblte_security_generate_k_enb_star(uint8 *k_enb,
uint32 pci,
uint32_t earfcn,
uint8 *k_enb_star)
{
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
uint8 s[9];
if (k_enb_star != NULL &&
k_enb != NULL) {
// Construct S
s[0] = 0x13; // FC
s[1] = (pci >> 8) & 0xFF; // First byte of P0
s[2] = pci & 0xFF; // Second byte of P0
s[3] = 0x00; // First byte of L0
s[4] = 0x02; // Second byte of L0
s[5] = (earfcn >> 8) & 0xFF; // First byte of P0
s[6] = earfcn & 0xFF; // Second byte of P0
s[7] = 0x00; // First byte of L0
s[8] = 0x02; // Second byte of L0
// Derive Kenb
sha256(k_enb, 32, s, 9, k_enb_star, 0);
err = LIBLTE_SUCCESS;
}
return (err);
}
/*********************************************************************
Name: liblte_security_generate_k_nas

@ -41,7 +41,7 @@ void mac_pcap::enable(bool en)
void mac_pcap::open(const char* filename, uint32_t ue_id)
{
pcap_file = MAC_LTE_PCAP_Open(filename);
ue_id = ue_id;
this->ue_id = ue_id;
enable_write = true;
}
void mac_pcap::close()
@ -50,6 +50,10 @@ void mac_pcap::close()
MAC_LTE_PCAP_Close(pcap_file);
}
void mac_pcap::set_ue_id(uint16_t ue_id) {
this->ue_id = ue_id;
}
void mac_pcap::pack_and_write(uint8_t* pdu, uint32_t pdu_len_bytes, uint32_t reTX, bool crc_ok, uint32_t tti,
uint16_t crnti, uint8_t direction, uint8_t rnti_type)
{

@ -61,6 +61,17 @@ uint8_t security_generate_k_enb( uint8_t *k_asme,
k_enb);
}
uint8_t security_generate_k_enb_star( uint8_t *k_enb,
uint32_t pci,
uint32_t earfcn,
uint8_t *k_enb_star)
{
return liblte_security_generate_k_enb_star(k_enb,
pci,
earfcn,
k_enb_star);
}
uint8_t security_generate_k_nas( uint8_t *k_asme,
CIPHERING_ALGORITHM_ID_ENUM enc_alg_id,
INTEGRITY_ALGORITHM_ID_ENUM int_alg_id,

@ -199,7 +199,7 @@ int main(int argc, char **argv) {
srslte_timestamp_t tstamp;
srslte_rf_start_rx_stream(&rf);
srslte_rf_start_rx_stream(&rf, false);
uint32_t nframe=0;
while(nframe<nof_frames) {

@ -101,7 +101,7 @@ int rf_blade_start_tx_stream(void *h)
return 0;
}
int rf_blade_start_rx_stream(void *h)
int rf_blade_start_rx_stream(void *h, bool now)
{
int status;
rf_blade_handler_t *handler = (rf_blade_handler_t*) h;

@ -44,7 +44,7 @@ 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);
SRSLTE_API int rf_blade_start_rx_stream(void *h, bool now);
SRSLTE_API int rf_blade_start_rx_stream_nsamples(void *h,
uint32_t nsamples);

@ -30,7 +30,7 @@ typedef struct {
const char *name;
char* (*srslte_rf_devname) (void *h);
bool (*srslte_rf_rx_wait_lo_locked) (void *h);
int (*srslte_rf_start_rx_stream)(void *h);
int (*srslte_rf_start_rx_stream)(void *h, bool now);
int (*srslte_rf_stop_rx_stream)(void *h);
void (*srslte_rf_flush_buffer)(void *h);
bool (*srslte_rf_has_rssi)(void *h);

@ -149,9 +149,9 @@ bool srslte_rf_rx_wait_lo_locked(srslte_rf_t *rf)
return ((rf_dev_t*) rf->dev)->srslte_rf_rx_wait_lo_locked(rf->handler);
}
int srslte_rf_start_rx_stream(srslte_rf_t *rf)
int srslte_rf_start_rx_stream(srslte_rf_t *rf, bool now)
{
return ((rf_dev_t*) rf->dev)->srslte_rf_start_rx_stream(rf->handler);
return ((rf_dev_t*) rf->dev)->srslte_rf_start_rx_stream(rf->handler, now);
}
int srslte_rf_stop_rx_stream(srslte_rf_t *rf)

@ -114,7 +114,7 @@ void rf_soapy_set_rx_cal(void *h, srslte_rf_cal_t *cal)
}
int rf_soapy_start_rx_stream(void *h)
int rf_soapy_start_rx_stream(void *h, bool now)
{
rf_soapy_handler_t *handler = (rf_soapy_handler_t*) h;
if(handler->rx_stream_active == false){

@ -45,7 +45,7 @@ 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);
SRSLTE_API int rf_soapy_start_rx_stream(void *h, bool now);
SRSLTE_API int rf_soapy_stop_rx_stream(void *h);

@ -219,19 +219,21 @@ void rf_uhd_set_rx_cal(void *h, srslte_rf_cal_t *cal)
}
int rf_uhd_start_rx_stream(void *h)
int rf_uhd_start_rx_stream(void *h, bool now)
{
rf_uhd_handler_t *handler = (rf_uhd_handler_t*) h;
uhd_stream_cmd_t stream_cmd = {
.stream_mode = UHD_STREAM_MODE_START_CONTINUOUS,
.stream_now = false
.stream_now = now
};
uhd_usrp_get_time_now(handler->usrp, 0, &stream_cmd.time_spec_full_secs, &stream_cmd.time_spec_frac_secs);
stream_cmd.time_spec_frac_secs += 0.1;
if (stream_cmd.time_spec_frac_secs > 1) {
stream_cmd.time_spec_frac_secs -= 1;
stream_cmd.time_spec_full_secs += 1;
if (!now) {
uhd_usrp_get_time_now(handler->usrp, 0, &stream_cmd.time_spec_full_secs, &stream_cmd.time_spec_frac_secs);
stream_cmd.time_spec_frac_secs += 0.1;
if (stream_cmd.time_spec_frac_secs > 1) {
stream_cmd.time_spec_frac_secs -= 1;
stream_cmd.time_spec_full_secs += 1;
}
}
uhd_rx_streamer_issue_stream_cmd(handler->rx_stream, &stream_cmd);
return 0;

@ -49,7 +49,8 @@ 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);
SRSLTE_API int rf_uhd_start_rx_stream(void *h,
bool now);
SRSLTE_API int rf_uhd_start_rx_stream_nsamples(void *h,
uint32_t nsamples);

@ -60,7 +60,7 @@ int rf_rssi_scan(srslte_rf_t *rf, float *freqs, float *rssi, int nof_bands, doub
srslte_rf_set_rx_freq(rf, f);
srslte_rf_rx_wait_lo_locked(rf);
usleep(10000);
srslte_rf_start_rx_stream(rf);
srslte_rf_start_rx_stream(rf, false);
/* discard first samples */
for (j=0;j<2;j++) {
@ -122,7 +122,7 @@ int rf_mib_decoder(srslte_rf_t *rf, uint32_t nof_rx_antennas,cell_search_cfg_t *
srslte_rf_set_rx_srate(rf, (float) srate);
INFO("Starting receiver...\n", 0);
srslte_rf_start_rx_stream(rf);
srslte_rf_start_rx_stream(rf, false);
// Set CFO if available
if (cfo) {
@ -184,7 +184,7 @@ int rf_cell_search(srslte_rf_t *rf, uint32_t nof_rx_antennas,
srslte_rf_set_rx_srate(rf, SRSLTE_CS_SAMP_FREQ);
INFO("Starting receiver...\n", 0);
srslte_rf_start_rx_stream(rf);
srslte_rf_start_rx_stream(rf, false);
/* Find a cell in the given N_id_2 or go through the 3 of them to find the strongest */
uint32_t max_peak_cell = 0;

@ -198,7 +198,7 @@ int main(int argc, char **argv) {
printf("N_id_2: %d\n", N_id_2);
srslte_rf_start_rx_stream(&rf);
srslte_rf_start_rx_stream(&rf, false);
printf("Frame length %d samples\n", flen);
printf("PSS detection threshold: %.2f\n", threshold);

@ -392,9 +392,9 @@ void radio::set_tx_srate(double srate)
tx_adv_sec = nsamples/cur_tx_srate;
}
void radio::start_rx()
void radio::start_rx(bool now)
{
srslte_rf_start_rx_stream(&rf_device);
srslte_rf_start_rx_stream(&rf_device, now);
}
void radio::stop_rx()

@ -53,6 +53,14 @@ void pdcp::init(srsue::rlc_interface_pdcp *rlc_, srsue::rrc_interface_pdcp *rrc_
void pdcp::stop()
{}
void pdcp::reestablish() {
for(uint32_t i=0;i<SRSLTE_N_RADIO_BEARERS;i++) {
if (pdcp_array[i].is_active()) {
pdcp_array[i].reestablish();
}
}
}
void pdcp::reset()
{
for(uint32_t i=0;i<SRSLTE_N_RADIO_BEARERS;i++) {

@ -33,7 +33,6 @@ namespace srslte {
pdcp_entity::pdcp_entity()
:active(false)
,tx_count(0)
,rx_count(0)
{
pool = byte_buffer_pool::get_instance();
}
@ -54,11 +53,23 @@ void pdcp_entity::init(srsue::rlc_interface_pdcp *rlc_,
active = true;
tx_count = 0;
rx_count = 0;
log->debug("Init %s\n", rrc->get_rb_name(lcid).c_str());
}
// Reestablishment procedure: 36.323 5.2
void pdcp_entity::reestablish() {
// For SRBs
if (cfg.is_control) {
tx_count = 0;
cfg.do_security = false;
} else {
if (rlc->rb_is_um(lcid)) {
tx_count = 0;
}
}
}
void pdcp_entity::reset()
{
active = false;
@ -80,6 +91,7 @@ void pdcp_entity::write_sdu(byte_buffer_t *sdu)
pdcp_pack_control_pdu(tx_count, sdu);
if(cfg.do_security)
{
log->info("rrc_int[0]=0x%x, tx_count=%d\n", k_rrc_int[0], tx_count);
integrity_generate(&k_rrc_int[16],
tx_count,
lcid-1,

@ -95,6 +95,14 @@ void rlc::get_metrics(rlc_metrics_t &m)
reset_metrics();
}
void rlc::reestablish() {
for(uint32_t i=0; i<SRSLTE_N_RADIO_BEARERS; i++) {
if(rlc_array[i].active()) {
rlc_array[i].reestablish();
}
}
}
void rlc::reset()
{
for(uint32_t i=0; i<SRSLTE_N_RADIO_BEARERS; i++) {
@ -123,6 +131,10 @@ void rlc::write_sdu(uint32_t lcid, byte_buffer_t *sdu)
}
}
bool rlc::rb_is_um(uint32_t lcid) {
return rlc_array[lcid].get_mode()==RLC_MODE_UM;
}
std::string rlc::get_rb_name(uint32_t lcid)
{
return rrc->get_rb_name(lcid);

@ -70,6 +70,10 @@ void rlc_entity::configure(srslte_rlc_config_t cnfg)
rlc->configure(cnfg);
}
void rlc_entity::reestablish() {
rlc->reset();
}
void rlc_entity::reset()
{
rlc->reset();

@ -68,6 +68,7 @@ private:
srsenb::rlc_interface_pdcp *rlc;
// rlc_interface_pdcp
void write_sdu(uint32_t lcid, srslte::byte_buffer_t *sdu);
bool rb_is_um(uint32_t lcid);
};
class user_interface_gtpu : public srsue::gw_interface_pdcp

@ -54,6 +54,7 @@ public:
// rlc_interface_pdcp
void write_sdu(uint16_t rnti, uint32_t lcid, srslte::byte_buffer_t *sdu);
bool rb_is_um(uint16_t rnti, uint32_t lcid);
std::string get_rb_name(uint32_t lcid);
// rlc_interface_mac

@ -124,6 +124,10 @@ void pdcp::user_interface_rlc::write_sdu(uint32_t lcid, srslte::byte_buffer_t* s
rlc->write_sdu(rnti, lcid, sdu);
}
bool pdcp::user_interface_rlc::rb_is_um(uint32_t lcid) {
return rlc->rb_is_um(rnti, lcid);
}
void pdcp::user_interface_rrc::write_pdu(uint32_t lcid, srslte::byte_buffer_t* pdu)
{
rrc->write_pdu(rnti, lcid, pdu);

@ -160,6 +160,14 @@ void rlc::write_sdu(uint16_t rnti, uint32_t lcid, srslte::byte_buffer_t* sdu)
}
}
bool rlc::rb_is_um(uint16_t rnti, uint32_t lcid) {
if (users.count(rnti)) {
return users[rnti].rlc->rb_is_um(lcid);
} else {
return false;
}
}
void rlc::user_interface::max_retx_attempted()
{
rrc->max_retx_attempted(rnti);

@ -80,6 +80,7 @@ public:
void setup_lcid(uint32_t lcid, uint32_t lcg, uint32_t priority, int PBR_x_tti, uint32_t BSD);
void reconfiguration();
void reset();
void wait_uplink();
/******** set/get MAC configuration ****************/
void set_config(mac_cfg_t *mac_cfg);
@ -89,7 +90,11 @@ public:
void set_config_sr(LIBLTE_RRC_SCHEDULING_REQUEST_CONFIG_STRUCT *sr_cfg);
void set_contention_id(uint64_t uecri);
void start_noncont_ho(uint32_t preamble_index, uint32_t prach_mask);
void start_cont_ho();
void get_rntis(ue_rnti_t *rntis);
void set_ho_rnti(uint16_t crnti, uint16_t target_pci);
void start_pcap(srslte::mac_pcap* pcap);

@ -43,164 +43,175 @@ namespace srsue {
class ra_proc : public srslte::timer_callback
{
public:
ra_proc() : rar_pdu_msg(20) {
bzero(&softbuffer_rar, sizeof(srslte_softbuffer_rx_t));
pcap = NULL;
backoff_interval_start = 0;
backoff_inteval = 0;
received_target_power_dbm = 0;
ra_rnti = 0;
current_ta = 0;
state = IDLE;
last_msg3_group = RA_GROUP_A;
msg3_transmitted = false;
first_rar_received = false;
phy_h = NULL;
log_h = NULL;
mac_cfg = NULL;
mux_unit = NULL;
demux_unit = NULL;
rrc = NULL;
transmitted_contention_id = 0;
transmitted_crnti = 0;
pdcch_to_crnti_received = PDCCH_CRNTI_NOT_RECEIVED;
started_by_pdcch = false;
rar_grant_nbytes = 0;
rar_grant_tti = 0;
msg3_flushed = false;
time_alignment_timer = NULL;
contention_resolution_timer = NULL;
};
~ra_proc();
void init(phy_interface_mac *phy_h,
rrc_interface_mac *rrc_,
srslte::log *log_h,
mac_interface_rrc::ue_rnti_t *rntis,
mac_interface_rrc::mac_cfg_t *mac_cfg,
srslte::timers::timer* time_alignment_timer_,
srslte::timers::timer* contention_resolution_timer_,
mux *mux_unit,
demux *demux_unit);
void reset();
void start_pdcch_order();
void start_mac_order(uint32_t msg_len_bits = 56);
void step(uint32_t tti);
bool is_successful();
bool is_response_error();
bool is_contention_resolution();
void harq_retx();
bool is_error();
bool in_progress();
void pdcch_to_crnti(bool contains_uplink_grant);
void timer_expired(uint32_t timer_id);
void new_grant_dl(mac_interface_phy::mac_grant_t grant, mac_interface_phy::tb_action_dl_t* action);
void tb_decoded_ok();
void start_pcap(srslte::mac_pcap* pcap);
public:
ra_proc() : rar_pdu_msg(20) {
bzero(&softbuffer_rar, sizeof(srslte_softbuffer_rx_t));
pcap = NULL;
backoff_interval_start = 0;
backoff_inteval = 0;
received_target_power_dbm = 0;
ra_rnti = 0;
current_ta = 0;
state = IDLE;
last_msg3_group = RA_GROUP_A;
msg3_transmitted = false;
first_rar_received = false;
phy_h = NULL;
log_h = NULL;
mac_cfg = NULL;
mux_unit = NULL;
demux_unit = NULL;
rrc = NULL;
transmitted_contention_id = 0;
transmitted_crnti = 0;
pdcch_to_crnti_received = PDCCH_CRNTI_NOT_RECEIVED;
started_by_pdcch = false;
rar_grant_nbytes = 0;
rar_grant_tti = 0;
msg3_flushed = false;
noncontention_enabled = false;
next_preamble_idx = 0;
next_prach_mask = 0;
time_alignment_timer = NULL;
contention_resolution_timer = NULL;
};
~ra_proc();
void init(phy_interface_mac *phy_h,
rrc_interface_mac *rrc_,
srslte::log *log_h,
mac_interface_rrc::ue_rnti_t *rntis,
mac_interface_rrc::mac_cfg_t *mac_cfg,
srslte::timers::timer* time_alignment_timer_,
srslte::timers::timer* contention_resolution_timer_,
mux *mux_unit,
demux *demux_unit);
void reset();
void start_pdcch_order();
void start_mac_order(uint32_t msg_len_bits = 56, bool is_ho = false);
void step(uint32_t tti);
bool is_successful();
bool is_response_error();
bool is_contention_resolution();
void harq_retx();
bool is_error();
bool in_progress();
void pdcch_to_crnti(bool contains_uplink_grant);
void timer_expired(uint32_t timer_id);
void new_grant_dl(mac_interface_phy::mac_grant_t grant, mac_interface_phy::tb_action_dl_t* action);
void tb_decoded_ok();
void start_noncont(uint32_t preamble_index, uint32_t prach_mask);
void start_pcap(srslte::mac_pcap* pcap);
private:
static bool uecrid_callback(void *arg, uint64_t uecri);
bool contention_resolution_id_received(uint64_t uecri);
void process_timeadv_cmd(uint32_t ta_cmd);
void step_initialization();
void step_resource_selection();
void step_preamble_transmission();
void step_pdcch_setup();
void step_response_reception();
void step_response_error();
void step_backoff_wait();
void step_contention_resolution();
void step_completition();
// Buffer to receive RAR PDU
static const uint32_t MAX_RAR_PDU_LEN = 2048;
uint8_t rar_pdu_buffer[MAX_RAR_PDU_LEN];
srslte::rar_pdu rar_pdu_msg;
// Random Access parameters provided by higher layers defined in 5.1.1
uint32_t configIndex;
uint32_t nof_preambles;
uint32_t nof_groupA_preambles;
uint32_t nof_groupB_preambles;
uint32_t messagePowerOffsetGroupB;
uint32_t messageSizeGroupA;
uint32_t responseWindowSize;
uint32_t powerRampingStep;
uint32_t preambleTransMax;
uint32_t iniReceivedTargetPower;
int delta_preamble_db;
uint32_t contentionResolutionTimer;
uint32_t maskIndex;
int preambleIndex;
uint32_t new_ra_msg_len;
// Internal variables
uint32_t preambleTransmissionCounter;
uint32_t backoff_param_ms;
uint32_t sel_maskIndex;
uint32_t sel_preamble;
uint32_t backoff_interval_start;
uint32_t backoff_inteval;
int received_target_power_dbm;
uint32_t ra_rnti;
uint32_t current_ta;
srslte_softbuffer_rx_t softbuffer_rar;
enum {
IDLE = 0,
INITIALIZATION, // Section 5.1.1
RESOURCE_SELECTION, // Section 5.1.2
PREAMBLE_TRANSMISSION, // Section 5.1.3
PDCCH_SETUP,
RESPONSE_RECEPTION, // Section 5.1.4
RESPONSE_ERROR,
BACKOFF_WAIT,
CONTENTION_RESOLUTION, // Section 5.1.5
COMPLETION, // Section 5.1.6
COMPLETION_DONE,
RA_PROBLEM // Section 5.1.5 last part
} state;
typedef enum {RA_GROUP_A, RA_GROUP_B} ra_group_t;
ra_group_t last_msg3_group;
bool msg3_transmitted;
bool first_rar_received;
void read_params();
phy_interface_mac *phy_h;
srslte::log *log_h;
mux *mux_unit;
demux *demux_unit;
srslte::mac_pcap *pcap;
rrc_interface_mac *rrc;
srslte::timers::timer *time_alignment_timer;
srslte::timers::timer *contention_resolution_timer;
mac_interface_rrc::ue_rnti_t *rntis;
mac_interface_rrc::mac_cfg_t *mac_cfg;
uint64_t transmitted_contention_id;
uint16_t transmitted_crnti;
enum {
PDCCH_CRNTI_NOT_RECEIVED = 0,
PDCCH_CRNTI_UL_GRANT,
PDCCH_CRNTI_DL_GRANT
} pdcch_to_crnti_received;
bool started_by_pdcch;
uint32_t rar_grant_nbytes;
uint32_t rar_grant_tti;
bool msg3_flushed;
bool rar_received;
static bool uecrid_callback(void *arg, uint64_t uecri);
bool contention_resolution_id_received(uint64_t uecri);
void process_timeadv_cmd(uint32_t ta_cmd);
void step_initialization();
void step_resource_selection();
void step_preamble_transmission();
void step_pdcch_setup();
void step_response_reception();
void step_response_error();
void step_backoff_wait();
void step_contention_resolution();
void step_completition();
// Buffer to receive RAR PDU
static const uint32_t MAX_RAR_PDU_LEN = 2048;
uint8_t rar_pdu_buffer[MAX_RAR_PDU_LEN];
srslte::rar_pdu rar_pdu_msg;
// Random Access parameters provided by higher layers defined in 5.1.1
uint32_t configIndex;
uint32_t nof_preambles;
uint32_t nof_groupA_preambles;
uint32_t nof_groupB_preambles;
uint32_t messagePowerOffsetGroupB;
uint32_t messageSizeGroupA;
uint32_t responseWindowSize;
uint32_t powerRampingStep;
uint32_t preambleTransMax;
uint32_t iniReceivedTargetPower;
int delta_preamble_db;
uint32_t contentionResolutionTimer;
uint32_t maskIndex;
int preambleIndex;
uint32_t new_ra_msg_len;
bool noncontention_enabled;
uint32_t next_preamble_idx;
uint32_t next_prach_mask;
// Internal variables
uint32_t preambleTransmissionCounter;
uint32_t backoff_param_ms;
uint32_t sel_maskIndex;
uint32_t sel_preamble;
uint32_t backoff_interval_start;
uint32_t backoff_inteval;
int received_target_power_dbm;
uint32_t ra_rnti;
uint32_t current_ta;
srslte_softbuffer_rx_t softbuffer_rar;
enum {
IDLE = 0,
INITIALIZATION, // Section 5.1.1
RESOURCE_SELECTION, // Section 5.1.2
PREAMBLE_TRANSMISSION, // Section 5.1.3
PDCCH_SETUP,
RESPONSE_RECEPTION, // Section 5.1.4
RESPONSE_ERROR,
BACKOFF_WAIT,
CONTENTION_RESOLUTION, // Section 5.1.5
COMPLETION, // Section 5.1.6
COMPLETION_DONE,
RA_PROBLEM // Section 5.1.5 last part
} state;
typedef enum {RA_GROUP_A, RA_GROUP_B} ra_group_t;
ra_group_t last_msg3_group;
bool msg3_transmitted;
bool first_rar_received;
void read_params();
phy_interface_mac *phy_h;
srslte::log *log_h;
mux *mux_unit;
demux *demux_unit;
srslte::mac_pcap *pcap;
rrc_interface_mac *rrc;
srslte::timers::timer *time_alignment_timer;
srslte::timers::timer *contention_resolution_timer;
mac_interface_rrc::ue_rnti_t *rntis;
mac_interface_rrc::mac_cfg_t *mac_cfg;
uint64_t transmitted_contention_id;
uint16_t transmitted_crnti;
enum {
PDCCH_CRNTI_NOT_RECEIVED = 0,
PDCCH_CRNTI_UL_GRANT,
PDCCH_CRNTI_DL_GRANT
} pdcch_to_crnti_received;
bool ra_is_ho;
bool started_by_pdcch;
uint32_t rar_grant_nbytes;
uint32_t rar_grant_tti;
bool msg3_flushed;
bool rar_received;
};
} // namespace srsue

@ -66,7 +66,8 @@ namespace srsue {
float avg_noise;
float avg_rsrp;
uint32_t serving_cell_report_period;
bool pcell_meas_enabled;
uint32_t pcell_report_period;
phch_common(uint32_t max_mutex = 3);
void init(phy_interface_rrc::phy_cfg_t *config,
@ -92,6 +93,7 @@ namespace srsue {
void set_pending_ack(uint32_t tti, uint32_t I_lowest, uint32_t n_dmrs);
bool get_pending_ack(uint32_t tti);
bool get_pending_ack(uint32_t tti, uint32_t *I_lowest, uint32_t *n_dmrs);
bool is_any_pending_ack();
void worker_end(uint32_t tti, bool tx_enable, cf_t *buffer, uint32_t nof_samples, srslte_timestamp_t tx_time);
@ -112,6 +114,7 @@ namespace srsue {
void get_sync_metrics(sync_metrics_t &m);
void reset_ul();
void reset();
private:

@ -64,6 +64,7 @@ public:
void cell_search_stop();
void cell_search_next(bool reset = false);
bool cell_select(uint32_t earfcn, srslte_cell_t cell);
bool cell_handover(srslte_cell_t cell);
void meas_reset();
int meas_start(uint32_t earfcn, int pci);
@ -97,11 +98,11 @@ private:
bool set_cell();
void cell_search_inc();
void resync_sfn(bool is_connected = false);
void resync_sfn(bool is_connected = false, bool rx_now = false);
bool stop_sync();
void stop_rx();
void start_rx();
void start_rx(bool now = false);
bool radio_is_rx;
bool radio_is_resetting;
@ -169,6 +170,7 @@ private:
float rsrp();
float rsrq();
float snr();
void set_rx_gain_offset(float rx_gain_offset);
private:
srslte::log *log_h;
srslte_ue_dl_t ue_dl;
@ -176,6 +178,7 @@ private:
uint32_t cnt;
uint32_t nof_subframes;
uint32_t current_prb;
float rx_gain_offset;
float mean_rsrp, mean_rsrq, mean_snr;
const static int RSRP_MEASURE_NOF_FRAMES = 5;
};
@ -192,7 +195,7 @@ private:
} cell_info_t;
void init(srslte::log *log_h);
void reset();
int find_cells(cf_t *input_buffer, srslte_cell_t current_cell, uint32_t nof_sf, cell_info_t found_cells[MAX_CELLS]);
int find_cells(cf_t *input_buffer, float rx_gain_offset, srslte_cell_t current_cell, uint32_t nof_sf, cell_info_t found_cells[MAX_CELLS]);
private:
const static int DEFAULT_MEASUREMENT_LEN = 10;
@ -217,6 +220,7 @@ private:
void rem_cell(int pci);
void set_primay_cell(uint32_t earfcn, srslte_cell_t cell);
void clear_cells();
int get_offset(uint32_t pci);
void write(uint32_t tti, cf_t *data, uint32_t nsamples);
private:
void run_thread();

@ -147,6 +147,7 @@ private:
srslte_cqi_periodic_cfg_t period_cqi;
srslte_ue_ul_powerctrl_t power_ctrl;
uint32_t I_sr;
bool sr_configured;
float cfo;
bool rar_cqi_request;

@ -87,6 +87,7 @@ public:
void cell_search_stop();
void cell_search_next();
bool cell_select(uint32_t earfcn, srslte_cell_t phy_cell);
bool cell_handover(srslte_cell_t cell);
void meas_reset();
int meas_start(uint32_t earfcn, int pci);

@ -101,6 +101,7 @@ public:
void new_phy_meas(float rsrp, float rsrq, uint32_t tti, uint32_t earfcn, uint32_t pci);
// MAC interface
void ho_ra_completed(bool ra_successful);
void release_pucch_srs();
void run_tti(uint32_t tti);
@ -143,6 +144,9 @@ private:
bool reestablishment_in_progress;
bool pending_mob_reconf;
LIBLTE_RRC_CONNECTION_RECONFIGURATION_STRUCT mob_reconf;
// timeouts in ms
uint32_t connecting_timeout;
@ -172,7 +176,7 @@ private:
srslte::mac_interface_timers *mac_timers;
uint32_t n310_cnt, N310;
uint32_t n311_cnt, N311;
uint32_t t301, t310, t311;
uint32_t t301, t310, t311, t304;
int ue_category;
typedef struct {
@ -189,7 +193,6 @@ private:
std::vector<cell_t> known_cells;
cell_t *current_cell;
typedef enum {
SI_ACQUIRE_IDLE = 0,
SI_ACQUIRE_SIB1,
@ -242,6 +245,7 @@ private:
void new_phy_meas(uint32_t earfcn, uint32_t pci, float rsrp, float rsrq, uint32_t tti);
void run_tti(uint32_t tti);
bool timer_expired(uint32_t timer_id);
void ho_finish();
private:
const static int NOF_MEASUREMENTS = 3;
@ -304,10 +308,12 @@ private:
bool s_measure_enabled;
float s_measure_value;
void stop_reports(meas_t *m);
void stop_reports_object(uint32_t object_id);
void remove_meas_object(uint32_t object_id);
void remove_meas_report(uint32_t report_id);
void remove_meas_id(uint32_t meas_id);
void remove_meas_id(uint32_t measId);
void remove_meas_id(std::map<uint32_t, meas_t>::iterator it);
void calculate_triggers(uint32_t tti);
void update_phy();
void L3_filter(meas_value_t *value, float rsrp[NOF_MEASUREMENTS]);
@ -334,7 +340,7 @@ private:
void send_con_setup_complete(byte_buffer_t *nas_msg);
void send_ul_info_transfer(uint32_t lcid, byte_buffer_t *sdu);
void send_security_mode_complete(uint32_t lcid, byte_buffer_t *pdu);
void send_rrc_con_reconfig_complete(uint32_t lcid, byte_buffer_t *pdu);
void send_rrc_con_reconfig_complete(byte_buffer_t *pdu);
void send_rrc_ue_cap_info(uint32_t lcid, byte_buffer_t *pdu);
// Parsers
@ -343,11 +349,15 @@ private:
void parse_dl_info_transfer(uint32_t lcid, byte_buffer_t *pdu);
// Helpers
void ho_prepare();
void add_neighbour_cell(uint32_t earfcn, uint32_t pci, float rsrp);
void rrc_connection_release();
void con_restablish_cell_reselected();
void radio_link_failure();
static void* start_sib_thread(void *rrc_);
void sib_search();
void apply_rr_config_common_dl(LIBLTE_RRC_RR_CONFIG_COMMON_STRUCT *config);
void apply_rr_config_common_ul(LIBLTE_RRC_RR_CONFIG_COMMON_STRUCT *config);
void apply_sib2_configs(LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_2_STRUCT *sib2);
void handle_con_setup(LIBLTE_RRC_CONNECTION_SETUP_STRUCT *setup);
void handle_con_reest(LIBLTE_RRC_CONNECTION_REESTABLISHMENT_STRUCT *setup);

@ -38,6 +38,8 @@ typedef enum {
RRC_STATE_CELL_SELECTED,
RRC_STATE_CONNECTING,
RRC_STATE_CONNECTED,
RRC_STATE_HO_PREPARE,
RRC_STATE_HO_PROCESS,
RRC_STATE_LEAVE_CONNECTED,
RRC_STATE_N_ITEMS,
} rrc_state_t;

@ -84,6 +84,15 @@ public:
srslte::CIPHERING_ALGORITHM_ID_ENUM cipher_algo,
srslte::INTEGRITY_ALGORITHM_ID_ENUM integ_algo);
void generate_as_keys_ho(uint32_t pci,
uint32_t earfcn,
uint8_t *k_rrc_enc,
uint8_t *k_rrc_int,
uint8_t *k_up_enc,
uint8_t *k_up_int,
srslte::CIPHERING_ALGORITHM_ID_ENUM cipher_algo,
srslte::INTEGRITY_ALGORITHM_ID_ENUM integ_algo);
private:
void gen_auth_res_milenage( uint8_t *rand,
@ -119,6 +128,7 @@ private:
uint8_t autn[16];
uint8_t k_asme[32];
uint8_t k_enb[32];
uint8_t k_enb_star[32];
bool initiated;

@ -110,6 +110,15 @@ void mac::reconfiguration()
}
void mac::wait_uplink() {
int cnt=0;
Info("Waiting to uplink...\n");
while(mux_unit.is_pending_any_sdu() && cnt<20) {
usleep(1000);
cnt++;
}
}
// Implement Section 5.9
void mac::reset()
{
@ -371,11 +380,31 @@ void mac::get_rntis(ue_rnti_t* rntis)
memcpy(rntis, &uernti, sizeof(ue_rnti_t));
}
void mac::set_ho_rnti(uint16_t crnti, uint16_t target_pci) {
phy_h->pdcch_dl_search_reset();
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);
}
}
void mac::set_contention_id(uint64_t uecri)
{
uernti.contention_id = uecri;
}
void mac::start_noncont_ho(uint32_t preamble_index, uint32_t prach_mask)
{
ra_procedure.start_noncont(preamble_index, prach_mask);
}
void mac::start_cont_ho()
{
ra_procedure.start_mac_order(56, true);
}
void mac::get_config(mac_cfg_t* mac_cfg)
{
memcpy(mac_cfg, &config, sizeof(mac_cfg_t));

@ -62,7 +62,9 @@ void mux::init(rlc_interface_mac *rlc_, srslte::log *log_h_, bsr_interface_mux *
void mux::reset()
{
lch.clear();
for (uint32_t i=0;i<lch.size();i++) {
lch[i].Bj = 0;
}
pending_crnti_ce = 0;
}
@ -164,17 +166,22 @@ uint8_t* mux::pdu_get(uint8_t *payload, uint32_t pdu_sz, uint32_t tx_tti, uint32
// Logical Channel Procedure
bool is_rar = false;
pdu_msg.init_tx(payload, pdu_sz, true);
// MAC control element for C-RNTI or data from UL-CCCH
if (!allocate_sdu(0, &pdu_msg, -1)) {
if (pending_crnti_ce) {
is_rar = true;
if (pdu_msg.new_subh()) {
if (!pdu_msg.get()->set_c_rnti(pending_crnti_ce)) {
Warning("Pending C-RNTI CE could not be inserted in MAC PDU\n");
}
}
}
} else {
is_rar = true;
}
pending_crnti_ce = 0;
@ -200,44 +207,48 @@ uint8_t* mux::pdu_get(uint8_t *payload, uint32_t pdu_sz, uint32_t tx_tti, uint32
}
}
// Update buffer states for all logical channels
int sdu_space = pdu_msg.get_sdu_space();
for (uint32_t i=0;i<lch.size();i++) {
lch[i].buffer_len = rlc->get_buffer_state(lch[i].id);
lch[i].sched_len = 0;
}
if (!is_rar) {
// Update buffer states for all logical channels
int sdu_space = pdu_msg.get_sdu_space();
for (uint32_t i=0;i<lch.size();i++) {
lch[i].buffer_len = rlc->get_buffer_state(lch[i].id);
lch[i].sched_len = 0;
Info("lch[%d].buffer_len=%d\n",i,lch[i].buffer_len);
}
// data from any Logical Channel, except data from UL-CCCH;
// first only those with positive Bj
for (uint32_t i=0;i<lch.size();i++) {
if (lch[i].id != 0) {
if (sched_sdu(&lch[i], &sdu_space, (lch[i].PBR<0)?-1:lch[i].Bj) && lch[i].PBR >= 0) {
lch[i].Bj -= lch[i].sched_len;
// data from any Logical Channel, except data from UL-CCCH;
// first only those with positive Bj
for (uint32_t i=0;i<lch.size();i++) {
if (lch[i].id != 0) {
if (sched_sdu(&lch[i], &sdu_space, (lch[i].PBR<0)?-1:lch[i].Bj) && lch[i].PBR >= 0) {
lch[i].Bj -= lch[i].sched_len;
}
}
}
}
// If resources remain, allocate regardless of their Bj value
for (uint32_t i=0;i<lch.size();i++) {
if (lch[i].id != 0) {
sched_sdu(&lch[i], &sdu_space, -1);
// If resources remain, allocate regardless of their Bj value
for (uint32_t i=0;i<lch.size();i++) {
if (lch[i].id != 0) {
sched_sdu(&lch[i], &sdu_space, -1);
}
}
}
// Maximize the grant utilization
if (lch.size() > 0) {
for (int i=(int)lch.size()-1;i>=0;i--) {
if (lch[i].sched_len > 0) {
lch[i].sched_len = -1;
break;
// Maximize the grant utilization
if (lch.size() > 0) {
for (int i=(int)lch.size()-1;i>=0;i--) {
if (lch[i].sched_len > 0) {
lch[i].sched_len = -1;
break;
}
}
}
}
// Now allocate the SDUs from the RLC
for (uint32_t i=0;i<lch.size();i++) {
if (lch[i].sched_len != 0) {
log_h->info("Allocating scheduled lch=%d len=%d\n", lch[i].id, lch[i].sched_len);
allocate_sdu(lch[i].id, &pdu_msg, lch[i].sched_len);
// Now allocate the SDUs from the RLC
for (uint32_t i=0;i<lch.size();i++) {
if (lch[i].sched_len != 0) {
log_h->info("Allocating scheduled lch=%d len=%d\n", lch[i].id, lch[i].sched_len);
allocate_sdu(lch[i].id, &pdu_msg, lch[i].sched_len);
}
}
}

@ -96,8 +96,14 @@ void ra_proc::read_params() {
// Read initialization parameters
configIndex = mac_cfg->prach_config_index;
preambleIndex = 0; // pass when called from higher layers for non-contention based RA
maskIndex = 0; // same
if (noncontention_enabled) {
preambleIndex = next_preamble_idx;
maskIndex = next_prach_mask;
noncontention_enabled = false;
} else {
preambleIndex = 0; // pass when called from higher layers for non-contention based RA
maskIndex = 0; // same
}
nof_preambles = liblte_rrc_number_of_ra_preambles_num[mac_cfg->rach.num_ra_preambles];
if (mac_cfg->rach.preambles_group_a_cnfg.present) {
nof_groupA_preambles = liblte_rrc_size_of_ra_preambles_group_a_num[mac_cfg->rach.preambles_group_a_cnfg.size_of_ra];
@ -386,8 +392,13 @@ void ra_proc::step_response_reception() {
}
}
void ra_proc::step_response_error() {
void ra_proc::step_response_error()
{
if (ra_is_ho) {
state = RA_PROBLEM;
rrc->ho_ra_completed(false);
return;
}
preambleTransmissionCounter++;
if (preambleTransmissionCounter >= preambleTransMax + 1) {
rError("Maximum number of transmissions reached (%d)\n", preambleTransMax);
@ -497,6 +508,9 @@ void ra_proc::step_completition() {
msg3_transmitted = false;
state = COMPLETION_DONE;
if (ra_is_ho) {
rrc->ho_ra_completed(true);
}
}
void ra_proc::step(uint32_t tti_)
@ -536,9 +550,17 @@ void ra_proc::step(uint32_t tti_)
}
}
void ra_proc::start_mac_order(uint32_t msg_len_bits)
void ra_proc::start_noncont(uint32_t preamble_index, uint32_t prach_mask) {
next_preamble_idx = preamble_index;
next_prach_mask = prach_mask;
noncontention_enabled = true;
start_mac_order(56, true);
}
void ra_proc::start_mac_order(uint32_t msg_len_bits, bool is_ho)
{
if (state == IDLE || state == COMPLETION_DONE || state == RA_PROBLEM) {
ra_is_ho = is_ho;
started_by_pdcch = false;
new_ra_msg_len = msg_len_bits;
state = INITIALIZATION;

@ -47,27 +47,7 @@ phch_common::phch_common(uint32_t max_mutex_) : tx_mutex(max_mutex_)
mac = NULL;
max_mutex = max_mutex_;
nof_mutex = 0;
sr_enabled = false;
is_first_of_burst = true;
is_first_tx = true;
rar_grant_pending = false;
pathloss = 0;
cur_pathloss = 0;
cur_pusch_power = 0;
p0_preamble = 0;
cur_radio_power = 0;
rx_gain_offset = 0;
sr_last_tx_tti = -1;
cur_pusch_power = 0;
serving_cell_report_period = 20;
bzero(zeros, 50000*sizeof(cf_t));
// FIXME: This is an ungly fix to avoid the TX filters to empty
for (int i=0;i<50000;i++) {
zeros[i] = 0.01*cexpf(((float) i/50000)*0.1*_Complex_I);
}
bzero(&dl_metrics, sizeof(dl_metrics_t));
dl_metrics_read = true;
dl_metrics_count = 0;
@ -77,6 +57,16 @@ phch_common::phch_common(uint32_t max_mutex_) : tx_mutex(max_mutex_)
bzero(&sync_metrics, sizeof(sync_metrics_t));
sync_metrics_read = true;
sync_metrics_count = 0;
bzero(zeros, 50000*sizeof(cf_t));
// FIXME: This is an ugly fix to avoid the TX filters to empty
for (int i=0;i<50000;i++) {
zeros[i] = 0.01*cexpf(((float) i/50000)*0.1*_Complex_I);
}
reset();
}
void phch_common::init(phy_interface_rrc::phy_cfg_t *_config, phy_args_t *_args, srslte::log *_log, srslte::radio *_radio, rrc_interface_phy *_rrc, mac_interface_phy *_mac)
@ -224,6 +214,15 @@ bool phch_common::get_pending_ack(uint32_t tti, uint32_t *I_lowest, uint32_t *n_
return pending_ack[TTIMOD(tti)].enabled;
}
bool phch_common::is_any_pending_ack() {
for (int i=0;i<TTIMOD_SZ;i++) {
if (pending_ack[i].enabled) {
return true;
}
}
return false;
}
/* The transmisison of UL subframes must be in sequence. Each worker uses this function to indicate
* that all processing is done and data is ready for transmission or there is no transmission at all (tx_enable).
* In that case, the end of burst message will be send to the radio
@ -331,6 +330,27 @@ void phch_common::get_sync_metrics(sync_metrics_t &m) {
sync_metrics_read = true;
}
void phch_common::reset() {
sr_enabled = false;
is_first_of_burst = true;
is_first_tx = true;
rar_grant_pending = false;
pathloss = 0;
cur_pathloss = 0;
cur_pusch_power = 0;
p0_preamble = 0;
cur_radio_power = 0;
rx_gain_offset = 0;
sr_last_tx_tti = -1;
cur_pusch_power = 0;
pcell_meas_enabled = false;
pcell_report_period = 20;
bzero(pending_ack, sizeof(pending_ack_t)*TTIMOD_SZ);
}
void phch_common::reset_ul()
{
is_first_tx = true;

@ -241,12 +241,13 @@ bool phch_recv::set_cell() {
return cell_is_set;
}
void phch_recv::resync_sfn(bool is_connected) {
void phch_recv::resync_sfn(bool is_connected, bool now) {
wait_radio_reset();
stop_rx();
start_rx();
if (!now) {
wait_radio_reset();
stop_rx();
}
start_rx(now);
sfn_p.reset();
Info("SYNC: Starting SFN synchronization\n");
@ -287,7 +288,7 @@ void phch_recv::reset_sync() {
Warning("SYNC: Resetting sync, cell_search_in_progress=%s\n", cell_search_in_progress?"yes":"no");
search_p.reset();
srslte_ue_sync_reset(&ue_sync);
resync_sfn(true);
resync_sfn(true, true);
}
void phch_recv::cell_search_inc()
@ -339,6 +340,38 @@ void phch_recv::cell_search_stop() {
cell_search_in_progress = false;
}
bool phch_recv::cell_handover(srslte_cell_t cell)
{
int offset = intra_freq_meas.get_offset(cell.id);
if (offset < 0) {
log_h->error("Cell HO: Can't find PCI=%d\n", cell.id);
return false;
}
int cnt = 0;
while(worker_com->is_any_pending_ack() && cnt < 10) {
usleep(1000);
cnt++;
log_h->info("Cell HO: Waiting pending PHICH\n");
}
bool ret;
this->cell = cell;
Info("Cell HO: Stopping sync with current cell\n");
worker_com->reset_ul();
stop_sync();
Info("Cell HO: Reconfiguring cell\n");
if (set_cell()) {
Info("Cell HO: Synchronizing with new cell\n");
resync_sfn(true, true);
ret = true;
} else {
log_h->error("Cell HO: Configuring cell PCI=%d\n", cell.id);
ret = false;
}
return ret;
}
bool phch_recv::cell_select(uint32_t earfcn, srslte_cell_t cell) {
// Check if we are already camping in this cell
@ -373,7 +406,7 @@ bool phch_recv::cell_select(uint32_t earfcn, srslte_cell_t cell) {
resync_sfn();
usleep(500000); // Time offset we set start_rx to start receveing samples
usleep(500000); // Time offset we set start_rx to start receiving samples
return true;
} else {
log_h->error("Cell Select: Configuring cell in EARFCN=%d, PCI=%d\n", earfcn, cell.id);
@ -443,10 +476,10 @@ void phch_recv::stop_rx() {
radio_is_rx = false;
}
void phch_recv::start_rx() {
void phch_recv::start_rx(bool now) {
if (!radio_is_rx) {
Info("SYNC: Starting RX streaming\n");
radio_h->start_rx();
radio_h->start_rx(now);
}
radio_is_rx = true;
}
@ -626,7 +659,6 @@ void phch_recv::run_thread()
workers_pool->start_worker(worker);
intra_freq_meas.write(tti, buffer[0], SRSLTE_SF_LEN_PRB(cell.nof_prb));
break;
case 0:
log_h->error("SYNC: Sync error. Sending out-of-sync to RRC\n");
@ -984,6 +1016,10 @@ float phch_recv::measure::snr() {
return mean_snr;
}
void phch_recv::measure::set_rx_gain_offset(float rx_gain_offset) {
this->rx_gain_offset = rx_gain_offset;
}
phch_recv::measure::ret_code phch_recv::measure::run_subframe_sync(srslte_ue_sync_t *ue_sync, uint32_t sf_idx)
{
int sync_res = srslte_ue_sync_zerocopy_multi(ue_sync, buffer);
@ -1023,7 +1059,7 @@ phch_recv::measure::ret_code phch_recv::measure::run_subframe(uint32_t sf_idx)
return ERROR;
}
float rsrp = 10*log10(srslte_chest_dl_get_rsrp(&ue_dl.chest)) + 30;
float rsrp = 10*log10(srslte_chest_dl_get_rsrp(&ue_dl.chest)) + 30 - rx_gain_offset;
float rsrq = 10*log10(srslte_chest_dl_get_rsrq(&ue_dl.chest));
float snr = 10*log10(srslte_chest_dl_get_snr(&ue_dl.chest));
@ -1081,7 +1117,7 @@ void phch_recv::scell_recv::reset()
measure_p.reset();
}
int phch_recv::scell_recv::find_cells(cf_t *input_buffer, 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 current_cell, uint32_t nof_sf, cell_info_t cells[MAX_CELLS])
{
uint32_t fft_sz = srslte_symbol_sz(current_cell.nof_prb);
uint32_t sf_len = SRSLTE_SF_LEN(fft_sz);
@ -1100,6 +1136,8 @@ int phch_recv::scell_recv::find_cells(cf_t *input_buffer, srslte_cell_t current_
srslte_cell_t found_cell;
memcpy(&found_cell, &current_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) {
@ -1164,10 +1202,12 @@ int phch_recv::scell_recv::find_cells(cf_t *input_buffer, srslte_cell_t current_
void phch_recv::meas_reset() {
// Stop all measurements
intra_freq_meas.clear_cells();
worker_com->pcell_meas_enabled = false;
}
int phch_recv::meas_start(uint32_t earfcn, int pci) {
if (earfcn == current_earfcn) {
worker_com->pcell_meas_enabled = true;
intra_freq_meas.add_cell(pci);
return 0;
} else {
@ -1199,7 +1239,7 @@ void phch_recv::intra_measure::init(phch_common *common, rrc_interface_phy *rrc,
search_buffer = (cf_t*) srslte_vec_malloc(CAPTURE_LEN_SF*SRSLTE_SF_LEN_PRB(SRSLTE_MAX_PRB)*sizeof(cf_t));
if (srslte_ringbuffer_init(&ring_buffer, sizeof(cf_t)*50*SRSLTE_SF_LEN_PRB(SRSLTE_MAX_PRB))) {
if (srslte_ringbuffer_init(&ring_buffer, sizeof(cf_t)*100*SRSLTE_SF_LEN_PRB(SRSLTE_MAX_PRB))) {
return;
}
@ -1222,6 +1262,9 @@ void phch_recv::intra_measure::set_primay_cell(uint32_t earfcn, srslte_cell_t ce
void phch_recv::intra_measure::clear_cells() {
active_pci.clear();
receive_enabled = false;
receiving = false;
receive_cnt = 0;
srslte_ringbuffer_reset(&ring_buffer);
}
void phch_recv::intra_measure::add_cell(int pci) {
@ -1234,6 +1277,15 @@ void phch_recv::intra_measure::add_cell(int pci) {
}
}
int phch_recv::intra_measure::get_offset(uint32_t pci) {
for (int i=0;i<scell_recv::MAX_CELLS;i++) {
if (info[i].pci == pci) {
return info[i].offset;
}
}
return -1;
}
void phch_recv::intra_measure::rem_cell(int pci) {
std::vector<int>::iterator newEnd = std::remove(active_pci.begin(), active_pci.end(), pci);
@ -1257,6 +1309,7 @@ void phch_recv::intra_measure::write(uint32_t tti, cf_t *data, uint32_t nsamples
}
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 {
@ -1282,12 +1335,11 @@ void phch_recv::intra_measure::run_thread()
// Read 5 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, 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;
srslte_ringbuffer_reset(&ring_buffer);
for (int i=0;i<found_cells;i++) {
info[i].rsrp -= common->rx_gain_offset;
rrc->new_phy_meas(info[i].rsrp, info[i].rsrq, measure_tti, current_earfcn, info[i].pci);
}
// Look for other cells not found automatically

@ -94,10 +94,11 @@ void phch_worker::reset()
bzero(&pucch_sched, sizeof(srslte_pucch_sched_t));
bzero(&srs_cfg, sizeof(srslte_refsignal_srs_cfg_t));
bzero(&period_cqi, sizeof(srslte_cqi_periodic_cfg_t));
I_sr = 0;
sr_configured = false;
rnti_is_set = false;
rar_cqi_request = false;
cfi = 0;
I_sr = 0;
cfi = 0;
}
void phch_worker::set_common(phch_common* phy_)
@ -801,7 +802,7 @@ void phch_worker::set_uci_ack(bool ack[SRSLTE_MAX_CODEWORDS], bool tb_en[SRSLTE_
void phch_worker::set_uci_sr()
{
uci_data.scheduling_request = false;
if (phy->sr_enabled) {
if (phy->sr_enabled && sr_configured) {
uint32_t sr_tx_tti = TTI_TX(tti);
// Get I_sr parameter
if (srslte_ue_ul_sr_send_tti(I_sr, sr_tx_tti)) {
@ -944,7 +945,8 @@ void phch_worker::encode_pusch(srslte_ra_ul_grant_t *grant, uint8_t *payload, ui
snprintf(timestr, 64, ", tot_time=%4d us", (int) logtime_start[0].tv_usec);
#endif
Info("PUSCH: tti_tx=%d, alloc=(%d,%d), tbs=%d, mcs=%d, rv=%d, ack=%s, ri=%s, cfo=%.1f KHz%s\n",
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",
(tti+HARQ_DELAY_MS)%10240,
grant->n_prb[0], grant->n_prb[0]+grant->L_prb,
grant->mcs.tbs/8, grant->mcs.idx, rv,
@ -1144,7 +1146,7 @@ void phch_worker::set_ul_params(bool pregen_disabled)
/* SR configuration */
I_sr = dedicated->sched_request_cnfg.sr_cnfg_idx;
sr_configured = true;
if (pregen_enabled && !pregen_disabled) {
Info("Pre-generating UL signals worker=%d\n", get_id());
@ -1253,7 +1255,7 @@ void phch_worker::update_measurements()
} else {
phy->avg_rsrp_db = SRSLTE_VEC_EMA(phy->avg_rsrp_db, rsrp, 0.8);
}
if ((tti%phy->serving_cell_report_period) == 0) {
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);
}
}

@ -206,15 +206,11 @@ void phy::set_timeadv(uint32_t ta_cmd) {
void phy::configure_prach_params()
{
if (sf_recv.status_is_sync()) {
Debug("Configuring PRACH parameters\n");
srslte_cell_t cell;
sf_recv.get_current_cell(&cell);
if (!prach_buffer.set_cell(cell)) {
Error("Configuring PRACH parameters\n");
}
} else {
Error("Cell is not synchronized\n");
Debug("Configuring PRACH parameters\n");
srslte_cell_t cell;
sf_recv.get_current_cell(&cell);
if (!prach_buffer.set_cell(cell)) {
Error("Configuring PRACH parameters\n");
}
}
@ -264,6 +260,10 @@ bool phy::cell_select(uint32_t earfcn, srslte_cell_t phy_cell)
return sf_recv.cell_select(earfcn, phy_cell);
}
bool phy::cell_handover(srslte_cell_t cell) {
return sf_recv.cell_handover(cell);
}
float phy::get_phr()
{
float phr = radio_handler->get_max_tx_power() - workers_common.cur_pusch_power;
@ -321,6 +321,7 @@ void phy::reset()
for(uint32_t i=0;i<nof_workers;i++) {
workers[i].reset();
}
workers_common.reset();
workers_common.reset_ul();
}

@ -96,6 +96,7 @@ void rrc::init(phy_interface_rrc *phy_,
t301 = mac_timers->timer_get_unique_id();
t310 = mac_timers->timer_get_unique_id();
t311 = mac_timers->timer_get_unique_id();
t304 = mac_timers->timer_get_unique_id();
transaction_id = 0;
@ -105,6 +106,8 @@ void rrc::init(phy_interface_rrc *phy_,
nof_sib1_trials = 0;
last_win_start = 0;
pending_mob_reconf = false;
// Set default values for all layers
set_rrc_default();
set_phy_default();
@ -232,6 +235,13 @@ void rrc::run_thread() {
case RRC_STATE_CONNECTED:
// Take measurements, cell reselection, etc
break;
case RRC_STATE_HO_PREPARE:
ho_prepare();
state = RRC_STATE_HO_PROCESS;
break;
case RRC_STATE_HO_PROCESS:
// wait for HO to finish
break;
case RRC_STATE_LEAVE_CONNECTED:
usleep(60000);
rrc_log->info("Leaving RRC_CONNECTED state\n");
@ -412,6 +422,9 @@ void rrc::select_next_cell_in_plmn() {
{
last_selected_cell = i;
current_cell = &known_cells[i];
rrc_log->info("Selected cell PCI=%d, EARFCN=%d, Cell ID=0x%x, addr=0x%x\n",
current_cell->phy_cell.id, current_cell->earfcn,
current_cell->sib1.cell_id, current_cell);
return;
} else {
rrc_log->warning("Selecting cell EARFCN=%d, Cell ID=0x%x.\n",
@ -433,17 +446,17 @@ 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++) {
if (earfcn == known_cells[i].earfcn && phy_cell.id == known_cells[i].phy_cell.id) {
known_cells[i].rsrp = rsrp;
known_cells[i].in_sync = true;
current_cell = &known_cells[i];
rrc_log->info("Updating cell EARFCN=%d, PCI=%d, RSRP=%.1f dBm\n", known_cells[i].earfcn,
known_cells[i].phy_cell.id, known_cells[i].rsrp);
current_cell->rsrp = rsrp;
current_cell->in_sync = true;
rrc_log->info("Updating cell EARFCN=%d, PCI=%d, RSRP=%.1f dBm\n", current_cell->earfcn,
current_cell->phy_cell.id, current_cell->rsrp);
if (!known_cells[i].has_valid_sib1) {
if (!current_cell->has_valid_sib1) {
si_acquire_state = SI_ACQUIRE_SIB1;
} else if (state == RRC_STATE_PLMN_SELECTION) {
for (uint32_t i = 0; i < current_cell->sib1.N_plmn_ids; i++) {
nas->plmn_found(current_cell->sib1.plmn_id[i].id, current_cell->sib1.tracking_area_code);
for (uint32_t j = 0; j < current_cell->sib1.N_plmn_ids; j++) {
nas->plmn_found(current_cell->sib1.plmn_id[j].id, current_cell->sib1.tracking_area_code);
}
usleep(5000);
phy->cell_search_next();
@ -465,9 +478,9 @@ void rrc::cell_found(uint32_t earfcn, srslte_cell_t phy_cell, float rsrp) {
si_acquire_state = SI_ACQUIRE_SIB1;
rrc_log->info("New Cell: PCI=%d, PRB=%d, Ports=%d, EARFCN=%d, RSRP=%.1f dBm\n",
cell.phy_cell.id, cell.phy_cell.nof_prb, cell.phy_cell.nof_ports,
cell.earfcn, cell.rsrp);
rrc_log->info("New Cell: PCI=%d, PRB=%d, Ports=%d, EARFCN=%d, RSRP=%.1f dBm, addr=0x%x\n",
current_cell->phy_cell.id, current_cell->phy_cell.nof_prb, current_cell->phy_cell.nof_ports,
current_cell->earfcn, current_cell->rsrp, current_cell);
}
// PHY indicates that has gone through all known EARFCN
@ -480,7 +493,22 @@ 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++) {
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);
}
@ -572,6 +600,8 @@ void rrc::timer_expired(uint32_t timeout_id) {
} else if (timeout_id == t301) {
rrc_log->info("Timer T301 expired: Going to RRC IDLE\n");
state = RRC_STATE_LEAVE_CONNECTED;
} else if (timeout_id == t304) {
rrc_log->console("Timer T304 expired: Handover failed\n");
// fw to measurement
} else if (!measurements.timer_expired(timeout_id)) {
rrc_log->error("Timeout from unknown timer id %d\n", timeout_id);
@ -777,40 +807,134 @@ void rrc::send_security_mode_complete(uint32_t lcid, byte_buffer_t *pdu) {
send_ul_dcch_msg(pdu);
}
void rrc::send_rrc_con_reconfig_complete(uint32_t lcid, byte_buffer_t *pdu) {
void rrc::send_rrc_con_reconfig_complete(byte_buffer_t *pdu) {
rrc_log->debug("Preparing RRC Connection Reconfig Complete\n");
ul_dcch_msg.msg_type = LIBLTE_RRC_UL_DCCH_MSG_TYPE_RRC_CON_RECONFIG_COMPLETE;
ul_dcch_msg.msg.rrc_con_reconfig_complete.rrc_transaction_id = transaction_id;
send_ul_dcch_msg();
send_ul_dcch_msg(pdu);
}
void rrc::ho_prepare() {
if (pending_mob_reconf) {
rrc_log->info("Processing HO command to target PCell=%d\n", mob_reconf.mob_ctrl_info.target_pci);
// Section 5.3.5.4
mac_timers->timer_get(t310)->stop();
mac_timers->timer_get(t304)->set(this, liblte_rrc_t304_num[mob_reconf.mob_ctrl_info.t304]);
if (mob_reconf.mob_ctrl_info.carrier_freq_eutra_present &&
mob_reconf.mob_ctrl_info.carrier_freq_eutra.dl_carrier_freq != current_cell->earfcn) {
rrc_log->warning("Received mobilityControlInfo for inter-frequency handover\n");
}
phy->meas_reset();
mac->wait_uplink();
pdcp->reestablish();
rlc->reestablish();
mac->reset();
phy->reset();
mac->set_ho_rnti(mob_reconf.mob_ctrl_info.new_ue_id, mob_reconf.mob_ctrl_info.target_pci);
apply_rr_config_common_dl(&mob_reconf.mob_ctrl_info.rr_cnfg_common);
uint32_t current_earfcn = 0;
phy->get_current_cell(NULL, &current_earfcn);
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);
if (known_cells[i].earfcn == 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);
if (!phy->cell_handover(known_cells[i].phy_cell)) {
rrc_log->error("Could not synchronize with target cell pci=%d\n", known_cells[i].phy_cell.id);
}
found = true;
break;
}
}
if (!found) {
rrc_log->error("Could not find target cell pci=%d\n", mob_reconf.mob_ctrl_info.target_pci);
return;
}
if (mob_reconf.mob_ctrl_info.rach_cnfg_ded_present) {
mac->start_noncont_ho(mob_reconf.mob_ctrl_info.rach_cnfg_ded.preamble_index,
mob_reconf.mob_ctrl_info.rach_cnfg_ded.prach_mask_index);
} else {
mac->start_cont_ho();
}
printf("ncc=%d\n", mob_reconf.sec_cnfg_ho.intra_lte.next_hop_chaining_count);
usim->generate_as_keys_ho(mob_reconf.mob_ctrl_info.target_pci, current_earfcn,
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);
}
}
void rrc::ho_ra_completed(bool ra_successful) {
if (pending_mob_reconf) {
measurements.ho_finish();
if (mob_reconf.meas_cnfg_present) {
measurements.parse_meas_config(&mob_reconf.meas_cnfg);
}
if (ra_successful) {
mac_timers->timer_get(t304)->stop();
apply_rr_config_common_ul(&mob_reconf.mob_ctrl_info.rr_cnfg_common);
if (mob_reconf.rr_cnfg_ded_present) {
apply_rr_config_dedicated(&mob_reconf.rr_cnfg_ded);
}
}
rrc_log->info("HO %ssuccessful\n", ra_successful?"":"un");
rrc_log->console("HO %ssuccessful\n", ra_successful?"":"un");
pending_mob_reconf = false;
state = RRC_STATE_CONNECTED;
} else {
rrc_log->error("Received HO random access completed but no pending mobility reconfiguration info\n");
}
}
void rrc::handle_rrc_con_reconfig(uint32_t lcid, LIBLTE_RRC_CONNECTION_RECONFIGURATION_STRUCT *reconfig,
byte_buffer_t *pdu) {
uint32_t i;
if (reconfig->rr_cnfg_ded_present) {
apply_rr_config_dedicated(&reconfig->rr_cnfg_ded);
} else {
printf("received con reconfig no rr confg present\n");
}
if (reconfig->meas_cnfg_present) {
measurements.parse_meas_config(&reconfig->meas_cnfg);
}
if (reconfig->mob_ctrl_info_present) {
//TODO: handle mob_ctrl_info
}
send_rrc_con_reconfig_complete(lcid, pdu);
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);
// store mobilityControlInfo
memcpy(&mob_reconf, reconfig, sizeof(LIBLTE_RRC_CONNECTION_RECONFIGURATION_STRUCT));
pending_mob_reconf = true;
state = RRC_STATE_HO_PREPARE;
} else {
// Section 5.3.5.3
if (reconfig->rr_cnfg_ded_present) {
apply_rr_config_dedicated(&reconfig->rr_cnfg_ded);
}
if (reconfig->meas_cnfg_present) {
measurements.parse_meas_config(&reconfig->meas_cnfg);
}
send_rrc_con_reconfig_complete(pdu);
byte_buffer_t *nas_sdu;
for (i = 0; i < reconfig->N_ded_info_nas; i++) {
nas_sdu = pool_allocate;
memcpy(nas_sdu->msg, &reconfig->ded_info_nas_list[i].msg, reconfig->ded_info_nas_list[i].N_bytes);
nas_sdu->N_bytes = reconfig->ded_info_nas_list[i].N_bytes;
nas->write_pdu(lcid, nas_sdu);
byte_buffer_t *nas_sdu;
for (i = 0; i < reconfig->N_ded_info_nas; i++) {
nas_sdu = pool_allocate;
memcpy(nas_sdu->msg, &reconfig->ded_info_nas_list[i].msg, reconfig->ded_info_nas_list[i].N_bytes);
nas_sdu->N_bytes = reconfig->ded_info_nas_list[i].N_bytes;
nas->write_pdu(lcid, nas_sdu);
}
}
}
@ -1022,7 +1146,7 @@ void rrc::send_ul_dcch_msg(byte_buffer_t *pdu)
}
void rrc::write_sdu(uint32_t lcid, byte_buffer_t *sdu) {
rrc_log->info_hex(sdu->msg, sdu->N_bytes, "RX %s SDU", get_rb_name(lcid).c_str());
rrc_log->info_hex(sdu->msg, sdu->N_bytes, "TX %s SDU", get_rb_name(lcid).c_str());
switch (state) {
case RRC_STATE_CONNECTING:
send_con_setup_complete(sdu);
@ -1037,8 +1161,8 @@ void rrc::write_sdu(uint32_t lcid, byte_buffer_t *sdu) {
}
void rrc::write_pdu(uint32_t lcid, byte_buffer_t *pdu) {
rrc_log->info_hex(pdu->msg, pdu->N_bytes, "TX %s PDU", get_rb_name(lcid).c_str());
rrc_log->info("TX PDU Stack latency: %ld us\n", pdu->get_latency_us());
rrc_log->info_hex(pdu->msg, pdu->N_bytes, "RX %s PDU", get_rb_name(lcid).c_str());
rrc_log->info("RX PDU Stack latency: %ld us\n", pdu->get_latency_us());
switch (lcid) {
case RB_ID_SRB0:
@ -1049,7 +1173,7 @@ void rrc::write_pdu(uint32_t lcid, byte_buffer_t *pdu) {
parse_dl_dcch(lcid, pdu);
break;
default:
rrc_log->error("TX PDU with invalid bearer id: %s", lcid);
rrc_log->error("RX PDU with invalid bearer id: %s", lcid);
break;
}
}
@ -1265,6 +1389,54 @@ void rrc::send_rrc_ue_cap_info(uint32_t lcid, byte_buffer_t *pdu) {
*
*******************************************************************************/
void rrc::apply_rr_config_common_dl(LIBLTE_RRC_RR_CONFIG_COMMON_STRUCT *config) {
mac_interface_rrc::mac_cfg_t mac_cfg;
mac->get_config(&mac_cfg);
if (config->rach_cnfg_present) {
memcpy(&mac_cfg.rach, &config->rach_cnfg, sizeof(LIBLTE_RRC_RACH_CONFIG_COMMON_STRUCT));
}
mac_cfg.prach_config_index = config->prach_cnfg.root_sequence_index;
mac_cfg.ul_harq_params.max_harq_msg3_tx = config->rach_cnfg.max_harq_msg3_tx;
mac->set_config(&mac_cfg);
phy_interface_rrc::phy_cfg_t phy_cfg;
phy->get_config(&phy_cfg);
phy_interface_rrc::phy_cfg_common_t *common = &phy_cfg.common;
if (config->pdsch_cnfg_present) {
memcpy(&common->pdsch_cnfg, &config->pdsch_cnfg, sizeof(LIBLTE_RRC_PDSCH_CONFIG_COMMON_STRUCT));
}
common->prach_cnfg.root_sequence_index = config->prach_cnfg.root_sequence_index;
if (config->prach_cnfg.prach_cnfg_info_present) {
memcpy(&common->prach_cnfg.prach_cnfg_info, &config->prach_cnfg.prach_cnfg_info, sizeof(LIBLTE_RRC_PRACH_CONFIG_INFO_STRUCT));
}
phy->set_config_common(common);
}
void rrc::apply_rr_config_common_ul(LIBLTE_RRC_RR_CONFIG_COMMON_STRUCT *config) {
phy_interface_rrc::phy_cfg_t phy_cfg;
phy->get_config(&phy_cfg);
phy_interface_rrc::phy_cfg_common_t *common = &phy_cfg.common;
memcpy(&common->pusch_cnfg, &config->pusch_cnfg, sizeof(LIBLTE_RRC_PUSCH_CONFIG_COMMON_STRUCT));
if (config->pucch_cnfg_present) {
memcpy(&common->pucch_cnfg, &config->pucch_cnfg, sizeof(LIBLTE_RRC_PUCCH_CONFIG_COMMON_STRUCT));
}
if (config->ul_pwr_ctrl_present) {
memcpy(&common->ul_pwr_ctrl, &config->ul_pwr_ctrl, sizeof(LIBLTE_RRC_UL_POWER_CONTROL_COMMON_STRUCT));
}
if (config->srs_ul_cnfg.present) {
memcpy(&common->srs_ul_cnfg, &config->srs_ul_cnfg, sizeof(LIBLTE_RRC_SRS_UL_CONFIG_COMMON_STRUCT));
} else {
// default is release
common->srs_ul_cnfg.present = false;
}
phy->set_config_common(common);
phy->configure_ul_params();
}
void rrc::apply_sib2_configs(LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_2_STRUCT *sib2) {
// Apply RACH timeAlginmentTimer configuration
@ -1800,6 +1972,9 @@ void rrc::rrc_meas::new_phy_meas(uint32_t earfcn, uint32_t pci, float rsrp, floa
if (earfcn == 0) {
L3_filter(&pcell_measurement, values);
} else {
// Add to known cells
parent->add_neighbour_cell(earfcn, pci, rsrp);
// 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;
@ -1815,6 +1990,7 @@ void rrc::rrc_meas::new_phy_meas(uint32_t earfcn, uint32_t pci, float rsrp, floa
return;
}
}
parent->rrc_log->warning("MEAS: Received measurement from unknown EARFCN=%d\n", earfcn);
}
}
@ -1866,7 +2042,7 @@ void rrc::rrc_meas::generate_report(uint32_t meas_id)
report->pcell_rsrp_result = value_to_range(RSRP, pcell_measurement.ms[RSRP]);
report->pcell_rsrq_result = value_to_range(RSRQ, pcell_measurement.ms[RSRQ]);
log_h->console("MEAS: Generate report MeasId=%d, rsrp=%f rsrq=%f\n",
log_h->info("MEAS: Generate report MeasId=%d, rsrp=%f rsrq=%f\n",
report->meas_id, pcell_measurement.ms[RSRP], pcell_measurement.ms[RSRQ]);
// TODO: report up to 8 best cells
@ -1882,7 +2058,7 @@ void rrc::rrc_meas::generate_report(uint32_t meas_id)
rc->meas_result.rsrp_result = value_to_range(RSRP, cell->second.ms[RSRP]);
rc->meas_result.rsrq_result = value_to_range(RSRQ, cell->second.ms[RSRQ]);
log_h->console("MEAS: Add neigh=%d, pci=%d, rsrp=%f, rsrq=%f\n",
log_h->info("MEAS: Add neigh=%d, pci=%d, rsrp=%f, rsrq=%f\n",
report->meas_result_neigh_cells.eutra.n_result, rc->phys_cell_id,
cell->second.ms[RSRP], cell->second.ms[RSRQ]);
@ -2037,6 +2213,26 @@ void rrc::rrc_meas::calculate_triggers(uint32_t tti)
}
}
// Procedure upon handover or reestablishment 5.5.6.1
void rrc::rrc_meas::ho_finish() {
// Remove all measId with trigger periodic
std::map<uint32_t, meas_t>::iterator iter = active.begin();
while (iter != active.end()) {
if (reports_cfg[iter->second.report_id].trigger_type == report_cfg_t::PERIODIC) {
remove_meas_id(iter++);
} else {
++iter;
}
}
//TODO: Inter-frequency handover
// Stop all reports
for (std::map<uint32_t, meas_t>::iterator iter = active.begin(); iter != active.end(); ++iter) {
stop_reports(&iter->second);
}
}
// 5.5.4.1 expiry of periodical reporting timer
bool rrc::rrc_meas::timer_expired(uint32_t timer_id) {
for (std::map<uint32_t, meas_t>::iterator iter = active.begin(); iter != active.end(); ++iter) {
@ -2048,41 +2244,53 @@ bool rrc::rrc_meas::timer_expired(uint32_t timer_id) {
return false;
}
void rrc::rrc_meas::stop_reports(meas_t *m) {
mac_timers->timer_get(m->periodic_timer)->stop();
m->triggered = false;
}
void rrc::rrc_meas::stop_reports_object(uint32_t object_id) {
for (std::map<uint32_t, meas_t>::iterator iter = active.begin(); iter != active.end(); ++iter) {
meas_t *m = &iter->second;
if (m->object_id == object_id) {
mac_timers->timer_get(m->periodic_timer)->stop();
m->triggered = false;
if (iter->second.object_id == object_id) {
stop_reports(&iter->second);
}
}
}
void rrc::rrc_meas::remove_meas_object(uint32_t object_id) {
// CHECKME: Is the delete from the map correct?
for(std::map<uint32_t, meas_t>::iterator iter=active.begin(); iter!=active.end(); ++iter) {
meas_t m = iter->second;
if (m.object_id == object_id) {
remove_meas_id(iter->first);
std::map<uint32_t, meas_t>::iterator iter = active.begin();
while (iter != active.end()) {
if (iter->second.object_id == object_id) {
remove_meas_id(iter++);
} else {
++iter;
}
}
}
void rrc::rrc_meas::remove_meas_report(uint32_t report_id) {
// CHECKME: Is the delete from the map correct?
for(std::map<uint32_t, meas_t>::iterator iter=active.begin(); iter!=active.end(); ++iter) {
meas_t m = iter->second;
if (m.report_id == report_id) {
remove_meas_id(iter->first);
std::map<uint32_t, meas_t>::iterator iter = active.begin();
while (iter != active.end()) {
if (iter->second.report_id == report_id) {
remove_meas_id(iter++);
} else {
++iter;
}
}
}
void rrc::rrc_meas::remove_meas_id(uint32_t meas_id) {
mac_timers->timer_get(active[meas_id].periodic_timer)->stop();
mac_timers->timer_release_id(active[meas_id].periodic_timer);
active.erase(meas_id);
log_h->info("MEAS: Removed measId=%d\n", meas_id);
void rrc::rrc_meas::remove_meas_id(uint32_t measId) {
mac_timers->timer_get(active[measId].periodic_timer)->stop();
mac_timers->timer_release_id(active[measId].periodic_timer);
log_h->info("MEAS: Removed measId=%d\n", measId);
active.erase(measId);
}
void rrc::rrc_meas::remove_meas_id(std::map<uint32_t, meas_t>::iterator it) {
mac_timers->timer_get(it->second.periodic_timer)->stop();
mac_timers->timer_release_id(it->second.periodic_timer);
log_h->info("MEAS: Removed measId=%d\n", it->first);
active.erase(it);
}
/* Parses MeasConfig object from RRCConnectionReconfiguration message and applies configuration
@ -2091,28 +2299,6 @@ void rrc::rrc_meas::remove_meas_id(uint32_t meas_id) {
void rrc::rrc_meas::parse_meas_config(LIBLTE_RRC_MEAS_CONFIG_STRUCT *cfg)
{
// Measurement identity removal 5.5.2.2
for (uint32_t i=0;i<cfg->N_meas_id_to_remove;i++) {
remove_meas_id(cfg->meas_id_to_remove_list[i]);
}
// Measurement identity addition/modification 5.5.2.3
if (cfg->meas_id_to_add_mod_list_present) {
for (uint32_t i=0;i<cfg->meas_id_to_add_mod_list.N_meas_id;i++) {
LIBLTE_RRC_MEAS_ID_TO_ADD_MOD_STRUCT *measId = &cfg->meas_id_to_add_mod_list.meas_id_list[i];
// Stop the timer if the entry exists or create the timer if not
if (active.count(measId->meas_id)) {
mac_timers->timer_get(active[measId->meas_id].periodic_timer)->stop();
} else {
active[measId->meas_id].periodic_timer = mac_timers->timer_get_unique_id();
}
active[measId->meas_id].object_id = measId->meas_obj_id;
active[measId->meas_id].report_id = measId->rep_cnfg_id;
log_h->info("MEAS: Added measId=%d, measObjectId=%d, reportConfigId=%d\n",
measId->meas_id, measId->meas_obj_id, measId->rep_cnfg_id);
}
}
// Measurement object removal 5.5.2.4
for (uint32_t i=0;i<cfg->N_meas_obj_to_remove;i++) {
objects.erase(cfg->meas_obj_to_remove_list[i]);
@ -2196,11 +2382,9 @@ void rrc::rrc_meas::parse_meas_config(LIBLTE_RRC_MEAS_CONFIG_STRUCT *cfg)
// Reset reports counter
for(std::map<uint32_t, meas_t>::iterator iter=active.begin(); iter!=active.end(); ++iter) {
meas_t m = iter->second;
if (m.report_id == cfg->rep_cnfg_to_add_mod_list.rep_cnfg_list[i].rep_cnfg_id) {
if (iter->second.report_id == cfg->rep_cnfg_to_add_mod_list.rep_cnfg_list[i].rep_cnfg_id) {
iter->second.nof_reports_sent = 0;
m.triggered = false;
mac_timers->timer_get(m.periodic_timer)->stop();
stop_reports(&iter->second);
}
}
} else {
@ -2227,6 +2411,28 @@ void rrc::rrc_meas::parse_meas_config(LIBLTE_RRC_MEAS_CONFIG_STRUCT *cfg)
log_h->info("MEAS: Quantity configuration k_rsrp=%d, k_rsrq=%d\n", filter_k_rsrp, filter_k_rsrq);
}
// Measurement identity removal 5.5.2.2
for (uint32_t i=0;i<cfg->N_meas_id_to_remove;i++) {
remove_meas_id(cfg->meas_id_to_remove_list[i]);
}
// Measurement identity addition/modification 5.5.2.3
if (cfg->meas_id_to_add_mod_list_present) {
for (uint32_t i=0;i<cfg->meas_id_to_add_mod_list.N_meas_id;i++) {
LIBLTE_RRC_MEAS_ID_TO_ADD_MOD_STRUCT *measId = &cfg->meas_id_to_add_mod_list.meas_id_list[i];
// Stop the timer if the entry exists or create the timer if not
if (active.count(measId->meas_id)) {
mac_timers->timer_get(active[measId->meas_id].periodic_timer)->stop();
} else {
active[measId->meas_id].periodic_timer = mac_timers->timer_get_unique_id();
}
active[measId->meas_id].object_id = measId->meas_obj_id;
active[measId->meas_id].report_id = measId->rep_cnfg_id;
log_h->info("MEAS: Added measId=%d, measObjectId=%d, reportConfigId=%d\n",
measId->meas_id, measId->meas_obj_id, measId->rep_cnfg_id);
}
}
// S-Measure
if (cfg->s_meas_present) {
if (cfg->s_meas) {

@ -222,6 +222,7 @@ void usim::generate_as_keys(uint32_t count_ul,
CIPHERING_ALGORITHM_ID_ENUM cipher_algo,
INTEGRITY_ALGORITHM_ID_ENUM integ_algo)
{
// Generate K_enb
security_generate_k_enb( k_asme,
count_ul,
@ -242,6 +243,39 @@ void usim::generate_as_keys(uint32_t count_ul,
k_up_int);
}
void usim::generate_as_keys_ho(uint32_t pci,
uint32_t earfcn,
uint8_t *k_rrc_enc,
uint8_t *k_rrc_int,
uint8_t *k_up_enc,
uint8_t *k_up_int,
CIPHERING_ALGORITHM_ID_ENUM cipher_algo,
INTEGRITY_ALGORITHM_ID_ENUM integ_algo)
{
// Generate K_enb
security_generate_k_enb_star( k_enb,
pci,
earfcn,
k_enb_star);
memcpy(k_enb, k_enb_star, 32);
// Generate K_rrc_enc and K_rrc_int
security_generate_k_rrc( k_enb,
cipher_algo,
integ_algo,
k_rrc_enc,
k_rrc_int);
// Generate K_up_enc and K_up_int
security_generate_k_up( k_enb,
cipher_algo,
integ_algo,
k_up_enc,
k_up_int);
}
/*******************************************************************************
Helpers
*******************************************************************************/

Loading…
Cancel
Save