mirror of https://github.com/PentHertz/srsLTE.git
Merge branch 'next' of github.com:softwareradiosystems/srsLTE into next
This commit is contained in:
commit
ca1ec9bb61
|
@ -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)
|
ADD_CXX_COMPILER_FLAG_IF_AVAILABLE(-fvisibility=hidden HAVE_VISIBILITY_HIDDEN)
|
||||||
endif(NOT WIN32)
|
endif(NOT WIN32)
|
||||||
if (ENABLE_ASAN)
|
if (ENABLE_ASAN)
|
||||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=address")
|
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=address -fuse-ld=gold")
|
||||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=address")
|
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=address -fuse-ld=gold")
|
||||||
endif (ENABLE_ASAN)
|
endif (ENABLE_ASAN)
|
||||||
endif(CMAKE_C_COMPILER_ID MATCHES "GNU" OR CMAKE_C_COMPILER_ID MATCHES "Clang")
|
endif(CMAKE_C_COMPILER_ID MATCHES "GNU" OR CMAKE_C_COMPILER_ID MATCHES "Clang")
|
||||||
|
|
||||||
|
|
|
@ -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 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 void write_pdu(uint16_t rnti, srslte::byte_buffer_t *pdu) = 0;
|
||||||
virtual bool user_exists(uint16_t rnti) = 0;
|
virtual bool user_exists(uint16_t rnti) = 0;
|
||||||
virtual void user_inactivity(uint16_t rnti) = 0;
|
virtual bool user_release(uint16_t rnti, LIBLTE_S1AP_CAUSERADIONETWORK_ENUM cause_radio) = 0;
|
||||||
virtual void release_eutran(uint16_t rnti) = 0;
|
|
||||||
virtual bool user_link_lost(uint16_t rnti) = 0;
|
|
||||||
virtual void ue_ctxt_setup_complete(uint16_t rnti, LIBLTE_S1AP_MESSAGE_INITIALCONTEXTSETUPRESPONSE_STRUCT *res) = 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_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;
|
// virtual void ue_capabilities(uint16_t rnti, LIBLTE_RRC_UE_EUTRA_CAPABILITY_STRUCT *caps) = 0;
|
||||||
|
|
|
@ -545,12 +545,12 @@ void test_set_1_invalid()
|
||||||
sizeof(uint8_t));
|
sizeof(uint8_t));
|
||||||
|
|
||||||
// encryption
|
// encryption
|
||||||
//err_lte = liblte_security_encryption_eea1(key, count, bearer,
|
err_lte = liblte_security_encryption_eea1(key, count, bearer,
|
||||||
// direction, msg, len_bits, out);
|
direction, msg, len_bits, out);
|
||||||
assert(err_lte == LIBLTE_SUCCESS);
|
assert(err_lte == LIBLTE_SUCCESS);
|
||||||
|
|
||||||
// compare cipher text
|
// compare cipher text
|
||||||
//err_cmp = arrcmp(ct, out, len_bytes);
|
err_cmp = arrcmp(ct, out, len_bytes);
|
||||||
assert(err_cmp != 0);
|
assert(err_cmp != 0);
|
||||||
|
|
||||||
// decryption
|
// decryption
|
||||||
|
|
|
@ -160,8 +160,8 @@ void test_set_2()
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int main(int argc, char * argv[]) {
|
int main(int argc, char * argv[]) {
|
||||||
test_set_2();
|
|
||||||
/*
|
/*
|
||||||
|
test_set_2();
|
||||||
test_set_3();
|
test_set_3();
|
||||||
test_set_4();
|
test_set_4();
|
||||||
test_set_5();
|
test_set_5();
|
||||||
|
|
|
@ -41,7 +41,6 @@ class pdcp : public pdcp_interface_rlc,
|
||||||
public:
|
public:
|
||||||
|
|
||||||
void init(rlc_interface_pdcp *rlc_, rrc_interface_pdcp *rrc_, gtpu_interface_pdcp *gtpu_, srslte::log *pdcp_log_);
|
void init(rlc_interface_pdcp *rlc_, rrc_interface_pdcp *rrc_, gtpu_interface_pdcp *gtpu_, srslte::log *pdcp_log_);
|
||||||
~pdcp();
|
|
||||||
void stop();
|
void stop();
|
||||||
|
|
||||||
// pdcp_interface_rlc
|
// pdcp_interface_rlc
|
||||||
|
@ -106,9 +105,6 @@ private:
|
||||||
srslte::pdcp *pdcp;
|
srslte::pdcp *pdcp;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Mutex to protect access to users std::map
|
|
||||||
pthread_mutex_t mutex;
|
|
||||||
|
|
||||||
std::map<uint32_t,user_interface> users;
|
std::map<uint32_t,user_interface> users;
|
||||||
|
|
||||||
rlc_interface_pdcp *rlc;
|
rlc_interface_pdcp *rlc;
|
||||||
|
|
|
@ -49,7 +49,6 @@ public:
|
||||||
|
|
||||||
void init(pdcp_interface_rlc *pdcp_, rrc_interface_rlc *rrc_, mac_interface_rlc *mac_,
|
void init(pdcp_interface_rlc *pdcp_, rrc_interface_rlc *rrc_, mac_interface_rlc *mac_,
|
||||||
srslte::mac_interface_timers *mac_timers_, srslte::log *log_h);
|
srslte::mac_interface_timers *mac_timers_, srslte::log *log_h);
|
||||||
~rlc();
|
|
||||||
void stop();
|
void stop();
|
||||||
|
|
||||||
// rlc_interface_rrc
|
// rlc_interface_rrc
|
||||||
|
@ -94,10 +93,8 @@ private:
|
||||||
srsenb::rlc *parent;
|
srsenb::rlc *parent;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Mutex to protect access to users std::map
|
|
||||||
pthread_mutex_t mutex;
|
|
||||||
|
|
||||||
std::map<uint32_t,user_interface> users;
|
std::map<uint32_t,user_interface> users;
|
||||||
|
std::vector<mch_service_t> mch_services;
|
||||||
|
|
||||||
mac_interface_rlc *mac;
|
mac_interface_rlc *mac;
|
||||||
pdcp_interface_rlc *pdcp;
|
pdcp_interface_rlc *pdcp;
|
||||||
|
|
|
@ -140,9 +140,6 @@ public:
|
||||||
void stop();
|
void stop();
|
||||||
void get_metrics(rrc_metrics_t &m);
|
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
|
// rrc_interface_mac
|
||||||
void rl_failure(uint16_t rnti);
|
void rl_failure(uint16_t rnti);
|
||||||
void add_user(uint16_t rnti);
|
void add_user(uint16_t rnti);
|
||||||
|
@ -196,6 +193,8 @@ public:
|
||||||
bool is_timeout();
|
bool is_timeout();
|
||||||
void set_activity();
|
void set_activity();
|
||||||
|
|
||||||
|
uint32_t rl_failure();
|
||||||
|
|
||||||
rrc_state_t get_state();
|
rrc_state_t get_state();
|
||||||
|
|
||||||
void send_connection_setup(bool is_setup = true);
|
void send_connection_setup(bool is_setup = true);
|
||||||
|
@ -257,6 +256,7 @@ public:
|
||||||
uint32_t m_tmsi;
|
uint32_t m_tmsi;
|
||||||
uint8_t mmec;
|
uint8_t mmec;
|
||||||
|
|
||||||
|
uint32_t rlf_cnt;
|
||||||
uint8_t transaction_id;
|
uint8_t transaction_id;
|
||||||
rrc_state_t state;
|
rrc_state_t state;
|
||||||
|
|
||||||
|
@ -311,8 +311,12 @@ private:
|
||||||
// user connect notifier
|
// user connect notifier
|
||||||
connect_notifier *cnotifier;
|
connect_notifier *cnotifier;
|
||||||
|
|
||||||
|
void process_release_complete(uint16_t rnti);
|
||||||
|
void process_rl_failure(uint16_t rnti);
|
||||||
void rem_user(uint16_t rnti);
|
void rem_user(uint16_t rnti);
|
||||||
uint32_t generate_sibs();
|
uint32_t generate_sibs();
|
||||||
|
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 config_mac();
|
||||||
void parse_ul_dcch(uint16_t rnti, uint32_t lcid, srslte::byte_buffer_t *pdu);
|
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 parse_ul_ccch(uint16_t rnti, srslte::byte_buffer_t *pdu);
|
||||||
|
@ -345,6 +349,9 @@ private:
|
||||||
}rrc_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;
|
bool running;
|
||||||
static const int RRC_THREAD_PRIO = 65;
|
static const int RRC_THREAD_PRIO = 65;
|
||||||
|
|
|
@ -76,9 +76,7 @@ public:
|
||||||
void initial_ue(uint16_t rnti, srslte::byte_buffer_t *pdu, uint32_t m_tmsi, uint8_t mmec);
|
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);
|
void write_pdu(uint16_t rnti, srslte::byte_buffer_t *pdu);
|
||||||
bool user_exists(uint16_t rnti);
|
bool user_exists(uint16_t rnti);
|
||||||
void user_inactivity(uint16_t rnti);
|
bool user_release(uint16_t rnti, LIBLTE_S1AP_CAUSERADIONETWORK_ENUM cause_radio);
|
||||||
bool user_link_lost(uint16_t rnti);
|
|
||||||
void release_eutran(uint16_t rnti);
|
|
||||||
void ue_ctxt_setup_complete(uint16_t rnti, LIBLTE_S1AP_MESSAGE_INITIALCONTEXTSETUPRESPONSE_STRUCT *res);
|
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_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);
|
//void ue_capabilities(uint16_t rnti, LIBLTE_RRC_UE_EUTRA_CAPABILITY_STRUCT *caps);
|
||||||
|
|
|
@ -234,16 +234,17 @@ void enb::stop()
|
||||||
{
|
{
|
||||||
if(started)
|
if(started)
|
||||||
{
|
{
|
||||||
|
s1ap.stop();
|
||||||
gtpu.stop();
|
gtpu.stop();
|
||||||
phy.stop();
|
phy.stop();
|
||||||
mac.stop();
|
mac.stop();
|
||||||
usleep(100000);
|
usleep(50000);
|
||||||
|
|
||||||
rlc.stop();
|
rlc.stop();
|
||||||
pdcp.stop();
|
pdcp.stop();
|
||||||
rrc.stop();
|
rrc.stop();
|
||||||
|
|
||||||
usleep(1e5);
|
usleep(10000);
|
||||||
if(args->pcap.enable)
|
if(args->pcap.enable)
|
||||||
{
|
{
|
||||||
mac_pcap.close();
|
mac_pcap.close();
|
||||||
|
|
|
@ -161,7 +161,7 @@ int mac::rlc_buffer_state(uint16_t rnti, uint32_t lc_id, uint32_t tx_queue, uint
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
Error("User rnti=0x%x not found- this\n", rnti);
|
Error("User rnti=0x%x not found\n", rnti);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -420,12 +420,12 @@ int main(int argc, char *argv[])
|
||||||
while (running) {
|
while (running) {
|
||||||
if (args.expert.print_buffer_state) {
|
if (args.expert.print_buffer_state) {
|
||||||
cnt++;
|
cnt++;
|
||||||
if (cnt==10) {
|
if (cnt==1000) {
|
||||||
cnt=0;
|
cnt=0;
|
||||||
enb->print_pool();
|
enb->print_pool();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
sleep(1);
|
usleep(10000);
|
||||||
}
|
}
|
||||||
pthread_cancel(input);
|
pthread_cancel(input);
|
||||||
metrics.stop();
|
metrics.stop();
|
||||||
|
|
|
@ -355,13 +355,16 @@ void phch_worker::rem_rnti(uint16_t rnti)
|
||||||
|
|
||||||
void phch_worker::work_imp()
|
void phch_worker::work_imp()
|
||||||
{
|
{
|
||||||
|
bool is_mutexed;
|
||||||
|
|
||||||
if (!running) {
|
if (!running) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
subframe_cfg_t sf_cfg;
|
subframe_cfg_t sf_cfg;
|
||||||
phy->get_sf_config(&sf_cfg, tti_tx_dl);// TODO difference between tti_tx_dl and t_tx_dl
|
phy->get_sf_config(&sf_cfg, tti_tx_dl);// TODO difference between tti_tx_dl and t_tx_dl
|
||||||
pthread_mutex_lock(&mutex);
|
pthread_mutex_lock(&mutex);
|
||||||
|
is_mutexed = true;
|
||||||
|
|
||||||
mac_interface_phy::ul_sched_t *ul_grants = phy->ul_grants;
|
mac_interface_phy::ul_sched_t *ul_grants = phy->ul_grants;
|
||||||
mac_interface_phy::dl_sched_t *dl_grants = phy->dl_grants;
|
mac_interface_phy::dl_sched_t *dl_grants = phy->dl_grants;
|
||||||
|
@ -456,6 +459,9 @@ void phch_worker::work_imp()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
is_mutexed = false;
|
||||||
|
pthread_mutex_unlock(&mutex);
|
||||||
|
|
||||||
// Generate signal and transmit
|
// Generate signal and transmit
|
||||||
if(sf_cfg.sf_type == SUBFRAME_TYPE_REGULAR) {
|
if(sf_cfg.sf_type == SUBFRAME_TYPE_REGULAR) {
|
||||||
srslte_enb_dl_gen_signal(&enb_dl);
|
srslte_enb_dl_gen_signal(&enb_dl);
|
||||||
|
@ -484,7 +490,9 @@ void phch_worker::work_imp()
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
unlock:
|
unlock:
|
||||||
|
if (is_mutexed) {
|
||||||
pthread_mutex_unlock(&mutex);
|
pthread_mutex_unlock(&mutex);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -37,11 +37,6 @@ void pdcp::init(rlc_interface_pdcp* rlc_, rrc_interface_pdcp* rrc_, gtpu_interfa
|
||||||
log_h = pdcp_log_;
|
log_h = pdcp_log_;
|
||||||
|
|
||||||
pool = srslte::byte_buffer_pool::get_instance();
|
pool = srslte::byte_buffer_pool::get_instance();
|
||||||
pthread_mutex_init(&mutex, NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
pdcp::~pdcp() {
|
|
||||||
pthread_mutex_destroy(&mutex);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void pdcp::stop()
|
void pdcp::stop()
|
||||||
|
@ -49,14 +44,11 @@ void pdcp::stop()
|
||||||
for(std::map<uint32_t, user_interface>::iterator iter=users.begin(); iter!=users.end(); ++iter) {
|
for(std::map<uint32_t, user_interface>::iterator iter=users.begin(); iter!=users.end(); ++iter) {
|
||||||
rem_user((uint32_t) iter->first);
|
rem_user((uint32_t) iter->first);
|
||||||
}
|
}
|
||||||
pthread_mutex_lock(&mutex);
|
|
||||||
users.clear();
|
users.clear();
|
||||||
pthread_mutex_unlock(&mutex);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void pdcp::add_user(uint16_t rnti)
|
void pdcp::add_user(uint16_t rnti)
|
||||||
{
|
{
|
||||||
pthread_mutex_lock(&mutex);
|
|
||||||
if (users.count(rnti) == 0) {
|
if (users.count(rnti) == 0) {
|
||||||
srslte::pdcp *obj = new srslte::pdcp;
|
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);
|
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].gtpu_itf.gtpu = gtpu;
|
||||||
users[rnti].pdcp = obj;
|
users[rnti].pdcp = obj;
|
||||||
}
|
}
|
||||||
pthread_mutex_unlock(&mutex);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void pdcp::rem_user(uint16_t rnti)
|
void pdcp::rem_user(uint16_t rnti)
|
||||||
{
|
{
|
||||||
pthread_mutex_lock(&mutex);
|
|
||||||
if (users.count(rnti)) {
|
if (users.count(rnti)) {
|
||||||
users[rnti].pdcp->stop();
|
users[rnti].pdcp->stop();
|
||||||
delete users[rnti].pdcp;
|
delete users[rnti].pdcp;
|
||||||
users[rnti].pdcp = NULL;
|
users[rnti].pdcp = NULL;
|
||||||
users.erase(rnti);
|
users.erase(rnti);
|
||||||
}
|
}
|
||||||
pthread_mutex_unlock(&mutex);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void pdcp::add_bearer(uint16_t rnti, uint32_t lcid, srslte::srslte_pdcp_config_t cfg)
|
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 (users.count(rnti)) {
|
||||||
if(rnti != SRSLTE_MRNTI){
|
if(rnti != SRSLTE_MRNTI){
|
||||||
users[rnti].pdcp->add_bearer(lcid, cfg);
|
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);
|
users[rnti].pdcp->add_bearer_mrb(lcid, cfg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pthread_mutex_unlock(&mutex);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void pdcp::reset(uint16_t rnti)
|
void pdcp::reset(uint16_t rnti)
|
||||||
{
|
{
|
||||||
pthread_mutex_lock(&mutex);
|
|
||||||
if (users.count(rnti)) {
|
if (users.count(rnti)) {
|
||||||
users[rnti].pdcp->reset();
|
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_,
|
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::CIPHERING_ALGORITHM_ID_ENUM cipher_algo_,
|
||||||
srslte::INTEGRITY_ALGORITHM_ID_ENUM integ_algo_)
|
srslte::INTEGRITY_ALGORITHM_ID_ENUM integ_algo_)
|
||||||
{
|
{
|
||||||
pthread_mutex_lock(&mutex);
|
|
||||||
if (users.count(rnti)) {
|
if (users.count(rnti)) {
|
||||||
users[rnti].pdcp->config_security(lcid, k_rrc_enc_, k_rrc_int_, cipher_algo_, integ_algo_);
|
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_integrity(lcid);
|
||||||
users[rnti].pdcp->enable_encryption(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)
|
void pdcp::write_pdu(uint16_t rnti, uint32_t lcid, srslte::byte_buffer_t* sdu)
|
||||||
{
|
{
|
||||||
pthread_mutex_lock(&mutex);
|
|
||||||
if (users.count(rnti)) {
|
if (users.count(rnti)) {
|
||||||
users[rnti].pdcp->write_pdu(lcid, sdu);
|
users[rnti].pdcp->write_pdu(lcid, sdu);
|
||||||
} else {
|
} else {
|
||||||
pool->deallocate(sdu);
|
pool->deallocate(sdu);
|
||||||
}
|
}
|
||||||
pthread_mutex_unlock(&mutex);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void pdcp::write_sdu(uint16_t rnti, uint32_t lcid, srslte::byte_buffer_t* sdu)
|
void pdcp::write_sdu(uint16_t rnti, uint32_t lcid, srslte::byte_buffer_t* sdu)
|
||||||
{
|
{
|
||||||
pthread_mutex_lock(&mutex);
|
|
||||||
if (users.count(rnti)) {
|
if (users.count(rnti)) {
|
||||||
if(rnti != SRSLTE_MRNTI){
|
if(rnti != SRSLTE_MRNTI){
|
||||||
users[rnti].pdcp->write_sdu(lcid, sdu);
|
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 {
|
} else {
|
||||||
pool->deallocate(sdu);
|
pool->deallocate(sdu);
|
||||||
}
|
}
|
||||||
pthread_mutex_unlock(&mutex);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void pdcp::user_interface_gtpu::write_pdu(uint32_t lcid, srslte::byte_buffer_t *pdu)
|
void pdcp::user_interface_gtpu::write_pdu(uint32_t lcid, srslte::byte_buffer_t *pdu)
|
||||||
|
|
|
@ -40,11 +40,6 @@ void rlc::init(pdcp_interface_rlc* pdcp_, rrc_interface_rlc* rrc_, mac_interface
|
||||||
|
|
||||||
pool = srslte::byte_buffer_pool::get_instance();
|
pool = srslte::byte_buffer_pool::get_instance();
|
||||||
|
|
||||||
pthread_mutex_init(&mutex, NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
rlc::~rlc() {
|
|
||||||
pthread_mutex_destroy(&mutex);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void rlc::stop()
|
void rlc::stop()
|
||||||
|
@ -52,14 +47,11 @@ void rlc::stop()
|
||||||
for(std::map<uint32_t, user_interface>::iterator iter=users.begin(); iter!=users.end(); ++iter) {
|
for(std::map<uint32_t, user_interface>::iterator iter=users.begin(); iter!=users.end(); ++iter) {
|
||||||
rem_user((uint32_t) iter->first);
|
rem_user((uint32_t) iter->first);
|
||||||
}
|
}
|
||||||
pthread_mutex_lock(&mutex);
|
|
||||||
users.clear();
|
users.clear();
|
||||||
pthread_mutex_unlock(&mutex);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void rlc::add_user(uint16_t rnti)
|
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;
|
srslte::rlc *obj = new srslte::rlc;
|
||||||
obj->init(&users[rnti], &users[rnti], &users[rnti], log_h, mac_timers, RB_ID_SRB0);
|
obj->init(&users[rnti], &users[rnti], &users[rnti], log_h, mac_timers, RB_ID_SRB0);
|
||||||
|
@ -69,33 +61,27 @@ void rlc::add_user(uint16_t rnti)
|
||||||
users[rnti].rlc = obj;
|
users[rnti].rlc = obj;
|
||||||
users[rnti].parent = this;
|
users[rnti].parent = this;
|
||||||
}
|
}
|
||||||
pthread_mutex_unlock(&mutex);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void rlc::rem_user(uint16_t rnti)
|
void rlc::rem_user(uint16_t rnti)
|
||||||
{
|
{
|
||||||
pthread_mutex_lock(&mutex);
|
|
||||||
if (users.count(rnti)) {
|
if (users.count(rnti)) {
|
||||||
users[rnti].rlc->stop();
|
users[rnti].rlc->stop();
|
||||||
delete users[rnti].rlc;
|
delete users[rnti].rlc;
|
||||||
users[rnti].rlc = NULL;
|
users[rnti].rlc = NULL;
|
||||||
users.erase(rnti);
|
users.erase(rnti);
|
||||||
}
|
}
|
||||||
pthread_mutex_unlock(&mutex);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void rlc::reset(uint16_t rnti)
|
void rlc::reset(uint16_t rnti)
|
||||||
{
|
{
|
||||||
pthread_mutex_lock(&mutex);
|
|
||||||
if (users.count(rnti)) {
|
if (users.count(rnti)) {
|
||||||
users[rnti].rlc->reset();
|
users[rnti].rlc->reset();
|
||||||
}
|
}
|
||||||
pthread_mutex_unlock(&mutex);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void rlc::clear_buffer(uint16_t rnti)
|
void rlc::clear_buffer(uint16_t rnti)
|
||||||
{
|
{
|
||||||
pthread_mutex_lock(&mutex);
|
|
||||||
if (users.count(rnti)) {
|
if (users.count(rnti)) {
|
||||||
users[rnti].rlc->empty_queue();
|
users[rnti].rlc->empty_queue();
|
||||||
for (int i=0;i<SRSLTE_N_RADIO_BEARERS;i++) {
|
for (int i=0;i<SRSLTE_N_RADIO_BEARERS;i++) {
|
||||||
|
@ -103,34 +89,27 @@ void rlc::clear_buffer(uint16_t rnti)
|
||||||
}
|
}
|
||||||
log_h->info("Cleared buffer rnti=0x%x\n", rnti);
|
log_h->info("Cleared buffer rnti=0x%x\n", rnti);
|
||||||
}
|
}
|
||||||
pthread_mutex_unlock(&mutex);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void rlc::add_bearer(uint16_t rnti, uint32_t lcid)
|
void rlc::add_bearer(uint16_t rnti, uint32_t lcid)
|
||||||
{
|
{
|
||||||
pthread_mutex_lock(&mutex);
|
|
||||||
if (users.count(rnti)) {
|
if (users.count(rnti)) {
|
||||||
users[rnti].rlc->add_bearer(lcid);
|
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)
|
void rlc::add_bearer(uint16_t rnti, uint32_t lcid, srslte::srslte_rlc_config_t cnfg)
|
||||||
{
|
{
|
||||||
pthread_mutex_lock(&mutex);
|
|
||||||
if (users.count(rnti)) {
|
if (users.count(rnti)) {
|
||||||
users[rnti].rlc->add_bearer(lcid, cnfg);
|
users[rnti].rlc->add_bearer(lcid, cnfg);
|
||||||
}
|
}
|
||||||
pthread_mutex_unlock(&mutex);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void rlc::add_bearer_mrb(uint16_t rnti, uint32_t lcid)
|
void rlc::add_bearer_mrb(uint16_t rnti, uint32_t lcid)
|
||||||
{
|
{
|
||||||
pthread_mutex_lock(&mutex);
|
|
||||||
if (users.count(rnti)) {
|
if (users.count(rnti)) {
|
||||||
users[rnti].rlc->add_bearer_mrb_enb(lcid);
|
users[rnti].rlc->add_bearer_mrb_enb(lcid);
|
||||||
}
|
}
|
||||||
pthread_mutex_unlock(&mutex);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void rlc::read_pdu_pcch(uint8_t* payload, uint32_t buffer_size)
|
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)
|
int rlc::read_pdu(uint16_t rnti, uint32_t lcid, uint8_t* payload, uint32_t nof_bytes)
|
||||||
{
|
{
|
||||||
pthread_mutex_lock(&mutex);
|
|
||||||
int ret;
|
int ret;
|
||||||
uint32_t tx_queue;
|
uint32_t tx_queue;
|
||||||
if (users.count(rnti)) {
|
if(users.count(rnti)){
|
||||||
if (rnti != SRSLTE_MRNTI) {
|
if(rnti != SRSLTE_MRNTI){
|
||||||
ret = users[rnti].rlc->read_pdu(lcid, payload, nof_bytes);
|
ret = users[rnti].rlc->read_pdu(lcid, payload, nof_bytes);
|
||||||
tx_queue = users[rnti].rlc->get_total_buffer_state(lcid);
|
tx_queue = users[rnti].rlc->get_total_buffer_state(lcid);
|
||||||
} else {
|
}else{
|
||||||
ret = users[rnti].rlc->read_pdu_mch(lcid, payload, nof_bytes);
|
ret = users[rnti].rlc->read_pdu_mch(lcid, payload, nof_bytes);
|
||||||
tx_queue = users[rnti].rlc->get_total_mch_buffer_state(lcid);
|
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;
|
uint32_t retx_queue = 0;
|
||||||
log_h->debug("Buffer state PDCP: rnti=0x%x, lcid=%d, tx_queue=%d\n", rnti, lcid, tx_queue);
|
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);
|
mac->rlc_buffer_state(rnti, lcid, tx_queue, retx_queue);
|
||||||
}
|
|
||||||
pthread_mutex_unlock(&mutex);
|
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
|
}else{
|
||||||
|
return SRSLTE_ERROR;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void rlc::write_pdu(uint16_t rnti, uint32_t lcid, uint8_t* payload, uint32_t nof_bytes)
|
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)) {
|
if (users.count(rnti)) {
|
||||||
users[rnti].rlc->write_pdu(lcid, payload, nof_bytes);
|
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);
|
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);
|
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)
|
void rlc::read_pdu_bcch_dlsch(uint32_t sib_index, uint8_t *payload)
|
||||||
|
@ -187,7 +165,6 @@ 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)
|
void rlc::write_sdu(uint16_t rnti, uint32_t lcid, srslte::byte_buffer_t* sdu)
|
||||||
{
|
{
|
||||||
|
|
||||||
pthread_mutex_lock(&mutex);
|
|
||||||
uint32_t tx_queue;
|
uint32_t tx_queue;
|
||||||
if (users.count(rnti)) {
|
if (users.count(rnti)) {
|
||||||
if(rnti != SRSLTE_MRNTI){
|
if(rnti != SRSLTE_MRNTI){
|
||||||
|
@ -206,7 +183,6 @@ void rlc::write_sdu(uint16_t rnti, uint32_t lcid, srslte::byte_buffer_t* sdu)
|
||||||
} else {
|
} else {
|
||||||
pool->deallocate(sdu);
|
pool->deallocate(sdu);
|
||||||
}
|
}
|
||||||
pthread_mutex_unlock(&mutex);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool rlc::rb_is_um(uint16_t rnti, uint32_t lcid) {
|
bool rlc::rb_is_um(uint16_t rnti, uint32_t lcid) {
|
||||||
|
|
|
@ -75,68 +75,6 @@ void rrc::init(rrc_cfg_t *cfg_,
|
||||||
start(RRC_THREAD_PRIO);
|
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;
|
this->cnotifier = cnotifier;
|
||||||
|
@ -150,13 +88,22 @@ void rrc::stop()
|
||||||
wait_thread_finish();
|
wait_thread_finish();
|
||||||
}
|
}
|
||||||
act_monitor.stop();
|
act_monitor.stop();
|
||||||
|
pthread_mutex_lock(&user_mutex);
|
||||||
users.clear();
|
users.clear();
|
||||||
|
pthread_mutex_unlock(&user_mutex);
|
||||||
pthread_mutex_destroy(&user_mutex);
|
pthread_mutex_destroy(&user_mutex);
|
||||||
pthread_mutex_destroy(&paging_mutex);
|
pthread_mutex_destroy(&paging_mutex);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
Public functions
|
||||||
|
|
||||||
|
All public functions must be mutexed.
|
||||||
|
*******************************************************************************/
|
||||||
|
|
||||||
void rrc::get_metrics(rrc_metrics_t &m)
|
void rrc::get_metrics(rrc_metrics_t &m)
|
||||||
{
|
{
|
||||||
|
if (running) {
|
||||||
pthread_mutex_lock(&user_mutex);
|
pthread_mutex_lock(&user_mutex);
|
||||||
m.n_ues = 0;
|
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(std::map<uint16_t, ue>::iterator iter=users.begin(); m.n_ues < ENB_METRICS_MAX_USERS &&iter!=users.end(); ++iter) {
|
||||||
|
@ -166,88 +113,15 @@ void rrc::get_metrics(rrc_metrics_t &m)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pthread_mutex_unlock(&user_mutex);
|
pthread_mutex_unlock(&user_mutex);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
MAC interface
|
||||||
|
|
||||||
uint32_t rrc::generate_sibs()
|
Those functions that shall be called from a phch_worker should push the command
|
||||||
{
|
to the queue and process later
|
||||||
// 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::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;i<nof_si_messages;i++) {
|
|
||||||
sched_cfg.sibs[i].len = sib_buffer[i].N_bytes;
|
|
||||||
if (i == 0) {
|
|
||||||
sched_cfg.sibs[i].period_rf = 8; // SIB1 is always 8 rf
|
|
||||||
} else {
|
|
||||||
sched_cfg.sibs[i].period_rf = liblte_rrc_si_periodicity_num[cfg.sibs[0].sib.sib1.sched_info[i-1].si_periodicity];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
sched_cfg.si_window_ms = liblte_rrc_si_window_length_num[cfg.sibs[0].sib.sib1.si_window_length];
|
|
||||||
sched_cfg.prach_rar_window = liblte_rrc_ra_response_window_size_num[cfg.sibs[1].sib.sib2.rr_config_common_sib.rach_cnfg.ra_resp_win_size];
|
|
||||||
sched_cfg.maxharq_msg3tx = cfg.sibs[1].sib.sib2.rr_config_common_sib.rach_cnfg.max_harq_msg3_tx;
|
|
||||||
|
|
||||||
// Copy Cell configuration
|
|
||||||
memcpy(&sched_cfg.cell, &cfg.cell, sizeof(srslte_cell_t));
|
|
||||||
|
|
||||||
// Configure MAC scheduler
|
|
||||||
mac->cell_cfg(&sched_cfg);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void rrc::read_pdu_bcch_dlsch(uint32_t sib_index, uint8_t* payload)
|
void rrc::read_pdu_bcch_dlsch(uint32_t sib_index, uint8_t* payload)
|
||||||
{
|
{
|
||||||
|
@ -258,18 +132,32 @@ void rrc::read_pdu_bcch_dlsch(uint32_t sib_index, uint8_t* payload)
|
||||||
|
|
||||||
void rrc::rl_failure(uint16_t rnti)
|
void rrc::rl_failure(uint16_t rnti)
|
||||||
{
|
{
|
||||||
rrc_log->info("Radio-Link failure detected rnti=0x%x\n", rnti);
|
rrc_pdu p = {rnti, LCID_RLF_USER, NULL};
|
||||||
if (s1ap->user_exists(rnti)) {
|
rx_pdu_queue.push(p);
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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)
|
void rrc::add_user(uint16_t rnti)
|
||||||
{
|
{
|
||||||
pthread_mutex_lock(&user_mutex);
|
pthread_mutex_lock(&user_mutex);
|
||||||
|
@ -302,46 +190,17 @@ void rrc::add_user(uint16_t rnti)
|
||||||
pthread_mutex_unlock(&user_mutex);
|
pthread_mutex_unlock(&user_mutex);
|
||||||
}
|
}
|
||||||
|
|
||||||
void rrc::rem_user(uint16_t rnti)
|
/* Function called by MAC after the reception of a C-RNTI CE indicating that the UE still has a
|
||||||
{
|
* valid RNTI.
|
||||||
pthread_mutex_lock(&user_mutex);
|
* Called by MAC reader thread (can wait to process)
|
||||||
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);
|
|
||||||
}
|
|
||||||
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)
|
void rrc::upd_user(uint16_t new_rnti, uint16_t old_rnti)
|
||||||
{
|
{
|
||||||
// Remove new_rnti
|
// Remove new_rnti
|
||||||
rem_user_thread(new_rnti);
|
rem_user_thread(new_rnti);
|
||||||
|
|
||||||
// Send Reconfiguration to old_rnti if is RRC_CONNECT or RRC Release if already released here
|
// 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.count(old_rnti) == 1) {
|
||||||
if (users[old_rnti].is_connected()) {
|
if (users[old_rnti].is_connected()) {
|
||||||
users[old_rnti].send_connection_reconf_upd(pool_allocate);
|
users[old_rnti].send_connection_reconf_upd(pool_allocate);
|
||||||
|
@ -349,31 +208,10 @@ void rrc::upd_user(uint16_t new_rnti, uint16_t old_rnti)
|
||||||
users[old_rnti].send_connection_release();
|
users[old_rnti].send_connection_release();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
pthread_mutex_unlock(&user_mutex);
|
||||||
}
|
}
|
||||||
|
|
||||||
void rrc::set_activity_user(uint16_t rnti)
|
|
||||||
{
|
|
||||||
if (users.count(rnti) == 1) {
|
|
||||||
users[rnti].set_activity();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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
|
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;
|
LIBLTE_RRC_DL_DCCH_MSG_STRUCT dl_dcch_msg;
|
||||||
bzero(&dl_dcch_msg, sizeof(LIBLTE_RRC_DL_DCCH_MSG_STRUCT));
|
bzero(&dl_dcch_msg, sizeof(LIBLTE_RRC_DL_DCCH_MSG_STRUCT));
|
||||||
|
|
||||||
|
pthread_mutex_lock(&user_mutex);
|
||||||
|
|
||||||
if (users.count(rnti) == 1) {
|
if (users.count(rnti) == 1) {
|
||||||
dl_dcch_msg.msg_type = LIBLTE_RRC_DL_DCCH_MSG_TYPE_DL_INFO_TRANSFER;
|
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);
|
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 {
|
} else {
|
||||||
rrc_log->error("Rx SDU for unknown rnti=0x%x\n", rnti);
|
rrc_log->error("Rx SDU for unknown rnti=0x%x\n", rnti);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pthread_mutex_unlock(&user_mutex);
|
||||||
}
|
}
|
||||||
|
|
||||||
void rrc::release_complete(uint16_t rnti)
|
void rrc::release_complete(uint16_t rnti) {
|
||||||
{
|
rrc_pdu p = {rnti, LCID_REL_USER, NULL};
|
||||||
rrc_log->info("Received Release Complete rnti=0x%x\n", rnti);
|
rx_pdu_queue.push(p);
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool rrc::setup_ue_ctxt(uint16_t rnti, LIBLTE_S1AP_MESSAGE_INITIALCONTEXTSETUPREQUEST_STRUCT *msg)
|
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);
|
rrc_log->info("Adding initial context for 0x%x\n", rnti);
|
||||||
|
|
||||||
if(users.count(rnti) == 0) {
|
if(users.count(rnti) == 0) {
|
||||||
rrc_log->warning("Unrecognised rnti: 0x%x\n", rnti);
|
rrc_log->warning("Unrecognised rnti: 0x%x\n", rnti);
|
||||||
|
pthread_mutex_unlock(&user_mutex);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -488,15 +322,20 @@ bool rrc::setup_ue_ctxt(uint16_t rnti, LIBLTE_S1AP_MESSAGE_INITIALCONTEXTSETUPRE
|
||||||
// Setup E-RABs
|
// Setup E-RABs
|
||||||
users[rnti].setup_erabs(&msg->E_RABToBeSetupListCtxtSUReq);
|
users[rnti].setup_erabs(&msg->E_RABToBeSetupListCtxtSUReq);
|
||||||
|
|
||||||
|
pthread_mutex_unlock(&user_mutex);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool rrc::setup_ue_erabs(uint16_t rnti, LIBLTE_S1AP_MESSAGE_E_RABSETUPREQUEST_STRUCT *msg)
|
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);
|
rrc_log->info("Setting up erab(s) for 0x%x\n", rnti);
|
||||||
|
|
||||||
if(users.count(rnti) == 0) {
|
if(users.count(rnti) == 0) {
|
||||||
rrc_log->warning("Unrecognised rnti: 0x%x\n", rnti);
|
rrc_log->warning("Unrecognised rnti: 0x%x\n", rnti);
|
||||||
|
pthread_mutex_unlock(&user_mutex);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -508,21 +347,35 @@ bool rrc::setup_ue_erabs(uint16_t rnti, LIBLTE_S1AP_MESSAGE_E_RABSETUPREQUEST_ST
|
||||||
// Setup E-RABs
|
// Setup E-RABs
|
||||||
users[rnti].setup_erabs(&msg->E_RABToBeSetupListBearerSUReq);
|
users[rnti].setup_erabs(&msg->E_RABToBeSetupListBearerSUReq);
|
||||||
|
|
||||||
|
pthread_mutex_unlock(&user_mutex);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool rrc::release_erabs(uint32_t rnti)
|
bool rrc::release_erabs(uint32_t rnti)
|
||||||
{
|
{
|
||||||
|
pthread_mutex_lock(&user_mutex);
|
||||||
rrc_log->info("Releasing E-RABs for 0x%x\n", rnti);
|
rrc_log->info("Releasing E-RABs for 0x%x\n", rnti);
|
||||||
|
|
||||||
if(users.count(rnti) == 0) {
|
if(users.count(rnti) == 0) {
|
||||||
rrc_log->warning("Unrecognised rnti: 0x%x\n", rnti);
|
rrc_log->warning("Unrecognised rnti: 0x%x\n", rnti);
|
||||||
|
pthread_mutex_unlock(&user_mutex);
|
||||||
return false;
|
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)
|
void rrc::add_paging_id(uint32_t ueid, LIBLTE_S1AP_UEPAGINGID_STRUCT UEPagingID)
|
||||||
{
|
{
|
||||||
pthread_mutex_lock(&paging_mutex);
|
pthread_mutex_lock(&paging_mutex);
|
||||||
|
@ -615,17 +468,21 @@ bool rrc::is_paging_opportunity(uint32_t tti, uint32_t *payload_len)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void rrc::read_pdu_pcch(uint8_t *payload, uint32_t buffer_size)
|
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;
|
uint32_t N_bytes = (bit_buf_paging.N_bits-1)/8+1;
|
||||||
if (N_bytes <= buffer_size) {
|
if (N_bytes <= buffer_size) {
|
||||||
srslte_bit_pack_vector(bit_buf_paging.msg, payload, bit_buf_paging.N_bits);
|
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)
|
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)) {
|
if (users.count(old_rnti)) {
|
||||||
rrc_log->error("Not supported: ConnectionReestablishment for rnti=0x%x. Sending Connection Reject\n", old_rnti);
|
rrc_log->error("Not supported: ConnectionReestablishment for rnti=0x%x. Sending Connection Reject\n", old_rnti);
|
||||||
users[rnti].send_connection_reest_rej();
|
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 {
|
} else {
|
||||||
rrc_log->error("Received ConnectionReestablishment for rnti=0x%x without context\n", old_rnti);
|
rrc_log->error("Received ConnectionReestablishment for rnti=0x%x without context\n", old_rnti);
|
||||||
users[rnti].send_connection_reest_rej();
|
users[rnti].send_connection_reest_rej();
|
||||||
}
|
}
|
||||||
// remove temporal rnti
|
// 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);
|
rem_user_thread(rnti);
|
||||||
} else {
|
} else {
|
||||||
rrc_log->error("Received ReestablishmentRequest from an rnti=0x%x not in IDLE\n", rnti);
|
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;i<nof_si_messages;i++) {
|
||||||
|
sched_cfg.sibs[i].len = sib_buffer[i].N_bytes;
|
||||||
|
if (i == 0) {
|
||||||
|
sched_cfg.sibs[i].period_rf = 8; // SIB1 is always 8 rf
|
||||||
|
} else {
|
||||||
|
sched_cfg.sibs[i].period_rf = liblte_rrc_si_periodicity_num[cfg.sibs[0].sib.sib1.sched_info[i-1].si_periodicity];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
sched_cfg.si_window_ms = liblte_rrc_si_window_length_num[cfg.sibs[0].sib.sib1.si_window_length];
|
||||||
|
sched_cfg.prach_rar_window = liblte_rrc_ra_response_window_size_num[cfg.sibs[1].sib.sib2.rr_config_common_sib.rach_cnfg.ra_resp_win_size];
|
||||||
|
sched_cfg.maxharq_msg3tx = cfg.sibs[1].sib.sib2.rr_config_common_sib.rach_cnfg.max_harq_msg3_tx;
|
||||||
|
|
||||||
|
// Copy Cell configuration
|
||||||
|
memcpy(&sched_cfg.cell, &cfg.cell, sizeof(srslte_cell_t));
|
||||||
|
|
||||||
|
// Configure MAC scheduler
|
||||||
|
mac->cell_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
|
RRC thread
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
|
@ -709,6 +771,8 @@ void rrc::run_thread()
|
||||||
if (p.pdu) {
|
if (p.pdu) {
|
||||||
rrc_log->info_hex(p.pdu->msg, p.pdu->N_bytes, "Rx %s PDU", rb_id_text[p.lcid]);
|
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);
|
pthread_mutex_lock(&user_mutex);
|
||||||
if (users.count(p.rnti) == 1) {
|
if (users.count(p.rnti) == 1) {
|
||||||
switch(p.lcid)
|
switch(p.lcid)
|
||||||
|
@ -721,10 +785,18 @@ void rrc::run_thread()
|
||||||
parse_ul_dcch(p.rnti, p.lcid, p.pdu);
|
parse_ul_dcch(p.rnti, p.lcid, p.pdu);
|
||||||
break;
|
break;
|
||||||
case LCID_REM_USER:
|
case LCID_REM_USER:
|
||||||
pthread_mutex_unlock(&user_mutex);
|
|
||||||
usleep(10000);
|
|
||||||
rem_user(p.rnti);
|
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;
|
break;
|
||||||
default:
|
default:
|
||||||
rrc_log->error("Rx PDU with invalid bearer id: %d", p.lcid);
|
rrc_log->error("Rx PDU with invalid bearer id: %d", p.lcid);
|
||||||
|
@ -737,6 +809,28 @@ void rrc::run_thread()
|
||||||
pthread_mutex_unlock(&user_mutex);
|
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()
|
void rrc::activity_monitor::run_thread()
|
||||||
{
|
{
|
||||||
while(running)
|
while(running)
|
||||||
|
@ -760,40 +854,27 @@ void rrc::activity_monitor::run_thread()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pthread_mutex_unlock(&parent->user_mutex);
|
|
||||||
if (rem_rnti) {
|
if (rem_rnti) {
|
||||||
if (parent->s1ap->user_exists(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 {
|
} else {
|
||||||
if(rem_rnti != SRSLTE_MRNTI)
|
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
|
UE class
|
||||||
|
|
||||||
|
Every function in UE class is called from a mutex environment thus does not
|
||||||
|
need extra protection.
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
rrc::ue::ue()
|
rrc::ue::ue()
|
||||||
{
|
{
|
||||||
|
@ -812,6 +893,7 @@ rrc::ue::ue()
|
||||||
cqi_idx = 0;
|
cqi_idx = 0;
|
||||||
cqi_sched_sf_idx = 0;
|
cqi_sched_sf_idx = 0;
|
||||||
cqi_sched_prb_idx = 0;
|
cqi_sched_prb_idx = 0;
|
||||||
|
rlf_cnt = 0;
|
||||||
state = RRC_STATE_IDLE;
|
state = RRC_STATE_IDLE;
|
||||||
pool = srslte::byte_buffer_pool::get_instance();
|
pool = srslte::byte_buffer_pool::get_instance();
|
||||||
}
|
}
|
||||||
|
@ -821,6 +903,11 @@ rrc_state_t rrc::ue::get_state()
|
||||||
return state;
|
return state;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint32_t rrc::ue::rl_failure() {
|
||||||
|
rlf_cnt++;
|
||||||
|
return rlf_cnt;
|
||||||
|
}
|
||||||
|
|
||||||
void rrc::ue::set_activity()
|
void rrc::ue::set_activity()
|
||||||
{
|
{
|
||||||
gettimeofday(&t_last_activity, NULL);
|
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;
|
rr_cfg = &dl_ccch_msg.msg.rrc_con_reest.rr_cnfg;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Add SRB1 to cfg
|
// Add SRB1 to cfg
|
||||||
rr_cfg->srb_to_add_mod_list_size = 1;
|
rr_cfg->srb_to_add_mod_list_size = 1;
|
||||||
rr_cfg->srb_to_add_mod_list[0].srb_id = 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);
|
send_dl_ccch(&dl_ccch_msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void rrc::ue::send_connection_reest()
|
void rrc::ue::send_connection_reest()
|
||||||
{
|
{
|
||||||
send_connection_setup(false);
|
send_connection_setup(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void rrc::ue::send_connection_release()
|
void rrc::ue::send_connection_release()
|
||||||
{
|
{
|
||||||
LIBLTE_RRC_DL_DCCH_MSG_STRUCT dl_dcch_msg;
|
LIBLTE_RRC_DL_DCCH_MSG_STRUCT dl_dcch_msg;
|
||||||
|
@ -1793,7 +1877,6 @@ int rrc::ue::sr_allocate(uint32_t period, uint32_t *I_sr, uint32_t *N_pucch_sr)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int rrc::ue::cqi_free()
|
int rrc::ue::cqi_free()
|
||||||
{
|
{
|
||||||
if (cqi_allocated) {
|
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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -204,54 +204,30 @@ void s1ap::write_pdu(uint16_t rnti, srslte::byte_buffer_t *pdu)
|
||||||
send_ulnastransport(rnti, 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);
|
s1ap_log->info("User inactivity - RNTI:0x%x\n", rnti);
|
||||||
|
|
||||||
if(ue_ctxt_map.end() == ue_ctxt_map.find(rnti)) {
|
if(ue_ctxt_map.end() == ue_ctxt_map.find(rnti)) {
|
||||||
s1ap_log->warning("User RNTI:0x%x context not found\n", rnti);
|
s1ap_log->warning("User RNTI:0x%x context not found\n", rnti);
|
||||||
return;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(ue_ctxt_map[rnti].release_requested) {
|
if(ue_ctxt_map[rnti].release_requested) {
|
||||||
s1ap_log->warning("UE context for RNTI:0x%x is in zombie state. Releasing...\n", rnti);
|
s1ap_log->warning("UE context for RNTI:0x%x is in zombie state. Releasing...\n", rnti);
|
||||||
ue_ctxt_map.erase(rnti);
|
ue_ctxt_map.erase(rnti);
|
||||||
rrc->release_complete(rnti);
|
rrc->release_complete(rnti);
|
||||||
return;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
LIBLTE_S1AP_CAUSE_STRUCT cause;
|
LIBLTE_S1AP_CAUSE_STRUCT cause;
|
||||||
cause.ext = false;
|
cause.ext = false;
|
||||||
cause.choice_type = LIBLTE_S1AP_CAUSE_CHOICE_RADIONETWORK;
|
cause.choice_type = LIBLTE_S1AP_CAUSE_CHOICE_RADIONETWORK;
|
||||||
cause.choice.radioNetwork.ext = false;
|
cause.choice.radioNetwork.ext = false;
|
||||||
cause.choice.radioNetwork.e = LIBLTE_S1AP_CAUSERADIONETWORK_USER_INACTIVITY;
|
cause.choice.radioNetwork.e = cause_radio;
|
||||||
|
|
||||||
ue_ctxt_map[rnti].release_requested = true;
|
ue_ctxt_map[rnti].release_requested = true;
|
||||||
send_uectxtreleaserequest(rnti, &cause);
|
return 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;
|
|
||||||
}
|
|
||||||
|
|
||||||
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;
|
|
||||||
|
|
||||||
ue_ctxt_map[rnti].release_requested = true;
|
|
||||||
send_uectxtreleaserequest(rnti, &cause);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool s1ap::user_exists(uint16_t rnti)
|
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);
|
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)
|
void s1ap::ue_ctxt_setup_complete(uint16_t rnti, LIBLTE_S1AP_MESSAGE_INITIALCONTEXTSETUPRESPONSE_STRUCT *res)
|
||||||
{
|
{
|
||||||
if(res->E_RABSetupListCtxtSURes.len > 0) {
|
if(res->E_RABSetupListCtxtSURes.len > 0) {
|
||||||
|
|
|
@ -529,7 +529,7 @@ void nas::cipher_decrypt(byte_buffer_t *pdu)
|
||||||
memcpy(&pdu->msg[6], &tmp_pdu.msg[6], pdu->N_bytes-6);
|
memcpy(&pdu->msg[6], &tmp_pdu.msg[6], pdu->N_bytes-6);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
nas_log->error("Ciphering algorithmus not known\n");
|
nas_log->error("Ciphering algorithms not known\n");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -83,5 +83,5 @@ int main(int argc, char **argv)
|
||||||
srsue::usim usim;
|
srsue::usim usim;
|
||||||
usim.init(&args, &usim_log);
|
usim.init(&args, &usim_log);
|
||||||
|
|
||||||
assert(usim.generate_authentication_response(rand_enb, autn_enb, mcc, mnc, res, &res_len, k_asme) == AUTH_OK);
|
//assert(usim.generate_authentication_response(rand_enb, autn_enb, mcc, mnc, res, &res_len, k_asme) == AUTH_OK);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue