feat: Indirect Data Forwarding in N2-Handover

This commit is contained in:
Sukchan Lee 2021-01-31 23:01:15 -05:00
parent 388e64213f
commit ff5236f3e0
44 changed files with 3020 additions and 393 deletions

View File

@ -304,4 +304,12 @@ pool:
# o Message Wait Duration (3000 ms)
# message:
# duration: 3000
#
# o Handover Wait Duration (Default : 300 ms)
# Time to wait for AMF to send UEContextReleaseCommand
# to the source gNB after receiving HandoverNotify
#
# o Handover Wait Duration (500ms)
# handover:
# duration: 500
time:

View File

@ -417,4 +417,12 @@ sctp:
# o Message Wait Duration (3000 ms)
# message:
# duration: 3000
#
# o Handover Wait Duration (Default : 300 ms)
# Time to wait for MME to send UEContextReleaseCommand
# to the source eNB after receiving HandoverNotify
#
# o Handover Wait Duration (500ms)
# handover:
# duration: 500
time:

View File

@ -353,4 +353,13 @@ pool:
# o Message Wait Duration (3000 ms)
# message:
# duration: 3000
#
# o Handover Wait Duration (Default : 300 ms)
# Time to wait for SMF to send
# PFCP Session Modification Request(Remove Indirect Tunnel) to the UPF
# after sending Nsmf_PDUSession_UpdateSMContext Response(hoState:COMPLETED)
#
# o Handover Wait Duration (500ms)
# handover:
# duration: 500
time:

View File

@ -203,6 +203,14 @@ static void app_context_prepare(void)
*/
self.time.message.duration = ogs_time_from_sec(10);
/*
* Handover Wait Duration : 300 ms (Default)
*
* Time to wait for AMF/MME to send UEContextReleaseCommand
* to the source gNB/eNB after receiving HandoverNotify
*/
self.time.handover.duration = ogs_time_from_msec(300);
regenerate_all_timer_duration();
}
@ -482,13 +490,31 @@ int ogs_app_context_parse_config(void)
if (!strcmp(msg_key, "duration")) {
const char *v = ogs_yaml_iter_value(&msg_iter);
if (v) {
self.time.message.duration =
self.time.message.duration =
ogs_time_from_msec(atoll(v));
regenerate_all_timer_duration();
}
} else
ogs_warn("unknown key `%s`", msg_key);
}
} else if (!strcmp(time_key, "handover")) {
ogs_yaml_iter_t msg_iter;
ogs_yaml_iter_recurse(&time_iter, &msg_iter);
while (ogs_yaml_iter_next(&msg_iter)) {
const char *msg_key =
ogs_yaml_iter_key(&msg_iter);
ogs_assert(msg_key);
if (!strcmp(msg_key, "duration")) {
const char *v = ogs_yaml_iter_value(&msg_iter);
if (v) {
self.time.handover.duration =
ogs_time_from_msec(atoll(v));
}
} else
ogs_warn("unknown key `%s`", msg_key);
}
} else
ogs_warn("unknown key `%s`", time_key);
}

View File

@ -146,6 +146,12 @@ typedef struct ogs_app_context_s {
ogs_time_t no_heartbeat_duration;
} pfcp;
} message;
struct {
ogs_time_t duration;
ogs_time_t complete_delay;
} handover;
} time;
} ogs_app_context_t;

View File

@ -567,7 +567,7 @@ static void response_timeout(void *data)
{
char buf[OGS_ADDRSTRLEN];
ogs_gtp_xact_t *xact = data;
ogs_assert(xact);
ogs_assert(xact->gnode);
@ -618,7 +618,7 @@ static void holding_timeout(void *data)
{
char buf[OGS_ADDRSTRLEN];
ogs_gtp_xact_t *xact = data;
ogs_assert(xact);
ogs_assert(xact->gnode);

View File

@ -99,6 +99,10 @@ typedef struct ogs_gtp_xact_s {
#define OGS_GTP_RELEASE_S1_CONTEXT_REMOVE_BY_RESET_ALL 3
#define OGS_GTP_RELEASE_S1_CONTEXT_REMOVE_BY_RESET_PARTIAL 4
int release_action;
#define OGS_GTP_DELETE_INDIRECT_HANDOVER_COMPLETE 1
#define OGS_GTP_DELETE_INDIRECT_HANDOVER_CANCEL 2
int delete_indirect_action;
} ogs_gtp_xact_t;
int ogs_gtp_xact_init(void);

View File

@ -487,6 +487,7 @@ ED5(uint8_t spare1:4;,
uint8_t ipv4:1;)
union {
#define OGS_PFCP_DEFAULT_CHOOSE_ID 5
#define OGS_PFCP_INDIRECT_DATA_FORWARDING_CHOOSE_ID 10
struct {
ED4(uint8_t choose_id;,
uint8_t spare2;,

View File

@ -41,6 +41,7 @@ static int ogs_pfcp_xact_delete(ogs_pfcp_xact_t *xact);
static void response_timeout(void *data);
static void holding_timeout(void *data);
static void delayed_commit_timeout(void *data);
int ogs_pfcp_xact_init(void)
{
@ -95,6 +96,10 @@ ogs_pfcp_xact_t *ogs_pfcp_xact_local_create(ogs_pfcp_node_t *node,
ogs_assert(xact->tm_holding);
xact->holding_rcount = ogs_app()->time.message.pfcp.n1_holding_rcount,
xact->tm_delayed_commit = ogs_timer_add(
ogs_app()->timer_mgr, delayed_commit_timeout, xact);
ogs_assert(xact->tm_delayed_commit);
ogs_list_add(xact->org == OGS_PFCP_LOCAL_ORIGINATOR ?
&xact->node->local_list : &xact->node->remote_list, xact);
@ -141,6 +146,10 @@ ogs_pfcp_xact_t *ogs_pfcp_xact_remote_create(
ogs_assert(xact->tm_holding);
xact->holding_rcount = ogs_app()->time.message.pfcp.n1_holding_rcount,
xact->tm_delayed_commit = ogs_timer_add(
ogs_app()->timer_mgr, delayed_commit_timeout, xact);
ogs_assert(xact->tm_delayed_commit);
ogs_list_add(xact->org == OGS_PFCP_LOCAL_ORIGINATOR ?
&xact->node->local_list : &xact->node->remote_list, xact);
@ -449,7 +458,6 @@ int ogs_pfcp_xact_update_rx(ogs_pfcp_xact_t *xact, uint8_t type)
return OGS_OK;
}
int ogs_pfcp_xact_commit(ogs_pfcp_xact_t *xact)
{
int rv;
@ -561,11 +569,20 @@ int ogs_pfcp_xact_commit(ogs_pfcp_xact_t *xact)
return OGS_OK;
}
void ogs_pfcp_xact_delayed_commit(ogs_pfcp_xact_t *xact, ogs_time_t duration)
{
ogs_assert(xact);
ogs_assert(duration);
ogs_assert(xact->tm_delayed_commit);
ogs_timer_start(xact->tm_delayed_commit, duration);
}
static void response_timeout(void *data)
{
char buf[OGS_ADDRSTRLEN];
ogs_pfcp_xact_t *xact = data;
ogs_assert(xact);
ogs_assert(xact->node);
@ -616,7 +633,7 @@ static void holding_timeout(void *data)
{
char buf[OGS_ADDRSTRLEN];
ogs_pfcp_xact_t *xact = data;
ogs_assert(xact);
ogs_assert(xact->node);
@ -644,6 +661,24 @@ static void holding_timeout(void *data)
}
}
static void delayed_commit_timeout(void *data)
{
char buf[OGS_ADDRSTRLEN];
ogs_pfcp_xact_t *xact = data;
ogs_assert(xact);
ogs_assert(xact->node);
ogs_debug("[%d] %s Delayed Send Timeout "
"for step %d type %d peer [%s]:%d",
xact->xid,
xact->org == OGS_PFCP_LOCAL_ORIGINATOR ? "LOCAL " : "REMOTE",
xact->step, xact->seq[xact->step-1].type,
OGS_ADDR(&xact->node->addr, buf),
OGS_PORT(&xact->node->addr));
ogs_pfcp_xact_commit(xact);
}
int ogs_pfcp_xact_receive(
ogs_pfcp_node_t *node, ogs_pfcp_header_t *h, ogs_pfcp_xact_t **xact)
@ -785,6 +820,8 @@ static int ogs_pfcp_xact_delete(ogs_pfcp_xact_t *xact)
ogs_timer_delete(xact->tm_response);
if (xact->tm_holding)
ogs_timer_delete(xact->tm_holding);
if (xact->tm_delayed_commit)
ogs_timer_delete(xact->tm_delayed_commit);
ogs_list_remove(xact->org == OGS_PFCP_LOCAL_ORIGINATOR ?
&xact->node->local_list : &xact->node->remote_list, xact);

View File

@ -61,6 +61,8 @@ typedef struct ogs_pfcp_xact_s {
ogs_timer_t *tm_holding; /**< Timer waiting for holding message */
uint8_t holding_rcount;
ogs_timer_t *tm_delayed_commit; /**< Timer waiting for commit xact */
void *assoc_xact; /**< Associated GTP transaction */
ogs_pkbuf_t *gtpbuf; /**< GTP packet buffer */
@ -82,6 +84,7 @@ typedef struct ogs_pfcp_xact_s {
#define OGS_PFCP_MODIFY_ERROR_INDICATION ((uint64_t)1<<11)
#define OGS_PFCP_MODIFY_XN_HANDOVER ((uint64_t)1<<12)
#define OGS_PFCP_MODIFY_N2_HANDOVER ((uint64_t)1<<13)
#define OGS_PFCP_MODIFY_HANDOVER_CANCEL ((uint64_t)1<<14)
uint64_t modify_flags;
#define OGS_PFCP_DELETE_TRIGGER_UE_REQUESTED 1
@ -109,6 +112,7 @@ int ogs_pfcp_xact_update_tx(ogs_pfcp_xact_t *xact,
int ogs_pfcp_xact_update_rx(ogs_pfcp_xact_t *xact, uint8_t type);
int ogs_pfcp_xact_commit(ogs_pfcp_xact_t *xact);
void ogs_pfcp_xact_delayed_commit(ogs_pfcp_xact_t *xact, ogs_time_t duration);
int ogs_pfcp_xact_receive(ogs_pfcp_node_t *node,
ogs_pfcp_header_t *h, ogs_pfcp_xact_t **xact);

View File

@ -184,6 +184,8 @@ struct ran_ue_s {
#define NGAP_UE_CTX_REL_NG_REMOVE_AND_UNLINK 2
#define NGAP_UE_CTX_REL_UE_CONTEXT_REMOVE 3
#define NGAP_UE_CTX_REL_NG_HANDOVER_COMPLETE 4
#define NGAP_UE_CTX_REL_NG_HANDOVER_CANCEL 5
#define NGAP_UE_CTX_REL_NG_HANDOVER_FAILURE 6
uint8_t ue_ctx_rel_action;
/* Related Context */

View File

@ -1909,6 +1909,7 @@ ogs_pkbuf_t *ngap_build_handover_request(ran_ue_t *target_ue)
NGAP_PDUSessionResourceSetupListHOReq_t *PDUSessionList = NULL;
NGAP_PDUSessionResourceSetupItemHOReq_t *PDUSessionItem = NULL;
NGAP_AllowedNSSAI_t *AllowedNSSAI = NULL;
NGAP_MaskedIMEISV_t *MaskedIMEISV = NULL;
NGAP_SourceToTarget_TransparentContainer_t
*SourceToTarget_TransparentContainer = NULL;
NGAP_GUAMI_t *GUAMI = NULL;
@ -2137,6 +2138,31 @@ ogs_pkbuf_t *ngap_build_handover_request(ran_ue_t *target_ue)
}
}
/* TS23.003 6.2.2 Composition of IMEISV
*
* The International Mobile station Equipment Identity and
* Software Version Number (IMEISV) is composed.
*
* TAC(8 digits) - SNR(6 digits) - SVN(2 digits)
* IMEISV(16 digits) ==> 8bytes
*/
if (amf_ue->masked_imeisv_len == OGS_MAX_IMEISV_LEN) {
ie = CALLOC(1, sizeof(NGAP_HandoverRequestIEs_t));
ogs_assert(ie);
ASN_SEQUENCE_ADD(&HandoverRequest->protocolIEs, ie);
ie->id = NGAP_ProtocolIE_ID_id_MaskedIMEISV;
ie->criticality = NGAP_Criticality_ignore;
ie->value.present = NGAP_HandoverRequestIEs__value_PR_MaskedIMEISV;
MaskedIMEISV = &ie->value.choice.MaskedIMEISV;
MaskedIMEISV->size = amf_ue->masked_imeisv_len;
MaskedIMEISV->buf = CALLOC(MaskedIMEISV->size, sizeof(uint8_t));
MaskedIMEISV->bits_unused = 0;
memcpy(MaskedIMEISV->buf, amf_ue->masked_imeisv, MaskedIMEISV->size);
}
ie = CALLOC(1, sizeof(NGAP_HandoverRequestIEs_t));
ogs_assert(ie);
ASN_SEQUENCE_ADD(&HandoverRequest->protocolIEs, ie);

View File

@ -1274,18 +1274,25 @@ void ngap_handle_ue_context_release_action(ran_ue_t *ran_ue)
ran_ue_remove(ran_ue);
ogs_expect_or_return(amf_ue);
#if 0
if (amf_ue_have_indirect_tunnel(amf_ue)) {
amf_gtp_send_delete_indirect_data_forwarding_tunnel_request(
amf_ue);
} else {
ogs_warn("Check your eNodeB");
ogs_warn(" There is no INDIRECT TUNNEL");
ogs_warn(" Packet could be dropped during S1-Handover");
rv = amf_ue_clear_indirect_tunnel(amf_ue);
ogs_expect(rv == OGS_OK);
}
#endif
break;
case NGAP_UE_CTX_REL_NG_HANDOVER_CANCEL:
ogs_warn(" Action: NG handover cancel");
source_ue_deassociate_target_ue(ran_ue);
ran_ue_remove(ran_ue);
ogs_expect_or_return(amf_ue);
ogs_expect_or_return(amf_ue->ran_ue);
ngap_send_handover_cancel_ack(amf_ue->ran_ue);
break;
case NGAP_UE_CTX_REL_NG_HANDOVER_FAILURE:
ogs_warn(" Action: NG handover failure");
source_ue_deassociate_target_ue(ran_ue);
ran_ue_remove(ran_ue);
ogs_expect_or_return(amf_ue);
break;
default:
ogs_error("Invalid Action[%d]", ran_ue->ue_ctx_rel_action);
@ -2769,7 +2776,7 @@ void ngap_handle_handover_failure(
ngap_send_ran_ue_context_release_command(target_ue,
NGAP_Cause_PR_radioNetwork, NGAP_CauseRadioNetwork_ho_failure_in_target_5GC_ngran_node_or_target_system,
NGAP_UE_CTX_REL_NG_HANDOVER_COMPLETE, 0);
NGAP_UE_CTX_REL_NG_HANDOVER_FAILURE, 0);
}
void ngap_handle_handover_cancel(
@ -3144,6 +3151,12 @@ void ngap_handle_handover_notification(
memcpy(&amf_ue->tai, &target_ue->saved.tai, sizeof(ogs_5gs_tai_t));
memcpy(&amf_ue->nr_cgi, &target_ue->saved.nr_cgi, sizeof(ogs_nr_cgi_t));
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_app()->time.handover.duration);
ogs_list_for_each(&amf_ue->sess_list, sess) {
memset(&param, 0, sizeof(param));
param.hoState = OpenAPI_ho_state_COMPLETED;

View File

@ -410,30 +410,15 @@ int amf_nsmf_pdusession_handle_update_sm_context(
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));
NGAP_UE_CTX_REL_NG_HANDOVER_CANCEL, 0);
}
} 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));
}
/* Nothing to do */
} else if (state == AMF_REMOVE_S1_CONTEXT_BY_LO_CONNREFUSED) {
if (SESSION_SYNC_DONE(amf_ue, state)) {

View File

@ -263,7 +263,9 @@ struct enb_ue_s {
#define S1AP_UE_CTX_REL_S1_REMOVE_AND_UNLINK 2
#define S1AP_UE_CTX_REL_UE_CONTEXT_REMOVE 3
#define S1AP_UE_CTX_REL_S1_HANDOVER_COMPLETE 4
#define S1AP_UE_CTX_REL_S1_PAGING 5
#define S1AP_UE_CTX_REL_S1_HANDOVER_CANCEL 5
#define S1AP_UE_CTX_REL_S1_HANDOVER_FAILURE 6
#define S1AP_UE_CTX_REL_S1_PAGING 7
uint8_t ue_ctx_rel_action;
bool part_of_s1_reset_requested;
@ -491,7 +493,6 @@ struct mme_ue_s {
#define MAX_NUM_OF_GTP_COUNTER 16
#define GTP_COUNTER_MODIFY_BEARER_BY_PATH_SWITCH 1
#define GTP_COUNTER_MODIFY_BEARER_BY_HANDOVER_NOTIFY 2
struct {
uint8_t request;
uint8_t response;

View File

@ -515,13 +515,14 @@ void mme_gtp_send_create_indirect_data_forwarding_tunnel_request(
}
void mme_gtp_send_delete_indirect_data_forwarding_tunnel_request(
mme_ue_t *mme_ue)
mme_ue_t *mme_ue, int action)
{
int rv;
ogs_gtp_header_t h;
ogs_pkbuf_t *pkbuf = NULL;
ogs_gtp_xact_t *xact = NULL;
ogs_assert(action);
ogs_assert(mme_ue);
memset(&h, 0, sizeof(ogs_gtp_header_t));
@ -534,6 +535,7 @@ void mme_gtp_send_delete_indirect_data_forwarding_tunnel_request(
xact = ogs_gtp_xact_local_create(mme_ue->gnode, &h, pkbuf, timeout, mme_ue);
ogs_expect_or_return(xact);
xact->delete_indirect_action = action;
rv = ogs_gtp_xact_commit(xact);
ogs_expect(rv == OGS_OK);

View File

@ -49,7 +49,7 @@ void mme_gtp_send_downlink_data_notification_ack(
void mme_gtp_send_create_indirect_data_forwarding_tunnel_request(
mme_ue_t *mme_ue);
void mme_gtp_send_delete_indirect_data_forwarding_tunnel_request(
mme_ue_t *mme_ue);
mme_ue_t *mme_ue, int action);
void mme_gtp_send_bearer_resource_command(
mme_bearer_t *bearer, ogs_nas_eps_message_t *nas_message);

View File

@ -253,7 +253,6 @@ void mme_s11_handle_modify_bearer_response(
{
int rv;
uint8_t cause_value = 0;
enb_ue_t *source_ue = NULL, *target_ue = NULL;
ogs_assert(xact);
ogs_assert(rsp);
@ -294,19 +293,6 @@ void mme_s11_handle_modify_bearer_response(
GTP_COUNTER_CHECK(mme_ue, GTP_COUNTER_MODIFY_BEARER_BY_PATH_SWITCH,
s1ap_send_path_switch_ack(mme_ue);
);
GTP_COUNTER_CHECK(mme_ue, GTP_COUNTER_MODIFY_BEARER_BY_HANDOVER_NOTIFY,
target_ue = mme_ue->enb_ue;
ogs_assert(target_ue);
source_ue = target_ue->source_ue;
ogs_assert(source_ue);
s1ap_send_ue_context_release_command(source_ue,
S1AP_Cause_PR_radioNetwork,
S1AP_CauseRadioNetwork_successful_handover,
S1AP_UE_CTX_REL_S1_HANDOVER_COMPLETE,
ogs_time_from_msec(300));
);
}
void mme_s11_handle_delete_session_response(
@ -1065,8 +1051,11 @@ void mme_s11_handle_delete_indirect_data_forwarding_tunnel_response(
{
int rv;
uint8_t cause_value = 0;
int action = 0;
ogs_assert(xact);
action = xact->delete_indirect_action;
ogs_assert(action);
ogs_assert(rsp);
ogs_debug("Delete Indirect Data Forwarding Tunnel Response");
@ -1098,6 +1087,15 @@ void mme_s11_handle_delete_indirect_data_forwarding_tunnel_response(
mme_ue->mme_s11_teid, mme_ue->sgw_s11_teid);
mme_ue_clear_indirect_tunnel(mme_ue);
if (action == OGS_GTP_DELETE_INDIRECT_HANDOVER_COMPLETE) {
/* Nothing to do */
} else if (action == OGS_GTP_DELETE_INDIRECT_HANDOVER_CANCEL) {
s1ap_send_handover_cancel_ack(mme_ue->enb_ue);
} else {
ogs_fatal("Invalid action = %d", action);
ogs_assert_if_reached();
}
}
void mme_s11_handle_bearer_resource_failure_indication(

View File

@ -1810,6 +1810,7 @@ ogs_pkbuf_t *s1ap_build_handover_request(
*Source_ToTarget_TransparentContainer = NULL;
S1AP_UESecurityCapabilities_t *UESecurityCapabilities = NULL;
S1AP_SecurityContext_t *SecurityContext = NULL;
S1AP_Masked_IMEISV_t *Masked_IMEISV = NULL;
mme_ue_t *mme_ue = NULL;
mme_sess_t *sess = NULL;
@ -1914,8 +1915,7 @@ ogs_pkbuf_t *s1ap_build_handover_request(
ie->id = S1AP_ProtocolIE_ID_id_SecurityContext;
ie->criticality = S1AP_Criticality_reject;
ie->value.present =
S1AP_HandoverRequestIEs__value_PR_SecurityContext;
ie->value.present = S1AP_HandoverRequestIEs__value_PR_SecurityContext;
SecurityContext = &ie->value.choice.SecurityContext;
@ -2020,6 +2020,30 @@ ogs_pkbuf_t *s1ap_build_handover_request(
memcpy(SecurityContext->nextHopParameter.buf,
mme_ue->nh, SecurityContext->nextHopParameter.size);
/* TS23.003 6.2.2 Composition of IMEISV
*
* The International Mobile station Equipment Identity and
* Software Version Number (IMEISV) is composed.
*
* TAC(8 digits) - SNR(6 digits) - SVN(2 digits)
* IMEISV(16 digits) ==> 8bytes
*/
if (mme_ue->imeisv_len == OGS_MAX_IMEISV_LEN) {
ie = CALLOC(1, sizeof(S1AP_HandoverRequestIEs_t));
ASN_SEQUENCE_ADD(&HandoverRequest->protocolIEs, ie);
ie->id = S1AP_ProtocolIE_ID_id_Masked_IMEISV;
ie->criticality = S1AP_Criticality_ignore;
ie->value.present = S1AP_HandoverRequestIEs__value_PR_Masked_IMEISV;
Masked_IMEISV = &ie->value.choice.Masked_IMEISV;
Masked_IMEISV->size = mme_ue->masked_imeisv_len;
Masked_IMEISV->buf = CALLOC(Masked_IMEISV->size, sizeof(uint8_t));
Masked_IMEISV->bits_unused = 0;
memcpy(Masked_IMEISV->buf, mme_ue->masked_imeisv, Masked_IMEISV->size);
}
return ogs_s1ap_encode(&pdu);
}

View File

@ -1262,14 +1262,47 @@ void s1ap_handle_ue_context_release_action(enb_ue_t *enb_ue)
ogs_expect_or_return(mme_ue);
if (mme_ue_have_indirect_tunnel(mme_ue) == true) {
mme_gtp_send_delete_indirect_data_forwarding_tunnel_request(
mme_ue);
mme_ue, OGS_GTP_DELETE_INDIRECT_HANDOVER_COMPLETE);
} else {
ogs_warn("Check your eNodeB");
ogs_warn(" There is no INDIRECT TUNNEL");
ogs_warn(" No INDIRECT TUNNEL");
ogs_warn(" Packet could be dropped during S1-Handover");
mme_ue_clear_indirect_tunnel(mme_ue);
}
break;
case S1AP_UE_CTX_REL_S1_HANDOVER_CANCEL:
ogs_warn(" Action: S1 handover cancel");
source_ue_deassociate_target_ue(enb_ue);
enb_ue_remove(enb_ue);
ogs_expect_or_return(mme_ue);
if (mme_ue_have_indirect_tunnel(mme_ue) == true) {
mme_gtp_send_delete_indirect_data_forwarding_tunnel_request(
mme_ue, OGS_GTP_DELETE_INDIRECT_HANDOVER_CANCEL);
} else {
ogs_warn("Check your eNodeB");
ogs_warn(" No INDIRECT TUNNEL");
ogs_warn(" Packet could be dropped during S1-Handover");
mme_ue_clear_indirect_tunnel(mme_ue);
ogs_expect_or_return(mme_ue->enb_ue);
s1ap_send_handover_cancel_ack(mme_ue->enb_ue);
}
break;
case S1AP_UE_CTX_REL_S1_HANDOVER_FAILURE:
ogs_warn(" Action: S1 handover failure");
source_ue_deassociate_target_ue(enb_ue);
enb_ue_remove(enb_ue);
ogs_expect_or_return(mme_ue);
if (mme_ue_have_indirect_tunnel(mme_ue) == true) {
ogs_error("Check your eNodeB");
ogs_error(" We found INDIRECT TUNNEL in HandoverFailure");
mme_ue_clear_indirect_tunnel(mme_ue);
}
break;
case S1AP_UE_CTX_REL_S1_PAGING:
ogs_debug(" Action: S1 paging");
enb_ue_remove(enb_ue);
@ -1884,7 +1917,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_S1_HANDOVER_COMPLETE, 0);
S1AP_UE_CTX_REL_S1_HANDOVER_FAILURE, 0);
}
void s1ap_handle_handover_cancel(mme_enb_t *enb, ogs_s1ap_message_t *message)
@ -1948,13 +1981,10 @@ void s1ap_handle_handover_cancel(mme_enb_t *enb, ogs_s1ap_message_t *message)
ogs_debug(" Target : ENB_UE_S1AP_ID[%d] MME_UE_S1AP_ID[%d]",
target_ue->enb_ue_s1ap_id, target_ue->mme_ue_s1ap_id);
s1ap_send_handover_cancel_ack(source_ue);
s1ap_send_ue_context_release_command(
target_ue, S1AP_Cause_PR_radioNetwork,
S1AP_CauseRadioNetwork_handover_cancelled,
S1AP_UE_CTX_REL_S1_HANDOVER_COMPLETE,
ogs_time_from_msec(300));
S1AP_UE_CTX_REL_S1_HANDOVER_CANCEL, 0);
ogs_debug("Handover Cancel : "
"UE[eNB-UE-S1AP-ID(%d)] --> eNB[%s:%d]",
@ -2146,22 +2176,20 @@ void s1ap_handle_handover_notification(
memcpy(&mme_ue->tai, &target_ue->saved.tai, sizeof(ogs_eps_tai_t));
memcpy(&mme_ue->e_cgi, &target_ue->saved.e_cgi, sizeof(ogs_e_cgi_t));
sess = mme_sess_first(mme_ue);
while (sess) {
bearer = mme_bearer_first(sess);
while (bearer) {
s1ap_send_ue_context_release_command(source_ue,
S1AP_Cause_PR_radioNetwork,
S1AP_CauseRadioNetwork_successful_handover,
S1AP_UE_CTX_REL_S1_HANDOVER_COMPLETE,
ogs_app()->time.handover.duration);
ogs_list_for_each(&mme_ue->sess_list, sess) {
ogs_list_for_each(&sess->bearer_list, bearer) {
bearer->enb_s1u_teid = bearer->target_s1u_teid;
memcpy(&bearer->enb_s1u_ip, &bearer->target_s1u_ip,
sizeof(ogs_ip_t));
GTP_COUNTER_INCREMENT(
mme_ue, GTP_COUNTER_MODIFY_BEARER_BY_HANDOVER_NOTIFY);
mme_gtp_send_modify_bearer_request(bearer, 1);
bearer = mme_bearer_next(bearer);
}
sess = mme_sess_next(sess);
}
}

View File

@ -1083,9 +1083,7 @@ void sgwc_s11_handle_delete_indirect_data_forwarding_tunnel_request(
sess->state.delete_indirect_tunnel = false;
sgwc_pfcp_send_sess_modification_request(
sess, s11_xact, gtpbuf,
OGS_PFCP_MODIFY_SESSION|
OGS_PFCP_MODIFY_INDIRECT|
OGS_PFCP_MODIFY_REMOVE);
OGS_PFCP_MODIFY_INDIRECT| OGS_PFCP_MODIFY_REMOVE);
}
}

View File

@ -437,15 +437,15 @@ void sgwc_sxa_handle_session_modification_response(
}
if (cause_value != OGS_GTP_CAUSE_REQUEST_ACCEPTED) {
if (flags & OGS_PFCP_MODIFY_CREATE) {
s5c_xact = pfcp_xact->assoc_xact;
ogs_assert(s5c_xact);
ogs_gtp_send_error_message(
s5c_xact, sess ? sess->pgw_s5c_teid : 0,
OGS_GTP_CREATE_BEARER_RESPONSE_TYPE, cause_value);
} else if (flags & OGS_PFCP_MODIFY_REMOVE) {
/*
* You should not change the following order to support
* OGS_PFCP_MODIFY_REMOVE|OGS_PFCP_MODIFY_CREATE.
*
* 1. if (flags & OGS_PFCP_MODIFY_REMOVE) {
* 2. } else if (flags & OGS_PFCP_MODIFY_CREATE) {
* }
*/
if (flags & OGS_PFCP_MODIFY_REMOVE) {
s5c_xact = pfcp_xact->assoc_xact;
if (s5c_xact) {
@ -455,6 +455,14 @@ void sgwc_sxa_handle_session_modification_response(
}
sgwc_bearer_remove(bearer);
} else if (flags & OGS_PFCP_MODIFY_CREATE) {
s5c_xact = pfcp_xact->assoc_xact;
ogs_assert(s5c_xact);
ogs_gtp_send_error_message(
s5c_xact, sess ? sess->pgw_s5c_teid : 0,
OGS_GTP_CREATE_BEARER_RESPONSE_TYPE, cause_value);
} else if (flags & OGS_PFCP_MODIFY_ACTIVATE) {
if (flags & OGS_PFCP_MODIFY_UL_ONLY) {
@ -489,7 +497,97 @@ void sgwc_sxa_handle_session_modification_response(
return;
}
if (flags & OGS_PFCP_MODIFY_CREATE) {
/*
* You should not change the following order to support
* OGS_PFCP_MODIFY_REMOVE|OGS_PFCP_MODIFY_CREATE.
*
* 1. if (flags & OGS_PFCP_MODIFY_REMOVE) {
* 2. } else if (flags & OGS_PFCP_MODIFY_CREATE) {
* }
*/
if (flags & OGS_PFCP_MODIFY_REMOVE) {
if (flags & OGS_PFCP_MODIFY_INDIRECT) {
bool delete_indirect_tunnel_is_done;
s11_xact = pfcp_xact->assoc_xact;
ogs_assert(s11_xact);
sess->state.delete_indirect_tunnel = true;
delete_indirect_tunnel_is_done = true;
ogs_list_for_each(&sgwc_ue->sess_list, sess) {
if (sess->state.delete_indirect_tunnel == false)
delete_indirect_tunnel_is_done = false;
}
if (delete_indirect_tunnel_is_done == true) {
sgwc_tunnel_t *tunnel = NULL, *next_tunnel = NULL;
ogs_gtp_delete_indirect_data_forwarding_tunnel_response_t
*gtp_rsp = NULL;
ogs_list_for_each(&sgwc_ue->sess_list, sess) {
ogs_list_for_each(&sess->bearer_list, bearer) {
ogs_list_for_each_safe(&bearer->tunnel_list,
next_tunnel, tunnel) {
if (tunnel->interface_type ==
OGS_GTP_F_TEID_SGW_GTP_U_FOR_DL_DATA_FORWARDING ||
tunnel->interface_type ==
OGS_GTP_F_TEID_SGW_GTP_U_FOR_UL_DATA_FORWARDING) {
sgwc_tunnel_remove(tunnel);
}
}
}
}
gtp_rsp = &send_message.
delete_indirect_data_forwarding_tunnel_response;
ogs_assert(gtp_rsp);
memset(&send_message, 0, sizeof(ogs_gtp_message_t));
memset(&cause, 0, sizeof(cause));
cause.value = OGS_GTP_CAUSE_REQUEST_ACCEPTED;
gtp_rsp->cause.presence = 1;
gtp_rsp->cause.data = &cause;
gtp_rsp->cause.len = sizeof(cause);
send_message.h.type =
OGS_GTP_DELETE_INDIRECT_DATA_FORWARDING_TUNNEL_RESPONSE_TYPE;
send_message.h.teid = sgwc_ue->mme_s11_teid;
pkbuf = ogs_gtp_build_msg(&send_message);
ogs_expect_or_return(pkbuf);
rv = ogs_gtp_xact_update_tx(s11_xact, &send_message.h, pkbuf);
ogs_expect_or_return(rv == OGS_OK);
rv = ogs_gtp_xact_commit(s11_xact);
ogs_expect(rv == OGS_OK);
}
} else {
s5c_xact = pfcp_xact->assoc_xact;
if (s5c_xact) {
ogs_assert(recv_message);
recv_message->h.type = OGS_GTP_DELETE_BEARER_RESPONSE_TYPE;
recv_message->h.teid = sess->pgw_s5c_teid;
pkbuf = ogs_gtp_build_msg(recv_message);
ogs_expect_or_return(pkbuf);
rv = ogs_gtp_xact_update_tx(s5c_xact, &recv_message->h, pkbuf);
ogs_expect_or_return(rv == OGS_OK);
rv = ogs_gtp_xact_commit(s5c_xact);
ogs_expect(rv == OGS_OK);
}
sgwc_bearer_remove(bearer);
}
} else if (flags & OGS_PFCP_MODIFY_CREATE) {
if (flags & OGS_PFCP_MODIFY_UL_ONLY) {
ogs_gtp_create_bearer_request_t *gtp_req = NULL;
ogs_gtp_f_teid_t sgw_s1u_teid;
@ -715,88 +813,6 @@ void sgwc_sxa_handle_session_modification_response(
ogs_assert_if_reached();
}
} else if (flags & OGS_PFCP_MODIFY_REMOVE) {
if (flags & OGS_PFCP_MODIFY_INDIRECT) {
bool delete_indirect_tunnel_is_done;
s11_xact = pfcp_xact->assoc_xact;
ogs_assert(s11_xact);
sess->state.delete_indirect_tunnel = true;
delete_indirect_tunnel_is_done = true;
ogs_list_for_each(&sgwc_ue->sess_list, sess) {
if (sess->state.delete_indirect_tunnel == false)
delete_indirect_tunnel_is_done = false;
}
if (delete_indirect_tunnel_is_done == true) {
sgwc_tunnel_t *tunnel = NULL, *next_tunnel = NULL;
ogs_gtp_delete_indirect_data_forwarding_tunnel_response_t
*gtp_rsp = NULL;
ogs_list_for_each(&sgwc_ue->sess_list, sess) {
ogs_list_for_each(&sess->bearer_list, bearer) {
ogs_list_for_each_safe(&bearer->tunnel_list,
next_tunnel, tunnel) {
if (tunnel->interface_type ==
OGS_GTP_F_TEID_SGW_GTP_U_FOR_DL_DATA_FORWARDING ||
tunnel->interface_type ==
OGS_GTP_F_TEID_SGW_GTP_U_FOR_UL_DATA_FORWARDING) {
sgwc_tunnel_remove(tunnel);
}
}
}
}
gtp_rsp = &send_message.
delete_indirect_data_forwarding_tunnel_response;
ogs_assert(gtp_rsp);
memset(&send_message, 0, sizeof(ogs_gtp_message_t));
memset(&cause, 0, sizeof(cause));
cause.value = OGS_GTP_CAUSE_REQUEST_ACCEPTED;
gtp_rsp->cause.presence = 1;
gtp_rsp->cause.data = &cause;
gtp_rsp->cause.len = sizeof(cause);
send_message.h.type =
OGS_GTP_DELETE_INDIRECT_DATA_FORWARDING_TUNNEL_RESPONSE_TYPE;
send_message.h.teid = sgwc_ue->mme_s11_teid;
pkbuf = ogs_gtp_build_msg(&send_message);
ogs_expect_or_return(pkbuf);
rv = ogs_gtp_xact_update_tx(s11_xact, &send_message.h, pkbuf);
ogs_expect_or_return(rv == OGS_OK);
rv = ogs_gtp_xact_commit(s11_xact);
ogs_expect(rv == OGS_OK);
}
} else {
s5c_xact = pfcp_xact->assoc_xact;
if (s5c_xact) {
ogs_assert(recv_message);
recv_message->h.type = OGS_GTP_DELETE_BEARER_RESPONSE_TYPE;
recv_message->h.teid = sess->pgw_s5c_teid;
pkbuf = ogs_gtp_build_msg(recv_message);
ogs_expect_or_return(pkbuf);
rv = ogs_gtp_xact_update_tx(s5c_xact, &recv_message->h, pkbuf);
ogs_expect_or_return(rv == OGS_OK);
rv = ogs_gtp_xact_commit(s5c_xact);
ogs_expect(rv == OGS_OK);
}
sgwc_bearer_remove(bearer);
}
} else if (flags & OGS_PFCP_MODIFY_ACTIVATE) {
s11_xact = pfcp_xact->assoc_xact;
ogs_assert(s11_xact);

View File

@ -1171,6 +1171,11 @@ void smf_sess_remove(smf_sess_t *sess)
if (sess->upf_n3_addr6)
ogs_freeaddrinfo(sess->upf_n3_addr6);
if (sess->handover.upf_dl_addr)
ogs_freeaddrinfo(sess->handover.upf_dl_addr);
if (sess->handover.upf_dl_addr6)
ogs_freeaddrinfo(sess->handover.upf_dl_addr6);
if (sess->pcf_id)
ogs_free(sess->pcf_id);
@ -1371,6 +1376,118 @@ smf_bearer_t *smf_qos_flow_add(smf_sess_t *sess)
return qos_flow;
}
void smf_sess_create_indirect_data_forwarding(smf_sess_t *sess)
{
smf_bearer_t *qos_flow = NULL;
ogs_assert(sess);
ogs_list_for_each(&sess->bearer_list, qos_flow) {
ogs_pfcp_pdr_t *pdr = NULL;
ogs_pfcp_far_t *far = NULL;
ogs_pfcp_qer_t *qer = NULL;
ogs_assert(sess);
pdr = ogs_pfcp_pdr_add(&sess->pfcp);
ogs_assert(pdr);
pdr->src_if = OGS_PFCP_INTERFACE_ACCESS;
pdr->outer_header_removal_len = 1;
if (sess->pdn.pdn_type == OGS_GTP_PDN_TYPE_IPV4) {
pdr->outer_header_removal.description =
OGS_PFCP_OUTER_HEADER_REMOVAL_GTPU_UDP_IPV4;
} else if (sess->pdn.pdn_type == OGS_GTP_PDN_TYPE_IPV6) {
pdr->outer_header_removal.description =
OGS_PFCP_OUTER_HEADER_REMOVAL_GTPU_UDP_IPV6;
} else if (sess->pdn.pdn_type == OGS_GTP_PDN_TYPE_IPV4V6) {
pdr->outer_header_removal.description =
OGS_PFCP_OUTER_HEADER_REMOVAL_GTPU_UDP_IP;
} else
ogs_assert_if_reached();
far = ogs_pfcp_far_add(&sess->pfcp);
ogs_assert(far);
far->dst_if = OGS_PFCP_INTERFACE_ACCESS;
ogs_pfcp_pdr_associate_far(pdr, far);
far->apply_action = OGS_PFCP_APPLY_ACTION_FORW;
qer = qos_flow->qer;
ogs_assert(qer);
ogs_pfcp_pdr_associate_qer(pdr, qer);
pdr->qfi = qos_flow->qfi;
ogs_assert(sess->pfcp_node);
if (sess->pfcp_node->up_function_features.ftup) {
pdr->f_teid.ch = 1;
pdr->f_teid.chid = 1;
pdr->f_teid.choose_id = OGS_PFCP_INDIRECT_DATA_FORWARDING_CHOOSE_ID;
pdr->f_teid_len = 2;
} else {
ogs_assert(sess->upf_n3_addr || sess->upf_n3_addr6);
ogs_pfcp_sockaddr_to_f_teid(
sess->upf_n3_addr, sess->upf_n3_addr6,
&pdr->f_teid, &pdr->f_teid_len);
pdr->f_teid.teid = sess->upf_n3_teid;
}
ogs_pfcp_ip_to_outer_header_creation(
&sess->handover.gnb_dl_ip,
&far->outer_header_creation,
&far->outer_header_creation_len);
far->outer_header_creation.teid = sess->handover.gnb_dl_teid;
/* Indirect Data Forwarding PDRs is set to highest precedence
* (lowest precedence value) */
pdr->precedence = 1;
}
}
bool smf_sess_have_indirect_data_forwarding(smf_sess_t *sess)
{
ogs_pfcp_pdr_t *pdr = NULL;
ogs_assert(sess);
ogs_list_for_each(&sess->pfcp.pdr_list, pdr) {
ogs_pfcp_far_t *far = pdr->far;
ogs_assert(far);
if ((pdr->src_if == OGS_PFCP_INTERFACE_ACCESS) &&
(far->dst_if == OGS_PFCP_INTERFACE_ACCESS)) {
return true;
}
}
return false;
}
void smf_sess_delete_indirect_data_forwarding(smf_sess_t *sess)
{
ogs_pfcp_pdr_t *pdr = NULL;
ogs_assert(sess);
ogs_list_for_each(&sess->pfcp.pdr_list, pdr) {
ogs_pfcp_far_t *far = pdr->far;
ogs_assert(far);
if ((pdr->src_if == OGS_PFCP_INTERFACE_ACCESS) &&
(far->dst_if == OGS_PFCP_INTERFACE_ACCESS)) {
ogs_pfcp_pdr_remove(pdr);
ogs_pfcp_far_remove(far);
}
}
}
smf_bearer_t *smf_qos_flow_find_by_qfi(smf_sess_t *sess, uint8_t qfi)
{
smf_bearer_t *qos_flow = NULL;
@ -1525,9 +1642,13 @@ int smf_bearer_remove(smf_bearer_t *bearer)
ogs_list_remove(&bearer->sess->bearer_list, bearer);
ogs_assert(bearer->dl_pdr);
ogs_pfcp_pdr_remove(bearer->dl_pdr);
ogs_assert(bearer->ul_pdr);
ogs_pfcp_pdr_remove(bearer->ul_pdr);
ogs_assert(bearer->dl_far);
ogs_pfcp_far_remove(bearer->dl_far);
ogs_assert(bearer->ul_far);
ogs_pfcp_far_remove(bearer->ul_far);
if (bearer->qer)
ogs_pfcp_qer_remove(bearer->qer);

View File

@ -305,9 +305,20 @@ typedef struct smf_sess_s {
/* Handover */
struct {
bool prepared;
bool direct_available;
bool indirect_data_forwarding;
/* NG-U UP Transport Information Saved Temporally */
uint32_t gnb_n3_teid;
ogs_ip_t gnb_n3_ip;
} handover; /* Saved from N2-Handover Request Acknowledge */
/* Indirect DL Forwarding */
uint32_t upf_dl_teid;
ogs_sockaddr_t *upf_dl_addr;
ogs_sockaddr_t *upf_dl_addr6;
uint32_t gnb_dl_teid;
ogs_ip_t gnb_dl_ip;
} handover;
ogs_list_t bearer_list;
@ -358,6 +369,10 @@ smf_sess_t *smf_sess_find_by_error_indication_report(
smf_ue_t *smf_ue,
ogs_pfcp_tlv_error_indication_report_t *error_indication_report);
void smf_sess_create_indirect_data_forwarding(smf_sess_t *sess);
bool smf_sess_have_indirect_data_forwarding(smf_sess_t *sess);
void smf_sess_delete_indirect_data_forwarding(smf_sess_t *sess);
smf_bearer_t *smf_qos_flow_add(smf_sess_t *sess);
smf_bearer_t *smf_qos_flow_find_by_qfi(smf_sess_t *sess, uint8_t qfi);
smf_bearer_t *smf_qos_flow_find_by_pcc_rule_id(

View File

@ -111,13 +111,18 @@ ogs_pkbuf_t *smf_n4_build_session_establishment_request(
ogs_pkbuf_t *smf_n4_build_session_modification_request(
uint8_t type, smf_sess_t *sess, uint64_t modify_flags)
{
int i;
ogs_pfcp_pdr_t *pdr = NULL;
ogs_pfcp_message_t pfcp_message;
ogs_pfcp_session_modification_request_t *req = NULL;
ogs_pfcp_far_t *far = NULL;
ogs_pkbuf_t *pkbuf = NULL;
int num_of_remove_pdr = 0;
int num_of_remove_far = 0;
int num_of_create_pdr = 0;
int num_of_create_far = 0;
int num_of_update_far = 0;
ogs_debug("Session Modification Request");
ogs_assert(sess);
ogs_assert(modify_flags);
@ -125,14 +130,55 @@ ogs_pkbuf_t *smf_n4_build_session_modification_request(
req = &pfcp_message.pfcp_session_modification_request;
memset(&pfcp_message, 0, sizeof(ogs_pfcp_message_t));
i = 0;
ogs_list_for_each(&sess->pfcp.far_list, far) {
ogs_list_for_each(&sess->pfcp.pdr_list, pdr) {
ogs_pfcp_far_t *far = pdr->far;
ogs_assert(far);
/* Update FAR - Only DL */
if (far->dst_if == OGS_PFCP_INTERFACE_ACCESS) {
if (((modify_flags &
(OGS_PFCP_MODIFY_DL_ONLY|
OGS_PFCP_MODIFY_UL_ONLY|
OGS_PFCP_MODIFY_INDIRECT)) == 0) ||
if (modify_flags & OGS_PFCP_MODIFY_ACTIVATE) {
((modify_flags & OGS_PFCP_MODIFY_DL_ONLY) &&
(pdr->src_if == OGS_PFCP_INTERFACE_CORE) &&
(far->dst_if == OGS_PFCP_INTERFACE_ACCESS)) ||
((modify_flags & OGS_PFCP_MODIFY_UL_ONLY) &&
(pdr->src_if == OGS_PFCP_INTERFACE_ACCESS) &&
(far->dst_if == OGS_PFCP_INTERFACE_CORE)) ||
((modify_flags & OGS_PFCP_MODIFY_INDIRECT) &&
(pdr->src_if == OGS_PFCP_INTERFACE_ACCESS) &&
(far->dst_if == OGS_PFCP_INTERFACE_ACCESS))) {
if (modify_flags & OGS_PFCP_MODIFY_REMOVE) {
ogs_pfcp_tlv_remove_pdr_t *remove_pdr = NULL;
ogs_pfcp_tlv_remove_far_t *remove_far = NULL;
remove_pdr = &req->remove_pdr[num_of_remove_pdr];
remove_pdr->presence = 1;
remove_pdr->pdr_id.presence = 1;
remove_pdr->pdr_id.u16 = pdr->id;
num_of_remove_pdr++;
remove_far = &req->remove_far[num_of_remove_far];
remove_far->presence = 1;
remove_far->far_id.presence = 1;
remove_far->far_id.u32 = far->id;
num_of_remove_far++;
} else if (modify_flags & OGS_PFCP_MODIFY_CREATE) {
ogs_pfcp_build_create_pdr(
&req->create_pdr[num_of_create_pdr],
num_of_create_pdr, pdr);
num_of_create_pdr++;
ogs_pfcp_build_create_far(
&req->create_far[num_of_create_far],
num_of_create_far, far);
num_of_create_far++;
} else if (modify_flags & OGS_PFCP_MODIFY_ACTIVATE) {
if (far->apply_action & OGS_PFCP_APPLY_ACTION_FORW) {
if (modify_flags & OGS_PFCP_MODIFY_END_MARKER) {
@ -140,19 +186,65 @@ ogs_pkbuf_t *smf_n4_build_session_modification_request(
}
ogs_pfcp_build_update_far_activate(
&req->update_far[i], i, far);
&req->update_far[num_of_update_far],
num_of_update_far, far);
/* Clear all FAR flags */
far->smreq_flags.value = 0;
}
num_of_update_far++;
}
} else if (modify_flags & OGS_PFCP_MODIFY_DEACTIVATE) {
ogs_pfcp_build_update_far_deactivate(
&req->update_far[i], i, far);
&req->update_far[num_of_update_far],
num_of_update_far, far);
num_of_update_far++;
} else {
ogs_fatal("Invalid modify_flags = %lld",
(long long)modify_flags);
ogs_assert_if_reached();
}
}
}
#if 0
i = 0;
ogs_list_for_each(&sess->bearer_list, qos_flow) {
if (modify_flags & OGS_PFCP_MODIFY_ACTIVATE) {
/* Update FAR - Only DL */
if (qos_flow->dl_far) {
if (qos_flow->dl_far->apply_action &
OGS_PFCP_APPLY_ACTION_FORW) {
if (modify_flags & OGS_PFCP_MODIFY_END_MARKER) {
qos_flow->dl_far->
smreq_flags.send_end_marker_packets = 1;
}
ogs_fatal("FAR = %d", qos_flow->dl_far->id);
ogs_pfcp_build_update_far_activate(
&req->update_far[i], i, qos_flow->dl_far);
/* Clear all FAR flags */
qos_flow->dl_far->smreq_flags.value = 0;
i++;
}
}
} else if (modify_flags & OGS_PFCP_MODIFY_DEACTIVATE) {
if (qos_flow->dl_far) {
ogs_pfcp_build_update_far_deactivate(
&req->update_far[i], i, qos_flow->dl_far);
ogs_error("FAR = %d", qos_flow->dl_far->id);
i++;
}
i++;
}
}
#endif
pfcp_message.h.type = type;
pkbuf = ogs_pfcp_build_msg(&pfcp_message);
@ -292,7 +384,8 @@ ogs_pkbuf_t *smf_n4_build_qos_flow_modification_request(
OGS_PFCP_APPLY_ACTION_FORW) {
if (modify_flags & OGS_PFCP_MODIFY_END_MARKER) {
qos_flow->dl_far->smreq_flags.send_end_marker_packets = 1;
qos_flow->dl_far->
smreq_flags.send_end_marker_packets = 1;
}
ogs_pfcp_build_update_far_activate(

View File

@ -264,15 +264,32 @@ void smf_5gc_n4_handle_session_modification_response(
ogs_assert(sess->pfcp_node);
if (sess->pfcp_node->up_function_features.ftup &&
pdr->f_teid_len) {
if (sess->upf_n3_addr)
ogs_freeaddrinfo(sess->upf_n3_addr);
if (sess->upf_n3_addr6)
ogs_freeaddrinfo(sess->upf_n3_addr6);
ogs_pfcp_f_teid_to_sockaddr(
&pdr->f_teid, pdr->f_teid_len,
&sess->upf_n3_addr, &sess->upf_n3_addr6);
sess->upf_n3_teid = pdr->f_teid.teid;
ogs_pfcp_far_t *far = pdr->far;
ogs_assert(far);
if (far->dst_if == OGS_PFCP_INTERFACE_CORE) {
if (sess->upf_n3_addr)
ogs_freeaddrinfo(sess->upf_n3_addr);
if (sess->upf_n3_addr6)
ogs_freeaddrinfo(sess->upf_n3_addr6);
ogs_pfcp_f_teid_to_sockaddr(
&pdr->f_teid, pdr->f_teid_len,
&sess->upf_n3_addr, &sess->upf_n3_addr6);
sess->upf_n3_teid = pdr->f_teid.teid;
} else if (far->dst_if == OGS_PFCP_INTERFACE_ACCESS) {
if (sess->handover.upf_dl_addr)
ogs_freeaddrinfo(sess->handover.upf_dl_addr);
if (sess->handover.upf_dl_addr6)
ogs_freeaddrinfo(sess->handover.upf_dl_addr6);
ogs_pfcp_f_teid_to_sockaddr(
&pdr->f_teid, pdr->f_teid_len,
&sess->handover.upf_dl_addr,
&sess->handover.upf_dl_addr6);
sess->handover.upf_dl_teid = pdr->f_teid.teid;
}
}
}
@ -308,6 +325,13 @@ void smf_5gc_n4_handle_session_modification_response(
OpenAPI_n2_sm_info_type_PATH_SWITCH_REQ_ACK, n2smbuf);
} else if (flags & OGS_PFCP_MODIFY_N2_HANDOVER) {
if (smf_sess_have_indirect_data_forwarding(sess) == true) {
smf_5gc_pfcp_send_session_modification_request(
sess, stream,
OGS_PFCP_MODIFY_INDIRECT|OGS_PFCP_MODIFY_REMOVE,
ogs_app()->time.handover.duration);
}
smf_sbi_send_sm_context_updated_data_ho_state(
sess, stream, OpenAPI_ho_state_COMPLETED);
@ -332,23 +356,61 @@ void smf_5gc_n4_handle_session_modification_response(
smf_namf_comm_send_n1_n2_message_transfer(sess, &param);
} else {
/* Only ACTIVING & DEACTIVATED is Included */
smf_sbi_send_sm_context_updated_data_up_cnx_state(
sess, stream, OpenAPI_up_cnx_state_DEACTIVATED);
}
/*
* You should not change the following order to support
* OGS_PFCP_MODIFY_REMOVE|OGS_PFCP_MODIFY_CREATE.
*
* 1. if (flags & OGS_PFCP_MODIFY_REMOVE) {
* 2. } else if (flags & OGS_PFCP_MODIFY_CREATE) {
* }
*/
} else if (flags & OGS_PFCP_MODIFY_REMOVE) {
if (flags & OGS_PFCP_MODIFY_INDIRECT) {
smf_sess_delete_indirect_data_forwarding(sess);
/*
* OGS_PFCP_MODIFY_CREATE remains.
* So now we do some extra work to create an indirect tunnel.
*/
if (flags & OGS_PFCP_MODIFY_CREATE) {
smf_sess_create_indirect_data_forwarding(sess);
smf_5gc_pfcp_send_session_modification_request(
sess, stream,
OGS_PFCP_MODIFY_INDIRECT|OGS_PFCP_MODIFY_CREATE,
0);
} else if (flags & OGS_PFCP_MODIFY_HANDOVER_CANCEL) {
smf_sbi_send_sm_context_updated_data_ho_state(
sess, stream, OpenAPI_ho_state_CANCELLED);
}
}
} else if (flags & OGS_PFCP_MODIFY_CREATE) {
smf_n1_n2_message_transfer_param_t param;
if (flags & OGS_PFCP_MODIFY_INDIRECT) {
ogs_pkbuf_t *n2smbuf = ngap_build_handover_command_transfer(sess);
ogs_assert(n2smbuf);
memset(&param, 0, sizeof(param));
param.state = SMF_NETWORK_REQUESTED_QOS_FLOW_MODIFICATION;
param.n1smbuf = gsm_build_qos_flow_modification_command(
qos_flow, OGS_NAS_PROCEDURE_TRANSACTION_IDENTITY_UNASSIGNED);
ogs_assert(param.n1smbuf);
param.n2smbuf = ngap_build_qos_flow_resource_modify_request_transfer(
qos_flow);
ogs_assert(param.n2smbuf);
smf_sbi_send_sm_context_updated_data(
sess, stream, 0, OpenAPI_ho_state_PREPARED,
NULL, OpenAPI_n2_sm_info_type_HANDOVER_CMD, n2smbuf);
smf_namf_comm_send_n1_n2_message_transfer(sess, &param);
} else {
smf_n1_n2_message_transfer_param_t param;
memset(&param, 0, sizeof(param));
param.state = SMF_NETWORK_REQUESTED_QOS_FLOW_MODIFICATION;
param.n1smbuf = gsm_build_qos_flow_modification_command(qos_flow,
OGS_NAS_PROCEDURE_TRANSACTION_IDENTITY_UNASSIGNED);
ogs_assert(param.n1smbuf);
param.n2smbuf =
ngap_build_qos_flow_resource_modify_request_transfer(qos_flow);
ogs_assert(param.n2smbuf);
smf_namf_comm_send_n1_n2_message_transfer(sess, &param);
}
}
}
@ -619,12 +681,12 @@ void smf_epc_n4_handle_session_modification_response(
return;
}
if (flags & OGS_PFCP_MODIFY_CREATE) {
smf_gtp_send_create_bearer_request(bearer);
} else if (flags & OGS_PFCP_MODIFY_REMOVE) {
if (flags & OGS_PFCP_MODIFY_REMOVE) {
smf_bearer_remove(bearer);
} else if (flags & OGS_PFCP_MODIFY_CREATE) {
smf_gtp_send_create_bearer_request(bearer);
} else if (flags & OGS_PFCP_MODIFY_ACTIVATE) {
/* Nothing */
}
@ -807,7 +869,9 @@ void smf_n4_handle_session_report_request(
smf_5gc_pfcp_send_session_modification_request(
error_indication_session, NULL,
OGS_PFCP_MODIFY_DEACTIVATE|OGS_PFCP_MODIFY_ERROR_INDICATION);
OGS_PFCP_MODIFY_DL_ONLY|OGS_PFCP_MODIFY_DEACTIVATE|
OGS_PFCP_MODIFY_ERROR_INDICATION,
0);
} else {
ogs_error("Not supported Report Type[%d]", report_type.value);

View File

@ -31,6 +31,7 @@ ogs_pkbuf_t *ngap_build_pdu_session_resource_setup_request_transfer(
NGAP_PDUSessionAggregateMaximumBitRate_t *PDUSessionAggregateMaximumBitRate;
NGAP_UPTransportLayerInformation_t *UPTransportLayerInformation = NULL;
NGAP_GTPTunnel_t *gTPTunnel = NULL;
NGAP_DataForwardingNotPossible_t *DataForwardingNotPossible = NULL;
NGAP_PDUSessionType_t *PDUSessionType = NULL;
NGAP_QosFlowSetupRequestList_t *QosFlowSetupRequestList = NULL;
NGAP_QosFlowSetupRequestItem_t *QosFlowSetupRequestItem = NULL;
@ -49,6 +50,7 @@ ogs_pkbuf_t *ngap_build_pdu_session_resource_setup_request_transfer(
if (sess->pdn.ambr.downlink || sess->pdn.ambr.uplink) {
ie = CALLOC(1,
sizeof(NGAP_PDUSessionResourceSetupRequestTransferIEs_t));
ogs_assert(ie);
ASN_SEQUENCE_ADD(&message.protocolIEs, ie);
ie->id = NGAP_ProtocolIE_ID_id_PDUSessionAggregateMaximumBitRate;
@ -65,6 +67,7 @@ ogs_pkbuf_t *ngap_build_pdu_session_resource_setup_request_transfer(
}
ie = CALLOC(1, sizeof(NGAP_PDUSessionResourceSetupRequestTransferIEs_t));
ogs_assert(ie);
ASN_SEQUENCE_ADD(&message.protocolIEs, ie);
ie->id = NGAP_ProtocolIE_ID_id_UL_NGU_UP_TNLInformation;
@ -74,6 +77,7 @@ ogs_pkbuf_t *ngap_build_pdu_session_resource_setup_request_transfer(
UPTransportLayerInformation = &ie->value.choice.UPTransportLayerInformation;
gTPTunnel = CALLOC(1, sizeof(struct NGAP_GTPTunnel));
ogs_assert(gTPTunnel);
UPTransportLayerInformation->present =
NGAP_UPTransportLayerInformation_PR_gTPTunnel;
UPTransportLayerInformation->choice.gTPTunnel = gTPTunnel;
@ -83,7 +87,24 @@ ogs_pkbuf_t *ngap_build_pdu_session_resource_setup_request_transfer(
ogs_asn_ip_to_BIT_STRING(&upf_n3_ip, &gTPTunnel->transportLayerAddress);
ogs_asn_uint32_to_OCTET_STRING(sess->upf_n3_teid, &gTPTunnel->gTP_TEID);
if (sess->handover.direct_available == false) {
ie = CALLOC(1,
sizeof(NGAP_PDUSessionResourceSetupRequestTransferIEs_t));
ogs_assert(ie);
ASN_SEQUENCE_ADD(&message.protocolIEs, ie);
ie->id = NGAP_ProtocolIE_ID_id_DataForwardingNotPossible;
ie->criticality = NGAP_Criticality_reject;
ie->value.present = NGAP_PDUSessionResourceSetupRequestTransferIEs__value_PR_DataForwardingNotPossible;
DataForwardingNotPossible = &ie->value.choice.DataForwardingNotPossible;
*DataForwardingNotPossible =
NGAP_DataForwardingNotPossible_data_forwarding_not_possible;
}
ie = CALLOC(1, sizeof(NGAP_PDUSessionResourceSetupRequestTransferIEs_t));
ogs_assert(ie);
ASN_SEQUENCE_ADD(&message.protocolIEs, ie);
ie->id = NGAP_ProtocolIE_ID_id_PDUSessionType;
@ -109,6 +130,7 @@ ogs_pkbuf_t *ngap_build_pdu_session_resource_setup_request_transfer(
}
ie = CALLOC(1, sizeof(NGAP_PDUSessionResourceSetupRequestTransferIEs_t));
ogs_assert(ie);
ASN_SEQUENCE_ADD(&message.protocolIEs, ie);
ie->id = NGAP_ProtocolIE_ID_id_QosFlowSetupRequestList;
@ -120,6 +142,7 @@ ogs_pkbuf_t *ngap_build_pdu_session_resource_setup_request_transfer(
ogs_list_for_each(&sess->bearer_list, qos_flow) {
QosFlowSetupRequestItem =
CALLOC(1, sizeof(struct NGAP_QosFlowSetupRequestItem));
ogs_assert(QosFlowSetupRequestItem);
ASN_SEQUENCE_ADD(&QosFlowSetupRequestList->list,
QosFlowSetupRequestItem);
@ -131,6 +154,7 @@ ogs_pkbuf_t *ngap_build_pdu_session_resource_setup_request_transfer(
&qosFlowLevelQosParameters->allocationAndRetentionPriority;
qosCharacteristics = &qosFlowLevelQosParameters->qosCharacteristics;
nonDynamic5QI = CALLOC(1, sizeof(struct NGAP_NonDynamic5QIDescriptor));
ogs_assert(nonDynamic5QI);
qosCharacteristics->choice.nonDynamic5QI = nonDynamic5QI;
qosCharacteristics->present = NGAP_QosCharacteristics_PR_nonDynamic5QI;
@ -165,6 +189,7 @@ ogs_pkbuf_t *ngap_build_pdu_session_resource_setup_request_transfer(
qosFlowLevelQosParameters->gBR_QosInformation =
gBR_QosInformation = CALLOC(1, sizeof(*gBR_QosInformation));
ogs_assert(gBR_QosInformation);
asn_uint642INTEGER(&gBR_QosInformation->maximumFlowBitRateDL,
qos_flow->qos.mbr.downlink);
@ -339,34 +364,68 @@ 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_ip_t upf_dl_ip;
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);
if (sess->handover.indirect_data_forwarding == true) {
ogs_pfcp_pdr_t *pdr = NULL;
dLForwardingUP_TNLInformation->present =
NGAP_UPTransportLayerInformation_PR_gTPTunnel;
dLForwardingUP_TNLInformation->choice.gTPTunnel = gTPTunnel =
CALLOC(1, sizeof(*gTPTunnel));
ogs_assert(gTPTunnel);
NGAP_UPTransportLayerInformation_t
*dLForwardingUP_TNLInformation = NULL;
NGAP_GTPTunnel_t *gTPTunnel = NULL;
NGAP_QosFlowToBeForwardedList_t *qosFlowToBeForwardedList = NULL;
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
message.dLForwardingUP_TNLInformation = dLForwardingUP_TNLInformation =
CALLOC(1, sizeof(*dLForwardingUP_TNLInformation));
ogs_assert(dLForwardingUP_TNLInformation);
return ogs_asn_encode(
&asn_DEF_NGAP_HandoverCommandTransfer, &message);
dLForwardingUP_TNLInformation->present =
NGAP_UPTransportLayerInformation_PR_gTPTunnel;
dLForwardingUP_TNLInformation->choice.gTPTunnel = gTPTunnel =
CALLOC(1, sizeof(*gTPTunnel));
ogs_assert(gTPTunnel);
ogs_sockaddr_to_ip(
sess->handover.upf_dl_addr, sess->handover.upf_dl_addr6,
&upf_dl_ip);
ogs_asn_ip_to_BIT_STRING(&upf_dl_ip, &gTPTunnel->transportLayerAddress);
ogs_asn_uint32_to_OCTET_STRING(
sess->handover.upf_dl_teid, &gTPTunnel->gTP_TEID);
ogs_list_for_each(&sess->pfcp.pdr_list, pdr) {
ogs_pfcp_far_t *far = pdr->far;
ogs_assert(far);
if (pdr->src_if == OGS_PFCP_INTERFACE_ACCESS &&
far->dst_if == OGS_PFCP_INTERFACE_ACCESS) {
NGAP_QosFlowToBeForwardedItem_t *qosFlowToBeForwardedItem;
NGAP_QosFlowIdentifier_t *qosFlowIdentifier = NULL;
if (!qosFlowToBeForwardedList) {
message.qosFlowToBeForwardedList =
qosFlowToBeForwardedList =
CALLOC(1, sizeof(*qosFlowToBeForwardedList));
ogs_assert(qosFlowToBeForwardedList);
}
qosFlowToBeForwardedItem =
CALLOC(1, sizeof(*qosFlowToBeForwardedItem));
ogs_assert(qosFlowToBeForwardedItem);
ASN_SEQUENCE_ADD(&qosFlowToBeForwardedList->list,
qosFlowToBeForwardedItem);
qosFlowIdentifier =
&qosFlowToBeForwardedItem->qosFlowIdentifier;
*qosFlowIdentifier = pdr->qfi;
}
}
}
return ogs_asn_encode(&asn_DEF_NGAP_HandoverCommandTransfer, &message);
}

View File

@ -26,13 +26,11 @@ int ngap_handle_pdu_session_resource_setup_response_transfer(
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;
uint32_t gnb_n3_teid;
ogs_ip_t gnb_n3_ip;
ogs_pfcp_far_t *dl_far = NULL;
bool far_update = false;
NGAP_PDUSessionResourceSetupResponseTransfer_t message;
@ -111,11 +109,11 @@ int ngap_handle_pdu_session_resource_setup_response_transfer(
associatedQosFlowList->list.array[i];
if (associatedQosFlowItem) {
qos_flow = smf_qos_flow_find_by_qfi(sess,
associatedQosFlowItem->qosFlowIdentifier);
smf_bearer_t *qos_flow = smf_qos_flow_find_by_qfi(
sess, associatedQosFlowItem->qosFlowIdentifier);
if (qos_flow) {
dl_far = qos_flow->dl_far;
ogs_pfcp_far_t *dl_far = qos_flow->dl_far;
ogs_assert(dl_far);
if (dl_far->apply_action != OGS_PFCP_APPLY_ACTION_FORW) {
far_update = true;
@ -139,7 +137,8 @@ int ngap_handle_pdu_session_resource_setup_response_transfer(
if (far_update) {
smf_5gc_pfcp_send_session_modification_request(
sess, stream, OGS_PFCP_MODIFY_ACTIVATE);
sess, stream, OGS_PFCP_MODIFY_DL_ONLY|OGS_PFCP_MODIFY_ACTIVATE,
0);
} else {
/* ACTIVATED Is NOT Included in RESPONSE */
smf_sbi_send_http_status_no_content(stream);
@ -235,13 +234,11 @@ 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;
smf_bearer_t *qos_flow = NULL;
int rv, i;
uint32_t gnb_n3_teid;
ogs_ip_t gnb_n3_ip;
ogs_pfcp_far_t *dl_far = NULL;
bool far_update = false;
NGAP_PathSwitchRequestTransfer_t message;
@ -311,11 +308,11 @@ int ngap_handle_path_switch_request_transfer(
acceptedQosFlowItem = (NGAP_QosFlowAcceptedItem_t *)
qosFlowAcceptedList->list.array[i];
if (acceptedQosFlowItem) {
qos_flow = smf_qos_flow_find_by_qfi(sess,
acceptedQosFlowItem->qosFlowIdentifier);
smf_bearer_t *qos_flow = smf_qos_flow_find_by_qfi(
sess, acceptedQosFlowItem->qosFlowIdentifier);
if (qos_flow) {
dl_far = qos_flow->dl_far;
ogs_pfcp_far_t *dl_far = qos_flow->dl_far;
ogs_assert(dl_far);
if (dl_far->apply_action != OGS_PFCP_APPLY_ACTION_FORW) {
far_update = true;
@ -340,8 +337,9 @@ int ngap_handle_path_switch_request_transfer(
if (far_update) {
smf_5gc_pfcp_send_session_modification_request(
sess, stream,
OGS_PFCP_MODIFY_ACTIVATE | OGS_PFCP_MODIFY_XN_HANDOVER |
OGS_PFCP_MODIFY_END_MARKER);
OGS_PFCP_MODIFY_DL_ONLY|OGS_PFCP_MODIFY_ACTIVATE|
OGS_PFCP_MODIFY_XN_HANDOVER|OGS_PFCP_MODIFY_END_MARKER,
0);
} else {
/* ACTIVATED Is NOT Included in RESPONSE */
smf_sbi_send_http_status_no_content(stream);
@ -362,6 +360,9 @@ int ngap_handle_handover_required_transfer(
NGAP_HandoverRequiredTransfer_t message;
NGAP_DirectForwardingPathAvailability_t
*directForwardingPathAvailability = NULL;
ogs_pkbuf_t *n2smbuf = NULL;
ogs_assert(pkbuf);
@ -382,6 +383,13 @@ int ngap_handle_handover_required_transfer(
goto cleanup;
}
directForwardingPathAvailability = message.directForwardingPathAvailability;
if (directForwardingPathAvailability) {
sess->handover.direct_available = true;
} else {
sess->handover.direct_available = false;
}
n2smbuf = ngap_build_pdu_session_resource_setup_request_transfer(sess);
ogs_assert(n2smbuf);
@ -400,20 +408,16 @@ 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_UPTransportLayerInformation_t *dLForwardingUP_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);
@ -456,23 +460,21 @@ int ngap_handle_handover_request_ack(
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);
smf_bearer_t *qos_flow = smf_qos_flow_find_by_qfi(
sess, qosFlowSetupResponseItem->qosFlowIdentifier);
if (qos_flow) {
dl_far = qos_flow->dl_far;
ogs_pfcp_far_t *dl_far = qos_flow->dl_far;
ogs_assert(dl_far);
dl_far->handover.prepared = true;
@ -487,12 +489,78 @@ int ngap_handle_handover_request_ack(
}
}
n2smbuf = ngap_build_handover_command_transfer(sess);
ogs_assert(n2smbuf);
dLForwardingUP_TNLInformation = message.dLForwardingUP_TNLInformation;
if (dLForwardingUP_TNLInformation) {
if (dLForwardingUP_TNLInformation->present !=
NGAP_UPTransportLayerInformation_PR_gTPTunnel) {
ogs_error(
"[%s:%d] Unknown dLForwardingUP_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 dLForwardingUP_TNLInformation->present",
smf_ue->supi, NULL, NULL);
goto cleanup;
}
smf_sbi_send_sm_context_updated_data(
sess, stream, 0, OpenAPI_ho_state_PREPARED,
NULL, OpenAPI_n2_sm_info_type_HANDOVER_CMD, n2smbuf);
gTPTunnel = dLForwardingUP_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;
}
ogs_asn_BIT_STRING_to_ip(&gTPTunnel->transportLayerAddress,
&sess->handover.gnb_dl_ip);
ogs_asn_OCTET_STRING_to_uint32(&gTPTunnel->gTP_TEID,
&sess->handover.gnb_dl_teid);
sess->handover.indirect_data_forwarding = true;
}
sess->handover.prepared = true;
if (sess->handover.indirect_data_forwarding == true) {
if (smf_sess_have_indirect_data_forwarding(sess) == true) {
ogs_error("We found redundant INDIRECT Tunnel");
ogs_error("It will be automatically removed");
smf_5gc_pfcp_send_session_modification_request(
sess, stream,
OGS_PFCP_MODIFY_INDIRECT|
/*
* Firstly, OGS_PFCP_MODIFY_REMOVE is only appled.
* And then, after receiving PFCP response message,
* we can apply OGS_PFCP_MODIFY_CREATE.
*
* PFCP build is implemented as below.
*
* if OGS_PFCP_MODIFY_REMOVE
* else if OGS_PFCP_MODIFY_CREATE
* else if ..
* ...
*/
OGS_PFCP_MODIFY_REMOVE|OGS_PFCP_MODIFY_CREATE,
0);
} else {
smf_sess_create_indirect_data_forwarding(sess);
smf_5gc_pfcp_send_session_modification_request(
sess, stream,
OGS_PFCP_MODIFY_INDIRECT|OGS_PFCP_MODIFY_CREATE,
0);
}
} else {
ogs_pkbuf_t *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;

View File

@ -350,7 +350,9 @@ bool smf_nsmf_handle_update_sm_context(
* Handle DEACTIVATED
********************************************************/
smf_5gc_pfcp_send_session_modification_request(
sess, stream, OGS_PFCP_MODIFY_DEACTIVATE);
sess, stream,
OGS_PFCP_MODIFY_DL_ONLY|OGS_PFCP_MODIFY_DEACTIVATE,
0);
} else if (SmContextUpdateData->up_cnx_state ==
OpenAPI_up_cnx_state_ACTIVATING) {
@ -402,7 +404,6 @@ bool smf_nsmf_handle_update_sm_context(
sendmsg.SmContextUpdatedData = &SmContextUpdatedData;
memset(&SmContextUpdatedData, 0, sizeof(SmContextUpdatedData));
/* Only ACTIVING & DEACTIVATED is Included */
SmContextUpdatedData.up_cnx_state = OpenAPI_up_cnx_state_ACTIVATING;
SmContextUpdatedData.n2_sm_info_type =
OpenAPI_n2_sm_info_type_PDU_RES_SETUP_REQ;
@ -484,8 +485,9 @@ bool smf_nsmf_handle_update_sm_context(
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);
OGS_PFCP_MODIFY_DL_ONLY|OGS_PFCP_MODIFY_ACTIVATE|
OGS_PFCP_MODIFY_N2_HANDOVER|OGS_PFCP_MODIFY_END_MARKER,
0);
} else {
char *strerror = ogs_msprintf(
"[%s:%d] No FAR Update", smf_ue->supi, sess->psi);
@ -512,8 +514,16 @@ bool smf_nsmf_handle_update_sm_context(
dl_far->handover.prepared = false;
}
smf_sbi_send_sm_context_updated_data_ho_state(
sess, stream, OpenAPI_ho_state_CANCELLED);
if (smf_sess_have_indirect_data_forwarding(sess) == true) {
smf_5gc_pfcp_send_session_modification_request(
sess, stream,
OGS_PFCP_MODIFY_INDIRECT|OGS_PFCP_MODIFY_REMOVE|
OGS_PFCP_MODIFY_HANDOVER_CANCEL,
0);
} else {
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]",

View File

@ -330,7 +330,8 @@ void smf_5gc_pfcp_send_session_establishment_request(
}
void smf_5gc_pfcp_send_session_modification_request(
smf_sess_t *sess, ogs_sbi_stream_t *stream, uint64_t flags)
smf_sess_t *sess, ogs_sbi_stream_t *stream,
uint64_t flags, ogs_time_t duration)
{
int rv;
ogs_pkbuf_t *n4buf = NULL;
@ -354,8 +355,12 @@ void smf_5gc_pfcp_send_session_modification_request(
xact->assoc_stream = stream;
xact->modify_flags = flags | OGS_PFCP_MODIFY_SESSION;
rv = ogs_pfcp_xact_commit(xact);
ogs_expect(rv == OGS_OK);
if (duration) {
ogs_pfcp_xact_delayed_commit(xact, duration);
} else {
rv = ogs_pfcp_xact_commit(xact);
ogs_expect(rv == OGS_OK);
}
}
void smf_5gc_pfcp_send_qos_flow_modification_request(smf_bearer_t *qos_flow,

View File

@ -32,7 +32,8 @@ void smf_pfcp_close(void);
void smf_5gc_pfcp_send_session_establishment_request(
smf_sess_t *sess, ogs_sbi_stream_t *stream);
void smf_5gc_pfcp_send_session_modification_request(
smf_sess_t *sess, ogs_sbi_stream_t *stream, uint64_t flags);
smf_sess_t *sess, ogs_sbi_stream_t *stream,
uint64_t flags, ogs_time_t duration);
void smf_5gc_pfcp_send_qos_flow_modification_request(smf_bearer_t *qos_flow,
ogs_sbi_stream_t *stream, uint64_t flags);
void smf_5gc_pfcp_send_session_deletion_request(

View File

@ -227,6 +227,7 @@ static void _gtpv1_u_recv_cb(short when, ogs_socket_t fd, void *data)
struct ip *ip_h = NULL;
ogs_pfcp_pdr_t *pdr = NULL;
ogs_pfcp_far_t *far = NULL;
upf_sess_t *sess = NULL;
ogs_pfcp_subnet_t *subnet = NULL;
@ -240,38 +241,60 @@ static void _gtpv1_u_recv_cb(short when, ogs_socket_t fd, void *data)
/* TODO : Send Error Indication */
goto cleanup;
}
ogs_assert(pdr->sess);
sess = UPF_SESS(pdr->sess);
ogs_assert(sess);
if (ip_h->ip_v == 4 && sess->ipv4)
subnet = sess->ipv4->subnet;
else if (ip_h->ip_v == 6 && sess->ipv6)
subnet = sess->ipv6->subnet;
far = pdr->far;
ogs_assert(far);
if (!subnet) {
if (far->dst_if == OGS_PFCP_INTERFACE_ACCESS) {
ogs_pfcp_up_handle_pdr(pdr, pkbuf, &report);
if (report.type.downlink_data_report) {
ogs_error("Indirect Data Fowarding Buffered");
report.downlink_data.pdr_id = pdr->id;
if (pdr->qer && pdr->qer->qfi)
report.downlink_data.qfi = pdr->qer->qfi; /* for 5GC */
upf_pfcp_send_session_report_request(sess, &report);
}
} else if (far->dst_if == OGS_PFCP_INTERFACE_CORE) {
if (ip_h->ip_v == 4 && sess->ipv4)
subnet = sess->ipv4->subnet;
else if (ip_h->ip_v == 6 && sess->ipv6)
subnet = sess->ipv6->subnet;
if (!subnet) {
#if 0 /* It's redundant log message */
ogs_error("[DROP] Cannot find subnet V:%d, IPv4:%p, IPv6:%p",
ip_h->ip_v, sess->ipv4, sess->ipv6);
ogs_log_hexdump(OGS_LOG_ERROR, pkbuf->data, pkbuf->len);
ogs_error("[DROP] Cannot find subnet V:%d, IPv4:%p, IPv6:%p",
ip_h->ip_v, sess->ipv4, sess->ipv6);
ogs_log_hexdump(OGS_LOG_ERROR, pkbuf->data, pkbuf->len);
#endif
goto cleanup;
}
/* Check IPv6 */
if (ogs_app()->parameter.no_slaac == 0 && ip_h->ip_v == 6) {
rv = upf_gtp_handle_slaac(sess, pkbuf);
if (rv == UPF_GTP_HANDLED) {
goto cleanup;
}
ogs_assert(rv == OGS_OK);
}
dev = subnet->dev;
ogs_assert(dev);
if (ogs_write(dev->fd, pkbuf->data, pkbuf->len) <= 0) {
ogs_log_message(OGS_LOG_ERROR,
ogs_socket_errno, "ogs_write() failed");
/* Check IPv6 */
if (ogs_app()->parameter.no_slaac == 0 && ip_h->ip_v == 6) {
rv = upf_gtp_handle_slaac(sess, pkbuf);
if (rv == UPF_GTP_HANDLED) {
goto cleanup;
}
ogs_assert(rv == OGS_OK);
}
dev = subnet->dev;
ogs_assert(dev);
if (ogs_write(dev->fd, pkbuf->data, pkbuf->len) <= 0) {
ogs_log_message(OGS_LOG_ERROR,
ogs_socket_errno, "ogs_write() failed");
}
} else {
ogs_fatal("Not implemented : FAR-DST_IF[%d]", far->dst_if);
ogs_assert_if_reached();
}
} else {
ogs_error("[DROP] Invalid GTPU Type [%d]", gtp_h->type);

View File

@ -418,6 +418,14 @@ typedef struct test_sess_s {
test_pdn_connectivity_param_t pdn_connectivity_param;
test_esm_information_param_t esm_information_param;
struct {
bool data_forwarding_not_possible;
/* Indirect DL Forwarding */
uint32_t upf_dl_teid;
ogs_ip_t upf_dl_ip;
} handover;
ogs_list_t bearer_list;
test_ue_t *test_ue;

View File

@ -327,8 +327,6 @@ int test_gtpu_send_error_indication(
sess = bearer->sess;
ogs_assert(sess);
ogs_assert(bearer);
if (bearer->qfi) {
/* 5GC */
teid = sess->gnb_n3_teid;
@ -354,3 +352,38 @@ int test_gtpu_send_error_indication(
return test_gtpu_send(node, bearer, &gtp_hdesc, &ext_hdesc, pkbuf);
}
int test_gtpu_send_indirect_data_forwarding(
ogs_socknode_t *node, test_bearer_t *bearer, ogs_pkbuf_t *pkbuf)
{
test_sess_t *sess = NULL;
ogs_gtp_header_t gtp_hdesc;
ogs_gtp_extension_header_t ext_hdesc;
ogs_assert(bearer);
sess = bearer->sess;
ogs_assert(sess);
ogs_assert(pkbuf);
memset(&gtp_hdesc, 0, sizeof(gtp_hdesc));
memset(&ext_hdesc, 0, sizeof(ext_hdesc));
gtp_hdesc.type = OGS_GTPU_MSGTYPE_GPDU;
if (bearer->qfi) {
gtp_hdesc.teid = sess->handover.upf_dl_teid;
ext_hdesc.qos_flow_identifier = bearer->qfi;
} else if (bearer->ebi) {
ogs_fatal("Not implmented EPC Indirect Tunnel");
ogs_assert_if_reached();
} else {
ogs_fatal("No QFI[%d] and EBI[%d]", bearer->qfi, bearer->ebi);
ogs_assert_if_reached();
}
return test_gtpu_send(node, bearer, &gtp_hdesc, &ext_hdesc, pkbuf);
}

View File

@ -40,6 +40,8 @@ int test_gtpu_send_ping(
int test_gtpu_send_slacc_rs(ogs_socknode_t *node, test_bearer_t *bearer);
int test_gtpu_send_error_indication(
ogs_socknode_t *node, test_bearer_t *bearer);
int test_gtpu_send_indirect_data_forwarding(
ogs_socknode_t *node, test_bearer_t *bearer, ogs_pkbuf_t *pkbuf);
#ifdef __cplusplus
}

View File

@ -1607,7 +1607,6 @@ ogs_pkbuf_t *testngap_build_handover_request_ack(test_ue_t *test_ue)
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;
@ -1657,6 +1656,7 @@ ogs_pkbuf_t *testngap_build_handover_request_ack(test_ue_t *test_ue)
*RAN_UE_NGAP_ID = test_ue->ran_ue_ngap_id;
ogs_list_for_each(&test_ue->sess_list, sess) {
NGAP_PDUSessionResourceAdmittedItem_t *PDUSessionItem = NULL;
OCTET_STRING_t *transfer = NULL;
ogs_pkbuf_t *n2smbuf = NULL;
@ -1672,8 +1672,7 @@ ogs_pkbuf_t *testngap_build_handover_request_ack(test_ue_t *test_ue)
PDUSessionList = &ie->value.choice.PDUSessionResourceAdmittedList;
}
PDUSessionItem = CALLOC(1,
sizeof(struct NGAP_PDUSessionResourceAdmittedItem));
PDUSessionItem = CALLOC(1, sizeof(*PDUSessionItem));
ogs_assert(PDUSessionItem);
ASN_SEQUENCE_ADD(&PDUSessionList->list, PDUSessionItem);
@ -2203,6 +2202,7 @@ static ogs_pkbuf_t *testngap_build_handover_request_ack_transfer(
NGAP_HandoverRequestAcknowledgeTransfer_t message;
NGAP_UPTransportLayerInformation_t *dL_NGU_UP_TNLInformation = NULL;
NGAP_UPTransportLayerInformation_t *dLForwardingUP_TNLInformation = NULL;
NGAP_QosFlowListWithDataForwarding_t *qosFlowSetupResponseList = NULL;
NGAP_QosFlowItemWithDataForwarding_t *qosFlowSetupResponseItem = NULL;
NGAP_GTPTunnel_t *gTPTunnel = NULL;
@ -2214,7 +2214,7 @@ static ogs_pkbuf_t *testngap_build_handover_request_ack_transfer(
dL_NGU_UP_TNLInformation->present =
NGAP_UPTransportLayerInformation_PR_gTPTunnel;
dL_NGU_UP_TNLInformation->choice.gTPTunnel = gTPTunnel =
CALLOC(1, sizeof(struct NGAP_GTPTunnel));
CALLOC(1, sizeof(*gTPTunnel));
ogs_assert(gTPTunnel);
ogs_assert(sess->gnb_n3_addr || sess->gnb_n3_addr6);
@ -2228,6 +2228,25 @@ static ogs_pkbuf_t *testngap_build_handover_request_ack_transfer(
ogs_asn_ip_to_BIT_STRING(&ip, &gTPTunnel->transportLayerAddress);
ogs_asn_uint32_to_OCTET_STRING(sess->gnb_n3_teid, &gTPTunnel->gTP_TEID);
if (sess->handover.data_forwarding_not_possible) {
NGAP_GTPTunnel_t *gTPTunnelForDLForwarding = NULL;
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 =
gTPTunnelForDLForwarding =
CALLOC(1, sizeof(*gTPTunnelForDLForwarding));
ogs_assert(gTPTunnelForDLForwarding);
ogs_asn_ip_to_BIT_STRING(&ip,
&gTPTunnelForDLForwarding->transportLayerAddress);
ogs_asn_uint32_to_OCTET_STRING(sess->gnb_n3_teid+10,
&gTPTunnelForDLForwarding->gTP_TEID);
}
qosFlowSetupResponseList = &message.qosFlowSetupResponseList;
ogs_list_for_each(&sess->bearer_list, qos_flow) {

View File

@ -604,15 +604,24 @@ void testngap_handle_pdu_session_resource_release_command(
void testngap_handle_handover_request(
test_ue_t *test_ue, ogs_ngap_message_t *message)
{
int rv, i;
int rv, i, j, k;
char buf[OGS_ADDRSTRLEN];
test_sess_t *sess = NULL;
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;
NGAP_PDUSessionResourceSetupListHOReq_t *PDUSessionList = NULL;
NGAP_PDUSessionResourceSetupItemHOReq_t *PDUSessionItem = NULL;
NGAP_PDUSessionResourceSetupRequestTransfer_t n2sm_message;
NGAP_PDUSessionResourceSetupRequestTransferIEs_t *ie2 = NULL;
OCTET_STRING_t *transfer = NULL;
ogs_pkbuf_t *n2smbuf = NULL;
ogs_assert(test_ue);
ogs_assert(message);
@ -628,6 +637,8 @@ void testngap_handle_handover_request(
case NGAP_ProtocolIE_ID_id_AMF_UE_NGAP_ID:
AMF_UE_NGAP_ID = &ie->value.choice.AMF_UE_NGAP_ID;
break;
case NGAP_ProtocolIE_ID_id_PDUSessionResourceSetupListHOReq:
PDUSessionList = &ie->value.choice.PDUSessionResourceSetupListHOReq;
default:
break;
}
@ -638,4 +649,299 @@ void testngap_handle_handover_request(
asn_INTEGER2ulong(AMF_UE_NGAP_ID, (unsigned long *)&amf_ue_ngap_id);
test_ue->amf_ue_ngap_id = (uint64_t)amf_ue_ngap_id;
}
if (PDUSessionList) {
for (j = 0; j < PDUSessionList->list.count; j++) {
PDUSessionItem = (NGAP_PDUSessionResourceSetupItemHOReq_t *)
PDUSessionList->list.array[j];
ogs_assert(PDUSessionItem);
sess = test_sess_find_by_psi(
test_ue, PDUSessionItem->pDUSessionID);
ogs_assert(sess);
transfer = &PDUSessionItem->handoverRequestTransfer;
ogs_assert(transfer);
n2smbuf = ogs_pkbuf_alloc(NULL, OGS_MAX_SDU_LEN);
ogs_assert(n2smbuf);
ogs_pkbuf_put_data(n2smbuf, transfer->buf, transfer->size);
rv = ogs_asn_decode(
&asn_DEF_NGAP_PDUSessionResourceSetupRequestTransfer,
&n2sm_message, sizeof(n2sm_message), n2smbuf);
ogs_assert(rv == OGS_OK);
for (k = 0; k < n2sm_message.protocolIEs.list.count; k++) {
ie2 = n2sm_message.protocolIEs.list.array[k];
switch (ie2->id) {
case NGAP_ProtocolIE_ID_id_DataForwardingNotPossible:
sess->handover.data_forwarding_not_possible = true;
break;
default:
break;
}
}
ogs_asn_free(
&asn_DEF_NGAP_PDUSessionResourceSetupRequestTransfer,
&n2sm_message);
ogs_pkbuf_free(n2smbuf);
}
}
}
void testngap_handle_handover_command(
test_ue_t *test_ue, ogs_ngap_message_t *message)
{
int rv, i, j;
char buf[OGS_ADDRSTRLEN];
test_sess_t *sess = NULL;
NGAP_NGAP_PDU_t pdu;
NGAP_SuccessfulOutcome_t *successfulOutcome = NULL;
NGAP_HandoverCommand_t *HandoverCommand = NULL;
NGAP_HandoverCommandIEs_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_PDUSessionResourceHandoverList_t *PDUSessionList = NULL;
NGAP_PDUSessionResourceHandoverItem_t *PDUSessionItem = NULL;
NGAP_HandoverCommandTransfer_t n2sm_message;
OCTET_STRING_t *transfer = NULL;
ogs_pkbuf_t *n2smbuf = NULL;
ogs_assert(test_ue);
ogs_assert(message);
successfulOutcome = message->choice.successfulOutcome;
ogs_assert(successfulOutcome);
HandoverCommand = &successfulOutcome->value.choice.HandoverCommand;
ogs_assert(HandoverCommand);
for (i = 0; i < HandoverCommand->protocolIEs.list.count; i++) {
ie = HandoverCommand->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;
case NGAP_ProtocolIE_ID_id_RAN_UE_NGAP_ID:
RAN_UE_NGAP_ID = &ie->value.choice.RAN_UE_NGAP_ID;
break;
case NGAP_ProtocolIE_ID_id_PDUSessionResourceHandoverList:
PDUSessionList =
&ie->value.choice.PDUSessionResourceHandoverList;
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;
}
if (RAN_UE_NGAP_ID) {
test_ue->ran_ue_ngap_id = *RAN_UE_NGAP_ID;
}
if (PDUSessionList) {
for (j = 0; j < PDUSessionList->list.count; j++) {
NGAP_UPTransportLayerInformation_t *dLForwardingUP_TNLInformation;
PDUSessionItem = (NGAP_PDUSessionResourceHandoverItem_t *)
PDUSessionList->list.array[j];
ogs_assert(PDUSessionItem);
sess = test_sess_find_by_psi(
test_ue, PDUSessionItem->pDUSessionID);
ogs_assert(sess);
transfer = &PDUSessionItem->handoverCommandTransfer;
ogs_assert(transfer);
n2smbuf = ogs_pkbuf_alloc(NULL, OGS_MAX_SDU_LEN);
ogs_assert(n2smbuf);
ogs_pkbuf_put_data(n2smbuf, transfer->buf, transfer->size);
rv = ogs_asn_decode(
&asn_DEF_NGAP_HandoverCommandTransfer,
&n2sm_message, sizeof(n2sm_message), n2smbuf);
ogs_assert(rv == OGS_OK);
dLForwardingUP_TNLInformation =
n2sm_message.dLForwardingUP_TNLInformation;
if (dLForwardingUP_TNLInformation) {
if (dLForwardingUP_TNLInformation->present ==
NGAP_UPTransportLayerInformation_PR_gTPTunnel) {
NGAP_GTPTunnel_t *gTPTunnel =
dLForwardingUP_TNLInformation->choice.gTPTunnel;
if (gTPTunnel) {
ogs_asn_BIT_STRING_to_ip(
&gTPTunnel->transportLayerAddress,
&sess->handover.upf_dl_ip);
ogs_asn_OCTET_STRING_to_uint32(
&gTPTunnel->gTP_TEID,
&sess->handover.upf_dl_teid);
}
}
}
ogs_asn_free(
&asn_DEF_NGAP_HandoverCommandTransfer,
&n2sm_message);
ogs_pkbuf_free(n2smbuf);
}
}
}
void testngap_handle_handover_preparation_failure(
test_ue_t *test_ue, ogs_ngap_message_t *message)
{
int rv, i, j;
char buf[OGS_ADDRSTRLEN];
test_sess_t *sess = NULL;
NGAP_NGAP_PDU_t pdu;
NGAP_UnsuccessfulOutcome_t *unsuccessfulOutcome = NULL;
NGAP_HandoverPreparationFailure_t *HandoverPreparationFailure = NULL;
NGAP_HandoverPreparationFailureIEs_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;
ogs_assert(test_ue);
ogs_assert(message);
unsuccessfulOutcome = message->choice.unsuccessfulOutcome;
ogs_assert(unsuccessfulOutcome);
HandoverPreparationFailure =
&unsuccessfulOutcome->value.choice.HandoverPreparationFailure;
ogs_assert(HandoverPreparationFailure);
for (i = 0; i < HandoverPreparationFailure->protocolIEs.list.count; i++) {
ie = HandoverPreparationFailure->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;
case NGAP_ProtocolIE_ID_id_RAN_UE_NGAP_ID:
RAN_UE_NGAP_ID = &ie->value.choice.RAN_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;
}
if (RAN_UE_NGAP_ID) {
test_ue->ran_ue_ngap_id = *RAN_UE_NGAP_ID;
}
}
void testngap_handle_handover_cancel_ack(
test_ue_t *test_ue, ogs_ngap_message_t *message)
{
int rv, i, j;
char buf[OGS_ADDRSTRLEN];
test_sess_t *sess = NULL;
NGAP_NGAP_PDU_t pdu;
NGAP_SuccessfulOutcome_t *successfulOutcome = NULL;
NGAP_HandoverCancelAcknowledge_t *HandoverCancelAcknowledge = NULL;
NGAP_HandoverCancelAcknowledgeIEs_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;
ogs_assert(test_ue);
ogs_assert(message);
successfulOutcome = message->choice.successfulOutcome;
ogs_assert(successfulOutcome);
HandoverCancelAcknowledge = &successfulOutcome->value.choice.HandoverCancelAcknowledge;
ogs_assert(HandoverCancelAcknowledge);
for (i = 0; i < HandoverCancelAcknowledge->protocolIEs.list.count; i++) {
ie = HandoverCancelAcknowledge->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;
case NGAP_ProtocolIE_ID_id_RAN_UE_NGAP_ID:
RAN_UE_NGAP_ID = &ie->value.choice.RAN_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;
}
if (RAN_UE_NGAP_ID) {
test_ue->ran_ue_ngap_id = *RAN_UE_NGAP_ID;
}
}
void testngap_handle_downlink_ran_status_transfer(
test_ue_t *test_ue, ogs_ngap_message_t *message)
{
int i;
char buf[OGS_ADDRSTRLEN];
NGAP_NGAP_PDU_t pdu;
NGAP_InitiatingMessage_t *initiatingMessage = NULL;
NGAP_DownlinkRANStatusTransfer_t *DownlinkRANStatusTransfer = NULL;
NGAP_DownlinkRANStatusTransferIEs_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;
ogs_assert(test_ue);
ogs_assert(message);
initiatingMessage = message->choice.initiatingMessage;
ogs_assert(initiatingMessage);
DownlinkRANStatusTransfer =
&initiatingMessage->value.choice.DownlinkRANStatusTransfer;
ogs_assert(DownlinkRANStatusTransfer);
for (i = 0; i < DownlinkRANStatusTransfer->protocolIEs.list.count; i++) {
ie = DownlinkRANStatusTransfer->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;
case NGAP_ProtocolIE_ID_id_RAN_UE_NGAP_ID:
RAN_UE_NGAP_ID = &ie->value.choice.RAN_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;
}
if (RAN_UE_NGAP_ID) {
test_ue->ran_ue_ngap_id = *RAN_UE_NGAP_ID;
}
}

View File

@ -43,6 +43,14 @@ void testngap_handle_pdu_session_resource_release_command(
void testngap_handle_handover_request(
test_ue_t *test_ue, ogs_ngap_message_t *message);
void testngap_handle_handover_command(
test_ue_t *test_ue, ogs_ngap_message_t *message);
void testngap_handle_handover_preparation_failure(
test_ue_t *test_ue, ogs_ngap_message_t *message);
void testngap_handle_handover_cancel_ack(
test_ue_t *test_ue, ogs_ngap_message_t *message);
void testngap_handle_downlink_ran_status_transfer(
test_ue_t *test_ue, ogs_ngap_message_t *message);
#ifdef __cplusplus
}

View File

@ -71,6 +71,7 @@ void testngap_recv(test_ue_t *test_ue, ogs_pkbuf_t *pkbuf)
testngap_handle_handover_request(test_ue, pdu);
break;
case NGAP_ProcedureCode_id_DownlinkRANStatusTransfer:
testngap_handle_downlink_ran_status_transfer(test_ue, pdu);
break;
case NGAP_ProcedureCode_id_ErrorIndication:
case NGAP_ProcedureCode_id_Paging:
@ -96,8 +97,10 @@ void testngap_recv(test_ue_t *test_ue, ogs_pkbuf_t *pkbuf)
case NGAP_ProcedureCode_id_PathSwitchRequest:
break;
case NGAP_ProcedureCode_id_HandoverPreparation:
testngap_handle_handover_command(test_ue, pdu);
break;
case NGAP_ProcedureCode_id_HandoverCancel:
testngap_handle_handover_cancel_ack(test_ue, pdu);
break;
case NGAP_ProcedureCode_id_NGReset:
break;
@ -118,6 +121,7 @@ void testngap_recv(test_ue_t *test_ue, ogs_pkbuf_t *pkbuf)
case NGAP_ProcedureCode_id_NGSetup:
break;
case NGAP_ProcedureCode_id_HandoverPreparation:
testngap_handle_handover_preparation_failure(test_ue, pdu);
break;
default:
ogs_error("Not implemented(choice:%d, proc:%d)",

View File

@ -399,3 +399,178 @@ void tests1ap_handle_handover_request(
if (MME_UE_S1AP_ID)
test_ue->mme_ue_s1ap_id = *MME_UE_S1AP_ID;
}
void tests1ap_handle_handover_command(
test_ue_t *test_ue, ogs_s1ap_message_t *message)
{
int i;
char buf[OGS_ADDRSTRLEN];
test_sess_t *sess = NULL;
S1AP_S1AP_PDU_t pdu;
S1AP_SuccessfulOutcome_t *successfulOutcome = NULL;
S1AP_HandoverCommand_t *HandoverCommand = NULL;
S1AP_HandoverCommandIEs_t *ie = NULL;
S1AP_MME_UE_S1AP_ID_t *MME_UE_S1AP_ID = NULL;
S1AP_ENB_UE_S1AP_ID_t *ENB_UE_S1AP_ID = NULL;
ogs_assert(test_ue);
ogs_assert(message);
successfulOutcome = message->choice.successfulOutcome;
ogs_assert(successfulOutcome);
HandoverCommand = &successfulOutcome->value.choice.HandoverCommand;
ogs_assert(HandoverCommand);
for (i = 0; i < HandoverCommand->protocolIEs.list.count; i++) {
ie = HandoverCommand->protocolIEs.list.array[i];
switch (ie->id) {
case S1AP_ProtocolIE_ID_id_MME_UE_S1AP_ID:
MME_UE_S1AP_ID = &ie->value.choice.MME_UE_S1AP_ID;
break;
case S1AP_ProtocolIE_ID_id_eNB_UE_S1AP_ID:
ENB_UE_S1AP_ID = &ie->value.choice.ENB_UE_S1AP_ID;
break;
default:
break;
}
}
if (MME_UE_S1AP_ID)
test_ue->mme_ue_s1ap_id = *MME_UE_S1AP_ID;
if (ENB_UE_S1AP_ID)
test_ue->enb_ue_s1ap_id = *ENB_UE_S1AP_ID;
}
void tests1ap_handle_handover_preparation_failure(
test_ue_t *test_ue, ogs_s1ap_message_t *message)
{
int i;
char buf[OGS_ADDRSTRLEN];
test_sess_t *sess = NULL;
S1AP_S1AP_PDU_t pdu;
S1AP_UnsuccessfulOutcome_t *unsuccessfulOutcome = NULL;
S1AP_HandoverPreparationFailure_t *HandoverPreparationFailure = NULL;
S1AP_HandoverPreparationFailureIEs_t *ie = NULL;
S1AP_MME_UE_S1AP_ID_t *MME_UE_S1AP_ID = NULL;
S1AP_ENB_UE_S1AP_ID_t *ENB_UE_S1AP_ID = NULL;
ogs_assert(test_ue);
ogs_assert(message);
unsuccessfulOutcome = message->choice.unsuccessfulOutcome;
ogs_assert(unsuccessfulOutcome);
HandoverPreparationFailure =
&unsuccessfulOutcome->value.choice.HandoverPreparationFailure;
ogs_assert(HandoverPreparationFailure);
for (i = 0; i < HandoverPreparationFailure->protocolIEs.list.count; i++) {
ie = HandoverPreparationFailure->protocolIEs.list.array[i];
switch (ie->id) {
case S1AP_ProtocolIE_ID_id_MME_UE_S1AP_ID:
MME_UE_S1AP_ID = &ie->value.choice.MME_UE_S1AP_ID;
break;
case S1AP_ProtocolIE_ID_id_eNB_UE_S1AP_ID:
ENB_UE_S1AP_ID = &ie->value.choice.ENB_UE_S1AP_ID;
break;
default:
break;
}
}
if (MME_UE_S1AP_ID)
test_ue->mme_ue_s1ap_id = *MME_UE_S1AP_ID;
if (ENB_UE_S1AP_ID)
test_ue->enb_ue_s1ap_id = *ENB_UE_S1AP_ID;
}
void tests1ap_handle_handover_cancel_ack(
test_ue_t *test_ue, ogs_s1ap_message_t *message)
{
int i;
char buf[OGS_ADDRSTRLEN];
test_sess_t *sess = NULL;
S1AP_S1AP_PDU_t pdu;
S1AP_SuccessfulOutcome_t *successfulOutcome = NULL;
S1AP_HandoverCancelAcknowledge_t *HandoverCancelAcknowledge = NULL;
S1AP_HandoverCancelAcknowledgeIEs_t *ie = NULL;
S1AP_MME_UE_S1AP_ID_t *MME_UE_S1AP_ID = NULL;
S1AP_ENB_UE_S1AP_ID_t *ENB_UE_S1AP_ID = NULL;
ogs_assert(test_ue);
ogs_assert(message);
successfulOutcome = message->choice.successfulOutcome;
ogs_assert(successfulOutcome);
HandoverCancelAcknowledge =
&successfulOutcome->value.choice.HandoverCancelAcknowledge;
ogs_assert(HandoverCancelAcknowledge);
for (i = 0; i < HandoverCancelAcknowledge->protocolIEs.list.count; i++) {
ie = HandoverCancelAcknowledge->protocolIEs.list.array[i];
switch (ie->id) {
case S1AP_ProtocolIE_ID_id_MME_UE_S1AP_ID:
MME_UE_S1AP_ID = &ie->value.choice.MME_UE_S1AP_ID;
break;
case S1AP_ProtocolIE_ID_id_eNB_UE_S1AP_ID:
ENB_UE_S1AP_ID = &ie->value.choice.ENB_UE_S1AP_ID;
break;
default:
break;
}
}
if (MME_UE_S1AP_ID)
test_ue->mme_ue_s1ap_id = *MME_UE_S1AP_ID;
if (ENB_UE_S1AP_ID)
test_ue->enb_ue_s1ap_id = *ENB_UE_S1AP_ID;
}
void tests1ap_handle_mme_status_transfer(
test_ue_t *test_ue, ogs_s1ap_message_t *message)
{
int i;
S1AP_S1AP_PDU_t pdu;
S1AP_InitiatingMessage_t *initiatingMessage = NULL;
S1AP_MMEStatusTransfer_t *MMEStatusTransfer = NULL;
S1AP_MMEStatusTransferIEs_t *ie = NULL;
S1AP_MME_UE_S1AP_ID_t *MME_UE_S1AP_ID = NULL;
S1AP_ENB_UE_S1AP_ID_t *ENB_UE_S1AP_ID = NULL;
ogs_assert(test_ue);
ogs_assert(message);
initiatingMessage = message->choice.initiatingMessage;
ogs_assert(initiatingMessage);
MMEStatusTransfer = &initiatingMessage->value.choice.MMEStatusTransfer;
ogs_assert(MMEStatusTransfer);
for (i = 0; i < MMEStatusTransfer->protocolIEs.list.count; i++) {
ie = MMEStatusTransfer->protocolIEs.list.array[i];
switch (ie->id) {
case S1AP_ProtocolIE_ID_id_MME_UE_S1AP_ID:
MME_UE_S1AP_ID = &ie->value.choice.MME_UE_S1AP_ID;
break;
case S1AP_ProtocolIE_ID_id_eNB_UE_S1AP_ID:
ENB_UE_S1AP_ID = &ie->value.choice.ENB_UE_S1AP_ID;
break;
default:
break;
}
}
if (MME_UE_S1AP_ID)
test_ue->mme_ue_s1ap_id = *MME_UE_S1AP_ID;
if (ENB_UE_S1AP_ID)
test_ue->enb_ue_s1ap_id = *ENB_UE_S1AP_ID;
}

View File

@ -40,6 +40,14 @@ void tests1ap_handle_e_rab_release_command(
void tests1ap_handle_handover_request(
test_ue_t *test_ue, ogs_s1ap_message_t *message);
void tests1ap_handle_handover_command(
test_ue_t *test_ue, ogs_s1ap_message_t *message);
void tests1ap_handle_handover_preparation_failure(
test_ue_t *test_ue, ogs_s1ap_message_t *message);
void tests1ap_handle_handover_cancel_ack(
test_ue_t *test_ue, ogs_s1ap_message_t *message);
void tests1ap_handle_mme_status_transfer(
test_ue_t *test_ue, ogs_s1ap_message_t *message);
#ifdef __cplusplus
}

View File

@ -73,6 +73,7 @@ void tests1ap_recv(test_ue_t *test_ue, ogs_pkbuf_t *pkbuf)
tests1ap_handle_handover_request(test_ue, pdu);
break;
case S1AP_ProcedureCode_id_MMEStatusTransfer:
tests1ap_handle_mme_status_transfer(test_ue, pdu);
break;
case S1AP_ProcedureCode_id_Paging:
break;
@ -98,8 +99,10 @@ void tests1ap_recv(test_ue_t *test_ue, ogs_pkbuf_t *pkbuf)
case S1AP_ProcedureCode_id_PathSwitchRequest:
break;
case S1AP_ProcedureCode_id_HandoverPreparation:
tests1ap_handle_handover_command(test_ue, pdu);
break;
case S1AP_ProcedureCode_id_HandoverCancel:
tests1ap_handle_handover_cancel_ack(test_ue, pdu);
break;
case S1AP_ProcedureCode_id_Reset:
break;

File diff suppressed because it is too large Load Diff

View File

@ -443,17 +443,11 @@ static void test1_func(abts_case *tc, void *data)
tests1ap_recv(test_ue, recvbuf);
/* Send eNB Status Transfer */
mme_ue_s1ap_id = test_ue->mme_ue_s1ap_id--;
enb_ue_s1ap_id = test_ue->enb_ue_s1ap_id--;
sendbuf = test_s1ap_build_enb_status_transfer(test_ue);
ABTS_PTR_NOTNULL(tc, sendbuf);
rv = testenb_s1ap_send(s1ap1, sendbuf);
ABTS_INT_EQUAL(tc, OGS_OK, rv);
test_ue->mme_ue_s1ap_id = mme_ue_s1ap_id;
test_ue->enb_ue_s1ap_id = enb_ue_s1ap_id;
/* Receive MME Status Transfer */
recvbuf = testenb_s1ap_read(s1ap2);
ABTS_PTR_NOTNULL(tc, recvbuf);
@ -569,17 +563,11 @@ static void test1_func(abts_case *tc, void *data)
tests1ap_recv(test_ue, recvbuf);
/* Send eNB Status Transfer */
mme_ue_s1ap_id = test_ue->mme_ue_s1ap_id--;
enb_ue_s1ap_id = test_ue->enb_ue_s1ap_id--;
sendbuf = test_s1ap_build_enb_status_transfer(test_ue);
ABTS_PTR_NOTNULL(tc, sendbuf);
rv = testenb_s1ap_send(s1ap2, sendbuf);
ABTS_INT_EQUAL(tc, OGS_OK, rv);
test_ue->mme_ue_s1ap_id = mme_ue_s1ap_id;
test_ue->enb_ue_s1ap_id = enb_ue_s1ap_id;
/* Receive MME Status Transfer */
recvbuf = testenb_s1ap_read(s1ap1);
ABTS_PTR_NOTNULL(tc, recvbuf);
@ -672,9 +660,6 @@ static void test1_func(abts_case *tc, void *data)
tests1ap_recv(test_ue, recvbuf);
/* Send Handover Cancel */
mme_ue_s1ap_id = test_ue->mme_ue_s1ap_id--;
enb_ue_s1ap_id = test_ue->enb_ue_s1ap_id--;
sendbuf = test_s1ap_build_handover_cancel(test_ue,
S1AP_Cause_PR_radioNetwork,
S1AP_CauseRadioNetwork_tS1relocprep_expiry);
@ -682,15 +667,7 @@ static void test1_func(abts_case *tc, void *data)
rv = testenb_s1ap_send(s1ap1, sendbuf);
ABTS_INT_EQUAL(tc, OGS_OK, rv);
/* Recv Handover Cancel Ack */
recvbuf = testenb_s1ap_read(s1ap1);
ABTS_PTR_NOTNULL(tc, recvbuf);
tests1ap_recv(test_ue, recvbuf);
/* Receive UE Context Release Command */
mme_ue_s1ap_id = test_ue->mme_ue_s1ap_id;
enb_ue_s1ap_id = test_ue->enb_ue_s1ap_id;
recvbuf = testenb_s1ap_read(s1ap2);
ABTS_PTR_NOTNULL(tc, recvbuf);
tests1ap_recv(test_ue, recvbuf);
@ -701,8 +678,10 @@ static void test1_func(abts_case *tc, void *data)
rv = testenb_s1ap_send(s1ap2, sendbuf);
ABTS_INT_EQUAL(tc, OGS_OK, rv);
test_ue->mme_ue_s1ap_id = mme_ue_s1ap_id;
test_ue->enb_ue_s1ap_id = enb_ue_s1ap_id;
/* Recv HandoverCancelAcknowledge */
recvbuf = testenb_s1ap_read(s1ap1);
ABTS_PTR_NOTNULL(tc, recvbuf);
tests1ap_recv(test_ue, recvbuf);
ogs_msleep(300);
@ -742,9 +721,6 @@ static void test2_func(abts_case *tc, void *data)
test_sess_t *sess = NULL;
test_bearer_t *bearer = NULL;
uint32_t enb_ue_s1ap_id;
uint64_t mme_ue_s1ap_id;
const char *_k_string = "465b5ce8b199b49faa5f0a2ee238a6bc";
uint8_t k[OGS_KEY_LEN];
const char *_opc_string = "e8ed289deba952e4283b54e88e6183ca";
@ -1125,9 +1101,6 @@ static void test2_func(abts_case *tc, void *data)
tests1ap_recv(test_ue, recvbuf);
/* Send Handover Cancel */
mme_ue_s1ap_id = test_ue->mme_ue_s1ap_id--;
enb_ue_s1ap_id = test_ue->enb_ue_s1ap_id--;
sendbuf = test_s1ap_build_handover_cancel(test_ue,
S1AP_Cause_PR_radioNetwork,
S1AP_CauseRadioNetwork_tS1relocprep_expiry);
@ -1135,15 +1108,7 @@ static void test2_func(abts_case *tc, void *data)
rv = testenb_s1ap_send(s1ap1, sendbuf);
ABTS_INT_EQUAL(tc, OGS_OK, rv);
/* Recv Handover Cancel Ack */
recvbuf = testenb_s1ap_read(s1ap1);
ABTS_PTR_NOTNULL(tc, recvbuf);
tests1ap_recv(test_ue, recvbuf);
/* Receive UE Context Release Command */
mme_ue_s1ap_id = test_ue->mme_ue_s1ap_id;
enb_ue_s1ap_id = test_ue->enb_ue_s1ap_id;
recvbuf = testenb_s1ap_read(s1ap2);
ABTS_PTR_NOTNULL(tc, recvbuf);
tests1ap_recv(test_ue, recvbuf);
@ -1154,8 +1119,10 @@ static void test2_func(abts_case *tc, void *data)
rv = testenb_s1ap_send(s1ap2, sendbuf);
ABTS_INT_EQUAL(tc, OGS_OK, rv);
test_ue->mme_ue_s1ap_id = mme_ue_s1ap_id;
test_ue->enb_ue_s1ap_id = enb_ue_s1ap_id;
/* Recv Handover Cancel Ack */
recvbuf = testenb_s1ap_read(s1ap1);
ABTS_PTR_NOTNULL(tc, recvbuf);
tests1ap_recv(test_ue, recvbuf);
ogs_msleep(300);
@ -1195,9 +1162,6 @@ static void test3_func(abts_case *tc, void *data)
test_sess_t *sess = NULL;
test_bearer_t *bearer = NULL;
uint32_t enb_ue_s1ap_id;
uint64_t mme_ue_s1ap_id;
const char *_k_string = "465b5ce8b199b49faa5f0a2ee238a6bc";
uint8_t k[OGS_KEY_LEN];
const char *_opc_string = "e8ed289deba952e4283b54e88e6183ca";
@ -1569,27 +1533,22 @@ static void test3_func(abts_case *tc, void *data)
rv = testenb_s1ap_send(s1ap2, sendbuf);
ABTS_INT_EQUAL(tc, OGS_OK, rv);
/* Receive Handover Preparation Failure */
mme_ue_s1ap_id = test_ue->mme_ue_s1ap_id--;
recvbuf = testenb_s1ap_read(s1ap1);
ABTS_PTR_NOTNULL(tc, recvbuf);
tests1ap_recv(test_ue, recvbuf);
test_ue->mme_ue_s1ap_id = mme_ue_s1ap_id;
/* Receive UE Context Release Command */
recvbuf = testenb_s1ap_read(s1ap2);
ABTS_PTR_NOTNULL(tc, recvbuf);
tests1ap_recv(test_ue, recvbuf);
/* Send UE Context Release Complete */
test_ue->enb_ue_s1ap_id++;
sendbuf = test_s1ap_build_ue_context_release_complete(test_ue);
ABTS_PTR_NOTNULL(tc, sendbuf);
rv = testenb_s1ap_send(s1ap2, sendbuf);
ABTS_INT_EQUAL(tc, OGS_OK, rv);
/* Receive Handover Preparation Failure */
recvbuf = testenb_s1ap_read(s1ap1);
ABTS_PTR_NOTNULL(tc, recvbuf);
tests1ap_recv(test_ue, recvbuf);
ogs_msleep(300);
/********** Remove Subscriber in Database */