Handle RRC ConnectionReject at eNodeB and UE

master
Ismael Gomez 7 years ago
parent 839099d8d3
commit b6f905e2df

@ -260,6 +260,7 @@ public:
virtual void user_inactivity(uint16_t rnti) = 0; virtual void user_inactivity(uint16_t rnti) = 0;
virtual void release_eutran(uint16_t rnti) = 0; virtual void release_eutran(uint16_t rnti) = 0;
virtual bool user_link_lost(uint16_t rnti) = 0; virtual bool user_link_lost(uint16_t rnti) = 0;
virtual bool is_connected() = 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;

@ -97,9 +97,19 @@ public:
class nas_interface_rrc class nas_interface_rrc
{ {
public: public:
typedef enum {
BARRING_MT_ACCESS = 1,
BARRING_MO_CALL = 2,
BARRING_MO_SIGNALLING = 4,
BARRING_ALL = 7
} cell_barring_type_t;
virtual bool is_attached() = 0; virtual bool is_attached() = 0;
virtual bool is_attaching() = 0; virtual bool is_attaching() = 0;
virtual void notify_connection_setup() = 0; virtual void notify_connection_setup() = 0;
virtual void notify_connection_failure() = 0;
virtual void network_barring_state(bool is_barred, uint32_t type_mask = BARRING_ALL) = 0;
virtual void write_pdu(uint32_t lcid, srslte::byte_buffer_t *pdu) = 0; virtual void write_pdu(uint32_t lcid, srslte::byte_buffer_t *pdu) = 0;
virtual uint32_t get_ul_count() = 0; virtual uint32_t get_ul_count() = 0;
virtual bool get_s_tmsi(LIBLTE_RRC_S_TMSI_STRUCT *s_tmsi) = 0; virtual bool get_s_tmsi(LIBLTE_RRC_S_TMSI_STRUCT *s_tmsi) = 0;

@ -172,6 +172,7 @@ public:
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);
void send_connection_rej();
void send_connection_reest(); void send_connection_reest();
void send_connection_release(); void send_connection_release();
void send_connection_reest_rej(); void send_connection_reest_rej();

@ -80,6 +80,7 @@ public:
void user_inactivity(uint16_t rnti); void user_inactivity(uint16_t rnti);
bool user_link_lost(uint16_t rnti); bool user_link_lost(uint16_t rnti);
void release_eutran(uint16_t rnti); void release_eutran(uint16_t rnti);
bool is_connected();
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);

@ -834,6 +834,7 @@ void rrc::ue::handle_rrc_con_req(LIBLTE_RRC_CONNECTION_REQUEST_STRUCT *msg)
{ {
set_activity(); set_activity();
if (parent->s1ap->is_connected()) {
if(msg->ue_id_type == LIBLTE_RRC_CON_REQ_UE_ID_TYPE_S_TMSI) { if(msg->ue_id_type == LIBLTE_RRC_CON_REQ_UE_ID_TYPE_S_TMSI) {
mmec = msg->ue_id.s_tmsi.mmec; mmec = msg->ue_id.s_tmsi.mmec;
m_tmsi = msg->ue_id.s_tmsi.m_tmsi; m_tmsi = msg->ue_id.s_tmsi.m_tmsi;
@ -841,6 +842,11 @@ void rrc::ue::handle_rrc_con_req(LIBLTE_RRC_CONNECTION_REQUEST_STRUCT *msg)
} }
send_connection_setup(); send_connection_setup();
state = RRC_STATE_WAIT_FOR_CON_SETUP_COMPLETE; state = RRC_STATE_WAIT_FOR_CON_SETUP_COMPLETE;
} else {
parent->rrc_log->info("Received ConnectionRequest with no active S1 link\n");
parent->rrc_log->console("Received ConnectionRequest with no active S1 link\n");
send_connection_rej();
}
} }
void rrc::ue::handle_rrc_con_reest_req(LIBLTE_RRC_CONNECTION_REESTABLISHMENT_REQUEST_STRUCT *msg) void rrc::ue::handle_rrc_con_reest_req(LIBLTE_RRC_CONNECTION_REESTABLISHMENT_REQUEST_STRUCT *msg)
@ -1054,6 +1060,16 @@ void rrc::ue::send_connection_reest_rej()
} }
void rrc::ue::send_connection_rej()
{
LIBLTE_RRC_DL_CCCH_MSG_STRUCT dl_ccch_msg;
bzero(&dl_ccch_msg, sizeof(LIBLTE_RRC_DL_CCCH_MSG_STRUCT));
dl_ccch_msg.msg_type = LIBLTE_RRC_DL_CCCH_MSG_TYPE_RRC_CON_REJ;
dl_ccch_msg.msg.rrc_con_rej.wait_time = 10;
send_dl_ccch(&dl_ccch_msg);
}
void rrc::ue::send_connection_setup(bool is_setup) void rrc::ue::send_connection_setup(bool is_setup)
{ {
LIBLTE_RRC_DL_CCCH_MSG_STRUCT dl_ccch_msg; LIBLTE_RRC_DL_CCCH_MSG_STRUCT dl_ccch_msg;

@ -170,6 +170,11 @@ void s1ap::build_tai_cgi()
/******************************************************************************* /*******************************************************************************
/* RRC interface /* RRC interface
********************************************************************************/ ********************************************************************************/
bool s1ap::is_connected() {
return mme_connected;
}
void s1ap::initial_ue(uint16_t rnti, srslte::byte_buffer_t *pdu) void s1ap::initial_ue(uint16_t rnti, srslte::byte_buffer_t *pdu)
{ {
ue_ctxt_map[rnti].eNB_UE_S1AP_ID = next_eNB_UE_S1AP_ID++; ue_ctxt_map[rnti].eNB_UE_S1AP_ID = next_eNB_UE_S1AP_ID++;
@ -226,7 +231,6 @@ void s1ap::user_inactivity(uint16_t rnti)
send_uectxtreleaserequest(rnti, &cause); send_uectxtreleaserequest(rnti, &cause);
} }
void s1ap::release_eutran(uint16_t rnti) void s1ap::release_eutran(uint16_t rnti)
{ {
s1ap_log->info("Release by EUTRAN - RNTI:0x%x\n", rnti); s1ap_log->info("Release by EUTRAN - RNTI:0x%x\n", rnti);

@ -80,6 +80,9 @@ public:
// RRC interface // RRC interface
void notify_connection_setup(); void notify_connection_setup();
void notify_connection_failure();
void network_barring_state(bool is_barred, uint32_t type_mask);
void write_pdu(uint32_t lcid, byte_buffer_t *pdu); void write_pdu(uint32_t lcid, byte_buffer_t *pdu);
@ -135,6 +138,9 @@ private:
uint8_t k_nas_enc[32]; uint8_t k_nas_enc[32];
uint8_t k_nas_int[32]; uint8_t k_nas_int[32];
bool network_is_barred;
uint32_t network_barring_type;
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;

@ -127,7 +127,7 @@ private:
srslte::mac_interface_timers *mac_timers; srslte::mac_interface_timers *mac_timers;
uint32_t n310_cnt, N310; uint32_t n310_cnt, N310;
uint32_t n311_cnt, N311; uint32_t n311_cnt, N311;
uint32_t t301, t310, t311; uint32_t t300, t301, t302, t310, t311;
int ue_category; int ue_category;
typedef struct { typedef struct {
@ -240,15 +240,15 @@ private:
// Parsers // Parsers
void parse_dl_ccch(byte_buffer_t *pdu); void parse_dl_ccch(byte_buffer_t *pdu);
void parse_dl_dcch(uint32_t lcid, byte_buffer_t *pdu); void parse_dl_dcch(uint32_t lcid, byte_buffer_t *pdu);
void parse_dl_info_transfer(uint32_t lcid, byte_buffer_t *pdu);
// Helpers // Helpers
void timer_t300_expiry();
void timer_barring_expiry(uint32_t timer_id);
void rrc_connection_release(); void rrc_connection_release();
void radio_link_failure(); void radio_link_failure();
static void* start_sib_thread(void *rrc_);
void sib_search();
void apply_sib2_configs(LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_2_STRUCT *sib2); void apply_sib2_configs(LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_2_STRUCT *sib2);
void handle_con_setup(LIBLTE_RRC_CONNECTION_SETUP_STRUCT *setup); void handle_con_setup(LIBLTE_RRC_CONNECTION_SETUP_STRUCT *setup);
void handle_con_rej(LIBLTE_RRC_CONNECTION_REJECT_STRUCT *reject);
void handle_con_reest(LIBLTE_RRC_CONNECTION_REESTABLISHMENT_STRUCT *setup); void handle_con_reest(LIBLTE_RRC_CONNECTION_REESTABLISHMENT_STRUCT *setup);
void handle_rrc_con_reconfig(uint32_t lcid, LIBLTE_RRC_CONNECTION_RECONFIGURATION_STRUCT *reconfig, byte_buffer_t *pdu); void handle_rrc_con_reconfig(uint32_t lcid, LIBLTE_RRC_CONNECTION_RECONFIGURATION_STRUCT *reconfig, byte_buffer_t *pdu);
void add_srb(LIBLTE_RRC_SRB_TO_ADD_MOD_STRUCT *srb_cnfg); void add_srb(LIBLTE_RRC_SRB_TO_ADD_MOD_STRUCT *srb_cnfg);

@ -66,6 +66,7 @@ UE interface
*******************************************************************************/ *******************************************************************************/
void nas::attach_request() { void nas::attach_request() {
nas_log->info("Attach Request\n"); nas_log->info("Attach Request\n");
if (!network_is_barred) {
if (state == EMM_STATE_DEREGISTERED) { if (state == EMM_STATE_DEREGISTERED) {
state = EMM_STATE_REGISTERED_INITIATED; state = EMM_STATE_REGISTERED_INITIATED;
if (plmn_selection == PLMN_NOT_SELECTED) { if (plmn_selection == PLMN_NOT_SELECTED) {
@ -83,6 +84,10 @@ void nas::attach_request() {
} else { } else {
nas_log->info("Attach request ignored. State = %s\n", emm_state_text[state]); nas_log->info("Attach request ignored. State = %s\n", emm_state_text[state]);
} }
} else {
nas_log->info("Requested connection while network is barred\n");
nas_log->console("Requested connection while network is barred\n");
}
} }
void nas::deattach_request() { void nas::deattach_request() {
@ -94,6 +99,12 @@ void nas::deattach_request() {
RRC interface RRC interface
*******************************************************************************/ *******************************************************************************/
void nas::network_barring_state(bool is_barred, uint32_t type_mask)
{
network_is_barred = is_barred;
network_barring_type = type_mask;
}
void nas::plmn_found(LIBLTE_RRC_PLMN_IDENTITY_STRUCT plmn_id, uint16_t tracking_area_code) { void nas::plmn_found(LIBLTE_RRC_PLMN_IDENTITY_STRUCT plmn_id, uint16_t tracking_area_code) {
// Store PLMN if not registered // Store PLMN if not registered
@ -125,6 +136,12 @@ bool nas::is_attaching() {
return state == EMM_STATE_REGISTERED_INITIATED; return state == EMM_STATE_REGISTERED_INITIATED;
} }
void nas::notify_connection_failure() {
nas_log->info("Received RRC connection request failure\n");
nas_log->console("Connection Request Failure\n");
state = EMM_STATE_DEREGISTERED;
}
void nas::notify_connection_setup() { void nas::notify_connection_setup() {
nas_log->debug("State = %s\n", emm_state_text[state]); nas_log->debug("State = %s\n", emm_state_text[state]);
if (EMM_STATE_REGISTERED_INITIATED == state) { if (EMM_STATE_REGISTERED_INITIATED == state) {

@ -93,7 +93,9 @@ void rrc::init(phy_interface_rrc *phy_,
pthread_mutex_init(&mutex, NULL); pthread_mutex_init(&mutex, NULL);
ue_category = SRSLTE_UE_CATEGORY; ue_category = SRSLTE_UE_CATEGORY;
t300 = mac_timers->timer_get_unique_id();
t301 = mac_timers->timer_get_unique_id(); t301 = mac_timers->timer_get_unique_id();
t302 = mac_timers->timer_get_unique_id();
t310 = mac_timers->timer_get_unique_id(); t310 = mac_timers->timer_get_unique_id();
t311 = mac_timers->timer_get_unique_id(); t311 = mac_timers->timer_get_unique_id();
@ -538,14 +540,20 @@ void rrc::max_retx_attempted() {
} }
void rrc::timer_expired(uint32_t timeout_id) { void rrc::timer_expired(uint32_t timeout_id) {
if (timeout_id == t310) { if (timeout_id == t300) {
rrc_log->info("Timer T300 expired: ConnectionRequest timeout\n");
timer_t300_expiry();
} else if (timeout_id == t301) {
rrc_log->info("Timer T301 expired: ConnectionReestablishmentRequest timeout\n");
state = RRC_STATE_LEAVE_CONNECTED;
} else if (timeout_id == t302) {
rrc_log->info("Timer T302 expired: ConnectionReject Wait time expired\n");
timer_barring_expiry(timeout_id);
} else if (timeout_id == t310) {
rrc_log->info("Timer T310 expired: Radio Link Failure\n"); rrc_log->info("Timer T310 expired: Radio Link Failure\n");
radio_link_failure(); radio_link_failure();
} else if (timeout_id == t311) { } else if (timeout_id == t311) {
rrc_log->info("Timer T311 expired: Going to RRC IDLE\n"); rrc_log->info("Timer T311 expired: Start of Reestablishment procedure timeout\n");
state = RRC_STATE_LEAVE_CONNECTED;
} else if (timeout_id == t301) {
rrc_log->info("Timer T301 expired: Going to RRC IDLE\n");
state = RRC_STATE_LEAVE_CONNECTED; state = RRC_STATE_LEAVE_CONNECTED;
} else { } else {
rrc_log->error("Timeout from unknown timer id %d\n", timeout_id); rrc_log->error("Timeout from unknown timer id %d\n", timeout_id);
@ -608,6 +616,10 @@ void rrc::send_con_request() {
mac->set_contention_id(uecri); mac->set_contention_id(uecri);
// Start t300 timer
mac_timers->timer_get(t300)->reset();
mac_timers->timer_get(t300)->run();
rrc_log->info("Sending RRC Connection Request on SRB0\n"); rrc_log->info("Sending RRC Connection Request on SRB0\n");
pdcp->write_sdu(RB_ID_SRB0, pdcp_buf); pdcp->write_sdu(RB_ID_SRB0, pdcp_buf);
} }
@ -750,7 +762,6 @@ void rrc::send_con_setup_complete(byte_buffer_t *nas_msg) {
pdcp_buf->N_bytes = bit_buf.N_bits / 8; pdcp_buf->N_bytes = bit_buf.N_bits / 8;
pdcp_buf->set_timestamp(); pdcp_buf->set_timestamp();
state = RRC_STATE_CONNECTED;
rrc_log->console("RRC Connected\n"); rrc_log->console("RRC Connected\n");
rrc_log->info("Sending RRC Connection Setup Complete\n"); rrc_log->info("Sending RRC Connection Setup Complete\n");
pdcp->write_sdu(RB_ID_SRB1, pdcp_buf); pdcp->write_sdu(RB_ID_SRB1, pdcp_buf);
@ -864,6 +875,18 @@ void rrc::rrc_connection_release() {
rrc_log->console("Received RRC Connection Release\n"); rrc_log->console("Received RRC Connection Release\n");
} }
// Actions upon expiry of t300 timer 5.3.3.6
void rrc::timer_t300_expiry() {
mac->reset();
set_mac_default();
nas->notify_connection_failure();
state = RRC_STATE_IDLE;
}
// Actions upon expiry of timers related to cell barring 5.3.3.7
void rrc::timer_barring_expiry(uint32_t timer_id) {
nas->network_barring_state(false);
}
@ -1082,20 +1105,14 @@ void rrc::parse_dl_ccch(byte_buffer_t *pdu) {
switch (dl_ccch_msg.msg_type) { switch (dl_ccch_msg.msg_type) {
case LIBLTE_RRC_DL_CCCH_MSG_TYPE_RRC_CON_REJ: case LIBLTE_RRC_DL_CCCH_MSG_TYPE_RRC_CON_REJ:
rrc_log->info("Connection Reject received. Wait time: %d\n", transaction_id = dl_ccch_msg.msg.rrc_con_setup.rrc_transaction_id;
dl_ccch_msg.msg.rrc_con_rej.wait_time); handle_con_rej(&dl_ccch_msg.msg.rrc_con_rej);
state = RRC_STATE_IDLE;
break; break;
case LIBLTE_RRC_DL_CCCH_MSG_TYPE_RRC_CON_SETUP: case LIBLTE_RRC_DL_CCCH_MSG_TYPE_RRC_CON_SETUP:
rrc_log->info("Connection Setup received\n");
transaction_id = dl_ccch_msg.msg.rrc_con_setup.rrc_transaction_id; transaction_id = dl_ccch_msg.msg.rrc_con_setup.rrc_transaction_id;
handle_con_setup(&dl_ccch_msg.msg.rrc_con_setup); handle_con_setup(&dl_ccch_msg.msg.rrc_con_setup);
rrc_log->info("Notifying NAS of connection setup\n");
nas->notify_connection_setup();
break; break;
case LIBLTE_RRC_DL_CCCH_MSG_TYPE_RRC_CON_REEST: case LIBLTE_RRC_DL_CCCH_MSG_TYPE_RRC_CON_REEST:
rrc_log->info("Connection Reestablishment received\n");
rrc_log->console("Reestablishment OK\n");
transaction_id = dl_ccch_msg.msg.rrc_con_reest.rrc_transaction_id; transaction_id = dl_ccch_msg.msg.rrc_con_reest.rrc_transaction_id;
handle_con_reest(&dl_ccch_msg.msg.rrc_con_reest); handle_con_reest(&dl_ccch_msg.msg.rrc_con_reest);
break; break;
@ -1342,9 +1359,11 @@ void rrc::apply_sib2_configs(LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_2_STRUCT *sib2) {
liblte_rrc_srs_subfr_config_num[sib2->rr_config_common_sib.srs_ul_cnfg.subfr_cnfg], liblte_rrc_srs_subfr_config_num[sib2->rr_config_common_sib.srs_ul_cnfg.subfr_cnfg],
sib2->rr_config_common_sib.srs_ul_cnfg.ack_nack_simul_tx ? "yes" : "no"); sib2->rr_config_common_sib.srs_ul_cnfg.ack_nack_simul_tx ? "yes" : "no");
mac_timers->timer_get(t300)->set(this, liblte_rrc_t300_num[sib2->ue_timers_and_constants.t300]);
mac_timers->timer_get(t301)->set(this, liblte_rrc_t301_num[sib2->ue_timers_and_constants.t301]); mac_timers->timer_get(t301)->set(this, liblte_rrc_t301_num[sib2->ue_timers_and_constants.t301]);
mac_timers->timer_get(t310)->set(this, liblte_rrc_t310_num[sib2->ue_timers_and_constants.t310]); mac_timers->timer_get(t310)->set(this, liblte_rrc_t310_num[sib2->ue_timers_and_constants.t310]);
mac_timers->timer_get(t311)->set(this, liblte_rrc_t311_num[sib2->ue_timers_and_constants.t311]); mac_timers->timer_get(t311)->set(this, liblte_rrc_t311_num[sib2->ue_timers_and_constants.t311]);
N310 = liblte_rrc_n310_num[sib2->ue_timers_and_constants.n310]; N310 = liblte_rrc_n310_num[sib2->ue_timers_and_constants.n310];
N311 = liblte_rrc_n311_num[sib2->ue_timers_and_constants.n311]; N311 = liblte_rrc_n311_num[sib2->ue_timers_and_constants.n311];
@ -1581,13 +1600,50 @@ void rrc::apply_rr_config_dedicated(LIBLTE_RRC_RR_CONFIG_DEDICATED_STRUCT *cnfg)
} }
} }
// 5.3.3.4
void rrc::handle_con_setup(LIBLTE_RRC_CONNECTION_SETUP_STRUCT *setup) { void rrc::handle_con_setup(LIBLTE_RRC_CONNECTION_SETUP_STRUCT *setup) {
rrc_log->info("Connection Setup received\n");
// Apply the Radio Resource configuration // Apply the Radio Resource configuration
apply_rr_config_dedicated(&setup->rr_cnfg); apply_rr_config_dedicated(&setup->rr_cnfg);
// stop timers
mac_timers->timer_get(t300)->stop();
// enter RRC CONNECTED
state = RRC_STATE_CONNECTED;
rrc_log->info("Notifying NAS of connection setup\n");
nas->notify_connection_setup();
}
// 5.3.3.8
void rrc::handle_con_rej(LIBLTE_RRC_CONNECTION_REJECT_STRUCT *reject) {
rrc_log->info("Connection Reject received. Wait time: %d s\n",
dl_ccch_msg.msg.rrc_con_rej.wait_time);
rrc_log->console("Received Connection Reject. S1 link may not be active at the eNodeB\n");
mac_timers->timer_get(t300)->stop();
mac->reset();
set_mac_default();
mac_timers->timer_get(t302)->set(this, dl_ccch_msg.msg.rrc_con_rej.wait_time*1000);
mac_timers->timer_get(t302)->run();
nas->notify_connection_failure();
nas->network_barring_state(true);
state = RRC_STATE_IDLE;
} }
/* Reception of RRCConnectionReestablishment by the UE 5.3.7.5 */ /* Reception of RRCConnectionReestablishment by the UE 5.3.7.5 */
void rrc::handle_con_reest(LIBLTE_RRC_CONNECTION_REESTABLISHMENT_STRUCT *setup) { void rrc::handle_con_reest(LIBLTE_RRC_CONNECTION_REESTABLISHMENT_STRUCT *setup) {
rrc_log->info("Connection Reestablishment received\n");
rrc_log->console("Reestablishment OK\n");
mac_timers->timer_get(t301)->stop(); mac_timers->timer_get(t301)->stop();
// TODO: Restablish DRB1. Not done because never was suspended // TODO: Restablish DRB1. Not done because never was suspended

Loading…
Cancel
Save