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
|
||||
{
|
||||
public:
|
||||
|
||||
/**
|
||||
* Removes an RNTI context from all the physical layer components, including secondary cells
|
||||
* @param rnti identifier of the user
|
||||
|
@ -438,7 +437,8 @@ public:
|
|||
virtual uint16_t
|
||||
start_ho_ue_resource_alloc(const asn1::s1ap::ho_request_s& msg,
|
||||
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
|
||||
|
@ -508,6 +508,11 @@ public:
|
|||
* @return true if successful
|
||||
*/
|
||||
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)
|
||||
|
|
|
@ -468,7 +468,7 @@ SRSASN_CODE pack_constrained_whole_number(bit_ref& bref, IntType n, IntType lb,
|
|||
} else {
|
||||
// TODO: Check if this is correct
|
||||
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);
|
||||
HANDLE_CODE(bref.pack(n_octets - 1, n_bits_len));
|
||||
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_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; }
|
||||
|
||||
private:
|
||||
|
|
|
@ -90,7 +90,8 @@ public:
|
|||
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,
|
||||
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
|
||||
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();
|
||||
|
||||
// logging
|
||||
typedef enum { Rx = 0, Tx, S1AP } direction_t;
|
||||
typedef enum { Rx = 0, Tx, S1AP, fromS1AP } direction_t;
|
||||
template <class T>
|
||||
void log_rrc_message(const std::string& source,
|
||||
const direction_t dir,
|
||||
|
@ -106,18 +107,23 @@ public:
|
|||
const T& msg,
|
||||
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) {
|
||||
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) {
|
||||
asn1::json_writer json_writer;
|
||||
msg.to_json(json_writer);
|
||||
rrc_log->debug_hex(pdu->msg,
|
||||
pdu->N_bytes,
|
||||
"%s - %s %s (%d B)\n",
|
||||
source.c_str(),
|
||||
dir == Tx ? "Tx" : "Rx",
|
||||
msg_type.c_str(),
|
||||
pdu->N_bytes);
|
||||
rrc_log->debug_hex(
|
||||
pdu.data(), pdu.size(), "%s - %s %s (%zd B)\n", source.c_str(), dir_str[dir], msg_type.c_str(), pdu.size());
|
||||
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,
|
||||
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:
|
||||
// args
|
||||
|
@ -114,7 +115,8 @@ public:
|
|||
// S1-Handover
|
||||
bool start_s1_tenb_ho(const asn1::s1ap::ho_request_s& msg,
|
||||
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:
|
||||
// Handover from source cell
|
||||
|
@ -146,7 +148,10 @@ private:
|
|||
const asn1::rrc::meas_obj_to_add_mod_s* meas_obj = nullptr;
|
||||
};
|
||||
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 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);
|
||||
};
|
||||
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> {
|
||||
ho_meas_report_ev report;
|
||||
|
@ -199,6 +204,7 @@ private:
|
|||
|
||||
// FSM transition handlers
|
||||
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);
|
||||
|
||||
protected:
|
||||
|
@ -214,13 +220,16 @@ protected:
|
|||
// clang-format off
|
||||
using transitions = transition_table<
|
||||
// Start Target Event Action Guard
|
||||
// +---------------+----------------+--------------------+---------------------------+-------------------------+
|
||||
// +----------------+----------------+--------------------+---------------------------+-------------------------+
|
||||
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, 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 >
|
||||
// +---------------+----------------+--------------------+---------------------------+-------------------------+
|
||||
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
|
||||
};
|
||||
|
|
|
@ -82,7 +82,11 @@ public:
|
|||
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_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);
|
||||
|
||||
// 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);
|
||||
}
|
||||
|
||||
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
|
||||
|
|
|
@ -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,
|
||||
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/common/bcd_helpers.h"
|
||||
#include "srslte/common/common.h"
|
||||
#include "srslte/common/int_helpers.h"
|
||||
#include "srslte/rrc/rrc_cfg_utils.h"
|
||||
#include <algorithm>
|
||||
#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(
|
||||
const asn1::s1ap::ho_request_s& msg,
|
||||
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
|
||||
|
||||
|
@ -515,7 +517,7 @@ uint16_t rrc::enb_mobility_handler::start_ho_ue_resource_alloc(
|
|||
return SRSLTE_INVALID_RNTI;
|
||||
}
|
||||
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 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;
|
||||
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;
|
||||
// Add SRB2 to the message
|
||||
hoprep_r8.as_cfg.source_rr_cfg.srb_to_add_mod_list_present =
|
||||
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->last_rrc_conn_recfg.crit_exts.c1().rrc_conn_recfg_r8().rr_cfg_ded.srb_to_add_mod_list;
|
||||
// Add SRBs to the message
|
||||
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 = rrc_ue->bearer_list.get_established_srbs();
|
||||
// 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;
|
||||
// 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(
|
||||
const asn1::s1ap::ho_request_s& msg,
|
||||
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);
|
||||
|
||||
|
@ -806,6 +807,8 @@ bool rrc::ue::rrc_mobility::start_s1_tenb_ho(
|
|||
return false;
|
||||
}
|
||||
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 */
|
||||
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();
|
||||
|
||||
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,
|
||||
|
@ -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
|
||||
************************************************************************************************/
|
||||
|
|
|
@ -46,6 +46,17 @@ using namespace asn1::s1ap;
|
|||
|
||||
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"
|
||||
*********************************************************/
|
||||
|
@ -838,12 +849,13 @@ bool s1ap::handle_ho_request(const asn1::s1ap::ho_request_s& msg)
|
|||
|
||||
// Handle Handover Resource Allocation
|
||||
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) {
|
||||
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)
|
||||
|
@ -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");
|
||||
}
|
||||
|
||||
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;
|
||||
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;
|
||||
|
||||
// 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();
|
||||
container.erab_admitted_list.value.push_back({});
|
||||
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();
|
||||
c.erab_id = erabsetup.erab_id;
|
||||
c.gtp_teid = erabsetup.gtp_teid;
|
||||
c.transport_layer_address = erabsetup.transport_layer_address;
|
||||
c.gtp_teid = admitted_bearers[i];
|
||||
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;
|
||||
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");
|
||||
}
|
||||
|
||||
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
|
||||
********************************************************************************/
|
||||
|
@ -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.hfn = item.ul_hfn;
|
||||
// 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");
|
||||
|
|
|
@ -105,6 +105,7 @@ public:
|
|||
{
|
||||
return true;
|
||||
}
|
||||
void send_ho_notify(uint16_t rnti, uint64_t target_eci) override {}
|
||||
};
|
||||
|
||||
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();
|
||||
TESTASSERT(hoprepr8.as_cfg_present);
|
||||
// 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[0].drb_id == 1);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue