fix GTPU tunneling. Avoid forwarding packets to PDCP while the PDCP bearer is not yet created

master
Francisco 4 years ago committed by Francisco Paisana
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…
Cancel
Save