added parser for rrc_cnfg section of rr.conf file, and dummy rrc_mobility class

master
Francisco Paisana 5 years ago
parent 2ec62f7fa9
commit 7e62d6d1f9

@ -4971,9 +4971,10 @@ LIBLTE_ERROR_ENUM liblte_s1ap_unpack_timetowait(uint8_t** ptr, LIBLTE_S1AP_TIMET
/******************************************************************************* /*******************************************************************************
/* ProtocolIE UE_HistoryInformation DYNAMIC SEQUENCE OF /* ProtocolIE UE_HistoryInformation DYNAMIC SEQUENCE OF
********************************************************************************/ ********************************************************************************/
#define LIBLTE_S1AP_UE_HISTORYINFORMATION_BIT_STRING_LEN 32 // FIXME: Check if this size is adequate
// lb:1, ub:16 // lb:1, ub:16
typedef struct { typedef struct {
uint32_t len; uint32_t len;
LIBLTE_S1AP_LASTVISITEDCELL_ITEM_STRUCT buffer[32]; // WARNING: Artificial limit to reduce memory footprint LIBLTE_S1AP_LASTVISITEDCELL_ITEM_STRUCT buffer[32]; // WARNING: Artificial limit to reduce memory footprint
} LIBLTE_S1AP_UE_HISTORYINFORMATION_STRUCT; } LIBLTE_S1AP_UE_HISTORYINFORMATION_STRUCT;

@ -22,17 +22,18 @@
#ifndef SRSENB_PARSER_H #ifndef SRSENB_PARSER_H
#define SRSENB_PARSER_H #define SRSENB_PARSER_H
#include <stdarg.h> #include "srslte/asn1/asn1_utils.h"
#include <string> #include <algorithm>
#include <fstream>
#include <iostream>
#include <libconfig.h++>
#include <list> #include <list>
#include <stdlib.h> #include <stdarg.h>
#include <stdint.h> #include <stdint.h>
#include <typeinfo> #include <stdlib.h>
#include <libconfig.h++>
#include <string.h> #include <string.h>
#include <iostream> #include <string>
#include <fstream> #include <typeinfo>
namespace srsenb { namespace srsenb {
@ -41,16 +42,15 @@ using namespace libconfig;
class parser class parser
{ {
public: public:
class field_itf class field_itf
{ {
public: public:
virtual ~field_itf(){} virtual ~field_itf() = default;
virtual int parse(Setting &root) = 0; virtual int parse(Setting& root) = 0;
virtual const char* get_name() = 0; virtual const char* get_name() = 0;
}; };
template<class T> template <class T>
class field_enum_str : public field_itf class field_enum_str : public field_itf
{ {
public: public:
@ -303,10 +303,113 @@ public:
return r; return r;
} }
private: private:
std::list<section*> sections; std::list<section*> sections;
std::string filename; std::string filename;
}; };
template <typename T>
int parse_opt_field(T& obj, bool& flag, const char* field_name, Setting& root)
{
flag = root.lookupValue(field_name, obj);
return 0;
}
template <typename T, typename Parser>
int parse_opt_field(T& obj, bool& flag, const char* field_name, Setting& root, Parser field_parser)
{
flag = false;
if (root.exists(field_name)) {
flag = true;
return field_parser(obj, root[field_name]);
}
return 0;
}
namespace asn1_parsers {
template <class EnumType>
bool nowhitespace_string_to_enum(EnumType& e, const std::string& s)
{
std::string s_nows = s;
std::transform(s_nows.begin(), s_nows.end(), s_nows.begin(), ::tolower);
s_nows.erase(std::remove(s_nows.begin(), s_nows.end(), ' '), s_nows.end());
s_nows.erase(std::remove(s_nows.begin(), s_nows.end(), '-'), s_nows.end());
for (uint32_t i = 0; i < EnumType::nof_types; ++i) {
e = (typename EnumType::options)i;
std::string s_nows2 = e.to_string();
std::transform(s_nows2.begin(), s_nows2.end(), s_nows2.begin(), ::tolower);
s_nows2.erase(std::remove(s_nows2.begin(), s_nows2.end(), ' '), s_nows2.end());
s_nows2.erase(std::remove(s_nows2.begin(), s_nows2.end(), '-'), s_nows2.end());
if (s_nows2 == s_nows) {
return true;
}
}
return false;
}
template <class EnumType>
int str_to_enum(EnumType& enum_val, Setting& root)
{
std::string val = root;
bool found = nowhitespace_string_to_enum(enum_val, val);
if (not found) {
fprintf(stderr, "PARSER ERROR: Invalid option: \"%s\" for asn1 enum type\n", val.c_str());
fprintf(stderr, "Valid options: \"%s\"", EnumType((typename EnumType::options)0).to_string().c_str());
for (uint32_t i = 1; i < EnumType::nof_types; i++) {
fprintf(stderr, ", \"%s\"", EnumType((typename EnumType::options)i).to_string().c_str());
}
fprintf(stderr, "\n");
}
return found ? 0 : -1;
}
template <typename EnumType>
int opt_str_to_enum(EnumType& enum_val, bool& presence_flag, Setting& root, const char* name)
{
return parse_opt_field(enum_val, presence_flag, name, root, str_to_enum<EnumType>);
} }
template <typename EnumType>
int number_to_enum(EnumType& enum_val, Setting& root)
{
if (root.isNumber()) {
typename EnumType::number_type val;
if (root.getType() == Setting::TypeInt64) {
val = (long int)root;
} else if (root.getType() == Setting::TypeInt) {
val = (int)root;
}
bool found = asn1::number_to_enum(enum_val, val);
if (not found) {
std::ostringstream ss;
ss << val;
fprintf(stderr, "Invalid option: %s for enum field \"%s\"\n", ss.str().c_str(), root.getName());
ss.str("");
ss << EnumType((typename EnumType::options)0).to_number();
fprintf(stderr, "Valid options: %s", ss.str().c_str());
for (uint32_t i = 1; i < EnumType::nof_types; i++) {
ss.str("");
ss << EnumType((typename EnumType::options)i).to_number();
fprintf(stderr, ", %s", ss.str().c_str());
}
fprintf(stderr, "\n");
}
return found ? 0 : -1;
} else {
std::string str_val = root;
fprintf(stderr, "Expected a number for enum field %s but received a string %s\n", root.getName(), str_val.c_str());
}
return -1;
}
template <typename EnumType>
int opt_number_to_enum(EnumType& enum_val, bool& presence_flag, Setting& root, const char* name)
{
return parse_opt_field(enum_val, presence_flag, name, root, number_to_enum<EnumType>);
}
} // namespace asn1_parsers
} // namespace srsenb
#endif // PARSER_H #endif // PARSER_H

@ -70,9 +70,28 @@ typedef struct {
asn1::rrc::rlc_cfg_c rlc_cfg; asn1::rrc::rlc_cfg_c rlc_cfg;
} rrc_cfg_qci_t; } rrc_cfg_qci_t;
// structure used to parse the cfg file.
struct meas_cell_cfg_t {
uint32_t earfcn;
uint16_t pci;
uint32_t cell_id;
float q_offset;
};
// neigh measurement Cell info
struct rrc_meas_cfg_t {
std::vector<meas_cell_cfg_t> meas_cells;
std::vector<asn1::rrc::report_cfg_eutra_s> meas_reports;
asn1::rrc::quant_cfg_eutra_s quant_cfg;
// uint32_t nof_meas_ids;
// srslte::rrc_meas_id_t meas_ids[LIBLTE_RRC_MAX_MEAS_ID];
// FIXME: Add blacklist cells
// FIXME: Add multiple meas configs
};
#define MAX_NOF_QCI 10 #define MAX_NOF_QCI 10
typedef struct { struct rrc_cfg_t {
asn1::rrc::sib_type1_s sib1; asn1::rrc::sib_type1_s sib1;
asn1::rrc::sib_info_item_c sibs[ASN1_RRC_MAX_SIB]; asn1::rrc::sib_info_item_c sibs[ASN1_RRC_MAX_SIB];
asn1::rrc::mac_main_cfg_s mac_cnfg; asn1::rrc::mac_main_cfg_s mac_cnfg;
@ -83,21 +102,23 @@ typedef struct {
rrc_cfg_sr_t sr_cfg; rrc_cfg_sr_t sr_cfg;
rrc_cfg_cqi_t cqi_cfg; rrc_cfg_cqi_t cqi_cfg;
rrc_cfg_qci_t qci_cfg[MAX_NOF_QCI]; rrc_cfg_qci_t qci_cfg[MAX_NOF_QCI];
srslte_cell_t cell; srslte_cell_t cell;
bool enable_mbsfn; bool enable_mbsfn;
uint32_t inactivity_timeout_ms; uint32_t inactivity_timeout_ms;
srslte::CIPHERING_ALGORITHM_ID_ENUM srslte::CIPHERING_ALGORITHM_ID_ENUM eea_preference_list[srslte::CIPHERING_ALGORITHM_ID_N_ITEMS];
eea_preference_list[srslte::CIPHERING_ALGORITHM_ID_N_ITEMS]; srslte::INTEGRITY_ALGORITHM_ID_ENUM eia_preference_list[srslte::INTEGRITY_ALGORITHM_ID_N_ITEMS];
srslte::INTEGRITY_ALGORITHM_ID_ENUM bool meas_cfg_present = false;
eia_preference_list[srslte::INTEGRITY_ALGORITHM_ID_N_ITEMS]; rrc_meas_cfg_t meas_cfg;
} rrc_cfg_t; uint32_t pci; // TODO: add this to srslte_cell_t?
uint32_t dl_earfcn; // TODO: add this to srslte_cell_t?
};
static const char rrc_state_text[RRC_STATE_N_ITEMS][100] = {"IDLE", static const char rrc_state_text[RRC_STATE_N_ITEMS][100] = {"IDLE",
"WAIT FOR CON SETUP COMPLETE", "WAIT FOR CON SETUP COMPLETE",
"WAIT FOR SECURITY MODE COMPLETE", "WAIT FOR SECURITY MODE COMPLETE",
"WAIT FOR UE CAPABILITIY INFORMATION", "WAIT FOR UE CAPABILITIY INFORMATION",
"WAIT FOR CON RECONF COMPLETE", "WAIT FOR CON RECONF COMPLETE",
"RRC CONNECTED" "RRC CONNECTED",
"RELEASE REQUEST"}; "RELEASE REQUEST"};
class rrc : public rrc_interface_pdcp, class rrc : public rrc_interface_pdcp,
@ -107,27 +128,8 @@ class rrc : public rrc_interface_pdcp,
public thread public thread
{ {
public: public:
rrc() : act_monitor(this), cnotifier(NULL), running(false), nof_si_messages(0), thread("RRC") rrc();
{ ~rrc();
users.clear();
pending_paging.clear();
pool = NULL;
phy = NULL;
mac = NULL;
rlc = NULL;
pdcp = NULL;
gtpu = NULL;
s1ap = NULL;
rrc_log = NULL;
bzero(&sr_sched, sizeof(sr_sched));
bzero(&cqi_sched, sizeof(cqi_sched));
bzero(&cfg.sr_cfg, sizeof(cfg.sr_cfg));
bzero(&cfg.cqi_cfg, sizeof(cfg.cqi_cfg));
bzero(&cfg.qci_cfg, sizeof(cfg.qci_cfg));
bzero(&cfg.cell, sizeof(cfg.cell));
}
void init(rrc_cfg_t* cfg, void init(rrc_cfg_t* cfg,
phy_interface_stack_lte* phy, phy_interface_stack_lte* phy,
@ -156,9 +158,9 @@ public:
// rrc_interface_s1ap // rrc_interface_s1ap
void write_dl_info(uint16_t rnti, srslte::unique_byte_buffer_t sdu); void write_dl_info(uint16_t rnti, srslte::unique_byte_buffer_t sdu);
void release_complete(uint16_t rnti); void release_complete(uint16_t rnti);
bool setup_ue_ctxt(uint16_t rnti, LIBLTE_S1AP_MESSAGE_INITIALCONTEXTSETUPREQUEST_STRUCT *msg); bool setup_ue_ctxt(uint16_t rnti, LIBLTE_S1AP_MESSAGE_INITIALCONTEXTSETUPREQUEST_STRUCT* msg);
bool modify_ue_ctxt(uint16_t rnti, LIBLTE_S1AP_MESSAGE_UECONTEXTMODIFICATIONREQUEST_STRUCT *msg); bool modify_ue_ctxt(uint16_t rnti, LIBLTE_S1AP_MESSAGE_UECONTEXTMODIFICATIONREQUEST_STRUCT* msg);
bool setup_ue_erabs(uint16_t rnti, LIBLTE_S1AP_MESSAGE_E_RABSETUPREQUEST_STRUCT *msg); bool setup_ue_erabs(uint16_t rnti, LIBLTE_S1AP_MESSAGE_E_RABSETUPREQUEST_STRUCT* msg);
bool release_erabs(uint32_t rnti); bool release_erabs(uint32_t rnti);
void add_paging_id(uint32_t ueid, LIBLTE_S1AP_UEPAGINGID_STRUCT UEPagingID); void add_paging_id(uint32_t ueid, LIBLTE_S1AP_UEPAGINGID_STRUCT UEPagingID);
@ -194,7 +196,9 @@ public:
class ue class ue
{ {
public: public:
ue(); class rrc_mobility;
ue(rrc* outer_rrc = nullptr, uint16_t rnti = 0);
bool is_connected(); bool is_connected();
bool is_idle(); bool is_idle();
bool is_timeout(); bool is_timeout();
@ -228,15 +232,17 @@ public:
void set_security_capabilities(LIBLTE_S1AP_UESECURITYCAPABILITIES_STRUCT *caps); void set_security_capabilities(LIBLTE_S1AP_UESECURITYCAPABILITIES_STRUCT *caps);
void set_security_key(uint8_t* key, uint32_t length); void set_security_key(uint8_t* key, uint32_t length);
bool setup_erabs(LIBLTE_S1AP_E_RABTOBESETUPLISTCTXTSUREQ_STRUCT *e); bool setup_erabs(LIBLTE_S1AP_E_RABTOBESETUPLISTCTXTSUREQ_STRUCT* e);
bool setup_erabs(LIBLTE_S1AP_E_RABTOBESETUPLISTBEARERSUREQ_STRUCT *e); bool setup_erabs(LIBLTE_S1AP_E_RABTOBESETUPLISTBEARERSUREQ_STRUCT* e);
void setup_erab(uint8_t id, LIBLTE_S1AP_E_RABLEVELQOSPARAMETERS_STRUCT *qos, void setup_erab(uint8_t id,
LIBLTE_S1AP_TRANSPORTLAYERADDRESS_STRUCT *addr, uint32_t teid_out, LIBLTE_S1AP_E_RABLEVELQOSPARAMETERS_STRUCT* qos,
LIBLTE_S1AP_NAS_PDU_STRUCT *nas_pdu); LIBLTE_S1AP_TRANSPORTLAYERADDRESS_STRUCT* addr,
uint32_t teid_out,
LIBLTE_S1AP_NAS_PDU_STRUCT* nas_pdu);
bool release_erabs(); bool release_erabs();
void notify_s1ap_ue_ctxt_setup_complete(); void notify_s1ap_ue_ctxt_setup_complete();
void notify_s1ap_ue_erab_setup_response(LIBLTE_S1AP_E_RABTOBESETUPLISTBEARERSUREQ_STRUCT *e); void notify_s1ap_ue_erab_setup_response(LIBLTE_S1AP_E_RABTOBESETUPLISTBEARERSUREQ_STRUCT* e);
int sr_allocate(uint32_t period, uint8_t* I_sr, uint16_t* N_pucch_sr); int sr_allocate(uint32_t period, uint8_t* I_sr, uint16_t* N_pucch_sr);
void sr_get(uint8_t* I_sr, uint16_t* N_pucch_sr); void sr_get(uint8_t* I_sr, uint16_t* N_pucch_sr);
@ -261,11 +267,12 @@ public:
bool is_csfb; bool is_csfb;
private: private:
srslte::byte_buffer_pool *pool; srslte::byte_buffer_pool* pool;
struct timeval t_last_activity;
struct timeval t_last_activity; struct timeval t_ue_init;
asn1::rrc::establishment_cause_e establishment_cause; asn1::rrc::establishment_cause_e establishment_cause;
std::unique_ptr<rrc_mobility> mobility_handler;
// S-TMSI for this UE // S-TMSI for this UE
bool has_tmsi; bool has_tmsi;
@ -386,8 +393,11 @@ private:
asn1::rrc::sib_type2_s sib2; asn1::rrc::sib_type2_s sib2;
asn1::rrc::sib_type7_s sib7; asn1::rrc::sib_type7_s sib7;
void run_thread(); class mobility_cfg;
void rem_user_thread(uint16_t rnti); std::unique_ptr<mobility_cfg> enb_mobility_cfg;
void run_thread();
void rem_user_thread(uint16_t rnti);
pthread_mutex_t user_mutex; pthread_mutex_t user_mutex;
pthread_mutex_t paging_mutex; pthread_mutex_t paging_mutex;

@ -0,0 +1,53 @@
/*
* Copyright 2013-2019 Software Radio Systems Limited
*
* This file is part of srsLTE.
*
* srsLTE is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of
* the License, or (at your option) any later version.
*
* srsLTE is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* A copy of the GNU Affero General Public License can be found in
* the LICENSE file in the top-level directory of this distribution
* and at http://www.gnu.org/licenses/.
*
*/
#ifndef SRSENB_RRC_MOBILITY_H
#define SRSENB_RRC_MOBILITY_H
#include "rrc.h"
#include <map>
namespace srsenb {
class rrc::mobility_cfg
{
public:
explicit mobility_cfg(rrc* outer_rrc);
private:
rrc* rrc_enb = nullptr;
};
class rrc::ue::rrc_mobility
{
public:
rrc_mobility(srsenb::rrc::ue* outer_ue);
private:
rrc::ue* rrc_ue;
rrc* rrc_enb;
rrc::mobility_cfg* cfg;
srslte::byte_buffer_pool* pool;
srslte::log* rrc_log;
};
} // namespace srsenb
#endif // SRSENB_RRC_MOBILITY_H

@ -196,6 +196,9 @@ int enb::parse_args(const all_args_t& args_)
rrc_cfg.inactivity_timeout_ms = args.general.rrc_inactivity_timer; rrc_cfg.inactivity_timeout_ms = args.general.rrc_inactivity_timer;
rrc_cfg.enable_mbsfn = args.stack.embms.enable; rrc_cfg.enable_mbsfn = args.stack.embms.enable;
rrc_cfg.dl_earfcn = args.enb.dl_earfcn;
rrc_cfg.pci = args.enb.pci;
// Check number of control symbols // Check number of control symbols
if (cell_cfg.nof_prb < 50 && args.stack.mac.sched.nof_ctrl_symbols != 3) { if (cell_cfg.nof_prb < 50 && args.stack.mac.sched.nof_ctrl_symbols != 3) {
args.stack.mac.sched.nof_ctrl_symbols = 3; args.stack.mac.sched.nof_ctrl_symbols = 3;

@ -21,9 +21,15 @@
#include "enb_cfg_parser.h" #include "enb_cfg_parser.h"
#include "srsenb/hdr/cfg_parser.h" #include "srsenb/hdr/cfg_parser.h"
#include "srslte/asn1/rrc_asn1_utils.h"
#include "srslte/phy/common/phy_common.h" #include "srslte/phy/common/phy_common.h"
#include "srslte/srslte.h" #include "srslte/srslte.h"
#include "srslte/asn1/rrc_asn1_utils.h"
#define HANDLEPARSERCODE(cond) \
if ((cond) != 0) { \
printf("[%d][%s()] Parser Error detected\n", __LINE__, __FUNCTION__); \
return -1; \
}
using namespace asn1::rrc; using namespace asn1::rrc;
@ -940,10 +946,16 @@ int enb::parse_rr(all_args_t* args, rrc_cfg_t* rrc_cfg)
cqi_report_cnfg.add_field(new parser::field<bool>("simultaneousAckCQI", &rrc_cfg->cqi_cfg.simultaneousAckCQI)); cqi_report_cnfg.add_field(new parser::field<bool>("simultaneousAckCQI", &rrc_cfg->cqi_cfg.simultaneousAckCQI));
cqi_report_cnfg.add_field(new field_sf_mapping(rrc_cfg->cqi_cfg.sf_mapping, &rrc_cfg->cqi_cfg.nof_subframes)); cqi_report_cnfg.add_field(new field_sf_mapping(rrc_cfg->cqi_cfg.sf_mapping, &rrc_cfg->cqi_cfg.nof_subframes));
/* RRC config section */
parser::section rrc_cnfg("rrc_cnfg");
rrc_cnfg.set_optional(&rrc_cfg->meas_cfg_present);
rrc_cnfg.add_field(new rr_sections::rrc_cnfg_section(&rrc_cfg->meas_cfg));
// Run parser with two sections // Run parser with two sections
parser p(args->enb_files.rr_config); parser p(args->enb_files.rr_config);
p.add_section(&mac_cnfg); p.add_section(&mac_cnfg);
p.add_section(&phy_cfg); p.add_section(&phy_cfg);
p.add_section(&rrc_cnfg);
return p.parse(); return p.parse();
} }
@ -1147,4 +1159,59 @@ int field_qci::parse(libconfig::Setting& root)
return 0; return 0;
} }
namespace rr_sections {
static int parse_meas_cell_list(rrc_meas_cfg_t* meas_cfg, Setting& root)
{
meas_cfg->meas_cells.resize(root.getLength());
for (uint32_t i = 0; i < meas_cfg->meas_cells.size(); ++i) {
meas_cfg->meas_cells[i].earfcn = root[i]["dl_earfcn"];
meas_cfg->meas_cells[i].pci = (unsigned int)root[i]["pci"] % 504;
meas_cfg->meas_cells[i].cell_id = (unsigned int)root[i]["cell_idx"];
meas_cfg->meas_cells[i].q_offset = 0; // LIBLTE_RRC_Q_OFFSET_RANGE_DB_0; // TODO
// // FIXME: TEMP
// printf("PARSER: neighbor cell: {dl_earfcn=%d pci=%d cell_idx=0x%x}\n",
// meas_cfg->meas_cells[i].earfcn,
// meas_cfg->meas_cells[i].pci,
// meas_cfg->meas_cells[i].cell_id);
}
return 0;
}
static int parse_meas_report_desc(rrc_meas_cfg_t* meas_cfg, Setting& root)
{
// NOTE: For now, only support one meas_report for all cells.
// TODO: for a1
// TODO: for a2
// meas report parsing
meas_cfg->meas_reports.resize(1);
asn1::rrc::report_cfg_eutra_s& meas_item = meas_cfg->meas_reports[0];
HANDLEPARSERCODE(asn1_parsers::str_to_enum(meas_item.trigger_quant, root["a3_report_type"]));
auto& event = meas_item.trigger_type.set_event();
event.event_id.set_event_a3().report_on_leave = false;
event.event_id.event_a3().a3_offset = (int)root["a3_offset"];
event.hysteresis = (int)root["a3_hysteresis"];
meas_item.max_report_cells = 1; // TODO: parse
meas_item.report_amount.value = report_cfg_eutra_s::report_amount_e_::r1; // TODO: parse
meas_item.report_interv.value = report_interv_e::ms120; // TODO: parse
// quant coeff parsing
auto& quant = meas_cfg->quant_cfg;
HANDLEPARSERCODE(asn1_parsers::number_to_enum(event.time_to_trigger, root["a3_time_to_trigger"]));
HANDLEPARSERCODE(
asn1_parsers::opt_number_to_enum(quant.filt_coef_rsrp, quant.filt_coef_rsrp_present, root, "rsrp_config"));
HANDLEPARSERCODE(
asn1_parsers::opt_number_to_enum(quant.filt_coef_rsrq, quant.filt_coef_rsrq_present, root, "rsrq_config"));
return 0;
}
int rrc_cnfg_section::parse(libconfig::Setting& root)
{
HANDLEPARSERCODE(parse_meas_cell_list(meas_cfg, root["meas_cell_list"]));
HANDLEPARSERCODE(parse_meas_report_desc(meas_cfg, root["meas_report_desc"]));
return 0;
}
} // namespace rr_sections
} // namespace srsenb } // namespace srsenb

@ -113,15 +113,59 @@ class field_qci : public parser::field_itf
public: public:
field_qci(rrc_cfg_qci_t *cfg_) { cfg = cfg_; } field_qci(rrc_cfg_qci_t *cfg_) { cfg = cfg_; }
~field_qci(){} ~field_qci(){}
const char* get_name() { const char* get_name() { return "field_cqi"; }
return "field_cqi";
} int parse(Setting& root);
private:
rrc_cfg_qci_t* cfg;
};
namespace rr_sections {
// rrc_cnfg
class rrc_cnfg_section final : public parser::field_itf
{
public:
explicit rrc_cnfg_section(rrc_meas_cfg_t* meas_cfg_) : meas_cfg(meas_cfg_) {}
int parse(Setting& root) override;
const char* get_name() override { return "meas_cell_list"; }
private:
rrc_meas_cfg_t* meas_cfg;
};
class field_meas_cell_list final : public parser::field_itf
{
public:
explicit field_meas_cell_list(rrc_meas_cfg_t* meas_cfg_) : meas_cfg(meas_cfg_) {}
int parse(Setting& root) override;
const char* get_name() override { return "meas_cell_list"; }
int parse(Setting &root);
private: private:
rrc_cfg_qci_t *cfg; rrc_meas_cfg_t* meas_cfg;
}; };
class field_meas_report_desc final : public parser::field_itf
{
public:
explicit field_meas_report_desc(rrc_meas_cfg_t* meas_cfg_) : meas_cfg(meas_cfg_) {}
int parse(Setting& root) override;
const char* get_name() override { return "meas_report_desc"; }
private:
rrc_meas_cfg_t* meas_cfg;
};
} // namespace rr_sections
// ASN1 parsers // ASN1 parsers
class field_asn1 : public parser::field_itf class field_asn1 : public parser::field_itf
@ -275,32 +319,12 @@ bool parse_enum_by_number_str(EnumType& enum_val, const char* name, Setting& roo
return false; return false;
} }
template <class EnumType>
bool nowhitespace_string_to_enum(EnumType& e, const std::string& s)
{
std::string s_nows = s;
std::transform(s_nows.begin(), s_nows.end(), s_nows.begin(), ::tolower);
s_nows.erase(std::remove(s_nows.begin(), s_nows.end(), ' '), s_nows.end());
s_nows.erase(std::remove(s_nows.begin(), s_nows.end(), '-'), s_nows.end());
for (uint32_t i = 0; i < EnumType::nof_types; ++i) {
e = (typename EnumType::options)i;
std::string s_nows2 = e.to_string();
std::transform(s_nows2.begin(), s_nows2.end(), s_nows2.begin(), ::tolower);
s_nows2.erase(std::remove(s_nows2.begin(), s_nows2.end(), ' '), s_nows2.end());
s_nows2.erase(std::remove(s_nows2.begin(), s_nows2.end(), '-'), s_nows2.end());
if (s_nows2 == s_nows) {
return true;
}
}
return false;
}
template <class EnumType> template <class EnumType>
bool parse_enum_by_str(EnumType& enum_val, const char* name, Setting& root) bool parse_enum_by_str(EnumType& enum_val, const char* name, Setting& root)
{ {
std::string val; std::string val;
if (root.lookupValue(name, val)) { if (root.lookupValue(name, val)) {
bool found = nowhitespace_string_to_enum(enum_val, val); bool found = asn1_parsers::nowhitespace_string_to_enum(enum_val, val);
if (not found) { if (not found) {
fprintf(stderr, "PARSER ERROR: Invalid option: \"%s\" for field \"%s\"\n", val.c_str(), name); fprintf(stderr, "PARSER ERROR: Invalid option: \"%s\" for field \"%s\"\n", val.c_str(), name);
fprintf(stderr, "Valid options: \"%s\"", EnumType((typename EnumType::options)0).to_string().c_str()); fprintf(stderr, "Valid options: \"%s\"", EnumType((typename EnumType::options)0).to_string().c_str());

@ -18,7 +18,7 @@
# and at http://www.gnu.org/licenses/. # and at http://www.gnu.org/licenses/.
# #
set(SOURCES rrc.cc) set(SOURCES rrc.cc rrc_mobility.cc)
add_library(srsenb_rrc STATIC ${SOURCES}) add_library(srsenb_rrc STATIC ${SOURCES})

@ -20,6 +20,7 @@
*/ */
#include "srsenb/hdr/stack/rrc/rrc.h" #include "srsenb/hdr/stack/rrc/rrc.h"
#include "srsenb/hdr/stack/rrc/rrc_mobility.h"
#include "srslte/asn1/asn1_utils.h" #include "srslte/asn1/asn1_utils.h"
#include "srslte/asn1/liblte_mme.h" #include "srslte/asn1/liblte_mme.h"
#include "srslte/asn1/rrc_asn1_utils.h" #include "srslte/asn1/rrc_asn1_utils.h"
@ -37,6 +38,30 @@ using namespace asn1::rrc;
namespace srsenb { namespace srsenb {
rrc::rrc() : act_monitor(this), cnotifier(NULL), running(false), nof_si_messages(0), thread("RRC")
{
users.clear();
pending_paging.clear();
pool = NULL;
phy = NULL;
mac = NULL;
rlc = NULL;
pdcp = NULL;
gtpu = NULL;
s1ap = NULL;
rrc_log = NULL;
bzero(&sr_sched, sizeof(sr_sched));
bzero(&cqi_sched, sizeof(cqi_sched));
bzero(&cfg.sr_cfg, sizeof(cfg.sr_cfg));
bzero(&cfg.cqi_cfg, sizeof(cfg.cqi_cfg));
bzero(&cfg.qci_cfg, sizeof(cfg.qci_cfg));
bzero(&cfg.cell, sizeof(cfg.cell));
}
rrc::~rrc() {}
void rrc::init(rrc_cfg_t* cfg_, void rrc::init(rrc_cfg_t* cfg_,
phy_interface_stack_lte* phy_, phy_interface_stack_lte* phy_,
mac_interface_rrc* mac_, mac_interface_rrc* mac_,
@ -67,6 +92,7 @@ void rrc::init(rrc_cfg_t* cfg_,
nof_si_messages = generate_sibs(); nof_si_messages = generate_sibs();
config_mac(); config_mac();
enb_mobility_cfg.reset(new mobility_cfg(this));
pthread_mutex_init(&user_mutex, NULL); pthread_mutex_init(&user_mutex, NULL);
pthread_mutex_init(&paging_mutex, NULL); pthread_mutex_init(&paging_mutex, NULL);
@ -1002,19 +1028,18 @@ void rrc::activity_monitor::run_thread()
} }
} }
/******************************************************************************* /*******************************************************************************
UE class UE class
Every function in UE class is called from a mutex environment thus does not Every function in UE class is called from a mutex environment thus does not
need extra protection. need extra protection.
*******************************************************************************/ *******************************************************************************/
rrc::ue::ue()
rrc::ue::ue(rrc* outer_rrc, uint16_t rnti_) :
parent(outer_rrc),
rnti(rnti_),
pool(srslte::byte_buffer_pool::get_instance())
{ {
parent = NULL;
set_activity(); set_activity();
has_tmsi = false; has_tmsi = false;
connect_notified = false; connect_notified = false;
@ -1035,7 +1060,8 @@ rrc::ue::ue()
nas_pending = false; nas_pending = false;
is_csfb = false; is_csfb = false;
state = RRC_STATE_IDLE; state = RRC_STATE_IDLE;
pool = srslte::byte_buffer_pool::get_instance(); gettimeofday(&t_ue_init, NULL);
mobility_handler.reset(new rrc_mobility(this));
} }
rrc_state_t rrc::ue::get_state() rrc_state_t rrc::ue::get_state()
@ -2119,7 +2145,10 @@ void rrc::ue::send_dl_dcch(dl_dcch_msg_s* dl_dcch_msg, srslte::unique_byte_buffe
} }
if (pdu) { if (pdu) {
asn1::bit_ref bref(pdu->msg, pdu->get_tailroom()); asn1::bit_ref bref(pdu->msg, pdu->get_tailroom());
dl_dcch_msg->pack(bref); if (dl_dcch_msg->pack(bref) == asn1::SRSASN_ERROR_ENCODE_FAIL) {
parent->rrc_log->error("Failed to encode DL-DCCH-Msg\n");
return;
}
pdu->N_bytes = 1u + (uint32_t)bref.distance_bytes(pdu->msg); pdu->N_bytes = 1u + (uint32_t)bref.distance_bytes(pdu->msg);
// send on SRB2 if user is fully registered (after RRC reconfig complete) // send on SRB2 if user is fully registered (after RRC reconfig complete)

@ -0,0 +1,50 @@
/*
* Copyright 2013-2019 Software Radio Systems Limited
*
* This file is part of srsLTE.
*
* srsLTE is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of
* the License, or (at your option) any later version.
*
* srsLTE is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* A copy of the GNU Affero General Public License can be found in
* the LICENSE file in the top-level directory of this distribution
* and at http://www.gnu.org/licenses/.
*
*/
#include "srsenb/hdr/stack/rrc/rrc_mobility.h"
#include "srslte/common/bcd_helpers.h"
#include "srslte/common/common.h"
#include <algorithm>
#include <cstdio>
#include <cstring>
namespace srsenb {
/*************************************************************************************************
* mobility_cfg class
************************************************************************************************/
rrc::mobility_cfg::mobility_cfg(rrc* outer_rrc) : rrc_enb(outer_rrc) {}
/*************************************************************************************************
* rrc_mobility class
************************************************************************************************/
rrc::ue::rrc_mobility::rrc_mobility(rrc::ue* outer_ue) :
rrc_ue(outer_ue),
rrc_enb(outer_ue->parent),
cfg(outer_ue->parent->enb_mobility_cfg.get()),
pool(outer_ue->pool),
rrc_log(outer_ue->parent->rrc_log)
{
}
} // namespace srsenb
Loading…
Cancel
Save