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

This commit is contained in:
Francisco 2021-04-12 17:40:14 +01:00 committed by Francisco Paisana
parent 7842e3bff3
commit 49bd895e29
8 changed files with 91 additions and 54 deletions

View File

@ -233,7 +233,7 @@ public:
iterator begin() { return iterator(this, 0); }
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); }
iterator find(K id)

View File

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

View File

@ -26,6 +26,8 @@ namespace srsenb {
#define SRSENB_N_SRB 3
#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_srb;

View File

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

View File

@ -16,6 +16,7 @@
#include <map>
#include "srsenb/hdr/common/common_enb.h"
#include "srsran/adt/circular_map.h"
#include "srsran/common/buffer_pool.h"
#include "srsran/common/common.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_failure();
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,
const std::vector<uint16_t>& erabs_failed_to_release);
bool send_erab_release_response(
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(
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);

View File

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

View File

@ -735,15 +735,18 @@ bool s1ap::handle_erabmodifyrequest(const erab_modify_request_s& msg)
return false;
}
// make a copy, sort by ERAB ID
using erab_t = erab_to_be_modified_item_bearer_mod_req_s;
using failed_erab_t = std::pair<uint16_t, cause_c>;
srsran::bounded_vector<const erab_t*, 256> erab_mod_list;
std::vector<failed_erab_t> erabs_failed_to_modify;
auto& msg_erabs = msg.protocol_ies.erab_to_be_modified_list_bearer_mod_req.value;
srsran::bounded_vector<const erab_t*, MAX_ERAB_ID + 1> erab_mod_list;
srsran::bounded_vector<failed_erab_t, MAX_ERAB_ID + 1> erabs_failed_to_modify;
const auto& msg_erabs = msg.protocol_ies.erab_to_be_modified_list_bearer_mod_req.value;
for (const auto& msg_erab : msg_erabs) {
const erab_t& e = msg_erab.value.erab_to_be_modified_item_bearer_mod_req();
if (msg_erabs.size() > erab_mod_list.capacity()) {
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
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"
for (const auto& msg_erab2 : msg_erabs) {
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.set_radio_network().value = cause_radio_network_opts::multiple_erab_id_instances;
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)
{
std::vector<uint16_t> erab_successful_release = {};
std::vector<uint16_t> erab_failed_to_release = {};
if (msg.ext) {
logger.warning("Not handling S1AP message extension");
}
@ -814,11 +814,56 @@ bool s1ap::handle_erabreleasecommand(const erab_release_cmd_s& msg)
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
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
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");
return false;
}
@ -1391,8 +1436,9 @@ bool s1ap::ue::send_uectxtmodifyfailure(const cause_c& cause)
* @param erabs_failed_to_release
* @return true if message was sent
*/
bool s1ap::ue::send_erab_release_response(const std::vector<uint16_t>& erabs_successfully_released,
const std::vector<uint16_t>& erabs_failed_to_release)
bool s1ap::ue::send_erab_release_response(
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) {
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();
// 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.value.resize(erabs_successfully_released.size());
for (uint32_t i = 0; i < container.erab_release_list_bearer_rel_comp.value.size(); i++) {
container.erab_release_list_bearer_rel_comp.value.resize(erabs_released.size());
for (size_t i = 0; i < erabs_released.size(); ++i) {
container.erab_release_list_bearer_rel_comp.value[i].load_info_obj(
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 =
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()) {
container.erab_failed_to_release_list_present = true;
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++) {
container.erab_failed_to_release_list.value[i].load_info_obj(ASN1_S1AP_ID_ERAB_ITEM);
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[i].value.erab_item().cause.set(asn1::s1ap::cause_c::types::misc);
container.erab_failed_to_release_list.value[i].value.erab_item().cause.misc() =
asn1::s1ap::cause_misc_opts::unspecified;
size_t count = 0;
for (const auto& erab : erabs_failed_to_release) {
container.erab_failed_to_release_list.value[count].load_info_obj(ASN1_S1AP_ID_ERAB_ITEM);
container.erab_failed_to_release_list.value[count].value.erab_item() = erab->second;
count++;
}
}

View File

@ -174,10 +174,9 @@ public:
{}
bool has_erab(uint16_t rnti, uint32_t erab_id) const override { return true; }
bool release_erabs(uint32_t rnti) override { return true; }
void release_erabs(uint32_t rnti,
const asn1::s1ap::erab_release_cmd_s& msg,
std::vector<uint16_t>* erabs_released,
std::vector<uint16_t>* erabs_failed_to_release) override
void release_erabs(uint32_t rnti,
srsran::const_span<uint16_t> erabs_to_release,
const asn1::unbounded_octstring<true>* nas_pdu) 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,