gnb,rrc: handle RRC reestablishment request

implement basic support for sending RRC reestablishment
master
Andre Puschmann 3 years ago
parent 9bd368e0a9
commit 1616c09335

@ -160,6 +160,9 @@ private:
// TS 38.331, 5.3.3 - RRC connection establishment
void handle_rrc_setup_request(uint16_t rnti, const asn1::rrc_nr::rrc_setup_request_s& msg);
// TS 38.331, 5.3.7 RRC connection reestablishment
void handle_rrc_reest_request(uint16_t rnti, const asn1::rrc_nr::rrc_reest_request_s& msg);
/// This gets called by rrc_nr::sgnb_addition_request and WILL NOT TRIGGER the RX MSG3 activity timer
int add_user(uint16_t rnti, const sched_nr_ue_cfg_t& uecfg, bool start_msg3_timer);

@ -65,6 +65,9 @@ public:
/** TS 38.331 - 5.3.5 RRC reconfiguration */
void handle_rrc_reconfiguration_complete(const asn1::rrc_nr::rrc_recfg_complete_s& msg);
/** TS 38.331 - 5.3.7 RRC connection reestablishment */
void handle_rrc_reest_request(const asn1::rrc_nr::rrc_reest_request_s& msg);
/** TS 38.331 - 5.3.8 Connection Release */
void send_rrc_release();
@ -91,6 +94,9 @@ private:
void send_rrc_setup();
void send_rrc_reject(uint8_t reject_wait_time_secs);
/** TS 38.331 - 5.3.7 RRC connection reestablishment */
void send_connection_reest(uint8_t ncc);
/// Update PDCP bearers based on ASN1 structs passed to the UE
int update_pdcp_bearers(const asn1::rrc_nr::radio_bearer_cfg_s& radio_bearer_diff,
const asn1::rrc_nr::cell_group_cfg_s& cell_group_diff);

@ -483,6 +483,9 @@ void rrc_nr::handle_ul_ccch(uint16_t rnti, srsran::const_byte_span pdu)
case ul_ccch_msg_type_c::c1_c_::types_opts::rrc_setup_request:
handle_rrc_setup_request(rnti, ul_ccch_msg.msg.c1().rrc_setup_request());
break;
case ul_ccch_msg_type_c::c1_c_::types_opts::rrc_reest_request:
handle_rrc_reest_request(rnti, ul_ccch_msg.msg.c1().rrc_reest_request());
break;
default:
log_rx_pdu_fail(rnti, srb_to_lcid(lte_srb::srb0), pdu, "Unsupported UL-CCCH message type");
// TODO Remove user
@ -548,6 +551,19 @@ void rrc_nr::handle_rrc_setup_request(uint16_t rnti, const asn1::rrc_nr::rrc_set
u.handle_rrc_setup_request(msg);
}
void rrc_nr::handle_rrc_reest_request(uint16_t rnti, const asn1::rrc_nr::rrc_reest_request_s& msg)
{
auto ue_it = users.find(rnti);
// TODO: Defer creation of ue to this point
if (ue_it == users.end()) {
logger.error("%s received for inexistent rnti=0x%x", "UL-CCCH", rnti);
return;
}
ue& u = *ue_it->second;
u.handle_rrc_reest_request(msg);
}
/*******************************************************************************
PDCP interface
*******************************************************************************/

@ -15,6 +15,7 @@
#include "srsgnb/hdr/stack/rrc/rrc_nr_config_utils.h"
#include "srsran/asn1/rrc_nr_utils.h"
#include "srsran/common/bearer_manager.h"
#include "srsran/common/standard_streams.h"
#include "srsran/common/string_helpers.h"
using namespace asn1::rrc_nr;
@ -883,6 +884,129 @@ void rrc_nr::ue::handle_rrc_setup_request(const asn1::rrc_nr::rrc_setup_request_
set_activity_timeout(UE_INACTIVITY_TIMEOUT);
}
void rrc_nr::ue::handle_rrc_reest_request(const asn1::rrc_nr::rrc_reest_request_s& msg)
{
uint32_t old_rnti = msg.rrc_reest_request.ue_id.c_rnti;
uint16_t pci = msg.rrc_reest_request.ue_id.pci;
// Log event
parent->logger.debug("rnti=0x%x, phyid=0x%x, smac=0x%x, cause=%s",
old_rnti,
pci,
(uint32_t)msg.rrc_reest_request.ue_id.short_mac_i.to_number(),
msg.rrc_reest_request.reest_cause.to_string());
// Check AMF connection
const uint8_t max_wait_time_secs = 16;
if (not parent->ngap->is_amf_connected()) {
logger.error("AMF not connected. Sending Connection Reject.");
send_rrc_reject(max_wait_time_secs);
return;
}
// Allocate PUCCH resources and reject if not available
if (not init_pucch()) {
logger.warning("Could not allocate PUCCH resources for rnti=0x%x. Sending RRC Reject.", rnti);
send_rrc_reject(max_wait_time_secs);
return;
}
if (not is_idle()) {
// The created RNTI has to receive ReestablishmentRequest as first message
parent->logger.error(
"Could not reestablish connection for rnti=0x%x. Cause: old rnti=0x%x is not in RRC_IDLE.", rnti, old_rnti);
send_rrc_reject(max_wait_time_secs);
return;
}
auto old_ue_it = parent->users.find(old_rnti);
// Fallback to connection establishment for unrecognized rntis, and PCIs that do not belong to eNB
if (old_ue_it == parent->users.end()) {
parent->logger.info(
"Fallback to connection establishment for rnti=0x%x. Cause: no rnti=0x%x context available", rnti, old_rnti);
srsran::console("Fallback to connection establishment for rnti=0x%x. Cause: no context available\n", rnti);
// send RRC Setup
send_rrc_setup();
set_activity_timeout(UE_INACTIVITY_TIMEOUT);
return;
}
// Reestablishment procedure going forward
parent->logger.info("ConnectionReestablishmentRequest for rnti=0x%x. Sending Connection Reestablishment.", old_rnti);
srsran::console("User 0x%x requesting RRC Reestablishment as 0x%x. Cause: %s\n",
rnti,
old_rnti,
msg.rrc_reest_request.reest_cause.to_string());
ue* old_ue = old_ue_it->second.get();
// Recover security setup
sec_ctx = old_ue->sec_ctx;
auto& pscell_cfg = parent->cfg.cell_list.at(UE_PSCELL_CC_IDX);
sec_ctx.regenerate_keys_handover(pscell_cfg.phy_cell.carrier.pci, pscell_cfg.dl_arfcn);
// For the reestablishment, only add SRB1 to new UE context
next_radio_bearer_cfg.srb_to_add_mod_list_present = true;
next_radio_bearer_cfg.srb_to_add_mod_list.resize(1);
srb_to_add_mod_s& srb1 = next_radio_bearer_cfg.srb_to_add_mod_list[0];
srb1.srb_id = 1;
asn1::rrc_nr::radio_bearer_cfg_s dummy_radio_bearer_cfg; // just to compute difference, it's never sent to UE
compute_diff_radio_bearer_cfg(parent->cfg, radio_bearer_cfg, next_radio_bearer_cfg, dummy_radio_bearer_cfg);
// - Setup masterCellGroup
// - Derive master cell group config bearers
fill_cellgroup_with_radio_bearer_cfg(parent->cfg, dummy_radio_bearer_cfg, next_cell_group_cfg);
// send RRC Reestablishment message and restore bearer configuration
send_connection_reest(old_ue->sec_ctx.get_ncc());
// recover all previously created bearers from old UE object for (later) reconfiguration
next_radio_bearer_cfg = old_ue->radio_bearer_cfg;
next_cell_group_cfg = old_ue->cell_group_cfg;
// Recover GTP-U tunnels and NGAP context
// parent->gtpu->mod_bearer_rnti(old_rnti, rnti);
parent->ngap->user_mod(old_rnti, rnti);
// Reestablish E-RABs of old rnti later, during ConnectionReconfiguration
// bearer_list.reestablish_bearers(std::move(old_ue->bearer_list));
// remove old RNTI
// old_ue->mac_ctrl.set_drb_activation(false);
// parent->rem_user_thread(old_rnti);
// state = RRC_STATE_WAIT_FOR_CON_REEST_COMPLETE;
set_activity_timeout(MSG5_RX_TIMEOUT);
}
void rrc_nr::ue::send_connection_reest(uint8_t ncc)
{
dl_dcch_msg_s msg;
rrc_reest_ies_s& reest = msg.msg.set_c1().set_rrc_reest().crit_exts.set_rrc_reest();
msg.msg.c1().rrc_reest().rrc_transaction_id = (uint8_t)((transaction_id++) % 4);
// set NCC
reest.next_hop_chaining_count = ncc;
// add PDCP bearers
update_pdcp_bearers(next_radio_bearer_cfg, next_cell_group_cfg);
// add RLC bearers
update_rlc_bearers(next_cell_group_cfg);
// add MAC bearers
update_mac(next_cell_group_cfg, false);
if (send_dl_dcch(srsran::nr_srb::srb1, msg) != SRSRAN_SUCCESS) {
// TODO: Handle
}
}
/// TS 38.331, RRCReject message
void rrc_nr::ue::send_rrc_reject(uint8_t reject_wait_time_secs)
{
@ -913,7 +1037,6 @@ void rrc_nr::ue::send_rrc_setup()
srb1.srb_id = 1;
// Generate RRC setup message
dl_ccch_msg_s msg;
rrc_setup_s& setup = msg.msg.set_c1().set_rrc_setup();
setup.rrc_transaction_id = (uint8_t)((transaction_id++) % 4);
@ -1208,6 +1331,22 @@ int rrc_nr::ue::update_pdcp_bearers(const asn1::rrc_nr::radio_bearer_cfg_s& radi
return SRSRAN_ERROR;
}
parent->pdcp->add_bearer(rnti, rlc_bearer->lc_ch_id, pdcp_cnfg);
// enable security config
if (sec_ctx.is_as_sec_cfg_valid()) {
srsran::nr_as_security_config_t tmp_cnfg = sec_ctx.get_as_sec_cfg();
srsran::as_security_config_t pdcp_cnfg = {};
pdcp_cnfg.k_rrc_int = tmp_cnfg.k_nr_rrc_int;
pdcp_cnfg.k_rrc_enc = tmp_cnfg.k_nr_rrc_enc;
pdcp_cnfg.k_up_int = tmp_cnfg.k_nr_up_int;
pdcp_cnfg.k_up_enc = tmp_cnfg.k_nr_up_enc;
pdcp_cnfg.integ_algo = (srsran::INTEGRITY_ALGORITHM_ID_ENUM)tmp_cnfg.integ_algo;
pdcp_cnfg.cipher_algo = (srsran::CIPHERING_ALGORITHM_ID_ENUM)tmp_cnfg.cipher_algo;
// Setup SRB1 security/integrity. Encryption is set on completion
parent->pdcp->config_security(rnti, srb_to_lcid(srsran::nr_srb::srb1), pdcp_cnfg);
parent->pdcp->enable_integrity(rnti, srb_to_lcid(srsran::nr_srb::srb1));
}
}
// Add DRBs

Loading…
Cancel
Save