Create ngap files
This commit is contained in:
@@ -226,6 +226,7 @@ typedef enum {
|
|||||||
X2AP,
|
X2AP,
|
||||||
M2AP,
|
M2AP,
|
||||||
M3AP,
|
M3AP,
|
||||||
|
NGAP,
|
||||||
GNB_APP,
|
GNB_APP,
|
||||||
NR_RRC,
|
NR_RRC,
|
||||||
NR_MAC,
|
NR_MAC,
|
||||||
|
|||||||
@@ -0,0 +1,82 @@
|
|||||||
|
/*
|
||||||
|
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
|
||||||
|
* contributor license agreements. See the NOTICE file distributed with
|
||||||
|
* this work for additional information regarding copyright ownership.
|
||||||
|
* The OpenAirInterface Software Alliance licenses this file to You under
|
||||||
|
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
|
||||||
|
* except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.openairinterface.org/?page_id=698
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*-------------------------------------------------------------------------------
|
||||||
|
* For more information about the OpenAirInterface (OAI) Software Alliance:
|
||||||
|
* contact@openairinterface.org
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Messages for NGAP logging */
|
||||||
|
MESSAGE_DEF(NGAP_UPLINK_NAS_LOG , MESSAGE_PRIORITY_MED, IttiMsgText , ngap_uplink_nas_log)
|
||||||
|
MESSAGE_DEF(NGAP_UE_CAPABILITY_IND_LOG , MESSAGE_PRIORITY_MED, IttiMsgText , ngap_ue_capability_ind_log)
|
||||||
|
MESSAGE_DEF(NGAP_INITIAL_CONTEXT_SETUP_LOG , MESSAGE_PRIORITY_MED, IttiMsgText , ngap_initial_context_setup_log)
|
||||||
|
MESSAGE_DEF(NGAP_NAS_NON_DELIVERY_IND_LOG , MESSAGE_PRIORITY_MED, IttiMsgText , ngap_nas_non_delivery_ind_log)
|
||||||
|
MESSAGE_DEF(NGAP_DOWNLINK_NAS_LOG , MESSAGE_PRIORITY_MED, IttiMsgText , ngap_downlink_nas_log)
|
||||||
|
MESSAGE_DEF(NGAP_S1_SETUP_LOG , MESSAGE_PRIORITY_MED, IttiMsgText , ngap_s1_setup_log)
|
||||||
|
MESSAGE_DEF(NGAP_INITIAL_UE_MESSAGE_LOG , MESSAGE_PRIORITY_MED, IttiMsgText , ngap_initial_ue_message_log)
|
||||||
|
MESSAGE_DEF(NGAP_UE_CONTEXT_RELEASE_REQ_LOG, MESSAGE_PRIORITY_MED, IttiMsgText , ngap_ue_context_release_req_log)
|
||||||
|
MESSAGE_DEF(NGAP_UE_CONTEXT_RELEASE_COMMAND_LOG, MESSAGE_PRIORITY_MED, IttiMsgText , ngap_ue_context_release_command_log)
|
||||||
|
MESSAGE_DEF(NGAP_UE_CONTEXT_RELEASE_COMPLETE_LOG, MESSAGE_PRIORITY_MED, IttiMsgText , ngap_ue_context_release_complete_log)
|
||||||
|
MESSAGE_DEF(NGAP_UE_CONTEXT_RELEASE_LOG , MESSAGE_PRIORITY_MED, IttiMsgText , ngap_ue_context_release_log)
|
||||||
|
MESSAGE_DEF(NGAP_E_RAB_SETUP_REQUEST_LOG , MESSAGE_PRIORITY_MED, IttiMsgText , ngap_e_rab_setup_request_log)
|
||||||
|
MESSAGE_DEF(NGAP_E_RAB_SETUP_RESPONSE_LOG , MESSAGE_PRIORITY_MED, IttiMsgText , ngap_e_rab_setup_response_log)
|
||||||
|
MESSAGE_DEF(NGAP_E_RAB_MODIFY_REQUEST_LOG , MESSAGE_PRIORITY_MED, IttiMsgText , ngap_e_rab_modify_request_log)
|
||||||
|
MESSAGE_DEF(NGAP_E_RAB_MODIFY_RESPONSE_LOG , MESSAGE_PRIORITY_MED, IttiMsgText , ngap_e_rab_modify_response_log)
|
||||||
|
MESSAGE_DEF(NGAP_PAGING_LOG , MESSAGE_PRIORITY_MED, IttiMsgText , ngap_paging_log)
|
||||||
|
MESSAGE_DEF(NGAP_E_RAB_RELEASE_REQUEST_LOG , MESSAGE_PRIORITY_MED, IttiMsgText , ngap_e_rab_release_request_log)
|
||||||
|
MESSAGE_DEF(NGAP_E_RAB_RELEASE_RESPONSE_LOG , MESSAGE_PRIORITY_MED, IttiMsgText , ngap_e_rab_release_response_log)
|
||||||
|
MESSAGE_DEF(NGAP_ERROR_INDICATION_LOG , MESSAGE_PRIORITY_MED, IttiMsgText , ngap_error_indication_log)
|
||||||
|
MESSAGE_DEF(NGAP_PATH_SWITCH_REQ_LOG , MESSAGE_PRIORITY_MED, IttiMsgText , ngap_path_switch_req_log)
|
||||||
|
MESSAGE_DEF(NGAP_PATH_SWITCH_REQ_ACK_LOG , MESSAGE_PRIORITY_MED, IttiMsgText , ngap_path_switch_req_ack_log)
|
||||||
|
|
||||||
|
/* gNB application layer -> NGAP messages */
|
||||||
|
MESSAGE_DEF(NGAP_REGISTER_GNB_REQ , MESSAGE_PRIORITY_MED, ngap_register_enb_req_t , ngap_register_enb_req)
|
||||||
|
|
||||||
|
/* NGAP -> gNB application layer messages */
|
||||||
|
MESSAGE_DEF(NGAP_REGISTER_GNB_CNF , MESSAGE_PRIORITY_MED, ngap_register_enb_cnf_t , ngap_register_enb_cnf)
|
||||||
|
MESSAGE_DEF(NGAP_DEREGISTERED_GNB_IND , MESSAGE_PRIORITY_MED, ngap_deregistered_enb_ind_t , ngap_deregistered_enb_ind)
|
||||||
|
|
||||||
|
/* RRC -> NGAP messages */
|
||||||
|
MESSAGE_DEF(NGAP_NAS_FIRST_REQ , MESSAGE_PRIORITY_MED, ngap_nas_first_req_t , ngap_nas_first_req)
|
||||||
|
MESSAGE_DEF(NGAP_UPLINK_NAS , MESSAGE_PRIORITY_MED, ngap_uplink_nas_t , ngap_uplink_nas)
|
||||||
|
MESSAGE_DEF(NGAP_UE_CAPABILITIES_IND , MESSAGE_PRIORITY_MED, ngap_ue_cap_info_ind_t , ngap_ue_cap_info_ind)
|
||||||
|
MESSAGE_DEF(NGAP_INITIAL_CONTEXT_SETUP_RESP, MESSAGE_PRIORITY_MED, ngap_initial_context_setup_resp_t, ngap_initial_context_setup_resp)
|
||||||
|
MESSAGE_DEF(NGAP_INITIAL_CONTEXT_SETUP_FAIL, MESSAGE_PRIORITY_MED, ngap_initial_context_setup_fail_t, ngap_initial_context_setup_fail)
|
||||||
|
MESSAGE_DEF(NGAP_NAS_NON_DELIVERY_IND , MESSAGE_PRIORITY_MED, ngap_nas_non_delivery_ind_t , ngap_nas_non_delivery_ind)
|
||||||
|
MESSAGE_DEF(NGAP_UE_CONTEXT_RELEASE_RESP , MESSAGE_PRIORITY_MED, ngap_ue_release_resp_t , ngap_ue_release_resp)
|
||||||
|
MESSAGE_DEF(NGAP_UE_CONTEXT_RELEASE_COMPLETE, MESSAGE_PRIORITY_MED, ngap_ue_release_complete_t , ngap_ue_release_complete)
|
||||||
|
MESSAGE_DEF(NGAP_UE_CTXT_MODIFICATION_RESP , MESSAGE_PRIORITY_MED, ngap_ue_ctxt_modification_resp_t , ngap_ue_ctxt_modification_resp)
|
||||||
|
MESSAGE_DEF(NGAP_UE_CTXT_MODIFICATION_FAIL , MESSAGE_PRIORITY_MED, ngap_ue_ctxt_modification_fail_t , ngap_ue_ctxt_modification_fail)
|
||||||
|
MESSAGE_DEF(NGAP_E_RAB_SETUP_RESP , MESSAGE_PRIORITY_MED, ngap_e_rab_setup_resp_t , ngap_e_rab_setup_resp)
|
||||||
|
MESSAGE_DEF(NGAP_E_RAB_SETUP_REQUEST_FAIL , MESSAGE_PRIORITY_MED, ngap_e_rab_setup_req_fail_t , ngap_e_rab_setup_request_fail)
|
||||||
|
MESSAGE_DEF(NGAP_E_RAB_MODIFY_RESP , MESSAGE_PRIORITY_MED, ngap_e_rab_modify_resp_t , ngap_e_rab_modify_resp)
|
||||||
|
MESSAGE_DEF(NGAP_E_RAB_RELEASE_RESPONSE , MESSAGE_PRIORITY_MED, ngap_e_rab_release_resp_t , ngap_e_rab_release_resp)
|
||||||
|
MESSAGE_DEF(NGAP_PATH_SWITCH_REQ , MESSAGE_PRIORITY_MED, ngap_path_switch_req_t , ngap_path_switch_req)
|
||||||
|
MESSAGE_DEF(NGAP_PATH_SWITCH_REQ_ACK , MESSAGE_PRIORITY_MED, ngap_path_switch_req_ack_t , ngap_path_switch_req_ack)
|
||||||
|
MESSAGE_DEF(NGAP_E_RAB_MODIFICATION_IND , MESSAGE_PRIORITY_MED, ngap_e_rab_modification_ind_t , ngap_e_rab_modification_ind)
|
||||||
|
|
||||||
|
/* NGAP -> RRC messages */
|
||||||
|
MESSAGE_DEF(NGAP_DOWNLINK_NAS , MESSAGE_PRIORITY_MED, ngap_downlink_nas_t , ngap_downlink_nas )
|
||||||
|
MESSAGE_DEF(NGAP_INITIAL_CONTEXT_SETUP_REQ , MESSAGE_PRIORITY_MED, ngap_initial_context_setup_req_t , ngap_initial_context_setup_req )
|
||||||
|
MESSAGE_DEF(NGAP_UE_CTXT_MODIFICATION_REQ , MESSAGE_PRIORITY_MED, ngap_ue_ctxt_modification_req_t , ngap_ue_ctxt_modification_req)
|
||||||
|
MESSAGE_DEF(NGAP_PAGING_IND , MESSAGE_PRIORITY_MED, ngap_paging_ind_t , ngap_paging_ind )
|
||||||
|
MESSAGE_DEF(NGAP_E_RAB_SETUP_REQ , MESSAGE_PRIORITY_MED, ngap_e_rab_setup_req_t , ngap_e_rab_setup_req )
|
||||||
|
MESSAGE_DEF(NGAP_E_RAB_MODIFY_REQ , MESSAGE_PRIORITY_MED, ngap_e_rab_modify_req_t , ngap_e_rab_modify_req )
|
||||||
|
MESSAGE_DEF(NGAP_E_RAB_RELEASE_COMMAND , MESSAGE_PRIORITY_MED, ngap_e_rab_release_command_t , ngap_e_rab_release_command)
|
||||||
|
MESSAGE_DEF(NGAP_UE_CONTEXT_RELEASE_COMMAND, MESSAGE_PRIORITY_MED, ngap_ue_release_command_t , ngap_ue_release_command)
|
||||||
|
|
||||||
|
/* NGAP <-> RRC messages (can be initiated either by MME or gNB) */
|
||||||
|
MESSAGE_DEF(NGAP_UE_CONTEXT_RELEASE_REQ , MESSAGE_PRIORITY_MED, ngap_ue_release_req_t , ngap_ue_release_req)
|
||||||
@@ -0,0 +1,771 @@
|
|||||||
|
/*
|
||||||
|
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
|
||||||
|
* contributor license agreements. See the NOTICE file distributed with
|
||||||
|
* this work for additional information regarding copyright ownership.
|
||||||
|
* The OpenAirInterface Software Alliance licenses this file to You under
|
||||||
|
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
|
||||||
|
* except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.openairinterface.org/?page_id=698
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*-------------------------------------------------------------------------------
|
||||||
|
* For more information about the OpenAirInterface (OAI) Software Alliance:
|
||||||
|
* contact@openairinterface.org
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef NGAP_MESSAGES_TYPES_H_
|
||||||
|
#define NGAP_MESSAGES_TYPES_H_
|
||||||
|
|
||||||
|
#include "LTE_asn_constant.h"
|
||||||
|
//-------------------------------------------------------------------------------------------//
|
||||||
|
// Defines to access message fields.
|
||||||
|
|
||||||
|
#define NGAP_REGISTER_GNB_REQ(mSGpTR) (mSGpTR)->ittiMsg.ngap_register_enb_req
|
||||||
|
|
||||||
|
#define NGAP_REGISTER_GNB_CNF(mSGpTR) (mSGpTR)->ittiMsg.ngap_register_enb_cnf
|
||||||
|
#define NGAP_DEREGISTERED_GNB_IND(mSGpTR) (mSGpTR)->ittiMsg.ngap_deregistered_enb_ind
|
||||||
|
|
||||||
|
#define NGAP_NAS_FIRST_REQ(mSGpTR) (mSGpTR)->ittiMsg.ngap_nas_first_req
|
||||||
|
#define NGAP_UPLINK_NAS(mSGpTR) (mSGpTR)->ittiMsg.ngap_uplink_nas
|
||||||
|
#define NGAP_UE_CAPABILITIES_IND(mSGpTR) (mSGpTR)->ittiMsg.ngap_ue_cap_info_ind
|
||||||
|
#define NGAP_INITIAL_CONTEXT_SETUP_RESP(mSGpTR) (mSGpTR)->ittiMsg.ngap_initial_context_setup_resp
|
||||||
|
#define NGAP_INITIAL_CONTEXT_SETUP_FAIL(mSGpTR) (mSGpTR)->ittiMsg.ngap_initial_context_setup_fail
|
||||||
|
#define NGAP_UE_CONTEXT_RELEASE_RESP(mSGpTR) (mSGpTR)->ittiMsg.ngap_ue_release_resp
|
||||||
|
#define NGAP_NAS_NON_DELIVERY_IND(mSGpTR) (mSGpTR)->ittiMsg.ngap_nas_non_delivery_ind
|
||||||
|
#define NGAP_UE_CTXT_MODIFICATION_RESP(mSGpTR) (mSGpTR)->ittiMsg.ngap_ue_ctxt_modification_resp
|
||||||
|
#define NGAP_UE_CTXT_MODIFICATION_FAIL(mSGpTR) (mSGpTR)->ittiMsg.ngap_ue_ctxt_modification_fail
|
||||||
|
#define NGAP_E_RAB_SETUP_RESP(mSGpTR) (mSGpTR)->ittiMsg.ngap_e_rab_setup_resp
|
||||||
|
#define NGAP_E_RAB_SETUP_FAIL(mSGpTR) (mSGpTR)->ittiMsg.ngap_e_rab_setup_req_fail
|
||||||
|
#define NGAP_E_RAB_MODIFY_RESP(mSGpTR) (mSGpTR)->ittiMsg.ngap_e_rab_modify_resp
|
||||||
|
#define NGAP_PATH_SWITCH_REQ(mSGpTR) (mSGpTR)->ittiMsg.ngap_path_switch_req
|
||||||
|
#define NGAP_PATH_SWITCH_REQ_ACK(mSGpTR) (mSGpTR)->ittiMsg.ngap_path_switch_req_ack
|
||||||
|
#define NGAP_E_RAB_MODIFICATION_IND(mSGpTR) (mSGpTR)->ittiMsg.ngap_e_rab_modification_ind
|
||||||
|
|
||||||
|
#define NGAP_DOWNLINK_NAS(mSGpTR) (mSGpTR)->ittiMsg.ngap_downlink_nas
|
||||||
|
#define NGAP_INITIAL_CONTEXT_SETUP_REQ(mSGpTR) (mSGpTR)->ittiMsg.ngap_initial_context_setup_req
|
||||||
|
#define NGAP_UE_CTXT_MODIFICATION_REQ(mSGpTR) (mSGpTR)->ittiMsg.ngap_ue_ctxt_modification_req
|
||||||
|
#define NGAP_UE_CONTEXT_RELEASE_COMMAND(mSGpTR) (mSGpTR)->ittiMsg.ngap_ue_release_command
|
||||||
|
#define NGAP_UE_CONTEXT_RELEASE_COMPLETE(mSGpTR) (mSGpTR)->ittiMsg.ngap_ue_release_complete
|
||||||
|
#define NGAP_E_RAB_SETUP_REQ(mSGpTR) (mSGpTR)->ittiMsg.ngap_e_rab_setup_req
|
||||||
|
#define NGAP_E_RAB_MODIFY_REQ(mSGpTR) (mSGpTR)->ittiMsg.ngap_e_rab_modify_req
|
||||||
|
#define NGAP_PAGING_IND(mSGpTR) (mSGpTR)->ittiMsg.ngap_paging_ind
|
||||||
|
|
||||||
|
#define NGAP_UE_CONTEXT_RELEASE_REQ(mSGpTR) (mSGpTR)->ittiMsg.ngap_ue_release_req
|
||||||
|
#define NGAP_E_RAB_RELEASE_COMMAND(mSGpTR) (mSGpTR)->ittiMsg.ngap_e_rab_release_command
|
||||||
|
#define NGAP_E_RAB_RELEASE_RESPONSE(mSGpTR) (mSGpTR)->ittiMsg.ngap_e_rab_release_resp
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------------------------------//
|
||||||
|
/* Maximum number of e-rabs to be setup/deleted in a single message.
|
||||||
|
* Even if only one bearer will be modified by message.
|
||||||
|
*/
|
||||||
|
#define NGAP_MAX_E_RAB (LTE_maxDRB + 3)
|
||||||
|
|
||||||
|
/* Length of the transport layer address string
|
||||||
|
* 160 bits / 8 bits by char.
|
||||||
|
*/
|
||||||
|
#define NGAP_TRANSPORT_LAYER_ADDRESS_SIZE (160 / 8)
|
||||||
|
|
||||||
|
#define NGAP_MAX_NB_MME_IP_ADDRESS 10
|
||||||
|
#define NGAP_IMSI_LENGTH 16
|
||||||
|
|
||||||
|
/* Security key length used within gNB
|
||||||
|
* Even if only 16 bytes will be effectively used,
|
||||||
|
* the key length is 32 bytes (256 bits)
|
||||||
|
*/
|
||||||
|
#define SECURITY_KEY_LENGTH 32
|
||||||
|
typedef enum cell_type_e {
|
||||||
|
CELL_MACRO_GNB,
|
||||||
|
CELL_HOME_GNB,
|
||||||
|
CELL_MACRO_GNB
|
||||||
|
} cell_type_t;
|
||||||
|
|
||||||
|
typedef enum paging_drx_e {
|
||||||
|
PAGING_DRX_32 = 0x0,
|
||||||
|
PAGING_DRX_64 = 0x1,
|
||||||
|
PAGING_DRX_128 = 0x2,
|
||||||
|
PAGING_DRX_256 = 0x3
|
||||||
|
} paging_drx_t;
|
||||||
|
|
||||||
|
/* Lower value codepoint
|
||||||
|
* indicates higher priority.
|
||||||
|
*/
|
||||||
|
typedef enum paging_priority_s {
|
||||||
|
PAGING_PRIO_LEVEL1 = 0,
|
||||||
|
PAGING_PRIO_LEVEL2 = 1,
|
||||||
|
PAGING_PRIO_LEVEL3 = 2,
|
||||||
|
PAGING_PRIO_LEVEL4 = 3,
|
||||||
|
PAGING_PRIO_LEVEL5 = 4,
|
||||||
|
PAGING_PRIO_LEVEL6 = 5,
|
||||||
|
PAGING_PRIO_LEVEL7 = 6,
|
||||||
|
PAGING_PRIO_LEVEL8 = 7
|
||||||
|
} paging_priority_t;
|
||||||
|
|
||||||
|
typedef enum cn_domain_s {
|
||||||
|
CN_DOMAIN_PS = 1,
|
||||||
|
CN_DOMAIN_CS = 2
|
||||||
|
} cn_domain_t;
|
||||||
|
|
||||||
|
typedef struct net_ip_address_s {
|
||||||
|
unsigned ipv4:1;
|
||||||
|
unsigned ipv6:1;
|
||||||
|
char ipv4_address[16];
|
||||||
|
char ipv6_address[46];
|
||||||
|
} net_ip_address_t;
|
||||||
|
|
||||||
|
typedef uint64_t bitrate_t;
|
||||||
|
|
||||||
|
typedef struct ambr_s {
|
||||||
|
bitrate_t br_ul;
|
||||||
|
bitrate_t br_dl;
|
||||||
|
} ambr_t;
|
||||||
|
|
||||||
|
typedef enum priority_level_s {
|
||||||
|
PRIORITY_LEVEL_SPARE = 0,
|
||||||
|
PRIORITY_LEVEL_HIGHEST = 1,
|
||||||
|
PRIORITY_LEVEL_LOWEST = 14,
|
||||||
|
PRIORITY_LEVEL_NO_PRIORITY = 15
|
||||||
|
} priority_level_t;
|
||||||
|
|
||||||
|
typedef enum pre_emp_capability_e {
|
||||||
|
PRE_EMPTION_CAPABILITY_ENABLED = 0,
|
||||||
|
PRE_EMPTION_CAPABILITY_DISABLED = 1,
|
||||||
|
PRE_EMPTION_CAPABILITY_MAX,
|
||||||
|
} pre_emp_capability_t;
|
||||||
|
|
||||||
|
typedef enum pre_emp_vulnerability_e {
|
||||||
|
PRE_EMPTION_VULNERABILITY_ENABLED = 0,
|
||||||
|
PRE_EMPTION_VULNERABILITY_DISABLED = 1,
|
||||||
|
PRE_EMPTION_VULNERABILITY_MAX,
|
||||||
|
} pre_emp_vulnerability_t;
|
||||||
|
|
||||||
|
typedef struct allocation_retention_priority_s {
|
||||||
|
priority_level_t priority_level;
|
||||||
|
pre_emp_capability_t pre_emp_capability;
|
||||||
|
pre_emp_vulnerability_t pre_emp_vulnerability;
|
||||||
|
} allocation_retention_priority_t;
|
||||||
|
|
||||||
|
typedef struct security_capabilities_s {
|
||||||
|
uint16_t encryption_algorithms;
|
||||||
|
uint16_t integrity_algorithms;
|
||||||
|
} security_capabilities_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_establishment_cause_e {
|
||||||
|
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,
|
||||||
|
#if defined(UPDATE_RELEASE_10)
|
||||||
|
RRC_CAUSE_DELAY_TOLERANT_ACCESS = 0x5,
|
||||||
|
#endif
|
||||||
|
RRC_CAUSE_LAST
|
||||||
|
} rrc_establishment_cause_t;
|
||||||
|
|
||||||
|
typedef struct ngap_gummei_s {
|
||||||
|
uint16_t mcc;
|
||||||
|
uint16_t mnc;
|
||||||
|
uint8_t mnc_len;
|
||||||
|
uint8_t mme_code;
|
||||||
|
uint16_t mme_group_id;
|
||||||
|
} ngap_gummei_t;
|
||||||
|
|
||||||
|
typedef struct ngap_imsi_s {
|
||||||
|
uint8_t buffer[NGAP_IMSI_LENGTH];
|
||||||
|
uint8_t length;
|
||||||
|
} ngap_imsi_t;
|
||||||
|
|
||||||
|
typedef struct s_tmsi_s {
|
||||||
|
uint8_t mme_code;
|
||||||
|
uint32_t m_tmsi;
|
||||||
|
} s_tmsi_t;
|
||||||
|
|
||||||
|
typedef enum ue_paging_identity_presenceMask_e {
|
||||||
|
UE_PAGING_IDENTITY_NONE = 0,
|
||||||
|
UE_PAGING_IDENTITY_imsi = (1 << 1),
|
||||||
|
UE_PAGING_IDENTITY_s_tmsi = (1 << 2),
|
||||||
|
} ue_paging_identity_presenceMask_t;
|
||||||
|
|
||||||
|
typedef struct ue_paging_identity_s {
|
||||||
|
ue_paging_identity_presenceMask_t presenceMask;
|
||||||
|
union {
|
||||||
|
ngap_imsi_t imsi;
|
||||||
|
s_tmsi_t s_tmsi;
|
||||||
|
} choice;
|
||||||
|
} ue_paging_identity_t;
|
||||||
|
|
||||||
|
typedef enum ue_identities_presenceMask_e {
|
||||||
|
UE_IDENTITIES_NONE = 0,
|
||||||
|
UE_IDENTITIES_s_tmsi = 1 << 1,
|
||||||
|
UE_IDENTITIES_gummei = 1 << 2,
|
||||||
|
} ue_identities_presenceMask_t;
|
||||||
|
|
||||||
|
typedef struct ue_identity_s {
|
||||||
|
ue_identities_presenceMask_t presenceMask;
|
||||||
|
s_tmsi_t s_tmsi;
|
||||||
|
ngap_gummei_t gummei;
|
||||||
|
} ue_identity_t;
|
||||||
|
|
||||||
|
typedef struct nas_pdu_s {
|
||||||
|
/* Octet string data */
|
||||||
|
uint8_t *buffer;
|
||||||
|
/* Length of the octet string */
|
||||||
|
uint32_t length;
|
||||||
|
} nas_pdu_t, ue_radio_cap_t;
|
||||||
|
|
||||||
|
typedef struct transport_layer_addr_s {
|
||||||
|
/* Length of the transport layer address buffer in bits. NGAP layer received a
|
||||||
|
* bit string<1..160> containing one of the following addresses: ipv4,
|
||||||
|
* ipv6, or ipv4 and ipv6. The layer doesn't interpret the buffer but
|
||||||
|
* silently forward it to S1-U.
|
||||||
|
*/
|
||||||
|
uint8_t length;
|
||||||
|
uint8_t buffer[20]; // in network byte order
|
||||||
|
} transport_layer_addr_t;
|
||||||
|
|
||||||
|
#define TRANSPORT_LAYER_ADDR_COPY(dEST,sOURCE) \
|
||||||
|
do { \
|
||||||
|
AssertFatal(sOURCE.len <= 20); \
|
||||||
|
memcpy(dEST.buffer, sOURCE.buffer, sOURCE.len); \
|
||||||
|
dEST.length = sOURCE.length; \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
typedef struct e_rab_level_qos_parameter_s {
|
||||||
|
uint8_t qci;
|
||||||
|
|
||||||
|
allocation_retention_priority_t allocation_retention_priority;
|
||||||
|
} e_rab_level_qos_parameter_t;
|
||||||
|
|
||||||
|
typedef struct e_rab_s {
|
||||||
|
/* Unique e_rab_id for the UE. */
|
||||||
|
uint8_t e_rab_id;
|
||||||
|
/* Quality of service for this e_rab */
|
||||||
|
e_rab_level_qos_parameter_t qos;
|
||||||
|
/* The NAS PDU should be forwarded by the RRC layer to the NAS layer */
|
||||||
|
nas_pdu_t nas_pdu;
|
||||||
|
/* The transport layer address for the IP packets */
|
||||||
|
transport_layer_addr_t sgw_addr;
|
||||||
|
/* S-GW Tunnel endpoint identifier */
|
||||||
|
uint32_t gtp_teid;
|
||||||
|
} e_rab_t;
|
||||||
|
|
||||||
|
typedef struct e_rab_setup_s {
|
||||||
|
/* Unique e_rab_id for the UE. */
|
||||||
|
uint8_t e_rab_id;
|
||||||
|
|
||||||
|
/* The transport layer address for the IP packets */
|
||||||
|
transport_layer_addr_t gNB_addr;
|
||||||
|
|
||||||
|
/* S-GW Tunnel endpoint identifier */
|
||||||
|
uint32_t gtp_teid;
|
||||||
|
} e_rab_setup_t;
|
||||||
|
|
||||||
|
typedef struct e_rab_tobe_added_s {
|
||||||
|
/* Unique e_rab_id for the UE. */
|
||||||
|
uint8_t e_rab_id;
|
||||||
|
|
||||||
|
/* Unique drb_ID for the UE. */
|
||||||
|
uint8_t drb_ID;
|
||||||
|
|
||||||
|
/* The transport layer address for the IP packets */
|
||||||
|
transport_layer_addr_t sgw_addr;
|
||||||
|
|
||||||
|
/* S-GW Tunnel endpoint identifier */
|
||||||
|
uint32_t gtp_teid;
|
||||||
|
} e_rab_tobe_added_t;
|
||||||
|
|
||||||
|
typedef struct e_rab_admitted_tobe_added_s {
|
||||||
|
/* Unique e_rab_id for the UE. */
|
||||||
|
uint8_t e_rab_id;
|
||||||
|
|
||||||
|
/* Unique drb_ID for the UE. */
|
||||||
|
uint8_t drb_ID;
|
||||||
|
|
||||||
|
/* The transport layer address for the IP packets */
|
||||||
|
transport_layer_addr_t gnb_addr;
|
||||||
|
|
||||||
|
/* S-GW Tunnel endpoint identifier */
|
||||||
|
uint32_t gtp_teid;
|
||||||
|
} e_rab_admitted_tobe_added_t;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct e_rab_tobeswitched_s {
|
||||||
|
/* Unique e_rab_id for the UE. */
|
||||||
|
uint8_t e_rab_id;
|
||||||
|
|
||||||
|
/* The transport layer address for the IP packets */
|
||||||
|
transport_layer_addr_t sgw_addr;
|
||||||
|
|
||||||
|
/* S-GW Tunnel endpoint identifier */
|
||||||
|
uint32_t gtp_teid;
|
||||||
|
} e_rab_tobeswitched_t;
|
||||||
|
|
||||||
|
typedef struct e_rab_modify_s {
|
||||||
|
/* Unique e_rab_id for the UE. */
|
||||||
|
uint8_t e_rab_id;
|
||||||
|
} e_rab_modify_t;
|
||||||
|
|
||||||
|
typedef enum S1ap_Cause_e {
|
||||||
|
NGAP_CAUSE_NOTHING, /* No components present */
|
||||||
|
NGAP_CAUSE_RADIO_NETWORK,
|
||||||
|
NGAP_CAUSE_TRANSPORT,
|
||||||
|
NGAP_CAUSE_NAS,
|
||||||
|
NGAP_CAUSE_PROTOCOL,
|
||||||
|
NGAP_CAUSE_MISC,
|
||||||
|
/* Extensions may appear below */
|
||||||
|
|
||||||
|
} ngap_Cause_t;
|
||||||
|
|
||||||
|
typedef struct e_rab_failed_s {
|
||||||
|
/* Unique e_rab_id for the UE. */
|
||||||
|
uint8_t e_rab_id;
|
||||||
|
/* Cause of the failure */
|
||||||
|
// cause_t cause;
|
||||||
|
ngap_Cause_t cause;
|
||||||
|
uint8_t cause_value;
|
||||||
|
} e_rab_failed_t;
|
||||||
|
|
||||||
|
typedef enum ngap_ue_ctxt_modification_present_s {
|
||||||
|
NGAP_UE_CONTEXT_MODIFICATION_SECURITY_KEY = (1 << 0),
|
||||||
|
NGAP_UE_CONTEXT_MODIFICATION_UE_AMBR = (1 << 1),
|
||||||
|
NGAP_UE_CONTEXT_MODIFICATION_UE_SECU_CAP = (1 << 2),
|
||||||
|
} ngap_ue_ctxt_modification_present_t;
|
||||||
|
|
||||||
|
typedef enum ngap_paging_ind_present_s {
|
||||||
|
NGAP_PAGING_IND_PAGING_DRX = (1 << 0),
|
||||||
|
NGAP_PAGING_IND_PAGING_PRIORITY = (1 << 1),
|
||||||
|
} ngap_paging_ind_present_t;
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------------------------------//
|
||||||
|
// gNB application layer -> NGAP messages
|
||||||
|
typedef struct ngap_register_enb_req_s {
|
||||||
|
/* Unique gNB_id to identify the gNB within EPC.
|
||||||
|
* For macro gNB ids this field should be 20 bits long.
|
||||||
|
* For home gNB ids this field should be 28 bits long.
|
||||||
|
*/
|
||||||
|
uint32_t gNB_id;
|
||||||
|
/* The type of the cell */
|
||||||
|
enum cell_type_e cell_type;
|
||||||
|
|
||||||
|
/* Optional name for the cell
|
||||||
|
* NOTE: the name can be NULL (i.e no name) and will be cropped to 150
|
||||||
|
* characters.
|
||||||
|
*/
|
||||||
|
char *gNB_name;
|
||||||
|
|
||||||
|
/* Tracking area code */
|
||||||
|
uint16_t tac;
|
||||||
|
|
||||||
|
#define PLMN_LIST_MAX_SIZE 6
|
||||||
|
/* Mobile Country Code
|
||||||
|
* Mobile Network Code
|
||||||
|
*/
|
||||||
|
uint16_t mcc[PLMN_LIST_MAX_SIZE];
|
||||||
|
uint16_t mnc[PLMN_LIST_MAX_SIZE];
|
||||||
|
uint8_t mnc_digit_length[PLMN_LIST_MAX_SIZE];
|
||||||
|
uint8_t num_plmn;
|
||||||
|
|
||||||
|
/* Default Paging DRX of the gNB as defined in TS 36.304 */
|
||||||
|
paging_drx_t default_drx;
|
||||||
|
|
||||||
|
/* The gNB IP address to bind */
|
||||||
|
net_ip_address_t enb_ip_address;
|
||||||
|
|
||||||
|
/* Nb of MME to connect to */
|
||||||
|
uint8_t nb_mme;
|
||||||
|
/* List of MME to connect to */
|
||||||
|
net_ip_address_t mme_ip_address[NGAP_MAX_NB_MME_IP_ADDRESS];
|
||||||
|
uint8_t broadcast_plmn_num[NGAP_MAX_NB_MME_IP_ADDRESS];
|
||||||
|
uint8_t broadcast_plmn_index[NGAP_MAX_NB_MME_IP_ADDRESS][PLMN_LIST_MAX_SIZE];
|
||||||
|
|
||||||
|
/* Number of SCTP streams used for a mme association */
|
||||||
|
uint16_t sctp_in_streams;
|
||||||
|
uint16_t sctp_out_streams;
|
||||||
|
} ngap_register_enb_req_t;
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------------------------------//
|
||||||
|
// NGAP -> gNB application layer messages
|
||||||
|
typedef struct ngap_register_enb_cnf_s {
|
||||||
|
/* Nb of MME connected */
|
||||||
|
uint8_t nb_mme;
|
||||||
|
} ngap_register_enb_cnf_t;
|
||||||
|
|
||||||
|
typedef struct ngap_deregistered_enb_ind_s {
|
||||||
|
/* Nb of MME connected */
|
||||||
|
uint8_t nb_mme;
|
||||||
|
} ngap_deregistered_enb_ind_t;
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------------------------------//
|
||||||
|
// RRC -> NGAP messages
|
||||||
|
|
||||||
|
/* The NAS First Req is the first message exchanged between RRC and NGAP
|
||||||
|
* for an UE.
|
||||||
|
* The rnti uniquely identifies an UE within a cell. Later the enb_ue_ngap_id
|
||||||
|
* will be the unique identifier used between RRC and NGAP.
|
||||||
|
*/
|
||||||
|
typedef struct ngap_nas_first_req_s {
|
||||||
|
/* UE id for initial connection to NGAP */
|
||||||
|
uint16_t ue_initial_id;
|
||||||
|
|
||||||
|
/* the chosen PLMN identity as index, see TS 36.331 6.2.2 RRC Connection
|
||||||
|
* Setup Complete. This index here is zero-based, unlike the standard! */
|
||||||
|
int selected_plmn_identity;
|
||||||
|
|
||||||
|
/* Establishment cause as sent by UE */
|
||||||
|
rrc_establishment_cause_t establishment_cause;
|
||||||
|
|
||||||
|
/* NAS PDU */
|
||||||
|
nas_pdu_t nas_pdu;
|
||||||
|
|
||||||
|
/* If this flag is set NGAP layer is expecting the GUMMEI. If = 0,
|
||||||
|
* the temporary s-tmsi is used.
|
||||||
|
*/
|
||||||
|
ue_identity_t ue_identity;
|
||||||
|
} ngap_nas_first_req_t;
|
||||||
|
|
||||||
|
typedef struct ngap_uplink_nas_s {
|
||||||
|
/* Unique UE identifier within an gNB */
|
||||||
|
unsigned gNB_ue_ngap_id:24;
|
||||||
|
|
||||||
|
/* NAS pdu */
|
||||||
|
nas_pdu_t nas_pdu;
|
||||||
|
} ngap_uplink_nas_t;
|
||||||
|
|
||||||
|
typedef struct ngap_ue_cap_info_ind_s {
|
||||||
|
unsigned gNB_ue_ngap_id:24;
|
||||||
|
ue_radio_cap_t ue_radio_cap;
|
||||||
|
} ngap_ue_cap_info_ind_t;
|
||||||
|
|
||||||
|
typedef struct ngap_initial_context_setup_resp_s {
|
||||||
|
unsigned gNB_ue_ngap_id:24;
|
||||||
|
|
||||||
|
/* Number of e_rab setup-ed in the list */
|
||||||
|
uint8_t nb_of_e_rabs;
|
||||||
|
/* list of e_rab setup-ed by RRC layers */
|
||||||
|
e_rab_setup_t e_rabs[NGAP_MAX_E_RAB];
|
||||||
|
|
||||||
|
/* Number of e_rab failed to be setup in list */
|
||||||
|
uint8_t nb_of_e_rabs_failed;
|
||||||
|
/* list of e_rabs that failed to be setup */
|
||||||
|
e_rab_failed_t e_rabs_failed[NGAP_MAX_E_RAB];
|
||||||
|
} ngap_initial_context_setup_resp_t;
|
||||||
|
|
||||||
|
typedef struct ngap_initial_context_setup_fail_s {
|
||||||
|
unsigned gNB_ue_ngap_id:24;
|
||||||
|
|
||||||
|
/* TODO add cause */
|
||||||
|
} ngap_initial_context_setup_fail_t, ngap_ue_ctxt_modification_fail_t, ngap_e_rab_setup_req_fail_t;
|
||||||
|
|
||||||
|
typedef struct ngap_nas_non_delivery_ind_s {
|
||||||
|
unsigned gNB_ue_ngap_id:24;
|
||||||
|
nas_pdu_t nas_pdu;
|
||||||
|
/* TODO: add cause */
|
||||||
|
} ngap_nas_non_delivery_ind_t;
|
||||||
|
|
||||||
|
typedef struct ngap_ue_ctxt_modification_req_s {
|
||||||
|
unsigned gNB_ue_ngap_id:24;
|
||||||
|
|
||||||
|
/* Bit-mask of possible present parameters */
|
||||||
|
ngap_ue_ctxt_modification_present_t present;
|
||||||
|
|
||||||
|
/* Following fields are optionnaly present */
|
||||||
|
|
||||||
|
/* Security key */
|
||||||
|
uint8_t security_key[SECURITY_KEY_LENGTH];
|
||||||
|
|
||||||
|
/* UE aggregate maximum bitrate */
|
||||||
|
ambr_t ue_ambr;
|
||||||
|
|
||||||
|
/* Security capabilities */
|
||||||
|
security_capabilities_t security_capabilities;
|
||||||
|
} ngap_ue_ctxt_modification_req_t;
|
||||||
|
|
||||||
|
typedef struct ngap_ue_ctxt_modification_resp_s {
|
||||||
|
unsigned gNB_ue_ngap_id:24;
|
||||||
|
} ngap_ue_ctxt_modification_resp_t;
|
||||||
|
|
||||||
|
typedef struct ngap_ue_release_complete_s {
|
||||||
|
|
||||||
|
unsigned gNB_ue_ngap_id:24;
|
||||||
|
|
||||||
|
} ngap_ue_release_complete_t;
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------------------------------//
|
||||||
|
// NGAP -> RRC messages
|
||||||
|
typedef struct ngap_downlink_nas_s {
|
||||||
|
/* UE id for initial connection to NGAP */
|
||||||
|
uint16_t ue_initial_id;
|
||||||
|
|
||||||
|
/* Unique UE identifier within an gNB */
|
||||||
|
unsigned gNB_ue_ngap_id:24;
|
||||||
|
|
||||||
|
/* NAS pdu */
|
||||||
|
nas_pdu_t nas_pdu;
|
||||||
|
} ngap_downlink_nas_t;
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct ngap_initial_context_setup_req_s {
|
||||||
|
/* UE id for initial connection to NGAP */
|
||||||
|
uint16_t ue_initial_id;
|
||||||
|
|
||||||
|
/* gNB ue ngap id as initialized by NGAP layer */
|
||||||
|
unsigned gNB_ue_ngap_id:24;
|
||||||
|
|
||||||
|
uint32_t mme_ue_ngap_id;
|
||||||
|
|
||||||
|
/* UE aggregate maximum bitrate */
|
||||||
|
ambr_t ue_ambr;
|
||||||
|
|
||||||
|
/* Security algorithms */
|
||||||
|
security_capabilities_t security_capabilities;
|
||||||
|
|
||||||
|
/* Security key */
|
||||||
|
uint8_t security_key[SECURITY_KEY_LENGTH];
|
||||||
|
|
||||||
|
/* Number of e_rab to be setup in the list */
|
||||||
|
uint8_t nb_of_e_rabs;
|
||||||
|
/* list of e_rab to be setup by RRC layers */
|
||||||
|
e_rab_t e_rab_param[NGAP_MAX_E_RAB];
|
||||||
|
} ngap_initial_context_setup_req_t;
|
||||||
|
|
||||||
|
typedef struct tai_plmn_identity_s {
|
||||||
|
uint16_t mcc;
|
||||||
|
uint16_t mnc;
|
||||||
|
uint8_t mnc_digit_length;
|
||||||
|
} plmn_identity_t;
|
||||||
|
|
||||||
|
typedef struct ngap_paging_ind_s {
|
||||||
|
/* UE identity index value.
|
||||||
|
* Specified in 3GPP TS 36.304
|
||||||
|
*/
|
||||||
|
unsigned ue_index_value:10;
|
||||||
|
|
||||||
|
/* UE paging identity */
|
||||||
|
ue_paging_identity_t ue_paging_identity;
|
||||||
|
|
||||||
|
/* Indicates origin of paging */
|
||||||
|
cn_domain_t cn_domain;
|
||||||
|
|
||||||
|
/* PLMN_identity in TAI of Paging*/
|
||||||
|
plmn_identity_t plmn_identity[256];
|
||||||
|
|
||||||
|
/* TAC in TAIList of Paging*/
|
||||||
|
int16_t tac[256];
|
||||||
|
|
||||||
|
/* size of TAIList*/
|
||||||
|
int16_t tai_size;
|
||||||
|
|
||||||
|
/* Optional fields */
|
||||||
|
paging_drx_t paging_drx;
|
||||||
|
|
||||||
|
paging_priority_t paging_priority;
|
||||||
|
} ngap_paging_ind_t;
|
||||||
|
|
||||||
|
typedef struct ngap_e_rab_setup_req_s {
|
||||||
|
/* UE id for initial connection to NGAP */
|
||||||
|
uint16_t ue_initial_id;
|
||||||
|
|
||||||
|
/* MME UE id */
|
||||||
|
uint32_t mme_ue_ngap_id;
|
||||||
|
|
||||||
|
/* gNB ue ngap id as initialized by NGAP layer */
|
||||||
|
unsigned gNB_ue_ngap_id:24;
|
||||||
|
|
||||||
|
/* Number of e_rab to be setup in the list */
|
||||||
|
uint8_t nb_e_rabs_tosetup;
|
||||||
|
|
||||||
|
/* E RAB setup request */
|
||||||
|
e_rab_t e_rab_setup_params[NGAP_MAX_E_RAB];
|
||||||
|
|
||||||
|
} ngap_e_rab_setup_req_t;
|
||||||
|
|
||||||
|
typedef struct ngap_e_rab_setup_resp_s {
|
||||||
|
unsigned gNB_ue_ngap_id:24;
|
||||||
|
|
||||||
|
/* Number of e_rab setup-ed in the list */
|
||||||
|
uint8_t nb_of_e_rabs;
|
||||||
|
/* list of e_rab setup-ed by RRC layers */
|
||||||
|
e_rab_setup_t e_rabs[NGAP_MAX_E_RAB];
|
||||||
|
|
||||||
|
/* Number of e_rab failed to be setup in list */
|
||||||
|
uint8_t nb_of_e_rabs_failed;
|
||||||
|
/* list of e_rabs that failed to be setup */
|
||||||
|
e_rab_failed_t e_rabs_failed[NGAP_MAX_E_RAB];
|
||||||
|
} ngap_e_rab_setup_resp_t;
|
||||||
|
|
||||||
|
typedef struct ngap_path_switch_req_s {
|
||||||
|
|
||||||
|
unsigned gNB_ue_ngap_id:24;
|
||||||
|
|
||||||
|
/* Number of e_rab setup-ed in the list */
|
||||||
|
uint8_t nb_of_e_rabs;
|
||||||
|
|
||||||
|
/* list of e_rab setup-ed by RRC layers */
|
||||||
|
e_rab_setup_t e_rabs_tobeswitched[NGAP_MAX_E_RAB];
|
||||||
|
|
||||||
|
/* MME UE id */
|
||||||
|
uint32_t mme_ue_ngap_id;
|
||||||
|
|
||||||
|
ngap_gummei_t ue_gummei;
|
||||||
|
|
||||||
|
uint16_t ue_initial_id;
|
||||||
|
|
||||||
|
/* Security algorithms */
|
||||||
|
security_capabilities_t security_capabilities;
|
||||||
|
|
||||||
|
} ngap_path_switch_req_t;
|
||||||
|
|
||||||
|
typedef struct ngap_path_switch_req_ack_s {
|
||||||
|
|
||||||
|
/* UE id for initial connection to NGAP */
|
||||||
|
uint16_t ue_initial_id;
|
||||||
|
|
||||||
|
unsigned gNB_ue_ngap_id:24;
|
||||||
|
|
||||||
|
/* MME UE id */
|
||||||
|
uint32_t mme_ue_ngap_id;
|
||||||
|
|
||||||
|
/* UE aggregate maximum bitrate */
|
||||||
|
ambr_t ue_ambr;
|
||||||
|
|
||||||
|
/* Number of e_rab setup-ed in the list */
|
||||||
|
uint8_t nb_e_rabs_tobeswitched;
|
||||||
|
|
||||||
|
/* list of e_rab to be switched by RRC layers */
|
||||||
|
e_rab_tobeswitched_t e_rabs_tobeswitched[NGAP_MAX_E_RAB];
|
||||||
|
|
||||||
|
/* Number of e_rabs to be released by RRC */
|
||||||
|
uint8_t nb_e_rabs_tobereleased;
|
||||||
|
|
||||||
|
/* list of e_rabs to be released */
|
||||||
|
e_rab_failed_t e_rabs_tobereleased[NGAP_MAX_E_RAB];
|
||||||
|
|
||||||
|
/* Security key */
|
||||||
|
int next_hop_chain_count;
|
||||||
|
uint8_t next_security_key[SECURITY_KEY_LENGTH];
|
||||||
|
|
||||||
|
} ngap_path_switch_req_ack_t;
|
||||||
|
|
||||||
|
typedef struct ngap_e_rab_modification_ind_s {
|
||||||
|
|
||||||
|
unsigned gNB_ue_ngap_id:24;
|
||||||
|
|
||||||
|
/* MME UE id */
|
||||||
|
uint32_t mme_ue_ngap_id;
|
||||||
|
|
||||||
|
/* Number of e_rab setup-ed in the list */
|
||||||
|
uint8_t nb_of_e_rabs_tobemodified;
|
||||||
|
|
||||||
|
uint8_t nb_of_e_rabs_nottobemodified;
|
||||||
|
|
||||||
|
/* list of e_rab setup-ed by RRC layers */
|
||||||
|
e_rab_setup_t e_rabs_tobemodified[NGAP_MAX_E_RAB];
|
||||||
|
|
||||||
|
e_rab_setup_t e_rabs_nottobemodified[NGAP_MAX_E_RAB];
|
||||||
|
|
||||||
|
uint16_t ue_initial_id;
|
||||||
|
|
||||||
|
} ngap_e_rab_modification_ind_t;
|
||||||
|
|
||||||
|
// NGAP --> RRC messages
|
||||||
|
typedef struct ngap_ue_release_command_s {
|
||||||
|
|
||||||
|
unsigned gNB_ue_ngap_id:24;
|
||||||
|
|
||||||
|
} ngap_ue_release_command_t;
|
||||||
|
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------------------------------//
|
||||||
|
// NGAP <-- RRC messages
|
||||||
|
typedef struct ngap_ue_release_req_s {
|
||||||
|
unsigned gNB_ue_ngap_id:24;
|
||||||
|
ngap_Cause_t cause;
|
||||||
|
long cause_value;
|
||||||
|
} ngap_ue_release_req_t, ngap_ue_release_resp_t;
|
||||||
|
|
||||||
|
typedef struct ngap_e_rab_modify_req_s {
|
||||||
|
/* UE id for initial connection to NGAP */
|
||||||
|
uint16_t ue_initial_id;
|
||||||
|
|
||||||
|
/* MME UE id */
|
||||||
|
uint32_t mme_ue_ngap_id;
|
||||||
|
|
||||||
|
/* gNB ue ngap id as initialized by NGAP layer */
|
||||||
|
unsigned gNB_ue_ngap_id:24;
|
||||||
|
|
||||||
|
/* Number of e_rab to be modify in the list */
|
||||||
|
uint8_t nb_e_rabs_tomodify;
|
||||||
|
|
||||||
|
/* E RAB modify request */
|
||||||
|
e_rab_t e_rab_modify_params[NGAP_MAX_E_RAB];
|
||||||
|
} ngap_e_rab_modify_req_t;
|
||||||
|
|
||||||
|
typedef struct ngap_e_rab_modify_resp_s {
|
||||||
|
unsigned gNB_ue_ngap_id:24;
|
||||||
|
|
||||||
|
/* Number of e_rab modify-ed in the list */
|
||||||
|
uint8_t nb_of_e_rabs;
|
||||||
|
/* list of e_rab modify-ed by RRC layers */
|
||||||
|
e_rab_modify_t e_rabs[NGAP_MAX_E_RAB];
|
||||||
|
|
||||||
|
/* Number of e_rab failed to be modify in list */
|
||||||
|
uint8_t nb_of_e_rabs_failed;
|
||||||
|
/* list of e_rabs that failed to be modify */
|
||||||
|
e_rab_failed_t e_rabs_failed[NGAP_MAX_E_RAB];
|
||||||
|
} ngap_e_rab_modify_resp_t;
|
||||||
|
|
||||||
|
typedef struct e_rab_release_s {
|
||||||
|
/* Unique e_rab_id for the UE. */
|
||||||
|
uint8_t e_rab_id;
|
||||||
|
} e_rab_release_t;
|
||||||
|
|
||||||
|
typedef struct ngap_e_rab_release_command_s {
|
||||||
|
/* MME UE id */
|
||||||
|
uint32_t mme_ue_ngap_id;
|
||||||
|
|
||||||
|
/* gNB ue ngap id as initialized by NGAP layer */
|
||||||
|
unsigned gNB_ue_ngap_id:24;
|
||||||
|
|
||||||
|
/* The NAS PDU should be forwarded by the RRC layer to the NAS layer */
|
||||||
|
nas_pdu_t nas_pdu;
|
||||||
|
|
||||||
|
/* Number of e_rab to be released in the list */
|
||||||
|
uint8_t nb_e_rabs_torelease;
|
||||||
|
|
||||||
|
/* E RAB release command */
|
||||||
|
e_rab_release_t e_rab_release_params[NGAP_MAX_E_RAB];
|
||||||
|
|
||||||
|
} ngap_e_rab_release_command_t;
|
||||||
|
|
||||||
|
typedef struct ngap_e_rab_release_resp_s {
|
||||||
|
/* MME UE id */
|
||||||
|
uint32_t mme_ue_ngap_id;
|
||||||
|
|
||||||
|
/* gNB ue ngap id as initialized by NGAP layer */
|
||||||
|
unsigned gNB_ue_ngap_id:24;
|
||||||
|
|
||||||
|
/* Number of e_rab released in the list */
|
||||||
|
uint8_t nb_of_e_rabs_released;
|
||||||
|
|
||||||
|
/* list of e_rabs released */
|
||||||
|
e_rab_release_t e_rab_release[NGAP_MAX_E_RAB];
|
||||||
|
|
||||||
|
/* Number of e_rab failed to be released in list */
|
||||||
|
uint8_t nb_of_e_rabs_failed;
|
||||||
|
/* list of e_rabs that failed to be released */
|
||||||
|
e_rab_failed_t e_rabs_failed[NGAP_MAX_E_RAB];
|
||||||
|
|
||||||
|
} ngap_e_rab_release_resp_t;
|
||||||
|
|
||||||
|
#endif /* NGAP_MESSAGES_TYPES_H_ */
|
||||||
@@ -7449,7 +7449,7 @@ ShortMAC-I ::= BIT STRING (SIZE (16))
|
|||||||
SINR-Range ::= INTEGER(0..127)
|
SINR-Range ::= INTEGER(0..127)
|
||||||
|
|
||||||
-- TAG-SINR-RANGE-STOP
|
-- TAG-SINR-RANGE-STOP
|
||||||
-- TAG–SI-REQUESTCONFIG-START
|
-- TAG¨CSI-REQUESTCONFIG-START
|
||||||
|
|
||||||
SI-RequestConfig::= SEQUENCE {
|
SI-RequestConfig::= SEQUENCE {
|
||||||
rach-OccasionsSI SEQUENCE {
|
rach-OccasionsSI SEQUENCE {
|
||||||
@@ -7466,7 +7466,7 @@ SI-RequestResources ::= SEQUENCE {
|
|||||||
ra-ssb-OccasionMaskIndex INTEGER (0..15) OPTIONAL -- Need R
|
ra-ssb-OccasionMaskIndex INTEGER (0..15) OPTIONAL -- Need R
|
||||||
}
|
}
|
||||||
|
|
||||||
-- TAG–SI-SCHEDULINGINFO-START
|
-- TAG¨CSI-SCHEDULINGINFO-START
|
||||||
|
|
||||||
SI-SchedulingInfo ::= SEQUENCE {
|
SI-SchedulingInfo ::= SEQUENCE {
|
||||||
schedulingInfoList SEQUENCE (SIZE (1..maxSI-Message)) OF SchedulingInfo,
|
schedulingInfoList SEQUENCE (SIZE (1..maxSI-Message)) OF SchedulingInfo,
|
||||||
|
|||||||
@@ -0,0 +1,41 @@
|
|||||||
|
/*
|
||||||
|
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
|
||||||
|
* contributor license agreements. See the NOTICE file distributed with
|
||||||
|
* this work for additional information regarding copyright ownership.
|
||||||
|
* The OpenAirInterface Software Alliance licenses this file to You under
|
||||||
|
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
|
||||||
|
* except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.openairinterface.org/?page_id=698
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*-------------------------------------------------------------------------------
|
||||||
|
* For more information about the OpenAirInterface (OAI) Software Alliance:
|
||||||
|
* contact@openairinterface.org
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*! \file ngap_common.c
|
||||||
|
* \brief ngap procedures for both gNB and AMF
|
||||||
|
* \author Sebastien ROUX and Navid Nikaein
|
||||||
|
* \email navid.nikaein@eurecom.fr
|
||||||
|
* \date 2012-2015
|
||||||
|
* \version 0.1
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#include "ngap_common.h"
|
||||||
|
#include "NGAP_NGAP-PDU.h"
|
||||||
|
|
||||||
|
|
||||||
|
int asn1_xer_print = 0;
|
||||||
|
|
||||||
|
|
||||||
|
void ngap_handle_criticality(NGAP_Criticality_t criticality)
|
||||||
|
{
|
||||||
|
}
|
||||||
@@ -0,0 +1,125 @@
|
|||||||
|
/*
|
||||||
|
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
|
||||||
|
* contributor license agreements. See the NOTICE file distributed with
|
||||||
|
* this work for additional information regarding copyright ownership.
|
||||||
|
* The OpenAirInterface Software Alliance licenses this file to You under
|
||||||
|
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
|
||||||
|
* except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.openairinterface.org/?page_id=698
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*-------------------------------------------------------------------------------
|
||||||
|
* For more information about the OpenAirInterface (OAI) Software Alliance:
|
||||||
|
* contact@openairinterface.org
|
||||||
|
*/
|
||||||
|
|
||||||
|
/** @defgroup _ngap_impl_ NGAP Layer Reference Implementation
|
||||||
|
* @ingroup _ref_implementation_
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
|
||||||
|
#if HAVE_CONFIG_H_
|
||||||
|
# include "config.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef NGAP_COMMON_H_
|
||||||
|
#define NGAP_COMMON_H_
|
||||||
|
|
||||||
|
|
||||||
|
#include "common/utils/LOG/log.h"
|
||||||
|
/* replace ASN_DEBUG defined in asn_internal.h by oai tracing system
|
||||||
|
Would be cleaner to modify asn_internal.h but it seems to come
|
||||||
|
from non oai source, with BSD license, so prefer to do that here..
|
||||||
|
*/
|
||||||
|
#ifdef ASN_DEBUG
|
||||||
|
# undef ASN_DEBUG
|
||||||
|
#endif
|
||||||
|
#define ASN_DEBUG( x... ) LOG_I(ASN, x)
|
||||||
|
|
||||||
|
#include "NGAP_ProtocolIE-Field.h"
|
||||||
|
#include "NGAP_NGAP-PDU.h"
|
||||||
|
#include "NGAP_InitiatingMessage.h"
|
||||||
|
#include "NGAP_SuccessfulOutcome.h"
|
||||||
|
#include "NGAP_UnsuccessfulOutcome.h"
|
||||||
|
#include "NGAP_ProtocolIE-Field.h"
|
||||||
|
#include "NGAP_ProtocolIE-FieldPair.h"
|
||||||
|
#include "NGAP_ProtocolIE-ContainerPair.h"
|
||||||
|
#include "NGAP_ProtocolExtensionField.h"
|
||||||
|
#include "NGAP_ProtocolExtensionContainer.h"
|
||||||
|
#include "NGAP_asn_constant.h"
|
||||||
|
#include "NGAP_SupportedTAs-Item.h"
|
||||||
|
#include "NGAP_ServedGUMMEIsItem.h"
|
||||||
|
|
||||||
|
/* Checking version of ASN1C compiler */
|
||||||
|
#if (ASN1C_ENVIRONMENT_VERSION < ASN1C_MINIMUM_VERSION)
|
||||||
|
# error "You are compiling ngap with the wrong version of ASN1C"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef FALSE
|
||||||
|
# define FALSE (0)
|
||||||
|
#endif
|
||||||
|
#ifndef TRUE
|
||||||
|
# define TRUE (!FALSE)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define NGAP_UE_ID_FMT "0x%06"PRIX32
|
||||||
|
|
||||||
|
extern int asn_debug;
|
||||||
|
extern int asn1_xer_print;
|
||||||
|
|
||||||
|
#if defined(ENB_MODE)
|
||||||
|
# include "common/utils/LOG/log.h"
|
||||||
|
# include "ngap_eNB_default_values.h"
|
||||||
|
# define NGAP_ERROR(x, args...) LOG_E(NGAP, x, ##args)
|
||||||
|
# define NGAP_WARN(x, args...) LOG_W(NGAP, x, ##args)
|
||||||
|
# define NGAP_TRAF(x, args...) LOG_I(NGAP, x, ##args)
|
||||||
|
# define NGAP_INFO(x, args...) LOG_I(NGAP, x, ##args)
|
||||||
|
# define NGAP_DEBUG(x, args...) LOG_I(NGAP, x, ##args)
|
||||||
|
#else
|
||||||
|
# include "mme_default_values.h"
|
||||||
|
# define NGAP_ERROR(x, args...) do { fprintf(stdout, "[NGAP][E]"x, ##args); } while(0)
|
||||||
|
# define NGAP_WARN(x, args...) do { fprintf(stdout, "[NGAP][W]"x, ##args); } while(0)
|
||||||
|
# define NGAP_TRAF(x, args...) do { fprintf(stdout, "[NGAP][T]"x, ##args); } while(0)
|
||||||
|
# define NGAP_INFO(x, args...) do { fprintf(stdout, "[NGAP][I]"x, ##args); } while(0)
|
||||||
|
# define NGAP_DEBUG(x, args...) do { fprintf(stdout, "[NGAP][D]"x, ##args); } while(0)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#define NGAP_FIND_PROTOCOLIE_BY_ID(IE_TYPE, ie, container, IE_ID, mandatory) \
|
||||||
|
do {\
|
||||||
|
IE_TYPE **ptr; \
|
||||||
|
ie = NULL; \
|
||||||
|
for (ptr = container->protocolIEs.list.array; \
|
||||||
|
ptr < &container->protocolIEs.list.array[container->protocolIEs.list.count]; \
|
||||||
|
ptr++) { \
|
||||||
|
if((*ptr)->id == IE_ID) { \
|
||||||
|
ie = *ptr; \
|
||||||
|
break; \
|
||||||
|
} \
|
||||||
|
} \
|
||||||
|
if (ie == NULL ) { \
|
||||||
|
NGAP_ERROR("NGAP_FIND_PROTOCOLIE_BY_ID: %s %d: ie is NULL\n",__FILE__,__LINE__);\
|
||||||
|
} \
|
||||||
|
if (mandatory) DevAssert(ie != NULL); \
|
||||||
|
} while(0)
|
||||||
|
/** \brief Function callback prototype.
|
||||||
|
**/
|
||||||
|
typedef int (*ngap_message_decoded_callback)(
|
||||||
|
uint32_t assoc_id,
|
||||||
|
uint32_t stream,
|
||||||
|
NGAP_NGAP_PDU_t *pdu
|
||||||
|
);
|
||||||
|
|
||||||
|
/** \brief Handle criticality
|
||||||
|
\param criticality Criticality of the IE
|
||||||
|
@returns void
|
||||||
|
**/
|
||||||
|
void ngap_handle_criticality(NGAP_Criticality_t criticality);
|
||||||
|
|
||||||
|
#endif /* NGAP_COMMON_H_ */
|
||||||
@@ -0,0 +1,532 @@
|
|||||||
|
/*
|
||||||
|
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
|
||||||
|
* contributor license agreements. See the NOTICE file distributed with
|
||||||
|
* this work for additional information regarding copyright ownership.
|
||||||
|
* The OpenAirInterface Software Alliance licenses this file to You under
|
||||||
|
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
|
||||||
|
* except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.openairinterface.org/?page_id=698
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*-------------------------------------------------------------------------------
|
||||||
|
* For more information about the OpenAirInterface (OAI) Software Alliance:
|
||||||
|
* contact@openairinterface.org
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*! \file ngap_gNB.c
|
||||||
|
* \brief NGAP gNB task
|
||||||
|
* \author S. Roux and Navid Nikaein
|
||||||
|
* \date 2010 - 2015
|
||||||
|
* \email: navid.nikaein@eurecom.fr
|
||||||
|
* \version 1.0
|
||||||
|
* @ingroup _ngap
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <pthread.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <crypt.h>
|
||||||
|
|
||||||
|
#include "tree.h"
|
||||||
|
#include "queue.h"
|
||||||
|
|
||||||
|
#include "intertask_interface.h"
|
||||||
|
|
||||||
|
#include "ngap_gNB_default_values.h"
|
||||||
|
|
||||||
|
#include "ngap_common.h"
|
||||||
|
|
||||||
|
#include "ngap_gNB_defs.h"
|
||||||
|
#include "ngap_gNB.h"
|
||||||
|
#include "ngap_gNB_encoder.h"
|
||||||
|
#include "ngap_gNB_handlers.h"
|
||||||
|
#include "ngap_gNB_nnsf.h"
|
||||||
|
|
||||||
|
#include "ngap_gNB_nas_procedures.h"
|
||||||
|
#include "ngap_gNB_management_procedures.h"
|
||||||
|
#include "ngap_gNB_context_management_procedures.h"
|
||||||
|
|
||||||
|
#include "ngap_gNB_itti_messaging.h"
|
||||||
|
|
||||||
|
#include "ngap_gNB_ue_context.h" // test, to be removed
|
||||||
|
#include "msc.h"
|
||||||
|
|
||||||
|
#include "assertions.h"
|
||||||
|
#include "conversions.h"
|
||||||
|
#if defined(TEST_S1C_MME)
|
||||||
|
#include "oaisim_mme_test_s1c.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
ngap_gNB_config_t ngap_config;
|
||||||
|
|
||||||
|
static int ngap_gNB_generate_s1_setup_request(
|
||||||
|
ngap_gNB_instance_t *instance_p, ngap_gNB_mme_data_t *ngap_mme_data_p);
|
||||||
|
|
||||||
|
void ngap_gNB_handle_register_gNB(instance_t instance, ngap_register_enb_req_t *ngap_register_gNB);
|
||||||
|
|
||||||
|
void ngap_gNB_handle_sctp_association_resp(instance_t instance, sctp_new_association_resp_t *sctp_new_association_resp);
|
||||||
|
|
||||||
|
uint32_t ngap_generate_gNB_id(void) {
|
||||||
|
char *out;
|
||||||
|
char hostname[50];
|
||||||
|
int ret;
|
||||||
|
uint32_t gNB_id;
|
||||||
|
/* Retrieve the host name */
|
||||||
|
ret = gethostname(hostname, sizeof(hostname));
|
||||||
|
DevAssert(ret == 0);
|
||||||
|
out = crypt(hostname, "eurecom");
|
||||||
|
DevAssert(out != NULL);
|
||||||
|
gNB_id = ((out[0] << 24) | (out[1] << 16) | (out[2] << 8) | out[3]);
|
||||||
|
return gNB_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ngap_gNB_register_mme(ngap_gNB_instance_t *instance_p,
|
||||||
|
net_ip_address_t *mme_ip_address,
|
||||||
|
net_ip_address_t *local_ip_addr,
|
||||||
|
uint16_t in_streams,
|
||||||
|
uint16_t out_streams,
|
||||||
|
uint8_t broadcast_plmn_num,
|
||||||
|
uint8_t broadcast_plmn_index[PLMN_LIST_MAX_SIZE]) {
|
||||||
|
MessageDef *message_p = NULL;
|
||||||
|
sctp_new_association_req_t *sctp_new_association_req_p = NULL;
|
||||||
|
ngap_gNB_mme_data_t *ngap_mme_data_p = NULL;
|
||||||
|
struct ngap_gNB_mme_data_s *mme = NULL;
|
||||||
|
DevAssert(instance_p != NULL);
|
||||||
|
DevAssert(mme_ip_address != NULL);
|
||||||
|
message_p = itti_alloc_new_message(TASK_NGAP, SCTP_NEW_ASSOCIATION_REQ);
|
||||||
|
sctp_new_association_req_p = &message_p->ittiMsg.sctp_new_association_req;
|
||||||
|
sctp_new_association_req_p->port = NGAP_PORT_NUMBER;
|
||||||
|
sctp_new_association_req_p->ppid = NGAP_SCTP_PPID;
|
||||||
|
sctp_new_association_req_p->in_streams = in_streams;
|
||||||
|
sctp_new_association_req_p->out_streams = out_streams;
|
||||||
|
memcpy(&sctp_new_association_req_p->remote_address,
|
||||||
|
mme_ip_address,
|
||||||
|
sizeof(*mme_ip_address));
|
||||||
|
memcpy(&sctp_new_association_req_p->local_address,
|
||||||
|
local_ip_addr,
|
||||||
|
sizeof(*local_ip_addr));
|
||||||
|
NGAP_INFO("[gNB %d] check the mme registration state\n",instance_p->instance);
|
||||||
|
mme = NULL;
|
||||||
|
|
||||||
|
if ( mme == NULL ) {
|
||||||
|
/* Create new MME descriptor */
|
||||||
|
ngap_mme_data_p = calloc(1, sizeof(*ngap_mme_data_p));
|
||||||
|
DevAssert(ngap_mme_data_p != NULL);
|
||||||
|
ngap_mme_data_p->cnx_id = ngap_gNB_fetch_add_global_cnx_id();
|
||||||
|
sctp_new_association_req_p->ulp_cnx_id = ngap_mme_data_p->cnx_id;
|
||||||
|
ngap_mme_data_p->assoc_id = -1;
|
||||||
|
ngap_mme_data_p->broadcast_plmn_num = broadcast_plmn_num;
|
||||||
|
memcpy(&ngap_mme_data_p->mme_s1_ip,
|
||||||
|
mme_ip_address,
|
||||||
|
sizeof(*mme_ip_address));
|
||||||
|
for (int i = 0; i < broadcast_plmn_num; ++i)
|
||||||
|
ngap_mme_data_p->broadcast_plmn_index[i] = broadcast_plmn_index[i];
|
||||||
|
|
||||||
|
ngap_mme_data_p->ngap_gNB_instance = instance_p;
|
||||||
|
STAILQ_INIT(&ngap_mme_data_p->served_gummei);
|
||||||
|
/* Insert the new descriptor in list of known MME
|
||||||
|
* but not yet associated.
|
||||||
|
*/
|
||||||
|
RB_INSERT(ngap_mme_map, &instance_p->ngap_mme_head, ngap_mme_data_p);
|
||||||
|
ngap_mme_data_p->state = NGAP_GNB_STATE_WAITING;
|
||||||
|
instance_p->ngap_mme_nb ++;
|
||||||
|
instance_p->ngap_mme_pending_nb ++;
|
||||||
|
} else if (mme->state == NGAP_GNB_STATE_WAITING) {
|
||||||
|
instance_p->ngap_mme_pending_nb ++;
|
||||||
|
sctp_new_association_req_p->ulp_cnx_id = mme->cnx_id;
|
||||||
|
NGAP_INFO("[gNB %d] MME already registered, retrive the data (state %d, cnx %d, mme_nb %d, mme_pending_nb %d)\n",
|
||||||
|
instance_p->instance,
|
||||||
|
mme->state, mme->cnx_id,
|
||||||
|
instance_p->ngap_mme_nb, instance_p->ngap_mme_pending_nb);
|
||||||
|
/*ngap_mme_data_p->cnx_id = mme->cnx_id;
|
||||||
|
sctp_new_association_req_p->ulp_cnx_id = mme->cnx_id;
|
||||||
|
|
||||||
|
ngap_mme_data_p->assoc_id = -1;
|
||||||
|
ngap_mme_data_p->ngap_gNB_instance = instance_p;
|
||||||
|
*/
|
||||||
|
} else {
|
||||||
|
NGAP_WARN("[gNB %d] MME already registered but not in the waiting state, retrive the data (state %d, cnx %d, mme_nb %d, mme_pending_nb %d)\n",
|
||||||
|
instance_p->instance,
|
||||||
|
mme->state, mme->cnx_id,
|
||||||
|
instance_p->ngap_mme_nb, instance_p->ngap_mme_pending_nb);
|
||||||
|
}
|
||||||
|
|
||||||
|
itti_send_msg_to_task(TASK_SCTP, instance_p->instance, message_p);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void ngap_gNB_handle_register_gNB(instance_t instance, ngap_register_enb_req_t *ngap_register_gNB) {
|
||||||
|
ngap_gNB_instance_t *new_instance;
|
||||||
|
uint8_t index;
|
||||||
|
DevAssert(ngap_register_gNB != NULL);
|
||||||
|
/* Look if the provided instance already exists */
|
||||||
|
new_instance = ngap_gNB_get_instance(instance);
|
||||||
|
|
||||||
|
if (new_instance != NULL) {
|
||||||
|
/* Checks if it is a retry on the same gNB */
|
||||||
|
DevCheck(new_instance->gNB_id == ngap_register_gNB->gNB_id, new_instance->gNB_id, ngap_register_gNB->gNB_id, 0);
|
||||||
|
DevCheck(new_instance->cell_type == ngap_register_gNB->cell_type, new_instance->cell_type, ngap_register_gNB->cell_type, 0);
|
||||||
|
DevCheck(new_instance->num_plmn == ngap_register_gNB->num_plmn, new_instance->num_plmn, ngap_register_gNB->num_plmn, 0);
|
||||||
|
DevCheck(new_instance->tac == ngap_register_gNB->tac, new_instance->tac, ngap_register_gNB->tac, 0);
|
||||||
|
|
||||||
|
for (int i = 0; i < new_instance->num_plmn; i++) {
|
||||||
|
DevCheck(new_instance->mcc[i] == ngap_register_gNB->mcc[i], new_instance->mcc[i], ngap_register_gNB->mcc[i], 0);
|
||||||
|
DevCheck(new_instance->mnc[i] == ngap_register_gNB->mnc[i], new_instance->mnc[i], ngap_register_gNB->mnc[i], 0);
|
||||||
|
DevCheck(new_instance->mnc_digit_length[i] == ngap_register_gNB->mnc_digit_length[i], new_instance->mnc_digit_length[i], ngap_register_gNB->mnc_digit_length[i], 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
DevCheck(new_instance->default_drx == ngap_register_gNB->default_drx, new_instance->default_drx, ngap_register_gNB->default_drx, 0);
|
||||||
|
} else {
|
||||||
|
new_instance = calloc(1, sizeof(ngap_gNB_instance_t));
|
||||||
|
DevAssert(new_instance != NULL);
|
||||||
|
RB_INIT(&new_instance->ngap_ue_head);
|
||||||
|
RB_INIT(&new_instance->ngap_mme_head);
|
||||||
|
/* Copy usefull parameters */
|
||||||
|
new_instance->instance = instance;
|
||||||
|
new_instance->gNB_name = ngap_register_gNB->gNB_name;
|
||||||
|
new_instance->gNB_id = ngap_register_gNB->gNB_id;
|
||||||
|
new_instance->cell_type = ngap_register_gNB->cell_type;
|
||||||
|
new_instance->tac = ngap_register_gNB->tac;
|
||||||
|
|
||||||
|
memcpy(&new_instance->gNB_s1_ip,
|
||||||
|
&ngap_register_gNB->enb_ip_address,
|
||||||
|
sizeof(ngap_register_gNB->enb_ip_address));
|
||||||
|
|
||||||
|
for (int i = 0; i < ngap_register_gNB->num_plmn; i++) {
|
||||||
|
new_instance->mcc[i] = ngap_register_gNB->mcc[i];
|
||||||
|
new_instance->mnc[i] = ngap_register_gNB->mnc[i];
|
||||||
|
new_instance->mnc_digit_length[i] = ngap_register_gNB->mnc_digit_length[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
new_instance->num_plmn = ngap_register_gNB->num_plmn;
|
||||||
|
new_instance->default_drx = ngap_register_gNB->default_drx;
|
||||||
|
/* Add the new instance to the list of gNB (meaningfull in virtual mode) */
|
||||||
|
ngap_gNB_insert_new_instance(new_instance);
|
||||||
|
NGAP_INFO("Registered new gNB[%d] and %s gNB id %u\n",
|
||||||
|
instance,
|
||||||
|
ngap_register_gNB->cell_type == CELL_MACRO_GNB ? "macro" : "home",
|
||||||
|
ngap_register_gNB->gNB_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
DevCheck(ngap_register_gNB->nb_mme <= NGAP_MAX_NB_MME_IP_ADDRESS,
|
||||||
|
NGAP_MAX_NB_MME_IP_ADDRESS, ngap_register_gNB->nb_mme, 0);
|
||||||
|
|
||||||
|
/* Trying to connect to provided list of MME ip address */
|
||||||
|
for (index = 0; index < ngap_register_gNB->nb_mme; index++) {
|
||||||
|
net_ip_address_t *mme_ip = &ngap_register_gNB->mme_ip_address[index];
|
||||||
|
struct ngap_gNB_mme_data_s *mme = NULL;
|
||||||
|
RB_FOREACH(mme, ngap_mme_map, &new_instance->ngap_mme_head) {
|
||||||
|
/* Compare whether IPv4 and IPv6 information is already present, in which
|
||||||
|
* wase we do not register again */
|
||||||
|
if (mme->mme_s1_ip.ipv4 == mme_ip->ipv4 && (!mme_ip->ipv4
|
||||||
|
|| strncmp(mme->mme_s1_ip.ipv4_address, mme_ip->ipv4_address, 16) == 0)
|
||||||
|
&& mme->mme_s1_ip.ipv6 == mme_ip->ipv6 && (!mme_ip->ipv6
|
||||||
|
|| strncmp(mme->mme_s1_ip.ipv6_address, mme_ip->ipv6_address, 46) == 0))
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (mme)
|
||||||
|
continue;
|
||||||
|
ngap_gNB_register_mme(new_instance,
|
||||||
|
mme_ip,
|
||||||
|
&ngap_register_gNB->enb_ip_address,
|
||||||
|
ngap_register_gNB->sctp_in_streams,
|
||||||
|
ngap_register_gNB->sctp_out_streams,
|
||||||
|
ngap_register_gNB->broadcast_plmn_num[index],
|
||||||
|
ngap_register_gNB->broadcast_plmn_index[index]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ngap_gNB_handle_sctp_association_resp(instance_t instance, sctp_new_association_resp_t *sctp_new_association_resp) {
|
||||||
|
ngap_gNB_instance_t *instance_p;
|
||||||
|
ngap_gNB_mme_data_t *ngap_mme_data_p;
|
||||||
|
DevAssert(sctp_new_association_resp != NULL);
|
||||||
|
instance_p = ngap_gNB_get_instance(instance);
|
||||||
|
DevAssert(instance_p != NULL);
|
||||||
|
ngap_mme_data_p = ngap_gNB_get_MME(instance_p, -1,
|
||||||
|
sctp_new_association_resp->ulp_cnx_id);
|
||||||
|
DevAssert(ngap_mme_data_p != NULL);
|
||||||
|
|
||||||
|
if (sctp_new_association_resp->sctp_state != SCTP_STATE_ESTABLISHED) {
|
||||||
|
NGAP_WARN("Received unsuccessful result for SCTP association (%u), instance %d, cnx_id %u\n",
|
||||||
|
sctp_new_association_resp->sctp_state,
|
||||||
|
instance,
|
||||||
|
sctp_new_association_resp->ulp_cnx_id);
|
||||||
|
ngap_handle_s1_setup_message(ngap_mme_data_p, sctp_new_association_resp->sctp_state == SCTP_STATE_SHUTDOWN);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Update parameters */
|
||||||
|
ngap_mme_data_p->assoc_id = sctp_new_association_resp->assoc_id;
|
||||||
|
ngap_mme_data_p->in_streams = sctp_new_association_resp->in_streams;
|
||||||
|
ngap_mme_data_p->out_streams = sctp_new_association_resp->out_streams;
|
||||||
|
/* Prepare new S1 Setup Request */
|
||||||
|
ngap_gNB_generate_s1_setup_request(instance_p, ngap_mme_data_p);
|
||||||
|
}
|
||||||
|
|
||||||
|
static
|
||||||
|
void ngap_gNB_handle_sctp_data_ind(sctp_data_ind_t *sctp_data_ind) {
|
||||||
|
int result;
|
||||||
|
DevAssert(sctp_data_ind != NULL);
|
||||||
|
#if defined(TEST_S1C_MME)
|
||||||
|
mme_test_s1_notify_sctp_data_ind(sctp_data_ind->assoc_id, sctp_data_ind->stream,
|
||||||
|
sctp_data_ind->buffer, sctp_data_ind->buffer_length);
|
||||||
|
#else
|
||||||
|
ngap_gNB_handle_message(sctp_data_ind->assoc_id, sctp_data_ind->stream,
|
||||||
|
sctp_data_ind->buffer, sctp_data_ind->buffer_length);
|
||||||
|
#endif
|
||||||
|
result = itti_free(TASK_UNKNOWN, sctp_data_ind->buffer);
|
||||||
|
AssertFatal (result == EXIT_SUCCESS, "Failed to free memory (%d)!\n", result);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ngap_gNB_init(void) {
|
||||||
|
NGAP_DEBUG("Starting NGAP layer\n");
|
||||||
|
ngap_gNB_prepare_internal_data();
|
||||||
|
itti_mark_task_ready(TASK_NGAP);
|
||||||
|
MSC_START_USE();
|
||||||
|
}
|
||||||
|
|
||||||
|
void *ngap_gNB_process_itti_msg(void *notUsed) {
|
||||||
|
MessageDef *received_msg = NULL;
|
||||||
|
int result;
|
||||||
|
itti_receive_msg(TASK_NGAP, &received_msg);
|
||||||
|
|
||||||
|
switch (ITTI_MSG_ID(received_msg)) {
|
||||||
|
case TERMINATE_MESSAGE:
|
||||||
|
NGAP_WARN(" *** Exiting NGAP thread\n");
|
||||||
|
itti_exit_task();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case NGAP_REGISTER_GNB_REQ: {
|
||||||
|
/* Register a new gNB.
|
||||||
|
* in Virtual mode gNBs will be distinguished using the mod_id/
|
||||||
|
* Each gNB has to send an NGAP_REGISTER_GNB message with its
|
||||||
|
* own parameters.
|
||||||
|
*/
|
||||||
|
ngap_gNB_handle_register_gNB(ITTI_MESSAGE_GET_INSTANCE(received_msg),
|
||||||
|
&NGAP_REGISTER_GNB_REQ(received_msg));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SCTP_NEW_ASSOCIATION_RESP: {
|
||||||
|
ngap_gNB_handle_sctp_association_resp(ITTI_MESSAGE_GET_INSTANCE(received_msg),
|
||||||
|
&received_msg->ittiMsg.sctp_new_association_resp);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SCTP_DATA_IND: {
|
||||||
|
ngap_gNB_handle_sctp_data_ind(&received_msg->ittiMsg.sctp_data_ind);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case NGAP_NAS_FIRST_REQ: {
|
||||||
|
ngap_gNB_handle_nas_first_req(ITTI_MESSAGE_GET_INSTANCE(received_msg),
|
||||||
|
&NGAP_NAS_FIRST_REQ(received_msg));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case NGAP_UPLINK_NAS: {
|
||||||
|
ngap_gNB_nas_uplink(ITTI_MESSAGE_GET_INSTANCE(received_msg),
|
||||||
|
&NGAP_UPLINK_NAS(received_msg));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case NGAP_UE_CAPABILITIES_IND: {
|
||||||
|
ngap_gNB_ue_capabilities(ITTI_MESSAGE_GET_INSTANCE(received_msg),
|
||||||
|
&NGAP_UE_CAPABILITIES_IND(received_msg));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case NGAP_INITIAL_CONTEXT_SETUP_RESP: {
|
||||||
|
ngap_gNB_initial_ctxt_resp(ITTI_MESSAGE_GET_INSTANCE(received_msg),
|
||||||
|
&NGAP_INITIAL_CONTEXT_SETUP_RESP(received_msg));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case NGAP_E_RAB_SETUP_RESP: {
|
||||||
|
ngap_gNB_e_rab_setup_resp(ITTI_MESSAGE_GET_INSTANCE(received_msg),
|
||||||
|
&NGAP_E_RAB_SETUP_RESP(received_msg));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case NGAP_E_RAB_MODIFY_RESP: {
|
||||||
|
ngap_gNB_e_rab_modify_resp(ITTI_MESSAGE_GET_INSTANCE(received_msg),
|
||||||
|
&NGAP_E_RAB_MODIFY_RESP(received_msg));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case NGAP_NAS_NON_DELIVERY_IND: {
|
||||||
|
ngap_gNB_nas_non_delivery_ind(ITTI_MESSAGE_GET_INSTANCE(received_msg),
|
||||||
|
&NGAP_NAS_NON_DELIVERY_IND(received_msg));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case NGAP_PATH_SWITCH_REQ: {
|
||||||
|
ngap_gNB_path_switch_req(ITTI_MESSAGE_GET_INSTANCE(received_msg),
|
||||||
|
&NGAP_PATH_SWITCH_REQ(received_msg));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case NGAP_E_RAB_MODIFICATION_IND: {
|
||||||
|
ngap_gNB_generate_E_RAB_Modification_Indication(ITTI_MESSAGE_GET_INSTANCE(received_msg),
|
||||||
|
&NGAP_E_RAB_MODIFICATION_IND(received_msg));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case NGAP_UE_CONTEXT_RELEASE_COMPLETE: {
|
||||||
|
ngap_ue_context_release_complete(ITTI_MESSAGE_GET_INSTANCE(received_msg),
|
||||||
|
&NGAP_UE_CONTEXT_RELEASE_COMPLETE(received_msg));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case NGAP_UE_CONTEXT_RELEASE_REQ: {
|
||||||
|
ngap_gNB_instance_t *ngap_gNB_instance_p = NULL; // test
|
||||||
|
struct ngap_gNB_ue_context_s *ue_context_p = NULL; // test
|
||||||
|
ngap_ue_context_release_req(ITTI_MESSAGE_GET_INSTANCE(received_msg),
|
||||||
|
&NGAP_UE_CONTEXT_RELEASE_REQ(received_msg));
|
||||||
|
ngap_gNB_instance_p = ngap_gNB_get_instance(ITTI_MESSAGE_GET_INSTANCE(received_msg)); // test
|
||||||
|
DevAssert(ngap_gNB_instance_p != NULL); // test
|
||||||
|
|
||||||
|
if ((ue_context_p = ngap_gNB_get_ue_context(ngap_gNB_instance_p,
|
||||||
|
NGAP_UE_CONTEXT_RELEASE_REQ(received_msg).gNB_ue_ngap_id)) == NULL) { // test
|
||||||
|
/* The context for this gNB ue ngap id doesn't exist in the map of gNB UEs */
|
||||||
|
NGAP_ERROR("Failed to find ue context associated with gNB ue ngap id: %u\n",
|
||||||
|
NGAP_UE_CONTEXT_RELEASE_REQ(received_msg).gNB_ue_ngap_id); // test
|
||||||
|
} // test
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case NGAP_E_RAB_RELEASE_RESPONSE: {
|
||||||
|
ngap_gNB_e_rab_release_resp(ITTI_MESSAGE_GET_INSTANCE(received_msg),
|
||||||
|
&NGAP_E_RAB_RELEASE_RESPONSE(received_msg));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
NGAP_ERROR("Received unhandled message: %d:%s\n",
|
||||||
|
ITTI_MSG_ID(received_msg), ITTI_MSG_NAME(received_msg));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
result = itti_free (ITTI_MSG_ORIGIN_ID(received_msg), received_msg);
|
||||||
|
AssertFatal (result == EXIT_SUCCESS, "Failed to free memory (%d)!\n", result);
|
||||||
|
received_msg = NULL;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void *ngap_gNB_task(void *arg) {
|
||||||
|
ngap_gNB_init();
|
||||||
|
|
||||||
|
while (1) {
|
||||||
|
(void) ngap_gNB_process_itti_msg(NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
/*
|
||||||
|
* gNB generate a S1 setup request towards MME
|
||||||
|
*/
|
||||||
|
static int ngap_gNB_generate_s1_setup_request(
|
||||||
|
ngap_gNB_instance_t *instance_p,
|
||||||
|
ngap_gNB_mme_data_t *ngap_mme_data_p)
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
{
|
||||||
|
NGAP_NGAP_PDU_t pdu;
|
||||||
|
NGAP_S1SetupRequest_t *out = NULL;
|
||||||
|
NGAP_S1SetupRequestIEs_t *ie = NULL;
|
||||||
|
NGAP_SupportedTAs_Item_t *ta = NULL;
|
||||||
|
NGAP_PLMNidentity_t *plmn = NULL;
|
||||||
|
uint8_t *buffer = NULL;
|
||||||
|
uint32_t len = 0;
|
||||||
|
int ret = 0;
|
||||||
|
DevAssert(instance_p != NULL);
|
||||||
|
DevAssert(ngap_mme_data_p != NULL);
|
||||||
|
ngap_mme_data_p->state = NGAP_GNB_STATE_WAITING;
|
||||||
|
/* Prepare the NGAP message to encode */
|
||||||
|
memset(&pdu, 0, sizeof(pdu));
|
||||||
|
pdu.present = NGAP_NGAP_PDU_PR_initiatingMessage;
|
||||||
|
pdu.choice.initiatingMessage.procedureCode = NGAP_ProcedureCode_id_S1Setup;
|
||||||
|
pdu.choice.initiatingMessage.criticality = NGAP_Criticality_reject;
|
||||||
|
pdu.choice.initiatingMessage.value.present = NGAP_InitiatingMessage__value_PR_S1SetupRequest;
|
||||||
|
out = &pdu.choice.initiatingMessage.value.choice.S1SetupRequest;
|
||||||
|
/* mandatory */
|
||||||
|
ie = (NGAP_S1SetupRequestIEs_t *)calloc(1, sizeof(NGAP_S1SetupRequestIEs_t));
|
||||||
|
ie->id = NGAP_ProtocolIE_ID_id_Global_GNB_ID;
|
||||||
|
ie->criticality = NGAP_Criticality_reject;
|
||||||
|
ie->value.present = NGAP_S1SetupRequestIEs__value_PR_Global_GNB_ID;
|
||||||
|
MCC_MNC_TO_PLMNID(instance_p->mcc[ngap_mme_data_p->broadcast_plmn_index[0]],
|
||||||
|
instance_p->mnc[ngap_mme_data_p->broadcast_plmn_index[0]],
|
||||||
|
instance_p->mnc_digit_length[ngap_mme_data_p->broadcast_plmn_index[0]],
|
||||||
|
&ie->value.choice.Global_GNB_ID.pLMNidentity);
|
||||||
|
ie->value.choice.Global_GNB_ID.gNB_ID.present = NGAP_GNB_ID_PR_macroGNB_ID;
|
||||||
|
MACRO_GNB_ID_TO_BIT_STRING(instance_p->gNB_id,
|
||||||
|
&ie->value.choice.Global_GNB_ID.gNB_ID.choice.macroGNB_ID);
|
||||||
|
NGAP_INFO("%d -> %02x%02x%02x\n", instance_p->gNB_id,
|
||||||
|
ie->value.choice.Global_GNB_ID.gNB_ID.choice.macroGNB_ID.buf[0],
|
||||||
|
ie->value.choice.Global_GNB_ID.gNB_ID.choice.macroGNB_ID.buf[1],
|
||||||
|
ie->value.choice.Global_GNB_ID.gNB_ID.choice.macroGNB_ID.buf[2]);
|
||||||
|
ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
|
||||||
|
|
||||||
|
/* optional */
|
||||||
|
if (instance_p->gNB_name) {
|
||||||
|
ie = (NGAP_S1SetupRequestIEs_t *)calloc(1, sizeof(NGAP_S1SetupRequestIEs_t));
|
||||||
|
ie->id = NGAP_ProtocolIE_ID_id_gNBname;
|
||||||
|
ie->criticality = NGAP_Criticality_ignore;
|
||||||
|
ie->value.present = NGAP_S1SetupRequestIEs__value_PR_GNBname;
|
||||||
|
OCTET_STRING_fromBuf(&ie->value.choice.GNBname, instance_p->gNB_name,
|
||||||
|
strlen(instance_p->gNB_name));
|
||||||
|
ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* mandatory */
|
||||||
|
ie = (NGAP_S1SetupRequestIEs_t *)calloc(1, sizeof(NGAP_S1SetupRequestIEs_t));
|
||||||
|
ie->id = NGAP_ProtocolIE_ID_id_SupportedTAs;
|
||||||
|
ie->criticality = NGAP_Criticality_reject;
|
||||||
|
ie->value.present = NGAP_S1SetupRequestIEs__value_PR_SupportedTAs;
|
||||||
|
{
|
||||||
|
ta = (NGAP_SupportedTAs_Item_t *)calloc(1, sizeof(NGAP_SupportedTAs_Item_t));
|
||||||
|
INT16_TO_OCTET_STRING(instance_p->tac, &ta->tAC);
|
||||||
|
{
|
||||||
|
for (int i = 0; i < ngap_mme_data_p->broadcast_plmn_num; ++i) {
|
||||||
|
plmn = (NGAP_PLMNidentity_t *)calloc(1, sizeof(NGAP_PLMNidentity_t));
|
||||||
|
MCC_MNC_TO_TBCD(instance_p->mcc[ngap_mme_data_p->broadcast_plmn_index[i]],
|
||||||
|
instance_p->mnc[ngap_mme_data_p->broadcast_plmn_index[i]],
|
||||||
|
instance_p->mnc_digit_length[ngap_mme_data_p->broadcast_plmn_index[i]],
|
||||||
|
plmn);
|
||||||
|
ASN_SEQUENCE_ADD(&ta->broadcastPLMNs.list, plmn);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ASN_SEQUENCE_ADD(&ie->value.choice.SupportedTAs.list, ta);
|
||||||
|
}
|
||||||
|
ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
|
||||||
|
/* mandatory */
|
||||||
|
ie = (NGAP_S1SetupRequestIEs_t *)calloc(1, sizeof(NGAP_S1SetupRequestIEs_t));
|
||||||
|
ie->id = NGAP_ProtocolIE_ID_id_DefaultPagingDRX;
|
||||||
|
ie->criticality = NGAP_Criticality_ignore;
|
||||||
|
ie->value.present = NGAP_S1SetupRequestIEs__value_PR_PagingDRX;
|
||||||
|
ie->value.choice.PagingDRX = instance_p->default_drx;
|
||||||
|
ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
|
||||||
|
|
||||||
|
|
||||||
|
if (ngap_gNB_encode_pdu(&pdu, &buffer, &len) < 0) {
|
||||||
|
NGAP_ERROR("Failed to encode S1 setup request\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Non UE-Associated signalling -> stream = 0 */
|
||||||
|
ngap_gNB_itti_send_sctp_data_req(instance_p->instance, ngap_mme_data_p->assoc_id, buffer, len, 0);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -0,0 +1,52 @@
|
|||||||
|
/*
|
||||||
|
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
|
||||||
|
* contributor license agreements. See the NOTICE file distributed with
|
||||||
|
* this work for additional information regarding copyright ownership.
|
||||||
|
* The OpenAirInterface Software Alliance licenses this file to You under
|
||||||
|
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
|
||||||
|
* except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.openairinterface.org/?page_id=698
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*-------------------------------------------------------------------------------
|
||||||
|
* For more information about the OpenAirInterface (OAI) Software Alliance:
|
||||||
|
* contact@openairinterface.org
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
/** @defgroup _ngap_impl_ NGAP Layer Reference Implementation for gNB
|
||||||
|
* @ingroup _ref_implementation_
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef NGAP_GNB_H_
|
||||||
|
#define NGAP_GNB_H_
|
||||||
|
|
||||||
|
typedef struct ngap_gNB_config_s {
|
||||||
|
// MME related params
|
||||||
|
unsigned char mme_enabled; ///< MME enabled ?
|
||||||
|
} ngap_gNB_config_t;
|
||||||
|
|
||||||
|
extern ngap_gNB_config_t ngap_config;
|
||||||
|
|
||||||
|
#define EPC_MODE_ENABLED ngap_config.mme_enabled
|
||||||
|
|
||||||
|
void *ngap_gNB_process_itti_msg(void*);
|
||||||
|
void ngap_gNB_init(void);
|
||||||
|
void *ngap_gNB_task(void *arg);
|
||||||
|
|
||||||
|
uint32_t ngap_generate_gNB_id(void);
|
||||||
|
|
||||||
|
#endif /* NGAP_GNB_H_ */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @}
|
||||||
|
*/
|
||||||
@@ -0,0 +1,266 @@
|
|||||||
|
/*
|
||||||
|
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
|
||||||
|
* contributor license agreements. See the NOTICE file distributed with
|
||||||
|
* this work for additional information regarding copyright ownership.
|
||||||
|
* The OpenAirInterface Software Alliance licenses this file to You under
|
||||||
|
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
|
||||||
|
* except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.openairinterface.org/?page_id=698
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*-------------------------------------------------------------------------------
|
||||||
|
* For more information about the OpenAirInterface (OAI) Software Alliance:
|
||||||
|
* contact@openairinterface.org
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*! \file ngap_gNB_context_management_procedures.c
|
||||||
|
* \brief NGAP context management procedures
|
||||||
|
* \author S. Roux and Navid Nikaein
|
||||||
|
* \date 2010 - 2015
|
||||||
|
* \email: navid.nikaein@eurecom.fr
|
||||||
|
* \version 1.0
|
||||||
|
* @ingroup _ngap
|
||||||
|
*/
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#include "assertions.h"
|
||||||
|
#include "conversions.h"
|
||||||
|
|
||||||
|
#include "intertask_interface.h"
|
||||||
|
|
||||||
|
#include "ngap_common.h"
|
||||||
|
#include "ngap_gNB_defs.h"
|
||||||
|
|
||||||
|
#include "ngap_gNB_itti_messaging.h"
|
||||||
|
|
||||||
|
#include "ngap_gNB_encoder.h"
|
||||||
|
#include "ngap_gNB_nnsf.h"
|
||||||
|
#include "ngap_gNB_ue_context.h"
|
||||||
|
#include "ngap_gNB_nas_procedures.h"
|
||||||
|
#include "ngap_gNB_management_procedures.h"
|
||||||
|
#include "ngap_gNB_context_management_procedures.h"
|
||||||
|
#include "msc.h"
|
||||||
|
|
||||||
|
|
||||||
|
int ngap_ue_context_release_complete(instance_t instance,
|
||||||
|
ngap_ue_release_complete_t *ue_release_complete_p)
|
||||||
|
{
|
||||||
|
ngap_gNB_instance_t *ngap_gNB_instance_p = NULL;
|
||||||
|
struct ngap_gNB_ue_context_s *ue_context_p = NULL;
|
||||||
|
NGAP_NGAP_PDU_t pdu;
|
||||||
|
NGAP_UEContextReleaseComplete_t *out;
|
||||||
|
NGAP_UEContextReleaseComplete_IEs_t *ie;
|
||||||
|
uint8_t *buffer;
|
||||||
|
uint32_t length;
|
||||||
|
|
||||||
|
/* Retrieve the NGAP gNB instance associated with Mod_id */
|
||||||
|
ngap_gNB_instance_p = ngap_gNB_get_instance(instance);
|
||||||
|
|
||||||
|
DevAssert(ue_release_complete_p != NULL);
|
||||||
|
DevAssert(ngap_gNB_instance_p != NULL);
|
||||||
|
|
||||||
|
/*RB_FOREACH(ue_context_p, ngap_ue_map, &ngap_gNB_instance_p->ngap_ue_head) {
|
||||||
|
NGAP_WARN("in ngap_ue_map: UE context gNB_ue_ngap_id %u mme_ue_ngap_id %u state %u\n",
|
||||||
|
ue_context_p->gNB_ue_ngap_id, ue_context_p->mme_ue_ngap_id,
|
||||||
|
ue_context_p->ue_state);
|
||||||
|
}*/
|
||||||
|
if ((ue_context_p = ngap_gNB_get_ue_context(ngap_gNB_instance_p,
|
||||||
|
ue_release_complete_p->gNB_ue_ngap_id)) == NULL) {
|
||||||
|
/* The context for this gNB ue ngap id doesn't exist in the map of gNB UEs */
|
||||||
|
NGAP_WARN("Failed to find ue context associated with gNB ue ngap id: %u\n",
|
||||||
|
ue_release_complete_p->gNB_ue_ngap_id);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Prepare the NGAP message to encode */
|
||||||
|
memset(&pdu, 0, sizeof(pdu));
|
||||||
|
pdu.present = NGAP_NGAP_PDU_PR_successfulOutcome;
|
||||||
|
pdu.choice.successfulOutcome.procedureCode = NGAP_ProcedureCode_id_UEContextRelease;
|
||||||
|
pdu.choice.successfulOutcome.criticality = NGAP_Criticality_reject;
|
||||||
|
pdu.choice.successfulOutcome.value.present = NGAP_SuccessfulOutcome__value_PR_UEContextReleaseComplete;
|
||||||
|
out = &pdu.choice.successfulOutcome.value.choice.UEContextReleaseComplete;
|
||||||
|
|
||||||
|
/* mandatory */
|
||||||
|
ie = (NGAP_UEContextReleaseComplete_IEs_t *)calloc(1, sizeof(NGAP_UEContextReleaseComplete_IEs_t));
|
||||||
|
ie->id = NGAP_ProtocolIE_ID_id_MME_UE_NGAP_ID;
|
||||||
|
ie->criticality = NGAP_Criticality_ignore;
|
||||||
|
ie->value.present = NGAP_UEContextReleaseComplete_IEs__value_PR_MME_UE_NGAP_ID;
|
||||||
|
ie->value.choice.MME_UE_NGAP_ID = ue_context_p->mme_ue_ngap_id;
|
||||||
|
ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
|
||||||
|
|
||||||
|
/* mandatory */
|
||||||
|
ie = (NGAP_UEContextReleaseComplete_IEs_t *)calloc(1, sizeof(NGAP_UEContextReleaseComplete_IEs_t));
|
||||||
|
ie->id = NGAP_ProtocolIE_ID_id_gNB_UE_NGAP_ID;
|
||||||
|
ie->criticality = NGAP_Criticality_ignore;
|
||||||
|
ie->value.present = NGAP_UEContextReleaseComplete_IEs__value_PR_GNB_UE_NGAP_ID;
|
||||||
|
ie->value.choice.GNB_UE_NGAP_ID = ue_release_complete_p->gNB_ue_ngap_id;
|
||||||
|
ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
|
||||||
|
|
||||||
|
|
||||||
|
if (ngap_gNB_encode_pdu(&pdu, &buffer, &length) < 0) {
|
||||||
|
/* Encode procedure has failed... */
|
||||||
|
NGAP_ERROR("Failed to encode UE context release complete\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
MSC_LOG_TX_MESSAGE(
|
||||||
|
MSC_NGAP_GNB,
|
||||||
|
MSC_NGAP_MME,
|
||||||
|
buffer,
|
||||||
|
length,
|
||||||
|
MSC_AS_TIME_FMT" UEContextRelease successfulOutcome gNB_ue_ngap_id %u mme_ue_ngap_id %u",
|
||||||
|
0,0, //MSC_AS_TIME_ARGS(ctxt_pP),
|
||||||
|
ue_release_complete_p->gNB_ue_ngap_id,
|
||||||
|
ue_context_p->mme_ue_ngap_id);
|
||||||
|
|
||||||
|
/* UE associated signalling -> use the allocated stream */
|
||||||
|
ngap_gNB_itti_send_sctp_data_req(ngap_gNB_instance_p->instance,
|
||||||
|
ue_context_p->mme_ref->assoc_id, buffer,
|
||||||
|
length, ue_context_p->tx_stream);
|
||||||
|
|
||||||
|
//LG ngap_gNB_itti_send_sctp_close_association(ngap_gNB_instance_p->instance,
|
||||||
|
// ue_context_p->mme_ref->assoc_id);
|
||||||
|
// release UE context
|
||||||
|
struct ngap_gNB_ue_context_s *ue_context2_p = NULL;
|
||||||
|
|
||||||
|
if ((ue_context2_p = RB_REMOVE(ngap_ue_map, &ngap_gNB_instance_p->ngap_ue_head, ue_context_p))
|
||||||
|
!= NULL) {
|
||||||
|
NGAP_WARN("Removed UE context gNB_ue_ngap_id %u\n",
|
||||||
|
ue_context2_p->gNB_ue_ngap_id);
|
||||||
|
ngap_gNB_free_ue_context(ue_context2_p);
|
||||||
|
} else {
|
||||||
|
NGAP_WARN("Removing UE context gNB_ue_ngap_id %u: did not find context\n",
|
||||||
|
ue_context_p->gNB_ue_ngap_id);
|
||||||
|
}
|
||||||
|
/*RB_FOREACH(ue_context_p, ngap_ue_map, &ngap_gNB_instance_p->ngap_ue_head) {
|
||||||
|
NGAP_WARN("in ngap_ue_map: UE context gNB_ue_ngap_id %u mme_ue_ngap_id %u state %u\n",
|
||||||
|
ue_context_p->gNB_ue_ngap_id, ue_context_p->mme_ue_ngap_id,
|
||||||
|
ue_context_p->ue_state);
|
||||||
|
}*/
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int ngap_ue_context_release_req(instance_t instance,
|
||||||
|
ngap_ue_release_req_t *ue_release_req_p)
|
||||||
|
{
|
||||||
|
ngap_gNB_instance_t *ngap_gNB_instance_p = NULL;
|
||||||
|
struct ngap_gNB_ue_context_s *ue_context_p = NULL;
|
||||||
|
NGAP_NGAP_PDU_t pdu;
|
||||||
|
NGAP_UEContextReleaseRequest_t *out;
|
||||||
|
NGAP_UEContextReleaseRequest_IEs_t *ie;
|
||||||
|
uint8_t *buffer = NULL;
|
||||||
|
uint32_t length;
|
||||||
|
/* Retrieve the NGAP gNB instance associated with Mod_id */
|
||||||
|
ngap_gNB_instance_p = ngap_gNB_get_instance(instance);
|
||||||
|
|
||||||
|
DevAssert(ue_release_req_p != NULL);
|
||||||
|
DevAssert(ngap_gNB_instance_p != NULL);
|
||||||
|
|
||||||
|
if ((ue_context_p = ngap_gNB_get_ue_context(ngap_gNB_instance_p,
|
||||||
|
ue_release_req_p->gNB_ue_ngap_id)) == NULL) {
|
||||||
|
/* The context for this gNB ue ngap id doesn't exist in the map of gNB UEs */
|
||||||
|
NGAP_WARN("Failed to find ue context associated with gNB ue ngap id: %u\n",
|
||||||
|
ue_release_req_p->gNB_ue_ngap_id);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Prepare the NGAP message to encode */
|
||||||
|
memset(&pdu, 0, sizeof(pdu));
|
||||||
|
pdu.present = NGAP_NGAP_PDU_PR_initiatingMessage;
|
||||||
|
pdu.choice.initiatingMessage.procedureCode = NGAP_ProcedureCode_id_UEContextReleaseRequest;
|
||||||
|
pdu.choice.initiatingMessage.criticality = NGAP_Criticality_ignore;
|
||||||
|
pdu.choice.initiatingMessage.value.present = NGAP_InitiatingMessage__value_PR_UEContextReleaseRequest;
|
||||||
|
out = &pdu.choice.initiatingMessage.value.choice.UEContextReleaseRequest;
|
||||||
|
|
||||||
|
/* mandatory */
|
||||||
|
ie = (NGAP_UEContextReleaseRequest_IEs_t *)calloc(1, sizeof(NGAP_UEContextReleaseRequest_IEs_t));
|
||||||
|
ie->id = NGAP_ProtocolIE_ID_id_MME_UE_NGAP_ID;
|
||||||
|
ie->criticality = NGAP_Criticality_reject;
|
||||||
|
ie->value.present = NGAP_UEContextReleaseRequest_IEs__value_PR_MME_UE_NGAP_ID;
|
||||||
|
ie->value.choice.MME_UE_NGAP_ID = ue_context_p->mme_ue_ngap_id;
|
||||||
|
ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
|
||||||
|
|
||||||
|
/* mandatory */
|
||||||
|
ie = (NGAP_UEContextReleaseRequest_IEs_t *)calloc(1, sizeof(NGAP_UEContextReleaseRequest_IEs_t));
|
||||||
|
ie->id = NGAP_ProtocolIE_ID_id_gNB_UE_NGAP_ID;
|
||||||
|
ie->criticality = NGAP_Criticality_reject;
|
||||||
|
ie->value.present = NGAP_UEContextReleaseRequest_IEs__value_PR_GNB_UE_NGAP_ID;
|
||||||
|
ie->value.choice.GNB_UE_NGAP_ID = ue_release_req_p->gNB_ue_ngap_id;
|
||||||
|
ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
|
||||||
|
|
||||||
|
/* mandatory */
|
||||||
|
ie = (NGAP_UEContextReleaseRequest_IEs_t *)calloc(1, sizeof(NGAP_UEContextReleaseRequest_IEs_t));
|
||||||
|
ie->id = NGAP_ProtocolIE_ID_id_Cause;
|
||||||
|
ie->criticality = NGAP_Criticality_ignore;
|
||||||
|
ie->value.present = NGAP_UEContextReleaseRequest_IEs__value_PR_Cause;
|
||||||
|
|
||||||
|
switch (ue_release_req_p->cause) {
|
||||||
|
case NGAP_Cause_PR_radioNetwork:
|
||||||
|
ie->value.choice.Cause.present = NGAP_Cause_PR_radioNetwork;
|
||||||
|
ie->value.choice.Cause.choice.radioNetwork = ue_release_req_p->cause_value;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case NGAP_Cause_PR_transport:
|
||||||
|
ie->value.choice.Cause.present = NGAP_Cause_PR_transport;
|
||||||
|
ie->value.choice.Cause.choice.transport = ue_release_req_p->cause_value;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case NGAP_Cause_PR_nas:
|
||||||
|
ie->value.choice.Cause.present = NGAP_Cause_PR_nas;
|
||||||
|
ie->value.choice.Cause.choice.nas = ue_release_req_p->cause_value;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case NGAP_Cause_PR_protocol:
|
||||||
|
ie->value.choice.Cause.present = NGAP_Cause_PR_protocol;
|
||||||
|
ie->value.choice.Cause.choice.protocol = ue_release_req_p->cause_value;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case NGAP_Cause_PR_misc:
|
||||||
|
ie->value.choice.Cause.present = NGAP_Cause_PR_misc;
|
||||||
|
ie->value.choice.Cause.choice.misc = ue_release_req_p->cause_value;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case NGAP_Cause_PR_NOTHING:
|
||||||
|
default:
|
||||||
|
ie->value.choice.Cause.present = NGAP_Cause_PR_NOTHING;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
if (ngap_gNB_encode_pdu(&pdu, &buffer, &length) < 0) {
|
||||||
|
/* Encode procedure has failed... */
|
||||||
|
NGAP_ERROR("Failed to encode UE context release complete\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
MSC_LOG_TX_MESSAGE(
|
||||||
|
MSC_NGAP_GNB,
|
||||||
|
MSC_NGAP_MME,
|
||||||
|
buffer,
|
||||||
|
length,
|
||||||
|
MSC_AS_TIME_FMT" UEContextReleaseRequest initiatingMessage gNB_ue_ngap_id %u mme_ue_ngap_id %u",
|
||||||
|
0,0,//MSC_AS_TIME_ARGS(ctxt_pP),
|
||||||
|
ue_release_req_p->gNB_ue_ngap_id,
|
||||||
|
ue_context_p->mme_ue_ngap_id);
|
||||||
|
|
||||||
|
/* UE associated signalling -> use the allocated stream */
|
||||||
|
ngap_gNB_itti_send_sctp_data_req(ngap_gNB_instance_p->instance,
|
||||||
|
ue_context_p->mme_ref->assoc_id, buffer,
|
||||||
|
length, ue_context_p->tx_stream);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,32 @@
|
|||||||
|
/*
|
||||||
|
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
|
||||||
|
* contributor license agreements. See the NOTICE file distributed with
|
||||||
|
* this work for additional information regarding copyright ownership.
|
||||||
|
* The OpenAirInterface Software Alliance licenses this file to You under
|
||||||
|
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
|
||||||
|
* except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.openairinterface.org/?page_id=698
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*-------------------------------------------------------------------------------
|
||||||
|
* For more information about the OpenAirInterface (OAI) Software Alliance:
|
||||||
|
* contact@openairinterface.org
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef NGAP_GNB_CONTEXT_MANAGEMENT_PROCEDURES_H_
|
||||||
|
#define NGAP_GNB_CONTEXT_MANAGEMENT_PROCEDURES_H_
|
||||||
|
|
||||||
|
|
||||||
|
int ngap_ue_context_release_complete(instance_t instance,
|
||||||
|
ngap_ue_release_complete_t *ue_release_complete_p);
|
||||||
|
|
||||||
|
int ngap_ue_context_release_req(instance_t instance,
|
||||||
|
ngap_ue_release_req_t *ue_release_req_p);
|
||||||
|
|
||||||
|
#endif /* NGAP_GNB_CONTEXT_MANAGEMENT_PROCEDURES_H_ */
|
||||||
@@ -0,0 +1,187 @@
|
|||||||
|
/*
|
||||||
|
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
|
||||||
|
* contributor license agreements. See the NOTICE file distributed with
|
||||||
|
* this work for additional information regarding copyright ownership.
|
||||||
|
* The OpenAirInterface Software Alliance licenses this file to You under
|
||||||
|
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
|
||||||
|
* except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.openairinterface.org/?page_id=698
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*-------------------------------------------------------------------------------
|
||||||
|
* For more information about the OpenAirInterface (OAI) Software Alliance:
|
||||||
|
* contact@openairinterface.org
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*! \file ngap_gNB_decoder.c
|
||||||
|
* \brief ngap pdu decode procedures for gNB
|
||||||
|
* \author Sebastien ROUX and Navid Nikaein
|
||||||
|
* \email navid.nikaein@eurecom.fr
|
||||||
|
* \date 2013 - 2015
|
||||||
|
* \version 0.1
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#include "assertions.h"
|
||||||
|
|
||||||
|
#include "intertask_interface.h"
|
||||||
|
|
||||||
|
#include "ngap_common.h"
|
||||||
|
#include "ngap_gNB_decoder.h"
|
||||||
|
|
||||||
|
static int ngap_gNB_decode_initiating_message(NGAP_NGAP_PDU_t *pdu) {
|
||||||
|
asn_encode_to_new_buffer_result_t res = { NULL, {0, NULL, NULL} };
|
||||||
|
DevAssert(pdu != NULL);
|
||||||
|
|
||||||
|
switch(pdu->choice.initiatingMessage.procedureCode) {
|
||||||
|
case NGAP_ProcedureCode_id_downlinkNASTransport:
|
||||||
|
res = asn_encode_to_new_buffer(NULL, ATS_CANONICAL_XER, &asn_DEF_NGAP_NGAP_PDU, pdu);
|
||||||
|
free(res.buffer);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case NGAP_ProcedureCode_id_InitialContextSetup:
|
||||||
|
res = asn_encode_to_new_buffer(NULL, ATS_CANONICAL_XER, &asn_DEF_NGAP_NGAP_PDU, pdu);
|
||||||
|
free(res.buffer);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case NGAP_ProcedureCode_id_UEContextRelease:
|
||||||
|
res = asn_encode_to_new_buffer(NULL, ATS_CANONICAL_XER, &asn_DEF_NGAP_NGAP_PDU, pdu);
|
||||||
|
free(res.buffer);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case NGAP_ProcedureCode_id_Paging:
|
||||||
|
res = asn_encode_to_new_buffer(NULL, ATS_CANONICAL_XER, &asn_DEF_NGAP_NGAP_PDU, pdu);
|
||||||
|
NGAP_INFO("Paging initiating message\n");
|
||||||
|
free(res.buffer);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case NGAP_ProcedureCode_id_E_RABSetup:
|
||||||
|
res = asn_encode_to_new_buffer(NULL, ATS_CANONICAL_XER, &asn_DEF_NGAP_NGAP_PDU, pdu);
|
||||||
|
free(res.buffer);
|
||||||
|
NGAP_INFO("E_RABSetup initiating message\n");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case NGAP_ProcedureCode_id_E_RABModify:
|
||||||
|
res = asn_encode_to_new_buffer(NULL, ATS_CANONICAL_XER, &asn_DEF_NGAP_NGAP_PDU, pdu);
|
||||||
|
free(res.buffer);
|
||||||
|
NGAP_INFO("E_RABModify initiating message\n");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case NGAP_ProcedureCode_id_E_RABRelease:
|
||||||
|
res = asn_encode_to_new_buffer(NULL, ATS_CANONICAL_XER, &asn_DEF_NGAP_NGAP_PDU, pdu);
|
||||||
|
free(res.buffer);
|
||||||
|
NGAP_INFO("TODO E_RABRelease initiating message\n");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case NGAP_ProcedureCode_id_ErrorIndication:
|
||||||
|
res = asn_encode_to_new_buffer(NULL, ATS_CANONICAL_XER, &asn_DEF_NGAP_NGAP_PDU, pdu);
|
||||||
|
free(res.buffer);
|
||||||
|
NGAP_INFO("TODO ErrorIndication initiating message\n");
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
NGAP_ERROR("Unknown procedure ID (%d) for initiating message\n",
|
||||||
|
(int)pdu->choice.initiatingMessage.procedureCode);
|
||||||
|
AssertFatal( 0, "Unknown procedure ID (%d) for initiating message\n",
|
||||||
|
(int)pdu->choice.initiatingMessage.procedureCode);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int ngap_gNB_decode_successful_outcome(NGAP_NGAP_PDU_t *pdu) {
|
||||||
|
asn_encode_to_new_buffer_result_t res = { NULL, {0, NULL, NULL} };
|
||||||
|
DevAssert(pdu != NULL);
|
||||||
|
|
||||||
|
switch(pdu->choice.successfulOutcome.procedureCode) {
|
||||||
|
case NGAP_ProcedureCode_id_S1Setup:
|
||||||
|
res = asn_encode_to_new_buffer(NULL, ATS_CANONICAL_XER, &asn_DEF_NGAP_NGAP_PDU, pdu);
|
||||||
|
free(res.buffer);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case NGAP_ProcedureCode_id_PathSwitchRequest:
|
||||||
|
res = asn_encode_to_new_buffer(NULL, ATS_CANONICAL_XER, &asn_DEF_NGAP_NGAP_PDU, pdu);
|
||||||
|
free(res.buffer);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case NGAP_ProcedureCode_id_E_RABModificationIndication:
|
||||||
|
res = asn_encode_to_new_buffer(NULL, ATS_CANONICAL_XER, &asn_DEF_NGAP_NGAP_PDU, pdu);
|
||||||
|
free(res.buffer);
|
||||||
|
break;
|
||||||
|
|
||||||
|
|
||||||
|
default:
|
||||||
|
NGAP_ERROR("Unknown procedure ID (%d) for successfull outcome message\n",
|
||||||
|
(int)pdu->choice.successfulOutcome.procedureCode);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int ngap_gNB_decode_unsuccessful_outcome(NGAP_NGAP_PDU_t *pdu) {
|
||||||
|
asn_encode_to_new_buffer_result_t res = { NULL, {0, NULL, NULL} };
|
||||||
|
DevAssert(pdu != NULL);
|
||||||
|
|
||||||
|
switch(pdu->choice.unsuccessfulOutcome.procedureCode) {
|
||||||
|
case NGAP_ProcedureCode_id_S1Setup:
|
||||||
|
res = asn_encode_to_new_buffer(NULL, ATS_CANONICAL_XER, &asn_DEF_NGAP_NGAP_PDU, pdu);
|
||||||
|
free(res.buffer);
|
||||||
|
break;
|
||||||
|
case NGAP_ProcedureCode_id_PathSwitchRequest:
|
||||||
|
res = asn_encode_to_new_buffer(NULL, ATS_CANONICAL_XER, &asn_DEF_NGAP_NGAP_PDU, pdu);
|
||||||
|
free(res.buffer);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
NGAP_ERROR("Unknown procedure ID (%d) for unsuccessfull outcome message\n",
|
||||||
|
(int)pdu->choice.unsuccessfulOutcome.procedureCode);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int ngap_gNB_decode_pdu(NGAP_NGAP_PDU_t *pdu, const uint8_t *const buffer,
|
||||||
|
const uint32_t length) {
|
||||||
|
asn_dec_rval_t dec_ret;
|
||||||
|
DevAssert(pdu != NULL);
|
||||||
|
DevAssert(buffer != NULL);
|
||||||
|
dec_ret = aper_decode(NULL,
|
||||||
|
&asn_DEF_NGAP_NGAP_PDU,
|
||||||
|
(void **)&pdu,
|
||||||
|
buffer,
|
||||||
|
length,
|
||||||
|
0,
|
||||||
|
0);
|
||||||
|
|
||||||
|
if (dec_ret.code != RC_OK) {
|
||||||
|
NGAP_ERROR("Failed to decode pdu\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch(pdu->present) {
|
||||||
|
case NGAP_NGAP_PDU_PR_initiatingMessage:
|
||||||
|
return ngap_gNB_decode_initiating_message(pdu);
|
||||||
|
|
||||||
|
case NGAP_NGAP_PDU_PR_successfulOutcome:
|
||||||
|
return ngap_gNB_decode_successful_outcome(pdu);
|
||||||
|
|
||||||
|
case NGAP_NGAP_PDU_PR_unsuccessfulOutcome:
|
||||||
|
return ngap_gNB_decode_unsuccessful_outcome(pdu);
|
||||||
|
|
||||||
|
default:
|
||||||
|
NGAP_DEBUG("Unknown presence (%d) or not implemented\n", (int)pdu->present);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
/*
|
||||||
|
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
|
||||||
|
* contributor license agreements. See the NOTICE file distributed with
|
||||||
|
* this work for additional information regarding copyright ownership.
|
||||||
|
* The OpenAirInterface Software Alliance licenses this file to You under
|
||||||
|
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
|
||||||
|
* except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.openairinterface.org/?page_id=698
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*-------------------------------------------------------------------------------
|
||||||
|
* For more information about the OpenAirInterface (OAI) Software Alliance:
|
||||||
|
* contact@openairinterface.org
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#ifndef NGAP_GNB_DECODER_H_
|
||||||
|
#define NGAP_GNB_DECODER_H_
|
||||||
|
|
||||||
|
int ngap_gNB_decode_pdu(NGAP_NGAP_PDU_t *pdu, const uint8_t *const buffer,
|
||||||
|
const uint32_t length) __attribute__ ((warn_unused_result));
|
||||||
|
|
||||||
|
#endif /* NGAP_GNB_DECODER_H_ */
|
||||||
@@ -0,0 +1,38 @@
|
|||||||
|
/*
|
||||||
|
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
|
||||||
|
* contributor license agreements. See the NOTICE file distributed with
|
||||||
|
* this work for additional information regarding copyright ownership.
|
||||||
|
* The OpenAirInterface Software Alliance licenses this file to You under
|
||||||
|
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
|
||||||
|
* except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.openairinterface.org/?page_id=698
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*-------------------------------------------------------------------------------
|
||||||
|
* For more information about the OpenAirInterface (OAI) Software Alliance:
|
||||||
|
* contact@openairinterface.org
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef NGAP_GNB_DEFAULT_VALUES_H_
|
||||||
|
#define NGAP_GNB_DEFAULT_VALUES_H_
|
||||||
|
|
||||||
|
#define GNB_TAC (1)
|
||||||
|
#define GNB_MCC (208)
|
||||||
|
#define GNB_MNC (92)
|
||||||
|
|
||||||
|
#define GNB_NAME "Eurecom GNB"
|
||||||
|
#define GNB_NAME_FORMAT (GNB_NAME" %u")
|
||||||
|
|
||||||
|
#define NGAP_PORT_NUMBER (36412)
|
||||||
|
#define NGAP_SCTP_PPID (18)
|
||||||
|
|
||||||
|
#define X2AP_PORT_NUMBER (36422)
|
||||||
|
#define X2AP_SCTP_PPID (27)
|
||||||
|
|
||||||
|
#endif /* NGAP_GNB_DEFAULT_VALUES_H_ */
|
||||||
@@ -0,0 +1,240 @@
|
|||||||
|
/*
|
||||||
|
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
|
||||||
|
* contributor license agreements. See the NOTICE file distributed with
|
||||||
|
* this work for additional information regarding copyright ownership.
|
||||||
|
* The OpenAirInterface Software Alliance licenses this file to You under
|
||||||
|
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
|
||||||
|
* except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.openairinterface.org/?page_id=698
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*-------------------------------------------------------------------------------
|
||||||
|
* For more information about the OpenAirInterface (OAI) Software Alliance:
|
||||||
|
* contact@openairinterface.org
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#include "queue.h"
|
||||||
|
#include "tree.h"
|
||||||
|
|
||||||
|
#include "sctp_gNB_defs.h"
|
||||||
|
|
||||||
|
#ifndef NGAP_GNB_DEFS_H_
|
||||||
|
#define NGAP_GNB_DEFS_H_
|
||||||
|
|
||||||
|
#define NGAP_GNB_NAME_LENGTH_MAX (150)
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
/* Disconnected state: initial state for any association. */
|
||||||
|
NGAP_GNB_STATE_DISCONNECTED = 0x0,
|
||||||
|
/* State waiting for S1 Setup response message if gNB is MME accepted or
|
||||||
|
* S1 Setup failure if MME rejects the gNB.
|
||||||
|
*/
|
||||||
|
NGAP_GNB_STATE_WAITING = 0x1,
|
||||||
|
/* The gNB is successfully connected to MME, UE contexts can be created. */
|
||||||
|
NGAP_GNB_STATE_CONNECTED = 0x2,
|
||||||
|
/* The MME has sent an overload start message. Once the MME disables the
|
||||||
|
* OVERLOAD marker, the state of the association will be
|
||||||
|
* NGAP_GNB_STATE_CONNECTED.
|
||||||
|
*/
|
||||||
|
NGAP_GNB_OVERLOAD = 0x3,
|
||||||
|
/* Max number of states available */
|
||||||
|
NGAP_GNB_STATE_MAX,
|
||||||
|
} ngap_gNB_state_t;
|
||||||
|
|
||||||
|
/* If the Overload Action IE in the OVERLOAD START message is set to
|
||||||
|
* - “reject all RRC connection establishments for non-emergency mobile
|
||||||
|
* originated data transfer “ (i.e. reject traffic corresponding to RRC cause
|
||||||
|
* “mo-data “ (TS 36.331 [16])), or
|
||||||
|
* - “reject all RRC connection establishments for signalling “ (i.e. reject
|
||||||
|
* traffic corresponding to RRC cause “modata” and “mo-signalling”
|
||||||
|
* (TS 36.331 [16])),or
|
||||||
|
* - “only permit RRC connection establishments for emergency sessions and
|
||||||
|
* mobile terminated services” (i.e. only permit traffic corresponding to RRC
|
||||||
|
* cause “emergency” and “mt-Access” (TS 36.331 [16])).
|
||||||
|
*
|
||||||
|
* NOTE: When the Overload Action IE is set to “only permit RRC connection
|
||||||
|
* establishments for emergency sessions and mobile terminated services”,
|
||||||
|
* emergency calls with RRC cause “highPriorityAcess” from high priority users
|
||||||
|
* are rejected (TS 24.301 [24]).
|
||||||
|
*/
|
||||||
|
typedef enum {
|
||||||
|
NGAP_OVERLOAD_REJECT_MO_DATA = 0x0,
|
||||||
|
NGAP_OVERLOAD_REJECT_ALL_SIGNALLING = 0x1,
|
||||||
|
NGAP_OVERLOAD_ONLY_EMERGENCY_AND_MT = 0x2,
|
||||||
|
NGAP_NO_OVERLOAD = 0x3,
|
||||||
|
NGAP_OVERLOAD_MAX,
|
||||||
|
} ngap_overload_state_t;
|
||||||
|
|
||||||
|
/* Served PLMN identity element */
|
||||||
|
struct plmn_identity_s {
|
||||||
|
uint16_t mcc;
|
||||||
|
uint16_t mnc;
|
||||||
|
uint8_t mnc_digit_length;
|
||||||
|
STAILQ_ENTRY(plmn_identity_s) next;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Served group id element */
|
||||||
|
struct served_group_id_s {
|
||||||
|
uint16_t mme_group_id;
|
||||||
|
STAILQ_ENTRY(served_group_id_s) next;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Served mme code for a particular MME */
|
||||||
|
struct mme_code_s {
|
||||||
|
uint8_t mme_code;
|
||||||
|
STAILQ_ENTRY(mme_code_s) next;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Served gummei element */
|
||||||
|
struct served_gummei_s {
|
||||||
|
/* Number of MME served PLMNs */
|
||||||
|
uint8_t nb_served_plmns;
|
||||||
|
/* List of served PLMNs by MME */
|
||||||
|
STAILQ_HEAD(served_plmns_s, plmn_identity_s) served_plmns;
|
||||||
|
|
||||||
|
/* Number of group id in list */
|
||||||
|
uint8_t nb_group_id;
|
||||||
|
/* Served group id list */
|
||||||
|
STAILQ_HEAD(served_group_ids_s, served_group_id_s) served_group_ids;
|
||||||
|
|
||||||
|
/* Number of MME code */
|
||||||
|
uint8_t nb_mme_code;
|
||||||
|
/* MME Code to uniquely identify an MME within an MME pool area */
|
||||||
|
STAILQ_HEAD(mme_codes_s, mme_code_s) mme_codes;
|
||||||
|
|
||||||
|
/* Next GUMMEI element */
|
||||||
|
STAILQ_ENTRY(served_gummei_s) next;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ngap_gNB_instance_s;
|
||||||
|
|
||||||
|
/* This structure describes association of a gNB to a MME */
|
||||||
|
typedef struct ngap_gNB_mme_data_s {
|
||||||
|
/* MME descriptors tree, ordered by sctp assoc id */
|
||||||
|
RB_ENTRY(ngap_gNB_mme_data_s) entry;
|
||||||
|
|
||||||
|
/* This is the optional name provided by the MME */
|
||||||
|
char *mme_name;
|
||||||
|
|
||||||
|
/* MME NGAP IP address */
|
||||||
|
net_ip_address_t mme_s1_ip;
|
||||||
|
|
||||||
|
/* List of served GUMMEI per MME. There is one GUMMEI per RAT with a max
|
||||||
|
* number of 8 RATs but in our case only one is used. The LTE related pool
|
||||||
|
* configuration is included on the first place in the list.
|
||||||
|
*/
|
||||||
|
STAILQ_HEAD(served_gummeis_s, served_gummei_s) served_gummei;
|
||||||
|
|
||||||
|
/* Relative processing capacity of an MME with respect to the other MMEs
|
||||||
|
* in the pool in order to load-balance MMEs within a pool as defined
|
||||||
|
* in TS 23.401.
|
||||||
|
*/
|
||||||
|
uint8_t relative_mme_capacity;
|
||||||
|
|
||||||
|
/* Current MME overload information (if any). */
|
||||||
|
ngap_overload_state_t overload_state;
|
||||||
|
/* Current gNB->MME NGAP association state */
|
||||||
|
ngap_gNB_state_t state;
|
||||||
|
|
||||||
|
/* Next usable stream for UE signalling */
|
||||||
|
int32_t nextstream;
|
||||||
|
|
||||||
|
/* Number of input/ouput streams */
|
||||||
|
uint16_t in_streams;
|
||||||
|
uint16_t out_streams;
|
||||||
|
|
||||||
|
/* Connexion id used between SCTP/NGAP */
|
||||||
|
uint16_t cnx_id;
|
||||||
|
|
||||||
|
/* SCTP association id */
|
||||||
|
int32_t assoc_id;
|
||||||
|
|
||||||
|
/* This is served PLMN IDs communicated to the MME via an index over the
|
||||||
|
* MCC/MNC array in ngap_gNB_instance */
|
||||||
|
uint8_t broadcast_plmn_num;
|
||||||
|
uint8_t broadcast_plmn_index[PLMN_LIST_MAX_SIZE];
|
||||||
|
|
||||||
|
/* Only meaningfull in virtual mode */
|
||||||
|
struct ngap_gNB_instance_s *ngap_gNB_instance;
|
||||||
|
} ngap_gNB_mme_data_t;
|
||||||
|
|
||||||
|
typedef struct ngap_gNB_instance_s {
|
||||||
|
/* Next ngap gNB association.
|
||||||
|
* Only used for virtual mode.
|
||||||
|
*/
|
||||||
|
STAILQ_ENTRY(ngap_gNB_instance_s) ngap_gNB_entries;
|
||||||
|
|
||||||
|
/* Number of MME requested by gNB (tree size) */
|
||||||
|
uint32_t ngap_mme_nb;
|
||||||
|
/* Number of MME for which association is pending */
|
||||||
|
uint32_t ngap_mme_pending_nb;
|
||||||
|
/* Number of MME successfully associated to gNB */
|
||||||
|
uint32_t ngap_mme_associated_nb;
|
||||||
|
/* Tree of NGAP MME associations ordered by association ID */
|
||||||
|
RB_HEAD(ngap_mme_map, ngap_gNB_mme_data_s) ngap_mme_head;
|
||||||
|
|
||||||
|
/* TODO: add a map ordered by relative MME capacity */
|
||||||
|
|
||||||
|
/* Tree of UE ordered by gNB_ue_ngap_id's */
|
||||||
|
RB_HEAD(ngap_ue_map, ngap_gNB_ue_context_s) ngap_ue_head;
|
||||||
|
|
||||||
|
/* For virtual mode, mod_id as defined in the rest of the L1/L2 stack */
|
||||||
|
instance_t instance;
|
||||||
|
|
||||||
|
/* Displayable name of gNB */
|
||||||
|
char *gNB_name;
|
||||||
|
|
||||||
|
/* Unique gNB_id to identify the gNB within EPC.
|
||||||
|
* In our case the gNB is a macro gNB so the id will be 20 bits long.
|
||||||
|
* For Home gNB id, this field should be 28 bits long.
|
||||||
|
*/
|
||||||
|
uint32_t gNB_id;
|
||||||
|
/* The type of the cell */
|
||||||
|
enum cell_type_e cell_type;
|
||||||
|
|
||||||
|
/* Tracking area code */
|
||||||
|
uint16_t tac;
|
||||||
|
|
||||||
|
/* gNB NGAP IP address */
|
||||||
|
net_ip_address_t gNB_s1_ip;
|
||||||
|
|
||||||
|
/* Mobile Country Code
|
||||||
|
* Mobile Network Code
|
||||||
|
*/
|
||||||
|
uint16_t mcc[PLMN_LIST_MAX_SIZE];
|
||||||
|
uint16_t mnc[PLMN_LIST_MAX_SIZE];
|
||||||
|
uint8_t mnc_digit_length[PLMN_LIST_MAX_SIZE];
|
||||||
|
uint8_t num_plmn;
|
||||||
|
|
||||||
|
/* Default Paging DRX of the gNB as defined in TS 36.304 */
|
||||||
|
paging_drx_t default_drx;
|
||||||
|
} ngap_gNB_instance_t;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
/* List of served gNBs
|
||||||
|
* Only used for virtual mode
|
||||||
|
*/
|
||||||
|
STAILQ_HEAD(ngap_gNB_instances_head_s, ngap_gNB_instance_s) ngap_gNB_instances_head;
|
||||||
|
/* Nb of registered gNBs */
|
||||||
|
uint8_t nb_registered_gNBs;
|
||||||
|
|
||||||
|
/* Generate a unique connexion id used between NGAP and SCTP */
|
||||||
|
uint16_t global_cnx_id;
|
||||||
|
} ngap_gNB_internal_data_t;
|
||||||
|
|
||||||
|
int ngap_gNB_compare_assoc_id(
|
||||||
|
struct ngap_gNB_mme_data_s *p1, struct ngap_gNB_mme_data_s *p2);
|
||||||
|
|
||||||
|
/* Generate the tree management functions */
|
||||||
|
RB_PROTOTYPE(ngap_mme_map, ngap_gNB_mme_data_s, entry,
|
||||||
|
ngap_gNB_compare_assoc_id);
|
||||||
|
|
||||||
|
#endif /* NGAP_GNB_DEFS_H_ */
|
||||||
@@ -0,0 +1,222 @@
|
|||||||
|
/*
|
||||||
|
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
|
||||||
|
* contributor license agreements. See the NOTICE file distributed with
|
||||||
|
* this work for additional information regarding copyright ownership.
|
||||||
|
* The OpenAirInterface Software Alliance licenses this file to You under
|
||||||
|
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
|
||||||
|
* except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.openairinterface.org/?page_id=698
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*-------------------------------------------------------------------------------
|
||||||
|
* For more information about the OpenAirInterface (OAI) Software Alliance:
|
||||||
|
* contact@openairinterface.org
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*! \file ngap_gNB_encoder.c
|
||||||
|
* \brief ngap pdu encode procedures for gNB
|
||||||
|
* \author Sebastien ROUX and Navid Nikaein
|
||||||
|
* \email navid.nikaein@eurecom.fr
|
||||||
|
* \date 2013 - 2015
|
||||||
|
* \version 0.1
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#include "assertions.h"
|
||||||
|
#include "conversions.h"
|
||||||
|
#include "intertask_interface.h"
|
||||||
|
#include "ngap_common.h"
|
||||||
|
#include "ngap_gNB_encoder.h"
|
||||||
|
|
||||||
|
static inline int ngap_gNB_encode_initiating(NGAP_NGAP_PDU_t *pdu,
|
||||||
|
uint8_t **buffer,
|
||||||
|
uint32_t *len);
|
||||||
|
|
||||||
|
static inline int ngap_gNB_encode_successfull_outcome(NGAP_NGAP_PDU_t *pdu,
|
||||||
|
uint8_t **buffer, uint32_t *len);
|
||||||
|
|
||||||
|
static inline int ngap_gNB_encode_unsuccessfull_outcome(NGAP_NGAP_PDU_t *pdu,
|
||||||
|
uint8_t **buffer, uint32_t *len);
|
||||||
|
|
||||||
|
int ngap_gNB_encode_pdu(NGAP_NGAP_PDU_t *pdu, uint8_t **buffer, uint32_t *len) {
|
||||||
|
int ret = -1;
|
||||||
|
DevAssert(pdu != NULL);
|
||||||
|
DevAssert(buffer != NULL);
|
||||||
|
DevAssert(len != NULL);
|
||||||
|
|
||||||
|
switch(pdu->present) {
|
||||||
|
case NGAP_NGAP_PDU_PR_initiatingMessage:
|
||||||
|
ret = ngap_gNB_encode_initiating(pdu, buffer, len);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case NGAP_NGAP_PDU_PR_successfulOutcome:
|
||||||
|
ret = ngap_gNB_encode_successfull_outcome(pdu, buffer, len);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case NGAP_NGAP_PDU_PR_unsuccessfulOutcome:
|
||||||
|
ret = ngap_gNB_encode_unsuccessfull_outcome(pdu, buffer, len);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
NGAP_DEBUG("Unknown message outcome (%d) or not implemented",
|
||||||
|
(int)pdu->present);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_NGAP_NGAP_PDU, pdu);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline
|
||||||
|
int ngap_gNB_encode_initiating(NGAP_NGAP_PDU_t *pdu,
|
||||||
|
uint8_t **buffer, uint32_t *len) {
|
||||||
|
asn_encode_to_new_buffer_result_t res = { NULL, {0, NULL, NULL} };
|
||||||
|
DevAssert(pdu != NULL);
|
||||||
|
|
||||||
|
switch(pdu->choice.initiatingMessage.procedureCode) {
|
||||||
|
case NGAP_ProcedureCode_id_S1Setup:
|
||||||
|
res = asn_encode_to_new_buffer(NULL, ATS_CANONICAL_XER, &asn_DEF_NGAP_NGAP_PDU, pdu);
|
||||||
|
free(res.buffer);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case NGAP_ProcedureCode_id_uplinkNASTransport:
|
||||||
|
res = asn_encode_to_new_buffer(NULL, ATS_CANONICAL_XER, &asn_DEF_NGAP_NGAP_PDU, pdu);
|
||||||
|
free(res.buffer);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case NGAP_ProcedureCode_id_UECapabilityInfoIndication:
|
||||||
|
res = asn_encode_to_new_buffer(NULL, ATS_CANONICAL_XER, &asn_DEF_NGAP_NGAP_PDU, pdu);
|
||||||
|
free(res.buffer);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case NGAP_ProcedureCode_id_initialUEMessage:
|
||||||
|
res = asn_encode_to_new_buffer(NULL, ATS_CANONICAL_XER, &asn_DEF_NGAP_NGAP_PDU, pdu);
|
||||||
|
free(res.buffer);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case NGAP_ProcedureCode_id_NASNonDeliveryIndication:
|
||||||
|
res = asn_encode_to_new_buffer(NULL, ATS_CANONICAL_XER, &asn_DEF_NGAP_NGAP_PDU, pdu);
|
||||||
|
free(res.buffer);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case NGAP_ProcedureCode_id_UEContextReleaseRequest:
|
||||||
|
res = asn_encode_to_new_buffer(NULL, ATS_CANONICAL_XER, &asn_DEF_NGAP_NGAP_PDU, pdu);
|
||||||
|
free(res.buffer);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case NGAP_ProcedureCode_id_PathSwitchRequest:
|
||||||
|
res = asn_encode_to_new_buffer(NULL, ATS_CANONICAL_XER, &asn_DEF_NGAP_NGAP_PDU, pdu);
|
||||||
|
free(res.buffer);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case NGAP_ProcedureCode_id_E_RABModificationIndication:
|
||||||
|
res = asn_encode_to_new_buffer(NULL, ATS_CANONICAL_XER, &asn_DEF_NGAP_NGAP_PDU, pdu);
|
||||||
|
free(res.buffer);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
NGAP_DEBUG("Unknown procedure ID (%d) for initiating message\n",
|
||||||
|
(int)pdu->choice.initiatingMessage.procedureCode);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (asn1_xer_print) {
|
||||||
|
xer_fprint(stdout, &asn_DEF_NGAP_NGAP_PDU, (void *)pdu);
|
||||||
|
}
|
||||||
|
|
||||||
|
memset(&res, 0, sizeof(res));
|
||||||
|
res = asn_encode_to_new_buffer(NULL, ATS_ALIGNED_CANONICAL_PER, &asn_DEF_NGAP_NGAP_PDU, pdu);
|
||||||
|
*buffer = res.buffer;
|
||||||
|
*len = res.result.encoded;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline
|
||||||
|
int ngap_gNB_encode_successfull_outcome(NGAP_NGAP_PDU_t *pdu,
|
||||||
|
uint8_t **buffer, uint32_t *len) {
|
||||||
|
asn_encode_to_new_buffer_result_t res = { NULL, {0, NULL, NULL} };
|
||||||
|
DevAssert(pdu != NULL);
|
||||||
|
|
||||||
|
switch(pdu->choice.successfulOutcome.procedureCode) {
|
||||||
|
case NGAP_ProcedureCode_id_InitialContextSetup:
|
||||||
|
res = asn_encode_to_new_buffer(NULL, ATS_CANONICAL_XER, &asn_DEF_NGAP_NGAP_PDU, pdu);
|
||||||
|
free(res.buffer);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case NGAP_ProcedureCode_id_UEContextRelease:
|
||||||
|
res = asn_encode_to_new_buffer(NULL, ATS_CANONICAL_XER, &asn_DEF_NGAP_NGAP_PDU, pdu);
|
||||||
|
free(res.buffer);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case NGAP_ProcedureCode_id_E_RABSetup:
|
||||||
|
res = asn_encode_to_new_buffer(NULL, ATS_CANONICAL_XER, &asn_DEF_NGAP_NGAP_PDU, pdu);
|
||||||
|
free(res.buffer);
|
||||||
|
NGAP_INFO("E_RABSetup successful message\n");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case NGAP_ProcedureCode_id_E_RABModify:
|
||||||
|
res = asn_encode_to_new_buffer(NULL, ATS_CANONICAL_XER, &asn_DEF_NGAP_NGAP_PDU, pdu);
|
||||||
|
free(res.buffer);
|
||||||
|
NGAP_INFO("E_RABModify successful message\n");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case NGAP_ProcedureCode_id_E_RABRelease:
|
||||||
|
res = asn_encode_to_new_buffer(NULL, ATS_CANONICAL_XER, &asn_DEF_NGAP_NGAP_PDU, pdu);
|
||||||
|
free(res.buffer);
|
||||||
|
NGAP_INFO("E_RAB Release successful message\n");
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
NGAP_WARN("Unknown procedure ID (%d) for successfull outcome message\n",
|
||||||
|
(int)pdu->choice.successfulOutcome.procedureCode);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (asn1_xer_print) {
|
||||||
|
xer_fprint(stdout, &asn_DEF_NGAP_NGAP_PDU, (void *)pdu);
|
||||||
|
}
|
||||||
|
|
||||||
|
memset(&res, 0, sizeof(res));
|
||||||
|
res = asn_encode_to_new_buffer(NULL, ATS_ALIGNED_CANONICAL_PER, &asn_DEF_NGAP_NGAP_PDU, pdu);
|
||||||
|
*buffer = res.buffer;
|
||||||
|
*len = res.result.encoded;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline
|
||||||
|
int ngap_gNB_encode_unsuccessfull_outcome(NGAP_NGAP_PDU_t *pdu,
|
||||||
|
uint8_t **buffer, uint32_t *len) {
|
||||||
|
asn_encode_to_new_buffer_result_t res = { NULL, {0, NULL, NULL} };
|
||||||
|
DevAssert(pdu != NULL);
|
||||||
|
|
||||||
|
switch(pdu->choice.unsuccessfulOutcome.procedureCode) {
|
||||||
|
case NGAP_ProcedureCode_id_InitialContextSetup:
|
||||||
|
res = asn_encode_to_new_buffer(NULL, ATS_CANONICAL_XER, &asn_DEF_NGAP_NGAP_PDU, pdu);
|
||||||
|
free(res.buffer);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
NGAP_DEBUG("Unknown procedure ID (%d) for unsuccessfull outcome message\n",
|
||||||
|
(int)pdu->choice.unsuccessfulOutcome.procedureCode);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (asn1_xer_print) {
|
||||||
|
xer_fprint(stdout, &asn_DEF_NGAP_NGAP_PDU, (void *)pdu);
|
||||||
|
}
|
||||||
|
|
||||||
|
memset(&res, 0, sizeof(res));
|
||||||
|
res = asn_encode_to_new_buffer(NULL, ATS_ALIGNED_CANONICAL_PER, &asn_DEF_NGAP_NGAP_PDU, pdu);
|
||||||
|
*buffer = res.buffer;
|
||||||
|
*len = res.result.encoded;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
/*
|
||||||
|
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
|
||||||
|
* contributor license agreements. See the NOTICE file distributed with
|
||||||
|
* this work for additional information regarding copyright ownership.
|
||||||
|
* The OpenAirInterface Software Alliance licenses this file to You under
|
||||||
|
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
|
||||||
|
* except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.openairinterface.org/?page_id=698
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*-------------------------------------------------------------------------------
|
||||||
|
* For more information about the OpenAirInterface (OAI) Software Alliance:
|
||||||
|
* contact@openairinterface.org
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef NGAP_GNB_ENCODER_H_
|
||||||
|
#define NGAP_GNB_ENCODER_H_
|
||||||
|
|
||||||
|
int ngap_gNB_encode_pdu(NGAP_NGAP_PDU_t *pdu, uint8_t **buffer, uint32_t *len)
|
||||||
|
__attribute__ ((warn_unused_result));
|
||||||
|
|
||||||
|
#endif /* NGAP_GNB_ENCODER_H_ */
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,30 @@
|
|||||||
|
/*
|
||||||
|
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
|
||||||
|
* contributor license agreements. See the NOTICE file distributed with
|
||||||
|
* this work for additional information regarding copyright ownership.
|
||||||
|
* The OpenAirInterface Software Alliance licenses this file to You under
|
||||||
|
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
|
||||||
|
* except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.openairinterface.org/?page_id=698
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*-------------------------------------------------------------------------------
|
||||||
|
* For more information about the OpenAirInterface (OAI) Software Alliance:
|
||||||
|
* contact@openairinterface.org
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef NGAP_GNB_HANDLERS_H_
|
||||||
|
#define NGAP_GNB_HANDLERS_H_
|
||||||
|
|
||||||
|
void ngap_handle_s1_setup_message(ngap_gNB_mme_data_t *mme_desc_p, int sctp_shutdown);
|
||||||
|
|
||||||
|
int ngap_gNB_handle_message(uint32_t assoc_id, int32_t stream,
|
||||||
|
const uint8_t * const data, const uint32_t data_length);
|
||||||
|
|
||||||
|
#endif /* NGAP_GNB_HANDLERS_H_ */
|
||||||
@@ -0,0 +1,77 @@
|
|||||||
|
/*
|
||||||
|
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
|
||||||
|
* contributor license agreements. See the NOTICE file distributed with
|
||||||
|
* this work for additional information regarding copyright ownership.
|
||||||
|
* The OpenAirInterface Software Alliance licenses this file to You under
|
||||||
|
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
|
||||||
|
* except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.openairinterface.org/?page_id=698
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*-------------------------------------------------------------------------------
|
||||||
|
* For more information about the OpenAirInterface (OAI) Software Alliance:
|
||||||
|
* contact@openairinterface.org
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "intertask_interface.h"
|
||||||
|
|
||||||
|
#include "ngap_gNB_itti_messaging.h"
|
||||||
|
|
||||||
|
void ngap_gNB_itti_send_sctp_data_req(instance_t instance, int32_t assoc_id, uint8_t *buffer,
|
||||||
|
uint32_t buffer_length, uint16_t stream)
|
||||||
|
{
|
||||||
|
MessageDef *message_p;
|
||||||
|
sctp_data_req_t *sctp_data_req;
|
||||||
|
|
||||||
|
message_p = itti_alloc_new_message(TASK_NGAP, SCTP_DATA_REQ);
|
||||||
|
|
||||||
|
sctp_data_req = &message_p->ittiMsg.sctp_data_req;
|
||||||
|
|
||||||
|
sctp_data_req->assoc_id = assoc_id;
|
||||||
|
sctp_data_req->buffer = buffer;
|
||||||
|
sctp_data_req->buffer_length = buffer_length;
|
||||||
|
sctp_data_req->stream = stream;
|
||||||
|
|
||||||
|
itti_send_msg_to_task(TASK_SCTP, instance, message_p);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ngap_gNB_itti_send_nas_downlink_ind(instance_t instance,
|
||||||
|
uint16_t ue_initial_id,
|
||||||
|
uint32_t gNB_ue_ngap_id,
|
||||||
|
uint8_t *nas_pdu,
|
||||||
|
uint32_t nas_pdu_length)
|
||||||
|
{
|
||||||
|
MessageDef *message_p;
|
||||||
|
ngap_downlink_nas_t *ngap_downlink_nas;
|
||||||
|
|
||||||
|
message_p = itti_alloc_new_message(TASK_NGAP, NGAP_DOWNLINK_NAS);
|
||||||
|
|
||||||
|
ngap_downlink_nas = &message_p->ittiMsg.ngap_downlink_nas;
|
||||||
|
|
||||||
|
ngap_downlink_nas->ue_initial_id = ue_initial_id;
|
||||||
|
ngap_downlink_nas->gNB_ue_ngap_id = gNB_ue_ngap_id;
|
||||||
|
ngap_downlink_nas->nas_pdu.buffer = malloc(sizeof(uint8_t) * nas_pdu_length);
|
||||||
|
memcpy(ngap_downlink_nas->nas_pdu.buffer, nas_pdu, nas_pdu_length);
|
||||||
|
ngap_downlink_nas->nas_pdu.length = nas_pdu_length;
|
||||||
|
|
||||||
|
itti_send_msg_to_task(TASK_RRC_GNB, instance, message_p);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ngap_gNB_itti_send_sctp_close_association(instance_t instance, int32_t assoc_id)
|
||||||
|
{
|
||||||
|
MessageDef *message_p = NULL;
|
||||||
|
sctp_close_association_t *sctp_close_association_p = NULL;
|
||||||
|
|
||||||
|
message_p = itti_alloc_new_message(TASK_NGAP, SCTP_CLOSE_ASSOCIATION);
|
||||||
|
sctp_close_association_p = &message_p->ittiMsg.sctp_close_association;
|
||||||
|
sctp_close_association_p->assoc_id = assoc_id;
|
||||||
|
|
||||||
|
itti_send_msg_to_task(TASK_SCTP, instance, message_p);
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,38 @@
|
|||||||
|
/*
|
||||||
|
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
|
||||||
|
* contributor license agreements. See the NOTICE file distributed with
|
||||||
|
* this work for additional information regarding copyright ownership.
|
||||||
|
* The OpenAirInterface Software Alliance licenses this file to You under
|
||||||
|
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
|
||||||
|
* except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.openairinterface.org/?page_id=698
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*-------------------------------------------------------------------------------
|
||||||
|
* For more information about the OpenAirInterface (OAI) Software Alliance:
|
||||||
|
* contact@openairinterface.org
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef NGAP_GNB_ITTI_MESSAGING_H_
|
||||||
|
#define NGAP_GNB_ITTI_MESSAGING_H_
|
||||||
|
|
||||||
|
void ngap_gNB_itti_send_sctp_data_req(instance_t instance, int32_t assoc_id, uint8_t *buffer,
|
||||||
|
uint32_t buffer_length, uint16_t stream);
|
||||||
|
|
||||||
|
void ngap_gNB_itti_send_nas_downlink_ind(instance_t instance,
|
||||||
|
uint16_t ue_initial_id,
|
||||||
|
uint32_t gNB_ue_ngap_id,
|
||||||
|
uint8_t *nas_pdu,
|
||||||
|
uint32_t nas_pdu_length);
|
||||||
|
|
||||||
|
void ngap_gNB_itti_send_sctp_close_association(instance_t instance,
|
||||||
|
int32_t assoc_id);
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* NGAP_GNB_ITTI_MESSAGING_H_ */
|
||||||
@@ -0,0 +1,188 @@
|
|||||||
|
/*
|
||||||
|
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
|
||||||
|
* contributor license agreements. See the NOTICE file distributed with
|
||||||
|
* this work for additional information regarding copyright ownership.
|
||||||
|
* The OpenAirInterface Software Alliance licenses this file to You under
|
||||||
|
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
|
||||||
|
* except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.openairinterface.org/?page_id=698
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*-------------------------------------------------------------------------------
|
||||||
|
* For more information about the OpenAirInterface (OAI) Software Alliance:
|
||||||
|
* contact@openairinterface.org
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*! \file ngap_gNB_management_procedures.c
|
||||||
|
* \brief NGAP gNB task
|
||||||
|
* \author S. Roux and Navid Nikaein
|
||||||
|
* \date 2010 - 2016
|
||||||
|
* \email: navid.nikaein@eurecom.fr
|
||||||
|
* \version 1.0
|
||||||
|
* @ingroup _ngap
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#include "intertask_interface.h"
|
||||||
|
|
||||||
|
#include "assertions.h"
|
||||||
|
#include "conversions.h"
|
||||||
|
|
||||||
|
#include "ngap_common.h"
|
||||||
|
#include "ngap_gNB_defs.h"
|
||||||
|
#include "ngap_gNB.h"
|
||||||
|
|
||||||
|
ngap_gNB_internal_data_t ngap_gNB_internal_data;
|
||||||
|
|
||||||
|
RB_GENERATE(ngap_mme_map, ngap_gNB_mme_data_s, entry, ngap_gNB_compare_assoc_id);
|
||||||
|
|
||||||
|
int ngap_gNB_compare_assoc_id(
|
||||||
|
struct ngap_gNB_mme_data_s *p1, struct ngap_gNB_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 ngap_gNB_fetch_add_global_cnx_id(void)
|
||||||
|
{
|
||||||
|
return ++ngap_gNB_internal_data.global_cnx_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ngap_gNB_prepare_internal_data(void)
|
||||||
|
{
|
||||||
|
memset(&ngap_gNB_internal_data, 0, sizeof(ngap_gNB_internal_data));
|
||||||
|
STAILQ_INIT(&ngap_gNB_internal_data.ngap_gNB_instances_head);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ngap_gNB_insert_new_instance(ngap_gNB_instance_t *new_instance_p)
|
||||||
|
{
|
||||||
|
DevAssert(new_instance_p != NULL);
|
||||||
|
|
||||||
|
STAILQ_INSERT_TAIL(&ngap_gNB_internal_data.ngap_gNB_instances_head,
|
||||||
|
new_instance_p, ngap_gNB_entries);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct ngap_gNB_mme_data_s *ngap_gNB_get_MME(
|
||||||
|
ngap_gNB_instance_t *instance_p,
|
||||||
|
int32_t assoc_id, uint16_t cnx_id)
|
||||||
|
{
|
||||||
|
struct ngap_gNB_mme_data_s temp;
|
||||||
|
struct ngap_gNB_mme_data_s *found;
|
||||||
|
|
||||||
|
memset(&temp, 0, sizeof(struct ngap_gNB_mme_data_s));
|
||||||
|
|
||||||
|
temp.assoc_id = assoc_id;
|
||||||
|
temp.cnx_id = cnx_id;
|
||||||
|
|
||||||
|
if (instance_p == NULL) {
|
||||||
|
STAILQ_FOREACH(instance_p, &ngap_gNB_internal_data.ngap_gNB_instances_head,
|
||||||
|
ngap_gNB_entries) {
|
||||||
|
found = RB_FIND(ngap_mme_map, &instance_p->ngap_mme_head, &temp);
|
||||||
|
|
||||||
|
if (found != NULL) {
|
||||||
|
return found;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return RB_FIND(ngap_mme_map, &instance_p->ngap_mme_head, &temp);
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct ngap_gNB_mme_data_s *ngap_gNB_get_MME_from_instance(
|
||||||
|
ngap_gNB_instance_t *instance_p)
|
||||||
|
{
|
||||||
|
|
||||||
|
struct ngap_gNB_mme_data_s *mme = NULL;
|
||||||
|
struct ngap_gNB_mme_data_s *mme_next = NULL;
|
||||||
|
|
||||||
|
for (mme = RB_MIN(ngap_mme_map, &instance_p->ngap_mme_head); mme!=NULL ; mme = mme_next) {
|
||||||
|
mme_next = RB_NEXT(ngap_mme_map, &instance_p->ngap_mme_head, mme);
|
||||||
|
if (mme->ngap_gNB_instance == instance_p) {
|
||||||
|
return mme;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
ngap_gNB_instance_t *ngap_gNB_get_instance(instance_t instance)
|
||||||
|
{
|
||||||
|
ngap_gNB_instance_t *temp = NULL;
|
||||||
|
|
||||||
|
STAILQ_FOREACH(temp, &ngap_gNB_internal_data.ngap_gNB_instances_head,
|
||||||
|
ngap_gNB_entries) {
|
||||||
|
if (temp->instance == instance) {
|
||||||
|
/* Matching occurence */
|
||||||
|
return temp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ngap_gNB_remove_mme_desc(ngap_gNB_instance_t * instance)
|
||||||
|
{
|
||||||
|
|
||||||
|
struct ngap_gNB_mme_data_s *mme = NULL;
|
||||||
|
struct ngap_gNB_mme_data_s *mmeNext = NULL;
|
||||||
|
struct plmn_identity_s* plmnInfo;
|
||||||
|
struct served_group_id_s* groupInfo;
|
||||||
|
struct served_gummei_s* gummeiInfo;
|
||||||
|
struct mme_code_s* mmeCode;
|
||||||
|
|
||||||
|
for (mme = RB_MIN(ngap_mme_map, &instance->ngap_mme_head); mme; mme = mmeNext) {
|
||||||
|
mmeNext = RB_NEXT(ngap_mme_map, &instance->ngap_mme_head, mme);
|
||||||
|
RB_REMOVE(ngap_mme_map, &instance->ngap_mme_head, mme);
|
||||||
|
while (!STAILQ_EMPTY(&mme->served_gummei)) {
|
||||||
|
gummeiInfo = STAILQ_FIRST(&mme->served_gummei);
|
||||||
|
STAILQ_REMOVE_HEAD(&mme->served_gummei, next);
|
||||||
|
|
||||||
|
while (!STAILQ_EMPTY(&gummeiInfo->served_plmns)) {
|
||||||
|
plmnInfo = STAILQ_FIRST(&gummeiInfo->served_plmns);
|
||||||
|
STAILQ_REMOVE_HEAD(&gummeiInfo->served_plmns, next);
|
||||||
|
free(plmnInfo);
|
||||||
|
}
|
||||||
|
while (!STAILQ_EMPTY(&gummeiInfo->served_group_ids)) {
|
||||||
|
groupInfo = STAILQ_FIRST(&gummeiInfo->served_group_ids);
|
||||||
|
STAILQ_REMOVE_HEAD(&gummeiInfo->served_group_ids, next);
|
||||||
|
free(groupInfo);
|
||||||
|
}
|
||||||
|
while (!STAILQ_EMPTY(&gummeiInfo->mme_codes)) {
|
||||||
|
mmeCode = STAILQ_FIRST(&gummeiInfo->mme_codes);
|
||||||
|
STAILQ_REMOVE_HEAD(&gummeiInfo->mme_codes, next);
|
||||||
|
free(mmeCode);
|
||||||
|
}
|
||||||
|
free(gummeiInfo);
|
||||||
|
}
|
||||||
|
free(mme);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,41 @@
|
|||||||
|
/*
|
||||||
|
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
|
||||||
|
* contributor license agreements. See the NOTICE file distributed with
|
||||||
|
* this work for additional information regarding copyright ownership.
|
||||||
|
* The OpenAirInterface Software Alliance licenses this file to You under
|
||||||
|
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
|
||||||
|
* except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.openairinterface.org/?page_id=698
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*-------------------------------------------------------------------------------
|
||||||
|
* For more information about the OpenAirInterface (OAI) Software Alliance:
|
||||||
|
* contact@openairinterface.org
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef NGAP_GNB_MANAGEMENT_PROCEDURES_H_
|
||||||
|
#define NGAP_GNB_MANAGEMENT_PROCEDURES_H_
|
||||||
|
|
||||||
|
struct ngap_gNB_mme_data_s *ngap_gNB_get_MME(
|
||||||
|
ngap_gNB_instance_t *instance_p,
|
||||||
|
int32_t assoc_id, uint16_t cnx_id);
|
||||||
|
|
||||||
|
struct ngap_gNB_mme_data_s *ngap_gNB_get_MME_from_instance(ngap_gNB_instance_t *instance_p);
|
||||||
|
|
||||||
|
void ngap_gNB_remove_mme_desc(ngap_gNB_instance_t * instance);
|
||||||
|
|
||||||
|
void ngap_gNB_insert_new_instance(ngap_gNB_instance_t *new_instance_p);
|
||||||
|
|
||||||
|
ngap_gNB_instance_t *ngap_gNB_get_instance(uint8_t mod_id);
|
||||||
|
|
||||||
|
uint16_t ngap_gNB_fetch_add_global_cnx_id(void);
|
||||||
|
|
||||||
|
void ngap_gNB_prepare_internal_data(void);
|
||||||
|
|
||||||
|
#endif /* NGAP_GNB_MANAGEMENT_PROCEDURES_H_ */
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,59 @@
|
|||||||
|
/*
|
||||||
|
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
|
||||||
|
* contributor license agreements. See the NOTICE file distributed with
|
||||||
|
* this work for additional information regarding copyright ownership.
|
||||||
|
* The OpenAirInterface Software Alliance licenses this file to You under
|
||||||
|
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
|
||||||
|
* except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.openairinterface.org/?page_id=698
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*-------------------------------------------------------------------------------
|
||||||
|
* For more information about the OpenAirInterface (OAI) Software Alliance:
|
||||||
|
* contact@openairinterface.org
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef NGAP_GNB_NAS_PROCEDURES_H_
|
||||||
|
#define NGAP_GNB_NAS_PROCEDURES_H_
|
||||||
|
|
||||||
|
int ngap_gNB_handle_nas_downlink(
|
||||||
|
uint32_t assoc_id,
|
||||||
|
uint32_t stream,
|
||||||
|
NGAP_NGAP_PDU_t *pdu);
|
||||||
|
|
||||||
|
int ngap_gNB_nas_uplink(instance_t instance, ngap_uplink_nas_t *ngap_uplink_nas_p);
|
||||||
|
|
||||||
|
int ngap_gNB_nas_non_delivery_ind(instance_t instance,
|
||||||
|
ngap_nas_non_delivery_ind_t *ngap_nas_non_delivery_ind);
|
||||||
|
|
||||||
|
int ngap_gNB_handle_nas_first_req(
|
||||||
|
instance_t instance, ngap_nas_first_req_t *ngap_nas_first_req_p);
|
||||||
|
|
||||||
|
int ngap_gNB_initial_ctxt_resp(
|
||||||
|
instance_t instance, ngap_initial_context_setup_resp_t *initial_ctxt_resp_p);
|
||||||
|
|
||||||
|
int ngap_gNB_ue_capabilities(instance_t instance,
|
||||||
|
ngap_ue_cap_info_ind_t *ue_cap_info_ind_p);
|
||||||
|
|
||||||
|
int ngap_gNB_e_rab_setup_resp(instance_t instance,
|
||||||
|
ngap_e_rab_setup_resp_t *e_rab_setup_resp_p);
|
||||||
|
|
||||||
|
int ngap_gNB_e_rab_modify_resp(instance_t instance,
|
||||||
|
ngap_e_rab_modify_resp_t *e_rab_modify_resp_p);
|
||||||
|
|
||||||
|
int ngap_gNB_e_rab_release_resp(instance_t instance,
|
||||||
|
ngap_e_rab_release_resp_t *e_rab_release_resp_p);
|
||||||
|
|
||||||
|
int ngap_gNB_path_switch_req(instance_t instance,
|
||||||
|
ngap_path_switch_req_t *path_switch_req_p);
|
||||||
|
|
||||||
|
int ngap_gNB_generate_E_RAB_Modification_Indication(
|
||||||
|
instance_t instance, ngap_e_rab_modification_ind_t *e_rab_modification_ind);
|
||||||
|
|
||||||
|
#endif /* NGAP_GNB_NAS_PROCEDURES_H_ */
|
||||||
@@ -0,0 +1,399 @@
|
|||||||
|
/*
|
||||||
|
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
|
||||||
|
* contributor license agreements. See the NOTICE file distributed with
|
||||||
|
* this work for additional information regarding copyright ownership.
|
||||||
|
* The OpenAirInterface Software Alliance licenses this file to You under
|
||||||
|
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
|
||||||
|
* except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.openairinterface.org/?page_id=698
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*-------------------------------------------------------------------------------
|
||||||
|
* For more information about the OpenAirInterface (OAI) Software Alliance:
|
||||||
|
* contact@openairinterface.org
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*! \file ngap_gNB_nnsf.c
|
||||||
|
* \brief ngap NAS node selection functions
|
||||||
|
* \author Sebastien ROUX <sebastien.roux@eurecom.fr>
|
||||||
|
* \date 2012
|
||||||
|
* \version 0.1
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#include "intertask_interface.h"
|
||||||
|
|
||||||
|
#include "ngap_common.h"
|
||||||
|
|
||||||
|
#include "ngap_gNB_defs.h"
|
||||||
|
#include "ngap_gNB_nnsf.h"
|
||||||
|
|
||||||
|
struct ngap_gNB_mme_data_s *
|
||||||
|
ngap_gNB_nnsf_select_mme(ngap_gNB_instance_t *instance_p,
|
||||||
|
rrc_establishment_cause_t cause)
|
||||||
|
{
|
||||||
|
struct ngap_gNB_mme_data_s *mme_data_p = NULL;
|
||||||
|
struct ngap_gNB_mme_data_s *mme_highest_capacity_p = NULL;
|
||||||
|
uint8_t current_capacity = 0;
|
||||||
|
|
||||||
|
RB_FOREACH(mme_data_p, ngap_mme_map, &instance_p->ngap_mme_head) {
|
||||||
|
if (mme_data_p->state != NGAP_GNB_STATE_CONNECTED) {
|
||||||
|
/* The association between MME and gNB is not ready for the moment,
|
||||||
|
* go to the next known MME.
|
||||||
|
*/
|
||||||
|
if (mme_data_p->state == NGAP_GNB_OVERLOAD) {
|
||||||
|
/* MME is overloaded. We have to check the RRC establishment
|
||||||
|
* cause and take decision to the select this MME depending on
|
||||||
|
* the overload state.
|
||||||
|
*/
|
||||||
|
if ((cause == RRC_CAUSE_MO_DATA)
|
||||||
|
&& (mme_data_p->overload_state == NGAP_OVERLOAD_REJECT_MO_DATA)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((mme_data_p->overload_state == NGAP_OVERLOAD_REJECT_ALL_SIGNALLING)
|
||||||
|
&& ((cause == RRC_CAUSE_MO_SIGNALLING) || (cause == RRC_CAUSE_MO_DATA))) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((mme_data_p->overload_state == NGAP_OVERLOAD_ONLY_EMERGENCY_AND_MT)
|
||||||
|
&& ((cause == RRC_CAUSE_MO_SIGNALLING) || (cause == RRC_CAUSE_MO_DATA)
|
||||||
|
|| (cause == RRC_CAUSE_HIGH_PRIO_ACCESS))) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* At this point, the RRC establishment can be handled by the MME
|
||||||
|
* even if it is in overload state.
|
||||||
|
*/
|
||||||
|
} else {
|
||||||
|
/* The MME is not overloaded, association is simply not ready. */
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (current_capacity < mme_data_p->relative_mme_capacity) {
|
||||||
|
/* We find a better MME, keep a reference to it */
|
||||||
|
current_capacity = mme_data_p->relative_mme_capacity;
|
||||||
|
mme_highest_capacity_p = mme_data_p;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return mme_highest_capacity_p;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct ngap_gNB_mme_data_s *
|
||||||
|
ngap_gNB_nnsf_select_mme_by_plmn_id(ngap_gNB_instance_t *instance_p,
|
||||||
|
rrc_establishment_cause_t cause,
|
||||||
|
int selected_plmn_identity)
|
||||||
|
{
|
||||||
|
struct ngap_gNB_mme_data_s *mme_data_p = NULL;
|
||||||
|
struct ngap_gNB_mme_data_s *mme_highest_capacity_p = NULL;
|
||||||
|
uint8_t current_capacity = 0;
|
||||||
|
|
||||||
|
RB_FOREACH(mme_data_p, ngap_mme_map, &instance_p->ngap_mme_head) {
|
||||||
|
struct served_gummei_s *gummei_p = NULL;
|
||||||
|
struct plmn_identity_s *served_plmn_p = NULL;
|
||||||
|
if (mme_data_p->state != NGAP_GNB_STATE_CONNECTED) {
|
||||||
|
/* The association between MME and gNB is not ready for the moment,
|
||||||
|
* go to the next known MME.
|
||||||
|
*/
|
||||||
|
if (mme_data_p->state == NGAP_GNB_OVERLOAD) {
|
||||||
|
/* MME is overloaded. We have to check the RRC establishment
|
||||||
|
* cause and take decision to the select this MME depending on
|
||||||
|
* the overload state.
|
||||||
|
*/
|
||||||
|
if ((cause == RRC_CAUSE_MO_DATA)
|
||||||
|
&& (mme_data_p->overload_state == NGAP_OVERLOAD_REJECT_MO_DATA)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((mme_data_p->overload_state == NGAP_OVERLOAD_REJECT_ALL_SIGNALLING)
|
||||||
|
&& ((cause == RRC_CAUSE_MO_SIGNALLING) || (cause == RRC_CAUSE_MO_DATA))) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((mme_data_p->overload_state == NGAP_OVERLOAD_ONLY_EMERGENCY_AND_MT)
|
||||||
|
&& ((cause == RRC_CAUSE_MO_SIGNALLING) || (cause == RRC_CAUSE_MO_DATA)
|
||||||
|
|| (cause == RRC_CAUSE_HIGH_PRIO_ACCESS))) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* At this point, the RRC establishment can be handled by the MME
|
||||||
|
* even if it is in overload state.
|
||||||
|
*/
|
||||||
|
} else {
|
||||||
|
/* The MME is not overloaded, association is simply not ready. */
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Looking for served GUMMEI PLMN Identity selected matching the one provided by the UE */
|
||||||
|
STAILQ_FOREACH(gummei_p, &mme_data_p->served_gummei, next) {
|
||||||
|
STAILQ_FOREACH(served_plmn_p, &gummei_p->served_plmns, next) {
|
||||||
|
if ((served_plmn_p->mcc == instance_p->mcc[selected_plmn_identity]) &&
|
||||||
|
(served_plmn_p->mnc == instance_p->mnc[selected_plmn_identity])) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* if found, we can stop the outer loop, too */
|
||||||
|
if (served_plmn_p) break;
|
||||||
|
}
|
||||||
|
/* if we didn't find such a served PLMN, go on with the next MME */
|
||||||
|
if (!served_plmn_p) continue;
|
||||||
|
|
||||||
|
if (current_capacity < mme_data_p->relative_mme_capacity) {
|
||||||
|
/* We find a better MME, keep a reference to it */
|
||||||
|
current_capacity = mme_data_p->relative_mme_capacity;
|
||||||
|
mme_highest_capacity_p = mme_data_p;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return mme_highest_capacity_p;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct ngap_gNB_mme_data_s *
|
||||||
|
ngap_gNB_nnsf_select_mme_by_mme_code(ngap_gNB_instance_t *instance_p,
|
||||||
|
rrc_establishment_cause_t cause,
|
||||||
|
int selected_plmn_identity,
|
||||||
|
uint8_t mme_code)
|
||||||
|
{
|
||||||
|
struct ngap_gNB_mme_data_s *mme_data_p = NULL;
|
||||||
|
|
||||||
|
RB_FOREACH(mme_data_p, ngap_mme_map, &instance_p->ngap_mme_head) {
|
||||||
|
struct served_gummei_s *gummei_p = NULL;
|
||||||
|
|
||||||
|
if (mme_data_p->state != NGAP_GNB_STATE_CONNECTED) {
|
||||||
|
/* The association between MME and gNB is not ready for the moment,
|
||||||
|
* go to the next known MME.
|
||||||
|
*/
|
||||||
|
if (mme_data_p->state == NGAP_GNB_OVERLOAD) {
|
||||||
|
/* MME is overloaded. We have to check the RRC establishment
|
||||||
|
* cause and take decision to the select this MME depending on
|
||||||
|
* the overload state.
|
||||||
|
*/
|
||||||
|
if ((cause == RRC_CAUSE_MO_DATA)
|
||||||
|
&& (mme_data_p->overload_state == NGAP_OVERLOAD_REJECT_MO_DATA)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((mme_data_p->overload_state == NGAP_OVERLOAD_REJECT_ALL_SIGNALLING)
|
||||||
|
&& ((cause == RRC_CAUSE_MO_SIGNALLING) || (cause == RRC_CAUSE_MO_DATA))) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((mme_data_p->overload_state == NGAP_OVERLOAD_ONLY_EMERGENCY_AND_MT)
|
||||||
|
&& ((cause == RRC_CAUSE_MO_SIGNALLING) || (cause == RRC_CAUSE_MO_DATA)
|
||||||
|
|| (cause == RRC_CAUSE_HIGH_PRIO_ACCESS))) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* At this point, the RRC establishment can be handled by the MME
|
||||||
|
* even if it is in overload state.
|
||||||
|
*/
|
||||||
|
} else {
|
||||||
|
/* The MME is not overloaded, association is simply not ready. */
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Looking for MME code matching the one provided by NAS */
|
||||||
|
STAILQ_FOREACH(gummei_p, &mme_data_p->served_gummei, next) {
|
||||||
|
struct mme_code_s *mme_code_p = NULL;
|
||||||
|
struct plmn_identity_s *served_plmn_p = NULL;
|
||||||
|
|
||||||
|
STAILQ_FOREACH(served_plmn_p, &gummei_p->served_plmns, next) {
|
||||||
|
if ((served_plmn_p->mcc == instance_p->mcc[selected_plmn_identity]) &&
|
||||||
|
(served_plmn_p->mnc == instance_p->mnc[selected_plmn_identity])) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
STAILQ_FOREACH(mme_code_p, &gummei_p->mme_codes, next) {
|
||||||
|
if (mme_code_p->mme_code == mme_code) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* The MME matches the parameters provided by the NAS layer ->
|
||||||
|
* the MME is knwown and the association is ready.
|
||||||
|
* Return the reference to the MME to use it for this UE.
|
||||||
|
*/
|
||||||
|
if (mme_code_p && served_plmn_p) {
|
||||||
|
return mme_data_p;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* At this point no MME matches the selected PLMN and MME code. In this case,
|
||||||
|
* return NULL. That way the RRC layer should know about it and reject RRC
|
||||||
|
* connectivity. */
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct ngap_gNB_mme_data_s *
|
||||||
|
ngap_gNB_nnsf_select_mme_by_gummei(ngap_gNB_instance_t *instance_p,
|
||||||
|
rrc_establishment_cause_t cause,
|
||||||
|
ngap_gummei_t gummei)
|
||||||
|
{
|
||||||
|
struct ngap_gNB_mme_data_s *mme_data_p = NULL;
|
||||||
|
|
||||||
|
RB_FOREACH(mme_data_p, ngap_mme_map, &instance_p->ngap_mme_head) {
|
||||||
|
struct served_gummei_s *gummei_p = NULL;
|
||||||
|
|
||||||
|
if (mme_data_p->state != NGAP_GNB_STATE_CONNECTED) {
|
||||||
|
/* The association between MME and gNB is not ready for the moment,
|
||||||
|
* go to the next known MME.
|
||||||
|
*/
|
||||||
|
if (mme_data_p->state == NGAP_GNB_OVERLOAD) {
|
||||||
|
/* MME is overloaded. We have to check the RRC establishment
|
||||||
|
* cause and take decision to the select this MME depending on
|
||||||
|
* the overload state.
|
||||||
|
*/
|
||||||
|
if ((cause == RRC_CAUSE_MO_DATA)
|
||||||
|
&& (mme_data_p->overload_state == NGAP_OVERLOAD_REJECT_MO_DATA)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((mme_data_p->overload_state == NGAP_OVERLOAD_REJECT_ALL_SIGNALLING)
|
||||||
|
&& ((cause == RRC_CAUSE_MO_SIGNALLING) || (cause == RRC_CAUSE_MO_DATA))) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((mme_data_p->overload_state == NGAP_OVERLOAD_ONLY_EMERGENCY_AND_MT)
|
||||||
|
&& ((cause == RRC_CAUSE_MO_SIGNALLING) || (cause == RRC_CAUSE_MO_DATA)
|
||||||
|
|| (cause == RRC_CAUSE_HIGH_PRIO_ACCESS))) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* At this point, the RRC establishment can be handled by the MME
|
||||||
|
* even if it is in overload state.
|
||||||
|
*/
|
||||||
|
} else {
|
||||||
|
/* The MME is not overloaded, association is simply not ready. */
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Looking for MME gummei matching the one provided by NAS */
|
||||||
|
STAILQ_FOREACH(gummei_p, &mme_data_p->served_gummei, next) {
|
||||||
|
struct served_group_id_s *group_id_p = NULL;
|
||||||
|
struct mme_code_s *mme_code_p = NULL;
|
||||||
|
struct plmn_identity_s *served_plmn_p = NULL;
|
||||||
|
|
||||||
|
STAILQ_FOREACH(served_plmn_p, &gummei_p->served_plmns, next) {
|
||||||
|
if ((served_plmn_p->mcc == gummei.mcc) &&
|
||||||
|
(served_plmn_p->mnc == gummei.mnc)) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
STAILQ_FOREACH(mme_code_p, &gummei_p->mme_codes, next) {
|
||||||
|
if (mme_code_p->mme_code == gummei.mme_code) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
STAILQ_FOREACH(group_id_p, &gummei_p->served_group_ids, next) {
|
||||||
|
if (group_id_p->mme_group_id == gummei.mme_group_id) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* The MME matches the parameters provided by the NAS layer ->
|
||||||
|
* the MME is knwown and the association is ready.
|
||||||
|
* Return the reference to the MME to use it for this UE.
|
||||||
|
*/
|
||||||
|
if ((group_id_p != NULL) &&
|
||||||
|
(mme_code_p != NULL) &&
|
||||||
|
(served_plmn_p != NULL)) {
|
||||||
|
return mme_data_p;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* At this point no MME matches the provided GUMMEI. In this case, return
|
||||||
|
* NULL. That way the RRC layer should know about it and reject RRC
|
||||||
|
* connectivity. */
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
struct ngap_gNB_mme_data_s *
|
||||||
|
ngap_gNB_nnsf_select_mme_by_gummei_no_cause(ngap_gNB_instance_t *instance_p,
|
||||||
|
ngap_gummei_t gummei)
|
||||||
|
{
|
||||||
|
struct ngap_gNB_mme_data_s *mme_data_p = NULL;
|
||||||
|
struct ngap_gNB_mme_data_s *mme_highest_capacity_p = NULL;
|
||||||
|
uint8_t current_capacity = 0;
|
||||||
|
|
||||||
|
RB_FOREACH(mme_data_p, ngap_mme_map, &instance_p->ngap_mme_head) {
|
||||||
|
struct served_gummei_s *gummei_p = NULL;
|
||||||
|
|
||||||
|
if (mme_data_p->state != NGAP_GNB_STATE_CONNECTED) {
|
||||||
|
/* The association between MME and gNB is not ready for the moment,
|
||||||
|
* go to the next known MME.
|
||||||
|
*/
|
||||||
|
if (mme_data_p->state == NGAP_GNB_OVERLOAD) {
|
||||||
|
/* MME is overloaded. We have to check the RRC establishment
|
||||||
|
* cause and take decision to the select this MME depending on
|
||||||
|
* the overload state.
|
||||||
|
*/
|
||||||
|
} else {
|
||||||
|
/* The MME is not overloaded, association is simply not ready. */
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (current_capacity < mme_data_p->relative_mme_capacity) {
|
||||||
|
/* We find a better MME, keep a reference to it */
|
||||||
|
current_capacity = mme_data_p->relative_mme_capacity;
|
||||||
|
mme_highest_capacity_p = mme_data_p;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Looking for MME gummei matching the one provided by NAS */
|
||||||
|
STAILQ_FOREACH(gummei_p, &mme_data_p->served_gummei, next) {
|
||||||
|
struct served_group_id_s *group_id_p = NULL;
|
||||||
|
struct mme_code_s *mme_code_p = NULL;
|
||||||
|
struct plmn_identity_s *served_plmn_p = NULL;
|
||||||
|
|
||||||
|
STAILQ_FOREACH(served_plmn_p, &gummei_p->served_plmns, next) {
|
||||||
|
if ((served_plmn_p->mcc == gummei.mcc) &&
|
||||||
|
(served_plmn_p->mnc == gummei.mnc)) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
STAILQ_FOREACH(mme_code_p, &gummei_p->mme_codes, next) {
|
||||||
|
if (mme_code_p->mme_code == gummei.mme_code) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
STAILQ_FOREACH(group_id_p, &gummei_p->served_group_ids, next) {
|
||||||
|
if (group_id_p->mme_group_id == gummei.mme_group_id) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* The MME matches the parameters provided by the NAS layer ->
|
||||||
|
* the MME is knwown and the association is ready.
|
||||||
|
* Return the reference to the MME to use it for this UE.
|
||||||
|
*/
|
||||||
|
if ((group_id_p != NULL) &&
|
||||||
|
(mme_code_p != NULL) &&
|
||||||
|
(served_plmn_p != NULL)) {
|
||||||
|
return mme_data_p;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* At this point no MME matches the provided GUMMEI. Select the one with the
|
||||||
|
* highest relative capacity.
|
||||||
|
* In case the list of known MME is empty, simply return NULL, that way the RRC
|
||||||
|
* layer should know about it and reject RRC connectivity.
|
||||||
|
*/
|
||||||
|
return mme_highest_capacity_p;
|
||||||
|
}
|
||||||
@@ -0,0 +1,49 @@
|
|||||||
|
/*
|
||||||
|
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
|
||||||
|
* contributor license agreements. See the NOTICE file distributed with
|
||||||
|
* this work for additional information regarding copyright ownership.
|
||||||
|
* The OpenAirInterface Software Alliance licenses this file to You under
|
||||||
|
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
|
||||||
|
* except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.openairinterface.org/?page_id=698
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*-------------------------------------------------------------------------------
|
||||||
|
* For more information about the OpenAirInterface (OAI) Software Alliance:
|
||||||
|
* contact@openairinterface.org
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef NGAP_GNB_NNSF_H_
|
||||||
|
#define NGAP_GNB_NNSF_H_
|
||||||
|
|
||||||
|
struct ngap_gNB_mme_data_s *
|
||||||
|
ngap_gNB_nnsf_select_mme(ngap_gNB_instance_t *instance_p,
|
||||||
|
rrc_establishment_cause_t cause);
|
||||||
|
|
||||||
|
struct ngap_gNB_mme_data_s *
|
||||||
|
ngap_gNB_nnsf_select_mme_by_plmn_id(ngap_gNB_instance_t *instance_p,
|
||||||
|
rrc_establishment_cause_t cause,
|
||||||
|
int selected_plmn_identity);
|
||||||
|
|
||||||
|
struct ngap_gNB_mme_data_s*
|
||||||
|
ngap_gNB_nnsf_select_mme_by_mme_code(ngap_gNB_instance_t *instance_p,
|
||||||
|
rrc_establishment_cause_t cause,
|
||||||
|
int selected_plmn_identity,
|
||||||
|
uint8_t mme_code);
|
||||||
|
|
||||||
|
struct ngap_gNB_mme_data_s*
|
||||||
|
ngap_gNB_nnsf_select_mme_by_gummei(ngap_gNB_instance_t *instance_p,
|
||||||
|
rrc_establishment_cause_t cause,
|
||||||
|
ngap_gummei_t gummei);
|
||||||
|
|
||||||
|
struct ngap_gNB_mme_data_s*
|
||||||
|
ngap_gNB_nnsf_select_mme_by_gummei_no_cause(ngap_gNB_instance_t *instance_p,
|
||||||
|
ngap_gummei_t gummei);
|
||||||
|
|
||||||
|
#endif /* NGAP_GNB_NNSF_H_ */
|
||||||
@@ -0,0 +1,106 @@
|
|||||||
|
/*
|
||||||
|
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
|
||||||
|
* contributor license agreements. See the NOTICE file distributed with
|
||||||
|
* this work for additional information regarding copyright ownership.
|
||||||
|
* The OpenAirInterface Software Alliance licenses this file to You under
|
||||||
|
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
|
||||||
|
* except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.openairinterface.org/?page_id=698
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*-------------------------------------------------------------------------------
|
||||||
|
* For more information about the OpenAirInterface (OAI) Software Alliance:
|
||||||
|
* contact@openairinterface.org
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*! \file ngap_gNB_overload.c
|
||||||
|
* \brief ngap procedures for overload messages within gNB
|
||||||
|
* \author Sebastien ROUX <sebastien.roux@eurecom.fr>
|
||||||
|
* \date 2012
|
||||||
|
* \version 0.1
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#include "intertask_interface.h"
|
||||||
|
|
||||||
|
#include "ngap_common.h"
|
||||||
|
#include "ngap_gNB_defs.h"
|
||||||
|
|
||||||
|
#include "ngap_gNB.h"
|
||||||
|
#include "ngap_gNB_ue_context.h"
|
||||||
|
#include "ngap_gNB_encoder.h"
|
||||||
|
#include "ngap_gNB_overload.h"
|
||||||
|
#include "ngap_gNB_management_procedures.h"
|
||||||
|
|
||||||
|
#include "assertions.h"
|
||||||
|
|
||||||
|
int ngap_gNB_handle_overload_start(uint32_t assoc_id,
|
||||||
|
uint32_t stream,
|
||||||
|
NGAP_NGAP_PDU_t *pdu)
|
||||||
|
{
|
||||||
|
ngap_gNB_mme_data_t *mme_desc_p;
|
||||||
|
NGAP_OverloadStart_t *container;
|
||||||
|
NGAP_OverloadStartIEs_t *ie;
|
||||||
|
|
||||||
|
DevAssert(pdu != NULL);
|
||||||
|
|
||||||
|
container = &pdu->choice.initiatingMessage.value.choice.OverloadStart;
|
||||||
|
|
||||||
|
NGAP_FIND_PROTOCOLIE_BY_ID(NGAP_OverloadStartIEs_t, ie, container,
|
||||||
|
NGAP_ProtocolIE_ID_id_OverloadResponse, true);
|
||||||
|
if (ie != NULL) {
|
||||||
|
DevCheck(ie->value.choice.OverloadResponse.present ==
|
||||||
|
NGAP_OverloadResponse_PR_overloadAction,
|
||||||
|
NGAP_OverloadResponse_PR_overloadAction, 0, 0);
|
||||||
|
}
|
||||||
|
/* Non UE-associated signalling -> stream 0 */
|
||||||
|
DevCheck(stream == 0, stream, 0, 0);
|
||||||
|
|
||||||
|
if ((mme_desc_p = ngap_gNB_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 = NGAP_GNB_OVERLOAD;
|
||||||
|
mme_desc_p->overload_state =
|
||||||
|
ie->value.choice.OverloadResponse.choice.overloadAction;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int ngap_gNB_handle_overload_stop(uint32_t assoc_id,
|
||||||
|
uint32_t stream,
|
||||||
|
NGAP_NGAP_PDU_t *pdu)
|
||||||
|
{
|
||||||
|
/* We received Overload stop message, meaning that the MME is no more
|
||||||
|
* overloaded. This is an empty message, with only message header and no
|
||||||
|
* Information Element.
|
||||||
|
*/
|
||||||
|
DevAssert(pdu != NULL);
|
||||||
|
|
||||||
|
ngap_gNB_mme_data_t *mme_desc_p;
|
||||||
|
|
||||||
|
/* Non UE-associated signalling -> stream 0 */
|
||||||
|
DevCheck(stream == 0, stream, 0, 0);
|
||||||
|
|
||||||
|
if ((mme_desc_p = ngap_gNB_get_MME(NULL, assoc_id, 0)) == NULL) {
|
||||||
|
/* No MME context associated */
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
mme_desc_p->state = NGAP_GNB_STATE_CONNECTED;
|
||||||
|
mme_desc_p->overload_state = NGAP_NO_OVERLOAD;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
@@ -0,0 +1,45 @@
|
|||||||
|
/*
|
||||||
|
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
|
||||||
|
* contributor license agreements. See the NOTICE file distributed with
|
||||||
|
* this work for additional information regarding copyright ownership.
|
||||||
|
* The OpenAirInterface Software Alliance licenses this file to You under
|
||||||
|
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
|
||||||
|
* except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.openairinterface.org/?page_id=698
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*-------------------------------------------------------------------------------
|
||||||
|
* For more information about the OpenAirInterface (OAI) Software Alliance:
|
||||||
|
* contact@openairinterface.org
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef NGAP_GNB_OVERLOAD_H_
|
||||||
|
#define NGAP_GNB_OVERLOAD_H_
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Handle an overload start message
|
||||||
|
**/
|
||||||
|
// int ngap_gNB_handle_overload_start(gNB_mme_desc_t *gNB_desc_p,
|
||||||
|
// sctp_queue_item_t *packet_p,
|
||||||
|
// struct ngap_message_s *message_p);
|
||||||
|
int ngap_gNB_handle_overload_start(uint32_t assoc_id,
|
||||||
|
uint32_t stream,
|
||||||
|
NGAP_NGAP_PDU_t *pdu);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Handle an overload stop message
|
||||||
|
**/
|
||||||
|
// int ngap_gNB_handle_overload_stop(gNB_mme_desc_t *gNB_desc_p,
|
||||||
|
// sctp_queue_item_t *packet_p,
|
||||||
|
// struct ngap_message_s *message_p);
|
||||||
|
int ngap_gNB_handle_overload_stop(uint32_t assoc_id,
|
||||||
|
uint32_t stream,
|
||||||
|
NGAP_NGAP_PDU_t *pdu);
|
||||||
|
|
||||||
|
#endif /* NGAP_GNB_OVERLOAD_H_ */
|
||||||
@@ -0,0 +1,150 @@
|
|||||||
|
/*
|
||||||
|
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
|
||||||
|
* contributor license agreements. See the NOTICE file distributed with
|
||||||
|
* this work for additional information regarding copyright ownership.
|
||||||
|
* The OpenAirInterface Software Alliance licenses this file to You under
|
||||||
|
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
|
||||||
|
* except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.openairinterface.org/?page_id=698
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*-------------------------------------------------------------------------------
|
||||||
|
* For more information about the OpenAirInterface (OAI) Software Alliance:
|
||||||
|
* contact@openairinterface.org
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#include "assertions.h"
|
||||||
|
|
||||||
|
#include "intertask_interface.h"
|
||||||
|
|
||||||
|
#include "ngap_gNB_default_values.h"
|
||||||
|
|
||||||
|
#include "ngap_common.h"
|
||||||
|
#include "ngap_gNB_defs.h"
|
||||||
|
|
||||||
|
#include "ngap_gNB.h"
|
||||||
|
#include "ngap_gNB_ue_context.h"
|
||||||
|
#include "ngap_gNB_encoder.h"
|
||||||
|
#include "ngap_gNB_trace.h"
|
||||||
|
#include "ngap_gNB_itti_messaging.h"
|
||||||
|
#include "ngap_gNB_management_procedures.h"
|
||||||
|
|
||||||
|
static
|
||||||
|
void ngap_gNB_generate_trace_failure(struct ngap_gNB_ue_context_s *ue_desc_p,
|
||||||
|
NGAP_E_UTRAN_Trace_ID_t *trace_id,
|
||||||
|
NGAP_Cause_t *cause_p)
|
||||||
|
{
|
||||||
|
NGAP_NGAP_PDU_t pdu;
|
||||||
|
NGAP_TraceFailureIndication_t *out;
|
||||||
|
NGAP_TraceFailureIndicationIEs_t *ie;
|
||||||
|
uint8_t *buffer = NULL;
|
||||||
|
uint32_t length;
|
||||||
|
|
||||||
|
DevAssert(ue_desc_p != NULL);
|
||||||
|
DevAssert(trace_id != NULL);
|
||||||
|
DevAssert(cause_p != NULL);
|
||||||
|
|
||||||
|
/* Prepare the NGAP message to encode */
|
||||||
|
memset(&pdu, 0, sizeof(pdu));
|
||||||
|
pdu.present = NGAP_NGAP_PDU_PR_initiatingMessage;
|
||||||
|
pdu.choice.initiatingMessage.procedureCode = NGAP_ProcedureCode_id_TraceFailureIndication;
|
||||||
|
pdu.choice.initiatingMessage.criticality = NGAP_Criticality_ignore;
|
||||||
|
pdu.choice.initiatingMessage.value.present = NGAP_InitiatingMessage__value_PR_TraceFailureIndication;
|
||||||
|
out = &pdu.choice.initiatingMessage.value.choice.TraceFailureIndication;
|
||||||
|
|
||||||
|
/* mandatory */
|
||||||
|
ie = (NGAP_TraceFailureIndicationIEs_t *)calloc(1, sizeof(NGAP_TraceFailureIndicationIEs_t));
|
||||||
|
ie->id = NGAP_ProtocolIE_ID_id_MME_UE_NGAP_ID;
|
||||||
|
ie->criticality = NGAP_Criticality_reject;
|
||||||
|
ie->value.present = NGAP_TraceFailureIndicationIEs__value_PR_MME_UE_NGAP_ID;
|
||||||
|
ie->value.choice.MME_UE_NGAP_ID = ue_desc_p->mme_ue_ngap_id;
|
||||||
|
ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
|
||||||
|
|
||||||
|
/* mandatory */
|
||||||
|
ie = (NGAP_TraceFailureIndicationIEs_t *)calloc(1, sizeof(NGAP_TraceFailureIndicationIEs_t));
|
||||||
|
ie->id = NGAP_ProtocolIE_ID_id_gNB_UE_NGAP_ID;
|
||||||
|
ie->criticality = NGAP_Criticality_reject;
|
||||||
|
ie->value.present = NGAP_TraceFailureIndicationIEs__value_PR_GNB_UE_NGAP_ID;
|
||||||
|
ie->value.choice.GNB_UE_NGAP_ID = ue_desc_p->gNB_ue_ngap_id;
|
||||||
|
ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
|
||||||
|
|
||||||
|
/* mandatory */
|
||||||
|
ie = (NGAP_TraceFailureIndicationIEs_t *)calloc(1, sizeof(NGAP_TraceFailureIndicationIEs_t));
|
||||||
|
ie->id = NGAP_ProtocolIE_ID_id_E_UTRAN_Trace_ID;
|
||||||
|
ie->criticality = NGAP_Criticality_ignore;
|
||||||
|
ie->value.present = NGAP_TraceFailureIndicationIEs__value_PR_E_UTRAN_Trace_ID;
|
||||||
|
memcpy(&ie->value.choice.E_UTRAN_Trace_ID, trace_id, sizeof(NGAP_E_UTRAN_Trace_ID_t));
|
||||||
|
ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
|
||||||
|
|
||||||
|
/* mandatory */
|
||||||
|
ie = (NGAP_TraceFailureIndicationIEs_t *)calloc(1, sizeof(NGAP_TraceFailureIndicationIEs_t));
|
||||||
|
ie->id = NGAP_ProtocolIE_ID_id_Cause;
|
||||||
|
ie->criticality = NGAP_Criticality_ignore;
|
||||||
|
ie->value.present = NGAP_TraceFailureIndicationIEs__value_PR_Cause;
|
||||||
|
memcpy(&ie->value.choice.Cause, cause_p, sizeof(NGAP_Cause_t));
|
||||||
|
ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
|
||||||
|
|
||||||
|
if (ngap_gNB_encode_pdu(&pdu, &buffer, &length) < 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ngap_gNB_itti_send_sctp_data_req(ue_desc_p->mme_ref->ngap_gNB_instance->instance,
|
||||||
|
ue_desc_p->mme_ref->assoc_id, buffer,
|
||||||
|
length, ue_desc_p->tx_stream);
|
||||||
|
}
|
||||||
|
|
||||||
|
int ngap_gNB_handle_trace_start(uint32_t assoc_id,
|
||||||
|
uint32_t stream,
|
||||||
|
NGAP_NGAP_PDU_t *pdu)
|
||||||
|
{
|
||||||
|
NGAP_TraceStart_t *container;
|
||||||
|
NGAP_TraceStartIEs_t *ie;
|
||||||
|
struct ngap_gNB_ue_context_s *ue_desc_p = NULL;
|
||||||
|
struct ngap_gNB_mme_data_s *mme_ref_p;
|
||||||
|
|
||||||
|
DevAssert(pdu != NULL);
|
||||||
|
|
||||||
|
container = &pdu->choice.initiatingMessage.value.choice.TraceStart;
|
||||||
|
|
||||||
|
NGAP_FIND_PROTOCOLIE_BY_ID(NGAP_TraceStartIEs_t, ie, container,
|
||||||
|
NGAP_ProtocolIE_ID_id_gNB_UE_NGAP_ID, TRUE);
|
||||||
|
mme_ref_p = ngap_gNB_get_MME(NULL, assoc_id, 0);
|
||||||
|
DevAssert(mme_ref_p != NULL);
|
||||||
|
if (ie != NULL) {
|
||||||
|
ue_desc_p = ngap_gNB_get_ue_context(mme_ref_p->ngap_gNB_instance,
|
||||||
|
ie->value.choice.GNB_UE_NGAP_ID);
|
||||||
|
}
|
||||||
|
if (ue_desc_p == NULL) {
|
||||||
|
/* Could not find context associated with this gNB_ue_ngap_id -> generate
|
||||||
|
* trace failure indication.
|
||||||
|
*/
|
||||||
|
NGAP_E_UTRAN_Trace_ID_t trace_id;
|
||||||
|
NGAP_Cause_t cause;
|
||||||
|
memset(&trace_id, 0, sizeof(NGAP_E_UTRAN_Trace_ID_t));
|
||||||
|
memset(&cause, 0, sizeof(NGAP_Cause_t));
|
||||||
|
cause.present = NGAP_Cause_PR_radioNetwork;
|
||||||
|
cause.choice.radioNetwork = NGAP_CauseRadioNetwork_unknown_pair_ue_ngap_id;
|
||||||
|
ngap_gNB_generate_trace_failure(NULL, &trace_id, &cause);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int ngap_gNB_handle_deactivate_trace(uint32_t assoc_id,
|
||||||
|
uint32_t stream,
|
||||||
|
NGAP_NGAP_PDU_t *message_p)
|
||||||
|
{
|
||||||
|
// NGAP_DeactivateTraceIEs_t *deactivate_trace_p;
|
||||||
|
//
|
||||||
|
// deactivate_trace_p = &message_p->msg.deactivateTraceIEs;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
@@ -0,0 +1,46 @@
|
|||||||
|
/*
|
||||||
|
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
|
||||||
|
* contributor license agreements. See the NOTICE file distributed with
|
||||||
|
* this work for additional information regarding copyright ownership.
|
||||||
|
* The OpenAirInterface Software Alliance licenses this file to You under
|
||||||
|
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
|
||||||
|
* except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.openairinterface.org/?page_id=698
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*-------------------------------------------------------------------------------
|
||||||
|
* For more information about the OpenAirInterface (OAI) Software Alliance:
|
||||||
|
* contact@openairinterface.org
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef NGAP_GNB_TRACE_H_
|
||||||
|
#define NGAP_GNB_TRACE_H_
|
||||||
|
|
||||||
|
// int ngap_gNB_generate_trace_failure(sctp_data_t *sctp_data_p,
|
||||||
|
// int32_t stream,
|
||||||
|
// uint32_t gNB_ue_ngap_id,
|
||||||
|
// uint32_t mme_ue_ngap_id,
|
||||||
|
// E_UTRAN_Trace_ID_t *trace_id,
|
||||||
|
// Cause_t *cause_p);
|
||||||
|
|
||||||
|
// int ngap_gNB_handle_trace_start(gNB_mme_desc_t *gNB_desc_p,
|
||||||
|
// sctp_queue_item_t *packet_p,
|
||||||
|
// struct ngap_message_s *message_p);
|
||||||
|
int ngap_gNB_handle_trace_start(uint32_t assoc_id,
|
||||||
|
uint32_t stream,
|
||||||
|
NGAP_NGAP_PDU_t *pdu);
|
||||||
|
|
||||||
|
// int ngap_gNB_handle_deactivate_trace(gNB_mme_desc_t *gNB_desc_p,
|
||||||
|
// sctp_queue_item_t *packet_p,
|
||||||
|
// struct ngap_message_s *message_p);
|
||||||
|
int ngap_gNB_handle_deactivate_trace(uint32_t assoc_id,
|
||||||
|
uint32_t stream,
|
||||||
|
NGAP_NGAP_PDU_t *pdu);
|
||||||
|
|
||||||
|
#endif /* NGAP_GNB_TRACE_H_ */
|
||||||
@@ -0,0 +1,102 @@
|
|||||||
|
/*
|
||||||
|
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
|
||||||
|
* contributor license agreements. See the NOTICE file distributed with
|
||||||
|
* this work for additional information regarding copyright ownership.
|
||||||
|
* The OpenAirInterface Software Alliance licenses this file to You under
|
||||||
|
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
|
||||||
|
* except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.openairinterface.org/?page_id=698
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*-------------------------------------------------------------------------------
|
||||||
|
* For more information about the OpenAirInterface (OAI) Software Alliance:
|
||||||
|
* contact@openairinterface.org
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*! \file ngap_gNB_ue_context.c
|
||||||
|
* \brief ngap UE context management within gNB
|
||||||
|
* \author Sebastien ROUX <sebastien.roux@eurecom.fr>
|
||||||
|
* \date 2012
|
||||||
|
* \version 0.1
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#include "tree.h"
|
||||||
|
|
||||||
|
#include "intertask_interface.h"
|
||||||
|
|
||||||
|
#include "ngap_common.h"
|
||||||
|
#include "ngap_gNB_defs.h"
|
||||||
|
#include "ngap_gNB_ue_context.h"
|
||||||
|
|
||||||
|
int ngap_gNB_compare_gNB_ue_ngap_id(
|
||||||
|
struct ngap_gNB_ue_context_s *p1, struct ngap_gNB_ue_context_s *p2)
|
||||||
|
{
|
||||||
|
if (p1->gNB_ue_ngap_id > p2->gNB_ue_ngap_id) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (p1->gNB_ue_ngap_id < p2->gNB_ue_ngap_id) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Generate the tree management functions */
|
||||||
|
RB_GENERATE(ngap_ue_map, ngap_gNB_ue_context_s, entries,
|
||||||
|
ngap_gNB_compare_gNB_ue_ngap_id);
|
||||||
|
|
||||||
|
struct ngap_gNB_ue_context_s *ngap_gNB_allocate_new_UE_context(void)
|
||||||
|
{
|
||||||
|
struct ngap_gNB_ue_context_s *new_p;
|
||||||
|
|
||||||
|
new_p = malloc(sizeof(struct ngap_gNB_ue_context_s));
|
||||||
|
|
||||||
|
if (new_p == NULL) {
|
||||||
|
NGAP_ERROR("Cannot allocate new ue context\n");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
memset(new_p, 0, sizeof(struct ngap_gNB_ue_context_s));
|
||||||
|
|
||||||
|
return new_p;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct ngap_gNB_ue_context_s *ngap_gNB_get_ue_context(
|
||||||
|
ngap_gNB_instance_t *instance_p,
|
||||||
|
uint32_t gNB_ue_ngap_id)
|
||||||
|
{
|
||||||
|
ngap_gNB_ue_context_t temp;
|
||||||
|
|
||||||
|
memset(&temp, 0, sizeof(struct ngap_gNB_ue_context_s));
|
||||||
|
|
||||||
|
/* gNB ue ngap id = 24 bits wide */
|
||||||
|
temp.gNB_ue_ngap_id = gNB_ue_ngap_id & 0x00FFFFFF;
|
||||||
|
|
||||||
|
return RB_FIND(ngap_ue_map, &instance_p->ngap_ue_head, &temp);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ngap_gNB_free_ue_context(struct ngap_gNB_ue_context_s *ue_context_p)
|
||||||
|
{
|
||||||
|
if (ue_context_p == NULL) {
|
||||||
|
NGAP_ERROR("Trying to free a NULL context\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* TODO: check that context is currently not in the tree of known
|
||||||
|
* contexts.
|
||||||
|
*/
|
||||||
|
|
||||||
|
free(ue_context_p);
|
||||||
|
}
|
||||||
@@ -0,0 +1,95 @@
|
|||||||
|
/*
|
||||||
|
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
|
||||||
|
* contributor license agreements. See the NOTICE file distributed with
|
||||||
|
* this work for additional information regarding copyright ownership.
|
||||||
|
* The OpenAirInterface Software Alliance licenses this file to You under
|
||||||
|
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
|
||||||
|
* except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.openairinterface.org/?page_id=698
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*-------------------------------------------------------------------------------
|
||||||
|
* For more information about the OpenAirInterface (OAI) Software Alliance:
|
||||||
|
* contact@openairinterface.org
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "tree.h"
|
||||||
|
#include "queue.h"
|
||||||
|
|
||||||
|
#include "ngap_gNB_defs.h"
|
||||||
|
|
||||||
|
#ifndef NGAP_GNB_UE_CONTEXT_H_
|
||||||
|
#define NGAP_GNB_UE_CONTEXT_H_
|
||||||
|
|
||||||
|
// Forward declarations
|
||||||
|
struct ngap_gNB_mme_data_s;
|
||||||
|
struct ngap_ue_map;
|
||||||
|
struct gNB_mme_desc_s;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
/* UE has not been registered to a MME or UE association has failed. */
|
||||||
|
NGAP_UE_DECONNECTED = 0x0,
|
||||||
|
/* UE ngap state is waiting for initial context setup request message. */
|
||||||
|
NGAP_UE_WAITING_CSR = 0x1,
|
||||||
|
/* UE association is ready and bearers are established. */
|
||||||
|
NGAP_UE_CONNECTED = 0x2,
|
||||||
|
NGAP_UE_STATE_MAX,
|
||||||
|
} ngap_ue_state;
|
||||||
|
|
||||||
|
typedef struct ngap_gNB_ue_context_s {
|
||||||
|
/* Tree related data */
|
||||||
|
RB_ENTRY(ngap_gNB_ue_context_s) entries;
|
||||||
|
|
||||||
|
/* Uniquely identifies the UE between MME and gNB within the gNB.
|
||||||
|
* This id is encoded on 24bits.
|
||||||
|
*/
|
||||||
|
unsigned gNB_ue_ngap_id:24;
|
||||||
|
|
||||||
|
/* UE id for initial connection to NGAP */
|
||||||
|
uint16_t ue_initial_id;
|
||||||
|
|
||||||
|
/* Uniquely identifies the UE within MME. Encoded on 32 bits. */
|
||||||
|
uint32_t mme_ue_ngap_id;
|
||||||
|
|
||||||
|
/* Stream used for this particular UE */
|
||||||
|
int32_t tx_stream;
|
||||||
|
int32_t rx_stream;
|
||||||
|
|
||||||
|
/* Current UE state. */
|
||||||
|
ngap_ue_state ue_state;
|
||||||
|
|
||||||
|
/* Reference to MME data this UE is attached to */
|
||||||
|
struct ngap_gNB_mme_data_s *mme_ref;
|
||||||
|
|
||||||
|
/* Signaled by the UE in RRC Connection Setup Complete and used in NAS Uplink
|
||||||
|
* to route NAS messages correctly. 0-based, not 1-based as in TS 36.331
|
||||||
|
* 6.2.2 RRC Connection Setup Complete! */
|
||||||
|
int selected_plmn_identity;
|
||||||
|
|
||||||
|
/* Reference to gNB data this UE is attached to */
|
||||||
|
ngap_gNB_instance_t *gNB_instance;
|
||||||
|
} ngap_gNB_ue_context_t;
|
||||||
|
|
||||||
|
int ngap_gNB_compare_gNB_ue_ngap_id(
|
||||||
|
struct ngap_gNB_ue_context_s *p1, struct ngap_gNB_ue_context_s *p2);
|
||||||
|
|
||||||
|
/* Generate the tree management functions prototypes */
|
||||||
|
RB_PROTOTYPE(ngap_ue_map, ngap_gNB_ue_context_s, entries,
|
||||||
|
ngap_gNB_compare_gNB_ue_ngap_id);
|
||||||
|
|
||||||
|
struct ngap_gNB_ue_context_s *ngap_gNB_allocate_new_UE_context(void);
|
||||||
|
|
||||||
|
struct ngap_gNB_ue_context_s *ngap_gNB_get_ue_context(
|
||||||
|
ngap_gNB_instance_t *instance_p,
|
||||||
|
uint32_t gNB_ue_ngap_id);
|
||||||
|
|
||||||
|
void ngap_gNB_free_ue_context(struct ngap_gNB_ue_context_s *ue_context_p);
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* NGAP_GNB_UE_CONTEXT_H_ */
|
||||||
Reference in New Issue
Block a user