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 release_eutran(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_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;

@ -97,9 +97,19 @@ public:
class nas_interface_rrc
{
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_attaching() = 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 uint32_t get_ul_count() = 0;
virtual bool get_s_tmsi(LIBLTE_RRC_S_TMSI_STRUCT *s_tmsi) = 0;

@ -172,6 +172,7 @@ public:
rrc_state_t get_state();
void send_connection_setup(bool is_setup = true);
void send_connection_rej();
void send_connection_reest();
void send_connection_release();
void send_connection_reest_rej();

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

@ -834,13 +834,19 @@ void rrc::ue::handle_rrc_con_req(LIBLTE_RRC_CONNECTION_REQUEST_STRUCT *msg)
{
set_activity();
if(msg->ue_id_type == LIBLTE_RRC_CON_REQ_UE_ID_TYPE_S_TMSI) {
mmec = msg->ue_id.s_tmsi.mmec;
m_tmsi = msg->ue_id.s_tmsi.m_tmsi;
has_tmsi = true;
if (parent->s1ap->is_connected()) {
if(msg->ue_id_type == LIBLTE_RRC_CON_REQ_UE_ID_TYPE_S_TMSI) {
mmec = msg->ue_id.s_tmsi.mmec;
m_tmsi = msg->ue_id.s_tmsi.m_tmsi;
has_tmsi = true;
}
send_connection_setup();
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();
}
send_connection_setup();
state = RRC_STATE_WAIT_FOR_CON_SETUP_COMPLETE;
}
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)
{
LIBLTE_RRC_DL_CCCH_MSG_STRUCT dl_ccch_msg;

@ -170,6 +170,11 @@ void s1ap::build_tai_cgi()
/*******************************************************************************
/* RRC interface
********************************************************************************/
bool s1ap::is_connected() {
return mme_connected;
}
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++;
@ -226,7 +231,6 @@ void s1ap::user_inactivity(uint16_t rnti)
send_uectxtreleaserequest(rnti, &cause);
}
void s1ap::release_eutran(uint16_t rnti)
{
s1ap_log->info("Release by EUTRAN - RNTI:0x%x\n", rnti);

@ -80,6 +80,9 @@ public:
// RRC interface
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);
@ -135,6 +138,9 @@ private:
uint8_t k_nas_enc[32];
uint8_t k_nas_int[32];
bool network_is_barred;
uint32_t network_barring_type;
srslte::CIPHERING_ALGORITHM_ID_ENUM cipher_algo;
srslte::INTEGRITY_ALGORITHM_ID_ENUM integ_algo;

@ -127,7 +127,7 @@ private:
srslte::mac_interface_timers *mac_timers;
uint32_t n310_cnt, N310;
uint32_t n311_cnt, N311;
uint32_t t301, t310, t311;
uint32_t t300, t301, t302, t310, t311;
int ue_category;
typedef struct {
@ -240,15 +240,15 @@ private:
// Parsers
void parse_dl_ccch(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
void timer_t300_expiry();
void timer_barring_expiry(uint32_t timer_id);
void rrc_connection_release();
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 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_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);

@ -66,22 +66,27 @@ UE interface
*******************************************************************************/
void nas::attach_request() {
nas_log->info("Attach Request\n");
if (state == EMM_STATE_DEREGISTERED) {
state = EMM_STATE_REGISTERED_INITIATED;
if (plmn_selection == PLMN_NOT_SELECTED) {
nas_log->info("Starting PLMN Search...\n");
rrc->plmn_search();
} else if (plmn_selection == PLMN_SELECTED) {
nas_log->info("Selecting PLMN %s\n", plmn_id_to_c_str(current_plmn).c_str());
if (!network_is_barred) {
if (state == EMM_STATE_DEREGISTERED) {
state = EMM_STATE_REGISTERED_INITIATED;
if (plmn_selection == PLMN_NOT_SELECTED) {
nas_log->info("Starting PLMN Search...\n");
rrc->plmn_search();
} else if (plmn_selection == PLMN_SELECTED) {
nas_log->info("Selecting PLMN %s\n", plmn_id_to_c_str(current_plmn).c_str());
rrc->plmn_select(current_plmn);
selecting_plmn = current_plmn;
}
} else if (state == EMM_STATE_REGISTERED) {
nas_log->info("NAS state is registered, connecting to same PLMN\n");
rrc->plmn_select(current_plmn);
selecting_plmn = current_plmn;
} else {
nas_log->info("Attach request ignored. State = %s\n", emm_state_text[state]);
}
} else if (state == EMM_STATE_REGISTERED) {
nas_log->info("NAS state is registered, connecting to same PLMN\n");
rrc->plmn_select(current_plmn);
selecting_plmn = current_plmn;
} else {
nas_log->info("Attach request ignored. State = %s\n", emm_state_text[state]);
nas_log->info("Requested connection while network is barred\n");
nas_log->console("Requested connection while network is barred\n");
}
}
@ -94,6 +99,12 @@ void nas::deattach_request() {
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) {
// Store PLMN if not registered
@ -125,6 +136,12 @@ bool nas::is_attaching() {
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() {
nas_log->debug("State = %s\n", emm_state_text[state]);
if (EMM_STATE_REGISTERED_INITIATED == state) {

@ -93,7 +93,9 @@ void rrc::init(phy_interface_rrc *phy_,
pthread_mutex_init(&mutex, NULL);
ue_category = SRSLTE_UE_CATEGORY;
t300 = 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();
t311 = mac_timers->timer_get_unique_id();
@ -538,14 +540,20 @@ void rrc::max_retx_attempted() {
}
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");
radio_link_failure();
} else if (timeout_id == t311) {
rrc_log->info("Timer T311 expired: Going to RRC IDLE\n");
state = RRC_STATE_LEAVE_CONNECTED;
} else if (timeout_id == t301) {
rrc_log->info("Timer T301 expired: Going to RRC IDLE\n");
rrc_log->info("Timer T311 expired: Start of Reestablishment procedure timeout\n");
state = RRC_STATE_LEAVE_CONNECTED;
} else {
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);
// 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");
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->set_timestamp();
state = RRC_STATE_CONNECTED;
rrc_log->console("RRC Connected\n");
rrc_log->info("Sending RRC Connection Setup Complete\n");
pdcp->write_sdu(RB_ID_SRB1, pdcp_buf);
@ -857,13 +868,25 @@ void rrc::handle_rrc_con_reconfig(uint32_t lcid, LIBLTE_RRC_CONNECTION_RECONFIGU
}
}
/* Actions upon reception of RRCConnectionRelease 5.3.8.3 */
/* Actions upon reception of RRCConnectionRelease 5.3.8.3 */
void rrc::rrc_connection_release() {
// Save idleModeMobilityControlInfo, etc.
state = RRC_STATE_LEAVE_CONNECTED;
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) {
case LIBLTE_RRC_DL_CCCH_MSG_TYPE_RRC_CON_REJ:
rrc_log->info("Connection Reject received. Wait time: %d\n",
dl_ccch_msg.msg.rrc_con_rej.wait_time);
state = RRC_STATE_IDLE;
transaction_id = dl_ccch_msg.msg.rrc_con_setup.rrc_transaction_id;
handle_con_rej(&dl_ccch_msg.msg.rrc_con_rej);
break;
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;
handle_con_setup(&dl_ccch_msg.msg.rrc_con_setup);
rrc_log->info("Notifying NAS of connection setup\n");
nas->notify_connection_setup();
break;
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;
handle_con_reest(&dl_ccch_msg.msg.rrc_con_reest);
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],
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(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]);
N310 = liblte_rrc_n310_num[sib2->ue_timers_and_constants.n310];
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) {
rrc_log->info("Connection Setup received\n");
// Apply the Radio Resource configuration
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 */
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();
// TODO: Restablish DRB1. Not done because never was suspended

Loading…
Cancel
Save