updated s1ap rrc interface with new asn1 lib types

master
Francisco Paisana 5 years ago
parent 61b3e6b57e
commit b6c53d786b

@ -23,12 +23,12 @@
#include "srslte/asn1/liblte_s1ap.h" #include "srslte/asn1/liblte_s1ap.h"
#include "srslte/asn1/rrc_asn1.h" #include "srslte/asn1/rrc_asn1.h"
#include "srslte/asn1/s1ap_asn1.h"
#include "srslte/common/common.h" #include "srslte/common/common.h"
#include "srslte/common/interfaces_common.h" #include "srslte/common/interfaces_common.h"
#include "srslte/common/security.h" #include "srslte/common/security.h"
#include "srslte/interfaces/rrc_interface_types.h" #include "srslte/interfaces/rrc_interface_types.h"
#include "srslte/interfaces/sched_interface.h" #include "srslte/interfaces/sched_interface.h"
#include <vector> #include <vector>
#ifndef SRSLTE_ENB_INTERFACES_H #ifndef SRSLTE_ENB_INTERFACES_H
@ -303,18 +303,18 @@ public:
}; };
virtual void virtual void
initial_ue(uint16_t rnti, LIBLTE_S1AP_RRC_ESTABLISHMENT_CAUSE_ENUM cause, srslte::unique_byte_buffer_t pdu) = 0; initial_ue(uint16_t rnti, asn1::s1ap::rrc_establishment_cause_e cause, srslte::unique_byte_buffer_t pdu) = 0;
virtual void initial_ue(uint16_t rnti, virtual void initial_ue(uint16_t rnti,
LIBLTE_S1AP_RRC_ESTABLISHMENT_CAUSE_ENUM cause, asn1::s1ap::rrc_establishment_cause_e cause,
srslte::unique_byte_buffer_t pdu, srslte::unique_byte_buffer_t pdu,
uint32_t m_tmsi, uint32_t m_tmsi,
uint8_t mmec) = 0; uint8_t mmec) = 0;
virtual void write_pdu(uint16_t rnti, srslte::unique_byte_buffer_t pdu) = 0; virtual void write_pdu(uint16_t rnti, srslte::unique_byte_buffer_t pdu) = 0;
virtual bool user_exists(uint16_t rnti) = 0; virtual bool user_exists(uint16_t rnti) = 0;
virtual bool user_release(uint16_t rnti, LIBLTE_S1AP_CAUSERADIONETWORK_ENUM cause_radio) = 0; virtual bool user_release(uint16_t rnti, asn1::s1ap::cause_radio_network_e cause_radio) = 0;
virtual void ue_ctxt_setup_complete(uint16_t rnti, LIBLTE_S1AP_MESSAGE_INITIALCONTEXTSETUPRESPONSE_STRUCT* res) = 0; virtual void ue_ctxt_setup_complete(uint16_t rnti, const asn1::s1ap::init_context_setup_resp_s& res) = 0;
virtual void ue_erab_setup_complete(uint16_t rnti, LIBLTE_S1AP_MESSAGE_E_RABSETUPRESPONSE_STRUCT* res) = 0; virtual void ue_erab_setup_complete(uint16_t rnti, const asn1::s1ap::e_rab_setup_resp_s& res) = 0;
virtual bool is_mme_connected() = 0; virtual bool is_mme_connected() = 0;
virtual bool send_ho_required(uint16_t rnti, virtual bool send_ho_required(uint16_t rnti,
uint32_t target_eci, uint32_t target_eci,

@ -19,7 +19,7 @@
# #
add_executable(s1ap_test s1ap_test.cc) add_executable(s1ap_test s1ap_test.cc)
target_link_libraries(s1ap_test srslte_common srslte_asn1) target_link_libraries(s1ap_test srslte_common srslte_asn1 s1ap_asn1)
add_test(s1ap_test s1ap_test) add_test(s1ap_test s1ap_test)
add_executable(srslte_asn1_rrc_mcch_test srslte_asn1_rrc_mcch_test.cc) add_executable(srslte_asn1_rrc_mcch_test srslte_asn1_rrc_mcch_test.cc)

@ -63,18 +63,19 @@ public:
void get_metrics(s1ap_metrics_t& m); void get_metrics(s1ap_metrics_t& m);
// RRC interface // RRC interface
void initial_ue(uint16_t rnti, LIBLTE_S1AP_RRC_ESTABLISHMENT_CAUSE_ENUM cause, srslte::unique_byte_buffer_t pdu); void
initial_ue(uint16_t rnti, asn1::s1ap::rrc_establishment_cause_e cause, srslte::unique_byte_buffer_t pdu) override;
void initial_ue(uint16_t rnti, void initial_ue(uint16_t rnti,
LIBLTE_S1AP_RRC_ESTABLISHMENT_CAUSE_ENUM cause, asn1::s1ap::rrc_establishment_cause_e cause,
srslte::unique_byte_buffer_t pdu, srslte::unique_byte_buffer_t pdu,
uint32_t m_tmsi, uint32_t m_tmsi,
uint8_t mmec); uint8_t mmec) override;
void write_pdu(uint16_t rnti, srslte::unique_byte_buffer_t pdu); void write_pdu(uint16_t rnti, srslte::unique_byte_buffer_t pdu) override;
bool user_exists(uint16_t rnti); bool user_exists(uint16_t rnti) override;
bool user_release(uint16_t rnti, LIBLTE_S1AP_CAUSERADIONETWORK_ENUM cause_radio); bool user_release(uint16_t rnti, asn1::s1ap::cause_radio_network_e cause_radio) override;
void ue_ctxt_setup_complete(uint16_t rnti, LIBLTE_S1AP_MESSAGE_INITIALCONTEXTSETUPRESPONSE_STRUCT* res); void ue_ctxt_setup_complete(uint16_t rnti, const asn1::s1ap::init_context_setup_resp_s& res) override;
void ue_erab_setup_complete(uint16_t rnti, LIBLTE_S1AP_MESSAGE_E_RABSETUPRESPONSE_STRUCT* res); void ue_erab_setup_complete(uint16_t rnti, const asn1::s1ap::e_rab_setup_resp_s& res) override;
bool is_mme_connected(); bool is_mme_connected() override;
// void ue_capabilities(uint16_t rnti, LIBLTE_RRC_UE_EUTRA_CAPABILITY_STRUCT *caps); // void ue_capabilities(uint16_t rnti, LIBLTE_RRC_UE_EUTRA_CAPABILITY_STRUCT *caps);
// Stack interface // Stack interface
@ -114,6 +115,7 @@ private:
bool connect_mme(); bool connect_mme();
bool setup_s1(); bool setup_s1();
bool sctp_send_s1ap_pdu(LIBLTE_S1AP_S1AP_PDU_STRUCT* tx_pdu, uint32_t rnti, const char* procedure_name); bool sctp_send_s1ap_pdu(LIBLTE_S1AP_S1AP_PDU_STRUCT* tx_pdu, uint32_t rnti, const char* procedure_name);
bool sctp_send_s1ap_pdu(const asn1::s1ap::s1ap_pdu_c& tx_pdu, uint32_t rnti, const char* procedure_name);
bool handle_s1ap_rx_pdu(srslte::byte_buffer_t* pdu); bool handle_s1ap_rx_pdu(srslte::byte_buffer_t* pdu);
bool handle_initiatingmessage(LIBLTE_S1AP_INITIATINGMESSAGE_STRUCT* msg); bool handle_initiatingmessage(LIBLTE_S1AP_INITIATINGMESSAGE_STRUCT* msg);
@ -131,20 +133,20 @@ private:
bool handle_uecontextmodifyrequest(LIBLTE_S1AP_MESSAGE_UECONTEXTMODIFICATIONREQUEST_STRUCT* msg); bool handle_uecontextmodifyrequest(LIBLTE_S1AP_MESSAGE_UECONTEXTMODIFICATIONREQUEST_STRUCT* msg);
bool send_initialuemessage(uint16_t rnti, bool send_initialuemessage(uint16_t rnti,
LIBLTE_S1AP_RRC_ESTABLISHMENT_CAUSE_ENUM cause, asn1::s1ap::rrc_establishment_cause_e cause,
srslte::unique_byte_buffer_t pdu, srslte::unique_byte_buffer_t pdu,
bool has_tmsi, bool has_tmsi,
uint32_t m_tmsi = 0, uint32_t m_tmsi = 0,
uint8_t mmec = 0); uint8_t mmec = 0);
bool send_ulnastransport(uint16_t rnti, srslte::unique_byte_buffer_t pdu); bool send_ulnastransport(uint16_t rnti, srslte::unique_byte_buffer_t pdu);
bool send_uectxtreleaserequest(uint16_t rnti, LIBLTE_S1AP_CAUSE_STRUCT* cause); bool send_uectxtreleaserequest(uint16_t rnti, const asn1::s1ap::cause_c& cause);
bool send_uectxtreleasecomplete(uint16_t rnti, uint32_t mme_ue_id, uint32_t enb_ue_id); bool send_uectxtreleasecomplete(uint16_t rnti, uint32_t mme_ue_id, uint32_t enb_ue_id);
bool send_initial_ctxt_setup_response(uint16_t rnti, LIBLTE_S1AP_MESSAGE_INITIALCONTEXTSETUPRESPONSE_STRUCT* res_); bool send_initial_ctxt_setup_response(uint16_t rnti, const asn1::s1ap::init_context_setup_resp_s& res_);
bool send_initial_ctxt_setup_failure(uint16_t rnti); bool send_initial_ctxt_setup_failure(uint16_t rnti);
bool send_erab_setup_response(uint16_t rnti, LIBLTE_S1AP_MESSAGE_E_RABSETUPRESPONSE_STRUCT* res_); bool send_erab_setup_response(uint16_t rnti, const asn1::s1ap::e_rab_setup_resp_s& res_);
// 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)
bool send_uectxmodifyresp(uint16_t rnti); bool send_uectxmodifyresp(uint16_t rnti);
bool send_uectxmodifyfailure(uint16_t rnti, LIBLTE_S1AP_CAUSE_STRUCT* cause); bool send_uectxmodifyfailure(uint16_t rnti, const asn1::s1ap::cause_c& cause);
// handover // handover
bool send_ho_required(uint16_t rnti, bool send_ho_required(uint16_t rnti,
uint32_t target_eci, uint32_t target_eci,

@ -47,6 +47,7 @@ target_link_libraries(srsenb srsenb_radio
srslte_upper srslte_upper
srslte_radio srslte_radio
rrc_asn1 rrc_asn1
s1ap_asn1
enb_cfg_parser enb_cfg_parser
${CMAKE_THREAD_LIBS_INIT} ${CMAKE_THREAD_LIBS_INIT}
${Boost_LIBRARIES} ${Boost_LIBRARIES}

@ -659,7 +659,7 @@ void rrc::parse_ul_ccch(uint16_t rnti, srslte::unique_byte_buffer_t pdu)
rrc_log->error("Not supported: ConnectionReestablishment for rnti=0x%x. Sending Connection Reject\n", rrc_log->error("Not supported: ConnectionReestablishment for rnti=0x%x. Sending Connection Reject\n",
old_rnti); old_rnti);
user_it->second->send_connection_reest_rej(); user_it->second->send_connection_reest_rej();
s1ap->user_release(old_rnti, LIBLTE_S1AP_CAUSERADIONETWORK_RELEASE_DUE_TO_EUTRAN_GENERATED_REASON); s1ap->user_release(old_rnti, asn1::s1ap::cause_radio_network_opts::release_due_to_eutran_generated_reason);
} else { } else {
rrc_log->error("Received ConnectionReestablishment for rnti=0x%x without context\n", old_rnti); rrc_log->error("Received ConnectionReestablishment for rnti=0x%x without context\n", old_rnti);
user_it->second->send_connection_reest_rej(); user_it->second->send_connection_reest_rej();
@ -701,7 +701,7 @@ void rrc::process_rl_failure(uint16_t rnti)
if (n_rfl == 1) { if (n_rfl == 1) {
rrc_log->info("Radio-Link failure detected rnti=0x%x\n", rnti); rrc_log->info("Radio-Link failure detected rnti=0x%x\n", rnti);
if (s1ap->user_exists(rnti)) { if (s1ap->user_exists(rnti)) {
if (!s1ap->user_release(rnti, LIBLTE_S1AP_CAUSERADIONETWORK_RADIO_CONNECTION_WITH_UE_LOST)) { if (!s1ap->user_release(rnti, asn1::s1ap::cause_radio_network_opts::radio_conn_with_ue_lost)) {
rrc_log->info("Removing rnti=0x%x\n", rnti); rrc_log->info("Removing rnti=0x%x\n", rnti);
} }
} else { } else {
@ -1023,7 +1023,7 @@ void rrc::ue::activity_timer_expired()
} }
if (parent->s1ap->user_exists(rnti)) { if (parent->s1ap->user_exists(rnti)) {
parent->s1ap->user_release(rnti, LIBLTE_S1AP_CAUSERADIONETWORK_USER_INACTIVITY); parent->s1ap->user_release(rnti, asn1::s1ap::cause_radio_network_opts::user_inactivity);
} else { } else {
if (rnti != SRSLTE_MRNTI) { if (rnti != SRSLTE_MRNTI) {
parent->rem_user_thread(rnti); parent->rem_user_thread(rnti);
@ -1200,11 +1200,12 @@ void rrc::ue::handle_rrc_con_setup_complete(rrc_conn_setup_complete_s* msg, srsl
// Acknowledge Dedicated Configuration // Acknowledge Dedicated Configuration
parent->mac->phy_config_enabled(rnti, true); parent->mac->phy_config_enabled(rnti, true);
asn1::s1ap::rrc_establishment_cause_e s1ap_cause;
s1ap_cause.value = (asn1::s1ap::rrc_establishment_cause_opts::options)establishment_cause.value;
if (has_tmsi) { if (has_tmsi) {
parent->s1ap->initial_ue( parent->s1ap->initial_ue(rnti, s1ap_cause, std::move(pdu), m_tmsi, mmec);
rnti, (LIBLTE_S1AP_RRC_ESTABLISHMENT_CAUSE_ENUM)establishment_cause.value, std::move(pdu), m_tmsi, mmec);
} else { } else {
parent->s1ap->initial_ue(rnti, (LIBLTE_S1AP_RRC_ESTABLISHMENT_CAUSE_ENUM)establishment_cause.value, std::move(pdu)); parent->s1ap->initial_ue(rnti, s1ap_cause, std::move(pdu));
} }
state = RRC_STATE_WAIT_FOR_CON_RECONF_COMPLETE; state = RRC_STATE_WAIT_FOR_CON_RECONF_COMPLETE;
} }
@ -1380,49 +1381,36 @@ bool rrc::ue::release_erabs()
void rrc::ue::notify_s1ap_ue_ctxt_setup_complete() void rrc::ue::notify_s1ap_ue_ctxt_setup_complete()
{ {
LIBLTE_S1AP_MESSAGE_INITIALCONTEXTSETUPRESPONSE_STRUCT res; asn1::s1ap::init_context_setup_resp_s res;
res.ext = false;
res.E_RABFailedToSetupListCtxtSURes_present = false;
res.CriticalityDiagnostics_present = false;
res.E_RABSetupListCtxtSURes.len = 0;
res.E_RABFailedToSetupListCtxtSURes.len = 0;
res.protocol_ies.e_rab_setup_list_ctxt_su_res.value.resize(erabs.size());
uint32_t i = 0;
for (auto& erab : erabs) { for (auto& erab : erabs) {
uint32_t j = res.E_RABSetupListCtxtSURes.len++; res.protocol_ies.e_rab_setup_list_ctxt_su_res.value[i].load_info_obj(ASN1_S1AP_ID_E_RAB_SETUP_ITEM_CTXT_SU_RES);
res.E_RABSetupListCtxtSURes.buffer[j].ext = false; auto& item = res.protocol_ies.e_rab_setup_list_ctxt_su_res.value[i].value.e_rab_setup_item_ctxt_su_res();
res.E_RABSetupListCtxtSURes.buffer[j].iE_Extensions_present = false; item.e_rab_id = erab.second.id;
res.E_RABSetupListCtxtSURes.buffer[j].e_RAB_ID.ext = false; uint32_to_uint8(erab.second.teid_in, item.gtp_teid.data());
res.E_RABSetupListCtxtSURes.buffer[j].e_RAB_ID.E_RAB_ID = erab.second.id; i++;
uint32_to_uint8(erab.second.teid_in, res.E_RABSetupListCtxtSURes.buffer[j].gTP_TEID.buffer);
} }
parent->s1ap->ue_ctxt_setup_complete(rnti, &res); parent->s1ap->ue_ctxt_setup_complete(rnti, res);
} }
void rrc::ue::notify_s1ap_ue_erab_setup_response(LIBLTE_S1AP_E_RABTOBESETUPLISTBEARERSUREQ_STRUCT* e) void rrc::ue::notify_s1ap_ue_erab_setup_response(LIBLTE_S1AP_E_RABTOBESETUPLISTBEARERSUREQ_STRUCT* e)
{ {
LIBLTE_S1AP_MESSAGE_E_RABSETUPRESPONSE_STRUCT res; asn1::s1ap::e_rab_setup_resp_s res;
res.ext = false;
res.E_RABSetupListBearerSURes.len = 0;
res.E_RABFailedToSetupListBearerSURes.len = 0;
res.CriticalityDiagnostics_present = false;
res.E_RABFailedToSetupListBearerSURes_present = false;
for (uint32_t i = 0; i < e->len; i++) { res.protocol_ies.e_rab_setup_list_bearer_su_res.value.resize(e->len);
res.E_RABSetupListBearerSURes_present = true; for (uint32_t i = 0; i < e->len; ++i) {
LIBLTE_S1AP_E_RABTOBESETUPITEMBEARERSUREQ_STRUCT* erab = &e->buffer[i]; res.protocol_ies.e_rab_setup_list_bearer_su_res_present = true;
uint8_t id = erab->e_RAB_ID.E_RAB_ID; auto& item = res.protocol_ies.e_rab_setup_list_bearer_su_res.value[i];
uint32_t j = res.E_RABSetupListBearerSURes.len++; item.load_info_obj(ASN1_S1AP_ID_E_RAB_SETUP_ITEM_BEARER_SU_RES);
res.E_RABSetupListBearerSURes.buffer[j].ext = false; uint8_t id = e->buffer[i].e_RAB_ID.E_RAB_ID;
res.E_RABSetupListBearerSURes.buffer[j].iE_Extensions_present = false; item.value.e_rab_setup_item_bearer_su_res().e_rab_id = id;
res.E_RABSetupListBearerSURes.buffer[j].e_RAB_ID.ext = false; uint32_to_uint8(erabs[id].teid_in, &item.value.e_rab_setup_item_bearer_su_res().gtp_teid[0]);
res.E_RABSetupListBearerSURes.buffer[j].e_RAB_ID.E_RAB_ID = id;
uint32_to_uint8(erabs[id].teid_in, res.E_RABSetupListBearerSURes.buffer[j].gTP_TEID.buffer);
} }
parent->s1ap->ue_erab_setup_complete(rnti, &res); parent->s1ap->ue_erab_setup_complete(rnti, res);
} }
void rrc::ue::send_connection_reest_rej() void rrc::ue::send_connection_reest_rej()

@ -40,6 +40,8 @@ using srslte::uint32_to_uint8;
#define procWarning(fmt, ...) s1ap_ptr->s1ap_log->warning("Proc \"%s\" - " fmt, name(), ##__VA_ARGS__) #define procWarning(fmt, ...) s1ap_ptr->s1ap_log->warning("Proc \"%s\" - " fmt, name(), ##__VA_ARGS__)
#define procInfo(fmt, ...) s1ap_ptr->s1ap_log->info("Proc \"%s\" - " fmt, name(), ##__VA_ARGS__) #define procInfo(fmt, ...) s1ap_ptr->s1ap_log->info("Proc \"%s\" - " fmt, name(), ##__VA_ARGS__)
using namespace asn1::s1ap;
namespace srsenb { namespace srsenb {
/********************************************************* /*********************************************************
@ -319,14 +321,14 @@ void s1ap::build_tai_cgi()
/******************************************************************************* /*******************************************************************************
/* RRC interface /* RRC interface
********************************************************************************/ ********************************************************************************/
void s1ap::initial_ue(uint16_t rnti, LIBLTE_S1AP_RRC_ESTABLISHMENT_CAUSE_ENUM cause, srslte::unique_byte_buffer_t pdu) void s1ap::initial_ue(uint16_t rnti, asn1::s1ap::rrc_establishment_cause_e cause, srslte::unique_byte_buffer_t pdu)
{ {
users.insert(std::make_pair(rnti, std::unique_ptr<ue>(new ue{rnti, this}))); users.insert(std::make_pair(rnti, std::unique_ptr<ue>(new ue{rnti, this})));
send_initialuemessage(rnti, cause, std::move(pdu), false); send_initialuemessage(rnti, cause, std::move(pdu), false);
} }
void s1ap::initial_ue(uint16_t rnti, void s1ap::initial_ue(uint16_t rnti,
LIBLTE_S1AP_RRC_ESTABLISHMENT_CAUSE_ENUM cause, asn1::s1ap::rrc_establishment_cause_e cause,
srslte::unique_byte_buffer_t pdu, srslte::unique_byte_buffer_t pdu,
uint32_t m_tmsi, uint32_t m_tmsi,
uint8_t mmec) uint8_t mmec)
@ -344,7 +346,7 @@ void s1ap::write_pdu(uint16_t rnti, srslte::unique_byte_buffer_t pdu)
} }
} }
bool s1ap::user_release(uint16_t rnti, LIBLTE_S1AP_CAUSERADIONETWORK_ENUM cause_radio) bool s1ap::user_release(uint16_t rnti, asn1::s1ap::cause_radio_network_e cause_radio)
{ {
s1ap_log->info("User inactivity - RNTI:0x%x\n", rnti); s1ap_log->info("User inactivity - RNTI:0x%x\n", rnti);
@ -360,14 +362,11 @@ bool s1ap::user_release(uint16_t rnti, LIBLTE_S1AP_CAUSERADIONETWORK_ENUM cause_
return false; return false;
} }
LIBLTE_S1AP_CAUSE_STRUCT cause; cause_c cause;
cause.ext = false; cause.set_radio_network().value = cause_radio.value;
cause.choice_type = LIBLTE_S1AP_CAUSE_CHOICE_RADIONETWORK;
cause.choice.radioNetwork.ext = false;
cause.choice.radioNetwork.e = cause_radio;
ctxt->release_requested = true; ctxt->release_requested = true;
return send_uectxtreleaserequest(rnti, &cause); return send_uectxtreleaserequest(rnti, cause);
} }
bool s1ap::user_exists(uint16_t rnti) bool s1ap::user_exists(uint16_t rnti)
@ -375,16 +374,16 @@ bool s1ap::user_exists(uint16_t rnti)
return users.end() != users.find(rnti); return users.end() != users.find(rnti);
} }
void s1ap::ue_ctxt_setup_complete(uint16_t rnti, LIBLTE_S1AP_MESSAGE_INITIALCONTEXTSETUPRESPONSE_STRUCT* res) void s1ap::ue_ctxt_setup_complete(uint16_t rnti, const asn1::s1ap::init_context_setup_resp_s& res)
{ {
if (res->E_RABSetupListCtxtSURes.len > 0) { if (res.protocol_ies.e_rab_setup_list_ctxt_su_res.value.size() > 0) {
send_initial_ctxt_setup_response(rnti, res); send_initial_ctxt_setup_response(rnti, res);
} else { } else {
send_initial_ctxt_setup_failure(rnti); send_initial_ctxt_setup_failure(rnti);
} }
} }
void s1ap::ue_erab_setup_complete(uint16_t rnti, LIBLTE_S1AP_MESSAGE_E_RABSETUPRESPONSE_STRUCT* res) void s1ap::ue_erab_setup_complete(uint16_t rnti, const asn1::s1ap::e_rab_setup_resp_s& res)
{ {
send_erab_setup_response(rnti, res); send_erab_setup_response(rnti, res);
} }
@ -670,15 +669,12 @@ bool s1ap::handle_initialctxtsetuprequest(LIBLTE_S1AP_MESSAGE_INITIALCONTEXTSETU
if (msg->CSFallbackIndicator.e == LIBLTE_S1AP_CSFALLBACKINDICATOR_CS_FALLBACK_REQUIRED || if (msg->CSFallbackIndicator.e == LIBLTE_S1AP_CSFALLBACKINDICATOR_CS_FALLBACK_REQUIRED ||
msg->CSFallbackIndicator.e == LIBLTE_S1AP_CSFALLBACKINDICATOR_CS_FALLBACK_HIGH_PRIORITY) { msg->CSFallbackIndicator.e == LIBLTE_S1AP_CSFALLBACKINDICATOR_CS_FALLBACK_HIGH_PRIORITY) {
// Send RRC Release (cs-fallback-triggered) to MME // Send RRC Release (cs-fallback-triggered) to MME
LIBLTE_S1AP_CAUSE_STRUCT cause; cause_c cause;
cause.ext = false; cause.set_radio_network().value = cause_radio_network_opts::cs_fallback_triggered;
cause.choice_type = LIBLTE_S1AP_CAUSE_CHOICE_RADIONETWORK;
cause.choice.radioNetwork.ext = false;
cause.choice.radioNetwork.e = LIBLTE_S1AP_CAUSERADIONETWORK_CS_FALLBACK_TRIGGERED;
/* TODO: This should normally probably only be sent after the SecurityMode procedure has completed! */ /* TODO: This should normally probably only be sent after the SecurityMode procedure has completed! */
ctxt->release_requested = true; ctxt->release_requested = true;
send_uectxtreleaserequest(rnti, &cause); send_uectxtreleaserequest(rnti, cause);
} }
} }
@ -736,12 +732,9 @@ bool s1ap::handle_uecontextmodifyrequest(LIBLTE_S1AP_MESSAGE_UECONTEXTMODIFICATI
} }
if (!rrc->modify_ue_ctxt(rnti, msg)) { if (!rrc->modify_ue_ctxt(rnti, msg)) {
LIBLTE_S1AP_CAUSE_STRUCT cause; cause_c cause;
cause.ext = false; cause.set_misc().value = cause_misc_opts::unspecified;
cause.choice_type = LIBLTE_S1AP_CAUSE_CHOICE_MISC; send_uectxmodifyfailure(rnti, cause);
cause.choice.misc.ext = false;
cause.choice.misc.e = LIBLTE_S1AP_CAUSEMISC_UNSPECIFIED;
send_uectxmodifyfailure(rnti, &cause);
return true; return true;
} }
@ -753,14 +746,11 @@ bool s1ap::handle_uecontextmodifyrequest(LIBLTE_S1AP_MESSAGE_UECONTEXTMODIFICATI
if (msg->CSFallbackIndicator.e == LIBLTE_S1AP_CSFALLBACKINDICATOR_CS_FALLBACK_REQUIRED || if (msg->CSFallbackIndicator.e == LIBLTE_S1AP_CSFALLBACKINDICATOR_CS_FALLBACK_REQUIRED ||
msg->CSFallbackIndicator.e == LIBLTE_S1AP_CSFALLBACKINDICATOR_CS_FALLBACK_HIGH_PRIORITY) { msg->CSFallbackIndicator.e == LIBLTE_S1AP_CSFALLBACKINDICATOR_CS_FALLBACK_HIGH_PRIORITY) {
// Send RRC Release (cs-fallback-triggered) to MME // Send RRC Release (cs-fallback-triggered) to MME
LIBLTE_S1AP_CAUSE_STRUCT cause; cause_c cause;
cause.ext = false; cause.set_radio_network().value = cause_radio_network_opts::cs_fallback_triggered;
cause.choice_type = LIBLTE_S1AP_CAUSE_CHOICE_RADIONETWORK;
cause.choice.radioNetwork.ext = false;
cause.choice.radioNetwork.e = LIBLTE_S1AP_CAUSERADIONETWORK_CS_FALLBACK_TRIGGERED;
ctxt->release_requested = true; ctxt->release_requested = true;
send_uectxtreleaserequest(rnti, &cause); send_uectxtreleaserequest(rnti, cause);
} }
} }
@ -852,7 +842,7 @@ bool s1ap::handle_s1hocommand(LIBLTE_S1AP_MESSAGE_HANDOVERCOMMAND_STRUCT& msg)
********************************************************************************/ ********************************************************************************/
bool s1ap::send_initialuemessage(uint16_t rnti, bool s1ap::send_initialuemessage(uint16_t rnti,
LIBLTE_S1AP_RRC_ESTABLISHMENT_CAUSE_ENUM cause, asn1::s1ap::rrc_establishment_cause_e cause,
srslte::unique_byte_buffer_t pdu, srslte::unique_byte_buffer_t pdu,
bool has_tmsi, bool has_tmsi,
uint32_t m_tmsi, uint32_t m_tmsi,
@ -863,58 +853,42 @@ bool s1ap::send_initialuemessage(uint16_t rnti,
} }
srslte::byte_buffer_t msg; srslte::byte_buffer_t msg;
LIBLTE_S1AP_S1AP_PDU_STRUCT tx_pdu; s1ap_pdu_c tx_pdu;
tx_pdu.ext = false; tx_pdu.set_init_msg().load_info_obj(ASN1_S1AP_ID_INIT_UE_MSG);
tx_pdu.choice_type = LIBLTE_S1AP_S1AP_PDU_CHOICE_INITIATINGMESSAGE; init_ue_msg_ies_container& container = tx_pdu.init_msg().value.init_ue_msg().protocol_ies;
LIBLTE_S1AP_INITIATINGMESSAGE_STRUCT* init = &tx_pdu.choice.initiatingMessage;
init->procedureCode = LIBLTE_S1AP_PROC_ID_INITIALUEMESSAGE;
init->choice_type = LIBLTE_S1AP_INITIATINGMESSAGE_CHOICE_INITIALUEMESSAGE;
LIBLTE_S1AP_MESSAGE_INITIALUEMESSAGE_STRUCT* initue = &init->choice.InitialUEMessage;
initue->ext = false;
initue->CellAccessMode_present = false;
initue->CSG_Id_present = false;
initue->GUMMEIType_present = false;
initue->GUMMEI_ID_present = false;
initue->GW_TransportLayerAddress_present = false;
initue->LHN_ID_present = false;
initue->RelayNode_Indicator_present = false;
initue->SIPTO_L_GW_TransportLayerAddress_present = false;
initue->S_TMSI_present = false;
initue->Tunnel_Information_for_BBF_present = false;
// S_TMSI // S_TMSI
if (has_tmsi) { if (has_tmsi) {
initue->S_TMSI_present = true; container.s_tmsi_present = true;
initue->S_TMSI.ext = false; uint32_to_uint8(m_tmsi, container.s_tmsi.value.m_tmsi.data());
initue->S_TMSI.iE_Extensions_present = false; container.s_tmsi.value.mmec[0] = mmec;
uint32_to_uint8(m_tmsi, initue->S_TMSI.m_TMSI.buffer);
initue->S_TMSI.mMEC.buffer[0] = mmec;
} }
// ENB_UE_S1AP_ID // ENB_UE_S1AP_ID
initue->eNB_UE_S1AP_ID.ENB_UE_S1AP_ID = get_user_ctxt(rnti)->eNB_UE_S1AP_ID; container.enb_ue_s1ap_id.value = get_user_ctxt(rnti)->eNB_UE_S1AP_ID;
// NAS_PDU // NAS_PDU
memcpy(initue->NAS_PDU.buffer, pdu->msg, pdu->N_bytes); container.nas_pdu.value.resize(pdu->N_bytes);
initue->NAS_PDU.n_octets = pdu->N_bytes; memcpy(container.nas_pdu.value.data(), pdu->msg, pdu->N_bytes);
// TAI // TAI
memcpy(&initue->TAI, &tai, sizeof(LIBLTE_S1AP_TAI_STRUCT)); container.tai.value.ie_exts_present = tai.iE_Extensions_present;
container.tai.value.ext = tai.ext;
memcpy(container.tai.value.tac.data(), tai.tAC.buffer, 2);
memcpy(container.tai.value.plm_nid.data(), tai.pLMNidentity.buffer, 3);
// EUTRAN_CGI // EUTRAN_CGI
memcpy(&initue->EUTRAN_CGI, &eutran_cgi, sizeof(LIBLTE_S1AP_EUTRAN_CGI_STRUCT)); container.eutran_cgi.value.ext = eutran_cgi.ext;
container.eutran_cgi.value.ie_exts_present = eutran_cgi.iE_Extensions_present;
memcpy(container.eutran_cgi.value.plm_nid.data(), eutran_cgi.pLMNidentity.buffer, 3);
for (uint32_t i = 0; i < 28; ++i) {
container.eutran_cgi.value.cell_id.set(i, (bool)eutran_cgi.cell_ID.buffer[i]);
}
// RRC Establishment Cause // RRC Establishment Cause
initue->RRC_Establishment_Cause.ext = false; container.rrc_establishment_cause.value = cause;
initue->RRC_Establishment_Cause.e = cause;
liblte_s1ap_pack_s1ap_pdu(&tx_pdu, (LIBLTE_BYTE_MSG_STRUCT*)&msg);
s1ap_log->info_hex(msg.msg, msg.N_bytes, "Sending InitialUEMessage for RNTI:0x%x", rnti);
return sctp_send_s1ap_pdu(&tx_pdu, rnti, "InitialUEMessage"); return sctp_send_s1ap_pdu(tx_pdu, rnti, "InitialUEMessage");
} }
bool s1ap::send_ulnastransport(uint16_t rnti, srslte::unique_byte_buffer_t pdu) bool s1ap::send_ulnastransport(uint16_t rnti, srslte::unique_byte_buffer_t pdu)
@ -959,37 +933,26 @@ bool s1ap::send_ulnastransport(uint16_t rnti, srslte::unique_byte_buffer_t pdu)
return sctp_send_s1ap_pdu(&tx_pdu, rnti, "UplinkNASTransport"); return sctp_send_s1ap_pdu(&tx_pdu, rnti, "UplinkNASTransport");
} }
bool s1ap::send_uectxtreleaserequest(uint16_t rnti, LIBLTE_S1AP_CAUSE_STRUCT* cause) bool s1ap::send_uectxtreleaserequest(uint16_t rnti, const cause_c& cause)
{ {
if (!mme_connected) { if (!mme_connected) {
return false; return false;
} }
srslte::byte_buffer_t msg;
LIBLTE_S1AP_S1AP_PDU_STRUCT tx_pdu;
tx_pdu.ext = false;
tx_pdu.choice_type = LIBLTE_S1AP_S1AP_PDU_CHOICE_INITIATINGMESSAGE;
LIBLTE_S1AP_INITIATINGMESSAGE_STRUCT* init = &tx_pdu.choice.initiatingMessage;
init->procedureCode = LIBLTE_S1AP_PROC_ID_UECONTEXTRELEASEREQUEST;
init->choice_type = LIBLTE_S1AP_INITIATINGMESSAGE_CHOICE_UECONTEXTRELEASEREQUEST;
LIBLTE_S1AP_MESSAGE_UECONTEXTRELEASEREQUEST_STRUCT* req = &init->choice.UEContextReleaseRequest; s1ap_pdu_c tx_pdu;
req->ext = false; tx_pdu.set_init_msg().load_info_obj(ASN1_S1AP_ID_UE_CONTEXT_RELEASE_REQUEST);
req->GWContextReleaseIndication_present = false; ue_context_release_request_ies_container& container =
tx_pdu.init_msg().value.ue_context_release_request().protocol_ies;
// MME_UE_S1AP_ID // MME_UE_S1AP_ID
req->MME_UE_S1AP_ID.MME_UE_S1AP_ID = get_user_ctxt(rnti)->MME_UE_S1AP_ID; container.mme_ue_s1ap_id.value = get_user_ctxt(rnti)->MME_UE_S1AP_ID;
// ENB_UE_S1AP_ID // ENB_UE_S1AP_ID
req->eNB_UE_S1AP_ID.ENB_UE_S1AP_ID = get_user_ctxt(rnti)->eNB_UE_S1AP_ID; container.enb_ue_s1ap_id.value = get_user_ctxt(rnti)->eNB_UE_S1AP_ID;
// Cause // Cause
memcpy(&req->Cause, cause, sizeof(LIBLTE_S1AP_CAUSE_STRUCT)); container.cause.value = cause;
liblte_s1ap_pack_s1ap_pdu(&tx_pdu, (LIBLTE_BYTE_MSG_STRUCT*)&msg); return sctp_send_s1ap_pdu(tx_pdu, rnti, "UEContextReleaseRequest");
s1ap_log->info_hex(msg.msg, msg.N_bytes, "Sending UEContextReleaseRequest for RNTI:0x%x", rnti);
return sctp_send_s1ap_pdu(&tx_pdu, rnti, "UEContextReleaseRequest");
} }
bool s1ap::send_uectxtreleasecomplete(uint16_t rnti, uint32_t mme_ue_id, uint32_t enb_ue_id) bool s1ap::send_uectxtreleasecomplete(uint16_t rnti, uint32_t mme_ue_id, uint32_t enb_ue_id)
@ -997,105 +960,73 @@ bool s1ap::send_uectxtreleasecomplete(uint16_t rnti, uint32_t mme_ue_id, uint32_
if (!mme_connected) { if (!mme_connected) {
return false; return false;
} }
srslte::byte_buffer_t msg;
LIBLTE_S1AP_S1AP_PDU_STRUCT tx_pdu;
tx_pdu.ext = false;
tx_pdu.choice_type = LIBLTE_S1AP_S1AP_PDU_CHOICE_SUCCESSFULOUTCOME;
LIBLTE_S1AP_SUCCESSFULOUTCOME_STRUCT* succ = &tx_pdu.choice.successfulOutcome;
succ->procedureCode = LIBLTE_S1AP_PROC_ID_UECONTEXTRELEASE;
succ->choice_type = LIBLTE_S1AP_SUCCESSFULOUTCOME_CHOICE_UECONTEXTRELEASECOMPLETE;
LIBLTE_S1AP_MESSAGE_UECONTEXTRELEASECOMPLETE_STRUCT* comp = &succ->choice.UEContextReleaseComplete; s1ap_pdu_c tx_pdu;
comp->ext = false; tx_pdu.set_successful_outcome().load_info_obj(ASN1_S1AP_ID_UE_CONTEXT_RELEASE);
comp->CriticalityDiagnostics_present = false; auto& container = tx_pdu.successful_outcome().value.ue_context_mod_request().protocol_ies;
comp->UserLocationInformation_present = false; container.enb_ue_s1ap_id.value = enb_ue_id;
container.mme_ue_s1ap_id.value = mme_ue_id;
comp->eNB_UE_S1AP_ID.ENB_UE_S1AP_ID = enb_ue_id; return sctp_send_s1ap_pdu(tx_pdu, rnti, "UEContextReleaseComplete");
comp->MME_UE_S1AP_ID.MME_UE_S1AP_ID = mme_ue_id;
return sctp_send_s1ap_pdu(&tx_pdu, rnti, "UEContextReleaseComplete");
} }
bool s1ap::send_initial_ctxt_setup_response(uint16_t rnti, LIBLTE_S1AP_MESSAGE_INITIALCONTEXTSETUPRESPONSE_STRUCT* res_) bool s1ap::send_initial_ctxt_setup_response(uint16_t rnti, const asn1::s1ap::init_context_setup_resp_s& res_)
{ {
if (!mme_connected) { if (!mme_connected) {
return false; return false;
} }
srslte::unique_byte_buffer_t buf = srslte::allocate_unique_buffer(*pool);
if (!buf) {
s1ap_log->error("Fatal Error: Couldn't allocate buffer in s1ap::send_initial_ctxt_setup_response().\n");
return false;
}
LIBLTE_S1AP_S1AP_PDU_STRUCT tx_pdu; s1ap_pdu_c tx_pdu;
tx_pdu.set_successful_outcome().load_info_obj(ASN1_S1AP_ID_INIT_CONTEXT_SETUP);
tx_pdu.ext = false;
tx_pdu.choice_type = LIBLTE_S1AP_S1AP_PDU_CHOICE_SUCCESSFULOUTCOME;
LIBLTE_S1AP_SUCCESSFULOUTCOME_STRUCT* succ = &tx_pdu.choice.successfulOutcome;
succ->procedureCode = LIBLTE_S1AP_PROC_ID_INITIALCONTEXTSETUP;
succ->choice_type = LIBLTE_S1AP_SUCCESSFULOUTCOME_CHOICE_INITIALCONTEXTSETUPRESPONSE;
// Copy in the provided response message // Copy in the provided response message
LIBLTE_S1AP_MESSAGE_INITIALCONTEXTSETUPRESPONSE_STRUCT* res = &succ->choice.InitialContextSetupResponse; tx_pdu.successful_outcome().value.init_context_setup_request() = res_;
memcpy(res, res_, sizeof(LIBLTE_S1AP_MESSAGE_INITIALCONTEXTSETUPRESPONSE_STRUCT));
// Fill in the MME and eNB IDs
auto& container = tx_pdu.successful_outcome().value.init_context_setup_request().protocol_ies;
container.mme_ue_s1ap_id.value = get_user_ctxt(rnti)->MME_UE_S1AP_ID;
container.enb_ue_s1ap_id.value = get_user_ctxt(rnti)->eNB_UE_S1AP_ID;
// Fill in the GTP bind address for all bearers // Fill in the GTP bind address for all bearers
for (uint32_t i = 0; i < res->E_RABSetupListCtxtSURes.len; i++) { for (uint32_t i = 0; i < container.e_rab_setup_list_ctxt_su_res.value.size(); ++i) {
auto& item = container.e_rab_setup_list_ctxt_su_res.value[i].value.e_rab_setup_item_ctxt_su_res();
item.transport_layer_address.resize(32);
uint8_t addr[4]; uint8_t addr[4];
inet_pton(AF_INET, args.gtp_bind_addr.c_str(), addr); inet_pton(AF_INET, args.gtp_bind_addr.c_str(), addr);
liblte_unpack(addr, 4, res->E_RABSetupListCtxtSURes.buffer[i].transportLayerAddress.buffer); liblte_unpack(addr, 4, item.transport_layer_address.data());
res->E_RABSetupListCtxtSURes.buffer[i].transportLayerAddress.n_bits = 32;
res->E_RABSetupListCtxtSURes.buffer[i].transportLayerAddress.ext = false;
} }
// Fill in the MME and eNB IDs return sctp_send_s1ap_pdu(tx_pdu, rnti, "InitialContextSetupResponse");
res->MME_UE_S1AP_ID.MME_UE_S1AP_ID = get_user_ctxt(rnti)->MME_UE_S1AP_ID;
res->eNB_UE_S1AP_ID.ENB_UE_S1AP_ID = get_user_ctxt(rnti)->eNB_UE_S1AP_ID;
return sctp_send_s1ap_pdu(&tx_pdu, rnti, "InitialContextSetupResponse");
} }
bool s1ap::send_erab_setup_response(uint16_t rnti, LIBLTE_S1AP_MESSAGE_E_RABSETUPRESPONSE_STRUCT* res_) bool s1ap::send_erab_setup_response(uint16_t rnti, const e_rab_setup_resp_s& res_)
{ {
if (!mme_connected) { if (!mme_connected) {
return false; return false;
} }
srslte::unique_byte_buffer_t buf = srslte::allocate_unique_buffer(*pool);
if (!buf) {
s1ap_log->error("Fatal Error: Couldn't allocate buffer in s1ap::send_erab_setup_response().\n");
return false;
}
LIBLTE_S1AP_S1AP_PDU_STRUCT tx_pdu; asn1::s1ap::s1ap_pdu_c tx_pdu;
tx_pdu.set_successful_outcome().load_info_obj(ASN1_S1AP_ID_E_RAB_SETUP);
e_rab_setup_resp_s& res = tx_pdu.successful_outcome().value.e_rab_setup_request();
tx_pdu.ext = false; res = res_;
tx_pdu.choice_type = LIBLTE_S1AP_S1AP_PDU_CHOICE_SUCCESSFULOUTCOME;
LIBLTE_S1AP_SUCCESSFULOUTCOME_STRUCT* succ = &tx_pdu.choice.successfulOutcome;
succ->procedureCode = LIBLTE_S1AP_PROC_ID_E_RABSETUP;
succ->choice_type = LIBLTE_S1AP_SUCCESSFULOUTCOME_CHOICE_E_RABSETUPRESPONSE;
// Copy in the provided response message
LIBLTE_S1AP_MESSAGE_E_RABSETUPRESPONSE_STRUCT* res = &succ->choice.E_RABSetupResponse;
memcpy(res, res_, sizeof(LIBLTE_S1AP_MESSAGE_E_RABSETUPRESPONSE_STRUCT));
// Fill in the GTP bind address for all bearers // Fill in the GTP bind address for all bearers
for (uint32_t i = 0; i < res->E_RABSetupListBearerSURes.len; i++) { if (res.protocol_ies.e_rab_setup_list_bearer_su_res_present) {
for (uint32_t i = 0; i < res.protocol_ies.e_rab_setup_list_bearer_su_res.value.size(); ++i) {
auto& item = res.protocol_ies.e_rab_setup_list_bearer_su_res.value[i].value.e_rab_setup_item_bearer_su_res();
item.transport_layer_address.resize(32);
uint8_t addr[4]; uint8_t addr[4];
inet_pton(AF_INET, args.gtp_bind_addr.c_str(), addr); inet_pton(AF_INET, args.gtp_bind_addr.c_str(), addr);
liblte_unpack(addr, 4, res->E_RABSetupListBearerSURes.buffer[i].transportLayerAddress.buffer); liblte_unpack(addr, 4, item.transport_layer_address.data());
res->E_RABSetupListBearerSURes.buffer[i].transportLayerAddress.n_bits = 32; }
res->E_RABSetupListBearerSURes.buffer[i].transportLayerAddress.ext = false;
} }
// Fill in the MME and eNB IDs // Fill in the MME and eNB IDs
res->MME_UE_S1AP_ID.MME_UE_S1AP_ID = get_user_ctxt(rnti)->MME_UE_S1AP_ID; res.protocol_ies.mme_ue_s1ap_id.value = get_user_ctxt(rnti)->MME_UE_S1AP_ID;
res->eNB_UE_S1AP_ID.ENB_UE_S1AP_ID = get_user_ctxt(rnti)->eNB_UE_S1AP_ID; res.protocol_ies.enb_ue_s1ap_id.value = get_user_ctxt(rnti)->eNB_UE_S1AP_ID;
return sctp_send_s1ap_pdu(&tx_pdu, rnti, "E_RABSetupResponse"); return sctp_send_s1ap_pdu(tx_pdu, rnti, "E_RABSetupResponse");
} }
bool s1ap::send_initial_ctxt_setup_failure(uint16_t rnti) bool s1ap::send_initial_ctxt_setup_failure(uint16_t rnti)
@ -1164,35 +1095,21 @@ bool s1ap::send_uectxmodifyresp(uint16_t rnti)
return sctp_send_s1ap_pdu(&tx_pdu, rnti, "ContextModificationFailure"); return sctp_send_s1ap_pdu(&tx_pdu, rnti, "ContextModificationFailure");
} }
bool s1ap::send_uectxmodifyfailure(uint16_t rnti, LIBLTE_S1AP_CAUSE_STRUCT* cause) bool s1ap::send_uectxmodifyfailure(uint16_t rnti, const cause_c& cause)
{ {
if (!mme_connected) { if (!mme_connected) {
return false; return false;
} }
srslte::unique_byte_buffer_t buf = srslte::allocate_unique_buffer(*pool);
if (!buf) {
s1ap_log->error("Fatal Error: Couldn't allocate buffer in s1ap::send_initial_ctxt_setup_failure().\n");
return false;
}
LIBLTE_S1AP_S1AP_PDU_STRUCT tx_pdu;
tx_pdu.ext = false;
tx_pdu.choice_type = LIBLTE_S1AP_S1AP_PDU_CHOICE_UNSUCCESSFULOUTCOME;
LIBLTE_S1AP_UNSUCCESSFULOUTCOME_STRUCT* unsucc = &tx_pdu.choice.unsuccessfulOutcome;
unsucc->procedureCode = LIBLTE_S1AP_PROC_ID_UECONTEXTMODIFICATION;
unsucc->choice_type = LIBLTE_S1AP_UNSUCCESSFULOUTCOME_CHOICE_UECONTEXTMODIFICATIONFAILURE;
LIBLTE_S1AP_MESSAGE_UECONTEXTMODIFICATIONFAILURE_STRUCT* fail = &unsucc->choice.UEContextModificationFailure;
fail->ext = false;
fail->CriticalityDiagnostics_present = false;
fail->MME_UE_S1AP_ID.MME_UE_S1AP_ID = get_user_ctxt(rnti)->MME_UE_S1AP_ID; s1ap_pdu_c tx_pdu;
fail->eNB_UE_S1AP_ID.ENB_UE_S1AP_ID = get_user_ctxt(rnti)->eNB_UE_S1AP_ID; tx_pdu.set_unsuccessful_outcome().load_info_obj(ASN1_S1AP_ID_UE_CONTEXT_MOD);
auto& container = tx_pdu.unsuccessful_outcome().value.ue_context_mod_request().protocol_ies;
memcpy(&fail->Cause, cause, sizeof(LIBLTE_S1AP_CAUSE_STRUCT)); container.enb_ue_s1ap_id.value = get_user_ctxt(rnti)->MME_UE_S1AP_ID;
container.mme_ue_s1ap_id.value = get_user_ctxt(rnti)->eNB_UE_S1AP_ID;
container.cause.value = cause;
return sctp_send_s1ap_pdu(&tx_pdu, rnti, "UEContextModificationFailure"); return sctp_send_s1ap_pdu(tx_pdu, rnti, "UEContextModificationFailure");
} }
/********************* /*********************
@ -1270,6 +1187,45 @@ bool s1ap::send_enb_status_transfer_proc(uint16_t rnti, std::vector<bearer_statu
/* General helpers /* General helpers
********************************************************************************/ ********************************************************************************/
bool s1ap::sctp_send_s1ap_pdu(const asn1::s1ap::s1ap_pdu_c& tx_pdu, uint32_t rnti, const char* procedure_name)
{
srslte::unique_byte_buffer_t buf = srslte::allocate_unique_buffer(*pool, false);
if (buf == nullptr) {
s1ap_log->error("Fatal Error: Couldn't allocate buffer for %s.\n", procedure_name);
return false;
}
asn1::bit_ref bref(buf->msg, buf->get_tailroom());
tx_pdu.pack(bref);
buf->N_bytes = bref.distance_bytes();
if (rnti > 0) {
s1ap_log->info_hex(buf->msg, buf->N_bytes, "Sending %s for rnti=0x%x", procedure_name, rnti);
} else {
s1ap_log->info_hex(buf->msg, buf->N_bytes, "Sending %s to MME", procedure_name);
}
uint16_t streamid = rnti == 0 ? NONUE_STREAM_ID : get_user_ctxt(rnti)->stream_id;
ssize_t n_sent = sctp_sendmsg(s1ap_socket.fd(),
buf->msg,
buf->N_bytes,
(struct sockaddr*)&mme_addr,
sizeof(struct sockaddr_in),
htonl(PPID),
0,
streamid,
0,
0);
if (n_sent == -1) {
if (rnti > 0) {
s1ap_log->error("Failed to send %s for rnti=0x%x\n", procedure_name, rnti);
} else {
s1ap_log->error("Failed to send %s\n", procedure_name);
}
return false;
}
return true;
}
bool s1ap::sctp_send_s1ap_pdu(LIBLTE_S1AP_S1AP_PDU_STRUCT* tx_pdu, uint32_t rnti, const char* procedure_name) bool s1ap::sctp_send_s1ap_pdu(LIBLTE_S1AP_S1AP_PDU_STRUCT* tx_pdu, uint32_t rnti, const char* procedure_name)
{ {
srslte::unique_byte_buffer_t buf = srslte::allocate_unique_buffer(*pool, false); srslte::unique_byte_buffer_t buf = srslte::allocate_unique_buffer(*pool, false);

@ -83,12 +83,11 @@ public:
class s1ap_dummy : public s1ap_interface_rrc class s1ap_dummy : public s1ap_interface_rrc
{ {
public: public:
void void initial_ue(uint16_t rnti, asn1::s1ap::rrc_establishment_cause_e cause, srslte::unique_byte_buffer_t pdu) override
initial_ue(uint16_t rnti, LIBLTE_S1AP_RRC_ESTABLISHMENT_CAUSE_ENUM cause, srslte::unique_byte_buffer_t pdu) override
{ {
} }
void initial_ue(uint16_t rnti, void initial_ue(uint16_t rnti,
LIBLTE_S1AP_RRC_ESTABLISHMENT_CAUSE_ENUM cause, asn1::s1ap::rrc_establishment_cause_e cause,
srslte::unique_byte_buffer_t pdu, srslte::unique_byte_buffer_t pdu,
uint32_t m_tmsi, uint32_t m_tmsi,
uint8_t mmec) override uint8_t mmec) override
@ -97,9 +96,9 @@ public:
void write_pdu(uint16_t rnti, srslte::unique_byte_buffer_t pdu) override {} void write_pdu(uint16_t rnti, srslte::unique_byte_buffer_t pdu) override {}
bool user_exists(uint16_t rnti) override { return true; } bool user_exists(uint16_t rnti) override { return true; }
bool user_release(uint16_t rnti, LIBLTE_S1AP_CAUSERADIONETWORK_ENUM cause_radio) override { return true; } bool user_release(uint16_t rnti, asn1::s1ap::cause_radio_network_e cause_radio) override { return true; }
void ue_ctxt_setup_complete(uint16_t rnti, LIBLTE_S1AP_MESSAGE_INITIALCONTEXTSETUPRESPONSE_STRUCT* res) override {} void ue_ctxt_setup_complete(uint16_t rnti, const asn1::s1ap::init_context_setup_resp_s& res) override {}
void ue_erab_setup_complete(uint16_t rnti, LIBLTE_S1AP_MESSAGE_E_RABSETUPRESPONSE_STRUCT* res) override {} void ue_erab_setup_complete(uint16_t rnti, const asn1::s1ap::e_rab_setup_resp_s& res) override {}
bool is_mme_connected() override { return true; } bool is_mme_connected() override { return true; }
bool send_ho_required(uint16_t rnti, bool send_ho_required(uint16_t rnti,
uint32_t target_eci, uint32_t target_eci,

@ -23,10 +23,10 @@ add_executable(plmn_test plmn_test.cc)
target_link_libraries(plmn_test rrc_asn1) target_link_libraries(plmn_test rrc_asn1)
add_executable(rrc_mobility_test rrc_mobility_test.cc) add_executable(rrc_mobility_test rrc_mobility_test.cc)
target_link_libraries(rrc_mobility_test srsenb_rrc rrc_asn1 srslte_common srslte_asn1 enb_cfg_parser ${LIBCONFIGPP_LIBRARIES}) target_link_libraries(rrc_mobility_test srsenb_rrc rrc_asn1 s1ap_asn1 srslte_common srslte_asn1 enb_cfg_parser ${LIBCONFIGPP_LIBRARIES})
add_executable(erab_setup_test erab_setup_test.cc) add_executable(erab_setup_test erab_setup_test.cc)
target_link_libraries(erab_setup_test srsenb_rrc rrc_asn1 srslte_common srslte_asn1 enb_cfg_parser ${LIBCONFIGPP_LIBRARIES}) target_link_libraries(erab_setup_test srsenb_rrc rrc_asn1 s1ap_asn1 srslte_common srslte_asn1 enb_cfg_parser ${LIBCONFIGPP_LIBRARIES})
add_test(rrc_mobility_test rrc_mobility_test -i ${CMAKE_CURRENT_SOURCE_DIR}/../..) add_test(rrc_mobility_test rrc_mobility_test -i ${CMAKE_CURRENT_SOURCE_DIR}/../..)
add_test(erab_setup_test erab_setup_test -i ${CMAKE_CURRENT_SOURCE_DIR}/../..) add_test(erab_setup_test erab_setup_test -i ${CMAKE_CURRENT_SOURCE_DIR}/../..)

Loading…
Cancel
Save