diff --git a/lib/include/srsran/interfaces/enb_rrc_interface_types.h b/lib/include/srsran/interfaces/enb_rrc_interface_types.h index 9370ddb4e..d14f00785 100644 --- a/lib/include/srsran/interfaces/enb_rrc_interface_types.h +++ b/lib/include/srsran/interfaces/enb_rrc_interface_types.h @@ -32,6 +32,7 @@ struct meas_cell_cfg_t { uint16_t pci; uint32_t eci; float q_offset; + bool direct_forward_path_available; }; // neigh measurement Cell info diff --git a/lib/include/srsran/interfaces/enb_s1ap_interfaces.h b/lib/include/srsran/interfaces/enb_s1ap_interfaces.h index 4b214ed50..38fdf98f0 100644 --- a/lib/include/srsran/interfaces/enb_s1ap_interfaces.h +++ b/lib/include/srsran/interfaces/enb_s1ap_interfaces.h @@ -76,7 +76,8 @@ public: uint32_t target_eci, srsran::plmn_id_t target_plmn, srsran::span fwd_erabs, - srsran::unique_byte_buffer_t rrc_container) = 0; + srsran::unique_byte_buffer_t rrc_container, + bool has_direct_fwd_path) = 0; /** * Command the s1ap to transmit eNBStatusTransfer message to MME. This message passes the PDCP context of the UE diff --git a/srsenb/hdr/stack/rrc/rrc_mobility.h b/srsenb/hdr/stack/rrc/rrc_mobility.h index 9d7068388..8664be0a2 100644 --- a/srsenb/hdr/stack/rrc/rrc_mobility.h +++ b/srsenb/hdr/stack/rrc/rrc_mobility.h @@ -80,8 +80,9 @@ private: // events struct ho_meas_report_ev { - uint32_t target_eci = 0; - const asn1::rrc::meas_obj_to_add_mod_s* meas_obj = nullptr; + uint32_t target_eci = 0; + const asn1::rrc::meas_obj_to_add_mod_s* meas_obj = nullptr; + bool direct_fwd_path = false; }; struct ho_req_rx_ev { const asn1::s1ap::ho_request_s* ho_req_msg; diff --git a/srsenb/hdr/stack/upper/s1ap.h b/srsenb/hdr/stack/upper/s1ap.h index 07aa4d525..a7f53cba7 100644 --- a/srsenb/hdr/stack/upper/s1ap.h +++ b/srsenb/hdr/stack/upper/s1ap.h @@ -86,7 +86,8 @@ public: uint32_t target_eci, srsran::plmn_id_t target_plmn, srsran::span fwd_erabs, - srsran::unique_byte_buffer_t rrc_container) override; + srsran::unique_byte_buffer_t rrc_container, + bool has_direct_fwd_path) override; bool send_enb_status_transfer_proc(uint16_t rnti, std::vector& bearer_status_list) override; bool send_ho_req_ack(const asn1::s1ap::ho_request_s& msg, uint16_t rnti, @@ -213,7 +214,8 @@ private: srsran::proc_outcome_t init(uint32_t target_eci_, srsran::plmn_id_t target_plmn_, srsran::span fwd_erabs, - srsran::unique_byte_buffer_t rrc_container); + srsran::unique_byte_buffer_t rrc_container, + bool has_direct_fwd_path); srsran::proc_outcome_t step() { return srsran::proc_outcome_t::yield; } srsran::proc_outcome_t react(ts1_reloc_prep_expired e); srsran::proc_outcome_t react(const asn1::s1ap::ho_prep_fail_s& msg); @@ -263,7 +265,8 @@ private: bool send_ho_required(uint32_t target_eci_, srsran::plmn_id_t target_plmn_, srsran::span fwd_erabs, - srsran::unique_byte_buffer_t rrc_container); + srsran::unique_byte_buffer_t rrc_container, + bool has_direct_fwd_path); void get_erab_addr(uint16_t erab_id, transp_addr_t& transp_addr, asn1::fixed_octstring<4, true>& gtpu_teid_id); // args diff --git a/srsenb/rr.conf.example b/srsenb/rr.conf.example index a78d5e11b..af1eed69a 100644 --- a/srsenb/rr.conf.example +++ b/srsenb/rr.conf.example @@ -75,6 +75,7 @@ cell_list = eci = 0x19C02; dl_earfcn = 2850; pci = 2; + //direct_forward_path_available = false; } ); diff --git a/srsenb/src/enb_cfg_parser.cc b/srsenb/src/enb_cfg_parser.cc index 71993e7a8..06aba9fbe 100644 --- a/srsenb/src/enb_cfg_parser.cc +++ b/srsenb/src/enb_cfg_parser.cc @@ -675,15 +675,12 @@ static int parse_meas_cell_list(rrc_meas_cfg_t* meas_cfg, Setting& root) { meas_cfg->meas_cells.resize(root.getLength()); for (uint32_t i = 0; i < meas_cfg->meas_cells.size(); ++i) { - meas_cfg->meas_cells[i].earfcn = root[i]["dl_earfcn"]; - meas_cfg->meas_cells[i].pci = (unsigned int)root[i]["pci"] % SRSRAN_NUM_PCI; - meas_cfg->meas_cells[i].eci = (unsigned int)root[i]["eci"]; - meas_cfg->meas_cells[i].q_offset = 0; // LIBLTE_RRC_Q_OFFSET_RANGE_DB_0; // TODO - // // TODO: TEMP - // printf("PARSER: neighbor cell: {dl_earfcn=%d pci=%d cell_idx=0x%x}\n", - // meas_cfg->meas_cells[i].earfcn, - // meas_cfg->meas_cells[i].pci, - // meas_cfg->meas_cells[i].eci); + auto& cell = meas_cfg->meas_cells[i]; + cell.earfcn = root[i]["dl_earfcn"]; + cell.pci = (unsigned int)root[i]["pci"] % SRSRAN_NUM_PCI; + cell.eci = (unsigned int)root[i]["eci"]; + cell.q_offset = 0; // LIBLTE_RRC_Q_OFFSET_RANGE_DB_0; // TODO + parse_default_field(cell.direct_forward_path_available, root[i], "direct_forward_path_available", false); } return 0; } diff --git a/srsenb/src/stack/rrc/rrc_mobility.cc b/srsenb/src/stack/rrc/rrc_mobility.cc index 47cdfbb37..90f5744e5 100644 --- a/srsenb/src/stack/rrc/rrc_mobility.cc +++ b/srsenb/src/stack/rrc/rrc_mobility.cc @@ -250,7 +250,8 @@ void rrc::ue::rrc_mobility::handle_ue_meas_report(const meas_report_s& msg, srsr auto meas_it = std::find_if(meas_list_cfg.begin(), meas_list_cfg.end(), same_pci); const enb_cell_common* c = rrc_enb->cell_common_list->get_pci(e.pci); if (meas_it != meas_list_cfg.end()) { - meas_ev.target_eci = meas_it->eci; + meas_ev.target_eci = meas_it->eci; + meas_ev.direct_fwd_path = meas_it->direct_forward_path_available; } else if (c != nullptr) { meas_ev.target_eci = (rrc_enb->cfg.enb_id << 8u) + c->cell_cfg.cell_id; } else { @@ -281,11 +282,6 @@ bool rrc::ue::rrc_mobility::start_ho_preparation(uint32_t target_eci, uint8_t measobj_id, bool fwd_direct_path_available) { - if (fwd_direct_path_available) { - Error("Direct tunnels not supported supported"); - return false; - } - srsran::plmn_id_t target_plmn = srsran::make_plmn_id_t(rrc_enb->cfg.sib1.cell_access_related_info.plmn_id_list[0].plmn_id); const ue_cell_ded* src_cell_ded = rrc_ue->ue_cell_list.get_ue_cc_idx(UE_PCELL_CC_IDX); @@ -392,7 +388,8 @@ bool rrc::ue::rrc_mobility::start_ho_preparation(uint32_t target_eci, fwd_erabs.push_back(erab_pair.first); } - return rrc_enb->s1ap->send_ho_required(rrc_ue->rnti, target_eci, target_plmn, fwd_erabs, std::move(buffer)); + return rrc_enb->s1ap->send_ho_required( + rrc_ue->rnti, target_eci, target_plmn, fwd_erabs, std::move(buffer), fwd_direct_path_available); } /** @@ -628,7 +625,7 @@ void rrc::ue::rrc_mobility::s1_source_ho_st::enter(rrc_mobility* f, const ho_mea logger.info("Starting S1 Handover of rnti=0x%x to cellid=0x%x.", rrc_ue->rnti, ev.target_eci); report = ev; - if (not parent_fsm()->start_ho_preparation(report.target_eci, report.meas_obj->meas_obj_id, false)) { + if (not parent_fsm()->start_ho_preparation(report.target_eci, report.meas_obj->meas_obj_id, ev.direct_fwd_path)) { trigger(srsran::failure_ev{}); } } diff --git a/srsenb/src/stack/upper/s1ap.cc b/srsenb/src/stack/upper/s1ap.cc index da359263e..fd10734e1 100644 --- a/srsenb/src/stack/upper/s1ap.cc +++ b/srsenb/src/stack/upper/s1ap.cc @@ -117,14 +117,16 @@ s1ap::ue::ho_prep_proc_t::ho_prep_proc_t(s1ap::ue* ue_) : ue_ptr(ue_), s1ap_ptr( srsran::proc_outcome_t s1ap::ue::ho_prep_proc_t::init(uint32_t target_eci_, srsran::plmn_id_t target_plmn_, srsran::span fwd_erabs, - srsran::unique_byte_buffer_t rrc_container_) + srsran::unique_byte_buffer_t rrc_container_, + bool has_direct_fwd_path) { ho_cmd_msg = nullptr; target_eci = target_eci_; target_plmn = target_plmn_; procInfo("Sending HandoverRequired to MME id=%d", ue_ptr->ctxt.mme_ue_s1ap_id.value()); - if (not ue_ptr->send_ho_required(target_eci, target_plmn, fwd_erabs, std::move(rrc_container_))) { + if (not ue_ptr->send_ho_required( + target_eci, target_plmn, fwd_erabs, std::move(rrc_container_), has_direct_fwd_path)) { procError("Failed to send HORequired to cell 0x%x", target_eci); return srsran::proc_outcome_t::error; } @@ -1686,7 +1688,8 @@ bool s1ap::send_ho_required(uint16_t rnti, uint32_t target_eci, srsran::plmn_id_t target_plmn, srsran::span fwd_erabs, - srsran::unique_byte_buffer_t rrc_container) + srsran::unique_byte_buffer_t rrc_container, + bool has_direct_fwd_path) { if (!mme_connected) { return false; @@ -1697,7 +1700,7 @@ bool s1ap::send_ho_required(uint16_t rnti, } // launch procedure - if (not u->ho_prep_proc.launch(target_eci, target_plmn, fwd_erabs, std::move(rrc_container))) { + if (not u->ho_prep_proc.launch(target_eci, target_plmn, fwd_erabs, std::move(rrc_container), has_direct_fwd_path)) { logger.error("Failed to initiate an HandoverPreparation procedure for user rnti=0x%x", u->ctxt.rnti); return false; } @@ -1945,7 +1948,8 @@ s1ap::ue::ue(s1ap* s1ap_ptr_) : s1ap_ptr(s1ap_ptr_), ho_prep_proc(this), logger( bool s1ap::ue::send_ho_required(uint32_t target_eci, srsran::plmn_id_t target_plmn, srsran::span fwd_erabs, - srsran::unique_byte_buffer_t rrc_container) + srsran::unique_byte_buffer_t rrc_container, + bool has_direct_fwd_path) { /*** Setup S1AP PDU as HandoverRequired ***/ s1ap_pdu_c tx_pdu; @@ -1953,12 +1957,17 @@ bool s1ap::ue::send_ho_required(uint32_t target_eci, ho_required_ies_container& container = tx_pdu.init_msg().value.ho_required().protocol_ies; /*** fill HO Required message ***/ - container.enb_ue_s1ap_id.value = ctxt.enb_ue_s1ap_id; - container.mme_ue_s1ap_id.value = ctxt.mme_ue_s1ap_id.value(); - container.direct_forwarding_path_availability_present = false; // NOTE: X2 for fwd path not supported + container.enb_ue_s1ap_id.value = ctxt.enb_ue_s1ap_id; + container.mme_ue_s1ap_id.value = ctxt.mme_ue_s1ap_id.value(); container.handov_type.value.value = handov_type_opts::intralte; // NOTE: only intra-LTE HO supported container.cause.value.set_radio_network().value = cause_radio_network_opts::ho_desirable_for_radio_reason; + container.direct_forwarding_path_availability_present = has_direct_fwd_path; + if (container.direct_forwarding_path_availability_present) { + container.direct_forwarding_path_availability.value.value = + asn1::s1ap::direct_forwarding_path_availability_opts::direct_path_available; + } + /*** set the target eNB ***/ container.csg_id_present = false; // NOTE: CSG/hybrid target cell not supported container.cell_access_mode_present = false; // only for hybrid cells diff --git a/srsenb/test/common/dummy_classes.h b/srsenb/test/common/dummy_classes.h index 725478ea6..f4aff5085 100644 --- a/srsenb/test/common/dummy_classes.h +++ b/srsenb/test/common/dummy_classes.h @@ -110,7 +110,8 @@ public: uint32_t target_eci, srsran::plmn_id_t target_plmn, srsran::span fwd_erabs, - srsran::unique_byte_buffer_t rrc_container) override + srsran::unique_byte_buffer_t rrc_container, + bool has_direct_fwd_path) override { return true; } diff --git a/srsenb/test/upper/test_helpers.h b/srsenb/test/upper/test_helpers.h index 88800d26a..cadd06e94 100644 --- a/srsenb/test/upper/test_helpers.h +++ b/srsenb/test/upper/test_helpers.h @@ -83,7 +83,8 @@ public: uint32_t target_eci, srsran::plmn_id_t target_plmn, srsran::span fwd_erabs, - srsran::unique_byte_buffer_t rrc_container) final + srsran::unique_byte_buffer_t rrc_container, + bool has_direct_fwd_path) final { last_ho_required = ho_req_data{rnti, target_eci, target_plmn, std::move(rrc_container)}; return true;