mirror of https://github.com/PentHertz/srsLTE.git
fix GTPU tunneling. Avoid forwarding packets to PDCP while the PDCP bearer is not yet created
This commit is contained in:
parent
8e13f04684
commit
78d1b8083a
|
@ -478,6 +478,7 @@ public:
|
||||||
|
|
||||||
virtual uint32_t
|
virtual uint32_t
|
||||||
add_bearer(uint16_t rnti, uint32_t lcid, uint32_t addr, uint32_t teid_out, const bearer_props* props = nullptr) = 0;
|
add_bearer(uint16_t rnti, uint32_t lcid, uint32_t addr, uint32_t teid_out, const bearer_props* props = nullptr) = 0;
|
||||||
|
virtual void set_tunnel_status(uint32_t teidin, bool dl_active) = 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 mod_bearer_rnti(uint16_t old_rnti, uint16_t new_rnti) = 0;
|
virtual void mod_bearer_rnti(uint16_t old_rnti, uint16_t new_rnti) = 0;
|
||||||
virtual void rem_user(uint16_t rnti) = 0;
|
virtual void rem_user(uint16_t rnti) = 0;
|
||||||
|
|
|
@ -97,7 +97,9 @@ 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 {
|
||||||
|
std::vector<uint32_t> pending_tunnels;
|
||||||
|
};
|
||||||
struct wait_recfg_comp {};
|
struct wait_recfg_comp {};
|
||||||
struct s1_source_ho_st : public subfsm_t<s1_source_ho_st> {
|
struct s1_source_ho_st : public subfsm_t<s1_source_ho_st> {
|
||||||
struct ho_cmd_msg {
|
struct ho_cmd_msg {
|
||||||
|
@ -166,7 +168,7 @@ protected:
|
||||||
// +----------------+-------------------+---------------------+----------------------------+-------------------------+
|
// +----------------+-------------------+---------------------+----------------------------+-------------------------+
|
||||||
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, &fsm::handle_ho_requested >,
|
row< idle_st, s1_target_ho_st, ho_req_rx_ev, &fsm::handle_ho_requested >,
|
||||||
// +----------------+-------------------+---------------------+----------------------------+-------------------------+
|
// +----------------+-------------------+---------------------+----------------------------+-------------------------+
|
||||||
upd< intraenb_ho_st, user_crnti_upd_ev, &fsm::handle_crnti_ce >,
|
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 >,
|
||||||
|
|
|
@ -46,6 +46,7 @@ public:
|
||||||
uint32_t addr,
|
uint32_t addr,
|
||||||
uint32_t teid_out,
|
uint32_t teid_out,
|
||||||
const bearer_props* props = nullptr) override;
|
const bearer_props* props = nullptr) override;
|
||||||
|
void set_tunnel_status(uint32_t teidin, bool dl_active) override;
|
||||||
void rem_bearer(uint16_t rnti, uint32_t lcid) override;
|
void rem_bearer(uint16_t rnti, uint32_t lcid) override;
|
||||||
void mod_bearer_rnti(uint16_t old_rnti, uint16_t new_rnti) override;
|
void mod_bearer_rnti(uint16_t old_rnti, uint16_t new_rnti) override;
|
||||||
void rem_user(uint16_t rnti) override;
|
void rem_user(uint16_t rnti) override;
|
||||||
|
@ -100,6 +101,7 @@ private:
|
||||||
m1u_handler m1u;
|
m1u_handler m1u;
|
||||||
|
|
||||||
struct tunnel {
|
struct tunnel {
|
||||||
|
bool dl_enabled = true;
|
||||||
bool fwd_teid_in_present = false;
|
bool fwd_teid_in_present = false;
|
||||||
bool prior_teid_in_present = false;
|
bool prior_teid_in_present = false;
|
||||||
uint16_t rnti = SRSLTE_INVALID_RNTI;
|
uint16_t rnti = SRSLTE_INVALID_RNTI;
|
||||||
|
|
|
@ -75,7 +75,8 @@ uint16_t compute_mac_i(uint16_t crnti,
|
||||||
}
|
}
|
||||||
uint32_t N_bytes = bref.distance_bytes();
|
uint32_t N_bytes = bref.distance_bytes();
|
||||||
|
|
||||||
printf("Encoded varShortMAC: cellId=0x%x, PCI=%d, rnti=0x%x (%d bytes)", cellid, pci, crnti, N_bytes);
|
srslte::logmap::get("RRC")->info(
|
||||||
|
"Encoded varShortMAC: cellId=0x%x, PCI=%d, rnti=0x%x (%d bytes)", cellid, pci, crnti, N_bytes);
|
||||||
|
|
||||||
// Compute MAC-I
|
// Compute MAC-I
|
||||||
switch (integ_algo) {
|
switch (integ_algo) {
|
||||||
|
@ -731,6 +732,7 @@ void rrc::ue::rrc_mobility::handle_ho_requested(idle_st& s, const ho_req_rx_ev&
|
||||||
|
|
||||||
// Set admitted E-RABs
|
// Set admitted E-RABs
|
||||||
std::vector<asn1::s1ap::erab_admitted_item_s> admitted_erabs;
|
std::vector<asn1::s1ap::erab_admitted_item_s> admitted_erabs;
|
||||||
|
auto& fwd_tunnels = get_state<s1_target_ho_st>()->pending_tunnels;
|
||||||
for (auto& erab : rrc_ue->bearer_list.get_erabs()) {
|
for (auto& erab : rrc_ue->bearer_list.get_erabs()) {
|
||||||
admitted_erabs.emplace_back();
|
admitted_erabs.emplace_back();
|
||||||
asn1::s1ap::erab_admitted_item_s& admitted_erab = admitted_erabs.back();
|
asn1::s1ap::erab_admitted_item_s& admitted_erab = admitted_erabs.back();
|
||||||
|
@ -759,6 +761,7 @@ void rrc::ue::rrc_mobility::handle_ho_requested(idle_st& s, const ho_req_rx_ev&
|
||||||
props.flush_before_teidin = erab.second.teid_in;
|
props.flush_before_teidin = erab.second.teid_in;
|
||||||
uint32_t dl_teid_in = rrc_ue->bearer_list.add_gtpu_bearer(
|
uint32_t dl_teid_in = rrc_ue->bearer_list.add_gtpu_bearer(
|
||||||
erab.second.id, erab.second.teid_out, erab.second.address.to_number(), &props);
|
erab.second.id, erab.second.teid_out, erab.second.address.to_number(), &props);
|
||||||
|
fwd_tunnels.push_back(dl_teid_in);
|
||||||
srslte::uint32_to_uint8(dl_teid_in, admitted_erabs.back().dl_g_tp_teid.data());
|
srslte::uint32_to_uint8(dl_teid_in, admitted_erabs.back().dl_g_tp_teid.data());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -888,6 +891,11 @@ void rrc::ue::rrc_mobility::handle_status_transfer(s1_target_ho_st& s, const sta
|
||||||
rrc_enb->pdcp->set_bearer_state(rrc_ue->rnti, drb_it->lc_ch_id, drb_state);
|
rrc_enb->pdcp->set_bearer_state(rrc_ue->rnti, drb_it->lc_ch_id, drb_state);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Enable forwarding of GTPU SDUs to PDCP
|
||||||
|
for (uint32_t teid : s.pending_tunnels) {
|
||||||
|
rrc_enb->gtpu->set_tunnel_status(teid, true);
|
||||||
|
}
|
||||||
|
|
||||||
// Check if there is any pending Reconfiguration Complete. If there is, self-trigger
|
// Check if there is any pending Reconfiguration Complete. If there is, self-trigger
|
||||||
if (pending_recfg_complete.crit_exts.type().value != rrc_conn_recfg_complete_s::crit_exts_c_::types_opts::nulltype) {
|
if (pending_recfg_complete.crit_exts.type().value != rrc_conn_recfg_complete_s::crit_exts_c_::types_opts::nulltype) {
|
||||||
trigger(pending_recfg_complete);
|
trigger(pending_recfg_complete);
|
||||||
|
|
|
@ -160,7 +160,11 @@ uint32_t gtpu::add_bearer(uint16_t rnti, uint32_t lcid, uint32_t addr, uint32_t
|
||||||
|
|
||||||
if (props != nullptr) {
|
if (props != nullptr) {
|
||||||
if (props->flush_before_teidin_present) {
|
if (props->flush_before_teidin_present) {
|
||||||
|
// GTPU should wait for the bearer ctxt to arrive before sending SDUs from DL tunnel to PDCP
|
||||||
|
new_tun.dl_enabled = false;
|
||||||
|
// GTPU should not forward SDUs from main tunnel until the SeNB-TeNB tunnel has been flushed
|
||||||
tunnel& after_tun = tunnels.at(props->flush_before_teidin);
|
tunnel& after_tun = tunnels.at(props->flush_before_teidin);
|
||||||
|
after_tun.dl_enabled = false;
|
||||||
after_tun.prior_teid_in_present = true;
|
after_tun.prior_teid_in_present = true;
|
||||||
after_tun.prior_teid_in = teid_in;
|
after_tun.prior_teid_in = teid_in;
|
||||||
}
|
}
|
||||||
|
@ -177,6 +181,22 @@ uint32_t gtpu::add_bearer(uint16_t rnti, uint32_t lcid, uint32_t addr, uint32_t
|
||||||
return teid_in;
|
return teid_in;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void gtpu::set_tunnel_status(uint32_t teidin, bool dl_active)
|
||||||
|
{
|
||||||
|
auto tun_it = tunnels.find(teidin);
|
||||||
|
if (tun_it == tunnels.end()) {
|
||||||
|
logger.warning("Setting TEID=%d status", teidin);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
tun_it->second.dl_enabled = dl_active;
|
||||||
|
if (dl_active) {
|
||||||
|
for (auto& sdu : tun_it->second.buffer) {
|
||||||
|
pdcp->write_sdu(tun_it->second.rnti, tun_it->second.lcid, std::move(sdu));
|
||||||
|
}
|
||||||
|
tun_it->second.buffer.clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void gtpu::rem_bearer(uint16_t rnti, uint32_t lcid)
|
void gtpu::rem_bearer(uint16_t rnti, uint32_t lcid)
|
||||||
{
|
{
|
||||||
auto ue_it = ue_teidin_db.find(rnti);
|
auto ue_it = ue_teidin_db.find(rnti);
|
||||||
|
@ -298,7 +318,7 @@ void gtpu::handle_gtpu_s1u_rx_packet(srslte::unique_byte_buffer_t pdu, const soc
|
||||||
if (rx_tun.fwd_teid_in_present) {
|
if (rx_tun.fwd_teid_in_present) {
|
||||||
tunnel& tx_tun = tunnels.at(rx_tun.fwd_teid_in);
|
tunnel& tx_tun = tunnels.at(rx_tun.fwd_teid_in);
|
||||||
send_pdu_to_tunnel(tx_tun, std::move(pdu));
|
send_pdu_to_tunnel(tx_tun, std::move(pdu));
|
||||||
} else if (rx_tun.prior_teid_in_present) {
|
} else if (not rx_tun.dl_enabled) {
|
||||||
rx_tun.buffer.push_back(std::move(pdu));
|
rx_tun.buffer.push_back(std::move(pdu));
|
||||||
} else {
|
} else {
|
||||||
uint32_t pdcp_sn = -1;
|
uint32_t pdcp_sn = -1;
|
||||||
|
@ -328,6 +348,7 @@ void gtpu::handle_gtpu_s1u_rx_packet(srslte::unique_byte_buffer_t pdu, const soc
|
||||||
for (srslte::unique_byte_buffer_t& sdu : new_tun.buffer) {
|
for (srslte::unique_byte_buffer_t& sdu : new_tun.buffer) {
|
||||||
pdcp->write_sdu(new_tun.rnti, new_tun.lcid, std::move(sdu));
|
pdcp->write_sdu(new_tun.rnti, new_tun.lcid, std::move(sdu));
|
||||||
}
|
}
|
||||||
|
new_tun.dl_enabled = true;
|
||||||
new_tun.prior_teid_in_present = false;
|
new_tun.prior_teid_in_present = false;
|
||||||
new_tun.buffer.clear();
|
new_tun.buffer.clear();
|
||||||
}
|
}
|
||||||
|
@ -501,7 +522,7 @@ void gtpu::log_message(tunnel& tun, bool is_rx, srslte::span<uint8_t> pdu, int p
|
||||||
if (is_rx) {
|
if (is_rx) {
|
||||||
dir = "Rx";
|
dir = "Rx";
|
||||||
fmt::format_to(strbuf2, "{}:0x{:0x} > ", srslte::gtpu_ntoa(htonl(tun.spgw_addr)), tun.teid_in);
|
fmt::format_to(strbuf2, "{}:0x{:0x} > ", srslte::gtpu_ntoa(htonl(tun.spgw_addr)), tun.teid_in);
|
||||||
if (tun.prior_teid_in_present) {
|
if (not tun.dl_enabled) {
|
||||||
fmt::format_to(strbuf2, "DL (buffered), ");
|
fmt::format_to(strbuf2, "DL (buffered), ");
|
||||||
} else if (tun.fwd_teid_in_present) {
|
} else if (tun.fwd_teid_in_present) {
|
||||||
tunnel& tx_tun = tunnels.at(tun.fwd_teid_in);
|
tunnel& tx_tun = tunnels.at(tun.fwd_teid_in);
|
||||||
|
|
|
@ -139,6 +139,7 @@ public:
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
void set_tunnel_status(uint32_t teidin, bool dl_active) override {}
|
||||||
void rem_bearer(uint16_t rnti, uint32_t lcid) override {}
|
void rem_bearer(uint16_t rnti, uint32_t lcid) override {}
|
||||||
void mod_bearer_rnti(uint16_t old_rnti, uint16_t new_rnti) override {}
|
void mod_bearer_rnti(uint16_t old_rnti, uint16_t new_rnti) override {}
|
||||||
void rem_user(uint16_t rnti) override {}
|
void rem_user(uint16_t rnti) override {}
|
||||||
|
|
Loading…
Reference in New Issue