s1ap - handle invalid or repeated erab ids in s1ap erab release command

master
Francisco 4 years ago committed by Francisco Paisana
parent 7842e3bff3
commit 49bd895e29

@ -233,7 +233,7 @@ public:
iterator begin() { return iterator(this, 0); } iterator begin() { return iterator(this, 0); }
iterator end() { return iterator(this, N); } iterator end() { return iterator(this, N); }
const_iterator begin() const { return iterator(this, 0); } const_iterator begin() const { return const_iterator(this, 0); }
const_iterator end() const { return const_iterator(this, N); } const_iterator end() const { return const_iterator(this, N); }
iterator find(K id) iterator find(K id)

@ -34,9 +34,8 @@ public:
virtual bool has_erab(uint16_t rnti, uint32_t erab_id) const = 0; virtual bool has_erab(uint16_t rnti, uint32_t erab_id) const = 0;
virtual bool release_erabs(uint32_t rnti) = 0; virtual bool release_erabs(uint32_t rnti) = 0;
virtual void release_erabs(uint32_t rnti, virtual void release_erabs(uint32_t rnti,
const asn1::s1ap::erab_release_cmd_s& msg, srsran::const_span<uint16_t> erabs_to_release,
std::vector<uint16_t>* erabs_released, const asn1::unbounded_octstring<true>* nas_pdu) = 0;
std::vector<uint16_t>* erabs_failed_to_release) = 0;
virtual void add_paging_id(uint32_t ueid, const asn1::s1ap::ue_paging_id_c& ue_paging_id) = 0; virtual void add_paging_id(uint32_t ueid, const asn1::s1ap::ue_paging_id_c& ue_paging_id) = 0;
/** /**

@ -26,6 +26,8 @@ namespace srsenb {
#define SRSENB_N_SRB 3 #define SRSENB_N_SRB 3
#define SRSENB_MAX_UES 64 #define SRSENB_MAX_UES 64
const uint32_t MAX_ERAB_ID = 15;
const uint32_t MAX_NOF_ERABS = 16;
using srsran::lte_drb; using srsran::lte_drb;
using srsran::lte_srb; using srsran::lte_srb;

@ -92,9 +92,8 @@ public:
const asn1::unbounded_octstring<true>* nas_pdu); const asn1::unbounded_octstring<true>* nas_pdu);
bool release_erabs(uint32_t rnti) override; bool release_erabs(uint32_t rnti) override;
void release_erabs(uint32_t rnti, void release_erabs(uint32_t rnti,
const asn1::s1ap::erab_release_cmd_s& msg, srsran::const_span<uint16_t> erabs_to_release,
std::vector<uint16_t>* erabs_released, const asn1::unbounded_octstring<true>* nas_pdu) override;
std::vector<uint16_t>* erabs_failed_to_release) override;
void add_paging_id(uint32_t ueid, const asn1::s1ap::ue_paging_id_c& UEPagingID) override; void add_paging_id(uint32_t ueid, const asn1::s1ap::ue_paging_id_c& UEPagingID) override;
void ho_preparation_complete(uint16_t rnti, void ho_preparation_complete(uint16_t rnti,
bool is_success, bool is_success,

@ -16,6 +16,7 @@
#include <map> #include <map>
#include "srsenb/hdr/common/common_enb.h" #include "srsenb/hdr/common/common_enb.h"
#include "srsran/adt/circular_map.h"
#include "srsran/common/buffer_pool.h" #include "srsran/common/buffer_pool.h"
#include "srsran/common/common.h" #include "srsran/common/common.h"
#include "srsran/common/s1ap_pcap.h" #include "srsran/common/s1ap_pcap.h"
@ -237,8 +238,9 @@ private:
bool send_initial_ctxt_setup_response(const asn1::s1ap::init_context_setup_resp_s& res_); bool send_initial_ctxt_setup_response(const asn1::s1ap::init_context_setup_resp_s& res_);
bool send_initial_ctxt_setup_failure(); bool send_initial_ctxt_setup_failure();
bool send_erab_setup_response(const asn1::s1ap::erab_setup_resp_s& res_); bool send_erab_setup_response(const asn1::s1ap::erab_setup_resp_s& res_);
bool send_erab_release_response(const std::vector<uint16_t>& erabs_successfully_released, bool send_erab_release_response(
const std::vector<uint16_t>& erabs_failed_to_release); const srsran::bounded_vector<uint16_t, MAX_NOF_ERABS>& erabs_released,
const srsran::static_circular_map<uint16_t, asn1::s1ap::erab_item_s, MAX_NOF_ERABS>& erabs_failed_to_release);
bool send_erab_modify_response( bool send_erab_modify_response(
srsran::const_span<const asn1::s1ap::erab_to_be_modified_item_bearer_mod_req_s*> erabs_modified, srsran::const_span<const asn1::s1ap::erab_to_be_modified_item_bearer_mod_req_s*> erabs_modified,
srsran::const_span<std::pair<uint16_t, asn1::s1ap::cause_c> > erabs_failed_to_modify); srsran::const_span<std::pair<uint16_t, asn1::s1ap::cause_c> > erabs_failed_to_modify);

@ -359,9 +359,8 @@ bool rrc::release_erabs(uint32_t rnti)
} }
void rrc::release_erabs(uint32_t rnti, void rrc::release_erabs(uint32_t rnti,
const asn1::s1ap::erab_release_cmd_s& msg, srsran::const_span<uint16_t> erabs_to_release,
std::vector<uint16_t>* erabs_released, const asn1::unbounded_octstring<true>* nas_pdu)
std::vector<uint16_t>* erabs_failed_to_release)
{ {
logger.info("Releasing E-RAB for 0x%x", rnti); logger.info("Releasing E-RAB for 0x%x", rnti);
auto user_it = users.find(rnti); auto user_it = users.find(rnti);
@ -371,18 +370,10 @@ void rrc::release_erabs(uint32_t rnti,
return; return;
} }
for (uint32_t i = 0; i < msg.protocol_ies.erab_to_be_released_list.value.size(); i++) { for (uint16_t erab_id : erabs_to_release) {
const asn1::s1ap::erab_item_s& erab_to_release = bool ret = user_it->second->release_erab(erab_id);
msg.protocol_ies.erab_to_be_released_list.value[i].value.erab_item(); srsran_expect(ret, "E-RAB id=%d not found", erab_id);
bool ret = user_it->second->release_erab(erab_to_release.erab_id);
if (ret) {
erabs_released->push_back(erab_to_release.erab_id);
} else {
erabs_failed_to_release->push_back(erab_to_release.erab_id);
}
} }
const asn1::unbounded_octstring<true>* nas_pdu =
msg.protocol_ies.nas_pdu_present ? &msg.protocol_ies.nas_pdu.value : nullptr;
user_it->second->send_connection_reconf(nullptr, false, nas_pdu); user_it->second->send_connection_reconf(nullptr, false, nas_pdu);
} }

@ -735,15 +735,18 @@ bool s1ap::handle_erabmodifyrequest(const erab_modify_request_s& msg)
return false; return false;
} }
// make a copy, sort by ERAB ID
using erab_t = erab_to_be_modified_item_bearer_mod_req_s; using erab_t = erab_to_be_modified_item_bearer_mod_req_s;
using failed_erab_t = std::pair<uint16_t, cause_c>; using failed_erab_t = std::pair<uint16_t, cause_c>;
srsran::bounded_vector<const erab_t*, 256> erab_mod_list; srsran::bounded_vector<const erab_t*, MAX_ERAB_ID + 1> erab_mod_list;
std::vector<failed_erab_t> erabs_failed_to_modify; srsran::bounded_vector<failed_erab_t, MAX_ERAB_ID + 1> erabs_failed_to_modify;
auto& msg_erabs = msg.protocol_ies.erab_to_be_modified_list_bearer_mod_req.value; const auto& msg_erabs = msg.protocol_ies.erab_to_be_modified_list_bearer_mod_req.value;
for (const auto& msg_erab : msg_erabs) { if (msg_erabs.size() > erab_mod_list.capacity()) {
const erab_t& e = msg_erab.value.erab_to_be_modified_item_bearer_mod_req(); logger.warning("Not handling more than %d E-RABs per modify request message.", erab_mod_list.capacity());
}
for (size_t i = 0; i < SRSRAN_MIN(msg_erabs.size(), erab_mod_list.capacity()); ++i) {
const erab_t& e = msg_erabs[i].value.erab_to_be_modified_item_bearer_mod_req();
// Check if E-RAB exists. If not, add to "erabs_failed_to_modify" with "unknown_erab_id" cause // Check if E-RAB exists. If not, add to "erabs_failed_to_modify" with "unknown_erab_id" cause
if (not rrc->has_erab(u->ctxt.rnti, e.erab_id)) { if (not rrc->has_erab(u->ctxt.rnti, e.erab_id)) {
@ -757,7 +760,7 @@ bool s1ap::handle_erabmodifyrequest(const erab_modify_request_s& msg)
// with cause "multiple_erab_id_instances" // with cause "multiple_erab_id_instances"
for (const auto& msg_erab2 : msg_erabs) { for (const auto& msg_erab2 : msg_erabs) {
const erab_t& e2 = msg_erab2.value.erab_to_be_modified_item_bearer_mod_req(); const erab_t& e2 = msg_erab2.value.erab_to_be_modified_item_bearer_mod_req();
if (&msg_erab2 != &msg_erab and e2.erab_id == e.erab_id) { if (&e2 != &e and e2.erab_id == e.erab_id) {
cause_c cause; cause_c cause;
cause.set_radio_network().value = cause_radio_network_opts::multiple_erab_id_instances; cause.set_radio_network().value = cause_radio_network_opts::multiple_erab_id_instances;
erabs_failed_to_modify.emplace_back(e.erab_id, cause); erabs_failed_to_modify.emplace_back(e.erab_id, cause);
@ -802,9 +805,6 @@ bool s1ap::handle_erabmodifyrequest(const erab_modify_request_s& msg)
*/ */
bool s1ap::handle_erabreleasecommand(const erab_release_cmd_s& msg) bool s1ap::handle_erabreleasecommand(const erab_release_cmd_s& msg)
{ {
std::vector<uint16_t> erab_successful_release = {};
std::vector<uint16_t> erab_failed_to_release = {};
if (msg.ext) { if (msg.ext) {
logger.warning("Not handling S1AP message extension"); logger.warning("Not handling S1AP message extension");
} }
@ -814,11 +814,56 @@ bool s1ap::handle_erabreleasecommand(const erab_release_cmd_s& msg)
return false; return false;
} }
srsran::bounded_vector<uint16_t, MAX_NOF_ERABS> erabs_to_release;
srsran::static_circular_map<uint16_t, erab_item_s, MAX_NOF_ERABS> erabs_failed_to_release;
const auto& msg_erabs = msg.protocol_ies.erab_to_be_released_list.value;
for (const auto& msg_erab : msg_erabs) {
const erab_item_s& e = msg_erab.value.erab_item();
if (e.erab_id >= erabs_failed_to_release.capacity()) {
logger.warning("Not handling E-RAB Ids above %zd", erabs_to_release.capacity());
continue;
}
if (erabs_to_release.full()) {
logger.warning("Not handling more than %zd releases per ERAB release request message",
erabs_to_release.capacity());
break;
}
// Check if E-RAB exists. If not, add to "erabs_failed_to_modify" with "unknown_erab_id" cause
if (not rrc->has_erab(u->ctxt.rnti, e.erab_id)) {
erabs_failed_to_release.overwrite(e.erab_id, erab_item_s());
erabs_failed_to_release[e.erab_id].cause.set_radio_network().value = cause_radio_network_opts::unknown_erab_id;
continue;
}
// Check Repeated E-RABs in the modification list. If repeated, add to the list of "erabs_failed_to_modify"
// with cause "multiple_erab_id_instances"
for (const auto& msg_erab2 : msg_erabs) {
const erab_item_s& e2 = msg_erab2.value.erab_item();
if (&e2 != &e and e2.erab_id == e.erab_id) {
erabs_failed_to_release.overwrite(e.erab_id, erab_item_s());
erabs_failed_to_release[e.erab_id].cause.set_radio_network().value =
cause_radio_network_opts::multiple_erab_id_instances;
break;
}
}
if (erabs_failed_to_release.has_space(e.erab_id)) {
continue;
}
// Add to the list to modify
erabs_to_release.push_back(e.erab_id);
}
// Release E-RABs from RRC // Release E-RABs from RRC
rrc->release_erabs(u->ctxt.rnti, msg, &erab_successful_release, &erab_failed_to_release); std::sort(erabs_to_release.begin(), erabs_to_release.end());
erabs_to_release.erase(std::unique(erabs_to_release.begin(), erabs_to_release.end()), erabs_to_release.end());
rrc->release_erabs(
u->ctxt.rnti, erabs_to_release, msg.protocol_ies.nas_pdu_present ? &msg.protocol_ies.nas_pdu.value : nullptr);
// Send E-RAB release response back to the MME // Send E-RAB release response back to the MME
if (not u->send_erab_release_response(erab_successful_release, erab_failed_to_release)) { if (not u->send_erab_release_response(erabs_to_release, erabs_failed_to_release)) {
logger.info("Failed to send ERABReleaseResponse"); logger.info("Failed to send ERABReleaseResponse");
return false; return false;
} }
@ -1391,8 +1436,9 @@ bool s1ap::ue::send_uectxtmodifyfailure(const cause_c& cause)
* @param erabs_failed_to_release * @param erabs_failed_to_release
* @return true if message was sent * @return true if message was sent
*/ */
bool s1ap::ue::send_erab_release_response(const std::vector<uint16_t>& erabs_successfully_released, bool s1ap::ue::send_erab_release_response(
const std::vector<uint16_t>& erabs_failed_to_release) const srsran::bounded_vector<uint16_t, MAX_NOF_ERABS>& erabs_released,
const srsran::static_circular_map<uint16_t, asn1::s1ap::erab_item_s, MAX_NOF_ERABS>& erabs_failed_to_release)
{ {
if (not s1ap_ptr->mme_connected) { if (not s1ap_ptr->mme_connected) {
return false; return false;
@ -1406,14 +1452,14 @@ bool s1ap::ue::send_erab_release_response(const std::vector<uint16_t>& erabs_suc
container.mme_ue_s1ap_id.value = ctxt.mme_ue_s1ap_id.value(); container.mme_ue_s1ap_id.value = ctxt.mme_ue_s1ap_id.value();
// Fill in which E-RABs were successfully released // Fill in which E-RABs were successfully released
if (not erabs_successfully_released.empty()) { if (not erabs_released.empty()) {
container.erab_release_list_bearer_rel_comp_present = true; container.erab_release_list_bearer_rel_comp_present = true;
container.erab_release_list_bearer_rel_comp.value.resize(erabs_successfully_released.size()); container.erab_release_list_bearer_rel_comp.value.resize(erabs_released.size());
for (uint32_t i = 0; i < container.erab_release_list_bearer_rel_comp.value.size(); i++) { for (size_t i = 0; i < erabs_released.size(); ++i) {
container.erab_release_list_bearer_rel_comp.value[i].load_info_obj( container.erab_release_list_bearer_rel_comp.value[i].load_info_obj(
ASN1_S1AP_ID_ERAB_RELEASE_ITEM_BEARER_REL_COMP); ASN1_S1AP_ID_ERAB_RELEASE_ITEM_BEARER_REL_COMP);
container.erab_release_list_bearer_rel_comp.value[i].value.erab_release_item_bearer_rel_comp().erab_id = container.erab_release_list_bearer_rel_comp.value[i].value.erab_release_item_bearer_rel_comp().erab_id =
erabs_successfully_released[i]; erabs_released[i];
} }
} }
@ -1421,12 +1467,11 @@ bool s1ap::ue::send_erab_release_response(const std::vector<uint16_t>& erabs_suc
if (not erabs_failed_to_release.empty()) { if (not erabs_failed_to_release.empty()) {
container.erab_failed_to_release_list_present = true; container.erab_failed_to_release_list_present = true;
container.erab_failed_to_release_list.value.resize(erabs_failed_to_release.size()); container.erab_failed_to_release_list.value.resize(erabs_failed_to_release.size());
for (uint32_t i = 0; i < container.erab_failed_to_release_list.value.size(); i++) { size_t count = 0;
container.erab_failed_to_release_list.value[i].load_info_obj(ASN1_S1AP_ID_ERAB_ITEM); for (const auto& erab : erabs_failed_to_release) {
container.erab_failed_to_release_list.value[i].value.erab_item().erab_id = erabs_failed_to_release[i]; container.erab_failed_to_release_list.value[count].load_info_obj(ASN1_S1AP_ID_ERAB_ITEM);
container.erab_failed_to_release_list.value[i].value.erab_item().cause.set(asn1::s1ap::cause_c::types::misc); container.erab_failed_to_release_list.value[count].value.erab_item() = erab->second;
container.erab_failed_to_release_list.value[i].value.erab_item().cause.misc() = count++;
asn1::s1ap::cause_misc_opts::unspecified;
} }
} }

@ -175,9 +175,8 @@ public:
bool has_erab(uint16_t rnti, uint32_t erab_id) const override { return true; } bool has_erab(uint16_t rnti, uint32_t erab_id) const override { return true; }
bool release_erabs(uint32_t rnti) override { return true; } bool release_erabs(uint32_t rnti) override { return true; }
void release_erabs(uint32_t rnti, void release_erabs(uint32_t rnti,
const asn1::s1ap::erab_release_cmd_s& msg, srsran::const_span<uint16_t> erabs_to_release,
std::vector<uint16_t>* erabs_released, const asn1::unbounded_octstring<true>* nas_pdu) override
std::vector<uint16_t>* erabs_failed_to_release) override
{} {}
void add_paging_id(uint32_t ueid, const asn1::s1ap::ue_paging_id_c& ue_paging_id) override {} void add_paging_id(uint32_t ueid, const asn1::s1ap::ue_paging_id_c& ue_paging_id) override {}
void ho_preparation_complete(uint16_t rnti, void ho_preparation_complete(uint16_t rnti,

Loading…
Cancel
Save