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/asn1/liblte_s1ap.h"
#include "srslte/asn1/rrc_asn1.h"
#include "srslte/asn1/s1ap_asn1.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
liblte_common.cc
liblte_mme.cc
liblte_s1ap.cc
liblte_m2ap.cc
gtpc.cc
)

File diff suppressed because it is too large Load Diff

@ -72,7 +72,7 @@ private:
phy_rrc_cfg_t phy_rrc_config = {};
uint32_t nof_workers = 0;
const static int MAX_WORKERS = 4;
const static int MAX_WORKERS = 4;
const static int PRACH_WORKER_THREAD_PRIO = 3;
const static int SF_RECV_THREAD_PRIO = 1;

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

@ -176,7 +176,8 @@ void phy_common::build_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;
ss << "|";

@ -84,11 +84,11 @@ void txrx::stop()
void txrx::run_thread()
{
sf_worker* worker = nullptr;
sf_worker* worker = nullptr;
cf_t* buffer[worker_com->get_nof_carriers() * worker_com->get_nof_ports(0)] = {};
srslte_timestamp_t rx_time = {};
srslte_timestamp_t tx_time = {};
uint32_t sf_len = SRSLTE_SF_LEN_PRB(worker_com->get_nof_prb(0));
srslte_timestamp_t rx_time = {};
srslte_timestamp_t tx_time = {};
uint32_t sf_len = SRSLTE_SF_LEN_PRB(worker_com->get_nof_prb(0));
float samp_rate = srslte_sampling_freq_hz(worker_com->get_nof_prb(0));

@ -82,7 +82,7 @@ bool sched_cell_params_t::set_cfg(uint32_t enb_cc_id
// init regs
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");
return false;
}

@ -809,7 +809,7 @@ bool rrc::ue::rrc_mobility::start_ho_preparation(uint32_t target_eci,
// obj->meas_obj.meas_obj_eutra().cells_to_add_mod_list.resize(0);
empty_meascfg.compute_diff_meas_cfg(target_var_meas, &hoprep_r8.as_cfg.source_meas_cfg);
// - fill source RR Config
hoprep_r8.as_cfg.source_rr_cfg.sps_cfg_present = false; // TODO: CHECK
hoprep_r8.as_cfg.source_rr_cfg.sps_cfg_present = false; // TODO: CHECK
hoprep_r8.as_cfg.source_rr_cfg.mac_main_cfg_present =
rrc_ue->last_rrc_conn_recfg.crit_exts.c1().rrc_conn_recfg_r8().rr_cfg_ded.mac_main_cfg_present;
hoprep_r8.as_cfg.source_rr_cfg.mac_main_cfg =

@ -289,34 +289,15 @@ void s1ap::build_tai_cgi()
uint16_t tmp16;
// TAI
tai.ext = false;
tai.iE_Extensions_present = false;
s1ap_mccmnc_to_plmn(args.mcc, args.mnc, &plmn);
tmp32 = htonl(plmn);
tai.pLMNidentity.buffer[0] = ((uint8_t*)&tmp32)[1];
tai.pLMNidentity.buffer[1] = ((uint8_t*)&tmp32)[2];
tai.pLMNidentity.buffer[2] = ((uint8_t*)&tmp32)[3];
tmp16 = htons(args.tac);
memcpy(tai.tAC.buffer, (uint8_t*)&tmp16, 2);
tai.plm_nid.from_number(plmn);
tai.tac.from_number(args.tac);
// EUTRAN_CGI
eutran_cgi.ext = false;
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];
eutran_cgi.plm_nid.from_number(plmn);
tmp32 = htonl(args.enb_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);
eutran_cgi.cell_id.from_number((uint32_t)(args.enb_id << 8) | args.cell_id);
}
/*******************************************************************************
@ -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);
// TAI
container.tai.value.ie_exts_present = s1ap_ptr->tai.iE_Extensions_present;
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);
container.tai.value = s1ap_ptr->tai;
// EUTRAN_CGI
container.eutran_cgi.value.ext = s1ap_ptr->eutran_cgi.ext;
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]);
}
container.eutran_cgi.value = s1ap_ptr->eutran_cgi;
// RRC Establishment 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);
// EUTRAN CGI
container.eutran_cgi.value.ext = s1ap_ptr->eutran_cgi.ext;
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]);
}
container.eutran_cgi.value = s1ap_ptr->eutran_cgi;
// TAI
container.tai.value.ie_exts_present = s1ap_ptr->tai.iE_Extensions_present;
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);
container.tai.value = s1ap_ptr->tai;
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();
eutra.cell_type.cell_size.value = cell_size_opts::medium;
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.set(i, s1ap_ptr->eutran_cgi.cell_ID.buffer[i]);
}
eutra.global_cell_id.cell_id = s1ap_ptr->eutran_cgi.cell_id;
// - set time spent in current source cell
struct timeval ts[3];
memcpy(&ts[1], &ctxt.init_timestamp, sizeof(struct timeval));

@ -648,7 +648,9 @@ public:
std::string log_level,
uint16_t rnti_,
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
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/liblte_mme.h"
#include "srslte/asn1/liblte_s1ap.h"
#include "srslte/common/buffer_pool.h"
#include "srslte/common/security.h"
#include "srslte/interfaces/epc_interfaces.h"

@ -30,7 +30,7 @@
#include "srsepc/hdr/hss/hss.h"
#include "srslte/asn1/gtpc.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/log.h"
#include "srslte/common/s1ap_pcap.h"
@ -48,6 +48,8 @@ namespace srsepc {
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
{
public:
@ -62,10 +64,10 @@ public:
void delete_enb_ctx(int32_t assoc_id);
bool s1ap_tx_pdu(srslte::byte_buffer_t* pdu, struct sctp_sndrcvinfo* enb_sri);
bool 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);
bool handle_successful_outcome(LIBLTE_S1AP_SUCCESSFULOUTCOME_STRUCT* msg);
bool s1ap_tx_pdu(const s1ap_pdu_t& pdu, struct sctp_sndrcvinfo* enb_sri);
void handle_s1ap_rx_pdu(srslte::byte_buffer_t* pdu, struct sctp_sndrcvinfo* enb_sri);
void handle_initiating_message(const asn1::s1ap::init_msg_s& msg, struct sctp_sndrcvinfo* enb_sri);
void handle_successful_outcome(const asn1::s1ap::successful_outcome_s& msg);
void activate_eps_bearer(uint64_t imsi, uint8_t ebi);

@ -24,9 +24,10 @@
#include "srslte/asn1/gtpc_ies.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 <netinet/sctp.h>
#include <string.h>
namespace srsepc {
@ -51,17 +52,17 @@ typedef struct {
} s1ap_args_t;
typedef struct {
bool enb_name_present;
uint32_t enb_id;
uint8_t enb_name[150];
uint16_t mcc, mnc;
uint32_t plmn;
uint8_t nof_supported_ta;
uint16_t tac[MAX_TA];
uint8_t nof_supported_bplmns[MAX_TA];
uint16_t bplmns[MAX_TA][MAX_BPLMN];
LIBLTE_S1AP_PAGINGDRX_ENUM drx;
struct sctp_sndrcvinfo sri;
bool enb_name_present;
uint32_t enb_id;
std::string enb_name;
uint16_t mcc, mnc;
uint32_t plmn;
uint8_t nof_supported_ta;
std::array<uint8_t, MAX_TA> tac;
std::array<uint16_t, MAX_BPLMN> nof_supported_bplmns;
std::array<std::array<uint16_t, MAX_BPLMN>, MAX_TA> bplmns;
asn1::s1ap::paging_drx_opts drx;
struct sctp_sndrcvinfo sri;
} enb_ctx_t;
} // namespace srsepc

@ -23,7 +23,7 @@
#include "mme_gtpc.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/common.h"
#include "srslte/common/log_filter.h"
@ -42,13 +42,11 @@ public:
void init(void);
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_ue_context_release_request(LIBLTE_S1AP_MESSAGE_UECONTEXTRELEASEREQUEST_STRUCT* ue_rel,
struct sctp_sndrcvinfo* enb_sri,
srslte::byte_buffer_t* reply_buffer,
bool* reply_flag);
bool handle_initial_context_setup_response(const asn1::s1ap::init_context_setup_resp_s& in_ctxt_resp);
bool handle_ue_context_release_request(const asn1::s1ap::ue_context_release_request_s& ue_rel,
struct sctp_sndrcvinfo* enb_sri);
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:
s1ap_ctx_mngmt_proc();

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

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

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

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

@ -193,111 +193,112 @@ int s1ap::enb_listen()
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);
ssize_t n_sent = sctp_send(m_s1mme, pdu->msg, pdu->N_bytes, enb_sri, 0);
m_s1ap_log->debug("Transmitting S1AP PDU. eNB SCTP association Id: %d\n", enb_sri->sinfo_assoc_id);
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) {
m_s1ap_log->console("Failed to send S1AP PDU.\n");
m_s1ap_log->error("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. Error: %s \n", strerror(errno));
return false;
}
if (m_pcap_enable) {
m_pcap.write_s1ap(pdu->msg, pdu->N_bytes);
m_pcap.write_s1ap(buf->msg, buf->N_bytes);
}
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;
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;
}
// Save PCAP
if (m_pcap_enable) {
m_pcap.write_s1ap(pdu->msg, pdu->N_bytes);
}
switch (rx_pdu.choice_type) {
case LIBLTE_S1AP_S1AP_PDU_CHOICE_INITIATINGMESSAGE:
m_s1ap_log->info("Received initiating PDU\n");
return handle_initiating_message(&rx_pdu.choice.initiatingMessage, enb_sri);
// Get PDU type
s1ap_pdu_t rx_pdu;
asn1::cbit_ref bref(pdu->msg, pdu->N_bytes);
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;
case LIBLTE_S1AP_S1AP_PDU_CHOICE_SUCCESSFULOUTCOME:
case s1ap_pdu_t::types_opts::successful_outcome:
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;
case LIBLTE_S1AP_S1AP_PDU_CHOICE_UNSUCCESSFULOUTCOME:
case s1ap_pdu_t::types_opts::unsuccessful_outcome:
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;
default:
m_s1ap_log->error("Unhandled PDU type %d\n", rx_pdu.choice_type);
return false;
m_s1ap_log->error("Unhandled PDU type %d\n", rx_pdu.type().value);
}
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;
srslte::byte_buffer_t* reply_buffer = m_pool->allocate();
bool ret = false;
using init_msg_type_opts_t = asn1::s1ap::s1ap_elem_procs_o::init_msg_c::types_opts;
switch (msg->choice_type) {
case LIBLTE_S1AP_INITIATINGMESSAGE_CHOICE_S1SETUPREQUEST:
switch (msg.value.type().value) {
case init_msg_type_opts_t::s1_setup_request:
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;
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_nas_transport->handle_initial_ue_message(
&msg->choice.InitialUEMessage, enb_sri, reply_buffer, &reply_flag);
m_s1ap_nas_transport->handle_initial_ue_message(msg.value.init_ue_msg(), enb_sri);
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_nas_transport->handle_uplink_nas_transport(
&msg->choice.UplinkNASTransport, enb_sri, reply_buffer, &reply_flag);
m_s1ap_nas_transport->handle_uplink_nas_transport(msg.value.ul_nas_transport(), enb_sri);
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_ctx_mngmt_proc->handle_ue_context_release_request(
&msg->choice.UEContextReleaseRequest, enb_sri, reply_buffer, &reply_flag);
m_s1ap_ctx_mngmt_proc->handle_ue_context_release_request(msg.value.ue_context_release_request(), enb_sri);
break;
default:
m_s1ap_log->error("Unhandled S1AP intiating message: %s\n",
liblte_s1ap_initiatingmessage_choice_text[msg->choice_type]);
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_s1ap_log->error("Unhandled S1AP intiating message: %s\n", msg.value.type().to_string().c_str());
m_s1ap_log->console("Unhandled S1APintiating message: %s\n", msg.value.type().to_string().c_str());
}
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) {
case LIBLTE_S1AP_SUCCESSFULOUTCOME_CHOICE_INITIALCONTEXTSETUPRESPONSE:
using successful_outcome_type_opts_t = asn1::s1ap::s1ap_elem_procs_o::successful_outcome_c::types_opts;
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");
return m_s1ap_ctx_mngmt_proc->handle_initial_context_setup_response(&msg->choice.InitialContextSetupResponse);
case LIBLTE_S1AP_SUCCESSFULOUTCOME_CHOICE_UECONTEXTRELEASECOMPLETE:
m_s1ap_ctx_mngmt_proc->handle_initial_context_setup_response(msg.value.init_context_setup_resp());
break;
case successful_outcome_type_opts_t::ue_context_release_complete:
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:
m_s1ap_log->error("Unhandled successful outcome message: %s\n",
liblte_s1ap_successfuloutcome_choice_text[msg->choice_type]);
m_s1ap_log->error("Unhandled successful outcome message: %s\n", msg.value.type().to_string().c_str());
}
return true;
}
// 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);
std::set<uint32_t> ue_set;
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_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));
return;
}
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);
if (it == m_active_enbs.end()) {
return NULL;
return nullptr;
} else {
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;
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->info("%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.c_str(), enb_ctx.enb_id);
} else {
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);
@ -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 - 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;
}

@ -22,8 +22,10 @@
#include "srsepc/hdr/mme/s1ap_ctx_mngmt_proc.h"
#include "srsepc/hdr/mme/s1ap.h"
#include "srslte/common/bcd_helpers.h"
#include "srslte/common/buffer_pool.h"
#include "srslte/common/int_helpers.h"
#include "srslte/common/liblte_security.h"
#include <endian.h>
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)
{
// 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");
// 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];
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
in_ctxt_req->MME_UE_S1AP_ID.MME_UE_S1AP_ID = 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.mme_ue_s1ap_id.value = ecm_ctx->mme_ue_s1ap_id;
in_ctx_req.enb_ue_s1ap_id.value = ecm_ctx->enb_ue_s1ap_id;
// Set UE-AMBR
in_ctxt_req->uEaggregateMaximumBitrate.uEaggregateMaximumBitRateDL.BitRate = 1000000000;
in_ctxt_req->uEaggregateMaximumBitrate.uEaggregateMaximumBitRateUL.BitRate = 1000000000;
// UE-AMBR
in_ctx_req.ueaggregate_maximum_bitrate.value.ueaggregate_maximum_bit_rate_dl = 1000000000;
in_ctx_req.ueaggregate_maximum_bitrate.value.ueaggregate_maximum_bit_rate_ul = 1000000000;
// 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
LIBLTE_S1AP_E_RABTOBESETUPITEMCTXTSUREQ_STRUCT* erab_ctx_req = &in_ctxt_req->E_RABToBeSetupListCtxtSUReq.buffer[0];
erab_ctx_req->e_RAB_ID.E_RAB_ID = esm_ctx->erab_id;
asn1::s1ap::erab_to_be_setup_item_ctxt_su_req_s& erab_ctx_req =
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
erab_ctx_req->e_RABlevelQoSParameters.qCI.QCI = esm_ctx->qci;
erab_ctx_req->e_RABlevelQoSParameters.allocationRetentionPriority.priorityLevel.PriorityLevel = 15; // Lowest
erab_ctx_req->e_RABlevelQoSParameters.allocationRetentionPriority.pre_emptionCapability =
LIBLTE_S1AP_PRE_EMPTIONCAPABILITY_SHALL_NOT_TRIGGER_PRE_EMPTION;
erab_ctx_req->e_RABlevelQoSParameters.allocationRetentionPriority.pre_emptionVulnerability =
LIBLTE_S1AP_PRE_EMPTIONVULNERABILITY_PRE_EMPTABLE;
erab_ctx_req->e_RABlevelQoSParameters.gbrQosInformation_present = false;
erab_ctx_req.erab_level_qos_params.qci = esm_ctx->qci;
erab_ctx_req.erab_level_qos_params.alloc_retention_prio.prio_level = 15; // lowest
erab_ctx_req.erab_level_qos_params.alloc_retention_prio.pre_emption_cap =
asn1::s1ap::pre_emption_cap_opts::shall_not_trigger_pre_emption;
erab_ctx_req.erab_level_qos_params.alloc_retention_prio.pre_emption_vulnerability =
asn1::s1ap::pre_emption_vulnerability_opts::not_pre_emptable;
erab_ctx_req.erab_level_qos_params.gbr_qos_info_present = false;
// Set E-RAB S-GW F-TEID
erab_ctx_req->transportLayerAddress.n_bits = 32; // IPv4
uint32_t sgw_s1u_ip = htonl(esm_ctx->sgw_s1u_fteid.ipv4);
uint8_t* tmp_ptr = erab_ctx_req->transportLayerAddress.buffer;
liblte_value_2_bits(sgw_s1u_ip, &tmp_ptr, 32);
uint32_t sgw_s1u_teid = esm_ctx->sgw_s1u_fteid.teid;
srslte::uint32_to_uint8(sgw_s1u_teid, erab_ctx_req->gTP_TEID.buffer);
erab_ctx_req.transport_layer_address.resize(32); // IPv4
asn1::bitstring_utils::from_number(
erab_ctx_req.transport_layer_address.data(), ntohl(esm_ctx->sgw_s1u_fteid.ipv4), 32);
erab_ctx_req.gtp_teid.from_number(esm_ctx->sgw_s1u_fteid.teid);
// 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++) {
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 {
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) {
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 {
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
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");
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) {
// Attach procedure initiated from an attach request
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");
nas_ctx->pack_attach_accept(nas_buffer);
nas_ctx->pack_attach_accept(nas_buffer.get());
// Add nas message to context setup request
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.n_octets = nas_buffer->N_bytes;
erab_ctx_req.nas_pdu_present = true;
erab_ctx_req.nas_pdu.resize(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();
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)) {
if (!m_s1ap->s1ap_tx_pdu(tx_pdu, &ecm_ctx->enb_sri)) {
m_s1ap_log->error("Error sending Initial Context Setup Request.\n");
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;
struct in_addr addr;
addr.s_addr = htonl(sgw_s1u_ip);
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->info("Initial Context -- S1-U TEID 0x%x. IP %s \n", sgw_s1u_teid, inet_ntoa(addr));
m_s1ap_log->console("Initial Context Setup Request -- eNB UE S1AP Id %d, MME UE S1AP Id %d\n",
in_ctxt_req->eNB_UE_S1AP_ID.ENB_UE_S1AP_ID,
in_ctxt_req->MME_UE_S1AP_ID.MME_UE_S1AP_ID);
m_s1ap_log->console("Initial Context Setup Request -- E-RAB id %d\n", erab_ctx_req->e_RAB_ID.E_RAB_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->console("Initial Context Setup Request -- S1-U TEID 0x%x. IP %s \n", sgw_s1u_teid, inet_ntoa(addr));
m_s1ap_log->console("Initial Context Setup Request -- QCI %d \n", erab_ctx_req->e_RABlevelQoSParameters.qCI.QCI);
m_pool->deallocate(reply_buffer);
m_pool->deallocate(nas_buffer);
addr.s_addr = htonl(erab_ctx_req.transport_layer_address.to_number());
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%" PRIx64 ". IP %s \n", erab_ctx_req.gtp_teid.to_number(), inet_ntoa(addr));
m_s1ap_log->info("Initial Context Setup Request -- eNB UE S1AP Id %d, MME UE S1AP Id %" PRIu64 "\n",
in_ctx_req.enb_ue_s1ap_id.value.value,
in_ctx_req.mme_ue_s1ap_id.value.value);
m_s1ap_log->info("Initial Context Setup Request -- E-RAB id %d\n", erab_ctx_req.erab_id);
m_s1ap_log->info("Initial Context Setup Request -- S1-U TEID 0x%" PRIu64 ". IP %s \n",
erab_ctx_req.gtp_teid.to_number(),
inet_ntoa(addr));
m_s1ap_log->info("Initial Context Setup Request -- S1-U TEID 0x%" PRIu64 ". IP %s \n",
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;
}
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);
if (nas_ctx == NULL) {
if (nas_ctx == nullptr) {
m_s1ap_log->error("Could not find UE's context in active UE's map\n");
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;
m_s1ap_log->console("Received Initial Context Setup Response\n");
// Setup E-RABs
for (uint32_t i = 0; i < in_ctxt_resp->E_RABSetupListCtxtSURes.len; i++) {
uint8_t erab_id = in_ctxt_resp->E_RABSetupListCtxtSURes.buffer[i].e_RAB_ID.E_RAB_ID;
for (const asn1::s1ap::protocol_ie_single_container_s<asn1::s1ap::erab_setup_item_ctxt_su_res_ies_o>& ie_container :
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];
if (esm_ctx->state != ERAB_CTX_REQUESTED) {
m_s1ap_log->error("E-RAB requested was not previously requested %d\n", erab_id);
return false;
}
// Mark E-RAB with context setup
esm_ctx->state = ERAB_CTX_SETUP;
// Set the GTP information
uint8_t* bit_ptr = in_ctxt_resp->E_RABSetupListCtxtSURes.buffer[i].transportLayerAddress.buffer;
esm_ctx->enb_fteid.ipv4 = htonl(liblte_bits_2_value(&bit_ptr, 32));
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];
const char* err = inet_ntop(AF_INET, &esm_ctx->enb_fteid.ipv4, enb_addr_str, sizeof(enb_addr_str));
if (err == NULL) {
esm_ctx->enb_fteid.teid = erab_setup_item_ctxt.gtp_teid.to_number();
esm_ctx->enb_fteid.ipv4 = ntohl(erab_setup_item_ctxt.transport_layer_address.to_number());
char enb_addr_str[INET_ADDRSTRLEN + 1] = {};
struct in_addr tmp_addr = {};
tmp_addr.s_addr = esm_ctx->enb_fteid.ipv4;
const char* err = inet_ntop(AF_INET, &tmp_addr, enb_addr_str, INET_ADDRSTRLEN);
if (err == nullptr) {
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 -- 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);
@ -237,19 +242,15 @@ bool s1ap_ctx_mngmt_proc::handle_initial_context_setup_response(
return true;
}
bool s1ap_ctx_mngmt_proc::handle_ue_context_release_request(LIBLTE_S1AP_MESSAGE_UECONTEXTRELEASEREQUEST_STRUCT* ue_rel,
struct sctp_sndrcvinfo* enb_sri,
srslte::byte_buffer_t* reply_buffer,
bool* reply_flag)
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)
{
LIBLTE_S1AP_MESSAGE_UECONTEXTRELEASEREQUEST_STRUCT ue_rel_req;
uint32_t mme_ue_s1ap_id = ue_rel->MME_UE_S1AP_ID.MME_UE_S1AP_ID;
uint32_t mme_ue_s1ap_id = ue_rel.protocol_ies.mme_ue_s1ap_id.value.value;
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);
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->console("No UE context to release found. MME-UE S1AP Id: %d\n", mme_ue_s1ap_id);
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)
{
srslte::byte_buffer_t* reply_buffer = m_pool->allocate();
// 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_UECONTEXTRELEASE;
init->choice_type = LIBLTE_S1AP_INITIATINGMESSAGE_CHOICE_UECONTEXTRELEASECOMMAND;
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->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->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;
}
s1ap_pdu_t tx_pdu;
tx_pdu.set_init_msg().load_info_obj(ASN1_S1AP_ID_UE_CONTEXT_RELEASE);
asn1::s1ap::ue_context_release_cmd_ies_container& ctx_rel_cmd =
tx_pdu.init_msg().value.ue_context_release_cmd().protocol_ies;
ctx_rel_cmd.ue_s1ap_ids.value.set(asn1::s1ap::ue_s1ap_ids_c::types_opts::ue_s1ap_id_pair);
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;
ctx_rel_cmd.cause.value.set(asn1::s1ap::cause_c::types_opts::nas);
ctx_rel_cmd.cause.value.nas().value = asn1::s1ap::cause_nas_opts::options::normal_release;
// 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_pool->deallocate(reply_buffer);
return false;
}
m_pool->deallocate(reply_buffer);
return true;
}
bool s1ap_ctx_mngmt_proc::handle_ue_context_release_complete(
LIBLTE_S1AP_MESSAGE_UECONTEXTRELEASECOMPLETE_STRUCT* rel_comp)
bool s1ap_ctx_mngmt_proc::handle_ue_context_release_complete(const asn1::s1ap::ue_context_release_complete_s& 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->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);
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->console("No UE context to release found. MME-UE S1AP Id: %d\n", mme_ue_s1ap_id);
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->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.
for (int i = 0; i < MAX_ERABS_PER_UE; i++) {
nas_ctx->m_esm_ctx[i].state = ERAB_DEACTIVATED;
for (esm_ctx_t& esm_ctx : nas_ctx->m_esm_ctx) {
esm_ctx.state = ERAB_DEACTIVATED;
}
}

@ -66,13 +66,13 @@ void s1ap_mngmt_proc::init(void)
m_s1ap_args = m_s1ap->m_s1ap_args;
}
bool s1ap_mngmt_proc::handle_s1_setup_request(LIBLTE_S1AP_MESSAGE_S1SETUPREQUEST_STRUCT* msg,
struct sctp_sndrcvinfo* enb_sri,
srslte::byte_buffer_t* reply_buffer,
bool* reply_flag)
bool s1ap_mngmt_proc::handle_s1_setup_request(const asn1::s1ap::s1_setup_request_s& msg,
struct sctp_sndrcvinfo* enb_sri)
{
enb_ctx_t enb_ctx;
LIBLTE_S1AP_S1AP_PDU_STRUCT reply_pdu;
m_s1ap_log->console("Received S1 Setup Request.\n");
m_s1ap_log->info("Received S1 Setup Request.\n");
enb_ctx_t enb_ctx = {};
if (!unpack_s1_setup_request(msg, &enb_ctx)) {
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
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
m_s1ap_log->console("Received S1 Setup Request.\n");
m_s1ap->print_enb_ctx_info(std::string("S1 Setup Request"), enb_ctx);
// Check matching PLMNs
if (enb_ctx.plmn != m_s1ap->get_plmn()) {
m_s1ap_log->console("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 {
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
// TODO replace enb_ctx
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);
}
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->info("Sending S1 Setup Response\n");
}
*reply_flag = true;
return true;
}
/*
* 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];
@ -122,128 +120,105 @@ bool s1ap_mngmt_proc::unpack_s1_setup_request(LIBLTE_S1AP_MESSAGE_S1SETUPREQUEST
uint16_t tac, bplmn;
uint32_t tmp32 = 0;
const asn1::s1ap::s1_setup_request_ies_container& s1_req = msg.protocol_ies;
// eNB Name
enb_ctx->enb_name_present = msg->eNBname_present;
if (msg->eNBname_present) {
bzero(enb_ctx->enb_name, sizeof(enb_ctx->enb_name));
memcpy(enb_ctx->enb_name, &msg->eNBname.buffer, msg->eNBname.n_octets);
enb_ctx->enb_name_present = s1_req.enbname_present;
if (s1_req.enbname_present) {
enb_ctx->enb_name = s1_req.enbname.value.to_string();
}
// eNB Id
bzero(enb_id_bits, sizeof(enb_id_bits));
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);
enb_ctx->enb_id = s1_req.global_enb_id.value.enb_id.macro_enb_id().to_number();
// PLMN Id
((uint8_t*)&plmn)[1] = msg->Global_ENB_ID.pLMNidentity.buffer[0];
((uint8_t*)&plmn)[2] = msg->Global_ENB_ID.pLMNidentity.buffer[1];
((uint8_t*)&plmn)[3] = msg->Global_ENB_ID.pLMNidentity.buffer[2];
((uint8_t*)&plmn)[1] = s1_req.global_enb_id.value.plm_nid[0];
((uint8_t*)&plmn)[2] = s1_req.global_enb_id.value.plm_nid[1];
((uint8_t*)&plmn)[3] = s1_req.global_enb_id.value.plm_nid[2];
enb_ctx->plmn = ntohl(plmn);
srslte::s1ap_plmn_to_mccmnc(enb_ctx->plmn, &enb_ctx->mcc, &enb_ctx->mnc);
// SupportedTAs
enb_ctx->nof_supported_ta = msg->SupportedTAs.len;
for (uint16_t i = 0; i < msg->SupportedTAs.len; i++) {
enb_ctx->nof_supported_ta = s1_req.supported_tas.value.size();
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
((uint8_t*)&enb_ctx->tac[i])[0] = msg->SupportedTAs.buffer[i].tAC.buffer[0];
((uint8_t*)&enb_ctx->tac[i])[1] = msg->SupportedTAs.buffer[i].tAC.buffer[1];
((uint8_t*)&enb_ctx->tac[i])[0] = tas.tac[0];
((uint8_t*)&enb_ctx->tac[i])[1] = tas.tac[1];
enb_ctx->tac[i] = ntohs(enb_ctx->tac[i]);
enb_ctx->nof_supported_bplmns[i] = msg->SupportedTAs.buffer[i].broadcastPLMNs.len;
for (uint16_t j = 0; j < msg->SupportedTAs.buffer[i].broadcastPLMNs.len; j++) {
enb_ctx->nof_supported_bplmns[i] = tas.broadcast_plmns.size();
for (uint16_t j = 0; j < tas.broadcast_plmns.size(); j++) {
// 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])[2] = msg->SupportedTAs.buffer[i].broadcastPLMNs.buffer[j].buffer[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])[1] = tas.broadcast_plmns[j][0];
((uint8_t*)&enb_ctx->bplmns[i][j])[2] = tas.broadcast_plmns[j][1];
((uint8_t*)&enb_ctx->bplmns[i][j])[3] = tas.broadcast_plmns[j][2];
enb_ctx->bplmns[i][j] = ntohl(enb_ctx->bplmns[i][j]);
}
}
// Default Paging DRX
enb_ctx->drx = msg->DefaultPagingDRX.e;
enb_ctx->drx = s1_req.default_paging_drx.value;
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;
bzero(&pdu, sizeof(LIBLTE_S1AP_S1AP_PDU_STRUCT));
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;
s1ap_pdu_t tx_pdu;
tx_pdu.set_unsuccessful_outcome().load_info_obj(ASN1_S1AP_ID_S1_SETUP);
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->CriticalityDiagnostics_present = false;
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;
s1_fail.cause.value.set(asn1::s1ap::cause_c::types_opts::misc);
s1_fail.cause.value.misc().value = cause;
liblte_s1ap_pack_s1ap_pdu(&pdu, (LIBLTE_BYTE_MSG_STRUCT*)msg);
m_s1ap->s1ap_tx_pdu(tx_pdu, enb_sri);
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;
bzero(&pdu, sizeof(LIBLTE_S1AP_S1AP_PDU_STRUCT));
s1ap_pdu_t tx_pdu;
tx_pdu.set_successful_outcome().load_info_obj(ASN1_S1AP_ID_S1_SETUP);
pdu.choice_type = LIBLTE_S1AP_S1AP_PDU_CHOICE_SUCCESSFULOUTCOME;
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;
asn1::s1ap::s1_setup_resp_ies_container& s1_resp = tx_pdu.successful_outcome().value.s1_setup_resp().protocol_ies;
// MME Name
s1_resp->MMEname_present = true;
s1_resp->MMEname.ext = false;
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());
s1_resp.mm_ename_present = true;
s1_resp.mm_ename.value.from_string(s1ap_args.mme_name);
// Served GUMEIs
s1_resp->ServedGUMMEIs.len = 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;
s1_resp.served_gummeis.value.resize(1); // TODO Only one served GUMMEI supported
uint32_t plmn = 0;
srslte::s1ap_mccmnc_to_plmn(s1ap_args.mcc, s1ap_args.mnc, &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];
plmn = htonl(plmn);
serv_gummei->servedGroupIDs.len = 1; // LIBLTE_S1AP_SERVEDGROUPIDS_STRUCT
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];
asn1::s1ap::served_gummeis_item_s& serv_gummei = s1_resp.served_gummeis.value[0];
serv_gummei->servedMMECs.len = 1; // Only one MMEC served
serv_gummei->servedMMECs.buffer[0].buffer[0] = s1ap_args.mme_code;
serv_gummei.served_plmns.resize(1);
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;
s1_resp->MMERelaySupportIndicator_present = false;
s1_resp->CriticalityDiagnostics_present = false;
serv_gummei.served_group_ids.resize(1);
serv_gummei.served_group_ids[0].from_number(htons(s1ap_args.mme_group));
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;
}

@ -88,27 +88,25 @@ void s1ap_nas_transport::init()
m_nas_if.mme = mme::get_instance();
}
bool s1ap_nas_transport::handle_initial_ue_message(LIBLTE_S1AP_MESSAGE_INITIALUEMESSAGE_STRUCT* init_ue,
struct sctp_sndrcvinfo* enb_sri,
srslte::byte_buffer_t* reply_buffer,
bool* reply_flag)
bool s1ap_nas_transport::handle_initial_ue_message(const asn1::s1ap::init_ue_msg_s& init_ue,
struct sctp_sndrcvinfo* enb_sri)
{
bool err, mac_valid;
uint8_t pd, msg_type, sec_hdr_type;
srslte::byte_buffer_t* nas_msg = m_pool->allocate();
memcpy(nas_msg->msg, &init_ue->NAS_PDU.buffer, init_ue->NAS_PDU.n_octets);
nas_msg->N_bytes = 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.protocol_ies.nas_pdu.value.size();
uint64_t imsi = 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);
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));
if (init_ue->S_TMSI_present) {
srslte::uint8_to_uint32(init_ue->S_TMSI.m_TMSI.buffer, &m_tmsi);
if (init_ue.protocol_ies.s_tmsi_present) {
srslte::uint8_to_uint32(init_ue.protocol_ies.s_tmsi.value.m_tmsi.data(), &m_tmsi);
}
switch (msg_type) {
@ -144,20 +142,18 @@ bool s1ap_nas_transport::handle_initial_ue_message(LIBLTE_S1AP_MESSAGE_INITIALUE
return err;
}
bool s1ap_nas_transport::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 s1ap_nas_transport::handle_uplink_nas_transport(const asn1::s1ap::ul_nas_transport_s& ul_xport,
struct sctp_sndrcvinfo* enb_sri)
{
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 mme_ue_s1ap_id = ul_xport->MME_UE_S1AP_ID.MME_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.protocol_ies.mme_ue_s1ap_id.value.value;
bool mac_valid = false;
bool increase_ul_nas_cnt = true;
// Get UE NAS context
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);
return false;
}
@ -169,8 +165,8 @@ bool s1ap_nas_transport::handle_uplink_nas_transport(LIBLTE_S1AP_MESSAGE_UPLINKN
// Parse NAS message header
srslte::byte_buffer_t* nas_msg = m_pool->allocate();
memcpy(nas_msg->msg, &ul_xport->NAS_PDU.buffer, ul_xport->NAS_PDU.n_octets);
nas_msg->N_bytes = 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.protocol_ies.nas_pdu.value.size();
bool msg_encrypted = false;
// Parse the message security header
@ -351,42 +347,21 @@ bool s1ap_nas_transport::send_downlink_nas_transport(uint32_t enb_
mme_ue_s1ap_id,
enb_ue_s1ap_id);
// Allocate Reply buffer
srslte::byte_buffer_t* reply_msg = m_pool->allocate();
// Setup initiating message
LIBLTE_S1AP_S1AP_PDU_STRUCT tx_pdu;
bzero(&tx_pdu, sizeof(LIBLTE_S1AP_S1AP_PDU_STRUCT));
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;
s1ap_pdu_t tx_pdu;
tx_pdu.set_init_msg().load_info_obj(ASN1_S1AP_ID_DL_NAS_TRANSPORT);
// Setup Dw NAS structure
LIBLTE_S1AP_MESSAGE_DOWNLINKNASTRANSPORT_STRUCT* dw_nas = &init->choice.DownlinkNASTransport;
dw_nas->ext = false;
dw_nas->eNB_UE_S1AP_ID.ENB_UE_S1AP_ID = enb_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;
asn1::s1ap::dl_nas_transport_ies_container& dw_nas = tx_pdu.init_msg().value.dl_nas_transport().protocol_ies;
dw_nas.enb_ue_s1ap_id.value = enb_ue_s1ap_id;
dw_nas.mme_ue_s1ap_id.value = mme_ue_s1ap_id;
// 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.n_octets = nas_msg->N_bytes;
// Pack Downlink NAS Transport Message
LIBLTE_ERROR_ENUM err = liblte_s1ap_pack_s1ap_pdu(&tx_pdu, (LIBLTE_BYTE_MSG_STRUCT*)reply_msg);
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);
dw_nas.nas_pdu.value.resize(nas_msg->N_bytes);
memcpy(dw_nas.nas_pdu.value.data(), nas_msg->msg, nas_msg->N_bytes);
// Send Downlink NAS Transport Message
m_s1ap->s1ap_tx_pdu(tx_pdu, &enb_sri);
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);
// 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_PAGING;
init->choice_type = LIBLTE_S1AP_INITIATINGMESSAGE_CHOICE_PAGING;
LIBLTE_S1AP_MESSAGE_PAGING_STRUCT* paging = &init->choice.Paging;
s1ap_pdu_t tx_pdu;
tx_pdu.set_init_msg().load_info_obj(ASN1_S1AP_ID_PAGING);
asn1::s1ap::paging_ies_container& paging = tx_pdu.init_msg().value.paging().protocol_ies;
// Getting UE NAS Context
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
uint16_t ue_index = imsi % 1024; // LIBLTE_S1AP_UEIDENTITYINDEXVALUE_BIT_STRING_LEN == 10
uint8_t* tmp_ptr = paging->UEIdentityIndexValue.buffer;
liblte_value_2_bits(ue_index, &tmp_ptr, 10);
uint16_t ue_index = imsi % 1024;
paging.ue_id_idx_value.value.from_number(ue_index);
// UE Paging Id
paging->UEPagingID.choice_type = LIBLTE_S1AP_UEPAGINGID_CHOICE_S_TMSI;
paging->UEPagingID.choice.s_TMSI.ext = false;
paging->UEPagingID.choice.s_TMSI.mMEC.buffer[0] = m_s1ap->m_s1ap_args.mme_code;
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;
paging.ue_paging_id.value.set_s_tmsi();
paging.ue_paging_id.value.s_tmsi().mmec.from_number(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);
// CMDomain
paging->CNDomain = LIBLTE_S1AP_CNDOMAIN_PS;
paging.cn_domain.value = asn1::s1ap::cn_domain_opts::ps;
// TAI List
paging->TAIList.len = 1;
paging->TAIList.buffer[0].ext = false;
paging->TAIList.buffer[0].tAI.ext = false;
uint32_t plmn = htonl(m_s1ap->get_plmn()); // LIBLTE_S1AP_TBCD_STRING_OCTET_STRING_LEN == 3
paging->TAIList.buffer[0].tAI.pLMNidentity.buffer[0] = ((uint8_t*)&plmn)[1];
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 = htons(m_s1ap->m_s1ap_args.tac); // LIBLTE_S1AP_TAC_OCTET_STRING_LEN == 2
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;
paging.tai_list.value.resize(1);
paging.tai_list.value[0].load_info_obj(ASN1_S1AP_ID_TAI_ITEM);
uint32_t plmn = m_s1ap->get_plmn();
paging.tai_list.value[0].value.tai_item().tai.plm_nid.from_number(plmn);
uint16_t tac = m_s1ap->m_s1ap_args.tac;
paging.tai_list.value[0].value.tai_item().tai.tac.from_number(tac);
// Start T3413
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
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();
it++) {
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_pool->deallocate(reply_buffer);
return false;
}
}

Loading…
Cancel
Save