new NAS/RRC structure. Attaching and ping working

master
Ismael Gomez 8 years ago
parent fa05304632
commit fa9eaee498

@ -30,6 +30,7 @@
#include <ctype.h>
#include <stdint.h>
#include <string>
#include <srslte/asn1/liblte_rrc.h>
namespace srslte {
@ -112,6 +113,12 @@ inline bool mnc_to_string(uint16_t mnc, std::string *str)
*str += (mnc & 0x000F) + '0';
return true;
}
inline std::string plmn_id_to_c_str(LIBLTE_RRC_PLMN_IDENTITY_STRUCT plmn_id) {
std::string mcc_str, mnc_str;
mnc_to_string(plmn_id.mnc, &mnc_str);
mcc_to_string(plmn_id.mcc, &mcc_str);
return mcc_str + mnc_str;
}
} // namespace srslte

@ -623,6 +623,8 @@ int rf_uhd_recv_with_time_multi(void *h,
log_overflow(handler);
} else if (error_code == UHD_RX_METADATA_ERROR_CODE_LATE_COMMAND) {
log_late(handler);
} else if (error_code == UHD_RX_METADATA_ERROR_CODE_TIMEOUT) {
fprintf(stderr, "Error timed out while receiving asynchronoous messages from UHD.\n");
} else if (error_code != UHD_RX_METADATA_ERROR_CODE_NONE ) {
fprintf(stderr, "Error code 0x%x was returned during streaming. Aborting.\n", error_code);
}

@ -389,8 +389,6 @@ void radio::set_tx_srate(float srate)
// Calculate TX advance in seconds from samples and sampling rate
tx_adv_sec = nsamples/cur_tx_srate;
printf("Setting TX/RX offset %d samples, %.2f us\n", nsamples, tx_adv_sec*1e6);
}
void radio::start_rx()

@ -74,7 +74,6 @@ private:
void set_ue_sync_opts(srslte_ue_sync_t *q);
void run_thread();
int sync_sfn();
bool running;
@ -91,15 +90,19 @@ private:
uint32_t nof_rx_antennas;
cf_t *sf_buffer_sfn[SRSLTE_MAX_PORTS];
cf_t *sf_buffer[SRSLTE_MAX_PORTS];
// Sync metrics
sync_metrics_t metrics;
enum {
IDLE, CELL_SEARCH, CELL_SELECT, CAMPING
IDLE, CELL_SEARCH, CELL_MEASURE, CELL_SELECT, CELL_CAMP
} phy_state;
enum {
SRATE_NONE=0, SRATE_FIND, SRATE_CAMP
} srate_mode;
srslte_cell_t cell;
bool cell_is_set;
bool is_sfn_synched;
@ -118,7 +121,16 @@ private:
const static uint32_t SYNC_SFN_TIMEOUT = 5000;
float ul_dl_factor;
int cur_earfcn_index;
bool cell_search_in_progress;
uint32_t measure_cnt;
float measure_rsrp;
srslte_ue_dl_t ue_dl_measure;
const static int RSRP_MEASURE_NOF_FRAMES = 20;
int cell_sync_sfn();
int cell_meas_rsrp();
bool cell_search(int force_N_id_2 = -1);
bool init_cell();
void free_cell();

@ -61,6 +61,7 @@ namespace srsue {
*******************************************************************************/
typedef struct {
uint32_t dl_earfcn;
float dl_freq;
float ul_freq;
float rx_gain;

@ -107,6 +107,9 @@ namespace srsue {
plmn_selection_state_t plmn_selection;
LIBLTE_RRC_PLMN_IDENTITY_STRUCT current_plmn;
LIBLTE_RRC_PLMN_IDENTITY_STRUCT home_plmn;
std::vector<LIBLTE_RRC_PLMN_IDENTITY_STRUCT > known_plmns;
// Save short MAC

@ -61,8 +61,7 @@ namespace srsue {
typedef enum {
SI_ACQUIRE_IDLE = 0,
SI_ACQUIRE_SIB1,
SI_ACQUIRE_SIB2,
SI_ACQUIRE_DONE
SI_ACQUIRE_SIB2
} si_acquire_state_t;

@ -141,7 +141,7 @@ void mac::run_thread() {
while(started) {
while (!phy_h->sync_status()) {
while (!phy_h->sync_status() && started) {
usleep(5000);
if (phy_h->sync_status()) {
Debug("Setting ttysync to %d\n", phy_h->get_current_tti());

@ -61,8 +61,9 @@ void parse_args(all_args_t *args, int argc, char *argv[]) {
// Command line or config file options
bpo::options_description common("Configuration options");
common.add_options()
("rf.dl_freq", bpo::value<float>(&args->rf.dl_freq)->default_value(2680000000), "Downlink centre frequency")
("rf.ul_freq", bpo::value<float>(&args->rf.ul_freq)->default_value(2560000000), "Uplink centre frequency")
("rf.dl_earfcn", bpo::value<uint32_t>(&args->rf.dl_earfcn)->default_value(3400), "Downlink EARFCN")
("rf.dl_freq", bpo::value<float>(&args->rf.dl_freq)->default_value(2680000000), "(optional) Downlink centre frequency")
("rf.ul_freq", bpo::value<float>(&args->rf.ul_freq)->default_value(2560000000), "(optional) Uplink centre frequency")
("rf.rx_gain", bpo::value<float>(&args->rf.rx_gain)->default_value(-1), "Front-end receiver gain")
("rf.tx_gain", bpo::value<float>(&args->rf.tx_gain)->default_value(-1), "Front-end transmitter gain")
("rf.nof_rx_ant", bpo::value<uint32_t>(&args->rf.nof_rx_ant)->default_value(1), "Number of RX antennas")

@ -25,6 +25,7 @@
*/
#include <unistd.h>
#include <srslte/srslte.h>
#include "srslte/srslte.h"
#include "srslte/common/log.h"
#include "phy/phch_worker.h"
@ -62,9 +63,11 @@ namespace srsue {
time_adv_sec = 0;
cell_is_set = false;
sync_sfn_cnt = 0;
srate_mode = SRATE_NONE;
cell_search_in_progress = false;
for (uint32_t i = 0; i < nof_rx_antennas; i++) {
sf_buffer_sfn[i] = (cf_t *) srslte_vec_malloc(sizeof(cf_t) * 3 * SRSLTE_SF_LEN_PRB(100));
sf_buffer[i] = (cf_t *) srslte_vec_malloc(sizeof(cf_t) * 3 * SRSLTE_SF_LEN_PRB(100));
}
nof_tx_mutex = MUTEX_X_WORKER * workers_pool->get_nof_workers();
@ -82,8 +85,8 @@ namespace srsue {
running = false;
wait_thread_finish();
for (uint32_t i = 0; i < nof_rx_antennas; i++) {
if (sf_buffer_sfn[i]) {
free(sf_buffer_sfn[i]);
if (sf_buffer[i]) {
free(sf_buffer[i]);
}
}
}
@ -152,9 +155,14 @@ namespace srsue {
// Set options defined in expert section
set_ue_sync_opts(&ue_sync);
if (srslte_ue_dl_init_multi(&ue_dl_measure, cell, nof_rx_antennas)) {
Error("Setting cell: initiating ue_dl_measure\n");
return false;
}
for (uint32_t i = 0; i < workers_pool->get_nof_workers(); i++) {
if (!((phch_worker *) workers_pool->get_worker(i))->init_cell(cell)) {
Error("Error setting cell: initiating PHCH worker\n");
Error("Setting cell: initiating PHCH worker\n");
return false;
}
}
@ -179,6 +187,10 @@ namespace srsue {
usleep(2000);
}
srslte_ue_sync_free(&ue_sync);
srslte_ue_dl_free(&ue_dl_measure);
if (cell_is_set) {
for (uint32_t i = 0; i < workers_pool->get_nof_workers(); i++) {
((phch_worker *) workers_pool->get_worker(i))->free_cell();
@ -198,7 +210,6 @@ namespace srsue {
bzero(found_cells, 3 * sizeof(srslte_ue_cellsearch_result_t));
log_h->console("Searching for cell...\n");
if (srslte_ue_cellsearch_init_multi(&cs, SRSLTE_DEFAULT_MAX_FRAMES_PSS, radio_recv_wrapper_cs, nof_rx_antennas,
radio_h)) {
Error("Initiating UE cell search\n");
@ -214,7 +225,10 @@ namespace srsue {
srslte_ue_sync_start_agc(&cs.ue_sync, callback_set_rx_gain, last_gain);
}
if (srate_mode != SRATE_FIND) {
srate_mode = SRATE_FIND;
radio_h->set_rx_srate(1.92e6);
}
radio_h->start_rx();
/* Find a cell in the given N_id_2 or go through the 3 of them to find the strongest */
@ -246,9 +260,6 @@ namespace srsue {
cell.cp = found_cells[max_peak_cell].cp;
cellsearch_cfo = found_cells[max_peak_cell].cfo;
log_h->console("Found CELL ID: %d CP: %s, CFO: %.1f KHz.\nTrying to decode MIB...\n",
cell.id, srslte_cp_string(cell.cp), cellsearch_cfo / 1000);
srslte_ue_mib_sync_t ue_mib_sync;
if (srslte_ue_mib_sync_init_multi(&ue_mib_sync, cell.id, cell.cp, radio_recv_wrapper_cs, nof_rx_antennas,
@ -281,10 +292,6 @@ namespace srsue {
if (ret == 1) {
srslte_pbch_mib_unpack(bch_payload, &cell, NULL);
worker_com->set_cell(cell);
srslte_cell_fprint(stdout, &cell, 0);
srslte_bit_pack_vector(bch_payload, bch_payload_bits, SRSLTE_BCH_PAYLOAD_LEN);
mac->bch_decoded_ok(bch_payload_bits, SRSLTE_BCH_PAYLOAD_LEN / 8);
return true;
} else {
Warning("Error decoding MIB: Error decoding PBCH\n");
@ -293,45 +300,6 @@ namespace srsue {
}
int phch_recv::sync_sfn(void) {
int ret = SRSLTE_ERROR;
uint8_t bch_payload[SRSLTE_BCH_PAYLOAD_LEN];
srslte_ue_sync_decode_sss_on_track(&ue_sync, true);
ret = srslte_ue_sync_zerocopy_multi(&ue_sync, sf_buffer_sfn);
if (ret < 0) {
Error("Error calling ue_sync_get_buffer");
return -1;
}
if (ret == 1) {
if (srslte_ue_sync_get_sfidx(&ue_sync) == 0) {
int sfn_offset = 0;
Info("SYNC: Decoding MIB...\n");
int n = srslte_ue_mib_decode(&ue_mib, sf_buffer_sfn[0], bch_payload, NULL, &sfn_offset);
if (n < 0) {
Error("Error decoding MIB while synchronising SFN");
return -1;
} else if (n == SRSLTE_UE_MIB_FOUND) {
uint32_t sfn;
srslte_pbch_mib_unpack(bch_payload, &cell, &sfn);
sfn = (sfn+sfn_offset)%1024;
tti = sfn * 10;
srslte_ue_sync_decode_sss_on_track(&ue_sync, true);
Info("SYNC: DONE, TTI=%d, sfn_offset=%d\n", tti, sfn_offset);
srslte_ue_mib_reset(&ue_mib);
return 1;
}
}
} else {
Debug("SYNC: PSS/SSS not found...\n");
}
return 0;
}
void phch_recv::resync_sfn() {
sync_sfn_cnt = 0;
phy_state = CELL_SELECT;
@ -342,17 +310,17 @@ namespace srsue {
}
void phch_recv::cell_search_next() {
cell_search_in_progress = true;
cur_earfcn_index++;
if (cur_earfcn_index >= 0) {
if ((uint32_t) cur_earfcn_index >= earfcn.size() - 1) {
if (cur_earfcn_index >= (int) earfcn.size() - 1) {
cur_earfcn_index = 0;
}
// If PHY is running, stop and free resources
free_cell();
float dl_freq = srslte_band_fd(earfcn[cur_earfcn_index]);
float dl_freq = 1e6*srslte_band_fd(earfcn[cur_earfcn_index]);
if (dl_freq >= 0) {
log_h->console("Cell Search: Set DL EARFCN=%d, frequency=%.1f MHz\n", earfcn[cur_earfcn_index], dl_freq / 1e6);
log_h->info("Cell Search: Set DL EARFCN=%d, frequency=%.1f MHz, channel_index=%d\n", earfcn[cur_earfcn_index],
dl_freq / 1e6, cur_earfcn_index);
radio_h->set_rx_freq(dl_freq);
@ -366,25 +334,39 @@ namespace srsue {
}
void phch_recv::cell_search_start() {
if (earfcn.size() > 0) {
cur_earfcn_index = -1;
log_h->console("Cell Search: Starting procedure...\n");
log_h->console("Starting Cell Search procedure in %d EARFCNs...\n", earfcn.size());
log_h->info("Cell Search: Starting procedure...\n");
cell_search_next();
} else {
log_h->info("Empty EARFCN list. Stopping cell search...\n");
log_h->console("Empty EARFCN list. Stopping cell search...\n");
}
}
bool phch_recv::cell_select(uint32_t earfcn, srslte_cell_t cell) {
free_cell();
float dl_freq = srslte_band_fd(earfcn);
float ul_freq = srslte_band_ul_earfcn(earfcn);
int cnt=0;
while(phy_state == CELL_SEARCH && cnt<100) {
usleep(10000);
log_h->info("PHY in CELL_SEARCH. Waiting...\n");
}
if (phy_state==CELL_SEARCH) {
log_h->warning("PHY still in CELL_SEARCH, forcing CELL_SELECT...\n");
}
float dl_freq = 1e6*srslte_band_fd(earfcn);
float ul_freq = 1e6*srslte_band_fu(srslte_band_ul_earfcn(earfcn));
if (dl_freq >= 0 || ul_freq <= 0) {
log_h->console("Cell Select: Set EARFCN=%d, DL frequency=%.1f MHz, UL frequency=%.1f MHz\n", earfcn,
dl_freq / 1e6, ul_freq / 1e6);
log_h->info("Cell Select: Set EARFCN=%d, frequency=%.1f MHz, UL frequency=%.1f MHz\n", earfcn, dl_freq / 1e6,
ul_freq / 1e6);
radio_h->set_rx_freq(dl_freq);
radio_h->set_tx_freq(ul_freq);
ul_dl_factor = ul_freq/dl_freq;
cell_search_in_progress = false;
this->cell = cell;
if (init_cell()) {
phy_state = CELL_SELECT;
@ -398,6 +380,77 @@ namespace srsue {
return false;
}
int phch_recv::cell_sync_sfn(void) {
int ret = SRSLTE_ERROR;
uint8_t bch_payload[SRSLTE_BCH_PAYLOAD_LEN];
srslte_ue_sync_decode_sss_on_track(&ue_sync, true);
ret = srslte_ue_sync_zerocopy_multi(&ue_sync, sf_buffer);
if (ret < 0) {
Error("Error calling ue_sync_get_buffer");
return -1;
}
if (ret == 1) {
if (srslte_ue_sync_get_sfidx(&ue_sync) == 0) {
int sfn_offset = 0;
Info("SYNC: Decoding MIB...\n");
int n = srslte_ue_mib_decode(&ue_mib, sf_buffer[0], bch_payload, NULL, &sfn_offset);
if (n < 0) {
Error("SYNC: Error decoding MIB while synchronising SFN");
return -1;
} else if (n == SRSLTE_UE_MIB_FOUND) {
uint32_t sfn;
srslte_pbch_mib_unpack(bch_payload, &cell, &sfn);
sfn = (sfn+sfn_offset)%1024;
tti = sfn * 10;
srslte_ue_sync_decode_sss_on_track(&ue_sync, true);
Info("SYNC: DONE, TTI=%d, sfn_offset=%d\n", tti, sfn_offset);
srslte_ue_mib_reset(&ue_mib);
return 1;
}
}
} else {
Debug("SYNC: PSS/SSS not found...\n");
}
return 0;
}
int phch_recv::cell_meas_rsrp() {
uint32_t cfi = 0;
tti = (tti+1) % 10240;
log_h->step(tti);
uint32_t sf_idx = tti%10;
int sync_res = srslte_ue_sync_zerocopy_multi(&ue_sync, sf_buffer);
if (sync_res == 1) {
if (srslte_ue_dl_decode_fft_estimate_multi(&ue_dl_measure, sf_buffer, sf_idx, &cfi)) {
log_h->error("SYNC: Measuring RSRP: Estimating channel\n");
return -1;
}
float rsrp = srslte_chest_dl_get_rsrp(&ue_dl_measure.chest);
measure_rsrp = SRSLTE_VEC_CMA(rsrp, measure_rsrp, measure_cnt);
measure_cnt++;
log_h->info("SYNC: Measuring RSRP %d/%d, sf_idx=%d, RSRP=%.1f dBm\n",
measure_cnt, RSRP_MEASURE_NOF_FRAMES, sf_idx, 10 * log10(rsrp / 1000));
if (measure_cnt >= RSRP_MEASURE_NOF_FRAMES) {
return 1;
}
} else {
log_h->error("SYNC: Measuring RSRP: Sync error\n");
return -1;
}
return 0;
}
void phch_recv::run_thread() {
int sync_res;
phch_worker *worker = NULL;
@ -406,7 +459,6 @@ namespace srsue {
switch (phy_state) {
case CELL_SEARCH:
if (cell_search()) {
log_h->console("Initializating cell configuration...\n");
init_cell();
float srate = (float) srslte_sampling_freq_hz(cell.nof_prb);
@ -416,12 +468,11 @@ namespace srsue {
radio_h->set_master_clock_rate(23.04e6);
}
log_h->console("Setting Sampling frequency %.2f MHz\n", (float) srate / 1000000);
log_h->info("Setting Sampling frequency %.2f MHz\n", (float) srate / 1000000);
srate_mode = SRATE_CAMP;
radio_h->set_rx_srate(srate);
radio_h->set_tx_srate(srate);
ul_dl_factor = radio_h->get_tx_freq() / radio_h->get_rx_freq();
Info("SYNC: Cell found. Synchronizing...\n");
phy_state = CELL_SELECT;
sync_sfn_cnt = 0;
@ -438,14 +489,21 @@ namespace srsue {
radio_is_streaming = true;
}
switch (sync_sfn()) {
switch (cell_sync_sfn()) {
default:
log_h->console("Going IDLE\n");
phy_state = IDLE;
break;
case 1:
srslte_ue_sync_set_agc_period(&ue_sync, 20);
phy_state = CAMPING;
if (!cell_search_in_progress) {
phy_state = CELL_CAMP;
log_h->console("Sync OK. Camping on cell PCI=%d...\n", cell.id);
} else {
measure_cnt = 0;
measure_rsrp = 0;
phy_state = CELL_MEASURE;
}
break;
case 0:
break;
@ -459,10 +517,21 @@ namespace srsue {
log_h->warning("Timeout while synchronizing SFN\n");
}
break;
case CAMPING:
case CELL_MEASURE:
switch(cell_meas_rsrp()) {
case 1:
rrc->cell_found(earfcn[cur_earfcn_index], cell, 10*log10(measure_rsrp/1000));
phy_state = CELL_CAMP;
case 0:
break;
default:
log_h->error("SYNC: Getting RSRP cell measurement.\n");
cell_search_next();
}
break;
case CELL_CAMP:
tti = (tti+1) % 10240;
worker = (phch_worker *) workers_pool->wait_worker(tti);
sync_res = 0;
if (worker) {
for (uint32_t i = 0; i < nof_rx_antennas; i++) {
buffer[i] = worker->get_buffer(i);
@ -535,7 +604,7 @@ namespace srsue {
}
bool phch_recv::status_is_sync() {
return phy_state == CAMPING;
return phy_state == CELL_CAMP;
}
void phch_recv::get_current_cell(srslte_cell_t *cell_) {

@ -33,6 +33,7 @@
#include <string>
#include <algorithm>
#include <iterator>
#include <ue.h>
using namespace srslte;
@ -169,6 +170,7 @@ bool ue::init(all_args_t *args_)
}
if (args->rf.tx_gain > 0) {
radio.set_tx_gain(args->rf.tx_gain);
printf("set tx gain %f\n", args->rf.tx_gain);
} else {
radio.set_tx_gain(args->rf.rx_gain);
std::cout << std::endl <<
@ -189,6 +191,14 @@ bool ue::init(all_args_t *args_)
gw.init(&pdcp, &rrc, this, &gw_log);
usim.init(&args->usim, &usim_log);
// Currently EARFCN list is set to only one frequency as indicated in ue.conf
std::vector<uint32_t> earfcn_list;
earfcn_list.push_back(args->rf.dl_earfcn);
phy.set_earfcn(earfcn_list);
printf("\n\nRequesting NAS Attach...\n");
nas.attach_request();
started = true;
return true;
}

@ -25,7 +25,9 @@
*/
#include "srslte/asn1/liblte_rrc.h"
#include "upper/nas.h"
#include "srslte/common/bcd_helpers.h"
using namespace srslte;
@ -45,11 +47,9 @@ namespace srsue {
gw = gw_;
nas_log = nas_log_;
state = EMM_STATE_DEREGISTERED;
// Manual PLMN selection procedure
current_plmn.mcc = 1;
current_plmn.mnc = 1;
plmn_selection = PLMN_SELECTED;
plmn_selection = PLMN_NOT_SELECTED;
home_plmn.mcc = 61441; // This is 001
home_plmn.mnc = 65281; // This is 01
}
void nas::stop() {}
@ -62,11 +62,14 @@ namespace srsue {
UE interface
*******************************************************************************/
void nas::attach_request() {
nas_log->info("Attach Request\n");
if (state == EMM_STATE_DEREGISTERED) {
state = EMM_STATE_REGISTERED_INITIATED;
if (plmn_selection == PLMN_NOT_SELECTED) {
nas_log->info("Starting PLMN Search...\n");
rrc->plmn_search();
} else if (plmn_selection == PLMN_SELECTED) {
nas_log->info("Selecting PLMN %s\n", plmn_id_to_c_str(current_plmn).c_str());
rrc->plmn_select(current_plmn);
}
} else {
@ -84,24 +87,39 @@ namespace srsue {
*******************************************************************************/
void nas::plmn_found(LIBLTE_RRC_PLMN_IDENTITY_STRUCT plmn_id, uint16_t tracking_area_code) {
// if it's the plmn we want rrc->plmn_select() and plmn_selection = PLMN_SELECTED
// Store PLMN if not registered
for (uint32_t i=0;i<known_plmns.size();i++) {
if (plmn_id.mcc == known_plmns[i].mcc && plmn_id.mnc == known_plmns[i].mnc) {
nas_log->info("Detected known PLMN %s\n", plmn_id_to_c_str(plmn_id).c_str());
if (plmn_id.mcc == home_plmn.mcc && plmn_id.mnc == home_plmn.mnc) {
rrc->plmn_select(plmn_id);
}
return;
}
}
nas_log->info("Found PLMN: Id=%s, TAC=%d\n", plmn_id_to_c_str(plmn_id).c_str(),
tracking_area_code);
nas_log->console("Found PLMN: Id=%s, TAC=%d\n", plmn_id_to_c_str(plmn_id).c_str(),
tracking_area_code);
if (plmn_id.mcc == home_plmn.mcc && plmn_id.mnc == home_plmn.mnc) {
rrc->plmn_select(plmn_id);
}
}
void nas::cell_selected() {
if (state == EMM_STATE_REGISTERED_INITIATED) {
rrc->connect();
} else {
nas_log->info("Cell selcted in invalid state = %s\n", emm_state_text[state]);
nas_log->info("Cell selected in invalid state = %s\n", emm_state_text[state]);
}
}
bool nas::is_attached()
{
bool nas::is_attached() {
return state == EMM_STATE_REGISTERED;
}
void nas::notify_connection_setup()
{
void nas::notify_connection_setup() {
nas_log->debug("State = %s\n", emm_state_text[state]);
if (EMM_STATE_REGISTERED_INITIATED == state) {
send_attach_request();
@ -110,8 +128,7 @@ void nas::notify_connection_setup()
}
}
void nas::write_pdu(uint32_t lcid, byte_buffer_t *pdu)
{
void nas::write_pdu(uint32_t lcid, byte_buffer_t *pdu) {
uint8 pd;
uint8 msg_type;
@ -119,8 +136,7 @@ void nas::write_pdu(uint32_t lcid, byte_buffer_t *pdu)
// Parse the message
liblte_mme_parse_msg_header((LIBLTE_BYTE_MSG_STRUCT *) pdu, &pd, &msg_type);
switch(msg_type)
{
switch (msg_type) {
case LIBLTE_MME_MSG_TYPE_ATTACH_ACCEPT:
parse_attach_accept(lcid, pdu);
break;
@ -155,13 +171,11 @@ void nas::write_pdu(uint32_t lcid, byte_buffer_t *pdu)
}
}
uint32_t nas::get_ul_count()
{
uint32_t nas::get_ul_count() {
return count_ul;
}
bool nas::get_s_tmsi(LIBLTE_RRC_S_TMSI_STRUCT *s_tmsi)
{
bool nas::get_s_tmsi(LIBLTE_RRC_S_TMSI_STRUCT *s_tmsi) {
if (is_guti_set) {
s_tmsi->mmec = guti.mme_code;
s_tmsi->m_tmsi = guti.m_tmsi;
@ -181,10 +195,8 @@ void nas::integrity_generate(uint8_t *key_128,
uint8_t direction,
uint8_t *msg,
uint32_t msg_len,
uint8_t *mac)
{
switch(integ_algo)
{
uint8_t *mac) {
switch (integ_algo) {
case INTEGRITY_ALGORITHM_ID_EIA0:
break;
case INTEGRITY_ALGORITHM_ID_128_EIA1:
@ -210,29 +222,24 @@ void nas::integrity_generate(uint8_t *key_128,
}
}
void nas::integrity_check()
{
void nas::integrity_check() {
}
void nas::cipher_encrypt()
{
void nas::cipher_encrypt() {
}
void nas::cipher_decrypt()
{
void nas::cipher_decrypt() {
}
/*******************************************************************************
Parsers
*******************************************************************************/
void nas::parse_attach_accept(uint32_t lcid, byte_buffer_t *pdu)
{
void nas::parse_attach_accept(uint32_t lcid, byte_buffer_t *pdu) {
LIBLTE_MME_ATTACH_ACCEPT_MSG_STRUCT attach_accept;
LIBLTE_MME_ACTIVATE_DEFAULT_EPS_BEARER_CONTEXT_REQUEST_MSG_STRUCT act_def_eps_bearer_context_req;
LIBLTE_MME_ATTACH_COMPLETE_MSG_STRUCT attach_complete;
@ -243,42 +250,30 @@ void nas::parse_attach_accept(uint32_t lcid, byte_buffer_t *pdu)
liblte_mme_unpack_attach_accept_msg((LIBLTE_BYTE_MSG_STRUCT *) pdu, &attach_accept);
if(attach_accept.eps_attach_result == LIBLTE_MME_EPS_ATTACH_RESULT_EPS_ONLY)
{
if (attach_accept.eps_attach_result == LIBLTE_MME_EPS_ATTACH_RESULT_EPS_ONLY) {
//FIXME: Handle t3412.unit
//FIXME: Handle tai_list
if(attach_accept.guti_present)
{
if (attach_accept.guti_present) {
memcpy(&guti, &attach_accept.guti.guti, sizeof(LIBLTE_MME_EPS_MOBILE_ID_GUTI_STRUCT));
is_guti_set = true;
// TODO: log message to console
}
if(attach_accept.lai_present)
{
}
if(attach_accept.ms_id_present)
{}
if(attach_accept.emm_cause_present)
{}
if(attach_accept.t3402_present)
{}
if(attach_accept.t3423_present)
{}
if(attach_accept.equivalent_plmns_present)
{}
if(attach_accept.emerg_num_list_present)
{}
if(attach_accept.eps_network_feature_support_present)
{}
if(attach_accept.additional_update_result_present)
{}
if(attach_accept.t3412_ext_present)
{}
liblte_mme_unpack_activate_default_eps_bearer_context_request_msg(&attach_accept.esm_msg, &act_def_eps_bearer_context_req);
if(LIBLTE_MME_PDN_TYPE_IPV4 == act_def_eps_bearer_context_req.pdn_addr.pdn_type)
{
if (attach_accept.lai_present) {
}
if (attach_accept.ms_id_present) {}
if (attach_accept.emm_cause_present) {}
if (attach_accept.t3402_present) {}
if (attach_accept.t3423_present) {}
if (attach_accept.equivalent_plmns_present) {}
if (attach_accept.emerg_num_list_present) {}
if (attach_accept.eps_network_feature_support_present) {}
if (attach_accept.additional_update_result_present) {}
if (attach_accept.t3412_ext_present) {}
liblte_mme_unpack_activate_default_eps_bearer_context_request_msg(&attach_accept.esm_msg,
&act_def_eps_bearer_context_req);
if (LIBLTE_MME_PDN_TYPE_IPV4 == act_def_eps_bearer_context_req.pdn_addr.pdn_type) {
ip_addr |= act_def_eps_bearer_context_req.pdn_addr.addr[0] << 24;
ip_addr |= act_def_eps_bearer_context_req.pdn_addr.addr[1] << 16;
ip_addr |= act_def_eps_bearer_context_req.pdn_addr.addr[2] << 8;
@ -298,20 +293,16 @@ void nas::parse_attach_accept(uint32_t lcid, byte_buffer_t *pdu)
// Setup GW
char *err_str = NULL;
if(gw->setup_if_addr(ip_addr, err_str))
{
if (gw->setup_if_addr(ip_addr, err_str)) {
nas_log->error("Failed to set gateway address - %s\n", err_str);
}
}
else
{
} else {
nas_log->error("Not handling IPV6 or IPV4V6\n");
pool->deallocate(pdu);
return;
}
eps_bearer_id = act_def_eps_bearer_context_req.eps_bearer_id;
if(act_def_eps_bearer_context_req.transaction_id_present)
{
if (act_def_eps_bearer_context_req.transaction_id_present) {
transaction_id = act_def_eps_bearer_context_req.proc_transaction_id;
}
@ -337,7 +328,8 @@ void nas::parse_attach_accept(uint32_t lcid, byte_buffer_t *pdu)
act_def_eps_bearer_context_accept.eps_bearer_id = eps_bearer_id;
act_def_eps_bearer_context_accept.proc_transaction_id = transaction_id;
act_def_eps_bearer_context_accept.protocol_cnfg_opts_present = false;
liblte_mme_pack_activate_default_eps_bearer_context_accept_msg(&act_def_eps_bearer_context_accept, &attach_complete.esm_msg);
liblte_mme_pack_activate_default_eps_bearer_context_accept_msg(&act_def_eps_bearer_context_accept,
&attach_complete.esm_msg);
liblte_mme_pack_attach_complete_msg(&attach_complete,
LIBLTE_MME_SECURITY_HDR_TYPE_INTEGRITY_AND_CIPHERED,
count_ul,
@ -356,17 +348,14 @@ void nas::parse_attach_accept(uint32_t lcid, byte_buffer_t *pdu)
nas_log->info("Sending Attach Complete\n");
rrc->write_sdu(lcid, pdu);
}
else
{
} else {
nas_log->info("Not handling attach type %u\n", attach_accept.eps_attach_result);
state = EMM_STATE_DEREGISTERED;
pool->deallocate(pdu);
}
}
void nas::parse_attach_reject(uint32_t lcid, byte_buffer_t *pdu)
{
void nas::parse_attach_reject(uint32_t lcid, byte_buffer_t *pdu) {
LIBLTE_MME_ATTACH_REJECT_MSG_STRUCT attach_rej;
liblte_mme_unpack_attach_reject_msg((LIBLTE_BYTE_MSG_STRUCT *) pdu, &attach_rej);
@ -377,8 +366,7 @@ void nas::parse_attach_reject(uint32_t lcid, byte_buffer_t *pdu)
// FIXME: Command RRC to release?
}
void nas::parse_authentication_request(uint32_t lcid, byte_buffer_t *pdu)
{
void nas::parse_authentication_request(uint32_t lcid, byte_buffer_t *pdu) {
LIBLTE_MME_AUTHENTICATION_REQUEST_MSG_STRUCT auth_req;
LIBLTE_MME_AUTHENTICATION_RESPONSE_MSG_STRUCT auth_res;
@ -399,41 +387,34 @@ void nas::parse_authentication_request(uint32_t lcid, byte_buffer_t *pdu)
uint8_t res[16];
usim->generate_authentication_response(auth_req.rand, auth_req.autn, mcc, mnc, &net_valid, res);
if(net_valid)
{
if (net_valid) {
nas_log->info("Network authentication successful\n");
for(int i=0; i<8; i++)
{
for (int i = 0; i < 8; i++) {
auth_res.res[i] = res[i];
}
liblte_mme_pack_authentication_response_msg(&auth_res, (LIBLTE_BYTE_MSG_STRUCT *) pdu);
nas_log->info("Sending Authentication Response\n");
rrc->write_sdu(lcid, pdu);
}
else
{
} else {
nas_log->warning("Network authentication failure\n");
nas_log->console("Warning: Network authentication failure\n");
pool->deallocate(pdu);
}
}
void nas::parse_authentication_reject(uint32_t lcid, byte_buffer_t *pdu)
{
void nas::parse_authentication_reject(uint32_t lcid, byte_buffer_t *pdu) {
nas_log->warning("Received Authentication Reject\n");
pool->deallocate(pdu);
state = EMM_STATE_DEREGISTERED;
// FIXME: Command RRC to release?
}
void nas::parse_identity_request(uint32_t lcid, byte_buffer_t *pdu)
{
void nas::parse_identity_request(uint32_t lcid, byte_buffer_t *pdu) {
nas_log->error("TODO:parse_identity_request\n");
}
void nas::parse_security_mode_command(uint32_t lcid, byte_buffer_t *pdu)
{
void nas::parse_security_mode_command(uint32_t lcid, byte_buffer_t *pdu) {
bool success;
LIBLTE_MME_SECURITY_MODE_COMMAND_MSG_STRUCT sec_mode_cmd;
LIBLTE_MME_SECURITY_MODE_COMPLETE_MSG_STRUCT sec_mode_comp;
@ -456,14 +437,11 @@ void nas::parse_security_mode_command(uint32_t lcid, byte_buffer_t *pdu)
if (CIPHERING_ALGORITHM_ID_EEA0 != cipher_algo ||
(INTEGRITY_ALGORITHM_ID_128_EIA2 != integ_algo &&
INTEGRITY_ALGORITHM_ID_128_EIA1 != integ_algo) ||
sec_mode_cmd.nas_ksi.tsc_flag != LIBLTE_MME_TYPE_OF_SECURITY_CONTEXT_FLAG_NATIVE)
{
sec_mode_cmd.nas_ksi.tsc_flag != LIBLTE_MME_TYPE_OF_SECURITY_CONTEXT_FLAG_NATIVE) {
sec_mode_rej.emm_cause = LIBLTE_MME_EMM_CAUSE_UE_SECURITY_CAPABILITIES_MISMATCH;
nas_log->warning("Sending Security Mode Reject due to security capabilities mismatch\n");
success = false;
}
else
{
} else {
// Generate NAS encryption key and integrity protection key
usim->generate_nas_keys(k_nas_enc, k_nas_int, cipher_algo, integ_algo);
nas_log->debug_hex(k_nas_enc, 32, "NAS encryption key - k_nas_enc");
@ -495,16 +473,13 @@ void nas::parse_security_mode_command(uint32_t lcid, byte_buffer_t *pdu)
success = false;
} else {
if(sec_mode_cmd.imeisv_req_present && LIBLTE_MME_IMEISV_REQUESTED == sec_mode_cmd.imeisv_req)
{
if (sec_mode_cmd.imeisv_req_present && LIBLTE_MME_IMEISV_REQUESTED == sec_mode_cmd.imeisv_req) {
sec_mode_comp.imeisv_present = true;
sec_mode_comp.imeisv.type_of_id = LIBLTE_MME_MOBILE_ID_TYPE_IMEISV;
usim->get_imei_vec(sec_mode_comp.imeisv.imeisv, 15);
sec_mode_comp.imeisv.imeisv[14] = 5;
sec_mode_comp.imeisv.imeisv[15] = 3;
}
else
{
} else {
sec_mode_comp.imeisv_present = false;
}
@ -537,16 +512,15 @@ void nas::parse_security_mode_command(uint32_t lcid, byte_buffer_t *pdu)
rrc->write_sdu(lcid, pdu);
}
void nas::parse_service_reject(uint32_t lcid, byte_buffer_t *pdu)
{
void nas::parse_service_reject(uint32_t lcid, byte_buffer_t *pdu) {
nas_log->error("TODO:parse_service_reject\n");
}
void nas::parse_esm_information_request(uint32_t lcid, byte_buffer_t *pdu)
{
void nas::parse_esm_information_request(uint32_t lcid, byte_buffer_t *pdu) {
nas_log->error("TODO:parse_esm_information_request\n");
}
void nas::parse_emm_information(uint32_t lcid, byte_buffer_t *pdu)
{
void nas::parse_emm_information(uint32_t lcid, byte_buffer_t *pdu) {
nas_log->error("TODO:parse_emm_information\n");
}
@ -554,16 +528,14 @@ void nas::parse_emm_information(uint32_t lcid, byte_buffer_t *pdu)
Senders
*******************************************************************************/
void nas::send_attach_request()
{
void nas::send_attach_request() {
LIBLTE_MME_ATTACH_REQUEST_MSG_STRUCT attach_req;
byte_buffer_t *msg = pool_allocate;
u_int32_t i;
attach_req.eps_attach_type = LIBLTE_MME_EPS_ATTACH_TYPE_EPS_ATTACH;
for(i=0; i<8; i++)
{
for (i = 0; i < 8; i++) {
attach_req.ue_network_cap.eea[i] = false;
attach_req.ue_network_cap.eia[i] = false;
}
@ -605,8 +577,7 @@ void nas::send_attach_request()
rrc->write_sdu(RB_ID_SRB1, msg);
}
void nas::gen_pdn_connectivity_request(LIBLTE_BYTE_MSG_STRUCT *msg)
{
void nas::gen_pdn_connectivity_request(LIBLTE_BYTE_MSG_STRUCT *msg) {
LIBLTE_MME_PDN_CONNECTIVITY_REQUEST_MSG_STRUCT pdn_con_req;
nas_log->info("Generating PDN Connectivity Request\n");
@ -629,8 +600,7 @@ void nas::gen_pdn_connectivity_request(LIBLTE_BYTE_MSG_STRUCT *msg)
void nas::send_identity_response() {}
void nas::send_service_request()
{
void nas::send_service_request() {
byte_buffer_t *msg = pool_allocate;
count_ul++;

@ -27,6 +27,9 @@
#include <unistd.h>
#include <sstream>
#include <srslte/asn1/liblte_rrc.h>
#include <upper/rrc.h>
#include <srslte/phy/common/phy_common.h>
#include "upper/rrc.h"
#include "srslte/common/security.h"
@ -44,17 +47,14 @@ namespace srsue{
*******************************************************************************/
rrc::rrc()
:state(RRC_STATE_IDLE)
,drb_up(false)
{}
: state(RRC_STATE_IDLE), drb_up(false) {}
static void liblte_rrc_handler(void *ctx, char *str) {
rrc *r = (rrc *) ctx;
r->liblte_rrc_log(str);
}
void rrc::liblte_rrc_log(char* str)
{
void rrc::liblte_rrc_log(char *str) {
if (rrc_log) {
rrc_log->warning("[ASN]: %s\n", str);
} else {
@ -69,8 +69,7 @@ void rrc::init(phy_interface_rrc *phy_,
nas_interface_rrc *nas_,
usim_interface_rrc *usim_,
mac_interface_timers *mac_timers_,
srslte::log *rrc_log_)
{
srslte::log *rrc_log_) {
pool = byte_buffer_pool::get_instance();
phy = phy_;
mac = mac_;
@ -101,19 +100,16 @@ void rrc::init(phy_interface_rrc *phy_,
set_mac_default();
}
void rrc::stop()
{
void rrc::stop() {
thread_running = false;
wait_thread_finish();
}
rrc_state_t rrc::get_state()
{
rrc_state_t rrc::get_state() {
return state;
}
void rrc::set_ue_category(int category)
{
void rrc::set_ue_category(int category) {
if (category >= 1 && category <= 5) {
ue_category = category;
} else {
@ -138,8 +134,7 @@ void rrc::set_ue_category(int category)
NAS interface
*******************************************************************************/
uint16_t rrc::get_mcc()
{
uint16_t rrc::get_mcc() {
if (current_cell) {
if (current_cell->sib1.N_plmn_ids > 0) {
return current_cell->sib1.plmn_id[0].id.mcc;
@ -148,8 +143,7 @@ uint16_t rrc::get_mcc()
return 0;
}
uint16_t rrc::get_mnc()
{
uint16_t rrc::get_mnc() {
if (current_cell) {
if (current_cell->sib1.N_plmn_ids > 0) {
return current_cell->sib1.plmn_id[0].id.mnc;
@ -158,15 +152,14 @@ uint16_t rrc::get_mnc()
return 0;
}
void rrc::plmn_search()
{
void rrc::plmn_search() {
rrc_log->info("Starting PLMN search procedure\n");
state = RRC_STATE_PLMN_SELECTION;
phy->cell_search_start();
}
void rrc::plmn_select(LIBLTE_RRC_PLMN_IDENTITY_STRUCT plmn_id)
{
bool sync_ok = false;
void rrc::plmn_select(LIBLTE_RRC_PLMN_IDENTITY_STRUCT plmn_id) {
rrc_log->info("PLMN %s selected\n", plmn_id_to_c_str(plmn_id).c_str());
state = RRC_STATE_CELL_SELECTING;
@ -178,17 +171,12 @@ void rrc::plmn_select(LIBLTE_RRC_PLMN_IDENTITY_STRUCT plmn_id)
select_next_cell_in_plmn();
}
void rrc::connect()
{
void rrc::connect() {
pthread_mutex_lock(&mutex);
if (RRC_STATE_CELL_SELECTED == state) {
if (si_acquire_state == SI_ACQUIRE_IDLE) {
rrc_log->info("RRC in IDLE state - sending connection request.\n");
state = RRC_STATE_CONNECTING;
send_con_request();
} else {
rrc_log->warning("Received connect() but SI not acquired\n");
}
} else {
rrc_log->warning("Received connect() but cell is not selected\n");
}
@ -199,13 +187,38 @@ void rrc::select_next_cell_in_plmn() {
for (uint32_t i = last_selected_cell + 1; i < known_cells.size(); i++) {
for (uint32_t j = 0; j < known_cells[i].sib1.N_plmn_ids; j++) {
if (known_cells[i].sib1.plmn_id[j].id.mcc == selected_plmn_id.mcc ||
known_cells[i].sib1.plmn_id[j].id.mnc == selected_plmn_id.mnc)
{
known_cells[i].sib1.plmn_id[j].id.mnc == selected_plmn_id.mnc) {
rrc_log->info("Selecting cell PCI=%d, EARFCN=%d, Cell ID=0x%x\n",
known_cells[i].phy_cell.id, known_cells[i].earfcn,
known_cells[i].sib1.cell_id);
rrc_log->console("Selecting cell PCI=%d, EARFCN=%d, Cell ID=0x%x\n",
known_cells[i].phy_cell.id, known_cells[i].earfcn,
known_cells[i].sib1.cell_id);
// Check that cell satisfies S criteria
if (phy->cell_select(known_cells[i].earfcn, known_cells[i].phy_cell)) {
// Give time to the PHY to sync on the new cell
int cnt=0;
while(!phy->sync_status() && cnt<100) {
usleep(1000);
cnt++;
}
if (phy->sync_status()) {
if (!known_cells[i].has_valid_sib1) {
si_acquire_state = SI_ACQUIRE_SIB1;
} else if (!known_cells[i].has_valid_sib2) {
si_acquire_state = SI_ACQUIRE_SIB2;
} else {
si_acquire_state = SI_ACQUIRE_IDLE;
}
last_selected_cell = i;
} else {
rrc_log->warning("Selecting cell EARFCN=%d, Cell ID=0x%x: Could not synchronize\n",
known_cells[i].earfcn, known_cells[i].sib1.cell_id);
}
return;
} else {
rrc_log->warning("Selecting cell EARFCN=%d, Cell ID=0x%x.\n",
known_cells[i].earfcn, known_cells[i].sib1.cell_id);
}
}
}
@ -223,7 +236,8 @@ void rrc::cell_found(uint32_t earfcn, srslte_cell_t phy_cell, float rsrp) {
if (earfcn == known_cells[i].earfcn && phy_cell.id == known_cells[i].phy_cell.id) {
known_cells[i].rsrp = rsrp;
current_cell = &known_cells[i];
rrc_log->info("Updating cell EARFCN=%d, PCI=%d, RSRP=%d dBm\n", known_cells[i].earfcn, known_cells[i].phy_cell.id, known_cells[i].rsrp);
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);
return;
}
}
@ -239,13 +253,20 @@ void rrc::cell_found(uint32_t earfcn, srslte_cell_t phy_cell, float rsrp) {
// save current cell
current_cell = &known_cells.back();
rrc_log->info("Found new cell EARFCN=%d, PCI=%d, RSRP=%d dBm\n", cell.earfcn, cell.phy_cell.id, cell.rsrp);
si_acquire_state = SI_ACQUIRE_SIB1;
rrc_log->info("Found 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->console("Found 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);
}
// Detection of physical layer problems (5.3.11.1)
void rrc::out_of_sync()
{
void rrc::out_of_sync() {
if (!mac_timers->get(t311)->is_running() && !mac_timers->get(t310)->is_running()) {
n310_cnt++;
if (n310_cnt == N310) {
@ -258,8 +279,7 @@ void rrc::out_of_sync()
}
// Recovery of physical layer problems (5.3.11.2)
void rrc::in_sync()
{
void rrc::in_sync() {
if (mac_timers->get(t310)->is_running()) {
n311_cnt++;
if (n311_cnt == N311) {
@ -273,20 +293,17 @@ void rrc::in_sync()
/*******************************************************************************
PDCP interface
*******************************************************************************/
void rrc::write_pdu_bcch_bch(byte_buffer_t *pdu)
{
void rrc::write_pdu_bcch_bch(byte_buffer_t *pdu) {
pool->deallocate(pdu);
if (state == RRC_STATE_PLMN_SELECTION) {
// Do we need to do something with BCH?
rrc_log->info_hex(pdu->msg, pdu->N_bytes, "BCCH BCH message received.");
si_acquire_state = SI_ACQUIRE_SIB1;
} else {
rrc_log->warning("Received BCCH BCH in incorrect state\n");
}
}
void rrc::write_pdu_bcch_dlsch(byte_buffer_t *pdu)
{
void rrc::write_pdu_bcch_dlsch(byte_buffer_t *pdu) {
rrc_log->info_hex(pdu->msg, pdu->N_bytes, "BCCH DLSCH message received.");
rrc_log->info("BCCH DLSCH message Stack latency: %ld us\n", pdu->get_latency_us());
LIBLTE_RRC_BCCH_DLSCH_MSG_STRUCT dlsch_msg;
@ -296,8 +313,7 @@ void rrc::write_pdu_bcch_dlsch(byte_buffer_t *pdu)
liblte_rrc_unpack_bcch_dlsch_msg((LIBLTE_BIT_MSG_STRUCT *) &bit_buf, &dlsch_msg);
if (dlsch_msg.N_sibs > 0) {
if (LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_1 == dlsch_msg.sibs[0].sib_type && SI_ACQUIRE_SIB1 == si_acquire_state)
{
if (LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_1 == dlsch_msg.sibs[0].sib_type && SI_ACQUIRE_SIB1 == si_acquire_state) {
mac->bcch_stop_rx();
// Handle SIB1
@ -308,64 +324,75 @@ void rrc::write_pdu_bcch_dlsch(byte_buffer_t *pdu)
liblte_rrc_si_window_length_num[current_cell->sib1.si_window_length],
liblte_rrc_si_periodicity_num[current_cell->sib1.sched_info[0].si_periodicity]);
// Send PLMN and TAC to NAS
std::stringstream ss;
for(uint32_t i=0;i<current_cell->sib1.N_plmn_ids;i++){
std::string mcc;
std::string mnc;
mcc_to_string(current_cell->sib1.plmn_id[i].id.mcc, &mcc);
mnc_to_string(current_cell->sib1.plmn_id[i].id.mnc, &mnc);
ss << " PLMN Id: MCC " << mcc << " MNC " << mnc;
nas->plmn_found(current_cell->sib1.plmn_id[i].id, current_cell->sib1.tracking_area_code);
}
// Set TDD Config
if (current_cell->sib1.tdd) {
phy->set_config_tdd(&current_cell->sib1.tdd_cnfg);
}
rrc_log->console("SIB1 received, CellID=%d, %s\n",
current_cell->sib1.cell_id&0xfff,
ss.str().c_str());
current_cell->has_valid_sib1 = true;
// Jump to next state
switch(state) {
case RRC_STATE_CELL_SELECTING:
si_acquire_state = SI_ACQUIRE_SIB2;
break;
case RRC_STATE_PLMN_SELECTION:
si_acquire_state = SI_ACQUIRE_IDLE;
rrc_log->info("SI Acquisition done. Searching next cell...\n");
usleep(5000);
phy->cell_search_next();
break;
default:
si_acquire_state = SI_ACQUIRE_IDLE;
}
} else if (LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_2 == dlsch_msg.sibs[0].sib_type && SI_ACQUIRE_SIB2 == si_acquire_state)
{
// Send PLMN and TAC to NAS
std::stringstream ss;
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);
}
} else if (LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_2 == dlsch_msg.sibs[0].sib_type &&
SI_ACQUIRE_SIB2 == si_acquire_state) {
mac->bcch_stop_rx();
// Handle SIB2
memcpy(&current_cell->sib2, &dlsch_msg.sibs[0].sib.sib2, sizeof(LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_2_STRUCT));
rrc_log->console("SIB2 received\n");
rrc_log->info("SIB2 received\n");
apply_sib2_configs(&current_cell->sib2);
current_cell->has_valid_sib2 = true;
// Jump to next state
switch(state) {
case RRC_STATE_CELL_SELECTING:
si_acquire_state = SI_ACQUIRE_IDLE;
state = RRC_STATE_CELL_SELECTED;
nas->cell_selected();
break;
default:
si_acquire_state = SI_ACQUIRE_IDLE;
}
}
}
}
// Right now, this thread only controls System Information acquisition procedure
void rrc::run_thread()
{
void rrc::run_thread() {
uint32_t tti;
uint32_t si_win_start, si_win_len;
uint16_t period;
uint32_t nof_sib1_trials = 0;
const int SIB1_SEARCH_TIMEOUT = 30;
while(thread_running)
{
switch(si_acquire_state)
{
while (thread_running) {
switch (si_acquire_state) {
case SI_ACQUIRE_SIB1:
// Instruct MAC to look for SIB1
if (!current_cell->has_valid_sib1) {
tti = mac->get_current_tti();
si_win_start = sib_start_tti(tti, 2, 5);
mac->bcch_start_rx(si_win_start, 1);
@ -381,13 +408,10 @@ void rrc::run_thread()
}
nof_sib1_trials = 0;
}
} else {
si_acquire_state = SI_ACQUIRE_SIB2;
}
usleep(20000);
break;
case SI_ACQUIRE_SIB2:
// Instruct MAC to look for SIB2 only when selecting a cell
if (state == RRC_STATE_CELL_SELECTING && !current_cell->has_valid_sib2) {
tti = mac->get_current_tti();
period = liblte_rrc_si_periodicity_num[current_cell->sib1.sched_info[0].si_periodicity];
si_win_start = sib_start_tti(tti, period, 0);
@ -396,21 +420,7 @@ void rrc::run_thread()
mac->bcch_start_rx(si_win_start, si_win_len);
rrc_log->debug("Instructed MAC to search for SIB2, win_start=%d, win_len=%d\n",
si_win_start, si_win_len);
} else {
si_acquire_state = SI_ACQUIRE_DONE;
}
break;
case SI_ACQUIRE_DONE:
// After acquiring SI, tell NAS that the cell is selected or go to next cell in case of PLMN selection
if (state == RRC_STATE_CELL_SELECTING) {
nas->cell_selected();
state = RRC_STATE_CELL_SELECTED;
} else if (state == RRC_STATE_PLMN_SELECTION) {
phy->cell_search_next();
}
si_acquire_state = SI_ACQUIRE_IDLE;
usleep(current_cell->sib1.si_window_length*1000);
break;
default:
break;
@ -456,12 +466,10 @@ void rrc::run_thread()
NAS interface
*******************************************************************************/
void rrc::write_sdu(uint32_t lcid, byte_buffer_t *sdu)
{
void rrc::write_sdu(uint32_t lcid, byte_buffer_t *sdu) {
rrc_log->info_hex(sdu->msg, sdu->N_bytes, "RX %s SDU", rb_id_text[lcid]);
switch(state)
{
switch (state) {
case RRC_STATE_CONNECTING:
send_con_setup_complete(sdu);
break;
@ -480,8 +488,7 @@ void rrc::write_sdu(uint32_t lcid, byte_buffer_t *sdu)
MAC interface
*******************************************************************************/
/* Reception of PUCCH/SRS release procedure (Section 5.3.13) */
void rrc::release_pucch_srs()
{
void rrc::release_pucch_srs() {
// Apply default configuration for PUCCH (CQI and SR) and SRS (release)
set_phy_default_pucch_srs();
@ -498,13 +505,11 @@ void rrc::ra_problem() {
GW interface
*******************************************************************************/
bool rrc::is_connected()
{
bool rrc::is_connected() {
return (RRC_STATE_CONNECTED == state);
}
bool rrc::have_drb()
{
bool rrc::have_drb() {
return drb_up;
}
@ -512,13 +517,11 @@ bool rrc::have_drb()
PDCP interface
*******************************************************************************/
void rrc::write_pdu(uint32_t lcid, byte_buffer_t *pdu)
{
void rrc::write_pdu(uint32_t lcid, byte_buffer_t *pdu) {
rrc_log->info_hex(pdu->msg, pdu->N_bytes, "TX %s PDU", rb_id_text[lcid]);
rrc_log->info("TX PDU Stack latency: %ld us\n", pdu->get_latency_us());
switch(lcid)
{
switch (lcid) {
case RB_ID_SRB0:
parse_dl_ccch(pdu);
break;
@ -534,8 +537,7 @@ void rrc::write_pdu(uint32_t lcid, byte_buffer_t *pdu)
}
void rrc::write_pdu_pcch(byte_buffer_t *pdu)
{
void rrc::write_pdu_pcch(byte_buffer_t *pdu) {
if (pdu->N_bytes > 0 && pdu->N_bytes < SRSLTE_MAX_BUFFER_SIZE_BITS) {
rrc_log->info_hex(pdu->msg, pdu->N_bytes, "PCCH message received %d bytes\n", pdu->N_bytes);
rrc_log->info("PCCH message Stack latency: %ld us\n", pdu->get_latency_us());
@ -582,8 +584,7 @@ void rrc::write_pdu_pcch(byte_buffer_t *pdu)
RLC interface
*******************************************************************************/
void rrc::max_retx_attempted()
{
void rrc::max_retx_attempted() {
//TODO: Handle the radio link failure
rrc_log->warning("Max RLC reTx attempted\n");
//radio_link_failure();
@ -593,8 +594,7 @@ void rrc::max_retx_attempted()
Senders
*******************************************************************************/
void rrc::send_con_request()
{
void rrc::send_con_request() {
rrc_log->debug("Preparing RRC Connection Request\n");
LIBLTE_RRC_UL_CCCH_MSG_STRUCT ul_ccch_msg;
LIBLTE_RRC_S_TMSI_STRUCT s_tmsi;
@ -612,8 +612,7 @@ void rrc::send_con_request()
liblte_rrc_pack_ul_ccch_msg(&ul_ccch_msg, (LIBLTE_BIT_MSG_STRUCT *) &bit_buf);
// Byte align and pack the message bits for PDCP
if((bit_buf.N_bits % 8) != 0)
{
if ((bit_buf.N_bits % 8) != 0) {
for (uint32_t i = 0; i < 8 - (bit_buf.N_bits % 8); i++)
bit_buf.msg[bit_buf.N_bits + i] = 0;
bit_buf.N_bits += 8 - (bit_buf.N_bits % 8);
@ -640,8 +639,7 @@ void rrc::send_con_request()
/* RRC connection re-establishment procedure (5.3.7) */
void rrc::send_con_restablish_request()
{
void rrc::send_con_restablish_request() {
srslte_cell_t cell;
phy->get_current_cell(&cell);
@ -705,8 +703,7 @@ void rrc::send_con_restablish_request()
rrc_log->info("Cell Selection finished. Initiating transmission of RRC Connection Reestablishment Request\n");
// Byte align and pack the message bits for PDCP
if((bit_buf.N_bits % 8) != 0)
{
if ((bit_buf.N_bits % 8) != 0) {
for (uint32_t i = 0; i < 8 - (bit_buf.N_bits % 8); i++)
bit_buf.msg[bit_buf.N_bits + i] = 0;
bit_buf.N_bits += 8 - (bit_buf.N_bits % 8);
@ -730,8 +727,7 @@ void rrc::send_con_restablish_request()
}
void rrc::send_con_restablish_complete()
{
void rrc::send_con_restablish_complete() {
rrc_log->debug("Preparing RRC Connection Reestablishment Complete\n");
LIBLTE_RRC_UL_DCCH_MSG_STRUCT ul_dcch_msg;
@ -741,8 +737,7 @@ void rrc::send_con_restablish_complete()
liblte_rrc_pack_ul_dcch_msg(&ul_dcch_msg, (LIBLTE_BIT_MSG_STRUCT *) &bit_buf);
// Byte align and pack the message bits for PDCP
if((bit_buf.N_bits % 8) != 0)
{
if ((bit_buf.N_bits % 8) != 0) {
for (uint32_t i = 0; i < 8 - (bit_buf.N_bits % 8); i++)
bit_buf.msg[bit_buf.N_bits + i] = 0;
bit_buf.N_bits += 8 - (bit_buf.N_bits % 8);
@ -757,8 +752,7 @@ void rrc::send_con_restablish_complete()
pdcp->write_sdu(RB_ID_SRB1, pdcp_buf);
}
void rrc::send_con_setup_complete(byte_buffer_t *nas_msg)
{
void rrc::send_con_setup_complete(byte_buffer_t *nas_msg) {
rrc_log->debug("Preparing RRC Connection Setup Complete\n");
LIBLTE_RRC_UL_DCCH_MSG_STRUCT ul_dcch_msg;
@ -772,8 +766,7 @@ void rrc::send_con_setup_complete(byte_buffer_t *nas_msg)
liblte_rrc_pack_ul_dcch_msg(&ul_dcch_msg, (LIBLTE_BIT_MSG_STRUCT *) &bit_buf);
// Byte align and pack the message bits for PDCP
if((bit_buf.N_bits % 8) != 0)
{
if ((bit_buf.N_bits % 8) != 0) {
for (uint32_t i = 0; i < 8 - (bit_buf.N_bits % 8); i++)
bit_buf.msg[bit_buf.N_bits + i] = 0;
bit_buf.N_bits += 8 - (bit_buf.N_bits % 8);
@ -789,8 +782,7 @@ void rrc::send_con_setup_complete(byte_buffer_t *nas_msg)
pdcp->write_sdu(RB_ID_SRB1, pdcp_buf);
}
void rrc::send_ul_info_transfer(uint32_t lcid, byte_buffer_t *sdu)
{
void rrc::send_ul_info_transfer(uint32_t lcid, byte_buffer_t *sdu) {
rrc_log->debug("Preparing RX Info Transfer\n");
LIBLTE_RRC_UL_DCCH_MSG_STRUCT ul_dcch_msg;
@ -806,8 +798,7 @@ void rrc::send_ul_info_transfer(uint32_t lcid, byte_buffer_t *sdu)
pdu->reset();
// Byte align and pack the message bits for PDCP
if((bit_buf.N_bits % 8) != 0)
{
if ((bit_buf.N_bits % 8) != 0) {
for (uint32_t i = 0; i < 8 - (bit_buf.N_bits % 8); i++)
bit_buf.msg[bit_buf.N_bits + i] = 0;
bit_buf.N_bits += 8 - (bit_buf.N_bits % 8);
@ -821,8 +812,7 @@ void rrc::send_ul_info_transfer(uint32_t lcid, byte_buffer_t *sdu)
pdcp->write_sdu(lcid, pdu);
}
void rrc::send_security_mode_complete(uint32_t lcid, byte_buffer_t *pdu)
{
void rrc::send_security_mode_complete(uint32_t lcid, byte_buffer_t *pdu) {
rrc_log->debug("Preparing Security Mode Complete\n");
LIBLTE_RRC_UL_DCCH_MSG_STRUCT ul_dcch_msg;
ul_dcch_msg.msg_type = LIBLTE_RRC_UL_DCCH_MSG_TYPE_SECURITY_MODE_COMPLETE;
@ -830,8 +820,7 @@ void rrc::send_security_mode_complete(uint32_t lcid, byte_buffer_t *pdu)
liblte_rrc_pack_ul_dcch_msg(&ul_dcch_msg, (LIBLTE_BIT_MSG_STRUCT *) &bit_buf);
// Byte align and pack the message bits for PDCP
if((bit_buf.N_bits % 8) != 0)
{
if ((bit_buf.N_bits % 8) != 0) {
for (uint32_t i = 0; i < 8 - (bit_buf.N_bits % 8); i++)
bit_buf.msg[bit_buf.N_bits + i] = 0;
bit_buf.N_bits += 8 - (bit_buf.N_bits % 8);
@ -844,8 +833,7 @@ void rrc::send_security_mode_complete(uint32_t lcid, byte_buffer_t *pdu)
pdcp->write_sdu(lcid, pdu);
}
void rrc::send_rrc_con_reconfig_complete(uint32_t lcid, byte_buffer_t *pdu)
{
void rrc::send_rrc_con_reconfig_complete(uint32_t lcid, byte_buffer_t *pdu) {
rrc_log->debug("Preparing RRC Connection Reconfig Complete\n");
LIBLTE_RRC_UL_DCCH_MSG_STRUCT ul_dcch_msg;
@ -854,8 +842,7 @@ void rrc::send_rrc_con_reconfig_complete(uint32_t lcid, byte_buffer_t *pdu)
liblte_rrc_pack_ul_dcch_msg(&ul_dcch_msg, (LIBLTE_BIT_MSG_STRUCT *) &bit_buf);
// Byte align and pack the message bits for PDCP
if((bit_buf.N_bits % 8) != 0)
{
if ((bit_buf.N_bits % 8) != 0) {
for (uint32_t i = 0; i < 8 - (bit_buf.N_bits % 8); i++)
bit_buf.msg[bit_buf.N_bits + i] = 0;
bit_buf.N_bits += 8 - (bit_buf.N_bits % 8);
@ -868,15 +855,13 @@ void rrc::send_rrc_con_reconfig_complete(uint32_t lcid, byte_buffer_t *pdu)
pdcp->write_sdu(lcid, pdu);
}
void rrc::enable_capabilities()
{
void rrc::enable_capabilities() {
bool enable_ul_64 = ue_category >= 5 && current_cell->sib2.rr_config_common_sib.pusch_cnfg.enable_64_qam;
rrc_log->info("%s 64QAM PUSCH\n", enable_ul_64 ? "Enabling" : "Disabling");
phy->set_config_64qam_en(enable_ul_64);
}
void rrc::send_rrc_ue_cap_info(uint32_t lcid, byte_buffer_t *pdu)
{
void rrc::send_rrc_ue_cap_info(uint32_t lcid, byte_buffer_t *pdu) {
rrc_log->debug("Preparing UE Capability Info\n");
LIBLTE_RRC_UL_DCCH_MSG_STRUCT ul_dcch_msg;
@ -941,8 +926,7 @@ void rrc::send_rrc_ue_cap_info(uint32_t lcid, byte_buffer_t *pdu)
liblte_rrc_pack_ul_dcch_msg(&ul_dcch_msg, (LIBLTE_BIT_MSG_STRUCT *) &bit_buf);
// Byte align and pack the message bits for PDCP
if((bit_buf.N_bits % 8) != 0)
{
if ((bit_buf.N_bits % 8) != 0) {
for (uint32_t i = 0; i < 8 - (bit_buf.N_bits % 8); i++)
bit_buf.msg[bit_buf.N_bits + i] = 0;
bit_buf.N_bits += 8 - (bit_buf.N_bits % 8);
@ -959,8 +943,7 @@ void rrc::send_rrc_ue_cap_info(uint32_t lcid, byte_buffer_t *pdu)
Parsers
*******************************************************************************/
void rrc::parse_dl_ccch(byte_buffer_t *pdu)
{
void rrc::parse_dl_ccch(byte_buffer_t *pdu) {
srslte_bit_unpack_vector(pdu->msg, bit_buf.msg, pdu->N_bytes * 8);
bit_buf.N_bits = pdu->N_bytes * 8;
pool->deallocate(pdu);
@ -970,8 +953,7 @@ void rrc::parse_dl_ccch(byte_buffer_t *pdu)
rrc_log->info("SRB0 - Received %s\n",
liblte_rrc_dl_ccch_msg_type_text[dl_ccch_msg.msg_type]);
switch(dl_ccch_msg.msg_type)
{
switch (dl_ccch_msg.msg_type) {
case LIBLTE_RRC_DL_CCCH_MSG_TYPE_RRC_CON_REJ:
rrc_log->info("Connection Reject received. Wait time: %d\n",
dl_ccch_msg.msg.rrc_con_rej.wait_time);
@ -1001,8 +983,7 @@ void rrc::parse_dl_ccch(byte_buffer_t *pdu)
}
}
void rrc::parse_dl_dcch(uint32_t lcid, byte_buffer_t *pdu)
{
void rrc::parse_dl_dcch(uint32_t lcid, byte_buffer_t *pdu) {
srslte_bit_unpack_vector(pdu->msg, bit_buf.msg, pdu->N_bytes * 8);
bit_buf.N_bits = pdu->N_bytes * 8;
liblte_rrc_unpack_dl_dcch_msg((LIBLTE_BIT_MSG_STRUCT *) &bit_buf, &dl_dcch_msg);
@ -1014,10 +995,10 @@ void rrc::parse_dl_dcch(uint32_t lcid, byte_buffer_t *pdu)
// Reset and reuse pdu buffer if possible
pdu->reset();
switch(dl_dcch_msg.msg_type)
{
switch (dl_dcch_msg.msg_type) {
case LIBLTE_RRC_DL_DCCH_MSG_TYPE_DL_INFO_TRANSFER:
memcpy(pdu->msg, dl_dcch_msg.msg.dl_info_transfer.dedicated_info.msg, dl_dcch_msg.msg.dl_info_transfer.dedicated_info.N_bytes);
memcpy(pdu->msg, dl_dcch_msg.msg.dl_info_transfer.dedicated_info.msg,
dl_dcch_msg.msg.dl_info_transfer.dedicated_info.N_bytes);
pdu->N_bytes = dl_dcch_msg.msg.dl_info_transfer.dedicated_info.N_bytes;
nas->write_pdu(lcid, pdu);
break;
@ -1038,10 +1019,8 @@ void rrc::parse_dl_dcch(uint32_t lcid, byte_buffer_t *pdu)
break;
case LIBLTE_RRC_DL_DCCH_MSG_TYPE_UE_CAPABILITY_ENQUIRY:
transaction_id = dl_dcch_msg.msg.ue_cap_enquiry.rrc_transaction_id;
for(uint32_t i=0; i<dl_dcch_msg.msg.ue_cap_enquiry.N_ue_cap_reqs; i++)
{
if(LIBLTE_RRC_RAT_TYPE_EUTRA == dl_dcch_msg.msg.ue_cap_enquiry.ue_capability_request[i])
{
for (uint32_t i = 0; i < dl_dcch_msg.msg.ue_cap_enquiry.N_ue_cap_reqs; i++) {
if (LIBLTE_RRC_RAT_TYPE_EUTRA == dl_dcch_msg.msg.ue_cap_enquiry.ue_capability_request[i]) {
send_rrc_ue_cap_info(lcid, pdu);
break;
}
@ -1059,8 +1038,7 @@ void rrc::parse_dl_dcch(uint32_t lcid, byte_buffer_t *pdu)
/*******************************************************************************
Timer expiration callback
*******************************************************************************/
void rrc::timer_expired(uint32_t timeout_id)
{
void rrc::timer_expired(uint32_t timeout_id) {
if (timeout_id == t310) {
rrc_log->info("Timer T310 expired: Radio Link Failure\n");
radio_link_failure();
@ -1107,8 +1085,7 @@ void rrc::rrc_connection_release() {
pthread_mutex_unlock(&mutex);
}
void rrc::test_con_restablishment()
{
void rrc::test_con_restablishment() {
printf("Testing connection Reestablishment\n");
send_con_restablish_request();
}
@ -1132,8 +1109,7 @@ uint32_t rrc::sib_start_tti(uint32_t tti, uint32_t period, uint32_t x) {
return (period * 10 * (1 + tti / (period * 10)) + x) % 10240; // the 1 means next opportunity
}
void rrc::apply_sib2_configs(LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_2_STRUCT *sib2)
{
void rrc::apply_sib2_configs(LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_2_STRUCT *sib2) {
// Apply RACH timeAlginmentTimer configuration
mac_interface_rrc::mac_cfg_t cfg;
@ -1153,10 +1129,12 @@ void rrc::apply_sib2_configs(LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_2_STRUCT *sib2)
memcpy(&common.pdsch_cnfg, &sib2->rr_config_common_sib.pdsch_cnfg, sizeof(LIBLTE_RRC_PDSCH_CONFIG_COMMON_STRUCT));
memcpy(&common.pusch_cnfg, &sib2->rr_config_common_sib.pusch_cnfg, sizeof(LIBLTE_RRC_PUSCH_CONFIG_COMMON_STRUCT));
memcpy(&common.pucch_cnfg, &sib2->rr_config_common_sib.pucch_cnfg, sizeof(LIBLTE_RRC_PUCCH_CONFIG_COMMON_STRUCT));
memcpy(&common.ul_pwr_ctrl, &sib2->rr_config_common_sib.ul_pwr_ctrl, sizeof(LIBLTE_RRC_UL_POWER_CONTROL_COMMON_STRUCT));
memcpy(&common.ul_pwr_ctrl, &sib2->rr_config_common_sib.ul_pwr_ctrl,
sizeof(LIBLTE_RRC_UL_POWER_CONTROL_COMMON_STRUCT));
memcpy(&common.prach_cnfg, &sib2->rr_config_common_sib.prach_cnfg, sizeof(LIBLTE_RRC_PRACH_CONFIG_SIB_STRUCT));
if (sib2->rr_config_common_sib.srs_ul_cnfg.present) {
memcpy(&common.srs_ul_cnfg, &sib2->rr_config_common_sib.srs_ul_cnfg, sizeof(LIBLTE_RRC_SRS_UL_CONFIG_COMMON_STRUCT));
memcpy(&common.srs_ul_cnfg, &sib2->rr_config_common_sib.srs_ul_cnfg,
sizeof(LIBLTE_RRC_SRS_UL_CONFIG_COMMON_STRUCT));
} else {
// default is release
common.srs_ul_cnfg.present = false;
@ -1202,8 +1180,7 @@ void rrc::apply_sib2_configs(LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_2_STRUCT *sib2)
}
// Go through all information elements and apply defaults (9.2.4) if not defined
void rrc::apply_phy_config_dedicated(LIBLTE_RRC_PHYSICAL_CONFIG_DEDICATED_STRUCT *phy_cnfg, bool apply_defaults)
{
void rrc::apply_phy_config_dedicated(LIBLTE_RRC_PHYSICAL_CONFIG_DEDICATED_STRUCT *phy_cnfg, bool apply_defaults) {
// Get current configuration
LIBLTE_RRC_PHYSICAL_CONFIG_DEDICATED_STRUCT *current_cfg;
phy_interface_rrc::phy_cfg_t c;
@ -1224,7 +1201,8 @@ void rrc::apply_phy_config_dedicated(LIBLTE_RRC_PHYSICAL_CONFIG_DEDICATED_STRUCT
current_cfg->pusch_cnfg_ded.beta_offset_cqi_idx = 15;
}
if (phy_cnfg->ul_pwr_ctrl_ded_present) {
memcpy(&current_cfg->ul_pwr_ctrl_ded, &phy_cnfg->ul_pwr_ctrl_ded, sizeof(LIBLTE_RRC_UL_POWER_CONTROL_DEDICATED_STRUCT));
memcpy(&current_cfg->ul_pwr_ctrl_ded, &phy_cnfg->ul_pwr_ctrl_ded,
sizeof(LIBLTE_RRC_UL_POWER_CONTROL_DEDICATED_STRUCT));
} else if (apply_defaults) {
current_cfg->ul_pwr_ctrl_ded.p0_ue_pusch = 0;
current_cfg->ul_pwr_ctrl_ded.delta_mcs_en = LIBLTE_RRC_DELTA_MCS_ENABLED_EN0;
@ -1235,18 +1213,21 @@ void rrc::apply_phy_config_dedicated(LIBLTE_RRC_PHYSICAL_CONFIG_DEDICATED_STRUCT
current_cfg->ul_pwr_ctrl_ded.filter_coeff_present = true;
}
if (phy_cnfg->tpc_pdcch_cnfg_pucch_present) {
memcpy(&current_cfg->tpc_pdcch_cnfg_pucch, &phy_cnfg->tpc_pdcch_cnfg_pucch, sizeof(LIBLTE_RRC_TPC_PDCCH_CONFIG_STRUCT));
memcpy(&current_cfg->tpc_pdcch_cnfg_pucch, &phy_cnfg->tpc_pdcch_cnfg_pucch,
sizeof(LIBLTE_RRC_TPC_PDCCH_CONFIG_STRUCT));
} else if (apply_defaults) {
current_cfg->tpc_pdcch_cnfg_pucch.setup_present = false;
}
if (phy_cnfg->tpc_pdcch_cnfg_pusch_present) {
memcpy(&current_cfg->tpc_pdcch_cnfg_pusch, &phy_cnfg->tpc_pdcch_cnfg_pusch, sizeof(LIBLTE_RRC_TPC_PDCCH_CONFIG_STRUCT));
memcpy(&current_cfg->tpc_pdcch_cnfg_pusch, &phy_cnfg->tpc_pdcch_cnfg_pusch,
sizeof(LIBLTE_RRC_TPC_PDCCH_CONFIG_STRUCT));
} else {
current_cfg->tpc_pdcch_cnfg_pusch.setup_present = false;
}
if (phy_cnfg->cqi_report_cnfg_present) {
if (phy_cnfg->cqi_report_cnfg.report_periodic_present) {
memcpy(&current_cfg->cqi_report_cnfg.report_periodic, &phy_cnfg->cqi_report_cnfg.report_periodic, sizeof(LIBLTE_RRC_CQI_REPORT_PERIODIC_STRUCT));
memcpy(&current_cfg->cqi_report_cnfg.report_periodic, &phy_cnfg->cqi_report_cnfg.report_periodic,
sizeof(LIBLTE_RRC_CQI_REPORT_PERIODIC_STRUCT));
current_cfg->cqi_report_cnfg.report_periodic_setup_present = phy_cnfg->cqi_report_cnfg.report_periodic_setup_present;
} else if (apply_defaults) {
current_cfg->cqi_report_cnfg.report_periodic_setup_present = false;
@ -1260,7 +1241,8 @@ void rrc::apply_phy_config_dedicated(LIBLTE_RRC_PHYSICAL_CONFIG_DEDICATED_STRUCT
current_cfg->cqi_report_cnfg.nom_pdsch_rs_epre_offset = phy_cnfg->cqi_report_cnfg.nom_pdsch_rs_epre_offset;
}
if (phy_cnfg->srs_ul_cnfg_ded_present && phy_cnfg->srs_ul_cnfg_ded.setup_present) {
memcpy(&current_cfg->srs_ul_cnfg_ded, &phy_cnfg->srs_ul_cnfg_ded, sizeof(LIBLTE_RRC_SRS_UL_CONFIG_DEDICATED_STRUCT));
memcpy(&current_cfg->srs_ul_cnfg_ded, &phy_cnfg->srs_ul_cnfg_ded,
sizeof(LIBLTE_RRC_SRS_UL_CONFIG_DEDICATED_STRUCT));
} else if (apply_defaults) {
current_cfg->srs_ul_cnfg_ded.setup_present = false;
}
@ -1268,9 +1250,11 @@ void rrc::apply_phy_config_dedicated(LIBLTE_RRC_PHYSICAL_CONFIG_DEDICATED_STRUCT
if (!phy_cnfg->antenna_info_default_value) {
if (phy_cnfg->antenna_info_explicit_value.tx_mode != LIBLTE_RRC_TRANSMISSION_MODE_1 &&
phy_cnfg->antenna_info_explicit_value.tx_mode != LIBLTE_RRC_TRANSMISSION_MODE_2) {
rrc_log->error("Transmission mode TM%s not currently supported by srsUE\n", liblte_rrc_transmission_mode_text[phy_cnfg->antenna_info_explicit_value.tx_mode]);
rrc_log->error("Transmission mode TM%s not currently supported by srsUE\n",
liblte_rrc_transmission_mode_text[phy_cnfg->antenna_info_explicit_value.tx_mode]);
}
memcpy(&current_cfg->antenna_info_explicit_value, &phy_cnfg->antenna_info_explicit_value, sizeof(LIBLTE_RRC_ANTENNA_INFO_DEDICATED_STRUCT));
memcpy(&current_cfg->antenna_info_explicit_value, &phy_cnfg->antenna_info_explicit_value,
sizeof(LIBLTE_RRC_ANTENNA_INFO_DEDICATED_STRUCT));
} else if (apply_defaults) {
current_cfg->antenna_info_explicit_value.tx_mode = LIBLTE_RRC_TRANSMISSION_MODE_2;
current_cfg->antenna_info_explicit_value.codebook_subset_restriction_present = false;
@ -1282,7 +1266,8 @@ void rrc::apply_phy_config_dedicated(LIBLTE_RRC_PHYSICAL_CONFIG_DEDICATED_STRUCT
current_cfg->antenna_info_explicit_value.ue_tx_antenna_selection_setup_present = false;
}
if (phy_cnfg->sched_request_cnfg_present) {
memcpy(&current_cfg->sched_request_cnfg, &phy_cnfg->sched_request_cnfg, sizeof(LIBLTE_RRC_SCHEDULING_REQUEST_CONFIG_STRUCT));
memcpy(&current_cfg->sched_request_cnfg, &phy_cnfg->sched_request_cnfg,
sizeof(LIBLTE_RRC_SCHEDULING_REQUEST_CONFIG_STRUCT));
} else if (apply_defaults) {
current_cfg->sched_request_cnfg.setup_present = false;
}
@ -1329,8 +1314,7 @@ void rrc::apply_phy_config_dedicated(LIBLTE_RRC_PHYSICAL_CONFIG_DEDICATED_STRUCT
}
void rrc::apply_mac_config_dedicated(LIBLTE_RRC_MAC_MAIN_CONFIG_STRUCT *mac_cnfg, bool apply_defaults)
{
void rrc::apply_mac_config_dedicated(LIBLTE_RRC_MAC_MAIN_CONFIG_STRUCT *mac_cnfg, bool apply_defaults) {
// Set Default MAC main configuration (9.2.2)
LIBLTE_RRC_MAC_MAIN_CONFIG_STRUCT default_cfg;
bzero(&default_cfg, sizeof(LIBLTE_RRC_MAC_MAIN_CONFIG_STRUCT));
@ -1344,8 +1328,7 @@ void rrc::apply_mac_config_dedicated(LIBLTE_RRC_MAC_MAIN_CONFIG_STRUCT *mac_cnfg
if (!apply_defaults) {
if(mac_cnfg->ulsch_cnfg_present)
{
if (mac_cnfg->ulsch_cnfg_present) {
if (mac_cnfg->ulsch_cnfg.max_harq_tx_present) {
default_cfg.ulsch_cnfg.max_harq_tx = mac_cnfg->ulsch_cnfg.max_harq_tx;
default_cfg.ulsch_cnfg.max_harq_tx_present = true;
@ -1415,15 +1398,13 @@ void rrc::apply_rr_config_dedicated(LIBLTE_RRC_RR_CONFIG_DEDICATED_STRUCT *cnfg)
}
}
void rrc::handle_con_setup(LIBLTE_RRC_CONNECTION_SETUP_STRUCT *setup)
{
void rrc::handle_con_setup(LIBLTE_RRC_CONNECTION_SETUP_STRUCT *setup) {
// Apply the Radio Resource configuration
apply_rr_config_dedicated(&setup->rr_cnfg);
}
/* Reception of RRCConnectionReestablishment by the UE 5.3.7.5 */
void rrc::handle_con_reest(LIBLTE_RRC_CONNECTION_REESTABLISHMENT_STRUCT *setup)
{
void rrc::handle_con_reest(LIBLTE_RRC_CONNECTION_REESTABLISHMENT_STRUCT *setup) {
mac_timers->get(t301)->stop();
// TODO: Restablish DRB1. Not done because never was suspended
@ -1437,8 +1418,8 @@ void rrc::handle_con_reest(LIBLTE_RRC_CONNECTION_REESTABLISHMENT_STRUCT *setup)
}
void rrc::handle_rrc_con_reconfig(uint32_t lcid, LIBLTE_RRC_CONNECTION_RECONFIGURATION_STRUCT *reconfig, byte_buffer_t *pdu)
{
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) {
@ -1446,20 +1427,17 @@ void rrc::handle_rrc_con_reconfig(uint32_t lcid, LIBLTE_RRC_CONNECTION_RECONFIGU
} else {
printf("received con reconfig no rr confg present\n");
}
if(reconfig->meas_cnfg_present)
{
if (reconfig->meas_cnfg_present) {
//TODO: handle meas_cnfg
}
if(reconfig->mob_ctrl_info_present)
{
if (reconfig->mob_ctrl_info_present) {
//TODO: handle mob_ctrl_info
}
send_rrc_con_reconfig_complete(lcid, pdu);
byte_buffer_t *nas_sdu;
for(i=0;i<reconfig->N_ded_info_nas;i++)
{
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;
@ -1467,18 +1445,15 @@ void rrc::handle_rrc_con_reconfig(uint32_t lcid, LIBLTE_RRC_CONNECTION_RECONFIGU
}
}
void rrc::add_srb(LIBLTE_RRC_SRB_TO_ADD_MOD_STRUCT *srb_cnfg)
{
void rrc::add_srb(LIBLTE_RRC_SRB_TO_ADD_MOD_STRUCT *srb_cnfg) {
// Setup PDCP
pdcp->add_bearer(srb_cnfg->srb_id);
if (RB_ID_SRB2 == srb_cnfg->srb_id)
pdcp->config_security(srb_cnfg->srb_id, k_rrc_enc, k_rrc_int, cipher_algo, integ_algo);
// Setup RLC
if(srb_cnfg->rlc_cnfg_present)
{
if(srb_cnfg->rlc_default_cnfg_present)
{
if (srb_cnfg->rlc_cnfg_present) {
if (srb_cnfg->rlc_default_cnfg_present) {
rlc->add_bearer(srb_cnfg->srb_id);
} else {
rlc->add_bearer(srb_cnfg->srb_id, &srb_cnfg->rlc_explicit_cnfg);
@ -1491,19 +1466,15 @@ void rrc::add_srb(LIBLTE_RRC_SRB_TO_ADD_MOD_STRUCT *srb_cnfg)
int prioritized_bit_rate = -1;
int bucket_size_duration = -1;
if(srb_cnfg->lc_cnfg_present)
{
if(srb_cnfg->lc_default_cnfg_present)
{
if (srb_cnfg->lc_cnfg_present) {
if (srb_cnfg->lc_default_cnfg_present) {
if (RB_ID_SRB2 == srb_cnfg->srb_id)
priority = 3;
} else {
if(srb_cnfg->lc_explicit_cnfg.log_chan_sr_mask_present)
{
if (srb_cnfg->lc_explicit_cnfg.log_chan_sr_mask_present) {
//TODO
}
if(srb_cnfg->lc_explicit_cnfg.ul_specific_params_present)
{
if (srb_cnfg->lc_explicit_cnfg.ul_specific_params_present) {
if (srb_cnfg->lc_explicit_cnfg.ul_specific_params.log_chan_group_present)
log_chan_group = srb_cnfg->lc_explicit_cnfg.ul_specific_params.log_chan_group;
@ -1519,13 +1490,11 @@ void rrc::add_srb(LIBLTE_RRC_SRB_TO_ADD_MOD_STRUCT *srb_cnfg)
rrc_log->info("Added radio bearer %s\n", rb_id_text[srb_cnfg->srb_id]);
}
void rrc::add_drb(LIBLTE_RRC_DRB_TO_ADD_MOD_STRUCT *drb_cnfg)
{
void rrc::add_drb(LIBLTE_RRC_DRB_TO_ADD_MOD_STRUCT *drb_cnfg) {
if (!drb_cnfg->pdcp_cnfg_present ||
!drb_cnfg->rlc_cnfg_present ||
!drb_cnfg->lc_cnfg_present)
{
!drb_cnfg->lc_cnfg_present) {
rrc_log->error("Cannot add DRB - incomplete configuration\n");
return;
}
@ -1549,8 +1518,7 @@ void rrc::add_drb(LIBLTE_RRC_DRB_TO_ADD_MOD_STRUCT *drb_cnfg)
uint8_t priority = 1;
int prioritized_bit_rate = -1;
int bucket_size_duration = -1;
if(drb_cnfg->lc_cnfg.ul_specific_params_present)
{
if (drb_cnfg->lc_cnfg.ul_specific_params_present) {
if (drb_cnfg->lc_cnfg.ul_specific_params.log_chan_group_present) {
log_chan_group = drb_cnfg->lc_cnfg.ul_specific_params.log_chan_group;
} else {
@ -1573,8 +1541,7 @@ void rrc::add_drb(LIBLTE_RRC_DRB_TO_ADD_MOD_STRUCT *drb_cnfg)
rrc_log->info("Added radio bearer %s\n", rb_id_text[lcid]);
}
void rrc::release_drb(uint8_t lcid)
{
void rrc::release_drb(uint8_t lcid) {
// TODO
}
@ -1583,8 +1550,7 @@ void rrc::release_drb(uint8_t lcid)
****************************/
// PHY CONFIG DEDICATED Defaults (3GPP 36.331 v10 9.2.4)
void rrc::set_phy_default_pucch_srs()
{
void rrc::set_phy_default_pucch_srs() {
phy_interface_rrc::phy_cfg_t current_cfg;
phy->get_config(&current_cfg);
@ -1602,15 +1568,13 @@ void rrc::set_phy_default_pucch_srs()
mac->set_config_sr(&cfg);
}
void rrc::set_phy_default()
{
void rrc::set_phy_default() {
LIBLTE_RRC_PHYSICAL_CONFIG_DEDICATED_STRUCT defaults;
bzero(&defaults, sizeof(LIBLTE_RRC_PHYSICAL_CONFIG_DEDICATED_STRUCT));
apply_phy_config_dedicated(&defaults, true);
}
void rrc::set_mac_default()
{
void rrc::set_mac_default() {
apply_mac_config_dedicated(NULL, true);
LIBLTE_RRC_SCHEDULING_REQUEST_CONFIG_STRUCT sr_cfg;
bzero(&sr_cfg, sizeof(LIBLTE_RRC_SCHEDULING_REQUEST_CONFIG_STRUCT));

Loading…
Cancel
Save