forked from acouzens/open5gs
feat: Add N2-Handover
This commit is contained in:
parent
0fc5190a09
commit
49a9e58efe
|
@ -183,6 +183,10 @@ typedef struct ogs_pfcp_far_s {
|
|||
uint32_t num_of_buffered_packet;
|
||||
ogs_pkbuf_t *buffered_packet[OGS_MAX_NUM_OF_PACKET_BUFFER];
|
||||
|
||||
struct {
|
||||
bool prepared;
|
||||
} handover; /* Saved from N2-Handover Request Acknowledge */
|
||||
|
||||
/* Related Context */
|
||||
ogs_pfcp_sess_t *sess;
|
||||
void *gnode;
|
||||
|
|
|
@ -80,7 +80,8 @@ typedef struct ogs_pfcp_xact_s {
|
|||
#define OGS_PFCP_MODIFY_DEACTIVATE ((uint64_t)1<<9)
|
||||
#define OGS_PFCP_MODIFY_END_MARKER ((uint64_t)1<<10)
|
||||
#define OGS_PFCP_MODIFY_ERROR_INDICATION ((uint64_t)1<<11)
|
||||
#define OGS_PFCP_MODIFY_PATH_SWITCH ((uint64_t)1<<12)
|
||||
#define OGS_PFCP_MODIFY_XN_HANDOVER ((uint64_t)1<<12)
|
||||
#define OGS_PFCP_MODIFY_N2_HANDOVER ((uint64_t)1<<13)
|
||||
uint64_t modify_flags;
|
||||
|
||||
#define OGS_PFCP_DELETE_TRIGGER_UE_REQUESTED 1
|
||||
|
|
|
@ -136,7 +136,7 @@ typedef struct ogs_sbi_xact_s {
|
|||
ogs_timer_t *t_response;
|
||||
|
||||
ogs_sbi_stream_t *assoc_stream;
|
||||
uint8_t state;
|
||||
int state;
|
||||
|
||||
ogs_sbi_object_t *sbi_object;
|
||||
} ogs_sbi_xact_t;
|
||||
|
|
|
@ -418,7 +418,7 @@ void amf_state_operational(ogs_fsm_t *s, amf_event_t *e)
|
|||
|
||||
SWITCH(sbi_message.h.resource.component[2])
|
||||
CASE(OGS_SBI_RESOURCE_NAME_MODIFY)
|
||||
amf_nsmf_pdu_session_handle_update_sm_context(
|
||||
amf_nsmf_pdusession_handle_update_sm_context(
|
||||
sess, state, &sbi_message);
|
||||
break;
|
||||
|
||||
|
@ -432,11 +432,11 @@ void amf_state_operational(ogs_fsm_t *s, amf_event_t *e)
|
|||
amf_ue->supi, sbi_message.res_status);
|
||||
}
|
||||
|
||||
amf_nsmf_pdu_session_handle_release_sm_context(sess, state);
|
||||
amf_nsmf_pdusession_handle_release_sm_context(sess, state);
|
||||
break;
|
||||
|
||||
DEFAULT
|
||||
amf_nsmf_pdu_session_handle_create_sm_context(
|
||||
amf_nsmf_pdusession_handle_create_sm_context(
|
||||
sess, &sbi_message);
|
||||
END
|
||||
break;
|
||||
|
|
|
@ -975,6 +975,10 @@ ran_ue_t *ran_ue_add(amf_gnb_t *gnb, uint32_t ran_ue_ngap_id)
|
|||
ran_ue->gnb_ostream_id =
|
||||
OGS_NEXT_ID(gnb->ostream_id, 1, gnb->max_num_of_ostreams-1);
|
||||
|
||||
ran_ue->t_ng_holding = ogs_timer_add(
|
||||
ogs_app()->timer_mgr, amf_timer_ng_holding_timer_expire, ran_ue);
|
||||
ogs_assert(ran_ue->t_ng_holding);
|
||||
|
||||
ran_ue->gnb = gnb;
|
||||
|
||||
ogs_list_add(&gnb->ran_ue_list, ran_ue);
|
||||
|
@ -991,8 +995,8 @@ void ran_ue_remove(ran_ue_t *ran_ue)
|
|||
|
||||
ogs_list_remove(&ran_ue->gnb->ran_ue_list, ran_ue);
|
||||
|
||||
if (ran_ue->t_ng_holding)
|
||||
ogs_timer_delete(ran_ue->t_ng_holding);
|
||||
ogs_assert(ran_ue->t_ng_holding);
|
||||
ogs_timer_delete(ran_ue->t_ng_holding);
|
||||
|
||||
ogs_pool_free(&ran_ue_pool, ran_ue);
|
||||
|
||||
|
@ -1177,7 +1181,7 @@ void amf_ue_remove(amf_ue_t *amf_ue)
|
|||
OGS_ASN_CLEAR_DATA(&amf_ue->ueRadioCapability);
|
||||
|
||||
/* Clear Transparent Container */
|
||||
OGS_ASN_CLEAR_DATA(&amf_ue->container);
|
||||
OGS_ASN_CLEAR_DATA(&amf_ue->handover.container);
|
||||
|
||||
/* Clear Paging Info */
|
||||
AMF_UE_CLEAR_PAGING_INFO(amf_ue);
|
||||
|
@ -1523,17 +1527,10 @@ void amf_sess_remove(amf_sess_t *sess)
|
|||
if (sess->pdu_session_establishment_accept)
|
||||
ogs_pkbuf_free(sess->pdu_session_establishment_accept);
|
||||
|
||||
if (sess->transfer.pdu_session_resource_setup_request)
|
||||
ogs_pkbuf_free(sess->transfer.pdu_session_resource_setup_request);
|
||||
sess->transfer.pdu_session_resource_setup_request = NULL;
|
||||
|
||||
if (sess->transfer.path_switch_request_ack)
|
||||
ogs_pkbuf_free(sess->transfer.path_switch_request_ack);
|
||||
sess->transfer.path_switch_request_ack = NULL;
|
||||
|
||||
if (sess->transfer.pdu_session_resource_release_command)
|
||||
ogs_pkbuf_free(sess->transfer.pdu_session_resource_release_command);
|
||||
sess->transfer.pdu_session_resource_release_command = NULL;
|
||||
AMF_SESS_CLEAR_N2_TRANSFER(sess, pdu_session_resource_setup_request);
|
||||
AMF_SESS_CLEAR_N2_TRANSFER(sess, path_switch_request_ack);
|
||||
AMF_SESS_CLEAR_N2_TRANSFER(sess, handover_request);
|
||||
AMF_SESS_CLEAR_N2_TRANSFER(sess, handover_command);
|
||||
|
||||
if (sess->paging.client)
|
||||
ogs_sbi_client_remove(sess->paging.client);
|
||||
|
|
|
@ -162,7 +162,6 @@ struct ran_ue_s {
|
|||
bool initial_context_setup_request_sent;
|
||||
|
||||
/* Handover Info */
|
||||
NGAP_HandoverType_t handover_type;
|
||||
ran_ue_t *source_ue;
|
||||
ran_ue_t *target_ue;
|
||||
|
||||
|
@ -184,7 +183,7 @@ struct ran_ue_s {
|
|||
#define NGAP_UE_CTX_REL_NG_CONTEXT_REMOVE 1
|
||||
#define NGAP_UE_CTX_REL_NG_REMOVE_AND_UNLINK 2
|
||||
#define NGAP_UE_CTX_REL_UE_CONTEXT_REMOVE 3
|
||||
#define NGAP_UE_CTX_REL_DELETE_INDIRECT_TUNNEL 4
|
||||
#define NGAP_UE_CTX_REL_NG_HANDOVER_COMPLETE 4
|
||||
uint8_t ue_ctx_rel_action;
|
||||
|
||||
/* Related Context */
|
||||
|
@ -387,8 +386,13 @@ struct amf_ue_s {
|
|||
/* UE Radio Capability */
|
||||
OCTET_STRING_t ueRadioCapability;
|
||||
|
||||
/* NGAP Transparent Container */
|
||||
OCTET_STRING_t container;
|
||||
/* Handover Info */
|
||||
struct {
|
||||
NGAP_HandoverType_t type;
|
||||
OCTET_STRING_t container;
|
||||
NGAP_Cause_PR group;
|
||||
long cause;
|
||||
} handover;
|
||||
|
||||
ogs_list_t sess_list;
|
||||
};
|
||||
|
@ -448,7 +452,8 @@ typedef struct amf_sess_s {
|
|||
struct {
|
||||
ogs_pkbuf_t *pdu_session_resource_setup_request;
|
||||
ogs_pkbuf_t *path_switch_request_ack;
|
||||
ogs_pkbuf_t *pdu_session_resource_release_command;
|
||||
ogs_pkbuf_t *handover_request;
|
||||
ogs_pkbuf_t *handover_command;
|
||||
} transfer;
|
||||
#define AMF_SESS_STORE_N2_TRANSFER(__sESS, __n2Type, __n2Buf) \
|
||||
do { \
|
||||
|
@ -463,14 +468,18 @@ typedef struct amf_sess_s {
|
|||
ogs_assert(sess->transfer.__n2Type); \
|
||||
} while(0);
|
||||
|
||||
#define AMF_SESS_CLEAR_N2_TRANSFER(__sESS, __n2Type) \
|
||||
do { \
|
||||
if ((__sESS)->transfer.__n2Type) \
|
||||
ogs_pkbuf_free((__sESS)->transfer.__n2Type); \
|
||||
(__sESS)->transfer.__n2Type = NULL; \
|
||||
} while(0);
|
||||
|
||||
#define AMF_UE_CLEAR_N2_TRANSFER(__aMF, __n2Type) \
|
||||
do { \
|
||||
amf_sess_t *sess = NULL; \
|
||||
ogs_list_for_each(&((__aMF)->sess_list), sess) { \
|
||||
if (sess->transfer.__n2Type) { \
|
||||
ogs_pkbuf_free(sess->transfer.__n2Type); \
|
||||
sess->transfer.__n2Type = NULL; \
|
||||
} \
|
||||
AMF_SESS_CLEAR_N2_TRANSFER(sess, __n2Type) \
|
||||
} \
|
||||
} while(0);
|
||||
|
||||
|
|
|
@ -305,7 +305,8 @@ int gmm_handle_registration_update(amf_ue_t *amf_ue,
|
|||
ogs_list_for_each(&amf_ue->sess_list, sess) {
|
||||
if (psimask & (1 << sess->psi)) {
|
||||
if (SESSION_CONTEXT_IN_SMF(sess))
|
||||
amf_sbi_send_activating_session(sess);
|
||||
amf_sbi_send_activating_session(
|
||||
sess, AMF_UPDATE_SM_CONTEXT_REGISTRATION_REQUEST);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -473,7 +474,8 @@ int gmm_handle_service_update(amf_ue_t *amf_ue,
|
|||
ogs_list_for_each(&amf_ue->sess_list, sess) {
|
||||
if (psimask & (1 << sess->psi)) {
|
||||
if (SESSION_CONTEXT_IN_SMF(sess))
|
||||
amf_sbi_send_activating_session(sess);
|
||||
amf_sbi_send_activating_session(
|
||||
sess, AMF_UPDATE_SM_CONTEXT_SERVICE_REQUEST);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -653,7 +655,7 @@ int gmm_handle_ul_nas_transport(amf_ue_t *amf_ue,
|
|||
ogs_nas_5gs_ul_nas_transport_t *ul_nas_transport)
|
||||
{
|
||||
amf_sess_t *sess = NULL;
|
||||
amf_nsmf_pdu_session_update_sm_context_param_t param;
|
||||
amf_nsmf_pdusession_update_sm_context_param_t param;
|
||||
|
||||
ogs_nas_payload_container_type_t *payload_container_type = NULL;
|
||||
ogs_nas_payload_container_t *payload_container = NULL;
|
||||
|
@ -796,7 +798,7 @@ int gmm_handle_ul_nas_transport(amf_ue_t *amf_ue,
|
|||
|
||||
amf_sess_sbi_discover_and_send(OpenAPI_nf_type_SMF,
|
||||
sess, AMF_SESS_SM_CONTEXT_NO_STATE, NULL,
|
||||
amf_nsmf_pdu_session_build_create_sm_context);
|
||||
amf_nsmf_pdusession_build_create_sm_context);
|
||||
|
||||
} else {
|
||||
|
||||
|
@ -819,7 +821,7 @@ int gmm_handle_ul_nas_transport(amf_ue_t *amf_ue,
|
|||
|
||||
amf_sess_sbi_discover_and_send(OpenAPI_nf_type_SMF,
|
||||
sess, AMF_UPDATE_SM_CONTEXT_N1_RELEASED, ¶m,
|
||||
amf_nsmf_pdu_session_build_update_sm_context);
|
||||
amf_nsmf_pdusession_build_update_sm_context);
|
||||
|
||||
if (gsm_header->message_type ==
|
||||
OGS_NAS_5GS_PDU_SESSION_RELEASE_COMPLETE) {
|
||||
|
|
|
@ -464,7 +464,7 @@ int amf_namf_callback_handle_sm_context_status(
|
|||
sess->resource_status == OpenAPI_resource_status_RELEASED) {
|
||||
|
||||
ogs_debug("[%s:%d] SM context remove", amf_ue->supi, sess->psi);
|
||||
amf_nsmf_pdu_session_handle_release_sm_context(
|
||||
amf_nsmf_pdusession_handle_release_sm_context(
|
||||
sess, AMF_SESS_SM_CONTEXT_NO_STATE);
|
||||
}
|
||||
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -52,31 +52,21 @@ ogs_pkbuf_t *ngap_build_pdu_session_resource_release_command(
|
|||
|
||||
ogs_pkbuf_t *ngap_build_paging(amf_ue_t *amf_ue);
|
||||
|
||||
ogs_pkbuf_t *ngap_build_amf_configuration_transfer(
|
||||
NGAP_SONConfigurationTransfer_t *son_configuration_transfer);
|
||||
ogs_pkbuf_t *ngap_build_downlink_ran_configuration_transfer(
|
||||
NGAP_SONConfigurationTransfer_t *transfer);
|
||||
|
||||
ogs_pkbuf_t *ngap_build_path_switch_ack(amf_ue_t *amf_ue);
|
||||
|
||||
ogs_pkbuf_t *ngap_build_handover_command(ran_ue_t *source_ue);
|
||||
ogs_pkbuf_t *ngap_build_handover_request(ran_ue_t *target_ue);
|
||||
ogs_pkbuf_t *ngap_build_handover_preparation_failure(
|
||||
ran_ue_t *source_ue, NGAP_Cause_t *cause);
|
||||
|
||||
ogs_pkbuf_t *ngap_build_handover_request(
|
||||
amf_ue_t *amf_ue, ran_ue_t *target_ue,
|
||||
NGAP_RAN_UE_NGAP_ID_t *ran_ue_ngap_id,
|
||||
NGAP_AMF_UE_NGAP_ID_t *amf_ue_ngap_id,
|
||||
NGAP_HandoverType_t *handovertype,
|
||||
NGAP_Cause_t *cause,
|
||||
NGAP_SourceToTarget_TransparentContainer_t
|
||||
*source_totarget_transparentContainer);
|
||||
ogs_pkbuf_t *ngap_build_handover_command(ran_ue_t *source_ue);
|
||||
ogs_pkbuf_t *ngap_build_handover_cancel_ack(ran_ue_t *source_ue);
|
||||
|
||||
ogs_pkbuf_t *ngap_build_handover_cancel_ack(
|
||||
ran_ue_t *source_ue);
|
||||
|
||||
ogs_pkbuf_t *ngap_build_amf_status_transfer(
|
||||
ogs_pkbuf_t *ngap_build_uplink_ran_status_transfer(
|
||||
ran_ue_t *target_ue,
|
||||
NGAP_RANStatusTransfer_TransparentContainer_t
|
||||
*gnb_statustransfer_transparentContainer);
|
||||
NGAP_RANStatusTransfer_TransparentContainer_t *transfer);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -57,6 +57,9 @@ void ngap_handle_ue_context_release_complete(
|
|||
amf_gnb_t *gnb, ogs_ngap_message_t *message);
|
||||
void ngap_handle_ue_context_release_action(ran_ue_t *ran_ue);
|
||||
|
||||
void ngap_handle_uplink_ran_configuration_transfer(
|
||||
amf_gnb_t *gnb, ogs_ngap_message_t *message, ogs_pkbuf_t *pkbuf);
|
||||
|
||||
void ngap_handle_path_switch_request(
|
||||
amf_gnb_t *gnb, ogs_ngap_message_t *message);
|
||||
|
||||
|
@ -68,11 +71,8 @@ void ngap_handle_handover_failure(
|
|||
amf_gnb_t *gnb, ogs_ngap_message_t *message);
|
||||
void ngap_handle_handover_cancel(
|
||||
amf_gnb_t *gnb, ogs_ngap_message_t *message);
|
||||
|
||||
void ngap_handle_gnb_status_transfer(
|
||||
void ngap_handle_uplink_ran_status_transfer(
|
||||
amf_gnb_t *gnb, ogs_ngap_message_t *message);
|
||||
void ngap_handle_gnb_configuration_transfer(
|
||||
amf_gnb_t *gnb, ogs_ngap_message_t *message, ogs_pkbuf_t *pkbuf);
|
||||
void ngap_handle_handover_notification(
|
||||
amf_gnb_t *gnb, ogs_ngap_message_t *message);
|
||||
|
||||
|
|
|
@ -269,7 +269,7 @@ void ngap_send_ue_context_modification_request(amf_ue_t *amf_ue)
|
|||
|
||||
void ngap_send_ran_ue_context_release_command(
|
||||
ran_ue_t *ran_ue, NGAP_Cause_PR group, long cause,
|
||||
uint8_t action, uint32_t delay)
|
||||
uint8_t action, ogs_time_t duration)
|
||||
{
|
||||
int rv;
|
||||
ogs_pkbuf_t *ngapbuf = NULL;
|
||||
|
@ -283,41 +283,34 @@ void ngap_send_ran_ue_context_release_command(
|
|||
ogs_assert(action != NGAP_UE_CTX_REL_INVALID_ACTION);
|
||||
ran_ue->ue_ctx_rel_action = action;
|
||||
|
||||
ogs_debug(" Group[%d] Cause[%d] Action[%d] Delay[%d]",
|
||||
group, (int)cause, action, delay);
|
||||
ogs_debug(" Group[%d] Cause[%d] Action[%d] Duration[%d]",
|
||||
group, (int)cause, action, (int)duration);
|
||||
|
||||
ngapbuf = ngap_build_ue_context_release_command(ran_ue, group, cause);
|
||||
ogs_expect_or_return(ngapbuf);
|
||||
|
||||
rv = ngap_delayed_send_to_ran_ue(ran_ue, ngapbuf, delay);
|
||||
rv = ngap_delayed_send_to_ran_ue(ran_ue, ngapbuf, duration);
|
||||
ogs_expect(rv == OGS_OK);
|
||||
|
||||
if (ran_ue->t_ng_holding)
|
||||
ogs_timer_delete(ran_ue->t_ng_holding);
|
||||
|
||||
ran_ue->t_ng_holding = ogs_timer_add(
|
||||
ogs_app()->timer_mgr, amf_timer_ng_holding_timer_expire, ran_ue);
|
||||
ogs_assert(ran_ue->t_ng_holding);
|
||||
|
||||
ogs_timer_start(ran_ue->t_ng_holding,
|
||||
amf_timer_cfg(AMF_TIMER_NG_HOLDING)->duration);
|
||||
}
|
||||
|
||||
void ngap_send_amf_ue_context_release_command(
|
||||
amf_ue_t *amf_ue, NGAP_Cause_PR group, long cause,
|
||||
uint8_t action, uint32_t delay)
|
||||
uint8_t action, ogs_time_t duration)
|
||||
{
|
||||
ogs_assert(amf_ue);
|
||||
|
||||
ran_ue_t *ran_ue = ran_ue_cycle(amf_ue->ran_ue);
|
||||
if (ran_ue) {
|
||||
ngap_send_ran_ue_context_release_command(ran_ue,
|
||||
group, cause, action, delay);
|
||||
group, cause, action, duration);
|
||||
ogs_debug(" SUPI[%s]", amf_ue->supi);
|
||||
} else {
|
||||
ogs_error("[%s] No NG Context - "
|
||||
"Group[%d] Cause[%d] Action[%d] Delay[%d]",
|
||||
amf_ue->supi, group, (int)cause, action, delay);
|
||||
"Group[%d] Cause[%d] Action[%d] Duration[%d]",
|
||||
amf_ue->supi, group, (int)cause, action, (int)duration);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -392,26 +385,22 @@ void ngap_send_pdu_resource_setup_request(
|
|||
}
|
||||
}
|
||||
|
||||
#if 0
|
||||
void ngap_send_amf_configuration_transfer(
|
||||
amf_gnb_t *target_gnb,
|
||||
NGAP_SONConfigurationTransfer_t *SONConfigurationTransfer)
|
||||
void ngap_send_downlink_ran_configuration_transfer(
|
||||
amf_gnb_t *target_gnb, NGAP_SONConfigurationTransfer_t *transfer)
|
||||
{
|
||||
int rv;
|
||||
ogs_pkbuf_t *ngapbuf = NULL;
|
||||
|
||||
ogs_assert(target_gnb);
|
||||
ogs_assert(SONConfigurationTransfer);
|
||||
ogs_assert(transfer);
|
||||
|
||||
ngapbuf = ngap_build_amf_configuration_transfer(SONConfigurationTransfer);
|
||||
ngapbuf = ngap_build_downlink_ran_configuration_transfer(transfer);
|
||||
ogs_expect_or_return(ngapbuf);
|
||||
|
||||
rv = ngap_send_to_gnb(target_gnb, ngapbuf, NGAP_NON_UE_SIGNALLING);
|
||||
ogs_expect(rv == OGS_OK);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
void ngap_send_path_switch_ack(amf_sess_t *sess)
|
||||
{
|
||||
int rv;
|
||||
|
@ -430,18 +419,23 @@ void ngap_send_path_switch_ack(amf_sess_t *sess)
|
|||
ogs_expect(rv == OGS_OK);
|
||||
}
|
||||
|
||||
#if 0
|
||||
void ngap_send_handover_command(ran_ue_t *source_ue)
|
||||
void ngap_send_handover_request(amf_ue_t *amf_ue)
|
||||
{
|
||||
int rv;
|
||||
|
||||
ran_ue_t *source_ue = NULL, *target_ue = NULL;
|
||||
ogs_pkbuf_t *ngapbuf = NULL;
|
||||
|
||||
ogs_assert(amf_ue);
|
||||
source_ue = amf_ue->ran_ue;
|
||||
ogs_assert(source_ue);
|
||||
target_ue = source_ue->target_ue;
|
||||
ogs_assert(target_ue);
|
||||
|
||||
ngapbuf = ngap_build_handover_command(source_ue);
|
||||
ngapbuf = ngap_build_handover_request(target_ue);
|
||||
ogs_expect_or_return(ngapbuf);
|
||||
|
||||
rv = ngap_send_to_ran_ue(source_ue, ngapbuf);
|
||||
rv = ngap_send_to_ran_ue(target_ue, ngapbuf);
|
||||
ogs_expect(rv == OGS_OK);
|
||||
}
|
||||
|
||||
|
@ -461,6 +455,24 @@ void ngap_send_handover_preparation_failure(
|
|||
ogs_expect(rv == OGS_OK);
|
||||
}
|
||||
|
||||
void ngap_send_handover_command(amf_ue_t *amf_ue)
|
||||
{
|
||||
int rv;
|
||||
|
||||
ran_ue_t *source_ue = NULL;
|
||||
ogs_pkbuf_t *ngapbuf = NULL;
|
||||
|
||||
ogs_assert(amf_ue);
|
||||
source_ue = amf_ue->ran_ue;
|
||||
ogs_assert(source_ue);
|
||||
|
||||
ngapbuf = ngap_build_handover_command(source_ue);
|
||||
ogs_expect_or_return(ngapbuf);
|
||||
|
||||
rv = ngap_send_to_ran_ue(source_ue, ngapbuf);
|
||||
ogs_expect(rv == OGS_OK);
|
||||
}
|
||||
|
||||
void ngap_send_handover_cancel_ack(ran_ue_t *source_ue)
|
||||
{
|
||||
int rv;
|
||||
|
@ -475,69 +487,22 @@ void ngap_send_handover_cancel_ack(ran_ue_t *source_ue)
|
|||
ogs_expect(rv == OGS_OK);
|
||||
}
|
||||
|
||||
|
||||
void ngap_send_handover_request(
|
||||
amf_ue_t *amf_ue,
|
||||
amf_gnb_t *target_gnb,
|
||||
NGAP_RAN_UE_NGAP_ID_t *ran_ue_ngap_id,
|
||||
NGAP_AMF_UE_NGAP_ID_t *amf_ue_ngap_id,
|
||||
NGAP_HandoverType_t *handovertype,
|
||||
NGAP_Cause_t *cause,
|
||||
NGAP_Source_ToTarget_TransparentContainer_t
|
||||
*source_totarget_transparentContainer)
|
||||
{
|
||||
int rv;
|
||||
ogs_pkbuf_t *ngapbuf = NULL;
|
||||
|
||||
ran_ue_t *source_ue = NULL, *target_ue = NULL;
|
||||
|
||||
ogs_debug("[AMF] Handover request");
|
||||
|
||||
ogs_assert(target_gnb);
|
||||
|
||||
ogs_assert(amf_ue);
|
||||
source_ue = ran_ue_cycle(amf_ue->ran_ue);
|
||||
ogs_assert(source_ue);
|
||||
ogs_assert(source_ue->target_ue == NULL);
|
||||
|
||||
target_ue = ran_ue_add(target_gnb, INVALID_UE_NGAP_ID);
|
||||
ogs_assert(target_ue);
|
||||
|
||||
ogs_debug(" Source : RAN_UE_NGAP_ID[%d] AMF_UE_NGAP_ID[%d]",
|
||||
source_ue->ran_ue_ngap_id, source_ue->amf_ue_ngap_id);
|
||||
ogs_debug(" Target : RAN_UE_NGAP_ID[Unknown] AMF_UE_NGAP_ID[%d]",
|
||||
target_ue->amf_ue_ngap_id);
|
||||
|
||||
source_ue_associate_target_ue(source_ue, target_ue);
|
||||
|
||||
ngapbuf = ngap_build_handover_request(amf_ue, target_ue,
|
||||
ran_ue_ngap_id, amf_ue_ngap_id,
|
||||
handovertype, cause,
|
||||
source_totarget_transparentContainer);
|
||||
ogs_expect_or_return(ngapbuf);
|
||||
|
||||
rv = ngap_send_to_ran_ue(target_ue, ngapbuf);
|
||||
ogs_expect(rv == OGS_OK);
|
||||
}
|
||||
|
||||
void ngap_send_amf_status_transfer(
|
||||
void ngap_send_downlink_ran_status_transfer(
|
||||
ran_ue_t *target_ue,
|
||||
NGAP_RAN_StatusTransfer_TransparentContainer_t
|
||||
*gnb_statustransfer_transparentContainer)
|
||||
NGAP_RANStatusTransfer_TransparentContainer_t *transfer)
|
||||
{
|
||||
int rv;
|
||||
ogs_pkbuf_t *ngapbuf = NULL;
|
||||
|
||||
ogs_assert(target_ue);
|
||||
ogs_assert(transfer);
|
||||
|
||||
ngapbuf = ngap_build_amf_status_transfer(target_ue,
|
||||
gnb_statustransfer_transparentContainer);
|
||||
ngapbuf = ngap_build_uplink_ran_status_transfer(target_ue, transfer);
|
||||
ogs_expect_or_return(ngapbuf);
|
||||
|
||||
rv = ngap_send_to_ran_ue(target_ue, ngapbuf);
|
||||
ogs_expect(rv == OGS_OK);
|
||||
}
|
||||
#endif
|
||||
|
||||
void ngap_send_error_indication(
|
||||
amf_gnb_t *gnb,
|
||||
|
|
|
@ -55,41 +55,30 @@ void ngap_send_ue_context_modification_request(amf_ue_t *amf_ue);
|
|||
|
||||
void ngap_send_ran_ue_context_release_command(
|
||||
ran_ue_t *ran_ue, NGAP_Cause_PR group, long cause,
|
||||
uint8_t action, uint32_t delay);
|
||||
uint8_t action, ogs_time_t delay);
|
||||
void ngap_send_amf_ue_context_release_command(
|
||||
amf_ue_t *amf_ue, NGAP_Cause_PR group, long cause,
|
||||
uint8_t action, uint32_t delay);
|
||||
uint8_t action, ogs_time_t delay);
|
||||
|
||||
void ngap_send_paging(amf_ue_t *amf_ue);
|
||||
void ngap_send_pdu_resource_setup_request(
|
||||
amf_sess_t *sess, ogs_pkbuf_t *n2smbuf);
|
||||
|
||||
void ngap_send_amf_configuration_transfer(
|
||||
amf_gnb_t *target_gnb,
|
||||
NGAP_SONConfigurationTransfer_t *SONConfigurationTransfer);
|
||||
void ngap_send_downlink_ran_configuration_transfer(
|
||||
amf_gnb_t *target_gnb, NGAP_SONConfigurationTransfer_t *transfer);
|
||||
|
||||
void ngap_send_path_switch_ack(amf_sess_t *sess);
|
||||
|
||||
void ngap_send_handover_command(ran_ue_t *source_ue);
|
||||
void ngap_send_handover_request(amf_ue_t *amf_ue);
|
||||
void ngap_send_handover_preparation_failure(
|
||||
ran_ue_t *source_ue, NGAP_Cause_t *cause);
|
||||
|
||||
void ngap_send_handover_request(
|
||||
amf_ue_t *amf_ue,
|
||||
amf_gnb_t *target_gnb,
|
||||
NGAP_RAN_UE_NGAP_ID_t *ran_ue_ngap_id,
|
||||
NGAP_AMF_UE_NGAP_ID_t *amf_ue_ngap_id,
|
||||
NGAP_HandoverType_t *handovertype,
|
||||
NGAP_Cause_t *cause,
|
||||
NGAP_SourceToTarget_TransparentContainer_t
|
||||
*source_totarget_transparentContainer);
|
||||
|
||||
void ngap_send_handover_command(amf_ue_t *amf_ue);
|
||||
void ngap_send_handover_cancel_ack(ran_ue_t *source_ue);
|
||||
|
||||
void ngap_send_amf_status_transfer(
|
||||
void ngap_send_downlink_ran_status_transfer(
|
||||
ran_ue_t *target_ue,
|
||||
NGAP_RANStatusTransfer_TransparentContainer_t
|
||||
*gnb_statustransfer_transparentContainer);
|
||||
NGAP_RANStatusTransfer_TransparentContainer_t *transfer);
|
||||
|
||||
void ngap_send_error_indication(
|
||||
amf_gnb_t *gnb,
|
||||
uint32_t *ran_ue_ngap_id,
|
||||
|
|
|
@ -40,9 +40,7 @@ void ngap_state_final(ogs_fsm_t *s, amf_event_t *e)
|
|||
void ngap_state_operational(ogs_fsm_t *s, amf_event_t *e)
|
||||
{
|
||||
amf_gnb_t *gnb = NULL;
|
||||
#if 0
|
||||
ogs_pkbuf_t *pkbuf = NULL;
|
||||
#endif
|
||||
|
||||
NGAP_NGAP_PDU_t *pdu = NULL;
|
||||
NGAP_InitiatingMessage_t *initiatingMessage = NULL;
|
||||
|
@ -97,26 +95,24 @@ void ngap_state_operational(ogs_fsm_t *s, amf_event_t *e)
|
|||
case NGAP_ProcedureCode_id_PathSwitchRequest:
|
||||
ngap_handle_path_switch_request(gnb, pdu);
|
||||
break;
|
||||
#if 0
|
||||
case NGAP_ProcedureCode_id_eNBConfigurationTransfer:
|
||||
case NGAP_ProcedureCode_id_UplinkRANConfigurationTransfer:
|
||||
pkbuf = e->pkbuf;
|
||||
ogs_assert(pkbuf);
|
||||
|
||||
ngap_handle_gnb_configuration_transfer(gnb, pdu, pkbuf);
|
||||
ngap_handle_uplink_ran_configuration_transfer(gnb, pdu, pkbuf);
|
||||
break;
|
||||
case NGAP_ProcedureCode_id_HandoverPreparation:
|
||||
ngap_handle_handover_required(gnb, pdu);
|
||||
break;
|
||||
case NGAP_ProcedureCode_id_HandoverCancel:
|
||||
ngap_handle_handover_cancel(gnb, pdu);
|
||||
break;
|
||||
case NGAP_ProcedureCode_id_eNBStatusTransfer:
|
||||
ngap_handle_gnb_status_transfer(gnb, pdu);
|
||||
case NGAP_ProcedureCode_id_UplinkRANStatusTransfer:
|
||||
ngap_handle_uplink_ran_status_transfer(gnb, pdu);
|
||||
break;
|
||||
case NGAP_ProcedureCode_id_HandoverNotification:
|
||||
ngap_handle_handover_notification(gnb, pdu);
|
||||
break;
|
||||
#endif
|
||||
case NGAP_ProcedureCode_id_HandoverCancel:
|
||||
ngap_handle_handover_cancel(gnb, pdu);
|
||||
break;
|
||||
case NGAP_ProcedureCode_id_NGReset:
|
||||
ngap_handle_ng_reset(gnb, pdu);
|
||||
break;
|
||||
|
@ -151,11 +147,9 @@ void ngap_state_operational(ogs_fsm_t *s, amf_event_t *e)
|
|||
case NGAP_ProcedureCode_id_UEContextRelease:
|
||||
ngap_handle_ue_context_release_complete(gnb, pdu);
|
||||
break;
|
||||
#if 0
|
||||
case NGAP_ProcedureCode_id_HandoverResourceAllocation:
|
||||
ngap_handle_handover_request_ack(gnb, pdu);
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
ogs_error("Not implemented(choice:%d, proc:%d)",
|
||||
pdu->present, (int)successfulOutcome->procedureCode);
|
||||
|
@ -174,10 +168,10 @@ void ngap_state_operational(ogs_fsm_t *s, amf_event_t *e)
|
|||
case NGAP_ProcedureCode_id_UEContextModification:
|
||||
ngap_handle_ue_context_modification_failure(gnb, pdu);
|
||||
break;
|
||||
#endif
|
||||
case NGAP_ProcedureCode_id_HandoverResourceAllocation :
|
||||
ngap_handle_handover_failure(gnb, pdu);
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
ogs_error("Not implemented(choice:%d, proc:%d)",
|
||||
pdu->present, (int)unsuccessfulOutcome->procedureCode);
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
|
||||
#include "nsmf-build.h"
|
||||
|
||||
ogs_sbi_request_t *amf_nsmf_pdu_session_build_create_sm_context(
|
||||
ogs_sbi_request_t *amf_nsmf_pdusession_build_create_sm_context(
|
||||
amf_sess_t *sess, void *data)
|
||||
{
|
||||
ogs_sbi_message_t message;
|
||||
|
@ -157,10 +157,10 @@ ogs_sbi_request_t *amf_nsmf_pdu_session_build_create_sm_context(
|
|||
return request;
|
||||
}
|
||||
|
||||
ogs_sbi_request_t *amf_nsmf_pdu_session_build_update_sm_context(
|
||||
ogs_sbi_request_t *amf_nsmf_pdusession_build_update_sm_context(
|
||||
amf_sess_t *sess, void *data)
|
||||
{
|
||||
amf_nsmf_pdu_session_update_sm_context_param_t *param = data;
|
||||
amf_nsmf_pdusession_update_sm_context_param_t *param = data;
|
||||
ogs_sbi_message_t message;
|
||||
ogs_sbi_request_t *request = NULL;
|
||||
|
||||
|
@ -225,16 +225,28 @@ ogs_sbi_request_t *amf_nsmf_pdu_session_build_update_sm_context(
|
|||
if (param->upCnxState) {
|
||||
SmContextUpdateData.up_cnx_state = param->upCnxState;
|
||||
|
||||
if (param->ngApCause.group) {
|
||||
SmContextUpdateData.ng_ap_cause = &ngApCause;
|
||||
memset(&ngApCause, 0, sizeof(ngApCause));
|
||||
ngApCause.group = param->ngApCause.group;
|
||||
ngApCause.value = param->ngApCause.value;
|
||||
message.SmContextUpdateData = &SmContextUpdateData;
|
||||
}
|
||||
|
||||
if (param->hoState) {
|
||||
SmContextUpdateData.ho_state = param->hoState;
|
||||
|
||||
if (param->TargetID) {
|
||||
SmContextUpdateData.target_id =
|
||||
amf_nsmf_pdusession_build_target_id(param->TargetID);
|
||||
ogs_assert(SmContextUpdateData.target_id);
|
||||
}
|
||||
|
||||
message.SmContextUpdateData = &SmContextUpdateData;
|
||||
}
|
||||
|
||||
if (param->ngApCause.group) {
|
||||
SmContextUpdateData.ng_ap_cause = &ngApCause;
|
||||
memset(&ngApCause, 0, sizeof(ngApCause));
|
||||
ngApCause.group = param->ngApCause.group;
|
||||
ngApCause.value = param->ngApCause.value;
|
||||
}
|
||||
|
||||
memset(&ueLocation, 0, sizeof(ueLocation));
|
||||
if (param->ue_location) {
|
||||
ueLocation.nr_location = ogs_sbi_build_nr_location(
|
||||
|
@ -260,11 +272,14 @@ ogs_sbi_request_t *amf_nsmf_pdu_session_build_update_sm_context(
|
|||
}
|
||||
if (SmContextUpdateData.ue_time_zone)
|
||||
ogs_free(SmContextUpdateData.ue_time_zone);
|
||||
if (SmContextUpdateData.target_id)
|
||||
amf_nsmf_pdusession_free_target_id(SmContextUpdateData.target_id);
|
||||
|
||||
|
||||
return request;
|
||||
}
|
||||
|
||||
ogs_sbi_request_t *amf_nsmf_pdu_session_build_release_sm_context(
|
||||
ogs_sbi_request_t *amf_nsmf_pdusession_build_release_sm_context(
|
||||
amf_sess_t *sess, void *data)
|
||||
{
|
||||
ogs_sbi_message_t message;
|
||||
|
@ -361,3 +376,109 @@ ogs_sbi_request_t *amf_nsmf_callback_build_n1_n2_failure_notify(
|
|||
|
||||
return request;
|
||||
}
|
||||
|
||||
OpenAPI_ng_ran_target_id_t *amf_nsmf_pdusession_build_target_id(
|
||||
NGAP_TargetID_t *TargetID)
|
||||
{
|
||||
ogs_plmn_id_t plmn_id;
|
||||
ogs_5gs_tai_t nr_tai;
|
||||
|
||||
NGAP_TargetRANNodeID_t *targetRANNodeID = NULL;
|
||||
NGAP_GlobalRANNodeID_t *globalRANNodeID = NULL;
|
||||
NGAP_GlobalGNB_ID_t *globalGNB_ID = NULL;
|
||||
|
||||
OpenAPI_ng_ran_target_id_t *targetId = NULL;
|
||||
OpenAPI_global_ran_node_id_t *ranNodeId = NULL;
|
||||
OpenAPI_g_nb_id_t *gNbId = NULL;
|
||||
OpenAPI_tai_t *tai = NULL;
|
||||
|
||||
ogs_assert(TargetID);
|
||||
|
||||
if (TargetID->present != NGAP_TargetID_PR_targetRANNodeID) {
|
||||
ogs_error("Not implemented TargetID[%d]", TargetID->present);
|
||||
return NULL;
|
||||
}
|
||||
targetRANNodeID = TargetID->choice.targetRANNodeID;
|
||||
if (!targetRANNodeID) {
|
||||
ogs_error("No targetRANNodeID");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
globalRANNodeID = &targetRANNodeID->globalRANNodeID;
|
||||
if (globalRANNodeID->present != NGAP_GlobalRANNodeID_PR_globalGNB_ID) {
|
||||
ogs_error("Not implemented globalRANNodeID[%d]",
|
||||
globalRANNodeID->present);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
globalGNB_ID = globalRANNodeID->choice.globalGNB_ID;
|
||||
if (!globalGNB_ID) {
|
||||
ogs_error("No globalGNB_ID");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
targetId = ogs_calloc(1, sizeof(*targetId));
|
||||
ogs_assert(targetId);
|
||||
|
||||
targetId->ran_node_id = ranNodeId = ogs_calloc(1, sizeof(*ranNodeId));;
|
||||
ogs_assert(ranNodeId);
|
||||
|
||||
memcpy(&plmn_id, globalGNB_ID->pLMNIdentity.buf, OGS_PLMN_ID_LEN);
|
||||
ranNodeId->plmn_id = ogs_sbi_build_plmn_id(&plmn_id);
|
||||
ogs_assert(ranNodeId->plmn_id);
|
||||
|
||||
ranNodeId->g_nb_id = gNbId = ogs_calloc(1, sizeof(*gNbId));
|
||||
ogs_assert(gNbId);
|
||||
|
||||
gNbId->g_nb_value = ogs_calloc(
|
||||
1, OGS_KEYSTRLEN(globalGNB_ID->gNB_ID.choice.gNB_ID.size));
|
||||
ogs_assert(gNbId->g_nb_value);
|
||||
ogs_hex_to_ascii(
|
||||
globalGNB_ID->gNB_ID.choice.gNB_ID.buf,
|
||||
globalGNB_ID->gNB_ID.choice.gNB_ID.size,
|
||||
gNbId->g_nb_value,
|
||||
OGS_KEYSTRLEN(globalGNB_ID->gNB_ID.choice.gNB_ID.size));
|
||||
gNbId->bit_length = 32 - globalGNB_ID->gNB_ID.choice.gNB_ID.bits_unused;
|
||||
|
||||
targetId->tai = tai = ogs_calloc(1, sizeof(*tai));;
|
||||
ogs_assert(tai);
|
||||
|
||||
ogs_ngap_ASN_to_5gs_tai(&targetRANNodeID->selectedTAI, &nr_tai);
|
||||
tai->plmn_id = ogs_sbi_build_plmn_id(&nr_tai.plmn_id);
|
||||
ogs_assert(tai->plmn_id);
|
||||
tai->tac = ogs_uint24_to_0string(nr_tai.tac);
|
||||
ogs_assert(tai->tac);
|
||||
|
||||
return targetId;
|
||||
}
|
||||
|
||||
void amf_nsmf_pdusession_free_target_id(OpenAPI_ng_ran_target_id_t *targetId)
|
||||
{
|
||||
ogs_assert(targetId);
|
||||
|
||||
if (targetId->ran_node_id) {
|
||||
OpenAPI_global_ran_node_id_t *ranNodeId = targetId->ran_node_id;
|
||||
OpenAPI_tai_t *tai = targetId->tai;
|
||||
|
||||
if (ranNodeId) {
|
||||
if (ranNodeId->plmn_id)
|
||||
OpenAPI_plmn_id_free(ranNodeId->plmn_id);
|
||||
if (ranNodeId->g_nb_id) {
|
||||
OpenAPI_g_nb_id_t *gNbId = ranNodeId->g_nb_id;
|
||||
if (gNbId->g_nb_value)
|
||||
ogs_free(gNbId->g_nb_value);
|
||||
ogs_free(gNbId);
|
||||
}
|
||||
ogs_free(ranNodeId);
|
||||
}
|
||||
|
||||
if (tai) {
|
||||
if (tai->plmn_id)
|
||||
OpenAPI_plmn_id_free(tai->plmn_id);
|
||||
if (tai->tac)
|
||||
ogs_free(tai->tac);
|
||||
ogs_free(tai);
|
||||
}
|
||||
}
|
||||
ogs_free(targetId);
|
||||
}
|
||||
|
|
|
@ -26,7 +26,7 @@
|
|||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct amf_nsmf_pdu_session_update_sm_context_param_s {
|
||||
typedef struct amf_nsmf_pdusession_update_sm_context_param_s {
|
||||
ogs_pkbuf_t *n1smbuf;
|
||||
ogs_pkbuf_t *n2smbuf;
|
||||
OpenAPI_n2_sm_info_type_e n2SmInfoType;
|
||||
|
@ -43,18 +43,27 @@ typedef struct amf_nsmf_pdu_session_update_sm_context_param_s {
|
|||
};
|
||||
uint8_t indications;
|
||||
};
|
||||
} amf_nsmf_pdu_session_update_sm_context_param_t;
|
||||
|
||||
ogs_sbi_request_t *amf_nsmf_pdu_session_build_create_sm_context(
|
||||
OpenAPI_ho_state_e hoState;
|
||||
OpenAPI_ng_ran_target_id_t *targetId;
|
||||
NGAP_TargetID_t *TargetID;
|
||||
} amf_nsmf_pdusession_update_sm_context_param_t;
|
||||
|
||||
ogs_sbi_request_t *amf_nsmf_pdusession_build_create_sm_context(
|
||||
amf_sess_t *sess, void *data);
|
||||
ogs_sbi_request_t *amf_nsmf_pdu_session_build_update_sm_context(
|
||||
ogs_sbi_request_t *amf_nsmf_pdusession_build_update_sm_context(
|
||||
amf_sess_t *sess, void *data);
|
||||
ogs_sbi_request_t *amf_nsmf_pdu_session_build_release_sm_context(
|
||||
ogs_sbi_request_t *amf_nsmf_pdusession_build_release_sm_context(
|
||||
amf_sess_t *sess, void *data);
|
||||
|
||||
ogs_sbi_request_t *amf_nsmf_callback_build_n1_n2_failure_notify(
|
||||
amf_sess_t *sess, OpenAPI_n1_n2_message_transfer_cause_e cause);
|
||||
|
||||
OpenAPI_ng_ran_target_id_t *amf_nsmf_pdusession_build_target_id(
|
||||
NGAP_TargetID_t *TargetID);
|
||||
|
||||
void amf_nsmf_pdusession_free_target_id(OpenAPI_ng_ran_target_id_t *targetId);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -24,7 +24,7 @@
|
|||
|
||||
#include "gmm-build.h"
|
||||
|
||||
int amf_nsmf_pdu_session_handle_create_sm_context(
|
||||
int amf_nsmf_pdusession_handle_create_sm_context(
|
||||
amf_sess_t *sess, ogs_sbi_message_t *recvmsg)
|
||||
{
|
||||
int rv;
|
||||
|
@ -142,7 +142,7 @@ int amf_nsmf_pdu_session_handle_create_sm_context(
|
|||
return OGS_OK;
|
||||
}
|
||||
|
||||
int amf_nsmf_pdu_session_handle_update_sm_context(
|
||||
int amf_nsmf_pdusession_handle_update_sm_context(
|
||||
amf_sess_t *sess, int state, ogs_sbi_message_t *recvmsg)
|
||||
{
|
||||
amf_ue_t *amf_ue = NULL;
|
||||
|
@ -189,44 +189,46 @@ int amf_nsmf_pdu_session_handle_update_sm_context(
|
|||
return OGS_ERROR;
|
||||
}
|
||||
|
||||
/*
|
||||
* To Deliver N2 SM Content to gNB Temporarily,
|
||||
* Store N2 SM Context in Session Context
|
||||
*/
|
||||
AMF_SESS_STORE_N2_TRANSFER(
|
||||
sess, pdu_session_resource_setup_request,
|
||||
ogs_pkbuf_copy(n2smbuf));
|
||||
if (state == AMF_UPDATE_SM_CONTEXT_REGISTRATION_REQUEST) {
|
||||
AMF_SESS_STORE_N2_TRANSFER(
|
||||
sess, pdu_session_resource_setup_request,
|
||||
ogs_pkbuf_copy(n2smbuf));
|
||||
|
||||
switch(amf_ue->nas.message_type) {
|
||||
case OGS_NAS_5GS_REGISTRATION_REQUEST:
|
||||
if (SESSION_SYNC_DONE(amf_ue,
|
||||
AMF_RELEASE_SM_CONTEXT_REGISTRATION_ACCEPT) &&
|
||||
SESSION_SYNC_DONE(amf_ue,
|
||||
AMF_UPDATE_SM_CONTEXT_ACTIVATING)) {
|
||||
AMF_UPDATE_SM_CONTEXT_REGISTRATION_REQUEST)) {
|
||||
nas_5gs_send_registration_accept(amf_ue);
|
||||
|
||||
/* After sending accept message,
|
||||
* N2 tranfer message is freed */
|
||||
AMF_UE_CLEAR_N2_TRANSFER(
|
||||
amf_ue, pdu_session_resource_setup_request);
|
||||
}
|
||||
break;
|
||||
case OGS_NAS_5GS_SERVICE_REQUEST:
|
||||
} else if (state == AMF_UPDATE_SM_CONTEXT_SERVICE_REQUEST) {
|
||||
AMF_SESS_STORE_N2_TRANSFER(
|
||||
sess, pdu_session_resource_setup_request,
|
||||
ogs_pkbuf_copy(n2smbuf));
|
||||
|
||||
if (SESSION_SYNC_DONE(amf_ue,
|
||||
AMF_RELEASE_SM_CONTEXT_SERVICE_ACCEPT) &&
|
||||
SESSION_SYNC_DONE(amf_ue,
|
||||
AMF_UPDATE_SM_CONTEXT_ACTIVATING)) {
|
||||
AMF_UPDATE_SM_CONTEXT_SERVICE_REQUEST)) {
|
||||
nas_5gs_send_service_accept(amf_ue);
|
||||
|
||||
/* After sending accept message,
|
||||
* N2 tranfer message is freed */
|
||||
AMF_UE_CLEAR_N2_TRANSFER(
|
||||
amf_ue, pdu_session_resource_setup_request);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
ogs_error("Unknown message type [%d]",
|
||||
amf_ue->nas.message_type);
|
||||
} else if (state == AMF_UPDATE_SM_CONTEXT_HANDOVER_REQUIRED) {
|
||||
AMF_SESS_STORE_N2_TRANSFER(
|
||||
sess, handover_request, ogs_pkbuf_copy(n2smbuf));
|
||||
|
||||
if (SESSION_SYNC_DONE(amf_ue,
|
||||
AMF_UPDATE_SM_CONTEXT_HANDOVER_REQUIRED)) {
|
||||
ngap_send_handover_request(amf_ue);
|
||||
|
||||
AMF_UE_CLEAR_N2_TRANSFER(amf_ue, handover_request);
|
||||
}
|
||||
} else {
|
||||
ogs_error("Invalid STATE[%d]", state);
|
||||
ogs_assert_if_reached();
|
||||
}
|
||||
break;
|
||||
|
@ -271,10 +273,6 @@ int amf_nsmf_pdu_session_handle_update_sm_context(
|
|||
return OGS_ERROR;
|
||||
}
|
||||
|
||||
/*
|
||||
* To Deliver N2 SM Content to gNB Temporarily,
|
||||
* Store N2 SM Context in Session Context
|
||||
*/
|
||||
AMF_SESS_STORE_N2_TRANSFER(
|
||||
sess, path_switch_request_ack,
|
||||
ogs_pkbuf_copy(n2smbuf));
|
||||
|
@ -282,11 +280,30 @@ int amf_nsmf_pdu_session_handle_update_sm_context(
|
|||
if (SESSION_SYNC_DONE(amf_ue, state)) {
|
||||
ngap_send_path_switch_ack(sess);
|
||||
|
||||
/* After sending ack message, N2 SM context is freed */
|
||||
AMF_UE_CLEAR_N2_TRANSFER(amf_ue, path_switch_request_ack);
|
||||
}
|
||||
break;
|
||||
|
||||
case OpenAPI_n2_sm_info_type_HANDOVER_CMD:
|
||||
if (!n2smbuf) {
|
||||
ogs_error("[%s:%d] No N2 SM Content",
|
||||
amf_ue->supi, sess->psi);
|
||||
ngap_send_error_indication2(amf_ue,
|
||||
NGAP_Cause_PR_protocol,
|
||||
NGAP_CauseProtocol_semantic_error);
|
||||
return OGS_ERROR;
|
||||
}
|
||||
|
||||
AMF_SESS_STORE_N2_TRANSFER(
|
||||
sess, handover_command, ogs_pkbuf_copy(n2smbuf));
|
||||
|
||||
if (SESSION_SYNC_DONE(amf_ue, state)) {
|
||||
ngap_send_handover_command(amf_ue);
|
||||
|
||||
AMF_UE_CLEAR_N2_TRANSFER(amf_ue, handover_command);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
ogs_error("Not implemented [%d]",
|
||||
SmContextUpdatedData->n2_sm_info_type);
|
||||
|
@ -335,7 +352,12 @@ int amf_nsmf_pdu_session_handle_update_sm_context(
|
|||
NGAP_UE_CTX_REL_NG_REMOVE_AND_UNLINK, 0);
|
||||
}
|
||||
|
||||
} else if (state == AMF_UPDATE_SM_CONTEXT_ACTIVATING) {
|
||||
} else if (state == AMF_UPDATE_SM_CONTEXT_REGISTRATION_REQUEST) {
|
||||
|
||||
/* Not reached here */
|
||||
ogs_assert_if_reached();
|
||||
|
||||
} else if (state == AMF_UPDATE_SM_CONTEXT_SERVICE_REQUEST) {
|
||||
|
||||
/* Not reached here */
|
||||
ogs_assert_if_reached();
|
||||
|
@ -363,6 +385,56 @@ int amf_nsmf_pdu_session_handle_update_sm_context(
|
|||
|
||||
sess->n1_released = true;
|
||||
|
||||
} else if (state == AMF_UPDATE_SM_CONTEXT_PATH_SWITCH_REQUEST) {
|
||||
|
||||
/* Not reached here */
|
||||
ogs_assert_if_reached();
|
||||
|
||||
} else if (state == AMF_UPDATE_SM_CONTEXT_HANDOVER_REQUIRED) {
|
||||
|
||||
/* Not reached here */
|
||||
ogs_assert_if_reached();
|
||||
|
||||
} else if (state == AMF_UPDATE_SM_CONTEXT_HANDOVER_REQ_ACK) {
|
||||
|
||||
/* Not reached here */
|
||||
ogs_assert_if_reached();
|
||||
|
||||
} else if (state == AMF_UPDATE_SM_CONTEXT_HANDOVER_CANCEL) {
|
||||
|
||||
if (SESSION_SYNC_DONE(amf_ue, state)) {
|
||||
ran_ue_t *source_ue = NULL, *target_ue = NULL;
|
||||
|
||||
source_ue = amf_ue->ran_ue;
|
||||
ogs_assert(source_ue);
|
||||
target_ue = source_ue->target_ue;
|
||||
ogs_assert(target_ue);
|
||||
|
||||
ngap_send_handover_cancel_ack(source_ue);
|
||||
|
||||
ngap_send_ran_ue_context_release_command(target_ue,
|
||||
NGAP_Cause_PR_radioNetwork,
|
||||
NGAP_CauseRadioNetwork_handover_cancelled,
|
||||
NGAP_UE_CTX_REL_NG_HANDOVER_COMPLETE,
|
||||
ogs_time_from_msec(300));
|
||||
}
|
||||
|
||||
} else if (state == AMF_UPDATE_SM_CONTEXT_HANDOVER_NOTIFY) {
|
||||
if (SESSION_SYNC_DONE(amf_ue, state)) {
|
||||
ran_ue_t *target_ue = NULL, *source_ue = NULL;
|
||||
|
||||
target_ue = amf_ue->ran_ue;
|
||||
ogs_assert(target_ue);
|
||||
source_ue = target_ue->source_ue;
|
||||
ogs_assert(source_ue);
|
||||
|
||||
ngap_send_ran_ue_context_release_command(source_ue,
|
||||
NGAP_Cause_PR_radioNetwork,
|
||||
NGAP_CauseRadioNetwork_successful_handover,
|
||||
NGAP_UE_CTX_REL_NG_HANDOVER_COMPLETE,
|
||||
ogs_time_from_msec(300));
|
||||
}
|
||||
|
||||
} else if (state == AMF_REMOVE_S1_CONTEXT_BY_LO_CONNREFUSED) {
|
||||
if (SESSION_SYNC_DONE(amf_ue, state)) {
|
||||
ran_ue_t *ran_ue = ran_ue_cycle(amf_ue->ran_ue);
|
||||
|
@ -406,20 +478,21 @@ int amf_nsmf_pdu_session_handle_update_sm_context(
|
|||
|
||||
} else {
|
||||
ogs_error("Invalid STATE[%d]", state);
|
||||
ogs_assert_if_reached();
|
||||
}
|
||||
|
||||
/*
|
||||
* If resource-status has already been updated by
|
||||
* notify(/namf-callback/v1/{supi}/sm-context-status/{psi})
|
||||
* Remove 'amf_sess_t' context to call
|
||||
* amf_nsmf_pdu_session_handle_release_sm_context().
|
||||
* amf_nsmf_pdusession_handle_release_sm_context().
|
||||
*/
|
||||
if (sess->n1_released == true &&
|
||||
sess->n2_released == true &&
|
||||
sess->resource_status == OpenAPI_resource_status_RELEASED) {
|
||||
|
||||
ogs_debug("[%s:%d] SM context remove", amf_ue->supi, sess->psi);
|
||||
amf_nsmf_pdu_session_handle_release_sm_context(
|
||||
amf_nsmf_pdusession_handle_release_sm_context(
|
||||
sess, AMF_SESS_SM_CONTEXT_NO_STATE);
|
||||
}
|
||||
}
|
||||
|
@ -499,7 +572,7 @@ int amf_nsmf_pdu_session_handle_update_sm_context(
|
|||
return OGS_OK;
|
||||
}
|
||||
|
||||
int amf_nsmf_pdu_session_handle_release_sm_context(amf_sess_t *sess, int state)
|
||||
int amf_nsmf_pdusession_handle_release_sm_context(amf_sess_t *sess, int state)
|
||||
{
|
||||
amf_ue_t *amf_ue = NULL;
|
||||
|
||||
|
@ -515,9 +588,10 @@ int amf_nsmf_pdu_session_handle_release_sm_context(amf_sess_t *sess, int state)
|
|||
* 2. Release All SM contexts
|
||||
* 3. Registration accept
|
||||
*/
|
||||
if (SESSION_SYNC_DONE(amf_ue,
|
||||
AMF_RELEASE_SM_CONTEXT_REGISTRATION_ACCEPT) &&
|
||||
SESSION_SYNC_DONE(amf_ue, AMF_UPDATE_SM_CONTEXT_ACTIVATING))
|
||||
if (SESSION_SYNC_DONE(
|
||||
amf_ue, AMF_RELEASE_SM_CONTEXT_REGISTRATION_ACCEPT) &&
|
||||
SESSION_SYNC_DONE(
|
||||
amf_ue, AMF_UPDATE_SM_CONTEXT_REGISTRATION_REQUEST))
|
||||
nas_5gs_send_registration_accept(amf_ue);
|
||||
|
||||
} else if (state == AMF_RELEASE_SM_CONTEXT_SERVICE_ACCEPT) {
|
||||
|
@ -527,7 +601,7 @@ int amf_nsmf_pdu_session_handle_release_sm_context(amf_sess_t *sess, int state)
|
|||
* 3. Service accept
|
||||
*/
|
||||
if (SESSION_SYNC_DONE(amf_ue, AMF_RELEASE_SM_CONTEXT_SERVICE_ACCEPT) &&
|
||||
SESSION_SYNC_DONE(amf_ue, AMF_UPDATE_SM_CONTEXT_ACTIVATING))
|
||||
SESSION_SYNC_DONE(amf_ue, AMF_UPDATE_SM_CONTEXT_SERVICE_REQUEST))
|
||||
nas_5gs_send_service_accept(amf_ue);
|
||||
|
||||
} else {
|
||||
|
|
|
@ -26,11 +26,11 @@ extern "C" {
|
|||
|
||||
#include "context.h"
|
||||
|
||||
int amf_nsmf_pdu_session_handle_create_sm_context(
|
||||
int amf_nsmf_pdusession_handle_create_sm_context(
|
||||
amf_sess_t *sess, ogs_sbi_message_t *message);
|
||||
int amf_nsmf_pdu_session_handle_update_sm_context(
|
||||
int amf_nsmf_pdusession_handle_update_sm_context(
|
||||
amf_sess_t *sess, int state, ogs_sbi_message_t *recvmsg);
|
||||
int amf_nsmf_pdu_session_handle_release_sm_context(amf_sess_t *sess, int state);
|
||||
int amf_nsmf_pdusession_handle_release_sm_context(amf_sess_t *sess, int state);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
|
|
@ -167,9 +167,9 @@ void amf_sess_sbi_discover_and_send(OpenAPI_nf_type_e target_nf_type,
|
|||
}
|
||||
}
|
||||
|
||||
void amf_sbi_send_activating_session(amf_sess_t *sess)
|
||||
void amf_sbi_send_activating_session(amf_sess_t *sess, int state)
|
||||
{
|
||||
amf_nsmf_pdu_session_update_sm_context_param_t param;
|
||||
amf_nsmf_pdusession_update_sm_context_param_t param;
|
||||
|
||||
ogs_assert(sess);
|
||||
|
||||
|
@ -177,14 +177,14 @@ void amf_sbi_send_activating_session(amf_sess_t *sess)
|
|||
param.upCnxState = OpenAPI_up_cnx_state_ACTIVATING;
|
||||
|
||||
amf_sess_sbi_discover_and_send(OpenAPI_nf_type_SMF,
|
||||
sess, AMF_UPDATE_SM_CONTEXT_ACTIVATING, ¶m,
|
||||
amf_nsmf_pdu_session_build_update_sm_context);
|
||||
sess, state, ¶m,
|
||||
amf_nsmf_pdusession_build_update_sm_context);
|
||||
}
|
||||
|
||||
void amf_sbi_send_deactivate_session(
|
||||
amf_sess_t *sess, int state, int group, int cause)
|
||||
{
|
||||
amf_nsmf_pdu_session_update_sm_context_param_t param;
|
||||
amf_nsmf_pdusession_update_sm_context_param_t param;
|
||||
|
||||
ogs_assert(sess);
|
||||
|
||||
|
@ -196,7 +196,7 @@ void amf_sbi_send_deactivate_session(
|
|||
param.ue_timezone = true;
|
||||
|
||||
amf_sess_sbi_discover_and_send(OpenAPI_nf_type_SMF,
|
||||
sess, state, ¶m, amf_nsmf_pdu_session_build_update_sm_context);
|
||||
sess, state, ¶m, amf_nsmf_pdusession_build_update_sm_context);
|
||||
}
|
||||
|
||||
void amf_sbi_send_deactivate_all_sessions(
|
||||
|
@ -258,7 +258,7 @@ void amf_sbi_send_release_session(amf_sess_t *sess, int state)
|
|||
|
||||
amf_sess_sbi_discover_and_send(
|
||||
OpenAPI_nf_type_SMF, sess, state, NULL,
|
||||
amf_nsmf_pdu_session_build_release_sm_context);
|
||||
amf_nsmf_pdusession_build_release_sm_context);
|
||||
|
||||
/* Prevent to invoke SMF for this session */
|
||||
CLEAR_SM_CONTEXT_REF(sess);
|
||||
|
|
|
@ -38,23 +38,29 @@ void amf_ue_sbi_discover_and_send(OpenAPI_nf_type_e target_nf_type,
|
|||
ogs_sbi_request_t *(*build)(amf_ue_t *amf_ue, void *data));
|
||||
|
||||
#define AMF_SESS_SM_CONTEXT_NO_STATE 0
|
||||
#define AMF_UPDATE_SM_CONTEXT_ACTIVATED 1
|
||||
#define AMF_UPDATE_SM_CONTEXT_DEACTIVATED 2
|
||||
#define AMF_UPDATE_SM_CONTEXT_ACTIVATING 3
|
||||
#define AMF_UPDATE_SM_CONTEXT_MODIFIED 4
|
||||
#define AMF_UPDATE_SM_CONTEXT_N2_RELEASED 5
|
||||
#define AMF_UPDATE_SM_CONTEXT_N1_RELEASED 6
|
||||
#define AMF_RELEASE_SM_CONTEXT_NG_CONTEXT_REMOVE 7
|
||||
#define AMF_RELEASE_SM_CONTEXT_REGISTRATION_ACCEPT 8
|
||||
#define AMF_RELEASE_SM_CONTEXT_SERVICE_ACCEPT 9
|
||||
#define AMF_REMOVE_S1_CONTEXT_BY_LO_CONNREFUSED 10
|
||||
#define AMF_REMOVE_S1_CONTEXT_BY_RESET_ALL 11
|
||||
#define AMF_REMOVE_S1_CONTEXT_BY_RESET_PARTIAL 12
|
||||
#define AMF_UPDATE_SM_CONTEXT_ACTIVATED 11
|
||||
#define AMF_UPDATE_SM_CONTEXT_DEACTIVATED 12
|
||||
#define AMF_UPDATE_SM_CONTEXT_REGISTRATION_REQUEST 13
|
||||
#define AMF_UPDATE_SM_CONTEXT_SERVICE_REQUEST 14
|
||||
#define AMF_UPDATE_SM_CONTEXT_MODIFIED 15
|
||||
#define AMF_UPDATE_SM_CONTEXT_N2_RELEASED 16
|
||||
#define AMF_UPDATE_SM_CONTEXT_N1_RELEASED 17
|
||||
#define AMF_UPDATE_SM_CONTEXT_PATH_SWITCH_REQUEST 18
|
||||
#define AMF_UPDATE_SM_CONTEXT_HANDOVER_REQUIRED 19
|
||||
#define AMF_UPDATE_SM_CONTEXT_HANDOVER_REQ_ACK 20
|
||||
#define AMF_UPDATE_SM_CONTEXT_HANDOVER_NOTIFY 21
|
||||
#define AMF_UPDATE_SM_CONTEXT_HANDOVER_CANCEL 22
|
||||
#define AMF_RELEASE_SM_CONTEXT_NG_CONTEXT_REMOVE 31
|
||||
#define AMF_RELEASE_SM_CONTEXT_REGISTRATION_ACCEPT 32
|
||||
#define AMF_RELEASE_SM_CONTEXT_SERVICE_ACCEPT 33
|
||||
#define AMF_REMOVE_S1_CONTEXT_BY_LO_CONNREFUSED 51
|
||||
#define AMF_REMOVE_S1_CONTEXT_BY_RESET_ALL 52
|
||||
#define AMF_REMOVE_S1_CONTEXT_BY_RESET_PARTIAL 53
|
||||
void amf_sess_sbi_discover_and_send(OpenAPI_nf_type_e target_nf_type,
|
||||
amf_sess_t *sess, int state, void *data,
|
||||
ogs_sbi_request_t *(*build)(amf_sess_t *sess, void *data));
|
||||
|
||||
void amf_sbi_send_activating_session(amf_sess_t *sess);
|
||||
void amf_sbi_send_activating_session(amf_sess_t *sess, int state);
|
||||
|
||||
void amf_sbi_send_deactivate_session(
|
||||
amf_sess_t *sess, int state, int group, int cause);
|
||||
|
|
|
@ -2027,6 +2027,10 @@ enb_ue_t *enb_ue_add(mme_enb_t *enb, uint32_t enb_ue_s1ap_id)
|
|||
enb_ue->enb_ostream_id =
|
||||
OGS_NEXT_ID(enb->ostream_id, 1, enb->max_num_of_ostreams-1);
|
||||
|
||||
enb_ue->t_s1_holding = ogs_timer_add(
|
||||
ogs_app()->timer_mgr, mme_timer_s1_holding_timer_expire, enb_ue);
|
||||
ogs_assert(enb_ue->t_s1_holding);
|
||||
|
||||
enb_ue->enb = enb;
|
||||
|
||||
ogs_list_add(&enb->enb_ue_list, enb_ue);
|
||||
|
@ -2046,8 +2050,8 @@ void enb_ue_remove(enb_ue_t *enb_ue)
|
|||
|
||||
ogs_list_remove(&enb->enb_ue_list, enb_ue);
|
||||
|
||||
if (enb_ue->t_s1_holding)
|
||||
ogs_timer_delete(enb_ue->t_s1_holding);
|
||||
ogs_assert(enb_ue->t_s1_holding);
|
||||
ogs_timer_delete(enb_ue->t_s1_holding);
|
||||
|
||||
ogs_pool_free(&enb_ue_pool, enb_ue);
|
||||
|
||||
|
|
|
@ -262,7 +262,7 @@ struct enb_ue_s {
|
|||
#define S1AP_UE_CTX_REL_S1_CONTEXT_REMOVE 1
|
||||
#define S1AP_UE_CTX_REL_S1_REMOVE_AND_UNLINK 2
|
||||
#define S1AP_UE_CTX_REL_UE_CONTEXT_REMOVE 3
|
||||
#define S1AP_UE_CTX_REL_DELETE_INDIRECT_TUNNEL 4
|
||||
#define S1AP_UE_CTX_REL_S1_HANDOVER_COMPLETE 4
|
||||
#define S1AP_UE_CTX_REL_S1_PAGING 5
|
||||
uint8_t ue_ctx_rel_action;
|
||||
|
||||
|
|
|
@ -304,7 +304,7 @@ void mme_s11_handle_modify_bearer_response(
|
|||
s1ap_send_ue_context_release_command(source_ue,
|
||||
S1AP_Cause_PR_radioNetwork,
|
||||
S1AP_CauseRadioNetwork_successful_handover,
|
||||
S1AP_UE_CTX_REL_DELETE_INDIRECT_TUNNEL,
|
||||
S1AP_UE_CTX_REL_S1_HANDOVER_COMPLETE,
|
||||
ogs_time_from_msec(300));
|
||||
);
|
||||
}
|
||||
|
|
|
@ -1782,13 +1782,9 @@ ogs_pkbuf_t *s1ap_build_handover_preparation_failure(
|
|||
}
|
||||
|
||||
ogs_pkbuf_t *s1ap_build_handover_request(
|
||||
mme_ue_t *mme_ue, enb_ue_t *target_ue,
|
||||
S1AP_ENB_UE_S1AP_ID_t *enb_ue_s1ap_id,
|
||||
S1AP_MME_UE_S1AP_ID_t *mme_ue_s1ap_id,
|
||||
S1AP_HandoverType_t *handovertype,
|
||||
S1AP_Cause_t *cause,
|
||||
S1AP_Source_ToTarget_TransparentContainer_t
|
||||
*source_totarget_transparentContainer)
|
||||
enb_ue_t *target_ue, S1AP_HandoverType_t *handovertype, S1AP_Cause_t *cause,
|
||||
S1AP_Source_ToTarget_TransparentContainer_t
|
||||
*source_totarget_transparentContainer)
|
||||
{
|
||||
int rv;
|
||||
|
||||
|
@ -1807,6 +1803,7 @@ ogs_pkbuf_t *s1ap_build_handover_request(
|
|||
S1AP_UESecurityCapabilities_t *UESecurityCapabilities = NULL;
|
||||
S1AP_SecurityContext_t *SecurityContext = NULL;
|
||||
|
||||
mme_ue_t *mme_ue = NULL;
|
||||
mme_sess_t *sess = NULL;
|
||||
mme_bearer_t *bearer = NULL;
|
||||
ogs_subscription_data_t *subscription_data = NULL;
|
||||
|
@ -1816,6 +1813,7 @@ ogs_pkbuf_t *s1ap_build_handover_request(
|
|||
ogs_assert(source_totarget_transparentContainer);
|
||||
|
||||
ogs_assert(target_ue);
|
||||
mme_ue = target_ue->mme_ue;
|
||||
ogs_assert(mme_ue);
|
||||
subscription_data = &mme_ue->subscription_data;
|
||||
ogs_assert(subscription_data);
|
||||
|
@ -1985,8 +1983,8 @@ ogs_pkbuf_t *s1ap_build_handover_request(
|
|||
}
|
||||
|
||||
ogs_s1ap_buffer_to_OCTET_STRING(
|
||||
source_totarget_transparentContainer->buf,
|
||||
source_totarget_transparentContainer->size,
|
||||
source_totarget_transparentContainer->buf,
|
||||
source_totarget_transparentContainer->size,
|
||||
Source_ToTarget_TransparentContainer);
|
||||
|
||||
UESecurityCapabilities->encryptionAlgorithms.size = 2;
|
||||
|
|
|
@ -64,11 +64,7 @@ ogs_pkbuf_t *s1ap_build_handover_preparation_failure(
|
|||
enb_ue_t *source_ue, S1AP_Cause_t *cause);
|
||||
|
||||
ogs_pkbuf_t *s1ap_build_handover_request(
|
||||
mme_ue_t *mme_ue, enb_ue_t *target_ue,
|
||||
S1AP_ENB_UE_S1AP_ID_t *enb_ue_s1ap_id,
|
||||
S1AP_MME_UE_S1AP_ID_t *mme_ue_s1ap_id,
|
||||
S1AP_HandoverType_t *handovertype,
|
||||
S1AP_Cause_t *cause,
|
||||
enb_ue_t *target_ue, S1AP_HandoverType_t *handovertype, S1AP_Cause_t *cause,
|
||||
S1AP_Source_ToTarget_TransparentContainer_t
|
||||
*source_totarget_transparentContainer);
|
||||
|
||||
|
|
|
@ -1253,8 +1253,8 @@ void s1ap_handle_ue_context_release_action(enb_ue_t *enb_ue)
|
|||
ogs_expect_or_return(mme_ue);
|
||||
mme_ue_remove(mme_ue);
|
||||
break;
|
||||
case S1AP_UE_CTX_REL_DELETE_INDIRECT_TUNNEL:
|
||||
ogs_debug(" Action: Delete indirect tunnel");
|
||||
case S1AP_UE_CTX_REL_S1_HANDOVER_COMPLETE:
|
||||
ogs_debug(" Action: S1 handover complete");
|
||||
|
||||
source_ue_deassociate_target_ue(enb_ue);
|
||||
enb_ue_remove(enb_ue);
|
||||
|
@ -1556,15 +1556,15 @@ void s1ap_handle_enb_configuration_transfer(
|
|||
target_tac = be16toh(target_tac);
|
||||
|
||||
ogs_debug(" Source : ENB_ID[%s:%d], TAC[%d]",
|
||||
sourceeNB_ID->global_ENB_ID.eNB_ID.present ==
|
||||
S1AP_ENB_ID_PR_homeENB_ID ? "Home" :
|
||||
sourceeNB_ID->global_ENB_ID.eNB_ID.present ==
|
||||
sourceeNB_ID->global_ENB_ID.eNB_ID.present ==
|
||||
S1AP_ENB_ID_PR_homeENB_ID ? "Home" :
|
||||
sourceeNB_ID->global_ENB_ID.eNB_ID.present ==
|
||||
S1AP_ENB_ID_PR_macroENB_ID ? "Macro" : "Others",
|
||||
source_enb_id, source_tac);
|
||||
ogs_debug(" Target : ENB_ID[%s:%d], TAC[%d]",
|
||||
targeteNB_ID->global_ENB_ID.eNB_ID.present ==
|
||||
S1AP_ENB_ID_PR_homeENB_ID ? "Home" :
|
||||
targeteNB_ID->global_ENB_ID.eNB_ID.present ==
|
||||
targeteNB_ID->global_ENB_ID.eNB_ID.present ==
|
||||
S1AP_ENB_ID_PR_homeENB_ID ? "Home" :
|
||||
targeteNB_ID->global_ENB_ID.eNB_ID.present ==
|
||||
S1AP_ENB_ID_PR_macroENB_ID ? "Macro" : "Others",
|
||||
target_enb_id, target_tac);
|
||||
|
||||
|
@ -1687,9 +1687,8 @@ void s1ap_handle_handover_required(mme_enb_t *enb, ogs_s1ap_message_t *message)
|
|||
ogs_assert(HandoverType);
|
||||
source_ue->handover_type = *HandoverType;
|
||||
|
||||
s1ap_send_handover_request(mme_ue, target_enb,
|
||||
ENB_UE_S1AP_ID, MME_UE_S1AP_ID,
|
||||
HandoverType, Cause,
|
||||
s1ap_send_handover_request(
|
||||
source_ue, target_enb, HandoverType, Cause,
|
||||
Source_ToTarget_TransparentContainer);
|
||||
}
|
||||
|
||||
|
@ -1885,7 +1884,7 @@ void s1ap_handle_handover_failure(mme_enb_t *enb, ogs_s1ap_message_t *message)
|
|||
s1ap_send_ue_context_release_command(
|
||||
target_ue, S1AP_Cause_PR_radioNetwork,
|
||||
S1AP_CauseRadioNetwork_ho_failure_in_target_EPC_eNB_or_target_system,
|
||||
S1AP_UE_CTX_REL_DELETE_INDIRECT_TUNNEL, 0);
|
||||
S1AP_UE_CTX_REL_S1_HANDOVER_COMPLETE, 0);
|
||||
}
|
||||
|
||||
void s1ap_handle_handover_cancel(mme_enb_t *enb, ogs_s1ap_message_t *message)
|
||||
|
@ -1954,7 +1953,7 @@ void s1ap_handle_handover_cancel(mme_enb_t *enb, ogs_s1ap_message_t *message)
|
|||
s1ap_send_ue_context_release_command(
|
||||
target_ue, S1AP_Cause_PR_radioNetwork,
|
||||
S1AP_CauseRadioNetwork_handover_cancelled,
|
||||
S1AP_UE_CTX_REL_DELETE_INDIRECT_TUNNEL,
|
||||
S1AP_UE_CTX_REL_S1_HANDOVER_COMPLETE,
|
||||
ogs_time_from_msec(300));
|
||||
|
||||
ogs_debug("Handover Cancel : "
|
||||
|
|
|
@ -284,7 +284,7 @@ void s1ap_send_ue_context_modification_request(mme_ue_t *mme_ue)
|
|||
|
||||
void s1ap_send_ue_context_release_command(
|
||||
enb_ue_t *enb_ue, S1AP_Cause_PR group, long cause,
|
||||
uint8_t action, uint32_t delay)
|
||||
uint8_t action, ogs_time_t duration)
|
||||
{
|
||||
int rv;
|
||||
ogs_pkbuf_t *s1apbuf = NULL;
|
||||
|
@ -298,22 +298,15 @@ void s1ap_send_ue_context_release_command(
|
|||
ogs_assert(action != S1AP_UE_CTX_REL_INVALID_ACTION);
|
||||
enb_ue->ue_ctx_rel_action = action;
|
||||
|
||||
ogs_debug(" Group[%d] Cause[%d] Action[%d] Delay[%d]",
|
||||
group, (int)cause, action, delay);
|
||||
ogs_debug(" Group[%d] Cause[%d] Action[%d] Duration[%d]",
|
||||
group, (int)cause, action, (int)duration);
|
||||
|
||||
s1apbuf = s1ap_build_ue_context_release_command(enb_ue, group, cause);
|
||||
ogs_expect_or_return(s1apbuf);
|
||||
|
||||
rv = s1ap_delayed_send_to_enb_ue(enb_ue, s1apbuf, delay);
|
||||
rv = s1ap_delayed_send_to_enb_ue(enb_ue, s1apbuf, duration);
|
||||
ogs_expect(rv == OGS_OK);
|
||||
|
||||
if (enb_ue->t_s1_holding)
|
||||
ogs_timer_delete(enb_ue->t_s1_holding);
|
||||
|
||||
enb_ue->t_s1_holding = ogs_timer_add(
|
||||
ogs_app()->timer_mgr, mme_timer_s1_holding_timer_expire, enb_ue);
|
||||
ogs_assert(enb_ue->t_s1_holding);
|
||||
|
||||
ogs_timer_start(enb_ue->t_s1_holding,
|
||||
mme_timer_cfg(MME_TIMER_S1_HOLDING)->duration);
|
||||
}
|
||||
|
@ -430,28 +423,21 @@ void s1ap_send_handover_cancel_ack(enb_ue_t *source_ue)
|
|||
|
||||
|
||||
void s1ap_send_handover_request(
|
||||
mme_ue_t *mme_ue,
|
||||
mme_enb_t *target_enb,
|
||||
S1AP_ENB_UE_S1AP_ID_t *enb_ue_s1ap_id,
|
||||
S1AP_MME_UE_S1AP_ID_t *mme_ue_s1ap_id,
|
||||
S1AP_HandoverType_t *handovertype,
|
||||
S1AP_Cause_t *cause,
|
||||
enb_ue_t *source_ue, mme_enb_t *target_enb,
|
||||
S1AP_HandoverType_t *handovertype, S1AP_Cause_t *cause,
|
||||
S1AP_Source_ToTarget_TransparentContainer_t
|
||||
*source_totarget_transparentContainer)
|
||||
{
|
||||
int rv;
|
||||
ogs_pkbuf_t *s1apbuf = NULL;
|
||||
|
||||
enb_ue_t *source_ue = NULL, *target_ue = NULL;
|
||||
enb_ue_t *target_ue = NULL;
|
||||
|
||||
ogs_info("Handover request");
|
||||
|
||||
ogs_assert(target_enb);
|
||||
|
||||
ogs_assert(mme_ue);
|
||||
source_ue = enb_ue_cycle(mme_ue->enb_ue);
|
||||
ogs_assert(source_ue);
|
||||
ogs_assert(source_ue->target_ue == NULL);
|
||||
ogs_assert(target_enb);
|
||||
|
||||
target_ue = enb_ue_add(target_enb, INVALID_UE_S1AP_ID);
|
||||
ogs_assert(target_ue);
|
||||
|
@ -463,9 +449,8 @@ void s1ap_send_handover_request(
|
|||
|
||||
source_ue_associate_target_ue(source_ue, target_ue);
|
||||
|
||||
s1apbuf = s1ap_build_handover_request(mme_ue, target_ue,
|
||||
enb_ue_s1ap_id, mme_ue_s1ap_id,
|
||||
handovertype, cause,
|
||||
s1apbuf = s1ap_build_handover_request(
|
||||
target_ue, handovertype, cause,
|
||||
source_totarget_transparentContainer);
|
||||
ogs_expect_or_return(s1apbuf);
|
||||
|
||||
|
|
|
@ -54,7 +54,7 @@ void s1ap_send_initial_context_setup_request(mme_ue_t *mme_ue);
|
|||
void s1ap_send_ue_context_modification_request(mme_ue_t *mme_ue);
|
||||
void s1ap_send_ue_context_release_command(
|
||||
enb_ue_t *enb_ue, S1AP_Cause_PR group, long cause,
|
||||
uint8_t action, uint32_t delay);
|
||||
uint8_t action, ogs_time_t duration);
|
||||
|
||||
void s1ap_send_paging(mme_ue_t *mme_ue, S1AP_CNDomain_t cn_domain);
|
||||
|
||||
|
@ -69,12 +69,8 @@ void s1ap_send_handover_preparation_failure(
|
|||
enb_ue_t *source_ue, S1AP_Cause_t *cause);
|
||||
|
||||
void s1ap_send_handover_request(
|
||||
mme_ue_t *mme_ue,
|
||||
mme_enb_t *target_enb,
|
||||
S1AP_ENB_UE_S1AP_ID_t *enb_ue_s1ap_id,
|
||||
S1AP_MME_UE_S1AP_ID_t *mme_ue_s1ap_id,
|
||||
S1AP_HandoverType_t *handovertype,
|
||||
S1AP_Cause_t *cause,
|
||||
enb_ue_t *source_ue, mme_enb_t *target_enb,
|
||||
S1AP_HandoverType_t *handovertype, S1AP_Cause_t *cause,
|
||||
S1AP_Source_ToTarget_TransparentContainer_t
|
||||
*source_totarget_transparentContainer);
|
||||
|
||||
|
|
|
@ -302,6 +302,13 @@ typedef struct smf_sess_s {
|
|||
int pdu_session_resource_release;
|
||||
} ngap_state;
|
||||
|
||||
/* Handover */
|
||||
struct {
|
||||
bool prepared;
|
||||
uint32_t gnb_n3_teid;
|
||||
ogs_ip_t gnb_n3_ip;
|
||||
} handover; /* Saved from N2-Handover Request Acknowledge */
|
||||
|
||||
ogs_list_t bearer_list;
|
||||
|
||||
ogs_gtp_node_t *gnode;
|
||||
|
|
|
@ -329,8 +329,25 @@ void smf_gsm_state_operational(ogs_fsm_t *s, smf_event_t *e)
|
|||
break;
|
||||
|
||||
case OpenAPI_n2_sm_info_type_PATH_SWITCH_REQ:
|
||||
rv = ngap_handle_pdu_session_resource_to_be_switched_dl_transfer(
|
||||
sess, stream, pkbuf);
|
||||
rv = ngap_handle_path_switch_request_transfer(sess, stream, pkbuf);
|
||||
if (rv != OGS_OK) {
|
||||
ogs_error("[%s:%d] Cannot handle NGAP message",
|
||||
smf_ue->supi, sess->psi);
|
||||
OGS_FSM_TRAN(s, smf_gsm_state_exception);
|
||||
}
|
||||
break;
|
||||
|
||||
case OpenAPI_n2_sm_info_type_HANDOVER_REQUIRED:
|
||||
rv = ngap_handle_handover_required_transfer(sess, stream, pkbuf);
|
||||
if (rv != OGS_OK) {
|
||||
ogs_error("[%s:%d] Cannot handle NGAP message",
|
||||
smf_ue->supi, sess->psi);
|
||||
OGS_FSM_TRAN(s, smf_gsm_state_exception);
|
||||
}
|
||||
break;
|
||||
|
||||
case OpenAPI_n2_sm_info_type_HANDOVER_REQ_ACK:
|
||||
rv = ngap_handle_handover_request_ack(sess, stream, pkbuf);
|
||||
if (rv != OGS_OK) {
|
||||
ogs_error("[%s:%d] Cannot handle NGAP message",
|
||||
smf_ue->supi, sess->psi);
|
||||
|
|
|
@ -195,7 +195,7 @@ void smf_5gc_n4_handle_session_establishment_response(
|
|||
param.n1smbuf = gsm_build_pdu_session_establishment_accept(sess);
|
||||
ogs_assert(param.n1smbuf);
|
||||
param.n2smbuf = ngap_build_pdu_session_resource_setup_request_transfer(
|
||||
sess);
|
||||
sess);
|
||||
ogs_assert(param.n2smbuf);
|
||||
|
||||
smf_namf_comm_send_n1_n2_message_transfer(sess, ¶m);
|
||||
|
@ -299,13 +299,18 @@ void smf_5gc_n4_handle_session_modification_response(
|
|||
}
|
||||
|
||||
if (flags & OGS_PFCP_MODIFY_ACTIVATE) {
|
||||
if (flags & OGS_PFCP_MODIFY_PATH_SWITCH) {
|
||||
if (flags & OGS_PFCP_MODIFY_XN_HANDOVER) {
|
||||
ogs_pkbuf_t *n2smbuf =
|
||||
ngap_build_path_switch_request_ack_transfer(sess);
|
||||
ogs_assert(n2smbuf);
|
||||
|
||||
smf_sbi_send_sm_context_updated_data_n2smbuf(sess, stream,
|
||||
OpenAPI_n2_sm_info_type_PATH_SWITCH_REQ_ACK, n2smbuf);
|
||||
} else if (flags & OGS_PFCP_MODIFY_N2_HANDOVER) {
|
||||
|
||||
smf_sbi_send_sm_context_updated_data_ho_state(
|
||||
sess, stream, OpenAPI_ho_state_COMPLETED);
|
||||
|
||||
} else {
|
||||
sess->paging.ue_requested_pdu_session_establishment_done = true;
|
||||
smf_sbi_send_http_status_no_content(stream);
|
||||
|
@ -778,7 +783,8 @@ void smf_n4_handle_session_report_request(
|
|||
memset(¶m, 0, sizeof(param));
|
||||
param.state = SMF_NETWORK_TRIGGERED_SERVICE_REQUEST;
|
||||
param.n2smbuf =
|
||||
ngap_build_pdu_session_resource_setup_request_transfer(sess);
|
||||
ngap_build_pdu_session_resource_setup_request_transfer(
|
||||
sess);
|
||||
ogs_assert(param.n2smbuf);
|
||||
|
||||
param.n1n2_failure_txf_notif_uri = true;
|
||||
|
|
|
@ -303,14 +303,14 @@ ogs_pkbuf_t *ngap_build_path_switch_request_ack_transfer(smf_sess_t *sess)
|
|||
{
|
||||
NGAP_PathSwitchRequestAcknowledgeTransfer_t message;
|
||||
|
||||
#if 0
|
||||
#if 0 /* The following is optional. So I've removed */
|
||||
ogs_ip_t upf_n3_ip;
|
||||
|
||||
NGAP_UPTransportLayerInformation_t *UPTransportLayerInformation = NULL;
|
||||
NGAP_GTPTunnel_t *gTPTunnel = NULL;
|
||||
#endif
|
||||
|
||||
ogs_assert(sess);
|
||||
#endif
|
||||
|
||||
ogs_debug("PathSwitchRequestAcknowledgeTransfer");
|
||||
memset(&message, 0, sizeof(NGAP_PathSwitchRequestAcknowledgeTransfer_t));
|
||||
|
@ -334,3 +334,39 @@ ogs_pkbuf_t *ngap_build_path_switch_request_ack_transfer(smf_sess_t *sess)
|
|||
return ogs_asn_encode(
|
||||
&asn_DEF_NGAP_PathSwitchRequestAcknowledgeTransfer, &message);
|
||||
}
|
||||
|
||||
ogs_pkbuf_t *ngap_build_handover_command_transfer(smf_sess_t *sess)
|
||||
{
|
||||
NGAP_HandoverCommandTransfer_t message;
|
||||
|
||||
#if 0 /* The following is optional. So I've removed */
|
||||
ogs_ip_t upf_n3_ip;
|
||||
|
||||
NGAP_UPTransportLayerInformation_t *dLForwardingUP_TNLInformation = NULL;
|
||||
NGAP_GTPTunnel_t *gTPTunnel = NULL;
|
||||
#endif
|
||||
|
||||
ogs_assert(sess);
|
||||
|
||||
ogs_debug("HandoverCommandTransfer");
|
||||
memset(&message, 0, sizeof(NGAP_HandoverCommandTransfer_t));
|
||||
|
||||
#if 0 /* The following is optional. So I've removed */
|
||||
message.dLForwardingUP_TNLInformation = dLForwardingUP_TNLInformation =
|
||||
CALLOC(1, sizeof(*dLForwardingUP_TNLInformation));
|
||||
ogs_assert(dLForwardingUP_TNLInformation);
|
||||
|
||||
dLForwardingUP_TNLInformation->present =
|
||||
NGAP_UPTransportLayerInformation_PR_gTPTunnel;
|
||||
dLForwardingUP_TNLInformation->choice.gTPTunnel = gTPTunnel =
|
||||
CALLOC(1, sizeof(*gTPTunnel));
|
||||
ogs_assert(gTPTunnel);
|
||||
|
||||
ogs_sockaddr_to_ip(sess->upf_n3_addr, sess->upf_n3_addr6, &upf_n3_ip);
|
||||
ogs_asn_ip_to_BIT_STRING(&upf_n3_ip, &gTPTunnel->transportLayerAddress);
|
||||
ogs_asn_uint32_to_OCTET_STRING(sess->upf_n3_teid, &gTPTunnel->gTP_TEID);
|
||||
#endif
|
||||
|
||||
return ogs_asn_encode(
|
||||
&asn_DEF_NGAP_HandoverCommandTransfer, &message);
|
||||
}
|
||||
|
|
|
@ -37,6 +37,8 @@ ogs_pkbuf_t *ngap_build_pdu_session_resource_release_command_transfer(
|
|||
|
||||
ogs_pkbuf_t *ngap_build_path_switch_request_ack_transfer(smf_sess_t *sess);
|
||||
|
||||
ogs_pkbuf_t *ngap_build_handover_command_transfer(smf_sess_t *sess);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
#include "ngap-handler.h"
|
||||
#include "sbi-path.h"
|
||||
#include "pfcp-path.h"
|
||||
#include "ngap-path.h"
|
||||
|
||||
int ngap_handle_pdu_session_resource_setup_response_transfer(
|
||||
smf_sess_t *sess, ogs_sbi_stream_t *stream, ogs_pkbuf_t *pkbuf)
|
||||
|
@ -230,7 +231,7 @@ cleanup:
|
|||
return rv;
|
||||
}
|
||||
|
||||
int ngap_handle_pdu_session_resource_to_be_switched_dl_transfer(
|
||||
int ngap_handle_path_switch_request_transfer(
|
||||
smf_sess_t *sess, ogs_sbi_stream_t *stream, ogs_pkbuf_t *pkbuf)
|
||||
{
|
||||
smf_ue_t *smf_ue = NULL;
|
||||
|
@ -246,6 +247,7 @@ int ngap_handle_pdu_session_resource_to_be_switched_dl_transfer(
|
|||
NGAP_PathSwitchRequestTransfer_t message;
|
||||
|
||||
NGAP_UPTransportLayerInformation_t *dL_NGU_UP_TNLInformation = NULL;
|
||||
NGAP_QosFlowAcceptedItem_t *acceptedQosFlowItem = NULL;
|
||||
NGAP_GTPTunnel_t *gTPTunnel = NULL;
|
||||
|
||||
NGAP_QosFlowAcceptedList_t *qosFlowAcceptedList = NULL;
|
||||
|
@ -274,11 +276,11 @@ int ngap_handle_pdu_session_resource_to_be_switched_dl_transfer(
|
|||
if (dL_NGU_UP_TNLInformation->present !=
|
||||
NGAP_UPTransportLayerInformation_PR_gTPTunnel) {
|
||||
ogs_error(
|
||||
"[%s:%d] Unknown NGAP_UPTransportLayerInformation.present [%d]",
|
||||
"[%s:%d] Unknown dL_NGU_UP_TNLInformation->present [%d]",
|
||||
smf_ue->supi, sess->psi, dL_NGU_UP_TNLInformation->present);
|
||||
smf_sbi_send_sm_context_update_error(stream,
|
||||
OGS_SBI_HTTP_STATUS_BAD_REQUEST,
|
||||
"Unknown NGAP_UPTransportLayerInformation.present",
|
||||
"Unknown dL_NGU_UP_TNLInformation->present",
|
||||
smf_ue->supi, NULL, NULL);
|
||||
goto cleanup;
|
||||
}
|
||||
|
@ -306,7 +308,6 @@ int ngap_handle_pdu_session_resource_to_be_switched_dl_transfer(
|
|||
|
||||
qosFlowAcceptedList = &message.qosFlowAcceptedList;
|
||||
for (i = 0; i < qosFlowAcceptedList->list.count; i++) {
|
||||
NGAP_QosFlowAcceptedItem_t *acceptedQosFlowItem = NULL;
|
||||
acceptedQosFlowItem = (NGAP_QosFlowAcceptedItem_t *)
|
||||
qosFlowAcceptedList->list.array[i];
|
||||
if (acceptedQosFlowItem) {
|
||||
|
@ -339,7 +340,7 @@ int ngap_handle_pdu_session_resource_to_be_switched_dl_transfer(
|
|||
if (far_update) {
|
||||
smf_5gc_pfcp_send_session_modification_request(
|
||||
sess, stream,
|
||||
OGS_PFCP_MODIFY_ACTIVATE | OGS_PFCP_MODIFY_PATH_SWITCH |
|
||||
OGS_PFCP_MODIFY_ACTIVATE | OGS_PFCP_MODIFY_XN_HANDOVER |
|
||||
OGS_PFCP_MODIFY_END_MARKER);
|
||||
} else {
|
||||
/* ACTIVATED Is NOT Included in RESPONSE */
|
||||
|
@ -352,3 +353,150 @@ cleanup:
|
|||
ogs_asn_free(&asn_DEF_NGAP_PathSwitchRequestTransfer, &message);
|
||||
return rv;
|
||||
}
|
||||
|
||||
int ngap_handle_handover_required_transfer(
|
||||
smf_sess_t *sess, ogs_sbi_stream_t *stream, ogs_pkbuf_t *pkbuf)
|
||||
{
|
||||
smf_ue_t *smf_ue = NULL;
|
||||
int rv;
|
||||
|
||||
NGAP_HandoverRequiredTransfer_t message;
|
||||
|
||||
ogs_pkbuf_t *n2smbuf = NULL;
|
||||
|
||||
ogs_assert(pkbuf);
|
||||
ogs_assert(stream);
|
||||
|
||||
ogs_assert(sess);
|
||||
smf_ue = sess->smf_ue;
|
||||
ogs_assert(smf_ue);
|
||||
|
||||
rv = ogs_asn_decode(&asn_DEF_NGAP_HandoverRequiredTransfer,
|
||||
&message, sizeof(message), pkbuf);
|
||||
if (rv != OGS_OK) {
|
||||
ogs_error("[%s:%d] Cannot decode NGAP message",
|
||||
smf_ue->supi, sess->psi);
|
||||
smf_sbi_send_sm_context_update_error(stream,
|
||||
OGS_SBI_HTTP_STATUS_BAD_REQUEST,
|
||||
"No N2 SM Info Type", smf_ue->supi, NULL, NULL);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
n2smbuf = ngap_build_pdu_session_resource_setup_request_transfer(sess);
|
||||
ogs_assert(n2smbuf);
|
||||
|
||||
smf_sbi_send_sm_context_updated_data(
|
||||
sess, stream, 0, OpenAPI_ho_state_PREPARING,
|
||||
NULL, OpenAPI_n2_sm_info_type_PDU_RES_SETUP_REQ, n2smbuf);
|
||||
|
||||
rv = OGS_OK;
|
||||
|
||||
cleanup:
|
||||
ogs_asn_free(&asn_DEF_NGAP_HandoverRequiredTransfer, &message);
|
||||
return rv;
|
||||
}
|
||||
|
||||
int ngap_handle_handover_request_ack(
|
||||
smf_sess_t *sess, ogs_sbi_stream_t *stream, ogs_pkbuf_t *pkbuf)
|
||||
{
|
||||
smf_ue_t *smf_ue = NULL;
|
||||
smf_bearer_t *qos_flow = NULL;
|
||||
int rv, i;
|
||||
|
||||
ogs_pfcp_far_t *dl_far = NULL;
|
||||
|
||||
NGAP_HandoverRequestAcknowledgeTransfer_t message;
|
||||
|
||||
NGAP_UPTransportLayerInformation_t *dL_NGU_UP_TNLInformation = NULL;
|
||||
NGAP_QosFlowListWithDataForwarding_t *qosFlowSetupResponseList = NULL;
|
||||
NGAP_QosFlowItemWithDataForwarding_t *qosFlowSetupResponseItem = NULL;
|
||||
NGAP_GTPTunnel_t *gTPTunnel = NULL;
|
||||
|
||||
ogs_pkbuf_t *n2smbuf = NULL;
|
||||
|
||||
ogs_assert(pkbuf);
|
||||
ogs_assert(stream);
|
||||
|
||||
ogs_assert(sess);
|
||||
smf_ue = sess->smf_ue;
|
||||
ogs_assert(smf_ue);
|
||||
|
||||
rv = ogs_asn_decode(&asn_DEF_NGAP_HandoverRequestAcknowledgeTransfer,
|
||||
&message, sizeof(message), pkbuf);
|
||||
if (rv != OGS_OK) {
|
||||
ogs_error("[%s:%d] Cannot decode NGAP message",
|
||||
smf_ue->supi, sess->psi);
|
||||
smf_sbi_send_sm_context_update_error(stream,
|
||||
OGS_SBI_HTTP_STATUS_BAD_REQUEST,
|
||||
"No N2 SM Info Type", smf_ue->supi, NULL, NULL);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
rv = OGS_ERROR;
|
||||
|
||||
dL_NGU_UP_TNLInformation = &message.dL_NGU_UP_TNLInformation;
|
||||
if (dL_NGU_UP_TNLInformation->present !=
|
||||
NGAP_UPTransportLayerInformation_PR_gTPTunnel) {
|
||||
ogs_error(
|
||||
"[%s:%d] Unknown dL_NGU_UP_TNLInformation->present [%d]",
|
||||
smf_ue->supi, sess->psi, dL_NGU_UP_TNLInformation->present);
|
||||
smf_sbi_send_sm_context_update_error(stream,
|
||||
OGS_SBI_HTTP_STATUS_BAD_REQUEST,
|
||||
"Unknown dL_NGU_UP_TNLInformation->present",
|
||||
smf_ue->supi, NULL, NULL);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
gTPTunnel = dL_NGU_UP_TNLInformation->choice.gTPTunnel;
|
||||
if (!gTPTunnel) {
|
||||
ogs_error("[%s:%d] No GTPTunnel", smf_ue->supi, sess->psi);
|
||||
smf_sbi_send_sm_context_update_error(stream,
|
||||
OGS_SBI_HTTP_STATUS_BAD_REQUEST,
|
||||
"No GTPTunnel", smf_ue->supi, NULL, NULL);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
/* Store FAR */
|
||||
ogs_asn_BIT_STRING_to_ip(&gTPTunnel->transportLayerAddress,
|
||||
&sess->handover.gnb_n3_ip);
|
||||
ogs_asn_OCTET_STRING_to_uint32(&gTPTunnel->gTP_TEID,
|
||||
&sess->handover.gnb_n3_teid);
|
||||
sess->handover.prepared = true;
|
||||
|
||||
qosFlowSetupResponseList = &message.qosFlowSetupResponseList;
|
||||
for (i = 0; i < qosFlowSetupResponseList->list.count; i++) {
|
||||
qosFlowSetupResponseItem = (NGAP_QosFlowItemWithDataForwarding_t *)
|
||||
qosFlowSetupResponseList->list.array[i];
|
||||
if (qosFlowSetupResponseItem) {
|
||||
qos_flow = smf_qos_flow_find_by_qfi(sess,
|
||||
qosFlowSetupResponseItem->qosFlowIdentifier);
|
||||
|
||||
if (qos_flow) {
|
||||
dl_far = qos_flow->dl_far;
|
||||
ogs_assert(dl_far);
|
||||
|
||||
dl_far->handover.prepared = true;
|
||||
|
||||
} else {
|
||||
ogs_error("[%s:%d] No QoS flow", smf_ue->supi, sess->psi);
|
||||
smf_sbi_send_sm_context_update_error(stream,
|
||||
OGS_SBI_HTTP_STATUS_BAD_REQUEST,
|
||||
"No QoS flow", smf_ue->supi, NULL, NULL);
|
||||
goto cleanup;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
n2smbuf = ngap_build_handover_command_transfer(sess);
|
||||
ogs_assert(n2smbuf);
|
||||
|
||||
smf_sbi_send_sm_context_updated_data(
|
||||
sess, stream, 0, OpenAPI_ho_state_PREPARED,
|
||||
NULL, OpenAPI_n2_sm_info_type_HANDOVER_CMD, n2smbuf);
|
||||
|
||||
rv = OGS_OK;
|
||||
|
||||
cleanup:
|
||||
ogs_asn_free(&asn_DEF_NGAP_HandoverRequestAcknowledgeTransfer, &message);
|
||||
return rv;
|
||||
}
|
||||
|
|
|
@ -30,7 +30,11 @@ int ngap_handle_pdu_session_resource_setup_response_transfer(
|
|||
smf_sess_t *sess, ogs_sbi_stream_t *stream, ogs_pkbuf_t *pkbuf);
|
||||
int ngap_handle_pdu_session_resource_modify_response_transfer(
|
||||
smf_sess_t *sess, ogs_sbi_stream_t *stream, ogs_pkbuf_t *pkbuf);
|
||||
int ngap_handle_pdu_session_resource_to_be_switched_dl_transfer(
|
||||
int ngap_handle_path_switch_request_transfer(
|
||||
smf_sess_t *sess, ogs_sbi_stream_t *stream, ogs_pkbuf_t *pkbuf);
|
||||
int ngap_handle_handover_required_transfer(
|
||||
smf_sess_t *sess, ogs_sbi_stream_t *stream, ogs_pkbuf_t *pkbuf);
|
||||
int ngap_handle_handover_request_ack(
|
||||
smf_sess_t *sess, ogs_sbi_stream_t *stream, ogs_pkbuf_t *pkbuf);
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
|
|
@ -341,14 +341,7 @@ bool smf_nsmf_handle_update_sm_context(
|
|||
ngap_send_to_n2sm(
|
||||
sess, stream, SmContextUpdateData->n2_sm_info_type, n2smbuf);
|
||||
|
||||
} else {
|
||||
if (!SmContextUpdateData->up_cnx_state) {
|
||||
ogs_error("[%s:%d] No upCnxState", smf_ue->supi, sess->psi);
|
||||
smf_sbi_send_sm_context_update_error(stream,
|
||||
OGS_SBI_HTTP_STATUS_BAD_REQUEST,
|
||||
"No upCnxState", smf_ue->supi, NULL, NULL);
|
||||
return false;
|
||||
}
|
||||
} else if (SmContextUpdateData->up_cnx_state) {
|
||||
|
||||
if (SmContextUpdateData->up_cnx_state ==
|
||||
OpenAPI_up_cnx_state_DEACTIVATED) {
|
||||
|
@ -450,6 +443,96 @@ bool smf_nsmf_handle_update_sm_context(
|
|||
|
||||
return false;
|
||||
}
|
||||
} else if (SmContextUpdateData->ho_state) {
|
||||
if (SmContextUpdateData->ho_state == OpenAPI_ho_state_COMPLETED) {
|
||||
bool far_update = false;
|
||||
smf_bearer_t *qos_flow = NULL;
|
||||
|
||||
if (sess->handover.prepared == true) {
|
||||
/* Need to Update? */
|
||||
if (memcmp(&sess->gnb_n3_ip, &sess->handover.gnb_n3_ip,
|
||||
sizeof(sess->gnb_n3_ip)) != 0 ||
|
||||
sess->gnb_n3_teid != sess->handover.gnb_n3_teid)
|
||||
far_update = true;
|
||||
|
||||
memcpy(&sess->gnb_n3_ip,
|
||||
&sess->handover.gnb_n3_ip, sizeof(sess->gnb_n3_ip));
|
||||
sess->gnb_n3_teid = sess->handover.gnb_n3_teid;
|
||||
}
|
||||
sess->handover.prepared = false;
|
||||
|
||||
ogs_list_for_each(&sess->bearer_list, qos_flow) {
|
||||
ogs_pfcp_far_t *dl_far = qos_flow->dl_far;
|
||||
ogs_assert(dl_far);
|
||||
|
||||
if (dl_far->handover.prepared == true) {
|
||||
|
||||
if (dl_far->apply_action != OGS_PFCP_APPLY_ACTION_FORW) {
|
||||
far_update = true;
|
||||
}
|
||||
|
||||
dl_far->apply_action = OGS_PFCP_APPLY_ACTION_FORW;
|
||||
ogs_pfcp_ip_to_outer_header_creation(
|
||||
&sess->gnb_n3_ip,
|
||||
&dl_far->outer_header_creation,
|
||||
&dl_far->outer_header_creation_len);
|
||||
dl_far->outer_header_creation.teid = sess->gnb_n3_teid;
|
||||
}
|
||||
dl_far->handover.prepared = false;
|
||||
}
|
||||
|
||||
if (far_update) {
|
||||
smf_5gc_pfcp_send_session_modification_request(
|
||||
sess, stream,
|
||||
OGS_PFCP_MODIFY_ACTIVATE | OGS_PFCP_MODIFY_N2_HANDOVER |
|
||||
OGS_PFCP_MODIFY_END_MARKER);
|
||||
} else {
|
||||
char *strerror = ogs_msprintf(
|
||||
"[%s:%d] No FAR Update", smf_ue->supi, sess->psi);
|
||||
ogs_assert(strerror);
|
||||
|
||||
ogs_error("%s", strerror);
|
||||
smf_sbi_send_sm_context_update_error(
|
||||
stream, OGS_SBI_HTTP_STATUS_BAD_REQUEST,
|
||||
strerror, NULL, NULL, NULL);
|
||||
ogs_free(strerror);
|
||||
|
||||
return false;
|
||||
}
|
||||
} else if (SmContextUpdateData->ho_state ==
|
||||
OpenAPI_ho_state_CANCELLED) {
|
||||
smf_bearer_t *qos_flow = NULL;
|
||||
|
||||
sess->handover.prepared = false;
|
||||
|
||||
ogs_list_for_each(&sess->bearer_list, qos_flow) {
|
||||
ogs_pfcp_far_t *dl_far = qos_flow->dl_far;
|
||||
ogs_assert(dl_far);
|
||||
|
||||
dl_far->handover.prepared = false;
|
||||
}
|
||||
|
||||
smf_sbi_send_sm_context_updated_data_ho_state(
|
||||
sess, stream, OpenAPI_ho_state_CANCELLED);
|
||||
|
||||
} else {
|
||||
char *strerror = ogs_msprintf("[%s:%d] Invalid hoState [%d]",
|
||||
smf_ue->supi, sess->psi, SmContextUpdateData->ho_state);
|
||||
ogs_assert(strerror);
|
||||
|
||||
ogs_error("%s", strerror);
|
||||
smf_sbi_send_sm_context_update_error(stream,
|
||||
OGS_SBI_HTTP_STATUS_BAD_REQUEST, strerror, NULL, NULL, NULL);
|
||||
ogs_free(strerror);
|
||||
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
ogs_error("[%s:%d] No UpdateData", smf_ue->supi, sess->psi);
|
||||
smf_sbi_send_sm_context_update_error(stream,
|
||||
OGS_SBI_HTTP_STATUS_BAD_REQUEST,
|
||||
"No UpdateData", smf_ue->supi, NULL, NULL);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
|
|
|
@ -236,6 +236,7 @@ void smf_sbi_send_sm_context_create_error(
|
|||
void smf_sbi_send_sm_context_updated_data(
|
||||
smf_sess_t *sess, ogs_sbi_stream_t *stream,
|
||||
OpenAPI_up_cnx_state_e up_cnx_state,
|
||||
OpenAPI_ho_state_e ho_state,
|
||||
ogs_pkbuf_t *n1smbuf,
|
||||
OpenAPI_n2_sm_info_type_e n2type, ogs_pkbuf_t *n2smbuf)
|
||||
{
|
||||
|
@ -251,7 +252,9 @@ void smf_sbi_send_sm_context_updated_data(
|
|||
ogs_assert(sess);
|
||||
ogs_assert(stream);
|
||||
|
||||
ogs_assert(up_cnx_state != OpenAPI_up_cnx_state_NULL || n1smbuf || n2smbuf);
|
||||
ogs_assert(up_cnx_state != OpenAPI_up_cnx_state_NULL ||
|
||||
ho_state != OpenAPI_ho_state_NULL ||
|
||||
n1smbuf || n2smbuf);
|
||||
|
||||
memset(&sendmsg, 0, sizeof(sendmsg));
|
||||
|
||||
|
@ -260,6 +263,9 @@ void smf_sbi_send_sm_context_updated_data(
|
|||
/* up_cnx_state */
|
||||
SmContextUpdatedData.up_cnx_state = up_cnx_state;
|
||||
|
||||
/* ho_state */
|
||||
SmContextUpdatedData.ho_state = ho_state;
|
||||
|
||||
/* n1smbuf */
|
||||
if (n1smbuf) {
|
||||
n1SmMsg.content_id = (char *)OGS_SBI_CONTENT_5GNAS_SM_ID;
|
||||
|
|
|
@ -54,18 +54,23 @@ void smf_sbi_send_sm_context_create_error(
|
|||
#define smf_sbi_send_sm_context_updated_data_up_cnx_state( \
|
||||
__sESS, __sTREAM, __uPCnxState) \
|
||||
smf_sbi_send_sm_context_updated_data(\
|
||||
__sESS, __sTREAM, __uPCnxState, NULL, 0, NULL)
|
||||
__sESS, __sTREAM, __uPCnxState, 0, NULL, 0, NULL)
|
||||
#define smf_sbi_send_sm_context_updated_data_n2smbuf( \
|
||||
__sESS, __sTREAM, __n2Type, __n2SmBuf) \
|
||||
smf_sbi_send_sm_context_updated_data(\
|
||||
__sESS, __sTREAM, 0, NULL, __n2Type, __n2SmBuf)
|
||||
__sESS, __sTREAM, 0, 0, NULL, __n2Type, __n2SmBuf)
|
||||
#define smf_sbi_send_sm_context_updated_data_ho_state( \
|
||||
__sESS, __sTREAM, __hoState) \
|
||||
smf_sbi_send_sm_context_updated_data(\
|
||||
__sESS, __sTREAM, 0, __hoState, NULL, 0, NULL)
|
||||
#define smf_sbi_send_sm_context_updated_data_n1_n2_message( \
|
||||
__sESS, __sTREAM, __n1SmBuf, __n2Type, __n2SmBuf) \
|
||||
smf_sbi_send_sm_context_updated_data(\
|
||||
__sESS, __sTREAM, 0, __n1SmBuf, __n2Type, __n2SmBuf)
|
||||
__sESS, __sTREAM, 0, 0, __n1SmBuf, __n2Type, __n2SmBuf)
|
||||
void smf_sbi_send_sm_context_updated_data(
|
||||
smf_sess_t *sess, ogs_sbi_stream_t *stream,
|
||||
OpenAPI_up_cnx_state_e up_cnx_state,
|
||||
OpenAPI_ho_state_e ho_state,
|
||||
ogs_pkbuf_t *n1smbuf,
|
||||
OpenAPI_n2_sm_info_type_e n2type, ogs_pkbuf_t *n2smbuf);
|
||||
|
||||
|
|
|
@ -25,6 +25,10 @@ static ogs_pkbuf_t *testngap_build_pdu_session_resource_modify_response_trasfer(
|
|||
test_bearer_t *qos_flow);
|
||||
static ogs_pkbuf_t *testngap_build_path_switch_request_trasfer(
|
||||
test_sess_t *sess);
|
||||
static ogs_pkbuf_t *testngap_build_handover_required_transfer(
|
||||
test_sess_t *sess, bool direct);
|
||||
static ogs_pkbuf_t *testngap_build_handover_request_ack_transfer(
|
||||
test_sess_t *sess);
|
||||
|
||||
ogs_pkbuf_t *testngap_build_ng_setup_request(uint32_t gnb_id, uint8_t bitsize)
|
||||
{
|
||||
|
@ -1149,6 +1153,101 @@ ogs_pkbuf_t *testngap_build_pdu_session_resource_release_response(
|
|||
return ogs_ngap_encode(&pdu);
|
||||
}
|
||||
|
||||
ogs_pkbuf_t *testngap_build_uplink_ran_configuration_transfer(
|
||||
uint32_t source_gnb_id, uint8_t source_bitsize,
|
||||
uint32_t target_gnb_id, uint8_t target_bitsize)
|
||||
{
|
||||
int rv;
|
||||
ogs_plmn_id_t *plmn_id = NULL;
|
||||
|
||||
NGAP_NGAP_PDU_t pdu;
|
||||
NGAP_InitiatingMessage_t *initiatingMessage = NULL;
|
||||
NGAP_UplinkRANConfigurationTransfer_t
|
||||
*UplinkRANConfigurationTransfer = NULL;
|
||||
|
||||
NGAP_UplinkRANConfigurationTransferIEs_t *ie = NULL;
|
||||
NGAP_SONConfigurationTransfer_t *SONConfigurationTransfer = NULL;
|
||||
NGAP_SourceRANNodeID_t *sourceRANNodeID = NULL;
|
||||
NGAP_GlobalRANNodeID_t *sourceGlobalRANNodeID;
|
||||
NGAP_GlobalGNB_ID_t *sourceGlobalGNB_ID;
|
||||
NGAP_TAI_t *sourceSelectedTAI;
|
||||
NGAP_TargetRANNodeID_t *targetRANNodeID = NULL;
|
||||
NGAP_GlobalRANNodeID_t *targetGlobalRANNodeID;
|
||||
NGAP_GlobalGNB_ID_t *targetGlobalGNB_ID;
|
||||
NGAP_TAI_t *targetSelectedTAI;
|
||||
NGAP_SONInformation_t *sONInformation = NULL;
|
||||
NGAP_SONInformationRequest_t *sONInformationRequest = NULL;
|
||||
|
||||
ogs_debug("Uplink Configuration Transfer");
|
||||
|
||||
memset(&pdu, 0, sizeof (NGAP_NGAP_PDU_t));
|
||||
pdu.present = NGAP_NGAP_PDU_PR_initiatingMessage;
|
||||
pdu.choice.initiatingMessage = CALLOC(1, sizeof(NGAP_InitiatingMessage_t));
|
||||
ogs_assert(pdu.choice.initiatingMessage);
|
||||
|
||||
initiatingMessage = pdu.choice.initiatingMessage;
|
||||
initiatingMessage->procedureCode =
|
||||
NGAP_ProcedureCode_id_UplinkRANConfigurationTransfer;
|
||||
initiatingMessage->criticality = NGAP_Criticality_ignore;
|
||||
initiatingMessage->value.present =
|
||||
NGAP_InitiatingMessage__value_PR_UplinkRANConfigurationTransfer;
|
||||
|
||||
UplinkRANConfigurationTransfer =
|
||||
&initiatingMessage->value.choice.UplinkRANConfigurationTransfer;
|
||||
|
||||
ie = CALLOC(1, sizeof(NGAP_UplinkRANConfigurationTransferIEs_t));
|
||||
ogs_assert(ie);
|
||||
ASN_SEQUENCE_ADD(&UplinkRANConfigurationTransfer->protocolIEs, ie);
|
||||
|
||||
ie->id = NGAP_ProtocolIE_ID_id_SONConfigurationTransferUL;
|
||||
ie->criticality = NGAP_Criticality_ignore;
|
||||
ie->value.present = NGAP_UplinkRANConfigurationTransferIEs__value_PR_SONConfigurationTransfer;
|
||||
|
||||
SONConfigurationTransfer = &ie->value.choice.SONConfigurationTransfer;
|
||||
|
||||
plmn_id = &test_self()->plmn_support[0].plmn_id;
|
||||
|
||||
targetRANNodeID = &SONConfigurationTransfer->targetRANNodeID;
|
||||
targetGlobalRANNodeID = &targetRANNodeID->globalRANNodeID;
|
||||
targetSelectedTAI = &targetRANNodeID->selectedTAI;
|
||||
|
||||
targetGlobalRANNodeID->present = NGAP_GlobalRANNodeID_PR_globalGNB_ID;
|
||||
targetGlobalRANNodeID->choice.globalGNB_ID = targetGlobalGNB_ID =
|
||||
CALLOC(1, sizeof(*targetGlobalGNB_ID));
|
||||
ogs_assert(targetGlobalGNB_ID);
|
||||
|
||||
ogs_asn_buffer_to_OCTET_STRING(
|
||||
plmn_id, OGS_PLMN_ID_LEN, &targetGlobalGNB_ID->pLMNIdentity);
|
||||
ogs_ngap_uint32_to_GNB_ID(target_gnb_id, target_bitsize,
|
||||
&targetGlobalGNB_ID->gNB_ID);
|
||||
ogs_ngap_5gs_tai_to_ASN(&test_self()->nr_tai, targetSelectedTAI);
|
||||
|
||||
sourceRANNodeID = &SONConfigurationTransfer->sourceRANNodeID;
|
||||
sourceGlobalRANNodeID = &sourceRANNodeID->globalRANNodeID;
|
||||
sourceSelectedTAI = &sourceRANNodeID->selectedTAI;
|
||||
|
||||
sourceGlobalRANNodeID->present = NGAP_GlobalRANNodeID_PR_globalGNB_ID;
|
||||
sourceGlobalRANNodeID->choice.globalGNB_ID = sourceGlobalGNB_ID =
|
||||
CALLOC(1, sizeof(*sourceGlobalGNB_ID));
|
||||
ogs_assert(sourceGlobalGNB_ID);
|
||||
|
||||
ogs_asn_buffer_to_OCTET_STRING(
|
||||
plmn_id, OGS_PLMN_ID_LEN, &sourceGlobalGNB_ID->pLMNIdentity);
|
||||
ogs_ngap_uint32_to_GNB_ID(source_gnb_id, source_bitsize,
|
||||
&sourceGlobalGNB_ID->gNB_ID);
|
||||
ogs_ngap_5gs_tai_to_ASN(&test_self()->nr_tai, sourceSelectedTAI);
|
||||
|
||||
sONInformation = &SONConfigurationTransfer->sONInformation;
|
||||
|
||||
sONInformation->present = NGAP_SONInformation_PR_sONInformationRequest;
|
||||
sONInformationRequest = &sONInformation->choice.sONInformationRequest;
|
||||
|
||||
*sONInformationRequest =
|
||||
NGAP_SONInformationRequest_xn_TNL_configuration_info;
|
||||
|
||||
return ogs_ngap_encode(&pdu);
|
||||
}
|
||||
|
||||
ogs_pkbuf_t *testngap_build_path_switch_request(test_ue_t *test_ue)
|
||||
{
|
||||
int rv;
|
||||
|
@ -1315,6 +1414,610 @@ ogs_pkbuf_t *testngap_build_path_switch_request(test_ue_t *test_ue)
|
|||
return ogs_ngap_encode(&pdu);
|
||||
}
|
||||
|
||||
ogs_pkbuf_t *testngap_build_handover_required(
|
||||
test_ue_t *test_ue, NGAP_HandoverType_t handover_type,
|
||||
uint32_t gnb_id, uint8_t bitsize,
|
||||
NGAP_Cause_PR group, long cause,
|
||||
bool direct)
|
||||
{
|
||||
test_sess_t *sess = NULL;
|
||||
|
||||
ogs_pkbuf_t *n2smbuf = NULL;
|
||||
|
||||
ogs_plmn_id_t *plmn_id = NULL;
|
||||
|
||||
NGAP_NGAP_PDU_t pdu;
|
||||
NGAP_InitiatingMessage_t *initiatingMessage = NULL;
|
||||
NGAP_HandoverRequired_t *HandoverRequired = NULL;
|
||||
|
||||
NGAP_HandoverRequiredIEs_t *ie = NULL;
|
||||
NGAP_AMF_UE_NGAP_ID_t *AMF_UE_NGAP_ID = NULL;
|
||||
NGAP_RAN_UE_NGAP_ID_t *RAN_UE_NGAP_ID = NULL;
|
||||
NGAP_HandoverType_t *HandoverType = NULL;
|
||||
NGAP_Cause_t *Cause = NULL;
|
||||
NGAP_TargetID_t *TargetID = NULL;
|
||||
NGAP_TargetRANNodeID_t *targetRANNodeID = NULL;
|
||||
NGAP_GlobalRANNodeID_t *globalRANNodeID = NULL;
|
||||
NGAP_GlobalGNB_ID_t *globalGNB_ID = NULL;
|
||||
NGAP_TAI_t *selectedTAI = NULL;
|
||||
|
||||
NGAP_PDUSessionResourceListHORqd_t *PDUSessionList = NULL;
|
||||
NGAP_PDUSessionResourceItemHORqd_t *PDUSessionItem = NULL;
|
||||
OCTET_STRING_t *transfer = NULL;
|
||||
|
||||
NGAP_SourceToTarget_TransparentContainer_t
|
||||
*SourceToTarget_TransparentContainer = NULL;
|
||||
|
||||
uint8_t tmp[OGS_MAX_SDU_LEN];
|
||||
char *_container =
|
||||
"40"
|
||||
"0300001100000a00 010002f839000102 0120000002f83900 0000001000000a";
|
||||
|
||||
memset(&pdu, 0, sizeof (NGAP_NGAP_PDU_t));
|
||||
pdu.present = NGAP_NGAP_PDU_PR_initiatingMessage;
|
||||
pdu.choice.initiatingMessage = CALLOC(1, sizeof(NGAP_InitiatingMessage_t));
|
||||
ogs_assert(pdu.choice.initiatingMessage);
|
||||
|
||||
initiatingMessage = pdu.choice.initiatingMessage;
|
||||
initiatingMessage->procedureCode =
|
||||
NGAP_ProcedureCode_id_HandoverPreparation;
|
||||
initiatingMessage->criticality = NGAP_Criticality_reject;
|
||||
initiatingMessage->value.present =
|
||||
NGAP_InitiatingMessage__value_PR_HandoverRequired;
|
||||
|
||||
HandoverRequired = &initiatingMessage->value.choice.HandoverRequired;
|
||||
|
||||
ie = CALLOC(1, sizeof(NGAP_HandoverRequiredIEs_t));
|
||||
ogs_assert(ie);
|
||||
ASN_SEQUENCE_ADD(&HandoverRequired->protocolIEs, ie);
|
||||
|
||||
ie->id = NGAP_ProtocolIE_ID_id_AMF_UE_NGAP_ID;
|
||||
ie->criticality = NGAP_Criticality_reject;
|
||||
ie->value.present = NGAP_HandoverRequiredIEs__value_PR_AMF_UE_NGAP_ID;
|
||||
|
||||
AMF_UE_NGAP_ID = &ie->value.choice.AMF_UE_NGAP_ID;
|
||||
|
||||
ie = CALLOC(1, sizeof(NGAP_HandoverRequiredIEs_t));
|
||||
ogs_assert(ie);
|
||||
ASN_SEQUENCE_ADD(&HandoverRequired->protocolIEs, ie);
|
||||
|
||||
ie->id = NGAP_ProtocolIE_ID_id_RAN_UE_NGAP_ID;
|
||||
ie->criticality = NGAP_Criticality_reject;
|
||||
ie->value.present = NGAP_HandoverRequiredIEs__value_PR_RAN_UE_NGAP_ID;
|
||||
|
||||
RAN_UE_NGAP_ID = &ie->value.choice.RAN_UE_NGAP_ID;
|
||||
|
||||
asn_uint642INTEGER(AMF_UE_NGAP_ID, test_ue->amf_ue_ngap_id);
|
||||
*RAN_UE_NGAP_ID = test_ue->ran_ue_ngap_id;
|
||||
|
||||
ie = CALLOC(1, sizeof(NGAP_HandoverRequiredIEs_t));
|
||||
ASN_SEQUENCE_ADD(&HandoverRequired->protocolIEs, ie);
|
||||
|
||||
ie->id = NGAP_ProtocolIE_ID_id_HandoverType;
|
||||
ie->criticality = NGAP_Criticality_reject;
|
||||
ie->value.present = NGAP_HandoverRequiredIEs__value_PR_HandoverType;
|
||||
|
||||
HandoverType = &ie->value.choice.HandoverType;
|
||||
|
||||
*HandoverType = handover_type;
|
||||
|
||||
ie = CALLOC(1, sizeof(NGAP_HandoverRequiredIEs_t));
|
||||
ogs_assert(ie);
|
||||
ASN_SEQUENCE_ADD(&HandoverRequired->protocolIEs, ie);
|
||||
|
||||
ie->id = NGAP_ProtocolIE_ID_id_Cause;
|
||||
ie->criticality = NGAP_Criticality_ignore;
|
||||
ie->value.present = NGAP_HandoverRequiredIEs__value_PR_Cause;
|
||||
|
||||
Cause = &ie->value.choice.Cause;
|
||||
|
||||
Cause->present = group;
|
||||
Cause->choice.radioNetwork = cause;
|
||||
|
||||
ie = CALLOC(1, sizeof(NGAP_HandoverRequiredIEs_t));
|
||||
ogs_assert(ie);
|
||||
ASN_SEQUENCE_ADD(&HandoverRequired->protocolIEs, ie);
|
||||
|
||||
ie->id = NGAP_ProtocolIE_ID_id_TargetID;
|
||||
ie->criticality = NGAP_Criticality_reject;
|
||||
ie->value.present = NGAP_HandoverRequiredIEs__value_PR_TargetID;
|
||||
|
||||
TargetID = &ie->value.choice.TargetID;
|
||||
|
||||
TargetID->present = NGAP_TargetID_PR_targetRANNodeID;
|
||||
TargetID->choice.targetRANNodeID = targetRANNodeID =
|
||||
CALLOC(1, sizeof(*targetRANNodeID));
|
||||
ogs_assert(targetRANNodeID);
|
||||
|
||||
globalRANNodeID = &targetRANNodeID->globalRANNodeID;
|
||||
globalRANNodeID->present = NGAP_GlobalRANNodeID_PR_globalGNB_ID;
|
||||
globalRANNodeID->choice.globalGNB_ID = globalGNB_ID =
|
||||
CALLOC(1, sizeof(*globalGNB_ID));
|
||||
ogs_assert(globalGNB_ID);
|
||||
|
||||
plmn_id = &test_self()->plmn_support[0].plmn_id;
|
||||
ogs_asn_buffer_to_OCTET_STRING(
|
||||
plmn_id, OGS_PLMN_ID_LEN, &globalGNB_ID->pLMNIdentity);
|
||||
|
||||
ogs_ngap_uint32_to_GNB_ID(gnb_id, bitsize, &globalGNB_ID->gNB_ID);
|
||||
|
||||
selectedTAI = &targetRANNodeID->selectedTAI;
|
||||
ogs_ngap_5gs_tai_to_ASN(&test_ue->nr_tai, selectedTAI);
|
||||
|
||||
ogs_list_for_each(&test_ue->sess_list, sess) {
|
||||
if (!PDUSessionList) {
|
||||
ie = CALLOC(1, sizeof(NGAP_HandoverRequiredIEs_t));
|
||||
ogs_assert(ie);
|
||||
ASN_SEQUENCE_ADD(&HandoverRequired->protocolIEs, ie);
|
||||
|
||||
ie->id = NGAP_ProtocolIE_ID_id_PDUSessionResourceListHORqd;
|
||||
ie->criticality = NGAP_Criticality_reject;
|
||||
ie->value.present = NGAP_HandoverRequiredIEs__value_PR_PDUSessionResourceListHORqd;
|
||||
|
||||
PDUSessionList = &ie->value.choice.PDUSessionResourceListHORqd;
|
||||
}
|
||||
|
||||
PDUSessionItem = CALLOC(1, sizeof(*PDUSessionItem));
|
||||
ogs_assert(PDUSessionItem);
|
||||
ASN_SEQUENCE_ADD(&PDUSessionList->list, PDUSessionItem);
|
||||
|
||||
PDUSessionItem->pDUSessionID = sess->psi;
|
||||
|
||||
n2smbuf = testngap_build_handover_required_transfer(sess, direct);
|
||||
ogs_assert(n2smbuf);
|
||||
transfer = &PDUSessionItem->handoverRequiredTransfer;
|
||||
|
||||
transfer->size = n2smbuf->len;
|
||||
transfer->buf = CALLOC(transfer->size, sizeof(uint8_t));
|
||||
memcpy(transfer->buf, n2smbuf->data, transfer->size);
|
||||
ogs_pkbuf_free(n2smbuf);
|
||||
}
|
||||
|
||||
ie = CALLOC(1, sizeof(NGAP_HandoverRequiredIEs_t));
|
||||
ogs_assert(ie);
|
||||
ASN_SEQUENCE_ADD(&HandoverRequired->protocolIEs, ie);
|
||||
|
||||
ie->id = NGAP_ProtocolIE_ID_id_SourceToTarget_TransparentContainer;
|
||||
ie->criticality = NGAP_Criticality_reject;
|
||||
ie->value.present = NGAP_HandoverRequiredIEs__value_PR_SourceToTarget_TransparentContainer;
|
||||
|
||||
SourceToTarget_TransparentContainer =
|
||||
&ie->value.choice.SourceToTarget_TransparentContainer;
|
||||
|
||||
OGS_HEX(_container, strlen(_container), tmp),
|
||||
|
||||
SourceToTarget_TransparentContainer->size = 32;
|
||||
SourceToTarget_TransparentContainer->buf =
|
||||
CALLOC(SourceToTarget_TransparentContainer->size, sizeof(uint8_t));
|
||||
memcpy(SourceToTarget_TransparentContainer->buf,
|
||||
tmp, SourceToTarget_TransparentContainer->size);
|
||||
|
||||
return ogs_ngap_encode(&pdu);
|
||||
}
|
||||
|
||||
ogs_pkbuf_t *testngap_build_handover_request_ack(test_ue_t *test_ue)
|
||||
{
|
||||
int rv;
|
||||
test_sess_t *sess = NULL;
|
||||
|
||||
NGAP_NGAP_PDU_t pdu;
|
||||
NGAP_SuccessfulOutcome_t *successfulOutcome = NULL;
|
||||
NGAP_HandoverRequestAcknowledge_t *HandoverRequestAcknowledge = NULL;
|
||||
|
||||
NGAP_HandoverRequestAcknowledgeIEs_t *ie = NULL;
|
||||
NGAP_AMF_UE_NGAP_ID_t *AMF_UE_NGAP_ID = NULL;
|
||||
NGAP_RAN_UE_NGAP_ID_t *RAN_UE_NGAP_ID = NULL;
|
||||
NGAP_PDUSessionResourceAdmittedList_t *PDUSessionList = NULL;
|
||||
NGAP_PDUSessionResourceAdmittedItem_t *PDUSessionItem = NULL;
|
||||
NGAP_TargetToSource_TransparentContainer_t
|
||||
*TargetToSource_TransparentContainer = NULL;
|
||||
|
||||
uint8_t tmp[OGS_MAX_SDU_LEN];
|
||||
char *_container =
|
||||
"00010000";
|
||||
|
||||
memset(&pdu, 0, sizeof (NGAP_NGAP_PDU_t));
|
||||
pdu.present = NGAP_NGAP_PDU_PR_successfulOutcome;
|
||||
pdu.choice.successfulOutcome = CALLOC(1, sizeof(NGAP_SuccessfulOutcome_t));
|
||||
|
||||
successfulOutcome = pdu.choice.successfulOutcome;
|
||||
successfulOutcome->procedureCode =
|
||||
NGAP_ProcedureCode_id_HandoverResourceAllocation;
|
||||
successfulOutcome->criticality = NGAP_Criticality_reject;
|
||||
successfulOutcome->value.present =
|
||||
NGAP_SuccessfulOutcome__value_PR_HandoverRequestAcknowledge;
|
||||
|
||||
HandoverRequestAcknowledge =
|
||||
&successfulOutcome->value.choice.HandoverRequestAcknowledge;
|
||||
|
||||
ie = CALLOC(1, sizeof(NGAP_HandoverRequestAcknowledgeIEs_t));
|
||||
ogs_assert(ie);
|
||||
ASN_SEQUENCE_ADD(&HandoverRequestAcknowledge->protocolIEs, ie);
|
||||
|
||||
ie->id = NGAP_ProtocolIE_ID_id_AMF_UE_NGAP_ID;
|
||||
ie->criticality = NGAP_Criticality_ignore;
|
||||
ie->value.present =
|
||||
NGAP_HandoverRequestAcknowledgeIEs__value_PR_AMF_UE_NGAP_ID;
|
||||
|
||||
AMF_UE_NGAP_ID = &ie->value.choice.AMF_UE_NGAP_ID;
|
||||
|
||||
ie = CALLOC(1, sizeof(NGAP_HandoverRequestAcknowledgeIEs_t));
|
||||
ogs_assert(ie);
|
||||
ASN_SEQUENCE_ADD(&HandoverRequestAcknowledge->protocolIEs, ie);
|
||||
|
||||
ie->id = NGAP_ProtocolIE_ID_id_RAN_UE_NGAP_ID;
|
||||
ie->criticality = NGAP_Criticality_ignore;
|
||||
ie->value.present =
|
||||
NGAP_HandoverRequestAcknowledgeIEs__value_PR_RAN_UE_NGAP_ID;
|
||||
|
||||
RAN_UE_NGAP_ID = &ie->value.choice.RAN_UE_NGAP_ID;
|
||||
|
||||
asn_uint642INTEGER(AMF_UE_NGAP_ID, test_ue->amf_ue_ngap_id);
|
||||
|
||||
test_ue->ran_ue_ngap_id++;
|
||||
*RAN_UE_NGAP_ID = test_ue->ran_ue_ngap_id;
|
||||
|
||||
ogs_list_for_each(&test_ue->sess_list, sess) {
|
||||
OCTET_STRING_t *transfer = NULL;
|
||||
ogs_pkbuf_t *n2smbuf = NULL;
|
||||
|
||||
if (!PDUSessionList) {
|
||||
ie = CALLOC(1, sizeof(NGAP_HandoverRequestAcknowledgeIEs_t));
|
||||
ogs_assert(ie);
|
||||
ASN_SEQUENCE_ADD(&HandoverRequestAcknowledge->protocolIEs, ie);
|
||||
|
||||
ie->id = NGAP_ProtocolIE_ID_id_PDUSessionResourceAdmittedList;
|
||||
ie->criticality = NGAP_Criticality_ignore;
|
||||
ie->value.present = NGAP_HandoverRequestAcknowledgeIEs__value_PR_PDUSessionResourceAdmittedList;
|
||||
|
||||
PDUSessionList = &ie->value.choice.PDUSessionResourceAdmittedList;
|
||||
}
|
||||
|
||||
PDUSessionItem = CALLOC(1,
|
||||
sizeof(struct NGAP_PDUSessionResourceAdmittedItem));
|
||||
ogs_assert(PDUSessionItem);
|
||||
ASN_SEQUENCE_ADD(&PDUSessionList->list, PDUSessionItem);
|
||||
|
||||
PDUSessionItem->pDUSessionID = sess->psi;
|
||||
|
||||
n2smbuf = testngap_build_handover_request_ack_transfer(sess);
|
||||
ogs_assert(n2smbuf);
|
||||
transfer = &PDUSessionItem->handoverRequestAcknowledgeTransfer;
|
||||
|
||||
transfer->size = n2smbuf->len;
|
||||
transfer->buf = CALLOC(transfer->size, sizeof(uint8_t));
|
||||
memcpy(transfer->buf, n2smbuf->data, transfer->size);
|
||||
ogs_pkbuf_free(n2smbuf);
|
||||
}
|
||||
|
||||
ie = CALLOC(1, sizeof(NGAP_HandoverRequestAcknowledgeIEs_t));
|
||||
ogs_assert(ie);
|
||||
ASN_SEQUENCE_ADD(&HandoverRequestAcknowledge->protocolIEs, ie);
|
||||
|
||||
ie->id = NGAP_ProtocolIE_ID_id_TargetToSource_TransparentContainer;
|
||||
ie->criticality = NGAP_Criticality_reject;
|
||||
ie->value.present = NGAP_HandoverRequestAcknowledgeIEs__value_PR_TargetToSource_TransparentContainer;
|
||||
|
||||
TargetToSource_TransparentContainer =
|
||||
&ie->value.choice.TargetToSource_TransparentContainer;
|
||||
|
||||
OGS_HEX(_container, strlen(_container), tmp),
|
||||
|
||||
TargetToSource_TransparentContainer->size = 4;
|
||||
TargetToSource_TransparentContainer->buf =
|
||||
CALLOC(TargetToSource_TransparentContainer->size, sizeof(uint8_t));
|
||||
memcpy(TargetToSource_TransparentContainer->buf,
|
||||
tmp, TargetToSource_TransparentContainer->size);
|
||||
|
||||
return ogs_ngap_encode(&pdu);
|
||||
}
|
||||
|
||||
ogs_pkbuf_t *testngap_build_uplink_ran_status_transfer(test_ue_t *test_ue)
|
||||
{
|
||||
test_sess_t *sess = NULL;
|
||||
|
||||
NGAP_NGAP_PDU_t pdu;
|
||||
NGAP_InitiatingMessage_t *initiatingMessage = NULL;
|
||||
NGAP_UplinkRANStatusTransfer_t *UplinkRANStatusTransfer = NULL;
|
||||
|
||||
NGAP_UplinkRANStatusTransferIEs_t *ie = NULL;
|
||||
NGAP_AMF_UE_NGAP_ID_t *AMF_UE_NGAP_ID = NULL;
|
||||
NGAP_RAN_UE_NGAP_ID_t *RAN_UE_NGAP_ID = NULL;
|
||||
NGAP_RANStatusTransfer_TransparentContainer_t
|
||||
*RANStatusTransfer_TransparentContainer = NULL;
|
||||
NGAP_DRBsSubjectToStatusTransferList_t *StatusTransferList = NULL;
|
||||
|
||||
ogs_assert(test_ue);
|
||||
|
||||
memset(&pdu, 0, sizeof (NGAP_NGAP_PDU_t));
|
||||
pdu.present = NGAP_NGAP_PDU_PR_initiatingMessage;
|
||||
pdu.choice.initiatingMessage = CALLOC(1, sizeof(NGAP_InitiatingMessage_t));
|
||||
|
||||
initiatingMessage = pdu.choice.initiatingMessage;
|
||||
initiatingMessage->procedureCode =
|
||||
NGAP_ProcedureCode_id_UplinkRANStatusTransfer;
|
||||
initiatingMessage->criticality = NGAP_Criticality_ignore;
|
||||
initiatingMessage->value.present =
|
||||
NGAP_InitiatingMessage__value_PR_UplinkRANStatusTransfer;
|
||||
|
||||
UplinkRANStatusTransfer = &initiatingMessage->value.choice.UplinkRANStatusTransfer;
|
||||
|
||||
ie = CALLOC(1, sizeof(NGAP_UplinkRANStatusTransferIEs_t));
|
||||
ogs_assert(ie);
|
||||
ASN_SEQUENCE_ADD(&UplinkRANStatusTransfer->protocolIEs, ie);
|
||||
|
||||
ie->id = NGAP_ProtocolIE_ID_id_AMF_UE_NGAP_ID;
|
||||
ie->criticality = NGAP_Criticality_reject;
|
||||
ie->value.present =
|
||||
NGAP_UplinkRANStatusTransferIEs__value_PR_AMF_UE_NGAP_ID;
|
||||
|
||||
AMF_UE_NGAP_ID = &ie->value.choice.AMF_UE_NGAP_ID;
|
||||
|
||||
ie = CALLOC(1, sizeof(NGAP_UplinkRANStatusTransferIEs_t));
|
||||
ogs_assert(ie);
|
||||
ASN_SEQUENCE_ADD(&UplinkRANStatusTransfer->protocolIEs, ie);
|
||||
|
||||
ie->id = NGAP_ProtocolIE_ID_id_RAN_UE_NGAP_ID;
|
||||
ie->criticality = NGAP_Criticality_reject;
|
||||
ie->value.present =
|
||||
NGAP_UplinkRANStatusTransferIEs__value_PR_RAN_UE_NGAP_ID;
|
||||
|
||||
RAN_UE_NGAP_ID = &ie->value.choice.RAN_UE_NGAP_ID;
|
||||
|
||||
asn_uint642INTEGER(AMF_UE_NGAP_ID, test_ue->amf_ue_ngap_id);
|
||||
*RAN_UE_NGAP_ID = test_ue->ran_ue_ngap_id;
|
||||
|
||||
ie = CALLOC(1, sizeof(NGAP_UplinkRANStatusTransferIEs_t));
|
||||
ogs_assert(ie);
|
||||
ASN_SEQUENCE_ADD(&UplinkRANStatusTransfer->protocolIEs, ie);
|
||||
|
||||
ie->id = NGAP_ProtocolIE_ID_id_RANStatusTransfer_TransparentContainer;
|
||||
ie->criticality = NGAP_Criticality_reject;
|
||||
ie->value.present = NGAP_UplinkRANStatusTransferIEs__value_PR_RANStatusTransfer_TransparentContainer;
|
||||
|
||||
RANStatusTransfer_TransparentContainer =
|
||||
&ie->value.choice.RANStatusTransfer_TransparentContainer;
|
||||
|
||||
StatusTransferList = &RANStatusTransfer_TransparentContainer->dRBsSubjectToStatusTransferList;
|
||||
|
||||
ogs_list_for_each(&test_ue->sess_list, sess) {
|
||||
NGAP_DRBsSubjectToStatusTransferItem_t *StatusTransferItem = NULL;
|
||||
NGAP_DRB_ID_t *dRB_ID = NULL;
|
||||
NGAP_DRBStatusUL_t *dRBStatusUL = NULL;
|
||||
NGAP_DRBStatusUL12_t *dRBStatusUL12 = NULL;
|
||||
NGAP_COUNTValueForPDCP_SN12_t *uL_COUNTValue = NULL;
|
||||
NGAP_DRBStatusDL_t *dRBStatusDL = NULL;
|
||||
NGAP_DRBStatusDL18_t *dRBStatusDL18 = NULL;
|
||||
NGAP_COUNTValueForPDCP_SN18_t *dL_COUNTValue = NULL;
|
||||
|
||||
StatusTransferItem = CALLOC(1, sizeof(*StatusTransferItem));
|
||||
ogs_assert(StatusTransferItem);
|
||||
ASN_SEQUENCE_ADD(&StatusTransferList->list, StatusTransferItem);
|
||||
|
||||
dRB_ID = &StatusTransferItem->dRB_ID;
|
||||
|
||||
*dRB_ID = sess->psi;
|
||||
|
||||
dRBStatusUL = &StatusTransferItem->dRBStatusUL;
|
||||
dRBStatusUL->present = NGAP_DRBStatusUL_PR_dRBStatusUL12;
|
||||
dRBStatusUL->choice.dRBStatusUL12 = dRBStatusUL12 =
|
||||
CALLOC(1, sizeof(*dRBStatusUL12));
|
||||
uL_COUNTValue = &dRBStatusUL12->uL_COUNTValue;
|
||||
uL_COUNTValue->pDCP_SN12 = 1;
|
||||
uL_COUNTValue->hFN_PDCP_SN12 = 2;
|
||||
|
||||
dRBStatusDL = &StatusTransferItem->dRBStatusDL;
|
||||
dRBStatusDL->present = NGAP_DRBStatusDL_PR_dRBStatusDL18;
|
||||
dRBStatusDL->choice.dRBStatusDL18 = dRBStatusDL18 =
|
||||
CALLOC(1, sizeof(*dRBStatusDL18));
|
||||
dL_COUNTValue = &dRBStatusDL18->dL_COUNTValue;
|
||||
dL_COUNTValue->pDCP_SN18 = 3;
|
||||
dL_COUNTValue->hFN_PDCP_SN18 = 4;
|
||||
}
|
||||
|
||||
return ogs_ngap_encode(&pdu);
|
||||
}
|
||||
|
||||
ogs_pkbuf_t *testngap_build_handover_notify(test_ue_t *test_ue)
|
||||
{
|
||||
NGAP_NGAP_PDU_t pdu;
|
||||
NGAP_InitiatingMessage_t *initiatingMessage = NULL;
|
||||
NGAP_HandoverNotify_t *HandoverNotify = NULL;
|
||||
|
||||
NGAP_HandoverNotifyIEs_t *ie = NULL;
|
||||
NGAP_AMF_UE_NGAP_ID_t *AMF_UE_NGAP_ID = NULL;
|
||||
NGAP_RAN_UE_NGAP_ID_t *RAN_UE_NGAP_ID = NULL;
|
||||
NGAP_UserLocationInformation_t *UserLocationInformation = NULL;
|
||||
NGAP_UserLocationInformationNR_t *userLocationInformationNR = NULL;
|
||||
NGAP_NR_CGI_t *nR_CGI = NULL;
|
||||
NGAP_TAI_t *tAI = NULL;
|
||||
|
||||
ogs_assert(test_ue);
|
||||
|
||||
memset(&pdu, 0, sizeof (NGAP_NGAP_PDU_t));
|
||||
pdu.present = NGAP_NGAP_PDU_PR_initiatingMessage;
|
||||
pdu.choice.initiatingMessage = CALLOC(1, sizeof(NGAP_InitiatingMessage_t));
|
||||
|
||||
initiatingMessage = pdu.choice.initiatingMessage;
|
||||
initiatingMessage->procedureCode =
|
||||
NGAP_ProcedureCode_id_HandoverNotification;
|
||||
initiatingMessage->criticality = NGAP_Criticality_ignore;
|
||||
initiatingMessage->value.present =
|
||||
NGAP_InitiatingMessage__value_PR_HandoverNotify;
|
||||
|
||||
HandoverNotify = &initiatingMessage->value.choice.HandoverNotify;
|
||||
|
||||
ie = CALLOC(1, sizeof(NGAP_HandoverNotifyIEs_t));
|
||||
ogs_assert(ie);
|
||||
ASN_SEQUENCE_ADD(&HandoverNotify->protocolIEs, ie);
|
||||
|
||||
ie->id = NGAP_ProtocolIE_ID_id_AMF_UE_NGAP_ID;
|
||||
ie->criticality = NGAP_Criticality_reject;
|
||||
ie->value.present = NGAP_HandoverNotifyIEs__value_PR_AMF_UE_NGAP_ID;
|
||||
|
||||
AMF_UE_NGAP_ID = &ie->value.choice.AMF_UE_NGAP_ID;
|
||||
|
||||
ie = CALLOC(1, sizeof(NGAP_HandoverNotifyIEs_t));
|
||||
ogs_assert(ie);
|
||||
ASN_SEQUENCE_ADD(&HandoverNotify->protocolIEs, ie);
|
||||
|
||||
ie->id = NGAP_ProtocolIE_ID_id_RAN_UE_NGAP_ID;
|
||||
ie->criticality = NGAP_Criticality_reject;
|
||||
ie->value.present = NGAP_HandoverNotifyIEs__value_PR_RAN_UE_NGAP_ID;
|
||||
|
||||
RAN_UE_NGAP_ID = &ie->value.choice.RAN_UE_NGAP_ID;
|
||||
|
||||
asn_uint642INTEGER(AMF_UE_NGAP_ID, test_ue->amf_ue_ngap_id);
|
||||
*RAN_UE_NGAP_ID = test_ue->ran_ue_ngap_id;
|
||||
|
||||
ie = CALLOC(1, sizeof(NGAP_HandoverNotifyIEs_t));
|
||||
ogs_assert(ie);
|
||||
ASN_SEQUENCE_ADD(&HandoverNotify->protocolIEs, ie);
|
||||
|
||||
ie->id = NGAP_ProtocolIE_ID_id_UserLocationInformation;
|
||||
ie->criticality = NGAP_Criticality_ignore;
|
||||
ie->value.present =
|
||||
NGAP_HandoverNotifyIEs__value_PR_UserLocationInformation;
|
||||
|
||||
UserLocationInformation = &ie->value.choice.UserLocationInformation;
|
||||
|
||||
userLocationInformationNR =
|
||||
CALLOC(1, sizeof(NGAP_UserLocationInformationNR_t));
|
||||
ogs_assert(userLocationInformationNR);
|
||||
|
||||
nR_CGI = &userLocationInformationNR->nR_CGI;
|
||||
ogs_ngap_nr_cgi_to_ASN(&test_ue->nr_cgi, nR_CGI);
|
||||
|
||||
tAI = &userLocationInformationNR->tAI;
|
||||
ogs_ngap_5gs_tai_to_ASN(&test_ue->nr_tai, tAI);
|
||||
|
||||
UserLocationInformation->present =
|
||||
NGAP_UserLocationInformation_PR_userLocationInformationNR;
|
||||
UserLocationInformation->choice.userLocationInformationNR =
|
||||
userLocationInformationNR;
|
||||
|
||||
return ogs_ngap_encode(&pdu);
|
||||
}
|
||||
|
||||
ogs_pkbuf_t *testngap_build_handover_failure(test_ue_t *test_ue,
|
||||
NGAP_Cause_PR group, long cause)
|
||||
{
|
||||
int rv;
|
||||
|
||||
NGAP_NGAP_PDU_t pdu;
|
||||
NGAP_UnsuccessfulOutcome_t *unsuccessfulOutcome = NULL;
|
||||
NGAP_HandoverFailure_t *HandoverFailure = NULL;
|
||||
|
||||
NGAP_HandoverFailureIEs_t *ie = NULL;
|
||||
NGAP_AMF_UE_NGAP_ID_t *AMF_UE_NGAP_ID = NULL;
|
||||
NGAP_Cause_t *Cause = NULL;
|
||||
|
||||
memset(&pdu, 0, sizeof (NGAP_NGAP_PDU_t));
|
||||
pdu.present = NGAP_NGAP_PDU_PR_unsuccessfulOutcome;
|
||||
pdu.choice.unsuccessfulOutcome =
|
||||
CALLOC(1, sizeof(NGAP_UnsuccessfulOutcome_t));
|
||||
|
||||
unsuccessfulOutcome = pdu.choice.unsuccessfulOutcome;
|
||||
unsuccessfulOutcome->procedureCode =
|
||||
NGAP_ProcedureCode_id_HandoverResourceAllocation;
|
||||
unsuccessfulOutcome->criticality = NGAP_Criticality_reject;
|
||||
unsuccessfulOutcome->value.present =
|
||||
NGAP_UnsuccessfulOutcome__value_PR_HandoverFailure;
|
||||
|
||||
HandoverFailure = &unsuccessfulOutcome->value.choice.HandoverFailure;
|
||||
|
||||
ie = CALLOC(1, sizeof(NGAP_HandoverFailureIEs_t));
|
||||
ogs_assert(ie);
|
||||
ASN_SEQUENCE_ADD(&HandoverFailure->protocolIEs, ie);
|
||||
|
||||
ie->id = NGAP_ProtocolIE_ID_id_AMF_UE_NGAP_ID;
|
||||
ie->criticality = NGAP_Criticality_ignore;
|
||||
ie->value.present = NGAP_HandoverFailureIEs__value_PR_AMF_UE_NGAP_ID;
|
||||
|
||||
AMF_UE_NGAP_ID = &ie->value.choice.AMF_UE_NGAP_ID;
|
||||
|
||||
ie = CALLOC(1, sizeof(NGAP_HandoverFailureIEs_t));
|
||||
ASN_SEQUENCE_ADD(&HandoverFailure->protocolIEs, ie);
|
||||
|
||||
ie->id = NGAP_ProtocolIE_ID_id_Cause;
|
||||
ie->criticality = NGAP_Criticality_ignore;
|
||||
ie->value.present = NGAP_HandoverFailureIEs__value_PR_Cause;
|
||||
|
||||
Cause = &ie->value.choice.Cause;
|
||||
|
||||
asn_uint642INTEGER(AMF_UE_NGAP_ID, test_ue->amf_ue_ngap_id);
|
||||
|
||||
Cause->present = group;
|
||||
Cause->choice.radioNetwork = cause;
|
||||
|
||||
return ogs_ngap_encode(&pdu);
|
||||
}
|
||||
|
||||
ogs_pkbuf_t *testngap_build_handover_cancel(test_ue_t *test_ue,
|
||||
NGAP_Cause_PR group, long cause)
|
||||
{
|
||||
NGAP_NGAP_PDU_t pdu;
|
||||
NGAP_InitiatingMessage_t *initiatingMessage = NULL;
|
||||
NGAP_HandoverCancel_t *HandoverCancel = NULL;
|
||||
|
||||
NGAP_HandoverCancelIEs_t *ie = NULL;
|
||||
NGAP_AMF_UE_NGAP_ID_t *AMF_UE_NGAP_ID = NULL;
|
||||
NGAP_RAN_UE_NGAP_ID_t *RAN_UE_NGAP_ID = NULL;
|
||||
NGAP_Cause_t *Cause = NULL;
|
||||
|
||||
ogs_assert(test_ue);
|
||||
|
||||
memset(&pdu, 0, sizeof (NGAP_NGAP_PDU_t));
|
||||
pdu.present = NGAP_NGAP_PDU_PR_initiatingMessage;
|
||||
pdu.choice.initiatingMessage = CALLOC(1, sizeof(NGAP_InitiatingMessage_t));
|
||||
|
||||
initiatingMessage = pdu.choice.initiatingMessage;
|
||||
initiatingMessage->procedureCode = NGAP_ProcedureCode_id_HandoverCancel;
|
||||
initiatingMessage->criticality = NGAP_Criticality_reject;
|
||||
initiatingMessage->value.present =
|
||||
NGAP_InitiatingMessage__value_PR_HandoverCancel;
|
||||
|
||||
HandoverCancel = &initiatingMessage->value.choice.HandoverCancel;
|
||||
|
||||
ie = CALLOC(1, sizeof(NGAP_HandoverCancelIEs_t));
|
||||
ogs_assert(ie);
|
||||
ASN_SEQUENCE_ADD(&HandoverCancel->protocolIEs, ie);
|
||||
|
||||
ie->id = NGAP_ProtocolIE_ID_id_AMF_UE_NGAP_ID;
|
||||
ie->criticality = NGAP_Criticality_reject;
|
||||
ie->value.present = NGAP_HandoverCancelIEs__value_PR_AMF_UE_NGAP_ID;
|
||||
|
||||
AMF_UE_NGAP_ID = &ie->value.choice.AMF_UE_NGAP_ID;
|
||||
|
||||
ie = CALLOC(1, sizeof(NGAP_HandoverCancelIEs_t));
|
||||
ogs_assert(ie);
|
||||
ASN_SEQUENCE_ADD(&HandoverCancel->protocolIEs, ie);
|
||||
|
||||
ie->id = NGAP_ProtocolIE_ID_id_RAN_UE_NGAP_ID;
|
||||
ie->criticality = NGAP_Criticality_reject;
|
||||
ie->value.present = NGAP_HandoverCancelIEs__value_PR_RAN_UE_NGAP_ID;
|
||||
|
||||
RAN_UE_NGAP_ID = &ie->value.choice.RAN_UE_NGAP_ID;
|
||||
|
||||
asn_uint642INTEGER(AMF_UE_NGAP_ID, test_ue->amf_ue_ngap_id);
|
||||
*RAN_UE_NGAP_ID = test_ue->ran_ue_ngap_id;
|
||||
|
||||
ie = CALLOC(1, sizeof(NGAP_HandoverCancelIEs_t));
|
||||
ogs_assert(ie);
|
||||
ASN_SEQUENCE_ADD(&HandoverCancel->protocolIEs, ie);
|
||||
|
||||
ie->id = NGAP_ProtocolIE_ID_id_Cause;
|
||||
ie->criticality = NGAP_Criticality_ignore;
|
||||
ie->value.present = NGAP_HandoverCancelIEs__value_PR_Cause;
|
||||
|
||||
Cause = &ie->value.choice.Cause;
|
||||
|
||||
Cause->present = group;
|
||||
Cause->choice.radioNetwork = cause;
|
||||
|
||||
return ogs_ngap_encode(&pdu);
|
||||
}
|
||||
|
||||
static ogs_pkbuf_t *testngap_build_pdu_session_resource_setup_response_trasfer(
|
||||
test_sess_t *sess)
|
||||
{
|
||||
|
@ -1340,6 +2043,7 @@ static ogs_pkbuf_t *testngap_build_pdu_session_resource_setup_response_trasfer(
|
|||
memset(&message, 0, sizeof(message));
|
||||
|
||||
dLQosFlowPerTNLInformation = &message.dLQosFlowPerTNLInformation;
|
||||
|
||||
uPTransportLayerInformation =
|
||||
&dLQosFlowPerTNLInformation->uPTransportLayerInformation;
|
||||
|
||||
|
@ -1450,6 +2154,93 @@ static ogs_pkbuf_t *testngap_build_path_switch_request_trasfer(
|
|||
qosFlowAcceptedItem->qosFlowIdentifier = qos_flow->qfi;
|
||||
}
|
||||
|
||||
return ogs_asn_encode(
|
||||
&asn_DEF_NGAP_PathSwitchRequestTransfer, &message);
|
||||
return ogs_asn_encode(&asn_DEF_NGAP_PathSwitchRequestTransfer, &message);
|
||||
}
|
||||
|
||||
static ogs_pkbuf_t *testngap_build_handover_required_transfer(
|
||||
test_sess_t *sess, bool direct)
|
||||
{
|
||||
int rv;
|
||||
|
||||
test_bearer_t *qos_flow = NULL;
|
||||
|
||||
ogs_gtp_f_teid_t f_teid;
|
||||
ogs_ip_t ip;
|
||||
int len;
|
||||
|
||||
ogs_assert(sess);
|
||||
|
||||
NGAP_HandoverRequiredTransfer_t message;
|
||||
|
||||
NGAP_DirectForwardingPathAvailability_t
|
||||
*directForwardingPathAvailability = NULL;
|
||||
|
||||
memset(&message, 0, sizeof(message));
|
||||
|
||||
if (direct == true) {
|
||||
message.directForwardingPathAvailability =
|
||||
directForwardingPathAvailability =
|
||||
CALLOC(1, sizeof(*directForwardingPathAvailability));
|
||||
|
||||
*directForwardingPathAvailability =
|
||||
NGAP_DirectForwardingPathAvailability_direct_path_available;
|
||||
}
|
||||
|
||||
return ogs_asn_encode(&asn_DEF_NGAP_HandoverRequiredTransfer, &message);
|
||||
}
|
||||
|
||||
static ogs_pkbuf_t *testngap_build_handover_request_ack_transfer(
|
||||
test_sess_t *sess)
|
||||
{
|
||||
int rv;
|
||||
test_bearer_t *qos_flow = NULL;
|
||||
|
||||
ogs_gtp_f_teid_t f_teid;
|
||||
ogs_ip_t ip;
|
||||
int len;
|
||||
|
||||
ogs_assert(sess);
|
||||
|
||||
NGAP_HandoverRequestAcknowledgeTransfer_t message;
|
||||
|
||||
NGAP_UPTransportLayerInformation_t *dL_NGU_UP_TNLInformation = NULL;
|
||||
NGAP_QosFlowListWithDataForwarding_t *qosFlowSetupResponseList = NULL;
|
||||
NGAP_QosFlowItemWithDataForwarding_t *qosFlowSetupResponseItem = NULL;
|
||||
NGAP_GTPTunnel_t *gTPTunnel = NULL;
|
||||
|
||||
memset(&message, 0, sizeof(message));
|
||||
|
||||
dL_NGU_UP_TNLInformation = &message.dL_NGU_UP_TNLInformation;
|
||||
|
||||
dL_NGU_UP_TNLInformation->present =
|
||||
NGAP_UPTransportLayerInformation_PR_gTPTunnel;
|
||||
dL_NGU_UP_TNLInformation->choice.gTPTunnel = gTPTunnel =
|
||||
CALLOC(1, sizeof(struct NGAP_GTPTunnel));
|
||||
ogs_assert(gTPTunnel);
|
||||
|
||||
ogs_assert(sess->gnb_n3_addr || sess->gnb_n3_addr6);
|
||||
rv = ogs_gtp_sockaddr_to_f_teid(
|
||||
sess->gnb_n3_addr, sess->gnb_n3_addr6, &f_teid, &len);
|
||||
ogs_assert(rv == OGS_OK);
|
||||
|
||||
rv = ogs_gtp_f_teid_to_ip(&f_teid, &ip);
|
||||
ogs_assert(rv == OGS_OK);
|
||||
|
||||
ogs_asn_ip_to_BIT_STRING(&ip, &gTPTunnel->transportLayerAddress);
|
||||
ogs_asn_uint32_to_OCTET_STRING(sess->gnb_n3_teid, &gTPTunnel->gTP_TEID);
|
||||
|
||||
qosFlowSetupResponseList = &message.qosFlowSetupResponseList;
|
||||
|
||||
ogs_list_for_each(&sess->bearer_list, qos_flow) {
|
||||
qosFlowSetupResponseItem =
|
||||
CALLOC(1, sizeof(struct NGAP_QosFlowItemWithDataForwarding));
|
||||
ogs_assert(qosFlowSetupResponseItem);
|
||||
ASN_SEQUENCE_ADD(&qosFlowSetupResponseList->list,
|
||||
qosFlowSetupResponseItem);
|
||||
|
||||
qosFlowSetupResponseItem->qosFlowIdentifier = qos_flow->qfi;
|
||||
}
|
||||
|
||||
return ogs_asn_encode(
|
||||
&asn_DEF_NGAP_HandoverRequestAcknowledgeTransfer, &message);
|
||||
}
|
||||
|
|
|
@ -52,8 +52,25 @@ ogs_pkbuf_t *testngap_build_pdu_session_resource_modify_response(
|
|||
ogs_pkbuf_t *testngap_build_pdu_session_resource_release_response(
|
||||
test_sess_t *sess);
|
||||
|
||||
ogs_pkbuf_t *testngap_build_uplink_ran_configuration_transfer(
|
||||
uint32_t source_gnb_id, uint8_t source_bitsize,
|
||||
uint32_t target_gnb_id, uint8_t target_bitsize);
|
||||
|
||||
ogs_pkbuf_t *testngap_build_path_switch_request(test_ue_t *test_ue);
|
||||
|
||||
ogs_pkbuf_t *testngap_build_handover_required(
|
||||
test_ue_t *test_ue, NGAP_HandoverType_t handover_type,
|
||||
uint32_t gnb_id, uint8_t bitsize,
|
||||
NGAP_Cause_PR group, long cause,
|
||||
bool direct);
|
||||
ogs_pkbuf_t *testngap_build_uplink_ran_status_transfer(test_ue_t *test_ue);
|
||||
ogs_pkbuf_t *testngap_build_handover_request_ack(test_ue_t *test_ue);
|
||||
ogs_pkbuf_t *testngap_build_handover_notify(test_ue_t *test_ue);
|
||||
ogs_pkbuf_t *testngap_build_handover_failure(test_ue_t *test_ue,
|
||||
NGAP_Cause_PR group, long cause);
|
||||
ogs_pkbuf_t *testngap_build_handover_cancel(test_ue_t *test_ue,
|
||||
NGAP_Cause_PR group, long cause);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -600,3 +600,42 @@ void testngap_handle_pdu_session_resource_release_command(
|
|||
if (NAS_PDU)
|
||||
testngap_send_to_nas(test_ue, NAS_PDU);
|
||||
}
|
||||
|
||||
void testngap_handle_handover_request(
|
||||
test_ue_t *test_ue, ogs_ngap_message_t *message)
|
||||
{
|
||||
int rv, i;
|
||||
char buf[OGS_ADDRSTRLEN];
|
||||
|
||||
NGAP_NGAP_PDU_t pdu;
|
||||
NGAP_InitiatingMessage_t *initiatingMessage = NULL;
|
||||
NGAP_HandoverRequest_t *HandoverRequest = NULL;
|
||||
|
||||
NGAP_HandoverRequestIEs_t *ie = NULL;
|
||||
NGAP_AMF_UE_NGAP_ID_t *AMF_UE_NGAP_ID = NULL;
|
||||
|
||||
ogs_assert(test_ue);
|
||||
ogs_assert(message);
|
||||
|
||||
initiatingMessage = message->choice.initiatingMessage;
|
||||
ogs_assert(initiatingMessage);
|
||||
HandoverRequest = &initiatingMessage->value.choice.HandoverRequest;
|
||||
ogs_assert(HandoverRequest);
|
||||
|
||||
for (i = 0; i < HandoverRequest->protocolIEs.list.count; i++) {
|
||||
ie = HandoverRequest->protocolIEs.list.array[i];
|
||||
switch (ie->id) {
|
||||
case NGAP_ProtocolIE_ID_id_AMF_UE_NGAP_ID:
|
||||
AMF_UE_NGAP_ID = &ie->value.choice.AMF_UE_NGAP_ID;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (AMF_UE_NGAP_ID) {
|
||||
uint64_t amf_ue_ngap_id;
|
||||
asn_INTEGER2ulong(AMF_UE_NGAP_ID, (unsigned long *)&amf_ue_ngap_id);
|
||||
test_ue->amf_ue_ngap_id = (uint64_t)amf_ue_ngap_id;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -33,6 +33,7 @@ void testngap_handle_initial_context_setup_request(
|
|||
test_ue_t *test_ue, ogs_ngap_message_t *message);
|
||||
void testngap_handle_ue_release_context_command(
|
||||
test_ue_t *test_ue, ogs_ngap_message_t *message);
|
||||
|
||||
void testngap_handle_pdu_session_resource_setup_request(
|
||||
test_ue_t *test_ue, ogs_ngap_message_t *message);
|
||||
void testngap_handle_pdu_session_resource_modify_request(
|
||||
|
@ -40,6 +41,9 @@ void testngap_handle_pdu_session_resource_modify_request(
|
|||
void testngap_handle_pdu_session_resource_release_command(
|
||||
test_ue_t *test_ue, ogs_ngap_message_t *message);
|
||||
|
||||
void testngap_handle_handover_request(
|
||||
test_ue_t *test_ue, ogs_ngap_message_t *message);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -65,6 +65,13 @@ void testngap_recv(test_ue_t *test_ue, ogs_pkbuf_t *pkbuf)
|
|||
case NGAP_ProcedureCode_id_PDUSessionResourceRelease:
|
||||
testngap_handle_pdu_session_resource_release_command(test_ue, pdu);
|
||||
break;
|
||||
case NGAP_ProcedureCode_id_DownlinkRANConfigurationTransfer:
|
||||
break;
|
||||
case NGAP_ProcedureCode_id_HandoverResourceAllocation:
|
||||
testngap_handle_handover_request(test_ue, pdu);
|
||||
break;
|
||||
case NGAP_ProcedureCode_id_DownlinkRANStatusTransfer:
|
||||
break;
|
||||
case NGAP_ProcedureCode_id_ErrorIndication:
|
||||
case NGAP_ProcedureCode_id_Paging:
|
||||
/* Nothing */
|
||||
|
@ -88,6 +95,10 @@ void testngap_recv(test_ue_t *test_ue, ogs_pkbuf_t *pkbuf)
|
|||
break;
|
||||
case NGAP_ProcedureCode_id_PathSwitchRequest:
|
||||
break;
|
||||
case NGAP_ProcedureCode_id_HandoverPreparation:
|
||||
break;
|
||||
case NGAP_ProcedureCode_id_HandoverCancel:
|
||||
break;
|
||||
case NGAP_ProcedureCode_id_NGReset:
|
||||
break;
|
||||
default:
|
||||
|
@ -106,6 +117,8 @@ void testngap_recv(test_ue_t *test_ue, ogs_pkbuf_t *pkbuf)
|
|||
switch (unsuccessfulOutcome->procedureCode) {
|
||||
case NGAP_ProcedureCode_id_NGSetup:
|
||||
break;
|
||||
case NGAP_ProcedureCode_id_HandoverPreparation:
|
||||
break;
|
||||
default:
|
||||
ogs_error("Not implemented(choice:%d, proc:%d)",
|
||||
pdu->present, (int)unsuccessfulOutcome->procedureCode);
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -22,6 +22,7 @@
|
|||
abts_suite *test_epc_x2(abts_suite *suite);
|
||||
abts_suite *test_epc_s1(abts_suite *suite);
|
||||
abts_suite *test_5gc_xn(abts_suite *suite);
|
||||
abts_suite *test_5gc_n2(abts_suite *suite);
|
||||
|
||||
const struct testlist {
|
||||
abts_suite *(*func)(abts_suite *suite);
|
||||
|
@ -29,6 +30,7 @@ const struct testlist {
|
|||
{test_epc_x2},
|
||||
{test_epc_s1},
|
||||
{test_5gc_xn},
|
||||
{test_5gc_n2},
|
||||
{NULL},
|
||||
};
|
||||
|
||||
|
|
|
@ -20,6 +20,7 @@ testapp_handover_sources = files('''
|
|||
epc-x2-test.c
|
||||
epc-s1-test.c
|
||||
5gc-xn-test.c
|
||||
5gc-n2-test.c
|
||||
'''.split())
|
||||
|
||||
testapp_handover_exe = executable('handover',
|
||||
|
|
Loading…
Reference in New Issue