|
|
|
@ -29,8 +29,8 @@
|
|
|
|
|
#include "srslte/interfaces/sched_interface.h"
|
|
|
|
|
#include "srslte/srslte.h"
|
|
|
|
|
|
|
|
|
|
using srslte::byte_buffer_t;
|
|
|
|
|
using srslte::bit_buffer_t;
|
|
|
|
|
using srslte::byte_buffer_t;
|
|
|
|
|
using srslte::uint32_to_uint8;
|
|
|
|
|
using srslte::uint8_to_uint32;
|
|
|
|
|
|
|
|
|
@ -38,19 +38,19 @@ using namespace asn1::rrc;
|
|
|
|
|
|
|
|
|
|
namespace srsenb {
|
|
|
|
|
|
|
|
|
|
rrc::rrc() : act_monitor(this), cnotifier(NULL), running(false), nof_si_messages(0), thread("RRC")
|
|
|
|
|
rrc::rrc() : act_monitor(this), cnotifier(nullptr), 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;
|
|
|
|
|
pool = nullptr;
|
|
|
|
|
phy = nullptr;
|
|
|
|
|
mac = nullptr;
|
|
|
|
|
rlc = nullptr;
|
|
|
|
|
pdcp = nullptr;
|
|
|
|
|
gtpu = nullptr;
|
|
|
|
|
s1ap = nullptr;
|
|
|
|
|
rrc_log = nullptr;
|
|
|
|
|
|
|
|
|
|
bzero(&sr_sched, sizeof(sr_sched));
|
|
|
|
|
bzero(&cqi_sched, sizeof(cqi_sched));
|
|
|
|
@ -78,7 +78,7 @@ void rrc::init(rrc_cfg_t* cfg_,
|
|
|
|
|
gtpu = gtpu_;
|
|
|
|
|
s1ap = s1ap_;
|
|
|
|
|
rrc_log = log_rrc;
|
|
|
|
|
cnotifier = NULL;
|
|
|
|
|
cnotifier = nullptr;
|
|
|
|
|
|
|
|
|
|
running = false;
|
|
|
|
|
pool = srslte::byte_buffer_pool::get_instance();
|
|
|
|
@ -94,8 +94,8 @@ void rrc::init(rrc_cfg_t* cfg_,
|
|
|
|
|
config_mac();
|
|
|
|
|
enb_mobility_cfg.reset(new mobility_cfg(&cfg, log_rrc));
|
|
|
|
|
|
|
|
|
|
pthread_mutex_init(&user_mutex, NULL);
|
|
|
|
|
pthread_mutex_init(&paging_mutex, NULL);
|
|
|
|
|
pthread_mutex_init(&user_mutex, nullptr);
|
|
|
|
|
pthread_mutex_init(&paging_mutex, nullptr);
|
|
|
|
|
|
|
|
|
|
act_monitor.start(RRC_THREAD_PRIO);
|
|
|
|
|
bzero(&sr_sched, sizeof(sr_sched_t));
|
|
|
|
@ -112,7 +112,7 @@ void rrc::stop()
|
|
|
|
|
{
|
|
|
|
|
if (running) {
|
|
|
|
|
running = false;
|
|
|
|
|
rrc_pdu p = {0, LCID_EXIT, NULL};
|
|
|
|
|
rrc_pdu p = {0, LCID_EXIT, nullptr};
|
|
|
|
|
rx_pdu_queue.push(std::move(p));
|
|
|
|
|
wait_thread_finish();
|
|
|
|
|
}
|
|
|
|
@ -124,7 +124,6 @@ void rrc::stop()
|
|
|
|
|
pthread_mutex_destroy(&paging_mutex);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*******************************************************************************
|
|
|
|
|
Public functions
|
|
|
|
|
|
|
|
|
@ -136,7 +135,7 @@ void rrc::get_metrics(rrc_metrics_t &m)
|
|
|
|
|
if (running) {
|
|
|
|
|
pthread_mutex_lock(&user_mutex);
|
|
|
|
|
m.n_ues = 0;
|
|
|
|
|
for(std::map<uint16_t, ue>::iterator iter=users.begin(); m.n_ues < ENB_METRICS_MAX_USERS &&iter!=users.end(); ++iter) {
|
|
|
|
|
for (auto iter = users.begin(); m.n_ues < ENB_METRICS_MAX_USERS && iter != users.end(); ++iter) {
|
|
|
|
|
ue* u = (ue*)&iter->second;
|
|
|
|
|
if (iter->first != SRSLTE_MRNTI) {
|
|
|
|
|
m.ues[m.n_ues++].state = u->get_state();
|
|
|
|
@ -162,46 +161,54 @@ void rrc::read_pdu_bcch_dlsch(uint32_t sib_index, uint8_t* payload)
|
|
|
|
|
|
|
|
|
|
void rrc::rl_failure(uint16_t rnti)
|
|
|
|
|
{
|
|
|
|
|
rrc_pdu p = {rnti, LCID_RLF_USER, NULL};
|
|
|
|
|
rrc_pdu p = {rnti, LCID_RLF_USER, nullptr};
|
|
|
|
|
rx_pdu_queue.push(std::move(p));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void rrc::set_activity_user(uint16_t rnti)
|
|
|
|
|
{
|
|
|
|
|
rrc_pdu p = {rnti, LCID_ACT_USER, NULL};
|
|
|
|
|
rrc_pdu p = {rnti, LCID_ACT_USER, nullptr};
|
|
|
|
|
rx_pdu_queue.push(std::move(p));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void rrc::rem_user_thread(uint16_t rnti)
|
|
|
|
|
{
|
|
|
|
|
rrc_pdu p = {rnti, LCID_REM_USER, NULL};
|
|
|
|
|
rrc_pdu p = {rnti, LCID_REM_USER, nullptr};
|
|
|
|
|
rx_pdu_queue.push(std::move(p));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
uint32_t rrc::get_nof_users() {
|
|
|
|
|
uint32_t rrc::get_nof_users()
|
|
|
|
|
{
|
|
|
|
|
return users.size();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
template <class T>
|
|
|
|
|
void rrc::log_rrc_message(const std::string& source, const direction_t dir, const srslte::byte_buffer_t* pdu,
|
|
|
|
|
void rrc::log_rrc_message(const std::string& source,
|
|
|
|
|
const direction_t dir,
|
|
|
|
|
const srslte::byte_buffer_t* pdu,
|
|
|
|
|
const T& msg)
|
|
|
|
|
{
|
|
|
|
|
if (rrc_log->get_level() == srslte::LOG_LEVEL_INFO) {
|
|
|
|
|
rrc_log->info("%s - %s %s (%d B)\n", source.c_str(), dir == Tx ? "Tx" : "Rx",
|
|
|
|
|
msg.msg.c1().type().to_string().c_str(), pdu->N_bytes);
|
|
|
|
|
rrc_log->info("%s - %s %s (%d B)\n",
|
|
|
|
|
source.c_str(),
|
|
|
|
|
dir == Tx ? "Tx" : "Rx",
|
|
|
|
|
msg.msg.c1().type().to_string().c_str(),
|
|
|
|
|
pdu->N_bytes);
|
|
|
|
|
} else if (rrc_log->get_level() >= srslte::LOG_LEVEL_DEBUG) {
|
|
|
|
|
asn1::json_writer json_writer;
|
|
|
|
|
msg.to_json(json_writer);
|
|
|
|
|
rrc_log->debug_hex(pdu->msg, pdu->N_bytes, "%s - %s %s (%d B)\n", source.c_str(), dir == Tx ? "Tx" : "Rx",
|
|
|
|
|
msg.msg.c1().type().to_string().c_str(), pdu->N_bytes);
|
|
|
|
|
rrc_log->debug_hex(pdu->msg,
|
|
|
|
|
pdu->N_bytes,
|
|
|
|
|
"%s - %s %s (%d B)\n",
|
|
|
|
|
source.c_str(),
|
|
|
|
|
dir == Tx ? "Tx" : "Rx",
|
|
|
|
|
msg.msg.c1().type().to_string().c_str(),
|
|
|
|
|
pdu->N_bytes);
|
|
|
|
|
rrc_log->debug("Content:\n%s\n", json_writer.to_string().c_str());
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void rrc::max_retx_attempted(uint16_t rnti)
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
void rrc::max_retx_attempted(uint16_t rnti) {}
|
|
|
|
|
|
|
|
|
|
// This function is called from PRACH worker (can wait)
|
|
|
|
|
void rrc::add_user(uint16_t rnti)
|
|
|
|
@ -218,18 +225,16 @@ void rrc::add_user(uint16_t rnti)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (rnti == SRSLTE_MRNTI) {
|
|
|
|
|
srslte::pdcp_config_t pdcp_cfg = {.bearer_id = 1,
|
|
|
|
|
.rb_type = srslte::PDCP_RB_IS_DRB,
|
|
|
|
|
.tx_direction = srslte::SECURITY_DIRECTION_DOWNLINK,
|
|
|
|
|
.rx_direction = srslte::SECURITY_DIRECTION_UPLINK,
|
|
|
|
|
.sn_len = srslte::PDCP_SN_LEN_12,
|
|
|
|
|
.t_reorderding = srslte::pdcp_t_reordering_t::ms500};
|
|
|
|
|
|
|
|
|
|
srslte::pdcp_config_t pdcp_cfg{1,
|
|
|
|
|
srslte::PDCP_RB_IS_DRB,
|
|
|
|
|
srslte::SECURITY_DIRECTION_DOWNLINK,
|
|
|
|
|
srslte::SECURITY_DIRECTION_UPLINK,
|
|
|
|
|
srslte::PDCP_SN_LEN_12,
|
|
|
|
|
srslte::pdcp_t_reordering_t::ms500};
|
|
|
|
|
uint32_t teid_in = 1;
|
|
|
|
|
|
|
|
|
|
for (uint32_t i = 0; i < mcch.msg.c1().mbsfn_area_cfg_r9().pmch_info_list_r9[0].mbms_session_info_list_r9.size();
|
|
|
|
|
i++) {
|
|
|
|
|
uint32_t lcid = mcch.msg.c1().mbsfn_area_cfg_r9().pmch_info_list_r9[0].mbms_session_info_list_r9[i].lc_ch_id_r9;
|
|
|
|
|
for (auto& mbms_item : mcch.msg.c1().mbsfn_area_cfg_r9().pmch_info_list_r9[0].mbms_session_info_list_r9) {
|
|
|
|
|
uint32_t lcid = mbms_item.lc_ch_id_r9;
|
|
|
|
|
rlc->add_bearer_mrb(SRSLTE_MRNTI, lcid);
|
|
|
|
|
pdcp->add_bearer(SRSLTE_MRNTI, lcid, pdcp_cfg);
|
|
|
|
|
gtpu->add_bearer(SRSLTE_MRNTI, lcid, 1, 1, &teid_in);
|
|
|
|
@ -261,8 +266,6 @@ void rrc::upd_user(uint16_t new_rnti, uint16_t old_rnti)
|
|
|
|
|
pthread_mutex_unlock(&user_mutex);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*******************************************************************************
|
|
|
|
|
PDCP interface
|
|
|
|
|
*******************************************************************************/
|
|
|
|
@ -292,7 +295,8 @@ void rrc::write_dl_info(uint16_t rnti, srslte::unique_byte_buffer_t sdu)
|
|
|
|
|
dl_info_r8->ded_info_type.set_ded_info_nas();
|
|
|
|
|
dl_info_r8->ded_info_type.ded_info_nas().resize(sdu->N_bytes);
|
|
|
|
|
memcpy(msg_c1->dl_info_transfer().crit_exts.c1().dl_info_transfer_r8().ded_info_type.ded_info_nas().data(),
|
|
|
|
|
sdu->msg, sdu->N_bytes);
|
|
|
|
|
sdu->msg,
|
|
|
|
|
sdu->N_bytes);
|
|
|
|
|
|
|
|
|
|
sdu->clear();
|
|
|
|
|
|
|
|
|
@ -304,8 +308,9 @@ void rrc::write_dl_info(uint16_t rnti, srslte::unique_byte_buffer_t sdu)
|
|
|
|
|
pthread_mutex_unlock(&user_mutex);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void rrc::release_complete(uint16_t rnti) {
|
|
|
|
|
rrc_pdu p = {rnti, LCID_REL_USER, NULL};
|
|
|
|
|
void rrc::release_complete(uint16_t rnti)
|
|
|
|
|
{
|
|
|
|
|
rrc_pdu p = {rnti, LCID_REL_USER, nullptr};
|
|
|
|
|
rx_pdu_queue.push(std::move(p));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -459,7 +464,6 @@ bool rrc::modify_ue_ctxt(uint16_t rnti, LIBLTE_S1AP_MESSAGE_UECONTEXTMODIFICATIO
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
bool rrc::setup_ue_erabs(uint16_t rnti, LIBLTE_S1AP_MESSAGE_E_RABSETUPREQUEST_STRUCT* msg)
|
|
|
|
|
{
|
|
|
|
|
pthread_mutex_lock(&user_mutex);
|
|
|
|
@ -546,8 +550,7 @@ bool rrc::is_paging_opportunity(uint32_t tti, uint32_t *payload_len)
|
|
|
|
|
std::vector<uint32_t> ue_to_remove;
|
|
|
|
|
|
|
|
|
|
int n = 0;
|
|
|
|
|
for (std::map<uint32_t, LIBLTE_S1AP_UEPAGINGID_STRUCT>::iterator iter = pending_paging.begin();
|
|
|
|
|
n < ASN1_RRC_MAX_PAGE_REC && iter != pending_paging.end(); ++iter) {
|
|
|
|
|
for (auto iter = pending_paging.begin(); n < ASN1_RRC_MAX_PAGE_REC && iter != pending_paging.end(); ++iter) {
|
|
|
|
|
LIBLTE_S1AP_UEPAGINGID_STRUCT u = (LIBLTE_S1AP_UEPAGINGID_STRUCT)iter->second;
|
|
|
|
|
uint32_t ueid = ((uint32_t)iter->first) % 1024;
|
|
|
|
|
uint32_t i_s = (ueid / N) % Ns;
|
|
|
|
@ -571,7 +574,7 @@ bool rrc::is_paging_opportunity(uint32_t tti, uint32_t *payload_len)
|
|
|
|
|
paging_elem.ue_id.s_tmsi().mmec.from_number(u.choice.s_TMSI.mMEC.buffer[0]);
|
|
|
|
|
uint32_t m_tmsi = 0;
|
|
|
|
|
for (int i = 0; i < LIBLTE_S1AP_M_TMSI_OCTET_STRING_LEN; i++) {
|
|
|
|
|
m_tmsi |= u.choice.s_TMSI.m_TMSI.buffer[i] << (8 * (LIBLTE_S1AP_M_TMSI_OCTET_STRING_LEN - i - 1));
|
|
|
|
|
m_tmsi |= u.choice.s_TMSI.m_TMSI.buffer[i] << (8u * (LIBLTE_S1AP_M_TMSI_OCTET_STRING_LEN - i - 1));
|
|
|
|
|
}
|
|
|
|
|
paging_elem.ue_id.s_tmsi().m_tmsi.from_number(m_tmsi);
|
|
|
|
|
}
|
|
|
|
@ -601,7 +604,9 @@ bool rrc::is_paging_opportunity(uint32_t tti, uint32_t *payload_len)
|
|
|
|
|
*payload_len = byte_buf_paging.N_bytes;
|
|
|
|
|
}
|
|
|
|
|
rrc_log->info("Assembling PCCH payload with %d UE identities, payload_len=%d bytes, nbits=%d\n",
|
|
|
|
|
paging_rec->paging_record_list.size(), byte_buf_paging.N_bytes, N_bits);
|
|
|
|
|
paging_rec->paging_record_list.size(),
|
|
|
|
|
byte_buf_paging.N_bytes,
|
|
|
|
|
N_bits);
|
|
|
|
|
log_rrc_message("PCCH-Message", Tx, &byte_buf_paging, pcch_msg);
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
@ -790,7 +795,8 @@ void rrc::config_mac()
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
sched_cfg.prach_config = cfg.sibs[1].sib2().rr_cfg_common.prach_cfg.prach_cfg_info.prach_cfg_idx;
|
|
|
|
|
sched_cfg.prach_nof_preambles = cfg.sibs[1].sib2().rr_cfg_common.rach_cfg_common.preamb_info.nof_ra_preambs.to_number();
|
|
|
|
|
sched_cfg.prach_nof_preambles =
|
|
|
|
|
cfg.sibs[1].sib2().rr_cfg_common.rach_cfg_common.preamb_info.nof_ra_preambs.to_number();
|
|
|
|
|
sched_cfg.si_window_ms = cfg.sib1.si_win_len.to_number();
|
|
|
|
|
sched_cfg.prach_rar_window =
|
|
|
|
|
cfg.sibs[1].sib2().rr_cfg_common.rach_cfg_common.ra_supervision_info.ra_resp_win_size.to_number();
|
|
|
|
@ -836,8 +842,8 @@ uint32_t rrc::generate_sibs()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Add other SIBs to this message, if any
|
|
|
|
|
for (uint32_t mapping = 0; mapping < sched_info[sched_info_elem].sib_map_info.size(); mapping++) {
|
|
|
|
|
sib_list.push_back(cfg.sibs[(int)sched_info[sched_info_elem].sib_map_info[mapping] + 2]);
|
|
|
|
|
for (auto& mapping_enum : sched_info[sched_info_elem].sib_map_info) {
|
|
|
|
|
sib_list.push_back(cfg.sibs[(int)mapping_enum + 2]);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -861,7 +867,7 @@ uint32_t rrc::generate_sibs()
|
|
|
|
|
return nof_messages;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void rrc::configure_mbsfn_sibs(sib_type2_s* sib2, sib_type13_r9_s* sib13)
|
|
|
|
|
void rrc::configure_mbsfn_sibs(sib_type2_s* sib2_, sib_type13_r9_s* sib13_)
|
|
|
|
|
{
|
|
|
|
|
// Temp assignment of MCCH, this will eventually come from a cfg file
|
|
|
|
|
mcch.msg.set_c1();
|
|
|
|
@ -894,15 +900,16 @@ void rrc::configure_mbsfn_sibs(sib_type2_s* sib2, sib_type13_r9_s* sib13)
|
|
|
|
|
pmch_item->mbms_session_info_list_r9[1].tmgi_r9.plmn_id_r9.set_explicit_value_r9() =
|
|
|
|
|
pmch_item->mbms_session_info_list_r9[0].tmgi_r9.plmn_id_r9.explicit_value_r9();
|
|
|
|
|
byte[2] = 1;
|
|
|
|
|
memcpy(&pmch_item->mbms_session_info_list_r9[1].tmgi_r9.service_id_r9[0], &byte[0],
|
|
|
|
|
memcpy(&pmch_item->mbms_session_info_list_r9[1].tmgi_r9.service_id_r9[0],
|
|
|
|
|
&byte[0],
|
|
|
|
|
3); // FIXME: Check if service is set to 1
|
|
|
|
|
}
|
|
|
|
|
pmch_item->pmch_cfg_r9.data_mcs_r9 = 20;
|
|
|
|
|
pmch_item->pmch_cfg_r9.mch_sched_period_r9 = pmch_cfg_r9_s::mch_sched_period_r9_e_::rf64;
|
|
|
|
|
pmch_item->pmch_cfg_r9.sf_alloc_end_r9 = 64 * 6;
|
|
|
|
|
|
|
|
|
|
phy->configure_mbsfn(sib2, sib13, mcch);
|
|
|
|
|
mac->write_mcch(sib2, sib13, &mcch);
|
|
|
|
|
phy->configure_mbsfn(sib2_, sib13_, mcch);
|
|
|
|
|
mac->write_mcch(sib2_, sib13_, &mcch);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void rrc::configure_security(uint16_t rnti,
|
|
|
|
@ -979,8 +986,6 @@ void rrc::run_thread()
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*******************************************************************************
|
|
|
|
|
Activity monitor class
|
|
|
|
|
*******************************************************************************/
|
|
|
|
@ -1002,12 +1007,11 @@ void rrc::activity_monitor::stop()
|
|
|
|
|
|
|
|
|
|
void rrc::activity_monitor::run_thread()
|
|
|
|
|
{
|
|
|
|
|
while(running)
|
|
|
|
|
{
|
|
|
|
|
while (running) {
|
|
|
|
|
usleep(10000);
|
|
|
|
|
pthread_mutex_lock(&parent->user_mutex);
|
|
|
|
|
uint16_t rem_rnti = 0;
|
|
|
|
|
for(std::map<uint16_t, ue>::iterator iter=parent->users.begin(); rem_rnti == 0 && iter!=parent->users.end(); ++iter) {
|
|
|
|
|
for (auto iter = parent->users.begin(); rem_rnti == 0 && iter != parent->users.end(); ++iter) {
|
|
|
|
|
if (iter->first != SRSLTE_MRNTI) {
|
|
|
|
|
ue* u = (ue*)&iter->second;
|
|
|
|
|
uint16_t rnti = (uint16_t)iter->first;
|
|
|
|
@ -1018,7 +1022,8 @@ void rrc::activity_monitor::run_thread()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (u->is_timeout()) {
|
|
|
|
|
parent->rrc_log->info("User rnti=0x%x timed out. Exists in s1ap=%s\n", rnti, parent->s1ap->user_exists(rnti)?"yes":"no");
|
|
|
|
|
parent->rrc_log->info(
|
|
|
|
|
"User rnti=0x%x timed out. Exists in s1ap=%s\n", rnti, parent->s1ap->user_exists(rnti) ? "yes" : "no");
|
|
|
|
|
rem_rnti = rnti;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
@ -1048,26 +1053,9 @@ rrc::ue::ue(rrc* outer_rrc, uint16_t rnti_) :
|
|
|
|
|
pool(srslte::byte_buffer_pool::get_instance())
|
|
|
|
|
{
|
|
|
|
|
set_activity();
|
|
|
|
|
has_tmsi = false;
|
|
|
|
|
connect_notified = false;
|
|
|
|
|
transaction_id = 0;
|
|
|
|
|
sr_allocated = false;
|
|
|
|
|
sr_sched_sf_idx = 0;
|
|
|
|
|
sr_sched_prb_idx = 0;
|
|
|
|
|
sr_N_pucch = 0;
|
|
|
|
|
sr_I = 0;
|
|
|
|
|
cqi_allocated = false;
|
|
|
|
|
cqi_pucch = 0;
|
|
|
|
|
cqi_idx = 0;
|
|
|
|
|
cqi_sched_sf_idx = 0;
|
|
|
|
|
cqi_sched_prb_idx = 0;
|
|
|
|
|
rlf_cnt = 0;
|
|
|
|
|
integ_algo = srslte::INTEGRITY_ALGORITHM_ID_EIA0;
|
|
|
|
|
cipher_algo = srslte::CIPHERING_ALGORITHM_ID_EEA0;
|
|
|
|
|
nas_pending = false;
|
|
|
|
|
is_csfb = false;
|
|
|
|
|
state = RRC_STATE_IDLE;
|
|
|
|
|
gettimeofday(&t_ue_init, NULL);
|
|
|
|
|
gettimeofday(&t_ue_init, nullptr);
|
|
|
|
|
mobility_handler.reset(new rrc_mobility(this));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -1076,14 +1064,15 @@ rrc_state_t rrc::ue::get_state()
|
|
|
|
|
return state;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
uint32_t rrc::ue::rl_failure() {
|
|
|
|
|
uint32_t rrc::ue::rl_failure()
|
|
|
|
|
{
|
|
|
|
|
rlf_cnt++;
|
|
|
|
|
return rlf_cnt;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void rrc::ue::set_activity()
|
|
|
|
|
{
|
|
|
|
|
gettimeofday(&t_last_activity, NULL);
|
|
|
|
|
gettimeofday(&t_last_activity, nullptr);
|
|
|
|
|
if (parent) {
|
|
|
|
|
if (parent->rrc_log) {
|
|
|
|
|
parent->rrc_log->debug("Activity registered rnti=0x%x\n", rnti);
|
|
|
|
@ -1091,11 +1080,13 @@ void rrc::ue::set_activity()
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool rrc::ue::is_connected() {
|
|
|
|
|
bool rrc::ue::is_connected()
|
|
|
|
|
{
|
|
|
|
|
return state == RRC_STATE_REGISTERED;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool rrc::ue::is_idle() {
|
|
|
|
|
bool rrc::ue::is_idle()
|
|
|
|
|
{
|
|
|
|
|
return state == RRC_STATE_IDLE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -1108,9 +1099,9 @@ bool rrc::ue::is_timeout()
|
|
|
|
|
struct timeval t[3];
|
|
|
|
|
uint32_t deadline_s = 0;
|
|
|
|
|
uint32_t deadline_us = 0;
|
|
|
|
|
const char *deadline_str = NULL;
|
|
|
|
|
const char* deadline_str = nullptr;
|
|
|
|
|
memcpy(&t[1], &t_last_activity, sizeof(struct timeval));
|
|
|
|
|
gettimeofday(&t[2], NULL);
|
|
|
|
|
gettimeofday(&t[2], nullptr);
|
|
|
|
|
get_time_interval(t);
|
|
|
|
|
|
|
|
|
|
switch (state) {
|
|
|
|
@ -1142,9 +1133,12 @@ bool rrc::ue::is_timeout()
|
|
|
|
|
int64_t elapsed = t[0].tv_sec * 1e6 + t[0].tv_usec;
|
|
|
|
|
if (elapsed > deadline && elapsed > 0) {
|
|
|
|
|
parent->rrc_log->warning("User rnti=0x%x expired %s deadline: %ld:%ld>%d:%d us\n",
|
|
|
|
|
rnti, deadline_str,
|
|
|
|
|
t[0].tv_sec, t[0].tv_usec,
|
|
|
|
|
deadline_s, deadline_us);
|
|
|
|
|
rnti,
|
|
|
|
|
deadline_str,
|
|
|
|
|
t[0].tv_sec,
|
|
|
|
|
t[0].tv_usec,
|
|
|
|
|
deadline_s,
|
|
|
|
|
deadline_us);
|
|
|
|
|
memcpy(&t_last_activity, &t[2], sizeof(struct timeval));
|
|
|
|
|
state = RRC_STATE_RELEASE_REQUEST;
|
|
|
|
|
return true;
|
|
|
|
@ -1248,7 +1242,6 @@ void rrc::ue::handle_rrc_con_reest_req(rrc_conn_reest_request_r8_ies_s* msg)
|
|
|
|
|
{
|
|
|
|
|
// TODO: Check Short-MAC-I value
|
|
|
|
|
parent->rrc_log->error("Not Supported: ConnectionReestablishment. \n");
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void rrc::ue::handle_rrc_con_setup_complete(rrc_conn_setup_complete_s* msg, srslte::unique_byte_buffer_t pdu)
|
|
|
|
@ -1344,16 +1337,9 @@ void rrc::ue::set_security_key(uint8_t* key, uint32_t length)
|
|
|
|
|
srslte::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);
|
|
|
|
|
security_generate_k_up(k_enb, cipher_algo, integ_algo, k_up_enc, k_up_int);
|
|
|
|
|
|
|
|
|
|
parent->configure_security(rnti, RB_ID_SRB1,
|
|
|
|
|
k_rrc_enc, k_rrc_int,
|
|
|
|
|
k_up_enc, k_up_int,
|
|
|
|
|
cipher_algo, integ_algo);
|
|
|
|
|
parent->configure_security(rnti, RB_ID_SRB1, k_rrc_enc, k_rrc_int, k_up_enc, k_up_int, cipher_algo, integ_algo);
|
|
|
|
|
|
|
|
|
|
parent->enable_integrity(rnti, RB_ID_SRB1);
|
|
|
|
|
|
|
|
|
@ -1379,9 +1365,9 @@ bool rrc::ue::setup_erabs(LIBLTE_S1AP_E_RABTOBESETUPLISTCTXTSUREQ_STRUCT *e)
|
|
|
|
|
|
|
|
|
|
uint32_t teid_out;
|
|
|
|
|
uint8_to_uint32(erab->gTP_TEID.buffer, &teid_out);
|
|
|
|
|
LIBLTE_S1AP_NAS_PDU_STRUCT *nas_pdu = erab->nAS_PDU_present ? &erab->nAS_PDU : NULL;
|
|
|
|
|
setup_erab(erab->e_RAB_ID.E_RAB_ID, &erab->e_RABlevelQoSParameters,
|
|
|
|
|
&erab->transportLayerAddress, teid_out, nas_pdu);
|
|
|
|
|
LIBLTE_S1AP_NAS_PDU_STRUCT* nas_pdu = erab->nAS_PDU_present ? &erab->nAS_PDU : nullptr;
|
|
|
|
|
setup_erab(
|
|
|
|
|
erab->e_RAB_ID.E_RAB_ID, &erab->e_RABlevelQoSParameters, &erab->transportLayerAddress, teid_out, nas_pdu);
|
|
|
|
|
}
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
@ -1403,8 +1389,11 @@ bool rrc::ue::setup_erabs(LIBLTE_S1AP_E_RABTOBESETUPLISTBEARERSUREQ_STRUCT *e)
|
|
|
|
|
|
|
|
|
|
uint32_t teid_out;
|
|
|
|
|
uint8_to_uint32(erab->gTP_TEID.buffer, &teid_out);
|
|
|
|
|
setup_erab(erab->e_RAB_ID.E_RAB_ID, &erab->e_RABlevelQoSParameters,
|
|
|
|
|
&erab->transportLayerAddress, teid_out, &erab->nAS_PDU);
|
|
|
|
|
setup_erab(erab->e_RAB_ID.E_RAB_ID,
|
|
|
|
|
&erab->e_RABlevelQoSParameters,
|
|
|
|
|
&erab->transportLayerAddress,
|
|
|
|
|
teid_out,
|
|
|
|
|
&erab->nAS_PDU);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Work in progress
|
|
|
|
@ -1413,8 +1402,10 @@ bool rrc::ue::setup_erabs(LIBLTE_S1AP_E_RABTOBESETUPLISTBEARERSUREQ_STRUCT *e)
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void rrc::ue::setup_erab(uint8_t id, LIBLTE_S1AP_E_RABLEVELQOSPARAMETERS_STRUCT *qos,
|
|
|
|
|
LIBLTE_S1AP_TRANSPORTLAYERADDRESS_STRUCT *addr, uint32_t teid_out,
|
|
|
|
|
void rrc::ue::setup_erab(uint8_t id,
|
|
|
|
|
LIBLTE_S1AP_E_RABLEVELQOSPARAMETERS_STRUCT* qos,
|
|
|
|
|
LIBLTE_S1AP_TRANSPORTLAYERADDRESS_STRUCT* addr,
|
|
|
|
|
uint32_t teid_out,
|
|
|
|
|
LIBLTE_S1AP_NAS_PDU_STRUCT* nas_pdu)
|
|
|
|
|
{
|
|
|
|
|
erabs[id].id = id;
|
|
|
|
@ -1439,10 +1430,7 @@ void rrc::ue::setup_erab(uint8_t id, LIBLTE_S1AP_E_RABLEVELQOSPARAMETERS_STRUCT
|
|
|
|
|
|
|
|
|
|
bool rrc::ue::release_erabs()
|
|
|
|
|
{
|
|
|
|
|
typedef std::map<uint8_t, erab_t>::iterator it_t;
|
|
|
|
|
for(it_t it=erabs.begin(); it!=erabs.end(); ++it) {
|
|
|
|
|
// TODO: notify GTPU layer
|
|
|
|
|
}
|
|
|
|
|
// TODO: notify GTPU layer for each ERAB
|
|
|
|
|
erabs.clear();
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
@ -1457,14 +1445,13 @@ void rrc::ue::notify_s1ap_ue_ctxt_setup_complete()
|
|
|
|
|
res.E_RABSetupListCtxtSURes.len = 0;
|
|
|
|
|
res.E_RABFailedToSetupListCtxtSURes.len = 0;
|
|
|
|
|
|
|
|
|
|
typedef std::map<uint8_t, erab_t>::iterator it_t;
|
|
|
|
|
for(it_t it=erabs.begin(); it!=erabs.end(); ++it) {
|
|
|
|
|
for (auto& erab : erabs) {
|
|
|
|
|
uint32_t j = res.E_RABSetupListCtxtSURes.len++;
|
|
|
|
|
res.E_RABSetupListCtxtSURes.buffer[j].ext = false;
|
|
|
|
|
res.E_RABSetupListCtxtSURes.buffer[j].iE_Extensions_present = false;
|
|
|
|
|
res.E_RABSetupListCtxtSURes.buffer[j].e_RAB_ID.ext = false;
|
|
|
|
|
res.E_RABSetupListCtxtSURes.buffer[j].e_RAB_ID.E_RAB_ID = it->second.id;
|
|
|
|
|
uint32_to_uint8(it->second.teid_in, res.E_RABSetupListCtxtSURes.buffer[j].gTP_TEID.buffer);
|
|
|
|
|
res.E_RABSetupListCtxtSURes.buffer[j].e_RAB_ID.E_RAB_ID = erab.second.id;
|
|
|
|
|
uint32_to_uint8(erab.second.teid_in, res.E_RABSetupListCtxtSURes.buffer[j].gTP_TEID.buffer);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
parent->s1ap->ue_ctxt_setup_complete(rnti, &res);
|
|
|
|
@ -1518,7 +1505,7 @@ void rrc::ue::send_connection_setup(bool is_setup)
|
|
|
|
|
dl_ccch_msg_s dl_ccch_msg;
|
|
|
|
|
dl_ccch_msg.msg.set_c1();
|
|
|
|
|
|
|
|
|
|
rr_cfg_ded_s* rr_cfg = NULL;
|
|
|
|
|
rr_cfg_ded_s* rr_cfg = nullptr;
|
|
|
|
|
if (is_setup) {
|
|
|
|
|
dl_ccch_msg.msg.c1().set_rrc_conn_setup();
|
|
|
|
|
dl_ccch_msg.msg.c1().rrc_conn_setup().rrc_transaction_id = (uint8_t)((transaction_id++) % 4);
|
|
|
|
@ -1569,7 +1556,8 @@ void rrc::ue::send_connection_setup(bool is_setup)
|
|
|
|
|
phy_cfg->ant_info.explicit_value().ue_tx_ant_sel.set(setup_e::release);
|
|
|
|
|
|
|
|
|
|
if (is_setup) {
|
|
|
|
|
if (sr_allocate(parent->cfg.sr_cfg.period, &phy_cfg->sched_request_cfg.setup().sr_cfg_idx,
|
|
|
|
|
if (sr_allocate(parent->cfg.sr_cfg.period,
|
|
|
|
|
&phy_cfg->sched_request_cfg.setup().sr_cfg_idx,
|
|
|
|
|
&phy_cfg->sched_request_cfg.setup().sr_pucch_res_idx)) {
|
|
|
|
|
parent->rrc_log->error("Allocating SR resources for rnti=%d\n", rnti);
|
|
|
|
|
return;
|
|
|
|
@ -1604,7 +1592,8 @@ void rrc::ue::send_connection_setup(bool is_setup)
|
|
|
|
|
cqi_report_periodic_c::setup_s_::cqi_format_ind_periodic_c_::types::wideband_cqi);
|
|
|
|
|
phy_cfg->cqi_report_cfg.cqi_report_periodic.setup().simul_ack_nack_and_cqi = false;
|
|
|
|
|
if (is_setup) {
|
|
|
|
|
if (cqi_allocate(parent->cfg.cqi_cfg.period, &phy_cfg->cqi_report_cfg.cqi_report_periodic.setup().cqi_pmi_cfg_idx,
|
|
|
|
|
if (cqi_allocate(parent->cfg.cqi_cfg.period,
|
|
|
|
|
&phy_cfg->cqi_report_cfg.cqi_report_periodic.setup().cqi_pmi_cfg_idx,
|
|
|
|
|
&phy_cfg->cqi_report_cfg.cqi_report_periodic.setup().cqi_pucch_res_idx)) {
|
|
|
|
|
parent->rrc_log->error("Allocating CQI resources for rnti=%d\n", rnti);
|
|
|
|
|
return;
|
|
|
|
@ -1621,7 +1610,8 @@ void rrc::ue::send_connection_setup(bool is_setup)
|
|
|
|
|
bzero(&sched_cfg, sizeof(srsenb::sched_interface::ue_cfg_t));
|
|
|
|
|
sched_cfg.maxharq_tx = parent->cfg.mac_cnfg.ul_sch_cfg.max_harq_tx.to_number();
|
|
|
|
|
sched_cfg.continuous_pusch = false;
|
|
|
|
|
sched_cfg.aperiodic_cqi_period = parent->cfg.cqi_cfg.mode == RRC_CFG_CQI_MODE_APERIODIC?parent->cfg.cqi_cfg.period:0;
|
|
|
|
|
sched_cfg.aperiodic_cqi_period =
|
|
|
|
|
parent->cfg.cqi_cfg.mode == RRC_CFG_CQI_MODE_APERIODIC ? parent->cfg.cqi_cfg.period : 0;
|
|
|
|
|
sched_cfg.ue_bearers[0].direction = srsenb::sched_interface::ue_bearer_cfg_t::BOTH;
|
|
|
|
|
sched_cfg.ue_bearers[1].direction = srsenb::sched_interface::ue_bearer_cfg_t::BOTH;
|
|
|
|
|
if (parent->cfg.cqi_cfg.mode == RRC_CFG_CQI_MODE_APERIODIC) {
|
|
|
|
@ -1647,12 +1637,12 @@ void rrc::ue::send_connection_setup(bool is_setup)
|
|
|
|
|
parent->rlc->add_bearer(rnti, 1, srslte::rlc_config_t::srb_config(1));
|
|
|
|
|
|
|
|
|
|
// Configure SRB1 in PDCP
|
|
|
|
|
srslte::pdcp_config_t pdcp_cnfg{.bearer_id = 1,
|
|
|
|
|
.rb_type = srslte::PDCP_RB_IS_SRB,
|
|
|
|
|
.tx_direction = srslte::SECURITY_DIRECTION_DOWNLINK,
|
|
|
|
|
.rx_direction = srslte::SECURITY_DIRECTION_UPLINK,
|
|
|
|
|
.sn_len = srslte::PDCP_SN_LEN_5,
|
|
|
|
|
.t_reorderding = srslte::pdcp_t_reordering_t::ms500};
|
|
|
|
|
srslte::pdcp_config_t pdcp_cnfg{1,
|
|
|
|
|
srslte::PDCP_RB_IS_SRB,
|
|
|
|
|
srslte::SECURITY_DIRECTION_DOWNLINK,
|
|
|
|
|
srslte::SECURITY_DIRECTION_UPLINK,
|
|
|
|
|
srslte::PDCP_SN_LEN_5,
|
|
|
|
|
srslte::pdcp_t_reordering_t::ms500};
|
|
|
|
|
|
|
|
|
|
parent->pdcp->add_bearer(rnti, 1, pdcp_cnfg);
|
|
|
|
|
|
|
|
|
@ -1777,7 +1767,6 @@ void rrc::ue::send_connection_reconf_upd(srslte::unique_byte_buffer_t pdu)
|
|
|
|
|
send_dl_dcch(&dl_dcch_msg, std::move(pdu));
|
|
|
|
|
|
|
|
|
|
state = RRC_STATE_WAIT_FOR_CON_RECONF_COMPLETE;
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void rrc::ue::send_connection_reconf(srslte::unique_byte_buffer_t pdu)
|
|
|
|
@ -1868,12 +1857,12 @@ void rrc::ue::send_connection_reconf(srslte::unique_byte_buffer_t pdu)
|
|
|
|
|
parent->rlc->add_bearer(rnti, 2, srslte::rlc_config_t::srb_config(2));
|
|
|
|
|
|
|
|
|
|
// Configure SRB2 in PDCP
|
|
|
|
|
srslte::pdcp_config_t pdcp_cnfg_srb = {.bearer_id = 2,
|
|
|
|
|
.rb_type = srslte::PDCP_RB_IS_SRB,
|
|
|
|
|
.tx_direction = srslte::SECURITY_DIRECTION_DOWNLINK,
|
|
|
|
|
.rx_direction = srslte::SECURITY_DIRECTION_UPLINK,
|
|
|
|
|
.sn_len = srslte::PDCP_SN_LEN_5,
|
|
|
|
|
.t_reorderding = srslte::pdcp_t_reordering_t::ms500};
|
|
|
|
|
srslte::pdcp_config_t pdcp_cnfg_srb = {2,
|
|
|
|
|
srslte::PDCP_RB_IS_SRB,
|
|
|
|
|
srslte::SECURITY_DIRECTION_DOWNLINK,
|
|
|
|
|
srslte::SECURITY_DIRECTION_UPLINK,
|
|
|
|
|
srslte::PDCP_SN_LEN_5,
|
|
|
|
|
srslte::pdcp_t_reordering_t::ms500};
|
|
|
|
|
|
|
|
|
|
parent->pdcp->add_bearer(rnti, 2, pdcp_cnfg_srb);
|
|
|
|
|
parent->pdcp->config_security(rnti, 2, k_rrc_enc, k_rrc_int, k_up_enc, cipher_algo, integ_algo);
|
|
|
|
@ -1884,12 +1873,12 @@ void rrc::ue::send_connection_reconf(srslte::unique_byte_buffer_t pdu)
|
|
|
|
|
parent->rlc->add_bearer(rnti, 3, srslte::make_rlc_config_t(conn_reconf->rr_cfg_ded.drb_to_add_mod_list[0].rlc_cfg));
|
|
|
|
|
|
|
|
|
|
// Configure DRB1 in PDCP
|
|
|
|
|
srslte::pdcp_config_t pdcp_cnfg_drb = {.bearer_id = 1,
|
|
|
|
|
.rb_type = srslte::PDCP_RB_IS_DRB,
|
|
|
|
|
.tx_direction = srslte::SECURITY_DIRECTION_DOWNLINK,
|
|
|
|
|
.rx_direction = srslte::SECURITY_DIRECTION_UPLINK,
|
|
|
|
|
.sn_len = srslte::PDCP_SN_LEN_12,
|
|
|
|
|
.t_reorderding = srslte::pdcp_t_reordering_t::ms500};
|
|
|
|
|
srslte::pdcp_config_t pdcp_cnfg_drb = {1,
|
|
|
|
|
srslte::PDCP_RB_IS_DRB,
|
|
|
|
|
srslte::SECURITY_DIRECTION_DOWNLINK,
|
|
|
|
|
srslte::SECURITY_DIRECTION_UPLINK,
|
|
|
|
|
srslte::PDCP_SN_LEN_12,
|
|
|
|
|
srslte::pdcp_t_reordering_t::ms500};
|
|
|
|
|
|
|
|
|
|
if (conn_reconf->rr_cfg_ded.drb_to_add_mod_list[0].pdcp_cfg.rlc_um_present) {
|
|
|
|
|
if (conn_reconf->rr_cfg_ded.drb_to_add_mod_list[0].pdcp_cfg.rlc_um.pdcp_sn_size.value ==
|
|
|
|
@ -1905,7 +1894,8 @@ void rrc::ue::send_connection_reconf(srslte::unique_byte_buffer_t pdu)
|
|
|
|
|
|
|
|
|
|
// Add NAS Attach accept
|
|
|
|
|
if (nas_pending) {
|
|
|
|
|
parent->rrc_log->info_hex(erab_info.buffer, erab_info.N_bytes, "connection_reconf erab_info -> nas_info rnti 0x%x\n", rnti);
|
|
|
|
|
parent->rrc_log->info_hex(
|
|
|
|
|
erab_info.buffer, erab_info.N_bytes, "connection_reconf erab_info -> nas_info rnti 0x%x\n", rnti);
|
|
|
|
|
conn_reconf->ded_info_nas_list_present = true;
|
|
|
|
|
conn_reconf->ded_info_nas_list.resize(1);
|
|
|
|
|
conn_reconf->ded_info_nas_list[0].resize(erab_info.N_bytes);
|
|
|
|
@ -1959,12 +1949,12 @@ void rrc::ue::send_connection_reconf_new_bearer(LIBLTE_S1AP_E_RABTOBESETUPLISTBE
|
|
|
|
|
|
|
|
|
|
// Configure DRB in PDCP
|
|
|
|
|
srslte::pdcp_config_t pdcp_config = {
|
|
|
|
|
.bearer_id = (uint8_t)(drb_item.drb_id - 1), // TODO: Review all ID mapping LCID DRB ERAB EPSBID Mapping
|
|
|
|
|
.rb_type = srslte::PDCP_RB_IS_DRB,
|
|
|
|
|
.tx_direction = srslte::SECURITY_DIRECTION_DOWNLINK,
|
|
|
|
|
.rx_direction = srslte::SECURITY_DIRECTION_UPLINK,
|
|
|
|
|
.sn_len = srslte::PDCP_SN_LEN_12,
|
|
|
|
|
.t_reorderding = srslte::pdcp_t_reordering_t::ms500};
|
|
|
|
|
(uint8_t)(drb_item.drb_id - 1), // TODO: Review all ID mapping LCID DRB ERAB EPSBID Mapping
|
|
|
|
|
srslte::PDCP_RB_IS_DRB,
|
|
|
|
|
srslte::SECURITY_DIRECTION_DOWNLINK,
|
|
|
|
|
srslte::SECURITY_DIRECTION_UPLINK,
|
|
|
|
|
srslte::PDCP_SN_LEN_12,
|
|
|
|
|
srslte::pdcp_t_reordering_t::ms500};
|
|
|
|
|
|
|
|
|
|
parent->pdcp->add_bearer(rnti, lcid, pdcp_config);
|
|
|
|
|
|
|
|
|
@ -1973,7 +1963,8 @@ void rrc::ue::send_connection_reconf_new_bearer(LIBLTE_S1AP_E_RABTOBESETUPLISTBE
|
|
|
|
|
conn_reconf->rr_cfg_ded.drb_to_add_mod_list.push_back(drb_item);
|
|
|
|
|
|
|
|
|
|
// Add NAS message
|
|
|
|
|
parent->rrc_log->info_hex(erab_info.buffer, erab_info.N_bytes, "reconf_new_bearer erab_info -> nas_info rnti 0x%x\n", rnti);
|
|
|
|
|
parent->rrc_log->info_hex(
|
|
|
|
|
erab_info.buffer, erab_info.N_bytes, "reconf_new_bearer erab_info -> nas_info rnti 0x%x\n", rnti);
|
|
|
|
|
asn1::dyn_octstring octstr(erab_info.N_bytes);
|
|
|
|
|
memcpy(octstr.data(), erab_info.msg, erab_info.N_bytes);
|
|
|
|
|
conn_reconf->ded_info_nas_list.push_back(octstr);
|
|
|
|
@ -2031,8 +2022,8 @@ bool rrc::ue::select_security_algorithms()
|
|
|
|
|
bool enc_algo_found = false;
|
|
|
|
|
bool integ_algo_found = false;
|
|
|
|
|
|
|
|
|
|
for (int i = 0; i < srslte::CIPHERING_ALGORITHM_ID_N_ITEMS; i++) {
|
|
|
|
|
switch (parent->cfg.eea_preference_list[i]) {
|
|
|
|
|
for (auto& cipher_item : parent->cfg.eea_preference_list) {
|
|
|
|
|
switch (cipher_item) {
|
|
|
|
|
case srslte::CIPHERING_ALGORITHM_ID_EEA0:
|
|
|
|
|
// “all bits equal to 0” – UE supports no other algorithm than EEA0,
|
|
|
|
|
// specification does not cover the case in which EEA0 is supported with other algorithms
|
|
|
|
@ -2043,8 +2034,7 @@ bool rrc::ue::select_security_algorithms()
|
|
|
|
|
break;
|
|
|
|
|
case srslte::CIPHERING_ALGORITHM_ID_128_EEA1:
|
|
|
|
|
// “first bit” – 128-EEA1,
|
|
|
|
|
if (security_capabilities.encryptionAlgorithms
|
|
|
|
|
.buffer[srslte::CIPHERING_ALGORITHM_ID_128_EEA1 - 1]) {
|
|
|
|
|
if (security_capabilities.encryptionAlgorithms.buffer[srslte::CIPHERING_ALGORITHM_ID_128_EEA1 - 1]) {
|
|
|
|
|
cipher_algo = srslte::CIPHERING_ALGORITHM_ID_128_EEA1;
|
|
|
|
|
enc_algo_found = true;
|
|
|
|
|
parent->rrc_log->info("Selected EEA1 as RRC encryption algorithm\n");
|
|
|
|
@ -2055,8 +2045,7 @@ bool rrc::ue::select_security_algorithms()
|
|
|
|
|
break;
|
|
|
|
|
case srslte::CIPHERING_ALGORITHM_ID_128_EEA2:
|
|
|
|
|
// “second bit” – 128-EEA2,
|
|
|
|
|
if (security_capabilities.encryptionAlgorithms
|
|
|
|
|
.buffer[srslte::CIPHERING_ALGORITHM_ID_128_EEA2 - 1]) {
|
|
|
|
|
if (security_capabilities.encryptionAlgorithms.buffer[srslte::CIPHERING_ALGORITHM_ID_128_EEA2 - 1]) {
|
|
|
|
|
cipher_algo = srslte::CIPHERING_ALGORITHM_ID_128_EEA2;
|
|
|
|
|
enc_algo_found = true;
|
|
|
|
|
parent->rrc_log->info("Selected EEA2 as RRC encryption algorithm\n");
|
|
|
|
@ -2085,8 +2074,8 @@ bool rrc::ue::select_security_algorithms()
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (int i = 0; i < srslte::INTEGRITY_ALGORITHM_ID_N_ITEMS; i++) {
|
|
|
|
|
switch (parent->cfg.eia_preference_list[i]) {
|
|
|
|
|
for (auto& eia_enum : parent->cfg.eia_preference_list) {
|
|
|
|
|
switch (eia_enum) {
|
|
|
|
|
case srslte::INTEGRITY_ALGORITHM_ID_EIA0:
|
|
|
|
|
// Null integrity is not supported
|
|
|
|
|
parent->rrc_log->info("Skipping EIA0 as RRC integrity algorithm. Null integrity is not supported.\n");
|
|
|
|
@ -2190,9 +2179,11 @@ int rrc::ue::sr_free()
|
|
|
|
|
if (parent->sr_sched.nof_users[sr_sched_prb_idx][sr_sched_sf_idx] > 0) {
|
|
|
|
|
parent->sr_sched.nof_users[sr_sched_prb_idx][sr_sched_sf_idx]--;
|
|
|
|
|
} else {
|
|
|
|
|
parent->rrc_log->warning("Removing SR resources: no users in time-frequency slot (%d, %d)\n", sr_sched_prb_idx, sr_sched_sf_idx);
|
|
|
|
|
parent->rrc_log->warning(
|
|
|
|
|
"Removing SR resources: no users in time-frequency slot (%d, %d)\n", sr_sched_prb_idx, sr_sched_sf_idx);
|
|
|
|
|
}
|
|
|
|
|
parent->rrc_log->info("Deallocated SR resources for time-frequency slot (%d, %d)\n", sr_sched_prb_idx, sr_sched_sf_idx);
|
|
|
|
|
parent->rrc_log->info(
|
|
|
|
|
"Deallocated SR resources for time-frequency slot (%d, %d)\n", sr_sched_prb_idx, sr_sched_sf_idx);
|
|
|
|
|
}
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
@ -2236,7 +2227,8 @@ int rrc::ue::sr_allocate(uint32_t period, uint8_t* I_sr, uint16_t* N_pucch_sr)
|
|
|
|
|
if (parent->cfg.sr_cfg.sf_mapping[j_min] < period) {
|
|
|
|
|
*I_sr = period - 5 + parent->cfg.sr_cfg.sf_mapping[j_min];
|
|
|
|
|
} else {
|
|
|
|
|
parent->rrc_log->error("Allocating SR: invalid sf_idx=%d for period=%d\n", parent->cfg.sr_cfg.sf_mapping[j_min], period);
|
|
|
|
|
parent->rrc_log->error(
|
|
|
|
|
"Allocating SR: invalid sf_idx=%d for period=%d\n", parent->cfg.sr_cfg.sf_mapping[j_min], period);
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -2255,7 +2247,10 @@ int rrc::ue::sr_allocate(uint32_t period, uint8_t* I_sr, uint16_t* N_pucch_sr)
|
|
|
|
|
sr_N_pucch = *N_pucch_sr;
|
|
|
|
|
|
|
|
|
|
parent->rrc_log->info("Allocated SR resources for time-frequency slot (%d, %d), N_pucch_sr=%d, I_sr=%d\n",
|
|
|
|
|
sr_sched_prb_idx, sr_sched_sf_idx, *N_pucch_sr, *I_sr);
|
|
|
|
|
sr_sched_prb_idx,
|
|
|
|
|
sr_sched_sf_idx,
|
|
|
|
|
*N_pucch_sr,
|
|
|
|
|
*I_sr);
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
@ -2266,9 +2261,11 @@ int rrc::ue::cqi_free()
|
|
|
|
|
if (parent->cqi_sched.nof_users[cqi_sched_prb_idx][cqi_sched_sf_idx] > 0) {
|
|
|
|
|
parent->cqi_sched.nof_users[cqi_sched_prb_idx][cqi_sched_sf_idx]--;
|
|
|
|
|
} else {
|
|
|
|
|
parent->rrc_log->warning("Removing CQI resources: no users in time-frequency slot (%d, %d)\n", cqi_sched_prb_idx, cqi_sched_sf_idx);
|
|
|
|
|
parent->rrc_log->warning(
|
|
|
|
|
"Removing CQI resources: no users in time-frequency slot (%d, %d)\n", cqi_sched_prb_idx, cqi_sched_sf_idx);
|
|
|
|
|
}
|
|
|
|
|
parent->rrc_log->info("Deallocated CQI resources for time-frequency slot (%d, %d)\n", cqi_sched_prb_idx, cqi_sched_sf_idx);
|
|
|
|
|
parent->rrc_log->info(
|
|
|
|
|
"Deallocated CQI resources for time-frequency slot (%d, %d)\n", cqi_sched_prb_idx, cqi_sched_sf_idx);
|
|
|
|
|
}
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
@ -2305,8 +2302,8 @@ int rrc::ue::cqi_allocate(uint32_t period, uint16_t* pmi_idx, uint16_t* n_pucch)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Compute I_sr
|
|
|
|
|
if (period != 2 && period != 5 && period != 10 && period != 20 && period != 40 && period != 80 &&
|
|
|
|
|
period != 160 && period != 32 && period != 64 && period != 128) {
|
|
|
|
|
if (period != 2 && period != 5 && period != 10 && period != 20 && period != 40 && period != 80 && period != 160 &&
|
|
|
|
|
period != 32 && period != 64 && period != 128) {
|
|
|
|
|
parent->rrc_log->error("Invalid CQI Report period %d ms\n", period);
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
@ -2327,7 +2324,8 @@ int rrc::ue::cqi_allocate(uint32_t period, uint16_t* pmi_idx, uint16_t* n_pucch)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
parent->rrc_log->error("Allocating SR: invalid sf_idx=%d for period=%d\n", parent->cfg.cqi_cfg.sf_mapping[j_min], period);
|
|
|
|
|
parent->rrc_log->error(
|
|
|
|
|
"Allocating SR: invalid sf_idx=%d for period=%d\n", parent->cfg.cqi_cfg.sf_mapping[j_min], period);
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -2393,4 +2391,4 @@ int rrc::ue::ri_get(uint32_t m_ri, uint16_t* ri_idx)
|
|
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
} // namespace srsenb
|
|
|
|
|