Added support for S1AP modify bearer request support. This includes:

- Handle received E-RAB S1AP at s1ap.cc.
 - Added methods to rrc.cc, rrc_ue.cc and rrc_bearer_cfg.cc to handle erab modify request.
 - Made RLC add_bearer() function capable of re-creating the RLC entity.
 - Send RRC reconfiguration to the UE and reply to the EPC with S1AP
   modify bearer response.

This commit also adds support to srsEPC to send S1AP modify bearer request for
testing purposes.
master
Pedro Alvarez 4 years ago
parent 48b37394f1
commit 0c20b7a455

@ -26,6 +26,7 @@ struct init_context_setup_request_s;
struct ue_context_mod_request_s; struct ue_context_mod_request_s;
struct erab_setup_request_s; struct erab_setup_request_s;
struct erab_release_cmd_s; struct erab_release_cmd_s;
struct erab_modify_request_s;
struct ue_paging_id_c; struct ue_paging_id_c;
struct ho_request_s; struct ho_request_s;
struct sourceenb_to_targetenb_transparent_container_s; struct sourceenb_to_targetenb_transparent_container_s;
@ -34,6 +35,7 @@ struct erab_setup_resp_s;
struct rrc_establishment_cause_opts; struct rrc_establishment_cause_opts;
struct cause_radio_network_opts; struct cause_radio_network_opts;
struct bearers_subject_to_status_transfer_item_ies_o; struct bearers_subject_to_status_transfer_item_ies_o;
struct erab_level_qos_params_s;
template <class ies_set_paramT_> template <class ies_set_paramT_>
struct protocol_ie_single_container_s; struct protocol_ie_single_container_s;

@ -425,6 +425,10 @@ public:
virtual bool setup_ue_ctxt(uint16_t rnti, const asn1::s1ap::init_context_setup_request_s& msg) = 0; virtual bool setup_ue_ctxt(uint16_t rnti, const asn1::s1ap::init_context_setup_request_s& msg) = 0;
virtual bool modify_ue_ctxt(uint16_t rnti, const asn1::s1ap::ue_context_mod_request_s& msg) = 0; virtual bool modify_ue_ctxt(uint16_t rnti, const asn1::s1ap::ue_context_mod_request_s& msg) = 0;
virtual bool setup_ue_erabs(uint16_t rnti, const asn1::s1ap::erab_setup_request_s& msg) = 0; virtual bool setup_ue_erabs(uint16_t rnti, const asn1::s1ap::erab_setup_request_s& msg) = 0;
virtual void modify_erabs(uint16_t rnti,
const asn1::s1ap::erab_modify_request_s& msg,
std::vector<uint16_t>* erabs_modified,
std::vector<uint16_t>* erabs_failed_to_modify) = 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, const asn1::s1ap::erab_release_cmd_s& msg,

@ -63,6 +63,11 @@ public:
uint32_t mme_ue_s1ap_id, uint32_t mme_ue_s1ap_id,
std::vector<uint16_t> erabs_to_release, std::vector<uint16_t> erabs_to_release,
struct sctp_sndrcvinfo enb_sri) = 0; struct sctp_sndrcvinfo enb_sri) = 0;
virtual bool send_erab_modify_request(uint32_t enb_ue_s1ap_id,
uint32_t mme_ue_s1ap_id,
std::map<uint16_t, uint16_t> erabs_to_modify,
srslte::byte_buffer_t* nas_msg,
struct sctp_sndrcvinfo enb_sri) = 0;
virtual bool send_downlink_nas_transport(uint32_t enb_ue_s1ap_id, virtual bool send_downlink_nas_transport(uint32_t enb_ue_s1ap_id,
uint32_t mme_ue_s1ap_id, uint32_t mme_ue_s1ap_id,
srslte::byte_buffer_t* nas_msg, srslte::byte_buffer_t* nas_msg,

@ -14,6 +14,8 @@
#define SRSLTE_RRC_CFG_UTILS_H #define SRSLTE_RRC_CFG_UTILS_H
#include "srslte/asn1/rrc_utils.h" #include "srslte/asn1/rrc_utils.h"
#include "srslte/common/common.h"
#include "srslte/common/logmap.h"
#include <algorithm> #include <algorithm>
#include <cassert> #include <cassert>
@ -289,12 +291,16 @@ void compute_cfg_diff(const toAddModList& src_list,
if (&src_list == &target_list) { if (&src_list == &target_list) {
// early exit // early exit
return; return;
} else if (&src_list == &add_diff_list) { }
if (&src_list == &add_diff_list) {
// use const src_list // use const src_list
toAddModList src_list2 = src_list; toAddModList src_list2 = src_list;
compute_cfg_diff(src_list2, target_list, add_diff_list, rem_diff_list); compute_cfg_diff(src_list2, target_list, add_diff_list, rem_diff_list);
return; return;
} else if (&target_list == &add_diff_list) { }
if (&target_list == &add_diff_list) {
// use const target_list // use const target_list
toAddModList target_list2 = target_list; toAddModList target_list2 = target_list;
compute_cfg_diff(src_list, target_list2, add_diff_list, rem_diff_list); compute_cfg_diff(src_list, target_list2, add_diff_list, rem_diff_list);

@ -167,7 +167,8 @@ void rlc::reset()
delete (it->second); delete (it->second);
} }
rlc_array.clear(); rlc_array.clear();
// the multicast bearer (MRB) is not removed here because eMBMS services continue to be streamed in idle mode (3GPP TS 23.246 version 14.1.0 Release 14 section 8) // the multicast bearer (MRB) is not removed here because eMBMS services continue to be streamed in idle mode (3GPP
// TS 23.246 version 14.1.0 Release 14 section 8)
} }
// Add SRB0 again // Add SRB0 again
@ -390,6 +391,11 @@ void rlc::add_bearer(uint32_t lcid, const rlc_config_t& cnfg)
rlc_common* rlc_entity = nullptr; rlc_common* rlc_entity = nullptr;
if (cnfg.rlc_mode != rlc_mode_t::tm and rlc_array.find(lcid) != rlc_array.end()) {
// RLC entity already exists. Recreating it.
rlc_array.erase(lcid);
}
if (not valid_lcid(lcid)) { if (not valid_lcid(lcid)) {
if (cnfg.rat == srslte_rat_t::lte) { if (cnfg.rat == srslte_rat_t::lte) {
switch (cnfg.rlc_mode) { switch (cnfg.rlc_mode) {

@ -76,6 +76,14 @@ public:
bool setup_ue_ctxt(uint16_t rnti, const asn1::s1ap::init_context_setup_request_s& msg) override; bool setup_ue_ctxt(uint16_t rnti, const asn1::s1ap::init_context_setup_request_s& msg) override;
bool modify_ue_ctxt(uint16_t rnti, const asn1::s1ap::ue_context_mod_request_s& msg) override; bool modify_ue_ctxt(uint16_t rnti, const asn1::s1ap::ue_context_mod_request_s& msg) override;
bool setup_ue_erabs(uint16_t rnti, const asn1::s1ap::erab_setup_request_s& msg) override; bool setup_ue_erabs(uint16_t rnti, const asn1::s1ap::erab_setup_request_s& msg) override;
void modify_erabs(uint16_t rnti,
const asn1::s1ap::erab_modify_request_s& msg,
std::vector<uint16_t>* erabs_modified,
std::vector<uint16_t>* erabs_failed_to_modify) override;
bool modify_ue_erab(uint16_t rnti,
uint8_t erab_id,
const asn1::s1ap::erab_level_qos_params_s& qos_params,
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, const asn1::s1ap::erab_release_cmd_s& msg,

@ -69,6 +69,9 @@ public:
const asn1::unbounded_octstring<true>* nas_pdu); const asn1::unbounded_octstring<true>* nas_pdu);
bool release_erab(uint8_t erab_id); bool release_erab(uint8_t erab_id);
void release_erabs(); void release_erabs();
bool modify_erab(uint8_t erab_id,
const asn1::s1ap::erab_level_qos_params_s& qos,
const asn1::unbounded_octstring<true>* nas_pdu);
// Methods to apply bearer updates // Methods to apply bearer updates
void add_gtpu_bearer(gtpu_interface_rrc* gtpu, uint32_t erab_id); void add_gtpu_bearer(gtpu_interface_rrc* gtpu, uint32_t erab_id);

@ -67,6 +67,9 @@ public:
bool setup_erabs(const asn1::s1ap::erab_to_be_setup_list_bearer_su_req_l& e); bool setup_erabs(const asn1::s1ap::erab_to_be_setup_list_bearer_su_req_l& e);
bool release_erabs(); bool release_erabs();
bool release_erab(uint32_t erab_id); bool release_erab(uint32_t erab_id);
bool modify_erab(uint16_t erab_id,
const asn1::s1ap::erab_level_qos_params_s& qos_params,
const asn1::unbounded_octstring<true>* nas_pdu);
// handover // handover
void handle_ho_preparation_complete(bool is_success, srslte::unique_byte_buffer_t container); void handle_ho_preparation_complete(bool is_success, srslte::unique_byte_buffer_t container);

@ -139,6 +139,7 @@ private:
bool handle_s1setupfailure(const asn1::s1ap::s1_setup_fail_s& msg); bool handle_s1setupfailure(const asn1::s1ap::s1_setup_fail_s& msg);
bool handle_erabsetuprequest(const asn1::s1ap::erab_setup_request_s& msg); bool handle_erabsetuprequest(const asn1::s1ap::erab_setup_request_s& msg);
bool handle_erabreleasecommand(const asn1::s1ap::erab_release_cmd_s& msg); bool handle_erabreleasecommand(const asn1::s1ap::erab_release_cmd_s& msg);
bool handle_erabmodifyrequest(const asn1::s1ap::erab_modify_request_s& msg);
bool handle_uecontextmodifyrequest(const asn1::s1ap::ue_context_mod_request_s& msg); bool handle_uecontextmodifyrequest(const asn1::s1ap::ue_context_mod_request_s& msg);
// bool send_ue_capabilities(uint16_t rnti, LIBLTE_RRC_UE_EUTRA_CAPABILITY_STRUCT *caps) // bool send_ue_capabilities(uint16_t rnti, LIBLTE_RRC_UE_EUTRA_CAPABILITY_STRUCT *caps)
@ -192,6 +193,8 @@ private:
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_successfully_released,
const std::vector<uint16_t>& erabs_failed_to_release); const std::vector<uint16_t>& erabs_failed_to_release);
bool send_erab_modify_response(const std::vector<uint16_t>& erabs_successfully_released,
const std::vector<uint16_t>& erabs_failed_to_release);
bool was_uectxtrelease_requested() const { return release_requested; } bool was_uectxtrelease_requested() const { return release_requested; }
ue_ctxt_t ctxt = {}; ue_ctxt_t ctxt = {};

@ -333,6 +333,56 @@ void rrc::release_erabs(uint32_t rnti,
return; return;
} }
void rrc::modify_erabs(uint16_t rnti,
const asn1::s1ap::erab_modify_request_s& msg,
std::vector<uint16_t>* erabs_modified,
std::vector<uint16_t>* erabs_failed_to_modify)
{
rrc_log->info("Modifying E-RABs for 0x%x\n", rnti);
auto user_it = users.find(rnti);
if (user_it == users.end()) {
rrc_log->warning("Unrecognised rnti: 0x%x\n", rnti);
return;
}
// Iterate over bearers
for (uint32_t i = 0; i < msg.protocol_ies.erab_to_be_modified_list_bearer_mod_req.value.size(); i++) {
const asn1::s1ap::erab_to_be_modified_item_bearer_mod_req_s& erab_to_mod =
msg.protocol_ies.erab_to_be_modified_list_bearer_mod_req.value[i]
.value.erab_to_be_modified_item_bearer_mod_req();
uint32_t erab_id = erab_to_mod.erab_id;
asn1::s1ap::erab_level_qos_params_s qos_params = erab_to_mod.erab_level_qos_params;
bool ret = modify_ue_erab(rnti, erab_id, qos_params, &erab_to_mod.nas_pdu);
if (ret) {
erabs_modified->push_back(erab_to_mod.erab_id);
} else {
erabs_failed_to_modify->push_back(erab_to_mod.erab_id);
}
}
return;
}
bool rrc::modify_ue_erab(uint16_t rnti,
uint8_t erab_id,
const asn1::s1ap::erab_level_qos_params_s& qos_params,
const asn1::unbounded_octstring<true>* nas_pdu)
{
rrc_log->info("Modifying E-RAB for 0x%x. E-RAB Id %d\n", rnti, erab_id);
auto user_it = users.find(rnti);
if (user_it == users.end()) {
rrc_log->warning("Unrecognised rnti: 0x%x\n", rnti);
return false;
}
bool ret = user_it->second->modify_erab(erab_id, qos_params, nas_pdu);
return ret;
}
/******************************************************************************* /*******************************************************************************
Paging functions Paging functions
These functions use a different mutex because access different shared variables These functions use a different mutex because access different shared variables

@ -285,6 +285,23 @@ void bearer_cfg_handler::release_erabs()
} }
} }
bool bearer_cfg_handler::modify_erab(uint8_t erab_id,
const asn1::s1ap::erab_level_qos_params_s& qos,
const asn1::unbounded_octstring<true>* nas_pdu)
{
log_h->info("Modifying E-RAB %d\n", erab_id);
std::map<uint8_t, erab_t>::iterator erab_it = erabs.find(erab_id);
if (erab_it == erabs.end()) {
log_h->error("Could not find E-RAB to modify\n");
return false;
}
auto address = erab_it->second.address;
uint32_t teid_out = erab_it->second.teid_out;
release_erab(erab_id);
add_erab(erab_id, qos, address, teid_out, nas_pdu);
return true;
}
void bearer_cfg_handler::add_gtpu_bearer(srsenb::gtpu_interface_rrc* gtpu, uint32_t erab_id) void bearer_cfg_handler::add_gtpu_bearer(srsenb::gtpu_interface_rrc* gtpu, uint32_t erab_id)
{ {
auto it = erabs.find(erab_id); auto it = erabs.find(erab_id);

@ -838,6 +838,17 @@ bool rrc::ue::release_erab(uint32_t erab_id)
return bearer_list.release_erab(erab_id); return bearer_list.release_erab(erab_id);
} }
bool rrc::ue::modify_erab(uint16_t erab_id,
const asn1::s1ap::erab_level_qos_params_s& qos_params,
const asn1::unbounded_octstring<true>* nas_pdu)
{
bool ret = bearer_list.modify_erab(erab_id, qos_params, nas_pdu);
if (ret) {
send_connection_reconf(nullptr, false);
}
return ret;
}
void rrc::ue::notify_s1ap_ue_erab_setup_response(const asn1::s1ap::erab_to_be_setup_list_bearer_su_req_l& e) void rrc::ue::notify_s1ap_ue_erab_setup_response(const asn1::s1ap::erab_to_be_setup_list_bearer_su_req_l& e)
{ {
asn1::s1ap::erab_setup_resp_s res; asn1::s1ap::erab_setup_resp_s res;

@ -127,9 +127,7 @@ void fill_cqi_report_enb_cfg(cqi_report_cfg_s& cqi_report_cfg, const rrc_cfg_t&
cqi_report_cfg.nom_pdsch_rs_epre_offset = 0; cqi_report_cfg.nom_pdsch_rs_epre_offset = 0;
} }
int fill_cqi_report_setup(cqi_report_cfg_s& cqi_rep, int fill_cqi_report_setup(cqi_report_cfg_s& cqi_rep, const rrc_cfg_t& enb_cfg, const ue_cell_ded_list& ue_cell_list)
const rrc_cfg_t& enb_cfg,
const ue_cell_ded_list& ue_cell_list)
{ {
// eNB params set at this point // eNB params set at this point
@ -148,9 +146,7 @@ int fill_cqi_report_setup(cqi_report_cfg_s& cqi_rep,
return SRSLTE_SUCCESS; return SRSLTE_SUCCESS;
} }
void fill_cqi_report_reconf(cqi_report_cfg_s& cqi_rep, void fill_cqi_report_reconf(cqi_report_cfg_s& cqi_rep, const rrc_cfg_t& enb_cfg, const ue_cell_ded_list& ue_cell_list)
const rrc_cfg_t& enb_cfg,
const ue_cell_ded_list& ue_cell_list)
{ {
// Get RRC setup CQI config // Get RRC setup CQI config
if (fill_cqi_report_setup(cqi_rep, enb_cfg, ue_cell_list) == SRSLTE_ERROR) { if (fill_cqi_report_setup(cqi_rep, enb_cfg, ue_cell_list) == SRSLTE_ERROR) {
@ -229,9 +225,7 @@ void fill_phy_cfg_ded_enb_cfg(phys_cfg_ded_s& phy_cfg, const rrc_cfg_t& enb_cfg)
fill_cqi_report_enb_cfg(phy_cfg.cqi_report_cfg, enb_cfg); fill_cqi_report_enb_cfg(phy_cfg.cqi_report_cfg, enb_cfg);
} }
void fill_phy_cfg_ded_setup(phys_cfg_ded_s& phy_cfg, void fill_phy_cfg_ded_setup(phys_cfg_ded_s& phy_cfg, const rrc_cfg_t& enb_cfg, const ue_cell_ded_list& ue_cell_list)
const rrc_cfg_t& enb_cfg,
const ue_cell_ded_list& ue_cell_list)
{ {
// Set PHYConfigDedicated base // Set PHYConfigDedicated base
fill_phy_cfg_ded_enb_cfg(phy_cfg, enb_cfg); fill_phy_cfg_ded_enb_cfg(phy_cfg, enb_cfg);

@ -569,6 +569,8 @@ bool s1ap::handle_initiatingmessage(const init_msg_s& msg)
return handle_erabsetuprequest(msg.value.erab_setup_request()); return handle_erabsetuprequest(msg.value.erab_setup_request());
case s1ap_elem_procs_o::init_msg_c::types_opts::erab_release_cmd: case s1ap_elem_procs_o::init_msg_c::types_opts::erab_release_cmd:
return handle_erabreleasecommand(msg.value.erab_release_cmd()); return handle_erabreleasecommand(msg.value.erab_release_cmd());
case s1ap_elem_procs_o::init_msg_c::types_opts::erab_modify_request:
return handle_erabmodifyrequest(msg.value.erab_modify_request());
case s1ap_elem_procs_o::init_msg_c::types_opts::ue_context_mod_request: case s1ap_elem_procs_o::init_msg_c::types_opts::ue_context_mod_request:
return handle_uecontextmodifyrequest(msg.value.ue_context_mod_request()); return handle_uecontextmodifyrequest(msg.value.ue_context_mod_request());
case s1ap_elem_procs_o::init_msg_c::types_opts::ho_request: case s1ap_elem_procs_o::init_msg_c::types_opts::ho_request:
@ -707,9 +709,12 @@ bool s1ap::handle_erabsetuprequest(const erab_setup_request_s& msg)
return rrc->setup_ue_erabs(u->ctxt.rnti, msg); return rrc->setup_ue_erabs(u->ctxt.rnti, msg);
} }
bool s1ap::handle_erabreleasecommand(const erab_release_cmd_s& msg) bool s1ap::handle_erabmodifyrequest(const erab_modify_request_s& msg)
{ {
s1ap_log->info("Received ERABReleaseCommand\n"); s1ap_log->info("Received ERABModifyRequest\n");
std::vector<uint16_t> erab_successful_modified = {};
std::vector<uint16_t> erab_failed_to_modify = {};
if (msg.ext) { if (msg.ext) {
s1ap_log->warning("Not handling S1AP message extension\n"); s1ap_log->warning("Not handling S1AP message extension\n");
} }
@ -718,9 +723,32 @@ bool s1ap::handle_erabreleasecommand(const erab_release_cmd_s& msg)
return false; return false;
} }
// Modify E-RABs from RRC
rrc->modify_erabs(u->ctxt.rnti, msg, &erab_successful_modified, &erab_failed_to_modify);
// Send E-RAB modify response back to the MME
if (not u->send_erab_modify_response(erab_successful_modified, erab_failed_to_modify)) {
s1ap_log->info("Failed to send ERABReleaseResponse\n");
return false;
}
return true;
}
bool s1ap::handle_erabreleasecommand(const erab_release_cmd_s& msg)
{
s1ap_log->info("Received ERABReleaseCommand\n");
std::vector<uint16_t> erab_successful_release = {}; std::vector<uint16_t> erab_successful_release = {};
std::vector<uint16_t> erab_failed_to_release = {}; std::vector<uint16_t> erab_failed_to_release = {};
if (msg.ext) {
s1ap_log->warning("Not handling S1AP message extension\n");
}
ue* u = find_s1apmsg_user(msg.protocol_ies.enb_ue_s1ap_id.value.value, msg.protocol_ies.mme_ue_s1ap_id.value.value);
if (u == nullptr) {
return false;
}
// Release E-RABs from RRC // Release E-RABs from RRC
rrc->release_erabs(u->ctxt.rnti, msg, &erab_successful_release, &erab_failed_to_release); rrc->release_erabs(u->ctxt.rnti, msg, &erab_successful_release, &erab_failed_to_release);
@ -1279,6 +1307,47 @@ bool s1ap::ue::send_erab_release_response(const std::vector<uint16_t>& erabs_suc
return s1ap_ptr->sctp_send_s1ap_pdu(tx_pdu, ctxt.rnti, "E_RABReleaseResponse"); return s1ap_ptr->sctp_send_s1ap_pdu(tx_pdu, ctxt.rnti, "E_RABReleaseResponse");
} }
bool s1ap::ue::send_erab_modify_response(const std::vector<uint16_t>& erabs_successfully_modified,
const std::vector<uint16_t>& erabs_failed_to_modify)
{
if (not s1ap_ptr->mme_connected) {
return false;
}
asn1::s1ap::s1ap_pdu_c tx_pdu;
tx_pdu.set_successful_outcome().load_info_obj(ASN1_S1AP_ID_ERAB_MODIFY);
auto& container = tx_pdu.successful_outcome().value.erab_modify_resp().protocol_ies;
container.enb_ue_s1ap_id.value = ctxt.enb_ue_s1ap_id;
container.mme_ue_s1ap_id.value = ctxt.mme_ue_s1ap_id;
// Fill in which E-RABs were successfully released
if (not erabs_successfully_modified.empty()) {
container.erab_modify_list_bearer_mod_res_present = true;
container.erab_modify_list_bearer_mod_res.value.resize(erabs_successfully_modified.size());
for (uint32_t i = 0; i < container.erab_modify_list_bearer_mod_res.value.size(); i++) {
container.erab_modify_list_bearer_mod_res.value[i].load_info_obj(ASN1_S1AP_ID_ERAB_MODIFY_ITEM_BEARER_MOD_RES);
container.erab_modify_list_bearer_mod_res.value[i].value.erab_modify_item_bearer_mod_res().erab_id =
erabs_successfully_modified[i];
}
}
// Fill in which E-RABs were *not* successfully released
if (not erabs_failed_to_modify.empty()) {
container.erab_failed_to_modify_list_present = true;
container.erab_failed_to_modify_list.value.resize(erabs_failed_to_modify.size());
for (uint32_t i = 0; i < container.erab_failed_to_modify_list.value.size(); i++) {
container.erab_failed_to_modify_list.value[i].load_info_obj(ASN1_S1AP_ID_ERAB_ITEM);
container.erab_failed_to_modify_list.value[i].value.erab_item().erab_id = erabs_failed_to_modify[i];
container.erab_failed_to_modify_list.value[i].value.erab_item().cause.set(asn1::s1ap::cause_c::types::misc);
container.erab_failed_to_modify_list.value[i].value.erab_item().cause.misc() =
asn1::s1ap::cause_misc_opts::unspecified;
}
}
return s1ap_ptr->sctp_send_s1ap_pdu(tx_pdu, ctxt.rnti, "E_RABReleaseResponse");
}
/********************* /*********************
* Handover Messages * Handover Messages
********************/ ********************/

@ -106,6 +106,11 @@ public:
uint32_t mme_ue_s1ap_id, uint32_t mme_ue_s1ap_id,
std::vector<uint16_t> erabs_to_release, std::vector<uint16_t> erabs_to_release,
struct sctp_sndrcvinfo enb_sri); struct sctp_sndrcvinfo enb_sri);
virtual bool send_erab_modify_request(uint32_t enb_ue_s1ap_id,
uint32_t mme_ue_s1ap_id,
std::map<uint16_t, uint16_t> erabs_to_be_modified,
srslte::byte_buffer_t* nas_msg,
struct sctp_sndrcvinfo enb_sri);
virtual bool send_downlink_nas_transport(uint32_t enb_ue_s1ap_id, virtual bool send_downlink_nas_transport(uint32_t enb_ue_s1ap_id,
uint32_t mme_ue_s1ap_id, uint32_t mme_ue_s1ap_id,
srslte::byte_buffer_t* nas_msg, srslte::byte_buffer_t* nas_msg,

@ -37,6 +37,11 @@ public:
uint32_t mme_ue_s1ap_id, uint32_t mme_ue_s1ap_id,
std::vector<uint16_t> erabs_to_release, std::vector<uint16_t> erabs_to_release,
struct sctp_sndrcvinfo enb_sri); struct sctp_sndrcvinfo enb_sri);
bool send_erab_modify_request(uint32_t enb_ue_s1ap_id,
uint32_t mme_ue_s1ap_id,
std::map<uint16_t, uint16_t> erabs_to_modify,
srslte::byte_buffer_t* nas_msg,
struct sctp_sndrcvinfo enb_sri);
bool handle_erab_release_response(const asn1::s1ap::init_context_setup_resp_s& in_ctxt_resp); bool handle_erab_release_response(const asn1::s1ap::init_context_setup_resp_s& in_ctxt_resp);
private: private:

@ -630,6 +630,16 @@ bool s1ap::send_erab_release_command(uint32_t enb_ue_s1ap_id,
enb_ue_s1ap_id, mme_ue_s1ap_id, erabs_to_be_released, enb_sri); enb_ue_s1ap_id, mme_ue_s1ap_id, erabs_to_be_released, enb_sri);
} }
bool s1ap::send_erab_modify_request(uint32_t enb_ue_s1ap_id,
uint32_t mme_ue_s1ap_id,
std::map<uint16_t, uint16_t> erabs_to_be_modified,
srslte::byte_buffer_t* nas_msg,
struct sctp_sndrcvinfo enb_sri)
{
return m_s1ap_erab_mngmt_proc->send_erab_modify_request(
enb_ue_s1ap_id, mme_ue_s1ap_id, erabs_to_be_modified, nas_msg, enb_sri);
}
bool s1ap::send_downlink_nas_transport(uint32_t enb_ue_s1ap_id, bool s1ap::send_downlink_nas_transport(uint32_t enb_ue_s1ap_id,
uint32_t mme_ue_s1ap_id, uint32_t mme_ue_s1ap_id,
srslte::byte_buffer_t* nas_msg, srslte::byte_buffer_t* nas_msg,

@ -96,4 +96,51 @@ bool s1ap_erab_mngmt_proc::send_erab_release_command(uint32_t enb_
return true; return true;
} }
bool s1ap_erab_mngmt_proc::send_erab_modify_request(uint32_t enb_ue_s1ap_id,
uint32_t mme_ue_s1ap_id,
std::map<uint16_t, uint16_t> erabs_to_modify,
srslte::byte_buffer_t* nas_msg,
struct sctp_sndrcvinfo enb_sri)
{
m_s1ap_log->info("Preparing to send E-RAB Modify Command\n");
// Prepare reply PDU
s1ap_pdu_t tx_pdu;
tx_pdu.set_init_msg().load_info_obj(ASN1_S1AP_ID_ERAB_MODIFY);
asn1::s1ap::erab_modify_request_ies_container& erab_mod_req =
tx_pdu.init_msg().value.erab_modify_request().protocol_ies;
// Add MME and eNB S1AP Ids
erab_mod_req.enb_ue_s1ap_id.value = enb_ue_s1ap_id;
erab_mod_req.mme_ue_s1ap_id.value = mme_ue_s1ap_id;
// Number of E-RABs to be setup
erab_mod_req.erab_to_be_modified_list_bearer_mod_req.value.resize(erabs_to_modify.size());
uint32_t i = 0;
for (auto erab_it = erabs_to_modify.begin(); erab_it != erabs_to_modify.end(); erab_it++) {
erab_mod_req.erab_to_be_modified_list_bearer_mod_req.value[i].load_info_obj(
ASN1_S1AP_ID_ERAB_TO_BE_MODIFIED_ITEM_BEARER_MOD_REQ);
asn1::s1ap::erab_to_be_modified_item_bearer_mod_req_s& erab_to_mod =
erab_mod_req.erab_to_be_modified_list_bearer_mod_req.value[i].value.erab_to_be_modified_item_bearer_mod_req();
erab_to_mod.erab_id = erab_it->first;
erab_to_mod.erab_level_qos_params.qci = erab_it->second;
erab_to_mod.erab_level_qos_params.alloc_retention_prio.prio_level = 15; // lowest
erab_to_mod.erab_level_qos_params.alloc_retention_prio.pre_emption_cap =
asn1::s1ap::pre_emption_cap_opts::shall_not_trigger_pre_emption;
erab_to_mod.erab_level_qos_params.alloc_retention_prio.pre_emption_vulnerability =
asn1::s1ap::pre_emption_vulnerability_opts::not_pre_emptable;
erab_to_mod.nas_pdu.resize(nas_msg->N_bytes);
memcpy(erab_to_mod.nas_pdu.data(), nas_msg->msg, nas_msg->N_bytes);
m_s1ap_log->info("Sending release comman to E-RAB Id %d\n", erab_it->first);
i++;
}
if (!m_s1ap->s1ap_tx_pdu(tx_pdu, &enb_sri)) {
m_s1ap_log->error("Error sending Initial Context Setup Request.\n");
return false;
}
return true;
}
} // namespace srsepc } // namespace srsepc

Loading…
Cancel
Save