Added handling of RRC re-establishment to srsENB.

* Added the appropriate code for handling and sending the
   re-establishment procedure messages to rrc_ue.c/.h.
 * Triggered RRC reconfiguration after the reception of RRC
   re-establishment complete
 * Refreshed K_eNB at the reception of re-establishment
   request
 * Changed the mapping of TEIDs to RNTIs in the GTP-U layer,
   as the RNTI might change with reestablishment.
master
Pedro Alvarez 5 years ago
parent 0e99e2f6eb
commit 960c0e97cd

@ -465,9 +465,10 @@ public:
class gtpu_interface_rrc class gtpu_interface_rrc
{ {
public: public:
virtual void add_bearer(uint16_t rnti, uint32_t lcid, uint32_t addr, uint32_t teid_out, uint32_t* teid_in) = 0; virtual uint32_t add_bearer(uint16_t rnti, uint32_t lcid, uint32_t addr, uint32_t teid_out) = 0;
virtual void rem_bearer(uint16_t rnti, uint32_t lcid) = 0; virtual void rem_bearer(uint16_t rnti, uint32_t lcid) = 0;
virtual void rem_user(uint16_t rnti) = 0; virtual void mod_bearer_rnti(uint16_t old_rnti, uint16_t new_rnti) = 0;
virtual void rem_user(uint16_t rnti) = 0;
}; };
// S1AP interface for RRC // S1AP interface for RRC

@ -122,7 +122,6 @@ public:
private: private:
class ue; class ue;
// args // args
srslte::timer_handler* timers = nullptr; srslte::timer_handler* timers = nullptr;
srslte::byte_buffer_pool* pool = nullptr; srslte::byte_buffer_pool* pool = nullptr;

@ -36,21 +36,22 @@ public:
bool set_security_capabilities(const asn1::s1ap::ue_security_cap_s& caps); bool set_security_capabilities(const asn1::s1ap::ue_security_cap_s& caps);
void set_security_key(const asn1::fixed_bitstring<256, false, true>& key); void set_security_key(const asn1::fixed_bitstring<256, false, true>& key);
void regenerate_keys_handover(uint32_t new_pci, uint32_t new_dl_earfcn);
asn1::rrc::security_algorithm_cfg_s get_security_algorithm_cfg(); asn1::rrc::security_algorithm_cfg_s get_security_algorithm_cfg();
const srslte::as_security_config_t& get_as_sec_cfg() const { return sec_cfg; } const srslte::as_security_config_t& get_as_sec_cfg() const { return sec_cfg; }
bool is_as_sec_cfg_valid() const { return k_enb_present; } bool is_as_sec_cfg_valid() const { return k_enb_present; }
void regenerate_keys_handover(uint32_t new_pci, uint32_t new_dl_earfcn);
private: private:
void generate_as_keys(); void generate_as_keys();
srslte::log_ref log_h{"RRC"}; srslte::log_ref log_h{"RRC"};
const rrc_cfg_t* cfg; const rrc_cfg_t* cfg = nullptr;
bool k_enb_present = false; bool k_enb_present = false;
asn1::s1ap::ue_security_cap_s security_capabilities; asn1::s1ap::ue_security_cap_s security_capabilities = {};
uint8_t k_enb[32] = {}; // Provided by MME uint8_t k_enb[32] = {}; // Provided by MME
srslte::as_security_config_t sec_cfg = {}; srslte::as_security_config_t sec_cfg = {};
}; };
class bearer_cfg_handler class bearer_cfg_handler
@ -64,7 +65,7 @@ public:
uint32_t teid_in = 0; uint32_t teid_in = 0;
}; };
bearer_cfg_handler(uint16_t rnti_, const rrc_cfg_t& cfg_, gtpu_interface_rrc* gtpu_); bearer_cfg_handler(uint16_t rnti_, const rrc_cfg_t& cfg_);
void add_srb(uint8_t srb_id); void add_srb(uint8_t srb_id);
int add_erab(uint8_t erab_id, int add_erab(uint8_t erab_id,
@ -83,24 +84,25 @@ public:
void apply_mac_bearer_updates(mac_interface_rrc* mac, sched_interface::ue_cfg_t* sched_ue_cfg); void apply_mac_bearer_updates(mac_interface_rrc* mac, sched_interface::ue_cfg_t* sched_ue_cfg);
void apply_pdcp_bearer_updates(pdcp_interface_rrc* pdcp, const security_cfg_handler& ue_sec_cfg); void apply_pdcp_bearer_updates(pdcp_interface_rrc* pdcp, const security_cfg_handler& ue_sec_cfg);
void apply_rlc_bearer_updates(rlc_interface_rrc* rlc); void apply_rlc_bearer_updates(rlc_interface_rrc* rlc);
void add_gtpu_bearer(gtpu_interface_rrc* gtpu, uint32_t erab_id);
void fill_pending_nas_info(asn1::rrc::rrc_conn_recfg_r8_ies_s* msg); void fill_pending_nas_info(asn1::rrc::rrc_conn_recfg_r8_ies_s* msg);
const std::map<uint8_t, erab_t>& get_erabs() const { return erabs; } const std::map<uint8_t, erab_t>& get_erabs() const { return erabs; }
const asn1::rrc::drb_to_add_mod_list_l& established_drbs() const { return last_drbs; } const asn1::rrc::drb_to_add_mod_list_l& get_established_drbs() const { return current_drbs; }
const asn1::rrc::srb_to_add_mod_list_l& established_srbs() const { return last_srbs; } const asn1::rrc::srb_to_add_mod_list_l& get_established_srbs() const { return current_srbs; }
const asn1::rrc::drb_to_add_mod_list_l& get_pending_addmod_drbs() const { return drbs_to_add; }
private:
srslte::log_ref log_h{"RRC"};
uint16_t rnti;
const rrc_cfg_t* cfg;
gtpu_interface_rrc* gtpu;
std::map<uint8_t, std::vector<uint8_t> > erab_info_list; std::map<uint8_t, std::vector<uint8_t> > erab_info_list;
std::map<uint8_t, erab_t> erabs; std::map<uint8_t, erab_t> erabs;
private:
srslte::log_ref log_h{"RRC"};
uint16_t rnti = 0;
const rrc_cfg_t* cfg = nullptr;
// last cfg // last cfg
asn1::rrc::srb_to_add_mod_list_l last_srbs; asn1::rrc::srb_to_add_mod_list_l current_srbs;
asn1::rrc::drb_to_add_mod_list_l last_drbs; asn1::rrc::drb_to_add_mod_list_l current_drbs;
// pending cfg updates // pending cfg updates
asn1::rrc::srb_to_add_mod_list_l srbs_to_add; asn1::rrc::srb_to_add_mod_list_l srbs_to_add;

@ -29,6 +29,7 @@ namespace srsenb {
typedef enum { typedef enum {
RRC_STATE_IDLE = 0, RRC_STATE_IDLE = 0,
RRC_STATE_WAIT_FOR_CON_SETUP_COMPLETE, RRC_STATE_WAIT_FOR_CON_SETUP_COMPLETE,
RRC_STATE_WAIT_FOR_CON_REEST_COMPLETE,
RRC_STATE_WAIT_FOR_SECURITY_MODE_COMPLETE, RRC_STATE_WAIT_FOR_SECURITY_MODE_COMPLETE,
RRC_STATE_WAIT_FOR_UE_CAP_INFO, RRC_STATE_WAIT_FOR_UE_CAP_INFO,
RRC_STATE_WAIT_FOR_CON_RECONF_COMPLETE, RRC_STATE_WAIT_FOR_CON_RECONF_COMPLETE,

@ -51,7 +51,7 @@ public:
rrc_state_t get_state(); rrc_state_t get_state();
void send_connection_setup(bool is_setup = true); void send_connection_setup();
void send_connection_reest(); void send_connection_reest();
void send_connection_reject(); void send_connection_reject();
void send_connection_release(); void send_connection_release();
@ -66,6 +66,8 @@ public:
void handle_rrc_con_req(asn1::rrc::rrc_conn_request_s* msg); void handle_rrc_con_req(asn1::rrc::rrc_conn_request_s* msg);
void handle_rrc_con_reest_req(asn1::rrc::rrc_conn_reest_request_r8_ies_s* msg); void handle_rrc_con_reest_req(asn1::rrc::rrc_conn_reest_request_r8_ies_s* msg);
void handle_rrc_con_setup_complete(asn1::rrc::rrc_conn_setup_complete_s* msg, srslte::unique_byte_buffer_t pdu); void handle_rrc_con_setup_complete(asn1::rrc::rrc_conn_setup_complete_s* msg, srslte::unique_byte_buffer_t pdu);
void handle_rrc_con_reest_req(asn1::rrc::rrc_conn_reest_request_s* msg);
void handle_rrc_con_reest_complete(asn1::rrc::rrc_conn_reest_complete_s* msg, srslte::unique_byte_buffer_t pdu);
void handle_rrc_reconf_complete(asn1::rrc::rrc_conn_recfg_complete_s* msg, srslte::unique_byte_buffer_t pdu); void handle_rrc_reconf_complete(asn1::rrc::rrc_conn_recfg_complete_s* msg, srslte::unique_byte_buffer_t pdu);
void handle_security_mode_complete(asn1::rrc::security_mode_complete_s* msg); void handle_security_mode_complete(asn1::rrc::security_mode_complete_s* msg);
void handle_security_mode_failure(asn1::rrc::security_mode_fail_s* msg); void handle_security_mode_failure(asn1::rrc::security_mode_fail_s* msg);
@ -121,6 +123,7 @@ private:
sched_interface::ue_cfg_t current_sched_ue_cfg = {}; sched_interface::ue_cfg_t current_sched_ue_cfg = {};
uint32_t rlf_cnt = 0; uint32_t rlf_cnt = 0;
uint8_t transaction_id = 0; uint8_t transaction_id = 0;
uint16_t old_reest_rnti = SRSLTE_INVALID_RNTI;
rrc_state_t state = RRC_STATE_IDLE; rrc_state_t state = RRC_STATE_IDLE;
asn1::s1ap::ue_aggregate_maximum_bitrate_s bitrates; asn1::s1ap::ue_aggregate_maximum_bitrate_s bitrates;
@ -134,6 +137,12 @@ private:
bearer_cfg_handler bearer_list; bearer_cfg_handler bearer_list;
security_cfg_handler ue_security_cfg; security_cfg_handler ue_security_cfg;
///< Helper to add SRB to scheduler
void init_sched_ue_cfg(asn1::rrc::phys_cfg_ded_s* phy_cfg);
///< Helper to fill RR config dedicated struct for RRR Connection Setup/Reestablish
void fill_rrc_setup_rr_config_dedicated(asn1::rrc::rr_cfg_ded_s* rr_cfg);
///< Helper to access a cell cfg based on ue_cc_idx ///< Helper to access a cell cfg based on ue_cc_idx
cell_info_common* get_ue_cc_cfg(uint32_t ue_cc_idx); cell_info_common* get_ue_cc_cfg(uint32_t ue_cc_idx);

@ -49,9 +49,10 @@ public:
void stop(); void stop();
// gtpu_interface_rrc // gtpu_interface_rrc
void add_bearer(uint16_t rnti, uint32_t lcid, uint32_t addr, uint32_t teid_out, uint32_t* teid_in) override; uint32_t add_bearer(uint16_t rnti, uint32_t lcid, uint32_t addr, uint32_t teid_out) override;
void rem_bearer(uint16_t rnti, uint32_t lcid) override; void rem_bearer(uint16_t rnti, uint32_t lcid) override;
void rem_user(uint16_t rnti) override; void mod_bearer_rnti(uint16_t old_rnti, uint16_t new_rnti) override;
void rem_user(uint16_t rnti) override;
// gtpu_interface_pdcp // gtpu_interface_pdcp
void write_pdu(uint16_t rnti, uint32_t lcid, srslte::unique_byte_buffer_t pdu) override; void write_pdu(uint16_t rnti, uint32_t lcid, srslte::unique_byte_buffer_t pdu) override;
@ -105,6 +106,12 @@ private:
} bearer_map; } bearer_map;
std::map<uint16_t, bearer_map> rnti_bearers; std::map<uint16_t, bearer_map> rnti_bearers;
typedef struct {
uint16_t rnti;
uint16_t lcid;
} rnti_lcid_t;
std::map<uint32_t, rnti_lcid_t> teidin_to_rntilcid_map;
// Socket file descriptor // Socket file descriptor
int fd = -1; int fd = -1;
@ -113,8 +120,12 @@ private:
/**************************************************************************** /****************************************************************************
* TEID to RNIT/LCID helper functions * TEID to RNIT/LCID helper functions
***************************************************************************/ ***************************************************************************/
void teidin_to_rntilcid(uint32_t teidin, uint16_t* rnti, uint16_t* lcid); uint32_t next_teid_in = 0;
void rntilcid_to_teidin(uint16_t rnti, uint16_t lcid, uint32_t* teidin); uint32_t allocate_teidin(uint16_t rnti, uint16_t lcid);
void free_teidin(uint16_t rnti, uint16_t lcid);
void free_teidin(uint16_t rnti);
rnti_lcid_t teidin_to_rntilcid(uint32_t teidin);
uint32_t rntilcid_to_teidin(uint16_t rnti, uint16_t lcid);
}; };
} // namespace srsenb } // namespace srsenb

@ -179,7 +179,7 @@ void rrc::add_user(uint16_t rnti, const sched_interface::ue_cfg_t& sched_ue_cfg)
mac->ue_cfg(SRSLTE_MRNTI, NULL); mac->ue_cfg(SRSLTE_MRNTI, NULL);
rlc->add_bearer_mrb(SRSLTE_MRNTI, lcid); rlc->add_bearer_mrb(SRSLTE_MRNTI, lcid);
pdcp->add_bearer(SRSLTE_MRNTI, lcid, srslte::make_drb_pdcp_config_t(1, false)); pdcp->add_bearer(SRSLTE_MRNTI, lcid, srslte::make_drb_pdcp_config_t(1, false));
gtpu->add_bearer(SRSLTE_MRNTI, lcid, 1, 1, &teid_in); teid_in = gtpu->add_bearer(SRSLTE_MRNTI, lcid, 1, 1);
} }
} }
} }
@ -456,8 +456,6 @@ void rrc::ho_preparation_complete(uint16_t rnti, bool is_success, srslte::unique
void rrc::parse_ul_ccch(uint16_t rnti, srslte::unique_byte_buffer_t pdu) void rrc::parse_ul_ccch(uint16_t rnti, srslte::unique_byte_buffer_t pdu)
{ {
uint16_t old_rnti = 0;
if (pdu) { if (pdu) {
ul_ccch_msg_s ul_ccch_msg; ul_ccch_msg_s ul_ccch_msg;
asn1::cbit_ref bref(pdu->msg, pdu->N_bytes); asn1::cbit_ref bref(pdu->msg, pdu->N_bytes);
@ -479,41 +477,10 @@ void rrc::parse_ul_ccch(uint16_t rnti, srslte::unique_byte_buffer_t pdu)
} }
break; break;
case ul_ccch_msg_type_c::c1_c_::types::rrc_conn_reest_request: case ul_ccch_msg_type_c::c1_c_::types::rrc_conn_reest_request:
rrc_log->debug("rnti=0x%x, phyid=0x%x, smac=0x%x, cause=%s\n", if (user_it != users.end()) {
(uint32_t)ul_ccch_msg.msg.c1() user_it->second->handle_rrc_con_reest_req(&ul_ccch_msg.msg.c1().rrc_conn_reest_request());
.rrc_conn_reest_request()
.crit_exts.rrc_conn_reest_request_r8()
.ue_id.c_rnti.to_number(),
ul_ccch_msg.msg.c1().rrc_conn_reest_request().crit_exts.rrc_conn_reest_request_r8().ue_id.pci,
(uint32_t)ul_ccch_msg.msg.c1()
.rrc_conn_reest_request()
.crit_exts.rrc_conn_reest_request_r8()
.ue_id.short_mac_i.to_number(),
ul_ccch_msg.msg.c1()
.rrc_conn_reest_request()
.crit_exts.rrc_conn_reest_request_r8()
.reest_cause.to_string()
.c_str());
if (user_it->second->is_idle()) {
old_rnti = (uint16_t)ul_ccch_msg.msg.c1()
.rrc_conn_reest_request()
.crit_exts.rrc_conn_reest_request_r8()
.ue_id.c_rnti.to_number();
if (users.count(old_rnti)) {
rrc_log->error("Not supported: ConnectionReestablishment for rnti=0x%x. Sending Connection Reject\n",
old_rnti);
user_it->second->send_connection_reest_rej();
s1ap->user_release(old_rnti, asn1::s1ap::cause_radio_network_opts::release_due_to_eutran_generated_reason);
} else {
rrc_log->error("Received ConnectionReestablishment for rnti=0x%x without context\n", old_rnti);
user_it->second->send_connection_reest_rej();
}
// remove temporal rnti
rrc_log->warning(
"Received ConnectionReestablishment for rnti=0x%x. Removing temporal rnti=0x%x\n", old_rnti, rnti);
rem_user_thread(rnti);
} else { } else {
rrc_log->error("Received ReestablishmentRequest from an rnti=0x%x not in IDLE\n", rnti); rrc_log->error("Received ConnectionReestablishment for rnti=0x%x without context.\n", rnti);
} }
break; break;
default: default:

@ -178,8 +178,6 @@ void security_cfg_handler::set_security_key(const asn1::fixed_bitstring<256, fal
void security_cfg_handler::generate_as_keys() void security_cfg_handler::generate_as_keys()
{ {
log_h->info("Selected security algorithms EEA: EEA%d EIA: EIA%d\n", sec_cfg.cipher_algo, sec_cfg.integ_algo);
// Generate K_rrc_enc and K_rrc_int // Generate K_rrc_enc and K_rrc_int
srslte::security_generate_k_rrc( srslte::security_generate_k_rrc(
k_enb, sec_cfg.cipher_algo, sec_cfg.integ_algo, sec_cfg.k_rrc_enc.data(), sec_cfg.k_rrc_int.data()); k_enb, sec_cfg.cipher_algo, sec_cfg.integ_algo, sec_cfg.k_rrc_enc.data(), sec_cfg.k_rrc_int.data());
@ -203,17 +201,18 @@ void security_cfg_handler::regenerate_keys_handover(uint32_t new_pci, uint32_t n
memcpy(k_enb, k_enb_star, 32); memcpy(k_enb, k_enb_star, 32);
generate_as_keys(); generate_as_keys();
log_h->info("Regenerating KeNB with PCI=0x%02x, DL-EARFCN=%d\n", new_pci, new_dl_earfcn);
log_h->info_hex(sec_cfg.k_rrc_enc.data(), 32, "RRC Encryption Key (k_rrc_enc)");
log_h->info_hex(sec_cfg.k_rrc_int.data(), 32, "RRC Integrity Key (k_rrc_int)");
log_h->info_hex(sec_cfg.k_up_enc.data(), 32, "UP Encryption Key (k_up_enc)");
} }
/***************************** /*****************************
* Bearer Handler * Bearer Handler
****************************/ ****************************/
bearer_cfg_handler::bearer_cfg_handler(uint16_t rnti_, const rrc_cfg_t& cfg_, gtpu_interface_rrc* gtpu_) : bearer_cfg_handler::bearer_cfg_handler(uint16_t rnti_, const rrc_cfg_t& cfg_) : rnti(rnti_), cfg(&cfg_) {}
rnti(rnti_),
cfg(&cfg_),
gtpu(gtpu_)
{}
void bearer_cfg_handler::add_srb(uint8_t srb_id) void bearer_cfg_handler::add_srb(uint8_t srb_id)
{ {
@ -283,9 +282,6 @@ int bearer_cfg_handler::add_erab(uint8_t
drb_it->rlc_cfg_present = true; drb_it->rlc_cfg_present = true;
drb_it->rlc_cfg = cfg->qci_cfg[qos.qci].rlc_cfg; drb_it->rlc_cfg = cfg->qci_cfg[qos.qci].rlc_cfg;
// Initialize ERAB in GTPU right-away. DRBs are only created during RRC setup/reconf
uint32_t addr_ = addr.to_number();
gtpu->add_bearer(rnti, lcid, addr_, erabs[erab_id].teid_out, &(erabs[erab_id].teid_in));
return SRSLTE_SUCCESS; return SRSLTE_SUCCESS;
} }
@ -316,15 +312,15 @@ void bearer_cfg_handler::release_erabs()
void bearer_cfg_handler::reest_bearers() void bearer_cfg_handler::reest_bearers()
{ {
// Re-add all SRBs/DRBs // Re-add all SRBs/DRBs
srbs_to_add = last_srbs; srbs_to_add = current_srbs;
drbs_to_add = last_drbs; drbs_to_add = current_drbs;
} }
void bearer_cfg_handler::rr_ded_cfg_complete() void bearer_cfg_handler::rr_ded_cfg_complete()
{ {
// Apply changes in internal bearer_handler DRB/SRBtoAddModLists // Apply changes in internal bearer_handler DRB/SRBtoAddModLists
srslte::apply_addmodlist_diff(last_srbs, srbs_to_add, last_srbs); srslte::apply_addmodlist_diff(current_srbs, srbs_to_add, current_srbs);
srslte::apply_addmodremlist_diff(last_drbs, drbs_to_add, drbs_to_release, last_drbs); srslte::apply_addmodremlist_diff(current_drbs, drbs_to_add, drbs_to_release, current_drbs);
// Reset DRBs/SRBs to Add/mod/release // Reset DRBs/SRBs to Add/mod/release
srbs_to_add = {}; srbs_to_add = {};
@ -416,6 +412,19 @@ void bearer_cfg_handler::apply_rlc_bearer_updates(rlc_interface_rrc* rlc)
} }
} }
void bearer_cfg_handler::add_gtpu_bearer(srsenb::gtpu_interface_rrc* gtpu, uint32_t erab_id)
{
auto it = erabs.find(erab_id);
if (it != erabs.end()) {
erab_t& erab = it->second;
// Initialize ERAB in GTPU right-away. DRBs are only created during RRC setup/reconf
uint32_t addr_ = erab.address.to_number();
erab.teid_in = gtpu->add_bearer(rnti, erab.id - 2, addr_, erab.teid_out);
} else {
log_h->error("Adding erab_id=%d to GTPU\n", erab_id);
}
}
void bearer_cfg_handler::fill_pending_nas_info(asn1::rrc::rrc_conn_recfg_r8_ies_s* msg) void bearer_cfg_handler::fill_pending_nas_info(asn1::rrc::rrc_conn_recfg_r8_ies_s* msg)
{ {
// Add space for NAS messages // Add space for NAS messages

@ -528,10 +528,9 @@ void rrc::ue::rrc_mobility::handle_ue_meas_report(const meas_report_s& msg)
continue; continue;
} }
meas_ev.meas_cell = cell_it; meas_ev.meas_cell = cell_it;
meas_ev.target_eci = std::find_if(meas_list_cfg.begin(), meas_ev.target_eci = std::find_if(meas_list_cfg.begin(), meas_list_cfg.end(), [pci](const meas_cell_cfg_t& c) {
meas_list_cfg.end(), return c.pci == pci;
[pci](const meas_cell_cfg_t& c) { return c.pci == pci; }) })->eci;
->eci;
// eNB found the respective cell. eNB takes "HO Decision" // eNB found the respective cell. eNB takes "HO Decision"
// NOTE: From now we just choose the strongest. // NOTE: From now we just choose the strongest.
@ -968,7 +967,7 @@ void rrc::ue::rrc_mobility::intraenb_ho_st::enter(rrc_mobility* f)
} }
/* Freeze all DRBs. SRBs are needed for sending the HO Cmd */ /* Freeze all DRBs. SRBs are needed for sending the HO Cmd */
for (const drb_to_add_mod_s& drb : f->rrc_ue->bearer_list.established_drbs()) { for (const drb_to_add_mod_s& drb : f->rrc_ue->bearer_list.get_established_drbs()) {
f->rrc_enb->pdcp->del_bearer(f->rrc_ue->rnti, drb.drb_id + 2); f->rrc_enb->pdcp->del_bearer(f->rrc_ue->rnti, drb.drb_id + 2);
f->rrc_enb->mac->bearer_ue_rem(f->rrc_ue->rnti, drb.drb_id + 2); f->rrc_enb->mac->bearer_ue_rem(f->rrc_ue->rnti, drb.drb_id + 2);
} }

File diff suppressed because it is too large Load Diff

@ -140,17 +140,17 @@ void gtpu::write_pdu(uint16_t rnti, uint32_t lcid, srslte::unique_byte_buffer_t
* If access to any element created in init (such as gtpu_log) is required, it must be considered * If access to any element created in init (such as gtpu_log) is required, it must be considered
* the case of it being NULL. * the case of it being NULL.
*/ */
void gtpu::add_bearer(uint16_t rnti, uint32_t lcid, uint32_t addr, uint32_t teid_out, uint32_t* teid_in) uint32_t gtpu::add_bearer(uint16_t rnti, uint32_t lcid, uint32_t addr, uint32_t teid_out)
{ {
// Allocate a TEID for the incoming tunnel // Allocate a TEID for the incoming tunnel
rntilcid_to_teidin(rnti, lcid, teid_in); uint32_t teid_in = allocate_teidin(rnti, lcid);
if (gtpu_log) { if (gtpu_log) {
gtpu_log->info("Adding bearer for rnti: 0x%x, lcid: %d, addr: 0x%x, teid_out: 0x%x, teid_in: 0x%x\n", gtpu_log->info("Adding bearer for rnti: 0x%x, lcid: %d, addr: 0x%x, teid_out: 0x%x, teid_in: 0x%x\n",
rnti, rnti,
lcid, lcid,
addr, addr,
teid_out, teid_out,
*teid_in); teid_in);
} }
// Initialize maps if it's a new RNTI // Initialize maps if it's a new RNTI
@ -162,15 +162,21 @@ void gtpu::add_bearer(uint16_t rnti, uint32_t lcid, uint32_t addr, uint32_t teid
} }
} }
rnti_bearers[rnti].teids_in[lcid] = *teid_in; rnti_bearers[rnti].teids_in[lcid] = teid_in;
rnti_bearers[rnti].teids_out[lcid] = teid_out; rnti_bearers[rnti].teids_out[lcid] = teid_out;
rnti_bearers[rnti].spgw_addrs[lcid] = addr; rnti_bearers[rnti].spgw_addrs[lcid] = addr;
return teid_in;
} }
void gtpu::rem_bearer(uint16_t rnti, uint32_t lcid) void gtpu::rem_bearer(uint16_t rnti, uint32_t lcid)
{ {
gtpu_log->info("Removing bearer for rnti: 0x%x, lcid: %d\n", rnti, lcid); gtpu_log->info("Removing bearer for rnti: 0x%x, lcid: %d\n", rnti, lcid);
// Remove from TEID from map
free_teidin(rnti, lcid);
// Remove
rnti_bearers[rnti].teids_in[lcid] = 0; rnti_bearers[rnti].teids_in[lcid] = 0;
rnti_bearers[rnti].teids_out[lcid] = 0; rnti_bearers[rnti].teids_out[lcid] = 0;
@ -186,8 +192,43 @@ void gtpu::rem_bearer(uint16_t rnti, uint32_t lcid)
} }
} }
void gtpu::mod_bearer_rnti(uint16_t old_rnti, uint16_t new_rnti)
{
gtpu_log->info("Modifying bearer rnti. Old rnti: 0x%x, new rnti: 0x%x\n", old_rnti, new_rnti);
if (rnti_bearers.count(new_rnti) != 0) {
gtpu_log->error("New rnti already exists, aborting.\n");
return;
}
if (rnti_bearers.count(old_rnti) == 0) {
gtpu_log->error("Old rnti does not exist, aborting.\n");
return;
}
// Change RNTI bearers map
auto entry = rnti_bearers.find(old_rnti);
if (entry != rnti_bearers.end()) {
auto const value = std::move(entry->second);
rnti_bearers.erase(entry);
rnti_bearers.insert({new_rnti, std::move(value)});
}
// Change TEID
for (std::map<uint32_t, rnti_lcid_t>::iterator it = teidin_to_rntilcid_map.begin();
it != teidin_to_rntilcid_map.end();
it++) {
if (it->second.rnti == old_rnti) {
it->second.rnti = new_rnti;
}
}
}
void gtpu::rem_user(uint16_t rnti) void gtpu::rem_user(uint16_t rnti)
{ {
// Free from TEID map
free_teidin(rnti);
// Remove user from RNTI map
rnti_bearers.erase(rnti); rnti_bearers.erase(rnti);
} }
@ -206,14 +247,14 @@ void gtpu::handle_gtpu_s1u_rx_packet(srslte::unique_byte_buffer_t pdu, const soc
echo_response(addr.sin_addr.s_addr, addr.sin_port, header.seq_number); echo_response(addr.sin_addr.s_addr, addr.sin_port, header.seq_number);
break; break;
case GTPU_MSG_DATA_PDU: { case GTPU_MSG_DATA_PDU: {
uint16_t rnti = 0; rnti_lcid_t rnti_lcid = teidin_to_rntilcid(header.teid);
uint16_t lcid = 0; uint16_t rnti = rnti_lcid.rnti;
teidin_to_rntilcid(header.teid, &rnti, &lcid); uint16_t lcid = rnti_lcid.lcid;
bool user_exists = (rnti_bearers.count(rnti) > 0); bool user_exists = (rnti_bearers.count(rnti) > 0);
if (not user_exists) { if (not user_exists) {
gtpu_log->error("Unrecognized RNTI for DL PDU: 0x%x - dropping packet\n", rnti); gtpu_log->error("Unrecognized TEID In=%d for DL PDU. Dropping packet\n", header.teid);
return; return;
} }
@ -264,17 +305,71 @@ void gtpu::echo_response(in_addr_t addr, in_port_t port, uint16_t seq)
} }
/**************************************************************************** /****************************************************************************
* TEID to RNIT/LCID helper functions * TEID to RNTI/LCID helper functions
***************************************************************************/ ***************************************************************************/
void gtpu::teidin_to_rntilcid(uint32_t teidin, uint16_t* rnti, uint16_t* lcid) uint32_t gtpu::allocate_teidin(uint16_t rnti, uint16_t lcid)
{
uint32_t teid_in = ++next_teid_in;
if (teidin_to_rntilcid_map.count(teid_in) != 0) {
gtpu_log->error("TEID In already exists\n");
return 0;
}
rnti_lcid_t rnti_lcid = {rnti, lcid};
teidin_to_rntilcid_map[teid_in] = rnti_lcid;
gtpu_log->debug("TEID In=%d added\n", teid_in);
return teid_in;
}
void gtpu::free_teidin(uint16_t rnti, uint16_t lcid)
{ {
*lcid = teidin & 0xFFFF; for (std::map<uint32_t, rnti_lcid_t>::iterator it = teidin_to_rntilcid_map.begin();
*rnti = (teidin >> 16) & 0xFFFF; it != teidin_to_rntilcid_map.end();) {
if (it->second.rnti == rnti && it->second.lcid == lcid) {
gtpu_log->debug("TEID In=%d erased\n", it->first);
it = teidin_to_rntilcid_map.erase(it);
} else {
it++;
}
}
} }
void gtpu::rntilcid_to_teidin(uint16_t rnti, uint16_t lcid, uint32_t* teidin) void gtpu::free_teidin(uint16_t rnti)
{ {
*teidin = (rnti << 16) | lcid; for (std::map<uint32_t, rnti_lcid_t>::iterator it = teidin_to_rntilcid_map.begin();
it != teidin_to_rntilcid_map.end();) {
if (it->second.rnti == rnti) {
gtpu_log->debug("TEID In=%d erased\n", it->first);
it = teidin_to_rntilcid_map.erase(it);
} else {
it++;
}
}
}
gtpu::rnti_lcid_t gtpu::teidin_to_rntilcid(uint32_t teidin)
{
rnti_lcid_t rnti_lcid = {};
if (teidin_to_rntilcid_map.count(teidin) == 0) {
gtpu_log->error("TEID=%d In does not exist.\n", teidin);
return rnti_lcid;
}
rnti_lcid.rnti = teidin_to_rntilcid_map[teidin].rnti;
rnti_lcid.lcid = teidin_to_rntilcid_map[teidin].lcid;
return rnti_lcid;
}
uint32_t gtpu::rntilcid_to_teidin(uint16_t rnti, uint16_t lcid)
{
uint32_t teidin = 0;
for (const std::pair<const uint32_t, rnti_lcid_t>& item : teidin_to_rntilcid_map) {
if (item.second.rnti == rnti and item.second.lcid == lcid) {
teidin = item.first;
}
}
if (teidin == 0) {
gtpu_log->error("Could not find TEID. RNTI=0x%x, LCID=%d.\n", rnti, lcid);
}
return teidin;
} }
/**************************************************************************** /****************************************************************************
@ -314,8 +409,7 @@ bool gtpu::m1u_handler::init(std::string m1u_multiaddr_, std::string m1u_if_addr
} }
/* Send an ADD MEMBERSHIP message via setsockopt */ /* Send an ADD MEMBERSHIP message via setsockopt */
struct ip_mreq mreq { struct ip_mreq mreq {};
};
mreq.imr_multiaddr.s_addr = inet_addr(m1u_multiaddr.c_str()); // Multicast address of the service mreq.imr_multiaddr.s_addr = inet_addr(m1u_multiaddr.c_str()); // Multicast address of the service
mreq.imr_interface.s_addr = inet_addr(m1u_if_addr.c_str()); // Address of the IF the socket will listen to. mreq.imr_interface.s_addr = inet_addr(m1u_if_addr.c_str()); // Address of the IF the socket will listen to.
if (setsockopt(m1u_sd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof(mreq)) < 0) { if (setsockopt(m1u_sd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof(mreq)) < 0) {

@ -124,9 +124,10 @@ public:
class gtpu_dummy : public gtpu_interface_rrc class gtpu_dummy : public gtpu_interface_rrc
{ {
public: public:
void add_bearer(uint16_t rnti, uint32_t lcid, uint32_t addr, uint32_t teid_out, uint32_t* teid_in) override {} uint32_t add_bearer(uint16_t rnti, uint32_t lcid, uint32_t addr, uint32_t teid_out) override { return 0; }
void rem_bearer(uint16_t rnti, uint32_t lcid) override {} void rem_bearer(uint16_t rnti, uint32_t lcid) override {}
void rem_user(uint16_t rnti) override {} void mod_bearer_rnti(uint16_t old_rnti, uint16_t new_rnti) override {}
void rem_user(uint16_t rnti) override {}
}; };
} // namespace srsenb } // namespace srsenb

@ -138,14 +138,14 @@ void rrc::init(phy_interface_rrc_lte* phy_,
gw_interface_rrc* gw_, gw_interface_rrc* gw_,
const rrc_args_t& args_) const rrc_args_t& args_)
{ {
pool = byte_buffer_pool::get_instance(); pool = byte_buffer_pool::get_instance();
phy = phy_; phy = phy_;
mac = mac_; mac = mac_;
rlc = rlc_; rlc = rlc_;
pdcp = pdcp_; pdcp = pdcp_;
nas = nas_; nas = nas_;
usim = usim_; usim = usim_;
gw = gw_; gw = gw_;
args = args_; args = args_;
@ -1818,6 +1818,7 @@ void rrc::write_pdu(uint32_t lcid, unique_byte_buffer_t pdu)
void rrc::process_pdu(uint32_t lcid, srslte::unique_byte_buffer_t pdu) void rrc::process_pdu(uint32_t lcid, srslte::unique_byte_buffer_t pdu)
{ {
rrc_log->debug("RX PDU, LCID: %d\n", lcid);
switch (lcid) { switch (lcid) {
case RB_ID_SRB0: case RB_ID_SRB0:
parse_dl_ccch(std::move(pdu)); parse_dl_ccch(std::move(pdu));
@ -1827,7 +1828,7 @@ void rrc::process_pdu(uint32_t lcid, srslte::unique_byte_buffer_t pdu)
parse_dl_dcch(lcid, std::move(pdu)); parse_dl_dcch(lcid, std::move(pdu));
break; break;
default: default:
rrc_log->error("RX PDU with invalid bearer id: %d", lcid); rrc_log->error("RX PDU with invalid bearer id: %d\n", lcid);
break; break;
} }
} }

@ -214,7 +214,7 @@ void usim::generate_nas_keys(uint8_t* k_asme,
RRC interface RRC interface
*******************************************************************************/ *******************************************************************************/
void usim::generate_as_keys(uint8_t* k_asme, uint32_t count_ul, srslte::as_security_config_t *sec_cfg) void usim::generate_as_keys(uint8_t* k_asme, uint32_t count_ul, srslte::as_security_config_t* sec_cfg)
{ {
// Generate K_enb // Generate K_enb
security_generate_k_enb(k_asme, count_ul, k_enb); security_generate_k_enb(k_asme, count_ul, k_enb);
@ -238,6 +238,9 @@ void usim::generate_as_keys(uint8_t* k_asme, uint32_t count_ul, srslte::as_secur
void usim::generate_as_keys_ho(uint32_t pci, uint32_t earfcn, int ncc, srslte::as_security_config_t* sec_cfg) void usim::generate_as_keys_ho(uint32_t pci, uint32_t earfcn, int ncc, srslte::as_security_config_t* sec_cfg)
{ {
usim_log->info("Generating AS Keys HO. PCI 0x%02x, DL-EARFCN %d, NCC %d\n", pci, earfcn, ncc);
usim_log->info_hex(sec_cfg->k_rrc_enc.data(), sec_cfg->k_rrc_enc.size(), "Original HO K_RCC_enc");
usim_log->info_hex(sec_cfg->k_rrc_int.data(), sec_cfg->k_rrc_int.size(), "Original HO K_RCC_int");
uint8_t* enb_star_key = k_enb; uint8_t* enb_star_key = k_enb;
if (ncc < 0) { if (ncc < 0) {
@ -276,6 +279,9 @@ void usim::generate_as_keys_ho(uint32_t pci, uint32_t earfcn, int ncc, srslte::a
// Generate K_up_enc and K_up_int // Generate K_up_enc and K_up_int
security_generate_k_up( security_generate_k_up(
k_enb, sec_cfg->cipher_algo, sec_cfg->integ_algo, sec_cfg->k_up_enc.data(), sec_cfg->k_up_int.data()); k_enb, sec_cfg->cipher_algo, sec_cfg->integ_algo, sec_cfg->k_up_enc.data(), sec_cfg->k_up_int.data());
usim_log->info_hex(sec_cfg->k_rrc_enc.data(), sec_cfg->k_rrc_enc.size(), "HO K_RCC_enc");
usim_log->info_hex(sec_cfg->k_rrc_int.data(), sec_cfg->k_rrc_int.size(), "HO K_RCC_int");
} }
/******************************************************************************* /*******************************************************************************

Loading…
Cancel
Save