From 6120f202905d3a3cec6c5ae565a7d1f015e1c661 Mon Sep 17 00:00:00 2001 From: Ismael Gomez Date: Tue, 12 Jun 2018 17:31:07 +0200 Subject: [PATCH] Changes in RRC and S1AP to make enb more robust on UE add/rem operations. * Consolidated functions in S1AP * Fixed ASAN in some GCC * Stop quicker the enb * Minor typo edit * Fixed mutexing issues in RRC and possibly RLC/PDCP when adding/removing users --- CMakeLists.txt | 4 +- .../srslte/interfaces/enb_interfaces.h | 4 +- srsenb/hdr/upper/pdcp.h | 6 +- srsenb/hdr/upper/rlc.h | 11 +- srsenb/hdr/upper/rrc.h | 19 +- srsenb/hdr/upper/s1ap.h | 4 +- srsenb/src/enb.cc | 5 +- srsenb/src/mac/mac.cc | 2 +- srsenb/src/main.cc | 4 +- srsenb/src/phy/phch_worker.cc | 14 +- srsenb/src/upper/pdcp.cc | 21 - srsenb/src/upper/rlc.cc | 42 +- srsenb/src/upper/rrc.cc | 666 ++++++++++-------- srsenb/src/upper/s1ap.cc | 57 +- srsue/src/upper/nas.cc | 2 +- 15 files changed, 427 insertions(+), 434 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 30986ece9..0c1e5a1e3 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -324,8 +324,8 @@ if(CMAKE_C_COMPILER_ID MATCHES "GNU" OR CMAKE_C_COMPILER_ID MATCHES "Clang") ADD_CXX_COMPILER_FLAG_IF_AVAILABLE(-fvisibility=hidden HAVE_VISIBILITY_HIDDEN) endif(NOT WIN32) if (ENABLE_ASAN) - set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=address") - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=address") + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=address -fuse-ld=gold") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=address -fuse-ld=gold") endif (ENABLE_ASAN) endif(CMAKE_C_COMPILER_ID MATCHES "GNU" OR CMAKE_C_COMPILER_ID MATCHES "Clang") diff --git a/lib/include/srslte/interfaces/enb_interfaces.h b/lib/include/srslte/interfaces/enb_interfaces.h index 66aea467a..1b4f0da56 100644 --- a/lib/include/srslte/interfaces/enb_interfaces.h +++ b/lib/include/srslte/interfaces/enb_interfaces.h @@ -278,9 +278,7 @@ public: virtual void initial_ue(uint16_t rnti, srslte::byte_buffer_t *pdu, uint32_t m_tmsi, uint8_t mmec) = 0; virtual void write_pdu(uint16_t rnti, srslte::byte_buffer_t *pdu) = 0; virtual bool user_exists(uint16_t rnti) = 0; - virtual void user_inactivity(uint16_t rnti) = 0; - virtual void release_eutran(uint16_t rnti) = 0; - virtual bool user_link_lost(uint16_t rnti) = 0; + virtual bool user_release(uint16_t rnti, LIBLTE_S1AP_CAUSERADIONETWORK_ENUM cause_radio) = 0; virtual void ue_ctxt_setup_complete(uint16_t rnti, LIBLTE_S1AP_MESSAGE_INITIALCONTEXTSETUPRESPONSE_STRUCT *res) = 0; virtual void ue_erab_setup_complete(uint16_t rnti, LIBLTE_S1AP_MESSAGE_E_RABSETUPRESPONSE_STRUCT *res) = 0; // virtual void ue_capabilities(uint16_t rnti, LIBLTE_RRC_UE_EUTRA_CAPABILITY_STRUCT *caps) = 0; diff --git a/srsenb/hdr/upper/pdcp.h b/srsenb/hdr/upper/pdcp.h index 37f473117..c249b856e 100644 --- a/srsenb/hdr/upper/pdcp.h +++ b/srsenb/hdr/upper/pdcp.h @@ -41,7 +41,6 @@ class pdcp : public pdcp_interface_rlc, public: void init(rlc_interface_pdcp *rlc_, rrc_interface_pdcp *rrc_, gtpu_interface_pdcp *gtpu_, srslte::log *pdcp_log_); - ~pdcp(); void stop(); // pdcp_interface_rlc @@ -104,10 +103,7 @@ private: user_interface_gtpu gtpu_itf; user_interface_rrc rrc_itf; srslte::pdcp *pdcp; - }; - - // Mutex to protect access to users std::map - pthread_mutex_t mutex; + }; std::map users; diff --git a/srsenb/hdr/upper/rlc.h b/srsenb/hdr/upper/rlc.h index 92911df70..2b0752cf1 100644 --- a/srsenb/hdr/upper/rlc.h +++ b/srsenb/hdr/upper/rlc.h @@ -49,7 +49,6 @@ public: void init(pdcp_interface_rlc *pdcp_, rrc_interface_rlc *rrc_, mac_interface_rlc *mac_, srslte::mac_interface_timers *mac_timers_, srslte::log *log_h); - ~rlc(); void stop(); // rlc_interface_rrc @@ -92,13 +91,11 @@ private: srsenb::rrc_interface_rlc *rrc; srslte::rlc *rlc; srsenb::rlc *parent; - }; - - // Mutex to protect access to users std::map - pthread_mutex_t mutex; - + }; + std::map users; - + std::vector mch_services; + mac_interface_rlc *mac; pdcp_interface_rlc *pdcp; rrc_interface_rlc *rrc; diff --git a/srsenb/hdr/upper/rrc.h b/srsenb/hdr/upper/rrc.h index b2b0b37b8..77895facb 100644 --- a/srsenb/hdr/upper/rrc.h +++ b/srsenb/hdr/upper/rrc.h @@ -140,9 +140,6 @@ public: void stop(); void get_metrics(rrc_metrics_t &m); - //rrc_interface_phy - void configure_mbsfn_sibs(LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_2_STRUCT *sib2, LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_13_STRUCT *sib13); - // rrc_interface_mac void rl_failure(uint16_t rnti); void add_user(uint16_t rnti); @@ -195,7 +192,9 @@ public: bool is_idle(); bool is_timeout(); void set_activity(); - + + uint32_t rl_failure(); + rrc_state_t get_state(); void send_connection_setup(bool is_setup = true); @@ -257,6 +256,7 @@ public: uint32_t m_tmsi; uint8_t mmec; + uint32_t rlf_cnt; uint8_t transaction_id; rrc_state_t state; @@ -311,9 +311,13 @@ private: // user connect notifier connect_notifier *cnotifier; + void process_release_complete(uint16_t rnti); + void process_rl_failure(uint16_t rnti); void rem_user(uint16_t rnti); uint32_t generate_sibs(); - void config_mac(); + void configure_mbsfn_sibs(LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_2_STRUCT *sib2, LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_13_STRUCT *sib13); + + void config_mac(); void parse_ul_dcch(uint16_t rnti, uint32_t lcid, srslte::byte_buffer_t *pdu); void parse_ul_ccch(uint16_t rnti, srslte::byte_buffer_t *pdu); void configure_security(uint16_t rnti, @@ -344,7 +348,10 @@ private: srslte::byte_buffer_t* pdu; }rrc_pdu; - const static uint32_t LCID_REM_USER = 0xffff0001; + const static uint32_t LCID_REM_USER = 0xffff0001; + const static uint32_t LCID_REL_USER = 0xffff0002; + const static uint32_t LCID_RLF_USER = 0xffff0003; + const static uint32_t LCID_ACT_USER = 0xffff0004; bool running; static const int RRC_THREAD_PRIO = 65; diff --git a/srsenb/hdr/upper/s1ap.h b/srsenb/hdr/upper/s1ap.h index 35b871bdc..2e355649f 100644 --- a/srsenb/hdr/upper/s1ap.h +++ b/srsenb/hdr/upper/s1ap.h @@ -76,9 +76,7 @@ public: void initial_ue(uint16_t rnti, srslte::byte_buffer_t *pdu, uint32_t m_tmsi, uint8_t mmec); void write_pdu(uint16_t rnti, srslte::byte_buffer_t *pdu); bool user_exists(uint16_t rnti); - void user_inactivity(uint16_t rnti); - bool user_link_lost(uint16_t rnti); - void release_eutran(uint16_t rnti); + bool user_release(uint16_t rnti, LIBLTE_S1AP_CAUSERADIONETWORK_ENUM cause_radio); void ue_ctxt_setup_complete(uint16_t rnti, LIBLTE_S1AP_MESSAGE_INITIALCONTEXTSETUPRESPONSE_STRUCT *res); void ue_erab_setup_complete(uint16_t rnti, LIBLTE_S1AP_MESSAGE_E_RABSETUPRESPONSE_STRUCT *res); //void ue_capabilities(uint16_t rnti, LIBLTE_RRC_UE_EUTRA_CAPABILITY_STRUCT *caps); diff --git a/srsenb/src/enb.cc b/srsenb/src/enb.cc index 2f22a8e5e..1bdfafb41 100644 --- a/srsenb/src/enb.cc +++ b/srsenb/src/enb.cc @@ -234,16 +234,17 @@ void enb::stop() { if(started) { + s1ap.stop(); gtpu.stop(); phy.stop(); mac.stop(); - usleep(100000); + usleep(50000); rlc.stop(); pdcp.stop(); rrc.stop(); - usleep(1e5); + usleep(10000); if(args->pcap.enable) { mac_pcap.close(); diff --git a/srsenb/src/mac/mac.cc b/srsenb/src/mac/mac.cc index 98139f735..3b3919061 100644 --- a/srsenb/src/mac/mac.cc +++ b/srsenb/src/mac/mac.cc @@ -161,7 +161,7 @@ int mac::rlc_buffer_state(uint16_t rnti, uint32_t lc_id, uint32_t tx_queue, uint return 0; } } else { - Error("User rnti=0x%x not found- this\n", rnti); + Error("User rnti=0x%x not found\n", rnti); return -1; } } diff --git a/srsenb/src/main.cc b/srsenb/src/main.cc index 8a2a5ce2e..e9b94d531 100644 --- a/srsenb/src/main.cc +++ b/srsenb/src/main.cc @@ -420,12 +420,12 @@ int main(int argc, char *argv[]) while (running) { if (args.expert.print_buffer_state) { cnt++; - if (cnt==10) { + if (cnt==1000) { cnt=0; enb->print_pool(); } } - sleep(1); + usleep(10000); } pthread_cancel(input); metrics.stop(); diff --git a/srsenb/src/phy/phch_worker.cc b/srsenb/src/phy/phch_worker.cc index 19291fac0..de9c03bf2 100644 --- a/srsenb/src/phy/phch_worker.cc +++ b/srsenb/src/phy/phch_worker.cc @@ -355,13 +355,16 @@ void phch_worker::rem_rnti(uint16_t rnti) void phch_worker::work_imp() { + bool is_mutexed; + if (!running) { return; } + subframe_cfg_t sf_cfg; phy->get_sf_config(&sf_cfg, tti_tx_dl);// TODO difference between tti_tx_dl and t_tx_dl pthread_mutex_lock(&mutex); - + is_mutexed = true; mac_interface_phy::ul_sched_t *ul_grants = phy->ul_grants; mac_interface_phy::dl_sched_t *dl_grants = phy->dl_grants; @@ -455,7 +458,10 @@ void phch_worker::work_imp() } } } - + + is_mutexed = false; + pthread_mutex_unlock(&mutex); + // Generate signal and transmit if(sf_cfg.sf_type == SUBFRAME_TYPE_REGULAR) { srslte_enb_dl_gen_signal(&enb_dl); @@ -484,7 +490,9 @@ void phch_worker::work_imp() #endif unlock: - pthread_mutex_unlock(&mutex); + if (is_mutexed) { + pthread_mutex_unlock(&mutex); + } } diff --git a/srsenb/src/upper/pdcp.cc b/srsenb/src/upper/pdcp.cc index a8774e408..e6f4f40f5 100644 --- a/srsenb/src/upper/pdcp.cc +++ b/srsenb/src/upper/pdcp.cc @@ -37,11 +37,6 @@ void pdcp::init(rlc_interface_pdcp* rlc_, rrc_interface_pdcp* rrc_, gtpu_interfa log_h = pdcp_log_; pool = srslte::byte_buffer_pool::get_instance(); - pthread_mutex_init(&mutex, NULL); -} - -pdcp::~pdcp() { - pthread_mutex_destroy(&mutex); } void pdcp::stop() @@ -49,14 +44,11 @@ void pdcp::stop() for(std::map::iterator iter=users.begin(); iter!=users.end(); ++iter) { rem_user((uint32_t) iter->first); } - pthread_mutex_lock(&mutex); users.clear(); - pthread_mutex_unlock(&mutex); } void pdcp::add_user(uint16_t rnti) { - pthread_mutex_lock(&mutex); if (users.count(rnti) == 0) { srslte::pdcp *obj = new srslte::pdcp; obj->init(&users[rnti].rlc_itf, &users[rnti].rrc_itf, &users[rnti].gtpu_itf, log_h, RB_ID_SRB0, SECURITY_DIRECTION_DOWNLINK); @@ -69,24 +61,20 @@ void pdcp::add_user(uint16_t rnti) users[rnti].gtpu_itf.gtpu = gtpu; users[rnti].pdcp = obj; } - pthread_mutex_unlock(&mutex); } void pdcp::rem_user(uint16_t rnti) { - pthread_mutex_lock(&mutex); if (users.count(rnti)) { users[rnti].pdcp->stop(); delete users[rnti].pdcp; users[rnti].pdcp = NULL; users.erase(rnti); } - pthread_mutex_unlock(&mutex); } void pdcp::add_bearer(uint16_t rnti, uint32_t lcid, srslte::srslte_pdcp_config_t cfg) { - pthread_mutex_lock(&mutex); if (users.count(rnti)) { if(rnti != SRSLTE_MRNTI){ users[rnti].pdcp->add_bearer(lcid, cfg); @@ -94,45 +82,37 @@ void pdcp::add_bearer(uint16_t rnti, uint32_t lcid, srslte::srslte_pdcp_config_t users[rnti].pdcp->add_bearer_mrb(lcid, cfg); } } - pthread_mutex_unlock(&mutex); } void pdcp::reset(uint16_t rnti) { - pthread_mutex_lock(&mutex); if (users.count(rnti)) { users[rnti].pdcp->reset(); } - pthread_mutex_unlock(&mutex); } void pdcp::config_security(uint16_t rnti, uint32_t lcid, uint8_t* k_rrc_enc_, uint8_t* k_rrc_int_, srslte::CIPHERING_ALGORITHM_ID_ENUM cipher_algo_, srslte::INTEGRITY_ALGORITHM_ID_ENUM integ_algo_) { - pthread_mutex_lock(&mutex); if (users.count(rnti)) { users[rnti].pdcp->config_security(lcid, k_rrc_enc_, k_rrc_int_, cipher_algo_, integ_algo_); users[rnti].pdcp->enable_integrity(lcid); users[rnti].pdcp->enable_encryption(lcid); } - pthread_mutex_unlock(&mutex); } void pdcp::write_pdu(uint16_t rnti, uint32_t lcid, srslte::byte_buffer_t* sdu) { - pthread_mutex_lock(&mutex); if (users.count(rnti)) { users[rnti].pdcp->write_pdu(lcid, sdu); } else { pool->deallocate(sdu); } - pthread_mutex_unlock(&mutex); } void pdcp::write_sdu(uint16_t rnti, uint32_t lcid, srslte::byte_buffer_t* sdu) { - pthread_mutex_lock(&mutex); if (users.count(rnti)) { if(rnti != SRSLTE_MRNTI){ users[rnti].pdcp->write_sdu(lcid, sdu); @@ -142,7 +122,6 @@ void pdcp::write_sdu(uint16_t rnti, uint32_t lcid, srslte::byte_buffer_t* sdu) } else { pool->deallocate(sdu); } - pthread_mutex_unlock(&mutex); } void pdcp::user_interface_gtpu::write_pdu(uint32_t lcid, srslte::byte_buffer_t *pdu) diff --git a/srsenb/src/upper/rlc.cc b/srsenb/src/upper/rlc.cc index d9860b475..0624dbca4 100644 --- a/srsenb/src/upper/rlc.cc +++ b/srsenb/src/upper/rlc.cc @@ -40,11 +40,6 @@ void rlc::init(pdcp_interface_rlc* pdcp_, rrc_interface_rlc* rrc_, mac_interface pool = srslte::byte_buffer_pool::get_instance(); - pthread_mutex_init(&mutex, NULL); -} - -rlc::~rlc() { - pthread_mutex_destroy(&mutex); } void rlc::stop() @@ -52,15 +47,12 @@ void rlc::stop() for(std::map::iterator iter=users.begin(); iter!=users.end(); ++iter) { rem_user((uint32_t) iter->first); } - pthread_mutex_lock(&mutex); users.clear(); - pthread_mutex_unlock(&mutex); } void rlc::add_user(uint16_t rnti) { - pthread_mutex_lock(&mutex); - if (users.count(rnti) == 0) { + if (users.count(rnti) == 0) { srslte::rlc *obj = new srslte::rlc; obj->init(&users[rnti], &users[rnti], &users[rnti], log_h, mac_timers, RB_ID_SRB0); users[rnti].rnti = rnti; @@ -69,33 +61,27 @@ void rlc::add_user(uint16_t rnti) users[rnti].rlc = obj; users[rnti].parent = this; } - pthread_mutex_unlock(&mutex); } void rlc::rem_user(uint16_t rnti) { - pthread_mutex_lock(&mutex); if (users.count(rnti)) { users[rnti].rlc->stop(); delete users[rnti].rlc; users[rnti].rlc = NULL; users.erase(rnti); } - pthread_mutex_unlock(&mutex); } void rlc::reset(uint16_t rnti) { - pthread_mutex_lock(&mutex); if (users.count(rnti)) { users[rnti].rlc->reset(); } - pthread_mutex_unlock(&mutex); } void rlc::clear_buffer(uint16_t rnti) { - pthread_mutex_lock(&mutex); if (users.count(rnti)) { users[rnti].rlc->empty_queue(); for (int i=0;iinfo("Cleared buffer rnti=0x%x\n", rnti); } - pthread_mutex_unlock(&mutex); } void rlc::add_bearer(uint16_t rnti, uint32_t lcid) { - pthread_mutex_lock(&mutex); if (users.count(rnti)) { users[rnti].rlc->add_bearer(lcid); } - pthread_mutex_unlock(&mutex); } void rlc::add_bearer(uint16_t rnti, uint32_t lcid, srslte::srslte_rlc_config_t cnfg) { - pthread_mutex_lock(&mutex); if (users.count(rnti)) { users[rnti].rlc->add_bearer(lcid, cnfg); } - pthread_mutex_unlock(&mutex); } void rlc::add_bearer_mrb(uint16_t rnti, uint32_t lcid) { - pthread_mutex_lock(&mutex); if (users.count(rnti)) { users[rnti].rlc->add_bearer_mrb_enb(lcid); } - pthread_mutex_unlock(&mutex); } void rlc::read_pdu_pcch(uint8_t* payload, uint32_t buffer_size) @@ -140,14 +119,13 @@ void rlc::read_pdu_pcch(uint8_t* payload, uint32_t buffer_size) int rlc::read_pdu(uint16_t rnti, uint32_t lcid, uint8_t* payload, uint32_t nof_bytes) { - pthread_mutex_lock(&mutex); int ret; uint32_t tx_queue; - if (users.count(rnti)) { - if (rnti != SRSLTE_MRNTI) { + if(users.count(rnti)){ + if(rnti != SRSLTE_MRNTI){ ret = users[rnti].rlc->read_pdu(lcid, payload, nof_bytes); tx_queue = users[rnti].rlc->get_total_buffer_state(lcid); - } else { + }else{ ret = users[rnti].rlc->read_pdu_mch(lcid, payload, nof_bytes); tx_queue = users[rnti].rlc->get_total_mch_buffer_state(lcid); } @@ -157,14 +135,15 @@ int rlc::read_pdu(uint16_t rnti, uint32_t lcid, uint8_t* payload, uint32_t nof_b uint32_t retx_queue = 0; log_h->debug("Buffer state PDCP: rnti=0x%x, lcid=%d, tx_queue=%d\n", rnti, lcid, tx_queue); mac->rlc_buffer_state(rnti, lcid, tx_queue, retx_queue); + return ret; + + }else{ + return SRSLTE_ERROR; } - pthread_mutex_unlock(&mutex); - return ret; } void rlc::write_pdu(uint16_t rnti, uint32_t lcid, uint8_t* payload, uint32_t nof_bytes) { - pthread_mutex_lock(&mutex); if (users.count(rnti)) { users[rnti].rlc->write_pdu(lcid, payload, nof_bytes); @@ -175,7 +154,6 @@ void rlc::write_pdu(uint16_t rnti, uint32_t lcid, uint8_t* payload, uint32_t nof log_h->debug("Buffer state PDCP: rnti=0x%x, lcid=%d, tx_queue=%d\n", rnti, lcid, tx_queue); mac->rlc_buffer_state(rnti, lcid, tx_queue, retx_queue); } - pthread_mutex_unlock(&mutex); } void rlc::read_pdu_bcch_dlsch(uint32_t sib_index, uint8_t *payload) @@ -186,8 +164,7 @@ void rlc::read_pdu_bcch_dlsch(uint32_t sib_index, uint8_t *payload) void rlc::write_sdu(uint16_t rnti, uint32_t lcid, srslte::byte_buffer_t* sdu) { - - pthread_mutex_lock(&mutex); + uint32_t tx_queue; if (users.count(rnti)) { if(rnti != SRSLTE_MRNTI){ @@ -206,7 +183,6 @@ void rlc::write_sdu(uint16_t rnti, uint32_t lcid, srslte::byte_buffer_t* sdu) } else { pool->deallocate(sdu); } - pthread_mutex_unlock(&mutex); } bool rlc::rb_is_um(uint16_t rnti, uint32_t lcid) { diff --git a/srsenb/src/upper/rrc.cc b/srsenb/src/upper/rrc.cc index 4a1477a2d..f3d61829f 100644 --- a/srsenb/src/upper/rrc.cc +++ b/srsenb/src/upper/rrc.cc @@ -75,69 +75,7 @@ void rrc::init(rrc_cfg_t *cfg_, start(RRC_THREAD_PRIO); } -void rrc::configure_mbsfn_sibs(LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_2_STRUCT *sib2, LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_13_STRUCT *sib13) -{ - - // Temp assignment of MCCH, this will eventually come from a cfg file - mcch.pmch_infolist_r9_size = 1; - mcch.commonsf_allocpatternlist_r9_size = 1; - mcch.commonsf_allocperiod_r9 = LIBLTE_RRC_MBSFN_COMMON_SF_ALLOC_PERIOD_R9_RF64; - mcch.commonsf_allocpatternlist_r9[0].radio_fr_alloc_offset = 0; - mcch.commonsf_allocpatternlist_r9[0].radio_fr_alloc_period = LIBLTE_RRC_RADIO_FRAME_ALLOCATION_PERIOD_N1; - mcch.commonsf_allocpatternlist_r9[0].subfr_alloc = 32+31; - mcch.commonsf_allocpatternlist_r9[0].subfr_alloc_num_frames = LIBLTE_RRC_SUBFRAME_ALLOCATION_NUM_FRAMES_ONE; - - mcch.pmch_infolist_r9[0].mbms_sessioninfolist_r9_size = 1; - - - mcch.pmch_infolist_r9[0].mbms_sessioninfolist_r9[0].logicalchannelid_r9 = 1; - mcch.pmch_infolist_r9[0].mbms_sessioninfolist_r9[0].sessionid_r9 = 0; - mcch.pmch_infolist_r9[0].mbms_sessioninfolist_r9[0].sessionid_r9_present = true; - mcch.pmch_infolist_r9[0].mbms_sessioninfolist_r9[0].tmgi_r9.plmn_id_explicit = true; - mcch.pmch_infolist_r9[0].mbms_sessioninfolist_r9[0].tmgi_r9.plmn_id_r9.mcc = 0; - mcch.pmch_infolist_r9[0].mbms_sessioninfolist_r9[0].tmgi_r9.plmn_id_r9.mnc = 3; - mcch.pmch_infolist_r9[0].mbms_sessioninfolist_r9[0].tmgi_r9.plmn_index_r9 = 0; - mcch.pmch_infolist_r9[0].mbms_sessioninfolist_r9[0].tmgi_r9.serviceid_r9 = 0; - - if(mcch.pmch_infolist_r9[0].mbms_sessioninfolist_r9_size > 1) { - - mcch.pmch_infolist_r9[0].mbms_sessioninfolist_r9[1].logicalchannelid_r9 = 2; - mcch.pmch_infolist_r9[0].mbms_sessioninfolist_r9[1].sessionid_r9 = 1; - mcch.pmch_infolist_r9[0].mbms_sessioninfolist_r9[1].sessionid_r9_present = true; - mcch.pmch_infolist_r9[0].mbms_sessioninfolist_r9[1].tmgi_r9.plmn_id_explicit = true; - mcch.pmch_infolist_r9[0].mbms_sessioninfolist_r9[1].tmgi_r9.plmn_id_r9.mcc = 0; - mcch.pmch_infolist_r9[0].mbms_sessioninfolist_r9[1].tmgi_r9.plmn_id_r9.mnc = 3; - mcch.pmch_infolist_r9[0].mbms_sessioninfolist_r9[1].tmgi_r9.plmn_index_r9 = 0; - mcch.pmch_infolist_r9[0].mbms_sessioninfolist_r9[1].tmgi_r9.serviceid_r9 = 1; - - } - mcch.pmch_infolist_r9[0].pmch_config_r9.datamcs_r9 = 10; - mcch.pmch_infolist_r9[0].pmch_config_r9.mch_schedulingperiod_r9 = LIBLTE_RRC_MCH_SCHEDULING_PERIOD_R9_RF64; - mcch.pmch_infolist_r9[0].pmch_config_r9.sf_alloc_end_r9 = 64*6; - - - - phy->configure_mbsfn(sib2,sib13,mcch); - mac->write_mcch(sib2,sib13,&mcch); - -} - -rrc::activity_monitor::activity_monitor(rrc* parent_) -{ - running = true; - parent = parent_; -} - -void rrc::activity_monitor::stop() -{ - if (running) { - running = false; - thread_cancel(); - wait_thread_finish(); - } -} - -void rrc::set_connect_notifer(connect_notifier *cnotifier) +void rrc::set_connect_notifer(connect_notifier *cnotifier) { this->cnotifier = cnotifier; } @@ -150,104 +88,40 @@ void rrc::stop() wait_thread_finish(); } act_monitor.stop(); + pthread_mutex_lock(&user_mutex); users.clear(); + pthread_mutex_unlock(&user_mutex); pthread_mutex_destroy(&user_mutex); pthread_mutex_destroy(&paging_mutex); } -void rrc::get_metrics(rrc_metrics_t &m) -{ - pthread_mutex_lock(&user_mutex); - m.n_ues = 0; - for(std::map::iterator 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(); - } - } - pthread_mutex_unlock(&user_mutex); -} +/******************************************************************************* + Public functions + All public functions must be mutexed. +*******************************************************************************/ -uint32_t rrc::generate_sibs() +void rrc::get_metrics(rrc_metrics_t &m) { - // nof_messages includes SIB2 by default, plus all configured SIBs - uint32_t nof_messages = 1+cfg.sibs[0].sib.sib1.N_sched_info; - LIBLTE_RRC_SCHEDULING_INFO_STRUCT *sched_info = cfg.sibs[0].sib.sib1.sched_info; - - // msg is array of SI messages, each SI message msg[i] may contain multiple SIBs - // all SIBs in a SI message msg[i] share the same periodicity - LIBLTE_RRC_BCCH_DLSCH_MSG_STRUCT *msg = (LIBLTE_RRC_BCCH_DLSCH_MSG_STRUCT*)calloc(nof_messages+1, sizeof(LIBLTE_RRC_BCCH_DLSCH_MSG_STRUCT)); - - // Copy SIB1 to first SI message - msg[0].N_sibs = 1; - memcpy(&msg[0].sibs[0], &cfg.sibs[0], sizeof(LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_STRUCT)); - - // Copy rest of SIBs - for (uint32_t sched_info_elem = 0; sched_info_elem < nof_messages; sched_info_elem++) { - uint32_t msg_index = sched_info_elem + 1; // first msg is SIB1, therefore start with second - uint32_t current_msg_element_offset = 0; - - msg[msg_index].N_sibs = 0; - - // SIB2 always in second SI message - if (msg_index == 1) { - msg[msg_index].N_sibs++; - memcpy(&msg[msg_index].sibs[0], &cfg.sibs[1], sizeof(LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_STRUCT)); - current_msg_element_offset = 1; // make sure "other SIBs" do not overwrite this SIB2 - // Save SIB2 - memcpy(&sib2, &cfg.sibs[1].sib.sib2, sizeof(LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_2_STRUCT)); - } else { - current_msg_element_offset = 0; // no SIB2, no offset - } - - // Add other SIBs to this message, if any - for (uint32_t mapping = 0; mapping < sched_info[sched_info_elem].N_sib_mapping_info; mapping++) { - msg[msg_index].N_sibs++; - // current_msg_element_offset skips SIB2 if necessary - memcpy(&msg[msg_index].sibs[mapping + current_msg_element_offset], - &cfg.sibs[(int) sched_info[sched_info_elem].sib_mapping_info[mapping].sib_type+2], - sizeof(LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_STRUCT)); + if (running) { + pthread_mutex_lock(&user_mutex); + m.n_ues = 0; + for(std::map::iterator 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(); + } } + pthread_mutex_unlock(&user_mutex); } - - // Pack payload for all messages - for (uint32_t msg_index = 0; msg_index < nof_messages; msg_index++) { - LIBLTE_BIT_MSG_STRUCT bitbuffer; - liblte_rrc_pack_bcch_dlsch_msg(&msg[msg_index], &bitbuffer); - srslte_bit_pack_vector(bitbuffer.msg, sib_buffer[msg_index].msg, bitbuffer.N_bits); - sib_buffer[msg_index].N_bytes = (bitbuffer.N_bits-1)/8+1; - } - - free(msg); - return nof_messages; } -void rrc::config_mac() -{ - - // Fill MAC scheduler configuration for SIBs - sched_interface::cell_cfg_t sched_cfg; - bzero(&sched_cfg, sizeof(sched_interface::cell_cfg_t)); - for (uint32_t i=0;icell_cfg(&sched_cfg); -} +/******************************************************************************* + MAC interface + Those functions that shall be called from a phch_worker should push the command + to the queue and process later +*******************************************************************************/ void rrc::read_pdu_bcch_dlsch(uint32_t sib_index, uint8_t* payload) { @@ -257,123 +131,87 @@ void rrc::read_pdu_bcch_dlsch(uint32_t sib_index, uint8_t* payload) } void rrc::rl_failure(uint16_t rnti) -{ - rrc_log->info("Radio-Link failure detected rnti=0x%x\n", rnti); - if (s1ap->user_exists(rnti)) { - if (!s1ap->user_link_lost(rnti)) { - rrc_log->info("Removing rnti=0x%x\n", rnti); - rem_user_thread(rnti); - } - } else { - rrc_log->warning("User rnti=0x%x context not existing in S1AP. Removing user\n", rnti); - rem_user_thread(rnti); - } +{ + rrc_pdu p = {rnti, LCID_RLF_USER, NULL}; + rx_pdu_queue.push(p); +} + +void rrc::set_activity_user(uint16_t rnti) +{ + rrc_pdu p = {rnti, LCID_ACT_USER, NULL}; + rx_pdu_queue.push(p); +} + +void rrc::rem_user_thread(uint16_t rnti) +{ + rrc_pdu p = {rnti, LCID_REM_USER, NULL}; + rx_pdu_queue.push(p); +} + +uint32_t rrc::get_nof_users() { + return users.size(); +} + +void rrc::max_retx_attempted(uint16_t rnti) +{ + } +// This function is called from PRACH worker (can wait) void rrc::add_user(uint16_t rnti) { pthread_mutex_lock(&user_mutex); if (users.count(rnti) == 0) { - - users[rnti].parent = this; - users[rnti].rnti = rnti; + + users[rnti].parent = this; + users[rnti].rnti = rnti; rlc->add_user(rnti); - pdcp->add_user(rnti); + pdcp->add_user(rnti); rrc_log->info("Added new user rnti=0x%x\n", rnti); } else { rrc_log->error("Adding user rnti=0x%x (already exists)\n", rnti); } - - if(rnti == SRSLTE_MRNTI){ - srslte::srslte_pdcp_config_t cfg; - cfg.is_control = false; - cfg.is_data = true; - cfg.direction = SECURITY_DIRECTION_DOWNLINK; - uint32_t teid_in = 1; - - for(uint32_t i = 0; i add_bearer_mrb(SRSLTE_MRNTI,lcid); - pdcp->add_bearer(SRSLTE_MRNTI,lcid,cfg); - gtpu->add_bearer(SRSLTE_MRNTI,lcid, 1, 1, &teid_in); - } - } - - pthread_mutex_unlock(&user_mutex); -} -void rrc::rem_user(uint16_t rnti) -{ - pthread_mutex_lock(&user_mutex); - if (users.count(rnti) == 1) { - rrc_log->console("Disconnecting rnti=0x%x.\n", rnti); - rrc_log->info("Disconnecting rnti=0x%x.\n", rnti); - - /* First remove MAC and GTPU to stop processing DL/UL traffic for this user - */ - mac->ue_rem(rnti); // MAC handles PHY - gtpu->rem_user(rnti); + if(rnti == SRSLTE_MRNTI){ + srslte::srslte_pdcp_config_t cfg; + cfg.is_control = false; + cfg.is_data = true; + cfg.direction = SECURITY_DIRECTION_DOWNLINK; + uint32_t teid_in = 1; - // Wait enough time - pthread_mutex_unlock(&user_mutex); - usleep(50000); - pthread_mutex_lock(&user_mutex); - - // Now remove RLC and PDCP - rlc->rem_user(rnti); - pdcp->rem_user(rnti); - - // And deallocate resources from RRC - users[rnti].sr_free(); - users[rnti].cqi_free(); - users.erase(rnti); - rrc_log->info("Removed user rnti=0x%x\n", rnti); - } else { - rrc_log->error("Removing user rnti=0x%x (does not exist)\n", rnti); + for(uint32_t i = 0; i add_bearer_mrb(SRSLTE_MRNTI,lcid); + pdcp->add_bearer(SRSLTE_MRNTI,lcid,cfg); + gtpu->add_bearer(SRSLTE_MRNTI,lcid, 1, 1, &teid_in); + } } + pthread_mutex_unlock(&user_mutex); } -// Function called by MAC after the reception of a C-RNTI CE indicating that the UE still has a -// valid RNTI -void rrc::upd_user(uint16_t new_rnti, uint16_t old_rnti) +/* Function called by MAC after the reception of a C-RNTI CE indicating that the UE still has a + * valid RNTI. + * Called by MAC reader thread (can wait to process) + */ +void rrc::upd_user(uint16_t new_rnti, uint16_t old_rnti) { // Remove new_rnti rem_user_thread(new_rnti); - + // Send Reconfiguration to old_rnti if is RRC_CONNECT or RRC Release if already released here + pthread_mutex_lock(&user_mutex); if (users.count(old_rnti) == 1) { if (users[old_rnti].is_connected()) { users[old_rnti].send_connection_reconf_upd(pool_allocate); } else { users[old_rnti].send_connection_release(); } - } -} - -void rrc::set_activity_user(uint16_t rnti) -{ - if (users.count(rnti) == 1) { - users[rnti].set_activity(); } + pthread_mutex_unlock(&user_mutex); } -void rrc::rem_user_thread(uint16_t rnti) -{ - if (users.count(rnti) == 1) { - rrc_pdu p = {rnti, LCID_REM_USER, NULL}; - rx_pdu_queue.push(p); - } -} -uint32_t rrc::get_nof_users() { - return users.size(); -} - -void rrc::max_retx_attempted(uint16_t rnti) -{ - -} /******************************************************************************* PDCP interface @@ -392,6 +230,8 @@ void rrc::write_dl_info(uint16_t rnti, byte_buffer_t* sdu) LIBLTE_RRC_DL_DCCH_MSG_STRUCT dl_dcch_msg; bzero(&dl_dcch_msg, sizeof(LIBLTE_RRC_DL_DCCH_MSG_STRUCT)); + pthread_mutex_lock(&user_mutex); + if (users.count(rnti) == 1) { dl_dcch_msg.msg_type = LIBLTE_RRC_DL_DCCH_MSG_TYPE_DL_INFO_TRANSFER; memcpy(dl_dcch_msg.msg.dl_info_transfer.dedicated_info.msg, sdu->msg, sdu->N_bytes); @@ -404,30 +244,24 @@ void rrc::write_dl_info(uint16_t rnti, byte_buffer_t* sdu) } else { rrc_log->error("Rx SDU for unknown rnti=0x%x\n", rnti); } + + pthread_mutex_unlock(&user_mutex); } -void rrc::release_complete(uint16_t rnti) -{ - rrc_log->info("Received Release Complete rnti=0x%x\n", rnti); - if (users.count(rnti) == 1) { - if (!users[rnti].is_idle()) { - rlc->clear_buffer(rnti); - users[rnti].send_connection_release(); - // There is no RRCReleaseComplete message from UE thus wait ~100 subframes for tx - usleep(100000); - } - rem_user(rnti); - } else { - rrc_log->error("Received ReleaseComplete for unknown rnti=0x%x\n", rnti); - } +void rrc::release_complete(uint16_t rnti) { + rrc_pdu p = {rnti, LCID_REL_USER, NULL}; + rx_pdu_queue.push(p); } bool rrc::setup_ue_ctxt(uint16_t rnti, LIBLTE_S1AP_MESSAGE_INITIALCONTEXTSETUPREQUEST_STRUCT *msg) { + pthread_mutex_lock(&user_mutex); + rrc_log->info("Adding initial context for 0x%x\n", rnti); if(users.count(rnti) == 0) { rrc_log->warning("Unrecognised rnti: 0x%x\n", rnti); + pthread_mutex_unlock(&user_mutex); return false; } @@ -488,15 +322,20 @@ bool rrc::setup_ue_ctxt(uint16_t rnti, LIBLTE_S1AP_MESSAGE_INITIALCONTEXTSETUPRE // Setup E-RABs users[rnti].setup_erabs(&msg->E_RABToBeSetupListCtxtSUReq); + pthread_mutex_unlock(&user_mutex); + return true; } bool rrc::setup_ue_erabs(uint16_t rnti, LIBLTE_S1AP_MESSAGE_E_RABSETUPREQUEST_STRUCT *msg) { + pthread_mutex_lock(&user_mutex); + rrc_log->info("Setting up erab(s) for 0x%x\n", rnti); if(users.count(rnti) == 0) { rrc_log->warning("Unrecognised rnti: 0x%x\n", rnti); + pthread_mutex_unlock(&user_mutex); return false; } @@ -508,21 +347,35 @@ bool rrc::setup_ue_erabs(uint16_t rnti, LIBLTE_S1AP_MESSAGE_E_RABSETUPREQUEST_ST // Setup E-RABs users[rnti].setup_erabs(&msg->E_RABToBeSetupListBearerSUReq); + pthread_mutex_unlock(&user_mutex); + return true; } bool rrc::release_erabs(uint32_t rnti) { + pthread_mutex_lock(&user_mutex); rrc_log->info("Releasing E-RABs for 0x%x\n", rnti); if(users.count(rnti) == 0) { rrc_log->warning("Unrecognised rnti: 0x%x\n", rnti); + pthread_mutex_unlock(&user_mutex); return false; } - return users[rnti].release_erabs(); + bool ret = users[rnti].release_erabs(); + pthread_mutex_unlock(&user_mutex); + return ret; } + + +/******************************************************************************* + Paging functions + These functions use a different mutex because access different shared variables + than user map +*******************************************************************************/ + void rrc::add_paging_id(uint32_t ueid, LIBLTE_S1AP_UEPAGINGID_STRUCT UEPagingID) { pthread_mutex_lock(&paging_mutex); @@ -615,17 +468,21 @@ bool rrc::is_paging_opportunity(uint32_t tti, uint32_t *payload_len) return false; } - void rrc::read_pdu_pcch(uint8_t *payload, uint32_t buffer_size) { + pthread_mutex_lock(&paging_mutex); uint32_t N_bytes = (bit_buf_paging.N_bits-1)/8+1; if (N_bytes <= buffer_size) { srslte_bit_pack_vector(bit_buf_paging.msg, payload, bit_buf_paging.N_bits); - } + } + pthread_mutex_unlock(&paging_mutex); } + /******************************************************************************* - Parsers + Private functions + All private functions are not mutexed and must be called from a mutexed enviornment + from either a public function or the internal thread *******************************************************************************/ void rrc::parse_ul_ccch(uint16_t rnti, byte_buffer_t *pdu) @@ -664,12 +521,13 @@ void rrc::parse_ul_ccch(uint16_t rnti, byte_buffer_t *pdu) if (users.count(old_rnti)) { rrc_log->error("Not supported: ConnectionReestablishment for rnti=0x%x. Sending Connection Reject\n", old_rnti); users[rnti].send_connection_reest_rej(); - rem_user_thread(old_rnti); + s1ap->user_release(old_rnti, LIBLTE_S1AP_CAUSERADIONETWORK_RELEASE_DUE_TO_EUTRAN_GENERATED_REASON); } else { rrc_log->error("Received ConnectionReestablishment for rnti=0x%x without context\n", old_rnti); users[rnti].send_connection_reest_rej(); } // remove temporal rnti + rrc_log->warning("Received ConnectionReestablishment for rnti=0x%x. Removing temporal rnti=0x%x\n", old_rnti, rnti); rem_user_thread(rnti); } else { rrc_log->error("Received ReestablishmentRequest from an rnti=0x%x not in IDLE\n", rnti); @@ -695,6 +553,210 @@ void rrc::parse_ul_dcch(uint16_t rnti, uint32_t lcid, byte_buffer_t *pdu) } } +void rrc::process_rl_failure(uint16_t rnti) +{ + if (users.count(rnti) == 0) { + uint32_t n_rfl = users[rnti].rl_failure(); + if (n_rfl == 1) { + rrc_log->info("Radio-Link failure detected rnti=0x%x\n", rnti); + if (s1ap->user_exists(rnti)) { + if (!s1ap->user_release(rnti, LIBLTE_S1AP_CAUSERADIONETWORK_RADIO_CONNECTION_WITH_UE_LOST)) { + rrc_log->info("Removing rnti=0x%x\n", rnti); + } + } else { + rrc_log->warning("User rnti=0x%x context not existing in S1AP. Removing user\n", rnti); + // Remove user from separate thread to wait to close all resources + rem_user_thread(rnti); + } + } else { + rrc_log->info("%d Radio-Link failure detected rnti=0x%x\n", n_rfl, rnti); + } + } +} + +void rrc::process_release_complete(uint16_t rnti) +{ + rrc_log->info("Received Release Complete rnti=0x%x\n", rnti); + if (users.count(rnti) == 1) { + if (!users[rnti].is_idle()) { + rlc->clear_buffer(rnti); + users[rnti].send_connection_release(); + // There is no RRCReleaseComplete message from UE thus wait ~50 subframes for tx + usleep(50000); + } + // Save to call rem_user() directly without thread, because calling from private function + rem_user(rnti); + } else { + rrc_log->error("Received ReleaseComplete for unknown rnti=0x%x\n", rnti); + } +} + +void rrc::rem_user(uint16_t rnti) +{ + if (users.count(rnti) == 1) { + rrc_log->console("Disconnecting rnti=0x%x.\n", rnti); + rrc_log->info("Disconnecting rnti=0x%x.\n", rnti); + + /* First remove MAC and GTPU to stop processing DL/UL traffic for this user + */ + mac->ue_rem(rnti); // MAC handles PHY + gtpu->rem_user(rnti); + + // Wait enough time + pthread_mutex_unlock(&user_mutex); + usleep(50000); + pthread_mutex_lock(&user_mutex); + + // Now remove RLC and PDCP + rlc->rem_user(rnti); + pdcp->rem_user(rnti); + + // And deallocate resources from RRC + users[rnti].sr_free(); + users[rnti].cqi_free(); + users.erase(rnti); + rrc_log->info("Removed user rnti=0x%x\n", rnti); + } else { + rrc_log->error("Removing user rnti=0x%x (does not exist)\n", rnti); + } +} + +void rrc::config_mac() +{ + // Fill MAC scheduler configuration for SIBs + sched_interface::cell_cfg_t sched_cfg; + bzero(&sched_cfg, sizeof(sched_interface::cell_cfg_t)); + for (uint32_t i=0;icell_cfg(&sched_cfg); +} + +uint32_t rrc::generate_sibs() +{ + // nof_messages includes SIB2 by default, plus all configured SIBs + uint32_t nof_messages = 1+cfg.sibs[0].sib.sib1.N_sched_info; + LIBLTE_RRC_SCHEDULING_INFO_STRUCT *sched_info = cfg.sibs[0].sib.sib1.sched_info; + + // msg is array of SI messages, each SI message msg[i] may contain multiple SIBs + // all SIBs in a SI message msg[i] share the same periodicity + LIBLTE_RRC_BCCH_DLSCH_MSG_STRUCT *msg = (LIBLTE_RRC_BCCH_DLSCH_MSG_STRUCT*)calloc(nof_messages+1, sizeof(LIBLTE_RRC_BCCH_DLSCH_MSG_STRUCT)); + + // Copy SIB1 to first SI message + msg[0].N_sibs = 1; + memcpy(&msg[0].sibs[0], &cfg.sibs[0], sizeof(LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_STRUCT)); + + // Copy rest of SIBs + for (uint32_t sched_info_elem = 0; sched_info_elem < nof_messages; sched_info_elem++) { + uint32_t msg_index = sched_info_elem + 1; // first msg is SIB1, therefore start with second + uint32_t current_msg_element_offset = 0; + + msg[msg_index].N_sibs = 0; + + // SIB2 always in second SI message + if (msg_index == 1) { + msg[msg_index].N_sibs++; + memcpy(&msg[msg_index].sibs[0], &cfg.sibs[1], sizeof(LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_STRUCT)); + current_msg_element_offset = 1; // make sure "other SIBs" do not overwrite this SIB2 + // Save SIB2 + memcpy(&sib2, &cfg.sibs[1].sib.sib2, sizeof(LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_2_STRUCT)); + } else { + current_msg_element_offset = 0; // no SIB2, no offset + } + + // Add other SIBs to this message, if any + for (uint32_t mapping = 0; mapping < sched_info[sched_info_elem].N_sib_mapping_info; mapping++) { + msg[msg_index].N_sibs++; + // current_msg_element_offset skips SIB2 if necessary + memcpy(&msg[msg_index].sibs[mapping + current_msg_element_offset], + &cfg.sibs[(int) sched_info[sched_info_elem].sib_mapping_info[mapping].sib_type+2], + sizeof(LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_STRUCT)); + } + } + + // Pack payload for all messages + for (uint32_t msg_index = 0; msg_index < nof_messages; msg_index++) { + LIBLTE_BIT_MSG_STRUCT bitbuffer; + liblte_rrc_pack_bcch_dlsch_msg(&msg[msg_index], &bitbuffer); + srslte_bit_pack_vector(bitbuffer.msg, sib_buffer[msg_index].msg, bitbuffer.N_bits); + sib_buffer[msg_index].N_bytes = (bitbuffer.N_bits-1)/8+1; + } + + free(msg); + return nof_messages; +} + +void rrc::configure_mbsfn_sibs(LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_2_STRUCT *sib2, LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_13_STRUCT *sib13) +{ + // Temp assignment of MCCH, this will eventually come from a cfg file + mcch.pmch_infolist_r9_size = 1; + mcch.commonsf_allocpatternlist_r9_size = 1; + mcch.commonsf_allocperiod_r9 = LIBLTE_RRC_MBSFN_COMMON_SF_ALLOC_PERIOD_R9_RF64; + mcch.commonsf_allocpatternlist_r9[0].radio_fr_alloc_offset = 0; + mcch.commonsf_allocpatternlist_r9[0].radio_fr_alloc_period = LIBLTE_RRC_RADIO_FRAME_ALLOCATION_PERIOD_N1; + mcch.commonsf_allocpatternlist_r9[0].subfr_alloc = 32+31; + mcch.commonsf_allocpatternlist_r9[0].subfr_alloc_num_frames = LIBLTE_RRC_SUBFRAME_ALLOCATION_NUM_FRAMES_ONE; + + mcch.pmch_infolist_r9[0].mbms_sessioninfolist_r9_size = 1; + + + mcch.pmch_infolist_r9[0].mbms_sessioninfolist_r9[0].logicalchannelid_r9 = 1; + mcch.pmch_infolist_r9[0].mbms_sessioninfolist_r9[0].sessionid_r9 = 0; + mcch.pmch_infolist_r9[0].mbms_sessioninfolist_r9[0].sessionid_r9_present = true; + mcch.pmch_infolist_r9[0].mbms_sessioninfolist_r9[0].tmgi_r9.plmn_id_explicit = true; + mcch.pmch_infolist_r9[0].mbms_sessioninfolist_r9[0].tmgi_r9.plmn_id_r9.mcc = 0; + mcch.pmch_infolist_r9[0].mbms_sessioninfolist_r9[0].tmgi_r9.plmn_id_r9.mnc = 3; + mcch.pmch_infolist_r9[0].mbms_sessioninfolist_r9[0].tmgi_r9.plmn_index_r9 = 0; + mcch.pmch_infolist_r9[0].mbms_sessioninfolist_r9[0].tmgi_r9.serviceid_r9 = 0; + + if(mcch.pmch_infolist_r9[0].mbms_sessioninfolist_r9_size > 1) { + + mcch.pmch_infolist_r9[0].mbms_sessioninfolist_r9[1].logicalchannelid_r9 = 2; + mcch.pmch_infolist_r9[0].mbms_sessioninfolist_r9[1].sessionid_r9 = 1; + mcch.pmch_infolist_r9[0].mbms_sessioninfolist_r9[1].sessionid_r9_present = true; + mcch.pmch_infolist_r9[0].mbms_sessioninfolist_r9[1].tmgi_r9.plmn_id_explicit = true; + mcch.pmch_infolist_r9[0].mbms_sessioninfolist_r9[1].tmgi_r9.plmn_id_r9.mcc = 0; + mcch.pmch_infolist_r9[0].mbms_sessioninfolist_r9[1].tmgi_r9.plmn_id_r9.mnc = 3; + mcch.pmch_infolist_r9[0].mbms_sessioninfolist_r9[1].tmgi_r9.plmn_index_r9 = 0; + mcch.pmch_infolist_r9[0].mbms_sessioninfolist_r9[1].tmgi_r9.serviceid_r9 = 1; + + } + mcch.pmch_infolist_r9[0].pmch_config_r9.datamcs_r9 = 10; + mcch.pmch_infolist_r9[0].pmch_config_r9.mch_schedulingperiod_r9 = LIBLTE_RRC_MCH_SCHEDULING_PERIOD_R9_RF64; + mcch.pmch_infolist_r9[0].pmch_config_r9.sf_alloc_end_r9 = 64*6; + + + + phy->configure_mbsfn(sib2,sib13,mcch); + mac->write_mcch(sib2,sib13,&mcch); +} + +void rrc::configure_security(uint16_t rnti, + uint32_t lcid, + uint8_t *k_rrc_enc, + uint8_t *k_rrc_int, + uint8_t *k_up_enc, + uint8_t *k_up_int, + srslte::CIPHERING_ALGORITHM_ID_ENUM cipher_algo, + srslte::INTEGRITY_ALGORITHM_ID_ENUM integ_algo) +{ + // TODO: add k_up_enc, k_up_int support to PDCP + pdcp->config_security(rnti, lcid, k_rrc_enc, k_rrc_int, cipher_algo, integ_algo); +} + /******************************************************************************* RRC thread *******************************************************************************/ @@ -709,6 +771,8 @@ void rrc::run_thread() if (p.pdu) { rrc_log->info_hex(p.pdu->msg, p.pdu->N_bytes, "Rx %s PDU", rb_id_text[p.lcid]); } + + // Mutex these calls even though it's a private function pthread_mutex_lock(&user_mutex); if (users.count(p.rnti) == 1) { switch(p.lcid) @@ -721,10 +785,18 @@ void rrc::run_thread() parse_ul_dcch(p.rnti, p.lcid, p.pdu); break; case LCID_REM_USER: - pthread_mutex_unlock(&user_mutex); - usleep(10000); rem_user(p.rnti); - pthread_mutex_lock(&user_mutex); + break; + case LCID_REL_USER: + process_release_complete(p.rnti); + break; + case LCID_RLF_USER: + process_rl_failure(p.rnti); + break; + case LCID_ACT_USER: + if (users.count(p.rnti) == 1) { + users[p.rnti].set_activity(); + } break; default: rrc_log->error("Rx PDU with invalid bearer id: %d", p.lcid); @@ -737,63 +809,72 @@ void rrc::run_thread() pthread_mutex_unlock(&user_mutex); } } + + + +/******************************************************************************* + Activity monitor class +*******************************************************************************/ + +rrc::activity_monitor::activity_monitor(rrc* parent_) +{ + running = true; + parent = parent_; +} + +void rrc::activity_monitor::stop() +{ + if (running) { + running = false; + thread_cancel(); + wait_thread_finish(); + } +} + void rrc::activity_monitor::run_thread() { - while(running) + while(running) { usleep(10000); pthread_mutex_lock(&parent->user_mutex); - uint16_t rem_rnti = 0; + uint16_t rem_rnti = 0; for(std::map::iterator 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; + uint16_t rnti = (uint16_t) iter->first; if (parent->cnotifier && u->is_connected() && !u->connect_notified) { parent->cnotifier->user_connected(rnti); - u->connect_notified = true; + u->connect_notified = true; } 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"); - rem_rnti = rnti; - } - } + rem_rnti = rnti; + } + } } - pthread_mutex_unlock(&parent->user_mutex); if (rem_rnti) { if (parent->s1ap->user_exists(rem_rnti)) { - parent->s1ap->user_inactivity(rem_rnti); + parent->s1ap->user_release(rem_rnti, LIBLTE_S1AP_CAUSERADIONETWORK_USER_INACTIVITY); } else { if(rem_rnti != SRSLTE_MRNTI) - parent->rem_user(rem_rnti); + parent->rem_user(rem_rnti); } } + pthread_mutex_unlock(&parent->user_mutex); } } -/******************************************************************************* - RRC::UE Helpers -*******************************************************************************/ -void rrc::configure_security(uint16_t rnti, - uint32_t lcid, - uint8_t *k_rrc_enc, - uint8_t *k_rrc_int, - uint8_t *k_up_enc, - uint8_t *k_up_int, - srslte::CIPHERING_ALGORITHM_ID_ENUM cipher_algo, - srslte::INTEGRITY_ALGORITHM_ID_ENUM integ_algo) -{ - // TODO: add k_up_enc, k_up_int support to PDCP - pdcp->config_security(rnti, lcid, k_rrc_enc, k_rrc_int, cipher_algo, integ_algo); -} - - - - + + + /******************************************************************************* UE class + + Every function in UE class is called from a mutex environment thus does not + need extra protection. *******************************************************************************/ rrc::ue::ue() { @@ -812,6 +893,7 @@ rrc::ue::ue() cqi_idx = 0; cqi_sched_sf_idx = 0; cqi_sched_prb_idx = 0; + rlf_cnt = 0; state = RRC_STATE_IDLE; pool = srslte::byte_buffer_pool::get_instance(); } @@ -821,6 +903,11 @@ rrc_state_t rrc::ue::get_state() return state; } +uint32_t rrc::ue::rl_failure() { + rlf_cnt++; + return rlf_cnt; +} + void rrc::ue::set_activity() { gettimeofday(&t_last_activity, NULL); @@ -1222,7 +1309,6 @@ void rrc::ue::send_connection_setup(bool is_setup) rr_cfg = &dl_ccch_msg.msg.rrc_con_reest.rr_cnfg; } - // Add SRB1 to cfg rr_cfg->srb_to_add_mod_list_size = 1; rr_cfg->srb_to_add_mod_list[0].srb_id = 1; @@ -1349,13 +1435,11 @@ void rrc::ue::send_connection_setup(bool is_setup) send_dl_ccch(&dl_ccch_msg); } - void rrc::ue::send_connection_reest() { send_connection_setup(false); } - void rrc::ue::send_connection_release() { LIBLTE_RRC_DL_DCCH_MSG_STRUCT dl_dcch_msg; @@ -1692,7 +1776,7 @@ void rrc::ue::send_dl_ccch(LIBLTE_RRC_DL_CCCH_MSG_STRUCT *dl_ccch_msg) } } -void rrc::ue::send_dl_dcch(LIBLTE_RRC_DL_DCCH_MSG_STRUCT *dl_dcch_msg, byte_buffer_t *pdu) +void rrc::ue::send_dl_dcch(LIBLTE_RRC_DL_DCCH_MSG_STRUCT *dl_dcch_msg, byte_buffer_t *pdu) { if (!pdu) { pdu = pool_allocate; @@ -1793,7 +1877,6 @@ int rrc::ue::sr_allocate(uint32_t period, uint32_t *I_sr, uint32_t *N_pucch_sr) return 0; } - int rrc::ue::cqi_free() { if (cqi_allocated) { @@ -1885,7 +1968,4 @@ int rrc::ue::cqi_allocate(uint32_t period, uint32_t *pmi_idx, uint32_t *n_pucch) return 0; } - - - } diff --git a/srsenb/src/upper/s1ap.cc b/srsenb/src/upper/s1ap.cc index 6eafe5030..8e1643a0c 100644 --- a/srsenb/src/upper/s1ap.cc +++ b/srsenb/src/upper/s1ap.cc @@ -204,54 +204,30 @@ void s1ap::write_pdu(uint16_t rnti, srslte::byte_buffer_t *pdu) send_ulnastransport(rnti, pdu); } -void s1ap::user_inactivity(uint16_t rnti) +bool s1ap::user_release(uint16_t rnti, LIBLTE_S1AP_CAUSERADIONETWORK_ENUM cause_radio) { s1ap_log->info("User inactivity - RNTI:0x%x\n", rnti); if(ue_ctxt_map.end() == ue_ctxt_map.find(rnti)) { s1ap_log->warning("User RNTI:0x%x context not found\n", rnti); - return; + return false; } if(ue_ctxt_map[rnti].release_requested) { s1ap_log->warning("UE context for RNTI:0x%x is in zombie state. Releasing...\n", rnti); ue_ctxt_map.erase(rnti); rrc->release_complete(rnti); - return; - } - - LIBLTE_S1AP_CAUSE_STRUCT cause; - cause.ext = false; - cause.choice_type = LIBLTE_S1AP_CAUSE_CHOICE_RADIONETWORK; - cause.choice.radioNetwork.ext = false; - cause.choice.radioNetwork.e = LIBLTE_S1AP_CAUSERADIONETWORK_USER_INACTIVITY; - - ue_ctxt_map[rnti].release_requested = true; - send_uectxtreleaserequest(rnti, &cause); -} - - -void s1ap::release_eutran(uint16_t rnti) -{ - s1ap_log->info("Release by EUTRAN - RNTI:0x%x\n", rnti); - - if(ue_ctxt_map.end() == ue_ctxt_map.find(rnti)) { - s1ap_log->warning("User RNTI:0x%x context not found\n", rnti); - return; - } - - if(ue_ctxt_map[rnti].release_requested) { - return; + return false; } LIBLTE_S1AP_CAUSE_STRUCT cause; cause.ext = false; cause.choice_type = LIBLTE_S1AP_CAUSE_CHOICE_RADIONETWORK; cause.choice.radioNetwork.ext = false; - cause.choice.radioNetwork.e = LIBLTE_S1AP_CAUSERADIONETWORK_RELEASE_DUE_TO_EUTRAN_GENERATED_REASON; + cause.choice.radioNetwork.e = cause_radio; ue_ctxt_map[rnti].release_requested = true; - send_uectxtreleaserequest(rnti, &cause); + return send_uectxtreleaserequest(rnti, &cause); } bool s1ap::user_exists(uint16_t rnti) @@ -259,29 +235,6 @@ bool s1ap::user_exists(uint16_t rnti) return ue_ctxt_map.end() != ue_ctxt_map.find(rnti); } -bool s1ap::user_link_lost(uint16_t rnti) -{ - s1ap_log->info("User link lost - RNTI:0x%x\n", rnti); - - if(ue_ctxt_map.end() == ue_ctxt_map.find(rnti)) { - s1ap_log->warning("User RNTI:0x%x context not found\n", rnti); - return false; - } - - if(ue_ctxt_map[rnti].release_requested) { - return false; - } - - LIBLTE_S1AP_CAUSE_STRUCT cause; - cause.ext = false; - cause.choice_type = LIBLTE_S1AP_CAUSE_CHOICE_RADIONETWORK; - cause.choice.radioNetwork.ext = false; - cause.choice.radioNetwork.e = LIBLTE_S1AP_CAUSERADIONETWORK_RADIO_CONNECTION_WITH_UE_LOST; - - ue_ctxt_map[rnti].release_requested = true; - return send_uectxtreleaserequest(rnti, &cause); -} - void s1ap::ue_ctxt_setup_complete(uint16_t rnti, LIBLTE_S1AP_MESSAGE_INITIALCONTEXTSETUPRESPONSE_STRUCT *res) { if(res->E_RABSetupListCtxtSURes.len > 0) { diff --git a/srsue/src/upper/nas.cc b/srsue/src/upper/nas.cc index 8bc8e5d12..a6b47fca5 100644 --- a/srsue/src/upper/nas.cc +++ b/srsue/src/upper/nas.cc @@ -529,7 +529,7 @@ void nas::cipher_decrypt(byte_buffer_t *pdu) memcpy(&pdu->msg[6], &tmp_pdu.msg[6], pdu->N_bytes-6); break; default: - nas_log->error("Ciphering algorithmus not known\n"); + nas_log->error("Ciphering algorithms not known\n"); break; } }