X2AP MOBILITY PROCEDURES (X2AP HANDOVER REQUEST/REQUEST ACK)

S1AP PATH SWITCH REQUEST/REQUEST ACK/FAILURE
RRC MEASUREMENT REPORT
MINOR CHANGES IN MAC LAYER
parent e8a1fb5f
......@@ -62,9 +62,9 @@ typedef enum {
MSC_S11_MME,
MSC_S6A_MME,
MSC_HSS,
MAX_MSC_PROTOS,
MSC_X2AP_SRC_ENB,
MSC_X2AP_TARGET_ENB,
MAX_MSC_PROTOS,
} msc_proto_t;
......
......@@ -39,6 +39,8 @@ MESSAGE_DEF(S1AP_PAGING_LOG , MESSAGE_PRIORITY_MED, IttiMsgText
MESSAGE_DEF(S1AP_E_RAB_RELEASE_REQUEST_LOG , MESSAGE_PRIORITY_MED, IttiMsgText , s1ap_e_rab_release_request_log)
MESSAGE_DEF(S1AP_E_RAB_RELEASE_RESPONSE_LOG , MESSAGE_PRIORITY_MED, IttiMsgText , s1ap_e_rab_release_response_log)
MESSAGE_DEF(S1AP_ERROR_INDICATION_LOG , MESSAGE_PRIORITY_MED, IttiMsgText , s1ap_error_indication_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)
......@@ -62,6 +64,8 @@ MESSAGE_DEF(S1AP_E_RAB_SETUP_RESP , MESSAGE_PRIORITY_MED, s1ap_e_rab_se
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_E_RAB_MODIFY_RESP , MESSAGE_PRIORITY_MED, s1ap_e_rab_modify_resp_t , s1ap_e_rab_modify_resp)
MESSAGE_DEF(S1AP_E_RAB_RELEASE_RESPONSE , MESSAGE_PRIORITY_MED, s1ap_e_rab_release_resp_t , s1ap_e_rab_release_resp)
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 )
......
......@@ -42,6 +42,8 @@
#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_E_RAB_MODIFY_RESP(mSGpTR) (mSGpTR)->ittiMsg.s1ap_e_rab_modify_resp
#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
......@@ -269,6 +271,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_modify_s {
/* Unique e_rab_id for the UE. */
uint8_t e_rab_id;
......@@ -472,6 +485,8 @@ typedef struct s1ap_initial_context_setup_req_s {
/* eNB ue s1ap id as initialized by S1AP layer */
unsigned eNB_ue_s1ap_id:24;
uint32_t mme_ue_s1ap_id;
/* UE aggregate maximum bitrate */
ambr_t ue_ambr;
......@@ -525,7 +540,7 @@ typedef struct s1ap_e_rab_setup_req_s {
uint16_t ue_initial_id;
/* MME UE id */
uint16_t mme_ue_s1ap_id;
uint32_t mme_ue_s1ap_id;
/* eNB ue s1ap id as initialized by S1AP layer */
unsigned eNB_ue_s1ap_id:24;
......@@ -552,6 +567,58 @@ 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 */
uint32_t mme_ue_s1ap_id;
s1ap_gummei_t ue_gummei;
uint16_t ue_initial_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 */
uint32_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 {
......@@ -574,7 +641,7 @@ typedef struct s1ap_e_rab_modify_req_s {
uint16_t ue_initial_id;
/* MME UE id */
uint16_t mme_ue_s1ap_id;
uint32_t mme_ue_s1ap_id;
/* eNB ue s1ap id as initialized by S1AP layer */
unsigned eNB_ue_s1ap_id:24;
......@@ -607,7 +674,7 @@ typedef struct e_rab_release_s {
typedef struct s1ap_e_rab_release_command_s {
/* MME UE id */
uint16_t mme_ue_s1ap_id;
uint32_t mme_ue_s1ap_id;
/* eNB ue s1ap id as initialized by S1AP layer */
unsigned eNB_ue_s1ap_id:24;
......@@ -625,7 +692,7 @@ typedef struct s1ap_e_rab_release_command_s {
typedef struct s1ap_e_rab_release_resp_s {
/* MME UE id */
uint16_t mme_ue_s1ap_id;
uint32_t mme_ue_s1ap_id;
/* eNB ue s1ap id as initialized by S1AP layer */
unsigned eNB_ue_s1ap_id:24;
......
......@@ -132,7 +132,7 @@ 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;
int old_eNB_ue_x2ap_id;
PhysCellId_t target_physCellId;
......@@ -158,10 +158,14 @@ typedef struct x2ap_handover_req_s {
/* list of e_rab setup-ed by RRC layers */
e_rab_setup_t e_rabs_tobesetup[S1AP_MAX_E_RAB];
/* ue_context_pP->ue_context.e_rab[i].param.sgw_addr; */
/* list of e_rab to be setup by RRC layers */
e_rab_t e_rab_param[S1AP_MAX_E_RAB];
x2ap_lastvisitedcell_info_t lastvisitedcell_info;
uint8_t rrc_buffer[1024 /* arbitrary, big enough */];
int rrc_buffer_size;
/* TODO: this parameter has to be removed */
int target_mod_id;
} x2ap_handover_req_t;
......@@ -171,6 +175,15 @@ typedef struct x2ap_handover_req_ack_s {
int source_x2id; /* TODO: to be fixed/remove */
/* TODO: this parameter has to be removed */
int target_mod_id;
uint8_t nb_e_rabs_tobesetup;
/* list of e_rab setup-ed by RRC layers */
e_rab_setup_t e_rabs_tobesetup[S1AP_MAX_E_RAB];
/* list of e_rab to be setup by RRC layers */
e_rab_t e_rab_param[S1AP_MAX_E_RAB];
uint8_t rrc_buffer[1024 /* arbitrary, big enough */];
int rrc_buffer_size;
......
......@@ -2294,6 +2294,7 @@ int RCconfig_S1(MessageDef *msg_p, uint32_t i) {
if (strcmp(*(S1ParamList.paramarray[l][ENB_MME_IP_ADDRESS_PREFERENCE_IDX].strptr), "ipv4") == 0) {
S1AP_REGISTER_ENB_REQ (msg_p).mme_ip_address[l].ipv4 = 1;
S1AP_REGISTER_ENB_REQ (msg_p).mme_ip_address[l].ipv6 = 0;
} else if (strcmp(*(S1ParamList.paramarray[l][ENB_MME_IP_ADDRESS_PREFERENCE_IDX].strptr), "ipv6") == 0) {
S1AP_REGISTER_ENB_REQ (msg_p).mme_ip_address[l].ipv6 = 1;
} else if (strcmp(*(S1ParamList.paramarray[l][ENB_MME_IP_ADDRESS_PREFERENCE_IDX].strptr), "no") == 0) {
......
......@@ -896,6 +896,20 @@ rrc_mac_config_req_eNB(module_id_t Mod_idP,
}
} // mib != NULL
if (mobilityControlInfo !=NULL){
if ((UE_id = add_new_ue(Mod_idP, CC_idP,
rntiP, -1
#if (RRC_VERSION >= MAKE_VERSION(14, 0, 0))
,
-1
#endif
)) == -1)
{
LOG_E(MAC, "%s:%d: fatal\n", __FILE__, __LINE__);
abort();
}
}
// SRB2_lchan_config->choice.explicitValue.ul_SpecificParameters->logicalChannelGroup
if (logicalChannelConfig != NULL) { // check for eMTC specific things
UE_id = find_UE_id(Mod_idP, rntiP);
......
......@@ -323,51 +323,75 @@ rx_sdu(const module_id_t enb_mod_idP,
//cancel_ra_proc(enb_mod_idP, CC_idP, frameP,
// current_rnti);
if (old_UE_id != -1) {
/* TODO: if the UE did random access (followed by a MAC uplink with
* CRNTI) because none of its scheduling request was granted, then
* according to 36.321 5.4.4 the UE's MAC will notify RRC to release
* PUCCH/SRS. According to 36.331 5.3.13 the UE will then apply
* default configuration for CQI reporting and scheduling requests,
* which basically means that the CQI requests won't work anymore and
* that the UE won't do any scheduling request anymore as long as the
* eNB doesn't reconfigure the UE.
* We have to take care of this. As the code is, nothing is done and
* the UE state in the eNB is wrong.
*/
for (ii = 0; ii < NB_RA_PROC_MAX; ii++) {
ra = &mac->common_channels[CC_idP].ra[ii];
if ((ra->rnti == current_rnti) && (ra->state != IDLE)) {
mac_rrc_data_ind(enb_mod_idP,
CC_idP,
frameP, subframeP,
old_rnti,
DCCH,
(uint8_t *) payload_ptr,
rx_lengths[i],
0);
// prepare transmission of Msg4(RRCConnectionReconfiguration)
ra->state = MSGCRNTI;
LOG_I(MAC,
"[eNB %d] Frame %d, Subframe %d CC_id %d : (rnti %x UE_id %d) RRCConnectionReconfiguration(Msg4)\n",
enb_mod_idP, frameP, subframeP, CC_idP, old_rnti, old_UE_id);
UE_id = old_UE_id;
current_rnti = old_rnti;
ra->rnti = old_rnti;
ra->crnti_rrc_mui = rrc_eNB_mui-1;
ra->crnti_harq_pid = -1;
//clear timer
UE_list->UE_sched_ctrl[UE_id].uplane_inactivity_timer = 0;
UE_list->UE_sched_ctrl[UE_id].ul_inactivity_timer = 0;
UE_list->UE_sched_ctrl[UE_id].ul_failure_timer = 0;
if (UE_list->UE_sched_ctrl[UE_id].ul_out_of_sync > 0) {
UE_list->UE_sched_ctrl[UE_id].ul_out_of_sync = 0;
mac_eNB_rrc_ul_in_sync(enb_mod_idP, CC_idP, frameP,
subframeP, old_rnti);
if (mac_eNB_get_rrc_status(enb_mod_idP,old_rnti) == RRC_HO_EXECUTION) {
LOG_I(MAC,
"[eNB %d] Frame %d, Subframe %d CC_id %d : (rnti %x UE_id %d) Handover case\n",
enb_mod_idP, frameP, subframeP, CC_idP, old_rnti, old_UE_id);
UE_id = old_UE_id;
current_rnti = old_rnti;
//clear timer
UE_list->UE_sched_ctrl[UE_id].uplane_inactivity_timer = 0;
UE_list->UE_sched_ctrl[UE_id].ul_inactivity_timer = 0;
UE_list->UE_sched_ctrl[UE_id].ul_failure_timer = 0;
if (UE_list->UE_sched_ctrl[UE_id].ul_out_of_sync > 0) {
UE_list->UE_sched_ctrl[UE_id].ul_out_of_sync = 0;
mac_eNB_rrc_ul_in_sync(enb_mod_idP, CC_idP, frameP,
subframeP, old_rnti);
}
UE_list->UE_template[CC_idP][UE_id].ul_SR = 1;
UE_list->UE_sched_ctrl[UE_id].crnti_reconfigurationcomplete_flag = 1;
UE_list->UE_template[UE_PCCID(enb_mod_idP, UE_id)][UE_id].configured = 1;
cancel_ra_proc(enb_mod_idP, CC_idP, frameP,current_rnti);
}
else {
/* TODO: if the UE did random access (followed by a MAC uplink with
* CRNTI) because none of its scheduling request was granted, then
* according to 36.321 5.4.4 the UE's MAC will notify RRC to release
* PUCCH/SRS. According to 36.331 5.3.13 the UE will then apply
* default configuration for CQI reporting and scheduling requests,
* which basically means that the CQI requests won't work anymore and
* that the UE won't do any scheduling request anymore as long as the
* eNB doesn't reconfigure the UE.
* We have to take care of this. As the code is, nothing is done and
* the UE state in the eNB is wrong.
*/
for (ii = 0; ii < NB_RA_PROC_MAX; ii++) {
ra = &mac->common_channels[CC_idP].ra[ii];
if ((ra->rnti == current_rnti) && (ra->state != IDLE)) {
mac_rrc_data_ind(enb_mod_idP,
CC_idP,
frameP, subframeP,
old_rnti,
DCCH,
(uint8_t *) payload_ptr,
rx_lengths[i],
0);
// prepare transmission of Msg4(RRCConnectionReconfiguration)
ra->state = MSGCRNTI;
LOG_I(MAC,
"[eNB %d] Frame %d, Subframe %d CC_id %d : (rnti %x UE_id %d) RRCConnectionReconfiguration(Msg4)\n",
enb_mod_idP, frameP, subframeP, CC_idP, old_rnti, old_UE_id);
UE_id = old_UE_id;
current_rnti = old_rnti;
ra->rnti = old_rnti;
ra->crnti_rrc_mui = rrc_eNB_mui-1;
ra->crnti_harq_pid = -1;
//clear timer
UE_list->UE_sched_ctrl[UE_id].uplane_inactivity_timer = 0;
UE_list->UE_sched_ctrl[UE_id].ul_inactivity_timer = 0;
UE_list->UE_sched_ctrl[UE_id].ul_failure_timer = 0;
if (UE_list->UE_sched_ctrl[UE_id].ul_out_of_sync > 0) {
UE_list->UE_sched_ctrl[UE_id].ul_out_of_sync = 0;
mac_eNB_rrc_ul_in_sync(enb_mod_idP, CC_idP, frameP,
subframeP, old_rnti);
}
UE_list->UE_template[CC_idP][UE_id].ul_SR = 1;
UE_list->UE_sched_ctrl[UE_id].crnti_reconfigurationcomplete_flag = 1;
break;
}
UE_list->UE_template[CC_idP][UE_id].ul_SR = 1;
UE_list->UE_sched_ctrl[UE_id].crnti_reconfigurationcomplete_flag = 1;
break;
}
}
} else {
......
......@@ -52,6 +52,8 @@
#include "RRCConnectionSetup.h"
#include "SRB-ToAddModList.h"
#include "DRB-ToAddModList.h"
#include "HandoverPreparationInformation.h"
#include "HandoverCommand.h"
#if (RRC_VERSION >= MAKE_VERSION(10, 0, 0))
#include "MCCH-Message.h"
//#define MRB1 1
......@@ -2386,6 +2388,7 @@ do_RRCConnectionReconfiguration(
MAC_MainConfig_t *mac_MainConfig,
MeasGapConfig_t *measGapConfig,
MobilityControlInfo_t *mobilityInfo,
SecurityConfigHO_t *securityConfigHO,
struct MeasConfig__speedStatePars *speedStatePars,
RSRP_Range_t *rsrp,
C_RNTI_t *cba_rnti,
......@@ -2485,8 +2488,16 @@ do_RRCConnectionReconfiguration(
rrcConnectionReconfiguration->criticalExtensions.choice.c1.choice.rrcConnectionReconfiguration_r8.mobilityControlInfo = NULL;
}
if (securityConfigHO != NULL) {
rrcConnectionReconfiguration->criticalExtensions.choice.c1.choice.rrcConnectionReconfiguration_r8.securityConfigHO = CALLOC(1,
sizeof(*rrcConnectionReconfiguration->criticalExtensions.choice.c1.choice.rrcConnectionReconfiguration_r8.securityConfigHO));
memcpy((void*)rrcConnectionReconfiguration->criticalExtensions.choice.c1.choice.rrcConnectionReconfiguration_r8.securityConfigHO, (void*)securityConfigHO,
sizeof(SecurityConfigHO_t));
} else {
rrcConnectionReconfiguration->criticalExtensions.choice.c1.choice.rrcConnectionReconfiguration_r8.securityConfigHO = NULL;
}
rrcConnectionReconfiguration->criticalExtensions.choice.c1.choice.rrcConnectionReconfiguration_r8.dedicatedInfoNASList = dedicatedInfoNASList;
rrcConnectionReconfiguration->criticalExtensions.choice.c1.choice.rrcConnectionReconfiguration_r8.securityConfigHO = NULL;
//TTN for D2D
//allocate dedicated resource pools for SL communication (sl_CommConfig_r12)
......@@ -2545,7 +2556,7 @@ do_RRCConnectionReconfiguration(
#if defined(ENABLE_ITTI)
# if !defined(DISABLE_XER_SPRINT)
{
char message_string[30000];
char message_string[40000];
size_t message_string_size;
if ((message_string_size = xer_sprint(message_string, sizeof(message_string), &asn_DEF_DL_DCCH_Message, (void *) &dl_dcch_msg)) > 0) {
......@@ -3368,6 +3379,88 @@ uint8_t do_ULInformationTransfer(uint8_t **buffer, uint32_t pdu_length, uint8_t
return encoded;
}
int do_HandoverPreparation(char *ho_buf, int ho_size, UE_EUTRA_Capability_t *ue_eutra_cap, int rrc_size)
{
asn_enc_rval_t enc_rval;
HandoverPreparationInformation_t ho;
HandoverPreparationInformation_r8_IEs_t *ho_info;
UE_CapabilityRAT_Container_t *ue_cap_rat_container;
char rrc_buf[rrc_size];
memset(rrc_buf, 0, rrc_size);
enc_rval = uper_encode_to_buffer(&asn_DEF_UE_EUTRA_Capability,
NULL,
ue_eutra_cap,
rrc_buf,
rrc_size);
/* TODO: free the OCTET_STRING */
AssertFatal (enc_rval.encoded > 0, "ASN1 message encoding failed (%s, %lu)!\n",
enc_rval.failed_type->name, enc_rval.encoded);
memset(&ho, 0, sizeof(ho));
ho.criticalExtensions.present = HandoverPreparationInformation__criticalExtensions_PR_c1;
ho.criticalExtensions.choice.c1.present = HandoverPreparationInformation__criticalExtensions__c1_PR_handoverPreparationInformation_r8;
ho_info = &ho.criticalExtensions.choice.c1.choice.handoverPreparationInformation_r8;
{
ue_cap_rat_container = (UE_CapabilityRAT_Container_t *)calloc(1,sizeof(UE_CapabilityRAT_Container_t));
ue_cap_rat_container->rat_Type = RAT_Type_eutra;
AssertFatal (OCTET_STRING_fromBuf(
&ue_cap_rat_container->ueCapabilityRAT_Container,
rrc_buf, rrc_size) != -1, "fatal: OCTET_STRING_fromBuf failed\n");
ASN_SEQUENCE_ADD(&ho_info->ue_RadioAccessCapabilityInfo.list, ue_cap_rat_container);
}
enc_rval = uper_encode_to_buffer(&asn_DEF_HandoverPreparationInformation,
NULL,
&ho,
ho_buf,
ho_size);
/* TODO: free the OCTET_STRING */
AssertFatal (enc_rval.encoded > 0, "ASN1 message encoding failed (%s, %lu)!\n",
enc_rval.failed_type->name, enc_rval.encoded);
return((enc_rval.encoded+7)/8);
}
int do_HandoverCommand(char *ho_buf, int ho_size, char *rrc_buf, int rrc_size)
{
asn_enc_rval_t enc_rval;
HandoverCommand_t ho;
memset(&ho, 0, sizeof(ho));
ho.criticalExtensions.present = HandoverCommand__criticalExtensions_PR_c1;
ho.criticalExtensions.choice.c1.present = HandoverCommand__criticalExtensions__c1_PR_handoverCommand_r8;
AssertFatal (OCTET_STRING_fromBuf(
&ho.criticalExtensions.choice.c1.choice.handoverCommand_r8.handoverCommandMessage,
rrc_buf, rrc_size) != -1, "fatal: OCTET_STRING_fromBuf failed\n");
enc_rval = uper_encode_to_buffer(&asn_DEF_HandoverCommand,
NULL,
&ho,
ho_buf,
ho_size);
/* TODO: free the OCTET_STRING */
AssertFatal (enc_rval.encoded > 0, "ASN1 message encoding failed (%s, %lu)!\n",
enc_rval.failed_type->name, enc_rval.encoded);
return((enc_rval.encoded+7)/8);
}
OAI_UECapability_t *fill_ue_capability(char *UE_EUTRA_Capability_xer_fname)
{
static OAI_UECapability_t UECapability; /* TODO declared static to allow returning this has an address should be allocated in a cleaner way. */
......
......@@ -192,6 +192,7 @@ do_RRCConnectionReconfiguration(
MAC_MainConfig_t *mac_MainConfig,
MeasGapConfig_t *measGapConfig,
MobilityControlInfo_t *mobilityInfo,
SecurityConfigHO_t *securityConfigHO,
struct MeasConfig__speedStatePars *speedStatePars,
RSRP_Range_t *rsrp,
C_RNTI_t *cba_rnti,
......@@ -282,6 +283,10 @@ uint8_t do_Paging(uint8_t Mod_id, uint8_t *buffer, ue_paging_identity_t ue_pagin
uint8_t do_ULInformationTransfer(uint8_t **buffer, uint32_t pdu_length, uint8_t *pdu_buffer);
int do_HandoverPreparation(char *ho_buf, int ho_size, UE_EUTRA_Capability_t *ue_eutra_cap, int rrc_size);
int do_HandoverCommand(char *ho_buf, int ho_size, char *rrc_buf, int rrc_size);
OAI_UECapability_t *fill_ue_capability(char *UE_EUTRA_Capability_xer);
uint8_t
......
......@@ -344,10 +344,13 @@ typedef enum UE_STATE_e {
typedef enum HO_STATE_e {
HO_IDLE=0,
HO_MEASURMENT,
HO_MEASUREMENT,
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;
typedef enum SL_TRIGGER_e {
......@@ -433,6 +436,7 @@ 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_TORELEASE // to release DRB between eNB and UE
} e_rab_status_t;
......@@ -446,14 +450,13 @@ typedef struct e_rab_param_s {
} __attribute__ ((__packed__)) e_rab_param_t;
#endif
/* Intermediate structure for Handover management. Associated per-UE in eNB_RRC_INST */
typedef struct HANDOVER_INFO_s {
uint8_t ho_prepare;
uint8_t ho_complete;
uint8_t modid_s; //module_idP of serving cell
uint8_t modid_t; //module_idP of target cell
HO_STATE_t state; //current state of handover
uint32_t modid_s; //module_idP of serving cell
uint32_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
AS_Config_t as_config; /* these two parameters are taken from 36.331 section 10.2.2: HandoverPreparationInformation-r8-IEs */
......@@ -511,6 +514,14 @@ typedef struct HANDOVER_INFO_UE_s {
uint8_t measFlag;
} HANDOVER_INFO_UE;
typedef struct rrc_gummei_s {
uint16_t mcc;
uint16_t mnc;
uint8_t mnc_len;
uint8_t mme_code;
uint16_t mme_group_id;
} rrc_gummei_t;
typedef struct eNB_RRC_UE_s {
uint8_t primaryCC_id;
#if (RRC_VERSION >= MAKE_VERSION(10, 0, 0))
......@@ -537,8 +548,10 @@ typedef struct eNB_RRC_UE_s {
MeasConfig_t* measConfig;
HANDOVER_INFO* handover_info;
MeasResults_t* measResults;
MobilityControlInfo_t* mobilityInfo;
UE_EUTRA_Capability_t* UE_Capability;
int UE_Capability_size;
ImsiMobileIdentity_t imsi;
#if defined(ENABLE_SECURITY)
......@@ -570,8 +583,15 @@ typedef struct eNB_RRC_UE_s {
/* Information from S1AP initial_context_setup_req */
uint32_t eNB_ue_s1ap_id :24;
uint32_t mme_ue_s1ap_id;
rrc_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 */
......@@ -582,8 +602,12 @@ typedef struct eNB_RRC_UE_s {
e_rab_param_t modify_e_rab[NB_RB_MAX];//[S1AP_MAX_E_RAB];
/* 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;
//release e_rabs
uint8_t nb_release_of_e_rabs;
/* list of e_rab to be released by RRC layers */
uint8_t e_rabs_tobereleased[NB_RB_MAX];
e_rab_failed_t e_rabs_release_failed[S1AP_MAX_E_RAB];
// LG: For GTPV1 TUNNELS
uint32_t enb_gtp_teid[S1AP_MAX_E_RAB];
......@@ -639,6 +663,8 @@ typedef struct {
int p_eNB;
uint32_t dl_CarrierFreq;
uint32_t ul_CarrierFreq;
uint32_t eutra_band;
uint32_t N_RB_DL;
uint32_t pbch_repetition;
BCCH_BCH_Message_t mib;
BCCH_DL_SCH_Message_t siblock1;
......
This source diff could not be displayed because it is too large. You can view the blob instead.
This diff is collapsed.
......@@ -269,6 +269,10 @@ int rrc_eNB_process_S1AP_E_RAB_RELEASE_COMMAND(MessageDef *msg_p, const char *ms
*/
int rrc_eNB_send_S1AP_E_RAB_RELEASE_RESPONSE(const protocol_ctxt_t* const ctxt_pP, rrc_eNB_ue_context_t* const ue_context_pP, uint8_t xid );
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_ */
......@@ -309,6 +309,15 @@ flexran_rrc_eNB_generate_defaultRRCConnectionReconfiguration(
const uint8_t ho_state,
agent_reconf_rrc * trig_param
);
void
rrc_eNB_generate_HO_RRCConnectionReconfiguration(const protocol_ctxt_t* const ctxt_pP,
rrc_eNB_ue_context_t* const ue_context_pP,
uint8_t* buffer,
int *_size
//const uint8_t ho_state
);
void
rrc_eNB_configure_rbs_handover(struct rrc_eNB_ue_context_s* ue_context_p, protocol_ctxt_t* const ctxt_pP);
int freq_to_arfcn10(int band, unsigned long freq);
......@@ -345,6 +354,8 @@ void *rrc_enb_task(void *args_p);
void *rrc_ue_task(void *args_p);
#endif
void rrc_eNB_process_handoverPreparationInformation(int mod_id, x2ap_handover_req_t *m);
/**\brief Generate/decode the handover RRCConnectionReconfiguration at eNB
\param module_idP Instance ID for eNB/CH
\param frame Frame index
......@@ -573,9 +584,11 @@ rrc_eNB_process_MeasurementReport(
void
rrc_eNB_generate_HandoverPreparationInformation(
const protocol_ctxt_t* const ctxt_pP,
//const protocol_ctxt_t* const ctxt_pP,
rrc_eNB_ue_context_t* const ue_context_pP,
PhysCellId_t targetPhyId
uint8_t* buffer,
int *_size
//PhysCellId_t targetPhyId
);
void
......
......@@ -19,6 +19,13 @@
* contact@openairinterface.org
*/
/*! \file x2ap_eNB.c
* \brief x2ap tasks for eNB
* \author Konstantinos Alexandris <Konstantinos.Alexandris@eurecom.fr>, Cedric Roux <Cedric.Roux@eurecom.fr>, Navid Nikaein <Navid.Nikaein@eurecom.fr>
* \date 2018
* \version 1.0
*/
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
......@@ -64,6 +71,13 @@ void x2ap_eNB_register_eNB(x2ap_eNB_instance_t *instance_p,
uint32_t enb_port_for_X2C,
int multi_sd);
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_handle_sctp_data_ind(instance_t instance, sctp_data_ind_t *sctp_data_ind) {
......@@ -405,6 +419,62 @@ void x2ap_eNB_handle_sctp_init_msg_multi_cnf(
}
}
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;
int target_enb_id = x2ap_handover_req->target_physCellId;
instance_p = x2ap_eNB_pci_get_instance(target_enb_id);
DevAssert(instance_p != NULL);
//instance_p = x2ap_eNB_get_instance(instance);
//DevAssert(instance_p != NULL);
target = x2ap_is_eNB_id_in_list(instance_p->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(target, x2ap_handover_req);
}
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;
int target_enb_id = x2ap_handover_req_ack->target_mod_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_request_ack(target, x2ap_handover_req_ack);
//x2ap_eNB_generate_x2_handover_req_ack(instance_p, target, x2ap_handover_req_ack->source_x2id,
//x2ap_handover_req_ack->rrc_buffer, x2ap_handover_req_ack->rrc_buffer_size);
}
void *x2ap_task(void *arg)
{
MessageDef *received_msg = NULL;
......@@ -429,6 +499,16 @@ void *x2ap_task(void *arg)
&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_INIT_MSG_MULTI_CNF:
x2ap_eNB_handle_sctp_init_msg_multi_cnf(ITTI_MESSAGE_GET_INSTANCE(received_msg),
&received_msg->ittiMsg.sctp_init_msg_multi_cnf);
......
......@@ -19,6 +19,13 @@
* contact@openairinterface.org
*/
/*! \file x2ap_eNB.h
* \brief x2ap tasks for eNB
* \author Konstantinos Alexandris <Konstantinos.Alexandris@eurecom.fr>, Cedric Roux <Cedric.Roux@eurecom.fr>, Navid Nikaein <Navid.Nikaein@eurecom.fr>
* \date 2018
* \version 1.0
*/
#include <stdio.h>
#include <stdint.h>
......
......@@ -19,6 +19,13 @@
* contact@openairinterface.org
*/
/*! \file x2ap_eNB_decoder.c
* \brief x2ap decoder procedures for eNB
* \author Konstantinos Alexandris <Konstantinos.Alexandris@eurecom.fr>, Cedric Roux <Cedric.Roux@eurecom.fr>, Navid Nikaein <Navid.Nikaein@eurecom.fr>
* \date 2018
* \version 1.0
*/
#include <stdio.h>
#include "assertions.h"
......@@ -33,7 +40,12 @@ static int x2ap_eNB_decode_initiating_message(X2AP_X2AP_PDU_t *pdu)
switch(pdu->choice.initiatingMessage.procedureCode) {
case X2AP_ProcedureCode_id_x2Setup:
asn_encode_to_new_buffer(NULL, ATS_CANONICAL_XER, &asn_DEF_X2AP_X2AP_PDU, pdu);
//asn_encode_to_new_buffer(NULL, ATS_CANONICAL_XER, &asn_DEF_X2AP_X2AP_PDU, pdu);
X2AP_INFO("x2ap_eNB_decode_initiating_message!\n");
break;
case X2AP_ProcedureCode_id_handoverPreparation:
//asn_encode_to_new_buffer(NULL, ATS_CANONICAL_XER, &asn_DEF_X2AP_X2AP_PDU, pdu);
X2AP_INFO("x2ap_eNB_decode_initiating_message!\n");
break;
......@@ -54,7 +66,12 @@ static int x2ap_eNB_decode_successful_outcome(X2AP_X2AP_PDU_t *pdu)
switch(pdu->choice.successfulOutcome.procedureCode) {
case X2AP_ProcedureCode_id_x2Setup:
asn_encode_to_new_buffer(NULL, ATS_CANONICAL_XER, &asn_DEF_X2AP_X2AP_PDU, pdu);
//asn_encode_to_new_buffer(NULL, ATS_CANONICAL_XER, &asn_DEF_X2AP_X2AP_PDU, pdu);
X2AP_INFO("x2ap_eNB_decode_successfuloutcome_message!\n");
break;
case X2AP_ProcedureCode_id_handoverPreparation:
//asn_encode_to_new_buffer(NULL, ATS_CANONICAL_XER, &asn_DEF_X2AP_X2AP_PDU, pdu);
X2AP_INFO("x2ap_eNB_decode_successfuloutcome_message!\n");
break;
......@@ -73,7 +90,7 @@ static int x2ap_eNB_decode_unsuccessful_outcome(X2AP_X2AP_PDU_t *pdu)
switch(pdu->choice.unsuccessfulOutcome.procedureCode) {
case X2AP_ProcedureCode_id_x2Setup:
asn_encode_to_new_buffer(NULL, ATS_CANONICAL_XER, &asn_DEF_X2AP_X2AP_PDU, pdu);
//asn_encode_to_new_buffer(NULL, ATS_CANONICAL_XER, &asn_DEF_X2AP_X2AP_PDU, pdu);
X2AP_INFO("x2ap_eNB_decode_unsuccessfuloutcome_message!\n");
break;
......@@ -99,8 +116,9 @@ int x2ap_eNB_decode_pdu(X2AP_X2AP_PDU_t *pdu, const uint8_t *const buffer, uint3
length,
0,
0);
xer_fprint(stdout, &asn_DEF_X2AP_X2AP_PDU, pdu);
if (asn1_xer_print) {
xer_fprint(stdout, &asn_DEF_X2AP_X2AP_PDU, pdu);
}
if (dec_ret.code != RC_OK) {
X2AP_ERROR("Failed to decode pdu\n");
......
......@@ -19,6 +19,13 @@
* contact@openairinterface.org
*/
/*! \file x2ap_eNB_decoder.h
* \brief x2ap decoder procedures for eNB
* \author Konstantinos Alexandris <Konstantinos.Alexandris@eurecom.fr>, Cedric Roux <Cedric.Roux@eurecom.fr>, Navid Nikaein <Navid.Nikaein@eurecom.fr>
* \date 2018
* \version 1.0
*/
#ifndef X2AP_ENB_DECODER_H_
#define X2AP_ENB_DECODER_H_
......
......@@ -19,6 +19,13 @@
* contact@openairinterface.org
*/
/*! \file x2ap_eNB_defs.h
* \brief x2ap struct definitions for eNB
* \author Konstantinos Alexandris <Konstantinos.Alexandris@eurecom.fr>, Cedric Roux <Cedric.Roux@eurecom.fr>, Navid Nikaein <Navid.Nikaein@eurecom.fr>
* \date 2018
* \version 1.0
*/
#include <stdint.h>
#include "queue.h"
......@@ -156,6 +163,7 @@ typedef struct x2ap_eNB_instance_s {
uint32_t downlink_frequency[MAX_NUM_CCs];
int32_t uplink_frequency_offset[MAX_NUM_CCs];
uint32_t Nid_cell[MAX_NUM_CCs];
uint32_t Nid_target_cell[MAX_NUM_CCs];
int16_t N_RB_DL[MAX_NUM_CCs];
lte_frame_type_t frame_type[MAX_NUM_CCs];
uint32_t fdd_earfcn_DL[MAX_NUM_CCs];
......
......@@ -19,6 +19,13 @@
* contact@openairinterface.org
*/
/*! \file x2ap_eNB_encoder.c
* \brief x2ap encoder procedures for eNB
* \author Konstantinos Alexandris <Konstantinos.Alexandris@eurecom.fr>, Cedric Roux <Cedric.Roux@eurecom.fr>, Navid Nikaein <Navid.Nikaein@eurecom.fr>
* \date 2018
* \version 1.0
*/
#include <stdio.h>
#include <string.h>
#include <stdint.h>
......
......@@ -19,6 +19,13 @@
* contact@openairinterface.org
*/
/*! \file x2ap_eNB_encoder.h
* \brief x2ap encoder procedures for eNB
* \author Konstantinos Alexandris <Konstantinos.Alexandris@eurecom.fr>, Cedric Roux <Cedric.Roux@eurecom.fr>, Navid Nikaein <Navid.Nikaein@eurecom.fr>
* \date 2018
* \version 1.0
*/
#ifndef X2AP_ENB_ENCODER_H_
#define X2AP_ENB_ENCODER_H_
......
This diff is collapsed.
......@@ -19,6 +19,13 @@
* contact@openairinterface.org
*/
/*! \file x2ap_eNB_generate_messages.h
* \brief x2ap procedures for eNB
* \author Konstantinos Alexandris <Konstantinos.Alexandris@eurecom.fr>, Cedric Roux <Cedric.Roux@eurecom.fr>, Navid Nikaein <Navid.Nikaein@eurecom.fr>
* \date 2018
* \version 1.0
*/
#ifndef X2AP_ENB_GENERATE_MESSAGES_H_
#define X2AP_ENB_GENERATE_MESSAGES_H_
......@@ -26,9 +33,9 @@
#include "x2ap_common.h"
int x2ap_eNB_generate_x2_setup_request(x2ap_eNB_instance_t *instance_p,
x2ap_eNB_data_t *x2ap_enb_data_p);
x2ap_eNB_data_t *x2ap_eNB_data_p);
int x2ap_eNB_generate_x2_setup_response(x2ap_eNB_data_t *x2ap_enb_data_p);
int x2ap_eNB_generate_x2_setup_response(x2ap_eNB_data_t *x2ap_eNB_data_p);
int x2ap_eNB_generate_x2_setup_failure(instance_t instance,
uint32_t assoc_id,
......@@ -40,5 +47,12 @@ int x2ap_eNB_set_cause (X2AP_Cause_t * cause_p,
X2AP_Cause_PR cause_type,
long cause_value);
int x2ap_eNB_generate_x2_handover_request (x2ap_eNB_data_t *x2ap_eNB_data_p,
x2ap_handover_req_t *x2ap_handover_req);
int x2ap_eNB_generate_x2_handover_request_ack (x2ap_eNB_data_t *x2ap_eNB_data_p,
x2ap_handover_req_ack_t *x2ap_handover_req_ack);
int x2ap_eNB_generate_x2_ue_context_release (x2ap_eNB_data_t *x2ap_eNB_data_p);
#endif /* X2AP_ENB_GENERATE_MESSAGES_H_ */
This diff is collapsed.
......@@ -19,6 +19,13 @@
* contact@openairinterface.org
*/
/*! \file x2ap_eNB_handler.h
* \brief x2ap handler procedures for eNB
* \author Konstantinos Alexandris <Konstantinos.Alexandris@eurecom.fr>, Cedric Roux <Cedric.Roux@eurecom.fr>, Navid Nikaein <Navid.Nikaein@eurecom.fr>
* \date 2018
* \version 1.0
*/
#ifndef X2AP_ENB_HANDLERS_H_
#define X2AP_ENB_HANDLERS_H_
......
......@@ -19,6 +19,13 @@
* contact@openairinterface.org
*/
/*! \file x2ap_eNB_itti_messaging.c
* \brief x2ap tasks for eNB
* \author Konstantinos Alexandris <Konstantinos.Alexandris@eurecom.fr>, Cedric Roux <Cedric.Roux@eurecom.fr>, Navid Nikaein <Navid.Nikaein@eurecom.fr>
* \date 2018
* \version 1.0
*/
#include "intertask_interface.h"
#include "x2ap_eNB_itti_messaging.h"
......
......@@ -19,6 +19,13 @@
* contact@openairinterface.org
*/
/*! \file x2ap_eNB_itti_messaging.h
* \brief x2ap tasks for eNB
* \author Konstantinos Alexandris <Konstantinos.Alexandris@eurecom.fr>, Cedric Roux <Cedric.Roux@eurecom.fr>, Navid Nikaein <Navid.Nikaein@eurecom.fr>
* \date 2018
* \version 1.0
*/
#ifndef X2AP_ENB_ITTI_MESSAGING_H_
#define X2AP_ENB_ITTI_MESSAGING_H_
......
......@@ -19,6 +19,13 @@
* contact@openairinterface.org
*/
/*! \file x2ap_eNB_management_procedures.c
* \brief x2ap tasks for eNB
* \author Konstantinos Alexandris <Konstantinos.Alexandris@eurecom.fr>, Cedric Roux <Cedric.Roux@eurecom.fr>, Navid Nikaein <Navid.Nikaein@eurecom.fr>
* \date 2018
* \version 1.0
*/
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
......@@ -162,6 +169,22 @@ x2ap_eNB_instance_t *x2ap_eNB_get_instance(instance_t instance)
return NULL;
}
x2ap_eNB_instance_t *x2ap_eNB_pci_get_instance(uint32_t pci)
{
x2ap_eNB_instance_t *temp = NULL;
STAILQ_FOREACH(temp, &x2ap_eNB_internal_data.x2ap_eNB_instances_head,
x2ap_eNB_entries) {
for (int i=0; i<temp->num_cc;i++) {
if (temp->Nid_target_cell[i] == pci) {
/* Matching occurence */
return temp;
}
}
}
return NULL;
}
/// utility functions
......
......@@ -19,6 +19,13 @@
* contact@openairinterface.org
*/
/*! \file x2ap_eNB_management_procedures.h
* \brief x2ap tasks for eNB
* \author Konstantinos Alexandris <Konstantinos.Alexandris@eurecom.fr>, Cedric Roux <Cedric.Roux@eurecom.fr>, Navid Nikaein <Navid.Nikaein@eurecom.fr>
* \date 2018
* \version 1.0
*/
#ifndef X2AP_ENB_MANAGEMENT_PROCEDURES_H_
#define X2AP_ENB_MANAGEMENT_PROCEDURES_H
......@@ -30,6 +37,8 @@ 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);
x2ap_eNB_instance_t *x2ap_eNB_pci_get_instance(uint32_t pci);
uint16_t x2ap_eNB_fetch_add_global_cnx_id(void);
void x2ap_eNB_prepare_internal_data(void);
......
......@@ -150,7 +150,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);
......@@ -911,7 +911,7 @@ int gtpv1u_update_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)
{
......
......@@ -892,6 +892,11 @@ nwGtpv1uProcessUdpReq( NW_IN NwGtpv1uStackHandleT hGtpuStackHandle,
ret = nwGtpv1uProcessGpdu(thiz, udpData, udpDataLen, peerIp);
break;
case NW_GTP_END_MARKER:
GTPU_DEBUG("NW_GTP_END_MARKER\n");
ret = NW_GTPV1U_OK;
break;
default:
ret = NW_GTPV1U_FAILURE;
NW_ASSERT(0);
......
......@@ -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));
......
......@@ -166,6 +166,16 @@ static int s1ap_eNB_decode_successful_outcome(S1AP_S1AP_PDU_t *pdu)
free(res.buffer);
break;
case S1AP_ProcedureCode_id_PathSwitchRequest:
res = asn_encode_to_new_buffer(NULL, ATS_CANONICAL_XER, &asn_DEF_S1AP_S1AP_PDU, pdu);
message_id = S1AP_S1_SETUP_LOG;
message_p = itti_alloc_new_message_sized(TASK_S1AP, message_id, res.result.encoded + sizeof (IttiMsgText));
message_p->ittiMsg.s1ap_s1_setup_log.size = res.result.encoded;
memcpy(&message_p->ittiMsg.s1ap_s1_setup_log.text, res.buffer, res.result.encoded);
itti_send_msg_to_task(TASK_UNKNOWN, INSTANCE_DEFAULT, message_p);
free(res.buffer);
break;
default:
S1AP_ERROR("Unknown procedure ID (%d) for successfull outcome message\n",
(int)pdu->choice.successfulOutcome.procedureCode);
......@@ -192,6 +202,15 @@ static int s1ap_eNB_decode_unsuccessful_outcome(S1AP_S1AP_PDU_t *pdu)
itti_send_msg_to_task(TASK_UNKNOWN, INSTANCE_DEFAULT, message_p);
free(res.buffer);
break;
case S1AP_ProcedureCode_id_PathSwitchRequest:
res = asn_encode_to_new_buffer(NULL, ATS_CANONICAL_XER, &asn_DEF_S1AP_S1AP_PDU, pdu);
message_id = S1AP_S1_SETUP_LOG;
message_p = itti_alloc_new_message_sized(TASK_S1AP, message_id, res.result.encoded + sizeof (IttiMsgText));
message_p->ittiMsg.s1ap_s1_setup_log.size = res.result.encoded;
memcpy(&message_p->ittiMsg.s1ap_s1_setup_log.text, res.buffer, res.result.encoded);
itti_send_msg_to_task(TASK_UNKNOWN, INSTANCE_DEFAULT, message_p);
free(res.buffer);
break;
default:
S1AP_ERROR("Unknown procedure ID (%d) for unsuccessfull outcome message\n",
......
......@@ -147,6 +147,16 @@ int s1ap_eNB_encode_initiating(S1AP_S1AP_PDU_t *pdu,
free(res.buffer);
break;
case S1AP_ProcedureCode_id_PathSwitchRequest:
res = asn_encode_to_new_buffer(NULL, ATS_CANONICAL_XER, &asn_DEF_S1AP_S1AP_PDU, pdu);
message_id = S1AP_UE_CONTEXT_RELEASE_REQ_LOG;
message_p = itti_alloc_new_message_sized(TASK_S1AP, message_id, res.result.encoded + sizeof (IttiMsgText));
message_p->ittiMsg.s1ap_ue_context_release_req_log.size = res.result.encoded;
memcpy(&message_p->ittiMsg.s1ap_ue_context_release_req_log.text, res.buffer, res.result.encoded);
itti_send_msg_to_task(TASK_UNKNOWN, INSTANCE_DEFAULT, message_p);
free(res.buffer);
break;
default:
S1AP_DEBUG("Unknown procedure ID (%d) for initiating message\n",
(int)pdu->choice.initiatingMessage.procedureCode);
......
This diff is collapsed.
This diff is collapsed.
......@@ -49,4 +49,7 @@ int s1ap_eNB_e_rab_modify_resp(instance_t instance,
int s1ap_eNB_e_rab_release_resp(instance_t instance,
s1ap_e_rab_release_resp_t *e_rab_release_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_ */
......@@ -255,3 +255,79 @@ s1ap_eNB_nnsf_select_mme_by_gummei(s1ap_eNB_instance_t *instance_p,
*/
return mme_highest_capacity_p;
}
struct s1ap_eNB_mme_data_s *
s1ap_eNB_nnsf_select_mme_by_gummei_no_cause(s1ap_eNB_instance_t *instance_p,
s1ap_gummei_t gummei)
{
struct s1ap_eNB_mme_data_s *mme_data_p = NULL;
struct s1ap_eNB_mme_data_s *mme_highest_capacity_p = NULL;
uint8_t current_capacity = 0;
RB_FOREACH(mme_data_p, s1ap_mme_map, &instance_p->s1ap_mme_head) {
struct served_gummei_s *gummei_p = NULL;
if (mme_data_p->state != S1AP_ENB_STATE_CONNECTED) {
/* The association between MME and eNB is not ready for the moment,
* go to the next known MME.
*/
if (mme_data_p->state == S1AP_ENB_OVERLOAD) {
/* MME is overloaded. We have to check the RRC establishment
* cause and take decision to the select this MME depending on
* the overload state.
*/
} else {
/* The MME is not overloaded, association is simply not ready. */
continue;
}
}
if (current_capacity < mme_data_p->relative_mme_capacity) {
/* We find a better MME, keep a reference to it */
current_capacity = mme_data_p->relative_mme_capacity;
mme_highest_capacity_p = mme_data_p;
}
/* Looking for MME gummei matching the one provided by NAS */
STAILQ_FOREACH(gummei_p, &mme_data_p->served_gummei, next) {
struct served_group_id_s *group_id_p = NULL;
struct mme_code_s *mme_code_p = NULL;
struct plmn_identity_s *served_plmn_p = NULL;
STAILQ_FOREACH(served_plmn_p, &gummei_p->served_plmns, next) {
if ((served_plmn_p->mcc == gummei.mcc) &&
(served_plmn_p->mnc == gummei.mnc)) {
break;
}
}
STAILQ_FOREACH(mme_code_p, &gummei_p->mme_codes, next) {
if (mme_code_p->mme_code == gummei.mme_code) {
break;
}
}
STAILQ_FOREACH(group_id_p, &gummei_p->served_group_ids, next) {
if (group_id_p->mme_group_id == gummei.mme_group_id) {
break;
}
}
/* The MME matches the parameters provided by the NAS layer ->
* the MME is knwown and the association is ready.
* Return the reference to the MME to use it for this UE.
*/
if ((group_id_p != NULL) &&
(mme_code_p != NULL) &&
(served_plmn_p != NULL)) {
return mme_data_p;
}
}
}
/* At this point no MME matches the provided GUMMEI. Select the one with the
* highest relative capacity.
* In case the list of known MME is empty, simply return NULL, that way the RRC
* layer should know about it and reject RRC connectivity.
*/
return mme_highest_capacity_p;
}
......@@ -36,4 +36,8 @@ s1ap_eNB_nnsf_select_mme_by_gummei(s1ap_eNB_instance_t *instance_p,
rrc_establishment_cause_t cause,
s1ap_gummei_t gummei);
struct s1ap_eNB_mme_data_s*
s1ap_eNB_nnsf_select_mme_by_gummei_no_cause(s1ap_eNB_instance_t *instance_p,
s1ap_gummei_t gummei);
#endif /* S1AP_ENB_NNSF_H_ */
......@@ -131,6 +131,54 @@ do { \
#define M_TMSI_TO_OCTET_STRING INT32_TO_OCTET_STRING
#define MME_GID_TO_OCTET_STRING INT16_TO_OCTET_STRING
#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 OCTET_STRING_TO_INT8(aSN, x) \
do { \
DevCheck((aSN)->size == 1, (aSN)->size, 0, 0); \
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment