- Fixed initial tac/mcc/mnc
- Trigger a dummy initial ue message when receiving s1 setup response - Added new S1AP <-> RRC messages - Fixed almost all S1AP messages to integrate ITTI git-svn-id: http://svn.eurecom.fr/openair4G/trunk@4347 818b1a75-f10b-46b9-bf7c-635c3b92a50f
This commit is contained in:
@@ -421,12 +421,6 @@ struct s1ap_message_s;
|
|||||||
|
|
||||||
/** \brief Function callback prototype.
|
/** \brief Function callback prototype.
|
||||||
**/
|
**/
|
||||||
// typedef int (*s1ap_message_decoded_callback)(
|
|
||||||
// eNB_mme_desc_t *eNB_desc_p,
|
|
||||||
// sctp_queue_item_t *packet_p,
|
|
||||||
// struct s1ap_message_s *message_p
|
|
||||||
// );
|
|
||||||
|
|
||||||
typedef int (*s1ap_message_decoded_callback)(
|
typedef int (*s1ap_message_decoded_callback)(
|
||||||
uint32_t assoc_id,
|
uint32_t assoc_id,
|
||||||
uint32_t stream,
|
uint32_t stream,
|
||||||
|
|||||||
+7
-232
@@ -55,69 +55,12 @@
|
|||||||
|
|
||||||
#include "s1ap_eNB_itti_messaging.h"
|
#include "s1ap_eNB_itti_messaging.h"
|
||||||
|
|
||||||
#include "sctp_primitives_client.h"
|
|
||||||
|
|
||||||
#include "assertions.h"
|
#include "assertions.h"
|
||||||
#include "conversions.h"
|
#include "conversions.h"
|
||||||
|
|
||||||
s1ap_eNB_internal_data_t s1ap_eNB_internal_data;
|
|
||||||
|
|
||||||
static int s1ap_eNB_generate_s1_setup_request(
|
static int s1ap_eNB_generate_s1_setup_request(
|
||||||
s1ap_eNB_instance_t *instance_p, s1ap_eNB_mme_data_t *s1ap_mme_data_p);
|
s1ap_eNB_instance_t *instance_p, s1ap_eNB_mme_data_t *s1ap_mme_data_p);
|
||||||
|
|
||||||
RB_GENERATE(s1ap_mme_map, s1ap_eNB_mme_data_s, entry, s1ap_eNB_compare_assoc_id);
|
|
||||||
|
|
||||||
inline int s1ap_eNB_compare_assoc_id(
|
|
||||||
struct s1ap_eNB_mme_data_s *p1, struct s1ap_eNB_mme_data_s *p2)
|
|
||||||
{
|
|
||||||
if (p1->assoc_id == -1) {
|
|
||||||
if (p1->cnx_id < p2->cnx_id) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
if (p1->cnx_id > p2->cnx_id) {
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (p1->assoc_id < p2->assoc_id) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
if (p1->assoc_id > p2->assoc_id) {
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Matching reference */
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline struct s1ap_eNB_mme_data_s *s1ap_eNB_get_MME(
|
|
||||||
s1ap_eNB_instance_t *instance_p,
|
|
||||||
int32_t assoc_id, uint16_t cnx_id)
|
|
||||||
{
|
|
||||||
struct s1ap_eNB_mme_data_s temp;
|
|
||||||
struct s1ap_eNB_mme_data_s *found;
|
|
||||||
|
|
||||||
memset(&temp, 0, sizeof(struct s1ap_eNB_mme_data_s));
|
|
||||||
|
|
||||||
temp.assoc_id = assoc_id;
|
|
||||||
temp.cnx_id = cnx_id;
|
|
||||||
|
|
||||||
if (instance_p == NULL) {
|
|
||||||
STAILQ_FOREACH(instance_p, &s1ap_eNB_internal_data.s1ap_eNB_instances_head,
|
|
||||||
s1ap_eNB_entries)
|
|
||||||
{
|
|
||||||
found = RB_FIND(s1ap_mme_map, &instance_p->s1ap_mme_head, &temp);
|
|
||||||
if (found != NULL) {
|
|
||||||
return found;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
return RB_FIND(s1ap_mme_map, &instance_p->s1ap_mme_head, &temp);
|
|
||||||
}
|
|
||||||
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t s1ap_generate_eNB_id(void)
|
uint32_t s1ap_generate_eNB_id(void)
|
||||||
{
|
{
|
||||||
char *out;
|
char *out;
|
||||||
@@ -137,55 +80,6 @@ uint32_t s1ap_generate_eNB_id(void)
|
|||||||
return eNB_id;
|
return eNB_id;
|
||||||
}
|
}
|
||||||
|
|
||||||
// int s1ap_run(eNB_mme_desc_t *eNB_desc_p)
|
|
||||||
// {
|
|
||||||
// int ret = 0;
|
|
||||||
// struct s1ap_eNB_mme_data_s *mme_p;
|
|
||||||
//
|
|
||||||
// DevAssert(eNB_desc_p != NULL);
|
|
||||||
//
|
|
||||||
// RB_FOREACH(mme_p, s1ap_mme_map, &eNB_desc_p->s1ap_mme_head) {
|
|
||||||
// struct sctp_queue_item_s *item_p;
|
|
||||||
//
|
|
||||||
// /* Run the SCTP part for each MME */
|
|
||||||
// sctp_run(&mme_p->sctp_data);
|
|
||||||
//
|
|
||||||
// S1AP_DEBUG("Entering s1ap_run for eNB %d: %d packet(s) to handle\n",
|
|
||||||
// eNB_desc_p->eNB_id, mme_p->sctp_data.queue_length);
|
|
||||||
//
|
|
||||||
// /* Handle every message in the queue */
|
|
||||||
// TAILQ_FOREACH(item_p, &mme_p->sctp_data.sctp_queue, entry) {
|
|
||||||
// /* Handle the message in S1AP */
|
|
||||||
// s1ap_eNB_handle_message(eNB_desc_p, item_p);
|
|
||||||
// /* Remove the packet from the list and update data */
|
|
||||||
// TAILQ_REMOVE(&mme_p->sctp_data.sctp_queue, item_p, entry);
|
|
||||||
// ret += item_p->length;
|
|
||||||
// mme_p->sctp_data.queue_size -= item_p->length;
|
|
||||||
// mme_p->sctp_data.queue_length--;
|
|
||||||
// /* Deallocate memory as the message has been handled */
|
|
||||||
// free(item_p->buffer);
|
|
||||||
// free(item_p);
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// return ret;
|
|
||||||
// }
|
|
||||||
|
|
||||||
static s1ap_eNB_instance_t *s1ap_eNB_get_instance(uint8_t mod_id)
|
|
||||||
{
|
|
||||||
s1ap_eNB_instance_t *temp = NULL;
|
|
||||||
|
|
||||||
STAILQ_FOREACH(temp, &s1ap_eNB_internal_data.s1ap_eNB_instances_head,
|
|
||||||
s1ap_eNB_entries)
|
|
||||||
{
|
|
||||||
if (temp->mod_id == mod_id) {
|
|
||||||
/* Matching occurence */
|
|
||||||
return temp;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void s1ap_eNB_register_mme(s1ap_eNB_instance_t *instance_p,
|
static void s1ap_eNB_register_mme(s1ap_eNB_instance_t *instance_p,
|
||||||
net_ip_address_t *mme_ip_address,
|
net_ip_address_t *mme_ip_address,
|
||||||
net_ip_address_t *local_ip_addr)
|
net_ip_address_t *local_ip_addr)
|
||||||
@@ -211,9 +105,8 @@ static void s1ap_eNB_register_mme(s1ap_eNB_instance_t *instance_p,
|
|||||||
s1ap_mme_data_p = calloc(1, sizeof(*s1ap_mme_data_p));
|
s1ap_mme_data_p = calloc(1, sizeof(*s1ap_mme_data_p));
|
||||||
DevAssert(s1ap_mme_data_p != NULL);
|
DevAssert(s1ap_mme_data_p != NULL);
|
||||||
|
|
||||||
s1ap_mme_data_p->cnx_id = s1ap_eNB_internal_data.global_cnx_id;
|
s1ap_mme_data_p->cnx_id = s1ap_eNB_fetch_add_global_cnx_id();
|
||||||
sctp_new_association_req_p->ulp_cnx_id = s1ap_mme_data_p->cnx_id;
|
sctp_new_association_req_p->ulp_cnx_id = s1ap_mme_data_p->cnx_id;
|
||||||
s1ap_eNB_internal_data.global_cnx_id++;
|
|
||||||
|
|
||||||
s1ap_mme_data_p->assoc_id = -1;
|
s1ap_mme_data_p->assoc_id = -1;
|
||||||
s1ap_mme_data_p->s1ap_eNB_instance = instance_p;
|
s1ap_mme_data_p->s1ap_eNB_instance = instance_p;
|
||||||
@@ -257,8 +150,8 @@ void s1ap_eNB_handle_register_eNB(s1ap_register_eNB_t *s1ap_register_eNB)
|
|||||||
new_instance->mnc = s1ap_register_eNB->mnc;
|
new_instance->mnc = s1ap_register_eNB->mnc;
|
||||||
new_instance->default_drx = s1ap_register_eNB->default_drx;
|
new_instance->default_drx = s1ap_register_eNB->default_drx;
|
||||||
|
|
||||||
STAILQ_INSERT_TAIL(&s1ap_eNB_internal_data.s1ap_eNB_instances_head,
|
/* Add the new instance to the list of eNB (meaningfull in virtual mode) */
|
||||||
new_instance, s1ap_eNB_entries);
|
s1ap_eNB_insert_new_instance(new_instance);
|
||||||
|
|
||||||
S1AP_DEBUG("Registered new eNB with mod_id %u and %s eNB id %u\n",
|
S1AP_DEBUG("Registered new eNB with mod_id %u and %s eNB id %u\n",
|
||||||
s1ap_register_eNB->mod_id,
|
s1ap_register_eNB->mod_id,
|
||||||
@@ -322,8 +215,7 @@ void *s1ap_eNB_task(void *arg)
|
|||||||
|
|
||||||
S1AP_DEBUG("Starting S1AP layer\n");
|
S1AP_DEBUG("Starting S1AP layer\n");
|
||||||
|
|
||||||
memset(&s1ap_eNB_internal_data, 0, sizeof(s1ap_eNB_internal_data));
|
s1ap_eNB_prepare_internal_data();
|
||||||
STAILQ_INIT(&s1ap_eNB_internal_data.s1ap_eNB_instances_head);
|
|
||||||
|
|
||||||
itti_mark_task_ready(TASK_S1AP);
|
itti_mark_task_ready(TASK_S1AP);
|
||||||
|
|
||||||
@@ -348,6 +240,9 @@ void *s1ap_eNB_task(void *arg)
|
|||||||
case SCTP_DATA_IND: {
|
case SCTP_DATA_IND: {
|
||||||
s1ap_eNB_handle_sctp_data_ind(&received_msg->msg.sctp_data_ind);
|
s1ap_eNB_handle_sctp_data_ind(&received_msg->msg.sctp_data_ind);
|
||||||
} break;
|
} break;
|
||||||
|
case S1AP_NAS_FIRST_REQ: {
|
||||||
|
s1ap_eNB_handle_nas_first_req(&received_msg->msg.s1ap_nas_first_req);
|
||||||
|
} break;
|
||||||
default:
|
default:
|
||||||
S1AP_ERROR("Received unhandled message with id %d\n",
|
S1AP_ERROR("Received unhandled message with id %d\n",
|
||||||
received_msg->header.messageId);
|
received_msg->header.messageId);
|
||||||
@@ -418,123 +313,3 @@ static int s1ap_eNB_generate_s1_setup_request(
|
|||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
// int s1ap_eNB_generate_initial_UE_message(eNB_mme_desc_t *eNB_desc_p,
|
|
||||||
// s1ap_nas_first_req_t nas_req_p)
|
|
||||||
// {
|
|
||||||
// s1ap_message message;
|
|
||||||
// struct s1ap_eNB_mme_data_s *mme_desc_p;
|
|
||||||
// struct s1ap_eNB_ue_context_s *ue_desc_p;
|
|
||||||
// InitialUEMessageIEs_t *initial_ue_message_p;
|
|
||||||
//
|
|
||||||
// uint8_t *buffer;
|
|
||||||
// uint32_t length;
|
|
||||||
//
|
|
||||||
// DevAssert(eNB_desc_p != NULL);
|
|
||||||
//
|
|
||||||
// memset(&message, 0, sizeof(s1ap_message));
|
|
||||||
//
|
|
||||||
// message.direction = S1AP_PDU_PR_initiatingMessage;
|
|
||||||
// message.procedureCode = ProcedureCode_id_initialUEMessage;
|
|
||||||
//
|
|
||||||
// initial_ue_message_p = &message.msg.initialUEMessageIEs;
|
|
||||||
//
|
|
||||||
// /* Select the MME corresponding to the provided GUMMEI.
|
|
||||||
// * If no MME corresponds to the GUMMEI, the function selects the MME with the
|
|
||||||
// * highest capacity.
|
|
||||||
// * In case eNB has no MME associated, the eNB should inform RRC and discard
|
|
||||||
// * this request.
|
|
||||||
// */
|
|
||||||
// if (nas_req_p.ue_identity.present == GUMMEI_PROVIDED) {
|
|
||||||
// mme_desc_p = s1ap_eNB_nnsf_select_mme_by_gummei(
|
|
||||||
// eNB_desc_p,
|
|
||||||
// nas_req_p.establishment_cause, nas_req_p.ue_identity.identity.gummei);
|
|
||||||
// } else {
|
|
||||||
// mme_desc_p = s1ap_eNB_nnsf_select_mme_by_mme_code(
|
|
||||||
// eNB_desc_p,
|
|
||||||
// nas_req_p.establishment_cause, nas_req_p.ue_identity.identity.s_tmsi.mme_code);
|
|
||||||
// }
|
|
||||||
// if (mme_desc_p == NULL) {
|
|
||||||
// S1AP_WARN("No MME is associated to the eNB\n");
|
|
||||||
// // TODO: Inform RRC
|
|
||||||
// return -1;
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// /* The eNB should allocate a unique eNB UE S1AP ID for this UE. The value
|
|
||||||
// * will be used for the duration of the connectivity.
|
|
||||||
// */
|
|
||||||
// if ((ue_desc_p = s1ap_eNB_allocate_new_UE_context()) == NULL) {
|
|
||||||
// return -1;
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// /* Keep a reference to the selected MME */
|
|
||||||
// ue_desc_p->mme_ref = mme_desc_p;
|
|
||||||
// ue_desc_p->rnti = nas_req_p.rnti;
|
|
||||||
//
|
|
||||||
// do {
|
|
||||||
// struct s1ap_eNB_ue_context_s *collision_p;
|
|
||||||
//
|
|
||||||
// /* Peek a random value for the eNB_ue_s1ap_id */
|
|
||||||
// ue_desc_p->eNB_ue_s1ap_id = (random() + random()) & 0x00ffffff;
|
|
||||||
// if ((collision_p = RB_INSERT(s1ap_ue_map, &eNB_desc_p->s1ap_ue_head, ue_desc_p))
|
|
||||||
// == NULL) {
|
|
||||||
// /* Break the loop as the id is not already used by another UE */
|
|
||||||
// break;
|
|
||||||
// }
|
|
||||||
// } while(1);
|
|
||||||
//
|
|
||||||
// initial_ue_message_p->eNB_UE_S1AP_ID = ue_desc_p->eNB_ue_s1ap_id;
|
|
||||||
// /* Prepare the NAS PDU */
|
|
||||||
// initial_ue_message_p->nas_pdu.buf = nas_req_p.nas_pdu.buffer;
|
|
||||||
// initial_ue_message_p->nas_pdu.size = nas_req_p.nas_pdu.length;
|
|
||||||
//
|
|
||||||
// /* Set the establishment cause according to those provided by RRC */
|
|
||||||
// DevCheck(nas_req_p.establishment_cause <= RRC_CAUSE_MAX,
|
|
||||||
// nas_req_p.establishment_cause, 0, 0);
|
|
||||||
// initial_ue_message_p->rrC_Establishment_Cause = nas_req_p.establishment_cause;
|
|
||||||
//
|
|
||||||
// if (nas_req_p.ue_identity.present == S_TMSI_PROVIDED) {
|
|
||||||
// initial_ue_message_p->presenceMask |= INITIALUEMESSAGEIES_S_TMSI_PRESENT;
|
|
||||||
//
|
|
||||||
// MME_CODE_TO_OCTET_STRING(nas_req_p.ue_identity.identity.s_tmsi.mme_code,
|
|
||||||
// &initial_ue_message_p->s_tmsi.mMEC);
|
|
||||||
// M_TMSI_TO_OCTET_STRING(nas_req_p.ue_identity.identity.s_tmsi.m_tmsi,
|
|
||||||
// &initial_ue_message_p->s_tmsi.m_TMSI);
|
|
||||||
// } else {
|
|
||||||
// initial_ue_message_p->presenceMask |= INITIALUEMESSAGEIES_GUMMEI_ID_PRESENT;
|
|
||||||
//
|
|
||||||
// MCC_MNC_TO_PLMNID(nas_req_p.ue_identity.identity.gummei.mcc,
|
|
||||||
// nas_req_p.ue_identity.identity.gummei.mnc,
|
|
||||||
// &initial_ue_message_p->gummei_id.pLMN_Identity);
|
|
||||||
// MME_GID_TO_OCTET_STRING(nas_req_p.ue_identity.identity.gummei.mme_group_id,
|
|
||||||
// &initial_ue_message_p->gummei_id.mME_Group_ID);
|
|
||||||
// MME_CODE_TO_OCTET_STRING(nas_req_p.ue_identity.identity.gummei.mme_code,
|
|
||||||
// &initial_ue_message_p->gummei_id.mME_Code);
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// /* Assuming TAI is the TAI from the cell */
|
|
||||||
// INT16_TO_OCTET_STRING(eNB_desc_p->tac, &initial_ue_message_p->tai.tAC);
|
|
||||||
// MCC_MNC_TO_PLMNID(eNB_desc_p->mcc, eNB_desc_p->mnc,
|
|
||||||
// &initial_ue_message_p->tai.pLMNidentity);
|
|
||||||
//
|
|
||||||
// /* Set the EUTRAN CGI
|
|
||||||
// * The cell identity is defined on 28 bits but as we use macro enb id,
|
|
||||||
// * we have to pad.
|
|
||||||
// */
|
|
||||||
// MACRO_ENB_ID_TO_CELL_IDENTITY(eNB_desc_p->eNB_id,
|
|
||||||
// &initial_ue_message_p->eutran_cgi.cell_ID);
|
|
||||||
// MCC_MNC_TO_TBCD(eNB_desc_p->mcc, eNB_desc_p->mnc,
|
|
||||||
// &initial_ue_message_p->eutran_cgi.pLMNidentity);
|
|
||||||
//
|
|
||||||
// if (s1ap_eNB_encode_pdu(&message, &buffer, &length) < 0) {
|
|
||||||
// /* Failed to encode message */
|
|
||||||
// return -1;
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// /* Update the current S1AP UE state */
|
|
||||||
// ue_desc_p->ue_state = S1AP_UE_WAITING_CSR;
|
|
||||||
//
|
|
||||||
// /* Send encoded message over sctp */
|
|
||||||
// return sctp_send_msg(&mme_desc_p->sctp_data, S1AP_SCTP_PPID, 1, buffer, length);
|
|
||||||
// }
|
|
||||||
|
|
||||||
|
|||||||
@@ -82,46 +82,6 @@ typedef enum {
|
|||||||
S1AP_OVERLOAD_MAX,
|
S1AP_OVERLOAD_MAX,
|
||||||
} s1ap_overload_state_t;
|
} s1ap_overload_state_t;
|
||||||
|
|
||||||
// typedef enum {
|
|
||||||
// PAGING_DRX_32 = 0x0,
|
|
||||||
// PAGING_DRX_64 = 0x1,
|
|
||||||
// PAGING_DRX_128 = 0x2,
|
|
||||||
// PAGING_DRX_256 = 0x3,
|
|
||||||
// } paging_drx_t;
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
/* Octet string data */
|
|
||||||
uint8_t *buffer;
|
|
||||||
/* Length of the octet string */
|
|
||||||
uint32_t length;
|
|
||||||
} nas_pdu_t, ue_radio_cap_t;
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
uint16_t mcc;
|
|
||||||
uint16_t mnc;
|
|
||||||
uint8_t mme_code;
|
|
||||||
uint16_t mme_group_id;
|
|
||||||
} gummei_t;
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
uint8_t mme_code;
|
|
||||||
uint32_t m_tmsi;
|
|
||||||
} s_tmsi_t;
|
|
||||||
|
|
||||||
/* Provides the establishment cause for the RRC connection request as provided
|
|
||||||
* by the upper layers. W.r.t. the cause value names: highPriorityAccess
|
|
||||||
* concerns AC11..AC15, ‘mt’ stands for ‘Mobile Terminating’ and ‘mo’ for
|
|
||||||
* 'Mobile Originating'. Defined in TS 36.331.
|
|
||||||
*/
|
|
||||||
typedef enum {
|
|
||||||
RRC_CAUSE_EMERGENCY = 0x0,
|
|
||||||
RRC_CAUSE_HIGH_PRIO_ACCESS = 0x1,
|
|
||||||
RRC_CAUSE_MT_ACCESS = 0x2,
|
|
||||||
RRC_CAUSE_MO_SIGNALLING = 0x3,
|
|
||||||
RRC_CAUSE_MO_DATA = 0x4,
|
|
||||||
RRC_CAUSE_MAX = RRC_CAUSE_MO_DATA,
|
|
||||||
} rrc_establishment_cause_t;
|
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
uint8_t qci;
|
uint8_t qci;
|
||||||
|
|
||||||
@@ -166,16 +126,6 @@ typedef struct {
|
|||||||
// cause_t cause;
|
// cause_t cause;
|
||||||
} e_rab_failed_t;
|
} e_rab_failed_t;
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
#define S_TMSI_PROVIDED 0x0
|
|
||||||
#define GUMMEI_PROVIDED 0x1
|
|
||||||
unsigned present:1;
|
|
||||||
union {
|
|
||||||
gummei_t gummei;
|
|
||||||
s_tmsi_t s_tmsi;
|
|
||||||
} identity;
|
|
||||||
} ue_identity_t;
|
|
||||||
|
|
||||||
/* Served PLMN identity element */
|
/* Served PLMN identity element */
|
||||||
struct plmn_identity_s {
|
struct plmn_identity_s {
|
||||||
uint16_t mcc;
|
uint16_t mcc;
|
||||||
|
|||||||
@@ -58,6 +58,7 @@ static
|
|||||||
int s1ap_eNB_handle_s1_setup_response(uint32_t assoc_id,
|
int s1ap_eNB_handle_s1_setup_response(uint32_t assoc_id,
|
||||||
uint32_t stream,
|
uint32_t stream,
|
||||||
struct s1ap_message_s *message_p);
|
struct s1ap_message_s *message_p);
|
||||||
|
static
|
||||||
int s1ap_eNB_handle_s1_setup_failure(uint32_t assoc_id,
|
int s1ap_eNB_handle_s1_setup_failure(uint32_t assoc_id,
|
||||||
uint32_t stream,
|
uint32_t stream,
|
||||||
struct s1ap_message_s *message_p);
|
struct s1ap_message_s *message_p);
|
||||||
@@ -164,6 +165,7 @@ int s1ap_eNB_handle_message(uint32_t assoc_id, int32_t stream,
|
|||||||
(assoc_id, stream, &message);
|
(assoc_id, stream, &message);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static
|
||||||
int s1ap_eNB_handle_s1_setup_failure(uint32_t assoc_id,
|
int s1ap_eNB_handle_s1_setup_failure(uint32_t assoc_id,
|
||||||
uint32_t stream,
|
uint32_t stream,
|
||||||
struct s1ap_message_s *message_p)
|
struct s1ap_message_s *message_p)
|
||||||
@@ -173,14 +175,11 @@ int s1ap_eNB_handle_s1_setup_failure(uint32_t assoc_id,
|
|||||||
S1AP_WARN("[SCTP %d] Received s1 setup failure on stream != 0 (%d)\n",
|
S1AP_WARN("[SCTP %d] Received s1 setup failure on stream != 0 (%d)\n",
|
||||||
assoc_id, stream);
|
assoc_id, stream);
|
||||||
}
|
}
|
||||||
S1AP_DEBUG("Received s1 setup failure for MME... please check your parameters\n");
|
S1AP_ERROR("Received s1 setup failure for MME... please check your parameters\n");
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// int s1ap_eNB_handle_s1_setup_response(eNB_mme_desc_t *eNB_desc_p,
|
|
||||||
// sctp_queue_item_t *packet_p,
|
|
||||||
// struct s1ap_message_s *message_p)
|
|
||||||
static
|
static
|
||||||
int s1ap_eNB_handle_s1_setup_response(uint32_t assoc_id,
|
int s1ap_eNB_handle_s1_setup_response(uint32_t assoc_id,
|
||||||
uint32_t stream,
|
uint32_t stream,
|
||||||
@@ -277,71 +276,62 @@ int s1ap_eNB_handle_s1_setup_response(uint32_t assoc_id,
|
|||||||
*/
|
*/
|
||||||
mme_desc_p->state = S1AP_ENB_STATE_CONNECTED;
|
mme_desc_p->state = S1AP_ENB_STATE_CONNECTED;
|
||||||
|
|
||||||
// /* We call back our self
|
/* We call back our self
|
||||||
// * -> generate a dummy initial UE message
|
* -> generate a dummy initial UE message
|
||||||
// */
|
*/
|
||||||
// {
|
{
|
||||||
// extern int s1ap_eNB_handle_api_req(eNB_mme_desc_t *eNB_desc_p,
|
s1ap_nas_first_req_t s1ap_nas_first_req;
|
||||||
// s1ap_rrc_api_req_t *api_req_p);
|
|
||||||
// s1ap_rrc_api_req_t api_req;
|
memset(&s1ap_nas_first_req, 0, sizeof(s1ap_nas_first_req_t));
|
||||||
// s1ap_nas_first_req_t *nas_req_p;
|
|
||||||
//
|
s1ap_nas_first_req.rnti = 0xC03A;
|
||||||
// memset(&api_req, 0, sizeof(s1ap_rrc_api_req_t));
|
s1ap_nas_first_req.establishment_cause = RRC_CAUSE_MO_DATA;
|
||||||
//
|
s1ap_nas_first_req.ue_identity.present = GUMMEI_PROVIDED;
|
||||||
// nas_req_p = &api_req.msg.first_nas_req;
|
|
||||||
// api_req.api_req = S1AP_API_NAS_FIRST_REQ;
|
s1ap_nas_first_req.ue_identity.identity.gummei.mcc = 208;
|
||||||
//
|
s1ap_nas_first_req.ue_identity.identity.gummei.mnc = 34;
|
||||||
// nas_req_p->rnti = 0xC03A;
|
s1ap_nas_first_req.ue_identity.identity.gummei.mme_code = 0;
|
||||||
// nas_req_p->establishment_cause = RRC_CAUSE_MO_DATA;
|
s1ap_nas_first_req.ue_identity.identity.gummei.mme_group_id = 0;
|
||||||
// nas_req_p->ue_identity.present = GUMMEI_PROVIDED;
|
|
||||||
//
|
/* NAS Attach request with IMSI */
|
||||||
// nas_req_p->ue_identity.identity.gummei.mcc = 208;
|
uint8_t nas_attach_req_imsi[] =
|
||||||
// nas_req_p->ue_identity.identity.gummei.mnc = 34;
|
{
|
||||||
// nas_req_p->ue_identity.identity.gummei.mme_code = 0;
|
0x07, 0x41,
|
||||||
// nas_req_p->ue_identity.identity.gummei.mme_group_id = 0;
|
/* EPS Mobile identity = IMSI */
|
||||||
//
|
0x71, 0x08, 0x29, 0x80, 0x43, 0x21, 0x43, 0x65, 0x87,
|
||||||
// /* NAS Attach request with IMSI */
|
0xF9,
|
||||||
// uint8_t nas_attach_req_imsi[] =
|
/* End of EPS Mobile Identity */
|
||||||
// {
|
0x02, 0xE0, 0xE0, 0x00, 0x20, 0x02, 0x03,
|
||||||
// 0x07, 0x41,
|
0xD0, 0x11, 0x27, 0x1A, 0x80, 0x80, 0x21, 0x10, 0x01, 0x00, 0x00,
|
||||||
// /* EPS Mobile identity = IMSI */
|
0x10, 0x81, 0x06, 0x00, 0x00, 0x00, 0x00, 0x83, 0x06, 0x00, 0x00,
|
||||||
// 0x71, 0x08, 0x29, 0x80, 0x43, 0x21, 0x43, 0x65, 0x87,
|
0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x0A, 0x00, 0x52, 0x12, 0xF2,
|
||||||
// 0xF9,
|
0x01, 0x27, 0x11,
|
||||||
// /* End of EPS Mobile Identity */
|
};
|
||||||
// 0x02, 0xE0, 0xE0, 0x00, 0x20, 0x02, 0x03,
|
|
||||||
// 0xD0, 0x11, 0x27, 0x1A, 0x80, 0x80, 0x21, 0x10, 0x01, 0x00, 0x00,
|
/* NAS Attach request with GUTI */
|
||||||
// 0x10, 0x81, 0x06, 0x00, 0x00, 0x00, 0x00, 0x83, 0x06, 0x00, 0x00,
|
uint8_t nas_attach_req_guti[] =
|
||||||
// 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x0A, 0x00, 0x52, 0x12, 0xF2,
|
{
|
||||||
// 0x01, 0x27, 0x11,
|
0x07, 0x41,
|
||||||
// };
|
/* EPS Mobile identity = IMSI */
|
||||||
//
|
0x71, 0x0B, 0xF6, 0x12, 0xF2, 0x01, 0x80, 0x00, 0x01, 0xE0, 0x00,
|
||||||
// /* NAS Attach request with GUTI */
|
0xDA, 0x1F,
|
||||||
// uint8_t nas_attach_req_guti[] =
|
/* End of EPS Mobile Identity */
|
||||||
// {
|
0x02, 0xE0, 0xE0, 0x00, 0x20, 0x02, 0x03,
|
||||||
// 0x07, 0x41,
|
0xD0, 0x11, 0x27, 0x1A, 0x80, 0x80, 0x21, 0x10, 0x01, 0x00, 0x00,
|
||||||
// /* EPS Mobile identity = IMSI */
|
0x10, 0x81, 0x06, 0x00, 0x00, 0x00, 0x00, 0x83, 0x06, 0x00, 0x00,
|
||||||
// 0x71, 0x0B, 0xF6, 0x12, 0xF2, 0x01, 0x80, 0x00, 0x01, 0xE0, 0x00,
|
0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x0A, 0x00, 0x52, 0x12, 0xF2,
|
||||||
// 0xDA, 0x1F,
|
0x01, 0x27, 0x11,
|
||||||
// /* End of EPS Mobile Identity */
|
};
|
||||||
// 0x02, 0xE0, 0xE0, 0x00, 0x20, 0x02, 0x03,
|
|
||||||
// 0xD0, 0x11, 0x27, 0x1A, 0x80, 0x80, 0x21, 0x10, 0x01, 0x00, 0x00,
|
s1ap_nas_first_req.nas_pdu.buffer = nas_attach_req_guti;
|
||||||
// 0x10, 0x81, 0x06, 0x00, 0x00, 0x00, 0x00, 0x83, 0x06, 0x00, 0x00,
|
s1ap_nas_first_req.nas_pdu.length = sizeof(nas_attach_req_guti);
|
||||||
// 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x0A, 0x00, 0x52, 0x12, 0xF2,
|
|
||||||
// 0x01, 0x27, 0x11,
|
s1ap_eNB_handle_nas_first_req(&s1ap_nas_first_req);
|
||||||
// };
|
}
|
||||||
//
|
|
||||||
// nas_req_p->nas_pdu.buffer = nas_attach_req_guti;
|
|
||||||
// nas_req_p->nas_pdu.length = sizeof(nas_attach_req_guti);
|
|
||||||
//
|
|
||||||
// s1ap_eNB_handle_api_req(eNB_desc_p, &api_req);
|
|
||||||
// }
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// int s1ap_eNB_handle_initial_context_request(eNB_mme_desc_t *eNB_desc_p,
|
|
||||||
// sctp_queue_item_t *packet_p,
|
|
||||||
// struct s1ap_message_s *message_p)
|
|
||||||
static
|
static
|
||||||
int s1ap_eNB_handle_initial_context_request(uint32_t assoc_id,
|
int s1ap_eNB_handle_initial_context_request(uint32_t assoc_id,
|
||||||
uint32_t stream,
|
uint32_t stream,
|
||||||
@@ -351,30 +341,28 @@ int s1ap_eNB_handle_initial_context_request(uint32_t assoc_id,
|
|||||||
s1ap_eNB_ue_context_t *ue_desc_p;
|
s1ap_eNB_ue_context_t *ue_desc_p;
|
||||||
|
|
||||||
InitialContextSetupRequestIEs_t *initialContextSetupRequest_p;
|
InitialContextSetupRequestIEs_t *initialContextSetupRequest_p;
|
||||||
|
|
||||||
// DevAssert(eNB_desc_p != NULL);
|
|
||||||
DevAssert(message_p != NULL);
|
DevAssert(message_p != NULL);
|
||||||
|
|
||||||
initialContextSetupRequest_p = &message_p->msg.initialContextSetupRequestIEs;
|
initialContextSetupRequest_p = &message_p->msg.initialContextSetupRequestIEs;
|
||||||
|
|
||||||
/* Initial context request = UE-related procedure -> stream != 0 */
|
if ((mme_desc_p = s1ap_eNB_get_MME(NULL, assoc_id, 0)) == NULL) {
|
||||||
if (stream == 0) {
|
S1AP_ERROR("[SCTP %d] Received initial context setup request for non "
|
||||||
S1AP_ERROR("[SCTP %d] Received UE-related procedure on stream = 0 (%d)\n",
|
"existing MME context\n", assoc_id);
|
||||||
assoc_id, stream);
|
return -1;
|
||||||
|
}
|
||||||
|
if ((ue_desc_p = s1ap_eNB_get_ue_context(mme_desc_p->s1ap_eNB_instance,
|
||||||
|
initialContextSetupRequest_p->eNB_UE_S1AP_ID)) == NULL) {
|
||||||
|
S1AP_ERROR("[SCTP %d] Received initial context setup request for non "
|
||||||
|
"existing UE context\n", assoc_id);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// if ((mme_desc_p = s1ap_eNB_get_MME(eNB_desc_p, assoc_id)) == NULL) {
|
/* Initial context request = UE-related procedure -> stream != 0 */
|
||||||
// S1AP_ERROR("[SCTP %d] Received initial context setup request for non "
|
if (stream != ue_desc_p->stream) {
|
||||||
// "existing MME context\n", packet_p->assoc_id);
|
S1AP_ERROR("[SCTP %d] Received UE-related procedure on stream (%d) whereas expecting (%d)\n",
|
||||||
// return -1;
|
assoc_id, stream, ue_desc_p->stream);
|
||||||
// }
|
return -1;
|
||||||
// if ((ue_desc_p = s1ap_eNB_get_ue_context(eNB_desc_p,
|
}
|
||||||
// initialContextSetupRequest_p->eNB_UE_S1AP_ID)) == NULL) {
|
|
||||||
// S1AP_ERROR("[SCTP %d] Received initial context setup request for non "
|
|
||||||
// "existing UE context\n", packet_p->assoc_id);
|
|
||||||
// return -1;
|
|
||||||
// }
|
|
||||||
|
|
||||||
ue_desc_p->mme_ue_s1ap_id = initialContextSetupRequest_p->mme_ue_s1ap_id;
|
ue_desc_p->mme_ue_s1ap_id = initialContextSetupRequest_p->mme_ue_s1ap_id;
|
||||||
|
|
||||||
|
|||||||
@@ -19,3 +19,20 @@ void s1ap_eNB_itti_send_sctp_data_req(int32_t assoc_id, uint8_t *buffer,
|
|||||||
|
|
||||||
itti_send_msg_to_task(TASK_SCTP, INSTANCE_DEFAULT, message_p);
|
itti_send_msg_to_task(TASK_SCTP, INSTANCE_DEFAULT, message_p);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void s1ap_eNB_itti_send_nas_downlink_ind(uint8_t mod_id, uint8_t *nas_pdu,
|
||||||
|
uint32_t nas_pdu_length)
|
||||||
|
{
|
||||||
|
MessageDef *message_p;
|
||||||
|
s1ap_downlink_nas_t *s1ap_downlink_nas;
|
||||||
|
|
||||||
|
message_p = itti_alloc_new_message(TASK_S1AP, S1AP_DOWNLINK_NAS);
|
||||||
|
|
||||||
|
s1ap_downlink_nas = &message_p->msg.s1ap_downlink_nas;
|
||||||
|
|
||||||
|
s1ap_downlink_nas->mod_id = mod_id;
|
||||||
|
s1ap_downlink_nas->nas_pdu.buffer = nas_pdu;
|
||||||
|
s1ap_downlink_nas->nas_pdu.length = nas_pdu_length;
|
||||||
|
|
||||||
|
itti_send_msg_to_task(TASK_RRC_ENB, INSTANCE_DEFAULT, message_p);
|
||||||
|
}
|
||||||
|
|||||||
@@ -4,4 +4,7 @@
|
|||||||
void s1ap_eNB_itti_send_sctp_data_req(int32_t assoc_id, uint8_t *buffer,
|
void s1ap_eNB_itti_send_sctp_data_req(int32_t assoc_id, uint8_t *buffer,
|
||||||
uint32_t buffer_length, uint16_t stream);
|
uint32_t buffer_length, uint16_t stream);
|
||||||
|
|
||||||
|
void s1ap_eNB_itti_send_nas_downlink_ind(uint8_t mod_id, uint8_t *nas_pdu,
|
||||||
|
uint32_t nas_pdu_length);
|
||||||
|
|
||||||
#endif /* S1AP_ENB_ITTI_MESSAGING_H_ */
|
#endif /* S1AP_ENB_ITTI_MESSAGING_H_ */
|
||||||
|
|||||||
@@ -35,17 +35,104 @@
|
|||||||
#include "intertask_interface.h"
|
#include "intertask_interface.h"
|
||||||
|
|
||||||
#include "assertions.h"
|
#include "assertions.h"
|
||||||
// #include "conversions.h"
|
#include "conversions.h"
|
||||||
|
|
||||||
#include "s1ap_common.h"
|
#include "s1ap_common.h"
|
||||||
#include "s1ap_ies_defs.h"
|
|
||||||
#include "s1ap_eNB_defs.h"
|
#include "s1ap_eNB_defs.h"
|
||||||
#include "s1ap_eNB.h"
|
#include "s1ap_eNB.h"
|
||||||
|
|
||||||
#include "s1ap_eNB_encoder.h"
|
s1ap_eNB_internal_data_t s1ap_eNB_internal_data;
|
||||||
#include "s1ap_eNB_management_procedures.h"
|
|
||||||
|
|
||||||
#include "sctp_primitives_client.h"
|
static int s1ap_eNB_generate_s1_setup_request(
|
||||||
|
s1ap_eNB_instance_t *instance_p, s1ap_eNB_mme_data_t *s1ap_mme_data_p);
|
||||||
|
|
||||||
|
RB_GENERATE(s1ap_mme_map, s1ap_eNB_mme_data_s, entry, s1ap_eNB_compare_assoc_id);
|
||||||
|
|
||||||
|
inline int s1ap_eNB_compare_assoc_id(
|
||||||
|
struct s1ap_eNB_mme_data_s *p1, struct s1ap_eNB_mme_data_s *p2)
|
||||||
|
{
|
||||||
|
if (p1->assoc_id == -1) {
|
||||||
|
if (p1->cnx_id < p2->cnx_id) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (p1->cnx_id > p2->cnx_id) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (p1->assoc_id < p2->assoc_id) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (p1->assoc_id > p2->assoc_id) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Matching reference */
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t s1ap_eNB_fetch_add_global_cnx_id(void)
|
||||||
|
{
|
||||||
|
return ++s1ap_eNB_internal_data.global_cnx_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
void s1ap_eNB_prepare_internal_data(void)
|
||||||
|
{
|
||||||
|
memset(&s1ap_eNB_internal_data, 0, sizeof(s1ap_eNB_internal_data));
|
||||||
|
STAILQ_INIT(&s1ap_eNB_internal_data.s1ap_eNB_instances_head);
|
||||||
|
}
|
||||||
|
|
||||||
|
void s1ap_eNB_insert_new_instance(s1ap_eNB_instance_t *new_instance_p)
|
||||||
|
{
|
||||||
|
DevAssert(new_instance_p != NULL);
|
||||||
|
|
||||||
|
STAILQ_INSERT_TAIL(&s1ap_eNB_internal_data.s1ap_eNB_instances_head,
|
||||||
|
new_instance_p, s1ap_eNB_entries);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline struct s1ap_eNB_mme_data_s *s1ap_eNB_get_MME(
|
||||||
|
s1ap_eNB_instance_t *instance_p,
|
||||||
|
int32_t assoc_id, uint16_t cnx_id)
|
||||||
|
{
|
||||||
|
struct s1ap_eNB_mme_data_s temp;
|
||||||
|
struct s1ap_eNB_mme_data_s *found;
|
||||||
|
|
||||||
|
memset(&temp, 0, sizeof(struct s1ap_eNB_mme_data_s));
|
||||||
|
|
||||||
|
temp.assoc_id = assoc_id;
|
||||||
|
temp.cnx_id = cnx_id;
|
||||||
|
|
||||||
|
if (instance_p == NULL) {
|
||||||
|
STAILQ_FOREACH(instance_p, &s1ap_eNB_internal_data.s1ap_eNB_instances_head,
|
||||||
|
s1ap_eNB_entries)
|
||||||
|
{
|
||||||
|
found = RB_FIND(s1ap_mme_map, &instance_p->s1ap_mme_head, &temp);
|
||||||
|
if (found != NULL) {
|
||||||
|
return found;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return RB_FIND(s1ap_mme_map, &instance_p->s1ap_mme_head, &temp);
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
s1ap_eNB_instance_t *s1ap_eNB_get_instance(uint8_t mod_id)
|
||||||
|
{
|
||||||
|
s1ap_eNB_instance_t *temp = NULL;
|
||||||
|
|
||||||
|
STAILQ_FOREACH(temp, &s1ap_eNB_internal_data.s1ap_eNB_instances_head,
|
||||||
|
s1ap_eNB_entries)
|
||||||
|
{
|
||||||
|
if (temp->mod_id == mod_id) {
|
||||||
|
/* Matching occurence */
|
||||||
|
return temp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
// int s1ap_eNB_ue_capabilities(eNB_mme_desc_t *eNB_desc_p,
|
// int s1ap_eNB_ue_capabilities(eNB_mme_desc_t *eNB_desc_p,
|
||||||
// s1ap_ue_cap_info_ind_t *ue_cap_info_ind_p)
|
// s1ap_ue_cap_info_ind_t *ue_cap_info_ind_p)
|
||||||
|
|||||||
@@ -31,7 +31,16 @@
|
|||||||
#ifndef S1AP_ENB_MANAGEMENT_PROCEDURES_H_
|
#ifndef S1AP_ENB_MANAGEMENT_PROCEDURES_H_
|
||||||
#define S1AP_ENB_MANAGEMENT_PROCEDURES_H_
|
#define S1AP_ENB_MANAGEMENT_PROCEDURES_H_
|
||||||
|
|
||||||
// int s1ap_eNB_ue_capabilities(eNB_mme_desc_t *eNB_desc_p,
|
inline struct s1ap_eNB_mme_data_s *s1ap_eNB_get_MME(
|
||||||
// s1ap_ue_cap_info_ind_t *ue_cap_info_ind_p);
|
s1ap_eNB_instance_t *instance_p,
|
||||||
|
int32_t assoc_id, uint16_t cnx_id);
|
||||||
|
|
||||||
|
void s1ap_eNB_insert_new_instance(s1ap_eNB_instance_t *new_instance_p);
|
||||||
|
|
||||||
|
s1ap_eNB_instance_t *s1ap_eNB_get_instance(uint8_t mod_id);
|
||||||
|
|
||||||
|
uint16_t s1ap_eNB_fetch_add_global_cnx_id(void);
|
||||||
|
|
||||||
|
void s1ap_eNB_prepare_internal_data(void);
|
||||||
|
|
||||||
#endif /* S1AP_ENB_MANAGEMENT_PROCEDURES_H_ */
|
#endif /* S1AP_ENB_MANAGEMENT_PROCEDURES_H_ */
|
||||||
|
|||||||
@@ -40,16 +40,142 @@
|
|||||||
#include "s1ap_common.h"
|
#include "s1ap_common.h"
|
||||||
#include "s1ap_eNB_defs.h"
|
#include "s1ap_eNB_defs.h"
|
||||||
|
|
||||||
|
#include "s1ap_eNB_itti_messaging.h"
|
||||||
|
|
||||||
#include "s1ap_ies_defs.h"
|
#include "s1ap_ies_defs.h"
|
||||||
#include "s1ap_eNB_encoder.h"
|
#include "s1ap_eNB_encoder.h"
|
||||||
|
#include "s1ap_eNB_nnsf.h"
|
||||||
#include "s1ap_eNB_ue_context.h"
|
#include "s1ap_eNB_ue_context.h"
|
||||||
#include "s1ap_eNB_nas_procedures.h"
|
#include "s1ap_eNB_nas_procedures.h"
|
||||||
|
#include "s1ap_eNB_management_procedures.h"
|
||||||
|
|
||||||
#include "sctp_primitives_client.h"
|
int s1ap_eNB_handle_nas_first_req(s1ap_nas_first_req_t *s1ap_nas_first_req_p)
|
||||||
|
{
|
||||||
|
s1ap_eNB_instance_t *instance_p;
|
||||||
|
struct s1ap_eNB_mme_data_s *mme_desc_p;
|
||||||
|
struct s1ap_eNB_ue_context_s *ue_desc_p;
|
||||||
|
|
||||||
|
s1ap_message message;
|
||||||
|
InitialUEMessageIEs_t *initial_ue_message_p;
|
||||||
|
|
||||||
|
uint8_t *buffer;
|
||||||
|
uint32_t length;
|
||||||
|
|
||||||
|
DevAssert(s1ap_nas_first_req_p != NULL);
|
||||||
|
|
||||||
|
/* Retrieve the S1AP eNB instance associated with Mod_id */
|
||||||
|
instance_p = s1ap_eNB_get_instance(s1ap_nas_first_req_p->mod_id);
|
||||||
|
DevAssert(instance_p != NULL);
|
||||||
|
|
||||||
|
memset(&message, 0, sizeof(s1ap_message));
|
||||||
|
|
||||||
|
message.direction = S1AP_PDU_PR_initiatingMessage;
|
||||||
|
message.procedureCode = ProcedureCode_id_initialUEMessage;
|
||||||
|
|
||||||
|
initial_ue_message_p = &message.msg.initialUEMessageIEs;
|
||||||
|
|
||||||
|
/* Select the MME corresponding to the provided GUMMEI.
|
||||||
|
* If no MME corresponds to the GUMMEI, the function selects the MME with the
|
||||||
|
* highest capacity.
|
||||||
|
* In case eNB has no MME associated, the eNB should inform RRC and discard
|
||||||
|
* this request.
|
||||||
|
*/
|
||||||
|
if (s1ap_nas_first_req_p->ue_identity.present == GUMMEI_PROVIDED) {
|
||||||
|
mme_desc_p = s1ap_eNB_nnsf_select_mme_by_gummei(
|
||||||
|
instance_p,
|
||||||
|
s1ap_nas_first_req_p->establishment_cause,
|
||||||
|
s1ap_nas_first_req_p->ue_identity.identity.gummei);
|
||||||
|
} else {
|
||||||
|
mme_desc_p = s1ap_eNB_nnsf_select_mme_by_mme_code(
|
||||||
|
instance_p,
|
||||||
|
s1ap_nas_first_req_p->establishment_cause,
|
||||||
|
s1ap_nas_first_req_p->ue_identity.identity.s_tmsi.mme_code);
|
||||||
|
}
|
||||||
|
if (mme_desc_p == NULL) {
|
||||||
|
S1AP_WARN("No MME is associated to the eNB\n");
|
||||||
|
// TODO: Inform RRC
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* The eNB should allocate a unique eNB UE S1AP ID for this UE. The value
|
||||||
|
* will be used for the duration of the connectivity.
|
||||||
|
*/
|
||||||
|
ue_desc_p = s1ap_eNB_allocate_new_UE_context();
|
||||||
|
DevAssert(ue_desc_p != NULL);
|
||||||
|
|
||||||
|
/* Keep a reference to the selected MME */
|
||||||
|
ue_desc_p->mme_ref = mme_desc_p;
|
||||||
|
ue_desc_p->rnti = s1ap_nas_first_req_p->rnti;
|
||||||
|
|
||||||
|
do {
|
||||||
|
struct s1ap_eNB_ue_context_s *collision_p;
|
||||||
|
|
||||||
|
/* Peek a random value for the eNB_ue_s1ap_id */
|
||||||
|
ue_desc_p->eNB_ue_s1ap_id = (random() + random()) & 0x00ffffff;
|
||||||
|
if ((collision_p = RB_INSERT(s1ap_ue_map, &instance_p->s1ap_ue_head, ue_desc_p))
|
||||||
|
== NULL) {
|
||||||
|
/* Break the loop as the id is not already used by another UE */
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} while(1);
|
||||||
|
|
||||||
|
initial_ue_message_p->eNB_UE_S1AP_ID = ue_desc_p->eNB_ue_s1ap_id;
|
||||||
|
/* Prepare the NAS PDU */
|
||||||
|
initial_ue_message_p->nas_pdu.buf = s1ap_nas_first_req_p->nas_pdu.buffer;
|
||||||
|
initial_ue_message_p->nas_pdu.size = s1ap_nas_first_req_p->nas_pdu.length;
|
||||||
|
|
||||||
|
/* Set the establishment cause according to those provided by RRC */
|
||||||
|
DevCheck(s1ap_nas_first_req_p->establishment_cause < RRC_CAUSE_LAST,
|
||||||
|
s1ap_nas_first_req_p->establishment_cause, RRC_CAUSE_LAST, 0);
|
||||||
|
initial_ue_message_p->rrC_Establishment_Cause = s1ap_nas_first_req_p->establishment_cause;
|
||||||
|
|
||||||
|
if (s1ap_nas_first_req_p->ue_identity.present == S_TMSI_PROVIDED) {
|
||||||
|
initial_ue_message_p->presenceMask |= INITIALUEMESSAGEIES_S_TMSI_PRESENT;
|
||||||
|
|
||||||
|
MME_CODE_TO_OCTET_STRING(s1ap_nas_first_req_p->ue_identity.identity.s_tmsi.mme_code,
|
||||||
|
&initial_ue_message_p->s_tmsi.mMEC);
|
||||||
|
M_TMSI_TO_OCTET_STRING(s1ap_nas_first_req_p->ue_identity.identity.s_tmsi.m_tmsi,
|
||||||
|
&initial_ue_message_p->s_tmsi.m_TMSI);
|
||||||
|
} else {
|
||||||
|
initial_ue_message_p->presenceMask |= INITIALUEMESSAGEIES_GUMMEI_ID_PRESENT;
|
||||||
|
|
||||||
|
MCC_MNC_TO_PLMNID(s1ap_nas_first_req_p->ue_identity.identity.gummei.mcc,
|
||||||
|
s1ap_nas_first_req_p->ue_identity.identity.gummei.mnc,
|
||||||
|
&initial_ue_message_p->gummei_id.pLMN_Identity);
|
||||||
|
MME_GID_TO_OCTET_STRING(s1ap_nas_first_req_p->ue_identity.identity.gummei.mme_group_id,
|
||||||
|
&initial_ue_message_p->gummei_id.mME_Group_ID);
|
||||||
|
MME_CODE_TO_OCTET_STRING(s1ap_nas_first_req_p->ue_identity.identity.gummei.mme_code,
|
||||||
|
&initial_ue_message_p->gummei_id.mME_Code);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Assuming TAI is the TAI from the cell */
|
||||||
|
INT16_TO_OCTET_STRING(instance_p->tac, &initial_ue_message_p->tai.tAC);
|
||||||
|
MCC_MNC_TO_PLMNID(instance_p->mcc, instance_p->mnc,
|
||||||
|
&initial_ue_message_p->tai.pLMNidentity);
|
||||||
|
|
||||||
|
/* Set the EUTRAN CGI
|
||||||
|
* The cell identity is defined on 28 bits but as we use macro enb id,
|
||||||
|
* we have to pad.
|
||||||
|
*/
|
||||||
|
MACRO_ENB_ID_TO_CELL_IDENTITY(instance_p->eNB_id,
|
||||||
|
&initial_ue_message_p->eutran_cgi.cell_ID);
|
||||||
|
MCC_MNC_TO_TBCD(instance_p->mcc, instance_p->mnc,
|
||||||
|
&initial_ue_message_p->eutran_cgi.pLMNidentity);
|
||||||
|
|
||||||
|
if (s1ap_eNB_encode_pdu(&message, &buffer, &length) < 0) {
|
||||||
|
/* Failed to encode message */
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Update the current S1AP UE state */
|
||||||
|
ue_desc_p->ue_state = S1AP_UE_WAITING_CSR;
|
||||||
|
|
||||||
|
/* Send encoded message over sctp */
|
||||||
|
s1ap_eNB_itti_send_sctp_data_req(mme_desc_p->assoc_id, buffer, length, ue_desc_p->stream);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
// int s1ap_eNB_handle_nas_downlink(eNB_mme_desc_t *eNB_desc_p,
|
|
||||||
// sctp_queue_item_t *packet_p,
|
|
||||||
// struct s1ap_message_s *message_p)
|
|
||||||
int s1ap_eNB_handle_nas_downlink(uint32_t assoc_id,
|
int s1ap_eNB_handle_nas_downlink(uint32_t assoc_id,
|
||||||
uint32_t stream,
|
uint32_t stream,
|
||||||
struct s1ap_message_s *message_p)
|
struct s1ap_message_s *message_p)
|
||||||
@@ -57,6 +183,7 @@ int s1ap_eNB_handle_nas_downlink(uint32_t assoc_id,
|
|||||||
DownlinkNASTransportIEs_t *downlink_NAS_transport_p;
|
DownlinkNASTransportIEs_t *downlink_NAS_transport_p;
|
||||||
s1ap_eNB_mme_data_t *mme_desc_p;
|
s1ap_eNB_mme_data_t *mme_desc_p;
|
||||||
s1ap_eNB_ue_context_t *ue_desc_p;
|
s1ap_eNB_ue_context_t *ue_desc_p;
|
||||||
|
s1ap_eNB_instance_t *s1ap_eNB_instance;
|
||||||
|
|
||||||
DevAssert(message_p != NULL);
|
DevAssert(message_p != NULL);
|
||||||
|
|
||||||
@@ -69,117 +196,120 @@ int s1ap_eNB_handle_nas_downlink(uint32_t assoc_id,
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// if ((mme_desc_p = s1ap_eNB_get_MME(eNB_desc_p, assoc_id)) == NULL) {
|
if ((mme_desc_p = s1ap_eNB_get_MME(NULL, assoc_id, 0)) == NULL) {
|
||||||
// S1AP_ERROR("[SCTP %d] Received initial context setup request for non "
|
S1AP_ERROR("[SCTP %d] Received initial context setup request for non "
|
||||||
// "existing MME context\n", assoc_id);
|
"existing MME context\n", assoc_id);
|
||||||
// return -1;
|
return -1;
|
||||||
// }
|
}
|
||||||
// if ((ue_desc_p = s1ap_eNB_get_ue_context(eNB_desc_p,
|
|
||||||
// downlink_NAS_transport_p->eNB_UE_S1AP_ID)) == NULL)
|
s1ap_eNB_instance = mme_desc_p->s1ap_eNB_instance;
|
||||||
// {
|
|
||||||
// S1AP_ERROR("[SCTP %d] Received initial context setup request for non "
|
if ((ue_desc_p = s1ap_eNB_get_ue_context(s1ap_eNB_instance,
|
||||||
// "existing UE context\n", assoc_id);
|
downlink_NAS_transport_p->eNB_UE_S1AP_ID)) == NULL)
|
||||||
// return -1;
|
{
|
||||||
// }
|
S1AP_ERROR("[SCTP %d] Received initial context setup request for non "
|
||||||
|
"existing UE context\n", assoc_id);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
/* Is it the first outcome of the MME for this UE ? If so store the mme
|
/* Is it the first outcome of the MME for this UE ? If so store the mme
|
||||||
* UE s1ap id.
|
* UE s1ap id.
|
||||||
*/
|
*/
|
||||||
// if (ue_desc_p->mme_ue_s1ap_id == 0) {
|
if (ue_desc_p->mme_ue_s1ap_id == 0) {
|
||||||
// ue_desc_p->mme_ue_s1ap_id = downlink_NAS_transport_p->mme_ue_s1ap_id;
|
ue_desc_p->mme_ue_s1ap_id = downlink_NAS_transport_p->mme_ue_s1ap_id;
|
||||||
// } else {
|
} else {
|
||||||
// /* We already have a mme ue s1ap id check the received is the same */
|
/* We already have a mme ue s1ap id check the received is the same */
|
||||||
// if (ue_desc_p->mme_ue_s1ap_id != downlink_NAS_transport_p->mme_ue_s1ap_id) {
|
if (ue_desc_p->mme_ue_s1ap_id != downlink_NAS_transport_p->mme_ue_s1ap_id) {
|
||||||
// S1AP_ERROR("[SCTP %d] Mismatch is MME UE S1AP ID (0x%08x != 0x%08x)\n",
|
S1AP_ERROR("[SCTP %d] Mismatch is MME UE S1AP ID (0x%08x != 0x%08x)\n",
|
||||||
// downlink_NAS_transport_p->mme_ue_s1ap_id,
|
downlink_NAS_transport_p->mme_ue_s1ap_id,
|
||||||
// ue_desc_p->mme_ue_s1ap_id,
|
ue_desc_p->mme_ue_s1ap_id,
|
||||||
// packet_p->assoc_id);
|
assoc_id);
|
||||||
// }
|
}
|
||||||
// }
|
}
|
||||||
|
|
||||||
/* TODO: forward NAS pdu to RRC for transmission */
|
/* Forward the NAS PDU to RRC */
|
||||||
|
s1ap_eNB_itti_send_nas_downlink_ind(s1ap_eNB_instance->mod_id,
|
||||||
|
downlink_NAS_transport_p->nas_pdu.buf,
|
||||||
|
downlink_NAS_transport_p->nas_pdu.size);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// int s1ap_eNB_nas_uplink(eNB_mme_desc_t *eNB_desc_p,
|
int s1ap_eNB_nas_uplink(s1ap_uplink_nas_t *s1ap_uplink_nas_p)
|
||||||
// s1ap_nas_uplink_t *nas_uplink_p)
|
{
|
||||||
// {
|
struct s1ap_eNB_ue_context_s *ue_context_p;
|
||||||
// struct s1ap_eNB_ue_context_s *ue_context_p;
|
UplinkNASTransportIEs_t *uplink_NAS_transport_p;
|
||||||
// UplinkNASTransportIEs_t *uplink_NAS_transport_p;
|
s1ap_eNB_instance_t *s1ap_eNB_instance_p;
|
||||||
//
|
|
||||||
// s1ap_message message;
|
|
||||||
//
|
|
||||||
// uint8_t *buffer;
|
|
||||||
// uint32_t length;
|
|
||||||
// int ret = -1;
|
|
||||||
//
|
|
||||||
// DevAssert(nas_uplink_p != NULL);
|
|
||||||
// DevAssert(eNB_desc_p != NULL);
|
|
||||||
//
|
|
||||||
// if ((ue_context_p = s1ap_eNB_get_ue_context(eNB_desc_p, nas_uplink_p->eNB_ue_s1ap_id)) == NULL)
|
|
||||||
// {
|
|
||||||
// /* The context for this eNB ue s1ap id doesn't exist in the map of eNB UEs */
|
|
||||||
// S1AP_WARN("Failed to find ue context associated with eNB ue s1ap id: %u\n",
|
|
||||||
// nas_uplink_p->eNB_ue_s1ap_id);
|
|
||||||
// return -1;
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// /* Uplink NAS transport can occur either during an s1ap connected state
|
|
||||||
// * or during initial attach (for example: NAS authentication).
|
|
||||||
// */
|
|
||||||
// if (!(ue_context_p->ue_state == S1AP_UE_CONNECTED ||
|
|
||||||
// ue_context_p->ue_state == S1AP_UE_WAITING_CSR))
|
|
||||||
// {
|
|
||||||
// S1AP_WARN("You are attempting to send NAS data over non-connected "
|
|
||||||
// "eNB ue s1ap id: %u, current state: %d\n",
|
|
||||||
// nas_uplink_p->eNB_ue_s1ap_id, ue_context_p->ue_state);
|
|
||||||
// return -1;
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// /* Prepare the S1AP message to encode */
|
|
||||||
// memset(&message, 0, sizeof(s1ap_message));
|
|
||||||
//
|
|
||||||
// message.direction = S1AP_PDU_PR_initiatingMessage;
|
|
||||||
// message.procedureCode = ProcedureCode_id_uplinkNASTransport;
|
|
||||||
//
|
|
||||||
// uplink_NAS_transport_p = &message.msg.uplinkNASTransportIEs;
|
|
||||||
//
|
|
||||||
// uplink_NAS_transport_p->mme_ue_s1ap_id = ue_context_p->mme_ue_s1ap_id;
|
|
||||||
// uplink_NAS_transport_p->eNB_UE_S1AP_ID = ue_context_p->eNB_ue_s1ap_id;
|
|
||||||
//
|
|
||||||
// uplink_NAS_transport_p->nas_pdu.buf = nas_uplink_p->nas_pdu.buffer;
|
|
||||||
// uplink_NAS_transport_p->nas_pdu.size = nas_uplink_p->nas_pdu.length;
|
|
||||||
//
|
|
||||||
// MCC_MNC_TO_PLMNID(eNB_desc_p->mcc, eNB_desc_p->mnc,
|
|
||||||
// &uplink_NAS_transport_p->eutran_cgi.pLMNidentity);
|
|
||||||
// MACRO_ENB_ID_TO_CELL_IDENTITY(eNB_desc_p->eNB_id,
|
|
||||||
// &uplink_NAS_transport_p->eutran_cgi.cell_ID);
|
|
||||||
//
|
|
||||||
// /* MCC/MNC should be repeated in TAI and EUTRAN CGI */
|
|
||||||
// MCC_MNC_TO_PLMNID(eNB_desc_p->mcc, eNB_desc_p->mnc,
|
|
||||||
// &uplink_NAS_transport_p->tai.pLMNidentity);
|
|
||||||
// TAC_TO_ASN1(eNB_desc_p->tac, &uplink_NAS_transport_p->tai.tAC);
|
|
||||||
//
|
|
||||||
// if (s1ap_eNB_encode_pdu(&message, &buffer, &length) < 0) {
|
|
||||||
// S1AP_ERROR("Failed to encode uplink NAS transport\n");
|
|
||||||
// /* Encode procedure has failed... */
|
|
||||||
// return -1;
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// /* UE associated signalling -> use the allocated stream */
|
|
||||||
// if ((ret = sctp_send_msg(&ue_context_p->mme_ref->sctp_data, S1AP_SCTP_PPID,
|
|
||||||
// ue_context_p->stream, buffer, length)) < 0)
|
|
||||||
// {
|
|
||||||
// S1AP_ERROR("[SCTP %d] Failed to send message over SCTP: %d\n",
|
|
||||||
// ue_context_p->mme_ref->sctp_data.assoc_id, ret);
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// free(buffer);
|
|
||||||
// return ret;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// int s1ap_eNB_initial_ctxt_resp(eNB_mme_desc_t *eNB_desc_p,
|
s1ap_message message;
|
||||||
|
|
||||||
|
uint8_t *buffer;
|
||||||
|
uint32_t length;
|
||||||
|
|
||||||
|
DevAssert(s1ap_uplink_nas_p != NULL);
|
||||||
|
|
||||||
|
/* Retrieve the S1AP eNB instance associated with Mod_id */
|
||||||
|
s1ap_eNB_instance_p = s1ap_eNB_get_instance(s1ap_uplink_nas_p->mod_id);
|
||||||
|
DevAssert(s1ap_eNB_instance_p != NULL);
|
||||||
|
|
||||||
|
if ((ue_context_p = s1ap_eNB_get_ue_context(s1ap_eNB_instance_p, s1ap_uplink_nas_p->eNB_ue_s1ap_id)) == NULL)
|
||||||
|
{
|
||||||
|
/* The context for this eNB ue s1ap id doesn't exist in the map of eNB UEs */
|
||||||
|
S1AP_WARN("Failed to find ue context associated with eNB ue s1ap id: %u\n",
|
||||||
|
s1ap_uplink_nas_p->eNB_ue_s1ap_id);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Uplink NAS transport can occur either during an s1ap connected state
|
||||||
|
* or during initial attach (for example: NAS authentication).
|
||||||
|
*/
|
||||||
|
if (!(ue_context_p->ue_state == S1AP_UE_CONNECTED ||
|
||||||
|
ue_context_p->ue_state == S1AP_UE_WAITING_CSR))
|
||||||
|
{
|
||||||
|
S1AP_WARN("You are attempting to send NAS data over non-connected "
|
||||||
|
"eNB ue s1ap id: %u, current state: %d\n",
|
||||||
|
s1ap_uplink_nas_p->eNB_ue_s1ap_id, ue_context_p->ue_state);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Prepare the S1AP message to encode */
|
||||||
|
memset(&message, 0, sizeof(s1ap_message));
|
||||||
|
|
||||||
|
message.direction = S1AP_PDU_PR_initiatingMessage;
|
||||||
|
message.procedureCode = ProcedureCode_id_uplinkNASTransport;
|
||||||
|
|
||||||
|
uplink_NAS_transport_p = &message.msg.uplinkNASTransportIEs;
|
||||||
|
|
||||||
|
uplink_NAS_transport_p->mme_ue_s1ap_id = ue_context_p->mme_ue_s1ap_id;
|
||||||
|
uplink_NAS_transport_p->eNB_UE_S1AP_ID = ue_context_p->eNB_ue_s1ap_id;
|
||||||
|
|
||||||
|
uplink_NAS_transport_p->nas_pdu.buf = s1ap_uplink_nas_p->nas_pdu.buffer;
|
||||||
|
uplink_NAS_transport_p->nas_pdu.size = s1ap_uplink_nas_p->nas_pdu.length;
|
||||||
|
|
||||||
|
MCC_MNC_TO_PLMNID(s1ap_eNB_instance_p->mcc, s1ap_eNB_instance_p->mnc,
|
||||||
|
&uplink_NAS_transport_p->eutran_cgi.pLMNidentity);
|
||||||
|
MACRO_ENB_ID_TO_CELL_IDENTITY(s1ap_eNB_instance_p->eNB_id,
|
||||||
|
&uplink_NAS_transport_p->eutran_cgi.cell_ID);
|
||||||
|
|
||||||
|
/* MCC/MNC should be repeated in TAI and EUTRAN CGI */
|
||||||
|
MCC_MNC_TO_PLMNID(s1ap_eNB_instance_p->mcc, s1ap_eNB_instance_p->mnc,
|
||||||
|
&uplink_NAS_transport_p->tai.pLMNidentity);
|
||||||
|
TAC_TO_ASN1(s1ap_eNB_instance_p->tac, &uplink_NAS_transport_p->tai.tAC);
|
||||||
|
|
||||||
|
if (s1ap_eNB_encode_pdu(&message, &buffer, &length) < 0) {
|
||||||
|
S1AP_ERROR("Failed to encode uplink NAS transport\n");
|
||||||
|
/* Encode procedure has failed... */
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* UE associated signalling -> use the allocated stream */
|
||||||
|
s1ap_eNB_itti_send_sctp_data_req(ue_context_p->mme_ref->assoc_id, buffer,
|
||||||
|
length, ue_context_p->stream);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// int s1ap_eNB_initial_ctxt_resp(eNB_mme_desc_t *s1ap_eNB_instance_p,
|
||||||
// s1ap_initial_ctxt_setup_resp_t *initial_ctxt_resp_p)
|
// s1ap_initial_ctxt_setup_resp_t *initial_ctxt_resp_p)
|
||||||
// {
|
// {
|
||||||
// struct s1ap_eNB_ue_context_s *ue_context_p;
|
// struct s1ap_eNB_ue_context_s *ue_context_p;
|
||||||
@@ -193,9 +323,9 @@ int s1ap_eNB_handle_nas_downlink(uint32_t assoc_id,
|
|||||||
// int i;
|
// int i;
|
||||||
//
|
//
|
||||||
// DevAssert(initial_ctxt_resp_p != NULL);
|
// DevAssert(initial_ctxt_resp_p != NULL);
|
||||||
// DevAssert(eNB_desc_p != NULL);
|
// DevAssert(s1ap_eNB_instance_p != NULL);
|
||||||
//
|
//
|
||||||
// if ((ue_context_p = s1ap_eNB_get_ue_context(eNB_desc_p,
|
// if ((ue_context_p = s1ap_eNB_get_ue_context(s1ap_eNB_instance_p,
|
||||||
// initial_ctxt_resp_p->eNB_ue_s1ap_id)) == NULL)
|
// initial_ctxt_resp_p->eNB_ue_s1ap_id)) == NULL)
|
||||||
// {
|
// {
|
||||||
// /* The context for this eNB ue s1ap id doesn't exist in the map of eNB UEs */
|
// /* The context for this eNB ue s1ap id doesn't exist in the map of eNB UEs */
|
||||||
|
|||||||
@@ -35,6 +35,8 @@ int s1ap_eNB_handle_nas_downlink(uint32_t assoc_id,
|
|||||||
uint32_t stream,
|
uint32_t stream,
|
||||||
struct s1ap_message_s *message_p);
|
struct s1ap_message_s *message_p);
|
||||||
|
|
||||||
|
int s1ap_eNB_handle_nas_first_req(s1ap_nas_first_req_t *s1ap_nas_first_req_p);
|
||||||
|
|
||||||
// int s1ap_eNB_initial_ctxt_resp(eNB_mme_desc_t *eNB_desc_p,
|
// int s1ap_eNB_initial_ctxt_resp(eNB_mme_desc_t *eNB_desc_p,
|
||||||
// s1ap_initial_ctxt_setup_resp_t *initial_ctxt_resp_p);
|
// s1ap_initial_ctxt_setup_resp_t *initial_ctxt_resp_p);
|
||||||
|
|
||||||
|
|||||||
@@ -28,11 +28,6 @@
|
|||||||
|
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
|
|
||||||
/** @defgroup _s1ap_impl_ S1AP Layer Reference Implementation
|
|
||||||
* @ingroup _ref_implementation_
|
|
||||||
* @{
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef S1AP_ENB_NNSF_H_
|
#ifndef S1AP_ENB_NNSF_H_
|
||||||
#define S1AP_ENB_NNSF_H_
|
#define S1AP_ENB_NNSF_H_
|
||||||
|
|
||||||
|
|||||||
@@ -54,9 +54,6 @@
|
|||||||
|
|
||||||
#include "assertions.h"
|
#include "assertions.h"
|
||||||
|
|
||||||
// int s1ap_eNB_handle_overload_start(eNB_mme_desc_t *eNB_desc_p,
|
|
||||||
// sctp_queue_item_t *packet_p,
|
|
||||||
// struct s1ap_message_s *message_p)
|
|
||||||
int s1ap_eNB_handle_overload_start(uint32_t assoc_id,
|
int s1ap_eNB_handle_overload_start(uint32_t assoc_id,
|
||||||
uint32_t stream,
|
uint32_t stream,
|
||||||
struct s1ap_message_s *message_p)
|
struct s1ap_message_s *message_p)
|
||||||
@@ -68,25 +65,24 @@ int s1ap_eNB_handle_overload_start(uint32_t assoc_id,
|
|||||||
|
|
||||||
overload_start_p = &message_p->msg.overloadStartIEs;
|
overload_start_p = &message_p->msg.overloadStartIEs;
|
||||||
|
|
||||||
// DevCheck(overload_start_p->overloadResponse.present ==
|
DevCheck(overload_start_p->overloadResponse.present ==
|
||||||
// OverloadResponse_PR_overloadAction,
|
OverloadResponse_PR_overloadAction,
|
||||||
// OverloadResponse_PR_overloadAction, 0, 0);
|
OverloadResponse_PR_overloadAction, 0, 0);
|
||||||
//
|
|
||||||
// /* Non UE-associated signalling -> stream 0 */
|
/* Non UE-associated signalling -> stream 0 */
|
||||||
// DevCheck(packet_p->local_stream == 0, packet_p->local_stream,
|
DevCheck(stream == 0, stream, 0, 0);
|
||||||
// packet_p->remote_port, packet_p->assoc_id);
|
|
||||||
//
|
if ((mme_desc_p = s1ap_eNB_get_MME(NULL, assoc_id, 0)) == NULL) {
|
||||||
// if ((mme_desc_p = s1ap_eNB_get_MME(eNB_desc_p, packet_p->assoc_id)) == NULL) {
|
/* No MME context associated */
|
||||||
// /* No MME context associated */
|
return -1;
|
||||||
// return -1;
|
}
|
||||||
// }
|
|
||||||
//
|
/* Mark the MME as overloaded and set the overload state according to
|
||||||
// /* Mark the MME as overloaded and set the overload state according to
|
* the value received.
|
||||||
// * the value received.
|
*/
|
||||||
// */
|
mme_desc_p->state = S1AP_ENB_OVERLOAD;
|
||||||
// mme_desc_p->state = S1AP_ENB_OVERLOAD;
|
mme_desc_p->overload_state =
|
||||||
// mme_desc_p->overload_state =
|
overload_start_p->overloadResponse.choice.overloadAction;
|
||||||
// overload_start_p->overloadResponse.choice.overloadAction;
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -94,9 +90,6 @@ int s1ap_eNB_handle_overload_start(uint32_t assoc_id,
|
|||||||
int s1ap_eNB_handle_overload_stop(uint32_t assoc_id,
|
int s1ap_eNB_handle_overload_stop(uint32_t assoc_id,
|
||||||
uint32_t stream,
|
uint32_t stream,
|
||||||
struct s1ap_message_s *message_p)
|
struct s1ap_message_s *message_p)
|
||||||
// int s1ap_eNB_handle_overload_stop(eNB_mme_desc_t *eNB_desc_p,
|
|
||||||
// sctp_queue_item_t *packet_p,
|
|
||||||
// struct s1ap_message_s *message_p)
|
|
||||||
{
|
{
|
||||||
/* We received Overload stop message, meaning that the MME is no more
|
/* We received Overload stop message, meaning that the MME is no more
|
||||||
* overloaded. This is an empty message, with only message header and no
|
* overloaded. This is an empty message, with only message header and no
|
||||||
@@ -105,18 +98,17 @@ int s1ap_eNB_handle_overload_stop(uint32_t assoc_id,
|
|||||||
|
|
||||||
DevAssert(message_p != NULL);
|
DevAssert(message_p != NULL);
|
||||||
|
|
||||||
// s1ap_eNB_mme_data_t *mme_desc_p;
|
s1ap_eNB_mme_data_t *mme_desc_p;
|
||||||
//
|
|
||||||
// /* Non UE-associated signalling -> stream 0 */
|
/* Non UE-associated signalling -> stream 0 */
|
||||||
// DevCheck(packet_p->local_stream == 0, packet_p->local_stream,
|
DevCheck(stream == 0, stream, 0, 0);
|
||||||
// packet_p->remote_port, packet_p->assoc_id);
|
|
||||||
//
|
if ((mme_desc_p = s1ap_eNB_get_MME(NULL, assoc_id, 0)) == NULL) {
|
||||||
// if ((mme_desc_p = s1ap_eNB_get_MME(eNB_desc_p, packet_p->assoc_id)) == NULL) {
|
/* No MME context associated */
|
||||||
// /* No MME context associated */
|
return -1;
|
||||||
// return -1;
|
}
|
||||||
// }
|
|
||||||
//
|
mme_desc_p->state = S1AP_ENB_STATE_CONNECTED;
|
||||||
// mme_desc_p->state = S1AP_ENB_STATE_CONNECTED;
|
mme_desc_p->overload_state = S1AP_NO_OVERLOAD;
|
||||||
// mme_desc_p->overload_state = S1AP_NO_OVERLOAD;
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -30,6 +30,8 @@
|
|||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#include "assertions.h"
|
||||||
|
|
||||||
#include "intertask_interface.h"
|
#include "intertask_interface.h"
|
||||||
|
|
||||||
#include "s1ap_eNB_default_values.h"
|
#include "s1ap_eNB_default_values.h"
|
||||||
@@ -42,95 +44,81 @@
|
|||||||
#include "s1ap_eNB_ue_context.h"
|
#include "s1ap_eNB_ue_context.h"
|
||||||
#include "s1ap_eNB_encoder.h"
|
#include "s1ap_eNB_encoder.h"
|
||||||
#include "s1ap_eNB_trace.h"
|
#include "s1ap_eNB_trace.h"
|
||||||
|
#include "s1ap_eNB_itti_messaging.h"
|
||||||
|
|
||||||
#include "sctp_primitives_client.h"
|
static
|
||||||
|
void s1ap_eNB_generate_trace_failure(struct s1ap_eNB_ue_context_s *ue_desc_p,
|
||||||
|
E_UTRAN_Trace_ID_t *trace_id,
|
||||||
|
Cause_t *cause_p)
|
||||||
|
{
|
||||||
|
s1ap_message message;
|
||||||
|
TraceFailureIndicationIEs_t *trace_failure_p;
|
||||||
|
uint8_t *buffer;
|
||||||
|
uint32_t length;
|
||||||
|
|
||||||
#include "assertions.h"
|
DevAssert(ue_desc_p != NULL);
|
||||||
|
DevAssert(trace_id != NULL);
|
||||||
|
DevAssert(cause_p != NULL);
|
||||||
|
|
||||||
// int s1ap_eNB_generate_trace_failure(sctp_data_t *sctp_data_p,
|
memset(&message, 0, sizeof(s1ap_message));
|
||||||
// int32_t stream,
|
|
||||||
// uint32_t eNB_ue_s1ap_id,
|
trace_failure_p = &message.msg.traceFailureIndicationIEs;
|
||||||
// uint32_t mme_ue_s1ap_id,
|
|
||||||
// E_UTRAN_Trace_ID_t *trace_id,
|
trace_failure_p->mme_ue_s1ap_id = ue_desc_p->mme_ue_s1ap_id;
|
||||||
// Cause_t *cause_p)
|
trace_failure_p->eNB_UE_S1AP_ID = ue_desc_p->eNB_ue_s1ap_id;
|
||||||
// {
|
|
||||||
// s1ap_message message;
|
memcpy(&trace_failure_p->e_UTRAN_Trace_ID, trace_id, sizeof(E_UTRAN_Trace_ID_t));
|
||||||
// TraceFailureIndicationIEs_t *trace_failure_p;
|
memcpy(&trace_failure_p->cause, cause_p, sizeof(Cause_t));
|
||||||
// uint8_t *buffer;
|
|
||||||
// uint32_t length;
|
if (s1ap_eNB_encode_pdu(&message, &buffer, &length) < 0) {
|
||||||
// int ret;
|
return;
|
||||||
//
|
}
|
||||||
// DevAssert(sctp_data_p != NULL);
|
|
||||||
//
|
s1ap_eNB_itti_send_sctp_data_req(ue_desc_p->mme_ref->assoc_id, buffer,
|
||||||
// memset(&message, 0, sizeof(s1ap_message));
|
length, ue_desc_p->stream);
|
||||||
//
|
}
|
||||||
// trace_failure_p = &message.msg.traceFailureIndicationIEs;
|
|
||||||
//
|
|
||||||
// trace_failure_p->mme_ue_s1ap_id = mme_ue_s1ap_id;
|
|
||||||
// trace_failure_p->eNB_UE_S1AP_ID = eNB_ue_s1ap_id;
|
|
||||||
//
|
|
||||||
// memcpy(&trace_failure_p->e_UTRAN_Trace_ID, trace_id, sizeof(E_UTRAN_Trace_ID_t));
|
|
||||||
// memcpy(&trace_failure_p->cause, cause_p, sizeof(Cause_t));
|
|
||||||
//
|
|
||||||
// if (s1ap_eNB_encode_pdu(&message, &buffer, &length) < 0) {
|
|
||||||
// return -1;
|
|
||||||
// }
|
|
||||||
// if ((ret = sctp_send_msg(sctp_data_p, S1AP_SCTP_PPID,
|
|
||||||
// stream, buffer, length)) < 0) {
|
|
||||||
// S1AP_ERROR("Failed to send Trace failure\n");
|
|
||||||
// }
|
|
||||||
// free(buffer);
|
|
||||||
// return ret;
|
|
||||||
// }
|
|
||||||
|
|
||||||
int s1ap_eNB_handle_trace_start(uint32_t assoc_id,
|
int s1ap_eNB_handle_trace_start(uint32_t assoc_id,
|
||||||
uint32_t stream,
|
uint32_t stream,
|
||||||
struct s1ap_message_s *message_p)
|
struct s1ap_message_s *message_p)
|
||||||
// int s1ap_eNB_handle_trace_start(eNB_mme_desc_t *eNB_desc_p,
|
|
||||||
// sctp_queue_item_t *packet_p,
|
|
||||||
// struct s1ap_message_s *message_p)
|
|
||||||
{
|
{
|
||||||
TraceStartIEs_t *trace_start_p;
|
TraceStartIEs_t *trace_start_p;
|
||||||
struct s1ap_eNB_ue_context_s *ue_desc_p;
|
struct s1ap_eNB_ue_context_s *ue_desc_p;
|
||||||
|
struct s1ap_eNB_mme_data_s *mme_ref_p;
|
||||||
|
|
||||||
DevAssert(message_p != NULL);
|
DevAssert(message_p != NULL);
|
||||||
|
|
||||||
trace_start_p = &message_p->msg.traceStartIEs;
|
trace_start_p = &message_p->msg.traceStartIEs;
|
||||||
|
|
||||||
// if ((ue_desc_p = s1ap_eNB_get_ue_context(eNB_desc_p,
|
mme_ref_p = s1ap_eNB_get_MME(NULL, assoc_id, 0);
|
||||||
// trace_start_p->eNB_UE_S1AP_ID)) == NULL) {
|
DevAssert(mme_ref_p != NULL);
|
||||||
// /* Could not find context associated with this eNB_ue_s1ap_id -> generate
|
|
||||||
// * trace failure indication.
|
if ((ue_desc_p = s1ap_eNB_get_ue_context(mme_ref_p->s1ap_eNB_instance,
|
||||||
// */
|
trace_start_p->eNB_UE_S1AP_ID)) == NULL) {
|
||||||
// struct s1ap_eNB_mme_data_s *mme_ref_p;
|
/* Could not find context associated with this eNB_ue_s1ap_id -> generate
|
||||||
// E_UTRAN_Trace_ID_t trace_id;
|
* trace failure indication.
|
||||||
// Cause_t cause;
|
*/
|
||||||
//
|
E_UTRAN_Trace_ID_t trace_id;
|
||||||
// memset(&trace_id, 0, sizeof(E_UTRAN_Trace_ID_t));
|
Cause_t cause;
|
||||||
// memset(&cause, 0, sizeof(Cause_t));
|
|
||||||
// mme_ref_p = s1ap_eNB_get_MME(eNB_desc_p, packet_p->assoc_id);
|
memset(&trace_id, 0, sizeof(E_UTRAN_Trace_ID_t));
|
||||||
//
|
memset(&cause, 0, sizeof(Cause_t));
|
||||||
// cause.present = Cause_PR_radioNetwork;
|
|
||||||
// cause.choice.radioNetwork = CauseRadioNetwork_unknown_pair_ue_s1ap_id;
|
cause.present = Cause_PR_radioNetwork;
|
||||||
//
|
cause.choice.radioNetwork = CauseRadioNetwork_unknown_pair_ue_s1ap_id;
|
||||||
// return s1ap_eNB_generate_trace_failure(&mme_ref_p->sctp_data,
|
|
||||||
// packet_p->local_stream,
|
s1ap_eNB_generate_trace_failure(ue_desc_p, &trace_id, &cause);
|
||||||
// trace_start_p->eNB_UE_S1AP_ID,
|
}
|
||||||
// trace_start_p->mme_ue_s1ap_id, &trace_id, &cause);
|
|
||||||
// }
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int s1ap_eNB_handle_deactivate_trace(uint32_t assoc_id,
|
int s1ap_eNB_handle_deactivate_trace(uint32_t assoc_id,
|
||||||
uint32_t stream,
|
uint32_t stream,
|
||||||
struct s1ap_message_s *message_p)
|
struct s1ap_message_s *message_p)
|
||||||
// int s1ap_eNB_handle_deactivate_trace(eNB_mme_desc_t *eNB_desc_p,
|
|
||||||
// sctp_queue_item_t *packet_p,
|
|
||||||
// struct s1ap_message_s *message_p)
|
|
||||||
{
|
{
|
||||||
DeactivateTraceIEs_t *deactivate_trace_p;
|
// DeactivateTraceIEs_t *deactivate_trace_p;
|
||||||
|
//
|
||||||
deactivate_trace_p = &message_p->msg.deactivateTraceIEs;
|
// deactivate_trace_p = &message_p->msg.deactivateTraceIEs;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user