Moved srsEPC to the new S1AP library. Deleted liblte_s1ap.cc and liblte_s1ap.h.

master
Pedro Alvarez 5 years ago committed by Francisco Paisana
parent a61ff0b0fc
commit bd3598f774

File diff suppressed because it is too large Load Diff

@ -21,7 +21,6 @@
#include "srslte/srslte.h" #include "srslte/srslte.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/asn1/s1ap_asn1.h"
#include "srslte/common/common.h" #include "srslte/common/common.h"

@ -22,7 +22,6 @@ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-switch -Wno-unused-variable -Wno-re
add_library(srslte_asn1 STATIC add_library(srslte_asn1 STATIC
liblte_common.cc liblte_common.cc
liblte_mme.cc liblte_mme.cc
liblte_s1ap.cc
liblte_m2ap.cc liblte_m2ap.cc
gtpc.cc gtpc.cc
) )

File diff suppressed because it is too large Load Diff

@ -111,8 +111,8 @@ private:
srslte::timer_handler::unique_timer mme_connect_timer, s1setup_timeout; srslte::timer_handler::unique_timer mme_connect_timer, s1setup_timeout;
// Protocol IEs sent with every UL S1AP message // Protocol IEs sent with every UL S1AP message
LIBLTE_S1AP_TAI_STRUCT tai; asn1::s1ap::tai_s tai;
LIBLTE_S1AP_EUTRAN_CGI_STRUCT eutran_cgi; asn1::s1ap::eutran_cgi_s eutran_cgi;
asn1::s1ap::s1_setup_resp_s s1setupresponse; asn1::s1ap::s1_setup_resp_s s1setupresponse;

@ -176,7 +176,8 @@ void phy_common::build_mcch_table()
{ {
ZERO_OBJECT(mcch_table); ZERO_OBJECT(mcch_table);
generate_mcch_table(mcch_table, static_cast<uint32>(mbsfn.mbsfn_area_info.mcch_cfg_r9.sf_alloc_info_r9.to_number())); generate_mcch_table(mcch_table,
static_cast<uint32_t>(mbsfn.mbsfn_area_info.mcch_cfg_r9.sf_alloc_info_r9.to_number()));
std::stringstream ss; std::stringstream ss;
ss << "|"; ss << "|";

@ -82,7 +82,7 @@ bool sched_cell_params_t::set_cfg(uint32_t enb_cc_id
// init regs // init regs
regs.reset(new srslte_regs_t{}); regs.reset(new srslte_regs_t{});
if (srslte_regs_init(regs.get(), cfg.cell) != LIBLTE_SUCCESS) { if (srslte_regs_init(regs.get(), cfg.cell) != SRSLTE_SUCCESS) {
Error("Getting DCI locations\n"); Error("Getting DCI locations\n");
return false; return false;
} }

@ -289,34 +289,15 @@ void s1ap::build_tai_cgi()
uint16_t tmp16; uint16_t tmp16;
// TAI // TAI
tai.ext = false;
tai.iE_Extensions_present = false;
s1ap_mccmnc_to_plmn(args.mcc, args.mnc, &plmn); s1ap_mccmnc_to_plmn(args.mcc, args.mnc, &plmn);
tmp32 = htonl(plmn); tai.plm_nid.from_number(plmn);
tai.pLMNidentity.buffer[0] = ((uint8_t*)&tmp32)[1];
tai.pLMNidentity.buffer[1] = ((uint8_t*)&tmp32)[2]; tai.tac.from_number(args.tac);
tai.pLMNidentity.buffer[2] = ((uint8_t*)&tmp32)[3];
tmp16 = htons(args.tac);
memcpy(tai.tAC.buffer, (uint8_t*)&tmp16, 2);
// EUTRAN_CGI // EUTRAN_CGI
eutran_cgi.ext = false; eutran_cgi.plm_nid.from_number(plmn);
eutran_cgi.iE_Extensions_present = false;
s1ap_mccmnc_to_plmn(args.mcc, args.mnc, &plmn);
tmp32 = htonl(plmn);
eutran_cgi.pLMNidentity.buffer[0] = ((uint8_t*)&tmp32)[1];
eutran_cgi.pLMNidentity.buffer[1] = ((uint8_t*)&tmp32)[2];
eutran_cgi.pLMNidentity.buffer[2] = ((uint8_t*)&tmp32)[3];
tmp32 = htonl(args.enb_id); eutran_cgi.cell_id.from_number((uint32_t)(args.enb_id << 8) | args.cell_id);
uint8_t enb_id_bits[4 * 8];
liblte_unpack((uint8_t*)&tmp32, 4, enb_id_bits);
uint8_t cell_id_bits[1 * 8];
liblte_unpack(&args.cell_id, 1, cell_id_bits);
memcpy(eutran_cgi.cell_ID.buffer,
&enb_id_bits[32 - LIBLTE_S1AP_MACROENB_ID_BIT_STRING_LEN],
LIBLTE_S1AP_MACROENB_ID_BIT_STRING_LEN);
memcpy(&eutran_cgi.cell_ID.buffer[LIBLTE_S1AP_MACROENB_ID_BIT_STRING_LEN], cell_id_bits, 8);
} }
/******************************************************************************* /*******************************************************************************
@ -826,18 +807,10 @@ bool s1ap::ue::send_initialuemessage(asn1::s1ap::rrc_establishment_cause_e cause
memcpy(container.nas_pdu.value.data(), pdu->msg, pdu->N_bytes); memcpy(container.nas_pdu.value.data(), pdu->msg, pdu->N_bytes);
// TAI // TAI
container.tai.value.ie_exts_present = s1ap_ptr->tai.iE_Extensions_present; container.tai.value = s1ap_ptr->tai;
container.tai.value.ext = s1ap_ptr->tai.ext;
memcpy(container.tai.value.tac.data(), s1ap_ptr->tai.tAC.buffer, 2);
memcpy(container.tai.value.plm_nid.data(), s1ap_ptr->tai.pLMNidentity.buffer, 3);
// EUTRAN_CGI // EUTRAN_CGI
container.eutran_cgi.value.ext = s1ap_ptr->eutran_cgi.ext; container.eutran_cgi.value = s1ap_ptr->eutran_cgi;
container.eutran_cgi.value.ie_exts_present = s1ap_ptr->eutran_cgi.iE_Extensions_present;
memcpy(container.eutran_cgi.value.plm_nid.data(), s1ap_ptr->eutran_cgi.pLMNidentity.buffer, 3);
for (uint32_t i = 0; i < 28; ++i) {
container.eutran_cgi.value.cell_id.set(i, (bool)s1ap_ptr->eutran_cgi.cell_ID.buffer[i]);
}
// RRC Establishment Cause // RRC Establishment Cause
container.rrc_establishment_cause.value = cause; container.rrc_establishment_cause.value = cause;
@ -862,18 +835,10 @@ bool s1ap::ue::send_ulnastransport(srslte::unique_byte_buffer_t pdu)
memcpy(container.nas_pdu.value.data(), pdu->msg, pdu->N_bytes); memcpy(container.nas_pdu.value.data(), pdu->msg, pdu->N_bytes);
// EUTRAN CGI // EUTRAN CGI
container.eutran_cgi.value.ext = s1ap_ptr->eutran_cgi.ext; container.eutran_cgi.value = s1ap_ptr->eutran_cgi;
container.eutran_cgi.value.ie_exts_present = s1ap_ptr->eutran_cgi.iE_Extensions_present;
memcpy(container.eutran_cgi.value.plm_nid.data(), s1ap_ptr->eutran_cgi.pLMNidentity.buffer, 3);
for (uint32_t i = 0; i < 28; ++i) {
container.eutran_cgi.value.cell_id.set(i, (bool)s1ap_ptr->eutran_cgi.cell_ID.buffer[i]);
}
// TAI // TAI
container.tai.value.ie_exts_present = s1ap_ptr->tai.iE_Extensions_present; container.tai.value = s1ap_ptr->tai;
container.tai.value.ext = s1ap_ptr->tai.ext;
memcpy(container.tai.value.tac.data(), s1ap_ptr->tai.tAC.buffer, 2);
memcpy(container.tai.value.plm_nid.data(), s1ap_ptr->tai.pLMNidentity.buffer, 3);
return s1ap_ptr->sctp_send_s1ap_pdu(tx_pdu, ctxt.rnti, "UplinkNASTransport"); return s1ap_ptr->sctp_send_s1ap_pdu(tx_pdu, ctxt.rnti, "UplinkNASTransport");
} }
@ -1317,9 +1282,8 @@ bool s1ap::ue::send_ho_required(uint32_t target_eci,
auto& eutra = transparent_cntr.ue_history_info[0].set_e_utran_cell(); auto& eutra = transparent_cntr.ue_history_info[0].set_e_utran_cell();
eutra.cell_type.cell_size.value = cell_size_opts::medium; eutra.cell_type.cell_size.value = cell_size_opts::medium;
target_plmn.to_s1ap_plmn_bytes(eutra.global_cell_id.plm_nid.data()); target_plmn.to_s1ap_plmn_bytes(eutra.global_cell_id.plm_nid.data());
for (uint32_t i = 0; i < eutra.global_cell_id.cell_id.length(); ++i) { eutra.global_cell_id.cell_id = s1ap_ptr->eutran_cgi.cell_id;
eutra.global_cell_id.cell_id.set(i, s1ap_ptr->eutran_cgi.cell_ID.buffer[i]);
}
// - set time spent in current source cell // - set time spent in current source cell
struct timeval ts[3]; struct timeval ts[3];
memcpy(&ts[1], &ctxt.init_timestamp, sizeof(struct timeval)); memcpy(&ts[1], &ctxt.init_timestamp, sizeof(struct timeval));

@ -648,7 +648,9 @@ public:
std::string log_level, std::string log_level,
uint16_t rnti_, uint16_t rnti_,
const srsenb::phy_interface_rrc_lte::phy_rrc_dedicated_list_t& phy_rrc_cfg_) : const srsenb::phy_interface_rrc_lte::phy_rrc_dedicated_list_t& phy_rrc_cfg_) :
radio(_radio), log_h("UE PHY", nullptr, true), phy_rrc_cfg(phy_rrc_cfg_) radio(_radio),
log_h("UE PHY", nullptr, true),
phy_rrc_cfg(phy_rrc_cfg_)
{ {
// Calculate subframe length // Calculate subframe length
sf_len = static_cast<uint32_t>(SRSLTE_SF_LEN_PRB(cell_list[0].cell.nof_prb)); sf_len = static_cast<uint32_t>(SRSLTE_SF_LEN_PRB(cell_list[0].cell.nof_prb));

@ -24,7 +24,6 @@
#include "srslte/asn1/gtpc_ies.h" #include "srslte/asn1/gtpc_ies.h"
#include "srslte/asn1/liblte_mme.h" #include "srslte/asn1/liblte_mme.h"
#include "srslte/asn1/liblte_s1ap.h"
#include "srslte/common/buffer_pool.h" #include "srslte/common/buffer_pool.h"
#include "srslte/common/security.h" #include "srslte/common/security.h"
#include "srslte/interfaces/epc_interfaces.h" #include "srslte/interfaces/epc_interfaces.h"

@ -30,7 +30,7 @@
#include "srsepc/hdr/hss/hss.h" #include "srsepc/hdr/hss/hss.h"
#include "srslte/asn1/gtpc.h" #include "srslte/asn1/gtpc.h"
#include "srslte/asn1/liblte_mme.h" #include "srslte/asn1/liblte_mme.h"
#include "srslte/asn1/liblte_s1ap.h" #include "srslte/asn1/s1ap_asn1.h"
#include "srslte/common/common.h" #include "srslte/common/common.h"
#include "srslte/common/log.h" #include "srslte/common/log.h"
#include "srslte/common/s1ap_pcap.h" #include "srslte/common/s1ap_pcap.h"
@ -48,6 +48,8 @@ namespace srsepc {
const uint16_t S1MME_PORT = 36412; const uint16_t S1MME_PORT = 36412;
using s1ap_pdu_t = asn1::s1ap::s1ap_pdu_c;
class s1ap : public s1ap_interface_nas, public s1ap_interface_gtpc, public s1ap_interface_mme class s1ap : public s1ap_interface_nas, public s1ap_interface_gtpc, public s1ap_interface_mme
{ {
public: public:
@ -62,10 +64,10 @@ public:
void delete_enb_ctx(int32_t assoc_id); void delete_enb_ctx(int32_t assoc_id);
bool s1ap_tx_pdu(srslte::byte_buffer_t* pdu, struct sctp_sndrcvinfo* enb_sri); bool s1ap_tx_pdu(const s1ap_pdu_t& pdu, struct sctp_sndrcvinfo* enb_sri);
bool handle_s1ap_rx_pdu(srslte::byte_buffer_t* pdu, struct sctp_sndrcvinfo* enb_sri); void handle_s1ap_rx_pdu(srslte::byte_buffer_t* pdu, struct sctp_sndrcvinfo* enb_sri);
bool handle_initiating_message(LIBLTE_S1AP_INITIATINGMESSAGE_STRUCT* msg, struct sctp_sndrcvinfo* enb_sri); void handle_initiating_message(const asn1::s1ap::init_msg_s& msg, struct sctp_sndrcvinfo* enb_sri);
bool handle_successful_outcome(LIBLTE_S1AP_SUCCESSFULOUTCOME_STRUCT* msg); void handle_successful_outcome(const asn1::s1ap::successful_outcome_s& msg);
void activate_eps_bearer(uint64_t imsi, uint8_t ebi); void activate_eps_bearer(uint64_t imsi, uint8_t ebi);

@ -24,9 +24,10 @@
#include "srslte/asn1/gtpc_ies.h" #include "srslte/asn1/gtpc_ies.h"
#include "srslte/asn1/liblte_mme.h" #include "srslte/asn1/liblte_mme.h"
#include "srslte/asn1/liblte_s1ap.h" #include "srslte/asn1/s1ap_asn1.h"
#include "srslte/common/security.h" #include "srslte/common/security.h"
#include <netinet/sctp.h> #include <netinet/sctp.h>
#include <string.h>
namespace srsepc { namespace srsepc {
@ -53,14 +54,14 @@ typedef struct {
typedef struct { typedef struct {
bool enb_name_present; bool enb_name_present;
uint32_t enb_id; uint32_t enb_id;
uint8_t enb_name[150]; std::string enb_name;
uint16_t mcc, mnc; uint16_t mcc, mnc;
uint32_t plmn; uint32_t plmn;
uint8_t nof_supported_ta; uint8_t nof_supported_ta;
uint16_t tac[MAX_TA]; std::array<uint8_t, MAX_TA> tac;
uint8_t nof_supported_bplmns[MAX_TA]; std::array<uint16_t, MAX_BPLMN> nof_supported_bplmns;
uint16_t bplmns[MAX_TA][MAX_BPLMN]; std::array<std::array<uint16_t, MAX_BPLMN>, MAX_TA> bplmns;
LIBLTE_S1AP_PAGINGDRX_ENUM drx; asn1::s1ap::paging_drx_opts drx;
struct sctp_sndrcvinfo sri; struct sctp_sndrcvinfo sri;
} enb_ctx_t; } enb_ctx_t;

@ -23,7 +23,7 @@
#include "mme_gtpc.h" #include "mme_gtpc.h"
#include "s1ap_common.h" #include "s1ap_common.h"
#include "srslte/asn1/liblte_s1ap.h" #include "srslte/asn1/s1ap_asn1.h"
#include "srslte/common/buffer_pool.h" #include "srslte/common/buffer_pool.h"
#include "srslte/common/common.h" #include "srslte/common/common.h"
#include "srslte/common/log_filter.h" #include "srslte/common/log_filter.h"
@ -42,13 +42,11 @@ public:
void init(void); void init(void);
bool send_initial_context_setup_request(nas* nas_ctx, uint16_t erab_to_setup); bool send_initial_context_setup_request(nas* nas_ctx, uint16_t erab_to_setup);
bool handle_initial_context_setup_response(LIBLTE_S1AP_MESSAGE_INITIALCONTEXTSETUPRESPONSE_STRUCT* in_ctxt_resp); bool handle_initial_context_setup_response(const asn1::s1ap::init_context_setup_resp_s& in_ctxt_resp);
bool handle_ue_context_release_request(LIBLTE_S1AP_MESSAGE_UECONTEXTRELEASEREQUEST_STRUCT* ue_rel, bool handle_ue_context_release_request(const asn1::s1ap::ue_context_release_request_s& ue_rel,
struct sctp_sndrcvinfo* enb_sri, struct sctp_sndrcvinfo* enb_sri);
srslte::byte_buffer_t* reply_buffer,
bool* reply_flag);
bool send_ue_context_release_command(nas* nas_ctx); bool send_ue_context_release_command(nas* nas_ctx);
bool handle_ue_context_release_complete(LIBLTE_S1AP_MESSAGE_UECONTEXTRELEASECOMPLETE_STRUCT* rel_comp); bool handle_ue_context_release_complete(const asn1::s1ap::ue_context_release_complete_s& rel_comp);
private: private:
s1ap_ctx_mngmt_proc(); s1ap_ctx_mngmt_proc();

@ -22,7 +22,7 @@
#define SRSEPC_S1AP_MNGMT_PROC_H #define SRSEPC_S1AP_MNGMT_PROC_H
#include "s1ap_common.h" #include "s1ap_common.h"
#include "srslte/asn1/liblte_s1ap.h" #include "srslte/asn1/s1ap_asn1.h"
#include "srslte/common/common.h" #include "srslte/common/common.h"
#include "srslte/common/log_filter.h" #include "srslte/common/log_filter.h"
@ -39,15 +39,12 @@ public:
static void cleanup(void); static void cleanup(void);
void init(void); void init(void);
bool handle_s1_setup_request(LIBLTE_S1AP_MESSAGE_S1SETUPREQUEST_STRUCT* msg, bool handle_s1_setup_request(const asn1::s1ap::s1_setup_request_s& msg, sctp_sndrcvinfo* enb_sri);
sctp_sndrcvinfo* enb_sri,
srslte::byte_buffer_t* reply_buffer,
bool* reply_flag);
// Packing/unpacking helper functions // Packing/unpacking helper functions
bool unpack_s1_setup_request(LIBLTE_S1AP_MESSAGE_S1SETUPREQUEST_STRUCT* msg, enb_ctx_t* enb_ctx); bool unpack_s1_setup_request(const asn1::s1ap::s1_setup_request_s& msg, enb_ctx_t* enb_ctx);
bool pack_s1_setup_failure(LIBLTE_S1AP_CAUSEMISC_ENUM cause, srslte::byte_buffer_t* msg); bool send_s1_setup_failure(asn1::s1ap::cause_misc_opts::options cause, struct sctp_sndrcvinfo* enb_sri);
bool pack_s1_setup_response(s1ap_args_t s1ap_args, srslte::byte_buffer_t* msg); bool send_s1_setup_response(s1ap_args_t s1ap_args, struct sctp_sndrcvinfo* enb_sri);
private: private:
s1ap_mngmt_proc(); s1ap_mngmt_proc();

@ -25,7 +25,7 @@
#include "s1ap_common.h" #include "s1ap_common.h"
#include "srsepc/hdr/hss/hss.h" #include "srsepc/hdr/hss/hss.h"
#include "srslte/asn1/gtpc.h" #include "srslte/asn1/gtpc.h"
#include "srslte/asn1/liblte_s1ap.h" #include "srslte/asn1/s1ap_asn1.h"
#include "srslte/common/buffer_pool.h" #include "srslte/common/buffer_pool.h"
namespace srsepc { namespace srsepc {
@ -38,16 +38,8 @@ public:
static void cleanup(); static void cleanup();
void init(); void init();
bool handle_initial_ue_message(LIBLTE_S1AP_MESSAGE_INITIALUEMESSAGE_STRUCT* init_ue, bool handle_initial_ue_message(const asn1::s1ap::init_ue_msg_s& init_ue, struct sctp_sndrcvinfo* enb_sri);
struct sctp_sndrcvinfo* enb_sri, bool handle_uplink_nas_transport(const asn1::s1ap::ul_nas_transport_s& ul_xport, struct sctp_sndrcvinfo* enb_sri);
srslte::byte_buffer_t* reply_buffer,
bool* reply_flag);
bool handle_uplink_nas_transport(LIBLTE_S1AP_MESSAGE_UPLINKNASTRANSPORT_STRUCT* ul_xport,
struct sctp_sndrcvinfo* enb_sri,
srslte::byte_buffer_t* reply_buffer,
bool* reply_flag);
bool send_downlink_nas_transport(uint32_t enb_ue_s1ap_id, 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,

@ -22,7 +22,6 @@
#define SRSEPC_S1AP_PAGING_H #define SRSEPC_S1AP_PAGING_H
#include "s1ap_common.h" #include "s1ap_common.h"
#include "srslte/asn1/liblte_s1ap.h"
#include "srslte/common/buffer_pool.h" #include "srslte/common/buffer_pool.h"
#include "srslte/common/common.h" #include "srslte/common/common.h"
#include "srslte/common/log_filter.h" #include "srslte/common/log_filter.h"

@ -38,6 +38,7 @@ add_executable(srsepc main.cc)
target_link_libraries( srsepc srsepc_mme target_link_libraries( srsepc srsepc_mme
srsepc_hss srsepc_hss
srsepc_sgw srsepc_sgw
s1ap_asn1
srslte_upper srslte_upper
srslte_common srslte_common
${CMAKE_THREAD_LIBS_INIT} ${CMAKE_THREAD_LIBS_INIT}

@ -193,111 +193,112 @@ int s1ap::enb_listen()
return sock_fd; return sock_fd;
} }
bool s1ap::s1ap_tx_pdu(srslte::byte_buffer_t* pdu, struct sctp_sndrcvinfo* enb_sri) bool s1ap::s1ap_tx_pdu(const asn1::s1ap::s1ap_pdu_c& pdu, struct sctp_sndrcvinfo* enb_sri)
{ {
m_s1ap_log->debug("Tx S1AP PDU. %d\n", enb_sri->sinfo_assoc_id); m_s1ap_log->debug("Transmitting S1AP PDU. eNB SCTP association Id: %d\n", enb_sri->sinfo_assoc_id);
ssize_t n_sent = sctp_send(m_s1mme, pdu->msg, pdu->N_bytes, enb_sri, 0);
srslte::unique_byte_buffer_t buf = srslte::allocate_unique_buffer(*m_pool);
if (buf == nullptr) {
m_s1ap_log->error("Fatal Error: Couldn't allocate buffer for S1AP PDU.\n");
return false;
}
asn1::bit_ref bref(buf->msg, buf->get_tailroom());
if (pdu.pack(bref) != asn1::SRSASN_SUCCESS) {
m_s1ap_log->error("Could not pack S1AP PDU correctly.\n");
return false;
}
buf->N_bytes = bref.distance_bytes();
ssize_t n_sent = sctp_send(m_s1mme, buf->msg, buf->N_bytes, enb_sri, 0);
if (n_sent == -1) { if (n_sent == -1) {
m_s1ap_log->console("Failed to send S1AP PDU.\n"); m_s1ap_log->console("Failed to send S1AP PDU. Error: %s\n", strerror(errno));
m_s1ap_log->error("Failed to send S1AP PDU. \n"); m_s1ap_log->error("Failed to send S1AP PDU. Error: %s \n", strerror(errno));
return false; return false;
} }
if (m_pcap_enable) { if (m_pcap_enable) {
m_pcap.write_s1ap(pdu->msg, pdu->N_bytes); m_pcap.write_s1ap(buf->msg, buf->N_bytes);
} }
return true; return true;
} }
bool s1ap::handle_s1ap_rx_pdu(srslte::byte_buffer_t* pdu, struct sctp_sndrcvinfo* enb_sri) void s1ap::handle_s1ap_rx_pdu(srslte::byte_buffer_t* pdu, struct sctp_sndrcvinfo* enb_sri)
{ {
LIBLTE_S1AP_S1AP_PDU_STRUCT rx_pdu; // Save PCAP
if (liblte_s1ap_unpack_s1ap_pdu((LIBLTE_BYTE_MSG_STRUCT*)pdu, &rx_pdu) != LIBLTE_SUCCESS) {
m_s1ap_log->error("Failed to unpack received PDU\n");
return false;
}
if (m_pcap_enable) { if (m_pcap_enable) {
m_pcap.write_s1ap(pdu->msg, pdu->N_bytes); m_pcap.write_s1ap(pdu->msg, pdu->N_bytes);
} }
switch (rx_pdu.choice_type) { // Get PDU type
case LIBLTE_S1AP_S1AP_PDU_CHOICE_INITIATINGMESSAGE: s1ap_pdu_t rx_pdu;
m_s1ap_log->info("Received initiating PDU\n"); asn1::cbit_ref bref(pdu->msg, pdu->N_bytes);
return handle_initiating_message(&rx_pdu.choice.initiatingMessage, enb_sri); if (rx_pdu.unpack(bref) != asn1::SRSASN_SUCCESS) {
m_s1ap_log->error("Failed to unpack received PDU\n");
return;
}
switch (rx_pdu.type().value) {
case s1ap_pdu_t::types_opts::init_msg:
m_s1ap_log->info("Received Initiating PDU\n");
handle_initiating_message(rx_pdu.init_msg(), enb_sri);
break; break;
case LIBLTE_S1AP_S1AP_PDU_CHOICE_SUCCESSFULOUTCOME: case s1ap_pdu_t::types_opts::successful_outcome:
m_s1ap_log->info("Received Succeseful Outcome PDU\n"); m_s1ap_log->info("Received Succeseful Outcome PDU\n");
return handle_successful_outcome(&rx_pdu.choice.successfulOutcome); handle_successful_outcome(rx_pdu.successful_outcome());
break; break;
case LIBLTE_S1AP_S1AP_PDU_CHOICE_UNSUCCESSFULOUTCOME: case s1ap_pdu_t::types_opts::unsuccessful_outcome:
m_s1ap_log->info("Received Unsucceseful Outcome PDU\n"); m_s1ap_log->info("Received Unsucceseful Outcome PDU\n");
return true; // TODO handle_unsuccessfuloutcome(&rx_pdu.choice.unsuccessfulOutcome); // TODO handle_unsuccessfuloutcome(&rx_pdu.choice.unsuccessfulOutcome);
break; break;
default: default:
m_s1ap_log->error("Unhandled PDU type %d\n", rx_pdu.choice_type); m_s1ap_log->error("Unhandled PDU type %d\n", rx_pdu.type().value);
return false;
} }
return true;
} }
bool s1ap::handle_initiating_message(LIBLTE_S1AP_INITIATINGMESSAGE_STRUCT* msg, struct sctp_sndrcvinfo* enb_sri) void s1ap::handle_initiating_message(const asn1::s1ap::init_msg_s& msg, struct sctp_sndrcvinfo* enb_sri)
{ {
bool reply_flag = false; using init_msg_type_opts_t = asn1::s1ap::s1ap_elem_procs_o::init_msg_c::types_opts;
srslte::byte_buffer_t* reply_buffer = m_pool->allocate();
bool ret = false;
switch (msg->choice_type) { switch (msg.value.type().value) {
case LIBLTE_S1AP_INITIATINGMESSAGE_CHOICE_S1SETUPREQUEST: case init_msg_type_opts_t::s1_setup_request:
m_s1ap_log->info("Received S1 Setup Request.\n"); m_s1ap_log->info("Received S1 Setup Request.\n");
m_s1ap_mngmt_proc->handle_s1_setup_request(&msg->choice.S1SetupRequest, enb_sri, reply_buffer, &reply_flag); m_s1ap_mngmt_proc->handle_s1_setup_request(msg.value.s1_setup_request(), enb_sri);
break; break;
case LIBLTE_S1AP_INITIATINGMESSAGE_CHOICE_INITIALUEMESSAGE: case init_msg_type_opts_t::init_ue_msg:
m_s1ap_log->info("Received Initial UE Message.\n"); m_s1ap_log->info("Received Initial UE Message.\n");
m_s1ap_nas_transport->handle_initial_ue_message( m_s1ap_nas_transport->handle_initial_ue_message(msg.value.init_ue_msg(), enb_sri);
&msg->choice.InitialUEMessage, enb_sri, reply_buffer, &reply_flag);
break; break;
case LIBLTE_S1AP_INITIATINGMESSAGE_CHOICE_UPLINKNASTRANSPORT: case init_msg_type_opts_t::ul_nas_transport:
m_s1ap_log->info("Received Uplink NAS Transport Message.\n"); m_s1ap_log->info("Received Uplink NAS Transport Message.\n");
m_s1ap_nas_transport->handle_uplink_nas_transport( m_s1ap_nas_transport->handle_uplink_nas_transport(msg.value.ul_nas_transport(), enb_sri);
&msg->choice.UplinkNASTransport, enb_sri, reply_buffer, &reply_flag);
break; break;
case LIBLTE_S1AP_INITIATINGMESSAGE_CHOICE_UECONTEXTRELEASEREQUEST: case init_msg_type_opts_t::ue_context_release_request:
m_s1ap_log->info("Received UE Context Release Request Message.\n"); m_s1ap_log->info("Received UE Context Release Request Message.\n");
m_s1ap_ctx_mngmt_proc->handle_ue_context_release_request( m_s1ap_ctx_mngmt_proc->handle_ue_context_release_request(msg.value.ue_context_release_request(), enb_sri);
&msg->choice.UEContextReleaseRequest, enb_sri, reply_buffer, &reply_flag);
break; break;
default: default:
m_s1ap_log->error("Unhandled S1AP intiating message: %s\n", m_s1ap_log->error("Unhandled S1AP intiating message: %s\n", msg.value.type().to_string().c_str());
liblte_s1ap_initiatingmessage_choice_text[msg->choice_type]); m_s1ap_log->console("Unhandled S1APintiating message: %s\n", msg.value.type().to_string().c_str());
m_s1ap_log->console("Unhandled S1APintiating message: %s\n",
liblte_s1ap_initiatingmessage_choice_text[msg->choice_type]);
}
// Send Reply to eNB
if (reply_flag == true) {
ret = s1ap_tx_pdu(reply_buffer, enb_sri);
} }
m_pool->deallocate(reply_buffer);
return ret;
} }
bool s1ap::handle_successful_outcome(LIBLTE_S1AP_SUCCESSFULOUTCOME_STRUCT* msg) void s1ap::handle_successful_outcome(const asn1::s1ap::successful_outcome_s& msg)
{ {
switch (msg->choice_type) { using successful_outcome_type_opts_t = asn1::s1ap::s1ap_elem_procs_o::successful_outcome_c::types_opts;
case LIBLTE_S1AP_SUCCESSFULOUTCOME_CHOICE_INITIALCONTEXTSETUPRESPONSE:
switch (msg.value.type().value) {
case successful_outcome_type_opts_t::init_context_setup_resp:
m_s1ap_log->info("Received Initial Context Setup Response.\n"); m_s1ap_log->info("Received Initial Context Setup Response.\n");
return m_s1ap_ctx_mngmt_proc->handle_initial_context_setup_response(&msg->choice.InitialContextSetupResponse); m_s1ap_ctx_mngmt_proc->handle_initial_context_setup_response(msg.value.init_context_setup_resp());
case LIBLTE_S1AP_SUCCESSFULOUTCOME_CHOICE_UECONTEXTRELEASECOMPLETE: break;
case successful_outcome_type_opts_t::ue_context_release_complete:
m_s1ap_log->info("Received UE Context Release Complete\n"); m_s1ap_log->info("Received UE Context Release Complete\n");
return m_s1ap_ctx_mngmt_proc->handle_ue_context_release_complete(&msg->choice.UEContextReleaseComplete); m_s1ap_ctx_mngmt_proc->handle_ue_context_release_complete(msg.value.ue_context_release_complete());
break;
default: default:
m_s1ap_log->error("Unhandled successful outcome message: %s\n", m_s1ap_log->error("Unhandled successful outcome message: %s\n", msg.value.type().to_string().c_str());
liblte_s1ap_successfuloutcome_choice_text[msg->choice_type]);
} }
return true;
} }
// eNB Context Managment // eNB Context Managment
@ -306,19 +307,17 @@ void s1ap::add_new_enb_ctx(const enb_ctx_t& enb_ctx, const struct sctp_sndrcvinf
m_s1ap_log->info("Adding new eNB context. eNB ID %d\n", enb_ctx.enb_id); m_s1ap_log->info("Adding new eNB context. eNB ID %d\n", enb_ctx.enb_id);
std::set<uint32_t> ue_set; std::set<uint32_t> ue_set;
enb_ctx_t* enb_ptr = new enb_ctx_t; enb_ctx_t* enb_ptr = new enb_ctx_t;
memcpy(enb_ptr, &enb_ctx, sizeof(enb_ctx_t)); *enb_ptr = enb_ctx;
m_active_enbs.insert(std::pair<uint16_t, enb_ctx_t*>(enb_ptr->enb_id, enb_ptr)); m_active_enbs.insert(std::pair<uint16_t, enb_ctx_t*>(enb_ptr->enb_id, enb_ptr));
m_sctp_to_enb_id.insert(std::pair<int32_t, uint16_t>(enb_sri->sinfo_assoc_id, enb_ptr->enb_id)); m_sctp_to_enb_id.insert(std::pair<int32_t, uint16_t>(enb_sri->sinfo_assoc_id, enb_ptr->enb_id));
m_enb_assoc_to_ue_ids.insert(std::pair<int32_t, std::set<uint32_t> >(enb_sri->sinfo_assoc_id, ue_set)); m_enb_assoc_to_ue_ids.insert(std::pair<int32_t, std::set<uint32_t> >(enb_sri->sinfo_assoc_id, ue_set));
return;
} }
enb_ctx_t* s1ap::find_enb_ctx(uint16_t enb_id) enb_ctx_t* s1ap::find_enb_ctx(uint16_t enb_id)
{ {
std::map<uint16_t, enb_ctx_t*>::iterator it = m_active_enbs.find(enb_id); std::map<uint16_t, enb_ctx_t*>::iterator it = m_active_enbs.find(enb_id);
if (it == m_active_enbs.end()) { if (it == m_active_enbs.end()) {
return NULL; return nullptr;
} else { } else {
return it->second; return it->second;
} }
@ -574,8 +573,8 @@ void s1ap::print_enb_ctx_info(const std::string& prefix, const enb_ctx_t& enb_ct
std::string mnc_str, mcc_str; std::string mnc_str, mcc_str;
if (enb_ctx.enb_name_present) { if (enb_ctx.enb_name_present) {
m_s1ap_log->console("%s - eNB Name: %s, eNB id: 0x%x\n", prefix.c_str(), enb_ctx.enb_name, enb_ctx.enb_id); m_s1ap_log->console("%s - eNB Name: %s, eNB id: 0x%x\n", prefix.c_str(), enb_ctx.enb_name.c_str(), enb_ctx.enb_id);
m_s1ap_log->info("%s - eNB Name: %s, eNB id: 0x%x\n", prefix.c_str(), enb_ctx.enb_name, enb_ctx.enb_id); m_s1ap_log->info("%s - eNB Name: %s, eNB id: 0x%x\n", prefix.c_str(), enb_ctx.enb_name.c_str(), enb_ctx.enb_id);
} else { } else {
m_s1ap_log->console("%s - eNB Id 0x%x\n", prefix.c_str(), enb_ctx.enb_id); m_s1ap_log->console("%s - eNB Id 0x%x\n", prefix.c_str(), enb_ctx.enb_id);
m_s1ap_log->info("%s - eNB Id 0x%x\n", prefix.c_str(), enb_ctx.enb_id); m_s1ap_log->info("%s - eNB Id 0x%x\n", prefix.c_str(), enb_ctx.enb_id);
@ -591,7 +590,7 @@ void s1ap::print_enb_ctx_info(const std::string& prefix, const enb_ctx_t& enb_ct
m_s1ap_log->console("%s - TAC %d, B-PLMN %d\n", prefix.c_str(), enb_ctx.tac[i], enb_ctx.bplmns[i][j]); m_s1ap_log->console("%s - TAC %d, B-PLMN %d\n", prefix.c_str(), enb_ctx.tac[i], enb_ctx.bplmns[i][j]);
} }
} }
m_s1ap_log->console("%s - Paging DRX %d\n", prefix.c_str(), enb_ctx.drx); m_s1ap_log->console("%s - Paging DRX %s\n", prefix.c_str(), enb_ctx.drx.to_string().c_str());
return; return;
} }

@ -22,8 +22,10 @@
#include "srsepc/hdr/mme/s1ap_ctx_mngmt_proc.h" #include "srsepc/hdr/mme/s1ap_ctx_mngmt_proc.h"
#include "srsepc/hdr/mme/s1ap.h" #include "srsepc/hdr/mme/s1ap.h"
#include "srslte/common/bcd_helpers.h" #include "srslte/common/bcd_helpers.h"
#include "srslte/common/buffer_pool.h"
#include "srslte/common/int_helpers.h" #include "srslte/common/int_helpers.h"
#include "srslte/common/liblte_security.h" #include "srslte/common/liblte_security.h"
#include <endian.h>
namespace srsepc { namespace srsepc {
@ -71,16 +73,6 @@ void s1ap_ctx_mngmt_proc::init()
bool s1ap_ctx_mngmt_proc::send_initial_context_setup_request(nas* nas_ctx, uint16_t erab_to_setup) bool s1ap_ctx_mngmt_proc::send_initial_context_setup_request(nas* nas_ctx, uint16_t erab_to_setup)
{ {
// Prepare reply PDU
LIBLTE_S1AP_S1AP_PDU_STRUCT pdu;
bzero(&pdu, sizeof(LIBLTE_S1AP_S1AP_PDU_STRUCT));
pdu.choice_type = LIBLTE_S1AP_S1AP_PDU_CHOICE_INITIATINGMESSAGE;
LIBLTE_S1AP_INITIATINGMESSAGE_STRUCT* init = &pdu.choice.initiatingMessage;
init->procedureCode = LIBLTE_S1AP_PROC_ID_INITIALCONTEXTSETUP;
init->choice_type = LIBLTE_S1AP_INITIATINGMESSAGE_CHOICE_INITIALCONTEXTSETUPREQUEST;
LIBLTE_S1AP_MESSAGE_INITIALCONTEXTSETUPREQUEST_STRUCT* in_ctxt_req = &init->choice.InitialContextSetupRequest;
m_s1ap_log->info("Preparing to send Initial Context Setup request\n"); m_s1ap_log->info("Preparing to send Initial Context Setup request\n");
// Get UE Context/E-RAB Context to setup // Get UE Context/E-RAB Context to setup
@ -89,79 +81,80 @@ bool s1ap_ctx_mngmt_proc::send_initial_context_setup_request(nas* nas_ctx, uint1
esm_ctx_t* esm_ctx = &nas_ctx->m_esm_ctx[erab_to_setup]; esm_ctx_t* esm_ctx = &nas_ctx->m_esm_ctx[erab_to_setup];
sec_ctx_t* sec_ctx = &nas_ctx->m_sec_ctx; sec_ctx_t* sec_ctx = &nas_ctx->m_sec_ctx;
// Prepare reply PDU
s1ap_pdu_t tx_pdu;
tx_pdu.set_init_msg().load_info_obj(ASN1_S1AP_ID_INIT_CONTEXT_SETUP);
asn1::s1ap::init_context_setup_request_ies_container& in_ctx_req =
tx_pdu.init_msg().value.init_context_setup_request().protocol_ies;
// Add MME and eNB S1AP Ids // Add MME and eNB S1AP Ids
in_ctxt_req->MME_UE_S1AP_ID.MME_UE_S1AP_ID = ecm_ctx->mme_ue_s1ap_id; in_ctx_req.mme_ue_s1ap_id.value = ecm_ctx->mme_ue_s1ap_id;
in_ctxt_req->eNB_UE_S1AP_ID.ENB_UE_S1AP_ID = ecm_ctx->enb_ue_s1ap_id; in_ctx_req.enb_ue_s1ap_id.value = ecm_ctx->enb_ue_s1ap_id;
// Set UE-AMBR // UE-AMBR
in_ctxt_req->uEaggregateMaximumBitrate.uEaggregateMaximumBitRateDL.BitRate = 1000000000; in_ctx_req.ueaggregate_maximum_bitrate.value.ueaggregate_maximum_bit_rate_dl = 1000000000;
in_ctxt_req->uEaggregateMaximumBitrate.uEaggregateMaximumBitRateUL.BitRate = 1000000000; in_ctx_req.ueaggregate_maximum_bitrate.value.ueaggregate_maximum_bit_rate_ul = 1000000000;
// Number of E-RABs to be setup // Number of E-RABs to be setup
in_ctxt_req->E_RABToBeSetupListCtxtSUReq.len = 1; in_ctx_req.erab_to_be_setup_list_ctxt_su_req.value.resize(1);
in_ctx_req.erab_to_be_setup_list_ctxt_su_req.value[0].load_info_obj(ASN1_S1AP_ID_ERAB_TO_BE_SETUP_ITEM_CTXT_SU_REQ);
// Setup eRAB context // Setup eRAB context
LIBLTE_S1AP_E_RABTOBESETUPITEMCTXTSUREQ_STRUCT* erab_ctx_req = &in_ctxt_req->E_RABToBeSetupListCtxtSUReq.buffer[0]; asn1::s1ap::erab_to_be_setup_item_ctxt_su_req_s& erab_ctx_req =
erab_ctx_req->e_RAB_ID.E_RAB_ID = esm_ctx->erab_id; in_ctx_req.erab_to_be_setup_list_ctxt_su_req.value[0].value.erab_to_be_setup_item_ctxt_su_req();
erab_ctx_req.erab_id = esm_ctx->erab_id;
// Setup E-RAB QoS parameters // Setup E-RAB QoS parameters
erab_ctx_req->e_RABlevelQoSParameters.qCI.QCI = esm_ctx->qci; erab_ctx_req.erab_level_qos_params.qci = esm_ctx->qci;
erab_ctx_req->e_RABlevelQoSParameters.allocationRetentionPriority.priorityLevel.PriorityLevel = 15; // Lowest erab_ctx_req.erab_level_qos_params.alloc_retention_prio.prio_level = 15; // lowest
erab_ctx_req->e_RABlevelQoSParameters.allocationRetentionPriority.pre_emptionCapability = erab_ctx_req.erab_level_qos_params.alloc_retention_prio.pre_emption_cap =
LIBLTE_S1AP_PRE_EMPTIONCAPABILITY_SHALL_NOT_TRIGGER_PRE_EMPTION; asn1::s1ap::pre_emption_cap_opts::shall_not_trigger_pre_emption;
erab_ctx_req->e_RABlevelQoSParameters.allocationRetentionPriority.pre_emptionVulnerability = erab_ctx_req.erab_level_qos_params.alloc_retention_prio.pre_emption_vulnerability =
LIBLTE_S1AP_PRE_EMPTIONVULNERABILITY_PRE_EMPTABLE; asn1::s1ap::pre_emption_vulnerability_opts::not_pre_emptable;
erab_ctx_req->e_RABlevelQoSParameters.gbrQosInformation_present = false; erab_ctx_req.erab_level_qos_params.gbr_qos_info_present = false;
// Set E-RAB S-GW F-TEID // Set E-RAB S-GW F-TEID
erab_ctx_req->transportLayerAddress.n_bits = 32; // IPv4 erab_ctx_req.transport_layer_address.resize(32); // IPv4
uint32_t sgw_s1u_ip = htonl(esm_ctx->sgw_s1u_fteid.ipv4); asn1::bitstring_utils::from_number(
uint8_t* tmp_ptr = erab_ctx_req->transportLayerAddress.buffer; erab_ctx_req.transport_layer_address.data(), ntohl(esm_ctx->sgw_s1u_fteid.ipv4), 32);
liblte_value_2_bits(sgw_s1u_ip, &tmp_ptr, 32); erab_ctx_req.gtp_teid.from_number(esm_ctx->sgw_s1u_fteid.teid);
uint32_t sgw_s1u_teid = esm_ctx->sgw_s1u_fteid.teid;
srslte::uint32_to_uint8(sgw_s1u_teid, erab_ctx_req->gTP_TEID.buffer);
// Set UE security capabilities and k_enb // Set UE security capabilities and k_enb
bzero(in_ctxt_req->UESecurityCapabilities.encryptionAlgorithms.buffer, sizeof(uint8_t) * 16);
bzero(in_ctxt_req->UESecurityCapabilities.integrityProtectionAlgorithms.buffer, sizeof(uint8_t) * 16);
for (int i = 0; i < 3; i++) { for (int i = 0; i < 3; i++) {
if (sec_ctx->ue_network_cap.eea[i + 1] == true) { if (sec_ctx->ue_network_cap.eea[i + 1] == true) {
in_ctxt_req->UESecurityCapabilities.encryptionAlgorithms.buffer[i] = 1; // EEA supported in_ctx_req.ue_security_cap.value.encryption_algorithms.set(16 - i, true); // EEA supported
} else { } else {
in_ctxt_req->UESecurityCapabilities.encryptionAlgorithms.buffer[i] = 0; // EEA not supported in_ctx_req.ue_security_cap.value.encryption_algorithms.set(16 - i, false); // EEA not supported
} }
if (sec_ctx->ue_network_cap.eia[i + 1] == true) { if (sec_ctx->ue_network_cap.eia[i + 1] == true) {
in_ctxt_req->UESecurityCapabilities.integrityProtectionAlgorithms.buffer[i] = 1; // EEA supported in_ctx_req.ue_security_cap.value.integrity_protection_algorithms.set(16 - i, true); // EIA supported
} else { } else {
in_ctxt_req->UESecurityCapabilities.integrityProtectionAlgorithms.buffer[i] = 0; // EEA not supported in_ctx_req.ue_security_cap.value.integrity_protection_algorithms.set(16 - i, false); // EIA not supported
} }
} }
// Get K eNB // Get K eNB
liblte_unpack(sec_ctx->k_enb, 32, in_ctxt_req->SecurityKey.buffer); // memcpy(in_ctx_req.security_key.value.data(),sec_ctx->k_enb, 32);
for (uint8_t i = 0; i < 32; ++i) {
in_ctx_req.security_key.value.data()[31 - i] = sec_ctx->k_enb[i];
}
m_s1ap_log->info_hex(sec_ctx->k_enb, 32, "Initial Context Setup Request -- Key eNB (k_enb)\n"); m_s1ap_log->info_hex(sec_ctx->k_enb, 32, "Initial Context Setup Request -- Key eNB (k_enb)\n");
srslte::byte_buffer_t* nas_buffer = m_pool->allocate(); srslte::unique_byte_buffer_t nas_buffer = allocate_unique_buffer(*m_pool);
if (emm_ctx->state == EMM_STATE_DEREGISTERED) { if (emm_ctx->state == EMM_STATE_DEREGISTERED) {
// Attach procedure initiated from an attach request // Attach procedure initiated from an attach request
m_s1ap_log->console("Adding attach accept to Initial Context Setup Request\n"); m_s1ap_log->console("Adding attach accept to Initial Context Setup Request\n");
m_s1ap_log->info("Adding attach accept to Initial Context Setup Request\n"); m_s1ap_log->info("Adding attach accept to Initial Context Setup Request\n");
nas_ctx->pack_attach_accept(nas_buffer); nas_ctx->pack_attach_accept(nas_buffer.get());
// Add nas message to context setup request // Add nas message to context setup request
erab_ctx_req->nAS_PDU_present = true; erab_ctx_req.nas_pdu_present = true;
memcpy(erab_ctx_req->nAS_PDU.buffer, nas_buffer->msg, nas_buffer->N_bytes); erab_ctx_req.nas_pdu.resize(nas_buffer->N_bytes);
erab_ctx_req->nAS_PDU.n_octets = nas_buffer->N_bytes; memcpy(erab_ctx_req.nas_pdu.data(), nas_buffer->msg, nas_buffer->N_bytes);
} }
srslte::byte_buffer_t* reply_buffer = m_pool->allocate(); if (!m_s1ap->s1ap_tx_pdu(tx_pdu, &ecm_ctx->enb_sri)) {
LIBLTE_ERROR_ENUM err = liblte_s1ap_pack_s1ap_pdu(&pdu, (LIBLTE_BYTE_MSG_STRUCT*)reply_buffer);
if (err != LIBLTE_SUCCESS) {
m_s1ap_log->error("Could not pack Initial Context Setup Request Message\n");
return false;
}
if (!m_s1ap->s1ap_tx_pdu(reply_buffer, &ecm_ctx->enb_sri)) {
m_s1ap_log->error("Error sending Initial Context Setup Request.\n"); m_s1ap_log->error("Error sending Initial Context Setup Request.\n");
return false; return false;
} }
@ -170,28 +163,30 @@ bool s1ap_ctx_mngmt_proc::send_initial_context_setup_request(nas* nas_ctx, uint1
esm_ctx->state = ERAB_CTX_REQUESTED; esm_ctx->state = ERAB_CTX_REQUESTED;
struct in_addr addr; struct in_addr addr;
addr.s_addr = htonl(sgw_s1u_ip); addr.s_addr = htonl(erab_ctx_req.transport_layer_address.to_number());
m_s1ap_log->info("Sent Initial Context Setup Request. E-RAB id %d \n", erab_ctx_req->e_RAB_ID.E_RAB_ID); m_s1ap_log->console("Sent Initial Context Setup Request. E-RAB id %d \n", erab_ctx_req.erab_id);
m_s1ap_log->info("Initial Context -- S1-U TEID 0x%x. IP %s \n", sgw_s1u_teid, inet_ntoa(addr)); m_s1ap_log->info(
m_s1ap_log->console("Initial Context Setup Request -- eNB UE S1AP Id %d, MME UE S1AP Id %d\n", "Initial Context -- S1-U TEID 0x%" PRIx64 ". IP %s \n", erab_ctx_req.gtp_teid.to_number(), inet_ntoa(addr));
in_ctxt_req->eNB_UE_S1AP_ID.ENB_UE_S1AP_ID, m_s1ap_log->info("Initial Context Setup Request -- eNB UE S1AP Id %d, MME UE S1AP Id %" PRIu64 "\n",
in_ctxt_req->MME_UE_S1AP_ID.MME_UE_S1AP_ID); in_ctx_req.enb_ue_s1ap_id.value.value,
m_s1ap_log->console("Initial Context Setup Request -- E-RAB id %d\n", erab_ctx_req->e_RAB_ID.E_RAB_ID); in_ctx_req.mme_ue_s1ap_id.value.value);
m_s1ap_log->console("Initial Context Setup Request -- S1-U TEID 0x%x. IP %s \n", sgw_s1u_teid, inet_ntoa(addr)); m_s1ap_log->info("Initial Context Setup Request -- E-RAB id %d\n", erab_ctx_req.erab_id);
m_s1ap_log->console("Initial Context Setup Request -- S1-U TEID 0x%x. IP %s \n", sgw_s1u_teid, inet_ntoa(addr)); m_s1ap_log->info("Initial Context Setup Request -- S1-U TEID 0x%" PRIu64 ". IP %s \n",
m_s1ap_log->console("Initial Context Setup Request -- QCI %d \n", erab_ctx_req->e_RABlevelQoSParameters.qCI.QCI); erab_ctx_req.gtp_teid.to_number(),
inet_ntoa(addr));
m_pool->deallocate(reply_buffer); m_s1ap_log->info("Initial Context Setup Request -- S1-U TEID 0x%" PRIu64 ". IP %s \n",
m_pool->deallocate(nas_buffer); erab_ctx_req.gtp_teid.to_number(),
inet_ntoa(addr));
m_s1ap_log->info("Initial Context Setup Request -- QCI %d\n", erab_ctx_req.erab_level_qos_params.qci);
return true; return true;
} }
bool s1ap_ctx_mngmt_proc::handle_initial_context_setup_response( bool s1ap_ctx_mngmt_proc::handle_initial_context_setup_response(
LIBLTE_S1AP_MESSAGE_INITIALCONTEXTSETUPRESPONSE_STRUCT* in_ctxt_resp) const asn1::s1ap::init_context_setup_resp_s& in_ctxt_resp)
{ {
uint32_t mme_ue_s1ap_id = in_ctxt_resp->MME_UE_S1AP_ID.MME_UE_S1AP_ID; uint32_t mme_ue_s1ap_id = in_ctxt_resp.protocol_ies.mme_ue_s1ap_id.value.value;
nas* nas_ctx = m_s1ap->find_nas_ctx_from_mme_ue_s1ap_id(mme_ue_s1ap_id); nas* nas_ctx = m_s1ap->find_nas_ctx_from_mme_ue_s1ap_id(mme_ue_s1ap_id);
if (nas_ctx == NULL) { if (nas_ctx == nullptr) {
m_s1ap_log->error("Could not find UE's context in active UE's map\n"); m_s1ap_log->error("Could not find UE's context in active UE's map\n");
return false; return false;
} }
@ -200,28 +195,38 @@ bool s1ap_ctx_mngmt_proc::handle_initial_context_setup_response(
ecm_ctx_t* ecm_ctx = &nas_ctx->m_ecm_ctx; ecm_ctx_t* ecm_ctx = &nas_ctx->m_ecm_ctx;
m_s1ap_log->console("Received Initial Context Setup Response\n"); m_s1ap_log->console("Received Initial Context Setup Response\n");
// Setup E-RABs // Setup E-RABs
for (uint32_t i = 0; i < in_ctxt_resp->E_RABSetupListCtxtSURes.len; i++) { for (const asn1::s1ap::protocol_ie_single_container_s<asn1::s1ap::erab_setup_item_ctxt_su_res_ies_o>& ie_container :
uint8_t erab_id = in_ctxt_resp->E_RABSetupListCtxtSURes.buffer[i].e_RAB_ID.E_RAB_ID; in_ctxt_resp.protocol_ies.erab_setup_list_ctxt_su_res.value) {
// Get E-RAB setup context item and E-RAB Id
const asn1::s1ap::erab_setup_item_ctxt_su_res_s& erab_setup_item_ctxt =
ie_container.value.erab_setup_item_ctxt_su_res();
uint8_t erab_id = erab_setup_item_ctxt.erab_id;
// Make sure we requested the context setup
esm_ctx_t* esm_ctx = &nas_ctx->m_esm_ctx[erab_id]; esm_ctx_t* esm_ctx = &nas_ctx->m_esm_ctx[erab_id];
if (esm_ctx->state != ERAB_CTX_REQUESTED) { if (esm_ctx->state != ERAB_CTX_REQUESTED) {
m_s1ap_log->error("E-RAB requested was not previously requested %d\n", erab_id); m_s1ap_log->error("E-RAB requested was not previously requested %d\n", erab_id);
return false; return false;
} }
// Mark E-RAB with context setup // Mark E-RAB with context setup
esm_ctx->state = ERAB_CTX_SETUP; esm_ctx->state = ERAB_CTX_SETUP;
// Set the GTP information // Set the GTP information
uint8_t* bit_ptr = in_ctxt_resp->E_RABSetupListCtxtSURes.buffer[i].transportLayerAddress.buffer; esm_ctx->enb_fteid.teid = erab_setup_item_ctxt.gtp_teid.to_number();
esm_ctx->enb_fteid.ipv4 = htonl(liblte_bits_2_value(&bit_ptr, 32)); esm_ctx->enb_fteid.ipv4 = ntohl(erab_setup_item_ctxt.transport_layer_address.to_number());
memcpy(&esm_ctx->enb_fteid.teid, in_ctxt_resp->E_RABSetupListCtxtSURes.buffer[i].gTP_TEID.buffer, 4);
esm_ctx->enb_fteid.teid = ntohl(esm_ctx->enb_fteid.teid); char enb_addr_str[INET_ADDRSTRLEN + 1] = {};
struct in_addr tmp_addr = {};
char enb_addr_str[INET_ADDRSTRLEN + 1]; tmp_addr.s_addr = esm_ctx->enb_fteid.ipv4;
const char* err = inet_ntop(AF_INET, &esm_ctx->enb_fteid.ipv4, enb_addr_str, sizeof(enb_addr_str)); const char* err = inet_ntop(AF_INET, &tmp_addr, enb_addr_str, INET_ADDRSTRLEN);
if (err == NULL) { if (err == nullptr) {
m_s1ap_log->error("Error converting IP to string\n"); m_s1ap_log->error("Error converting IP to string\n");
} }
m_s1ap_log->info("E-RAB Context Setup. E-RAB id %d\n", esm_ctx->erab_id); m_s1ap_log->info("E-RAB Context Setup. E-RAB id %d\n", esm_ctx->erab_id);
m_s1ap_log->info("E-RAB Context -- eNB TEID 0x%x, eNB Address %s\n", esm_ctx->enb_fteid.teid, enb_addr_str); m_s1ap_log->info("E-RAB Context -- eNB TEID 0x%x, eNB Address %s\n", esm_ctx->enb_fteid.teid, enb_addr_str);
m_s1ap_log->console("E-RAB Context Setup. E-RAB id %d\n", esm_ctx->erab_id); m_s1ap_log->console("E-RAB Context Setup. E-RAB id %d\n", esm_ctx->erab_id);
@ -237,19 +242,15 @@ bool s1ap_ctx_mngmt_proc::handle_initial_context_setup_response(
return true; return true;
} }
bool s1ap_ctx_mngmt_proc::handle_ue_context_release_request(LIBLTE_S1AP_MESSAGE_UECONTEXTRELEASEREQUEST_STRUCT* ue_rel, bool s1ap_ctx_mngmt_proc::handle_ue_context_release_request(const asn1::s1ap::ue_context_release_request_s& ue_rel,
struct sctp_sndrcvinfo* enb_sri, struct sctp_sndrcvinfo* enb_sri)
srslte::byte_buffer_t* reply_buffer,
bool* reply_flag)
{ {
LIBLTE_S1AP_MESSAGE_UECONTEXTRELEASEREQUEST_STRUCT ue_rel_req; uint32_t mme_ue_s1ap_id = ue_rel.protocol_ies.mme_ue_s1ap_id.value.value;
uint32_t mme_ue_s1ap_id = ue_rel->MME_UE_S1AP_ID.MME_UE_S1AP_ID;
m_s1ap_log->info("Received UE Context Release Request. MME-UE S1AP Id: %d\n", mme_ue_s1ap_id); m_s1ap_log->info("Received UE Context Release Request. MME-UE S1AP Id: %d\n", mme_ue_s1ap_id);
m_s1ap_log->console("Received UE Context Release Request. MME-UE S1AP Id %d\n", mme_ue_s1ap_id); m_s1ap_log->console("Received UE Context Release Request. MME-UE S1AP Id %d\n", mme_ue_s1ap_id);
nas* nas_ctx = m_s1ap->find_nas_ctx_from_mme_ue_s1ap_id(mme_ue_s1ap_id); nas* nas_ctx = m_s1ap->find_nas_ctx_from_mme_ue_s1ap_id(mme_ue_s1ap_id);
if (nas_ctx == NULL) { if (nas_ctx == nullptr) {
m_s1ap_log->info("No UE context to release found. MME-UE S1AP Id: %d\n", mme_ue_s1ap_id); m_s1ap_log->info("No UE context to release found. MME-UE S1AP Id: %d\n", mme_ue_s1ap_id);
m_s1ap_log->console("No UE context to release found. MME-UE S1AP Id: %d\n", mme_ue_s1ap_id); m_s1ap_log->console("No UE context to release found. MME-UE S1AP Id: %d\n", mme_ue_s1ap_id);
return false; return false;
@ -291,53 +292,36 @@ bool s1ap_ctx_mngmt_proc::handle_ue_context_release_request(LIBLTE_S1AP_MESSAGE_
bool s1ap_ctx_mngmt_proc::send_ue_context_release_command(nas* nas_ctx) bool s1ap_ctx_mngmt_proc::send_ue_context_release_command(nas* nas_ctx)
{ {
srslte::byte_buffer_t* reply_buffer = m_pool->allocate();
// Prepare reply PDU // Prepare reply PDU
LIBLTE_S1AP_S1AP_PDU_STRUCT pdu; s1ap_pdu_t tx_pdu;
bzero(&pdu, sizeof(LIBLTE_S1AP_S1AP_PDU_STRUCT)); tx_pdu.set_init_msg().load_info_obj(ASN1_S1AP_ID_UE_CONTEXT_RELEASE);
pdu.choice_type = LIBLTE_S1AP_S1AP_PDU_CHOICE_INITIATINGMESSAGE;
asn1::s1ap::ue_context_release_cmd_ies_container& ctx_rel_cmd =
LIBLTE_S1AP_INITIATINGMESSAGE_STRUCT* init = &pdu.choice.initiatingMessage; tx_pdu.init_msg().value.ue_context_release_cmd().protocol_ies;
init->procedureCode = LIBLTE_S1AP_PROC_ID_UECONTEXTRELEASE; ctx_rel_cmd.ue_s1ap_ids.value.set(asn1::s1ap::ue_s1ap_ids_c::types_opts::ue_s1ap_id_pair);
init->choice_type = LIBLTE_S1AP_INITIATINGMESSAGE_CHOICE_UECONTEXTRELEASECOMMAND; ctx_rel_cmd.ue_s1ap_ids.value.ue_s1ap_id_pair().mme_ue_s1ap_id = nas_ctx->m_ecm_ctx.mme_ue_s1ap_id;
ctx_rel_cmd.ue_s1ap_ids.value.ue_s1ap_id_pair().enb_ue_s1ap_id = nas_ctx->m_ecm_ctx.enb_ue_s1ap_id;
LIBLTE_S1AP_MESSAGE_UECONTEXTRELEASECOMMAND_STRUCT* ctx_rel_cmd = &init->choice.UEContextReleaseCommand;
ctx_rel_cmd->UE_S1AP_IDs.choice_type = LIBLTE_S1AP_UE_S1AP_IDS_CHOICE_UE_S1AP_ID_PAIR; ctx_rel_cmd.cause.value.set(asn1::s1ap::cause_c::types_opts::nas);
ctx_rel_cmd->UE_S1AP_IDs.choice.uE_S1AP_ID_pair.mME_UE_S1AP_ID.MME_UE_S1AP_ID = nas_ctx->m_ecm_ctx.mme_ue_s1ap_id; ctx_rel_cmd.cause.value.nas().value = asn1::s1ap::cause_nas_opts::options::normal_release;
ctx_rel_cmd->UE_S1AP_IDs.choice.uE_S1AP_ID_pair.eNB_UE_S1AP_ID.ENB_UE_S1AP_ID = nas_ctx->m_ecm_ctx.enb_ue_s1ap_id;
ctx_rel_cmd->Cause.choice_type = LIBLTE_S1AP_CAUSE_CHOICE_NAS;
ctx_rel_cmd->Cause.choice.nas.ext = false;
ctx_rel_cmd->Cause.choice.nas.e = LIBLTE_S1AP_CAUSENAS_NORMAL_RELEASE;
LIBLTE_ERROR_ENUM err = liblte_s1ap_pack_s1ap_pdu(&pdu, (LIBLTE_BYTE_MSG_STRUCT*)reply_buffer);
if (err != LIBLTE_SUCCESS) {
m_s1ap_log->error("Could not pack Context Release Command Message\n");
m_pool->deallocate(reply_buffer);
return false;
}
// Send Reply to eNB // Send Reply to eNB
if (!m_s1ap->s1ap_tx_pdu(reply_buffer, &nas_ctx->m_ecm_ctx.enb_sri)) { if (!m_s1ap->s1ap_tx_pdu(tx_pdu, &nas_ctx->m_ecm_ctx.enb_sri)) {
m_s1ap_log->error("Error sending UE Context Release Command.\n"); m_s1ap_log->error("Error sending UE Context Release Command.\n");
m_pool->deallocate(reply_buffer);
return false; return false;
} }
m_pool->deallocate(reply_buffer);
return true; return true;
} }
bool s1ap_ctx_mngmt_proc::handle_ue_context_release_complete( bool s1ap_ctx_mngmt_proc::handle_ue_context_release_complete(const asn1::s1ap::ue_context_release_complete_s& rel_comp)
LIBLTE_S1AP_MESSAGE_UECONTEXTRELEASECOMPLETE_STRUCT* rel_comp)
{ {
uint32_t mme_ue_s1ap_id = rel_comp->MME_UE_S1AP_ID.MME_UE_S1AP_ID; uint32_t mme_ue_s1ap_id = rel_comp.protocol_ies.mme_ue_s1ap_id.value.value;
m_s1ap_log->info("Received UE Context Release Complete. MME-UE S1AP Id: %d\n", mme_ue_s1ap_id); m_s1ap_log->info("Received UE Context Release Complete. MME-UE S1AP Id: %d\n", mme_ue_s1ap_id);
m_s1ap_log->console("Received UE Context Release Complete. MME-UE S1AP Id %d\n", mme_ue_s1ap_id); m_s1ap_log->console("Received UE Context Release Complete. MME-UE S1AP Id %d\n", mme_ue_s1ap_id);
nas* nas_ctx = m_s1ap->find_nas_ctx_from_mme_ue_s1ap_id(mme_ue_s1ap_id); nas* nas_ctx = m_s1ap->find_nas_ctx_from_mme_ue_s1ap_id(mme_ue_s1ap_id);
if (nas_ctx == NULL) { if (nas_ctx == nullptr) {
m_s1ap_log->info("No UE context to release found. MME-UE S1AP Id: %d\n", mme_ue_s1ap_id); m_s1ap_log->info("No UE context to release found. MME-UE S1AP Id: %d\n", mme_ue_s1ap_id);
m_s1ap_log->console("No UE context to release found. MME-UE S1AP Id: %d\n", mme_ue_s1ap_id); m_s1ap_log->console("No UE context to release found. MME-UE S1AP Id: %d\n", mme_ue_s1ap_id);
return false; return false;
@ -358,8 +342,8 @@ bool s1ap_ctx_mngmt_proc::handle_ue_context_release_complete(
m_s1ap_log->info("UE is not ECM connected. No need to release S1-U. MME UE S1AP Id %d\n", mme_ue_s1ap_id); m_s1ap_log->info("UE is not ECM connected. No need to release S1-U. MME UE S1AP Id %d\n", mme_ue_s1ap_id);
m_s1ap_log->console("UE is not ECM connected. No need to release S1-U. MME UE S1AP Id %d\n", mme_ue_s1ap_id); m_s1ap_log->console("UE is not ECM connected. No need to release S1-U. MME UE S1AP Id %d\n", mme_ue_s1ap_id);
// Make sure E-RABS are marked as DEACTIVATED. // Make sure E-RABS are marked as DEACTIVATED.
for (int i = 0; i < MAX_ERABS_PER_UE; i++) { for (esm_ctx_t& esm_ctx : nas_ctx->m_esm_ctx) {
nas_ctx->m_esm_ctx[i].state = ERAB_DEACTIVATED; esm_ctx.state = ERAB_DEACTIVATED;
} }
} }

@ -66,13 +66,13 @@ void s1ap_mngmt_proc::init(void)
m_s1ap_args = m_s1ap->m_s1ap_args; m_s1ap_args = m_s1ap->m_s1ap_args;
} }
bool s1ap_mngmt_proc::handle_s1_setup_request(LIBLTE_S1AP_MESSAGE_S1SETUPREQUEST_STRUCT* msg, bool s1ap_mngmt_proc::handle_s1_setup_request(const asn1::s1ap::s1_setup_request_s& msg,
struct sctp_sndrcvinfo* enb_sri, struct sctp_sndrcvinfo* enb_sri)
srslte::byte_buffer_t* reply_buffer,
bool* reply_flag)
{ {
enb_ctx_t enb_ctx; m_s1ap_log->console("Received S1 Setup Request.\n");
LIBLTE_S1AP_S1AP_PDU_STRUCT reply_pdu; m_s1ap_log->info("Received S1 Setup Request.\n");
enb_ctx_t enb_ctx = {};
if (!unpack_s1_setup_request(msg, &enb_ctx)) { if (!unpack_s1_setup_request(msg, &enb_ctx)) {
m_s1ap_log->error("Malformed S1 Setup Request\n"); m_s1ap_log->error("Malformed S1 Setup Request\n");
@ -81,19 +81,19 @@ bool s1ap_mngmt_proc::handle_s1_setup_request(LIBLTE_S1AP_MESSAGE_S1SETUPREQUEST
// Store SCTP sendrecv info // Store SCTP sendrecv info
memcpy(&enb_ctx.sri, enb_sri, sizeof(struct sctp_sndrcvinfo)); memcpy(&enb_ctx.sri, enb_sri, sizeof(struct sctp_sndrcvinfo));
m_s1ap_log->debug("eNB SCTP association Id: %d\n", enb_sri->sinfo_assoc_id);
// Log S1 Setup Request Info // Log S1 Setup Request Info
m_s1ap_log->console("Received S1 Setup Request.\n");
m_s1ap->print_enb_ctx_info(std::string("S1 Setup Request"), enb_ctx); m_s1ap->print_enb_ctx_info(std::string("S1 Setup Request"), enb_ctx);
// Check matching PLMNs // Check matching PLMNs
if (enb_ctx.plmn != m_s1ap->get_plmn()) { if (enb_ctx.plmn != m_s1ap->get_plmn()) {
m_s1ap_log->console("Sending S1 Setup Failure - Unknown PLMN\n"); m_s1ap_log->console("Sending S1 Setup Failure - Unknown PLMN\n");
m_s1ap_log->warning("Sending S1 Setup Failure - Unknown PLMN\n"); m_s1ap_log->warning("Sending S1 Setup Failure - Unknown PLMN\n");
pack_s1_setup_failure(LIBLTE_S1AP_CAUSEMISC_UNKNOWN_PLMN, reply_buffer); send_s1_setup_failure(asn1::s1ap::cause_misc_opts::unknown_plmn, enb_sri);
} else { } else {
enb_ctx_t* enb_ptr = m_s1ap->find_enb_ctx(enb_ctx.enb_id); enb_ctx_t* enb_ptr = m_s1ap->find_enb_ctx(enb_ctx.enb_id);
if (enb_ptr != NULL) { if (enb_ptr != nullptr) {
// eNB already registered // eNB already registered
// TODO replace enb_ctx // TODO replace enb_ctx
m_s1ap_log->warning("eNB Already registered\n"); m_s1ap_log->warning("eNB Already registered\n");
@ -102,19 +102,17 @@ bool s1ap_mngmt_proc::handle_s1_setup_request(LIBLTE_S1AP_MESSAGE_S1SETUPREQUEST
m_s1ap->add_new_enb_ctx(enb_ctx, enb_sri); m_s1ap->add_new_enb_ctx(enb_ctx, enb_sri);
} }
pack_s1_setup_response(m_s1ap_args, reply_buffer); send_s1_setup_response(m_s1ap_args, enb_sri);
m_s1ap_log->console("Sending S1 Setup Response\n"); m_s1ap_log->console("Sending S1 Setup Response\n");
m_s1ap_log->info("Sending S1 Setup Response\n"); m_s1ap_log->info("Sending S1 Setup Response\n");
} }
*reply_flag = true;
return true; return true;
} }
/* /*
* Packing/Unpacking helper functions. * Packing/Unpacking helper functions.
*/ */
bool s1ap_mngmt_proc::unpack_s1_setup_request(LIBLTE_S1AP_MESSAGE_S1SETUPREQUEST_STRUCT* msg, enb_ctx_t* enb_ctx) bool s1ap_mngmt_proc::unpack_s1_setup_request(const asn1::s1ap::s1_setup_request_s& msg, enb_ctx_t* enb_ctx)
{ {
uint8_t enb_id_bits[32]; uint8_t enb_id_bits[32];
@ -122,128 +120,105 @@ bool s1ap_mngmt_proc::unpack_s1_setup_request(LIBLTE_S1AP_MESSAGE_S1SETUPREQUEST
uint16_t tac, bplmn; uint16_t tac, bplmn;
uint32_t tmp32 = 0; uint32_t tmp32 = 0;
const asn1::s1ap::s1_setup_request_ies_container& s1_req = msg.protocol_ies;
// eNB Name // eNB Name
enb_ctx->enb_name_present = msg->eNBname_present; enb_ctx->enb_name_present = s1_req.enbname_present;
if (msg->eNBname_present) { if (s1_req.enbname_present) {
bzero(enb_ctx->enb_name, sizeof(enb_ctx->enb_name)); enb_ctx->enb_name = s1_req.enbname.value.to_string();
memcpy(enb_ctx->enb_name, &msg->eNBname.buffer, msg->eNBname.n_octets);
} }
// eNB Id // eNB Id
bzero(enb_id_bits, sizeof(enb_id_bits)); enb_ctx->enb_id = s1_req.global_enb_id.value.enb_id.macro_enb_id().to_number();
memcpy(&enb_id_bits[32 - LIBLTE_S1AP_MACROENB_ID_BIT_STRING_LEN],
msg->Global_ENB_ID.eNB_ID.choice.macroENB_ID.buffer,
LIBLTE_S1AP_MACROENB_ID_BIT_STRING_LEN);
liblte_pack(enb_id_bits, 32, (uint8_t*)&tmp32);
enb_ctx->enb_id = ntohl(tmp32);
// PLMN Id // PLMN Id
((uint8_t*)&plmn)[1] = msg->Global_ENB_ID.pLMNidentity.buffer[0]; ((uint8_t*)&plmn)[1] = s1_req.global_enb_id.value.plm_nid[0];
((uint8_t*)&plmn)[2] = msg->Global_ENB_ID.pLMNidentity.buffer[1]; ((uint8_t*)&plmn)[2] = s1_req.global_enb_id.value.plm_nid[1];
((uint8_t*)&plmn)[3] = msg->Global_ENB_ID.pLMNidentity.buffer[2]; ((uint8_t*)&plmn)[3] = s1_req.global_enb_id.value.plm_nid[2];
enb_ctx->plmn = ntohl(plmn); enb_ctx->plmn = ntohl(plmn);
srslte::s1ap_plmn_to_mccmnc(enb_ctx->plmn, &enb_ctx->mcc, &enb_ctx->mnc); srslte::s1ap_plmn_to_mccmnc(enb_ctx->plmn, &enb_ctx->mcc, &enb_ctx->mnc);
// SupportedTAs // SupportedTAs
enb_ctx->nof_supported_ta = msg->SupportedTAs.len; enb_ctx->nof_supported_ta = s1_req.supported_tas.value.size();
for (uint16_t i = 0; i < msg->SupportedTAs.len; i++) { for (uint16_t i = 0; i < enb_ctx->nof_supported_ta; i++) {
const asn1::s1ap::supported_tas_item_s& tas = s1_req.supported_tas.value[i];
// TAC // TAC
((uint8_t*)&enb_ctx->tac[i])[0] = msg->SupportedTAs.buffer[i].tAC.buffer[0]; ((uint8_t*)&enb_ctx->tac[i])[0] = tas.tac[0];
((uint8_t*)&enb_ctx->tac[i])[1] = msg->SupportedTAs.buffer[i].tAC.buffer[1]; ((uint8_t*)&enb_ctx->tac[i])[1] = tas.tac[1];
enb_ctx->tac[i] = ntohs(enb_ctx->tac[i]); enb_ctx->tac[i] = ntohs(enb_ctx->tac[i]);
enb_ctx->nof_supported_bplmns[i] = msg->SupportedTAs.buffer[i].broadcastPLMNs.len; enb_ctx->nof_supported_bplmns[i] = tas.broadcast_plmns.size();
for (uint16_t j = 0; j < msg->SupportedTAs.buffer[i].broadcastPLMNs.len; j++) { for (uint16_t j = 0; j < tas.broadcast_plmns.size(); j++) {
// BPLMNs // BPLMNs
((uint8_t*)&enb_ctx->bplmns[i][j])[1] = msg->SupportedTAs.buffer[i].broadcastPLMNs.buffer[j].buffer[0]; ((uint8_t*)&enb_ctx->bplmns[i][j])[1] = tas.broadcast_plmns[j][0];
((uint8_t*)&enb_ctx->bplmns[i][j])[2] = msg->SupportedTAs.buffer[i].broadcastPLMNs.buffer[j].buffer[1]; ((uint8_t*)&enb_ctx->bplmns[i][j])[2] = tas.broadcast_plmns[j][1];
((uint8_t*)&enb_ctx->bplmns[i][j])[3] = msg->SupportedTAs.buffer[i].broadcastPLMNs.buffer[j].buffer[2]; ((uint8_t*)&enb_ctx->bplmns[i][j])[3] = tas.broadcast_plmns[j][2];
enb_ctx->bplmns[i][j] = ntohl(enb_ctx->bplmns[i][j]); enb_ctx->bplmns[i][j] = ntohl(enb_ctx->bplmns[i][j]);
} }
} }
// Default Paging DRX // Default Paging DRX
enb_ctx->drx = msg->DefaultPagingDRX.e; enb_ctx->drx = s1_req.default_paging_drx.value;
return true; return true;
} }
bool s1ap_mngmt_proc::pack_s1_setup_failure(LIBLTE_S1AP_CAUSEMISC_ENUM cause, srslte::byte_buffer_t* msg) bool s1ap_mngmt_proc::send_s1_setup_failure(asn1::s1ap::cause_misc_opts::options cause, struct sctp_sndrcvinfo* enb_sri)
{ {
LIBLTE_S1AP_S1AP_PDU_STRUCT pdu; s1ap_pdu_t tx_pdu;
bzero(&pdu, sizeof(LIBLTE_S1AP_S1AP_PDU_STRUCT)); tx_pdu.set_unsuccessful_outcome().load_info_obj(ASN1_S1AP_ID_S1_SETUP);
pdu.choice_type = LIBLTE_S1AP_S1AP_PDU_CHOICE_UNSUCCESSFULOUTCOME;
LIBLTE_S1AP_UNSUCCESSFULOUTCOME_STRUCT* unsucc = &pdu.choice.unsuccessfulOutcome;
unsucc->procedureCode = LIBLTE_S1AP_PROC_ID_S1SETUP;
unsucc->criticality = LIBLTE_S1AP_CRITICALITY_REJECT;
unsucc->choice_type = LIBLTE_S1AP_UNSUCCESSFULOUTCOME_CHOICE_S1SETUPFAILURE;
LIBLTE_S1AP_MESSAGE_S1SETUPFAILURE_STRUCT* s1_fail = (LIBLTE_S1AP_MESSAGE_S1SETUPFAILURE_STRUCT*)&unsucc->choice; asn1::s1ap::s1_setup_fail_ies_container& s1_fail = tx_pdu.unsuccessful_outcome().value.s1_setup_fail().protocol_ies;
s1_fail->TimeToWait_present = false; s1_fail.cause.value.set(asn1::s1ap::cause_c::types_opts::misc);
s1_fail->CriticalityDiagnostics_present = false; s1_fail.cause.value.misc().value = cause;
s1_fail->Cause.ext = false;
s1_fail->Cause.choice_type = LIBLTE_S1AP_CAUSE_CHOICE_MISC;
s1_fail->Cause.choice.misc.ext = false;
s1_fail->Cause.choice.misc.e = cause;
liblte_s1ap_pack_s1ap_pdu(&pdu, (LIBLTE_BYTE_MSG_STRUCT*)msg); m_s1ap->s1ap_tx_pdu(tx_pdu, enb_sri);
return true; return true;
} }
bool s1ap_mngmt_proc::pack_s1_setup_response(s1ap_args_t s1ap_args, srslte::byte_buffer_t* msg) bool s1ap_mngmt_proc::send_s1_setup_response(s1ap_args_t s1ap_args, struct sctp_sndrcvinfo* enb_sri)
{ {
m_s1ap_log->debug("Sending S1 Setup Response\n");
LIBLTE_S1AP_S1AP_PDU_STRUCT pdu; s1ap_pdu_t tx_pdu;
bzero(&pdu, sizeof(LIBLTE_S1AP_S1AP_PDU_STRUCT)); tx_pdu.set_successful_outcome().load_info_obj(ASN1_S1AP_ID_S1_SETUP);
pdu.choice_type = LIBLTE_S1AP_S1AP_PDU_CHOICE_SUCCESSFULOUTCOME; asn1::s1ap::s1_setup_resp_ies_container& s1_resp = tx_pdu.successful_outcome().value.s1_setup_resp().protocol_ies;
LIBLTE_S1AP_SUCCESSFULOUTCOME_STRUCT* succ = &pdu.choice.successfulOutcome;
succ->procedureCode = LIBLTE_S1AP_PROC_ID_S1SETUP;
succ->criticality = LIBLTE_S1AP_CRITICALITY_IGNORE;
succ->choice_type = LIBLTE_S1AP_SUCCESSFULOUTCOME_CHOICE_S1SETUPRESPONSE;
LIBLTE_S1AP_MESSAGE_S1SETUPRESPONSE_STRUCT* s1_resp = (LIBLTE_S1AP_MESSAGE_S1SETUPRESPONSE_STRUCT*)&succ->choice;
s1_resp->ext = false;
// MME Name // MME Name
s1_resp->MMEname_present = true; s1_resp.mm_ename_present = true;
s1_resp->MMEname.ext = false; s1_resp.mm_ename.value.from_string(s1ap_args.mme_name);
s1_resp->MMEname.n_octets = s1ap_args.mme_name.length();
memcpy(s1_resp->MMEname.buffer, s1ap_args.mme_name.c_str(), s1ap_args.mme_name.length());
// Served GUMEIs // Served GUMEIs
s1_resp->ServedGUMMEIs.len = 1; // TODO Only one served GUMMEI supported s1_resp.served_gummeis.value.resize(1); // TODO Only one served GUMMEI supported
LIBLTE_S1AP_SERVEDGUMMEISITEM_STRUCT* serv_gummei = &s1_resp->ServedGUMMEIs.buffer[0];
serv_gummei->ext = false;
serv_gummei->iE_Extensions_present = false;
uint32_t plmn = 0; uint32_t plmn = 0;
srslte::s1ap_mccmnc_to_plmn(s1ap_args.mcc, s1ap_args.mnc, &plmn); srslte::s1ap_mccmnc_to_plmn(s1ap_args.mcc, s1ap_args.mnc, &plmn);
plmn = htonl(plmn); plmn = htonl(plmn);
serv_gummei->servedPLMNs.len = 1; // Only one PLMN supported
serv_gummei->servedPLMNs.buffer[0].buffer[0] = ((uint8_t*)&plmn)[1];
serv_gummei->servedPLMNs.buffer[0].buffer[1] = ((uint8_t*)&plmn)[2];
serv_gummei->servedPLMNs.buffer[0].buffer[2] = ((uint8_t*)&plmn)[3];
serv_gummei->servedGroupIDs.len = 1; // LIBLTE_S1AP_SERVEDGROUPIDS_STRUCT asn1::s1ap::served_gummeis_item_s& serv_gummei = s1_resp.served_gummeis.value[0];
uint16_t tmp = htons(s1ap_args.mme_group);
serv_gummei->servedGroupIDs.buffer[0].buffer[0] = ((uint8_t*)&tmp)[0];
serv_gummei->servedGroupIDs.buffer[0].buffer[1] = ((uint8_t*)&tmp)[1];
serv_gummei->servedMMECs.len = 1; // Only one MMEC served serv_gummei.served_plmns.resize(1);
serv_gummei->servedMMECs.buffer[0].buffer[0] = s1ap_args.mme_code; serv_gummei.served_plmns[0][0] = ((uint8_t*)&plmn)[1];
serv_gummei.served_plmns[0][1] = ((uint8_t*)&plmn)[2];
serv_gummei.served_plmns[0][2] = ((uint8_t*)&plmn)[3];
s1_resp->RelativeMMECapacity.RelativeMMECapacity = 255; serv_gummei.served_group_ids.resize(1);
s1_resp->MMERelaySupportIndicator_present = false; serv_gummei.served_group_ids[0].from_number(htons(s1ap_args.mme_group));
s1_resp->CriticalityDiagnostics_present = false;
liblte_s1ap_pack_s1ap_pdu(&pdu, (LIBLTE_BYTE_MSG_STRUCT*)msg); serv_gummei.served_mmecs.resize(1); // Only one MMEC served
serv_gummei.served_mmecs[0].from_number(s1ap_args.mme_code);
s1_resp.relative_mme_capacity.value = 255;
if (!m_s1ap->s1ap_tx_pdu(tx_pdu, enb_sri)) {
m_s1ap_log->error("Error sending S1 Setup Response.\n");
} else {
m_s1ap_log->debug("S1 Setup Response sent\n");
}
return true; return true;
} }

@ -88,27 +88,25 @@ void s1ap_nas_transport::init()
m_nas_if.mme = mme::get_instance(); m_nas_if.mme = mme::get_instance();
} }
bool s1ap_nas_transport::handle_initial_ue_message(LIBLTE_S1AP_MESSAGE_INITIALUEMESSAGE_STRUCT* init_ue, bool s1ap_nas_transport::handle_initial_ue_message(const asn1::s1ap::init_ue_msg_s& init_ue,
struct sctp_sndrcvinfo* enb_sri, struct sctp_sndrcvinfo* enb_sri)
srslte::byte_buffer_t* reply_buffer,
bool* reply_flag)
{ {
bool err, mac_valid; bool err, mac_valid;
uint8_t pd, msg_type, sec_hdr_type; uint8_t pd, msg_type, sec_hdr_type;
srslte::byte_buffer_t* nas_msg = m_pool->allocate(); srslte::byte_buffer_t* nas_msg = m_pool->allocate();
memcpy(nas_msg->msg, &init_ue->NAS_PDU.buffer, init_ue->NAS_PDU.n_octets); memcpy(nas_msg->msg, init_ue.protocol_ies.nas_pdu.value.data(), init_ue.protocol_ies.nas_pdu.value.size());
nas_msg->N_bytes = init_ue->NAS_PDU.n_octets; nas_msg->N_bytes = init_ue.protocol_ies.nas_pdu.value.size();
uint64_t imsi = 0; uint64_t imsi = 0;
uint32_t m_tmsi = 0; uint32_t m_tmsi = 0;
uint32_t enb_ue_s1ap_id = init_ue->eNB_UE_S1AP_ID.ENB_UE_S1AP_ID; uint32_t enb_ue_s1ap_id = init_ue.protocol_ies.enb_ue_s1ap_id.value.value;
liblte_mme_parse_msg_header((LIBLTE_BYTE_MSG_STRUCT*)nas_msg, &pd, &msg_type); liblte_mme_parse_msg_header((LIBLTE_BYTE_MSG_STRUCT*)nas_msg, &pd, &msg_type);
m_s1ap_log->console("Initial UE message: %s\n", liblte_nas_msg_type_to_string(msg_type)); m_s1ap_log->console("Initial UE message: %s\n", liblte_nas_msg_type_to_string(msg_type));
m_s1ap_log->info("Initial UE message: %s\n", liblte_nas_msg_type_to_string(msg_type)); m_s1ap_log->info("Initial UE message: %s\n", liblte_nas_msg_type_to_string(msg_type));
if (init_ue->S_TMSI_present) { if (init_ue.protocol_ies.s_tmsi_present) {
srslte::uint8_to_uint32(init_ue->S_TMSI.m_TMSI.buffer, &m_tmsi); srslte::uint8_to_uint32(init_ue.protocol_ies.s_tmsi.value.m_tmsi.data(), &m_tmsi);
} }
switch (msg_type) { switch (msg_type) {
@ -144,20 +142,18 @@ bool s1ap_nas_transport::handle_initial_ue_message(LIBLTE_S1AP_MESSAGE_INITIALUE
return err; return err;
} }
bool s1ap_nas_transport::handle_uplink_nas_transport(LIBLTE_S1AP_MESSAGE_UPLINKNASTRANSPORT_STRUCT* ul_xport, bool s1ap_nas_transport::handle_uplink_nas_transport(const asn1::s1ap::ul_nas_transport_s& ul_xport,
struct sctp_sndrcvinfo* enb_sri, struct sctp_sndrcvinfo* enb_sri)
srslte::byte_buffer_t* reply_buffer,
bool* reply_flag)
{ {
uint8_t pd, msg_type, sec_hdr_type; uint8_t pd, msg_type, sec_hdr_type;
uint32_t enb_ue_s1ap_id = ul_xport->eNB_UE_S1AP_ID.ENB_UE_S1AP_ID; uint32_t enb_ue_s1ap_id = ul_xport.protocol_ies.enb_ue_s1ap_id.value.value;
uint32_t mme_ue_s1ap_id = ul_xport->MME_UE_S1AP_ID.MME_UE_S1AP_ID; uint32_t mme_ue_s1ap_id = ul_xport.protocol_ies.mme_ue_s1ap_id.value.value;
bool mac_valid = false; bool mac_valid = false;
bool increase_ul_nas_cnt = true; bool increase_ul_nas_cnt = true;
// Get UE NAS context // Get UE NAS context
nas* nas_ctx = m_s1ap->find_nas_ctx_from_mme_ue_s1ap_id(mme_ue_s1ap_id); nas* nas_ctx = m_s1ap->find_nas_ctx_from_mme_ue_s1ap_id(mme_ue_s1ap_id);
if (nas_ctx == NULL) { if (nas_ctx == nullptr) {
m_s1ap_log->warning("Received uplink NAS, but could not find UE NAS context. MME-UE S1AP id: %d\n", mme_ue_s1ap_id); m_s1ap_log->warning("Received uplink NAS, but could not find UE NAS context. MME-UE S1AP id: %d\n", mme_ue_s1ap_id);
return false; return false;
} }
@ -169,8 +165,8 @@ bool s1ap_nas_transport::handle_uplink_nas_transport(LIBLTE_S1AP_MESSAGE_UPLINKN
// Parse NAS message header // Parse NAS message header
srslte::byte_buffer_t* nas_msg = m_pool->allocate(); srslte::byte_buffer_t* nas_msg = m_pool->allocate();
memcpy(nas_msg->msg, &ul_xport->NAS_PDU.buffer, ul_xport->NAS_PDU.n_octets); memcpy(nas_msg->msg, ul_xport.protocol_ies.nas_pdu.value.data(), ul_xport.protocol_ies.nas_pdu.value.size());
nas_msg->N_bytes = ul_xport->NAS_PDU.n_octets; nas_msg->N_bytes = ul_xport.protocol_ies.nas_pdu.value.size();
bool msg_encrypted = false; bool msg_encrypted = false;
// Parse the message security header // Parse the message security header
@ -351,42 +347,21 @@ bool s1ap_nas_transport::send_downlink_nas_transport(uint32_t enb_
mme_ue_s1ap_id, mme_ue_s1ap_id,
enb_ue_s1ap_id); enb_ue_s1ap_id);
// Allocate Reply buffer
srslte::byte_buffer_t* reply_msg = m_pool->allocate();
// Setup initiating message // Setup initiating message
LIBLTE_S1AP_S1AP_PDU_STRUCT tx_pdu; s1ap_pdu_t tx_pdu;
bzero(&tx_pdu, sizeof(LIBLTE_S1AP_S1AP_PDU_STRUCT)); tx_pdu.set_init_msg().load_info_obj(ASN1_S1AP_ID_DL_NAS_TRANSPORT);
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_DOWNLINKNASTRANSPORT;
init->choice_type = LIBLTE_S1AP_INITIATINGMESSAGE_CHOICE_DOWNLINKNASTRANSPORT;
// Setup Dw NAS structure // Setup Dw NAS structure
LIBLTE_S1AP_MESSAGE_DOWNLINKNASTRANSPORT_STRUCT* dw_nas = &init->choice.DownlinkNASTransport; asn1::s1ap::dl_nas_transport_ies_container& dw_nas = tx_pdu.init_msg().value.dl_nas_transport().protocol_ies;
dw_nas->ext = false; dw_nas.enb_ue_s1ap_id.value = enb_ue_s1ap_id;
dw_nas->eNB_UE_S1AP_ID.ENB_UE_S1AP_ID = enb_ue_s1ap_id; dw_nas.mme_ue_s1ap_id.value = mme_ue_s1ap_id;
dw_nas->MME_UE_S1AP_ID.MME_UE_S1AP_ID = mme_ue_s1ap_id;
dw_nas->HandoverRestrictionList_present = false;
dw_nas->SubscriberProfileIDforRFP_present = false;
// Copy NAS PDU to Downlink NAS Trasport message buffer // Copy NAS PDU to Downlink NAS Trasport message buffer
memcpy(dw_nas->NAS_PDU.buffer, nas_msg->msg, nas_msg->N_bytes); dw_nas.nas_pdu.value.resize(nas_msg->N_bytes);
dw_nas->NAS_PDU.n_octets = nas_msg->N_bytes; memcpy(dw_nas.nas_pdu.value.data(), nas_msg->msg, nas_msg->N_bytes);
// Pack Downlink NAS Transport Message // Send Downlink NAS Transport Message
LIBLTE_ERROR_ENUM err = liblte_s1ap_pack_s1ap_pdu(&tx_pdu, (LIBLTE_BYTE_MSG_STRUCT*)reply_msg); m_s1ap->s1ap_tx_pdu(tx_pdu, &enb_sri);
if (err != LIBLTE_SUCCESS) {
m_s1ap_log->error("Error packing Downlink NAS Transport.\n");
m_s1ap_log->console("Error packing Downlink NAS Transport.\n");
m_pool->deallocate(reply_msg);
return false;
}
m_s1ap->s1ap_tx_pdu(reply_msg, &enb_sri);
m_pool->deallocate(reply_msg);
return true; return true;
} }

@ -74,14 +74,9 @@ bool s1ap_paging::send_paging(uint64_t imsi, uint16_t erab_to_setup)
m_s1ap_log->info("Preparing to Page UE -- IMSI %015" PRIu64 "\n", imsi); m_s1ap_log->info("Preparing to Page UE -- IMSI %015" PRIu64 "\n", imsi);
// Prepare reply PDU // Prepare reply PDU
LIBLTE_S1AP_S1AP_PDU_STRUCT pdu; s1ap_pdu_t tx_pdu;
bzero(&pdu, sizeof(LIBLTE_S1AP_S1AP_PDU_STRUCT)); tx_pdu.set_init_msg().load_info_obj(ASN1_S1AP_ID_PAGING);
pdu.choice_type = LIBLTE_S1AP_S1AP_PDU_CHOICE_INITIATINGMESSAGE; asn1::s1ap::paging_ies_container& paging = tx_pdu.init_msg().value.paging().protocol_ies;
LIBLTE_S1AP_INITIATINGMESSAGE_STRUCT* init = &pdu.choice.initiatingMessage;
init->procedureCode = LIBLTE_S1AP_PROC_ID_PAGING;
init->choice_type = LIBLTE_S1AP_INITIATINGMESSAGE_CHOICE_PAGING;
LIBLTE_S1AP_MESSAGE_PAGING_STRUCT* paging = &init->choice.Paging;
// Getting UE NAS Context // Getting UE NAS Context
nas* nas_ctx = m_s1ap->find_nas_ctx_from_imsi(imsi); nas* nas_ctx = m_s1ap->find_nas_ctx_from_imsi(imsi);
@ -91,42 +86,26 @@ bool s1ap_paging::send_paging(uint64_t imsi, uint16_t erab_to_setup)
} }
// UE Identity Index // UE Identity Index
uint16_t ue_index = imsi % 1024; // LIBLTE_S1AP_UEIDENTITYINDEXVALUE_BIT_STRING_LEN == 10 uint16_t ue_index = imsi % 1024;
uint8_t* tmp_ptr = paging->UEIdentityIndexValue.buffer; paging.ue_id_idx_value.value.from_number(ue_index);
liblte_value_2_bits(ue_index, &tmp_ptr, 10);
// UE Paging Id // UE Paging Id
paging->UEPagingID.choice_type = LIBLTE_S1AP_UEPAGINGID_CHOICE_S_TMSI; paging.ue_paging_id.value.set_s_tmsi();
paging->UEPagingID.choice.s_TMSI.ext = false; paging.ue_paging_id.value.s_tmsi().mmec.from_number(m_s1ap->m_s1ap_args.mme_code);
paging->UEPagingID.choice.s_TMSI.mMEC.buffer[0] = m_s1ap->m_s1ap_args.mme_code; paging.ue_paging_id.value.s_tmsi().m_tmsi.from_number(nas_ctx->m_sec_ctx.guti.m_tmsi);
uint32_t m_tmsi = nas_ctx->m_sec_ctx.guti.m_tmsi;
srslte::uint32_to_uint8(m_tmsi, paging->UEPagingID.choice.s_TMSI.m_TMSI.buffer);
paging->UEPagingID.choice.s_TMSI.iE_Extensions_present = false;
// Paging DRX
paging->pagingDRX_present = false;
// CMDomain // CMDomain
paging->CNDomain = LIBLTE_S1AP_CNDOMAIN_PS; paging.cn_domain.value = asn1::s1ap::cn_domain_opts::ps;
// TAI List // TAI List
paging->TAIList.len = 1; paging.tai_list.value.resize(1);
paging->TAIList.buffer[0].ext = false; paging.tai_list.value[0].load_info_obj(ASN1_S1AP_ID_TAI_ITEM);
paging->TAIList.buffer[0].tAI.ext = false;
uint32_t plmn = htonl(m_s1ap->get_plmn()); // LIBLTE_S1AP_TBCD_STRING_OCTET_STRING_LEN == 3 uint32_t plmn = m_s1ap->get_plmn();
paging->TAIList.buffer[0].tAI.pLMNidentity.buffer[0] = ((uint8_t*)&plmn)[1]; paging.tai_list.value[0].value.tai_item().tai.plm_nid.from_number(plmn);
paging->TAIList.buffer[0].tAI.pLMNidentity.buffer[1] = ((uint8_t*)&plmn)[2];
paging->TAIList.buffer[0].tAI.pLMNidentity.buffer[2] = ((uint8_t*)&plmn)[3]; uint16_t tac = m_s1ap->m_s1ap_args.tac;
uint16_t tac = htons(m_s1ap->m_s1ap_args.tac); // LIBLTE_S1AP_TAC_OCTET_STRING_LEN == 2 paging.tai_list.value[0].value.tai_item().tai.tac.from_number(tac);
memcpy(paging->TAIList.buffer[0].tAI.tAC.buffer, &tac, sizeof(uint16_t));
paging->TAIList.buffer[0].tAI.iE_Extensions_present = false;
paging->TAIList.buffer[0].iE_Extensions_present = false;
// CSG Id List
paging->CSG_IdList_present = false;
// Paging Priority
paging->PagingPriority_present = false;
// Start T3413 // Start T3413
if (!nas_ctx->start_timer(T_3413)) { if (!nas_ctx->start_timer(T_3413)) {
@ -134,22 +113,12 @@ bool s1ap_paging::send_paging(uint64_t imsi, uint16_t erab_to_setup)
// TODO Send data notification failure to SPGW // TODO Send data notification failure to SPGW
return false; return false;
} }
// Send Paging to eNBs
m_s1ap_log->info("Paging UE -- M-TMSI :0x%x\n", m_tmsi);
srslte::byte_buffer_t* reply_buffer = m_pool->allocate();
LIBLTE_ERROR_ENUM err = liblte_s1ap_pack_s1ap_pdu(&pdu, (LIBLTE_BYTE_MSG_STRUCT*)reply_buffer);
if (err != LIBLTE_SUCCESS) {
m_s1ap_log->error("Could not pack Paging Message\n");
m_pool->deallocate(reply_buffer);
return false;
}
for (std::map<uint16_t, enb_ctx_t*>::iterator it = m_s1ap->m_active_enbs.begin(); it != m_s1ap->m_active_enbs.end(); for (std::map<uint16_t, enb_ctx_t*>::iterator it = m_s1ap->m_active_enbs.begin(); it != m_s1ap->m_active_enbs.end();
it++) { it++) {
enb_ctx_t* enb_ctx = it->second; enb_ctx_t* enb_ctx = it->second;
if (!m_s1ap->s1ap_tx_pdu(reply_buffer, &enb_ctx->sri)) { if (!m_s1ap->s1ap_tx_pdu(tx_pdu, &enb_ctx->sri)) {
m_s1ap_log->error("Error paging to eNB. eNB Id: 0x%x.\n", enb_ctx->enb_id); m_s1ap_log->error("Error paging to eNB. eNB Id: 0x%x.\n", enb_ctx->enb_id);
m_pool->deallocate(reply_buffer);
return false; return false;
} }
} }

Loading…
Cancel
Save