Compare commits

...

10 Commits

65 changed files with 6843 additions and 536 deletions

View File

@@ -412,7 +412,15 @@ add_library(S1AP_ENB
#X2AP
# Same limitation as described in RRC/S1AP: unknown generated file list
# so we generate it at cmake time
##############
########################################
# X2AP LAYER OPTIONS
##########################
add_boolean_option(ENABLE_USE_X2 True "Enable X2 interface for X2 handover")
if (${ENABLE_USE_X2})
#message("-- X2AP = ${ENABLE_USE_X2}")
add_list1_option(X2AP_VERSION R11 "X2AP Asn.1 grammar version" R10 R11)
set(X2AP_DIR ${OPENAIR2_DIR}/X2AP)
if (${X2AP_VERSION} STREQUAL "R11")
@@ -466,15 +474,30 @@ add_custom_command (
DEPENDS ${X2AP_ASN_FILES}
)
add_library(X2AP_LIB
add_library(X2AP_MSG_LIB
${X2AP_OAI_generated}
${X2AP_source}
${X2AP_DIR}/x2ap_common.c
)
set(X2AP_LIB X2AP_MSG_LIB)
include_directories ("${X2AP_C_DIR}")
include_directories ("${X2AP_DIR}")
add_library(X2AP_ENB_LIB
${X2AP_C_DIR}/x2ap_ies_defs.h
${X2AP_DIR}/x2ap_eNB.c
${X2AP_DIR}/x2ap_eNB_decoder.c
${X2AP_DIR}/x2ap_eNB_encoder.c
${X2AP_DIR}/x2ap_eNB_handler.c
${X2AP_DIR}/x2ap_eNB_itti_messaging.c
${X2AP_DIR}/x2ap_eNB_management_procedures.c
${X2AP_DIR}/x2ap_eNB_generate_messages.c
)
set(X2AP_ENB X2AP_ENB_LIB)
endif()
# Hardware dependant options
###################################
add_list1_option(NB_ANTENNAS_RX "2" "Number of antennas in reception" "1" "2" "4")
@@ -683,6 +706,7 @@ add_boolean_option(RRC_DEFAULT_RAB_IS_AM False "Otherwise it is UM, confi
##########################
# none
##########################
# PROJECTS (IST, FRENCH COLL., etc)
# SPECIFIC OPTIONS
@@ -1697,6 +1721,7 @@ add_definitions(-DASN1_MINIMUM_VERSION=924)
add_executable(lte-softmodem
${rrc_h}
${s1ap_h}
${x2ap_h}
${OPENAIR_BIN_DIR}/messages_xml.h
${OPENAIR_TARGETS}/RT/USER/rt_wrapper.c
${OPENAIR_TARGETS}/RT/USER/lte-ue.c
@@ -1719,7 +1744,7 @@ add_executable(lte-softmodem
target_link_libraries (lte-softmodem -ldl
-Wl,--start-group
RRC_LIB S1AP_LIB S1AP_ENB GTPV1U SECU_CN SECU_OSA UTIL HASHTABLE SCTP_CLIENT UDP SCHED_LIB PHY LFDS L2 ${MSC_LIB} ${RAL_LIB} ${NAS_UE_LIB} ${ITTI_LIB} ${MIH_LIB} ${FLPT_MSG_LIB} ${ASYNC_IF_LIB} ${FLEXRAN_AGENT_LIB} LFDS7
RRC_LIB S1AP_LIB S1AP_ENB ${X2AP_LIB} ${X2AP_ENB} GTPV1U SECU_CN SECU_OSA UTIL HASHTABLE SCTP_CLIENT UDP SCHED_LIB PHY LFDS L2 ${MSC_LIB} ${RAL_LIB} ${NAS_UE_LIB} ${ITTI_LIB} ${MIH_LIB} ${FLPT_MSG_LIB} ${ASYNC_IF_LIB} ${FLEXRAN_AGENT_LIB} LFDS7
-Wl,--end-group )
target_link_libraries (lte-softmodem ${LIBXML2_LIBRARIES})
@@ -1732,6 +1757,7 @@ target_link_libraries (lte-softmodem ${T_LIB})
add_executable(lte-softmodem-nos1
${rrc_h}
${s1ap_h}
${x2ap_h}
${OPENAIR_BIN_DIR}/messages_xml.h
${OPENAIR_TARGETS}/RT/USER/rt_wrapper.c
${OPENAIR_TARGETS}/RT/USER/lte-ue.c
@@ -1752,7 +1778,7 @@ add_executable(lte-softmodem-nos1
)
target_link_libraries (lte-softmodem-nos1
-Wl,--start-group
RRC_LIB SECU_CN SECU_OSA UTIL HASHTABLE SCHED_LIB PHY LFDS L2 ${MSC_LIB} ${RAL_LIB} ${ITTI_LIB} ${MIH_LIB} ${FLPT_MSG_LIB} ${ASYNC_IF_LIB} ${FLEXRAN_AGENT_LIB} LFDS7
RRC_LIB SECU_CN SECU_OSA ${X2AP_LIB} ${X2AP_ENB} UTIL HASHTABLE SCHED_LIB PHY LFDS L2 ${MSC_LIB} ${RAL_LIB} ${ITTI_LIB} ${MIH_LIB} ${FLPT_MSG_LIB} ${ASYNC_IF_LIB} ${FLEXRAN_AGENT_LIB} LFDS7
-Wl,--end-group )
target_link_libraries (lte-softmodem-nos1 ${LIBXML2_LIBRARIES})
@@ -1842,7 +1868,7 @@ add_executable(oaisim
target_include_directories(oaisim PUBLIC ${OPENAIR_TARGETS}/SIMU/USER)
target_link_libraries (oaisim
-Wl,-ldl,--start-group
RRC_LIB S1AP_LIB S1AP_ENB X2AP_LIB GTPV1U SECU_CN UTIL HASHTABLE SCTP_CLIENT UDP SCHED_LIB PHY LFDS ${MSC_LIB} L2 ${RAL_LIB} LIB_NAS_UE SIMU SIMU_ETH SECU_OSA ${ITTI_LIB} ${MIH_LIB}
RRC_LIB S1AP_LIB S1AP_ENB ${X2AP_LIB} ${X2AP_ENB} GTPV1U SECU_CN UTIL HASHTABLE SCTP_CLIENT UDP SCHED_LIB PHY LFDS ${MSC_LIB} L2 ${RAL_LIB} LIB_NAS_UE SIMU SIMU_ETH SECU_OSA ${ITTI_LIB} ${MIH_LIB} ${FLPT_MSG_LIB} ${ASYNC_IF_LIB} ${FLEXRAN_AGENT_LIB}
-Wl,--end-group )
target_link_libraries (oaisim ${LIBXML2_LIBRARIES} ${LAPACK_LIBRARIES})
@@ -1883,7 +1909,7 @@ add_executable(oaisim_nos1
target_include_directories(oaisim_nos1 PUBLIC ${OPENAIR_TARGETS}/SIMU/USER)
target_link_libraries (oaisim_nos1
-Wl,--start-group
RRC_LIB X2AP_LIB SECU_CN UTIL HASHTABLE SCHED_LIB PHY LFDS ${MSC_LIB} L2 ${RAL_LIB} SIMU SIMU_ETH SECU_OSA ${ITTI_LIB} ${MIH_LIB} ${FLPT_MSG_LIB} ${ASYNC_IF_LIB} ${FLEXRAN_AGENT_LIB} LFDS7
RRC_LIB ${X2AP_LIB} ${X2AP_ENB} SECU_CN UTIL HASHTABLE SCHED_LIB PHY LFDS ${MSC_LIB} L2 ${RAL_LIB} SIMU SIMU_ETH SECU_OSA ${ITTI_LIB} ${MIH_LIB} ${FLPT_MSG_LIB} ${ASYNC_IF_LIB} ${FLEXRAN_AGENT_LIB} LFDS7 SCTP_CLIENT UDP
-Wl,--end-group )
target_link_libraries (oaisim_nos1 ${LIBXML2_LIBRARIES} ${LAPACK_LIBRARIES})
@@ -1938,7 +1964,7 @@ add_executable(test_epc_generate_scenario
${OPENAIR_BIN_DIR}/messages_xml.h
)
target_link_libraries (test_epc_generate_scenario
-Wl,--start-group RRC_LIB S1AP_LIB S1AP_ENB X2AP_LIB GTPV1U LIB_NAS_UE SECU_CN UTIL HASHTABLE SCTP_CLIENT UDP SCHED_LIB PHY LFDS ${ITTI_LIB} ${MSC_LIB} L2 -Wl,--end-group pthread m rt crypt sctp ${LIBXML2_LIBRARIES} ${LIBXSLT_LIBRARIES} ${CRYPTO_LIBRARIES} ${OPENSSL_LIBRARIES} ${NETTLE_LIBRARIES} ${CONFIG_LIBRARIES}
-Wl,--start-group RRC_LIB S1AP_LIB S1AP_ENB ${X2AP_LIB} ${X2AP_ENB} GTPV1U LIB_NAS_UE SECU_CN UTIL HASHTABLE SCTP_CLIENT UDP SCHED_LIB PHY LFDS ${ITTI_LIB} ${MSC_LIB} L2 -Wl,--end-group pthread m rt crypt sctp ${LIBXML2_LIBRARIES} ${LIBXSLT_LIBRARIES} ${CRYPTO_LIBRARIES} ${OPENSSL_LIBRARIES} ${NETTLE_LIBRARIES} ${CONFIG_LIBRARIES}
)
add_executable(test_epc_play_scenario
@@ -1959,7 +1985,7 @@ add_executable(test_epc_play_scenario
)
target_include_directories(test_epc_play_scenario PUBLIC /usr/local/share/asn1c)
target_link_libraries (test_epc_play_scenario
-Wl,--start-group RRC_LIB S1AP_LIB X2AP_LIB GTPV1U LIB_NAS_UE SECU_CN UTIL HASHTABLE SCTP_CLIENT UDP SCHED_LIB PHY LFDS ${ITTI_LIB} ${MSC_LIB} -Wl,--end-group pthread m rt crypt sctp ${LIBXML2_LIBRARIES} ${LIBXSLT_LIBRARIES} ${CRYPTO_LIBRARIES} ${OPENSSL_LIBRARIES} ${NETTLE_LIBRARIES} ${CONFIG_LIBRARIES}
-Wl,--start-group RRC_LIB S1AP_LIB ${X2AP_LIB} ${X2AP_ENB} GTPV1U LIB_NAS_UE SECU_CN UTIL HASHTABLE SCTP_CLIENT UDP SCHED_LIB PHY LFDS ${ITTI_LIB} ${MSC_LIB} -Wl,--end-group pthread m rt crypt sctp ${LIBXML2_LIBRARIES} ${LIBXSLT_LIBRARIES} ${CRYPTO_LIBRARIES} ${OPENSSL_LIBRARIES} ${NETTLE_LIBRARIES} ${CONFIG_LIBRARIES}
)

View File

@@ -1639,5 +1639,41 @@ int phy_init_lte_eNB(PHY_VARS_eNB *eNB,
} // node_function != NGFI_RRU_IF4p5
return (0);
}
// Configure ue state in case of handover
void phy_config_ue_state_ho(uint8_t Mod_id,uint8_t CC_id,uint16_t rnti){
uint32_t k,j;
int UE_id = find_UE_id(Mod_id,rnti);
if(UE_id==-1){
printf("Program exited: phy_config_ue_state_ho: UE does not exist\n");
exit(-1);
}
LOG_I(PHY, "ho called for eNB %d CC %d rnti %x UE_id %d\n", Mod_id, CC_id, rnti, UE_id);
PHY_vars_eNB_g[Mod_id][CC_id]->UE_stats[UE_id].mode = PUSCH;
PHY_vars_eNB_g[Mod_id][CC_id]->ulsch[UE_id]->Msg3_flag = 0;
// HARQ processes
for (k=0; k<8; k++){ //harq_processes
for (j=0; j<PHY_vars_eNB_g[Mod_id][CC_id]->dlsch[UE_id][0]->Mdlharq; j++) {
PHY_vars_eNB_g[Mod_id][CC_id]->UE_stats[UE_id].dlsch_NAK[k][j]=0;
PHY_vars_eNB_g[Mod_id][CC_id]->UE_stats[UE_id].dlsch_ACK[k][j]=0;
PHY_vars_eNB_g[Mod_id][CC_id]->UE_stats[UE_id].dlsch_trials[k][j]=0;
}
PHY_vars_eNB_g[Mod_id][CC_id]->UE_stats[UE_id].dlsch_l2_errors[k]=0;
PHY_vars_eNB_g[Mod_id][CC_id]->UE_stats[UE_id].ulsch_errors[k]=0;
PHY_vars_eNB_g[Mod_id][CC_id]->UE_stats[UE_id].ulsch_consecutive_errors=0;
for (j=0; j<8; j++) {
PHY_vars_eNB_g[Mod_id][CC_id]->UE_stats[UE_id].ulsch_decoding_attempts[k][j]=0;
PHY_vars_eNB_g[Mod_id][CC_id]->UE_stats[UE_id].ulsch_decoding_attempts_last[k][j]=0;
PHY_vars_eNB_g[Mod_id][CC_id]->UE_stats[UE_id].ulsch_round_errors[k][j]=0;
PHY_vars_eNB_g[Mod_id][CC_id]->UE_stats[UE_id].ulsch_round_fer[k][j]=0;
}
}
PHY_vars_eNB_g[Mod_id][CC_id]->UE_stats[UE_id].dlsch_sliding_cnt=0;
PHY_vars_eNB_g[Mod_id][CC_id]->UE_stats[UE_id].dlsch_NAK_round0=0;
PHY_vars_eNB_g[Mod_id][CC_id]->UE_stats[UE_id].dlsch_mcs_offset=0;
}

View File

@@ -207,6 +207,7 @@ int16_t get_PL(module_id_t Mod_id,uint8_t CC_id,uint8_t eNB_index);
uint32_t get_RSRP(module_id_t Mod_id,uint8_t CC_id,uint8_t eNB_index);
uint32_t get_RSRQ(module_id_t Mod_id,uint8_t CC_id,uint8_t eNB_index);
uint8_t get_n_adj_cells(module_id_t Mod_id,uint8_t CC_id);
uint16_t get_nid_cell(uint8_t Mod_id,uint8_t CC_id);
uint32_t get_rx_total_gain_dB(module_id_t Mod_id,uint8_t CC_id);
uint32_t get_RSSI(module_id_t Mod_id,uint8_t CC_id);
int8_t set_RSRP_filtered(module_id_t Mod_id,uint8_t CC_id,uint8_t eNB_index,float rsrp);

View File

@@ -165,6 +165,11 @@ int8_t set_RSRQ_filtered(uint8_t Mod_id,uint8_t CC_id,uint8_t eNB_index,float rs
}
uint16_t get_nid_cell(uint8_t Mod_id,uint8_t CC_id){
LTE_DL_FRAME_PARMS *fp = &PHY_vars_UE_g[Mod_id][CC_id]->frame_parms;
return fp->Nid_cell;
}
void ue_rrc_measurements(PHY_VARS_UE *ue,
uint8_t slot,
uint8_t abstraction_flag)

View File

@@ -44,6 +44,7 @@ typedef struct {
long long p_time; /*!< \brief absolute process duration */
long long diff_square; /*!< \brief process duration square */
long long max;
long long min;
int trials;
int meas_flag;
} time_stats_t;
@@ -55,6 +56,7 @@ typedef struct {
uint32_t p_time; /*!< \brief absolute process duration */
uint32_t diff_square; /*!< \brief process duration square */
uint32_t max;
uint32_t min;
int trials;
} time_stats_t;
@@ -127,7 +129,11 @@ static inline void stop_meas(time_stats_t *ts)
if ((out-ts->in) > ts->max)
ts->max = out-ts->in;
if ((out-ts->in) < ts->min)
ts->min = out-ts->in;
ts->meas_flag=0;
}
}

View File

@@ -928,7 +928,8 @@ typedef struct {
SLIST_HEAD(ral_thresholds_gen_poll_s, ral_threshold_phy_t) ral_thresholds_gen_polled[RAL_LINK_PARAM_GEN_MAX];
SLIST_HEAD(ral_thresholds_lte_poll_s, ral_threshold_phy_t) ral_thresholds_lte_polled[RAL_LINK_PARAM_LTE_MAX];
#endif
// UE prach state for handover
uint8_t prach_ho;
} PHY_VARS_UE;
void exit_fun(const char* s);

View File

@@ -1716,13 +1716,19 @@ void ue_ulsch_uespec_procedures(PHY_VARS_UE *ue,UE_rxtx_proc_t *proc,uint8_t eNB
#endif
stop_meas(&ue->ulsch_encoding_stats);
if(ue->prach_ho){
ue->UE_mode[eNB_id] = PUSCH;
ue->prach_ho = 0;
}
if (ue->mac_enabled == 1) {
// signal MAC that Msg3 was sent
mac_xface->Msg3_transmitted(Mod_id,
CC_id,
frame_tx,
eNB_id);
eNB_id,
ue->UE_mode[eNB_id]);
}
} // Msg3_flag==1
else {
@@ -3601,7 +3607,8 @@ void process_rar(PHY_VARS_UE *ue, UE_rxtx_proc_t *proc, int eNB_id, runmode_t mo
dlsch0->harq_processes[0]->b,
&ue->pdcch_vars[subframe_rx & 0x1][eNB_id]->crnti,
ue->prach_resources[eNB_id]->ra_PreambleIndex,
dlsch0->harq_processes[0]->b); // alter the 'b' buffer so it contains only the selected RAR header and RAR payload
dlsch0->harq_processes[0]->b,
ue->prach_ho); // alter the 'b' buffer so it contains only the selected RAR header and RAR payload
ue->pdcch_vars[(subframe_rx+1) & 0x1][eNB_id]->crnti = ue->pdcch_vars[subframe_rx & 0x1][eNB_id]->crnti;
@@ -4562,17 +4569,20 @@ void phy_procedures_UE_lte(PHY_VARS_UE *ue,UE_rxtx_proc_t *proc,uint8_t eNB_id,u
LOG_E(PHY,"[UE %d] Frame %d, subframe %d RRC Connection lost, returning to PRACH\n",ue->Mod_id,
frame_rx,subframe_tx);
ue->UE_mode[eNB_id] = PRACH;
ue->prach_ho = 0;
// mac_xface->macphy_exit("Connection lost");
} else if (ret == PHY_RESYNCH) {
LOG_E(PHY,"[UE %d] Frame %d, subframe %d RRC Connection lost, trying to resynch\n",
ue->Mod_id,
frame_rx,subframe_tx);
ue->UE_mode[eNB_id] = RESYNCH;
ue->prach_ho = 0;
// mac_xface->macphy_exit("Connection lost");
} else if (ret == PHY_HO_PRACH) {
LOG_I(PHY,"[UE %d] Frame %d, subframe %d, return to PRACH and perform a contention-free access\n",
ue->Mod_id,frame_rx,subframe_tx);
ue->UE_mode[eNB_id] = PRACH;
ue->prach_ho = 1;
}
}
}

View File

@@ -33,6 +33,8 @@ MESSAGE_DEF(S1AP_UE_CONTEXT_RELEASE_COMPLETE_LOG, MESSAGE_PRIORITY_MED, IttiMsgT
MESSAGE_DEF(S1AP_UE_CONTEXT_RELEASE_LOG , MESSAGE_PRIORITY_MED, IttiMsgText , s1ap_ue_context_release_log)
MESSAGE_DEF(S1AP_E_RAB_SETUP_REQUEST_LOG , MESSAGE_PRIORITY_MED, IttiMsgText , s1ap_e_rab_setup_request_log)
MESSAGE_DEF(S1AP_E_RAB_SETUP_RESPONSE_LOG , MESSAGE_PRIORITY_MED, IttiMsgText , s1ap_e_rab_setup_response_log)
MESSAGE_DEF(S1AP_PATH_SWITCH_REQ_LOG , MESSAGE_PRIORITY_MED, IttiMsgText , s1ap_path_switch_req_log)
MESSAGE_DEF(S1AP_PATH_SWITCH_REQ_ACK_LOG , MESSAGE_PRIORITY_MED, IttiMsgText , s1ap_path_switch_req_ack_log)
/* eNB application layer -> S1AP messages */
MESSAGE_DEF(S1AP_REGISTER_ENB_REQ , MESSAGE_PRIORITY_MED, s1ap_register_enb_req_t , s1ap_register_enb_req)
@@ -54,6 +56,8 @@ MESSAGE_DEF(S1AP_UE_CTXT_MODIFICATION_RESP , MESSAGE_PRIORITY_MED, s1ap_ue_ctxt_
MESSAGE_DEF(S1AP_UE_CTXT_MODIFICATION_FAIL , MESSAGE_PRIORITY_MED, s1ap_ue_ctxt_modification_fail_t , s1ap_ue_ctxt_modification_fail)
MESSAGE_DEF(S1AP_E_RAB_SETUP_RESP , MESSAGE_PRIORITY_MED, s1ap_e_rab_setup_resp_t , s1ap_e_rab_setup_resp)
MESSAGE_DEF(S1AP_E_RAB_SETUP_REQUEST_FAIL , MESSAGE_PRIORITY_MED, s1ap_e_rab_setup_req_fail_t , s1ap_e_rab_setup_request_fail)
MESSAGE_DEF(S1AP_PATH_SWITCH_REQ , MESSAGE_PRIORITY_MED, s1ap_path_switch_req_t , s1ap_path_switch_req)
MESSAGE_DEF(S1AP_PATH_SWITCH_REQ_ACK , MESSAGE_PRIORITY_MED, s1ap_path_switch_req_ack_t , s1ap_path_switch_req_ack)
/* S1AP -> RRC messages */
MESSAGE_DEF(S1AP_DOWNLINK_NAS , MESSAGE_PRIORITY_MED, s1ap_downlink_nas_t , s1ap_downlink_nas )

View File

@@ -41,6 +41,8 @@
#define S1AP_UE_CTXT_MODIFICATION_FAIL(mSGpTR) (mSGpTR)->ittiMsg.s1ap_ue_ctxt_modification_fail
#define S1AP_E_RAB_SETUP_RESP(mSGpTR) (mSGpTR)->ittiMsg.s1ap_e_rab_setup_resp
#define S1AP_E_RAB_SETUP_FAIL(mSGpTR) (mSGpTR)->ittiMsg.s1ap_e_rab_setup_req_fail
#define S1AP_PATH_SWITCH_REQ(mSGpTR) (mSGpTR)->ittiMsg.s1ap_path_switch_req
#define S1AP_PATH_SWITCH_REQ_ACK(mSGpTR) (mSGpTR)->ittiMsg.s1ap_path_switch_req_ack
#define S1AP_DOWNLINK_NAS(mSGpTR) (mSGpTR)->ittiMsg.s1ap_downlink_nas
#define S1AP_INITIAL_CONTEXT_SETUP_REQ(mSGpTR) (mSGpTR)->ittiMsg.s1ap_initial_context_setup_req
@@ -74,6 +76,8 @@
#ifndef OCP_FRAMEWORK
typedef enum cell_type_e {
CELL_MACRO_ENB,
CELL_MICRO_ENB,
CELL_SMALL_ENB,
CELL_HOME_ENB
} cell_type_t;
@@ -107,6 +111,7 @@ typedef enum cn_domain_s {
typedef struct net_ip_address_s {
unsigned ipv4:1;
unsigned ipv6:1;
unsigned active:1;
char ipv4_address[16];
char ipv6_address[46];
} net_ip_address_t;
@@ -260,6 +265,17 @@ typedef struct e_rab_setup_s {
uint32_t gtp_teid;
} e_rab_setup_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_failed_s {
/* Unique e_rab_id for the UE. */
uint8_t e_rab_id;
@@ -510,6 +526,54 @@ typedef struct s1ap_e_rab_setup_resp_s {
e_rab_failed_t e_rabs_failed[S1AP_MAX_E_RAB];
} s1ap_e_rab_setup_resp_t;
typedef struct s1ap_path_switch_req_s {
unsigned eNB_ue_s1ap_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[S1AP_MAX_E_RAB];
/* MME UE id */
uint16_t mme_ue_s1ap_id;
/* Security algorithms */
security_capabilities_t security_capabilities;
} s1ap_path_switch_req_t;
typedef struct s1ap_path_switch_req_ack_s {
/* UE id for initial connection to S1AP */
uint16_t ue_initial_id;
unsigned eNB_ue_s1ap_id:24;
/* MME UE id */
uint16_t mme_ue_s1ap_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[S1AP_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[S1AP_MAX_E_RAB];
/* Security key */
int next_hop_chain_count;
uint8_t next_security_key[SECURITY_KEY_LENGTH];
} s1ap_path_switch_req_ack_t;
// S1AP --> RRC messages
typedef struct s1ap_ue_release_command_s {

View File

@@ -1,21 +1,51 @@
/*
* 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.0 (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
*/
/*******************************************************************************
OpenAirInterface
Copyright(c) 1999 - 2014 Eurecom
OpenAirInterface is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OpenAirInterface is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with OpenAirInterface.The full GNU General Public License is
included in this distribution in the file called "COPYING". If not,
see <http://www.gnu.org/licenses/>.
Contact Information
OpenAirInterface Admin: openair_admin@eurecom.fr
OpenAirInterface Tech : openair_tech@eurecom.fr
OpenAirInterface Dev : openair4g-devel@lists.eurecom.fr
Address : Eurecom, Campus SophiaTech, 450 Route des Chappes, CS 50193 - 06904 Biot Sophia Antipolis cedex, FRANCE
*******************************************************************************/
/* eNB application layer -> X2AP messages */
/* ITTI LOG messages */
/* ENCODER */
MESSAGE_DEF(X2AP_RESET_REQUST_LOG , MESSAGE_PRIORITY_MED, IttiMsgText , x2ap_reset_request_log)
MESSAGE_DEF(X2AP_RESOURCE_STATUS_RESPONSE_LOG , MESSAGE_PRIORITY_MED, IttiMsgText , x2ap_resource_status_response_log)
MESSAGE_DEF(X2AP_RESOURCE_STATUS_FAILURE_LOG , MESSAGE_PRIORITY_MED, IttiMsgText , x2ap_resource_status_failure_log)
/* Messages for X2AP logging */
MESSAGE_DEF(X2AP_SETUP_REQUEST_LOG , MESSAGE_PRIORITY_MED, IttiMsgText , x2ap_setup_request_log)
/* eNB application layer -> X2AP messages */
MESSAGE_DEF(X2AP_REGISTER_ENB_REQ , MESSAGE_PRIORITY_MED, x2ap_register_enb_req_t , x2ap_register_enb_req)
/* X2AP -> eNB application layer messages */
MESSAGE_DEF(X2AP_REGISTER_ENB_CNF , MESSAGE_PRIORITY_MED, x2ap_register_enb_cnf_t , x2ap_register_enb_cnf)
MESSAGE_DEF(X2AP_DEREGISTERED_ENB_IND , MESSAGE_PRIORITY_MED, x2ap_deregistered_enb_ind_t , x2ap_deregistered_enb_ind)
/* handover messages X2AP <-> RRC */
MESSAGE_DEF(X2AP_HANDOVER_REQ , MESSAGE_PRIORITY_MED, x2ap_handover_req_t , x2ap_handover_req)
MESSAGE_DEF(X2AP_HANDOVER_REQ_ACK , MESSAGE_PRIORITY_MED, x2ap_handover_req_ack_t , x2ap_handover_req_ack)

View File

@@ -1,21 +1,173 @@
/*
* 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.0 (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
*/
/*******************************************************************************
OpenAirInterface
Copyright(c) 1999 - 2014 Eurecom
OpenAirInterface is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OpenAirInterface is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with OpenAirInterface.The full GNU General Public License is
included in this distribution in the file called "COPYING". If not,
see <http://www.gnu.org/licenses/>.
Contact Information
OpenAirInterface Admin: openair_admin@eurecom.fr
OpenAirInterface Tech : openair_tech@eurecom.fr
OpenAirInterface Dev : openair4g-devel@lists.eurecom.fr
Address : Eurecom, Campus SophiaTech, 450 Route des Chappes, CS 50193 - 06904 Biot Sophia Antipolis cedex, FRANCE
*******************************************************************************/
#ifndef X2AP_MESSAGES_TYPES_H_
#define X2AP_MESSAGES_TYPES_H_
#include "PhysCellId.h"
//-------------------------------------------------------------------------------------------//
// Defines to access message fields.
#define X2AP_REGISTER_ENB_REQ(mSGpTR) (mSGpTR)->ittiMsg.x2ap_register_enb_req
#define X2AP_HANDOVER_REQ(mSGpTR) (mSGpTR)->ittiMsg.x2ap_handover_req
#define X2AP_HANDOVER_REQ_ACK(mSGpTR) (mSGpTR)->ittiMsg.x2ap_handover_req_ack
#define X2AP_REGISTER_ENB_CNF(mSGpTR) (mSGpTR)->ittiMsg.x2ap_register_enb_cnf
#define X2AP_DEREGISTERED_ENB_IND(mSGpTR) (mSGpTR)->ittiMsg.x2ap_deregistered_enb_ind
#define X2AP_MAX_NB_ENB_IP_ADDRESS 2
// eNB application layer -> X2AP messages
typedef struct x2ap_register_enb_req_s {
/* Unique eNB_id to identify the eNB within EPC.
* For macro eNB ids this field should be 20 bits long.
* For home eNB ids this field should be 28 bits long.
*/
uint32_t eNB_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 *eNB_name;
/* Tracking area code */
uint16_t tac;
/* Mobile Country Code
* Mobile Network Code
*/
uint16_t mcc;
uint16_t mnc;
uint8_t mnc_digit_length;
/*
* EARFCN
*/
uint16_t fdd_uL_EARFCN;
uint16_t fdd_dL_EARFCN;
uint16_t tdd_EARFCN;
uint16_t fdd_uL_Transmission_Bandwidth;
uint16_t fdd_dL_Transmission_Bandwidth;
uint16_t tdd_Transmission_Bandwidth;
/* The local eNB IP address to bind */
net_ip_address_t enb_x2_ip_address;
/* Nb of MME to connect to */
uint8_t nb_x2;
/* List of target eNB to connect to for X2*/
net_ip_address_t target_enb_x2_ip_address[X2AP_MAX_NB_ENB_IP_ADDRESS];
/* Number of SCTP streams used for associations */
uint16_t sctp_in_streams;
uint16_t sctp_out_streams;
} x2ap_register_enb_req_t;
//-------------------------------------------------------------------------------------------//
// X2AP -> eNB application layer messages
typedef struct x2ap_register_enb_cnf_s {
/* Nb of connected eNBs*/
uint8_t nb_x2;
} x2ap_register_enb_cnf_t;
typedef struct x2ap_deregistered_enb_ind_s {
/* Nb of connected eNBs */
uint8_t nb_x2;
} x2ap_deregistered_enb_ind_t;
//-------------------------------------------------------------------------------------------//
// X2AP <-> RRC
typedef struct x2ap_gummei_s {
uint16_t mcc;
uint16_t mnc;
uint8_t mnc_len;
uint8_t mme_code;
uint16_t mme_group_id;
} x2ap_gummei_t;
typedef struct x2ap_lastvisitedcell_info_s {
uint16_t mcc;
uint16_t mnc;
uint8_t mnc_len;
PhysCellId_t target_physCellId;
cell_type_t cell_type;
uint64_t time_UE_StayedInCell;
}x2ap_lastvisitedcell_info_t;
//used for src
typedef struct x2ap_handover_req_s {
int source_rnti; /* TODO: to be fixed/remove */
int source_x2id; /* TODO: to be fixed/remove */
unsigned old_eNB_ue_s1ap_id:24;
PhysCellId_t target_physCellId;
x2ap_gummei_t ue_gummei;
/*UE-ContextInformation */
/* MME UE id */
uint16_t mme_ue_s1ap_id;
security_capabilities_t security_capabilities;
uint8_t kenb[32]; // keNB or keNB*
/*next_hop_chaining_coun */
long int kenb_ncc;
/* UE aggregate maximum bitrate */
ambr_t ue_ambr;
/* list of e_rab setup-ed by RRC layers */
e_rab_setup_t e_rabs_tobesetup[S1AP_MAX_E_RAB];
x2ap_lastvisitedcell_info_t lastvisitedcell_info;
/* TODO: this parameter has to be removed */
int target_mod_id;
} x2ap_handover_req_t;
typedef struct x2ap_handover_req_ack_s {
int source_rnti; /* TODO: to be fixed/remove */
int source_x2id; /* TODO: to be fixed/remove */
/* TODO: this parameter has to be removed */
int target_mod_id;
} x2ap_handover_req_ack_t;
#endif /* X2AP_MESSAGES_TYPES_H_ */

View File

@@ -48,7 +48,11 @@
# include "sctp_eNB_task.h"
# include "gtpv1u_eNB_task.h"
# endif
# if defined(ENABLE_USE_X2)
# include "x2ap_eNB.h"
//# include "sctp_eNB_task.h"
//# include "gtpv1u_eNB_task.h"
#endif
#if defined(FLEXRAN_AGENT_SB_IF)
# include "flexran_agent.h"
#endif
@@ -63,6 +67,10 @@ extern unsigned char NB_eNB_INST;
# define ENB_REGISTER_RETRY_DELAY 10
# endif
# if defined(ENABLE_USE_X2)
# define X2AP_ENB_REGISTER_RETRY_DELAY 10
#endif
/*------------------------------------------------------------------------------*/
static void configure_phy(module_id_t enb_id, const Enb_properties_array_t* enb_properties)
{
@@ -193,7 +201,7 @@ static void configure_rrc(uint32_t enb_id, const Enb_properties_array_t *enb_pro
/*------------------------------------------------------------------------------*/
# if defined(ENABLE_USE_MME)
static uint32_t eNB_app_register(uint32_t enb_id_start, uint32_t enb_id_end, const Enb_properties_array_t *enb_properties)
static uint32_t eNB_app_register_s1(uint32_t enb_id_start, uint32_t enb_id_end, const Enb_properties_array_t *enb_properties)
{
uint32_t enb_id;
uint32_t mme_id;
@@ -265,6 +273,87 @@ static uint32_t eNB_app_register(uint32_t enb_id_start, uint32_t enb_id_end, con
return register_enb_pending;
}
# endif
/*------------------------------------------------------------------------------*/
# if defined(ENABLE_USE_X2)
static uint32_t eNB_app_register_x2(uint32_t enb_id_start, uint32_t enb_id_end,
const Enb_properties_array_t *enb_properties)
{
uint32_t enb_id;
uint32_t x2_id;
MessageDef *msg_p;
uint32_t register_enb_x2_pending = 0;
char *str = NULL;
struct in_addr addr;
# if defined(OAI_EMU)
# endif
for (enb_id = enb_id_start; (enb_id < enb_id_end) ; enb_id++) {
# if defined(OAI_EMU)
if (oai_emulation.info.cli_start_enb[enb_id] == 1)
# endif
{
x2ap_register_enb_req_t *x2ap_register_eNB;
msg_p = itti_alloc_new_message (TASK_ENB_APP, X2AP_REGISTER_ENB_REQ);
x2ap_register_eNB = &X2AP_REGISTER_ENB_REQ(msg_p);
/* Some default/random parameters */
x2ap_register_eNB->eNB_id = enb_properties->properties[enb_id]->eNB_id;
x2ap_register_eNB->cell_type = enb_properties->properties[enb_id]->cell_type;
x2ap_register_eNB->eNB_name = enb_properties->properties[enb_id]->eNB_name;
x2ap_register_eNB->tac = enb_properties->properties[enb_id]->tac;
x2ap_register_eNB->mcc = enb_properties->properties[enb_id]->mcc;
x2ap_register_eNB->mnc = enb_properties->properties[enb_id]->mnc;
x2ap_register_eNB->mnc_digit_length = enb_properties->properties[enb_id]->mnc_digit_length;
x2ap_register_eNB->nb_x2 = enb_properties->properties[enb_id]->nb_x2;
AssertFatal (x2ap_register_eNB->nb_x2 <= X2AP_MAX_NB_ENB_IP_ADDRESS,
"Too many X2 interfaces for eNB %d (%d/%d)!",
enb_id, x2ap_register_eNB->nb_x2,
X2AP_MAX_NB_ENB_IP_ADDRESS);
for (x2_id = 0; x2_id < x2ap_register_eNB->nb_x2; x2_id++) {
x2ap_register_eNB->target_enb_x2_ip_address[x2_id].ipv4 = enb_properties->properties[enb_id]->target_enb_x2_ip_address[x2_id].ipv4;
x2ap_register_eNB->target_enb_x2_ip_address[x2_id].ipv6 = enb_properties->properties[enb_id]->target_enb_x2_ip_address[x2_id].ipv6;
strncpy (x2ap_register_eNB->target_enb_x2_ip_address[x2_id].ipv4_address,
enb_properties->properties[enb_id]->target_enb_x2_ip_address[x2_id].ipv4_address,
sizeof(x2ap_register_eNB->target_enb_x2_ip_address[0].ipv4_address));
strncpy (x2ap_register_eNB->target_enb_x2_ip_address[x2_id].ipv6_address,
enb_properties->properties[enb_id]->target_enb_x2_ip_address[x2_id].ipv6_address,
sizeof(x2ap_register_eNB->target_enb_x2_ip_address[0].ipv6_address));
// this is used to identify whether this eNb is acting as an initiator (client) or listener (server)
x2ap_register_eNB->target_enb_x2_ip_address[x2_id].active = enb_properties->properties[enb_id]->target_enb_x2_ip_address[x2_id].active;
}
x2ap_register_eNB->sctp_in_streams = enb_properties->properties[enb_id]->sctp_in_streams;
x2ap_register_eNB->sctp_out_streams = enb_properties->properties[enb_id]->sctp_out_streams;
x2ap_register_eNB->enb_x2_ip_address.ipv6 = 0;
x2ap_register_eNB->enb_x2_ip_address.ipv4 = 1;
addr.s_addr = enb_properties->properties[enb_id]->enb_ipv4_address_for_X2C;
str = inet_ntoa(addr);
strcpy(x2ap_register_eNB->enb_x2_ip_address.ipv4_address, str);
itti_send_msg_to_task (TASK_X2AP, ENB_MODULE_ID_TO_INSTANCE(enb_id), msg_p);
register_enb_x2_pending++;
}
}
return register_enb_x2_pending;
}
# endif
#endif
/*------------------------------------------------------------------------------*/
@@ -276,9 +365,14 @@ void *eNB_app_task(void *args_p)
uint32_t enb_id_start = 0;
uint32_t enb_id_end = enb_id_start + enb_nb;
# if defined(ENABLE_USE_MME)
uint32_t register_enb_pending;
uint32_t register_enb_pending; // s1ap
uint32_t registered_enb;
long enb_register_retry_timer_id;
# endif
# if defined(ENABLE_USE_X2)
uint32_t x2_register_enb_pending;
uint32_t x2_registered_enb;
long x2_enb_register_retry_timer_id;
# endif
uint32_t enb_id;
MessageDef *msg_p = NULL;
@@ -291,7 +385,9 @@ void *eNB_app_task(void *args_p)
itti_mark_task_ready (TASK_ENB_APP);
# if defined(ENABLE_ITTI)
enb_properties_p = enb_config_get();
# if defined(ENABLE_ITTI)
# if defined(OAI_EMU)
enb_nb = oai_emulation.info.nb_enb_local;
enb_id_start = oai_emulation.info.first_enb_local;
@@ -300,10 +396,12 @@ void *eNB_app_task(void *args_p)
AssertFatal (enb_id_end <= NUMBER_OF_eNB_MAX,
"Last eNB index is greater or equal to maximum eNB index (%d/%d)!",
enb_id_end, NUMBER_OF_eNB_MAX);
# endif
# endif
enb_properties_p = enb_config_get();
#else
enb_nb = enb_properties_p->number;
enb_id_start = 0;
enb_id_end = enb_properties_p->number;
# endif
#endif
AssertFatal (enb_nb <= enb_properties_p->number,
"Number of eNB is greater than eNB defined in configuration file (%d/%d)!",
@@ -325,13 +423,24 @@ void *eNB_app_task(void *args_p)
# if defined(ENABLE_USE_MME)
/* Try to register each eNB */
registered_enb = 0;
register_enb_pending = eNB_app_register (enb_id_start, enb_id_end, enb_properties_p);
register_enb_pending = eNB_app_register_s1 (enb_id_start, enb_id_end, enb_properties_p);
# else
/* Start L2L1 task */
msg_p = itti_alloc_new_message(TASK_ENB_APP, INITIALIZE_MESSAGE);
itti_send_msg_to_task(TASK_L2L1, INSTANCE_DEFAULT, msg_p);
# endif
# if defined(ENABLE_USE_X2)
/* Try to register each eNB with each other */
x2_registered_enb = 0;
x2_register_enb_pending = eNB_app_register_x2 (enb_id_start, enb_id_end, enb_properties_p);
# else
# endif
do {
// Wait for a message
itti_receive_msg (TASK_ENB_APP, &msg_p);
@@ -395,7 +504,7 @@ void *eNB_app_task(void *args_p)
sleep(ENB_REGISTER_RETRY_DELAY);
/* Restart the registration process */
registered_enb = 0;
register_enb_pending = eNB_app_register (enb_id_start, enb_id_end, enb_properties_p);
register_enb_pending = eNB_app_register_s1 (enb_id_start, enb_id_end, enb_properties_p);
}
}
}
@@ -415,12 +524,60 @@ void *eNB_app_task(void *args_p)
if (TIMER_HAS_EXPIRED (msg_p).timer_id == enb_register_retry_timer_id) {
/* Restart the registration process */
registered_enb = 0;
register_enb_pending = eNB_app_register (enb_id_start, enb_id_end, enb_properties_p);
register_enb_pending = eNB_app_register_s1 (enb_id_start, enb_id_end, enb_properties_p);
}
break;
# endif
# endif
#ifdef ENABLE_USE_X2
case X2AP_DEREGISTERED_ENB_IND:
LOG_W(ENB_APP, "[eNB %d] Received %s: associated eNB %d\n", instance, msg_name,
X2AP_DEREGISTERED_ENB_IND(msg_p).nb_x2);
/* TODO handle recovering of registration */
break;
case X2AP_REGISTER_ENB_CNF:
LOG_I(ENB_APP, "[eNB %d] Received %s: associated eNB %d\n", instance, msg_name,
X2AP_REGISTER_ENB_CNF(msg_p).nb_x2);
DevAssert(x2_register_enb_pending > 0);
x2_register_enb_pending--;
/* Check if at least eNB is registered with one target eNB */
if (X2AP_REGISTER_ENB_CNF(msg_p).nb_x2 > 0) {
x2_registered_enb++;
}
/* Check if all register eNB requests have been processed */
if (x2_register_enb_pending == 0) {
if (x2_registered_enb == enb_nb) {
/* If all eNB are registered, start RRC HO task */
}else {
uint32_t x2_not_associated = enb_nb - x2_registered_enb;
LOG_W(ENB_APP, " %d eNB %s not associated with the target\n",
x2_not_associated, x2_not_associated > 1 ? "are" : "is");
// timer to retry
/* Restart the eNB registration process in ENB_REGISTER_RETRY_DELAY seconds */
if (timer_setup (X2AP_ENB_REGISTER_RETRY_DELAY, 0, TASK_ENB_APP,
INSTANCE_DEFAULT, TIMER_ONE_SHOT, NULL,
&x2_enb_register_retry_timer_id) < 0) {
LOG_E(ENB_APP, " Can not start eNB X2AP register: retry timer, use \"sleep\" instead!\n");
sleep(X2AP_ENB_REGISTER_RETRY_DELAY);
/* Restart the registration process */
x2_registered_enb = 0;
x2_register_enb_pending = eNB_app_register_x2 (enb_id_start, enb_id_end, enb_properties_p);
}
}
}
break;
#endif
default:
LOG_E(ENB_APP, "Received unexpected message %s\n", msg_name);
break;

View File

@@ -179,6 +179,12 @@
#define ENB_CONFIG_STRING_MME_IP_ADDRESS_ACTIVE "active"
#define ENB_CONFIG_STRING_MME_IP_ADDRESS_PREFERENCE "preference"
#define ENB_CONFIG_STRING_TARGET_ENB_X2_IP_ADDRESS "target_enb_x2_ip_address"
#define ENB_CONFIG_STRING_TARGET_ENB_X2_IPV4_ADDRESS "ipv4"
#define ENB_CONFIG_STRING_TARGET_ENB_X2_IPV6_ADDRESS "ipv6"
#define ENB_CONFIG_STRING_TARGET_ENB_X2_IP_ADDRESS_ACTIVE "active"
#define ENB_CONFIG_STRING_TARGET_ENB_X2_IP_ADDRESS_PREFERENCE "preference"
#define ENB_CONFIG_STRING_SCTP_CONFIG "SCTP"
#define ENB_CONFIG_STRING_SCTP_INSTREAMS "SCTP_INSTREAMS"
#define ENB_CONFIG_STRING_SCTP_OUTSTREAMS "SCTP_OUTSTREAMS"
@@ -190,6 +196,13 @@
#define ENB_CONFIG_STRING_ENB_IPV4_ADDR_FOR_S1U "ENB_IPV4_ADDRESS_FOR_S1U"
#define ENB_CONFIG_STRING_ENB_PORT_FOR_S1U "ENB_PORT_FOR_S1U"
#define ENB_CONFIG_STRING_ENB_INTERFACE_NAME_FOR_X2C "ENB_INTERFACE_NAME_FOR_X2C"
#define ENB_CONFIG_STRING_ENB_IPV4_ADDR_FOR_X2C "ENB_IPV4_ADDRESS_FOR_X2C"
#define ENB_CONFIG_STRING_ENB_PORT_FOR_X2C "ENB_PORT_FOR_X2C"
#define ENB_CONFIG_STRING_ENB_INTERFACE_NAME_FOR_X2U "ENB_INTERFACE_NAME_FOR_X2U"
#define ENB_CONFIG_STRING_ENB_IPV4_ADDR_FOR_X2U "ENB_IPV4_ADDRESS_FOR_X2U"
#define ENB_CONFIG_STRING_ENB_PORT_FOR_X2U "ENB_PORT_FOR_X2U"
#define ENB_CONFIG_STRING_NETWORK_CONTROLLER_CONFIG "NETWORK_CONTROLLER"
#define ENB_CONFIG_STRING_FLEXRAN_AGENT_INTERFACE_NAME "FLEXRAN_AGENT_INTERFACE_NAME"
#define ENB_CONFIG_STRING_FLEXRAN_AGENT_IPV4_ADDRESS "FLEXRAN_AGENT_IPV4_ADDRESS"
@@ -454,8 +467,9 @@ void enb_config_display(void)
printf( "\tue_TimersAndConstants_t311 for CC %d:\t%ld:\n",j,enb_properties.properties[i]->ue_TimersAndConstants_t311[j]);
printf( "\tue_TimersAndConstants_n311 for CC %d:\t%ld:\n",j,enb_properties.properties[i]->ue_TimersAndConstants_n311[j]);
printf( "\tue_TransmissionMode for CC %d:\t%ld:\n",j,enb_properties.properties[i]->ue_TransmissionMode[j]);
}
for (j=0; j < enb_properties.properties[i]->nb_x2; j++) {
printf( "\n\tTarget eNB IPv4 address: \t%s", enb_properties.properties[i]->target_enb_x2_ip_address[j].ipv4_address);
}
for (j=0; j < enb_properties.properties[i]->num_otg_elements; j++) {
@@ -540,6 +554,8 @@ const Enb_properties_array_t *enb_config_init(char* lib_config_file_name_pP)
config_setting_t *setting_srb1 = NULL;
config_setting_t *setting_mme_addresses = NULL;
config_setting_t *setting_mme_address = NULL;
config_setting_t *setting_x2_addresses = NULL;
config_setting_t *setting_x2_address = NULL;
config_setting_t *setting_rrh_gws = NULL;
config_setting_t *setting_rrh_gw = NULL;
config_setting_t *setting_enb = NULL;
@@ -551,6 +567,7 @@ const Enb_properties_array_t *enb_config_init(char* lib_config_file_name_pP)
int num_enbs = 0;
int num_mme_address = 0;
int num_rrh_gw = 0;
int num_x2_address = 0;
int num_otg_elements = 0;
int num_component_carriers = 0;
int i = 0;
@@ -671,9 +688,15 @@ const Enb_properties_array_t *enb_config_init(char* lib_config_file_name_pP)
const char* active_enb[MAX_ENB];
char* enb_interface_name_for_S1U = NULL;
char* enb_ipv4_address_for_S1U = NULL;
char* enb_interface_name_for_X2U = NULL;
char* enb_ipv4_address_for_X2U = NULL;
libconfig_int enb_port_for_S1U = 0;
libconfig_int enb_port_for_X2U = 0;
char* enb_interface_name_for_S1_MME = NULL;
char* enb_ipv4_address_for_S1_MME = NULL;
char* enb_interface_name_for_X2C = NULL;
char* enb_ipv4_address_for_X2C = NULL;
libconfig_int enb_port_for_X2C = 0;
char *address = NULL;
char *cidr = NULL;
char *astring = NULL;
@@ -2435,7 +2458,50 @@ const Enb_properties_array_t *enb_config_init(char* lib_config_file_name_pP)
enb_properties.properties[enb_properties_index]->rrh_gw_config[j].lmssdr = 0;
enb_properties.properties[enb_properties_index]->rrh_gw_config[j].if_compress = 0;
}
// X2_ENB_IP_ADDRESS
setting_x2_addresses = config_setting_get_member (setting_enb, ENB_CONFIG_STRING_TARGET_ENB_X2_IP_ADDRESS);
num_x2_address = config_setting_length(setting_x2_addresses);
enb_properties.properties[enb_properties_index]->nb_x2 = 0;
for (j = 0; j < num_x2_address; j++) {
setting_x2_address = config_setting_get_elem(setting_x2_addresses, j);
if ( !(
config_setting_lookup_string(setting_x2_address, ENB_CONFIG_STRING_TARGET_ENB_X2_IPV4_ADDRESS, (const char **)&ipv4)
&& config_setting_lookup_string(setting_x2_address, ENB_CONFIG_STRING_TARGET_ENB_X2_IPV6_ADDRESS, (const char **)&ipv6)
&& config_setting_lookup_string(setting_x2_address, ENB_CONFIG_STRING_TARGET_ENB_X2_IP_ADDRESS_ACTIVE, (const char **)&active)
&& config_setting_lookup_string(setting_x2_address, ENB_CONFIG_STRING_TARGET_ENB_X2_IP_ADDRESS_PREFERENCE, (const char **)&preference)
)
) {
AssertError (0, parse_errors ++,
"Failed to parse eNB configuration file %s, %u th enb %u the X2 address !\n",
lib_config_file_name_pP, i, j);
continue; // FIXME will prevent segfaults below, not sure what happens at function exit...
}
enb_properties.properties[enb_properties_index]->nb_x2 += 1;
enb_properties.properties[enb_properties_index]->target_enb_x2_ip_address[j].ipv4_address = strdup(ipv4);
enb_properties.properties[enb_properties_index]->target_enb_x2_ip_address[j].ipv6_address = strdup(ipv6);
if (strcmp(active, "yes") == 0) {
enb_properties.properties[enb_properties_index]->target_enb_x2_ip_address[j].active = 1;
} else {
enb_properties.properties[enb_properties_index]->target_enb_x2_ip_address[j].active = 0;
}
if (strcmp(preference, "ipv4") == 0) {
enb_properties.properties[enb_properties_index]->target_enb_x2_ip_address[j].ipv4 = 1;
} else if (strcmp(preference, "ipv6") == 0) {
enb_properties.properties[enb_properties_index]->target_enb_x2_ip_address[j].ipv6 = 1;
} else if (strcmp(preference, "no") == 0) {
enb_properties.properties[enb_properties_index]->target_enb_x2_ip_address[j].ipv4 = 1;
enb_properties.properties[enb_properties_index]->target_enb_x2_ip_address[j].ipv6 = 1;
}
}
// SCTP SETTING
enb_properties.properties[enb_properties_index]->sctp_out_streams = SCTP_OUT_STREAMS;
enb_properties.properties[enb_properties_index]->sctp_in_streams = SCTP_IN_STREAMS;
@@ -2468,6 +2534,19 @@ const Enb_properties_array_t *enb_config_init(char* lib_config_file_name_pP)
(const char **)&enb_ipv4_address_for_S1U)
&& config_setting_lookup_int(subsetting, ENB_CONFIG_STRING_ENB_PORT_FOR_S1U,
&enb_port_for_S1U)
&& config_setting_lookup_string( subsetting, ENB_CONFIG_STRING_ENB_INTERFACE_NAME_FOR_X2C,
(const char **)&enb_interface_name_for_X2C)
&& config_setting_lookup_string( subsetting, ENB_CONFIG_STRING_ENB_IPV4_ADDR_FOR_X2C,
(const char **)&enb_ipv4_address_for_X2C)
&& config_setting_lookup_int(subsetting, ENB_CONFIG_STRING_ENB_PORT_FOR_X2C,
&enb_port_for_X2C)
&& config_setting_lookup_string( subsetting, ENB_CONFIG_STRING_ENB_INTERFACE_NAME_FOR_X2U,
(const char **)&enb_interface_name_for_X2U)
&& config_setting_lookup_string( subsetting, ENB_CONFIG_STRING_ENB_IPV4_ADDR_FOR_X2U,
(const char **)&enb_ipv4_address_for_X2U)
&& config_setting_lookup_int(subsetting, ENB_CONFIG_STRING_ENB_PORT_FOR_X2U,
&enb_port_for_X2U)
)
) {
enb_properties.properties[enb_properties_index]->enb_interface_name_for_S1U = strdup(enb_interface_name_for_S1U);
@@ -2487,6 +2566,26 @@ const Enb_properties_array_t *enb_config_init(char* lib_config_file_name_pP)
if (address) {
IPV4_STR_ADDR_TO_INT_NWBO ( address, enb_properties.properties[enb_properties_index]->enb_ipv4_address_for_S1_MME, "BAD IP ADDRESS FORMAT FOR eNB S1_MME !\n" );
}
enb_properties.properties[enb_properties_index]->enb_interface_name_for_X2U = strdup(enb_interface_name_for_X2U);
cidr = enb_ipv4_address_for_X2U;
address = strtok(cidr, "/");
if (address) {
IPV4_STR_ADDR_TO_INT_NWBO ( address, enb_properties.properties[enb_properties_index]->enb_ipv4_address_for_X2U, "BAD IP ADDRESS FORMAT FOR eNB X2U !\n" );
}
enb_properties.properties[enb_properties_index]->enb_port_for_X2U = enb_port_for_X2U;
enb_properties.properties[enb_properties_index]->enb_interface_name_for_X2C = strdup(enb_interface_name_for_X2C);
cidr = enb_ipv4_address_for_X2C;
address = strtok(cidr, "/");
if (address) {
IPV4_STR_ADDR_TO_INT_NWBO ( address, enb_properties.properties[enb_properties_index]->enb_ipv4_address_for_X2C, "BAD IP ADDRESS FORMAT FOR eNB X2C !\n" );
}
enb_properties.properties[enb_properties_index]->enb_port_for_X2C = enb_port_for_X2C;
}
}

View File

@@ -40,6 +40,7 @@
#include "PHY/impl_defs_lte.h"
#include "PHY/defs.h"
#include "s1ap_messages_types.h"
#include "x2ap_messages_types.h"
#ifdef CMAKER
#include "SystemInformationBlockType2.h"
#include "rrc_messages_types.h"
@@ -73,6 +74,14 @@ typedef struct mme_ip_address_s {
char *ipv6_address;
} mme_ip_address_t;
typedef struct x2_enb_ip_address_s {
unsigned ipv4:1;
unsigned ipv6:1;
unsigned active:1;
char *ipv4_address;
char *ipv6_address;
} x2_enb_ip_address_t;
typedef struct rrh_gw_config_s {
unsigned udp:1;
unsigned raw:1;
@@ -219,6 +228,11 @@ typedef struct Enb_properties_s {
/* List of MME to connect to */
mme_ip_address_t mme_ip_address[S1AP_MAX_NB_MME_IP_ADDRESS];
/* Nb of X2 to connect to */
uint8_t nb_x2;
/* List of X2 to connect to */
x2_enb_ip_address_t target_enb_x2_ip_address[X2AP_MAX_NB_ENB_IP_ADDRESS];
int sctp_in_streams;
int sctp_out_streams;
@@ -229,6 +243,14 @@ typedef struct Enb_properties_s {
char *enb_interface_name_for_S1_MME;
in_addr_t enb_ipv4_address_for_S1_MME;
char *enb_interface_name_for_X2U;
in_addr_t enb_ipv4_address_for_X2U;
tcp_udp_port_t enb_port_for_X2U;
char *enb_interface_name_for_X2C;
in_addr_t enb_ipv4_address_for_X2C;
tcp_udp_port_t enb_port_for_X2C;
char *flexran_agent_interface_name;
in_addr_t flexran_agent_ipv4_address;
tcp_udp_port_t flexran_agent_port;

View File

@@ -567,6 +567,10 @@ rrc_mac_config_req(
return(0);
}
// Assign the new c-rnti in the UE context (during HO)
void rrc_mac_get_new_crnti(protocol_ctxt_t* ctxt_pP,uint8_t eNB_index){
PROTOCOL_CTXT_SET_BY_MODULE_ID(ctxt_pP, ctxt_pP->module_id, ENB_FLAG_NO,UE_mac_inst[ctxt_pP->module_id].crnti, ctxt_pP->frame, ctxt_pP->subframe, eNB_index);
}
#ifdef LOCALIZATION
//------------------------------------------------------------------------------
double

View File

@@ -298,12 +298,17 @@ printf("MAC: new UE id %d rnti %x\n", i, rntiP);
return(UE_id);
}
printf("MAC: cannot add new UE for rnti %x\n", rntiP);
printf("MAC: cannot add new UE for rnti %x\n", rntiP);
LOG_E(MAC,"error in add_new_ue(), could not find space in UE_list, Dumping UE list\n");
dump_ue_list(UE_list,0);
return(-1);
}
int add_new_ue_phy(module_id_t mod_idP, rnti_t rntiP){
int ret = mac_xface->add_ue(rntiP,PHY_vars_eNB_g[mod_idP][0]);
return (ret > 0) ? 0: -1;
}
//------------------------------------------------------------------------------
int rrc_mac_remove_ue(module_id_t mod_idP,rnti_t rntiP)
//------------------------------------------------------------------------------

View File

@@ -429,6 +429,8 @@ void mac_top_cleanup(void)
free(eNB_mac_inst);
}
rrc_top_cleanup();
free( Mac_rlc_xface);
}
@@ -474,6 +476,7 @@ int l2_init(LTE_DL_FRAME_PARMS *frame_parms,int eMBMS_active, char *uecap_xer,ui
mac_xface->ra_failed = ra_failed;
mac_xface->ra_succeeded = ra_succeeded;
mac_xface->mac_phy_remove_ue = mac_phy_remove_ue;
mac_xface->add_ue = add_ue;
LOG_I(MAC,"[MAIN] init UE MAC functions \n");
mac_xface->ue_decode_si = ue_decode_si;
@@ -500,6 +503,7 @@ int l2_init(LTE_DL_FRAME_PARMS *frame_parms,int eMBMS_active, char *uecap_xer,ui
mac_xface->get_RSRQ = get_RSRQ;
mac_xface->get_RSSI = get_RSSI;
mac_xface->get_n_adj_cells = get_n_adj_cells;
mac_xface->get_nid_cell = get_nid_cell;
mac_xface->get_rx_total_gain_dB = get_rx_total_gain_dB;
mac_xface->get_Po_NOMINAL_PUSCH = get_Po_NOMINAL_PUSCH;
mac_xface->get_num_prach_tdd = get_num_prach_tdd;

View File

@@ -466,7 +466,8 @@ ue_process_rar(
uint8_t * const dlsch_buffer,
rnti_t * const t_crnti,
const uint8_t preamble_index,
uint8_t* selected_rar_buffer
uint8_t* selected_rar_buffer,
uint8_t prach_state
);
@@ -521,6 +522,7 @@ uint8_t *parse_ulsch_header(uint8_t *mac_header,
int l2_init(LTE_DL_FRAME_PARMS *frame_parms,int eMBMS_active, char *uecap_xer, uint8_t cba_group_active, uint8_t HO_active);
int mac_init(void);
int add_new_ue(module_id_t Mod_id, int CC_id, rnti_t rnti,int harq_pid);
int add_new_ue_phy(module_id_t Mod_id, rnti_t rnti);
int rrc_mac_remove_ue(module_id_t Mod_id, rnti_t rntiP);
@@ -666,7 +668,7 @@ void update_phr (module_id_t module_idP,int CC_id);
\param[in] Mod_id Instance index of UE
\param[in] eNB_id Index of eNB
*/
void Msg3_tx(module_id_t module_idP,uint8_t CC_id,frame_t frameP,uint8_t eNB_id);
void Msg3_tx(module_id_t module_idP,uint8_t CC_id,frame_t frameP,uint8_t eNB_id,UE_MODE_t UE_mode);
/*! \brief Function to indicate the transmission of msg1/rach

View File

@@ -39,6 +39,7 @@
#include "COMMON/mac_rrc_primitives.h"
#include "RRC/LITE/extern.h"
#include "RRC/L2_INTERFACE/openair_rrc_L2_interface.h"
#include "RRC/LITE/proto.h"
#include "UTIL/LOG/log.h"
#include "UTIL/OPT/opt.h"
#include "OCG.h"
@@ -280,7 +281,7 @@ void Msg1_tx(module_id_t module_idP,uint8_t CC_id,frame_t frameP, uint8_t eNB_id
}
void Msg3_tx(module_id_t module_idP,uint8_t CC_id,frame_t frameP, uint8_t eNB_id)
void Msg3_tx(module_id_t module_idP,uint8_t CC_id,frame_t frameP, uint8_t eNB_id, UE_MODE_t UE_mode)
{
if (CC_id>0) {
@@ -292,8 +293,13 @@ void Msg3_tx(module_id_t module_idP,uint8_t CC_id,frame_t frameP, uint8_t eNB_id
// start contention resolution timer
LOG_D(MAC,"[UE %d][RAPROC] Frame %d : Msg3_tx: Setting contention resolution timer\n",module_idP,frameP);
UE_mac_inst[module_idP].RA_contention_resolution_cnt = 0;
UE_mac_inst[module_idP].RA_contention_resolution_timer_active = 1;
if(UE_mode==PUSCH){
// Call rrc to update the HO status
rrc_lite_ue_update_ho_status (module_idP);
}
else{
UE_mac_inst[module_idP].RA_contention_resolution_timer_active = 1;
}
if (opt_enabled) { // msg3
trace_pdu(0, &UE_mac_inst[module_idP].CCCH_pdu.payload[0], UE_mac_inst[module_idP].RA_Msg3_size,
module_idP, 3, UE_mac_inst[module_idP].crnti, UE_mac_inst[module_idP].txFrame, UE_mac_inst[module_idP].txSubframe, 0, 0);
@@ -398,6 +404,7 @@ PRACH_RESOURCES_t *ue_get_rach(module_id_t module_idP,int CC_id,frame_t frameP,
DCCH,
6);
if (rlc_status.bytes_in_buffer == 0) abort();
if (UE_mac_inst[module_idP].crnti_before_ho)
LOG_D(MAC,
"[UE %d] Frame %d : UL-DCCH -> ULSCH, HO RRCConnectionReconfigurationComplete (%x, %x), RRC message has %d bytes to send throug PRACH (mac header len %d)\n",
@@ -410,7 +417,7 @@ PRACH_RESOURCES_t *ue_get_rach(module_id_t module_idP,int CC_id,frame_t frameP,
eNB_indexP, frameP,ENB_FLAG_NO, MBMS_FLAG_NO,
DCCH,
6, //not used
(char *)&ulsch_buff[0]);
(char *)&ulsch_buff[0]); // (char *)&ulsch_buff[4]);
LOG_D(MAC,"[UE %d] TX Got %d bytes for DCCH\n",module_idP,sdu_lengths[0]);
update_bsr(module_idP, frameP, subframeP,eNB_indexP);
@@ -444,6 +451,7 @@ PRACH_RESOURCES_t *ue_get_rach(module_id_t module_idP,int CC_id,frame_t frameP,
UE_mac_inst[module_idP].RA_backoff_subframe = subframeP;
// Fill in preamble and PRACH resource
get_prach_resources(module_idP,CC_id,eNB_indexP,subframeP,1,NULL);
lcid = DCCH;
generate_ulsch_header((uint8_t*)ulsch_buff, // mac header
1, // num sdus
0, // short pading
@@ -455,7 +463,15 @@ PRACH_RESOURCES_t *ue_get_rach(module_id_t module_idP,int CC_id,frame_t frameP,
NULL, // short bsr
NULL, // long_bsr
0); //post_padding
#ifdef DEBUG_ULSCH
printf("length %d\n", sdu_lengths[0]);
{
int i;
for (i = 0; i < 13; i++)
printf("%2.2x ", (unsigned int)ulsch_buff[i]);
printf("\n");
}
#endif
return(&UE_mac_inst[module_idP].RA_prach_resources);
}
} else { // RACH is active

View File

@@ -137,7 +137,8 @@ ue_process_rar(
uint8_t* const dlsch_buffer,
rnti_t* const t_crnti,
const uint8_t preamble_index,
uint8_t* selected_rar_buffer // output argument for storing the selected RAR header and RAR payload
uint8_t* selected_rar_buffer,
uint8_t prach_state// output argument for storing the selected RAR header and RAR payload
)
//------------------------------------------------------------------------------
{
@@ -210,9 +211,12 @@ ue_process_rar(
}
if (preamble_index == rarh->RAPID) {
*t_crnti = (uint16_t)rar[5]+(rar[4]<<8);//rar->t_crnti;
UE_mac_inst[module_idP].crnti = *t_crnti;//rar->t_crnti;
//return(rar->Timing_Advance_Command);
if(prach_state==0){
*t_crnti = (uint16_t)rar[5]+(rar[4]<<8);//rar->t_crnti;
UE_mac_inst[module_idP].crnti = *t_crnti;//rar->t_crnti;
LOG_D(MAC,"Update the c-rnti (not HO case)\n");
}
//return(rar->Timing_Advance_Command);
ret = ((((uint16_t)(rar[0]&0x7f))<<4) + (rar[1]>>4));
} else {
UE_mac_inst[module_idP].crnti=0;

View File

@@ -137,6 +137,9 @@ typedef struct {
int16_t (*estimate_ue_tx_power)(uint32_t tbs, uint32_t nb_rb, uint8_t control_only, lte_prefix_type_t ncp, uint8_t use_srs);
int (*mac_phy_remove_ue)(module_id_t Mod_idP,rnti_t rntiP);
int (*add_ue)(int16_t rnti, PHY_VARS_eNB *eNB);
/// UE functions
/// reset the ue phy
@@ -170,7 +173,7 @@ typedef struct {
PRACH_RESOURCES_t* (*ue_get_rach)(module_id_t Mod_id,int CC_id,frame_t frameP,uint8_t Msg3_flag,sub_frame_t subframe);
/// Process Random-Access Response
uint16_t (*ue_process_rar)(module_id_t Mod_id,int CC_id,frame_t frameP, uint16_t ra_rnti, uint8_t *dlsch_buffer, uint16_t *t_crnti,uint8_t preamble_index, uint8_t* selected_rar_buffer);
uint16_t (*ue_process_rar)(module_id_t Mod_id,int CC_id,frame_t frameP, uint16_t ra_rnti, uint8_t *dlsch_buffer, uint16_t *t_crnti,uint8_t preamble_index, uint8_t* selected_rar_buffer, uint8_t prach_state);
/// Get SR payload (0,1) from UE MAC
uint32_t (*ue_get_SR)(module_id_t Mod_id,int CC_id,frame_t frameP,uint8_t eNB_id,rnti_t rnti,sub_frame_t subframe);
@@ -216,7 +219,7 @@ typedef struct {
void (*phy_config_afterHO_ue)(module_id_t Mod_id,uint8_t CC_id,uint8_t CH_index,
MobilityControlInfo_t *mobilityControlInfo,
uint8_t ho_failed);
void (*phy_config_ue_state_ho)(uint8_t Mod_id,uint8_t CC_id,uint16_t rnti);
/// Function to indicate failure of contention resolution or RA procedure
void (*ra_failed)(module_id_t Mod_id, uint8_t CC_id,uint8_t eNB_index);
@@ -227,7 +230,7 @@ typedef struct {
void (*Msg1_transmitted)(module_id_t Mod_id,uint8_t CC_id,frame_t frameP,uint8_t eNB_id);
/// Function to indicate Msg3 transmission/retransmission which initiates/reset Contention Resolution Timer
void (*Msg3_transmitted)(module_id_t Mod_id,uint8_t CC_id,frame_t frameP,uint8_t eNB_id);
void (*Msg3_transmitted)(module_id_t Mod_id,uint8_t CC_id,frame_t frameP,uint8_t eNB_id, UE_MODE_t UE_mode);
/// Function to pass inter-cell measurement parameters to PHY (cell Ids)
void (*phy_config_meas_ue)(module_id_t Mod_id,uint8_t CC_id,uint8_t eNB_index,uint8_t n_adj_cells,uint32_t *adj_cell_id);
@@ -296,6 +299,9 @@ typedef struct {
/// Function for UE MAC to set the layer3 filtered RSRP/RSRQ measurements
uint8_t (*set_RSRQ_filtered)(uint8_t Mod_id,uint8_t CC_id,uint8_t eNB_index,float rsrp);
// Function to get the Nid cell
uint16_t (*get_nid_cell) (uint8_t Mod_id,uint8_t CC_id);
/// Function for UE/eNB MAC to retrieve number of PRACH in TDD
uint8_t (*get_num_prach_tdd)(LTE_DL_FRAME_PARMS *frame_parms);

View File

@@ -74,6 +74,7 @@
#include "rrc_L2_proto.h"
#else
#include "RRC/LITE/defs.h"
#include "RRC/LITE/proto.h"
#endif //CELLULAR
#include "COMMON/mac_rrc_primitives.h"
#include "openair_rrc_L2_interface.h"
@@ -280,3 +281,7 @@ openair_rrc_eNB_init(
{
return openair_rrc_lite_eNB_init(module_idP);
}
//------------------------------------------------------------------------------
void mac_rrc_ue_update_ho_status(module_id_t module_idP){
return (rrc_lite_ue_update_ho_status(module_idP));
}

View File

@@ -130,4 +130,7 @@ void mac_in_sync_ind(
const frame_t frameP,
const uint16_t eNB_indexP);
void mac_rrc_ue_update_ho_status(
module_id_t module_idP);
#endif

View File

@@ -40,6 +40,7 @@
#include "rrc_eNB_UE_context.h"
#include "pdcp.h"
#include "msc.h"
#include "proto.h"
#ifdef PHY_EMUL
#include "SIMULATION/simulation_defs.h"
@@ -787,3 +788,13 @@ int mac_ue_ccch_success_ind(module_id_t Mod_idP, uint8_t eNB_index)
#endif
return 0;
}
void rrc_lite_ue_update_ho_status(module_id_t Mod_idP){
// Handover is done
LOG_D(RRC,"Reset HO timer in RRC\n");
UE_rrc_inst[Mod_idP].Info[0].T304_active = 0; // Stop the timer (MAC procedure was successful)
//UE_rrc_inst[Mod_idP].HandoverInfoUe.measFlag = 0; // Stop the measurements
UE_mac_inst[Mod_idP].RA_active = 0;
UE_rrc_inst[Mod_idP].Info[0].State = RRC_RECONFIGURED;
LOG_D(RRC,"UE is updated: Mod_id: %d/State: %d\n",Mod_idP,UE_rrc_inst[Mod_idP].Info[0].State);
}

View File

@@ -113,7 +113,7 @@ extern uint8_t usim_test;
uint16_t two_tier_hexagonal_cellIds[7] = {0,1,2,4,5,7,8};
uint16_t two_tier_hexagonal_adjacent_cellIds[7][6] = {{1,2,4,5,7,8}, // CellId 0
{11,18,2,0,8,15}, // CellId 1
{11,0,2,18,8,15}, // CellId 1
{18,13,3,4,0,1}, // CellId 2
{2,3,14,6,5,0}, // CellId 4
{0,4,6,16,9,7}, // CellId 5
@@ -2494,6 +2494,12 @@ uint8_t do_MeasurementReport(uint8_t Mod_id, uint8_t *buffer,int measid,int phy_
measurementReport->criticalExtensions.choice.c1.choice.measurementReport_r8.measResults.measResultNeighCells->choice.measResultListEUTRA=*(measResultListEUTRA2);
#ifdef Rel10
measurementReport->criticalExtensions.choice.c1.choice.measurementReport_r8.measResults.ext1=NULL;
measurementReport->criticalExtensions.choice.c1.choice.measurementReport_r8.measResults.ext2=NULL;
#endif
enc_rval = uper_encode_to_buffer(&asn_DEF_UL_DCCH_Message,
(void*)&ul_dcch_msg,
buffer,

View File

@@ -216,7 +216,11 @@ typedef enum HO_STATE_e {
HO_MEASURMENT,
HO_PREPARE,
HO_CMD, // initiated by the src eNB
HO_COMPLETE // initiated by the target eNB
HO_COMPLETE, // initiated by the target eNB
HO_REQUEST,
HO_ACK,
HO_CONFIGURED,
} HO_STATE_t;
//#define NUMBER_OF_UE_MAX MAX_MOBILES_PER_RG
@@ -232,7 +236,7 @@ typedef enum HO_STATE_e {
#define PAYLOAD_SIZE_MAX 1024
#define RRC_BUF_SIZE 255
#define UNDEF_SECURITY_MODE 0xff
#define NO_SECURITY_MODE 0x20
#define NO_SECURITY_MODE 0x20 // 0x33
#define CBA_OFFSET 0xfff4
// #define NUM_MAX_CBA_GROUP 4 // in the platform_constants
@@ -275,7 +279,9 @@ typedef enum e_rab_satus_e {
E_RAB_STATUS_NEW,
E_RAB_STATUS_DONE, // from the eNB perspective
E_RAB_STATUS_ESTABLISHED, // get the reconfigurationcomplete form UE
E_RAB_STATUS_REESTABLISHED, // after HO
E_RAB_STATUS_FAILED,
E_RAB_STATUS_RELEASED
} e_rab_status_t;
typedef struct e_rab_param_s {
@@ -291,14 +297,17 @@ typedef struct e_rab_param_s {
typedef struct HANDOVER_INFO_s {
uint8_t ho_prepare;
uint8_t ho_complete;
HO_STATE_t state; //current state of handover
uint8_t modid_s; //module_idP of serving cell
uint8_t modid_t; //module_idP of target cell
uint8_t ueid_s; //UE index in serving cell
uint8_t ueid_t; //UE index in target cell
uint16_t ueid_s; //UE index in serving cell
uint16_t ueid_t; //UE index in target cell
AS_Config_t as_config; /* these two parameters are taken from 36.331 section 10.2.2: HandoverPreparationInformation-r8-IEs */
AS_Context_t as_context; /* They are mandatory for HO */
uint8_t buf[RRC_BUF_SIZE]; /* ASN.1 encoded handoverCommandMessage */
int size; /* size of above message in bytes */
/* TODO: to remove or not? */
int source_x2id;
} HANDOVER_INFO;
#define RRC_HEADER_SIZE_MAX 64
@@ -350,6 +359,15 @@ typedef struct HANDOVER_INFO_UE_s {
uint8_t measFlag;
} HANDOVER_INFO_UE;
typedef struct ue_gummei_s {
uint16_t mcc;
uint16_t mnc;
uint8_t mnc_len;
uint8_t mme_code;
uint16_t mme_group_id;
} ue_gummei_t;
typedef struct eNB_RRC_UE_s {
uint8_t primaryCC_id;
#if defined(Rel10) || defined(Rel14)
@@ -378,6 +396,9 @@ typedef struct eNB_RRC_UE_s {
#if defined(ENABLE_SECURITY)
/* KeNB as derived from KASME received from EPC */
uint8_t kenb[32];
int8_t kenb_ncc;
uint8_t nh[32];
int8_t nh_ncc;
#endif
/* Used integrity/ciphering algorithms */
CipheringAlgorithm_r12_t ciphering_algorithm;
@@ -401,15 +422,27 @@ typedef struct eNB_RRC_UE_s {
/* Information from S1AP initial_context_setup_req */
uint32_t eNB_ue_s1ap_id :24;
security_capabilities_t security_capabilities;
/* UE GUMMEI */
ue_gummei_t ue_gummei;
security_capabilities_t security_capabilities;
int next_hop_chain_count;
uint8_t next_security_key[SECURITY_KEY_LENGTH];
/* Total number of e_rab already setup in the list */
uint8_t setup_e_rabs;
/* 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_param_t e_rab[NB_RB_MAX];//[S1AP_MAX_E_RAB];
/* UE aggregate maximum bitrate */
ambr_t ue_ambr;
/* Number of e_rab to be released in the list */
uint8_t nb_e_rabs_tobereleased;
/* list of e_rab to be released by RRC layers */
uint8_t e_rabs_tobereleased[NB_RB_MAX];
// LG: For GTPV1 TUNNELS
uint32_t enb_gtp_teid[S1AP_MAX_E_RAB];
transport_layer_addr_t enb_gtp_addrs[S1AP_MAX_E_RAB];
@@ -491,7 +524,6 @@ typedef struct eNB_RRC_INST_s {
/// localization list for aggregated measurements from PHY
struct list loc_list;
#endif
//RRC configuration
#if defined(ENABLE_ITTI)
RrcConfigurationReq configuration;
@@ -583,11 +615,20 @@ typedef struct UE_RRC_INST_s {
#if defined(ENABLE_SECURITY)
/* KeNB as computed from parameters within USIM card */
uint8_t kenb[32];
uint8_t nh[32];
int8_t nh_ncc;
#endif
/* Used integrity/ciphering algorithms */
CipheringAlgorithm_r12_t ciphering_algorithm;
e_SecurityAlgorithmConfig__integrityProtAlgorithm integrity_algorithm;
// X2 HO stats and measurements
uint8_t rrc_ue_do_meas; // flag to start the meas only once
uint32_t rrc_ue_x2_src_enb_ms; // form connected to idle : include x2 delay
struct list rrc_ue_x2_src_enb_list;
uint32_t rrc_ue_x2_target_enb_ms; // from idle to connected
struct list rrc_ue_x2_target_enb_list;
} UE_RRC_INST;
#include "proto.h"

View File

@@ -254,6 +254,8 @@ rrc_eNB_generate_defaultRRCConnectionReconfiguration(
const uint8_t ho_state
);
int freq_to_arfcn10(int band, unsigned long freq);
void
rrc_eNB_generate_dedeicatedRRCConnectionReconfiguration(
const protocol_ctxt_t* const ctxt_pP,
@@ -287,6 +289,10 @@ rrc_eNB_generate_RRCConnectionReconfiguration_handover(
const uint32_t nas_length
);
void rrc_eNB_configure_rbs_handover(struct rrc_eNB_ue_context_s* ue_context_p, protocol_ctxt_t* const ctxt_pP);
void rrc_eNB_target_add_ue_handover(protocol_ctxt_t* const ctxt_pP);
//L2_interface.c
int8_t
mac_rrc_data_req(
@@ -381,6 +387,8 @@ ue_measurement_report_triggering(
const uint8_t eNB_index
);
void rrc_lite_ue_update_ho_status(module_id_t Mod_idP);
int
mac_eNB_get_rrc_status(
const module_id_t Mod_idP,
@@ -454,7 +462,7 @@ rrc_eNB_free_mem_UE_context(
void
rrc_eNB_free_UE(
const module_id_t enb_mod_idP,
const struct rrc_eNB_ue_context_s* const ue_context_pP
struct rrc_eNB_ue_context_s* ue_context_pP
);
long binary_search_int(int elements[], long numElem, int value);

View File

@@ -2101,6 +2101,7 @@ rrc_ue_process_mobilityControlInfo(
// rrc_rlc_config_req(ue_mod_idP+NB_eNB_INST,frameP,0,CONFIG_ACTION_ADD,ue_mod_idP+DCCH,SIGNALLING_RADIO_BEARER,Rlc_info_am_config);
// rrc_rlc_config_req(ue_mod_idP+NB_eNB_INST,frameP,0,CONFIG_ACTION_ADD,ue_mod_idP+DCCH1,SIGNALLING_RADIO_BEARER,Rlc_info_am_config);
// rrc_rlc_config_req(ue_mod_idP+NB_eNB_INST,frameP,0,CONFIG_ACTION_ADD,ue_mod_idP+DTCH,RADIO_ACCESS_BEARER,Rlc_info_um);
//rrc_mac_get_new_crnti(ctxt_pP,eNB_index);
UE_rrc_inst[ctxt_pP->module_id].Info[eNB_index].State = RRC_SI_RECEIVED;
}
@@ -2272,12 +2273,27 @@ rrc_ue_decode_dcch(
eNB_indexP);
if (target_eNB_index != 0xFF) {
UE_rrc_inst[ctxt_pP->module_id].rrc_ue_do_meas=0;
// Stop to measure (delay to the UE-->source)
//stop_meas(&UE_rrc_inst[ctxt_pP->module_id].rrc_ue_x2_src_enb);
//double t_x2_src_enb = (double)UE_rrc_inst[ctxt_pP->module_id].rrc_ue_x2_src_enb.p_time/get_cpu_freq_GHz()/1000.0;
double t_x2_src_enb = (double)ctxt_pP->frame*10+ctxt_pP->subframe - UE_rrc_inst[ctxt_pP->module_id].rrc_ue_x2_src_enb_ms;
push_front(&UE_rrc_inst[ctxt_pP->module_id].rrc_ue_x2_src_enb_list, t_x2_src_enb);
LOG_D(RRC,"UE-Stop-Time-debug: %d/%lf/%d/%d\n", ctxt_pP->frame*10+ctxt_pP->subframe, (double) UE_rrc_inst[ctxt_pP->module_id].rrc_ue_x2_src_enb_ms,ctxt_pP->frame,ctxt_pP->subframe);
// Start to measure (delay to the UE-->target)
//start_meas(&UE_rrc_inst[ctxt_pP->module_id].rrc_ue_x2_target_enb);
UE_rrc_inst[ctxt_pP->module_id].rrc_ue_x2_target_enb_ms = ctxt_pP->frame*10+ctxt_pP->subframe;
LOG_D(RRC,"UE-Start-Time-debug: %lf/%d/%d\n", (double) UE_rrc_inst[ctxt_pP->module_id].rrc_ue_x2_target_enb_ms,ctxt_pP->frame,ctxt_pP->subframe);
init_meas_timers(ctxt_pP); // Initialize handover measurement timers
rrc_ue_generate_RRCConnectionReconfigurationComplete(
ctxt_pP,
target_eNB_index,
dl_dcch_msg->message.choice.c1.choice.rrcConnectionReconfiguration.rrc_TransactionIdentifier);
UE_rrc_inst[ctxt_pP->module_id].Info[eNB_indexP].State = RRC_HO_EXECUTION;
UE_rrc_inst[ctxt_pP->module_id].Info[target_eNB_index].State = RRC_RECONFIGURED;
if(eNB_indexP!=target_eNB_index){
UE_rrc_inst[ctxt_pP->module_id].Info[target_eNB_index].State = RRC_RECONFIGURED;
}
LOG_I(RRC, "[UE %d] State = RRC_RECONFIGURED during HO (eNB %d)\n",
ctxt_pP->module_id, target_eNB_index);
#if defined(ENABLE_ITTI)
@@ -4016,10 +4032,18 @@ void ue_measurement_report_triggering(protocol_ctxt_t* const ctxt_pP, const uint
UE_rrc_inst[ctxt_pP->module_id].measReportList[i][j]->measId = UE_rrc_inst[ctxt_pP->module_id].MeasId[i][j]->measId;
UE_rrc_inst[ctxt_pP->module_id].measReportList[i][j]->numberOfReportsSent = 0;
rrc_ue_generate_MeasurementReport(
ctxt_pP,
eNB_index);
UE_rrc_inst[ctxt_pP->module_id].HandoverInfoUe.measFlag = 1;
if (UE_rrc_inst[ctxt_pP->module_id].rrc_ue_do_meas == 0 ){
UE_rrc_inst[ctxt_pP->module_id].rrc_ue_do_meas = 1;
// Start to measure (delay to the UE-->source)
//start_meas(&UE_rrc_inst[ctxt_pP->module_id].rrc_ue_x2_src_enb);
UE_rrc_inst[ctxt_pP->module_id].rrc_ue_x2_src_enb_ms = ctxt_pP->frame*10+ctxt_pP->subframe;
LOG_D(RRC,"UE-Start-Time-debug: %lf/%d/%d\n", (double) UE_rrc_inst[ctxt_pP->module_id].rrc_ue_x2_src_enb_ms,ctxt_pP->frame,ctxt_pP->subframe);
}
rrc_ue_generate_MeasurementReport(
ctxt_pP,
eNB_index);
//UE_rrc_inst[ctxt_pP->module_id].HandoverInfoUe.measFlag = 1;
LOG_I(RRC,"[UE %d] Frame %d: A3 event detected, state: %d \n",
ctxt_pP->module_id, ctxt_pP->frame, UE_rrc_inst[ctxt_pP->module_id].Info[0].State);
} else {
@@ -4101,10 +4125,10 @@ static uint8_t check_trigger_meas_event(
}
if (UE_rrc_inst->measTimer[ue_cnx_index][meas_index][tmp_offset] >= ttt) {
UE_rrc_inst->HandoverInfoUe.targetCellId = get_adjacent_cell_id(ue_mod_idP,tmp_offset); //WARNING!!!...check this!
UE_rrc_inst->HandoverInfoUe.targetCellId = get_adjacent_cell_id(currentCellIndex,tmp_offset); //WARNING!!!...check this!
LOG_D(RRC,"[UE %d] Frame %d eNB %d: Handover triggered: targetCellId: %ld currentCellId: %d eNB_offset: %d rsrp source: %3.1f rsrp target: %3.1f\n", \
ue_mod_idP, frameP, eNB_index,
UE_rrc_inst->HandoverInfoUe.targetCellId,ue_cnx_index,eNB_offset,
UE_rrc_inst->HandoverInfoUe.targetCellId,currentCellIndex,eNB_offset,
(dB_fixed_times10(UE_rrc_inst[ue_mod_idP].rsrp_db[0])/10.0)-mac_xface->get_rx_total_gain_dB(ue_mod_idP,0)-dB_fixed(mac_xface->frame_parms->N_RB_DL*12),
(dB_fixed_times10(UE_rrc_inst[ue_mod_idP].rsrp_db[eNB_offset])/10.0)-mac_xface->get_rx_total_gain_dB(ue_mod_idP,
0)-dB_fixed(mac_xface->frame_parms->N_RB_DL*12));
@@ -4121,6 +4145,18 @@ static uint8_t check_trigger_meas_event(
return 0;
}
// Initialize the handover measurement timers
void init_meas_timers(const protocol_ctxt_t* const ctxt_pP){
uint8_t i,j,eNB_offset;
for(i=0 ; i<NB_CNX_UE ; i++) {
for(j=0 ; j<MAX_MEAS_ID ; j++) {
for (eNB_offset = 0; eNB_offset<1+mac_xface->get_n_adj_cells(ctxt_pP->module_id,0); eNB_offset++) {
UE_rrc_inst->measTimer[i][j][eNB_offset]=0;
}
}
}
}
#if defined(Rel10) || defined(Rel14)
//-----------------------------------------------------------------------------

View File

@@ -507,6 +507,7 @@ rrc_rx_tx(
if((UE_rrc_inst[ctxt_pP->module_id].Info[enb_indexP].State == RRC_HO_EXECUTION) &&
(UE_rrc_inst[ctxt_pP->module_id].HandoverInfoUe.targetCellId != 0xFF)) {
UE_rrc_inst[ctxt_pP->module_id].Srb0[enb_indexP].Tx_buffer.payload_size = 0;
UE_rrc_inst[ctxt_pP->module_id].Info[enb_indexP].State= RRC_IDLE;
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_RRC_RX_TX,VCD_FUNCTION_OUT);
return(RRC_HO_STARTED);

View File

@@ -790,7 +790,8 @@ rrc_eNB_free_mem_UE_context(
//-----------------------------------------------------------------------------
// should be called when UE is lost by eNB
void
rrc_eNB_free_UE(const module_id_t enb_mod_idP,const struct rrc_eNB_ue_context_s* const ue_context_pP)
rrc_eNB_free_UE(const module_id_t enb_mod_idP,
struct rrc_eNB_ue_context_s* ue_context_pP)
//-----------------------------------------------------------------------------
{
@@ -831,6 +832,7 @@ rrc_eNB_free_UE(const module_id_t enb_mod_idP,const struct rrc_eNB_ue_context_s*
oai_emulation.info.eNB_ue_module_id_to_rnti[enb_mod_idP][ue_module_id] = NOT_A_RNTI;
#endif
#endif
ue_context_pP->ue_context.Status = RRC_IDLE;
rrc_mac_remove_ue(enb_mod_idP,rnti);
rrc_rlc_remove_ue(&ctxt);
@@ -2158,7 +2160,113 @@ rrc_eNB_generate_defaultRRCConnectionReconfiguration(const protocol_ctxt_t* cons
PDCP_TRANSMISSION_MODE_CONTROL);
}
typedef enum { BAND_TYPE_FDD, BAND_TYPE_TDD } band_type;
typedef struct {
band_type t;
int band;
unsigned long ul_minfreq, ul_maxfreq;
unsigned long dl_minfreq, dl_maxfreq;
} band_freq;
static band_freq bands[] = {
{ BAND_TYPE_FDD, 1, 1920000000UL, 1980000000UL, 2110000000UL, 2170000000UL },
{ BAND_TYPE_FDD, 2, 1850000000UL, 1910000000UL, 1930000000UL, 1990000000UL },
{ BAND_TYPE_FDD, 3, 1710000000UL, 1785000000UL, 1805000000UL, 1880000000UL },
{ BAND_TYPE_FDD, 4, 1710000000UL, 1755000000UL, 2110000000UL, 2155000000UL },
{ BAND_TYPE_FDD, 5, 824000000UL, 849000000UL, 869000000UL, 894000000UL },
/* to remove? */{ BAND_TYPE_FDD, 6, 830000000UL, 840000000UL, 875000000UL, 885000000UL },
{ BAND_TYPE_FDD, 7, 2500000000UL, 2570000000UL, 2620000000UL, 2690000000UL },
{ BAND_TYPE_FDD, 8, 880000000UL, 915000000UL, 925000000UL, 960000000UL },
{ BAND_TYPE_FDD, 9, 1749900000UL, 1784900000UL, 1844900000UL, 1879900000UL },
{ BAND_TYPE_FDD, 10, 1710000000UL, 1770000000UL, 2110000000UL, 2170000000UL },
{ BAND_TYPE_FDD, 11, 1427900000UL, 1447900000UL, 1475900000UL, 1495900000UL },
{ BAND_TYPE_FDD, 12, 699000000UL, 716000000UL, 729000000UL, 746000000UL },
{ BAND_TYPE_FDD, 13, 777000000UL, 787000000UL, 746000000UL, 756000000UL },
{ BAND_TYPE_FDD, 14, 788000000UL, 798000000UL, 758000000UL, 768000000UL },
{ BAND_TYPE_FDD, 17, 704000000UL, 716000000UL, 734000000UL, 746000000UL },
{ BAND_TYPE_FDD, 18, 815000000UL, 830000000UL, 860000000UL, 875000000UL },
{ BAND_TYPE_FDD, 19, 830000000UL, 845000000UL, 875000000UL, 890000000UL },
{ BAND_TYPE_FDD, 20, 832000000UL, 862000000UL, 791000000UL, 821000000UL },
{ BAND_TYPE_FDD, 21, 1447900000UL, 1462900000UL, 1495900000UL, 1510900000UL },
{ BAND_TYPE_FDD, 22, 3410000000UL, 3490000000UL, 3510000000UL, 3590000000UL },
{ BAND_TYPE_FDD, 23, 2000000000UL, 2020000000UL, 2180000000UL, 2200000000UL },
{ BAND_TYPE_FDD, 24, 1626500000UL, 1660500000UL, 1525000000UL, 1559000000UL },
{ BAND_TYPE_FDD, 25, 1850000000UL, 1915000000UL, 1930000000UL, 1995000000UL },
{ BAND_TYPE_TDD, 33, 1900000000UL, 1920000000UL, 1900000000UL, 1920000000UL },
{ BAND_TYPE_TDD, 34, 2010000000UL, 2025000000UL, 2010000000UL, 2025000000UL },
{ BAND_TYPE_TDD, 35, 1850000000UL, 1910000000UL, 1850000000UL, 1910000000UL },
{ BAND_TYPE_TDD, 36, 1930000000UL, 1990000000UL, 1930000000UL, 1990000000UL },
{ BAND_TYPE_TDD, 37, 1910000000UL, 1930000000UL, 1910000000UL, 1930000000UL },
{ BAND_TYPE_TDD, 38, 2570000000UL, 2620000000UL, 2570000000UL, 2620000000UL },
{ BAND_TYPE_TDD, 39, 1880000000UL, 1920000000UL, 1880000000UL, 1920000000UL },
{ BAND_TYPE_TDD, 40, 2300000000UL, 2400000000UL, 2300000000UL, 2400000000UL },
{ BAND_TYPE_TDD, 41, 2496000000UL, 2690000000UL, 2496000000UL, 2690000000UL },
{ BAND_TYPE_TDD, 42, 3400000000UL, 3600000000UL, 3400000000UL, 3600000000UL },
{ BAND_TYPE_TDD, 43, 3600000000UL, 3800000000UL, 3600000000UL, 3800000000UL },
};
typedef struct {
int band;
unsigned long dl_flow;
int dl_off;
int dl_offmin, dl_offmax;
unsigned long ul_flow;
int ul_off;
int ul_offmin, ul_offmax;
} earfcn;
static earfcn earfcn_table[] = {
{ 1, 2110000000UL, 0, 0, 599, 1920000000UL, 18000, 18000, 18599 },
{ 2, 1930000000UL, 600, 600, 1199, 1850000000UL, 18600, 18600, 19199 },
{ 3, 1805000000UL, 1200, 1200, 1949, 1710000000UL, 19200, 19200, 19949 },
{ 4, 2110000000UL, 1950, 1950, 2399, 1710000000UL, 19950, 19950, 20399 },
{ 5, 869000000UL, 2400, 2400, 2649, 824000000UL, 20400, 20400, 20649 },
{ 6, 875000000UL, 2650, 2650, 2749, 830000000UL, 20650, 20650, 20749 },
{ 7, 2620000000UL, 2750, 2750, 3449, 2500000000UL, 20750, 20750, 21449 },
{ 8, 925000000UL, 3450, 3450, 3799, 880000000UL, 21450, 21450, 21799 },
{ 9, 1844900000UL, 3800, 3800, 4149, 1749900000UL, 21800, 21800, 22149 },
{ 10, 2110000000UL, 4150, 4150, 4749, 1710000000UL, 22150, 22150, 22749 },
{ 11, 1475900000UL, 4750, 4750, 4949, 1427900000UL, 22750, 22750, 22949 },
{ 12, 729000000UL, 5010, 5010, 5179, 699000000UL, 23010, 23010, 23179 },
{ 13, 746000000UL, 5180, 5180, 5279, 777000000UL, 23180, 23180, 23279 },
{ 14, 758000000UL, 5280, 5280, 5379, 788000000UL, 23280, 23280, 23379 },
{ 17, 734000000UL, 5730, 5730, 5849, 704000000UL, 23730, 23730, 23849 },
{ 18, 860000000UL, 5850, 5850, 5999, 815000000UL, 23850, 23850, 23999 },
{ 19, 875000000UL, 6000, 6000, 6149, 830000000UL, 24000, 24000, 24149 },
{ 20, 791000000UL, 6150, 6150, 6449, 832000000UL, 24150, 24150, 24449 },
{ 21, 1495900000UL, 6450, 6450, 6599, 1447900000UL, 24450, 24450, 24599 },
{ 22, 3510000000UL, 6600, 6600, 7399, 3410000000UL, 24600, 24600, 25399 },
{ 23, 2180000000UL, 7500, 7500, 7699, 2000000000UL, 25500, 25500, 25699 },
{ 24, 1525000000UL, 7700, 7700, 8039, 1626500000UL, 25700, 25700, 26039 },
{ 25, 1930000000UL, 8040, 8040, 8689, 1850000000UL, 26040, 26040, 26689 },
{ 33, 1900000000UL, 36000, 36000, 36199, 1900000000UL, 36000, 36000, 36199 },
{ 34, 2010000000UL, 36200, 36200, 36349, 2010000000UL, 36200, 36200, 36349 },
{ 35, 1850000000UL, 36350, 36350, 36949, 1850000000UL, 36350, 36350, 36949 },
{ 36, 1930000000UL, 36950, 36950, 37549, 1930000000UL, 36950, 36950, 37549 },
{ 37, 1910000000UL, 37550, 37550, 37749, 1910000000UL, 37550, 37550, 37749 },
{ 38, 2570000000UL, 37750, 37750, 38249, 2570000000UL, 37750, 37750, 38249 },
{ 39, 1880000000UL, 38250, 38250, 38649, 1880000000UL, 38250, 38250, 38649 },
{ 40, 2300000000UL, 38650, 38650, 39649, 2300000000UL, 38650, 38650, 39649 },
{ 41, 2496000000UL, 39650, 39650, 41589, 2496000000UL, 39650, 39650, 41589 },
{ 42, 3400000000UL, 41590, 41590, 43589, 3400000000UL, 41590, 41590, 43589 },
{ 43, 3600000000UL, 43590, 43590, 45589, 3600000000UL, 43590, 43590, 45589 },
};
int freq_to_arfcn10(int band, unsigned long freq)
{
int N = sizeof(earfcn_table) / sizeof(earfcn_table[0]);
int i;
for (i = 0; i < N; i++) if (bands[i].band == band) break;
if (i == N) return -1;
if (!(bands[i].dl_minfreq < freq && freq < bands[i].dl_maxfreq))
return -1;
return (freq - earfcn_table[i].dl_flow) / 100000UL + earfcn_table[i].dl_off;
}
//-----------------------------------------------------------------------------
int
@@ -2271,7 +2379,81 @@ rrc_eNB_process_MeasurementReport(
LOG_I(RRC, "RSRP of Source %ld\n", measResults2->measResultServCell.rsrpResult);
LOG_I(RRC, "RSRQ of Source %ld\n", measResults2->measResultServCell.rsrqResult);
#endif
/* algorithm to decide whether to trigger HO or not */
/* if the UE is not in handover mode, start handover procedure */
if (ue_context_pP->ue_context.Status != RRC_HO_EXECUTION) {
MessageDef *msg;
ue_context_pP->ue_context.handover_info = CALLOC(1, sizeof(*(ue_context_pP->ue_context.handover_info)));
ue_context_pP->ue_context.Status = RRC_HO_EXECUTION;
ue_context_pP->ue_context.handover_info->state = HO_REQUEST;
rrc_eNB_generate_HandoverPreparationInformation(ctxt_pP,
ue_context_pP,
measResults2->measResultNeighCells->choice.
measResultListEUTRA.list.array[0]->physCellId);
msg = itti_alloc_new_message(TASK_RRC_ENB, X2AP_HANDOVER_REQ);
X2AP_HANDOVER_REQ(msg).source_rnti = ctxt_pP->rnti;
X2AP_HANDOVER_REQ(msg).old_eNB_ue_s1ap_id=ue_context_pP->ue_context.eNB_ue_s1ap_id;
X2AP_HANDOVER_REQ(msg).target_physCellId = measResults2->measResultNeighCells->choice.
measResultListEUTRA.list.array[0]->physCellId;
X2AP_HANDOVER_REQ(msg).ue_gummei.mcc=ue_context_pP->ue_context.ue_gummei.mcc;
X2AP_HANDOVER_REQ(msg).ue_gummei.mnc=ue_context_pP->ue_context.ue_gummei.mnc;
X2AP_HANDOVER_REQ(msg).ue_gummei.mnc_len=ue_context_pP->ue_context.ue_gummei.mnc_len;
X2AP_HANDOVER_REQ(msg).ue_gummei.mme_code=ue_context_pP->ue_context.ue_gummei.mme_code;
X2AP_HANDOVER_REQ(msg).ue_gummei.mme_group_id=ue_context_pP->ue_context.ue_gummei.mme_group_id;
// Don't know how to get this ID?
//X2AP_HANDOVER_REQ(msg).mme_ue_s1ap_id=0;
X2AP_HANDOVER_REQ(msg).security_capabilities=ue_context_pP->ue_context.security_capabilities;
memcpy (X2AP_HANDOVER_REQ(msg).kenb,
ue_context_pP->ue_context.kenb,
32);
X2AP_HANDOVER_REQ(msg).kenb_ncc= ue_context_pP->ue_context.kenb_ncc;
X2AP_HANDOVER_REQ(msg).ue_ambr=ue_context_pP->ue_context.ue_ambr;
// to be done
// X2AP_HANDOVER_REQ(msg).e_rabs_tobesetu=;
/* TODO: don't do that, X2AP should find the target by itself */
X2AP_HANDOVER_REQ(msg).target_mod_id = get_adjacent_cell_mod_id(X2AP_HANDOVER_REQ(msg).target_physCellId);
LOG_I(RRC,
"[eNB %d] Frame %d: potential handover preparation: store the information in an intermediate structure in case of failure\n",
ctxt_pP->module_id, ctxt_pP->frame);
// store the information in an intermediate structure for Hanodver management
//rrc_inst->handover_info.as_config.sourceRadioResourceConfig.srb_ToAddModList = CALLOC(1,sizeof());
// ue_context_pP->ue_context.handover_info = CALLOC(1, sizeof(*(ue_context_pP->ue_context.handover_info)));
//memcpy((void *)rrc_inst->handover_info[ue_mod_idP]->as_config.sourceRadioResourceConfig.srb_ToAddModList,(void *)SRB_list,sizeof(SRB_ToAddModList_t));
ue_context_pP->ue_context.handover_info->as_config.sourceRadioResourceConfig.srb_ToAddModList = ue_context_pP->ue_context.SRB_configList; //SRB_configList2;
//memcpy((void *)rrc_inst->handover_info[ue_mod_idP]->as_config.sourceRadioResourceConfig.drb_ToAddModList,(void *)DRB_list,sizeof(DRB_ToAddModList_t));
ue_context_pP->ue_context.handover_info->as_config.sourceRadioResourceConfig.drb_ToAddModList = ue_context_pP->ue_context.DRB_configList; //*DRB_configList;
ue_context_pP->ue_context.handover_info->as_config.sourceRadioResourceConfig.drb_ToReleaseList = NULL;
ue_context_pP->ue_context.handover_info->as_config.sourceRadioResourceConfig.mac_MainConfig =
CALLOC(1, sizeof(*ue_context_pP->ue_context.handover_info->as_config.sourceRadioResourceConfig.mac_MainConfig));
memcpy((void*)ue_context_pP->ue_context.handover_info->as_config.sourceRadioResourceConfig.mac_MainConfig,
(void *)ue_context_pP->ue_context.mac_MainConfig /* mac_MainConfig */, sizeof(MAC_MainConfig_t));
ue_context_pP->ue_context.handover_info->as_config.sourceRadioResourceConfig.physicalConfigDedicated =
CALLOC(1, sizeof(PhysicalConfigDedicated_t));
memcpy((void*)ue_context_pP->ue_context.handover_info->as_config.sourceRadioResourceConfig.physicalConfigDedicated,
(void*)ue_context_pP->ue_context.physicalConfigDedicated, sizeof(PhysicalConfigDedicated_t));
ue_context_pP->ue_context.handover_info->as_config.sourceRadioResourceConfig.sps_Config = NULL;
//memcpy((void *)rrc_inst->handover_info[ue_mod_idP]->as_config.sourceRadioResourceConfig.sps_Config,(void *)rrc_inst->sps_Config[ue_mod_idP],sizeof(SPS_Config_t));
itti_send_msg_to_task(TASK_X2AP, ENB_MODULE_ID_TO_INSTANCE(ctxt_pP->module_id), msg);
} else {
LOG_D(RRC, "[eNB %d] Frame %d: Ignoring MeasReport from UE %x as Handover is in progress... \n", ctxt_pP->module_id, ctxt_pP->frame,
ctxt_pP->rnti);
}
#if 0
if (ue_context_pP->ue_context.handover_info->ho_prepare != 0xF0) {
rrc_eNB_generate_HandoverPreparationInformation(ctxt_pP,
ue_context_pP,
@@ -2281,6 +2463,7 @@ rrc_eNB_process_MeasurementReport(
LOG_D(RRC, "[eNB %d] Frame %d: Ignoring MeasReport from UE %x as Handover is in progress... \n", ctxt_pP->module_id, ctxt_pP->frame,
ctxt_pP->rnti);
}
#endif
//Look for IP address of the target eNB
//Send Handover Request -> target eNB
@@ -2309,7 +2492,7 @@ rrc_eNB_generate_HandoverPreparationInformation(
{
struct rrc_eNB_ue_context_s* ue_context_target_p = NULL;
//uint8_t UE_id_target = -1;
uint8_t mod_id_target = get_adjacent_cell_mod_id(targetPhyId);
uint8_t mod_id_target = get_adjacent_cell_mod_id(targetPhyId); /*simulation related var*/
HANDOVER_INFO *handoverInfo = CALLOC(1, sizeof(*handoverInfo));
/*
uint8_t buffer[100];
@@ -2327,7 +2510,7 @@ rrc_eNB_generate_HandoverPreparationInformation(
memcpy((void *)&handoverInfo->as_config.sourceMasterInformationBlock,
(void*)&eNB_rrc_inst[ctxt_pP->module_id].carrier[0] /* CROUX TBC */.mib, sizeof(MasterInformationBlock_t));
memcpy((void *)&handoverInfo->as_config.sourceMeasConfig,
(void*)ue_context_pP->ue_context.measConfig, sizeof(MeasConfig_t));
(void*)&ue_context_pP->ue_context.measConfig, sizeof(MeasConfig_t));
// FIXME handoverInfo not used...
free( handoverInfo );
@@ -2352,6 +2535,7 @@ rrc_eNB_generate_HandoverPreparationInformation(
ue_context_pP->ue_context.handover_info->ho_prepare = 0xFF; //0xF0;
ue_context_pP->ue_context.handover_info->ho_complete = 0;
/* simulation related logic */
if (mod_id_target != 0xFF) {
//UE_id_target = rrc_find_free_ue_index(modid_target);
ue_context_target_p =
@@ -2403,6 +2587,51 @@ rrc_eNB_generate_HandoverPreparationInformation(
}
}
static int global_rnti;
void rrc_eNB_process_handoverPreparationInformation(int mod_id, x2ap_handover_req_t *m)
{
struct rrc_eNB_ue_context_s* ue_context_target_p = NULL;
/* TODO: get proper UE rnti */
int rnti = taus() & 0xffff;
global_rnti = rnti;
ue_context_target_p = rrc_eNB_get_ue_context(&eNB_rrc_inst[mod_id], rnti);
if (ue_context_target_p != NULL) {
LOG_E(RRC, "\nError in obtaining free UE id in target eNB for handover \n");
return;
}
ue_context_target_p = rrc_eNB_allocate_new_UE_context(&eNB_rrc_inst[mod_id]);
if (ue_context_target_p == NULL) {
LOG_E(RRC, "Cannot create new UE context\n");
return;
}
ue_context_target_p->ue_id_rnti = rnti;
ue_context_target_p->ue_context.rnti = rnti;
RB_INSERT(rrc_ue_tree_s, &eNB_rrc_inst[mod_id].rrc_ue_head, ue_context_target_p);
LOG_D(RRC, "eNB %d: Created new UE context uid %u\n", mod_id, ue_context_target_p->local_uid);
ue_context_target_p->ue_context.handover_info = CALLOC(1, sizeof(*(ue_context_target_p->ue_context.handover_info)));
ue_context_target_p->ue_context.handover_info->source_x2id = m->source_x2id;
ue_context_target_p->ue_context.Status = RRC_HO_EXECUTION;
ue_context_target_p->ue_context.handover_info->state = HO_ACK;
/* TODO: remove this hack */
ue_context_target_p->ue_context.handover_info->modid_t = mod_id;
ue_context_target_p->ue_context.handover_info->modid_s = 1-mod_id;
ue_context_target_p->ue_context.handover_info->ueid_s = m->source_rnti;
memset (ue_context_target_p->ue_context.nh, 0, 32);
ue_context_target_p->ue_context.nh_ncc = -1;
memcpy (ue_context_target_p->ue_context.kenb, m->kenb, 32);
ue_context_target_p->ue_context.kenb_ncc = m->kenb_ncc;
}
#if 0
//-----------------------------------------------------------------------------
void
rrc_eNB_process_handoverPreparationInformation(
@@ -2414,6 +2643,8 @@ rrc_eNB_process_handoverPreparationInformation(
T(T_ENB_RRC_HANDOVER_PREPARATION_INFORMATION, T_INT(ctxt_pP->module_id), T_INT(ctxt_pP->frame),
T_INT(ctxt_pP->subframe), T_INT(ctxt_pP->rnti));
struct rrc_eNB_ue_context_s* ue_context_target_p = NULL;
uint8_t mod_id_target = ue_context_pP->ue_context.handover_info->modid_t;
LOG_I(RRC,
"[eNB %d] Frame %d : Logical Channel UL-DCCH, processing RRCHandoverPreparationInformation, sending RRCConnectionReconfiguration to UE %d \n",
@@ -2425,6 +2656,75 @@ rrc_eNB_process_handoverPreparationInformation(
0);
}
rrc_eNB_generate_RRCConnectionReconfiguration_handover(
ctxt_pP,
ue_context_pP,
NULL,
0);
//UE_id_target = rrc_find_free_ue_index(mod_id_target);
ue_context_target_p =
rrc_eNB_get_ue_context(
&eNB_rrc_inst[mod_id_target],
ue_context_pP->ue_context.handover_info->ueid_t);
/*UE_id_target = rrc_eNB_get_next_free_UE_index(
mod_id_target,
eNB_rrc_inst[ctxt_pP->module_id].Info.UE_list[ue_mod_idP]); //this should return a new index*/
if (ue_context_target_p == NULL) {
ue_context_target_p = rrc_eNB_allocate_new_UE_context(&eNB_rrc_inst[mod_id_target]);
if (ue_context_target_p == NULL) {
LOG_E(RRC,
PROTOCOL_RRC_CTXT_UE_FMT" Cannot create new UE context, no memory\n",
PROTOCOL_RRC_CTXT_UE_ARGS(ctxt_pP));
//return;
}
ue_context_target_p->ue_id_rnti = ue_context_pP->ue_context.handover_info->ueid_t; // here ue_id_rnti is just a key, may be something else
ue_context_target_p->ue_context.rnti = ue_context_pP->ue_context.handover_info->ueid_t; // yes duplicate, 1 may be removed
// ue_context_target_p->ue_context.random_ue_identity = ue_identityP;
RB_INSERT(rrc_ue_tree_s, &eNB_rrc_inst[mod_id_target].rrc_ue_head, ue_context_target_p);
LOG_D(RRC,
PROTOCOL_RRC_CTXT_UE_FMT" Created new UE context uid %u\n",
PROTOCOL_RRC_CTXT_UE_ARGS(ctxt_pP),
ue_context_pP->local_uid);
LOG_D(RRC,
"[eNB %d] Frame %d : Emulate sending HandoverPreparationInformation msg from eNB source/eNB target: source UE_id %x target UE_id %x source_modId: %d target_modId: %d\n",
ctxt_pP->module_id,
ctxt_pP->frame,
ue_context_pP->ue_context.rnti,
ue_context_target_p->ue_id_rnti,
ctxt_pP->module_id,
mod_id_target);
ue_context_target_p->ue_context.handover_info =
CALLOC(1, sizeof(*(ue_context_target_p->ue_context.handover_info)));
// memcpy((void*)&ue_context_target_p->ue_context.handover_info->as_context,
//(void*)&ue_context_pP->ue_context.handover_info->as_context,
//sizeof(AS_Context_t));
// memcpy((void*)&ue_context_target_p->ue_context.handover_info->as_config,
// (void*)&ue_context_pP->ue_context.handover_info->as_config,
// sizeof(AS_Config_t));
ue_context_target_p->ue_context.handover_info->ho_prepare = 0xF2;// 0xFF;
ue_context_target_p->ue_context.handover_info->ho_complete = 0x00;
ue_context_target_p->ue_context.handover_info->modid_t = mod_id_target;
ue_context_target_p->ue_context.handover_info->modid_s = ctxt_pP->module_id;
ue_context_target_p->ue_context.handover_info->ueid_s= ue_context_pP->ue_context.rnti;
} else {
LOG_E(RRC, "\nError in obtaining free UE id in target eNB for handover \n");
}
//rrc_create_new_crnti(ctxt_pP,ue_context_target_p->ue_context.handover_info->modid_t,0, ue_context_target_p->ue_id_rnti);
//rrc_create_old_crnti(ctxt_pP,ue_context_target_p->ue_context.handover_info->modid_s,0, ue_context_pP->ue_id_rnti);
}
#endif
//-----------------------------------------------------------------------------
void
@@ -2438,22 +2738,60 @@ check_handovers(
RB_FOREACH(ue_context_p, rrc_ue_tree_s, &eNB_rrc_inst[ctxt_pP->module_id].rrc_ue_head) {
ctxt_pP->rnti = ue_context_p->ue_id_rnti;
if (ue_context_p->ue_context.handover_info != NULL) {
if (ue_context_p->ue_context.handover_info->ho_prepare == 0xFF) {
if (ue_context_p->ue_context.Status == RRC_HO_EXECUTION && ue_context_p->ue_context.handover_info != NULL) {
/* in the source, UE in HO_PREPARE mode */
if (ue_context_p->ue_context.handover_info->state == HO_PREPARE /*ho_prepare == 0xFF*/) {
LOG_D(RRC,
"[eNB %d] Frame %d: Incoming handover detected for new UE_idx %d (source eNB %d->target eNB %d) \n",
"[eNB %d] Frame %d: Incoming handover detected for new UE_id %x (source eNB %d->target eNB %d) \n",
ctxt_pP->module_id,
ctxt_pP->frame,
ctxt_pP->rnti,
ctxt_pP->module_id,
ue_context_p->ue_context.handover_info->modid_t);
// source eNB generates rrcconnectionreconfiguration to prepare the HO
LOG_I(RRC,
"[eNB %d] Frame %d : Logical Channel UL-DCCH, processing RRCHandoverPreparationInformation, sending RRCConnectionReconfiguration to UE %d \n",
ctxt_pP->module_id, ctxt_pP->frame, ue_context_p->ue_context.rnti);
/* TODO: remove this hack, this call has to be done here I think but we must do
* it before rrc_eNB_configure_rbs_handover because the SRBs are copied
* instead of coming from the X2AP message as should be done
*/
// rrc_eNB_generate_RRCConnectionReconfiguration_handover(
// ctxt_pP,
// ue_context_p,
// NULL,
// 0);
#if 0
rrc_eNB_process_handoverPreparationInformation(
ctxt_pP,
ue_context_p);
ue_context_p->ue_context.handover_info->ho_prepare = 0xF1;
#endif
//ue_context_p->ue_context.handover_info->ho_prepare = 0xF0;
ue_context_p->ue_context.handover_info->state = HO_COMPLETE;
}
/* in the target, UE in HO_ACK mode */
if (ue_context_p->ue_context.handover_info->state == HO_ACK /*ho_prepare == 0xF2*/) {
MessageDef *msg;
// Configure target
rrc_eNB_configure_rbs_handover(ue_context_p,ctxt_pP);
// ue_context_p->ue_context.handover_info->ho_prepare = 0x00;
ue_context_p->ue_context.handover_info->state = HO_CONFIGURED;
/* HACK HACK!! "works" only for one UE */
memcpy(UE_rrc_inst[0].sib1[0]->cellAccessRelatedInfo.cellIdentity.buf,
eNB_rrc_inst[ctxt_pP->module_id].carrier[0].sib1->cellAccessRelatedInfo.cellIdentity.buf,
4);
msg = itti_alloc_new_message(TASK_RRC_ENB, X2AP_HANDOVER_REQ_ACK);
/* TODO: remove this hack */
X2AP_HANDOVER_REQ_ACK(msg).target_mod_id = 1 - ctxt_pP->module_id;
X2AP_HANDOVER_REQ_ACK(msg).source_x2id = ue_context_p->ue_context.handover_info->source_x2id;
itti_send_msg_to_task(TASK_X2AP, ENB_MODULE_ID_TO_INSTANCE(ctxt_pP->module_id), msg);
}
/* THIS CODE IS NOT RUN */
if (ue_context_p->ue_context.handover_info->ho_complete == 0xF1) {
LOG_D(RRC,
"[eNB %d] Frame %d: handover Command received for new UE_id %x current eNB %d target eNB: %d \n",
@@ -2478,6 +2816,140 @@ check_handovers(
}
}
void
rrc_eNB_configure_rbs_handover(struct rrc_eNB_ue_context_s* ue_context_p, protocol_ctxt_t* const ctxt_pP)
{
struct rrc_eNB_ue_context_s* ue_source_context;
uint16_t Idx;
ue_source_context =
rrc_eNB_get_ue_context(
&eNB_rrc_inst[ue_context_p->ue_context.handover_info->modid_s],
ue_context_p->ue_context.handover_info->ueid_s);
if(ue_source_context!=NULL){
/* HACK - we have to call rrc_eNB_generate_RRCConnectionReconfiguration_handover before for the SRBs to be okay */
/* to be removed when X2 messages are done */
{
protocol_ctxt_t c = *ctxt_pP;
c.module_id = 1 - c.module_id;
c.enb_flag = 1;
c.instance = 1 - c.instance;
c.rnti = ue_source_context->ue_context.rnti;
c.eNB_index = 1 - c.eNB_index;
rrc_eNB_generate_RRCConnectionReconfiguration_handover(
&c,
ue_source_context,
NULL,
0);
}
LOG_D(RRC,"Frame: %d-Entering target: C-RNTI %x-eNB: %d-MOD_ID: %d\n",ctxt_pP->frame,ctxt_pP->rnti,ctxt_pP->eNB_index,ctxt_pP->module_id);
// E-RABS
// Emulating transmission/reception (just a memory copy)
ue_context_p->ue_context.SRB_configList =
CALLOC(1, sizeof(*(ue_context_p->ue_context.SRB_configList)));
memcpy(ue_context_p->ue_context.SRB_configList,
(void*)ue_source_context->ue_context.handover_info->as_config.sourceRadioResourceConfig.srb_ToAddModList,
sizeof(SRB_ToAddModList_t));
ue_context_p->ue_context.DRB_configList =
CALLOC(1, sizeof(*(ue_context_p->ue_context.DRB_configList)));
memcpy((void*)ue_context_p->ue_context.DRB_configList,
(void*)ue_source_context->ue_context.handover_info->as_config.sourceRadioResourceConfig.drb_ToAddModList,
sizeof(DRB_ToAddModList_t));
//ue_context_pP->ue_context.handover_info->as_config.sourceRadioResourceConfig.drb_ToReleaseList = NULL;
ue_context_p->ue_context.mac_MainConfig =
CALLOC(1, sizeof(*(ue_context_p->ue_context.mac_MainConfig)));
memcpy((void*)ue_context_p->ue_context.mac_MainConfig,
(void*)ue_source_context->ue_context.handover_info->as_config.sourceRadioResourceConfig.mac_MainConfig,
sizeof(MAC_MainConfig_t));
ue_context_p->ue_context.physicalConfigDedicated =
CALLOC(1, sizeof(*(ue_context_p->ue_context.physicalConfigDedicated)));
memcpy((void*)ue_context_p->ue_context.physicalConfigDedicated,
(void*)ue_source_context->ue_context.handover_info->as_config.sourceRadioResourceConfig.physicalConfigDedicated,
sizeof(PhysicalConfigDedicated_t));
Idx = DCCH;
// Activate the radio bearers
// SRB1
ue_context_p->ue_context.Srb1.Active = 1;
ue_context_p->ue_context.Srb1.Srb_info.Srb_id = Idx;
memcpy(&ue_context_p->ue_context.Srb1.Srb_info.Lchan_desc[0], &DCCH_LCHAN_DESC, LCHAN_DESC_SIZE);
memcpy(&ue_context_p->ue_context.Srb1.Srb_info.Lchan_desc[1], &DCCH_LCHAN_DESC, LCHAN_DESC_SIZE);
// SRB2
ue_context_p->ue_context.Srb2.Active = 1;
ue_context_p->ue_context.Srb2.Srb_info.Srb_id = Idx;
memcpy(&ue_context_p->ue_context.Srb2.Srb_info.Lchan_desc[0], &DCCH_LCHAN_DESC, LCHAN_DESC_SIZE);
memcpy(&ue_context_p->ue_context.Srb2.Srb_info.Lchan_desc[1], &DCCH_LCHAN_DESC, LCHAN_DESC_SIZE);
LOG_I(RRC, "[eNB %d] CALLING RLC CONFIG SRB1 (rbid %d) for UE %x\n",
ctxt_pP->module_id, Idx, ue_context_p->ue_context.rnti);
// Configure PDCP/RLC for the target
rrc_pdcp_config_asn1_req(ctxt_pP,
ue_context_p->ue_context.SRB_configList,
(DRB_ToAddModList_t *) NULL,
(DRB_ToReleaseList_t *) NULL,
0xff,
NULL,
NULL,
NULL
#if defined(Rel10) || defined(Rel14)
, (PMCH_InfoList_r9_t *) NULL
#endif
, NULL);
rrc_rlc_config_asn1_req(ctxt_pP,
ue_context_p->ue_context.SRB_configList,
(DRB_ToAddModList_t *) NULL,
(DRB_ToReleaseList_t *) NULL
#if defined(Rel10) || defined(Rel14)
, (PMCH_InfoList_r9_t *) NULL
#endif
);
rrc_eNB_target_add_ue_handover(ctxt_pP);
// Configure MAC for the target
rrc_mac_config_req(
ctxt_pP->module_id,
ue_context_p->ue_context.primaryCC_id,
ENB_FLAG_YES,
ue_context_p->ue_context.rnti,
0,
(RadioResourceConfigCommonSIB_t *) NULL,
ue_context_p->ue_context.physicalConfigDedicated,
#if defined(Rel10) || defined(Rel14)
(SCellToAddMod_r10_t *)NULL,
//(struct PhysicalConfigDedicatedSCell_r10 *)NULL,
#endif
(MeasObjectToAddMod_t **) NULL,
ue_context_p->ue_context.mac_MainConfig,
1,
NULL,
ue_context_p->ue_context.measGapConfig,
(TDD_Config_t *) NULL,
(MobilityControlInfo_t *) NULL,
(uint8_t *) NULL, (uint16_t *) NULL, NULL, NULL, NULL,
(MBSFN_SubframeConfigList_t *) NULL
#if defined(Rel10) || defined(Rel14)
, 0, (MBSFN_AreaInfoList_r9_t *) NULL, (PMCH_InfoList_r9_t *) NULL
#endif
#ifdef CBA
, 0, 0
#endif
);
}
}
void
rrc_eNB_target_add_ue_handover(protocol_ctxt_t* const ctxt_pP){
// Add a new user (called during the HO procedure)
add_new_ue(ctxt_pP->module_id, 0, ctxt_pP->rnti, -1); // UE allocation MAC
add_new_ue_phy(ctxt_pP->module_id, ctxt_pP->rnti);
}
// 5.3.5.4 RRCConnectionReconfiguration including the mobilityControlInfo to prepare the UE handover
//-----------------------------------------------------------------------------
void
@@ -2499,6 +2971,7 @@ rrc_eNB_generate_RRCConnectionReconfiguration_handover(
uint8_t rv[2];
uint16_t Idx;
// configure SRB1/SRB2, PhysicalConfigDedicated, MAC_MainConfig for UE
//eNB_RRC_INST* rrc_inst = &eNB_rrc_inst[ue_context_pP->ue_context.handover_info->modid_t];
eNB_RRC_INST* rrc_inst = &eNB_rrc_inst[ctxt_pP->module_id];
struct PhysicalConfigDedicated** physicalConfigDedicated = &ue_context_pP->ue_context.physicalConfigDedicated;
@@ -2994,6 +3467,7 @@ rrc_eNB_generate_RRCConnectionReconfiguration_handover(
for (i = 0; i < 6; i++) {
CellToAdd = (CellsToAddMod_t *) CALLOC(1, sizeof(*CellToAdd));
CellToAdd->cellIndex = i + 1;
//CellToAdd->physCellId = get_adjacent_cell_id(ue_context_pP->ue_context.handover_info->modid_t, i);
CellToAdd->physCellId = get_adjacent_cell_id(ctxt_pP->module_id, i);
CellToAdd->cellIndividualOffset = Q_OffsetRange_dB0;
@@ -3164,7 +3638,7 @@ rrc_eNB_generate_RRCConnectionReconfiguration_handover(
ctxt_pP->module_id,
ctxt_pP->frame,
mobilityInfo->targetPhysCellId,
ctxt_pP->module_id,
ctxt_pP->module_id, // get_adjacent_cell_mod_id(mobilityInfo->targetPhysCellId),
ue_context_pP->ue_context.rnti);
mobilityInfo->additionalSpectrumEmission = CALLOC(1, sizeof(*mobilityInfo->additionalSpectrumEmission));
@@ -3235,6 +3709,9 @@ rrc_eNB_generate_RRCConnectionReconfiguration_handover(
mobilityInfo->carrierBandwidth->ul_Bandwidth = NULL;
mobilityInfo->rach_ConfigDedicated = NULL;
// Update target with the new c-rnti
//ue_context_pP->ue_context.handover_info->ueid_t=((mobilityInfo->newUE_Identity.buf[0])|(mobilityInfo->newUE_Identity.buf[1]<<8));
// store the srb and drb list for ho management, mainly in case of failure
memcpy(ue_context_pP->ue_context.handover_info->as_config.sourceRadioResourceConfig.srb_ToAddModList,
@@ -3402,6 +3879,15 @@ rrc_eNB_generate_RRCConnectionReconfiguration_handover(
ctxt_pP->module_id, ctxt_pP->frame);
#endif
rrc_data_req(ctxt_pP,
DCCH,
rrc_eNB_mui++,
SDU_CONFIRM_NO,
size,
buffer,
PDCP_TRANSMISSION_MODE_CONTROL);
}
/*
@@ -5079,6 +5565,25 @@ rrc_enb_task(
break;
# endif
case S1AP_PATH_SWITCH_REQ_ACK:
LOG_I(RRC, "[eNB %d] received path switch ack %s\n", instance, msg_name_p);
rrc_eNB_process_S1AP_PATH_SWITCH_REQ_ACK(msg_p, msg_name_p, instance);
break;
case X2AP_HANDOVER_REQ:
LOG_I(RRC, "[eNB %d] X2-Received %s\n", instance, msg_name_p);
rrc_eNB_process_handoverPreparationInformation(instance, &X2AP_HANDOVER_REQ(msg_p));
break;
case X2AP_HANDOVER_REQ_ACK: {
struct rrc_eNB_ue_context_s *ue_context_p = NULL;
ue_context_p = rrc_eNB_get_ue_context(&eNB_rrc_inst[instance], X2AP_HANDOVER_REQ_ACK(msg_p).source_rnti);
LOG_I(RRC, "[eNB %d] X2-Received %s\n", instance, msg_name_p);
DevAssert(ue_context_p != NULL);
if (ue_context_p->ue_context.handover_info->state != HO_REQUEST) abort();
ue_context_p->ue_context.handover_info->state = HO_PREPARE;
break;
}
/* Messages from eNB app */
case RRC_CONFIGURATION_REQ:

View File

@@ -339,6 +339,8 @@ static void process_eNB_security_key (
/* Saves the security key */
memcpy (ue_context_pP->ue_context.kenb, security_key_pP, SECURITY_KEY_LENGTH);
memset (ue_context_pP->ue_context.nh, 0, SECURITY_KEY_LENGTH);
ue_context_pP->ue_context.nh_ncc = -1;
for (i = 0; i < 32; i++) {
sprintf(&ascii_buffer[2 * i], "%02X", ue_context_pP->ue_context.kenb[i]);
@@ -682,6 +684,9 @@ rrc_eNB_send_S1AP_NAS_FIRST_REQ(
ue_context_pP->ue_context.rnti);
}
const Enb_properties_array_t *enb_properties_p = NULL;
enb_properties_p = enb_config_get();
if (rrcConnectionSetupComplete->registeredMME != NULL) {
/* Fill GUMMEI */
struct RegisteredMME *r_mme = rrcConnectionSetupComplete->registeredMME;
@@ -693,7 +698,8 @@ rrc_eNB_send_S1AP_NAS_FIRST_REQ(
if ((r_mme->plmn_Identity->mcc != NULL) && (r_mme->plmn_Identity->mcc->list.count > 0)) {
/* Use first indicated PLMN MCC if it is defined */
S1AP_NAS_FIRST_REQ (message_p).ue_identity.gummei.mcc = *r_mme->plmn_Identity->mcc->list.array[0];
LOG_I(S1AP, "[eNB %d] Build S1AP_NAS_FIRST_REQ adding in s_TMSI: GUMMEI MCC %u ue %x\n",
ue_context_pP->ue_context.ue_gummei.mcc = *r_mme->plmn_Identity->mcc->list.array[0];
LOG_I(S1AP, "[eNB %d] Build S1AP_NAS_FIRST_REQ adding in s_TMSI: GUMMEI MCC %u ue %x\n",
ctxt_pP->module_id,
S1AP_NAS_FIRST_REQ (message_p).ue_identity.gummei.mcc,
ue_context_pP->ue_context.rnti);
@@ -702,24 +708,30 @@ rrc_eNB_send_S1AP_NAS_FIRST_REQ(
if (r_mme->plmn_Identity->mnc.list.count > 0) {
/* Use first indicated PLMN MNC if it is defined */
S1AP_NAS_FIRST_REQ (message_p).ue_identity.gummei.mnc = *r_mme->plmn_Identity->mnc.list.array[0];
ue_context_pP->ue_context.ue_gummei.mnc = *r_mme->plmn_Identity->mnc.list.array[0];
LOG_I(S1AP, "[eNB %d] Build S1AP_NAS_FIRST_REQ adding in s_TMSI: GUMMEI MNC %u ue %x\n",
ctxt_pP->module_id,
S1AP_NAS_FIRST_REQ (message_p).ue_identity.gummei.mnc,
ue_context_pP->ue_context.rnti);
}
} else {
const Enb_properties_array_t *enb_properties_p = NULL;
enb_properties_p = enb_config_get();
// actually the eNB configuration contains only one PLMN (can be up to 6)
S1AP_NAS_FIRST_REQ (message_p).ue_identity.gummei.mcc = enb_properties_p->properties[ctxt_pP->module_id]->mcc;
S1AP_NAS_FIRST_REQ (message_p).ue_identity.gummei.mnc = enb_properties_p->properties[ctxt_pP->module_id]->mnc;
S1AP_NAS_FIRST_REQ (message_p).ue_identity.gummei.mnc_len = enb_properties_p->properties[ctxt_pP->module_id]->mnc_digit_length;
}
/* save gummei in ue context for other procedures such as x2 ho */
ue_context_pP->ue_context.ue_gummei.mcc=enb_properties_p->properties[ctxt_pP->module_id]->mcc;
ue_context_pP->ue_context.ue_gummei.mnc=enb_properties_p->properties[ctxt_pP->module_id]->mnc;
ue_context_pP->ue_context.ue_gummei.mnc_len=enb_properties_p->properties[ctxt_pP->module_id]->mnc_digit_length;
}
S1AP_NAS_FIRST_REQ (message_p).ue_identity.gummei.mme_code = BIT_STRING_to_uint8 (&r_mme->mmec);
S1AP_NAS_FIRST_REQ (message_p).ue_identity.gummei.mme_group_id = BIT_STRING_to_uint16 (&r_mme->mmegi);
ue_context_pP->ue_context.ue_gummei.mme_code = BIT_STRING_to_uint8 (&r_mme->mmec);
ue_context_pP->ue_context.ue_gummei.mme_group_id = BIT_STRING_to_uint16 (&r_mme->mmegi);
MSC_LOG_TX_MESSAGE(
MSC_S1AP_ENB,
MSC_S1AP_MME,
@@ -735,6 +747,19 @@ rrc_eNB_send_S1AP_NAS_FIRST_REQ(
S1AP_NAS_FIRST_REQ (message_p).ue_identity.gummei.mme_code,
S1AP_NAS_FIRST_REQ (message_p).ue_identity.gummei.mme_group_id,
ue_context_pP->ue_context.rnti);
} else {
// send the default GUMME even if the registered MME is not set
S1AP_NAS_FIRST_REQ (message_p).ue_identity.gummei.mcc = enb_properties_p->properties[ctxt_pP->module_id]->mcc;
S1AP_NAS_FIRST_REQ (message_p).ue_identity.gummei.mnc = enb_properties_p->properties[ctxt_pP->module_id]->mnc;
S1AP_NAS_FIRST_REQ (message_p).ue_identity.gummei.mnc_len = enb_properties_p->properties[ctxt_pP->module_id]->mnc_digit_length;
S1AP_NAS_FIRST_REQ (message_p).ue_identity.gummei.mme_code = 1;
S1AP_NAS_FIRST_REQ (message_p).ue_identity.gummei.mme_group_id = 4;
// keep these values in Ue context
ue_context_pP->ue_context.ue_gummei.mcc = enb_properties_p->properties[ctxt_pP->module_id]->mcc;
ue_context_pP->ue_context.ue_gummei.mnc = enb_properties_p->properties[ctxt_pP->module_id]->mnc;
ue_context_pP->ue_context.ue_gummei.mnc_len = enb_properties_p->properties[ctxt_pP->module_id]->mnc_digit_length;
ue_context_pP->ue_context.ue_gummei.mme_code = 1;
ue_context_pP->ue_context.ue_gummei.mme_group_id = 4;
}
}
itti_send_msg_to_task (TASK_S1AP, ctxt_pP->instance, message_p);
@@ -1428,5 +1453,168 @@ int rrc_eNB_send_S1AP_E_RAB_SETUP_RESP(const protocol_ctxt_t* const ctxt_pP,
return 0;
}
/*NN: careful about the typcast of xid (long -> uint8_t*/
int rrc_eNB_send_PATH_SWITCH_REQ(const protocol_ctxt_t* const ctxt_pP,
rrc_eNB_ue_context_t* const ue_context_pP){
MessageDef *msg_p = NULL;
int e_rab;
int e_rabs_done = 0;
msg_p = itti_alloc_new_message (TASK_RRC_ENB, S1AP_PATH_SWITCH_REQ);
S1AP_PATH_SWITCH_REQ (msg_p).eNB_ue_s1ap_id = ue_context_pP->ue_context.eNB_ue_s1ap_id;
S1AP_PATH_SWITCH_REQ (msg_p).security_capabilities.encryption_algorithms=ue_context_pP->ue_context.security_capabilities.encryption_algorithms;
S1AP_PATH_SWITCH_REQ (msg_p).security_capabilities.integrity_algorithms=ue_context_pP->ue_context.security_capabilities.integrity_algorithms;
// the context for UE to be handedover is obtained through ho_req message
for (e_rab = 0; e_rab < ue_context_pP->ue_context.setup_e_rabs ; e_rab++) {
if (ue_context_pP->ue_context.e_rab[e_rab].status == E_RAB_STATUS_ESTABLISHED) {
S1AP_PATH_SWITCH_REQ (msg_p).e_rabs_tobeswitched[e_rabs_done].e_rab_id = ue_context_pP->ue_context.e_rab[e_rab].param.e_rab_id;
S1AP_PATH_SWITCH_REQ (msg_p).e_rabs_tobeswitched[e_rabs_done].gtp_teid = ue_context_pP->ue_context.enb_gtp_teid[e_rab];
S1AP_PATH_SWITCH_REQ (msg_p).e_rabs_tobeswitched[e_rabs_done].eNB_addr = ue_context_pP->ue_context.enb_gtp_addrs[e_rab];
LOG_I (RRC,"enb_gtp_addr (msg index %d, e_rab index %d, status %d): nb_of_e_rabs %d, e_rab_id %d, teid: %u, addr: %d.%d.%d.%d \n ",
e_rabs_done, e_rab, ue_context_pP->ue_context.e_rab[e_rab].status,
ue_context_pP->ue_context.nb_of_e_rabs,
S1AP_PATH_SWITCH_REQ (msg_p).e_rabs_tobeswitched[e_rabs_done].e_rab_id,
S1AP_PATH_SWITCH_REQ (msg_p).e_rabs_tobeswitched[e_rabs_done].gtp_teid,
S1AP_PATH_SWITCH_REQ (msg_p).e_rabs_tobeswitched[e_rabs_done].eNB_addr.buffer[0],
S1AP_PATH_SWITCH_REQ (msg_p).e_rabs_tobeswitched[e_rabs_done].eNB_addr.buffer[1],
S1AP_PATH_SWITCH_REQ (msg_p).e_rabs_tobeswitched[e_rabs_done].eNB_addr.buffer[2],
S1AP_PATH_SWITCH_REQ (msg_p).e_rabs_tobeswitched[e_rabs_done].eNB_addr.buffer[3]);
e_rabs_done++;
}
S1AP_PATH_SWITCH_REQ (msg_p).nb_of_e_rabs = e_rabs_done;
// NN: add conditions for e_rabs_failed
if ((e_rabs_done > 0) ){
LOG_I(RRC,"S1AP_PATH_SWITCH_REQ: sending the message: nb_of_erabstobeswitched %d, total e_rabs %d, index %d\n",
ue_context_pP->ue_context.nb_of_e_rabs, ue_context_pP->ue_context.setup_e_rabs, e_rab);
MSC_LOG_TX_MESSAGE(
MSC_RRC_ENB,
MSC_S1AP_ENB,
(const char *)&S1AP_PATH_SWITCH_REQ (msg_p),
sizeof(s1ap_path_switch_req_t),
MSC_AS_TIME_FMT" PATH_SWITCH_REQ UE %X eNB_ue_s1ap_id %u e_rabs:%u succ",
MSC_AS_TIME_ARGS(ctxt_pP),
ue_context_pP->ue_id_rnti,
S1AP_PATH_SWITCH_REQ (msg_p).eNB_ue_s1ap_id,
e_rabs_done);
itti_send_msg_to_task (TASK_S1AP, ctxt_pP->instance, msg_p);
}
}
return 0;
}
int rrc_eNB_process_S1AP_PATH_SWITCH_REQ_ACK (MessageDef *msg_p, const char *msg_name, instance_t instance)
{
uint16_t ue_initial_id;
uint32_t eNB_ue_s1ap_id;
gtpv1u_enb_create_tunnel_req_t create_tunnel_req;
gtpv1u_enb_create_tunnel_resp_t create_tunnel_resp;
gtpv1u_enb_delete_tunnel_req_t delete_tunnel_req;
struct rrc_eNB_ue_context_s* ue_context_p = NULL;
protocol_ctxt_t ctxt;
int i;
ue_initial_id = S1AP_E_RAB_SETUP_REQ (msg_p).ue_initial_id;
//mme_ue_s1ap_id = S1AP_PATH_SWITCH_REQ_ACK (msg_p).mme_ue_s1ap_id;
eNB_ue_s1ap_id = S1AP_PATH_SWITCH_REQ_ACK (msg_p).eNB_ue_s1ap_id;
ue_context_p = rrc_eNB_get_ue_context_from_s1ap_ids(instance, ue_initial_id, eNB_ue_s1ap_id);
LOG_I(RRC, "[eNB %d] Received %s: ue_initial_id %d, eNB_ue_s1ap_id %d, nb_of_e_rabs %d\n",
instance, msg_name, ue_initial_id, eNB_ue_s1ap_id, S1AP_E_RAB_SETUP_REQ (msg_p).nb_e_rabs_tosetup);
if (ue_context_p == NULL) {
/* Can not associate this message to an UE index, send a failure to S1AP and discard it! */
MessageDef *msg_fail_p = NULL;
LOG_W(RRC, "[eNB %d] In S1AP_PATH_SWITCH_REQ_ACK: unknown UE from S1AP ids (%d, %d)\n", instance, ue_initial_id, eNB_ue_s1ap_id);
//msg_fail_p = itti_alloc_new_message (TASK_RRC_ENB, S1AP_PATH_SWITCH_REQ_ACK_FAIL);
//S1AP_PATH_SWITCH_REQ_ACK (msg_fail_p).eNB_ue_s1ap_id = eNB_ue_s1ap_id;
// TODO add failure cause when defined!
//itti_send_msg_to_task (TASK_S1AP, instance, msg_fail_p);
return (-1);
} else {
PROTOCOL_CTXT_SET_BY_INSTANCE(&ctxt, instance, ENB_FLAG_YES, ue_context_p->ue_context.rnti, 0, 0);
ue_context_p->ue_context.eNB_ue_s1ap_id = S1AP_PATH_SWITCH_REQ_ACK (msg_p).eNB_ue_s1ap_id;
/* Save e RAB information for later */
{
for (i = 0;
i < ue_context_p->ue_context.setup_e_rabs; // go over total number of e_rabs received through x2_ho_req msg
i++) {
// assume that we are releasing all the DRBs
ue_context_p->ue_context.e_rab[i].status = E_RAB_STATUS_RELEASED;
}
memset(&create_tunnel_req, 0 , sizeof(create_tunnel_req));
uint8_t nb_e_rabs_tobeswitched = S1AP_PATH_SWITCH_REQ_ACK (msg_p).nb_e_rabs_tobeswitched;
// keep the previous bearer
// the index for the rec
for (i = 0;
i < nb_e_rabs_tobeswitched; // go over total number of e_rabs received through x2_ho_req msg
i++) {
/* Harmonize with enb_gtp_teid, enb_gtp_addrs, and enb_gtp_rbi vars in the top level structure */
ue_context_p->ue_context.e_rab[i].status = E_RAB_STATUS_REESTABLISHED;
ue_context_p->ue_context.e_rab[i].param.e_rab_id = S1AP_PATH_SWITCH_REQ_ACK (msg_p).e_rabs_tobeswitched[i].e_rab_id;
ue_context_p->ue_context.e_rab[i].param.sgw_addr= S1AP_PATH_SWITCH_REQ_ACK (msg_p).e_rabs_tobeswitched[i].sgw_addr;
ue_context_p->ue_context.e_rab[i].param.gtp_teid = S1AP_PATH_SWITCH_REQ_ACK (msg_p).e_rabs_tobeswitched[i].gtp_teid;
/* Tunnel must have been already created in X2_HO_REQ procedure */
}
ue_context_p->ue_context.setup_e_rabs=i;
ue_context_p->ue_context.nb_of_e_rabs=i;
}
ue_context_p->ue_context.ue_ambr=S1AP_PATH_SWITCH_REQ_ACK (msg_p).ue_ambr;
ue_context_p->ue_context.nb_e_rabs_tobereleased = S1AP_PATH_SWITCH_REQ_ACK (msg_p).nb_e_rabs_tobereleased;
memset(&delete_tunnel_req, 0 , sizeof(delete_tunnel_req));
for (i = 0;
i < ue_context_p->ue_context.nb_e_rabs_tobereleased;
i++) {
ue_context_p->ue_context.e_rabs_tobereleased[i]=S1AP_PATH_SWITCH_REQ_ACK (msg_p).e_rabs_tobereleased[i].e_rab_id;
delete_tunnel_req.eps_bearer_id[i] = S1AP_PATH_SWITCH_REQ_ACK (msg_p).e_rabs_tobereleased[i].e_rab_id;
}
if (ue_context_p->ue_context.nb_e_rabs_tobereleased>0){
delete_tunnel_req.rnti= ue_context_p->ue_context.rnti;
delete_tunnel_req.num_erab= ue_context_p->ue_context.nb_e_rabs_tobereleased;
/* this could also be done through ITTI message */
gtpv1u_delete_s1u_tunnel(instance,
&delete_tunnel_req);
/* TBD: release the DRB not admitted */
//rrc_eNB_generate_dedicatedRRCConnectionReconfiguration(&ctxt, ue_context_p, 0);
}
/* Security key */
ue_context_p->ue_context.next_hop_chain_count=S1AP_PATH_SWITCH_REQ_ACK (msg_p).next_hop_chain_count;
memcpy ( ue_context_p->ue_context.next_security_key,
S1AP_PATH_SWITCH_REQ_ACK (msg_p).next_security_key,
SECURITY_KEY_LENGTH);
return (0);
}
}
# endif /* defined(ENABLE_ITTI) */
#endif /* defined(ENABLE_USE_MME) */

View File

@@ -213,6 +213,10 @@ int rrc_eNB_process_S1AP_UE_CONTEXT_RELEASE_REQ (MessageDef *msg_p, const char *
*/
int rrc_eNB_process_S1AP_UE_CONTEXT_RELEASE_COMMAND (MessageDef *msg_p, const char *msg_name, instance_t instance);
int rrc_eNB_send_PATH_SWITCH_REQ(const protocol_ctxt_t* const ctxt_pP,
rrc_eNB_ue_context_t* const ue_context_pP);
int rrc_eNB_process_S1AP_PATH_SWITCH_REQ_ACK (MessageDef *msg_p, const char *msg_name, instance_t instance);
# endif
# endif /* defined(ENABLE_USE_MME) */
#endif /* RRC_ENB_S1AP_H_ */

View File

@@ -33,26 +33,35 @@ def printDebug(string):
def outputHeaderToFile(f, filename):
now = datetime.datetime.now()
f.write("""/*
* 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.0 (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
*/
f.write("""/*******************************************************************************
Eurecom OpenAirInterface
Copyright(c) 1999 - 2013 Eurecom
This program is free software; you can redistribute it and/or modify it
under the terms and conditions of the GNU General Public License,
version 2, as published by the Free Software Foundation.
This program is distributed in the hope it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
more details.
You should have received a copy of the GNU General Public License along with
this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
The full GNU General Public License is included in this distribution in
the file called "COPYING".
Contact Information
Openair Admin: openair_admin@eurecom.fr
Openair Tech : openair_tech@eurecom.fr
Forums : http://forums.eurecom.fr/openairinterface
Address : EURECOM, Campus SophiaTech, 450 Route des Chappes
06410 Biot FRANCE
*******************************************************************************/
""")
f.write("/*******************************************************************************\n")

View File

@@ -1,70 +0,0 @@
/*
* 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.0 (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 <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include "intertask_interface.h"
#include "x2ap.h"
#include "assertions.h"
#include "conversions.h"
void *x2ap_task(void *arg)
{
MessageDef *received_msg = NULL;
int result;
X2AP_DEBUG("Starting X2AP layer\n");
x2ap_prepare_internal_data();
itti_mark_task_ready(TASK_X2AP);
while (1) {
itti_receive_msg(TASK_X2AP, &received_msg);
switch (ITTI_MSG_ID(received_msg)) {
case TERMINATE_MESSAGE:
itti_exit_task();
break;
default:
X2AP_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;
}

View File

@@ -1,47 +0,0 @@
/*
* 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.0 (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 _x2ap_impl_ X2AP Layer Reference Implementation
* @ingroup _ref_implementation_
* @{
*/
#ifndef X2AP_H_
#define X2AP_H_
typedef struct x2ap_config_s {
} x2ap_config_t;
#if defined(OAI_EMU)
#else
extern x2ap_config_t x2ap_config;
#endif
void *x2ap_task(void *arg);
#endif /* X2AP_H_ */
/**
* @}
*/

64
openair2/X2AP/x2ap_common.c Normal file → Executable file
View File

@@ -1,23 +1,31 @@
/*
* 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.0 (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
*/
/*******************************************************************************
OpenAirInterface
Copyright(c) 1999 - 2014 Eurecom
OpenAirInterface is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OpenAirInterface is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with OpenAirInterface.The full GNU General Public License is
included in this distribution in the file called "COPYING". If not,
see <http://www.gnu.org/licenses/>.
Contact Information
OpenAirInterface Admin: openair_admin@eurecom.fr
OpenAirInterface Tech : openair_tech@eurecom.fr
OpenAirInterface Dev : openair4g-devel@lists.eurecom.fr
Address : Eurecom, Campus SophiaTech, 450 Route des Chappes, CS 50193 - 06904 Biot Sophia Antipolis cedex, FRANCE
*******************************************************************************/
/*! \file x2ap_common.c
* \brief x2ap procedures for both eNB and MME
@@ -31,13 +39,13 @@
#include "x2ap_common.h"
#include "X2AP-PDU.h"
int asn_debug = 0;
int asn1_xer_print = 0;
int asn_debug_x2 = 0;
int asn1_xer_print_x2 = 0;
#if defined(EMIT_ASN_DEBUG_EXTERN)
inline void ASN_DEBUG(const char *fmt, ...)
inline void ASN_DEBUG_X2(const char *fmt, ...)
{
if (asn_debug) {
if (asn_debug_x2) {
int adi = asn_debug_indent;
va_list ap;
va_start(ap, fmt);
@@ -70,7 +78,7 @@ ssize_t x2ap_generate_initiating_message(
pdu.choice.initiatingMessage.criticality = criticality;
ANY_fromType_aper(&pdu.choice.initiatingMessage.value, td, sptr);
if (asn1_xer_print) {
if (asn1_xer_print_x2) {
xer_fprint(stdout, &asn_DEF_X2AP_PDU, (void *)&pdu);
}
@@ -104,7 +112,7 @@ ssize_t x2ap_generate_successfull_outcome(
pdu.choice.successfulOutcome.criticality = criticality;
ANY_fromType_aper(&pdu.choice.successfulOutcome.value, td, sptr);
if (asn1_xer_print) {
if (asn1_xer_print_x2) {
xer_fprint(stdout, &asn_DEF_X2AP_PDU, (void *)&pdu);
}
@@ -139,7 +147,7 @@ ssize_t x2ap_generate_unsuccessfull_outcome(
pdu.choice.successfulOutcome.criticality = criticality;
ANY_fromType_aper(&pdu.choice.successfulOutcome.value, td, sptr);
if (asn1_xer_print) {
if (asn1_xer_print_x2) {
xer_fprint(stdout, &asn_DEF_X2AP_PDU, (void *)&pdu);
}
@@ -180,7 +188,7 @@ X2ap_IE_t *x2ap_new_ie(
return NULL;
}
if (asn1_xer_print)
if (asn1_xer_print_x2)
if (xer_fprint(stdout, &asn_DEF_X2ap_IE, buff) < 0) {
free(buff);
return NULL;

52
openair2/X2AP/x2ap_common.h Normal file → Executable file
View File

@@ -1,23 +1,31 @@
/*
* 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.0 (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
*/
/*******************************************************************************
OpenAirInterface
Copyright(c) 1999 - 2014 Eurecom
OpenAirInterface is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OpenAirInterface is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with OpenAirInterface.The full GNU General Public License is
included in this distribution in the file called "COPYING". If not,
see <http://www.gnu.org/licenses/>.
Contact Information
OpenAirInterface Admin: openair_admin@eurecom.fr
OpenAirInterface Tech : openair_tech@eurecom.fr
OpenAirInterface Dev : openair4g-devel@lists.eurecom.fr
Address : Eurecom, Campus SophiaTech, 450 Route des Chappes, CS 50193 - 06904 Biot Sophia Antipolis cedex, FRANCE
*******************************************************************************/
#if HAVE_CONFIG_H_
# include "config.h"
@@ -284,6 +292,8 @@
#ifndef TRUE
#define TRUE 1
#endif
#ifndef FALSE
#define FALSE 0
#endif
@@ -292,10 +302,12 @@ extern int asn1_xer_print;
#if defined(ENB_MODE)
# include "log.h"
# define X2AP_INFO(x, args...) LOG_I(X2AP, x, ##args)
# define X2AP_ERROR(x, args...) LOG_E(X2AP, x, ##args)
# define X2AP_WARN(x, args...) LOG_W(X2AP, x, ##args)
# define X2AP_DEBUG(x, args...) LOG_D(X2AP, x, ##args)
#else
# define X2AP_INFO(x, args...) do { fprintf(stdout, "[X2AP][I]"x, ##args); } while(0)
# define X2AP_ERROR(x, args...) do { fprintf(stdout, "[X2AP][E]"x, ##args); } while(0)
# define X2AP_WARN(x, args...) do { fprintf(stdout, "[X2AP][W]"x, ##args); } while(0)
# define X2AP_DEBUG(x, args...) do { fprintf(stdout, "[X2AP][D]"x, ##args); } while(0)

512
openair2/X2AP/x2ap_eNB.c Normal file
View File

@@ -0,0 +1,512 @@
/*******************************************************************************
OpenAirInterface
Copyright(c) 1999 - 2014 Eurecom
OpenAirInterface is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OpenAirInterface is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with OpenAirInterface.The full GNU General Public License is
included in this distribution in the file called "COPYING". If not,
see <http://www.gnu.org/licenses/>.
Contact Information
OpenAirInterface Admin: openair_admin@eurecom.fr
OpenAirInterface Tech : openair_tech@eurecom.fr
OpenAirInterface Dev : openair4g-devel@lists.eurecom.fr
Address : Eurecom, Campus SophiaTech, 450 Route des Chappes, CS 50193 - 06904 Biot Sophia Antipolis cedex, FRANCE
*******************************************************************************/
/*! \file x2ap_eNB.c
* \brief x2ap protocol for eNB
* \author Navid Nikaein
* \date 2014 - 2015
* \version 1.0
* \company Eurecom
* \email: navid.nikaein@eurecom.fr
*/
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <arpa/inet.h>
#include "intertask_interface.h"
#include "assertions.h"
#include "queue.h"
#include "x2ap_eNB.h"
#include "x2ap_eNB_defs.h"
#include "x2ap_eNB_decoder.h"
#include "x2ap_eNB_handler.h"
#include "x2ap_ies_defs.h"
#include "x2ap_eNB_management_procedures.h"
#include "x2ap_eNB_generate_messages.h"
#include "msc.h"
#include "assertions.h"
#include "conversions.h"
struct x2ap_enb_map;
struct x2ap_eNB_data_s;
RB_PROTOTYPE(x2ap_enb_map, x2ap_eNB_data_s, entry, x2ap_eNB_compare_assoc_id);
static
void x2ap_eNB_handle_register_eNB(instance_t instance,
x2ap_register_enb_req_t *x2ap_register_eNB);
static
void x2ap_eNB_handle_handover_req(instance_t instance,
x2ap_handover_req_t *x2ap_handover_req);
static
void x2ap_eNB_handle_handover_req_ack(instance_t instance,
x2ap_handover_req_ack_t *x2ap_handover_req_ack);
static
void x2ap_eNB_register_eNB(x2ap_eNB_instance_t *instance_p,
net_ip_address_t *target_eNB_ip_addr,
net_ip_address_t *local_ip_addr,
uint16_t in_streams,
uint16_t out_streams);
static
void x2ap_eNB_handle_sctp_association_resp(instance_t instance,
sctp_new_association_resp_t *sctp_new_association_resp);
static
void x2ap_eNB_handle_sctp_data_ind(instance_t instance,
sctp_data_ind_t *sctp_data_ind) {
int result;
DevAssert(sctp_data_ind != NULL);
x2ap_eNB_handle_message(sctp_data_ind->assoc_id, sctp_data_ind->stream,
sctp_data_ind->buffer, sctp_data_ind->buffer_length);
result = itti_free(TASK_UNKNOWN, sctp_data_ind->buffer);
AssertFatal (result == EXIT_SUCCESS, "Failed to free memory (%d)!\n", result);
}
static
void x2ap_eNB_handle_sctp_association_resp(instance_t instance, sctp_new_association_resp_t *sctp_new_association_resp)
{
x2ap_eNB_instance_t *instance_p;
x2ap_eNB_data_t *x2ap_enb_data_p;
DevAssert(sctp_new_association_resp != NULL);
printf("x2ap_eNB_handle_sctp_association_resp at 1\n");
dump_trees();
instance_p = x2ap_eNB_get_instance(instance);
DevAssert(instance_p != NULL);
/* if the assoc_id is already known, it is certainly because an IND was received
* before. In this case, just update streams and return
*/
if (sctp_new_association_resp->assoc_id != -1) {
x2ap_enb_data_p = x2ap_get_eNB(instance_p, sctp_new_association_resp->assoc_id,
sctp_new_association_resp->ulp_cnx_id);
if (x2ap_enb_data_p != NULL) {
/* some sanity check - to be refined at some point */
if (sctp_new_association_resp->sctp_state != SCTP_STATE_ESTABLISHED) {
X2AP_ERROR("x2ap_enb_data_p not NULL and sctp state not SCTP_STATE_ESTABLISHED, what to do?\n");
abort();
}
x2ap_enb_data_p->in_streams = sctp_new_association_resp->in_streams;
x2ap_enb_data_p->out_streams = sctp_new_association_resp->out_streams;
return;
}
}
x2ap_enb_data_p = x2ap_get_eNB(instance_p, -1,
sctp_new_association_resp->ulp_cnx_id);
DevAssert(x2ap_enb_data_p != NULL);
printf("x2ap_eNB_handle_sctp_association_resp at 2\n");
dump_trees();
if (sctp_new_association_resp->sctp_state != SCTP_STATE_ESTABLISHED) {
X2AP_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);
x2ap_handle_x2_setup_message(x2ap_enb_data_p,
sctp_new_association_resp->sctp_state == SCTP_STATE_SHUTDOWN);
return;
}
printf("x2ap_eNB_handle_sctp_association_resp at 3\n");
dump_trees();
/* Update parameters */
x2ap_enb_data_p->assoc_id = sctp_new_association_resp->assoc_id;
x2ap_enb_data_p->in_streams = sctp_new_association_resp->in_streams;
x2ap_enb_data_p->out_streams = sctp_new_association_resp->out_streams;
printf("x2ap_eNB_handle_sctp_association_resp at 4\n");
dump_trees();
/* Prepare new x2 Setup Request */
x2ap_eNB_generate_x2_setup_request(instance_p, x2ap_enb_data_p);
}
static
void x2ap_eNB_handle_sctp_association_ind(instance_t instance, sctp_new_association_ind_t *sctp_new_association_ind)
{
x2ap_eNB_instance_t *instance_p;
x2ap_eNB_data_t *x2ap_enb_data_p;
printf("x2ap_eNB_handle_sctp_association_ind at 1 (called for instance %d)\n", instance);
dump_trees();
DevAssert(sctp_new_association_ind != NULL);
instance_p = x2ap_eNB_get_instance(instance);
DevAssert(instance_p != NULL);
x2ap_enb_data_p = x2ap_get_eNB(instance_p, sctp_new_association_ind->assoc_id, -1);
if (x2ap_enb_data_p != NULL) abort();
// DevAssert(x2ap_enb_data_p != NULL);
if (x2ap_enb_data_p == NULL) {
/* Create new eNB descriptor */
x2ap_enb_data_p = calloc(1, sizeof(*x2ap_enb_data_p));
DevAssert(x2ap_enb_data_p != NULL);
x2ap_enb_data_p->cnx_id = x2ap_eNB_fetch_add_global_cnx_id();
x2ap_enb_data_p->x2ap_eNB_instance = instance_p;
/* Insert the new descriptor in list of known eNB
* but not yet associated.
*/
RB_INSERT(x2ap_enb_map, &instance_p->x2ap_enb_head, x2ap_enb_data_p);
x2ap_enb_data_p->state = X2AP_ENB_STATE_CONNECTED;
instance_p->x2_target_enb_nb++;
if (instance_p->x2_target_enb_pending_nb > 0) {
instance_p->x2_target_enb_pending_nb--;
}
} else {
X2AP_WARN("x2ap_enb_data_p already exists\n");
}
printf("x2ap_eNB_handle_sctp_association_ind at 2\n");
dump_trees();
/* Update parameters */
x2ap_enb_data_p->assoc_id = sctp_new_association_ind->assoc_id;
x2ap_enb_data_p->in_streams = sctp_new_association_ind->in_streams;
x2ap_enb_data_p->out_streams = sctp_new_association_ind->out_streams;
printf("x2ap_eNB_handle_sctp_association_ind at 3\n");
dump_trees();
}
int x2ap_eNB_init_sctp (x2ap_eNB_instance_t *instance_p,
net_ip_address_t *local_ip_addr)
{
// Create and alloc new message
MessageDef *message;
sctp_init_t *sctp_init = NULL;
DevAssert(instance_p != NULL);
DevAssert(local_ip_addr != NULL);
message = itti_alloc_new_message (TASK_X2AP, SCTP_INIT_MSG);
sctp_init = &message->ittiMsg.sctp_init;
sctp_init->port = X2AP_PORT_NUMBER;
sctp_init->ppid = X2AP_SCTP_PPID;
sctp_init->ipv4 = 1;
sctp_init->ipv6 = 0;
sctp_init->nb_ipv4_addr = 1;
#if 0
memcpy(&sctp_init->ipv4_address,
local_ip_addr,
sizeof(*local_ip_addr));
#endif
sctp_init->ipv4_address[0] = inet_addr(local_ip_addr->ipv4_address);
/*
* SR WARNING: ipv6 multi-homing fails sometimes for localhost.
* * * * Disable it for now.
*/
sctp_init->nb_ipv6_addr = 0;
sctp_init->ipv6_address[0] = "0:0:0:0:0:0:0:1";
return itti_send_msg_to_task (TASK_SCTP, instance_p->instance, message);
}
static void x2ap_eNB_register_eNB(x2ap_eNB_instance_t *instance_p,
net_ip_address_t *target_eNB_ip_address,
net_ip_address_t *local_ip_addr,
uint16_t in_streams,
uint16_t out_streams)
{
MessageDef *message = NULL;
sctp_new_association_req_t *sctp_new_association_req = NULL;
x2ap_eNB_data_t *x2ap_enb_data = NULL;
DevAssert(instance_p != NULL);
DevAssert(target_eNB_ip_address != NULL);
message = itti_alloc_new_message(TASK_X2AP, SCTP_NEW_ASSOCIATION_REQ);
sctp_new_association_req = &message->ittiMsg.sctp_new_association_req;
sctp_new_association_req->port = X2AP_PORT_NUMBER;
sctp_new_association_req->ppid = X2AP_SCTP_PPID;
sctp_new_association_req->in_streams = in_streams;
sctp_new_association_req->out_streams = out_streams;
memcpy(&sctp_new_association_req->remote_address,
target_eNB_ip_address,
sizeof(*target_eNB_ip_address));
memcpy(&sctp_new_association_req->local_address,
local_ip_addr,
sizeof(*local_ip_addr));
/* Create new eNB descriptor */
x2ap_enb_data = calloc(1, sizeof(*x2ap_enb_data));
DevAssert(x2ap_enb_data != NULL);
x2ap_enb_data->cnx_id = x2ap_eNB_fetch_add_global_cnx_id();
sctp_new_association_req->ulp_cnx_id = x2ap_enb_data->cnx_id;
x2ap_enb_data->assoc_id = -1;
x2ap_enb_data->x2ap_eNB_instance = instance_p;
/* Insert the new descriptor in list of known eNB
* but not yet associated.
*/
RB_INSERT(x2ap_enb_map, &instance_p->x2ap_enb_head, x2ap_enb_data);
x2ap_enb_data->state = X2AP_ENB_STATE_WAITING;
instance_p->x2_target_enb_nb ++;
instance_p->x2_target_enb_pending_nb ++;
itti_send_msg_to_task(TASK_SCTP, instance_p->instance, message);
}
static
void x2ap_eNB_handle_register_eNB(instance_t instance,
x2ap_register_enb_req_t *x2ap_register_eNB)
{
x2ap_eNB_instance_t *new_instance;
uint8_t index;
DevAssert(x2ap_register_eNB != NULL);
/* Look if the provided instance already exists */
new_instance = x2ap_eNB_get_instance(instance);
if (new_instance != NULL) {
/* Checks if it is a retry on the same eNB */
DevCheck(new_instance->eNB_id == x2ap_register_eNB->eNB_id, new_instance->eNB_id, x2ap_register_eNB->eNB_id, 0);
DevCheck(new_instance->cell_type == x2ap_register_eNB->cell_type, new_instance->cell_type, x2ap_register_eNB->cell_type, 0);
DevCheck(new_instance->tac == x2ap_register_eNB->tac, new_instance->tac, x2ap_register_eNB->tac, 0);
DevCheck(new_instance->mcc == x2ap_register_eNB->mcc, new_instance->mcc, x2ap_register_eNB->mcc, 0);
DevCheck(new_instance->mnc == x2ap_register_eNB->mnc, new_instance->mnc, x2ap_register_eNB->mnc, 0);
}
else {
new_instance = calloc(1, sizeof(x2ap_eNB_instance_t));
DevAssert(new_instance != NULL);
RB_INIT(&new_instance->x2ap_enb_head);
/* Copy usefull parameters */
new_instance->instance = instance;
new_instance->eNB_name = x2ap_register_eNB->eNB_name;
new_instance->eNB_id = x2ap_register_eNB->eNB_id;
new_instance->cell_type = x2ap_register_eNB->cell_type;
new_instance->tac = x2ap_register_eNB->tac;
new_instance->mcc = x2ap_register_eNB->mcc;
new_instance->mnc = x2ap_register_eNB->mnc;
new_instance->mnc_digit_length = x2ap_register_eNB->mnc_digit_length;
/* Add the new instance to the list of eNB (meaningfull in virtual mode) */
x2ap_eNB_insert_new_instance(new_instance);
X2AP_INFO("Registered new eNB[%d] and %s eNB id %u\n",
instance,
x2ap_register_eNB->cell_type == CELL_MACRO_ENB ? "macro" : "home",
x2ap_register_eNB->eNB_id);
}
DevCheck(x2ap_register_eNB->nb_x2 <= X2AP_MAX_NB_ENB_IP_ADDRESS,
X2AP_MAX_NB_ENB_IP_ADDRESS, x2ap_register_eNB->nb_x2, 0);
/* Trying to connect to the provided list of eNB ip address */
for (index = 0; index < x2ap_register_eNB->nb_x2; index++) {
if (x2ap_register_eNB->target_enb_x2_ip_address[index].active == 1 ){
X2AP_INFO("eNB[%d] eNB id %u acting as an initiator (client)\n",
instance, x2ap_register_eNB->eNB_id);
x2ap_eNB_register_eNB(new_instance,
&x2ap_register_eNB->target_enb_x2_ip_address[index],
&x2ap_register_eNB->enb_x2_ip_address,
x2ap_register_eNB->sctp_in_streams,
x2ap_register_eNB->sctp_out_streams);
}
else {
/* initiate the SCTP listener */
if (x2ap_eNB_init_sctp(new_instance,&x2ap_register_eNB->enb_x2_ip_address) < 0 ) {
X2AP_ERROR ("Error while sending SCTP_INIT_MSG to SCTP \n");
return;
}
X2AP_INFO("eNB[%d] eNB id %u acting as a listner (server)\n",
instance, x2ap_register_eNB->eNB_id);
}
}
}
/* TODO: remove this hack, it's to map rnti to X2 ID in the source eNB, only 1 UE supported */
/* so we directly use index 0, no search no lock no nothing */
int x2id_to_source_rnti[1];
/* TODO: remove that, it's for the hack below */
#include "enb_config.h"
static
void x2ap_eNB_handle_handover_req(instance_t instance,
x2ap_handover_req_t *x2ap_handover_req)
{
/* TODO: remove this hack (the goal is to find the correct
* eNodeB structure for the target) - we need a proper way for RRC
* and X2AP to identify eNodeBs
* RRC knows about mod_id and X2AP knows about eNB_id (eNB_ID in
* the configuration file)
* as far as I understand.. CROUX
*/
x2ap_eNB_instance_t *instance_p;
x2ap_eNB_data_t *target;
const Enb_properties_array_t *enb_properties = enb_config_get();
int target_enb_id = enb_properties->properties[x2ap_handover_req->target_mod_id]->eNB_id;
instance_p = x2ap_eNB_get_instance(instance);
DevAssert(instance_p != NULL);
target = x2ap_is_eNB_id_in_list(target_enb_id);
DevAssert(target != NULL);
/* store rnti at index 0 */
x2id_to_source_rnti[0] = x2ap_handover_req->source_rnti;
x2ap_eNB_generate_x2_handover_request(instance_p, target, 0);
}
static
void x2ap_eNB_handle_handover_req_ack(instance_t instance,
x2ap_handover_req_ack_t *x2ap_handover_req_ack)
{
/* TODO: remove this hack (the goal is to find the correct
* eNodeB structure for the other end) - we need a proper way for RRC
* and X2AP to identify eNodeBs
* RRC knows about mod_id and X2AP knows about eNB_id (eNB_ID in
* the configuration file)
* as far as I understand.. CROUX
*/
x2ap_eNB_instance_t *instance_p;
x2ap_eNB_data_t *target;
const Enb_properties_array_t *enb_properties = enb_config_get();
int target_enb_id = enb_properties->properties[x2ap_handover_req_ack->target_mod_id]->eNB_id;
instance_p = x2ap_eNB_get_instance(instance);
DevAssert(instance_p != NULL);
target = x2ap_is_eNB_id_in_list(target_enb_id);
DevAssert(target != NULL);
x2ap_eNB_generate_x2_handover_req_ack(instance_p, target, x2ap_handover_req_ack->source_x2id);
}
void *x2ap_task(void *arg)
{
MessageDef *received_msg = NULL;
int result;
X2AP_DEBUG("Starting X2AP layer\n");
x2ap_eNB_prepare_internal_data();
itti_mark_task_ready(TASK_X2AP);
while (1) {
itti_receive_msg(TASK_X2AP, &received_msg);
switch (ITTI_MSG_ID(received_msg)) {
case TERMINATE_MESSAGE:
itti_exit_task();
break;
case X2AP_REGISTER_ENB_REQ:
x2ap_eNB_handle_register_eNB(ITTI_MESSAGE_GET_INSTANCE(received_msg),
&X2AP_REGISTER_ENB_REQ(received_msg));
break;
case X2AP_HANDOVER_REQ:
x2ap_eNB_handle_handover_req(ITTI_MESSAGE_GET_INSTANCE(received_msg),
&X2AP_HANDOVER_REQ(received_msg));
break;
case X2AP_HANDOVER_REQ_ACK:
x2ap_eNB_handle_handover_req_ack(ITTI_MESSAGE_GET_INSTANCE(received_msg),
&X2AP_HANDOVER_REQ_ACK(received_msg));
break;
case SCTP_NEW_ASSOCIATION_RESP:
x2ap_eNB_handle_sctp_association_resp(ITTI_MESSAGE_GET_INSTANCE(received_msg),
&received_msg->ittiMsg.sctp_new_association_resp);
break;
case SCTP_NEW_ASSOCIATION_IND:
x2ap_eNB_handle_sctp_association_ind(ITTI_MESSAGE_GET_INSTANCE(received_msg),
&received_msg->ittiMsg.sctp_new_association_ind);
break;
case SCTP_DATA_IND:
x2ap_eNB_handle_sctp_data_ind(ITTI_MESSAGE_GET_INSTANCE(received_msg),
&received_msg->ittiMsg.sctp_data_ind);
break;
default:
X2AP_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;
}

58
openair2/X2AP/x2ap_eNB.h Normal file
View File

@@ -0,0 +1,58 @@
/*******************************************************************************
OpenAirInterface
Copyright(c) 1999 - 2014 Eurecom
OpenAirInterface is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OpenAirInterface is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with OpenAirInterface.The full GNU General Public License is
included in this distribution in the file called "COPYING". If not,
see <http://www.gnu.org/licenses/>.
Contact Information
OpenAirInterface Admin: openair_admin@eurecom.fr
OpenAirInterface Tech : openair_tech@eurecom.fr
OpenAirInterface Dev : openair4g-devel@lists.eurecom.fr
Address : Eurecom, Campus SophiaTech, 450 Route des Chappes, CS 50193 - 06904 Biot Sophia Antipolis cedex, FRANCE
*******************************************************************************/
#include <stdio.h>
#include <stdint.h>
/** @defgroup _x2ap_impl_ X2AP Layer Reference Implementation
* @ingroup _ref_implementation_
* @{
*/
#ifndef X2AP_ENB_H_
#define X2AP_ENB_H_
#define X2AP_PORT_NUMBER (36422) ///< X2AP SCTP IANA ASSIGNED Port Number
#define X2AP_SCTP_PPID (27) ///< X2AP SCTP Payload Protocol Identifier (PPID)
typedef struct x2ap_config_s {
} x2ap_config_t;
#if defined(OAI_EMU)
#else
extern x2ap_config_t x2ap_config;
#endif
void *x2ap_task(void *arg);
#endif /* X2AP_H_ */
/**
* @}
*/

View File

@@ -0,0 +1,285 @@
/*******************************************************************************
OpenAirInterface
Copyright(c) 1999 - 2015 Eurecom
OpenAirInterface is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OpenAirInterface is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with OpenAirInterface.The full GNU General Public License is
included in this distribution in the file called "COPYING". If not,
see <http://www.gnu.org/licenses/>.
Contact Information
OpenAirInterface Admin: openair_admin@eurecom.fr
OpenAirInterface Tech : openair_tech@eurecom.fr
OpenAirInterface Dev : openair4g-devel@lists.eurecom.fr
Address : Eurecom, Compus SophiaTech 450, route des chappes, 06451 Biot, France.
*******************************************************************************/
/*! \file x2ap_eNB_decoder.c
* \brief x2ap pdu decode procedures for eNB
* \author Navid Nikaein
* \date 2015- 2016
* \version 0.1
*/
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <assert.h>
#include "x2ap_eNB_decoder.h"
#include "x2ap_common.h"
#include "x2ap_ies_defs.h"
#include "X2ap-ProcedureCode.h"
#include "intertask_interface.h"
#include "assertions.h"
int x2ap_eNB_decode_initiating(x2ap_message *x2ap_message_p, X2ap_InitiatingMessage_t *initiating_p);
int x2ap_eNB_decode_successful(x2ap_message *x2ap_message_p, X2ap_SuccessfulOutcome_t *successful_p);
int x2ap_eNB_decode_unsuccessful(x2ap_message *x2ap_message_p, X2ap_UnsuccessfulOutcome_t *unsuccessful_p);
int x2ap_eNB_decode_pdu(x2ap_message *x2ap_message_p, const uint8_t * const buffer, uint32_t len) {
X2AP_PDU_t pdu;
X2AP_PDU_t *pdu_p = &pdu;
asn_dec_rval_t dec_ret;
DevAssert(buffer != NULL);
memset((void *)pdu_p, 0, sizeof(X2AP_PDU_t));
dec_ret = aper_decode(NULL,
&asn_DEF_X2AP_PDU,
(void**)&pdu_p,
buffer,
len,
0,
0);
if (dec_ret.code != RC_OK){
X2AP_ERROR("Failed to decode X2AP pdu\n");
return -1;
}
x2ap_message_p->direction = pdu_p->present;
asn1_xer_print = 1;
asn_debug = 0;
switch(pdu_p->present) {
case X2AP_PDU_PR_initiatingMessage:
return x2ap_eNB_decode_initiating(x2ap_message_p, &pdu_p->choice.initiatingMessage);
case X2AP_PDU_PR_successfulOutcome:
return x2ap_eNB_decode_successful(x2ap_message_p, &pdu_p->choice.successfulOutcome);
case X2AP_PDU_PR_unsuccessfulOutcome:
return x2ap_eNB_decode_unsuccessful(x2ap_message_p, &pdu_p->choice.unsuccessfulOutcome);
default:
X2AP_DEBUG("Unknown message outcome (%d) or not implemented", (int)pdu_p->present);
break;
}
return -1;
}
int
x2ap_eNB_decode_initiating(x2ap_message *x2ap_message_p, X2ap_InitiatingMessage_t *initiating_p) {
int ret = -1;
MessageDef *message;
char *message_string = NULL;
size_t message_string_size;
MessagesIds message_id;
DevAssert(initiating_p != NULL);
message_string = calloc(10000, sizeof(char));
x2ap_string_total_size = 0;
x2ap_message_p->procedureCode = initiating_p->procedureCode;
x2ap_message_p->criticality = initiating_p->criticality;
switch(x2ap_message_p->procedureCode) {
case X2ap_ProcedureCode_id_x2Setup :
ret = x2ap_decode_x2setuprequest_ies(&x2ap_message_p->msg.x2SetupRequest_IEs, &initiating_p->value);
x2ap_xer_print_x2setuprequest_(x2ap_xer__print2sp,message_string,x2ap_message_p);
message_id = X2AP_SETUP_REQUEST_LOG;
message_string_size = strlen(message_string);
message = itti_alloc_new_message_sized(TASK_X2AP,
message_id,
message_string_size + sizeof (IttiMsgText));
message->ittiMsg.x2ap_setup_request_log.size = message_string_size;
memcpy(&message->ittiMsg.x2ap_setup_request_log.text, message_string, message_string_size);
itti_send_msg_to_task(TASK_UNKNOWN, INSTANCE_DEFAULT, message);
free(message_string);
break;
case X2ap_ProcedureCode_id_reset:
ret = x2ap_decode_x2ap_resetrequest_ies(&x2ap_message_p->msg.x2ap_ResetRequest_IEs, &initiating_p->value);
break;
case X2ap_ProcedureCode_id_resourceStatusReportingInitiation:
ret = x2ap_decode_x2ap_resourcestatusrequest_ies(&x2ap_message_p->msg.x2ap_ResourceStatusRequest_IEs, &initiating_p->value);
break;
case X2ap_ProcedureCode_id_resourceStatusReporting:
ret = x2ap_decode_x2ap_resourcestatusupdate_ies(&x2ap_message_p->msg.x2ap_ResourceStatusUpdate_IEs, &initiating_p->value);
break;
case X2ap_ProcedureCode_id_loadIndication:
ret = x2ap_decode_x2ap_loadinformation_ies(&x2ap_message_p->msg.x2ap_LoadInformation_IEs, &initiating_p->value);
break;
case X2ap_ProcedureCode_id_mobilitySettingsChange:
ret = x2ap_decode_x2ap_mobilitychangerequest_ies(&x2ap_message_p->msg.x2ap_MobilityChangeRequest_IEs, &initiating_p->value);
break;
case X2ap_ProcedureCode_id_eNBConfigurationUpdate:
ret = x2ap_decode_x2ap_enbconfigurationupdate_ies(&x2ap_message_p->msg.x2ap_ENBConfigurationUpdate_IEs, &initiating_p->value);
break;
case X2ap_ProcedureCode_id_errorIndication:
ret = x2ap_decode_x2ap_errorindication_ies(&x2ap_message_p->msg.x2ap_ErrorIndication_IEs, &initiating_p->value);
break;
case X2ap_ProcedureCode_id_handoverCancel:
ret = x2ap_decode_x2ap_handovercancel_ies(&x2ap_message_p->msg.x2ap_HandoverCancel_IEs, &initiating_p->value);
break;
case X2ap_ProcedureCode_id_handoverPreparation:
ret = x2ap_decode_x2ap_handoverrequest_ies(&x2ap_message_p->msg.x2ap_HandoverRequest_IEs, &initiating_p->value);
break;
case X2ap_ProcedureCode_id_uEContextRelease:
ret = x2ap_decode_x2ap_uecontextrelease_ies(&x2ap_message_p->msg.x2ap_UEContextRelease_IEs, &initiating_p->value);
break;
case X2ap_ProcedureCode_id_snStatusTransfer:
ret = x2ap_decode_x2ap_snstatustransfer_ies(&x2ap_message_p->msg.x2ap_SNStatusTransfer_IEs, &initiating_p->value);
break;
case X2ap_ProcedureCode_id_rLFIndication:
ret = x2ap_decode_x2ap_rlfindication_ies(&x2ap_message_p->msg.x2ap_RLFIndication_IEs, &initiating_p->value);
break;
case X2ap_ProcedureCode_id_cellActivation:
ret = x2ap_decode_x2ap_cellactivationrequest_ies(&x2ap_message_p->msg.x2ap_CellActivationRequest_IEs, &initiating_p->value);
break;
case X2ap_ProcedureCode_id_handoverReport:
ret = x2ap_decode_x2ap_handoverreport_ies(&x2ap_message_p->msg.x2ap_HandoverReport_IEs, &initiating_p->value);
break;
default:
X2AP_DEBUG("Unknown procedure (%d) or not implemented", (int)x2ap_message_p->procedureCode);
break;
}
return ret;
}
int
x2ap_eNB_decode_successful(x2ap_message *x2ap_message_p, X2ap_SuccessfulOutcome_t *successful_p) {
int ret = -1;
MessageDef *message_p;
char *message_string = NULL;
size_t message_string_size;
MessagesIds message_id;
DevAssert(successful_p != NULL);
message_string = calloc(10000, sizeof(char));
x2ap_string_total_size = 0;
x2ap_message_p->procedureCode = successful_p->procedureCode;
x2ap_message_p->criticality = successful_p->criticality;
switch(x2ap_message_p->procedureCode) {
case X2ap_ProcedureCode_id_x2Setup:
ret = x2ap_decode_x2setupresponse_ies(&x2ap_message_p->msg.x2SetupResponse_IEs, &successful_p->value);
break;
case X2ap_ProcedureCode_id_reset:
ret = x2ap_decode_x2ap_resetresponse_ies(&x2ap_message_p->msg.x2ap_ResetResponse_IEs, &successful_p->value);
break;
case X2ap_ProcedureCode_id_resourceStatusReportingInitiation:
ret = x2ap_decode_x2ap_resourcestatusresponse_ies(&x2ap_message_p->msg.x2ap_ResourceStatusResponse_IEs, &successful_p->value);
break;
case X2ap_ProcedureCode_id_mobilitySettingsChange:
ret = x2ap_decode_x2ap_mobilitychangeacknowledge_ies(&x2ap_message_p->msg.x2ap_MobilityChangeAcknowledge_IEs, &successful_p->value);
break;
case X2ap_ProcedureCode_id_eNBConfigurationUpdate:
ret = x2ap_decode_x2ap_enbconfigurationupdateacknowledge_ies(&x2ap_message_p->msg.x2ap_ENBConfigurationUpdateAcknowledge_IEs, &successful_p->value);
break;
case X2ap_ProcedureCode_id_handoverPreparation:
ret = x2ap_decode_x2ap_handoverrequestacknowledge_ies(&x2ap_message_p->msg.x2ap_HandoverRequestAcknowledge_IEs, &successful_p->value);
break;
case X2ap_ProcedureCode_id_cellActivation:
ret = x2ap_decode_x2ap_cellactivationresponse_ies(&x2ap_message_p->msg.x2ap_CellActivationResponse_IEs, &successful_p->value);
break;
default:
X2AP_DEBUG("Unknown procedure (%d) or not implemented", (int)x2ap_message_p->procedureCode);
break;
}
return ret;
}
int
x2ap_eNB_decode_unsuccessful(x2ap_message *x2ap_message_p, X2ap_UnsuccessfulOutcome_t *unsuccessful_p) {
int ret = -1;
MessageDef *message;
char *message_string = NULL;
size_t message_string_size;
MessagesIds message_id;
DevAssert(unsuccessful_p != NULL);
message_string = calloc(10000, sizeof(char));
x2ap_string_total_size = 0;
x2ap_message_p->procedureCode = unsuccessful_p->procedureCode;
x2ap_message_p->criticality = unsuccessful_p->criticality;
switch(x2ap_message_p->procedureCode) {
case X2ap_ProcedureCode_id_x2Setup:
ret = x2ap_decode_x2setupfailure_ies(&x2ap_message_p->msg.x2SetupFailure_IEs, &unsuccessful_p->value);
break;
case X2ap_ProcedureCode_id_resourceStatusReportingInitiation:
ret = x2ap_decode_x2ap_resourcestatusfailure_ies(&x2ap_message_p->msg.x2ap_ResourceStatusFailure_IEs, &unsuccessful_p->value);
break;
case X2ap_ProcedureCode_id_mobilitySettingsChange:
ret = x2ap_decode_x2ap_mobilitychangefailure_ies(&x2ap_message_p->msg.x2ap_MobilityChangeFailure_IEs, &unsuccessful_p->value);
break;
case X2ap_ProcedureCode_id_eNBConfigurationUpdate:
ret = x2ap_decode_x2ap_enbconfigurationupdatefailure_ies(&x2ap_message_p->msg.x2ap_ENBConfigurationUpdateFailure_IEs, &unsuccessful_p->value);
break;
case X2ap_ProcedureCode_id_handoverPreparation:
ret = x2ap_decode_x2ap_handoverpreparationfailure_ies(&x2ap_message_p->msg.x2ap_HandoverPreparationFailure_IEs, &unsuccessful_p->value);
break;
case X2ap_ProcedureCode_id_cellActivation:
ret = x2ap_decode_x2ap_cellactivationfailure_ies(&x2ap_message_p->msg.x2ap_CellActivationFailure_IEs, &unsuccessful_p->value);
break;
default:
X2AP_DEBUG("Unknown procedure (%d) or not implemented", (int)x2ap_message_p->procedureCode);
break;
}
return ret;
}

View File

@@ -0,0 +1,45 @@
/*******************************************************************************
OpenAirInterface
Copyright(c) 1999 - 2015 Eurecom
OpenAirInterface is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OpenAirInterface is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with OpenAirInterface.The full GNU General Public License is
included in this distribution in the file called "COPYING". If not,
see <http://www.gnu.org/licenses/>.
Contact Information
OpenAirInterface Admin: openair_admin@eurecom.fr
OpenAirInterface Tech : openair_tech@eurecom.fr
OpenAirInterface Dev : openair4g-devel@lists.eurecom.fr
Address : Eurecom, Compus SophiaTech 450, route des chappes, 06451 Biot, France.
*******************************************************************************/
/*! \file x2ap_eNB_decoder.c
* \brief x2ap pdu decode procedures for eNB
* \author Navid Nikaein
* \date 2015- 2016
* \version 0.1
*/
#include "x2ap_common.h"
#include "x2ap_ies_defs.h"
#ifndef X2AP_ENB_DECODER_H_
#define X2AP_ENB_DECODER_H_
int x2ap_eNB_decode_pdu(x2ap_message *x2ap_message, const uint8_t * const buffer, uint32_t len);
#endif /* X2AP_ENB_DECODER_H_ */

View File

@@ -0,0 +1,188 @@
/*******************************************************************************
OpenAirInterface
Copyright(c) 1999 - 2014 Eurecom
OpenAirInterface is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OpenAirInterface is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with OpenAirInterface.The full GNU General Public License is
included in this distribution in the file called "COPYING". If not,
see <http://www.gnu.org/licenses/>.
Contact Information
OpenAirInterface Admin: openair_admin@eurecom.fr
OpenAirInterface Tech : openair_tech@eurecom.fr
OpenAirInterface Dev : openair4g-devel@lists.eurecom.fr
Address : Eurecom, Compus SophiaTech 450, route des chappes, 06451 Biot, France.
*******************************************************************************/
#include <stdint.h>
#include "queue.h"
#include "tree.h"
#include "sctp_eNB_defs.h"
#ifndef X2AP_ENB_DEFS_H_
#define X2AP_ENB_DEFS_H_
#define X2AP_ENB_NAME_LENGTH_MAX (150)
typedef enum {
/* Disconnected state: initial state for any association. */
X2AP_ENB_STATE_DISCONNECTED = 0x0,
/* State waiting for x2 Setup response message if the target eNB accepts or
* X2 Setup failure if rejects the eNB.
*/
X2AP_ENB_STATE_WAITING = 0x1,
/* The eNB is successfully connected to another eNB. */
X2AP_ENB_STATE_CONNECTED = 0x2,
/* X2AP is ready, and the eNB is successfully connected to another eNB. */
X2AP_ENB_STATE_READY = 0x3,
/*
*/
X2AP_ENB_STATE_OVERLOAD = 0x4,
X2AP_ENB_STATE_RESETTING = 0x5,
/* Max number of states available */
X2AP_ENB_STATE_MAX,
} x2ap_eNB_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 enb_group_id;
STAILQ_ENTRY(served_group_id_s) next;
};
/* Served enn code for a particular eNB */
struct enb_code_s {
uint8_t enb_code;
STAILQ_ENTRY(enb_code_s) next;
};
struct x2ap_eNB_instance_s;
/* This structure describes association of a eNB to another eNB */
typedef struct x2ap_eNB_data_s {
/* eNB descriptors tree, ordered by sctp assoc id */
RB_ENTRY(x2ap_eNB_data_s) entry;
/* This is the optional name provided by the MME */
char *eNB_name;
/* target eNB ID */
uint32_t eNB_id;
/* Current eNB load information (if any). */
//x2ap_load_state_t overload_state;
/* Current eNB->eNB X2AP association state */
x2ap_eNB_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/X2AP */
uint16_t cnx_id;
/* SCTP association id */
int32_t assoc_id;
/* Only meaningfull in virtual mode */
struct x2ap_eNB_instance_s *x2ap_eNB_instance;
} x2ap_eNB_data_t;
typedef struct x2ap_eNB_instance_s {
/* used in simulation to store multiple eNB instances*/
STAILQ_ENTRY(x2ap_eNB_instance_s) x2ap_eNB_entries;
/* Number of target eNBs requested by eNB (tree size) */
uint32_t x2_target_enb_nb;
/* Number of target eNBs for which association is pending */
uint32_t x2_target_enb_pending_nb;
/* Number of target eNB successfully associated to eNB */
uint32_t x2_target_enb_associated_nb;
/* Tree of X2AP eNB associations ordered by association ID */
RB_HEAD(x2ap_enb_map, x2ap_eNB_data_s) x2ap_enb_head;
/* Tree of UE ordered by eNB_ue_x2ap_id's */
// RB_HEAD(x2ap_ue_map, x2ap_eNB_ue_context_s) x2ap_ue_head;
/* For virtual mode, mod_id as defined in the rest of the L1/L2 stack */
instance_t instance;
/* Displayable name of eNB */
char *eNB_name;
/* Unique eNB_id to identify the eNB within EPC.
* In our case the eNB is a macro eNB so the id will be 20 bits long.
* For Home eNB id, this field should be 28 bits long.
*/
uint32_t eNB_id;
/* The type of the cell */
cell_type_t cell_type;
/* Tracking area code */
uint16_t tac;
/* Mobile Country Code
* Mobile Network Code
*/
uint16_t mcc;
uint16_t mnc;
uint8_t mnc_digit_length;
} x2ap_eNB_instance_t;
typedef struct {
/* List of served eNBs
* Only used for virtual mode
*/
STAILQ_HEAD(x2ap_eNB_instances_head_s, x2ap_eNB_instance_s) x2ap_eNB_instances_head;
/* Nb of registered eNBs */
uint8_t nb_registered_eNBs;
/* Generate a unique connexion id used between X2AP and SCTP */
uint16_t global_cnx_id;
} x2ap_eNB_internal_data_t;
int x2ap_eNB_compare_assoc_id(struct x2ap_eNB_data_s *p1, struct x2ap_eNB_data_s *p2);
/* Generate the tree management functions */
struct x2ap_eNB_map;
struct x2ap_eNB_data_s;
RB_PROTOTYPE(x2ap_eNB_map, x2ap_eNB_data_s, entry, x2ap_eNB_compare_assoc_id);
#endif /* X2AP_ENB_DEFS_H_ */

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,39 @@
/*******************************************************************************
OpenAirInterface
Copyright(c) 1999 - 2014 Eurecom
OpenAirInterface is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OpenAirInterface is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with OpenAirInterface.The full GNU General Public License is
included in this distribution in the file called "COPYING". If not,
see <http://www.gnu.org/licenses/>.
Contact Information
OpenAirInterface Admin: openair_admin@eurecom.fr
OpenAirInterface Tech : openair_tech@eurecom.fr
OpenAirInterface Dev : openair4g-devel@lists.eurecom.fr
Address : Eurecom, Compus SophiaTech 450, route des chappes, 06451 Biot, France.
*******************************************************************************/
#ifndef X2AP_ENB_ENCODER_H_
#define X2AP_ENB_ENCODER_H_
#include "x2ap_common.h"
#include "x2ap_ies_defs.h"
int x2ap_eNB_encode_pdu(x2ap_message *x2ap_message_p, uint8_t **buffer, uint32_t *len)
__attribute__ ((warn_unused_result));
#endif /* X2AP_ENB_ENCODER_H_ */

View File

@@ -0,0 +1,483 @@
/*******************************************************************************
OpenAirInterface
Copyright(c) 1999 - 2014 Eurecom
OpenAirInterface is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OpenAirInterface is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with OpenAirInterface.The full GNU General Public License is
included in this distribution in the file called "COPYING". If not,
see <http://www.gnu.org/licenses/>.
Contact Information
OpenAirInterface Admin: openair_admin@eurecom.fr
OpenAirInterface Tech : openair_tech@eurecom.fr
OpenAirInterface Dev : openair4g-devel@lists.eurecom.fr
Address : Eurecom, Campus SophiaTech, 450 Route des Chappes, CS 50193 - 06904 Biot Sophia Antipolis cedex, FRANCE
*******************************************************************************/
/*! \file x2ap_eNB_generate_messages.c
* \brief x2ap message generator
* \author Navid Nikaein
* \date 2015 - 2016
* \version 1.0
* \company Eurecom
* \email: navid.nikaein@eurecom.fr
*/
#include "intertask_interface.h"
#include "x2ap_eNB.h"
#include "x2ap_eNB_generate_messages.h"
#include "x2ap_eNB_encoder.h"
#include "x2ap_eNB_itti_messaging.h"
#include "RRC/LITE/defs.h"
#include "RRC/LITE/extern.h"
#include "secu_defs.h"
#include "rrc_eNB_UE_context.h"
#include "enb_config.h"
#include "msc.h"
#include "assertions.h"
#include "conversions.h"
extern unsigned char NB_eNB_INST;
extern int x2id_to_source_rnti[1];
int x2ap_eNB_generate_x2_setup_request(x2ap_eNB_instance_t *instance_p,
x2ap_eNB_data_t *x2ap_enb_data_p)
{
x2ap_message message;
X2SetupRequest_IEs_t *x2SetupRequest;
X2ap_PLMN_Identity_t plmnIdentity;
X2ap_PLMN_Identity_t broadcast_plmnIdentity_1;
X2ap_PLMN_Identity_t broadcast_plmnIdentity_2;
X2ap_PLMN_Identity_t broadcast_plmnIdentity_3;
X2ap_ServedCellItem_t *served_cell= malloc(sizeof(X2ap_ServedCellItem_t));
uint8_t *buffer;
uint32_t len;
int ret = 0;
DevAssert(instance_p != NULL);
DevAssert(x2ap_enb_data_p != NULL);
memset(&message, 0, sizeof(x2ap_message));
message.direction = X2AP_PDU_PR_initiatingMessage;
message.procedureCode = X2ap_ProcedureCode_id_x2Setup;
message.criticality = X2ap_Criticality_reject;
x2SetupRequest = &message.msg.x2SetupRequest_IEs;
memset((void *)&plmnIdentity, 0, sizeof(X2ap_PLMN_Identity_t));
memset((void *)&broadcast_plmnIdentity_1, 0, sizeof(X2ap_PLMN_Identity_t));
memset((void *)&broadcast_plmnIdentity_2, 0, sizeof(X2ap_PLMN_Identity_t));
memset((void *)&broadcast_plmnIdentity_3, 0, sizeof(X2ap_PLMN_Identity_t));
x2ap_enb_data_p->state = X2AP_ENB_STATE_WAITING;
//----globalENB_ID------
x2SetupRequest->globalENB_ID.eNB_ID.present = X2ap_ENB_ID_PR_macro_eNB_ID ;
MACRO_ENB_ID_TO_BIT_STRING(instance_p->eNB_id,
&x2SetupRequest->globalENB_ID.eNB_ID.choice.macro_eNB_ID);
MCC_MNC_TO_PLMNID(instance_p->mcc, instance_p->mnc, instance_p->mnc_digit_length,
&x2SetupRequest->globalENB_ID.pLMN_Identity);
X2AP_INFO("%d -> %02x%02x%02x\n", instance_p->eNB_id,
x2SetupRequest->globalENB_ID.eNB_ID.choice.macro_eNB_ID.buf[0],
x2SetupRequest->globalENB_ID.eNB_ID.choice.macro_eNB_ID.buf[1],
x2SetupRequest->globalENB_ID.eNB_ID.choice.macro_eNB_ID.buf[2]);
//----served cells------
#warning update the value of the message
served_cell->servedCellInfo.pCI = 6;
served_cell->servedCellInfo.eUTRA_Mode_Info.present = X2ap_EUTRA_Mode_Info_PR_fDD;
served_cell->servedCellInfo.eUTRA_Mode_Info.choice.fDD.uL_EARFCN = 3350;
served_cell->servedCellInfo.eUTRA_Mode_Info.choice.fDD.dL_EARFCN = 3350;
served_cell->servedCellInfo.eUTRA_Mode_Info.choice.fDD.uL_Transmission_Bandwidth = 0;
served_cell->servedCellInfo.eUTRA_Mode_Info.choice.fDD.dL_Transmission_Bandwidth = 0;
MCC_MNC_TO_PLMNID(instance_p->mcc,instance_p->mnc,instance_p->mnc_digit_length,
&served_cell->servedCellInfo.cellId.pLMN_Identity);
MCC_MNC_TO_PLMNID(instance_p->mcc, instance_p->mnc,instance_p->mnc_digit_length,&broadcast_plmnIdentity_1);
MCC_MNC_TO_PLMNID(instance_p->mcc, instance_p->mnc,instance_p->mnc_digit_length,&broadcast_plmnIdentity_2);
MCC_MNC_TO_PLMNID(instance_p->mcc, instance_p->mnc,instance_p->mnc_digit_length,&broadcast_plmnIdentity_3);
ASN_SEQUENCE_ADD(&served_cell->servedCellInfo.broadcastPLMNs.list, &broadcast_plmnIdentity_1);
ASN_SEQUENCE_ADD(&served_cell->servedCellInfo.broadcastPLMNs.list, &broadcast_plmnIdentity_2);
ASN_SEQUENCE_ADD(&served_cell->servedCellInfo.broadcastPLMNs.list, &broadcast_plmnIdentity_3);
ECI_TO_BIT_STRING(instance_p->eNB_id, &served_cell->servedCellInfo.cellId.eUTRANcellIdentifier);
TAC_TO_OCTET_STRING(instance_p->tac, &served_cell->servedCellInfo.tAC);
ASN_SEQUENCE_ADD(&x2SetupRequest->servedCells.list, served_cell);
if (x2ap_eNB_encode_pdu(&message, &buffer, &len) < 0) {
X2AP_ERROR("Failed to encode X2 setup request\n");
return -1;
}
MSC_LOG_TX_MESSAGE (MSC_X2AP_SRC_ENB, MSC_X2AP_TARGET_ENB, NULL, 0, "0 X2Setup/initiatingMessage assoc_id %u", x2ap_enb_data_p->assoc_id);
/* Non UE-Associated signalling -> stream = 0 */
x2ap_eNB_itti_send_sctp_data_req(instance_p->instance, x2ap_enb_data_p->assoc_id, buffer, len, 0);
return ret;
}
int
x2ap_generate_x2_setup_response (x2ap_eNB_data_t * eNB_association)
{
x2ap_eNB_instance_t *instance=eNB_association->x2ap_eNB_instance;
x2ap_message message;
X2SetupResponse_IEs_t *x2SetupResponse;
// X2ap_PLMN_Identity_t plmnIdentity;
X2ap_PLMN_Identity_t broadcast_plmnIdentity_1;
X2ap_PLMN_Identity_t broadcast_plmnIdentity_2;
X2ap_PLMN_Identity_t broadcast_plmnIdentity_3;
X2ap_ServedCellItem_t *served_cell = calloc(1, sizeof(X2ap_ServedCellItem_t));;
uint8_t *buffer;
uint32_t len;
int ret = 0;
// get the eNB instance
//
DevAssert (eNB_association != NULL);
// Generating response
memset (&message, 0, sizeof (x2ap_message));
message.direction = X2AP_PDU_PR_successfulOutcome;
message.procedureCode = X2ap_ProcedureCode_id_x2Setup;
message.criticality = X2ap_Criticality_reject;
x2SetupResponse = &message.msg.x2SetupResponse_IEs;
// memset((void *)&plmnIdentity, 0, sizeof(X2ap_PLMN_Identity_t));
memset((void *)&broadcast_plmnIdentity_1, 0, sizeof(X2ap_PLMN_Identity_t));
memset((void *)&broadcast_plmnIdentity_2, 0, sizeof(X2ap_PLMN_Identity_t));
memset((void *)&broadcast_plmnIdentity_3, 0, sizeof(X2ap_PLMN_Identity_t));
//----globalENB_ID------
x2SetupResponse->globalENB_ID.eNB_ID.present = X2ap_ENB_ID_PR_macro_eNB_ID;
MACRO_ENB_ID_TO_BIT_STRING(instance->eNB_id,
&x2SetupResponse->globalENB_ID.eNB_ID.choice.macro_eNB_ID);
MCC_MNC_TO_PLMNID(instance->mcc, instance->mnc, instance->mnc_digit_length,
&x2SetupResponse->globalENB_ID.pLMN_Identity);
X2AP_INFO("%d -> %02x%02x%02x\n", instance->eNB_id,
x2SetupResponse->globalENB_ID.eNB_ID.choice.macro_eNB_ID.buf[0],
x2SetupResponse->globalENB_ID.eNB_ID.choice.macro_eNB_ID.buf[1],
x2SetupResponse->globalENB_ID.eNB_ID.choice.macro_eNB_ID.buf[2]);
//----served cells------
#warning update the value of the message
served_cell->servedCellInfo.pCI = 6;
served_cell->servedCellInfo.eUTRA_Mode_Info.present = X2ap_EUTRA_Mode_Info_PR_fDD;
served_cell->servedCellInfo.eUTRA_Mode_Info.choice.fDD.uL_EARFCN = 3350;
served_cell->servedCellInfo.eUTRA_Mode_Info.choice.fDD.dL_EARFCN = 3350;
served_cell->servedCellInfo.eUTRA_Mode_Info.choice.fDD.uL_Transmission_Bandwidth = 0;
served_cell->servedCellInfo.eUTRA_Mode_Info.choice.fDD.dL_Transmission_Bandwidth = 0;
MCC_MNC_TO_PLMNID(instance->mcc,instance->mnc,instance->mnc_digit_length,&served_cell->servedCellInfo.cellId.pLMN_Identity);
MCC_MNC_TO_PLMNID(instance->mcc, instance->mnc, instance->mnc_digit_length,&broadcast_plmnIdentity_1);
MCC_MNC_TO_PLMNID(instance->mcc, instance->mnc, instance->mnc_digit_length,&broadcast_plmnIdentity_2);
MCC_MNC_TO_PLMNID(instance->mcc, instance->mnc, instance->mnc_digit_length,&broadcast_plmnIdentity_3);
ASN_SEQUENCE_ADD(&served_cell->servedCellInfo.broadcastPLMNs.list, &broadcast_plmnIdentity_1);
ASN_SEQUENCE_ADD(&served_cell->servedCellInfo.broadcastPLMNs.list, &broadcast_plmnIdentity_2);
ASN_SEQUENCE_ADD(&served_cell->servedCellInfo.broadcastPLMNs.list, &broadcast_plmnIdentity_3);
ECI_TO_BIT_STRING(instance->eNB_id, &served_cell->servedCellInfo.cellId.eUTRANcellIdentifier);
TAC_TO_OCTET_STRING(instance->tac, &served_cell->servedCellInfo.tAC);
ASN_SEQUENCE_ADD(&x2SetupResponse->servedCells.list, served_cell);
if (x2ap_eNB_encode_pdu(&message, &buffer, &len) < 0) {
X2AP_ERROR("Failed to encode X2 setup request\n");
return -1;
}
eNB_association->state = X2AP_ENB_STATE_READY;
MSC_LOG_TX_MESSAGE (MSC_X2AP_TARGET_ENB, MSC_X2AP_SRC_ENB, NULL, 0, "0 X2Setup/successfulOutcome assoc_id %u", eNB_association->assoc_id);
/*
* Non-UE signalling -> stream 0
*/
x2ap_eNB_itti_send_sctp_data_req (instance->instance, eNB_association->assoc_id, buffer, len, 0);
return ret;
}
int x2ap_eNB_set_cause (X2ap_Cause_t * cause_p,
X2ap_Cause_PR cause_type,
long cause_value);
int x2ap_eNB_generate_x2_setup_failure ( uint32_t assoc_id,
X2ap_Cause_PR cause_type,
long cause_value,
long time_to_wait){
uint8_t *buffer_p;
uint32_t length;
x2ap_message message;
X2SetupFailure_IEs_t *x2_setup_failure_p;
int ret = 0;
memset (&message, 0, sizeof (x2ap_message));
x2_setup_failure_p = &message.msg.x2SetupFailure_IEs;
message.procedureCode = X2ap_ProcedureCode_id_x2Setup;
message.direction = X2AP_PDU_PR_unsuccessfulOutcome;
x2ap_eNB_set_cause (&x2_setup_failure_p->cause, cause_type, cause_value);
if (time_to_wait > -1) {
x2_setup_failure_p->presenceMask |= X2SETUPFAILURE_IES_TIMETOWAIT_PRESENT;
x2_setup_failure_p->timeToWait = time_to_wait;
}
if (x2ap_eNB_encode_pdu (&message, &buffer_p, &length) < 0) {
X2AP_ERROR ("Failed to encode x2 setup failure\n");
return -1;
}
MSC_LOG_TX_MESSAGE (MSC_X2AP_SRC_ENB,
MSC_X2AP_TARGET_ENB, NULL, 0,
"0 X2Setup/unsuccessfulOutcome assoc_id %u cause %u value %u",
assoc_id, cause_type, cause_value);
x2ap_eNB_itti_send_sctp_data_req (/* instance? */ 0, assoc_id, buffer_p, length, 0);
return ret;
}
int x2ap_eNB_set_cause (X2ap_Cause_t * cause_p,
X2ap_Cause_PR cause_type,
long cause_value)
{
DevAssert (cause_p != NULL);
cause_p->present = cause_type;
switch (cause_type) {
case X2ap_Cause_PR_radioNetwork:
cause_p->choice.misc = cause_value;
break;
case X2ap_Cause_PR_transport:
cause_p->choice.transport = cause_value;
break;
case X2ap_Cause_PR_protocol:
cause_p->choice.protocol = cause_value;
break;
case X2ap_Cause_PR_misc:
cause_p->choice.misc = cause_value;
break;
default:
return -1;
}
return 0;
}
int x2ap_eNB_generate_x2_handover_request(x2ap_eNB_instance_t *instance_p,
x2ap_eNB_data_t *x2ap_enb_data_p,
int source_x2id)
{
/* TODO: set correct values in there */
x2ap_message message;
uint8_t *buffer;
uint32_t len;
int ret = 0;
DevAssert(instance_p != NULL);
DevAssert(x2ap_enb_data_p != NULL);
memset(&message, 0, sizeof(x2ap_message));
message.direction = X2AP_PDU_PR_initiatingMessage;
message.procedureCode = X2ap_ProcedureCode_id_handoverPreparation;
message.criticality = X2ap_Criticality_reject;
message.msg.x2ap_HandoverRequest_IEs.old_eNB_UE_X2AP_ID = source_x2id;
message.msg.x2ap_HandoverRequest_IEs.cause.present = X2ap_Cause_PR_radioNetwork;
message.msg.x2ap_HandoverRequest_IEs.cause.choice.radioNetwork = X2ap_CauseRadioNetwork_handover_desirable_for_radio_reasons;
MCC_MNC_TO_PLMNID(123, 456, 3, &message.msg.x2ap_HandoverRequest_IEs.targetCell_ID.pLMN_Identity);
int eci1 = 79;
ECI_TO_BIT_STRING(eci1, &message.msg.x2ap_HandoverRequest_IEs.targetCell_ID.eUTRANcellIdentifier);
MCC_MNC_TO_PLMNID(456, 123, 3, &message.msg.x2ap_HandoverRequest_IEs.gummei_id.gU_Group_ID.pLMN_Identity);
MMEGID_TO_OCTET_STRING(26, &message.msg.x2ap_HandoverRequest_IEs.gummei_id.gU_Group_ID.mME_Group_ID);
MMEC_TO_OCTET_STRING(12, &message.msg.x2ap_HandoverRequest_IEs.gummei_id.mME_Code);
message.msg.x2ap_HandoverRequest_IEs.uE_ContextInformation.mME_UE_S1AP_ID = 12;
ENCRALG_TO_BIT_STRING(0,&message.msg.x2ap_HandoverRequest_IEs.uE_ContextInformation.uESecurityCapabilities.encryptionAlgorithms);
INTPROTALG_TO_BIT_STRING(0,&message.msg.x2ap_HandoverRequest_IEs.uE_ContextInformation.uESecurityCapabilities.integrityProtectionAlgorithms);
uint8_t KeNB_star[32] = { 0 };
// find UE context
// use hack defined in x2ap_eNB.c in x2ap_eNB_handle_handover_req(...):
if ((instance_p->instance < 0) || (instance_p->instance >= NB_eNB_INST)) {
X2AP_ERROR("Failed to find RRC eNB instance %d\n", instance_p->instance);
return -1;
}
eNB_RRC_INST* rrc_instance = &eNB_rrc_inst[instance_p->instance];
struct rrc_eNB_ue_context_s* rrc_eNB_ue_context = rrc_eNB_get_ue_context(rrc_instance, x2id_to_source_rnti[0]);
if (!rrc_eNB_ue_context) {
X2AP_ERROR("Failed to find RRC UE context RNTI %X\n", x2id_to_source_rnti[0]);
return -1;
}
const Enb_properties_array_t *enb_properties = enb_config_get();
uint16_t pci = enb_properties->properties[instance_p->instance]->Nid_cell[0];
uint32_t earfcn_dl = (uint32_t)freq_to_arfcn10(enb_properties->properties[instance_p->instance]->eutra_band[0],
enb_properties->properties[instance_p->instance]->downlink_frequency[0]);
if (rrc_eNB_ue_context->ue_context.nh_ncc >= 0) {
derive_keNB_star (rrc_eNB_ue_context->ue_context.nh, pci, earfcn_dl, false, KeNB_star);
message.msg.x2ap_HandoverRequest_IEs.uE_ContextInformation.aS_SecurityInformation.nextHopChainingCount = rrc_eNB_ue_context->ue_context.nh_ncc;
} else { // first HO
derive_keNB_star (rrc_eNB_ue_context->ue_context.kenb, pci, earfcn_dl, false, KeNB_star);
// LG: really 1 ?
message.msg.x2ap_HandoverRequest_IEs.uE_ContextInformation.aS_SecurityInformation.nextHopChainingCount = 1;
}
KENB_STAR_TO_BIT_STRING(KeNB_star,&message.msg.x2ap_HandoverRequest_IEs.uE_ContextInformation.aS_SecurityInformation.key_eNodeB_star);
UEAGMAXBITRTD_TO_ASN_PRIMITIVES(3L,&message.msg.x2ap_HandoverRequest_IEs.uE_ContextInformation.uEaggregateMaximumBitRate.uEaggregateMaximumBitRateDownlink);
UEAGMAXBITRTU_TO_ASN_PRIMITIVES(6L,&message.msg.x2ap_HandoverRequest_IEs.uE_ContextInformation.uEaggregateMaximumBitRate.uEaggregateMaximumBitRateUplink);
X2ap_E_RABs_ToBeSetup_Item_t *e_RABs_ToBeSetup_Item1 = calloc(1, sizeof(X2ap_E_RABs_ToBeSetup_Item_t));
e_RABs_ToBeSetup_Item1->e_RAB_ID=10;
e_RABs_ToBeSetup_Item1->e_RAB_Level_QoS_Parameters.qCI=1;
e_RABs_ToBeSetup_Item1->e_RAB_Level_QoS_Parameters.allocationAndRetentionPriority.priorityLevel = 1;
e_RABs_ToBeSetup_Item1->e_RAB_Level_QoS_Parameters.allocationAndRetentionPriority.pre_emptionCapability = 0;
e_RABs_ToBeSetup_Item1->e_RAB_Level_QoS_Parameters.allocationAndRetentionPriority.pre_emptionVulnerability = 0;
e_RABs_ToBeSetup_Item1->e_RAB_Level_QoS_Parameters.allocationAndRetentionPriority.iE_Extensions = NULL;
TRLA_TO_BIT_STRING(1, &e_RABs_ToBeSetup_Item1->uL_GTPtunnelEndpoint.transportLayerAddress); // IPv4
GTP_TEID_TO_OCTET_STRING (12, &e_RABs_ToBeSetup_Item1->uL_GTPtunnelEndpoint.gTP_TEID);
X2ap_E_RABs_ToBeSetup_ListIEs_t *e_RABs_ToBeSetup_List1 = calloc(1, sizeof(X2ap_E_RABs_ToBeSetup_ListIEs_t));
ASN_SEQUENCE_ADD(e_RABs_ToBeSetup_List1, e_RABs_ToBeSetup_Item1);
x2ap_encode_x2ap_e_rabs_tobesetup_list(&message.msg.x2ap_HandoverRequest_IEs.uE_ContextInformation.e_RABs_ToBeSetup_List, e_RABs_ToBeSetup_List1);
#if 0
char RRC[81] = { 0x0a,0x10,0x00,0x00,0x03,0x41,0x60,0x08,0xcf,0x50,0x4a,0x0e,0x07,0x00,0x8c,0xf5,0x04,0xa0,0xe0,0x03,0xc0,0x51,0xc2,0x28,
0xb8,0x56,0xd1,0x80,0x4a,0x00,0x00,0x08,0x18,0x02,0x20,0x42,0x08,0x00,0x80,0x60,0x00,0x20,0x00,0x00,0x03,0x82,0xca,0x04,
0x06,0x14,0x08,0x0f,0x59,0x95,0x64,0x80,0x00,0x02,0x0a,0x5a,0x00,0x20,0x00,0x08,0x04,0x01,0x2f,0x39,0x57,0x96,0xde,0xc0,
0x00,0x88,0xea,0x46,0x7d,0x10,0x00,0x03,0x40 };
#endif
char RRC[] = {
0x0A,0x10,0x31,0xC5,0x20,0x00,0x05,0x00,0x10,0x40,0xC1,0xC9,0x85,0x8B,0xF8,0xDF,0xE2,0xFE,0x37,0xF8,0xBF,0x8D,0xFE,0x2F,0xE3,0x7F,0x8B,0xF8,0xDF,0xE2,0xFE,0x37,0xF7,0xF0,0xFF,0xE9,0x88,0x81,0x00,0x87,0x0C,0xA7,0x4A,0x92,0x20,0x20,0x58,0x00,0x00,0x00,0x00,0x00,0x15,0xD8,0x00,0x00,0x06,0x8B,0x02,0x00,0x02,0x90,0x21,0x59,0x70,0x00,0x00,0x72,0xA2,0x40,0x37,0xB0,0x11,0xFA,0x9C,0x0B,0x81,0x1F,0xA9,0xC0,0x83,0xEA,0x26,0xE0,0x25,0x75,0x38,0xA1,0xD8,0x84,0xF9,0x80,0x3E,0x55,0x8F,0xFD,0x15,0x35,0x86,0x1C,0x86,0xC8,0xA1,0x82,0x40,0xA1,0x35,0x00,0x00,0x00,0x24,0x10,0x92,0x80,0x02,0x00,0x00,0x10,0x2C,0x00,0x30,0x00,0x40,0xF6,0x07,0xCA,0xCB,0xB2,0x4C,0x00,0x6C,0x05,0x35,0x00,0x10,0x00,0x04,0x01,0x00,0xF7,0x52,0xAB,0xCA,0xF7,0x20,0x07,0x43,0x45,0xA0,0x1E,0xB8,0xE0,
};
OCTET_STRING_fromBuf(&message.msg.x2ap_HandoverRequest_IEs.uE_ContextInformation.rRC_Context, (char*) RRC, sizeof(RRC));
X2ap_LastVisitedCell_Item_t *lastVisitedCell_Item1 = calloc(1, sizeof(X2ap_LastVisitedCell_Item_t));
lastVisitedCell_Item1->present = X2ap_LastVisitedCell_Item_PR_e_UTRAN_Cell;
lastVisitedCell_Item1->choice.e_UTRAN_Cell.cellType.cell_Size=1;
lastVisitedCell_Item1->choice.e_UTRAN_Cell.time_UE_StayedInCell=2;
MCC_MNC_TO_PLMNID(987,765, 3, &lastVisitedCell_Item1->choice.e_UTRAN_Cell.global_Cell_ID.pLMN_Identity);
int eci2 = 55;
ECI_TO_BIT_STRING(eci2,&lastVisitedCell_Item1->choice.e_UTRAN_Cell.global_Cell_ID.eUTRANcellIdentifier);
ASN_SEQUENCE_ADD(&message.msg.x2ap_HandoverRequest_IEs.uE_HistoryInformation.list,lastVisitedCell_Item1);
if (x2ap_eNB_encode_pdu(&message, &buffer, &len) < 0) {
X2AP_ERROR("Failed to encode X2 setup request\n");
abort();
return -1;
}
/* TODO: use correct stream, 1 for the moment */
x2ap_eNB_itti_send_sctp_data_req(instance_p->instance, x2ap_enb_data_p->assoc_id, buffer, len, 1);
return ret;
}
int x2ap_eNB_generate_x2_handover_req_ack(x2ap_eNB_instance_t *instance,
x2ap_eNB_data_t *x2ap_enb_data_p,
int source_x2id)
{
x2ap_message message;
uint8_t *buffer;
uint32_t len;
int ret = 0;
// Generating response
memset (&message, 0, sizeof (x2ap_message));
X2ap_E_RABs_Admitted_ListIEs_t *e_RABs_Admitted_List1;
X2ap_E_RABs_Admitted_Item_t *e_RABs_Admitted_Item1;
e_RABs_Admitted_Item1 = calloc(1, sizeof(X2ap_E_RABs_Admitted_Item_t));
e_RABs_Admitted_List1 = calloc(1, sizeof(X2ap_E_RABs_Admitted_ListIEs_t));
asn1_xer_print = 1;
asn_debug = 0;
X2ap_ProcedureCode_t procedure = X2ap_ProcedureCode_id_handoverPreparation;
X2ap_Criticality_t criticality = X2ap_Criticality_reject;
X2AP_PDU_PR present;
present = X2AP_PDU_PR_successfulOutcome;
message.procedureCode = procedure;
message.criticality= criticality;
message.direction = present;
//data is in file RRC_Context_acknowledge.txt
uint8_t RRC[63] = { 0x01,0xe9,0x00,0x90,0xa8,0x00,0x00,0x22,0x33,0xe9,0x42,0x80,0x02,0xf0,0x80,0x9e,0x20,0x23,0xc6,0x05,0x79,0x00,0xef,0x28,
0x21,0xe1,0x01,0x24,0x38,0x40,0x05,0x00,0x12,0x1c,0xa0,0x00,0x02,0x00,0x88,0x02,0x18,0x06,0x40,0x10,0xa0,0x2b,0x43,0x81,
0x1d,0xd9,0xc0,0x30,0x70,0x00,0xe0,0x21,0xc3,0x17,0x01,0x74,0x60,0x12,0x80 };
message.msg.x2ap_HandoverRequestAcknowledge_IEs.old_eNB_UE_X2AP_ID = source_x2id;
message.msg.x2ap_HandoverRequestAcknowledge_IEs.new_eNB_UE_X2AP_ID= 2001;
e_RABs_Admitted_Item1->e_RAB_ID=12;
e_RABs_Admitted_Item1->iE_Extensions = NULL;
ASN_SEQUENCE_ADD(e_RABs_Admitted_List1, e_RABs_Admitted_Item1);
memcpy(&message.msg.x2ap_HandoverRequestAcknowledge_IEs.e_RABs_Admitted_List, e_RABs_Admitted_List1, sizeof(X2ap_E_RABs_Admitted_ListIEs_t));
OCTET_STRING_fromBuf(&message.msg.x2ap_HandoverRequestAcknowledge_IEs.targeteNBtoSource_eNBTransparentContainer, (char*) RRC, sizeof(RRC));
if (x2ap_eNB_encode_pdu(&message, &buffer, &len) < 0) {
X2AP_ERROR("Failed to encode X2 handover response\n");
abort();
return -1;
}
//eNB_association->state = X2AP_ENB_STATE_READY;
/* TODO: use correct stream, 1 for the moment */
x2ap_eNB_itti_send_sctp_data_req(instance->instance, x2ap_enb_data_p->assoc_id, buffer, len, 1);
return ret;
}

View File

@@ -0,0 +1,54 @@
/*******************************************************************************
OpenAirInterface
Copyright(c) 1999 - 2014 Eurecom
OpenAirInterface is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OpenAirInterface is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with OpenAirInterface.The full GNU General Public License is
included in this distribution in the file called "COPYING". If not,
see <http://www.gnu.org/licenses/>.
Contact Information
OpenAirInterface Admin: openair_admin@eurecom.fr
OpenAirInterface Tech : openair_tech@eurecom.fr
OpenAirInterface Dev : openair4g-devel@lists.eurecom.fr
Address : Eurecom, Compus SophiaTech 450, route des chappes, 06451 Biot, France.
*******************************************************************************/
#ifndef X2AP_ENB_GENERATE_MESSAGES_H_
#define X2AP_ENB_GENERATE_MESSAGES_H_
#include "x2ap_eNB_defs.h"
#include "x2ap_ies_defs.h"
int x2ap_eNB_generate_x2_setup_request(x2ap_eNB_instance_t *instance_p,
x2ap_eNB_data_t *x2ap_enb_data_p);
int
x2ap_generate_x2_setup_response (x2ap_eNB_data_t * eNB_association);
int x2ap_eNB_generate_x2_setup_failure ( uint32_t assoc_id,
X2ap_Cause_PR cause_type,
long cause_value,
long time_to_waitx);
int x2ap_eNB_generate_x2_handover_request(x2ap_eNB_instance_t *instance_p,
x2ap_eNB_data_t *x2ap_enb_data_p,
int source_x2id);
int x2ap_eNB_generate_x2_handover_request_ack(x2ap_eNB_instance_t *instance_p,
x2ap_eNB_data_t *x2ap_enb_data_p,
int source_x2id);
#endif /* X2AP_ENB_GENERATE_MESSAGES_H_ */

View File

@@ -0,0 +1,849 @@
/*******************************************************************************
OpenAirInterface
Copyright(c) 1999 - 2014 Eurecom
OpenAirInterface is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OpenAirInterface is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with OpenAirInterface.The full GNU General Public License is
included in this distribution in the file called "COPYING". If not,
see <http://www.gnu.org/licenses/>.
Contact Information
OpenAirInterface Admin: openair_admin@eurecom.fr
OpenAirInterface Tech : openair_tech@eurecom.fr
OpenAirInterface Dev : openair4g-devel@lists.eurecom.fr
Address : Eurecom, Compus SophiaTech 450, route des chappes, 06451 Biot, France.
*******************************************************************************/
/*! \file x2ap_eNB_handlers.c
* \brief x2ap messages handlers for eNB part
* \author Navid Nikaein
* \date 2016
* \version 0.1
*/
#include <stdint.h>
#include "intertask_interface.h"
#include "asn1_conversions.h"
#include "x2ap_common.h"
#include "x2ap_ies_defs.h"
#include "x2ap_eNB_defs.h"
#include "x2ap_eNB_handler.h"
#include "x2ap_eNB_decoder.h"
#include "x2ap_eNB_management_procedures.h"
#include "x2ap_eNB_generate_messages.h"
//#include "x2ap_eNB_default_values.h"
#include "assertions.h"
#include "conversions.h"
#include "msc.h"
static
int x2ap_eNB_handle_handover_preparation(uint32_t assoc_id,
uint32_t stream,
struct x2ap_message_s *message);
static
int x2ap_eNB_handle_handover_response(uint32_t assoc_id,
uint32_t stream,
struct x2ap_message_s *message);
static
int x2ap_eNB_handle_x2_setup_request (uint32_t assoc_id,
uint32_t stream,
struct x2ap_message_s *message);
static
int x2ap_eNB_handle_x2_setup_response(uint32_t assoc_id,
uint32_t stream,
struct x2ap_message_s *message_p);
static
int x2ap_eNB_handle_x2_setup_failure(uint32_t assoc_id,
uint32_t stream,
struct x2ap_message_s *message_p);
static
int x2ap_eNB_handle_error_indication(uint32_t assoc_id,
uint32_t stream,
struct x2ap_message_s *message_p);
int x2ap_eNB_handle_initial_context_request(uint32_t assoc_id,
uint32_t stream,
struct x2ap_message_s *message_p);
static
int x2ap_eNB_handle_ue_context_release_command(uint32_t assoc_id,
uint32_t stream,
struct x2ap_message_s *message_p);
/* Handlers matrix. Only eNB related procedure present here */
// x2ap_messages_callback[message.procedureCode][message.direction]
x2ap_message_decoded_callback x2ap_messages_callback[][3] = {
// { x2ap_eNB_handle_handover_preparation, 0, 0 }, /* HandoverPreparation */
{ x2ap_eNB_handle_handover_preparation, x2ap_eNB_handle_handover_response, 0 }, /* HandoverPreparation */
{ 0, 0, 0 }, /* HandoverCancel */
{ 0, 0, 0 }, /* loadIndication */
{ x2ap_eNB_handle_error_indication, 0, 0 }, /* errorIndication */
{ 0, 0, 0 }, /* snStatusTransfer */
{ 0, 0, 0 }, /* uEContextRelease */
{ x2ap_eNB_handle_x2_setup_request, x2ap_eNB_handle_x2_setup_response, x2ap_eNB_handle_x2_setup_failure }, /* x2Setup */
{ 0, 0, 0 }, /* reset */
{ 0, 0, 0 }, /* eNBConfigurationUpdate */
{ 0, 0, 0 }, /* resourceStatusReportingInitiation */
{ 0, 0, 0 }, /* resourceStatusReporting */
{ 0, 0, 0 }, /* privateMessage */
{ 0, 0, 0 }, /* mobilitySettingsChange */
{ 0, 0, 0 }, /* rLFIndication */
{ 0, 0, 0 }, /* handoverReport */
{ 0, 0, 0 } /* cellActivation */
};
static const char *x2ap_direction2String[] = {
"", /* Nothing */
"Originating message", /* originating message */
"Successfull outcome", /* successfull outcome */
"UnSuccessfull outcome", /* successfull outcome */
};
int x2ap_eNB_handle_message(uint32_t assoc_id, int32_t stream,
const uint8_t * const data, const uint32_t data_length)
{
struct x2ap_message_s message;
DevAssert(data != NULL);
memset(&message, 0, sizeof(struct x2ap_message_s));
if (x2ap_eNB_decode_pdu(&message, data, data_length) < 0) {
X2AP_ERROR("Failed to decode X2AP PDU\n");
return -1;
}
/* Checking procedure Code and direction of message */
if (message.procedureCode > sizeof(x2ap_messages_callback) / (3 * sizeof(x2ap_message_decoded_callback))
|| (message.direction > X2AP_PDU_PR_unsuccessfulOutcome)) {
X2AP_ERROR("[SCTP %d] Either procedureCode %d or direction %d exceed expected\n",
assoc_id, message.procedureCode, message.direction);
return -1;
}
/* No handler present.
* This can mean not implemented or no procedure for eNB (wrong direction).
*/
if (x2ap_messages_callback[message.procedureCode][message.direction-1] == NULL) {
X2AP_ERROR("[SCTP %d] No handler for procedureCode %d in %s\n",
assoc_id, message.procedureCode,
x2ap_direction2String[message.direction]);
return -1;
}
/* Calling the right handler */
return (*x2ap_messages_callback[message.procedureCode][message.direction-1])
(assoc_id, stream, &message);
}
void x2ap_handle_x2_setup_message(x2ap_eNB_data_t *enb_desc_p, int sctp_shutdown)
{
if (sctp_shutdown) {
/* A previously connected eNB has been shutdown */
/* TODO check if it was used by some eNB and send a message to inform these eNB if there is no more associated MME */
if (enb_desc_p->state == X2AP_ENB_STATE_CONNECTED) {
enb_desc_p->state = X2AP_ENB_STATE_DISCONNECTED;
if (enb_desc_p->x2ap_eNB_instance-> x2_target_enb_associated_nb > 0) {
/* Decrease associated eNB number */
enb_desc_p->x2ap_eNB_instance-> x2_target_enb_associated_nb --;
}
/* If there are no more associated eNB, inform eNB app */
if (enb_desc_p->x2ap_eNB_instance->x2_target_enb_associated_nb == 0) {
MessageDef *message_p;
message_p = itti_alloc_new_message(TASK_X2AP, X2AP_DEREGISTERED_ENB_IND);
X2AP_DEREGISTERED_ENB_IND(message_p).nb_x2 = 0;
itti_send_msg_to_task(TASK_ENB_APP, enb_desc_p->x2ap_eNB_instance->instance, message_p);
}
}
} else {
/* Check that at least one setup message is pending */
DevCheck(enb_desc_p->x2ap_eNB_instance->x2_target_enb_pending_nb > 0,
enb_desc_p->x2ap_eNB_instance->instance,
enb_desc_p->x2ap_eNB_instance->x2_target_enb_pending_nb, 0);
if (enb_desc_p->x2ap_eNB_instance->x2_target_enb_pending_nb > 0) {
/* Decrease pending messages number */
enb_desc_p->x2ap_eNB_instance->x2_target_enb_pending_nb --;
}
/* If there are no more pending messages, inform eNB app */
if (enb_desc_p->x2ap_eNB_instance->x2_target_enb_pending_nb == 0) {
MessageDef *message_p;
message_p = itti_alloc_new_message(TASK_X2AP, X2AP_REGISTER_ENB_CNF);
X2AP_REGISTER_ENB_CNF(message_p).nb_x2 = enb_desc_p->x2ap_eNB_instance->x2_target_enb_associated_nb;
itti_send_msg_to_task(TASK_ENB_APP, enb_desc_p->x2ap_eNB_instance->instance, message_p);
}
}
}
int
x2ap_eNB_handle_handover_preparation(uint32_t assoc_id,
uint32_t stream,
struct x2ap_message_s *message)
{
X2ap_HandoverRequest_IEs_t *x2HandoverRequest;
x2ap_eNB_data_t *x2ap_eNB_data;
uint32_t eNB_id = 0;
int ta_ret;
//uint16_t max_enb_connected;
MessageDef *m;
DevAssert (message != NULL);
x2HandoverRequest = &message->msg.x2ap_HandoverRequest_IEs;
if (stream == 0) {
X2AP_ERROR ("Received new x2 handover request on stream == 0\n");
/* TODO: send a x2 failure response */
return 0;
}
X2AP_DEBUG ("Received a new X2 handover request\n");
x2ap_eNB_data = x2ap_get_eNB(NULL, assoc_id, 0);
DevAssert(x2ap_eNB_data != NULL);
m = itti_alloc_new_message(TASK_X2AP, X2AP_HANDOVER_REQ);
/* TODO: fill the message */
extern int x2id_to_source_rnti[1];
X2AP_HANDOVER_REQ(m).source_x2id = x2HandoverRequest->old_eNB_UE_X2AP_ID;
X2AP_HANDOVER_REQ(m).source_rnti = x2id_to_source_rnti[x2HandoverRequest->old_eNB_UE_X2AP_ID];
if ((x2HandoverRequest->uE_ContextInformation.aS_SecurityInformation.key_eNodeB_star.buf) &&
(x2HandoverRequest->uE_ContextInformation.aS_SecurityInformation.key_eNodeB_star.size == 256)) {
memcpy(X2AP_HANDOVER_REQ(m).kenb, x2HandoverRequest->uE_ContextInformation.aS_SecurityInformation.key_eNodeB_star.buf, 32);
X2AP_HANDOVER_REQ(m).kenb_ncc = x2HandoverRequest->uE_ContextInformation.aS_SecurityInformation.nextHopChainingCount;
itti_send_msg_to_task(TASK_RRC_ENB, x2ap_eNB_data->x2ap_eNB_instance->instance, m);
return 0;
} else {
return -1;
}
#if 0
if (x2SetupRequest->globalENB_ID.eNB_ID.present == X2ap_ENB_ID_PR_home_eNB_ID) {
// Home eNB ID = 28 bits
uint8_t *eNB_id_buf = x2SetupRequest->globalENB_ID.eNB_ID.choice.home_eNB_ID.buf;
if (x2SetupRequest->globalENB_ID.eNB_ID.choice.macro_eNB_ID.size != 28) {
//TODO: handle case were size != 28 -> notify ? reject ?
}
eNB_id = (eNB_id_buf[0] << 20) + (eNB_id_buf[1] << 12) + (eNB_id_buf[2] << 4) + ((eNB_id_buf[3] & 0xf0) >> 4);
X2AP_DEBUG ("Home eNB id: %07x\n", eNB_id);
} else {
// Macro eNB = 20 bits
uint8_t *eNB_id_buf = x2SetupRequest->globalENB_ID.eNB_ID.choice.macro_eNB_ID.buf;
if (x2SetupRequest->globalENB_ID.eNB_ID.choice.macro_eNB_ID.size != 20) {
//TODO: handle case were size != 20 -> notify ? reject ?
}
eNB_id = (eNB_id_buf[0] << 12) + (eNB_id_buf[1] << 4) + ((eNB_id_buf[2] & 0xf0) >> 4);
X2AP_DEBUG ("macro eNB id: %05x\n", eNB_id);
}
/*
* If none of the provided PLMNs/TAC match the one configured in MME,
* * * * the x2 setup should be rejected with a cause set to Unknown PLMN.
*/
// ta_ret = x2ap_eNB_compare_ta_lists (&x2SetupRequest_p->supportedTAs);
/*
* Source and Target eNBs have no common PLMN
*/
/*
if (ta_ret != TA_LIST_RET_OK) {
X2AP_ERROR ("No Common PLMN with the target eNB, generate_x2_setup_failure\n");
return x2ap_eNB_generate_x2_setup_failure (assoc_id,
X2ap_Cause_PR_misc,
X2ap_CauseMisc_unknown_PLMN,
X2ap_TimeToWait_v20s);
}
*/
X2AP_DEBUG ("Adding eNB to the list of associated eNBs\n");
if ((x2ap_eNB_data = x2ap_is_eNB_id_in_list (eNB_id)) == NULL) {
/*
* eNB has not been fount in list of associated eNB,
* * * * Add it to the tail of list and initialize data
*/
if ((x2ap_eNB_data = x2ap_is_eNB_assoc_id_in_list (assoc_id)) == NULL) {
/*
* ??
*/
return -1;
} else {
x2ap_eNB_data->state = X2AP_ENB_STATE_RESETTING;
x2ap_eNB_data->eNB_id = eNB_id;
}
} else {
x2ap_eNB_data->state = X2AP_ENB_STATE_RESETTING;
/*
* eNB has been fount in list, consider the x2 setup request as a reset connection,
* * * * reseting any previous UE state if sctp association is != than the previous one
*/
if (x2ap_eNB_data->assoc_id != assoc_id) {
X2SetupFailure_IEs_t x2SetupFailure;
memset (&x2SetupFailure, 0, sizeof (x2SetupFailure));
/*
* Send an overload cause...
*/
X2AP_ERROR ("Rejeting x2 setup request as eNB id %d is already associated to an active sctp association" "Previous known: %d, new one: %d\n", eNB_id, x2ap_eNB_data->assoc_id, assoc_id);
x2ap_eNB_generate_x2_setup_failure (assoc_id,
X2ap_Cause_PR_protocol,
X2ap_CauseProtocol_unspecified,
-1);
return -1;
}
/*
* TODO: call the reset procedure
*/
}
return x2ap_generate_x2_setup_response (x2ap_eNB_data);
#endif
}
int
x2ap_eNB_handle_handover_response(uint32_t assoc_id,
uint32_t stream,
struct x2ap_message_s *message)
{
X2ap_HandoverRequestAcknowledge_IEs_t *x2HandoverRequestAck;
x2ap_eNB_data_t *x2ap_eNB_data;
uint32_t eNB_id = 0;
int ta_ret;
//uint16_t max_enb_connected;
MessageDef *m;
DevAssert (message != NULL);
x2HandoverRequestAck = &message->msg.x2ap_HandoverRequestAcknowledge_IEs;
if (stream == 0) {
X2AP_ERROR ("Received new x2 handover response on stream == 0\n");
/* TODO: what to do? */
return 0;
}
X2AP_DEBUG ("Received a new X2 handover response\n");
x2ap_eNB_data = x2ap_get_eNB(NULL, assoc_id, 0);
DevAssert(x2ap_eNB_data != NULL);
m = itti_alloc_new_message(TASK_X2AP, X2AP_HANDOVER_REQ_ACK);
/* TODO: fill the message */
extern int x2id_to_source_rnti[1];
X2AP_HANDOVER_REQ_ACK(m).source_x2id = x2HandoverRequestAck->old_eNB_UE_X2AP_ID;
X2AP_HANDOVER_REQ_ACK(m).source_rnti = x2id_to_source_rnti[x2HandoverRequestAck->old_eNB_UE_X2AP_ID];
itti_send_msg_to_task(TASK_RRC_ENB, x2ap_eNB_data->x2ap_eNB_instance->instance, m);
return 0;
}
int
x2ap_eNB_handle_x2_setup_request (uint32_t assoc_id,
uint32_t stream,
struct x2ap_message_s *message)
{
X2SetupRequest_IEs_t *x2SetupRequest;
x2ap_eNB_data_t *x2ap_eNB_data;
uint32_t eNB_id = 0;
int ta_ret;
//uint16_t max_enb_connected;
DevAssert (message != NULL);
x2SetupRequest = &message->msg.x2SetupRequest_IEs;
MSC_LOG_RX_MESSAGE (MSC_X2AP_TARGET_ENB,
MSC_X2AP_SRC_ENB, NULL, 0,
"0 X2Setup/%s assoc_id %u stream %u",
x2ap_direction2String[message->direction],
assoc_id, stream);
/*
* We received a new valid X2 Setup Request on a stream != 0.
* * * * This should not happen -> reject eNB x2 setup request.
*/
if (stream != 0) {
X2AP_ERROR ("Received new x2 setup request on stream != 0\n");
/*
* Send a x2 setup failure with protocol cause unspecified
*/
return x2ap_eNB_generate_x2_setup_failure (assoc_id,
X2ap_Cause_PR_protocol,
X2ap_CauseProtocol_unspecified,
-1);
}
X2AP_DEBUG ("Received a new X2 setup request\n");
if (x2SetupRequest->globalENB_ID.eNB_ID.present == X2ap_ENB_ID_PR_home_eNB_ID) {
// Home eNB ID = 28 bits
uint8_t *eNB_id_buf = x2SetupRequest->globalENB_ID.eNB_ID.choice.home_eNB_ID.buf;
if (x2SetupRequest->globalENB_ID.eNB_ID.choice.macro_eNB_ID.size != 28) {
//TODO: handle case were size != 28 -> notify ? reject ?
}
eNB_id = (eNB_id_buf[0] << 20) + (eNB_id_buf[1] << 12) + (eNB_id_buf[2] << 4) + ((eNB_id_buf[3] & 0xf0) >> 4);
X2AP_DEBUG ("Home eNB id: %07x\n", eNB_id);
} else {
// Macro eNB = 20 bits
uint8_t *eNB_id_buf = x2SetupRequest->globalENB_ID.eNB_ID.choice.macro_eNB_ID.buf;
if (x2SetupRequest->globalENB_ID.eNB_ID.choice.macro_eNB_ID.size != 20) {
//TODO: handle case were size != 20 -> notify ? reject ?
}
eNB_id = (eNB_id_buf[0] << 12) + (eNB_id_buf[1] << 4) + ((eNB_id_buf[2] & 0xf0) >> 4);
X2AP_DEBUG ("macro eNB id: %05x\n", eNB_id);
}
/*
* If none of the provided PLMNs/TAC match the one configured in MME,
* * * * the x2 setup should be rejected with a cause set to Unknown PLMN.
*/
// ta_ret = x2ap_eNB_compare_ta_lists (&x2SetupRequest_p->supportedTAs);
/*
* Source and Target eNBs have no common PLMN
*/
/*
if (ta_ret != TA_LIST_RET_OK) {
X2AP_ERROR ("No Common PLMN with the target eNB, generate_x2_setup_failure\n");
return x2ap_eNB_generate_x2_setup_failure (assoc_id,
X2ap_Cause_PR_misc,
X2ap_CauseMisc_unknown_PLMN,
X2ap_TimeToWait_v20s);
}
*/
X2AP_DEBUG ("Adding eNB to the list of associated eNBs\n");
if ((x2ap_eNB_data = x2ap_is_eNB_id_in_list (eNB_id)) == NULL) {
/*
* eNB has not been fount in list of associated eNB,
* * * * Add it to the tail of list and initialize data
*/
if ((x2ap_eNB_data = x2ap_is_eNB_assoc_id_in_list (assoc_id)) == NULL) {
/*
* ??
*/
return -1;
} else {
x2ap_eNB_data->state = X2AP_ENB_STATE_RESETTING;
x2ap_eNB_data->eNB_id = eNB_id;
}
} else {
x2ap_eNB_data->state = X2AP_ENB_STATE_RESETTING;
/*
* eNB has been fount in list, consider the x2 setup request as a reset connection,
* * * * reseting any previous UE state if sctp association is != than the previous one
*/
if (x2ap_eNB_data->assoc_id != assoc_id) {
X2SetupFailure_IEs_t x2SetupFailure;
memset (&x2SetupFailure, 0, sizeof (x2SetupFailure));
/*
* Send an overload cause...
*/
X2AP_ERROR ("Rejeting x2 setup request as eNB id %d is already associated to an active sctp association" "Previous known: %d, new one: %d\n", eNB_id, x2ap_eNB_data->assoc_id, assoc_id);
x2ap_eNB_generate_x2_setup_failure (assoc_id,
X2ap_Cause_PR_protocol,
X2ap_CauseProtocol_unspecified,
-1);
return -1;
}
/*
* TODO: call the reset procedure
*/
}
return x2ap_generate_x2_setup_response (x2ap_eNB_data);
}
static
int x2ap_eNB_handle_x2_setup_failure(uint32_t assoc_id,
uint32_t stream,
struct x2ap_message_s *message_p)
{
X2SetupFailure_IEs_t *x2_setup_failure;
x2ap_eNB_data_t *x2ap_eNB_data;
DevAssert(message_p != NULL);
x2_setup_failure = &message_p->msg.x2SetupFailure_IEs;
/* x2 Setup Failure == Non UE-related procedure -> stream 0 */
if (stream != 0) {
X2AP_WARN("[SCTP %d] Received x2 setup failure on stream != 0 (%d)\n",
assoc_id, stream);
}
if ((x2ap_eNB_data = x2ap_get_eNB (NULL, assoc_id, 0)) == NULL) {
X2AP_ERROR("[SCTP %d] Received X2 setup response for non existing "
"eNB context\n", assoc_id);
return -1;
}
// need a FSM to handle all cases
if ((x2_setup_failure->cause.present == X2ap_Cause_PR_misc) &&
(x2_setup_failure->cause.choice.misc == X2ap_CauseMisc_unspecified)) {
X2AP_WARN("Received X2 setup failure for eNB ... eNB is not ready\n");
} else {
X2AP_ERROR("Received x2 setup failure for eNB... please check your parameters\n");
}
x2ap_eNB_data->state = X2AP_ENB_STATE_WAITING;
x2ap_handle_x2_setup_message(x2ap_eNB_data, 0);
return 0;
}
static
int x2ap_eNB_handle_x2_setup_response(uint32_t assoc_id,
uint32_t stream,
struct x2ap_message_s *message)
{
X2SetupResponse_IEs_t *x2SetupResponse;
x2ap_eNB_data_t *x2ap_eNB_data;
uint32_t eNB_id = 0;
DevAssert(message != NULL);
x2SetupResponse = &message->msg.x2SetupResponse_IEs;
MSC_LOG_RX_MESSAGE (MSC_X2AP_TARGET_ENB,
MSC_X2AP_SRC_ENB, NULL, 0,
"0 X2Setup/%s assoc_id %u stream %u",
x2ap_direction2String[message->direction],
assoc_id, stream);
/* X2 Setup Response == Non UE-related procedure -> stream 0 */
if (stream != 0) {
X2AP_ERROR("[SCTP %d] Received X2 setup response on stream != 0 (%d)\n",
assoc_id, stream);
return -1;
}
if ((x2ap_eNB_data = x2ap_get_eNB(NULL, assoc_id, 0)) == NULL) {
X2AP_ERROR("[SCTP %d] Received X2 setup response for non existing "
"MME context\n", assoc_id);
return -1;
}
/* check and store eNB info here*/
if (x2SetupResponse->globalENB_ID.eNB_ID.present == X2ap_ENB_ID_PR_home_eNB_ID) {
// Home eNB ID = 28 bits
uint8_t *eNB_id_buf = x2SetupResponse->globalENB_ID.eNB_ID.choice.home_eNB_ID.buf;
if (x2SetupResponse->globalENB_ID.eNB_ID.choice.macro_eNB_ID.size != 28) {
//TODO: handle case were size != 28 -> notify ? reject ?
}
eNB_id = (eNB_id_buf[0] << 20) + (eNB_id_buf[1] << 12) + (eNB_id_buf[2] << 4) + ((eNB_id_buf[3] & 0xf0) >> 4);
X2AP_DEBUG ("Home eNB id: %07x\n", eNB_id);
} else {
// Macro eNB = 20 bits
uint8_t *eNB_id_buf = x2SetupResponse->globalENB_ID.eNB_ID.choice.macro_eNB_ID.buf;
if (x2SetupResponse->globalENB_ID.eNB_ID.choice.macro_eNB_ID.size != 20) {
//TODO: handle case were size != 20 -> notify ? reject ?
}
eNB_id = (eNB_id_buf[0] << 12) + (eNB_id_buf[1] << 4) + ((eNB_id_buf[2] & 0xf0) >> 4);
X2AP_DEBUG ("macro eNB id: %05x\n", eNB_id);
}
if ((x2ap_eNB_data = x2ap_is_eNB_id_in_list (eNB_id)) == NULL) {
/*
* eNB has not been fount in list of associated eNB,
* * * * Add it to the tail of list and initialize data
*/
if ((x2ap_eNB_data = x2ap_is_eNB_assoc_id_in_list (assoc_id)) == NULL) {
/*
* ??
*/
return -1;
} else {
x2ap_eNB_data->state = X2AP_ENB_STATE_RESETTING;
x2ap_eNB_data->eNB_id = eNB_id;
}
} else {
x2ap_eNB_data->state = X2AP_ENB_STATE_RESETTING;
/*
if (x2ap_eNB_data->assoc_id != assoc_id) {
X2SetupFailure_IEs_t x2SetupFailure;
memset (&x2SetupFailure, 0, sizeof (x2SetupFailure));
// Send an overload cause
X2AP_ERROR ("Rejeting x2 setup response as eNB id %d is already associated to an active sctp association" "Previous known: %d, new one: %d\n", eNB_id, x2ap_eNB_data->assoc_id, assoc_id);
x2ap_eNB_generate_x2_setup_failure (assoc_id,
X2ap_Cause_PR_protocol,
X2ap_CauseProtocol_unspecified,
-1);
return -1;
}
*/
/*
* TODO: call the reset procedure
*/
}
/* Optionaly set the target eNB name */
/* The association is now ready as source and target eNBs know parameters of each other.
* Mark the association as connected.
*/
x2ap_eNB_data->state = X2AP_ENB_STATE_READY;
x2ap_eNB_data->x2ap_eNB_instance->x2_target_enb_associated_nb ++;
x2ap_handle_x2_setup_message(x2ap_eNB_data, 0);
return 0;
}
static
int x2ap_eNB_handle_error_indication(uint32_t assoc_id,
uint32_t stream,
struct x2ap_message_s *message_p)
{
X2ap_ErrorIndication_IEs_t *x2_error_indication;
x2ap_eNB_data_t *x2ap_eNB_data;
char *message_string = NULL;
DevAssert(message_p != NULL);
x2_error_indication = &message_p->msg.x2ap_ErrorIndication_IEs;
/* X2 Setup Failure == Non UE-related procedure -> stream 0 */
if (stream != 0) {
X2AP_WARN("[SCTP %d] Received X2 Error indication on stream != 0 (%d)\n",
assoc_id, stream);
}
x2ap_xer_print_x2ap_errorindication_(x2ap_xer__print2sp,
message_string,
message_p);
if ( x2_error_indication->presenceMask & X2AP_ERRORINDICATION_IES_OLD_ENB_UE_X2AP_ID_PRESENT ) {
X2AP_WARN("Received X2 Error indication OLD ENB UE X2AP ID 0x%x\n", x2_error_indication->old_eNB_UE_X2AP_ID);
}
if ( x2_error_indication->presenceMask & X2AP_ERRORINDICATION_IES_NEW_ENB_UE_X2AP_ID_PRESENT) {
X2AP_WARN("Received X2 Error indication NEW eNB UE X2AP ID 0x%x\n", x2_error_indication->new_eNB_UE_X2AP_ID);
}
if ( x2_error_indication->presenceMask & X2AP_ERRORINDICATION_IES_CAUSE_PRESENT) {
switch(x2_error_indication->cause.present) {
case X2ap_Cause_PR_NOTHING:
X2AP_WARN("Received X2 Error indication cause NOTHING\n");
break;
case X2ap_Cause_PR_radioNetwork:
switch (x2_error_indication->cause.choice.radioNetwork) {
case X2ap_CauseRadioNetwork_handover_desirable_for_radio_reasons:
X2AP_WARN("Received X2 Error indication X2ap_CauseRadioNetwork_handover_desirable_for_radio_reasons\n");
break;
case X2ap_CauseRadioNetwork_time_critical_handover:
X2AP_WARN("Received X2 Error indication X2ap_CauseRadioNetwork_time_critical_handover\n");
break;
case X2ap_CauseRadioNetwork_resource_optimisation_handover:
X2AP_WARN("Received X2 Error indication X2ap_CauseRadioNetwork_resource_optimisation_handover\n");
break;
case X2ap_CauseRadioNetwork_reduce_load_in_serving_cell:
X2AP_WARN("Received X2 Error indication X2ap_CauseRadioNetwork_reduce_load_in_serving_cell\n");
break;
case X2ap_CauseRadioNetwork_partial_handover:
X2AP_WARN("Received X2 Error indication X2ap_CauseRadioNetwork_partial_handover\n");
break;
case X2ap_CauseRadioNetwork_unknown_new_eNB_UE_X2AP_ID:
X2AP_WARN("Received X2 Error indication X2ap_CauseRadioNetwork_unknown_new_eNB_UE_X2AP_ID\n");
break;
case X2ap_CauseRadioNetwork_unknown_old_eNB_UE_X2AP_ID:
X2AP_WARN("Received X2 Error indication X2ap_CauseRadioNetwork_unknown_old_eNB_UE_X2AP_ID\n");
break;
case X2ap_CauseRadioNetwork_unknown_pair_of_UE_X2AP_ID:
X2AP_WARN("Received X2 Error indication X2ap_CauseRadioNetwork_unknown_pair_of_UE_X2AP_ID\n");
break;
case X2ap_CauseRadioNetwork_ho_target_not_allowed:
X2AP_WARN("Received X2 Error indication X2ap_CauseRadioNetwork_ho_target_not_allowed\n");
break;
case X2ap_CauseRadioNetwork_tx2relocoverall_expiry:
X2AP_WARN("Received X2 Error indication X2ap_CauseRadioNetwork_tx2relocoverall_expiry\n");
break;
case X2ap_CauseRadioNetwork_trelocprep_expiry:
X2AP_WARN("Received X2 Error indication X2ap_CauseRadioNetwork_trelocprep_expiry\n");
break;
case X2ap_CauseRadioNetwork_cell_not_available:
X2AP_WARN("Received X2 Error indication X2ap_CauseRadioNetwork_cell_not_available\n");
break;
case X2ap_CauseRadioNetwork_no_radio_resources_available_in_target_cell:
X2AP_WARN("Received X2 Error indication X2ap_CauseRadioNetwork_no_radio_resources_available_in_target_cell\n");
break;
case X2ap_CauseRadioNetwork_invalid_MME_GroupID:
X2AP_WARN("Received X2 Error indication X2ap_CauseRadioNetwork_invalid_MME_GroupID\n");
break;
case X2ap_CauseRadioNetwork_unknown_MME_Code:
X2AP_WARN("Received X2 Error indication X2ap_CauseRadioNetwork_unknown_MME_Code\n");
break;
case X2ap_CauseRadioNetwork_encryption_and_or_integrity_protection_algorithms_not_supported:
X2AP_WARN("Received X2 Error indication X2ap_CauseRadioNetwork_encryption_and_or_integrity_protection_algorithms_not_supported\n");
break;
case X2ap_CauseRadioNetwork_reportCharacteristicsEmpty:
X2AP_WARN("Received X2 Error indication X2ap_CauseRadioNetwork_reportCharacteristicsEmpty\n");
break;
case X2ap_CauseRadioNetwork_noReportPeriodicity:
X2AP_WARN("Received X2 Error indication X2ap_CauseRadioNetwork_noReportPeriodicity\n");
break;
case X2ap_CauseRadioNetwork_existingMeasurementID:
X2AP_WARN("Received X2 Error indication X2ap_CauseRadioNetwork_existingMeasurementID\n");
break;
case X2ap_CauseRadioNetwork_unknown_eNB_Measurement_ID:
X2AP_WARN("Received X2 Error indication X2ap_CauseRadioNetwork_unknown_eNB_Measurement_ID\n");
break;
case X2ap_CauseRadioNetwork_measurement_temporarily_not_available:
X2AP_WARN("Received X2 Error indication X2ap_CauseRadioNetwork_measurement_temporarily_not_available\n");
break;
case X2ap_CauseRadioNetwork_unspecified:
X2AP_WARN("Received X2 Error indication X2ap_CauseRadioNetwork_unspecified\n");
break;
case X2ap_CauseRadioNetwork_load_balancing:
X2AP_WARN("Received X2 Error indication X2ap_CauseRadioNetwork_load_balancing\n");
break;
case X2ap_CauseRadioNetwork_handover_optimisation:
X2AP_WARN("Received X2 Error indication X2ap_CauseRadioNetwork_handover_optimisation\n");
break;
case X2ap_CauseRadioNetwork_value_out_of_allowed_range:
X2AP_WARN("Received X2 Error indication X2ap_CauseRadioNetwork_value_out_of_allowed_range\n");
break;
case X2ap_CauseRadioNetwork_multiple_E_RAB_ID_instances:
X2AP_WARN("Received X2 Error indication X2ap_CauseRadioNetwork_multiple_E_RAB_ID_instances\n");
break;
case X2ap_CauseRadioNetwork_switch_off_ongoing:
X2AP_WARN("Received X2 Error indication X2ap_CauseRadioNetwork_switch_off_ongoing\n");
break;
case X2ap_CauseRadioNetwork_not_supported_QCI_value:
X2AP_WARN("Received X2 Error indication X2ap_CauseRadioNetwork_not_supported_QCI_value\n");
break;
case X2ap_CauseRadioNetwork_measurement_not_supported_for_the_object:
X2AP_WARN("Received X2 Error indication X2ap_CauseRadioNetwork_measurement_not_supported_for_the_object\n");
default:
X2AP_WARN("Received X2 Error indication cause radio network case not handled\n");
}
break;
case X2ap_Cause_PR_transport:
switch (x2_error_indication->cause.choice.transport) {
case X2ap_CauseTransport_transport_resource_unavailable:
X2AP_WARN("Received X2 Error indication X2ap_CauseTransport_transport_resource_unavailable\n");
break;
case X2ap_CauseTransport_unspecified:
X2AP_WARN("Received X2 Error indication SX2ap_CauseTransport_unspecified\n");
break;
default:
X2AP_WARN("Received X2 Error indication cause transport case not handled\n");
}
break;
case X2ap_Cause_PR_protocol:
switch (x2_error_indication->cause.choice.protocol) {
case X2ap_CauseProtocol_transfer_syntax_error:
X2AP_WARN("Received X2 Error indication X2ap_CauseProtocol_transfer_syntax_error\n");
break;
case X2ap_CauseProtocol_abstract_syntax_error_reject:
X2AP_WARN("Received X2 Error indication X2ap_CauseProtocol_abstract_syntax_error_reject\n");
break;
case X2ap_CauseProtocol_abstract_syntax_error_ignore_and_notify:
X2AP_WARN("Received X2 Error indication X2ap_CauseProtocol_abstract_syntax_error_ignore_and_notify\n");
break;
case X2ap_CauseProtocol_message_not_compatible_with_receiver_state:
X2AP_WARN("Received X2 Error indication X2ap_CauseProtocol_message_not_compatible_with_receiver_state\n");
break;
case X2ap_CauseProtocol_semantic_error:
X2AP_WARN("Received X2 Error indication X2ap_CauseProtocol_semantic_error\n");
break;
case X2ap_CauseProtocol_unspecified:
X2AP_WARN("Received X2 Error indication X2ap_CauseProtocol_unspecified\n");
break;
case X2ap_CauseProtocol_abstract_syntax_error_falsely_constructed_message:
X2AP_WARN("Received X2 Error indication X2ap_CauseProtocol_abstract_syntax_error_falsely_constructed_message\n");
break;
default:
X2AP_WARN("Received X2 Error indication cause protocol case not handled\n");
}
break;
case X2ap_Cause_PR_misc:
switch (x2_error_indication->cause.choice.protocol) {
case X2ap_CauseMisc_control_processing_overload:
X2AP_WARN("Received X2 Error indication X2ap_CauseMisc_control_processing_overload\n");
break;
case X2ap_CauseMisc_hardware_failure:
X2AP_WARN("Received X2 Error indication X2ap_CauseMisc_hardware_failure\n");
break;
case X2ap_CauseMisc_om_intervention:
X2AP_WARN("Received X2 Error indication X2ap_CauseMisc_om_intervention\n");
break;
case X2ap_CauseMisc_not_enough_user_plane_processing_resources:
X2AP_WARN("Received X2 Error indication X2ap_CauseMisc_not_enough_user_plane_processing_resources\n");
break;
case X2ap_CauseMisc_unspecified:
X2AP_WARN("Received X2 Error indication X2ap_CauseMisc_unspecified\n");
break;
default:
X2AP_WARN("Received X2 Error indication cause misc case not handled\n");
}
break;
}
}
if ( x2_error_indication->presenceMask &X2AP_ERRORINDICATION_IES_CRITICALITYDIAGNOSTICS_PRESENT) {
// TODO continue
}
// TODO continue
return 0;
}

View File

@@ -0,0 +1,40 @@
/*******************************************************************************
OpenAirInterface
Copyright(c) 1999 - 2014 Eurecom
OpenAirInterface is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OpenAirInterface is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with OpenAirInterface.The full GNU General Public License is
included in this distribution in the file called "COPYING". If not,
see <http://www.gnu.org/licenses/>.
Contact Information
OpenAirInterface Admin: openair_admin@eurecom.fr
OpenAirInterface Tech : openair_tech@eurecom.fr
OpenAirInterface Dev : openair4g-devel@lists.eurecom.fr
Address : Eurecom, Compus SophiaTech 450, route des chappes, 06451 Biot, France.
*******************************************************************************/
#ifndef X2AP_ENB_HANDLERS_H_
#define X2AP_ENB_HANDLERS_H_
#include "x2ap_eNB_defs.h"
void x2ap_handle_x2_setup_message(x2ap_eNB_data_t *mme_desc_p, int sctp_shutdown);
int x2ap_eNB_handle_message(uint32_t assoc_id, int32_t stream,
const uint8_t * const data, const uint32_t data_length);
#endif /* X2AP_ENB_HANDLERS_H_ */

View File

@@ -0,0 +1,70 @@
/*******************************************************************************
OpenAirInterface
Copyright(c) 1999 - 2014 Eurecom
OpenAirInterface is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OpenAirInterface is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with OpenAirInterface.The full GNU General Public License is
included in this distribution in the file called "COPYING". If not,
see <http://www.gnu.org/licenses/>.
Contact Information
OpenAirInterface Admin: openair_admin@eurecom.fr
OpenAirInterface Tech : openair_tech@eurecom.fr
OpenAirInterface Dev : openair4g-devel@lists.eurecom.fr
Address : Eurecom, Compus SophiaTech 450, route des chappes, 06451 Biot, France.
*******************************************************************************/
/*! \file x2ap_eNB_itti_messaging.c
* \brief itti interface between x2ap and sctp
* \author Navid Nikaein
* \date 2016
* \version 0.1
*/
#include "intertask_interface.h"
#include "x2ap_eNB_itti_messaging.h"
void x2ap_eNB_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_X2AP, 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 x2ap_eNB_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_X2AP, 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);
}

View File

@@ -0,0 +1,39 @@
/*******************************************************************************
OpenAirInterface
Copyright(c) 1999 - 2014 Eurecom
OpenAirInterface is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OpenAirInterface is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with OpenAirInterface.The full GNU General Public License is
included in this distribution in the file called "COPYING". If not,
see <http://www.gnu.org/licenses/>.
Contact Information
OpenAirInterface Admin: openair_admin@eurecom.fr
OpenAirInterface Tech : openair_tech@eurecom.fr
OpenAirInterface Dev : openair4g-devel@lists.eurecom.fr
Address : Eurecom, Compus SophiaTech 450, route des chappes, 06451 Biot, France.
*******************************************************************************/
#ifndef X2AP_ENB_ITTI_MESSAGING_H_
#define X2AP_ENB_ITTI_MESSAGING_H_
void x2ap_eNB_itti_send_sctp_data_req(instance_t instance, int32_t assoc_id, uint8_t *buffer,
uint32_t buffer_length, uint16_t stream);
void x2ap_eNB_itti_send_sctp_close_association(instance_t instance, int32_t assoc_id);
#endif /* X2AP_ENB_ITTI_MESSAGING_H_ */

View File

@@ -0,0 +1,251 @@
/*******************************************************************************
OpenAirInterface
Copyright(c) 1999 - 2014 Eurecom
OpenAirInterface is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OpenAirInterface is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with OpenAirInterface.The full GNU General Public License is
included in this distribution in the file called "COPYING". If not,
see <http://www.gnu.org/licenses/>.
Contact Information
OpenAirInterface Admin: openair_admin@eurecom.fr
OpenAirInterface Tech : openair_tech@eurecom.fr
OpenAirInterface Dev : openair4g-devel@lists.eurecom.fr
Address : Eurecom, Compus SophiaTech 450, route des chappes, 06451 Biot, France.
*******************************************************************************/
/*! \file x2ap_eNB_management_procedures.c
* \brief x2ap eNb management procedures
* \author Navid Nikaein
* \date 2016
* \version 0.1
*/
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include "intertask_interface.h"
#include "assertions.h"
#include "conversions.h"
#include "x2ap_common.h"
#include "x2ap_eNB_defs.h"
#include "x2ap_eNB.h"
#define X2AP_DEBUG_LIST
#ifdef X2AP_DEBUG_LIST
# define X2AP_eNB_LIST_OUT(x, args...) X2AP_DEBUG("[eNB]%*s"x"\n", 4*indent, "", ##args)
#else
# define X2AP_eNB_LIST_OUT(x, args...)
#endif
static int indent = 0;
x2ap_eNB_internal_data_t x2ap_eNB_internal_data;
RB_GENERATE(x2ap_enb_map, x2ap_eNB_data_s, entry, x2ap_eNB_compare_assoc_id);
int x2ap_eNB_compare_assoc_id(
struct x2ap_eNB_data_s *p1, struct x2ap_eNB_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 x2ap_eNB_fetch_add_global_cnx_id(void)
{
return ++x2ap_eNB_internal_data.global_cnx_id;
}
void x2ap_eNB_prepare_internal_data(void)
{
memset(&x2ap_eNB_internal_data, 0, sizeof(x2ap_eNB_internal_data));
STAILQ_INIT(&x2ap_eNB_internal_data.x2ap_eNB_instances_head);
}
void x2ap_eNB_insert_new_instance(x2ap_eNB_instance_t *new_instance_p)
{
DevAssert(new_instance_p != NULL);
STAILQ_INSERT_TAIL(&x2ap_eNB_internal_data.x2ap_eNB_instances_head,
new_instance_p, x2ap_eNB_entries);
}
void dump_tree(x2ap_eNB_data_t *t)
{
if (t == NULL) return;
printf("-----------------------\n");
printf("eNB id %d %s\n", t->eNB_id, t->eNB_name);
printf("state %d\n", t->state);
printf("nextstream %d\n", t->nextstream);
printf("in_streams %d out_streams %d\n", t->in_streams, t->out_streams);
printf("cnx_id %d assoc_id %d\n", t->cnx_id, t->assoc_id);
dump_tree(t->entry.rbe_left);
dump_tree(t->entry.rbe_right);
}
void dump_trees(void)
{
x2ap_eNB_instance_t *zz;
STAILQ_FOREACH(zz, &x2ap_eNB_internal_data.x2ap_eNB_instances_head,
x2ap_eNB_entries) {
printf("here comes the tree (instance %d):\n---------------------------------------------\n", zz->instance);
dump_tree(zz->x2ap_enb_head.rbh_root);
printf("---------------------------------------------\n");
}
}
struct x2ap_eNB_data_s *x2ap_get_eNB(x2ap_eNB_instance_t *instance_p,
int32_t assoc_id,
uint16_t cnx_id)
{
struct x2ap_eNB_data_s temp;
struct x2ap_eNB_data_s *found;
printf("x2ap_get_eNB at 1 (looking for assoc_id %d cnx_id %d)\n", assoc_id, cnx_id);
dump_trees();
memset(&temp, 0, sizeof(struct x2ap_eNB_data_s));
temp.assoc_id = assoc_id;
temp.cnx_id = cnx_id;
if (instance_p == NULL) {
STAILQ_FOREACH(instance_p, &x2ap_eNB_internal_data.x2ap_eNB_instances_head,
x2ap_eNB_entries) {
found = RB_FIND(x2ap_enb_map, &instance_p->x2ap_enb_head, &temp);
if (found != NULL) {
return found;
}
}
} else {
return RB_FIND(x2ap_enb_map, &instance_p->x2ap_enb_head, &temp);
}
return NULL;
}
x2ap_eNB_instance_t *x2ap_eNB_get_instance(instance_t instance)
{
x2ap_eNB_instance_t *temp = NULL;
STAILQ_FOREACH(temp, &x2ap_eNB_internal_data.x2ap_eNB_instances_head,
x2ap_eNB_entries) {
if (temp->instance == instance) {
/* Matching occurence */
return temp;
}
}
return NULL;
}
/// utility functions
void x2ap_dump_eNB (x2ap_eNB_data_t * eNB_ref);
void
x2ap_dump_eNB_list (void) {
x2ap_eNB_instance_t *inst = NULL;
struct x2ap_eNB_data_s *found = NULL;
struct x2ap_eNB_data_s temp;
memset(&temp, 0, sizeof(struct x2ap_eNB_data_s));
STAILQ_FOREACH (inst, &x2ap_eNB_internal_data.x2ap_eNB_instances_head, x2ap_eNB_entries) {
found = RB_FIND(x2ap_enb_map, &inst->x2ap_enb_head, &temp);
x2ap_dump_eNB (found);
}
}
void x2ap_dump_eNB (x2ap_eNB_data_t * eNB_ref) {
if (eNB_ref == NULL) {
return;
}
X2AP_eNB_LIST_OUT ("");
X2AP_eNB_LIST_OUT ("eNB name: %s", eNB_ref->eNB_name == NULL ? "not present" : eNB_ref->eNB_name);
X2AP_eNB_LIST_OUT ("eNB STATE: %07x", eNB_ref->state);
X2AP_eNB_LIST_OUT ("eNB ID: %07x", eNB_ref->eNB_id);
indent++;
X2AP_eNB_LIST_OUT ("SCTP cnx id: %d", eNB_ref->cnx_id);
X2AP_eNB_LIST_OUT ("SCTP assoc id: %d", eNB_ref->assoc_id);
X2AP_eNB_LIST_OUT ("SCTP instreams: %d", eNB_ref->in_streams);
X2AP_eNB_LIST_OUT ("SCTP outstreams: %d", eNB_ref->out_streams);
indent--;
}
x2ap_eNB_data_t * x2ap_is_eNB_id_in_list (const uint32_t eNB_id)
{
x2ap_eNB_instance_t *inst;
struct x2ap_eNB_data_s *elm;
STAILQ_FOREACH(inst, &x2ap_eNB_internal_data.x2ap_eNB_instances_head, x2ap_eNB_entries) {
RB_FOREACH(elm, x2ap_enb_map, &inst->x2ap_enb_head) {
if (elm->eNB_id == eNB_id)
return elm;
}
}
return NULL;
}
x2ap_eNB_data_t * x2ap_is_eNB_assoc_id_in_list (const uint32_t sctp_assoc_id)
{
x2ap_eNB_instance_t *inst;
struct x2ap_eNB_data_s *found;
struct x2ap_eNB_data_s temp;
temp.assoc_id = sctp_assoc_id;
temp.cnx_id = -1;
STAILQ_FOREACH(inst, &x2ap_eNB_internal_data.x2ap_eNB_instances_head, x2ap_eNB_entries) {
found = RB_FIND(x2ap_enb_map, &inst->x2ap_enb_head, &temp);
if (found != NULL){
if (found->assoc_id == sctp_assoc_id) {
return found;
}
}
}
return NULL;
}

View File

@@ -0,0 +1,53 @@
/*******************************************************************************
OpenAirInterface
Copyright(c) 1999 - 2014 Eurecom
OpenAirInterface is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OpenAirInterface is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with OpenAirInterface.The full GNU General Public License is
included in this distribution in the file called "COPYING". If not,
see <http://www.gnu.org/licenses/>.
Contact Information
OpenAirInterface Admin: openair_admin@eurecom.fr
OpenAirInterface Tech : openair_tech@eurecom.fr
OpenAirInterface Dev : openair4g-devel@lists.eurecom.fr
Address : Eurecom, Compus SophiaTech 450, route des chappes, 06451 Biot, France.
*******************************************************************************/
#ifndef X2AP_ENB_MANAGEMENT_PROCEDURES_H_
#define X2AP_ENB_MANAGEMENT_PROCEDURES_H_
/*
struct x2ap_eNB_mme_data_s *s1ap_eNB_get_MME(
s1ap_eNB_instance_t *instance_p,
int32_t assoc_id, uint16_t cnx_id);
*/
void x2ap_eNB_insert_new_instance(x2ap_eNB_instance_t *new_instance_p);
x2ap_eNB_instance_t *x2ap_eNB_get_instance(uint8_t mod_id);
uint16_t x2ap_eNB_fetch_add_global_cnx_id(void);
void x2ap_eNB_prepare_internal_data(void);
x2ap_eNB_data_t* x2ap_is_eNB_id_in_list(uint32_t eNB_id);
x2ap_eNB_data_t* x2ap_is_eNB_assoc_id_in_list(uint32_t sctp_assoc_id);
struct x2ap_eNB_data_s *x2ap_get_eNB(x2ap_eNB_instance_t *instance_p,
int32_t assoc_id,
uint16_t cnx_id);
#endif /* X2AP_ENB_MANAGEMENT_PROCEDURES_H_ */

View File

@@ -141,7 +141,7 @@ gtpv1u_create_s1u_tunnel(
const gtpv1u_enb_create_tunnel_req_t * const create_tunnel_req_pP,
gtpv1u_enb_create_tunnel_resp_t * const create_tunnel_resp_pP);
static int
int
gtpv1u_delete_s1u_tunnel(
const instance_t instanceP,
const gtpv1u_enb_delete_tunnel_req_t * const req_pP);
@@ -809,7 +809,8 @@ gtpv1u_create_s1u_tunnel(
//-----------------------------------------------------------------------------
static int gtpv1u_delete_s1u_tunnel(
int
gtpv1u_delete_s1u_tunnel(
const instance_t instanceP,
const gtpv1u_enb_delete_tunnel_req_t * const req_pP)
{

View File

@@ -371,6 +371,12 @@ void *s1ap_eNB_task(void *arg)
}
break;
case S1AP_PATH_SWITCH_REQ: {
s1ap_eNB_path_switch_req(ITTI_MESSAGE_GET_INSTANCE(received_msg),
&S1AP_PATH_SWITCH_REQ(received_msg));
}
break;
case S1AP_UE_CONTEXT_RELEASE_COMPLETE: {
s1ap_ue_context_release_complete(ITTI_MESSAGE_GET_INSTANCE(received_msg),
&S1AP_UE_CONTEXT_RELEASE_COMPLETE(received_msg));

View File

@@ -81,13 +81,36 @@ int s1ap_eNB_handle_e_rab_setup_request(uint32_t assoc_id,
uint32_t stream,
struct s1ap_message_s *s1ap_message_p);
static
int s1ap_eNB_handle_s1_path_switch_request_ack(uint32_t assoc_id,
uint32_t stream,
struct s1ap_message_s *message_p);
static
int s1ap_eNB_handle_s1_path_switch_request_failure(uint32_t assoc_id,
uint32_t stream,
struct s1ap_message_s *message_p);
static
void process_radio_network_failure(S1ap_CauseRadioNetwork_t cause);
static
void process_transport_failure(S1ap_CauseTransport_t cause);
static
void process_nas_failure(S1ap_CauseNas_t cause);
static
void process_protocol_failure(S1ap_CauseProtocol_t cause);
static
void process_misc_failure(S1ap_CauseMisc_t cause);
/* Handlers matrix. Only eNB related procedure present here */
s1ap_message_decoded_callback messages_callback[][3] = {
{ 0, 0, 0 }, /* HandoverPreparation */
{ 0, 0, 0 }, /* HandoverResourceAllocation */
{ 0, 0, 0 }, /* HandoverNotification */
{ 0, 0, 0 }, /* PathSwitchRequest */
{ 0, s1ap_eNB_handle_s1_path_switch_request_ack, s1ap_eNB_handle_s1_path_switch_request_failure}, /* PathSwitchRequest */
{ 0, 0, 0 }, /* HandoverCancel */
{ s1ap_eNB_handle_e_rab_setup_request, 0, 0 }, /* E_RABSetup */
{ 0, 0, 0 }, /* E_RABModify */
@@ -460,224 +483,34 @@ int s1ap_eNB_handle_error_indication(uint32_t assoc_id,
if ( s1_error_indication_p->presenceMask & S1AP_ERRORINDICATIONIES_CAUSE_PRESENT) {
switch(s1_error_indication_p->cause.present) {
case S1ap_Cause_PR_NOTHING:
S1AP_WARN("Received S1 Error indication cause NOTHING\n");
case S1ap_Cause_PR_NOTHING:
S1AP_WARN("Received S1 Error indication cause NOTHING\n");
break;
case S1ap_Cause_PR_radioNetwork:
switch (s1_error_indication_p->cause.choice.radioNetwork) {
case S1ap_CauseRadioNetwork_unspecified:
S1AP_WARN("Received S1 Error indication S1ap_CauseRadioNetwork_unspecified\n");
break;
case S1ap_CauseRadioNetwork_tx2relocoverall_expiry:
S1AP_WARN("Received S1 Error indication S1ap_CauseRadioNetwork_tx2relocoverall_expiry\n");
break;
case S1ap_CauseRadioNetwork_successful_handover:
S1AP_WARN("Received S1 Error indication S1ap_CauseRadioNetwork_successful_handover\n");
break;
case S1ap_CauseRadioNetwork_release_due_to_eutran_generated_reason:
S1AP_WARN("Received S1 Error indication S1ap_CauseRadioNetwork_release_due_to_eutran_generated_reason\n");
break;
case S1ap_CauseRadioNetwork_handover_cancelled:
S1AP_WARN("Received S1 Error indication S1ap_CauseRadioNetwork_handover_cancelled\n");
break;
case S1ap_CauseRadioNetwork_partial_handover:
S1AP_WARN("Received S1 Error indication S1ap_CauseRadioNetwork_partial_handover\n");
break;
case S1ap_CauseRadioNetwork_ho_failure_in_target_EPC_eNB_or_target_system:
S1AP_WARN("Received S1 Error indication S1ap_CauseRadioNetwork_ho_failure_in_target_EPC_eNB_or_target_system\n");
break;
case S1ap_CauseRadioNetwork_ho_target_not_allowed:
S1AP_WARN("Received S1 Error indication S1ap_CauseRadioNetwork_ho_target_not_allowed\n");
break;
case S1ap_CauseRadioNetwork_tS1relocoverall_expiry:
S1AP_WARN("Received S1 Error indication S1ap_CauseRadioNetwork_tS1relocoverall_expiry\n");
break;
case S1ap_CauseRadioNetwork_tS1relocprep_expiry:
S1AP_WARN("Received S1 Error indication S1ap_CauseRadioNetwork_tS1relocprep_expiry\n");
break;
case S1ap_CauseRadioNetwork_cell_not_available:
S1AP_WARN("Received S1 Error indication S1ap_CauseRadioNetwork_cell_not_available\n");
break;
case S1ap_CauseRadioNetwork_unknown_targetID:
S1AP_WARN("Received S1 Error indication S1ap_CauseRadioNetwork_unknown_targetID\n");
break;
case S1ap_CauseRadioNetwork_no_radio_resources_available_in_target_cell:
S1AP_WARN("Received S1 Error indication S1ap_CauseRadioNetwork_no_radio_resources_available_in_target_cell\n");
break;
case S1ap_CauseRadioNetwork_unknown_mme_ue_s1ap_id:
S1AP_WARN("Received S1 Error indication S1ap_CauseRadioNetwork_unknown_mme_ue_s1ap_id\n");
break;
case S1ap_CauseRadioNetwork_unknown_enb_ue_s1ap_id:
S1AP_WARN("Received S1 Error indication S1ap_CauseRadioNetwork_unknown_enb_ue_s1ap_id\n");
break;
case S1ap_CauseRadioNetwork_unknown_pair_ue_s1ap_id:
S1AP_WARN("Received S1 Error indication S1ap_CauseRadioNetwork_unknown_pair_ue_s1ap_id\n");
break;
case S1ap_CauseRadioNetwork_handover_desirable_for_radio_reason:
S1AP_WARN("Received S1 Error indication S1ap_CauseRadioNetwork_handover_desirable_for_radio_reason\n");
break;
case S1ap_CauseRadioNetwork_time_critical_handover:
S1AP_WARN("Received S1 Error indication S1ap_CauseRadioNetwork_time_critical_handover\n");
break;
case S1ap_CauseRadioNetwork_resource_optimisation_handover:
S1AP_WARN("Received S1 Error indication S1ap_CauseRadioNetwork_resource_optimisation_handover\n");
break;
case S1ap_CauseRadioNetwork_reduce_load_in_serving_cell:
S1AP_WARN("Received S1 Error indication S1ap_CauseRadioNetwork_reduce_load_in_serving_cell\n");
break;
case S1ap_CauseRadioNetwork_user_inactivity:
S1AP_WARN("Received S1 Error indication S1ap_CauseRadioNetwork_user_inactivity\n");
break;
case S1ap_CauseRadioNetwork_radio_connection_with_ue_lost:
S1AP_WARN("Received S1 Error indication S1ap_CauseRadioNetwork_radio_connection_with_ue_lost\n");
break;
case S1ap_CauseRadioNetwork_load_balancing_tau_required:
S1AP_WARN("Received S1 Error indication S1ap_CauseRadioNetwork_load_balancing_tau_required\n");
break;
case S1ap_CauseRadioNetwork_cs_fallback_triggered:
S1AP_WARN("Received S1 Error indication S1ap_CauseRadioNetwork_cs_fallback_triggered\n");
break;
case S1ap_CauseRadioNetwork_ue_not_available_for_ps_service:
S1AP_WARN("Received S1 Error indication S1ap_CauseRadioNetwork_ue_not_available_for_ps_service\n");
break;
case S1ap_CauseRadioNetwork_radio_resources_not_available:
S1AP_WARN("Received S1 Error indication S1ap_CauseRadioNetwork_radio_resources_not_available\n");
break;
case S1ap_CauseRadioNetwork_failure_in_radio_interface_procedure:
S1AP_WARN("Received S1 Error indication S1ap_CauseRadioNetwork_failure_in_radio_interface_procedure\n");
break;
case S1ap_CauseRadioNetwork_invals1ap_id_qos_combination:
S1AP_WARN("Received S1 Error indication S1ap_CauseRadioNetwork_invals1ap_id_qos_combination\n");
break;
case S1ap_CauseRadioNetwork_interrat_redirection:
S1AP_WARN("Received S1 Error indication S1ap_CauseRadioNetwork_interrat_redirection\n");
break;
case S1ap_CauseRadioNetwork_interaction_with_other_procedure:
S1AP_WARN("Received S1 Error indication S1ap_CauseRadioNetwork_interaction_with_other_procedure\n");
break;
case S1ap_CauseRadioNetwork_unknown_E_RAB_ID:
S1AP_WARN("Received S1 Error indication S1ap_CauseRadioNetwork_unknown_E_RAB_ID\n");
break;
case S1ap_CauseRadioNetwork_multiple_E_RAB_ID_instances:
S1AP_WARN("Received S1 Error indication S1ap_CauseRadioNetwork_multiple_E_RAB_ID_instances\n");
break;
case S1ap_CauseRadioNetwork_encryption_and_or_integrity_protection_algorithms_not_supported:
S1AP_WARN("Received S1 Error indication S1ap_CauseRadioNetwork_encryption_and_or_integrity_protection_algorithms_not_supported\n");
break;
case S1ap_CauseRadioNetwork_s1_intra_system_handover_triggered:
S1AP_WARN("Received S1 Error indication S1ap_CauseRadioNetwork_s1_intra_system_handover_triggered\n");
break;
case S1ap_CauseRadioNetwork_s1_inter_system_handover_triggered:
S1AP_WARN("Received S1 Error indication S1ap_CauseRadioNetwork_s1_inter_system_handover_triggered\n");
break;
case S1ap_CauseRadioNetwork_x2_handover_triggered:
S1AP_WARN("Received S1 Error indication S1ap_CauseRadioNetwork_x2_handover_triggered\n");
break;
case S1ap_CauseRadioNetwork_redirection_towards_1xRTT:
S1AP_WARN("Received S1 Error indication S1ap_CauseRadioNetwork_redirection_towards_1xRTT\n");
break;
case S1ap_CauseRadioNetwork_not_supported_QCI_value:
S1AP_WARN("Received S1 Error indication S1ap_CauseRadioNetwork_not_supported_QCI_value\n");
break;
case S1ap_CauseRadioNetwork_invals1ap_id_CSG_Id:
S1AP_WARN("Received S1 Error indication S1ap_CauseRadioNetwork_invals1ap_id_CSG_Id\n");
break;
default:
S1AP_WARN("Received S1 Error indication cause radio network case not handled\n");
}
case S1ap_Cause_PR_radioNetwork:
process_radio_network_failure(s1_error_indication_p->cause.choice.radioNetwork);
break;
case S1ap_Cause_PR_transport:
switch (s1_error_indication_p->cause.choice.transport) {
case S1ap_CauseTransport_transport_resource_unavailable:
S1AP_WARN("Received S1 Error indication S1ap_CauseTransport_transport_resource_unavailable\n");
break;
case S1ap_CauseTransport_unspecified:
S1AP_WARN("Received S1 Error indication S1ap_CauseTransport_unspecified\n");
break;
default:
S1AP_WARN("Received S1 Error indication cause transport case not handled\n");
}
case S1ap_Cause_PR_transport:
process_transport_failure(s1_error_indication_p->cause.choice.transport);
break;
case S1ap_Cause_PR_nas:
switch (s1_error_indication_p->cause.choice.nas) {
case S1ap_CauseNas_normal_release:
S1AP_WARN("Received S1 Error indication S1ap_CauseNas_normal_release\n");
break;
case S1ap_CauseNas_authentication_failure:
S1AP_WARN("Received S1 Error indication S1ap_CauseNas_authentication_failure\n");
break;
case S1ap_CauseNas_detach:
S1AP_WARN("Received S1 Error indication S1ap_CauseNas_detach\n");
break;
case S1ap_CauseNas_unspecified:
S1AP_WARN("Received S1 Error indication S1ap_CauseNas_unspecified\n");
break;
case S1ap_CauseNas_csg_subscription_expiry:
S1AP_WARN("Received S1 Error indication S1ap_CauseNas_csg_subscription_expiry\n");
break;
default:
S1AP_WARN("Received S1 Error indication cause nas case not handled\n");
}
case S1ap_Cause_PR_nas:
process_nas_failure(s1_error_indication_p->cause.choice.nas);
break;
case S1ap_Cause_PR_protocol:
switch (s1_error_indication_p->cause.choice.protocol) {
case S1ap_CauseProtocol_transfer_syntax_error:
S1AP_WARN("Received S1 Error indication S1ap_CauseProtocol_transfer_syntax_error\n");
break;
case S1ap_CauseProtocol_abstract_syntax_error_reject:
S1AP_WARN("Received S1 Error indication S1ap_CauseProtocol_abstract_syntax_error_reject\n");
break;
case S1ap_CauseProtocol_abstract_syntax_error_ignore_and_notify:
S1AP_WARN("Received S1 Error indication S1ap_CauseProtocol_abstract_syntax_error_ignore_and_notify\n");
break;
case S1ap_CauseProtocol_message_not_compatible_with_receiver_state:
S1AP_WARN("Received S1 Error indication S1ap_CauseProtocol_message_not_compatible_with_receiver_state\n");
break;
case S1ap_CauseProtocol_semantic_error:
S1AP_WARN("Received S1 Error indication S1ap_CauseProtocol_semantic_error\n");
break;
case S1ap_CauseProtocol_abstract_syntax_error_falsely_constructed_message:
S1AP_WARN("Received S1 Error indication S1ap_CauseProtocol_abstract_syntax_error_falsely_constructed_message\n");
break;
case S1ap_CauseProtocol_unspecified:
S1AP_WARN("Received S1 Error indication S1ap_CauseProtocol_unspecified\n");
break;
default:
S1AP_WARN("Received S1 Error indication cause protocol case not handled\n");
}
case S1ap_Cause_PR_protocol:
process_protocol_failure(s1_error_indication_p->cause.choice.protocol);
break;
case S1ap_Cause_PR_misc:
switch (s1_error_indication_p->cause.choice.protocol) {
case S1ap_CauseMisc_control_processing_overload:
S1AP_WARN("Received S1 Error indication S1ap_CauseMisc_control_processing_overload\n");
break;
case S1ap_CauseMisc_not_enough_user_plane_processing_resources:
S1AP_WARN("Received S1 Error indication S1ap_CauseMisc_not_enough_user_plane_processing_resources\n");
break;
case S1ap_CauseMisc_hardware_failure:
S1AP_WARN("Received S1 Error indication S1ap_CauseMisc_hardware_failure\n");
break;
case S1ap_CauseMisc_om_intervention:
S1AP_WARN("Received S1 Error indication S1ap_CauseMisc_om_intervention\n");
break;
case S1ap_CauseMisc_unspecified:
S1AP_WARN("Received S1 Error indication S1ap_CauseMisc_unspecified\n");
break;
case S1ap_CauseMisc_unknown_PLMN:
S1AP_WARN("Received S1 Error indication S1ap_CauseMisc_unknown_PLMN\n");
break;
default:
S1AP_WARN("Received S1 Error indication cause misc case not handled\n");
}
case S1ap_Cause_PR_misc:
process_misc_failure(s1_error_indication_p->cause.choice.protocol);
break;
default:
S1AP_WARN("Received an unknown S1 Error indication cause\n");
}
}
if ( s1_error_indication_p->presenceMask & S1AP_ERRORINDICATIONIES_CRITICALITYDIAGNOSTICS_PRESENT) {
// TODO continue
S1AP_WARN("Critical Diagnostic not supported\n");
}
// TODO continue
@@ -776,7 +609,7 @@ int s1ap_eNB_handle_initial_context_request(uint32_t assoc_id,
item_p->transportLayerAddress.size * 8 - item_p->transportLayerAddress.bits_unused;
/* GTP tunnel endpoint ID */
OCTET_STRING_TO_INT32(&item_p->gTP_TEID, S1AP_INITIAL_CONTEXT_SETUP_REQ(message_p).e_rab_param[i].gtp_teid);
OCTET_STRING_TO_INT32 (&item_p->gTP_TEID, S1AP_INITIAL_CONTEXT_SETUP_REQ(message_p).e_rab_param[i].gtp_teid);
/* Set the QOS informations */
S1AP_INITIAL_CONTEXT_SETUP_REQ(message_p).e_rab_param[i].qos.qci = item_p->e_RABlevelQoSParameters.qCI;
@@ -935,23 +768,7 @@ int s1ap_eNB_handle_e_rab_setup_request(uint32_t assoc_id,
item_p = (S1ap_E_RABToBeSetupItemBearerSUReq_t *)s1ap_E_RABSetupRequest->e_RABToBeSetupListBearerSUReq.s1ap_E_RABToBeSetupItemBearerSUReq.array[i];
S1AP_E_RAB_SETUP_REQ(message_p).e_rab_setup_params[i].e_rab_id = item_p->e_RAB_ID;
// check for the NAS PDU
if (item_p->nAS_PDU.size > 0 ) {
S1AP_E_RAB_SETUP_REQ(message_p).e_rab_setup_params[i].nas_pdu.length = item_p->nAS_PDU.size;
S1AP_E_RAB_SETUP_REQ(message_p).e_rab_setup_params[i].nas_pdu.buffer = malloc(sizeof(uint8_t) * item_p->nAS_PDU.size);
memcpy(S1AP_E_RAB_SETUP_REQ(message_p).e_rab_setup_params[i].nas_pdu.buffer,
item_p->nAS_PDU.buf, item_p->nAS_PDU.size);
// S1AP_INFO("received a NAS PDU with size %d (%02x.%02x)\n",S1AP_E_RAB_SETUP_REQ(message_p).e_rab_setup_params[i].nas_pdu.length, item_p->nAS_PDU.buf[0], item_p->nAS_PDU.buf[1]);
} else {
S1AP_E_RAB_SETUP_REQ(message_p).e_rab_setup_params[i].nas_pdu.length = 0;
S1AP_E_RAB_SETUP_REQ(message_p).e_rab_setup_params[i].nas_pdu.buffer = NULL;
S1AP_WARN("NAS PDU is not provided, generate a E_RAB_SETUP Failure (TBD) back to MME \n");
return -1;
}
/* Set the transport layer address */
memcpy(S1AP_E_RAB_SETUP_REQ(message_p).e_rab_setup_params[i].sgw_addr.buffer,
@@ -984,3 +801,404 @@ int s1ap_eNB_handle_e_rab_setup_request(uint32_t assoc_id,
}
static
int s1ap_eNB_handle_s1_path_switch_request_ack(uint32_t assoc_id,
uint32_t stream,
struct s1ap_message_s *s1ap_message_p)
{
S1ap_PathSwitchRequestAcknowledgeIEs_t *s1PathSwitchRequestAcknowledge_p;
s1ap_eNB_mme_data_t *mme_desc_p;
s1ap_eNB_ue_context_t *ue_desc_p = NULL;
MessageDef *message_p = NULL;
int i;
DevAssert(s1ap_message_p != NULL);
s1PathSwitchRequestAcknowledge_p = &s1ap_message_p->msg.s1ap_PathSwitchRequestAcknowledgeIEs;
/* S1 Setup Response == Non UE-related procedure -> stream 0 */
if (stream != 0) {
S1AP_ERROR("[SCTP %d] Received s1 path switch request ack on stream != 0 (%d)\n",
assoc_id, stream);
return -1;
}
if ((mme_desc_p = s1ap_eNB_get_MME(NULL, assoc_id, 0)) == NULL) {
S1AP_ERROR("[SCTP %d] Received S1 path switch request ack for non existing "
"MME context\n", assoc_id);
return -1;
}
if ((ue_desc_p = s1ap_eNB_get_ue_context(mme_desc_p->s1ap_eNB_instance,
s1PathSwitchRequestAcknowledge_p->eNB_UE_S1AP_ID)) == NULL) {
S1AP_ERROR("[SCTP %d] Received path switch request ack for non "
"existing UE context 0x%06lx\n", assoc_id,
s1PathSwitchRequestAcknowledge_p->eNB_UE_S1AP_ID);
return -1;
}
if ( ue_desc_p->mme_ue_s1ap_id != s1PathSwitchRequestAcknowledge_p->mme_ue_s1ap_id){
S1AP_WARN("UE context mme_ue_s1ap_id is different form that of the message (%d != %ld)",
ue_desc_p->mme_ue_s1ap_id, s1PathSwitchRequestAcknowledge_p->mme_ue_s1ap_id);
}
// send a message to RRC
message_p = itti_alloc_new_message(TASK_S1AP, S1AP_PATH_SWITCH_REQ_ACK);
S1AP_PATH_SWITCH_REQ_ACK(message_p).ue_initial_id = ue_desc_p->ue_initial_id;
S1AP_PATH_SWITCH_REQ_ACK(message_p).eNB_ue_s1ap_id = s1PathSwitchRequestAcknowledge_p->eNB_UE_S1AP_ID;
S1AP_PATH_SWITCH_REQ_ACK(message_p).mme_ue_s1ap_id = s1PathSwitchRequestAcknowledge_p->mme_ue_s1ap_id;
S1AP_PATH_SWITCH_REQ_ACK(message_p).next_hop_chain_count =
s1PathSwitchRequestAcknowledge_p->securityContext.nextHopChainingCount;
memcpy(&S1AP_PATH_SWITCH_REQ_ACK(message_p).next_security_key,
s1PathSwitchRequestAcknowledge_p->securityContext.nextHopParameter.buf,
s1PathSwitchRequestAcknowledge_p->securityContext.nextHopParameter.size);
// optional
if (s1PathSwitchRequestAcknowledge_p->presenceMask &
S1AP_PATHSWITCHREQUESTACKNOWLEDGEIES_UEAGGREGATEMAXIMUMBITRATE_PRESENT) {
// todo
OCTET_STRING_TO_INT32 (
&s1PathSwitchRequestAcknowledge_p->uEaggregateMaximumBitrate.uEaggregateMaximumBitRateUL,
S1AP_PATH_SWITCH_REQ_ACK(message_p).ue_ambr.br_ul
);
OCTET_STRING_TO_INT32 (
&s1PathSwitchRequestAcknowledge_p->uEaggregateMaximumBitrate.uEaggregateMaximumBitRateDL,
S1AP_PATH_SWITCH_REQ_ACK(message_p).ue_ambr.br_dl
);
//S1AP_PATH_SWITCH_REQ_ACK(message_p).ue_ambr.br_ul = 10000;
//S1AP_PATH_SWITCH_REQ_ACK(message_p).ue_ambr.br_dl = 10000;
} else {
S1AP_PATH_SWITCH_REQ_ACK(message_p).ue_ambr.br_ul = 0;
S1AP_PATH_SWITCH_REQ_ACK(message_p).ue_ambr.br_dl = 0;
}
if (s1PathSwitchRequestAcknowledge_p->presenceMask &
S1AP_PATHSWITCHREQUESTACKNOWLEDGEIES_E_RABTOBESWITCHEDULLIST_PRESENT) {
S1AP_PATH_SWITCH_REQ_ACK(message_p).nb_e_rabs_tobeswitched =
s1PathSwitchRequestAcknowledge_p->e_RABToBeSwitchedULList.s1ap_E_RABToBeSwitchedULItem.count;
for (i = 0; i < s1PathSwitchRequestAcknowledge_p->e_RABToBeSwitchedULList.s1ap_E_RABToBeSwitchedULItem.count; i++) {
S1ap_E_RABToBeSwitchedULItem_t *item_p;
item_p = (S1ap_E_RABToBeSwitchedULItem_t *)s1PathSwitchRequestAcknowledge_p->e_RABToBeSwitchedULList.s1ap_E_RABToBeSwitchedULItem.array[i];
S1AP_PATH_SWITCH_REQ_ACK (message_p).e_rabs_tobeswitched[i].e_rab_id = item_p->e_RAB_ID;
memcpy(S1AP_PATH_SWITCH_REQ_ACK (message_p).e_rabs_tobeswitched[i].sgw_addr.buffer,
item_p->transportLayerAddress.buf, item_p->transportLayerAddress.size);
S1AP_PATH_SWITCH_REQ_ACK (message_p).e_rabs_tobeswitched[i].sgw_addr.length =
item_p->transportLayerAddress.size * 8 - item_p->transportLayerAddress.bits_unused;
OCTET_STRING_TO_INT32(&item_p->gTP_TEID,
S1AP_PATH_SWITCH_REQ_ACK (message_p).e_rabs_tobeswitched[i].gtp_teid);
}
}
if (s1PathSwitchRequestAcknowledge_p->presenceMask &
S1AP_PATHSWITCHREQUESTACKNOWLEDGEIES_E_RABTOBERELEASEDLIST_PRESENT) {
S1AP_PATH_SWITCH_REQ_ACK(message_p).nb_e_rabs_tobereleased =
s1PathSwitchRequestAcknowledge_p->e_RABToBeReleasedList.s1ap_E_RABItem.count;
for (i = 0; i < s1PathSwitchRequestAcknowledge_p->e_RABToBeReleasedList.s1ap_E_RABItem.count; i++) {
S1ap_E_RABItem_t *item_p;
item_p = (S1ap_E_RABItem_t *) s1PathSwitchRequestAcknowledge_p->e_RABToBeReleasedList.s1ap_E_RABItem.array[i];
S1AP_PATH_SWITCH_REQ_ACK (message_p).e_rabs_tobereleased[i].e_rab_id = item_p->e_RAB_ID;
}
}
if (s1PathSwitchRequestAcknowledge_p->presenceMask &
S1AP_PATHSWITCHREQUESTACKNOWLEDGEIES_CRITICALITYDIAGNOSTICS_PRESENT) {
S1AP_WARN("S1AP_PATHSWITCHREQUESTACKNOWLEDGEIES_CRITICALITYDIAGNOSTICS flag not supported\n");
}
if (s1PathSwitchRequestAcknowledge_p->presenceMask &
S1AP_PATHSWITCHREQUESTACKNOWLEDGEIES_MME_UE_S1AP_ID_2_PRESENT) {
S1AP_WARN("S1AP_PATHSWITCHREQUESTACKNOWLEDGEIES_MME_UE_S1AP_ID_2 flag not supported\n");
}
itti_send_msg_to_task(TASK_RRC_ENB, ue_desc_p->eNB_instance->instance, message_p);
return 0;
}
static
int s1ap_eNB_handle_s1_path_switch_request_failure(uint32_t assoc_id,
uint32_t stream,
struct s1ap_message_s *s1ap_message_p)
{
S1ap_PathSwitchRequestFailureIEs_t *s1_PathSwitchRequestFailure_p;
s1ap_eNB_mme_data_t *mme_desc_p;
DevAssert(s1ap_message_p != NULL);
s1_PathSwitchRequestFailure_p = &s1ap_message_p->msg.s1ap_PathSwitchRequestFailureIEs;
/* S1 Setup Failure == Non UE-related procedure -> stream 0 */
if (stream != 0) {
S1AP_WARN("[SCTP %d] Received s1 path switch request failure on stream != 0 (%d)\n",
assoc_id, stream);
}
if ((mme_desc_p = s1ap_eNB_get_MME(NULL, assoc_id, 0)) == NULL) {
S1AP_ERROR("[SCTP %d] Received S1 path switch request for non existing "
"MME context\n", assoc_id);
return -1;
}
switch(s1_PathSwitchRequestFailure_p->cause.present) {
case S1ap_Cause_PR_NOTHING:
S1AP_WARN("Received S1 Error indication cause NOTHING\n");
break;
case S1ap_Cause_PR_radioNetwork:
process_radio_network_failure(s1_PathSwitchRequestFailure_p->cause.choice.radioNetwork);
break;
case S1ap_Cause_PR_transport:
process_transport_failure(s1_PathSwitchRequestFailure_p->cause.choice.transport);
break;
case S1ap_Cause_PR_nas:
process_nas_failure(s1_PathSwitchRequestFailure_p->cause.choice.nas);
break;
case S1ap_Cause_PR_misc:
process_misc_failure(s1_PathSwitchRequestFailure_p->cause.choice.protocol);
break;
default:
S1AP_WARN("Received an unknown S1 Error indication cause \n");
}
if (s1_PathSwitchRequestFailure_p->presenceMask & S1AP_PATHSWITCHREQUESTFAILUREIES_CRITICALITYDIAGNOSTICS_PRESENT) {
S1AP_WARN("Critical Diagnostic not supported\n");
}
// TODO continue
return 0;
}
// for the moment, only print the cause ;)
static
void process_radio_network_failure(S1ap_CauseRadioNetwork_t cause){
switch (cause) {
case S1ap_CauseRadioNetwork_unspecified:
S1AP_WARN("Received S1 Error indication S1ap_CauseRadioNetwork_unspecified\n");
break;
case S1ap_CauseRadioNetwork_tx2relocoverall_expiry:
S1AP_WARN("Received S1 Error indication S1ap_CauseRadioNetwork_tx2relocoverall_expiry\n");
break;
case S1ap_CauseRadioNetwork_successful_handover:
S1AP_WARN("Received S1 Error indication S1ap_CauseRadioNetwork_successful_handover\n");
break;
case S1ap_CauseRadioNetwork_release_due_to_eutran_generated_reason:
S1AP_WARN("Received S1 Error indication S1ap_CauseRadioNetwork_release_due_to_eutran_generated_reason\n");
break;
case S1ap_CauseRadioNetwork_handover_cancelled:
S1AP_WARN("Received S1 Error indication S1ap_CauseRadioNetwork_handover_cancelled\n");
break;
case S1ap_CauseRadioNetwork_partial_handover:
S1AP_WARN("Received S1 Error indication S1ap_CauseRadioNetwork_partial_handover\n");
break;
case S1ap_CauseRadioNetwork_ho_failure_in_target_EPC_eNB_or_target_system:
S1AP_WARN("Received S1 Error indication S1ap_CauseRadioNetwork_ho_failure_in_target_EPC_eNB_or_target_system\n");
break;
case S1ap_CauseRadioNetwork_ho_target_not_allowed:
S1AP_WARN("Received S1 Error indication S1ap_CauseRadioNetwork_ho_target_not_allowed\n");
break;
case S1ap_CauseRadioNetwork_tS1relocoverall_expiry:
S1AP_WARN("Received S1 Error indication S1ap_CauseRadioNetwork_tS1relocoverall_expiry\n");
break;
case S1ap_CauseRadioNetwork_tS1relocprep_expiry:
S1AP_WARN("Received S1 Error indication S1ap_CauseRadioNetwork_tS1relocprep_expiry\n");
break;
case S1ap_CauseRadioNetwork_cell_not_available:
S1AP_WARN("Received S1 Error indication S1ap_CauseRadioNetwork_cell_not_available\n");
break;
case S1ap_CauseRadioNetwork_unknown_targetID:
S1AP_WARN("Received S1 Error indication S1ap_CauseRadioNetwork_unknown_targetID\n");
break;
case S1ap_CauseRadioNetwork_no_radio_resources_available_in_target_cell:
S1AP_WARN("Received S1 Error indication S1ap_CauseRadioNetwork_no_radio_resources_available_in_target_cell\n");
break;
case S1ap_CauseRadioNetwork_unknown_mme_ue_s1ap_id:
S1AP_WARN("Received S1 Error indication S1ap_CauseRadioNetwork_unknown_mme_ue_s1ap_id\n");
break;
case S1ap_CauseRadioNetwork_unknown_enb_ue_s1ap_id:
S1AP_WARN("Received S1 Error indication S1ap_CauseRadioNetwork_unknown_enb_ue_s1ap_id\n");
break;
case S1ap_CauseRadioNetwork_unknown_pair_ue_s1ap_id:
S1AP_WARN("Received S1 Error indication S1ap_CauseRadioNetwork_unknown_pair_ue_s1ap_id\n");
break;
case S1ap_CauseRadioNetwork_handover_desirable_for_radio_reason:
S1AP_WARN("Received S1 Error indication S1ap_CauseRadioNetwork_handover_desirable_for_radio_reason\n");
break;
case S1ap_CauseRadioNetwork_time_critical_handover:
S1AP_WARN("Received S1 Error indication S1ap_CauseRadioNetwork_time_critical_handover\n");
break;
case S1ap_CauseRadioNetwork_resource_optimisation_handover:
S1AP_WARN("Received S1 Error indication S1ap_CauseRadioNetwork_resource_optimisation_handover\n");
break;
case S1ap_CauseRadioNetwork_reduce_load_in_serving_cell:
S1AP_WARN("Received S1 Error indication S1ap_CauseRadioNetwork_reduce_load_in_serving_cell\n");
break;
case S1ap_CauseRadioNetwork_user_inactivity:
S1AP_WARN("Received S1 Error indication S1ap_CauseRadioNetwork_user_inactivity\n");
break;
case S1ap_CauseRadioNetwork_radio_connection_with_ue_lost:
S1AP_WARN("Received S1 Error indication S1ap_CauseRadioNetwork_radio_connection_with_ue_lost\n");
break;
case S1ap_CauseRadioNetwork_load_balancing_tau_required:
S1AP_WARN("Received S1 Error indication S1ap_CauseRadioNetwork_load_balancing_tau_required\n");
break;
case S1ap_CauseRadioNetwork_cs_fallback_triggered:
S1AP_WARN("Received S1 Error indication S1ap_CauseRadioNetwork_cs_fallback_triggered\n");
break;
case S1ap_CauseRadioNetwork_ue_not_available_for_ps_service:
S1AP_WARN("Received S1 Error indication S1ap_CauseRadioNetwork_ue_not_available_for_ps_service\n");
break;
case S1ap_CauseRadioNetwork_radio_resources_not_available:
S1AP_WARN("Received S1 Error indication S1ap_CauseRadioNetwork_radio_resources_not_available\n");
break;
case S1ap_CauseRadioNetwork_failure_in_radio_interface_procedure:
S1AP_WARN("Received S1 Error indication S1ap_CauseRadioNetwork_failure_in_radio_interface_procedure\n");
break;
case S1ap_CauseRadioNetwork_invals1ap_id_qos_combination:
S1AP_WARN("Received S1 Error indication S1ap_CauseRadioNetwork_invals1ap_id_qos_combination\n");
break;
case S1ap_CauseRadioNetwork_interrat_redirection:
S1AP_WARN("Received S1 Error indication S1ap_CauseRadioNetwork_interrat_redirection\n");
break;
case S1ap_CauseRadioNetwork_interaction_with_other_procedure:
S1AP_WARN("Received S1 Error indication S1ap_CauseRadioNetwork_interaction_with_other_procedure\n");
break;
case S1ap_CauseRadioNetwork_unknown_E_RAB_ID:
S1AP_WARN("Received S1 Error indication S1ap_CauseRadioNetwork_unknown_E_RAB_ID\n");
break;
case S1ap_CauseRadioNetwork_multiple_E_RAB_ID_instances:
S1AP_WARN("Received S1 Error indication S1ap_CauseRadioNetwork_multiple_E_RAB_ID_instances\n");
break;
case S1ap_CauseRadioNetwork_encryption_and_or_integrity_protection_algorithms_not_supported:
S1AP_WARN("Received S1 Error indication S1ap_CauseRadioNetwork_encryption_and_or_integrity_protection_algorithms_not_supported\n");
break;
case S1ap_CauseRadioNetwork_s1_intra_system_handover_triggered:
S1AP_WARN("Received S1 Error indication S1ap_CauseRadioNetwork_s1_intra_system_handover_triggered\n");
break;
case S1ap_CauseRadioNetwork_s1_inter_system_handover_triggered:
S1AP_WARN("Received S1 Error indication S1ap_CauseRadioNetwork_s1_inter_system_handover_triggered\n");
break;
case S1ap_CauseRadioNetwork_x2_handover_triggered:
S1AP_WARN("Received S1 Error indication S1ap_CauseRadioNetwork_x2_handover_triggered\n");
break;
case S1ap_CauseRadioNetwork_redirection_towards_1xRTT:
S1AP_WARN("Received S1 Error indication S1ap_CauseRadioNetwork_redirection_towards_1xRTT\n");
break;
case S1ap_CauseRadioNetwork_not_supported_QCI_value:
S1AP_WARN("Received S1 Error indication S1ap_CauseRadioNetwork_not_supported_QCI_value\n");
break;
case S1ap_CauseRadioNetwork_invals1ap_id_CSG_Id:
S1AP_WARN("Received S1 Error indication S1ap_CauseRadioNetwork_invals1ap_id_CSG_Id\n");
break;
default:
S1AP_WARN("Received S1 Error indication cause radio network case not handled\n");
}
}
static
void process_transport_failure(S1ap_CauseTransport_t cause) {
switch (cause) {
case S1ap_CauseTransport_transport_resource_unavailable:
S1AP_WARN("Received S1 Error indication S1ap_CauseTransport_transport_resource_unavailable\n");
break;
case S1ap_CauseTransport_unspecified:
S1AP_WARN("Received S1 Error indication S1ap_CauseTransport_unspecified\n");
break;
default:
S1AP_WARN("Received S1 Error indication cause transport case not handled\n");
}
}
static
void process_nas_failure(S1ap_CauseNas_t cause) {
switch (cause) {
case S1ap_CauseNas_normal_release:
S1AP_WARN("Received S1 Error indication S1ap_CauseNas_normal_release\n");
break;
case S1ap_CauseNas_authentication_failure:
S1AP_WARN("Received S1 Error indication S1ap_CauseNas_authentication_failure\n");
break;
case S1ap_CauseNas_detach:
S1AP_WARN("Received S1 Error indication S1ap_CauseNas_detach\n");
break;
case S1ap_CauseNas_unspecified:
S1AP_WARN("Received S1 Error indication S1ap_CauseNas_unspecified\n");
break;
case S1ap_CauseNas_csg_subscription_expiry:
S1AP_WARN("Received S1 Error indication S1ap_CauseNas_csg_subscription_expiry\n");
break;
default:
S1AP_WARN("Received S1 Error indication cause nas case not handled\n");
}
}
static
void process_protocol_failure(S1ap_CauseProtocol_t cause){
switch (cause) {
case S1ap_CauseProtocol_transfer_syntax_error:
S1AP_WARN("Received S1 Error indication S1ap_CauseProtocol_transfer_syntax_error\n");
break;
case S1ap_CauseProtocol_abstract_syntax_error_reject:
S1AP_WARN("Received S1 Error indication S1ap_CauseProtocol_abstract_syntax_error_reject\n");
break;
case S1ap_CauseProtocol_abstract_syntax_error_ignore_and_notify:
S1AP_WARN("Received S1 Error indication S1ap_CauseProtocol_abstract_syntax_error_ignore_and_notify\n");
break;
case S1ap_CauseProtocol_message_not_compatible_with_receiver_state:
S1AP_WARN("Received S1 Error indication S1ap_CauseProtocol_message_not_compatible_with_receiver_state\n");
break;
case S1ap_CauseProtocol_semantic_error:
S1AP_WARN("Received S1 Error indication S1ap_CauseProtocol_semantic_error\n");
break;
case S1ap_CauseProtocol_abstract_syntax_error_falsely_constructed_message:
S1AP_WARN("Received S1 Error indication S1ap_CauseProtocol_abstract_syntax_error_falsely_constructed_message\n");
break;
case S1ap_CauseProtocol_unspecified:
S1AP_WARN("Received S1 Error indication S1ap_CauseProtocol_unspecified\n");
break;
default:
S1AP_WARN("Received S1 Error indication cause protocol case not handled\n");
}
}
static
void process_misc_failure(S1ap_CauseMisc_t cause){
switch (cause) {
case S1ap_CauseMisc_control_processing_overload:
S1AP_WARN("Received S1 Error indication S1ap_CauseMisc_control_processing_overload\n");
break;
case S1ap_CauseMisc_not_enough_user_plane_processing_resources:
S1AP_WARN("Received S1 Error indication S1ap_CauseMisc_not_enough_user_plane_processing_resources\n");
break;
case S1ap_CauseMisc_hardware_failure:
S1AP_WARN("Received S1 Error indication S1ap_CauseMisc_hardware_failure\n");
break;
case S1ap_CauseMisc_om_intervention:
S1AP_WARN("Received S1 Error indication S1ap_CauseMisc_om_intervention\n");
break;
case S1ap_CauseMisc_unspecified:
S1AP_WARN("Received S1 Error indication S1ap_CauseMisc_unspecified\n");
break;
case S1ap_CauseMisc_unknown_PLMN:
S1AP_WARN("Received S1 Error indication S1ap_CauseMisc_unknown_PLMN\n");
break;
default:
S1AP_WARN("Received S1 Error indication cause misc case not handled\n");
}
}

View File

@@ -837,3 +837,152 @@ int s1ap_eNB_e_rab_setup_resp(instance_t instance,
return ret;
}
//------------------------------------------------------------------------------
int s1ap_eNB_path_switch_req(instance_t instance,
s1ap_path_switch_req_t *path_switch_req_p)
//------------------------------------------------------------------------------
{
s1ap_eNB_instance_t *s1ap_eNB_instance_p = NULL;
struct s1ap_eNB_ue_context_s *ue_context_p = NULL;
S1ap_PathSwitchRequestIEs_t *initial_ies_p = NULL;
s1ap_message message;
uint8_t *buffer = NULL;
uint32_t length;
int ret = -1;
int i;
/* Retrieve the S1AP eNB instance associated with Mod_id */
s1ap_eNB_instance_p = s1ap_eNB_get_instance(instance);
DevAssert(path_switch_req_p != NULL);
DevAssert(s1ap_eNB_instance_p != NULL);
if ((ue_context_p = s1ap_eNB_get_ue_context(s1ap_eNB_instance_p,
path_switch_req_p->eNB_ue_s1ap_id)) == NULL) {
/* The context for this eNB ue s1ap id doesn't exist in the map of eNB UEs */
S1AP_WARN("Failed to find ue context associated with eNB ue s1ap id: 0x%06x\n",
path_switch_req_p->eNB_ue_s1ap_id);
return -1;
}
/* Uplink NAS transport can occur either during an s1ap connected state
* or during initial attach (for example: NAS authentication).
*/
if (!(ue_context_p->ue_state == S1AP_UE_CONNECTED ||
ue_context_p->ue_state == S1AP_UE_WAITING_CSR)) {
S1AP_WARN("You are attempting to send NAS data over non-connected "
"eNB ue s1ap id: %06x, current state: %d\n",
path_switch_req_p->eNB_ue_s1ap_id, ue_context_p->ue_state);
return -1;
}
/* Prepare the S1AP message to encode */
memset(&message, 0, sizeof(s1ap_message));
message.direction = S1AP_PDU_PR_successfulOutcome;
message.procedureCode = S1ap_ProcedureCode_id_PathSwitchRequest;
message.criticality = S1ap_Criticality_reject;
initial_ies_p = &message.msg.s1ap_PathSwitchRequestIEs;
initial_ies_p->eNB_UE_S1AP_ID = path_switch_req_p->eNB_ue_s1ap_id;
initial_ies_p->sourceMME_UE_S1AP_ID = ue_context_p->mme_ue_s1ap_id;
// S1AP_PATHSWITCHREQUESTIES_CSG_ID_PRESENT
// S1AP_PATHSWITCHREQUESTIES_CELLACCESSMODE_PRESENT
// S1AP_PATHSWITCHREQUESTIES_SOURCEMME_GUMMEI_PRESENT
initial_ies_p->presenceMask |= 0;
for (i = 0; i < path_switch_req_p->nb_of_e_rabs; i++) {
S1ap_E_RABToBeSwitchedDLItem_t *new_item;
new_item = calloc(1, sizeof(S1ap_E_RABToBeSwitchedDLListIEs_t));
new_item->e_RAB_ID = path_switch_req_p->e_rabs_tobeswitched[i].e_rab_id;
GTP_TEID_TO_ASN1(path_switch_req_p->e_rabs_tobeswitched[i].gtp_teid, &new_item->gTP_TEID);
new_item->transportLayerAddress.buf = path_switch_req_p->e_rabs_tobeswitched[i].eNB_addr.buffer;
new_item->transportLayerAddress.size = path_switch_req_p->e_rabs_tobeswitched[i].eNB_addr.length;
new_item->transportLayerAddress.bits_unused = 0;
S1AP_DEBUG("path_switch_req: e_rab ID %ld, teid %u, enb_addr %d.%d.%d.%d, SIZE %d\n",
new_item->e_RAB_ID,
path_switch_req_p->e_rabs_tobeswitched[i].gtp_teid,
new_item->transportLayerAddress.buf[0],
new_item->transportLayerAddress.buf[1],
new_item->transportLayerAddress.buf[2],
new_item->transportLayerAddress.buf[3],
new_item->transportLayerAddress.size);
S1ap_IE_t *ie = s1ap_new_ie(S1ap_ProtocolIE_ID_id_E_RABToBeSwitchedDLItem,
S1ap_Criticality_ignore,
&asn_DEF_S1ap_E_RABToBeSwitchedDLItem,
new_item);
ASN_SEQUENCE_ADD(&initial_ies_p->e_RABToBeSwitchedDLList.s1ap_E_RABToBeSwitchedDLItem,
ie);
}
// S1ap_EUTRAN_CGI_t
MCC_MNC_TO_PLMNID(
s1ap_eNB_instance_p->mcc,
s1ap_eNB_instance_p->mnc,
s1ap_eNB_instance_p->mnc_digit_length,
&initial_ies_p->eutran_cgi.pLMNidentity);
MACRO_ENB_ID_TO_CELL_IDENTITY(s1ap_eNB_instance_p->eNB_id,
0,
&initial_ies_p->eutran_cgi.cell_ID);
// S1ap_TAI_t
/* MCC/MNC should be repeated in TAI and EUTRAN CGI */
MCC_MNC_TO_PLMNID(
s1ap_eNB_instance_p->mcc,
s1ap_eNB_instance_p->mnc,
s1ap_eNB_instance_p->mnc_digit_length,
&initial_ies_p->tai.pLMNidentity);
TAC_TO_ASN1(s1ap_eNB_instance_p->tac,&initial_ies_p->tai.tAC);
//S1ap_UESecurityCapabilities_t
INT16_TO_OCTET_STRING(
path_switch_req_p->security_capabilities.encryption_algorithms,
&initial_ies_p->ueSecurityCapabilities.encryptionAlgorithms
);
INT16_TO_OCTET_STRING(
path_switch_req_p->security_capabilities.integrity_algorithms,
&initial_ies_p->ueSecurityCapabilities.encryptionAlgorithms
);
fprintf(stderr, "start encode\n");
if (s1ap_eNB_encode_pdu(&message, &buffer, &length) < 0) {
S1AP_ERROR("Failed to encode Path Switch Req \n");
/* Encode procedure has failed... */
return -1;
}
MSC_LOG_TX_MESSAGE(
MSC_S1AP_ENB,
MSC_S1AP_MME,
(const char *)buffer,
length,
MSC_AS_TIME_FMT" E_RAN Setup successfulOutcome eNB_ue_s1ap_id %u mme_ue_s1ap_id %u",
0,0,//MSC_AS_TIME_ARGS(ctxt_pP),
initial_ies_p->eNB_UE_S1AP_ID,
initial_ies_p->sourceMME_UE_S1AP_ID);
/* UE associated signalling -> use the allocated stream */
s1ap_eNB_itti_send_sctp_data_req(s1ap_eNB_instance_p->instance,
ue_context_p->mme_ref->assoc_id, buffer,
length, ue_context_p->tx_stream);
return ret;
}

View File

@@ -44,4 +44,7 @@ int s1ap_eNB_ue_capabilities(instance_t instance,
int s1ap_eNB_e_rab_setup_resp(instance_t instance,
s1ap_e_rab_setup_resp_t *e_rab_setup_resp_p);
int s1ap_eNB_path_switch_req(instance_t instance,
s1ap_path_switch_req_t *path_switch_req_p);
#endif /* S1AP_ENB_NAS_PROCEDURES_H_ */

View File

@@ -63,3 +63,45 @@ int derive_keNB(const uint8_t kasme[32], const uint32_t nas_count, uint8_t *keNB
}
#endif
int
derive_keNB_star (
const uint8_t *kenb_32,
const uint16_t pci,
const uint32_t earfcn_dl,
const bool is_rel8_only,
uint8_t *kenb_star)
{
// see 33.401 section A.5 KeNB* derivation function
uint8_t s[10] = {0};
// FC = 0x13
s[0] = FC_KENB_STAR;
// P0 = PCI (target physical cell id)
s[1] = (pci & 0x0000ff00) >> 8;
s[2] = (pci & 0x000000ff);
// L0 = length of PCI (i.e. 0x00 0x02)
s[3] = 0x00;
s[4] = 0x02;
// P1 = EARFCN-DL (target physical cell downlink frequency)
if (is_rel8_only) {
s[5] = (earfcn_dl & 0x0000ff00) >> 8;
s[6] = (earfcn_dl & 0x000000ff);
s[7] = 0x00;
s[8] = 0x02;
kdf (kenb_32, 32, s, 9, kenb_star, 32);
} else {
s[5] = (earfcn_dl & 0x00ff0000) >> 16;
s[6] = (earfcn_dl & 0x0000ff00) >> 8;
s[7] = (earfcn_dl & 0x000000ff);
s[8] = 0x00;
s[9] = 0x03;
kdf (kenb_32, 32, s, 10, kenb_star, 32);
}
// L1 length of EARFCN-DL (i.e. L1 = 0x00 0x02 if EARFCN-DL is between 0 and 65535, and L1 = 0x00 0x03 if EARFCN-DL is between 65536 and 262143)
// NOTE: The length of EARFCN-DL cannot be generally set to 3 bytes for backward compatibility reasons: A Rel-8
// entity (UE or eNB) would always assume an input parameter length of 2 bytes for the EARFCN-DL. This
// would lead to different derived keys if another entity assumed an input parameter length of 3 bytes for the
// EARFCN-DL.
return 0;
}

View File

@@ -23,6 +23,7 @@
#define SECU_DEFS_H_
#include "security_types.h"
#include <stdbool.h>
#define EIA0_ALG_ID 0x00
#define EIA1_128_ALG_ID 0x01
@@ -44,6 +45,9 @@ void kdf(const uint8_t *key,
int derive_keNB(const uint8_t kasme[32], const uint32_t nas_count, uint8_t *keNB);
int derive_keNB_star (const uint8_t *kenb_32, const uint16_t pci, const uint32_t earfcn_dl,
const bool is_rel8_only, uint8_t * kenb_star);
int derive_key_nas(algorithm_type_dist_t nas_alg_type, uint8_t nas_enc_alg_id,
const uint8_t kasme[32], uint8_t *knas);

View File

@@ -189,6 +189,109 @@ do { \
(oCTETsTRING)->size = 3; \
} while(0)
#define ECI_TO_BIT_STRING(eci, bitstring) \
do { \
(bitstring)->size=4; \
(bitstring)->bits_unused=4; \
(bitstring)->buf=calloc (4, sizeof (uint8_t)); \
(bitstring)->buf[0] = (eci) >> 20; \
(bitstring)->buf[1] = (eci) >> 12; \
(bitstring)->buf[2] = (eci) >> 4; \
(bitstring)->buf[3] = (eci) << 4; \
}while(0)
#define MMEGID_TO_OCTET_STRING(mmegid,octetstring) \
do { \
(octetstring)->size=2; \
(octetstring)->buf=calloc (2, sizeof (uint8_t)); \
(octetstring)->buf[0] = (mmegid) >> 8; \
(octetstring)->buf[1] = (mmegid); \
}while(0)
#define MMEC_TO_OCTET_STRING(mmec, octetstring) \
do { \
(octetstring)->size=1; \
(octetstring)->buf=calloc (1, sizeof (uint8_t));\
(octetstring)->buf[0] = (mmec); \
}while(0)
#define ENCRALG_TO_BIT_STRING(encralg, bitstring) \
do { \
(bitstring)->size=2; \
(bitstring)->bits_unused=0; \
(bitstring)->buf=calloc (1, sizeof (uint8_t)); \
(bitstring)->buf[0] = (encralg) >> 8; \
(bitstring)->buf[1] = (encralg); \
}while(0)
#define INTPROTALG_TO_BIT_STRING(intprotalg, bitstring) \
do { \
(bitstring)->size=2; \
(bitstring)->bits_unused=0; \
(bitstring)->buf=calloc (2, sizeof (uint8_t)); \
(bitstring)->buf[0] = (intprotalg) >> 8; \
(bitstring)->buf[1] = (intprotalg); \
}while(0)
#define KENB_STAR_TO_BIT_STRING(kenbstar, bitstring) \
do { \
(bitstring)->size=32; \
(bitstring)->bits_unused=0; \
(bitstring)->buf= calloc (32, sizeof (uint8_t));\
memcpy((bitstring)->buf, kenbstar, 32*sizeof(uint8_t)); \
}while(0)
#define UEAGMAXBITRTD_TO_ASN_PRIMITIVES(uegmaxbitrtd, asnprimitives) \
do { \
(asnprimitives)->size=5; \
(asnprimitives)->buf=calloc (5, sizeof (uint8_t)); \
(asnprimitives)->buf[0] = (uegmaxbitrtd) >> 32; \
(asnprimitives)->buf[1] = (uegmaxbitrtd) >> 24; \
(asnprimitives)->buf[2] = (uegmaxbitrtd) >> 16; \
(asnprimitives)->buf[3] = (uegmaxbitrtd) >> 8; \
(asnprimitives)->buf[4] = (uegmaxbitrtd); \
}while(0)
#define UEAGMAXBITRTU_TO_ASN_PRIMITIVES(uegmaxbitrtu, asnprimitives) \
do { \
(asnprimitives)->size=5; \
(asnprimitives)->buf=calloc (5, sizeof (uint8_t)); \
(asnprimitives)->buf[0] = (uegmaxbitrtu) >> 32; \
(asnprimitives)->buf[1] = (uegmaxbitrtu) >> 24; \
(asnprimitives)->buf[2] = (uegmaxbitrtu) >> 16; \
(asnprimitives)->buf[3] = (uegmaxbitrtu) >> 8; \
(asnprimitives)->buf[4] = (uegmaxbitrtu); \
}while(0)
#define TRLA_TO_BIT_STRING(trla, bitstring) \
do { \
(bitstring)->size=4; \
(bitstring)->bits_unused=0; \
(bitstring)->buf=calloc (4, sizeof (uint8_t)); \
(bitstring)->buf[0] = (trla)>>24; \
(bitstring)->buf[1] = (trla)>>16; \
(bitstring)->buf[2] = (trla)>>8; \
(bitstring)->buf[3] = (trla); \
}while(0)
#define GTP_TEID_TO_OCTET_STRING(gtpteid, octetstring) \
do { \
(octetstring)->size=4; \
(octetstring)->buf=calloc (4, sizeof (uint8_t));\
(octetstring)->buf[0] = (gtpteid)>>24; \
(octetstring)->buf[1] = (gtpteid)>>16; \
(octetstring)->buf[2] = (gtpteid)>>8; \
(octetstring)->buf[3] = (gtpteid); \
}while(0)
#define TAC_TO_OCTET_STRING(tac, octetstring)\
do { \
(octetstring)->size=2; \
(octetstring)->buf=calloc (2, sizeof (uint8_t)); \
(octetstring)->buf[0] = (tac) >> 8; \
(octetstring)->buf[1] = (tac); \
}while(0)
#define MCC_MNC_TO_TBCD(mCC, mNC, mNCdIGITlENGTH, tBCDsTRING) \
do { \
char _buf[3]; \

View File

@@ -32,6 +32,10 @@
# include "udp_eNB_task.h"
# include "gtpv1u_eNB_task.h"
# endif
# include "sctp_eNB_task.h"
# if defined (ENABLE_USE_X2)
# include "x2ap_eNB.h"
# endif
# if ENABLE_RAL
# include "lteRALue.h"
# include "lteRALenb.h"
@@ -62,11 +66,7 @@ int create_tasks(uint32_t enb_nb, uint32_t ue_nb)
# if defined(ENABLE_USE_MME)
{
if (enb_nb > 0) {
if (itti_create_task (TASK_SCTP, sctp_eNB_task, NULL) < 0) {
LOG_E(SCTP, "Create task for SCTP failed\n");
return -1;
}
if (itti_create_task (TASK_S1AP, s1ap_eNB_task, NULL) < 0) {
LOG_E(S1AP, "Create task for S1AP failed\n");
return -1;
@@ -96,6 +96,19 @@ int create_tasks(uint32_t enb_nb, uint32_t ue_nb)
# endif
}
# endif
if (enb_nb > 0) {
#if ENABLE_USE_X2
if (itti_create_task (TASK_X2AP, x2ap_task, NULL) < 0) {
LOG_E(X2AP, "Create task for X2AP failed\n");
return -1;
}
#endif
if (itti_create_task (TASK_SCTP, sctp_eNB_task, NULL) < 0) {
LOG_E(SCTP, "Create task for SCTP failed\n");
return -1;
}
}
if (enb_nb > 0) {
if (itti_create_task (TASK_RRC_ENB, rrc_enb_task, NULL) < 0) {

View File

@@ -0,0 +1,190 @@
Active_eNBs = ( "eNB_Eurecom_LTEBox");
# Asn1_verbosity, choice in: none, info, annoying
Asn1_verbosity = "none";
eNBs =
(
{
////////// Identification parameters:
eNB_ID = 0xe00;
cell_type = "CELL_MACRO_ENB";
eNB_name = "eNB_Eurecom_X2HO_LTEBox";
// Tracking area code, 0x0000 and 0xfffe are reserved values
tracking_area_code = "1";
mobile_country_code = "208";
mobile_network_code = "95";
////////// Physical parameters:
component_carriers = (
{
node_function = "eNodeB_3GPP";
node_timing = "synch_to_ext_device";
node_synch_ref = 0;
frame_type = "FDD";
tdd_config = 3;
tdd_config_s = 0;
prefix_type = "NORMAL";
eutra_band = 7;
downlink_frequency = 2660000000L;
uplink_frequency_offset = -120000000;
Nid_cell = 0;
N_RB_DL = 25;
Nid_cell_mbsfn = 0;
nb_antenna_ports = 1;
nb_antennas_tx = 1;
nb_antennas_rx = 1;
tx_gain = 90;
rx_gain = 125;
prach_root = 0;
prach_config_index = 0;
prach_high_speed = "DISABLE";
prach_zero_correlation = 1;
prach_freq_offset = 2;
pucch_delta_shift = 1;
pucch_nRB_CQI = 1;
pucch_nCS_AN = 0;
pucch_n1_AN = 32;
pdsch_referenceSignalPower = -24;
pdsch_p_b = 0;
pusch_n_SB = 1;
pusch_enable64QAM = "DISABLE";
pusch_hoppingMode = "interSubFrame";
pusch_hoppingOffset = 0;
pusch_groupHoppingEnabled = "ENABLE";
pusch_groupAssignment = 0;
pusch_sequenceHoppingEnabled = "DISABLE";
pusch_nDMRS1 = 1;
phich_duration = "NORMAL";
phich_resource = "ONESIXTH";
srs_enable = "DISABLE";
srs_BandwidthConfig = 2;
srs_SubframeConfig = 0;
srs_ackNackST = "DISABLE";
srs_MaxUpPts = "DISABLE";
pusch_p0_Nominal = -90;
pusch_alpha = "AL1";
pucch_p0_Nominal = -96;
msg3_delta_Preamble = 6;
pucch_deltaF_Format1 = "deltaF2";
pucch_deltaF_Format1b = "deltaF3";
pucch_deltaF_Format2 = "deltaF0";
pucch_deltaF_Format2a = "deltaF0";
pucch_deltaF_Format2b = "deltaF0";
rach_numberOfRA_Preambles = 64;
rach_preamblesGroupAConfig = "DISABLE";
/*
rach_sizeOfRA_PreamblesGroupA = ;
rach_messageSizeGroupA = ;
rach_messagePowerOffsetGroupB = ;
*/
rach_powerRampingStep = 4;
rach_preambleInitialReceivedTargetPower = -104;
rach_preambleTransMax = 10;
rach_raResponseWindowSize = 10;
rach_macContentionResolutionTimer = 48;
rach_maxHARQ_Msg3Tx = 4;
pcch_default_PagingCycle = 128;
pcch_nB = "oneT";
bcch_modificationPeriodCoeff = 2;
ue_TimersAndConstants_t300 = 1000;
ue_TimersAndConstants_t301 = 1000;
ue_TimersAndConstants_t310 = 1000;
ue_TimersAndConstants_t311 = 10000;
ue_TimersAndConstants_n310 = 20;
ue_TimersAndConstants_n311 = 1;
ue_TransmissionMode = 1;
}
);
srb1_parameters :
{
# timer_poll_retransmit = (ms) [5, 10, 15, 20,... 250, 300, 350, ... 500]
timer_poll_retransmit = 80;
# timer_reordering = (ms) [0,5, ... 100, 110, 120, ... ,200]
timer_reordering = 35;
# timer_reordering = (ms) [0,5, ... 250, 300, 350, ... ,500]
timer_status_prohibit = 0;
# poll_pdu = [4, 8, 16, 32 , 64, 128, 256, infinity(>10000)]
poll_pdu = 4;
# poll_byte = (kB) [25,50,75,100,125,250,375,500,750,1000,1250,1500,2000,3000,infinity(>10000)]
poll_byte = 99999;
# max_retx_threshold = [1, 2, 3, 4 , 6, 8, 16, 32]
max_retx_threshold = 4;
}
# ------- SCTP definitions
SCTP :
{
# Number of streams to use in input/output
SCTP_INSTREAMS = 2;
SCTP_OUTSTREAMS = 2;
};
////////// MME parameters:
mme_ip_address = ( { ipv4 = "192.168.12.26";
ipv6 = "192:168:30::17";
active = "yes";
preference = "ipv4";
}
);
///X2
target_enb_x2_ip_address = ( { ipv4 = "127.0.0.10";
ipv6 = "192:168:30::17";
active = "yes";
preference = "ipv4";
}
);
NETWORK_INTERFACES :
{
ENB_INTERFACE_NAME_FOR_S1_MME = "eth6";
ENB_IPV4_ADDRESS_FOR_S1_MME = "192.168.12.82/24";
ENB_INTERFACE_NAME_FOR_S1U = "eth6";
ENB_IPV4_ADDRESS_FOR_S1U = "192.168.12.82/24";
ENB_PORT_FOR_S1U = 2152; # Spec 2152
ENB_INTERFACE_NAME_FOR_X2C = "lo";
ENB_IPV4_ADDRESS_FOR_X2C = "127.0.0.11/24";
ENB_PORT_FOR_X2C = 36422; # Spec ?
ENB_INTERFACE_NAME_FOR_X2U = "eth0";
ENB_IPV4_ADDRESS_FOR_X2U = "10.0.1.100/24";
ENB_PORT_FOR_X2U = 1234; # Spec ?
};
log_config :
{
global_log_level ="info";
global_log_verbosity ="medium";
hw_log_level ="info";
hw_log_verbosity ="medium";
phy_log_level ="info";
phy_log_verbosity ="medium";
mac_log_level ="info";
mac_log_verbosity ="high";
rlc_log_level ="info";
rlc_log_verbosity ="medium";
pdcp_log_level ="info";
pdcp_log_verbosity ="medium";
rrc_log_level ="info";
rrc_log_verbosity ="medium";
};
}
);

View File

@@ -179,7 +179,7 @@ extern uint8_t target_ul_mcs;
extern uint8_t abstraction_flag;
extern uint8_t ethernet_flag;
extern uint16_t Nid_cell;
extern uint8_t use_user_control_interface;
extern LTE_DL_FRAME_PARMS *frame_parms[MAX_NUM_CCs];
double cpuf;
@@ -236,6 +236,7 @@ help (void)
printf ("-g Set multicast group ID (0,1,2,3) - valid if M is set\n");
printf ("-G Enable background traffic \n");
printf ("-H Enable handover operation (default disabled) \n");
printf ("-i Run with user control interface");
printf ("-I Enable CLI interface (to connect use telnet localhost 1352)\n");
printf ("-k Set the Ricean factor (linear)\n");
printf ("-K [log_file] Enable ITTI logging into log_file\n");
@@ -760,7 +761,13 @@ l2l1_task (void *args_p)
if (all_done == 0)
usleep(500);
}
// add this to the oai CLI
if (use_user_control_interface) {
if ( user_control_interface(10*frame + sf)==-1) {
frame=oai_emulation.info.n_frames; // exit main loop
break;
}
}
// increment timestamps
for (eNB_inst = oai_emulation.info.first_enb_local;
(eNB_inst

View File

@@ -117,6 +117,8 @@ uint8_t beta_ACK = 0;
uint8_t beta_RI = 0;
uint8_t beta_CQI = 2;
uint8_t target_ul_mcs = 16;
uint8_t use_user_control_interface = 0;
LTE_DL_FRAME_PARMS *frame_parms[MAX_NUM_CCs];
int map1,map2;
double **ShaF = NULL;
@@ -230,6 +232,8 @@ void get_simulation_options(int argc, char *argv[])
LONG_OPTION_T_NOWAIT,
LONG_OPTION_T_DONT_FORK,
#endif
LONG_OPTION_USER_CONTROL_INTERFACE
};
static struct option long_options[] = {
@@ -269,7 +273,7 @@ void get_simulation_options(int argc, char *argv[])
{"T_nowait", no_argument, 0, LONG_OPTION_T_NOWAIT},
{"T_dont_fork", no_argument, 0, LONG_OPTION_T_DONT_FORK},
#endif
{"user-control-interface",no_argument,0,LONG_OPTION_USER_CONTROL_INTERFACE},
{NULL, 0, NULL, 0}
};
@@ -432,6 +436,10 @@ void get_simulation_options(int argc, char *argv[])
break;
#endif
case LONG_OPTION_USER_CONTROL_INTERFACE:
use_user_control_interface=1;
break;
case LONG_OPTION_XFORMS:
xforms=1;
@@ -1958,6 +1966,93 @@ void init_time()
td_avg = TARGET_SF_TIME_NS;
}
int user_control_interface(int sfn) {
static int wait_sfn = 1<<31;
int wait_sfn_new=0,not_done=1;
char string[100],cp[100],*token;
PHY_VARS_UE *UE;
int UEid,ret;
while (not_done) {
if (sfn < wait_sfn) {
not_done=0;
return(0);
}
else {
printf("oaisim (%d)> ",sfn);
ret=fgets(string, sizeof(string), stdin);
}
token = strtok (string, " \n");
if (token && (strcmp(token,"run")==0)) {
token = strtok(NULL," \n");
if (token) {
wait_sfn_new = atoi(token);
}
else
wait_sfn_new = sfn+1;
if (wait_sfn_new <= sfn)
printf("Illegal sfn %d\n",wait_sfn_new);
else {
wait_sfn = wait_sfn_new;
not_done=0;
return(0);
}
}
else if (token && (strcmp(token,"quit")==0)) {
not_done=0;
return(-1);
}
else if (token && (strcmp(token,"step")==0)) {
wait_sfn_new = sfn+1;
not_done=0;
return(0);
}
else if (token && (strcmp(token,"dump")==0)) {
token = strtok(NULL," \n");
if (token && (strcmp(token,"UEPHY")==0)) {
token = strtok(NULL," \n");
if (token)
UEid=atoi(token);
else
UEid=0;
UE = PHY_vars_UE_g[UEid][0]; // fix to CCid 0
printf("UE %d Frame %3d Subframe %2d\n----------------------\n",UEid,sfn/10,sfn%10);
printf("N_id_Cell %d\t",UE->frame_parms.Nid_cell);
printf("N_RB_DL %d\t",UE->frame_parms.N_RB_DL);
printf("RX Gain %d\t",UE->rx_total_gain_dB);
printf("N0 %d dBm/RE\t",UE->measurements.n0_power_tot_dBm);
printf("RSSI %f dBm/RE\t",10*log10(UE->measurements.rssi)-UE->rx_total_gain_dB);
printf("\n");
printf("RSRP 0 (%d) %f dBm/RE\t",UE->frame_parms.Nid_cell,10*log10(1+UE->measurements.rsrp[0])-UE->rx_total_gain_dB);
printf("RSRP 1 (%d) %f dBm/RE\t",UE->measurements.adj_cell_id[0],10*log10(1+UE->measurements.rsrp[1])-UE->rx_total_gain_dB);
printf("RSRP 2 (%d) %f dBm/RE\t",UE->measurements.adj_cell_id[1],10*log10(1+UE->measurements.rsrp[2])-UE->rx_total_gain_dB);
printf("\n");
printf("RSRP 3 (%d) %f dBm/RE\t",UE->measurements.adj_cell_id[2],10*log10(1+UE->measurements.rsrp[3])-UE->rx_total_gain_dB);
printf("RSRP 4 (%d) %f dBm/RE\t",UE->measurements.adj_cell_id[3],10*log10(1+UE->measurements.rsrp[4])-UE->rx_total_gain_dB);
printf("RSRP 5 (%d) %f dBm/RE\t",UE->measurements.adj_cell_id[4],10*log10(1+UE->measurements.rsrp[5])-UE->rx_total_gain_dB);
printf("RSRP 6 (%d) %f dBm/RE\t",UE->measurements.adj_cell_id[5],10*log10(1+UE->measurements.rsrp[6])-UE->rx_total_gain_dB);
printf("\n");
}
else {
printf("Frame %3d Subframe %2d\n-----------------",sfn/10,sfn%10);
}
}
else {
printf("Commands \n\n");
printf("run sfn\t\t\t run until subframe number\n");
printf("step\t\t\t run one subframe\n");
printf("dump [UEPHY] index\t dump UE information\n");
printf("quit\t\t\t quit oaisim\n");
}
}
return(0);
}
/*
int openair0_transport_load(openair0_device *device, openair0_config_t *openair0_cfg, eth_params_t * eth_params) {

View File

@@ -67,4 +67,6 @@ int init_slot_isr(void);
void wait_for_slot_isr(void);
int user_control_interface(int);
#endif /* OAISIM_FUNCTIONS_H_ */