mirror of https://github.com/pvnis/srsRAN_4G.git
You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
165 lines
5.4 KiB
C++
165 lines
5.4 KiB
C++
6 years ago
|
/**
|
||
|
*
|
||
|
* \section COPYRIGHT
|
||
|
*
|
||
|
* Copyright 2013-2017 Software Radio Systems Limited
|
||
|
*
|
||
|
* \section LICENSE
|
||
|
*
|
||
|
* This file is part of srsLTE.
|
||
|
*
|
||
|
* srsLTE is free software: you can redistribute it and/or modify
|
||
|
* it under the terms of the GNU Affero General Public License as
|
||
|
* published by the Free Software Foundation, either version 3 of
|
||
|
* the License, or (at your option) any later version.
|
||
|
*
|
||
|
* srsLTE is distributed in the hope that it will be useful,
|
||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||
|
* GNU Affero General Public License for more details.
|
||
|
*
|
||
|
* A copy of the GNU Affero General Public License can be found in
|
||
|
* the LICENSE file in the top-level directory of this distribution
|
||
|
* and at http://www.gnu.org/licenses/.
|
||
|
*
|
||
|
*/
|
||
|
#include "srsepc/hdr/mme/s1ap_paging.h"
|
||
|
#include "srsepc/hdr/mme/mme.h"
|
||
|
#include "srsepc/hdr/mme/s1ap.h"
|
||
|
#include "srslte/common/bcd_helpers.h"
|
||
|
#include "srslte/common/int_helpers.h"
|
||
|
|
||
|
namespace srsepc {
|
||
|
|
||
|
s1ap_paging* s1ap_paging::m_instance = NULL;
|
||
|
pthread_mutex_t s1ap_paging_instance_mutex = PTHREAD_MUTEX_INITIALIZER;
|
||
|
|
||
|
s1ap_paging::s1ap_paging()
|
||
|
{
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
s1ap_paging::~s1ap_paging()
|
||
|
{
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
s1ap_paging* s1ap_paging::get_instance(void)
|
||
|
{
|
||
|
pthread_mutex_lock(&s1ap_paging_instance_mutex);
|
||
|
if (NULL == m_instance) {
|
||
|
m_instance = new s1ap_paging();
|
||
|
}
|
||
|
pthread_mutex_unlock(&s1ap_paging_instance_mutex);
|
||
|
return (m_instance);
|
||
|
}
|
||
|
|
||
|
void s1ap_paging::cleanup(void)
|
||
|
{
|
||
|
pthread_mutex_lock(&s1ap_paging_instance_mutex);
|
||
|
if (NULL != m_instance) {
|
||
|
delete m_instance;
|
||
|
m_instance = NULL;
|
||
|
}
|
||
|
pthread_mutex_unlock(&s1ap_paging_instance_mutex);
|
||
|
}
|
||
|
|
||
|
void s1ap_paging::init(void)
|
||
|
{
|
||
|
m_s1ap = s1ap::get_instance();
|
||
|
m_mme = mme::get_instance();
|
||
|
m_s1ap_log = m_s1ap->m_s1ap_log;
|
||
|
m_s1ap_args = m_s1ap->m_s1ap_args;
|
||
|
m_pool = srslte::byte_buffer_pool::get_instance();
|
||
|
}
|
||
|
|
||
|
bool s1ap_paging::send_paging(uint64_t imsi, uint16_t erab_to_setup)
|
||
|
{
|
||
|
m_s1ap_log->info("Preparing to Page UE -- IMSI %lu\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;
|
||
|
|
||
|
// Getting UE NAS Context
|
||
|
nas* nas_ctx = m_s1ap->find_nas_ctx_from_imsi(imsi);
|
||
|
if (nas_ctx == NULL) {
|
||
|
m_s1ap_log->error("Could not find UE to page NAS context\n");
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
// 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);
|
||
|
|
||
|
// 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;
|
||
|
|
||
|
// CMDomain
|
||
|
paging->CNDomain = LIBLTE_S1AP_CNDOMAIN_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;
|
||
|
|
||
|
// Start T3413
|
||
|
if (!nas_ctx->start_timer(T_3413)) {
|
||
|
m_s1ap_log->error("Could not start T3413 -- Aborting paging\n");
|
||
|
// 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)) {
|
||
|
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 true;
|
||
|
}
|
||
|
|
||
|
} // namespace srsepc
|