mirror of https://github.com/PentHertz/srsLTE.git
added s1ap handover notification, fixed s1ap asn1 bug, and fixed bad fields for admitted erabs in ho req ack
This commit is contained in:
parent
841b884796
commit
7605c7df23
|
@ -188,7 +188,6 @@ public:
|
||||||
class phy_interface_mac_lte
|
class phy_interface_mac_lte
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Removes an RNTI context from all the physical layer components, including secondary cells
|
* Removes an RNTI context from all the physical layer components, including secondary cells
|
||||||
* @param rnti identifier of the user
|
* @param rnti identifier of the user
|
||||||
|
@ -438,7 +437,8 @@ public:
|
||||||
virtual uint16_t
|
virtual uint16_t
|
||||||
start_ho_ue_resource_alloc(const asn1::s1ap::ho_request_s& msg,
|
start_ho_ue_resource_alloc(const asn1::s1ap::ho_request_s& msg,
|
||||||
const asn1::s1ap::sourceenb_to_targetenb_transparent_container_s& container,
|
const asn1::s1ap::sourceenb_to_targetenb_transparent_container_s& container,
|
||||||
srslte::byte_buffer_t& ho_cmd) = 0;
|
srslte::byte_buffer_t& ho_cmd,
|
||||||
|
std::vector<asn1::fixed_octstring<4, true> >& admitted_erabs) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
// GTPU interface for PDCP
|
// GTPU interface for PDCP
|
||||||
|
@ -508,6 +508,11 @@ public:
|
||||||
* @return true if successful
|
* @return true if successful
|
||||||
*/
|
*/
|
||||||
virtual bool send_enb_status_transfer_proc(uint16_t rnti, std::vector<bearer_status_info>& bearer_status_list) = 0;
|
virtual bool send_enb_status_transfer_proc(uint16_t rnti, std::vector<bearer_status_info>& bearer_status_list) = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Notify MME that Handover is complete
|
||||||
|
*/
|
||||||
|
virtual void send_ho_notify(uint16_t rnti, uint64_t target_eci) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Combined interface for PHY to access stack (MAC and RRC)
|
// Combined interface for PHY to access stack (MAC and RRC)
|
||||||
|
|
|
@ -468,7 +468,7 @@ SRSASN_CODE pack_constrained_whole_number(bit_ref& bref, IntType n, IntType lb,
|
||||||
} else {
|
} else {
|
||||||
// TODO: Check if this is correct
|
// TODO: Check if this is correct
|
||||||
uint32_t n_bits_len = (uint32_t)ceilf(log2f(ceil_frac(n_bits, 8u)));
|
uint32_t n_bits_len = (uint32_t)ceilf(log2f(ceil_frac(n_bits, 8u)));
|
||||||
n_bits = (uint32_t)floorf(log2f(toencode) + 1);
|
n_bits = (uint32_t)floorf(log2f(SRSLTE_MAX(toencode, 1)) + 1);
|
||||||
uint32_t n_octets = (uint32_t)((n_bits + 7) / 8);
|
uint32_t n_octets = (uint32_t)((n_bits + 7) / 8);
|
||||||
HANDLE_CODE(bref.pack(n_octets - 1, n_bits_len));
|
HANDLE_CODE(bref.pack(n_octets - 1, n_bits_len));
|
||||||
HANDLE_CODE(bref.align_bytes_zero());
|
HANDLE_CODE(bref.align_bytes_zero());
|
||||||
|
|
|
@ -43,6 +43,9 @@ public:
|
||||||
void handle_con_reconf(const asn1::rrc::rrc_conn_recfg_r8_ies_s& conn_recfg);
|
void handle_con_reconf(const asn1::rrc::rrc_conn_recfg_r8_ies_s& conn_recfg);
|
||||||
void handle_con_reconf_complete();
|
void handle_con_reconf_complete();
|
||||||
|
|
||||||
|
void handle_ho_prep(const asn1::rrc::ho_prep_info_r8_ies_s& ho_prep);
|
||||||
|
void handle_ho_prep_complete();
|
||||||
|
|
||||||
const sched_interface::ue_cfg_t& get_ue_sched_cfg() const { return current_sched_ue_cfg; }
|
const sched_interface::ue_cfg_t& get_ue_sched_cfg() const { return current_sched_ue_cfg; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
|
@ -90,7 +90,8 @@ public:
|
||||||
void ho_preparation_complete(uint16_t rnti, bool is_success, srslte::unique_byte_buffer_t rrc_container) override;
|
void ho_preparation_complete(uint16_t rnti, bool is_success, srslte::unique_byte_buffer_t rrc_container) override;
|
||||||
uint16_t start_ho_ue_resource_alloc(const asn1::s1ap::ho_request_s& msg,
|
uint16_t start_ho_ue_resource_alloc(const asn1::s1ap::ho_request_s& msg,
|
||||||
const asn1::s1ap::sourceenb_to_targetenb_transparent_container_s& container,
|
const asn1::s1ap::sourceenb_to_targetenb_transparent_container_s& container,
|
||||||
srslte::byte_buffer_t& ho_cmd) override;
|
srslte::byte_buffer_t& ho_cmd,
|
||||||
|
std::vector<asn1::fixed_octstring<4, true> >& admitted_erabs) override;
|
||||||
|
|
||||||
// rrc_interface_pdcp
|
// rrc_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;
|
||||||
|
@ -98,7 +99,7 @@ public:
|
||||||
uint32_t get_nof_users();
|
uint32_t get_nof_users();
|
||||||
|
|
||||||
// logging
|
// logging
|
||||||
typedef enum { Rx = 0, Tx, S1AP } direction_t;
|
typedef enum { Rx = 0, Tx, S1AP, fromS1AP } direction_t;
|
||||||
template <class T>
|
template <class T>
|
||||||
void log_rrc_message(const std::string& source,
|
void log_rrc_message(const std::string& source,
|
||||||
const direction_t dir,
|
const direction_t dir,
|
||||||
|
@ -106,18 +107,23 @@ public:
|
||||||
const T& msg,
|
const T& msg,
|
||||||
const std::string& msg_type)
|
const std::string& msg_type)
|
||||||
{
|
{
|
||||||
|
log_rrc_message(source, dir, srslte::make_span(*pdu), msg, msg_type);
|
||||||
|
}
|
||||||
|
template <class T>
|
||||||
|
void log_rrc_message(const std::string& source,
|
||||||
|
const direction_t dir,
|
||||||
|
srslte::const_byte_span pdu,
|
||||||
|
const T& msg,
|
||||||
|
const std::string& msg_type)
|
||||||
|
{
|
||||||
|
static const char* dir_str[] = {"Rx", "Tx", "S1AP Tx", "S1AP Rx"};
|
||||||
if (rrc_log->get_level() == srslte::LOG_LEVEL_INFO) {
|
if (rrc_log->get_level() == srslte::LOG_LEVEL_INFO) {
|
||||||
rrc_log->info("%s - %s %s (%d B)\n", source.c_str(), dir == Tx ? "Tx" : "Rx", msg_type.c_str(), pdu->N_bytes);
|
rrc_log->info("%s - %s %s (%zd B)\n", source.c_str(), dir_str[dir], msg_type.c_str(), pdu.size());
|
||||||
} else if (rrc_log->get_level() >= srslte::LOG_LEVEL_DEBUG) {
|
} else if (rrc_log->get_level() >= srslte::LOG_LEVEL_DEBUG) {
|
||||||
asn1::json_writer json_writer;
|
asn1::json_writer json_writer;
|
||||||
msg.to_json(json_writer);
|
msg.to_json(json_writer);
|
||||||
rrc_log->debug_hex(pdu->msg,
|
rrc_log->debug_hex(
|
||||||
pdu->N_bytes,
|
pdu.data(), pdu.size(), "%s - %s %s (%zd B)\n", source.c_str(), dir_str[dir], msg_type.c_str(), pdu.size());
|
||||||
"%s - %s %s (%d B)\n",
|
|
||||||
source.c_str(),
|
|
||||||
dir == Tx ? "Tx" : "Rx",
|
|
||||||
msg_type.c_str(),
|
|
||||||
pdu->N_bytes);
|
|
||||||
rrc_log->debug_long("Content:\n%s\n", json_writer.to_string().c_str());
|
rrc_log->debug_long("Content:\n%s\n", json_writer.to_string().c_str());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -88,7 +88,8 @@ public:
|
||||||
|
|
||||||
uint16_t start_ho_ue_resource_alloc(const asn1::s1ap::ho_request_s& msg,
|
uint16_t start_ho_ue_resource_alloc(const asn1::s1ap::ho_request_s& msg,
|
||||||
const asn1::s1ap::sourceenb_to_targetenb_transparent_container_s& container,
|
const asn1::s1ap::sourceenb_to_targetenb_transparent_container_s& container,
|
||||||
srslte::byte_buffer_t& ho_cmd);
|
srslte::byte_buffer_t& ho_cmd,
|
||||||
|
std::vector<asn1::fixed_octstring<4, true> >& admitted_erabs);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// args
|
// args
|
||||||
|
@ -114,7 +115,8 @@ public:
|
||||||
// S1-Handover
|
// S1-Handover
|
||||||
bool start_s1_tenb_ho(const asn1::s1ap::ho_request_s& msg,
|
bool start_s1_tenb_ho(const asn1::s1ap::ho_request_s& msg,
|
||||||
const asn1::s1ap::sourceenb_to_targetenb_transparent_container_s& container,
|
const asn1::s1ap::sourceenb_to_targetenb_transparent_container_s& container,
|
||||||
srslte::byte_buffer_t& ho_cmd);
|
srslte::byte_buffer_t& ho_cmd,
|
||||||
|
std::vector<asn1::fixed_octstring<4, true> >& admitted_erabs);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// Handover from source cell
|
// Handover from source cell
|
||||||
|
@ -146,7 +148,10 @@ private:
|
||||||
const asn1::rrc::meas_obj_to_add_mod_s* meas_obj = nullptr;
|
const asn1::rrc::meas_obj_to_add_mod_s* meas_obj = nullptr;
|
||||||
};
|
};
|
||||||
struct ho_req_rx_ev {
|
struct ho_req_rx_ev {
|
||||||
uint32_t target_cell_id;
|
asn1::rrc::rrc_conn_recfg_r8_ies_s ho_cmd;
|
||||||
|
const asn1::s1ap::ho_request_s* ho_req_msg;
|
||||||
|
const asn1::rrc::ho_prep_info_r8_ies_s* ho_prep_r8;
|
||||||
|
const asn1::s1ap::sourceenb_to_targetenb_transparent_container_s* transparent_container;
|
||||||
};
|
};
|
||||||
using unsuccessful_outcome_ev = std::false_type;
|
using unsuccessful_outcome_ev = std::false_type;
|
||||||
using recfg_complete_ev = asn1::rrc::rrc_conn_recfg_complete_s;
|
using recfg_complete_ev = asn1::rrc::rrc_conn_recfg_complete_s;
|
||||||
|
@ -161,7 +166,7 @@ private:
|
||||||
void enter(rrc_mobility* f, const ho_meas_report_ev& meas_report);
|
void enter(rrc_mobility* f, const ho_meas_report_ev& meas_report);
|
||||||
};
|
};
|
||||||
struct s1_target_ho_st {
|
struct s1_target_ho_st {
|
||||||
uint32_t target_cell_id;
|
void enter(rrc_mobility* f, const ho_req_rx_ev& ho_req);
|
||||||
};
|
};
|
||||||
struct s1_source_ho_st : public subfsm_t<s1_source_ho_st> {
|
struct s1_source_ho_st : public subfsm_t<s1_source_ho_st> {
|
||||||
ho_meas_report_ev report;
|
ho_meas_report_ev report;
|
||||||
|
@ -199,6 +204,7 @@ private:
|
||||||
|
|
||||||
// FSM transition handlers
|
// FSM transition handlers
|
||||||
void handle_crnti_ce(intraenb_ho_st& s, const user_crnti_upd_ev& ev);
|
void handle_crnti_ce(intraenb_ho_st& s, const user_crnti_upd_ev& ev);
|
||||||
|
void handle_recfg_complete(s1_target_ho_st& s, const recfg_complete_ev& ev);
|
||||||
void handle_recfg_complete(intraenb_ho_st& s, const recfg_complete_ev& ev);
|
void handle_recfg_complete(intraenb_ho_st& s, const recfg_complete_ev& ev);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
@ -213,14 +219,17 @@ protected:
|
||||||
using fsm = rrc_mobility;
|
using fsm = rrc_mobility;
|
||||||
// clang-format off
|
// clang-format off
|
||||||
using transitions = transition_table<
|
using transitions = transition_table<
|
||||||
// Start Target Event Action Guard
|
// Start Target Event Action Guard
|
||||||
// +---------------+----------------+--------------------+---------------------------+-------------------------+
|
// +----------------+----------------+--------------------+---------------------------+-------------------------+
|
||||||
row< idle_st, s1_source_ho_st, ho_meas_report_ev, nullptr, &fsm::needs_s1_ho >,
|
row< idle_st, s1_source_ho_st, ho_meas_report_ev, nullptr, &fsm::needs_s1_ho >,
|
||||||
row< idle_st, intraenb_ho_st, ho_meas_report_ev, nullptr, &fsm::needs_intraenb_ho >,
|
row< idle_st, intraenb_ho_st, ho_meas_report_ev, nullptr, &fsm::needs_intraenb_ho >,
|
||||||
// +---------------+----------------+--------------------+---------------------------+-------------------------+
|
row< idle_st, s1_target_ho_st, ho_req_rx_ev >,
|
||||||
upd< intraenb_ho_st, user_crnti_upd_ev, &fsm::handle_crnti_ce >,
|
// +----------------+----------------+--------------------+---------------------------+-------------------------+
|
||||||
row< intraenb_ho_st, idle_st, recfg_complete_ev, &fsm::handle_recfg_complete >
|
upd< intraenb_ho_st, user_crnti_upd_ev, &fsm::handle_crnti_ce >,
|
||||||
// +---------------+----------------+--------------------+---------------------------+-------------------------+
|
row< intraenb_ho_st, idle_st, recfg_complete_ev, &fsm::handle_recfg_complete >,
|
||||||
|
// +----------------+----------------+--------------------+---------------------------+-------------------------+
|
||||||
|
row< s1_target_ho_st, idle_st, recfg_complete_ev, &fsm::handle_recfg_complete >
|
||||||
|
// +----------------+----------------+--------------------+---------------------------+-------------------------+
|
||||||
>;
|
>;
|
||||||
// clang-format on
|
// clang-format on
|
||||||
};
|
};
|
||||||
|
|
|
@ -82,7 +82,11 @@ public:
|
||||||
srslte::unique_byte_buffer_t rrc_container) override;
|
srslte::unique_byte_buffer_t rrc_container) override;
|
||||||
bool send_enb_status_transfer_proc(uint16_t rnti, std::vector<bearer_status_info>& bearer_status_list) override;
|
bool send_enb_status_transfer_proc(uint16_t rnti, std::vector<bearer_status_info>& bearer_status_list) override;
|
||||||
bool send_ho_failure(uint32_t mme_ue_s1ap_id);
|
bool send_ho_failure(uint32_t mme_ue_s1ap_id);
|
||||||
bool send_ho_req_ack(const asn1::s1ap::ho_request_s& msg, uint16_t rnti, srslte::unique_byte_buffer_t ho_cmd);
|
bool send_ho_req_ack(const asn1::s1ap::ho_request_s& msg,
|
||||||
|
uint16_t rnti,
|
||||||
|
srslte::unique_byte_buffer_t ho_cmd,
|
||||||
|
srslte::span<asn1::fixed_octstring<4, true> > admitted_bearers);
|
||||||
|
void send_ho_notify(uint16_t rnti, uint64_t target_eci) override;
|
||||||
// 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);
|
||||||
|
|
||||||
// Stack interface
|
// Stack interface
|
||||||
|
|
|
@ -302,4 +302,11 @@ void rrc::ue::mac_controller::apply_scell_cfg_updates(uint32_t ue_cc_idx)
|
||||||
pending_scells_cfg->erase(it);
|
pending_scells_cfg->erase(it);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void rrc::ue::mac_controller::handle_ho_prep(const asn1::rrc::ho_prep_info_r8_ies_s& ho_prep) {}
|
||||||
|
|
||||||
|
void rrc::ue::mac_controller::handle_ho_prep_complete()
|
||||||
|
{
|
||||||
|
apply_current_bearers_cfg();
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace srsenb
|
} // namespace srsenb
|
||||||
|
|
|
@ -464,9 +464,10 @@ void rrc::ho_preparation_complete(uint16_t rnti, bool is_success, srslte::unique
|
||||||
|
|
||||||
uint16_t rrc::start_ho_ue_resource_alloc(const asn1::s1ap::ho_request_s& msg,
|
uint16_t rrc::start_ho_ue_resource_alloc(const asn1::s1ap::ho_request_s& msg,
|
||||||
const asn1::s1ap::sourceenb_to_targetenb_transparent_container_s& container,
|
const asn1::s1ap::sourceenb_to_targetenb_transparent_container_s& container,
|
||||||
srslte::byte_buffer_t& ho_cmd)
|
srslte::byte_buffer_t& ho_cmd,
|
||||||
|
std::vector<asn1::fixed_octstring<4, true> >& admitted_erabs)
|
||||||
{
|
{
|
||||||
return enb_mobility_cfg->start_ho_ue_resource_alloc(msg, container, ho_cmd);
|
return enb_mobility_cfg->start_ho_ue_resource_alloc(msg, container, ho_cmd, admitted_erabs);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
|
|
|
@ -25,6 +25,7 @@
|
||||||
#include "srslte/asn1/rrc_asn1_utils.h"
|
#include "srslte/asn1/rrc_asn1_utils.h"
|
||||||
#include "srslte/common/bcd_helpers.h"
|
#include "srslte/common/bcd_helpers.h"
|
||||||
#include "srslte/common/common.h"
|
#include "srslte/common/common.h"
|
||||||
|
#include "srslte/common/int_helpers.h"
|
||||||
#include "srslte/rrc/rrc_cfg_utils.h"
|
#include "srslte/rrc/rrc_cfg_utils.h"
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
|
@ -471,7 +472,8 @@ rrc::enb_mobility_handler::enb_mobility_handler(rrc* rrc_) : rrc_ptr(rrc_), cfg(
|
||||||
uint16_t rrc::enb_mobility_handler::start_ho_ue_resource_alloc(
|
uint16_t rrc::enb_mobility_handler::start_ho_ue_resource_alloc(
|
||||||
const asn1::s1ap::ho_request_s& msg,
|
const asn1::s1ap::ho_request_s& msg,
|
||||||
const asn1::s1ap::sourceenb_to_targetenb_transparent_container_s& container,
|
const asn1::s1ap::sourceenb_to_targetenb_transparent_container_s& container,
|
||||||
srslte::byte_buffer_t& ho_cmd)
|
srslte::byte_buffer_t& ho_cmd,
|
||||||
|
std::vector<asn1::fixed_octstring<4, true> >& admitted_erabs)
|
||||||
{
|
{
|
||||||
// TODO: Decision Making on whether the same QoS of the source eNB can be provided by target eNB
|
// TODO: Decision Making on whether the same QoS of the source eNB can be provided by target eNB
|
||||||
|
|
||||||
|
@ -515,7 +517,7 @@ uint16_t rrc::enb_mobility_handler::start_ho_ue_resource_alloc(
|
||||||
return SRSLTE_INVALID_RNTI;
|
return SRSLTE_INVALID_RNTI;
|
||||||
}
|
}
|
||||||
ue* ue_ptr = it->second.get();
|
ue* ue_ptr = it->second.get();
|
||||||
if (not ue_ptr->mobility_handler->start_s1_tenb_ho(msg, container, ho_cmd)) {
|
if (not ue_ptr->mobility_handler->start_s1_tenb_ho(msg, container, ho_cmd, admitted_erabs)) {
|
||||||
return SRSLTE_INVALID_RNTI;
|
return SRSLTE_INVALID_RNTI;
|
||||||
}
|
}
|
||||||
return rnti;
|
return rnti;
|
||||||
|
@ -691,11 +693,9 @@ bool rrc::ue::rrc_mobility::start_ho_preparation(uint32_t target_eci,
|
||||||
rrc_ue->last_rrc_conn_recfg.crit_exts.c1().rrc_conn_recfg_r8().rr_cfg_ded.phys_cfg_ded_present;
|
rrc_ue->last_rrc_conn_recfg.crit_exts.c1().rrc_conn_recfg_r8().rr_cfg_ded.phys_cfg_ded_present;
|
||||||
hoprep_r8.as_cfg.source_rr_cfg.phys_cfg_ded =
|
hoprep_r8.as_cfg.source_rr_cfg.phys_cfg_ded =
|
||||||
rrc_ue->last_rrc_conn_recfg.crit_exts.c1().rrc_conn_recfg_r8().rr_cfg_ded.phys_cfg_ded;
|
rrc_ue->last_rrc_conn_recfg.crit_exts.c1().rrc_conn_recfg_r8().rr_cfg_ded.phys_cfg_ded;
|
||||||
// Add SRB2 to the message
|
// Add SRBs to the message
|
||||||
hoprep_r8.as_cfg.source_rr_cfg.srb_to_add_mod_list_present =
|
hoprep_r8.as_cfg.source_rr_cfg.srb_to_add_mod_list_present = true;
|
||||||
rrc_ue->last_rrc_conn_recfg.crit_exts.c1().rrc_conn_recfg_r8().rr_cfg_ded.srb_to_add_mod_list_present;
|
hoprep_r8.as_cfg.source_rr_cfg.srb_to_add_mod_list = rrc_ue->bearer_list.get_established_srbs();
|
||||||
hoprep_r8.as_cfg.source_rr_cfg.srb_to_add_mod_list =
|
|
||||||
rrc_ue->last_rrc_conn_recfg.crit_exts.c1().rrc_conn_recfg_r8().rr_cfg_ded.srb_to_add_mod_list;
|
|
||||||
// hoprep_r8.as_cfg.source_rr_cfg.srb_to_add_mod_list_present = true;
|
// hoprep_r8.as_cfg.source_rr_cfg.srb_to_add_mod_list_present = true;
|
||||||
// asn1::rrc::srb_to_add_mod_list_l& srb_list = hoprep_r8.as_cfg.source_rr_cfg.srb_to_add_mod_list;
|
// asn1::rrc::srb_to_add_mod_list_l& srb_list = hoprep_r8.as_cfg.source_rr_cfg.srb_to_add_mod_list;
|
||||||
// srb_list.resize(1);
|
// srb_list.resize(1);
|
||||||
|
@ -789,7 +789,8 @@ void rrc::ue::rrc_mobility::handle_ho_preparation_complete(bool is_success, srsl
|
||||||
bool rrc::ue::rrc_mobility::start_s1_tenb_ho(
|
bool rrc::ue::rrc_mobility::start_s1_tenb_ho(
|
||||||
const asn1::s1ap::ho_request_s& msg,
|
const asn1::s1ap::ho_request_s& msg,
|
||||||
const asn1::s1ap::sourceenb_to_targetenb_transparent_container_s& container,
|
const asn1::s1ap::sourceenb_to_targetenb_transparent_container_s& container,
|
||||||
srslte::byte_buffer_t& ho_cmd_pdu)
|
srslte::byte_buffer_t& ho_cmd_pdu,
|
||||||
|
std::vector<asn1::fixed_octstring<4, true> >& admitted_erabs)
|
||||||
{
|
{
|
||||||
const cell_ctxt_dedicated* target_cell = rrc_ue->cell_ded_list.get_ue_cc_idx(UE_PCELL_CC_IDX);
|
const cell_ctxt_dedicated* target_cell = rrc_ue->cell_ded_list.get_ue_cc_idx(UE_PCELL_CC_IDX);
|
||||||
|
|
||||||
|
@ -806,6 +807,8 @@ bool rrc::ue::rrc_mobility::start_s1_tenb_ho(
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
const ho_prep_info_r8_ies_s& hoprep_r8 = hoprep.crit_exts.c1().ho_prep_info_r8();
|
const ho_prep_info_r8_ies_s& hoprep_r8 = hoprep.crit_exts.c1().ho_prep_info_r8();
|
||||||
|
rrc_enb->log_rrc_message(
|
||||||
|
"HandoverPreparation", direction_t::fromS1AP, container.rrc_container, hoprep, "HandoverPreparation");
|
||||||
|
|
||||||
/* Prepare Handover Request Acknowledgment - Handover Command */
|
/* Prepare Handover Request Acknowledgment - Handover Command */
|
||||||
dl_dcch_msg_s dl_dcch_msg;
|
dl_dcch_msg_s dl_dcch_msg;
|
||||||
|
@ -840,7 +843,14 @@ bool rrc::ue::rrc_mobility::start_s1_tenb_ho(
|
||||||
}
|
}
|
||||||
ho_cmd_pdu.N_bytes = bref2.distance_bytes();
|
ho_cmd_pdu.N_bytes = bref2.distance_bytes();
|
||||||
|
|
||||||
return true;
|
trigger(ho_req_rx_ev{recfg_r8, &msg, &hoprep_r8, &container});
|
||||||
|
|
||||||
|
for (auto& erab : rrc_ue->bearer_list.get_erabs()) {
|
||||||
|
admitted_erabs.push_back({});
|
||||||
|
srslte::uint32_to_uint8(erab.second.teid_in, admitted_erabs.back().data());
|
||||||
|
}
|
||||||
|
|
||||||
|
return is_in_state<s1_target_ho_st>();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool rrc::ue::rrc_mobility::update_ue_var_meas_cfg(const asn1::rrc::meas_cfg_s& source_meas_cfg,
|
bool rrc::ue::rrc_mobility::update_ue_var_meas_cfg(const asn1::rrc::meas_cfg_s& source_meas_cfg,
|
||||||
|
@ -1076,6 +1086,69 @@ void rrc::ue::rrc_mobility::s1_source_ho_st::status_transfer_st::enter(s1_source
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*************************************
|
||||||
|
* s1_target_ho state methods
|
||||||
|
*************************************/
|
||||||
|
|
||||||
|
void rrc::ue::rrc_mobility::s1_target_ho_st::enter(rrc_mobility* f, const ho_req_rx_ev& ho_req)
|
||||||
|
{
|
||||||
|
const cell_ctxt_dedicated* target_cell = f->rrc_ue->cell_ded_list.get_ue_cc_idx(UE_PCELL_CC_IDX);
|
||||||
|
const cell_cfg_t& target_cell_cfg = target_cell->cell_common->cell_cfg;
|
||||||
|
const asn1::rrc::rr_cfg_ded_s& src_rr_cfg = ho_req.ho_prep_r8->as_cfg.source_rr_cfg;
|
||||||
|
const asn1::s1ap::ho_request_s& msg = *ho_req.ho_req_msg;
|
||||||
|
|
||||||
|
// Establish SRBs
|
||||||
|
if (src_rr_cfg.srb_to_add_mod_list_present) {
|
||||||
|
for (auto& srb : src_rr_cfg.srb_to_add_mod_list) {
|
||||||
|
f->rrc_ue->bearer_list.add_srb(srb.srb_id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Establish ERABs/DRBs
|
||||||
|
for (const auto& erab_item : msg.protocol_ies.erab_to_be_setup_list_ho_req.value) {
|
||||||
|
auto& erab = erab_item.value.erab_to_be_setup_item_ho_req();
|
||||||
|
if (erab.ext) {
|
||||||
|
f->log_h->warning("Not handling E-RABToBeSetupList extensions\n");
|
||||||
|
}
|
||||||
|
if (erab.ie_exts_present) {
|
||||||
|
f->log_h->warning("Not handling E-RABToBeSetupList extensions\n");
|
||||||
|
}
|
||||||
|
if (erab.transport_layer_address.length() > 32) {
|
||||||
|
f->log_h->error("IPv6 addresses not currently supported\n");
|
||||||
|
f->trigger(srslte::failure_ev{});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t teid_out;
|
||||||
|
srslte::uint8_to_uint32(erab.gtp_teid.data(), &teid_out);
|
||||||
|
f->rrc_ue->bearer_list.add_erab(
|
||||||
|
erab.erab_id, erab.erab_level_qos_params, erab.transport_layer_address, teid_out, nullptr);
|
||||||
|
f->rrc_ue->bearer_list.add_gtpu_bearer(f->rrc_enb->gtpu, erab.erab_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update MAC
|
||||||
|
f->rrc_ue->mac_ctrl->handle_ho_prep(*ho_req.ho_prep_r8);
|
||||||
|
|
||||||
|
// Update RLC + PDCP
|
||||||
|
f->rrc_ue->ue_security_cfg.regenerate_keys_handover(target_cell_cfg.pci, target_cell_cfg.dl_earfcn);
|
||||||
|
f->rrc_ue->bearer_list.apply_pdcp_bearer_updates(f->rrc_enb->pdcp, f->rrc_ue->ue_security_cfg);
|
||||||
|
f->rrc_ue->bearer_list.apply_rlc_bearer_updates(f->rrc_enb->rlc);
|
||||||
|
}
|
||||||
|
|
||||||
|
void rrc::ue::rrc_mobility::handle_recfg_complete(s1_target_ho_st& s, const recfg_complete_ev& ev)
|
||||||
|
{
|
||||||
|
cell_ctxt_dedicated* target_cell = rrc_ue->cell_ded_list.get_ue_cc_idx(UE_PCELL_CC_IDX);
|
||||||
|
rrc_log->info("User rnti=0x%x successfully handovered to cell_id=0x%x\n",
|
||||||
|
rrc_ue->rnti,
|
||||||
|
target_cell->cell_common->cell_cfg.cell_id);
|
||||||
|
uint64_t target_eci = (rrc_enb->cfg.enb_id << 8u) + target_cell->cell_common->cell_cfg.cell_id;
|
||||||
|
|
||||||
|
// Activate bearers in MAC
|
||||||
|
rrc_ue->mac_ctrl->handle_ho_prep_complete();
|
||||||
|
|
||||||
|
rrc_enb->s1ap->send_ho_notify(rrc_ue->rnti, target_eci);
|
||||||
|
}
|
||||||
|
|
||||||
/*************************************************************************************************
|
/*************************************************************************************************
|
||||||
* intraENB Handover sub-FSM
|
* intraENB Handover sub-FSM
|
||||||
************************************************************************************************/
|
************************************************************************************************/
|
||||||
|
|
|
@ -46,6 +46,17 @@ using namespace asn1::s1ap;
|
||||||
|
|
||||||
namespace srsenb {
|
namespace srsenb {
|
||||||
|
|
||||||
|
asn1::bounded_bitstring<1, 160, true, true> addr_to_asn1(const char* addr_str)
|
||||||
|
{
|
||||||
|
asn1::bounded_bitstring<1, 160, true, true> transport_layer_addr(32);
|
||||||
|
uint8_t addr[4];
|
||||||
|
inet_pton(AF_INET, addr_str, addr);
|
||||||
|
for (uint32_t j = 0; j < 4; ++j) {
|
||||||
|
transport_layer_addr.data()[j] = addr[3 - j];
|
||||||
|
}
|
||||||
|
return transport_layer_addr;
|
||||||
|
}
|
||||||
|
|
||||||
/*********************************************************
|
/*********************************************************
|
||||||
* TS 36.413 - Section 8.4.1 - "Handover Preparation"
|
* TS 36.413 - Section 8.4.1 - "Handover Preparation"
|
||||||
*********************************************************/
|
*********************************************************/
|
||||||
|
@ -837,13 +848,14 @@ bool s1ap::handle_ho_request(const asn1::s1ap::ho_request_s& msg)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Handle Handover Resource Allocation
|
// Handle Handover Resource Allocation
|
||||||
srslte::unique_byte_buffer_t ho_cmd = srslte::allocate_unique_buffer(*pool);
|
srslte::unique_byte_buffer_t ho_cmd = srslte::allocate_unique_buffer(*pool);
|
||||||
uint16_t rnti = rrc->start_ho_ue_resource_alloc(msg, container, *ho_cmd);
|
std::vector<asn1::fixed_octstring<4, true> > admitted_erabs;
|
||||||
|
uint16_t rnti = rrc->start_ho_ue_resource_alloc(msg, container, *ho_cmd, admitted_erabs);
|
||||||
if (rnti == SRSLTE_INVALID_RNTI) {
|
if (rnti == SRSLTE_INVALID_RNTI) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return send_ho_req_ack(msg, rnti, std::move(ho_cmd));
|
return send_ho_req_ack(msg, rnti, std::move(ho_cmd), admitted_erabs);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool s1ap::send_ho_failure(uint32_t mme_ue_s1ap_id)
|
bool s1ap::send_ho_failure(uint32_t mme_ue_s1ap_id)
|
||||||
|
@ -859,7 +871,10 @@ bool s1ap::send_ho_failure(uint32_t mme_ue_s1ap_id)
|
||||||
return sctp_send_s1ap_pdu(tx_pdu, SRSLTE_INVALID_RNTI, "HandoverFailure");
|
return sctp_send_s1ap_pdu(tx_pdu, SRSLTE_INVALID_RNTI, "HandoverFailure");
|
||||||
}
|
}
|
||||||
|
|
||||||
bool s1ap::send_ho_req_ack(const asn1::s1ap::ho_request_s& msg, uint16_t rnti, srslte::unique_byte_buffer_t ho_cmd)
|
bool s1ap::send_ho_req_ack(const asn1::s1ap::ho_request_s& msg,
|
||||||
|
uint16_t rnti,
|
||||||
|
srslte::unique_byte_buffer_t ho_cmd,
|
||||||
|
srslte::span<asn1::fixed_octstring<4, true> > admitted_bearers)
|
||||||
{
|
{
|
||||||
s1ap_pdu_c tx_pdu;
|
s1ap_pdu_c tx_pdu;
|
||||||
tx_pdu.set_successful_outcome().load_info_obj(ASN1_S1AP_ID_HO_RES_ALLOC);
|
tx_pdu.set_successful_outcome().load_info_obj(ASN1_S1AP_ID_HO_RES_ALLOC);
|
||||||
|
@ -872,14 +887,19 @@ bool s1ap::send_ho_req_ack(const asn1::s1ap::ho_request_s& msg, uint16_t rnti, s
|
||||||
container.enb_ue_s1ap_id.value = ue_ptr->ctxt.enb_ue_s1ap_id;
|
container.enb_ue_s1ap_id.value = ue_ptr->ctxt.enb_ue_s1ap_id;
|
||||||
|
|
||||||
// TODO: Add admitted E-RABs
|
// TODO: Add admitted E-RABs
|
||||||
for (const auto& erab : msg.protocol_ies.erab_to_be_setup_list_ho_req.value) {
|
for (uint32_t i = 0; i < msg.protocol_ies.erab_to_be_setup_list_ho_req.value.size(); ++i) {
|
||||||
|
const auto& erab = msg.protocol_ies.erab_to_be_setup_list_ho_req.value[i];
|
||||||
const erab_to_be_setup_item_ho_req_s& erabsetup = erab.value.erab_to_be_setup_item_ho_req();
|
const erab_to_be_setup_item_ho_req_s& erabsetup = erab.value.erab_to_be_setup_item_ho_req();
|
||||||
container.erab_admitted_list.value.push_back({});
|
container.erab_admitted_list.value.push_back({});
|
||||||
container.erab_admitted_list.value.back().load_info_obj(ASN1_S1AP_ID_ERAB_ADMITTED_ITEM);
|
container.erab_admitted_list.value.back().load_info_obj(ASN1_S1AP_ID_ERAB_ADMITTED_ITEM);
|
||||||
auto& c = container.erab_admitted_list.value.back().value.erab_admitted_item();
|
auto& c = container.erab_admitted_list.value.back().value.erab_admitted_item();
|
||||||
c.erab_id = erabsetup.erab_id;
|
c.erab_id = erabsetup.erab_id;
|
||||||
c.gtp_teid = erabsetup.gtp_teid;
|
c.gtp_teid = admitted_bearers[i];
|
||||||
c.transport_layer_address = erabsetup.transport_layer_address;
|
c.transport_layer_address = addr_to_asn1(args.gtp_bind_addr.c_str());
|
||||||
|
// c.dl_transport_layer_address_present = true;
|
||||||
|
// c.dl_transport_layer_address = c.transport_layer_address;
|
||||||
|
// c.ul_transport_layer_address_present = true;
|
||||||
|
// c.ul_transport_layer_address = c.transport_layer_address;
|
||||||
}
|
}
|
||||||
asn1::s1ap::targetenb_to_sourceenb_transparent_container_s transparent_container;
|
asn1::s1ap::targetenb_to_sourceenb_transparent_container_s transparent_container;
|
||||||
transparent_container.rrc_container.resize(ho_cmd->N_bytes);
|
transparent_container.rrc_container.resize(ho_cmd->N_bytes);
|
||||||
|
@ -897,6 +917,28 @@ bool s1ap::send_ho_req_ack(const asn1::s1ap::ho_request_s& msg, uint16_t rnti, s
|
||||||
return sctp_send_s1ap_pdu(tx_pdu, rnti, "HandoverRequestAcknowledge");
|
return sctp_send_s1ap_pdu(tx_pdu, rnti, "HandoverRequestAcknowledge");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void s1ap::send_ho_notify(uint16_t rnti, uint64_t target_eci)
|
||||||
|
{
|
||||||
|
ue* user_ptr = users.find_ue_rnti(rnti);
|
||||||
|
if (user_ptr == nullptr) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
s1ap_pdu_c tx_pdu;
|
||||||
|
|
||||||
|
tx_pdu.set_init_msg().load_info_obj(ASN1_S1AP_ID_HO_NOTIF);
|
||||||
|
ho_notify_ies_container& container = tx_pdu.init_msg().value.ho_notify().protocol_ies;
|
||||||
|
|
||||||
|
container.mme_ue_s1ap_id.value = user_ptr->ctxt.mme_ue_s1ap_id;
|
||||||
|
container.enb_ue_s1ap_id.value = user_ptr->ctxt.enb_ue_s1ap_id;
|
||||||
|
|
||||||
|
container.eutran_cgi.value = eutran_cgi;
|
||||||
|
container.eutran_cgi.value.cell_id.from_number(target_eci);
|
||||||
|
container.tai.value = tai;
|
||||||
|
|
||||||
|
sctp_send_s1ap_pdu(tx_pdu, rnti, "HandoverNotify");
|
||||||
|
}
|
||||||
|
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
/* S1AP message senders
|
/* S1AP message senders
|
||||||
********************************************************************************/
|
********************************************************************************/
|
||||||
|
@ -1472,6 +1514,10 @@ bool s1ap::ue::send_enb_status_transfer_proc(std::vector<bearer_status_info>& be
|
||||||
asn1bearer.ul_coun_tvalue.pdcp_sn = item.pdcp_ul_sn;
|
asn1bearer.ul_coun_tvalue.pdcp_sn = item.pdcp_ul_sn;
|
||||||
asn1bearer.ul_coun_tvalue.hfn = item.ul_hfn;
|
asn1bearer.ul_coun_tvalue.hfn = item.ul_hfn;
|
||||||
// TODO: asn1bearer.receiveStatusofULPDCPSDUs_present
|
// TODO: asn1bearer.receiveStatusofULPDCPSDUs_present
|
||||||
|
|
||||||
|
// asn1::json_writer jw;
|
||||||
|
// asn1bearer.to_json(jw);
|
||||||
|
// printf("Bearer to add %s\n", jw.to_string().c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
return s1ap_ptr->sctp_send_s1ap_pdu(tx_pdu, ctxt.rnti, "ENBStatusTransfer");
|
return s1ap_ptr->sctp_send_s1ap_pdu(tx_pdu, ctxt.rnti, "ENBStatusTransfer");
|
||||||
|
|
|
@ -105,6 +105,7 @@ public:
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
void send_ho_notify(uint16_t rnti, uint64_t target_eci) override {}
|
||||||
};
|
};
|
||||||
|
|
||||||
class phy_dummy : public phy_interface_rrc_lte
|
class phy_dummy : public phy_interface_rrc_lte
|
||||||
|
|
|
@ -413,6 +413,9 @@ int test_s1ap_mobility(mobility_test_params test_params)
|
||||||
ho_prep_info_r8_ies_s& hoprepr8 = hoprep.crit_exts.c1().ho_prep_info_r8();
|
ho_prep_info_r8_ies_s& hoprepr8 = hoprep.crit_exts.c1().ho_prep_info_r8();
|
||||||
TESTASSERT(hoprepr8.as_cfg_present);
|
TESTASSERT(hoprepr8.as_cfg_present);
|
||||||
// Check if RRC sends the current active bearers
|
// Check if RRC sends the current active bearers
|
||||||
|
TESTASSERT(hoprepr8.as_cfg.source_rr_cfg.srb_to_add_mod_list_present);
|
||||||
|
TESTASSERT(hoprepr8.as_cfg.source_rr_cfg.srb_to_add_mod_list[0].srb_id == 1);
|
||||||
|
TESTASSERT(hoprepr8.as_cfg.source_rr_cfg.srb_to_add_mod_list[1].srb_id == 2);
|
||||||
TESTASSERT(hoprepr8.as_cfg.source_rr_cfg.drb_to_add_mod_list_present);
|
TESTASSERT(hoprepr8.as_cfg.source_rr_cfg.drb_to_add_mod_list_present);
|
||||||
TESTASSERT(hoprepr8.as_cfg.source_rr_cfg.drb_to_add_mod_list[0].drb_id == 1);
|
TESTASSERT(hoprepr8.as_cfg.source_rr_cfg.drb_to_add_mod_list[0].drb_id == 1);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue