479 lines
17 KiB
C
479 lines
17 KiB
C
/*
|
|
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
|
|
* contributor license agreements. See the NOTICE file distributed with
|
|
* this work for additional information regarding copyright ownership.
|
|
* The OpenAirInterface Software Alliance licenses this file to You under
|
|
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
|
|
* except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.openairinterface.org/?page_id=698
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*-------------------------------------------------------------------------------
|
|
* For more information about the OpenAirInterface (OAI) Software Alliance:
|
|
* contact@openairinterface.org
|
|
*/
|
|
|
|
/*****************************************************************************
|
|
Eurecom OpenAirInterface 3
|
|
Copyright(c) 2012 Eurecom
|
|
|
|
Source as_process.c
|
|
|
|
Version 0.1
|
|
|
|
Date 2013/04/11
|
|
|
|
Product Access-Stratum sublayer simulator
|
|
|
|
Subsystem AS message processing
|
|
|
|
Author Frederic Maurel
|
|
|
|
Description Defines functions executed by the Access-Stratum sublayer
|
|
upon receiving AS messages from the Non-Access-Stratum.
|
|
|
|
*****************************************************************************/
|
|
|
|
#include "as_process.h"
|
|
#include "nas_process.h"
|
|
|
|
#include "commonDef.h"
|
|
#include "as_data.h"
|
|
|
|
#include <sys/types.h>
|
|
#include <stdio.h> // snprintf
|
|
#include <string.h> // memcpy
|
|
|
|
/****************************************************************************/
|
|
/**************** E X T E R N A L D E F I N I T I O N S ****************/
|
|
/****************************************************************************/
|
|
|
|
/****************************************************************************/
|
|
/******************* L O C A L D E F I N I T I O N S *******************/
|
|
/****************************************************************************/
|
|
|
|
/* Message Sequence Chart Generator's buffer */
|
|
#define MSCGEN_BUFFER_SIZE 1024
|
|
static char _mscgen_buffer[MSCGEN_BUFFER_SIZE];
|
|
|
|
/* Tracking area code */
|
|
#define DEFAULT_TAC 0xCAFE // two byte in hexadecimal format
|
|
|
|
/* Cell identity */
|
|
#define DEFAULT_CI 0x01020304 // four byte in hexadecimal format
|
|
|
|
/* Reference signal received power */
|
|
#define DEFAULT_RSRP 27
|
|
|
|
/* Reference signal received quality */
|
|
#define DEFAULT_RSRQ 55
|
|
|
|
static ssize_t _process_plmn(char* buffer, const plmn_t* plmn, size_t len);
|
|
static int _process_dump(char* buffer, int len, const char* msg, int size);
|
|
|
|
/****************************************************************************/
|
|
/****************** E X P O R T E D F U N C T I O N S ******************/
|
|
/****************************************************************************/
|
|
|
|
/*
|
|
* =============================================================================
|
|
* Functions used to process messages received from the UE NAS process
|
|
* =============================================================================
|
|
*/
|
|
|
|
/*
|
|
* -----------------------------------------------------------------------------
|
|
* Process cell information request message
|
|
* -----------------------------------------------------------------------------
|
|
*/
|
|
int process_cell_info_req(int msg_id, const cell_info_req_t* req,
|
|
cell_info_cnf_t* cnf)
|
|
{
|
|
int index = 0;
|
|
|
|
printf("INFO\t: %s - Process cell information request\n", __FUNCTION__);
|
|
|
|
index += _process_plmn(_mscgen_buffer, &req->plmnID, MSCGEN_BUFFER_SIZE);
|
|
snprintf(_mscgen_buffer + index, MSCGEN_BUFFER_SIZE - index,
|
|
", rat = 0x%x%c", req->rat, '\0');
|
|
printf("[%s][%s][--- Cell Information Request (0x%.4x)\\n%s --->][%s]\n",
|
|
getTime(), _ue_id, msg_id, _mscgen_buffer, _as_id);
|
|
|
|
/* Setup cell information confirm message */
|
|
cnf->errCode = AS_SUCCESS;
|
|
cnf->tac = DEFAULT_TAC;
|
|
cnf->cellID = DEFAULT_CI;
|
|
cnf->rat = AS_EUTRAN;
|
|
cnf->rsrp = DEFAULT_RSRP;
|
|
cnf->rsrq = DEFAULT_RSRQ;
|
|
|
|
snprintf(_mscgen_buffer, MSCGEN_BUFFER_SIZE,
|
|
"tac = 0x%.4x, cellID = 0x%.8x, rat = 0x%x, RSRQ = %u, RSRP = %u%c",
|
|
cnf->tac, cnf->cellID, cnf->rat, cnf->rsrq, cnf->rsrp, '\0');
|
|
printf("[%s][%s][--- Cell Information Confirm (0x%.4x)\\n%s --->][%s]\n",
|
|
getTime(), _as_id, AS_CELL_INFO_CNF, _mscgen_buffer, _ue_id);
|
|
|
|
printf("INFO\t: %s - Send cell informtion confirm\n", __FUNCTION__);
|
|
return (AS_CELL_INFO_CNF);
|
|
}
|
|
|
|
/*
|
|
* -----------------------------------------------------------------------------
|
|
* Process NAS signalling connection establishment request message
|
|
* -----------------------------------------------------------------------------
|
|
*/
|
|
int process_nas_establish_req(int msg_id, const nas_establish_req_t* req,
|
|
nas_establish_ind_t* ind,
|
|
nas_establish_cnf_t* cnf)
|
|
{
|
|
int bytes;
|
|
|
|
printf("INFO\t: %s - Process NAS signalling connection establishment "
|
|
"request\n", __FUNCTION__);
|
|
|
|
snprintf(_mscgen_buffer, MSCGEN_BUFFER_SIZE,
|
|
"cause = %s, type = %s, tmsi = {MMEcode = %d, m_tmsi = %u}%c",
|
|
rrcCause(req->cause), rrcType(req->type),
|
|
req->s_tmsi.MMEcode, req->s_tmsi.m_tmsi, '\0');
|
|
printf("[%s][%s][--- NAS Signalling Connection Establishment Request "
|
|
"(0x%.4x)\\n%s --->][%s]\n",
|
|
getTime(), _ue_id, msg_id, _mscgen_buffer, _as_id);
|
|
|
|
_process_dump(_mscgen_buffer, MSCGEN_BUFFER_SIZE,
|
|
(char*)req->initialNasMsg.data, req->initialNasMsg.length);
|
|
printf("[%s][%s][%s]\n", _ue_id, _as_id, _mscgen_buffer);
|
|
|
|
/* Process initial NAS message */
|
|
bytes = nas_process(_mscgen_buffer, MSCGEN_BUFFER_SIZE,
|
|
(char*)req->initialNasMsg.data,
|
|
req->initialNasMsg.length);
|
|
|
|
if (bytes < 0) {
|
|
printf("[%s][%s][--- NAS Signalling Connection Establishment "
|
|
"Indication (0x%.4x)\\ntac = 0x%.4x\\n%s ---x][%s]\n", getTime(),
|
|
_as_id, AS_NAS_ESTABLISH_IND, ind->tac, _mscgen_buffer, _mme_id);
|
|
/* Setup NAS signalling connection establishment confirmation message */
|
|
cnf->errCode = AS_TERMINATED_AS;
|
|
return (0);
|
|
}
|
|
|
|
/* Setup NAS signalling connection establishment indication message */
|
|
ind->UEid = 1; // Valid UEid starts at index 1
|
|
ind->tac = DEFAULT_TAC;
|
|
|
|
if (req->initialNasMsg.length > 0) {
|
|
ind->initialNasMsg.data = malloc(req->initialNasMsg.length);
|
|
|
|
if (ind->initialNasMsg.data) {
|
|
memcpy(ind->initialNasMsg.data, req->initialNasMsg.data,
|
|
req->initialNasMsg.length);
|
|
ind->initialNasMsg.length = req->initialNasMsg.length;
|
|
}
|
|
}
|
|
|
|
// Attach_Request.messagetype = WRONG_MESSAGE_TYPE
|
|
//ind->initialNasMsg.data[1] = 0x47; // MME DEBUG (Send EMM status)
|
|
|
|
/* Setup NAS signalling connection establishment confirmation message */
|
|
cnf->errCode = AS_SUCCESS;
|
|
// Transmission failure of Attach Request message
|
|
//cnf->errCode = AS_FAILURE; // UE DEBUG
|
|
|
|
printf("[%s][%s][--- NAS Signalling Connection Establishment Indication "
|
|
"(0x%.4x)\\nUEid = %u, tac = 0x%.4x\\n%s --->][%s]\n", getTime(),
|
|
_as_id, AS_NAS_ESTABLISH_IND, ind->UEid, ind->tac, _mscgen_buffer, _mme_id);
|
|
|
|
printf("INFO\t: %s - Send NAS signalling connection establishment "
|
|
"indication\n", __FUNCTION__);
|
|
return (AS_NAS_ESTABLISH_IND);
|
|
}
|
|
|
|
/*
|
|
* -----------------------------------------------------------------------------
|
|
* Process Uplink data transfer request message
|
|
* -----------------------------------------------------------------------------
|
|
*/
|
|
int process_ul_info_transfer_req(int msg_id, const ul_info_transfer_req_t* req,
|
|
ul_info_transfer_ind_t* ind,
|
|
ul_info_transfer_cnf_t* cnf)
|
|
{
|
|
int bytes;
|
|
|
|
printf("INFO\t: %s - Process uplink data transfer request\n", __FUNCTION__);
|
|
|
|
snprintf(_mscgen_buffer, MSCGEN_BUFFER_SIZE,
|
|
"tmsi = {MMEcode = %d, m_tmsi = %u}%c",
|
|
req->s_tmsi.MMEcode, req->s_tmsi.m_tmsi, '\0');
|
|
printf("[%s][%s][--- Uplink Information Request "
|
|
"(0x%.4x)\\n%s --->][%s]\n",
|
|
getTime(), _ue_id, msg_id, _mscgen_buffer, _as_id);
|
|
|
|
_process_dump(_mscgen_buffer, MSCGEN_BUFFER_SIZE,
|
|
(char*)req->nasMsg.data, req->nasMsg.length);
|
|
printf("[%s][%s][%s]\n", _ue_id, _as_id, _mscgen_buffer);
|
|
|
|
/* Process NAS message */
|
|
bytes = nas_process(_mscgen_buffer, MSCGEN_BUFFER_SIZE,
|
|
(char*)req->nasMsg.data,
|
|
req->nasMsg.length);
|
|
|
|
if (bytes < 0) {
|
|
printf("[%s][%s][--- Uplink Information Indication "
|
|
"(0x%.4x)\\n%s ---x][%s]\n", getTime(),
|
|
_as_id, AS_UL_INFO_TRANSFER_IND, _mscgen_buffer, _mme_id);
|
|
/* Setup uplink information confirmation message */
|
|
cnf->errCode = AS_TERMINATED_AS;
|
|
return (0);
|
|
}
|
|
|
|
/* Setup uplink information indication message */
|
|
ind->UEid = 1; // Valid UEid starts at index 1
|
|
|
|
if (req->nasMsg.length > 0) {
|
|
ind->nasMsg.data = malloc(req->nasMsg.length);
|
|
|
|
if (ind->nasMsg.data) {
|
|
memcpy(ind->nasMsg.data, req->nasMsg.data, req->nasMsg.length);
|
|
ind->nasMsg.length = req->nasMsg.length;
|
|
}
|
|
}
|
|
|
|
/* Setup uplink information confirmation message */
|
|
cnf->UEid = 0;
|
|
cnf->errCode = AS_SUCCESS;
|
|
|
|
printf("[%s][%s][--- Uplink Information Indication "
|
|
"(0x%.4x), UEid = %u\\n%s --->][%s]\n", getTime(),
|
|
_as_id, AS_UL_INFO_TRANSFER_IND, ind->UEid, _mscgen_buffer, _mme_id);
|
|
|
|
printf("INFO\t: %s - Send uplink data transfer indication\n", __FUNCTION__);
|
|
return (AS_UL_INFO_TRANSFER_IND);
|
|
}
|
|
|
|
/*
|
|
* -----------------------------------------------------------------------------
|
|
* Process NAS signalling connection release request message
|
|
* -----------------------------------------------------------------------------
|
|
*/
|
|
int process_nas_release_req(int msg_id, const nas_release_req_t* req)
|
|
{
|
|
printf("INFO\t: %s - Process NAS signalling connection release request\n",
|
|
__FUNCTION__);
|
|
|
|
printf("[%s][%s][--- NAS Signalling Release Request "
|
|
"(0x%.4x), tmsi = {MMEcode = %d, m_tmsi = %u}, "
|
|
"cause = %s (%u) --->][%s]\n", getTime(), _ue_id, msg_id,
|
|
req->s_tmsi.MMEcode, req->s_tmsi.m_tmsi,
|
|
rrcReleaseCause(req->cause), req->cause, _as_id);
|
|
return (AS_NAS_RELEASE_REQ);
|
|
}
|
|
|
|
/*
|
|
* =============================================================================
|
|
* Functions used to process messages received from the MME NAS process
|
|
* =============================================================================
|
|
*/
|
|
|
|
/*
|
|
* -----------------------------------------------------------------------------
|
|
* Process NAS signalling connection establishment response message
|
|
* -----------------------------------------------------------------------------
|
|
*/
|
|
int process_nas_establish_rsp(int msg_id, const nas_establish_rsp_t* rsp,
|
|
nas_establish_cnf_t* cnf)
|
|
{
|
|
int bytes;
|
|
|
|
printf("INFO\t: %s - Process NAS signalling connection establishment "
|
|
"response\n", __FUNCTION__);
|
|
|
|
printf("[%s][%s][--- NAS Signalling Connection Establishment "
|
|
"Response (0x%.4x)\\nerrCode = %s, UEid = %u --->][%s]\n",
|
|
getTime(), _mme_id, msg_id,
|
|
rrcErrCode(rsp->errCode), rsp->UEid, _as_id);
|
|
|
|
_process_dump(_mscgen_buffer, MSCGEN_BUFFER_SIZE,
|
|
(char*)rsp->nasMsg.data, rsp->nasMsg.length);
|
|
printf("[%s][%s][%s]\n", _mme_id, _as_id, _mscgen_buffer);
|
|
|
|
// Discard Attach Accept message
|
|
//return (0); // UE DEBUG
|
|
|
|
/* Process initial NAS message */
|
|
bytes = nas_process(_mscgen_buffer, MSCGEN_BUFFER_SIZE,
|
|
(char*)rsp->nasMsg.data,
|
|
rsp->nasMsg.length);
|
|
|
|
if (bytes < 0) {
|
|
printf("[%s][%s][--- NAS Signalling Connection Establishment "
|
|
"Confirm (0x%.4x)\\n%s ---x][%s]\n", getTime(),
|
|
_as_id, AS_NAS_ESTABLISH_CNF, _mscgen_buffer, _ue_id);
|
|
return (0);
|
|
}
|
|
|
|
/* Setup NAS signalling connection establishment confirm message */
|
|
cnf->errCode = rsp->errCode;
|
|
|
|
if (rsp->nasMsg.length > 0) {
|
|
cnf->nasMsg.data = malloc(rsp->nasMsg.length);
|
|
|
|
if (cnf->nasMsg.data) {
|
|
memcpy(cnf->nasMsg.data, rsp->nasMsg.data,
|
|
rsp->nasMsg.length);
|
|
cnf->nasMsg.length = rsp->nasMsg.length;
|
|
}
|
|
}
|
|
|
|
printf("[%s][%s][--- NAS Signalling Connection Establishment "
|
|
"Confirm (0x%.4x)\\n%s --->][%s]\n", getTime(),
|
|
_as_id, AS_NAS_ESTABLISH_CNF, _mscgen_buffer, _ue_id);
|
|
|
|
printf("INFO\t: %s - Send NAS signalling connection establishment "
|
|
"confirm\n", __FUNCTION__);
|
|
return (AS_NAS_ESTABLISH_CNF);
|
|
}
|
|
|
|
/*
|
|
* -----------------------------------------------------------------------------
|
|
* Process Downlink data transfer request message
|
|
* -----------------------------------------------------------------------------
|
|
*/
|
|
int process_dl_info_transfer_req(int msg_id, const dl_info_transfer_req_t* req,
|
|
dl_info_transfer_ind_t* ind,
|
|
dl_info_transfer_cnf_t* cnf)
|
|
{
|
|
int bytes;
|
|
|
|
printf("INFO\t: %s - Process downlink data transfer request\n",
|
|
__FUNCTION__);
|
|
|
|
printf("[%s][%s][--- Downlink Information Request "
|
|
"(0x%.4x), UEid = %u --->][%s]\n",
|
|
getTime(), _mme_id, msg_id, req->UEid, _as_id);
|
|
|
|
_process_dump(_mscgen_buffer, MSCGEN_BUFFER_SIZE,
|
|
(char*)req->nasMsg.data, req->nasMsg.length);
|
|
printf("[%s][%s][%s]\n", _mme_id, _as_id, _mscgen_buffer);
|
|
|
|
/* Process NAS message */
|
|
bytes = nas_process(_mscgen_buffer, MSCGEN_BUFFER_SIZE,
|
|
(char*)req->nasMsg.data,
|
|
req->nasMsg.length);
|
|
|
|
if (bytes < 0) {
|
|
printf("[%s][%s][--- Downlink Information Indication "
|
|
"(0x%.4x)\\n%s ---x][%s]\n", getTime(),
|
|
_as_id, AS_DL_INFO_TRANSFER_IND, _mscgen_buffer, _ue_id);
|
|
/* Setup downlink information confirmation message */
|
|
cnf->UEid = req->UEid;
|
|
cnf->errCode = AS_TERMINATED_AS;
|
|
return (0);
|
|
}
|
|
|
|
/* Setup downlink information indication message */
|
|
if (req->nasMsg.length > 0) {
|
|
ind->nasMsg.data = malloc(req->nasMsg.length);
|
|
|
|
if (ind->nasMsg.data) {
|
|
memcpy(ind->nasMsg.data, req->nasMsg.data, req->nasMsg.length);
|
|
ind->nasMsg.length = req->nasMsg.length;
|
|
}
|
|
}
|
|
|
|
/* Setup downlink information confirmation message */
|
|
cnf->UEid = req->UEid;
|
|
cnf->errCode = AS_SUCCESS;
|
|
|
|
//if (req->nasMsg.data[1] == 0x55) {
|
|
// Transmission failure of identification request message
|
|
// cnf->errCode = AS_FAILURE; // MME DEBUG
|
|
// Discard identification request message
|
|
// return (0); // MME DEBUG
|
|
//}
|
|
|
|
printf("[%s][%s][--- Downlink Information Indication "
|
|
"(0x%.4x)\\n%s --->][%s]\n", getTime(),
|
|
_as_id, AS_DL_INFO_TRANSFER_IND, _mscgen_buffer, _ue_id);
|
|
|
|
printf("INFO\t: %s - Send downlink data transfer indication\n", __FUNCTION__);
|
|
return (AS_DL_INFO_TRANSFER_IND);
|
|
}
|
|
|
|
/*
|
|
* -----------------------------------------------------------------------------
|
|
* Process NAS signalling connection release indication message
|
|
* -----------------------------------------------------------------------------
|
|
*/
|
|
int process_nas_release_ind(int msg_id, const nas_release_req_t* req,
|
|
nas_release_ind_t* ind)
|
|
{
|
|
printf("INFO\t: %s - Process NAS signalling connection release request\n",
|
|
__FUNCTION__);
|
|
|
|
printf("[%s][%s][--- NAS Signalling Connection Release Request "
|
|
"(0x%.4x), UEid = %u, cause = %s (%u) --->][%s]\n",
|
|
getTime(), _mme_id, msg_id, req->UEid,
|
|
rrcReleaseCause(req->cause), req->cause, _as_id);
|
|
|
|
/* Forward NAS release indication to the UE */
|
|
ind->cause = req->cause;
|
|
printf("[%s][%s][--- NAS Signalling Connection Release Indication "
|
|
"(0x%.4x), cause = %s (%u) --->][%s]\n",
|
|
getTime(), _as_id, msg_id, rrcReleaseCause(req->cause),
|
|
ind->cause, _ue_id);
|
|
|
|
printf("INFO\t: %s - Send NAS signalling connection release indication\n",
|
|
__FUNCTION__);
|
|
return (AS_NAS_RELEASE_IND);
|
|
}
|
|
|
|
/****************************************************************************/
|
|
/********************* L O C A L F U N C T I O N S *********************/
|
|
/****************************************************************************/
|
|
|
|
/*
|
|
* -----------------------------------------------------------------------------
|
|
* Display PLMN identity
|
|
* -----------------------------------------------------------------------------
|
|
*/
|
|
static ssize_t _process_plmn(char* buffer, const plmn_t* plmn, size_t len)
|
|
{
|
|
int index = 0;
|
|
index += snprintf(buffer + index, len - index, "plmnID = %u%u%u%u%u",
|
|
plmn->MCCdigit1, plmn->MCCdigit2, plmn->MCCdigit3,
|
|
plmn->MNCdigit1, plmn->MNCdigit2);
|
|
|
|
if ( (index < len) && (plmn->MNCdigit3 != 0xf) ) {
|
|
index += snprintf(buffer + index, len - index, "%u", plmn->MNCdigit3);
|
|
}
|
|
|
|
return (index);
|
|
}
|
|
|
|
/*
|
|
* -----------------------------------------------------------------------------
|
|
* Message dump utility
|
|
* -----------------------------------------------------------------------------
|
|
*/
|
|
static int _process_dump(char* buffer, int len, const char* msg, int size)
|
|
{
|
|
int index = 0;
|
|
|
|
for (int i = 0; i < size; i++) {
|
|
if ( (i%16) == 0 ) index += snprintf(buffer + index,
|
|
len - index, "\\n");
|
|
|
|
index += snprintf(buffer + index, len - index,
|
|
" %.2hhx", (unsigned char)msg[i]);
|
|
}
|
|
|
|
buffer[index] = '\0';
|
|
return (index);
|
|
}
|