Commit 117f955d authored by Cedric Roux's avatar Cedric Roux

- 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
parent 7535f20c
......@@ -421,12 +421,6 @@ struct s1ap_message_s;
/** \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)(
uint32_t assoc_id,
uint32_t stream,
......
......@@ -55,69 +55,12 @@
#include "s1ap_eNB_itti_messaging.h"
#include "sctp_primitives_client.h"
#include "assertions.h"
#include "conversions.h"
s1ap_eNB_internal_data_t s1ap_eNB_internal_data;
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;
}
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)
{
char *out;
......@@ -137,55 +80,6 @@ uint32_t s1ap_generate_eNB_id(void)
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,
net_ip_address_t *mme_ip_address,
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));
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;
s1ap_eNB_internal_data.global_cnx_id++;
s1ap_mme_data_p->assoc_id = -1;
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->default_drx = s1ap_register_eNB->default_drx;
STAILQ_INSERT_TAIL(&s1ap_eNB_internal_data.s1ap_eNB_instances_head,
new_instance, s1ap_eNB_entries);
/* Add the new instance to the list of eNB (meaningfull in virtual mode) */
s1ap_eNB_insert_new_instance(new_instance);
S1AP_DEBUG("Registered new eNB with mod_id %u and %s eNB id %u\n",
s1ap_register_eNB->mod_id,
......@@ -322,8 +215,7 @@ void *s1ap_eNB_task(void *arg)
S1AP_DEBUG("Starting S1AP layer\n");
memset(&s1ap_eNB_internal_data, 0, sizeof(s1ap_eNB_internal_data));
STAILQ_INIT(&s1ap_eNB_internal_data.s1ap_eNB_instances_head);
s1ap_eNB_prepare_internal_data();
itti_mark_task_ready(TASK_S1AP);
......@@ -348,6 +240,9 @@ void *s1ap_eNB_task(void *arg)
case SCTP_DATA_IND: {
s1ap_eNB_handle_sctp_data_ind(&received_msg->msg.sctp_data_ind);
} break;
case S1AP_NAS_FIRST_REQ: {
s1ap_eNB_handle_nas_first_req(&received_msg->msg.s1ap_nas_first_req);
} break;
default:
S1AP_ERROR("Received unhandled message with id %d\n",
received_msg->header.messageId);
......@@ -418,123 +313,3 @@ static int s1ap_eNB_generate_s1_setup_request(
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_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 {
uint8_t qci;
......@@ -166,16 +126,6 @@ typedef struct {
// cause_t cause;
} 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 */
struct plmn_identity_s {
uint16_t mcc;
......
......@@ -58,6 +58,7 @@ static
int s1ap_eNB_handle_s1_setup_response(uint32_t assoc_id,
uint32_t stream,
struct s1ap_message_s *message_p);
static
int s1ap_eNB_handle_s1_setup_failure(uint32_t assoc_id,
uint32_t stream,
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);
}
static
int s1ap_eNB_handle_s1_setup_failure(uint32_t assoc_id,
uint32_t stream,
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",
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;
}
// 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
int s1ap_eNB_handle_s1_setup_response(uint32_t assoc_id,
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;
// /* We call back our self
// * -> generate a dummy initial UE message
// */
// {
// extern int s1ap_eNB_handle_api_req(eNB_mme_desc_t *eNB_desc_p,
// s1ap_rrc_api_req_t *api_req_p);
// s1ap_rrc_api_req_t api_req;
// s1ap_nas_first_req_t *nas_req_p;
//
// memset(&api_req, 0, sizeof(s1ap_rrc_api_req_t));
//
// nas_req_p = &api_req.msg.first_nas_req;
// api_req.api_req = S1AP_API_NAS_FIRST_REQ;
//
// nas_req_p->rnti = 0xC03A;
// nas_req_p->establishment_cause = RRC_CAUSE_MO_DATA;
// nas_req_p->ue_identity.present = GUMMEI_PROVIDED;
//
// nas_req_p->ue_identity.identity.gummei.mcc = 208;
// nas_req_p->ue_identity.identity.gummei.mnc = 34;
// nas_req_p->ue_identity.identity.gummei.mme_code = 0;
// nas_req_p->ue_identity.identity.gummei.mme_group_id = 0;
//
// /* NAS Attach request with IMSI */
// uint8_t nas_attach_req_imsi[] =
// {
// 0x07, 0x41,
// /* EPS Mobile identity = IMSI */
// 0x71, 0x08, 0x29, 0x80, 0x43, 0x21, 0x43, 0x65, 0x87,
// 0xF9,
// /* End of EPS Mobile Identity */
// 0x02, 0xE0, 0xE0, 0x00, 0x20, 0x02, 0x03,
// 0xD0, 0x11, 0x27, 0x1A, 0x80, 0x80, 0x21, 0x10, 0x01, 0x00, 0x00,
// 0x10, 0x81, 0x06, 0x00, 0x00, 0x00, 0x00, 0x83, 0x06, 0x00, 0x00,
// 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x0A, 0x00, 0x52, 0x12, 0xF2,
// 0x01, 0x27, 0x11,
// };
//
// /* NAS Attach request with GUTI */
// uint8_t nas_attach_req_guti[] =
// {
// 0x07, 0x41,
// /* EPS Mobile identity = IMSI */
// 0x71, 0x0B, 0xF6, 0x12, 0xF2, 0x01, 0x80, 0x00, 0x01, 0xE0, 0x00,
// 0xDA, 0x1F,
// /* End of EPS Mobile Identity */
// 0x02, 0xE0, 0xE0, 0x00, 0x20, 0x02, 0x03,
// 0xD0, 0x11, 0x27, 0x1A, 0x80, 0x80, 0x21, 0x10, 0x01, 0x00, 0x00,
// 0x10, 0x81, 0x06, 0x00, 0x00, 0x00, 0x00, 0x83, 0x06, 0x00, 0x00,
// 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x0A, 0x00, 0x52, 0x12, 0xF2,
// 0x01, 0x27, 0x11,
// };
//
// 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);
// }
/* We call back our self
* -> generate a dummy initial UE message
*/
{
s1ap_nas_first_req_t s1ap_nas_first_req;
memset(&s1ap_nas_first_req, 0, sizeof(s1ap_nas_first_req_t));
s1ap_nas_first_req.rnti = 0xC03A;
s1ap_nas_first_req.establishment_cause = RRC_CAUSE_MO_DATA;
s1ap_nas_first_req.ue_identity.present = GUMMEI_PROVIDED;
s1ap_nas_first_req.ue_identity.identity.gummei.mcc = 208;
s1ap_nas_first_req.ue_identity.identity.gummei.mnc = 34;
s1ap_nas_first_req.ue_identity.identity.gummei.mme_code = 0;
s1ap_nas_first_req.ue_identity.identity.gummei.mme_group_id = 0;
/* NAS Attach request with IMSI */
uint8_t nas_attach_req_imsi[] =
{
0x07, 0x41,
/* EPS Mobile identity = IMSI */
0x71, 0x08, 0x29, 0x80, 0x43, 0x21, 0x43, 0x65, 0x87,
0xF9,
/* End of EPS Mobile Identity */
0x02, 0xE0, 0xE0, 0x00, 0x20, 0x02, 0x03,
0xD0, 0x11, 0x27, 0x1A, 0x80, 0x80, 0x21, 0x10, 0x01, 0x00, 0x00,
0x10, 0x81, 0x06, 0x00, 0x00, 0x00, 0x00, 0x83, 0x06, 0x00, 0x00,
0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x0A, 0x00, 0x52, 0x12, 0xF2,
0x01, 0x27, 0x11,
};
/* NAS Attach request with GUTI */
uint8_t nas_attach_req_guti[] =
{
0x07, 0x41,
/* EPS Mobile identity = IMSI */
0x71, 0x0B, 0xF6, 0x12, 0xF2, 0x01, 0x80, 0x00, 0x01, 0xE0, 0x00,
0xDA, 0x1F,
/* End of EPS Mobile Identity */
0x02, 0xE0, 0xE0, 0x00, 0x20, 0x02, 0x03,
0xD0, 0x11, 0x27, 0x1A, 0x80, 0x80, 0x21, 0x10, 0x01, 0x00, 0x00,
0x10, 0x81, 0x06, 0x00, 0x00, 0x00, 0x00, 0x83, 0x06, 0x00, 0x00,
0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x0A, 0x00, 0x52, 0x12, 0xF2,
0x01, 0x27, 0x11,
};
s1ap_nas_first_req.nas_pdu.buffer = nas_attach_req_guti;
s1ap_nas_first_req.nas_pdu.length = sizeof(nas_attach_req_guti);
s1ap_eNB_handle_nas_first_req(&s1ap_nas_first_req);
}
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
int s1ap_eNB_handle_initial_context_request(uint32_t assoc_id,
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;
InitialContextSetupRequestIEs_t *initialContextSetupRequest_p;
// DevAssert(eNB_desc_p != NULL);
DevAssert(message_p != NULL);
initialContextSetupRequest_p = &message_p->msg.initialContextSetupRequestIEs;
/* Initial context request = UE-related procedure -> stream != 0 */
if (stream == 0) {
S1AP_ERROR("[SCTP %d] Received UE-related procedure on stream = 0 (%d)\n",
assoc_id, stream);
if ((mme_desc_p = s1ap_eNB_get_MME(NULL, assoc_id, 0)) == NULL) {
S1AP_ERROR("[SCTP %d] Received initial context setup request for non "
"existing MME context\n", assoc_id);
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;
}
// if ((mme_desc_p = s1ap_eNB_get_MME(eNB_desc_p, assoc_id)) == NULL) {
// S1AP_ERROR("[SCTP %d] Received initial context setup request for non "
// "existing MME context\n", packet_p->assoc_id);
// 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;
// }
/* Initial context request = UE-related procedure -> stream != 0 */
if (stream != ue_desc_p->stream) {
S1AP_ERROR("[SCTP %d] Received UE-related procedure on stream (%d) whereas expecting (%d)\n",
assoc_id, stream, ue_desc_p->stream);
return -1;
}
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);
}
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,
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_ */
......@@ -35,17 +35,104 @@
#include "intertask_interface.h"
#include "assertions.h"
// #include "conversions.h"
#include "conversions.h"
#include "s1ap_common.h"
#include "s1ap_ies_defs.h"
#include "s1ap_eNB_defs.h"
#include "s1ap_eNB.h"
#include "s1ap_eNB_encoder.h"
#include "s1ap_eNB_management_procedures.h"
s1ap_eNB_internal_data_t s1ap_eNB_internal_data;
#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,
// s1ap_ue_cap_info_ind_t *ue_cap_info_ind_p)
......
......@@ -31,7 +31,16 @@
#ifndef S1AP_ENB_MANAGEMENT_PROCEDURES_H_
#define S1AP_ENB_MANAGEMENT_PROCEDURES_H_
// int s1ap_eNB_ue_capabilities(eNB_mme_desc_t *eNB_desc_p,
// s1ap_ue_cap_info_ind_t *ue_cap_info_ind_p);
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);
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_ */
......@@ -40,16 +40,142 @@
#include "s1ap_common.h"
#include "s1ap_eNB_defs.h"
#include "s1ap_eNB_itti_messaging.h"
#include "s1ap_ies_defs.h"
#include "s1ap_eNB_encoder.h"
#include "s1ap_eNB_nnsf.h"
#include "s1ap_eNB_ue_context.h"
#include "s1ap_eNB_nas_procedures.h"
#include "s1ap_eNB_management_procedures.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;
}
#include "sctp_primitives_client.h"
/* 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,
uint32_t stream,
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;
s1ap_eNB_mme_data_t *mme_desc_p;
s1ap_eNB_ue_context_t *ue_desc_p;
s1ap_eNB_instance_t *s1ap_eNB_instance;
DevAssert(message_p != NULL);
......@@ -69,117 +196,120 @@ int s1ap_eNB_handle_nas_downlink(uint32_t assoc_id,
return -1;
}
// if ((mme_desc_p = s1ap_eNB_get_MME(eNB_desc_p, assoc_id)) == NULL) {
// S1AP_ERROR("[SCTP %d] Received initial context setup request for non "
// "existing MME context\n", assoc_id);
// return -1;
// }
// if ((ue_desc_p = s1ap_eNB_get_ue_context(eNB_desc_p,
// downlink_NAS_transport_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;
// }
if ((mme_desc_p = s1ap_eNB_get_MME(NULL, assoc_id, 0)) == NULL) {
S1AP_ERROR("[SCTP %d] Received initial context setup request for non "
"existing MME context\n", assoc_id);
return -1;
}
s1ap_eNB_instance = mme_desc_p->s1ap_eNB_instance;
if ((ue_desc_p = s1ap_eNB_get_ue_context(s1ap_eNB_instance,
downlink_NAS_transport_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;
}
/* Is it the first outcome of the MME for this UE ? If so store the mme
* UE s1ap id.
*/
// if (ue_desc_p->mme_ue_s1ap_id == 0) {
// ue_desc_p->mme_ue_s1ap_id = downlink_NAS_transport_p->mme_ue_s1ap_id;
// } else {
// /* 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) {
// S1AP_ERROR("[SCTP %d] Mismatch is MME UE S1AP ID (0x%08x != 0x%08x)\n",
// downlink_NAS_transport_p->mme_ue_s1ap_id,
// ue_desc_p->mme_ue_s1ap_id,
// packet_p->assoc_id);
// }
// }
if (ue_desc_p->mme_ue_s1ap_id == 0) {
ue_desc_p->mme_ue_s1ap_id = downlink_NAS_transport_p->mme_ue_s1ap_id;
} else {
/* 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) {
S1AP_ERROR("[SCTP %d] Mismatch is MME UE S1AP ID (0x%08x != 0x%08x)\n",
downlink_NAS_transport_p->mme_ue_s1ap_id,
ue_desc_p->mme_ue_s1ap_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;
}
// int s1ap_eNB_nas_uplink(eNB_mme_desc_t *eNB_desc_p,
// s1ap_nas_uplink_t *nas_uplink_p)
// {
// struct s1ap_eNB_ue_context_s *ue_context_p;
// UplinkNASTransportIEs_t *uplink_NAS_transport_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_nas_uplink(s1ap_uplink_nas_t *s1ap_uplink_nas_p)
{
struct s1ap_eNB_ue_context_s *ue_context_p;
UplinkNASTransportIEs_t *uplink_NAS_transport_p;
s1ap_eNB_instance_t *s1ap_eNB_instance_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 *eNB_desc_p,
// int s1ap_eNB_initial_ctxt_resp(eNB_mme_desc_t *s1ap_eNB_instance_p,
// s1ap_initial_ctxt_setup_resp_t *initial_ctxt_resp_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;
//
// 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)
// {
// /* 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,
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,
// 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_
#define S1AP_ENB_NNSF_H_
......
......@@ -54,9 +54,6 @@
#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,
uint32_t stream,
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;
// DevCheck(overload_start_p->overloadResponse.present ==
// OverloadResponse_PR_overloadAction,
// OverloadResponse_PR_overloadAction, 0, 0);
//
// /* Non UE-associated signalling -> stream 0 */
// DevCheck(packet_p->local_stream == 0, packet_p->local_stream,
// packet_p->remote_port, packet_p->assoc_id);
//
// if ((mme_desc_p = s1ap_eNB_get_MME(eNB_desc_p, packet_p->assoc_id)) == NULL) {
// /* No MME context associated */
// return -1;
// }
//
// /* Mark the MME as overloaded and set the overload state according to
// * the value received.
// */
// mme_desc_p->state = S1AP_ENB_OVERLOAD;
// mme_desc_p->overload_state =
// overload_start_p->overloadResponse.choice.overloadAction;
DevCheck(overload_start_p->overloadResponse.present ==
OverloadResponse_PR_overloadAction,
OverloadResponse_PR_overloadAction, 0, 0);
/* Non UE-associated signalling -> stream 0 */
DevCheck(stream == 0, stream, 0, 0);
if ((mme_desc_p = s1ap_eNB_get_MME(NULL, assoc_id, 0)) == NULL) {
/* No MME context associated */
return -1;
}
/* Mark the MME as overloaded and set the overload state according to
* the value received.
*/
mme_desc_p->state = S1AP_ENB_OVERLOAD;
mme_desc_p->overload_state =
overload_start_p->overloadResponse.choice.overloadAction;
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,
uint32_t stream,
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
* 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);
// s1ap_eNB_mme_data_t *mme_desc_p;
//
// /* Non UE-associated signalling -> stream 0 */
// DevCheck(packet_p->local_stream == 0, packet_p->local_stream,
// packet_p->remote_port, packet_p->assoc_id);
//
// if ((mme_desc_p = s1ap_eNB_get_MME(eNB_desc_p, packet_p->assoc_id)) == NULL) {
// /* No MME context associated */
// return -1;
// }
//
// mme_desc_p->state = S1AP_ENB_STATE_CONNECTED;
// mme_desc_p->overload_state = S1AP_NO_OVERLOAD;
s1ap_eNB_mme_data_t *mme_desc_p;
/* Non UE-associated signalling -> stream 0 */
DevCheck(stream == 0, stream, 0, 0);
if ((mme_desc_p = s1ap_eNB_get_MME(NULL, assoc_id, 0)) == NULL) {
/* No MME context associated */
return -1;
}
mme_desc_p->state = S1AP_ENB_STATE_CONNECTED;
mme_desc_p->overload_state = S1AP_NO_OVERLOAD;
return 0;
}
......@@ -30,6 +30,8 @@
#include <stdint.h>
#include "assertions.h"
#include "intertask_interface.h"
#include "s1ap_eNB_default_values.h"
......@@ -42,95 +44,81 @@
#include "s1ap_eNB_ue_context.h"
#include "s1ap_eNB_encoder.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,
// int32_t stream,
// uint32_t eNB_ue_s1ap_id,
// uint32_t mme_ue_s1ap_id,
// 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;
// int ret;
//
// DevAssert(sctp_data_p != NULL);
//
// memset(&message, 0, sizeof(s1ap_message));
//
// 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;
// }
memset(&message, 0, sizeof(s1ap_message));
trace_failure_p = &message.msg.traceFailureIndicationIEs;
trace_failure_p->mme_ue_s1ap_id = ue_desc_p->mme_ue_s1ap_id;
trace_failure_p->eNB_UE_S1AP_ID = ue_desc_p->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;
}
s1ap_eNB_itti_send_sctp_data_req(ue_desc_p->mme_ref->assoc_id, buffer,
length, ue_desc_p->stream);
}
int s1ap_eNB_handle_trace_start(uint32_t assoc_id,
uint32_t stream,
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;
struct s1ap_eNB_ue_context_s *ue_desc_p;
struct s1ap_eNB_mme_data_s *mme_ref_p;
DevAssert(message_p != NULL);
trace_start_p = &message_p->msg.traceStartIEs;
// if ((ue_desc_p = s1ap_eNB_get_ue_context(eNB_desc_p,
// trace_start_p->eNB_UE_S1AP_ID)) == NULL) {
// /* Could not find context associated with this eNB_ue_s1ap_id -> generate
// * trace failure indication.
// */
// struct s1ap_eNB_mme_data_s *mme_ref_p;
// E_UTRAN_Trace_ID_t trace_id;
// Cause_t cause;
//
// memset(&trace_id, 0, sizeof(E_UTRAN_Trace_ID_t));
// memset(&cause, 0, sizeof(Cause_t));
// mme_ref_p = s1ap_eNB_get_MME(eNB_desc_p, packet_p->assoc_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,
// trace_start_p->eNB_UE_S1AP_ID,
// trace_start_p->mme_ue_s1ap_id, &trace_id, &cause);
// }
mme_ref_p = s1ap_eNB_get_MME(NULL, assoc_id, 0);
DevAssert(mme_ref_p != NULL);
if ((ue_desc_p = s1ap_eNB_get_ue_context(mme_ref_p->s1ap_eNB_instance,
trace_start_p->eNB_UE_S1AP_ID)) == NULL) {
/* Could not find context associated with this eNB_ue_s1ap_id -> generate
* trace failure indication.
*/
E_UTRAN_Trace_ID_t trace_id;
Cause_t cause;
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;
s1ap_eNB_generate_trace_failure(ue_desc_p, &trace_id, &cause);
}
return 0;
}
int s1ap_eNB_handle_deactivate_trace(uint32_t assoc_id,
uint32_t stream,
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;
deactivate_trace_p = &message_p->msg.deactivateTraceIEs;
// DeactivateTraceIEs_t *deactivate_trace_p;
//
// deactivate_trace_p = &message_p->msg.deactivateTraceIEs;
return 0;
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment