From de2ecd64002e6f1d47e051925f12f67905ba5e09 Mon Sep 17 00:00:00 2001 From: Sukchan Lee Date: Fri, 29 Apr 2022 21:28:16 +0900 Subject: [PATCH] [GTP2] Fixed handling multi-bearer messages(#1498) --- lib/core/ogs-3gpp-types.h | 1 + lib/core/ogs-list.h | 4 +- lib/gtp/v2/message.c | 150 +++--- lib/gtp/v2/message.h | 6 +- lib/gtp/v2/support/gtp-tlv.py | 22 +- lib/gtp/xact.h | 4 + lib/pfcp/path.c | 21 +- lib/pfcp/xact.c | 9 +- lib/pfcp/xact.h | 4 +- src/amf/ngap-handler.c | 54 +-- src/mme/esm-sm.c | 5 +- src/mme/mme-context.c | 215 ++++++++- src/mme/mme-context.h | 133 +++-- src/mme/mme-event.h | 2 + src/mme/mme-gtp-path.c | 92 +++- src/mme/mme-gtp-path.h | 3 +- src/mme/mme-s11-build.c | 196 +++++--- src/mme/mme-s11-build.h | 4 +- src/mme/mme-s11-handler.c | 884 ++++++++++++++++++++++------------ src/mme/mme-s11-handler.h | 22 +- src/mme/mme-sm.c | 40 +- src/mme/mme-timer.c | 42 +- src/mme/mme-timer.h | 3 + src/mme/s1ap-handler.c | 243 ++++++---- src/mme/s1ap-path.c | 10 +- src/sgwc/context.c | 26 + src/sgwc/context.h | 19 +- src/sgwc/pfcp-path.c | 133 +++-- src/sgwc/pfcp-path.h | 17 + src/sgwc/s11-handler.c | 699 ++++++++++++++++----------- src/sgwc/s5c-handler.c | 471 +++++++++++------- src/sgwc/sxa-build.c | 171 ++----- src/sgwc/sxa-build.h | 8 +- src/sgwc/sxa-handler.c | 337 ++++++++----- src/sgwu/pfcp-path.c | 12 +- src/smf/n4-build.c | 24 +- src/smf/n4-build.h | 6 +- src/smf/n4-handler.c | 19 +- src/smf/pfcp-path.c | 109 ++--- src/smf/s5c-build.c | 24 +- src/smf/s5c-handler.c | 392 ++++++++++----- src/smf/smf-sm.c | 5 +- src/upf/pfcp-path.c | 8 +- 43 files changed, 2894 insertions(+), 1755 deletions(-) diff --git a/lib/core/ogs-3gpp-types.h b/lib/core/ogs-3gpp-types.h index f6f8ead6b..c643bf125 100644 --- a/lib/core/ogs-3gpp-types.h +++ b/lib/core/ogs-3gpp-types.h @@ -30,6 +30,7 @@ extern "C" { #define OGS_MAX_NUM_OF_SESS 4 /* Num of APN(Session) per UE */ #define OGS_MAX_NUM_OF_BEARER 4 /* Num of Bearer per Session */ +#define OGS_BEARER_PER_UE 8 /* Num of Bearer per UE */ #define OGS_MAX_NUM_OF_PACKET_BUFFER 64 /* Num of PacketBuffer per UE */ /* diff --git a/lib/core/ogs-list.h b/lib/core/ogs-list.h index c21c843aa..da6af540e 100644 --- a/lib/core/ogs-list.h +++ b/lib/core/ogs-list.h @@ -32,7 +32,7 @@ struct ogs_list_s { struct ogs_list_s *prev, *next; }; typedef struct ogs_list_s ogs_list_t; -typedef struct ogs_list_s ogs_lnode_t;; +typedef struct ogs_list_s ogs_lnode_t; #define OGS_LIST(name) \ ogs_list_t name = { NULL, NULL } @@ -123,7 +123,7 @@ static ogs_inline void ogs_list_remove(ogs_list_t *list, void *lnode) { ogs_list_t *node = lnode; ogs_list_t *prev = node->prev; - ogs_list_t *next = node->next;; + ogs_list_t *next = node->next; if (prev) prev->next = next; diff --git a/lib/gtp/v2/message.c b/lib/gtp/v2/message.c index 4a87031f4..070d042e1 100644 --- a/lib/gtp/v2/message.c +++ b/lib/gtp/v2/message.c @@ -20,7 +20,7 @@ /******************************************************************************* * This file had been created by gtp-tlv.py script v0.1.0 * Please do not modify this file but regenerate it via script. - * Created on: 2022-04-12 14:16:09.777673 by pespin + * Created on: 2022-04-22 03:19:22.029355 by acetcom * from 29274-g30.docx ******************************************************************************/ @@ -2166,6 +2166,7 @@ ogs_tlv_desc_t ogs_gtp2_tlv_desc_modify_bearer_request = &ogs_gtp2_tlv_desc_ambr_0, &ogs_gtp2_tlv_desc_delay_value_0, &ogs_gtp2_tlv_desc_bearer_context_0, + &ogs_tlv_desc_more8, &ogs_gtp2_tlv_desc_bearer_context_1, &ogs_gtp2_tlv_desc_recovery_0, &ogs_gtp2_tlv_desc_ue_time_zone_0, @@ -2204,6 +2205,7 @@ ogs_tlv_desc_t ogs_gtp2_tlv_desc_modify_bearer_response = &ogs_gtp2_tlv_desc_apn_restriction_0, &ogs_gtp2_tlv_desc_pco_0, &ogs_gtp2_tlv_desc_bearer_context_0, + &ogs_tlv_desc_more8, &ogs_gtp2_tlv_desc_bearer_context_1, &ogs_gtp2_tlv_desc_change_reporting_action_0, &ogs_gtp2_tlv_desc_csg_information_reporting_action_0, @@ -2685,20 +2687,20 @@ ogs_tlv_desc_t ogs_gtp2_tlv_desc_modify_access_bearers_response = }}; -int ogs_gtp2_parse_msg(ogs_gtp2_message_t *gtp_message, ogs_pkbuf_t *pkbuf) +int ogs_gtp2_parse_msg(ogs_gtp2_message_t *gtp2_message, ogs_pkbuf_t *pkbuf) { int rv = OGS_ERROR; ogs_gtp2_header_t *h = NULL; uint16_t size = 0; - ogs_assert(gtp_message); + ogs_assert(gtp2_message); ogs_assert(pkbuf); ogs_assert(pkbuf->len); h = (ogs_gtp2_header_t *)pkbuf->data; ogs_assert(h); - memset(gtp_message, 0, sizeof(ogs_gtp2_message_t)); + memset(gtp2_message, 0, sizeof(ogs_gtp2_message_t)); if (h->teid_presence) size = OGS_GTPV2C_HEADER_LEN; @@ -2706,143 +2708,143 @@ int ogs_gtp2_parse_msg(ogs_gtp2_message_t *gtp_message, ogs_pkbuf_t *pkbuf) size = OGS_GTPV2C_HEADER_LEN-OGS_GTP2_TEID_LEN; ogs_assert(ogs_pkbuf_pull(pkbuf, size)); - memcpy(>p_message->h, pkbuf->data - size, size); + memcpy(>p2_message->h, pkbuf->data - size, size); if (h->teid_presence) - gtp_message->h.teid = be32toh(gtp_message->h.teid); + gtp2_message->h.teid = be32toh(gtp2_message->h.teid); if (pkbuf->len == 0) { ogs_assert(ogs_pkbuf_push(pkbuf, size)); return OGS_OK; } - switch(gtp_message->h.type) { + switch(gtp2_message->h.type) { case OGS_GTP2_ECHO_REQUEST_TYPE: - rv = ogs_tlv_parse_msg(>p_message->echo_request, + rv = ogs_tlv_parse_msg(>p2_message->echo_request, &ogs_gtp2_tlv_desc_echo_request, pkbuf, OGS_TLV_MODE_T1_L2_I1); break; case OGS_GTP2_ECHO_RESPONSE_TYPE: - rv = ogs_tlv_parse_msg(>p_message->echo_response, + rv = ogs_tlv_parse_msg(>p2_message->echo_response, &ogs_gtp2_tlv_desc_echo_response, pkbuf, OGS_TLV_MODE_T1_L2_I1); break; case OGS_GTP2_CREATE_SESSION_REQUEST_TYPE: - rv = ogs_tlv_parse_msg(>p_message->create_session_request, + rv = ogs_tlv_parse_msg(>p2_message->create_session_request, &ogs_gtp2_tlv_desc_create_session_request, pkbuf, OGS_TLV_MODE_T1_L2_I1); break; case OGS_GTP2_CREATE_SESSION_RESPONSE_TYPE: - rv = ogs_tlv_parse_msg(>p_message->create_session_response, + rv = ogs_tlv_parse_msg(>p2_message->create_session_response, &ogs_gtp2_tlv_desc_create_session_response, pkbuf, OGS_TLV_MODE_T1_L2_I1); break; case OGS_GTP2_MODIFY_BEARER_REQUEST_TYPE: - rv = ogs_tlv_parse_msg(>p_message->modify_bearer_request, + rv = ogs_tlv_parse_msg(>p2_message->modify_bearer_request, &ogs_gtp2_tlv_desc_modify_bearer_request, pkbuf, OGS_TLV_MODE_T1_L2_I1); break; case OGS_GTP2_MODIFY_BEARER_RESPONSE_TYPE: - rv = ogs_tlv_parse_msg(>p_message->modify_bearer_response, + rv = ogs_tlv_parse_msg(>p2_message->modify_bearer_response, &ogs_gtp2_tlv_desc_modify_bearer_response, pkbuf, OGS_TLV_MODE_T1_L2_I1); break; case OGS_GTP2_DELETE_SESSION_REQUEST_TYPE: - rv = ogs_tlv_parse_msg(>p_message->delete_session_request, + rv = ogs_tlv_parse_msg(>p2_message->delete_session_request, &ogs_gtp2_tlv_desc_delete_session_request, pkbuf, OGS_TLV_MODE_T1_L2_I1); break; case OGS_GTP2_DELETE_SESSION_RESPONSE_TYPE: - rv = ogs_tlv_parse_msg(>p_message->delete_session_response, + rv = ogs_tlv_parse_msg(>p2_message->delete_session_response, &ogs_gtp2_tlv_desc_delete_session_response, pkbuf, OGS_TLV_MODE_T1_L2_I1); break; case OGS_GTP2_MODIFY_BEARER_COMMAND_TYPE: - rv = ogs_tlv_parse_msg(>p_message->modify_bearer_command, + rv = ogs_tlv_parse_msg(>p2_message->modify_bearer_command, &ogs_gtp2_tlv_desc_modify_bearer_command, pkbuf, OGS_TLV_MODE_T1_L2_I1); break; case OGS_GTP2_MODIFY_BEARER_FAILURE_INDICATION_TYPE: - rv = ogs_tlv_parse_msg(>p_message->modify_bearer_failure_indication, + rv = ogs_tlv_parse_msg(>p2_message->modify_bearer_failure_indication, &ogs_gtp2_tlv_desc_modify_bearer_failure_indication, pkbuf, OGS_TLV_MODE_T1_L2_I1); break; case OGS_GTP2_DELETE_BEARER_COMMAND_TYPE: - rv = ogs_tlv_parse_msg(>p_message->delete_bearer_command, + rv = ogs_tlv_parse_msg(>p2_message->delete_bearer_command, &ogs_gtp2_tlv_desc_delete_bearer_command, pkbuf, OGS_TLV_MODE_T1_L2_I1); break; case OGS_GTP2_DELETE_BEARER_FAILURE_INDICATION_TYPE: - rv = ogs_tlv_parse_msg(>p_message->delete_bearer_failure_indication, + rv = ogs_tlv_parse_msg(>p2_message->delete_bearer_failure_indication, &ogs_gtp2_tlv_desc_delete_bearer_failure_indication, pkbuf, OGS_TLV_MODE_T1_L2_I1); break; case OGS_GTP2_BEARER_RESOURCE_COMMAND_TYPE: - rv = ogs_tlv_parse_msg(>p_message->bearer_resource_command, + rv = ogs_tlv_parse_msg(>p2_message->bearer_resource_command, &ogs_gtp2_tlv_desc_bearer_resource_command, pkbuf, OGS_TLV_MODE_T1_L2_I1); break; case OGS_GTP2_BEARER_RESOURCE_FAILURE_INDICATION_TYPE: - rv = ogs_tlv_parse_msg(>p_message->bearer_resource_failure_indication, + rv = ogs_tlv_parse_msg(>p2_message->bearer_resource_failure_indication, &ogs_gtp2_tlv_desc_bearer_resource_failure_indication, pkbuf, OGS_TLV_MODE_T1_L2_I1); break; case OGS_GTP2_DOWNLINK_DATA_NOTIFICATION_FAILURE_INDICATION_TYPE: - rv = ogs_tlv_parse_msg(>p_message->downlink_data_notification_failure_indication, + rv = ogs_tlv_parse_msg(>p2_message->downlink_data_notification_failure_indication, &ogs_gtp2_tlv_desc_downlink_data_notification_failure_indication, pkbuf, OGS_TLV_MODE_T1_L2_I1); break; case OGS_GTP2_CREATE_BEARER_REQUEST_TYPE: - rv = ogs_tlv_parse_msg(>p_message->create_bearer_request, + rv = ogs_tlv_parse_msg(>p2_message->create_bearer_request, &ogs_gtp2_tlv_desc_create_bearer_request, pkbuf, OGS_TLV_MODE_T1_L2_I1); break; case OGS_GTP2_CREATE_BEARER_RESPONSE_TYPE: - rv = ogs_tlv_parse_msg(>p_message->create_bearer_response, + rv = ogs_tlv_parse_msg(>p2_message->create_bearer_response, &ogs_gtp2_tlv_desc_create_bearer_response, pkbuf, OGS_TLV_MODE_T1_L2_I1); break; case OGS_GTP2_UPDATE_BEARER_REQUEST_TYPE: - rv = ogs_tlv_parse_msg(>p_message->update_bearer_request, + rv = ogs_tlv_parse_msg(>p2_message->update_bearer_request, &ogs_gtp2_tlv_desc_update_bearer_request, pkbuf, OGS_TLV_MODE_T1_L2_I1); break; case OGS_GTP2_UPDATE_BEARER_RESPONSE_TYPE: - rv = ogs_tlv_parse_msg(>p_message->update_bearer_response, + rv = ogs_tlv_parse_msg(>p2_message->update_bearer_response, &ogs_gtp2_tlv_desc_update_bearer_response, pkbuf, OGS_TLV_MODE_T1_L2_I1); break; case OGS_GTP2_DELETE_BEARER_REQUEST_TYPE: - rv = ogs_tlv_parse_msg(>p_message->delete_bearer_request, + rv = ogs_tlv_parse_msg(>p2_message->delete_bearer_request, &ogs_gtp2_tlv_desc_delete_bearer_request, pkbuf, OGS_TLV_MODE_T1_L2_I1); break; case OGS_GTP2_DELETE_BEARER_RESPONSE_TYPE: - rv = ogs_tlv_parse_msg(>p_message->delete_bearer_response, + rv = ogs_tlv_parse_msg(>p2_message->delete_bearer_response, &ogs_gtp2_tlv_desc_delete_bearer_response, pkbuf, OGS_TLV_MODE_T1_L2_I1); break; case OGS_GTP2_CREATE_INDIRECT_DATA_FORWARDING_TUNNEL_REQUEST_TYPE: - rv = ogs_tlv_parse_msg(>p_message->create_indirect_data_forwarding_tunnel_request, + rv = ogs_tlv_parse_msg(>p2_message->create_indirect_data_forwarding_tunnel_request, &ogs_gtp2_tlv_desc_create_indirect_data_forwarding_tunnel_request, pkbuf, OGS_TLV_MODE_T1_L2_I1); break; case OGS_GTP2_CREATE_INDIRECT_DATA_FORWARDING_TUNNEL_RESPONSE_TYPE: - rv = ogs_tlv_parse_msg(>p_message->create_indirect_data_forwarding_tunnel_response, + rv = ogs_tlv_parse_msg(>p2_message->create_indirect_data_forwarding_tunnel_response, &ogs_gtp2_tlv_desc_create_indirect_data_forwarding_tunnel_response, pkbuf, OGS_TLV_MODE_T1_L2_I1); break; case OGS_GTP2_DELETE_INDIRECT_DATA_FORWARDING_TUNNEL_REQUEST_TYPE: - rv = ogs_tlv_parse_msg(>p_message->delete_indirect_data_forwarding_tunnel_request, + rv = ogs_tlv_parse_msg(>p2_message->delete_indirect_data_forwarding_tunnel_request, &ogs_gtp2_tlv_desc_delete_indirect_data_forwarding_tunnel_request, pkbuf, OGS_TLV_MODE_T1_L2_I1); break; case OGS_GTP2_DELETE_INDIRECT_DATA_FORWARDING_TUNNEL_RESPONSE_TYPE: - rv = ogs_tlv_parse_msg(>p_message->delete_indirect_data_forwarding_tunnel_response, + rv = ogs_tlv_parse_msg(>p2_message->delete_indirect_data_forwarding_tunnel_response, &ogs_gtp2_tlv_desc_delete_indirect_data_forwarding_tunnel_response, pkbuf, OGS_TLV_MODE_T1_L2_I1); break; case OGS_GTP2_RELEASE_ACCESS_BEARERS_REQUEST_TYPE: - rv = ogs_tlv_parse_msg(>p_message->release_access_bearers_request, + rv = ogs_tlv_parse_msg(>p2_message->release_access_bearers_request, &ogs_gtp2_tlv_desc_release_access_bearers_request, pkbuf, OGS_TLV_MODE_T1_L2_I1); break; case OGS_GTP2_RELEASE_ACCESS_BEARERS_RESPONSE_TYPE: - rv = ogs_tlv_parse_msg(>p_message->release_access_bearers_response, + rv = ogs_tlv_parse_msg(>p2_message->release_access_bearers_response, &ogs_gtp2_tlv_desc_release_access_bearers_response, pkbuf, OGS_TLV_MODE_T1_L2_I1); break; case OGS_GTP2_DOWNLINK_DATA_NOTIFICATION_TYPE: - rv = ogs_tlv_parse_msg(>p_message->downlink_data_notification, + rv = ogs_tlv_parse_msg(>p2_message->downlink_data_notification, &ogs_gtp2_tlv_desc_downlink_data_notification, pkbuf, OGS_TLV_MODE_T1_L2_I1); break; case OGS_GTP2_DOWNLINK_DATA_NOTIFICATION_ACKNOWLEDGE_TYPE: - rv = ogs_tlv_parse_msg(>p_message->downlink_data_notification_acknowledge, + rv = ogs_tlv_parse_msg(>p2_message->downlink_data_notification_acknowledge, &ogs_gtp2_tlv_desc_downlink_data_notification_acknowledge, pkbuf, OGS_TLV_MODE_T1_L2_I1); break; case OGS_GTP2_MODIFY_ACCESS_BEARERS_REQUEST_TYPE: - rv = ogs_tlv_parse_msg(>p_message->modify_access_bearers_request, + rv = ogs_tlv_parse_msg(>p2_message->modify_access_bearers_request, &ogs_gtp2_tlv_desc_modify_access_bearers_request, pkbuf, OGS_TLV_MODE_T1_L2_I1); break; case OGS_GTP2_MODIFY_ACCESS_BEARERS_RESPONSE_TYPE: - rv = ogs_tlv_parse_msg(>p_message->modify_access_bearers_response, + rv = ogs_tlv_parse_msg(>p2_message->modify_access_bearers_response, &ogs_gtp2_tlv_desc_modify_access_bearers_response, pkbuf, OGS_TLV_MODE_T1_L2_I1); break; default: - ogs_warn("Not implmeneted(type:%d)", gtp_message->h.type); + ogs_warn("Not implmeneted(type:%d)", gtp2_message->h.type); break; } @@ -2851,138 +2853,138 @@ int ogs_gtp2_parse_msg(ogs_gtp2_message_t *gtp_message, ogs_pkbuf_t *pkbuf) return rv; } -ogs_pkbuf_t *ogs_gtp2_build_msg(ogs_gtp2_message_t *gtp_message) +ogs_pkbuf_t *ogs_gtp2_build_msg(ogs_gtp2_message_t *gtp2_message) { ogs_pkbuf_t *pkbuf = NULL; - ogs_assert(gtp_message); - switch(gtp_message->h.type) { + ogs_assert(gtp2_message); + switch(gtp2_message->h.type) { case OGS_GTP2_ECHO_REQUEST_TYPE: pkbuf = ogs_tlv_build_msg(&ogs_gtp2_tlv_desc_echo_request, - >p_message->echo_request, OGS_TLV_MODE_T1_L2_I1); + >p2_message->echo_request, OGS_TLV_MODE_T1_L2_I1); break; case OGS_GTP2_ECHO_RESPONSE_TYPE: pkbuf = ogs_tlv_build_msg(&ogs_gtp2_tlv_desc_echo_response, - >p_message->echo_response, OGS_TLV_MODE_T1_L2_I1); + >p2_message->echo_response, OGS_TLV_MODE_T1_L2_I1); break; case OGS_GTP2_CREATE_SESSION_REQUEST_TYPE: pkbuf = ogs_tlv_build_msg(&ogs_gtp2_tlv_desc_create_session_request, - >p_message->create_session_request, OGS_TLV_MODE_T1_L2_I1); + >p2_message->create_session_request, OGS_TLV_MODE_T1_L2_I1); break; case OGS_GTP2_CREATE_SESSION_RESPONSE_TYPE: pkbuf = ogs_tlv_build_msg(&ogs_gtp2_tlv_desc_create_session_response, - >p_message->create_session_response, OGS_TLV_MODE_T1_L2_I1); + >p2_message->create_session_response, OGS_TLV_MODE_T1_L2_I1); break; case OGS_GTP2_MODIFY_BEARER_REQUEST_TYPE: pkbuf = ogs_tlv_build_msg(&ogs_gtp2_tlv_desc_modify_bearer_request, - >p_message->modify_bearer_request, OGS_TLV_MODE_T1_L2_I1); + >p2_message->modify_bearer_request, OGS_TLV_MODE_T1_L2_I1); break; case OGS_GTP2_MODIFY_BEARER_RESPONSE_TYPE: pkbuf = ogs_tlv_build_msg(&ogs_gtp2_tlv_desc_modify_bearer_response, - >p_message->modify_bearer_response, OGS_TLV_MODE_T1_L2_I1); + >p2_message->modify_bearer_response, OGS_TLV_MODE_T1_L2_I1); break; case OGS_GTP2_DELETE_SESSION_REQUEST_TYPE: pkbuf = ogs_tlv_build_msg(&ogs_gtp2_tlv_desc_delete_session_request, - >p_message->delete_session_request, OGS_TLV_MODE_T1_L2_I1); + >p2_message->delete_session_request, OGS_TLV_MODE_T1_L2_I1); break; case OGS_GTP2_DELETE_SESSION_RESPONSE_TYPE: pkbuf = ogs_tlv_build_msg(&ogs_gtp2_tlv_desc_delete_session_response, - >p_message->delete_session_response, OGS_TLV_MODE_T1_L2_I1); + >p2_message->delete_session_response, OGS_TLV_MODE_T1_L2_I1); break; case OGS_GTP2_MODIFY_BEARER_COMMAND_TYPE: pkbuf = ogs_tlv_build_msg(&ogs_gtp2_tlv_desc_modify_bearer_command, - >p_message->modify_bearer_command, OGS_TLV_MODE_T1_L2_I1); + >p2_message->modify_bearer_command, OGS_TLV_MODE_T1_L2_I1); break; case OGS_GTP2_MODIFY_BEARER_FAILURE_INDICATION_TYPE: pkbuf = ogs_tlv_build_msg(&ogs_gtp2_tlv_desc_modify_bearer_failure_indication, - >p_message->modify_bearer_failure_indication, OGS_TLV_MODE_T1_L2_I1); + >p2_message->modify_bearer_failure_indication, OGS_TLV_MODE_T1_L2_I1); break; case OGS_GTP2_DELETE_BEARER_COMMAND_TYPE: pkbuf = ogs_tlv_build_msg(&ogs_gtp2_tlv_desc_delete_bearer_command, - >p_message->delete_bearer_command, OGS_TLV_MODE_T1_L2_I1); + >p2_message->delete_bearer_command, OGS_TLV_MODE_T1_L2_I1); break; case OGS_GTP2_DELETE_BEARER_FAILURE_INDICATION_TYPE: pkbuf = ogs_tlv_build_msg(&ogs_gtp2_tlv_desc_delete_bearer_failure_indication, - >p_message->delete_bearer_failure_indication, OGS_TLV_MODE_T1_L2_I1); + >p2_message->delete_bearer_failure_indication, OGS_TLV_MODE_T1_L2_I1); break; case OGS_GTP2_BEARER_RESOURCE_COMMAND_TYPE: pkbuf = ogs_tlv_build_msg(&ogs_gtp2_tlv_desc_bearer_resource_command, - >p_message->bearer_resource_command, OGS_TLV_MODE_T1_L2_I1); + >p2_message->bearer_resource_command, OGS_TLV_MODE_T1_L2_I1); break; case OGS_GTP2_BEARER_RESOURCE_FAILURE_INDICATION_TYPE: pkbuf = ogs_tlv_build_msg(&ogs_gtp2_tlv_desc_bearer_resource_failure_indication, - >p_message->bearer_resource_failure_indication, OGS_TLV_MODE_T1_L2_I1); + >p2_message->bearer_resource_failure_indication, OGS_TLV_MODE_T1_L2_I1); break; case OGS_GTP2_DOWNLINK_DATA_NOTIFICATION_FAILURE_INDICATION_TYPE: pkbuf = ogs_tlv_build_msg(&ogs_gtp2_tlv_desc_downlink_data_notification_failure_indication, - >p_message->downlink_data_notification_failure_indication, OGS_TLV_MODE_T1_L2_I1); + >p2_message->downlink_data_notification_failure_indication, OGS_TLV_MODE_T1_L2_I1); break; case OGS_GTP2_CREATE_BEARER_REQUEST_TYPE: pkbuf = ogs_tlv_build_msg(&ogs_gtp2_tlv_desc_create_bearer_request, - >p_message->create_bearer_request, OGS_TLV_MODE_T1_L2_I1); + >p2_message->create_bearer_request, OGS_TLV_MODE_T1_L2_I1); break; case OGS_GTP2_CREATE_BEARER_RESPONSE_TYPE: pkbuf = ogs_tlv_build_msg(&ogs_gtp2_tlv_desc_create_bearer_response, - >p_message->create_bearer_response, OGS_TLV_MODE_T1_L2_I1); + >p2_message->create_bearer_response, OGS_TLV_MODE_T1_L2_I1); break; case OGS_GTP2_UPDATE_BEARER_REQUEST_TYPE: pkbuf = ogs_tlv_build_msg(&ogs_gtp2_tlv_desc_update_bearer_request, - >p_message->update_bearer_request, OGS_TLV_MODE_T1_L2_I1); + >p2_message->update_bearer_request, OGS_TLV_MODE_T1_L2_I1); break; case OGS_GTP2_UPDATE_BEARER_RESPONSE_TYPE: pkbuf = ogs_tlv_build_msg(&ogs_gtp2_tlv_desc_update_bearer_response, - >p_message->update_bearer_response, OGS_TLV_MODE_T1_L2_I1); + >p2_message->update_bearer_response, OGS_TLV_MODE_T1_L2_I1); break; case OGS_GTP2_DELETE_BEARER_REQUEST_TYPE: pkbuf = ogs_tlv_build_msg(&ogs_gtp2_tlv_desc_delete_bearer_request, - >p_message->delete_bearer_request, OGS_TLV_MODE_T1_L2_I1); + >p2_message->delete_bearer_request, OGS_TLV_MODE_T1_L2_I1); break; case OGS_GTP2_DELETE_BEARER_RESPONSE_TYPE: pkbuf = ogs_tlv_build_msg(&ogs_gtp2_tlv_desc_delete_bearer_response, - >p_message->delete_bearer_response, OGS_TLV_MODE_T1_L2_I1); + >p2_message->delete_bearer_response, OGS_TLV_MODE_T1_L2_I1); break; case OGS_GTP2_CREATE_INDIRECT_DATA_FORWARDING_TUNNEL_REQUEST_TYPE: pkbuf = ogs_tlv_build_msg(&ogs_gtp2_tlv_desc_create_indirect_data_forwarding_tunnel_request, - >p_message->create_indirect_data_forwarding_tunnel_request, OGS_TLV_MODE_T1_L2_I1); + >p2_message->create_indirect_data_forwarding_tunnel_request, OGS_TLV_MODE_T1_L2_I1); break; case OGS_GTP2_CREATE_INDIRECT_DATA_FORWARDING_TUNNEL_RESPONSE_TYPE: pkbuf = ogs_tlv_build_msg(&ogs_gtp2_tlv_desc_create_indirect_data_forwarding_tunnel_response, - >p_message->create_indirect_data_forwarding_tunnel_response, OGS_TLV_MODE_T1_L2_I1); + >p2_message->create_indirect_data_forwarding_tunnel_response, OGS_TLV_MODE_T1_L2_I1); break; case OGS_GTP2_DELETE_INDIRECT_DATA_FORWARDING_TUNNEL_REQUEST_TYPE: pkbuf = ogs_tlv_build_msg(&ogs_gtp2_tlv_desc_delete_indirect_data_forwarding_tunnel_request, - >p_message->delete_indirect_data_forwarding_tunnel_request, OGS_TLV_MODE_T1_L2_I1); + >p2_message->delete_indirect_data_forwarding_tunnel_request, OGS_TLV_MODE_T1_L2_I1); break; case OGS_GTP2_DELETE_INDIRECT_DATA_FORWARDING_TUNNEL_RESPONSE_TYPE: pkbuf = ogs_tlv_build_msg(&ogs_gtp2_tlv_desc_delete_indirect_data_forwarding_tunnel_response, - >p_message->delete_indirect_data_forwarding_tunnel_response, OGS_TLV_MODE_T1_L2_I1); + >p2_message->delete_indirect_data_forwarding_tunnel_response, OGS_TLV_MODE_T1_L2_I1); break; case OGS_GTP2_RELEASE_ACCESS_BEARERS_REQUEST_TYPE: pkbuf = ogs_tlv_build_msg(&ogs_gtp2_tlv_desc_release_access_bearers_request, - >p_message->release_access_bearers_request, OGS_TLV_MODE_T1_L2_I1); + >p2_message->release_access_bearers_request, OGS_TLV_MODE_T1_L2_I1); break; case OGS_GTP2_RELEASE_ACCESS_BEARERS_RESPONSE_TYPE: pkbuf = ogs_tlv_build_msg(&ogs_gtp2_tlv_desc_release_access_bearers_response, - >p_message->release_access_bearers_response, OGS_TLV_MODE_T1_L2_I1); + >p2_message->release_access_bearers_response, OGS_TLV_MODE_T1_L2_I1); break; case OGS_GTP2_DOWNLINK_DATA_NOTIFICATION_TYPE: pkbuf = ogs_tlv_build_msg(&ogs_gtp2_tlv_desc_downlink_data_notification, - >p_message->downlink_data_notification, OGS_TLV_MODE_T1_L2_I1); + >p2_message->downlink_data_notification, OGS_TLV_MODE_T1_L2_I1); break; case OGS_GTP2_DOWNLINK_DATA_NOTIFICATION_ACKNOWLEDGE_TYPE: pkbuf = ogs_tlv_build_msg(&ogs_gtp2_tlv_desc_downlink_data_notification_acknowledge, - >p_message->downlink_data_notification_acknowledge, OGS_TLV_MODE_T1_L2_I1); + >p2_message->downlink_data_notification_acknowledge, OGS_TLV_MODE_T1_L2_I1); break; case OGS_GTP2_MODIFY_ACCESS_BEARERS_REQUEST_TYPE: pkbuf = ogs_tlv_build_msg(&ogs_gtp2_tlv_desc_modify_access_bearers_request, - >p_message->modify_access_bearers_request, OGS_TLV_MODE_T1_L2_I1); + >p2_message->modify_access_bearers_request, OGS_TLV_MODE_T1_L2_I1); break; case OGS_GTP2_MODIFY_ACCESS_BEARERS_RESPONSE_TYPE: pkbuf = ogs_tlv_build_msg(&ogs_gtp2_tlv_desc_modify_access_bearers_response, - >p_message->modify_access_bearers_response, OGS_TLV_MODE_T1_L2_I1); + >p2_message->modify_access_bearers_response, OGS_TLV_MODE_T1_L2_I1); break; default: - ogs_warn("Not implmeneted(type:%d)", gtp_message->h.type); + ogs_warn("Not implmeneted(type:%d)", gtp2_message->h.type); break; } diff --git a/lib/gtp/v2/message.h b/lib/gtp/v2/message.h index 38bcb49e8..cd3d09186 100644 --- a/lib/gtp/v2/message.h +++ b/lib/gtp/v2/message.h @@ -20,7 +20,7 @@ /******************************************************************************* * This file had been created by gtp-tlv.py script v0.1.0 * Please do not modify this file but regenerate it via script. - * Created on: 2022-04-12 14:16:09.770077 by pespin + * Created on: 2022-04-22 03:19:22.024556 by acetcom * from 29274-g30.docx ******************************************************************************/ @@ -851,7 +851,7 @@ typedef struct ogs_gtp2_modify_bearer_request_s { ogs_gtp2_tlv_f_teid_t sender_f_teid_for_control_plane; ogs_gtp2_tlv_ambr_t aggregate_maximum_bit_rate; ogs_gtp2_tlv_delay_value_t delay_downlink_packet_notification_request; - ogs_gtp2_tlv_bearer_context_t bearer_contexts_to_be_modified; + ogs_gtp2_tlv_bearer_context_t bearer_contexts_to_be_modified[8]; ogs_gtp2_tlv_bearer_context_t bearer_contexts_to_be_removed; ogs_gtp2_tlv_recovery_t recovery; ogs_gtp2_tlv_ue_time_zone_t ue_time_zone; @@ -884,7 +884,7 @@ typedef struct ogs_gtp2_modify_bearer_response_s { ogs_gtp2_tlv_ebi_t linked_eps_bearer_id; ogs_gtp2_tlv_apn_restriction_t apn_restriction; ogs_gtp2_tlv_pco_t protocol_configuration_options; - ogs_gtp2_tlv_bearer_context_t bearer_contexts_modified; + ogs_gtp2_tlv_bearer_context_t bearer_contexts_modified[8]; ogs_gtp2_tlv_bearer_context_t bearer_contexts_marked_for_removal; ogs_gtp2_tlv_change_reporting_action_t change_reporting_action; ogs_gtp2_tlv_csg_information_reporting_action_t csg_information_reporting_action; diff --git a/lib/gtp/v2/support/gtp-tlv.py b/lib/gtp/v2/support/gtp-tlv.py index 3f093207a..8a4e0614e 100644 --- a/lib/gtp/v2/support/gtp-tlv.py +++ b/lib/gtp/v2/support/gtp-tlv.py @@ -219,7 +219,7 @@ if os.path.isfile(cachefile) and os.access(cachefile, os.R_OK): print("Read from " + cachefile) else: document = Document(filename) - f = open(cachefile, 'w') + f = open(cachefile, 'w') msg_table = "" for i, paragraph, table in document_paragraph_tables(document): @@ -252,7 +252,7 @@ if os.path.isfile(cachefile) and os.access(cachefile, os.R_OK): print("Read from " + cachefile) else: document = Document(filename) - f = open(cachefile, 'w') + f = open(cachefile, 'w') ie_table = "" for i, paragraph, table in document_paragraph_tables(document): @@ -298,7 +298,7 @@ if os.path.isfile(cachefile) and os.access(cachefile, os.R_OK): print("Read from " + cachefile) else: document = Document(filename) - f = open(cachefile, 'w') + f = open(cachefile, 'w') for i, paragraph, table in document_paragraph_tables(document): if table.rows[0].cells[0].text.find('Octet') != -1 and \ @@ -400,7 +400,7 @@ for key in msg_list.keys(): print("Read from " + cachefile) else: document = Document(filename) - f = open(cachefile, 'w') + f = open(cachefile, 'w') ies = [] write_file(f, "ies = []\n") @@ -580,7 +580,7 @@ for (k, v) in sorted_msg_list: if "ies" in msg_list[k]: f.write("typedef struct ogs_gtp2_" + v_lower(k) + "_s {\n") for ies in msg_list[k]["ies"]: - if (k == 'Create Indirect Data Forwarding Tunnel Request' or k == 'Create Indirect Data Forwarding Tunnel Response') and ies["ie_value"] == 'Bearer Contexts': + if ((k == 'Create Indirect Data Forwarding Tunnel Request' or k == 'Create Indirect Data Forwarding Tunnel Response') and ies["ie_value"] == 'Bearer Contexts') or (k == 'Modify Bearer Request' and ies["ie_value"] == 'Bearer Contexts to be modified') or (k == 'Modify Bearer Response' and ies["ie_value"] == 'Bearer Contexts modified'): f.write(" ogs_gtp2_tlv_" + v_lower(ies["ie_type"]) + "_t " + \ v_lower(ies["ie_value"]) + "[8];\n") else: @@ -671,13 +671,13 @@ for (k, v) in sorted_msg_list: f.write(" 0, 0, 0, 0, {\n") for ies in msg_list[k]["ies"]: f.write(" &ogs_gtp2_tlv_desc_%s_%s,\n" % (v_lower(ies["ie_type"]), v_lower(ies["instance"]))) - if (k == 'Create Indirect Data Forwarding Tunnel Request' or k == 'Create Indirect Data Forwarding Tunnel Response') and ies["ie_value"] == 'Bearer Contexts': + if ((k == 'Create Indirect Data Forwarding Tunnel Request' or k == 'Create Indirect Data Forwarding Tunnel Response') and ies["ie_value"] == 'Bearer Contexts') or (k == 'Modify Bearer Request' and ies["ie_value"] == 'Bearer Contexts to be modified') or (k == 'Modify Bearer Response' and ies["ie_value"] == 'Bearer Contexts modified'): f.write(" &ogs_tlv_desc_more8,\n") f.write(" NULL,\n") f.write("}};\n\n") f.write("\n") -f.write("""int ogs_gtp2_parse_msg(ogs_gtp2_message_t *gtp_message, ogs_pkbuf_t *pkbuf) +f.write("""int ogs_gtp2_parse_msg(ogs_gtp2_message_t *gtp2_message, ogs_pkbuf_t *pkbuf) { int rv = OGS_ERROR; ogs_gtp2_header_t *h = NULL; @@ -689,7 +689,7 @@ f.write("""int ogs_gtp2_parse_msg(ogs_gtp2_message_t *gtp_message, ogs_pkbuf_t * h = (ogs_gtp2_header_t *)pkbuf->data; ogs_assert(h); - + memset(gtp2_message, 0, sizeof(ogs_gtp2_message_t)); if (h->teid_presence) @@ -701,7 +701,7 @@ f.write("""int ogs_gtp2_parse_msg(ogs_gtp2_message_t *gtp_message, ogs_pkbuf_t * memcpy(>p2_message->h, pkbuf->data - size, size); if (h->teid_presence) - gtp2_message->h.teid = be32toh(gtp_message->h.teid); + gtp2_message->h.teid = be32toh(gtp2_message->h.teid); if (pkbuf->len == 0) { ogs_assert(ogs_pkbuf_push(pkbuf, size)); @@ -728,7 +728,7 @@ f.write(""" default: """) -f.write("""ogs_pkbuf_t *ogs_gtp2_build_msg(ogs_gtp2_message_t *gtp_message) +f.write("""ogs_pkbuf_t *ogs_gtp2_build_msg(ogs_gtp2_message_t *gtp2_message) { ogs_pkbuf_t *pkbuf = NULL; @@ -750,6 +750,4 @@ f.write(""" default: } """) -f.write("\n") - f.close() diff --git a/lib/gtp/xact.h b/lib/gtp/xact.h index e9907aee9..be6a31dcd 100644 --- a/lib/gtp/xact.h +++ b/lib/gtp/xact.h @@ -115,6 +115,10 @@ typedef struct ogs_gtp_xact_s { #define OGS_GTP_CREATE_IN_UPLINK_NAS_TRANSPORT 2 #define OGS_GTP_CREATE_IN_PATH_SWITCH_REQUEST 3 int create_action; + +#define OGS_GTP_MODIFY_IN_PATH_SWITCH_REQUEST 1 +#define OGS_GTP_MODIFY_IN_E_RAB_MODIFICATION 2 + int modify_action; } ogs_gtp_xact_t; int ogs_gtp_xact_init(void); diff --git a/lib/pfcp/path.c b/lib/pfcp/path.c index ad75b1a9b..b9569fb53 100644 --- a/lib/pfcp/path.c +++ b/lib/pfcp/path.c @@ -136,11 +136,14 @@ int ogs_pfcp_send_heartbeat_request(ogs_pfcp_node_t *node, h.type = OGS_PFCP_HEARTBEAT_REQUEST_TYPE; h.seid = 0; + xact = ogs_pfcp_xact_local_create(node, cb, node); + ogs_expect_or_return_val(xact, OGS_ERROR); + pkbuf = ogs_pfcp_build_heartbeat_request(h.type); ogs_expect_or_return_val(pkbuf, OGS_ERROR); - xact = ogs_pfcp_xact_local_create(node, &h, pkbuf, cb, node); - ogs_expect_or_return_val(xact, OGS_ERROR); + rv = ogs_pfcp_xact_update_tx(xact, &h, pkbuf); + ogs_expect_or_return_val(rv == OGS_OK, OGS_ERROR); rv = ogs_pfcp_xact_commit(xact); ogs_expect(rv == OGS_OK); @@ -186,11 +189,14 @@ int ogs_pfcp_cp_send_association_setup_request(ogs_pfcp_node_t *node, h.type = OGS_PFCP_ASSOCIATION_SETUP_REQUEST_TYPE; h.seid = 0; + xact = ogs_pfcp_xact_local_create(node, cb, node); + ogs_expect_or_return_val(xact, OGS_ERROR); + pkbuf = ogs_pfcp_cp_build_association_setup_request(h.type); ogs_expect_or_return_val(pkbuf, OGS_ERROR); - xact = ogs_pfcp_xact_local_create(node, &h, pkbuf, cb, node); - ogs_expect_or_return_val(xact, OGS_ERROR); + rv = ogs_pfcp_xact_update_tx(xact, &h, pkbuf); + ogs_expect_or_return_val(rv == OGS_OK, OGS_ERROR); rv = ogs_pfcp_xact_commit(xact); ogs_expect(rv == OGS_OK); @@ -237,11 +243,14 @@ int ogs_pfcp_up_send_association_setup_request(ogs_pfcp_node_t *node, h.type = OGS_PFCP_ASSOCIATION_SETUP_REQUEST_TYPE; h.seid = 0; + xact = ogs_pfcp_xact_local_create(node, cb, node); + ogs_expect_or_return_val(xact, OGS_ERROR); + pkbuf = ogs_pfcp_up_build_association_setup_request(h.type); ogs_expect_or_return_val(pkbuf, OGS_ERROR); - xact = ogs_pfcp_xact_local_create(node, &h, pkbuf, cb, node); - ogs_expect_or_return_val(xact, OGS_ERROR); + rv = ogs_pfcp_xact_update_tx(xact, &h, pkbuf); + ogs_expect_or_return_val(rv == OGS_OK, OGS_ERROR); rv = ogs_pfcp_xact_commit(xact); ogs_expect(rv == OGS_OK); diff --git a/lib/pfcp/xact.c b/lib/pfcp/xact.c index a548cc037..b78ae4f9a 100644 --- a/lib/pfcp/xact.c +++ b/lib/pfcp/xact.c @@ -72,10 +72,8 @@ void ogs_pfcp_xact_final(void) } ogs_pfcp_xact_t *ogs_pfcp_xact_local_create(ogs_pfcp_node_t *node, - ogs_pfcp_header_t *hdesc, ogs_pkbuf_t *pkbuf, void (*cb)(ogs_pfcp_xact_t *xact, void *data), void *data) { - int rv; char buf[OGS_ADDRSTRLEN]; ogs_pfcp_xact_t *xact = NULL; @@ -109,12 +107,7 @@ ogs_pfcp_xact_t *ogs_pfcp_xact_local_create(ogs_pfcp_node_t *node, ogs_list_add(xact->org == OGS_PFCP_LOCAL_ORIGINATOR ? &xact->node->local_list : &xact->node->remote_list, xact); - rv = ogs_pfcp_xact_update_tx(xact, hdesc, pkbuf); - if (rv != OGS_OK) { - ogs_error("ogs_pfcp_xact_update_tx(rv=%d) failed", (int)rv); - ogs_pfcp_xact_delete(xact); - return NULL; - } + ogs_list_init(&xact->pdr_to_create_list); ogs_debug("[%d] %s Create peer [%s]:%d", xact->xid, diff --git a/lib/pfcp/xact.h b/lib/pfcp/xact.h index 73595a483..eb77fd436 100644 --- a/lib/pfcp/xact.h +++ b/lib/pfcp/xact.h @@ -33,6 +33,8 @@ extern "C" { */ typedef struct ogs_pfcp_xact_s { ogs_lnode_t lnode; /**< A node of list */ + ogs_lnode_t tmpnode; /**< A node of temp-list */ + ogs_index_t index; #define OGS_PFCP_LOCAL_ORIGINATOR 0 @@ -114,13 +116,13 @@ typedef struct ogs_pfcp_xact_s { int delete_trigger; ogs_list_t pdr_to_create_list; + ogs_list_t bearer_to_modify_list; } ogs_pfcp_xact_t; int ogs_pfcp_xact_init(void); void ogs_pfcp_xact_final(void); ogs_pfcp_xact_t *ogs_pfcp_xact_local_create(ogs_pfcp_node_t *node, - ogs_pfcp_header_t *hdesc, ogs_pkbuf_t *pkbuf, void (*cb)(ogs_pfcp_xact_t *xact, void *data), void *data); ogs_pfcp_xact_t *ogs_pfcp_xact_cycle(ogs_pfcp_xact_t *xact); void ogs_pfcp_xact_delete_all(ogs_pfcp_node_t *node); diff --git a/src/amf/ngap-handler.c b/src/amf/ngap-handler.c index 0c317d4c1..057b5059b 100644 --- a/src/amf/ngap-handler.c +++ b/src/amf/ngap-handler.c @@ -1412,7 +1412,7 @@ void ngap_handle_ue_context_release_action(ran_ue_t *ran_ue) * An assert occurs when a NAS message retransmission occurs. * * Because there is no `ran_ue` context. - * + * * Therefore, before removing `ran_ue`, all Timers must be stopped * to prevent retransmission of NAS messages. */ @@ -2260,7 +2260,7 @@ void ngap_handle_path_switch_request( NGAP_InitiatingMessage_t *initiatingMessage = NULL; NGAP_PathSwitchRequest_t *PathSwitchRequest = NULL; - + NGAP_PathSwitchRequestIEs_t *ie = NULL; NGAP_RAN_UE_NGAP_ID_t *RAN_UE_NGAP_ID = NULL; NGAP_AMF_UE_NGAP_ID_t *AMF_UE_NGAP_ID = NULL; @@ -2294,7 +2294,7 @@ void ngap_handle_path_switch_request( ogs_assert(PathSwitchRequest); ogs_info("PathSwitchRequest"); - + for (i = 0; i < PathSwitchRequest->protocolIEs.list.count; i++) { ie = PathSwitchRequest->protocolIEs.list.array[i]; switch (ie->id) { @@ -2400,6 +2400,30 @@ void ngap_handle_path_switch_request( return; } + if (!UESecurityCapabilities) { + ogs_error("No UESecurityCapabilities"); + ogs_assert(OGS_OK == + ngap_send_error_indication2(amf_ue, + NGAP_Cause_PR_protocol, NGAP_CauseProtocol_semantic_error)); + return; + } + + if (!PDUSessionResourceToBeSwitchedDLList) { + ogs_error("No PDUSessionResourceToBeSwitchedDLList"); + ogs_assert(OGS_OK == + ngap_send_error_indication2(amf_ue, + NGAP_Cause_PR_protocol, NGAP_CauseProtocol_semantic_error)); + return; + } + + if (!SECURITY_CONTEXT_IS_VALID(amf_ue)) { + ogs_error("No Security Context"); + ogs_assert(OGS_OK == + ngap_send_error_indication2(amf_ue, + NGAP_Cause_PR_nas, NGAP_CauseNas_authentication_failure)); + return; + } + ogs_info(" [NEW] RAN_UE_NGAP_ID[%d] AMF_UE_NGAP_ID[%lld] ", ran_ue->ran_ue_ngap_id, (long long)ran_ue->amf_ue_ngap_id); @@ -2419,14 +2443,6 @@ void ngap_handle_path_switch_request( ogs_info(" [NEW] TAC[%d] CellID[0x%llx]", amf_ue->nr_tai.tac.v, (long long)amf_ue->nr_cgi.cell_id); - if (!UESecurityCapabilities) { - ogs_error("No UESecurityCapabilities"); - ogs_assert(OGS_OK == - ngap_send_error_indication2(amf_ue, - NGAP_Cause_PR_protocol, NGAP_CauseProtocol_semantic_error)); - return; - } - nRencryptionAlgorithms = &UESecurityCapabilities->nRencryptionAlgorithms; nRintegrityProtectionAlgorithms = &UESecurityCapabilities->nRintegrityProtectionAlgorithms; @@ -2460,26 +2476,10 @@ void ngap_handle_path_switch_request( amf_ue->ue_security_capability.eutra_ia = eutra_ia >> 9; amf_ue->ue_security_capability.eutra_ia0 = eutra_ia0; - if (!SECURITY_CONTEXT_IS_VALID(amf_ue)) { - ogs_error("No Security Context"); - ogs_assert(OGS_OK == - ngap_send_error_indication2(amf_ue, - NGAP_Cause_PR_nas, NGAP_CauseNas_authentication_failure)); - return; - } - /* Update Security Context (NextHop) */ amf_ue->nhcc++; ogs_kdf_nh_gnb(amf_ue->kamf, amf_ue->nh, amf_ue->nh); - if (!PDUSessionResourceToBeSwitchedDLList) { - ogs_error("No PDUSessionResourceToBeSwitchedDLList"); - ogs_assert(OGS_OK == - ngap_send_error_indication2(amf_ue, - NGAP_Cause_PR_protocol, NGAP_CauseProtocol_semantic_error)); - return; - } - for (i = 0; i < PDUSessionResourceToBeSwitchedDLList->list.count; i++) { amf_sess_t *sess = NULL; PDUSessionItem = (NGAP_PDUSessionResourceToBeSwitchedDLItem_t *) diff --git a/src/mme/esm-sm.c b/src/mme/esm-sm.c index abea64614..3db8d012c 100644 --- a/src/mme/esm-sm.c +++ b/src/mme/esm-sm.c @@ -179,8 +179,11 @@ void esm_state_inactive(ogs_fsm_t *s, mme_event_t *e) /* Check if Initial Context Setup Response or * E-RAB Setup Response is received */ if (MME_HAVE_ENB_S1U_PATH(bearer)) { + ogs_list_init(&mme_ue->bearer_to_modify_list); + ogs_list_add(&mme_ue->bearer_to_modify_list, + &bearer->to_modify_node); ogs_assert(OGS_OK == - mme_gtp_send_modify_bearer_request(bearer, 0)); + mme_gtp_send_modify_bearer_request(mme_ue, 0, 0)); } nas_eps_send_activate_all_dedicated_bearers(bearer); diff --git a/src/mme/mme-context.c b/src/mme/mme-context.c index f4b1124a7..c6ff06969 100644 --- a/src/mme/mme-context.c +++ b/src/mme/mme-context.c @@ -45,6 +45,7 @@ static OGS_POOL(mme_csmap_pool, mme_csmap_t); static OGS_POOL(mme_enb_pool, mme_enb_t); static OGS_POOL(mme_ue_pool, mme_ue_t); static OGS_POOL(enb_ue_pool, enb_ue_t); +static OGS_POOL(sgw_ue_pool, sgw_ue_t); static OGS_POOL(mme_sess_pool, mme_sess_t); static OGS_POOL(mme_bearer_pool, mme_bearer_t); @@ -58,6 +59,10 @@ static void stats_remove_enb_ue(void); static void stats_add_mme_session(void); static void stats_remove_mme_session(void); +static bool compare_ue_info(mme_sgw_t *node, enb_ue_t *enb_ue); +static mme_sgw_t *selected_sgw_node(mme_sgw_t *current, enb_ue_t *enb_ue); +static mme_sgw_t *changed_sgw_node(mme_sgw_t *current, enb_ue_t *enb_ue); + void mme_context_init() { ogs_assert(context_initialized == 0); @@ -96,6 +101,7 @@ void mme_context_init() ogs_pool_init(&mme_ue_pool, ogs_app()->max.ue); ogs_pool_init(&enb_ue_pool, ogs_app()->max.ue); + ogs_pool_init(&sgw_ue_pool, ogs_app()->max.ue); ogs_pool_init(&mme_sess_pool, ogs_app()->pool.sess); ogs_pool_init(&mme_bearer_pool, ogs_app()->pool.bearer); ogs_pool_init(&self.m_tmsi, ogs_app()->max.ue); @@ -141,6 +147,7 @@ void mme_context_final() ogs_pool_final(&mme_sess_pool); ogs_pool_final(&mme_ue_pool); ogs_pool_final(&enb_ue_pool); + ogs_pool_final(&sgw_ue_pool); ogs_pool_final(&mme_enb_pool); @@ -1557,6 +1564,8 @@ mme_sgw_t *mme_sgw_add(ogs_sockaddr_t *addr) ogs_list_init(&sgw->gnode.local_list); ogs_list_init(&sgw->gnode.remote_list); + ogs_list_init(&sgw->sgw_ue_list); + ogs_list_add(&self.sgw_list, sgw); return sgw; @@ -2019,6 +2028,112 @@ enb_ue_t *enb_ue_cycle(enb_ue_t *enb_ue) return ogs_pool_cycle(&enb_ue_pool, enb_ue); } +/** sgw_ue_context handling function */ +sgw_ue_t *sgw_ue_add(mme_sgw_t *sgw) +{ + sgw_ue_t *sgw_ue = NULL; + + ogs_assert(sgw); + + ogs_pool_alloc(&sgw_ue_pool, &sgw_ue); + ogs_assert(sgw_ue); + memset(sgw_ue, 0, sizeof *sgw_ue); + + sgw_ue->index = ogs_pool_index(&sgw_ue_pool, sgw_ue); + ogs_assert(sgw_ue->index > 0 && sgw_ue->index <= ogs_app()->max.ue); + + sgw_ue->mme_s11_teid = sgw_ue->index; + + sgw_ue->t_gtp2_holding = ogs_timer_add( + ogs_app()->timer_mgr, mme_timer_s11_holding_timer_expire, sgw_ue); + ogs_assert(sgw_ue->t_gtp2_holding); + + sgw_ue->sgw = sgw; + + ogs_list_add(&sgw->sgw_ue_list, sgw_ue); + + return sgw_ue; +} + +void sgw_ue_remove(sgw_ue_t *sgw_ue) +{ + mme_sgw_t *sgw = NULL; + + ogs_assert(sgw_ue); + sgw = sgw_ue->sgw; + ogs_assert(sgw); + + ogs_list_remove(&sgw->sgw_ue_list, sgw_ue); + + ogs_assert(sgw_ue->t_gtp2_holding); + ogs_timer_delete(sgw_ue->t_gtp2_holding); + + ogs_pool_free(&sgw_ue_pool, sgw_ue); +} + +void sgw_ue_switch_to_sgw(sgw_ue_t *sgw_ue, mme_sgw_t *new_sgw) +{ + ogs_assert(sgw_ue); + ogs_assert(sgw_ue->sgw); + ogs_assert(new_sgw); + + /* Remove from the old sgw */ + ogs_list_remove(&sgw_ue->sgw->sgw_ue_list, sgw_ue); + + /* Add to the new sgw */ + ogs_list_add(&new_sgw->sgw_ue_list, sgw_ue); + + /* Switch to sgw */ + sgw_ue->sgw = new_sgw; +} + +sgw_ue_t *sgw_ue_find(uint32_t index) +{ + return ogs_pool_find(&sgw_ue_pool, index); +} + +sgw_ue_t *sgw_ue_find_by_mme_s11_teid(uint32_t mme_s11_teid) +{ + return sgw_ue_find(mme_s11_teid); +} + +sgw_ue_t *sgw_ue_cycle(sgw_ue_t *sgw_ue) +{ + return ogs_pool_cycle(&sgw_ue_pool, sgw_ue); +} + +sgw_relocation_e sgw_ue_check_if_relocated(mme_ue_t *mme_ue) +{ + enb_ue_t *enb_ue = NULL; + sgw_ue_t *source_ue, *target_ue = NULL; + mme_sgw_t *current = NULL, *changed = NULL; + + ogs_assert(mme_ue); + enb_ue = enb_ue_cycle(mme_ue->enb_ue); + ogs_assert(enb_ue); + source_ue = sgw_ue_cycle(mme_ue->sgw_ue); + ogs_assert(source_ue); + + current = source_ue->sgw; + ogs_assert(current); + + changed = changed_sgw_node(current, enb_ue); + if (!changed) return SGW_WITHOUT_RELOCATION; + + target_ue = sgw_ue_cycle(source_ue->target_ue); + if (target_ue) { + ogs_error("SGW-UE source has already been associated with target"); + return SGW_HAS_ALREADY_BEEN_RELOCATED; + } + + target_ue = sgw_ue_add(changed); + ogs_assert(target_ue); + + sgw_ue_source_associate_target(source_ue, target_ue); + + return SGW_WITH_RELOCATION; +} + void mme_ue_new_guti(mme_ue_t *mme_ue) { served_gummei_t *served_gummei = NULL; @@ -2111,7 +2226,7 @@ static mme_sgw_t *selected_sgw_node(mme_sgw_t *current, enb_ue_t *enb_ue) return next ? next : ogs_list_first(&mme_self()->sgw_list); } -mme_sgw_t *mme_changed_sgw_node(mme_sgw_t *current, enb_ue_t *enb_ue) +static mme_sgw_t *changed_sgw_node(mme_sgw_t *current, enb_ue_t *enb_ue) { mme_sgw_t *changed = NULL; @@ -2129,6 +2244,7 @@ mme_ue_t *mme_ue_add(enb_ue_t *enb_ue) { mme_enb_t *enb = NULL; mme_ue_t *mme_ue = NULL; + sgw_ue_t *sgw_ue = NULL; char buf[OGS_ADDRSTRLEN]; @@ -2144,10 +2260,6 @@ mme_ue_t *mme_ue_add(enb_ue_t *enb_ue) ogs_list_init(&mme_ue->sess_list); - mme_ue->mme_s11_teid = ogs_pool_index(&mme_ue_pool, mme_ue); - ogs_assert(mme_ue->mme_s11_teid > 0 && - mme_ue->mme_s11_teid <= ogs_app()->max.ue); - /* * When used for the first time, if last node is set, * the search is performed from the first SGW in a round-robin manner. @@ -2156,10 +2268,16 @@ mme_ue_t *mme_ue_add(enb_ue_t *enb_ue) mme_self()->sgw = ogs_list_last(&mme_self()->sgw_list); /* setup GTP path with selected SGW */ - mme_ue->sgw = mme_self()->sgw = selected_sgw_node(mme_self()->sgw, enb_ue); - ogs_assert(mme_ue->sgw); - ogs_assert(mme_ue->gnode); - ogs_debug("UE using SGW on IP[%s]", OGS_ADDR(mme_ue->gnode->sa_list, buf)); + mme_self()->sgw = selected_sgw_node(mme_self()->sgw, enb_ue); + ogs_assert(mme_self()->sgw); + + sgw_ue = sgw_ue_add(mme_self()->sgw); + ogs_assert(sgw_ue); + ogs_assert(sgw_ue->gnode); + + sgw_ue_associate_mme_ue(sgw_ue, mme_ue); + + ogs_debug("UE using SGW on IP[%s]", OGS_ADDR(sgw_ue->gnode->sa_list, buf)); /* Clear VLR */ mme_ue->csmap = NULL; @@ -2213,6 +2331,9 @@ void mme_ue_remove(mme_ue_t *mme_ue) mme_ue_fsm_fini(mme_ue); + ogs_assert(mme_ue->sgw_ue); + sgw_ue_remove(mme_ue->sgw_ue); + if (mme_ue->current.m_tmsi) ogs_assert(mme_m_tmsi_free(mme_ue->current.m_tmsi) == OGS_OK); @@ -2239,7 +2360,7 @@ void mme_ue_remove(mme_ue_t *mme_ue) ogs_timer_delete(mme_ue->t3460.timer); ogs_timer_delete(mme_ue->t3470.timer); - mme_ue_deassociate(mme_ue); + enb_ue_unlink(mme_ue); mme_sess_remove_all(mme_ue); mme_session_remove_all(mme_ue); @@ -2317,11 +2438,6 @@ mme_ue_t *mme_ue_find_by_guti(ogs_nas_eps_guti_t *guti) self.guti_ue_hash, guti, sizeof(ogs_nas_eps_guti_t)); } -mme_ue_t *mme_ue_find_by_teid(uint32_t teid) -{ - return ogs_pool_find(&mme_ue_pool, teid); -} - mme_ue_t *mme_ue_find_by_message(ogs_nas_eps_message_t *message) { mme_ue_t *mme_ue = NULL; @@ -2598,7 +2714,7 @@ bool mme_ue_have_active_eps_bearers(mme_ue_t *mme_ue) return false; } -void mme_ue_associate_enb_ue(mme_ue_t *mme_ue, enb_ue_t *enb_ue) +void enb_ue_associate_mme_ue(enb_ue_t *enb_ue, mme_ue_t *mme_ue) { ogs_assert(mme_ue); ogs_assert(enb_ue); @@ -2613,14 +2729,13 @@ void enb_ue_deassociate(enb_ue_t *enb_ue) enb_ue->mme_ue = NULL; } -void mme_ue_deassociate(mme_ue_t *mme_ue) +void enb_ue_unlink(mme_ue_t *mme_ue) { ogs_assert(mme_ue); mme_ue->enb_ue = NULL; } -void source_ue_associate_target_ue( - enb_ue_t *source_ue, enb_ue_t *target_ue) +void enb_ue_source_associate_target(enb_ue_t *source_ue, enb_ue_t *target_ue) { mme_ue_t *mme_ue = NULL; @@ -2634,7 +2749,7 @@ void source_ue_associate_target_ue( source_ue->target_ue = target_ue; } -void source_ue_deassociate_target_ue(enb_ue_t *enb_ue) +void enb_ue_source_deassociate_target(enb_ue_t *enb_ue) { enb_ue_t *source_ue = NULL; enb_ue_t *target_ue = NULL; @@ -2659,6 +2774,66 @@ void source_ue_deassociate_target_ue(enb_ue_t *enb_ue) } } +void sgw_ue_associate_mme_ue(sgw_ue_t *sgw_ue, mme_ue_t *mme_ue) +{ + ogs_assert(mme_ue); + ogs_assert(sgw_ue); + + mme_ue->sgw_ue = sgw_ue; + sgw_ue->mme_ue = mme_ue; +} + +void sgw_ue_deassociate(sgw_ue_t *sgw_ue) +{ + ogs_assert(sgw_ue); + sgw_ue->mme_ue = NULL; +} + +void sgw_ue_unlink(mme_ue_t *mme_ue) +{ + ogs_assert(mme_ue); + mme_ue->sgw_ue = NULL; +} + +void sgw_ue_source_associate_target(sgw_ue_t *source_ue, sgw_ue_t *target_ue) +{ + mme_ue_t *mme_ue = NULL; + + ogs_assert(source_ue); + ogs_assert(target_ue); + mme_ue = source_ue->mme_ue; + ogs_assert(mme_ue); + + target_ue->mme_ue = mme_ue; + target_ue->source_ue = source_ue; + source_ue->target_ue = target_ue; +} + +void sgw_ue_source_deassociate_target(sgw_ue_t *sgw_ue) +{ + sgw_ue_t *source_ue = NULL; + sgw_ue_t *target_ue = NULL; + ogs_assert(sgw_ue); + + if (sgw_ue->target_ue) { + source_ue = sgw_ue; + target_ue = sgw_ue->target_ue; + + ogs_assert(source_ue->target_ue); + ogs_assert(target_ue->source_ue); + source_ue->target_ue = NULL; + target_ue->source_ue = NULL; + } else if (sgw_ue->source_ue) { + target_ue = sgw_ue; + source_ue = sgw_ue->source_ue; + + ogs_assert(source_ue->target_ue); + ogs_assert(target_ue->source_ue); + source_ue->target_ue = NULL; + target_ue->source_ue = NULL; + } +} + mme_sess_t *mme_sess_add(mme_ue_t *mme_ue, uint8_t pti) { mme_sess_t *sess = NULL; diff --git a/src/mme/mme-context.h b/src/mme/mme-context.h index f94788d83..26422b826 100644 --- a/src/mme/mme-context.h +++ b/src/mme/mme-context.h @@ -54,6 +54,7 @@ typedef struct mme_vlr_s mme_vlr_t; typedef struct mme_csmap_s mme_csmap_t; typedef struct enb_ue_s enb_ue_t; +typedef struct sgw_ue_s sgw_ue_t; typedef struct mme_ue_s mme_ue_t; typedef struct mme_sess_s mme_sess_t; typedef struct mme_bearer_s mme_bearer_t; @@ -153,6 +154,8 @@ typedef struct mme_sgw_s { uint8_t num_of_tac; uint32_t e_cell_id[OGS_MAX_NUM_OF_CELL_ID]; uint8_t num_of_e_cell_id; + + ogs_list_t sgw_ue_list; } mme_sgw_t; typedef struct mme_pgw_s { @@ -237,7 +240,7 @@ struct enb_ue_s { /* Use mme_ue->tai, mme_ue->e_cgi. * Do not access enb_ue->saved.tai enb_ue->saved.e_cgi. - * + * * Save TAI and ECGI. And then, this will copy 'mme_ue_t' context later */ struct { ogs_eps_tai_t tai; @@ -264,7 +267,37 @@ struct enb_ue_s { /* Related Context */ mme_enb_t *enb; mme_ue_t *mme_ue; -}; +}; + +struct sgw_ue_s { + ogs_lnode_t lnode; + uint32_t index; + + sgw_ue_t *source_ue; + sgw_ue_t *target_ue; + + /* UE identity */ + uint32_t mme_s11_teid; /* MME-S11-TEID is derived from INDEX */ + uint32_t sgw_s11_teid; /* SGW-S11-TEID is received from SGW */ + + /* + * If the MME sends Delete-Session-Request to the SGW for all sessions, + * session_context_will_deleted = 1 + * When the MME receives a Delete-Session-Response for the last session, + * session_context_will_deleted = 0 + */ + int session_context_will_deleted; + + /* GTPv2-C Holding timer for removing this context */ + ogs_timer_t *t_gtp2_holding; + + /* Related Context */ + union { + mme_sgw_t *sgw; + ogs_gtp_node_t *gnode; + }; + mme_ue_t *mme_ue; +}; struct mme_ue_s { ogs_lnode_t lnode; @@ -275,8 +308,8 @@ struct mme_ue_s { #define MME_EPS_TYPE_TAU_REQUEST 2 #define MME_EPS_TYPE_SERVICE_REQUEST 3 #define MME_EPS_TYPE_EXTENDED_SERVICE_REQUEST 4 -#define MME_EPS_TYPE_DETACH_REQUEST_FROM_UE 5 -#define MME_EPS_TYPE_DETACH_REQUEST_TO_UE 6 +#define MME_EPS_TYPE_DETACH_REQUEST_FROM_UE 5 +#define MME_EPS_TYPE_DETACH_REQUEST_TO_UE 6 uint8_t type; uint8_t ksi; union { @@ -318,9 +351,6 @@ struct mme_ue_s { ogs_nas_eps_guti_t guti; } current, next; - uint32_t mme_s11_teid; /* MME-S11-TEID is derived from INDEX */ - uint32_t sgw_s11_teid; /* SGW-S11-TEID is received from SGW */ - uint16_t vlr_ostream_id; /* SCTP output stream id for VLR */ /* UE Info */ @@ -354,7 +384,7 @@ struct mme_ue_s { uint8_t kasme[OGS_SHA256_DIGEST_SIZE]; uint8_t rand[OGS_RAND_LEN]; uint8_t autn[OGS_AUTN_LEN]; - uint8_t knas_int[OGS_SHA256_DIGEST_SIZE/2]; + uint8_t knas_int[OGS_SHA256_DIGEST_SIZE/2]; uint8_t knas_enc[OGS_SHA256_DIGEST_SIZE/2]; uint32_t dl_count; union { @@ -417,6 +447,9 @@ struct mme_ue_s { (((__mME)->enb_ue == NULL) || (enb_ue_cycle((__mME)->enb_ue) == NULL))) enb_ue_t *enb_ue; /* S1 UE context */ + /* SGW UE context */ + sgw_ue_t *sgw_ue; + /* Save PDN Connectivity Request */ ogs_nas_esm_message_container_t pdn_connectivity_request; @@ -507,32 +540,23 @@ struct mme_ue_s { uint8_t response; } gtp_counter[MAX_NUM_OF_GTP_COUNTER]; - /* - * If the MME sends Delete-Session-Request to the SGW for all sessions, - * session_context_will_deleted = 1 - * When the MME receives a Delete-Session-Response for the last session, - * session_context_will_deleted = 0 - */ - int session_context_will_deleted; + ogs_list_t bearer_to_modify_list; - union { - mme_sgw_t *sgw; - ogs_gtp_node_t *gnode; - }; mme_csmap_t *csmap; }; #define SESSION_CONTEXT_IS_AVAILABLE(__mME) \ - ((__mME) && ((__mME)->sgw_s11_teid)) + ((__mME) && ((__mME)->sgw_ue) && (((__mME)->sgw_ue)->sgw_s11_teid)) #define SESSION_CONTEXT_WILL_DELETED(__mME) \ - ((__mME) && ((__mME)->session_context_will_deleted)) + ((__mME) && ((__mME)->sgw_ue) && \ + (((__mME)->sgw_ue)->session_context_will_deleted)) #define CLEAR_SESSION_CONTEXT(__mME) \ do { \ ogs_assert((__mME)); \ - (__mME)->sgw_s11_teid = 0; \ - (__mME)->session_context_will_deleted = 0; \ + ((__mME)->sgw_ue)->sgw_s11_teid = 0; \ + ((__mME)->sgw_ue)->session_context_will_deleted = 0; \ } while(0) #define ACTIVE_EPS_BEARERS_IS_AVAIABLE(__mME) \ @@ -542,22 +566,24 @@ typedef struct mme_sess_s { uint8_t pti; /* Procedure Trasaction Identity */ + uint32_t pgw_s5c_teid; + /* PDN Connectivity Request */ - ogs_nas_request_type_t request_type; + ogs_nas_request_type_t request_type; /* mme_bearer_first(sess) : Default Bearer Context */ ogs_list_t bearer_list; /* Related Context */ - mme_ue_t *mme_ue; + mme_ue_t *mme_ue; - ogs_session_t *session; + ogs_session_t *session; /* Save Protocol Configuration Options from UE */ struct { uint8_t length; uint8_t *buffer; - } ue_pco; + } ue_pco; /* Save Protocol Configuration Options from PGW */ ogs_tlv_octet_t pgw_pco; @@ -600,6 +626,8 @@ typedef struct mme_sess_s { } while(0) typedef struct mme_bearer_s { ogs_lnode_t lnode; + ogs_lnode_t to_modify_node; + uint32_t index; ogs_fsm_t sm; /* State Machine */ @@ -702,6 +730,20 @@ enb_ue_t *enb_ue_find(uint32_t index); enb_ue_t *enb_ue_find_by_mme_ue_s1ap_id(uint32_t mme_ue_s1ap_id); enb_ue_t *enb_ue_cycle(enb_ue_t *enb_ue); +sgw_ue_t *sgw_ue_add(mme_sgw_t *sgw); +void sgw_ue_remove(sgw_ue_t *sgw_ue); +void sgw_ue_switch_to_sgw(sgw_ue_t *sgw_ue, mme_sgw_t *new_sgw); +sgw_ue_t *sgw_ue_find(uint32_t index); +sgw_ue_t *sgw_ue_find_by_mme_s11_teid(uint32_t mme_s11_teid); +sgw_ue_t *sgw_ue_cycle(sgw_ue_t *sgw_ue); + +typedef enum { + SGW_WITHOUT_RELOCATION = 1, + SGW_WITH_RELOCATION = 2, + SGW_HAS_ALREADY_BEEN_RELOCATED = 3, +} sgw_relocation_e; +sgw_relocation_e sgw_ue_check_if_relocated(mme_ue_t *mme_ue); + void mme_ue_new_guti(mme_ue_t *mme_ue); void mme_ue_confirm_guti(mme_ue_t *mme_ue); @@ -716,7 +758,6 @@ void mme_ue_fsm_fini(mme_ue_t *mme_ue); mme_ue_t *mme_ue_find_by_imsi(uint8_t *imsi, int imsi_len); mme_ue_t *mme_ue_find_by_imsi_bcd(char *imsi_bcd); mme_ue_t *mme_ue_find_by_guti(ogs_nas_eps_guti_t *nas_guti); -mme_ue_t *mme_ue_find_by_teid(uint32_t teid); mme_ue_t *mme_ue_find_by_message(ogs_nas_eps_message_t *message); int mme_ue_set_imsi(mme_ue_t *mme_ue, char *imsi_bcd); @@ -726,7 +767,7 @@ void mme_ue_clear_indirect_tunnel(mme_ue_t *mme_ue); bool mme_ue_have_active_eps_bearers(mme_ue_t *mme_ue); -/* +/* * o RECV Initial UE-Message : S-TMSI * o RECV Attach Request : IMSI, GUTI * o RECV TAU Request : GUTI @@ -734,23 +775,23 @@ bool mme_ue_have_active_eps_bearers(mme_ue_t *mme_ue); * ### MME_UE_ECM_CONNECTED() ### * * o RECV Initial Context Setup Failure in EMM Registered State - * ### MME_UE_DEASSOCIATE_ENB_UE() ### + * ### ENB_UE_DEASSOCIATE_MME_UE() ### * ### ENB_UE_REMOVE() ### - * ### MME_UE_DEASSOCIATE() ### + * ### ENB_UE_UNLINK() ### * - * o SEND UE Context Release Command with NO_ACTION + * o SEND UE Context Release Command with S1_REMOVE_AND_UNLINK * - RECV UE Context Release Complete * ### ENB_UE_REMOVE() ### - * ### MME_UE_DEASSOCIATE() ### + * ### ENB_UE_UNLINK() ### * - * o SEND UE Context Release Command with REMOVE_MME_UE_CONTEXT + * o SEND UE Context Release Command with UE_CONTEXT_REMOVE * - RECV UE Context Release Complete * ### ENB_UE_REMOVE() ### * ### MME_UE_REMOVE() ### * * * o RECV Handover Required - * ### SOURCE_UE_ASSOCIATE_TARGET_UE() #### + * ### ENB_UE_SOURCE_ASSOCIATE_TARGET() #### * - SEND Handover Request * * o RECV Handover Notify @@ -758,27 +799,33 @@ bool mme_ue_have_active_eps_bearers(mme_ue_t *mme_ue); * ### MME_UE_ECM_CONNECTED(TARGET) ### * - Modify Bearer Request/Response * - UE Context Release Command/Complete - * ### SOURCE_UE_DEASSOCIATE_TARGET_UE() #### + * ### ENB_UE_SOURCE_DEASSOCIATE_TARGET() #### * ### ENB_UE_REMOVE() #### * - Delete Indirect Data Forwarding Tunnel Request/Response * * o RECV Handover Cancel * - UE Context Release Command/Complete - * ### SOURCE_UE_DEASSOCIATE_TARGET_UE() #### + * ### ENB_UE_SOURCE_DEASSOCIATE_TARGET() #### * ### ENB_UE_REMOVE() #### * - Delete Indirect Data Forwarding Tunnel Request/Response * * o RECV Handover Failure * - UE Context Release Command/Complete - * ### SOURCE_UE_DEASSOCIATE_TARGET_UE() #### + * ### ENB_UE_SOURCE_DEASSOCIATE_TARGET() #### * ### ENB_UE_REMOVE() #### * - Delete Indirect Data Forwarding Tunnel Request/Response */ -void mme_ue_associate_enb_ue(mme_ue_t *mme_ue, enb_ue_t *enb_ue); +void enb_ue_associate_mme_ue(enb_ue_t *enb_ue, mme_ue_t *mme_ue); void enb_ue_deassociate(enb_ue_t *enb_ue); -void mme_ue_deassociate(mme_ue_t *mme_ue); -void source_ue_associate_target_ue(enb_ue_t *source_ue, enb_ue_t *target_ue); -void source_ue_deassociate_target_ue(enb_ue_t *enb_ue); +void enb_ue_unlink(mme_ue_t *mme_ue); +void enb_ue_source_associate_target(enb_ue_t *source_ue, enb_ue_t *target_ue); +void enb_ue_source_deassociate_target(enb_ue_t *enb_ue); + +void sgw_ue_associate_mme_ue(sgw_ue_t *sgw_ue, mme_ue_t *mme_ue); +void sgw_ue_deassociate(sgw_ue_t *sgw_ue); +void sgw_ue_unlink(mme_ue_t *mme_ue); +void sgw_ue_source_associate_target(sgw_ue_t *source_ue, sgw_ue_t *target_ue); +void sgw_ue_source_deassociate_target(sgw_ue_t *sgw_ue); mme_sess_t *mme_sess_add(mme_ue_t *mme_ue, uint8_t pti); void mme_sess_remove(mme_sess_t *sess); @@ -821,8 +868,6 @@ void mme_ebi_pool_clear(mme_ue_t *mme_ue); uint8_t mme_selected_int_algorithm(mme_ue_t *mme_ue); uint8_t mme_selected_enc_algorithm(mme_ue_t *mme_ue); -mme_sgw_t *mme_changed_sgw_node(mme_sgw_t *current, enb_ue_t *enb_ue); - #ifdef __cplusplus } #endif diff --git a/src/mme/mme-event.h b/src/mme/mme-event.h index 8654e01a8..38af33c47 100644 --- a/src/mme/mme-event.h +++ b/src/mme/mme-event.h @@ -61,6 +61,7 @@ typedef struct ogs_diam_s6a_message_s ogs_diam_s6a_message_t; typedef struct mme_vlr_s mme_vlr_t; typedef struct mme_enb_s mme_enb_t; typedef struct enb_ue_s enb_ue_t; +typedef struct sgw_ue_s sgw_ue_t; typedef struct mme_ue_s mme_ue_t; typedef struct mme_sess_s mme_sess_t; typedef struct mme_bearer_s mme_bearer_t; @@ -91,6 +92,7 @@ typedef struct mme_event_s { mme_vlr_t *vlr; mme_enb_t *enb; enb_ue_t *enb_ue; + sgw_ue_t *sgw_ue; mme_ue_t *mme_ue; mme_sess_t *sess; mme_bearer_t *bearer; diff --git a/src/mme/mme-gtp-path.c b/src/mme/mme-gtp-path.c index 1552d222a..291d11f13 100644 --- a/src/mme/mme-gtp-path.c +++ b/src/mme/mme-gtp-path.c @@ -86,6 +86,7 @@ static void timeout(ogs_gtp_xact_t *xact, void *data) type = xact->seq[0].type; switch (type) { + case OGS_GTP2_MODIFY_BEARER_REQUEST_TYPE: case OGS_GTP2_RELEASE_ACCESS_BEARERS_REQUEST_TYPE: case OGS_GTP2_CREATE_INDIRECT_DATA_FORWARDING_TUNNEL_REQUEST_TYPE: case OGS_GTP2_DELETE_INDIRECT_DATA_FORWARDING_TUNNEL_REQUEST_TYPE: @@ -99,7 +100,6 @@ static void timeout(ogs_gtp_xact_t *xact, void *data) mme_ue = sess->mme_ue; ogs_assert(mme_ue); break; - case OGS_GTP2_MODIFY_BEARER_REQUEST_TYPE: case OGS_GTP2_BEARER_RESOURCE_COMMAND_TYPE: bearer = data; ogs_assert(bearer); @@ -206,18 +206,26 @@ int mme_gtp_send_create_session_request(mme_sess_t *sess, int create_action) ogs_pkbuf_t *pkbuf = NULL; ogs_gtp_xact_t *xact = NULL; mme_ue_t *mme_ue = NULL; + sgw_ue_t *sgw_ue = NULL; mme_ue = sess->mme_ue; ogs_assert(mme_ue); + sgw_ue = sgw_ue_cycle(mme_ue->sgw_ue); + ogs_assert(sgw_ue); + + if (create_action == OGS_GTP_CREATE_IN_PATH_SWITCH_REQUEST) { + sgw_ue = sgw_ue_cycle(sgw_ue->target_ue); + ogs_assert(sgw_ue); + } memset(&h, 0, sizeof(ogs_gtp2_header_t)); h.type = OGS_GTP2_CREATE_SESSION_REQUEST_TYPE; - h.teid = mme_ue->sgw_s11_teid; + h.teid = sgw_ue->sgw_s11_teid; - pkbuf = mme_s11_build_create_session_request(h.type, sess); + pkbuf = mme_s11_build_create_session_request(h.type, sess, create_action); ogs_expect_or_return_val(pkbuf, OGS_ERROR); - xact = ogs_gtp_xact_local_create(mme_ue->gnode, &h, pkbuf, timeout, sess); + xact = ogs_gtp_xact_local_create(sgw_ue->gnode, &h, pkbuf, timeout, sess); ogs_expect_or_return_val(xact, OGS_ERROR); xact->create_action = create_action; @@ -227,29 +235,31 @@ int mme_gtp_send_create_session_request(mme_sess_t *sess, int create_action) return rv; } -int mme_gtp_send_modify_bearer_request(mme_bearer_t *bearer, int uli_presence) +int mme_gtp_send_modify_bearer_request( + mme_ue_t *mme_ue, int uli_presence, int modify_action) { int rv; ogs_gtp_xact_t *xact = NULL; - mme_ue_t *mme_ue = NULL; + sgw_ue_t *sgw_ue = NULL; ogs_gtp2_header_t h; ogs_pkbuf_t *pkbuf = NULL; - ogs_assert(bearer); - mme_ue = bearer->mme_ue; ogs_assert(mme_ue); + sgw_ue = mme_ue->sgw_ue; + ogs_assert(sgw_ue); memset(&h, 0, sizeof(ogs_gtp2_header_t)); h.type = OGS_GTP2_MODIFY_BEARER_REQUEST_TYPE; - h.teid = mme_ue->sgw_s11_teid; + h.teid = sgw_ue->sgw_s11_teid; - pkbuf = mme_s11_build_modify_bearer_request(h.type, bearer, uli_presence); + pkbuf = mme_s11_build_modify_bearer_request(h.type, mme_ue, uli_presence); ogs_expect_or_return_val(pkbuf, OGS_ERROR); - xact = ogs_gtp_xact_local_create(mme_ue->gnode, &h, pkbuf, timeout, bearer); + xact = ogs_gtp_xact_local_create(sgw_ue->gnode, &h, pkbuf, timeout, mme_ue); ogs_expect_or_return_val(xact, OGS_ERROR); + xact->modify_action = modify_action; rv = ogs_gtp_xact_commit(xact); ogs_expect(rv == OGS_OK); @@ -264,20 +274,23 @@ int mme_gtp_send_delete_session_request(mme_sess_t *sess, int action) ogs_gtp2_header_t h; ogs_gtp_xact_t *xact = NULL; mme_ue_t *mme_ue = NULL; + sgw_ue_t *sgw_ue = NULL; ogs_assert(action); ogs_assert(sess); mme_ue = sess->mme_ue; ogs_assert(mme_ue); + sgw_ue = mme_ue->sgw_ue; + ogs_assert(sgw_ue); memset(&h, 0, sizeof(ogs_gtp2_header_t)); h.type = OGS_GTP2_DELETE_SESSION_REQUEST_TYPE; - h.teid = mme_ue->sgw_s11_teid; + h.teid = sgw_ue->sgw_s11_teid; s11buf = mme_s11_build_delete_session_request(h.type, sess); ogs_expect_or_return_val(s11buf, OGS_ERROR); - xact = ogs_gtp_xact_local_create(mme_ue->gnode, &h, s11buf, timeout, sess); + xact = ogs_gtp_xact_local_create(sgw_ue->gnode, &h, s11buf, timeout, sess); ogs_expect_or_return_val(xact, OGS_ERROR); xact->delete_action = action; @@ -290,8 +303,11 @@ int mme_gtp_send_delete_session_request(mme_sess_t *sess, int action) void mme_gtp_send_delete_all_sessions(mme_ue_t *mme_ue, int action) { mme_sess_t *sess = NULL, *next_sess = NULL; + sgw_ue_t *sgw_ue = NULL; ogs_assert(mme_ue); + sgw_ue = mme_ue->sgw_ue; + ogs_assert(sgw_ue); ogs_assert(action); if (SESSION_CONTEXT_WILL_DELETED(mme_ue)) { @@ -300,7 +316,7 @@ void mme_gtp_send_delete_all_sessions(mme_ue_t *mme_ue, int action) return; } - mme_ue->session_context_will_deleted = 1; + sgw_ue->session_context_will_deleted = 1; sess = mme_sess_first(mme_ue); while (sess != NULL) { @@ -331,6 +347,7 @@ int mme_gtp_send_create_bearer_response( ogs_gtp_xact_t *xact = NULL; mme_ue_t *mme_ue = NULL; + sgw_ue_t *sgw_ue = NULL; ogs_gtp2_header_t h; ogs_pkbuf_t *pkbuf = NULL; @@ -338,12 +355,14 @@ int mme_gtp_send_create_bearer_response( ogs_assert(bearer); mme_ue = bearer->mme_ue; ogs_assert(mme_ue); + sgw_ue = mme_ue->sgw_ue; + ogs_assert(sgw_ue); xact = ogs_gtp_xact_cycle(bearer->create.xact); ogs_assert(xact); memset(&h, 0, sizeof(ogs_gtp2_header_t)); h.type = OGS_GTP2_CREATE_BEARER_RESPONSE_TYPE; - h.teid = mme_ue->sgw_s11_teid; + h.teid = sgw_ue->sgw_s11_teid; pkbuf = mme_s11_build_create_bearer_response(h.type, bearer, cause_value); ogs_expect_or_return_val(pkbuf, OGS_ERROR); @@ -364,6 +383,7 @@ int mme_gtp_send_update_bearer_response( ogs_gtp_xact_t *xact = NULL; mme_ue_t *mme_ue = NULL; + sgw_ue_t *sgw_ue = NULL; ogs_gtp2_header_t h; ogs_pkbuf_t *pkbuf = NULL; @@ -371,12 +391,14 @@ int mme_gtp_send_update_bearer_response( ogs_assert(bearer); mme_ue = bearer->mme_ue; ogs_assert(mme_ue); + sgw_ue = mme_ue->sgw_ue; + ogs_assert(sgw_ue); xact = ogs_gtp_xact_cycle(bearer->update.xact); ogs_assert(xact); memset(&h, 0, sizeof(ogs_gtp2_header_t)); h.type = OGS_GTP2_UPDATE_BEARER_RESPONSE_TYPE; - h.teid = mme_ue->sgw_s11_teid; + h.teid = sgw_ue->sgw_s11_teid; pkbuf = mme_s11_build_update_bearer_response(h.type, bearer, cause_value); ogs_expect_or_return_val(pkbuf, OGS_ERROR); @@ -397,6 +419,7 @@ int mme_gtp_send_delete_bearer_response( ogs_gtp_xact_t *xact = NULL; mme_ue_t *mme_ue = NULL; + sgw_ue_t *sgw_ue = NULL; ogs_gtp2_header_t h; ogs_pkbuf_t *pkbuf = NULL; @@ -404,12 +427,14 @@ int mme_gtp_send_delete_bearer_response( ogs_assert(bearer); mme_ue = bearer->mme_ue; ogs_assert(mme_ue); + sgw_ue = mme_ue->sgw_ue; + ogs_assert(sgw_ue); xact = ogs_gtp_xact_cycle(bearer->delete.xact); ogs_assert(xact); memset(&h, 0, sizeof(ogs_gtp2_header_t)); h.type = OGS_GTP2_DELETE_BEARER_RESPONSE_TYPE; - h.teid = mme_ue->sgw_s11_teid; + h.teid = sgw_ue->sgw_s11_teid; pkbuf = mme_s11_build_delete_bearer_response(h.type, bearer, cause_value); ogs_expect_or_return_val(pkbuf, OGS_ERROR); @@ -429,18 +454,21 @@ int mme_gtp_send_release_access_bearers_request(mme_ue_t *mme_ue, int action) ogs_gtp2_header_t h; ogs_pkbuf_t *pkbuf = NULL; ogs_gtp_xact_t *xact = NULL; + sgw_ue_t *sgw_ue = NULL; ogs_assert(action); ogs_assert(mme_ue); + sgw_ue = mme_ue->sgw_ue; + ogs_assert(sgw_ue); memset(&h, 0, sizeof(ogs_gtp2_header_t)); h.type = OGS_GTP2_RELEASE_ACCESS_BEARERS_REQUEST_TYPE; - h.teid = mme_ue->sgw_s11_teid; + h.teid = sgw_ue->sgw_s11_teid; pkbuf = mme_s11_build_release_access_bearers_request(h.type); ogs_expect_or_return_val(pkbuf, OGS_ERROR); - xact = ogs_gtp_xact_local_create(mme_ue->gnode, &h, pkbuf, timeout, mme_ue); + xact = ogs_gtp_xact_local_create(sgw_ue->gnode, &h, pkbuf, timeout, mme_ue); ogs_expect_or_return_val(xact, OGS_ERROR); xact->release_action = action; @@ -483,6 +511,7 @@ int mme_gtp_send_downlink_data_notification_ack( { int rv; mme_ue_t *mme_ue = NULL; + sgw_ue_t *sgw_ue = NULL; ogs_gtp_xact_t *xact = NULL; ogs_gtp2_header_t h; @@ -493,11 +522,13 @@ int mme_gtp_send_downlink_data_notification_ack( ogs_assert(xact); mme_ue = bearer->mme_ue; ogs_assert(mme_ue); + sgw_ue = mme_ue->sgw_ue; + ogs_assert(sgw_ue); /* Build Downlink data notification ack */ memset(&h, 0, sizeof(ogs_gtp2_header_t)); h.type = OGS_GTP2_DOWNLINK_DATA_NOTIFICATION_ACKNOWLEDGE_TYPE; - h.teid = mme_ue->sgw_s11_teid; + h.teid = sgw_ue->sgw_s11_teid; s11buf = mme_s11_build_downlink_data_notification_ack(h.type, cause_value); ogs_expect_or_return_val(s11buf, OGS_ERROR); @@ -518,18 +549,21 @@ int mme_gtp_send_create_indirect_data_forwarding_tunnel_request( ogs_gtp2_header_t h; ogs_pkbuf_t *pkbuf = NULL; ogs_gtp_xact_t *xact = NULL; + sgw_ue_t *sgw_ue = NULL; ogs_assert(mme_ue); + sgw_ue = mme_ue->sgw_ue; + ogs_assert(sgw_ue); memset(&h, 0, sizeof(ogs_gtp2_header_t)); h.type = OGS_GTP2_CREATE_INDIRECT_DATA_FORWARDING_TUNNEL_REQUEST_TYPE; - h.teid = mme_ue->sgw_s11_teid; + h.teid = sgw_ue->sgw_s11_teid; pkbuf = mme_s11_build_create_indirect_data_forwarding_tunnel_request( h.type, mme_ue); ogs_expect_or_return_val(pkbuf, OGS_ERROR); - xact = ogs_gtp_xact_local_create(mme_ue->gnode, &h, pkbuf, timeout, mme_ue); + xact = ogs_gtp_xact_local_create(sgw_ue->gnode, &h, pkbuf, timeout, mme_ue); ogs_expect_or_return_val(xact, OGS_ERROR); rv = ogs_gtp_xact_commit(xact); @@ -545,19 +579,22 @@ int mme_gtp_send_delete_indirect_data_forwarding_tunnel_request( ogs_gtp2_header_t h; ogs_pkbuf_t *pkbuf = NULL; ogs_gtp_xact_t *xact = NULL; + sgw_ue_t *sgw_ue = NULL; ogs_assert(action); ogs_assert(mme_ue); + sgw_ue = mme_ue->sgw_ue; + ogs_assert(sgw_ue); memset(&h, 0, sizeof(ogs_gtp2_header_t)); h.type = OGS_GTP2_DELETE_INDIRECT_DATA_FORWARDING_TUNNEL_REQUEST_TYPE; - h.teid = mme_ue->sgw_s11_teid; + h.teid = sgw_ue->sgw_s11_teid; pkbuf = ogs_pkbuf_alloc(NULL, OGS_TLV_MAX_HEADROOM); ogs_expect_or_return_val(pkbuf, OGS_ERROR); ogs_pkbuf_reserve(pkbuf, OGS_TLV_MAX_HEADROOM); - xact = ogs_gtp_xact_local_create(mme_ue->gnode, &h, pkbuf, timeout, mme_ue); + xact = ogs_gtp_xact_local_create(sgw_ue->gnode, &h, pkbuf, timeout, mme_ue); ogs_expect_or_return_val(xact, OGS_ERROR); xact->delete_indirect_action = action; @@ -576,19 +613,22 @@ int mme_gtp_send_bearer_resource_command( ogs_gtp_xact_t *xact = NULL; mme_ue_t *mme_ue = NULL; + sgw_ue_t *sgw_ue = NULL; ogs_assert(bearer); mme_ue = bearer->mme_ue; ogs_assert(mme_ue); + sgw_ue = mme_ue->sgw_ue; + ogs_assert(sgw_ue); memset(&h, 0, sizeof(ogs_gtp2_header_t)); h.type = OGS_GTP2_BEARER_RESOURCE_COMMAND_TYPE; - h.teid = mme_ue->sgw_s11_teid; + h.teid = sgw_ue->sgw_s11_teid; pkbuf = mme_s11_build_bearer_resource_command(h.type, bearer, nas_message); ogs_expect_or_return_val(pkbuf, OGS_ERROR); - xact = ogs_gtp_xact_local_create(mme_ue->gnode, &h, pkbuf, timeout, bearer); + xact = ogs_gtp_xact_local_create(sgw_ue->gnode, &h, pkbuf, timeout, bearer); ogs_expect_or_return_val(xact, OGS_ERROR); xact->xid |= OGS_GTP_CMD_XACT_ID; diff --git a/src/mme/mme-gtp-path.h b/src/mme/mme-gtp-path.h index 629c4e1eb..a20733902 100644 --- a/src/mme/mme-gtp-path.h +++ b/src/mme/mme-gtp-path.h @@ -30,7 +30,8 @@ int mme_gtp_open(void); void mme_gtp_close(void); int mme_gtp_send_create_session_request(mme_sess_t *sess, int create_action); -int mme_gtp_send_modify_bearer_request(mme_bearer_t *bearer, int uli_presence); +int mme_gtp_send_modify_bearer_request( + mme_ue_t *mme_ue, int uli_presence, int modify_action); int mme_gtp_send_delete_session_request(mme_sess_t *sess, int action); void mme_gtp_send_delete_all_sessions(mme_ue_t *mme_ue, int action); int mme_gtp_send_create_bearer_response( diff --git a/src/mme/mme-s11-build.c b/src/mme/mme-s11-build.c index 43b001f47..986412d14 100644 --- a/src/mme/mme-s11-build.c +++ b/src/mme/mme-s11-build.c @@ -22,14 +22,16 @@ #include "mme-s11-build.h" ogs_pkbuf_t *mme_s11_build_create_session_request( - uint8_t type, mme_sess_t *sess) + uint8_t type, mme_sess_t *sess, int create_action) { int rv; ogs_session_t *session = NULL; mme_ue_t *mme_ue = NULL; + sgw_ue_t *sgw_ue = NULL; mme_bearer_t *bearer = NULL; ogs_gtp2_message_t gtp_message; - ogs_gtp2_create_session_request_t *req = >p_message.create_session_request; + ogs_gtp2_create_session_request_t *req = + >p_message.create_session_request; ogs_gtp2_uli_t uli; char uli_buf[OGS_GTP2_MAX_ULI_LEN]; @@ -53,10 +55,17 @@ ogs_pkbuf_t *mme_s11_build_create_session_request( ogs_assert(bearer); mme_ue = sess->mme_ue; ogs_assert(mme_ue); + sgw_ue = mme_ue->sgw_ue; + ogs_assert(sgw_ue); + + if (create_action == OGS_GTP_CREATE_IN_PATH_SWITCH_REQUEST) { + sgw_ue = sgw_ue_cycle(sgw_ue->target_ue); + ogs_assert(sgw_ue); + } ogs_debug("Create Session Request"); ogs_debug(" MME_S11_TEID[%d] SGW_S11_TEID[%d]", - mme_ue->mme_s11_teid, mme_ue->sgw_s11_teid); + sgw_ue->mme_s11_teid, sgw_ue->sgw_s11_teid); memset(>p_message, 0, sizeof(ogs_gtp2_message_t)); ogs_assert(mme_ue->imsi_len); @@ -84,7 +93,7 @@ ogs_pkbuf_t *mme_s11_build_create_session_request( ogs_nas_from_plmn_id(&uli.e_cgi.nas_plmn_id, &mme_ue->e_cgi.plmn_id); uli.e_cgi.cell_id = mme_ue->e_cgi.cell_id; req->user_location_information.presence = 1; - ogs_gtp2_build_uli(&req->user_location_information, &uli, + ogs_gtp2_build_uli(&req->user_location_information, &uli, uli_buf, OGS_GTP2_MAX_ULI_LEN); req->serving_network.presence = 1; @@ -96,7 +105,7 @@ ogs_pkbuf_t *mme_s11_build_create_session_request( memset(&mme_s11_teid, 0, sizeof(ogs_gtp2_f_teid_t)); mme_s11_teid.interface_type = OGS_GTP2_F_TEID_S11_MME_GTP_C; - mme_s11_teid.teid = htobe32(mme_ue->mme_s11_teid); + mme_s11_teid.teid = htobe32(sgw_ue->mme_s11_teid); rv = ogs_gtp2_sockaddr_to_f_teid( ogs_gtp_self()->gtpc_addr, ogs_gtp_self()->gtpc_addr6, &mme_s11_teid, &len); @@ -107,6 +116,7 @@ ogs_pkbuf_t *mme_s11_build_create_session_request( memset(&pgw_s5c_teid, 0, sizeof(ogs_gtp2_f_teid_t)); pgw_s5c_teid.interface_type = OGS_GTP2_F_TEID_S5_S8_PGW_GTP_C; + pgw_s5c_teid.teid = htobe32(sess->pgw_s5c_teid); if (session->smf_ip.ipv4 || session->smf_ip.ipv6) { pgw_s5c_teid.ipv4 = session->smf_ip.ipv4; pgw_s5c_teid.ipv6 = session->smf_ip.ipv6; @@ -156,7 +166,7 @@ ogs_pkbuf_t *mme_s11_build_create_session_request( req->access_point_name.data = apn; req->selection_mode.presence = 1; - req->selection_mode.u8 = + req->selection_mode.u8 = OGS_GTP2_SELECTION_MODE_MS_OR_NETWORK_PROVIDED_APN; ogs_assert(sess->request_type.type == OGS_NAS_EPS_PDN_TYPE_IPV4 || @@ -178,7 +188,7 @@ ogs_pkbuf_t *mme_s11_build_create_session_request( } req->pdn_type.presence = 1; - /* If we started with both addrs (IPV4V6) but the above code + /* If we started with both addrs (IPV4V6) but the above code * (pdn_type & sess->request_type) truncates us down to just one, * we need to change position of addresses in struct. */ if (req->pdn_type.u8 == OGS_PDU_SESSION_TYPE_IPV4 && @@ -201,14 +211,14 @@ ogs_pkbuf_t *mme_s11_build_create_session_request( indication.change_reporting_support_indication = 1; indication.enb_change_reporting_support_indication = 1; - if (req->pdn_type.u8 == OGS_PDU_SESSION_TYPE_IPV4V6) { + if (req->pdn_type.u8 == OGS_PDU_SESSION_TYPE_IPV4V6) indication.dual_address_bearer_flag = 1; - } - if (sess->request_type.value == OGS_NAS_EPS_REQUEST_TYPE_HANDOVER) { + if (sess->request_type.value == OGS_NAS_EPS_REQUEST_TYPE_HANDOVER) indication.handover_indication = 1; - req->indication_flags.presence = 1; - } + + if (create_action == OGS_GTP_CREATE_IN_PATH_SWITCH_REQUEST) + indication.operation_indication = 1; session->paa.session_type = req->pdn_type.u8; req->pdn_address_allocation.data = &session->paa; @@ -269,11 +279,12 @@ ogs_pkbuf_t *mme_s11_build_create_session_request( if (time_exp.tm_gmtoff >= 0) { ue_timezone.timezone = OGS_GTP2_TIME_TO_BCD(time_exp.tm_gmtoff / 900); } else { - ue_timezone.timezone = OGS_GTP2_TIME_TO_BCD((-time_exp.tm_gmtoff) / 900); + ue_timezone.timezone = + OGS_GTP2_TIME_TO_BCD((-time_exp.tm_gmtoff) / 900); ue_timezone.timezone |= 0x08; } /* quarters of an hour */ - ue_timezone.daylight_saving_time = + ue_timezone.daylight_saving_time = OGS_GTP2_UE_TIME_ZONE_NO_ADJUSTMENT_FOR_DAYLIGHT_SAVING_TIME; req->ue_time_zone.presence = 1; req->ue_time_zone.data = &ue_timezone; @@ -288,61 +299,80 @@ ogs_pkbuf_t *mme_s11_build_create_session_request( } ogs_pkbuf_t *mme_s11_build_modify_bearer_request( - uint8_t type, mme_bearer_t *bearer, int uli_presence) + uint8_t type, mme_ue_t *mme_ue, int uli_presence) { - int rv; ogs_gtp2_message_t gtp_message; - ogs_gtp2_modify_bearer_request_t *req = >p_message.modify_bearer_request; + ogs_gtp2_modify_bearer_request_t *req = NULL; - ogs_gtp2_f_teid_t enb_s1u_teid; - int len; + ogs_gtp2_f_teid_t enb_s1u_teid[OGS_BEARER_PER_UE]; + int len, i; ogs_gtp2_uli_t uli; char uli_buf[OGS_GTP2_MAX_ULI_LEN]; ogs_gtp2_indication_t indication; - mme_ue_t *mme_ue = NULL; - mme_sess_t *sess = NULL; - - ogs_assert(bearer); - sess = bearer->sess; - ogs_assert(sess); - mme_ue = sess->mme_ue; - ogs_assert(mme_ue); + sgw_ue_t *sgw_ue = NULL; + mme_bearer_t *bearer = NULL; ogs_debug("Modifty Bearer Request"); - ogs_debug(" MME_S11_TEID[%d] SGW_S11_TEID[%d]", - mme_ue->mme_s11_teid, mme_ue->sgw_s11_teid); - ogs_debug(" ENB_S1U_TEID[%d] SGW_S1U_TEID[%d]", - bearer->enb_s1u_teid, bearer->sgw_s1u_teid); + ogs_assert(mme_ue); + sgw_ue = mme_ue->sgw_ue; + ogs_assert(sgw_ue); + ogs_assert(ogs_list_count(&mme_ue->bearer_to_modify_list)); + + /* Initialize message */ memset(>p_message, 0, sizeof(ogs_gtp2_message_t)); + req = >p_message.modify_bearer_request; - if (sess->request_type.value == OGS_NAS_EPS_REQUEST_TYPE_HANDOVER) { - memset(&indication, 0, sizeof(ogs_gtp2_indication_t)); - indication.handover_indication = 1; - req->indication_flags.presence = 1; - req->indication_flags.data = &indication; - req->indication_flags.len = sizeof(ogs_gtp2_indication_t); + ogs_debug(" MME_S11_TEID[%d] SGW_S11_TEID[%d]", + sgw_ue->mme_s11_teid, sgw_ue->sgw_s11_teid); + + i = 0; + ogs_list_for_each_entry( + &mme_ue->bearer_to_modify_list, bearer, to_modify_node) { + ogs_assert(i < OGS_BEARER_PER_UE); + + ogs_debug(" ENB_S1U_TEID[%d] SGW_S1U_TEID[%d]", + bearer->enb_s1u_teid, bearer->sgw_s1u_teid); + + /* Bearer Context : EBI */ + req->bearer_contexts_to_be_modified[i].presence = 1; + req->bearer_contexts_to_be_modified[i].eps_bearer_id.presence = 1; + req->bearer_contexts_to_be_modified[i].eps_bearer_id.u8 = bearer->ebi; + + /* Data Plane(DL) : ENB-S1U */ + memset(&enb_s1u_teid[i], 0, sizeof(ogs_gtp2_f_teid_t)); + enb_s1u_teid[i].interface_type = OGS_GTP2_F_TEID_S1_U_ENODEB_GTP_U; + enb_s1u_teid[i].teid = htobe32(bearer->enb_s1u_teid); + ogs_assert(OGS_OK == + ogs_gtp2_ip_to_f_teid(&bearer->enb_s1u_ip, &enb_s1u_teid[i], &len)); + req->bearer_contexts_to_be_modified[i].s1_u_enodeb_f_teid.presence = 1; + req->bearer_contexts_to_be_modified[i].s1_u_enodeb_f_teid.data = + &enb_s1u_teid[i]; + req->bearer_contexts_to_be_modified[i].s1_u_enodeb_f_teid.len = len; + + i++; } - /* Bearer Context : EBI */ - req->bearer_contexts_to_be_modified.presence = 1; - req->bearer_contexts_to_be_modified.eps_bearer_id.presence = 1; - req->bearer_contexts_to_be_modified.eps_bearer_id.u8 = bearer->ebi; + /* Indication */ + memset(&indication, 0, sizeof(ogs_gtp2_indication_t)); + ogs_list_for_each_entry( + &mme_ue->bearer_to_modify_list, bearer, to_modify_node) { + mme_sess_t *sess = bearer->sess; + ogs_assert(sess); - /* Data Plane(DL) : ENB-S1U */ - memset(&enb_s1u_teid, 0, sizeof(ogs_gtp2_f_teid_t)); - enb_s1u_teid.interface_type = OGS_GTP2_F_TEID_S1_U_ENODEB_GTP_U; - enb_s1u_teid.teid = htobe32(bearer->enb_s1u_teid); - rv = ogs_gtp2_ip_to_f_teid(&bearer->enb_s1u_ip, &enb_s1u_teid, &len); - ogs_expect_or_return_val(rv == OGS_OK, NULL); - req->bearer_contexts_to_be_modified.s1_u_enodeb_f_teid.presence = 1; - req->bearer_contexts_to_be_modified.s1_u_enodeb_f_teid.data = &enb_s1u_teid; - req->bearer_contexts_to_be_modified.s1_u_enodeb_f_teid.len = len; + if (sess->request_type.value == OGS_NAS_EPS_REQUEST_TYPE_HANDOVER) { + indication.handover_indication = 1; + req->indication_flags.presence = 1; + req->indication_flags.data = &indication; + req->indication_flags.len = sizeof(ogs_gtp2_indication_t); + break; + } + } + /* User Location Information(ULI) */ if (uli_presence) { - /* User Location Information(ULI) */ memset(&uli, 0, sizeof(ogs_gtp2_uli_t)); uli.flags.e_cgi = 1; uli.flags.tai = 1; @@ -351,7 +381,7 @@ ogs_pkbuf_t *mme_s11_build_modify_bearer_request( ogs_nas_from_plmn_id(&uli.e_cgi.nas_plmn_id, &mme_ue->e_cgi.plmn_id); uli.e_cgi.cell_id = mme_ue->e_cgi.cell_id; req->user_location_information.presence = 1; - ogs_gtp2_build_uli(&req->user_location_information, &uli, + ogs_gtp2_build_uli(&req->user_location_information, &uli, uli_buf, OGS_GTP2_MAX_ULI_LEN); } @@ -382,7 +412,8 @@ ogs_pkbuf_t *mme_s11_build_delete_session_request( uint8_t type, mme_sess_t *sess) { ogs_gtp2_message_t gtp_message; - ogs_gtp2_delete_session_request_t *req = >p_message.delete_session_request; + ogs_gtp2_delete_session_request_t *req = + >p_message.delete_session_request; ogs_gtp2_uli_t uli; char uli_buf[OGS_GTP2_MAX_ULI_LEN]; @@ -390,16 +421,19 @@ ogs_pkbuf_t *mme_s11_build_delete_session_request( mme_bearer_t *bearer = NULL; mme_ue_t *mme_ue = NULL; + sgw_ue_t *sgw_ue = NULL; ogs_assert(sess); mme_ue = sess->mme_ue; ogs_assert(mme_ue); + sgw_ue = mme_ue->sgw_ue; + ogs_assert(sgw_ue); bearer = mme_default_bearer_in_sess(sess); ogs_assert(bearer); ogs_debug("Delete Session Request"); ogs_debug(" MME_S11_TEID[%d] SGW_S11_TEID[%d]", - mme_ue->mme_s11_teid, mme_ue->sgw_s11_teid); + sgw_ue->mme_s11_teid, sgw_ue->sgw_s11_teid); memset(>p_message, 0, sizeof(ogs_gtp2_message_t)); @@ -433,7 +467,8 @@ ogs_pkbuf_t *mme_s11_build_create_bearer_response( { int rv; ogs_gtp2_message_t gtp_message; - ogs_gtp2_create_bearer_response_t *rsp = >p_message.create_bearer_response; + ogs_gtp2_create_bearer_response_t *rsp = + >p_message.create_bearer_response; ogs_gtp2_cause_t cause; ogs_gtp2_f_teid_t enb_s1u_teid, sgw_s1u_teid; @@ -445,14 +480,17 @@ ogs_pkbuf_t *mme_s11_build_create_bearer_response( struct tm time_exp; mme_ue_t *mme_ue = NULL; + sgw_ue_t *sgw_ue = NULL; ogs_assert(bearer); mme_ue = bearer->mme_ue; ogs_assert(mme_ue); + sgw_ue = mme_ue->sgw_ue; + ogs_assert(sgw_ue); ogs_debug("Create Bearer Response"); ogs_debug(" MME_S11_TEID[%d] SGW_S11_TEID[%d]", - mme_ue->mme_s11_teid, mme_ue->sgw_s11_teid); + sgw_ue->mme_s11_teid, sgw_ue->sgw_s11_teid); memset(>p_message, 0, sizeof(ogs_gtp2_message_t)); @@ -504,7 +542,7 @@ ogs_pkbuf_t *mme_s11_build_create_bearer_response( ogs_nas_from_plmn_id(&uli.e_cgi.nas_plmn_id, &mme_ue->e_cgi.plmn_id); uli.e_cgi.cell_id = mme_ue->e_cgi.cell_id; rsp->user_location_information.presence = 1; - ogs_gtp2_build_uli(&rsp->user_location_information, &uli, + ogs_gtp2_build_uli(&rsp->user_location_information, &uli, uli_buf, OGS_GTP2_MAX_ULI_LEN); /* UE Time Zone */ @@ -514,10 +552,11 @@ ogs_pkbuf_t *mme_s11_build_create_bearer_response( if (time_exp.tm_gmtoff >= 0) { ue_timezone.timezone = OGS_GTP2_TIME_TO_BCD(time_exp.tm_gmtoff / 900); } else { - ue_timezone.timezone = OGS_GTP2_TIME_TO_BCD((-time_exp.tm_gmtoff) / 900); + ue_timezone.timezone = + OGS_GTP2_TIME_TO_BCD((-time_exp.tm_gmtoff) / 900); ue_timezone.timezone |= 0x08; } - ue_timezone.daylight_saving_time = + ue_timezone.daylight_saving_time = OGS_GTP2_UE_TIME_ZONE_NO_ADJUSTMENT_FOR_DAYLIGHT_SAVING_TIME; rsp->ue_time_zone.presence = 1; rsp->ue_time_zone.data = &ue_timezone; @@ -531,7 +570,8 @@ ogs_pkbuf_t *mme_s11_build_update_bearer_response( uint8_t type, mme_bearer_t *bearer, uint8_t cause_value) { ogs_gtp2_message_t gtp_message; - ogs_gtp2_update_bearer_response_t *rsp = >p_message.update_bearer_response; + ogs_gtp2_update_bearer_response_t *rsp = + >p_message.update_bearer_response; ogs_gtp2_cause_t cause; ogs_gtp2_uli_t uli; @@ -541,14 +581,17 @@ ogs_pkbuf_t *mme_s11_build_update_bearer_response( struct tm time_exp; mme_ue_t *mme_ue = NULL; + sgw_ue_t *sgw_ue = NULL; ogs_assert(bearer); mme_ue = bearer->mme_ue; ogs_assert(mme_ue); + sgw_ue = mme_ue->sgw_ue; + ogs_assert(sgw_ue); ogs_debug("Update Bearer Response"); ogs_debug(" MME_S11_TEID[%d] SGW_S11_TEID[%d]", - mme_ue->mme_s11_teid, mme_ue->sgw_s11_teid); + sgw_ue->mme_s11_teid, sgw_ue->sgw_s11_teid); memset(>p_message, 0, sizeof(ogs_gtp2_message_t)); @@ -580,7 +623,7 @@ ogs_pkbuf_t *mme_s11_build_update_bearer_response( ogs_nas_from_plmn_id(&uli.e_cgi.nas_plmn_id, &mme_ue->e_cgi.plmn_id); uli.e_cgi.cell_id = mme_ue->e_cgi.cell_id; rsp->user_location_information.presence = 1; - ogs_gtp2_build_uli(&rsp->user_location_information, &uli, + ogs_gtp2_build_uli(&rsp->user_location_information, &uli, uli_buf, OGS_GTP2_MAX_ULI_LEN); /* UE Time Zone */ @@ -593,7 +636,7 @@ ogs_pkbuf_t *mme_s11_build_update_bearer_response( ue_timezone.timezone = OGS_GTP2_TIME_TO_BCD((-time_exp.tm_gmtoff) / 900); ue_timezone.timezone |= 0x08; } - ue_timezone.daylight_saving_time = + ue_timezone.daylight_saving_time = OGS_GTP2_UE_TIME_ZONE_NO_ADJUSTMENT_FOR_DAYLIGHT_SAVING_TIME; rsp->ue_time_zone.presence = 1; rsp->ue_time_zone.data = &ue_timezone; @@ -617,14 +660,17 @@ ogs_pkbuf_t *mme_s11_build_delete_bearer_response( struct tm time_exp; mme_ue_t *mme_ue = NULL; + sgw_ue_t *sgw_ue = NULL; ogs_assert(bearer); mme_ue = bearer->mme_ue; ogs_assert(mme_ue); + sgw_ue = mme_ue->sgw_ue; + ogs_assert(sgw_ue); ogs_debug("Delete Bearer Response"); ogs_debug(" MME_S11_TEID[%d] SGW_S11_TEID[%d]", - mme_ue->mme_s11_teid, mme_ue->sgw_s11_teid); + sgw_ue->mme_s11_teid, sgw_ue->sgw_s11_teid); memset(>p_message, 0, sizeof(ogs_gtp2_message_t)); @@ -688,7 +734,7 @@ ogs_pkbuf_t *mme_s11_build_delete_bearer_response( ogs_nas_from_plmn_id(&uli.e_cgi.nas_plmn_id, &mme_ue->e_cgi.plmn_id); uli.e_cgi.cell_id = mme_ue->e_cgi.cell_id; rsp->user_location_information.presence = 1; - ogs_gtp2_build_uli(&rsp->user_location_information, &uli, + ogs_gtp2_build_uli(&rsp->user_location_information, &uli, uli_buf, OGS_GTP2_MAX_ULI_LEN); /* UE Time Zone */ @@ -701,7 +747,7 @@ ogs_pkbuf_t *mme_s11_build_delete_bearer_response( ue_timezone.timezone = OGS_GTP2_TIME_TO_BCD((-time_exp.tm_gmtoff) / 900); ue_timezone.timezone |= 0x08; } - ue_timezone.daylight_saving_time = + ue_timezone.daylight_saving_time = OGS_GTP2_UE_TIME_ZONE_NO_ADJUSTMENT_FOR_DAYLIGHT_SAVING_TIME; rsp->ue_time_zone.presence = 1; rsp->ue_time_zone.data = &ue_timezone; @@ -714,7 +760,7 @@ ogs_pkbuf_t *mme_s11_build_delete_bearer_response( ogs_pkbuf_t *mme_s11_build_release_access_bearers_request(uint8_t type) { ogs_gtp2_message_t gtp_message; - ogs_gtp2_release_access_bearers_request_t *req = + ogs_gtp2_release_access_bearers_request_t *req = >p_message.release_access_bearers_request; ogs_debug("Release Access Bearers Request"); @@ -731,7 +777,7 @@ ogs_pkbuf_t *mme_s11_build_downlink_data_notification_ack( uint8_t type, uint8_t cause_value) { ogs_gtp2_message_t gtp_message; - ogs_gtp2_downlink_data_notification_acknowledge_t *ack = + ogs_gtp2_downlink_data_notification_acknowledge_t *ack = >p_message.downlink_data_notification_acknowledge; ogs_gtp2_cause_t cause; @@ -759,23 +805,26 @@ ogs_pkbuf_t *mme_s11_build_create_indirect_data_forwarding_tunnel_request( { int rv; int i; - + mme_sess_t *sess = NULL; mme_bearer_t *bearer = NULL; + sgw_ue_t *sgw_ue = NULL; ogs_gtp2_message_t gtp_message; ogs_gtp2_create_indirect_data_forwarding_tunnel_request_t *req = >p_message.create_indirect_data_forwarding_tunnel_request; - + ogs_gtp2_f_teid_t dl_teid[OGS_GTP2_MAX_INDIRECT_TUNNEL]; ogs_gtp2_f_teid_t ul_teid[OGS_GTP2_MAX_INDIRECT_TUNNEL]; int len; ogs_assert(mme_ue); + sgw_ue = mme_ue->sgw_ue; + ogs_assert(sgw_ue); ogs_debug("Create Indirect Data Forwarding Tunnel Request"); ogs_debug(" MME_S11_TEID[%d] SGW_S11_TEID[%d]", - mme_ue->mme_s11_teid, mme_ue->sgw_s11_teid); + sgw_ue->mme_s11_teid, sgw_ue->sgw_s11_teid); memset(>p_message, 0, sizeof(ogs_gtp2_message_t)); @@ -843,6 +892,7 @@ ogs_pkbuf_t *mme_s11_build_bearer_resource_command( char flow_qos_buf[GTP2_FLOW_QOS_LEN]; mme_ue_t *mme_ue = NULL; + sgw_ue_t *sgw_ue = NULL; mme_sess_t *sess = NULL; mme_bearer_t *linked_bearer = NULL; @@ -851,10 +901,12 @@ ogs_pkbuf_t *mme_s11_build_bearer_resource_command( ogs_assert(sess); mme_ue = sess->mme_ue; ogs_assert(mme_ue); + sgw_ue = mme_ue->sgw_ue; + ogs_assert(sgw_ue); ogs_debug("Bearer Resource Command"); ogs_debug(" MME_S11_TEID[%d] SGW_S11_TEID[%d]", - mme_ue->mme_s11_teid, mme_ue->sgw_s11_teid); + sgw_ue->mme_s11_teid, sgw_ue->sgw_s11_teid); ogs_assert(nas_message); switch (nas_message->esm.h.message_type) { diff --git a/src/mme/mme-s11-build.h b/src/mme/mme-s11-build.h index e515b26f8..c5dae8e16 100644 --- a/src/mme/mme-s11-build.h +++ b/src/mme/mme-s11-build.h @@ -25,9 +25,9 @@ extern "C" { #endif ogs_pkbuf_t *mme_s11_build_create_session_request( - uint8_t type, mme_sess_t *sess); + uint8_t type, mme_sess_t *sess, int create_action); ogs_pkbuf_t *mme_s11_build_modify_bearer_request( - uint8_t type, mme_bearer_t *bearer, int uli_presense); + uint8_t type, mme_ue_t *mme_ue, int uli_presense); ogs_pkbuf_t *mme_s11_build_delete_session_request( uint8_t type, mme_sess_t *sess); ogs_pkbuf_t *mme_s11_build_create_bearer_response( diff --git a/src/mme/mme-s11-handler.c b/src/mme/mme-s11-handler.c index c84022eaa..2f5fe61be 100644 --- a/src/mme/mme-s11-handler.c +++ b/src/mme/mme-s11-handler.c @@ -77,90 +77,98 @@ void mme_s11_handle_echo_response( } void mme_s11_handle_create_session_response( - ogs_gtp_xact_t *xact, mme_ue_t *mme_ue_from_teid, + ogs_gtp_xact_t *xact, sgw_ue_t *sgw_ue, ogs_gtp2_create_session_response_t *rsp) { int rv; uint8_t cause_value = 0; + ogs_gtp2_cause_t *cause = NULL; ogs_gtp2_f_teid_t *sgw_s11_teid = NULL; + ogs_gtp2_f_teid_t *pgw_s5c_teid = NULL; ogs_gtp2_f_teid_t *sgw_s1u_teid = NULL; mme_bearer_t *bearer = NULL; mme_sess_t *sess = NULL; - mme_ue_t *mme_ue = mme_ue_from_teid; + mme_ue_t *mme_ue = NULL; ogs_session_t *session = NULL; ogs_gtp2_bearer_qos_t bearer_qos; ogs_gtp2_ambr_t *ambr = NULL; uint16_t decoded = 0; int create_action = 0; - - ogs_assert(xact); - create_action = xact->create_action; + ogs_assert(rsp); ogs_debug("Create Session Response"); - cause_value = OGS_GTP2_CAUSE_REQUEST_ACCEPTED; - - if (rsp->pdn_address_allocation.presence == 0) { - ogs_error("No PDN Address Allocation"); - cause_value = OGS_GTP2_CAUSE_MANDATORY_IE_MISSING; - } - - if (rsp->sender_f_teid_for_control_plane.presence == 0) { - ogs_error("No S11 TEID"); - cause_value = OGS_GTP2_CAUSE_MANDATORY_IE_MISSING; - } - if (rsp->bearer_contexts_created.s1_u_enodeb_f_teid.presence == 0) { - ogs_error("No S1U TEID"); - cause_value = OGS_GTP2_CAUSE_MANDATORY_IE_MISSING; - } - if (rsp->bearer_contexts_created.presence == 0) { - ogs_error("No Bearer"); - cause_value = OGS_GTP2_CAUSE_MANDATORY_IE_MISSING; - } - if (rsp->bearer_contexts_created.eps_bearer_id.presence == 0) { - ogs_error("No EPS Bearer ID"); - cause_value = OGS_GTP2_CAUSE_MANDATORY_IE_MISSING; - } - - if (!mme_ue) { - ogs_warn("No Context in TEID"); - sess = xact->data; - ogs_assert(sess); - mme_ue = sess->mme_ue; - ogs_assert(mme_ue); - } + /******************** + * Check Transaction + ********************/ + ogs_assert(xact); + create_action = xact->create_action; + sess = xact->data; + ogs_assert(sess); + mme_ue = sess->mme_ue; + ogs_assert(mme_ue); rv = ogs_gtp_xact_commit(xact); ogs_expect_or_return(rv == OGS_OK); - if (rsp->cause.presence) { - ogs_gtp2_cause_t *cause = rsp->cause.data; - ogs_assert(cause); + /************************ + * Check SGW-UE Context + ************************/ + cause_value = OGS_GTP2_CAUSE_REQUEST_ACCEPTED; - cause_value = cause->value; - if (cause_value == OGS_GTP2_CAUSE_REQUEST_ACCEPTED || - cause_value == OGS_GTP2_CAUSE_REQUEST_ACCEPTED_PARTIALLY || - cause_value == - OGS_GTP2_CAUSE_NEW_PDN_TYPE_DUE_TO_NETWORK_PREFERENCE || - cause_value == - OGS_GTP2_CAUSE_NEW_PDN_TYPE_DUE_TO_SINGLE_ADDRESS_BEARER_ONLY) { - if (rsp->bearer_contexts_created.cause.presence) { - cause = rsp->bearer_contexts_created.cause.data; - ogs_assert(cause); - - cause_value = cause->value; - } else { - ogs_error("No Cause"); - cause_value = OGS_GTP2_CAUSE_MANDATORY_IE_MISSING; - } - } else { - ogs_warn("GTP Failed [CAUSE:%d]", cause_value); - } + if (!sgw_ue) { + ogs_error("No Context in TEID"); + cause_value = OGS_GTP2_CAUSE_CONTEXT_NOT_FOUND; } else { - ogs_error("No Cause"); - cause_value = OGS_GTP2_CAUSE_MANDATORY_IE_MISSING; + if (rsp->bearer_contexts_created.presence == 0) { + ogs_error("No Bearer"); + cause_value = OGS_GTP2_CAUSE_MANDATORY_IE_MISSING; + } + if (rsp->bearer_contexts_created.eps_bearer_id.presence == 0) { + ogs_error("No EPS Bearer ID"); + cause_value = OGS_GTP2_CAUSE_MANDATORY_IE_MISSING; + } + + if (cause_value == OGS_GTP2_CAUSE_REQUEST_ACCEPTED) { + bearer = mme_bearer_find_by_ue_ebi(mme_ue, + rsp->bearer_contexts_created.eps_bearer_id.u8); + + if (!bearer) { + ogs_error("No Context for EPS Bearer ID[%d]", + rsp->bearer_contexts_created.eps_bearer_id.u8); + cause_value = OGS_GTP2_CAUSE_CONTEXT_NOT_FOUND; + } + } + } + + if (cause_value != OGS_GTP2_CAUSE_REQUEST_ACCEPTED) { + if (create_action == OGS_GTP_CREATE_IN_ATTACH_REQUEST) { + ogs_error("[%s] Attach reject", mme_ue->imsi_bcd); + ogs_assert(OGS_OK == nas_eps_send_attach_reject(mme_ue, + EMM_CAUSE_NETWORK_FAILURE, ESM_CAUSE_NETWORK_FAILURE)); + } + mme_send_delete_session_or_mme_ue_context_release(mme_ue); + return; + } + + /***************************************** + * Check Mandatory/Conditional IE Missing + *****************************************/ + ogs_assert(cause_value == OGS_GTP2_CAUSE_REQUEST_ACCEPTED); + + if (rsp->sender_f_teid_for_control_plane.presence == 0) { + ogs_error("No S11 TEID"); + cause_value = OGS_GTP2_CAUSE_CONDITIONAL_IE_MISSING; + } + if (rsp->pgw_s5_s8__s2a_s2b_f_teid_for_pmip_based_interface_or_for_gtp_based_control_plane_interface.presence == 0) { + ogs_error("No S5C TEID"); + cause_value = OGS_GTP2_CAUSE_CONDITIONAL_IE_MISSING; + } + if (rsp->bearer_contexts_created.s1_u_enodeb_f_teid.presence == 0) { + ogs_error("No S1U TEID"); + cause_value = OGS_GTP2_CAUSE_CONDITIONAL_IE_MISSING; } if (rsp->pdn_address_allocation.presence) { @@ -173,37 +181,74 @@ void mme_s11_handle_create_session_response( ogs_error("Unknown PDN Type[%u]", paa.session_type); cause_value = OGS_GTP2_CAUSE_MANDATORY_IE_INCORRECT; } + } else { + ogs_error("No PDN Address Allocation"); + cause_value = OGS_GTP2_CAUSE_CONDITIONAL_IE_MISSING; } - if (mme_ue_from_teid && mme_ue && - cause_value == OGS_GTP2_CAUSE_REQUEST_ACCEPTED) { - bearer = mme_bearer_find_by_ue_ebi(mme_ue, - rsp->bearer_contexts_created.eps_bearer_id.u8); + if (rsp->cause.presence == 0) { + ogs_error("No Cause"); + cause_value = OGS_GTP2_CAUSE_MANDATORY_IE_MISSING; + } + if (rsp->bearer_contexts_created.cause.presence == 0) { + ogs_error("No Bearer Cause"); + cause_value = OGS_GTP2_CAUSE_MANDATORY_IE_MISSING; } - if (!bearer) { - ogs_warn("No Context"); - cause_value = OGS_GTP2_CAUSE_CONTEXT_NOT_FOUND; + if (cause_value != OGS_GTP2_CAUSE_REQUEST_ACCEPTED) { + if (create_action == OGS_GTP_CREATE_IN_ATTACH_REQUEST) { + ogs_error("[%s] Attach reject", mme_ue->imsi_bcd); + ogs_assert(OGS_OK == nas_eps_send_attach_reject(mme_ue, + EMM_CAUSE_NETWORK_FAILURE, ESM_CAUSE_NETWORK_FAILURE)); + } + mme_send_delete_session_or_mme_ue_context_release(mme_ue); + return; } + /******************** + * Check Cause Value + ********************/ + ogs_assert(cause_value == OGS_GTP2_CAUSE_REQUEST_ACCEPTED); + + cause = rsp->bearer_contexts_created.cause.data; + ogs_assert(cause); + cause_value = cause->value; + if (cause_value != OGS_GTP2_CAUSE_REQUEST_ACCEPTED) { + ogs_error("GTP Failed [Bearer-CAUSE:%d]", cause_value); + if (create_action == OGS_GTP_CREATE_IN_ATTACH_REQUEST) { + ogs_error("[%s] Attach reject", mme_ue->imsi_bcd); + ogs_assert(OGS_OK == nas_eps_send_attach_reject(mme_ue, + EMM_CAUSE_NETWORK_FAILURE, ESM_CAUSE_NETWORK_FAILURE)); + } + mme_send_delete_session_or_mme_ue_context_release(mme_ue); + return; + } + + cause = rsp->cause.data; + ogs_assert(cause); + cause_value = cause->value; if (cause_value != OGS_GTP2_CAUSE_REQUEST_ACCEPTED && cause_value != OGS_GTP2_CAUSE_REQUEST_ACCEPTED_PARTIALLY && cause_value != OGS_GTP2_CAUSE_NEW_PDN_TYPE_DUE_TO_NETWORK_PREFERENCE && cause_value != OGS_GTP2_CAUSE_NEW_PDN_TYPE_DUE_TO_SINGLE_ADDRESS_BEARER_ONLY) { - if (mme_ue_from_teid && mme_ue) { - if (create_action == OGS_GTP_CREATE_IN_ATTACH_REQUEST) { - ogs_error("[%s] Attach reject", mme_ue->imsi_bcd); - ogs_assert(OGS_OK == - nas_eps_send_attach_reject(mme_ue, - EMM_CAUSE_NETWORK_FAILURE, ESM_CAUSE_NETWORK_FAILURE)); - } - mme_send_delete_session_or_mme_ue_context_release(mme_ue); + ogs_error("GTP Failed [CAUSE:%d]", cause_value); + if (create_action == OGS_GTP_CREATE_IN_ATTACH_REQUEST) { + ogs_error("[%s] Attach reject", mme_ue->imsi_bcd); + ogs_assert(OGS_OK == nas_eps_send_attach_reject(mme_ue, + EMM_CAUSE_NETWORK_FAILURE, ESM_CAUSE_NETWORK_FAILURE)); } + mme_send_delete_session_or_mme_ue_context_release(mme_ue); return; } + /******************** + * Check ALL Context + ********************/ + ogs_assert(mme_ue); + ogs_assert(sgw_ue); + ogs_assert(bearer); sess = bearer->sess; ogs_assert(sess); @@ -212,7 +257,11 @@ void mme_s11_handle_create_session_response( /* Control Plane(UL) : SGW-S11 */ sgw_s11_teid = rsp->sender_f_teid_for_control_plane.data; - mme_ue->sgw_s11_teid = be32toh(sgw_s11_teid->teid); + sgw_ue->sgw_s11_teid = be32toh(sgw_s11_teid->teid); + + /* Control Plane(UL) : PGW-S5C */ + pgw_s5c_teid = rsp->pgw_s5_s8__s2a_s2b_f_teid_for_pmip_based_interface_or_for_gtp_based_control_plane_interface.data; + sess->pgw_s5c_teid = be32toh(pgw_s5c_teid->teid); memcpy(&session->paa, rsp->pdn_address_allocation.data, rsp->pdn_address_allocation.len); @@ -249,9 +298,9 @@ void mme_s11_handle_create_session_response( bearer->sgw_s1u_teid = be32toh(sgw_s1u_teid->teid); ogs_debug(" MME_S11_TEID[%d] SGW_S11_TEID[%d]", - mme_ue->mme_s11_teid, mme_ue->sgw_s11_teid); + sgw_ue->mme_s11_teid, sgw_ue->sgw_s11_teid); ogs_debug(" ENB_S1U_TEID[%d] SGW_S1U_TEID[%d]", - bearer->enb_s1u_teid, bearer->sgw_s1u_teid); + bearer->enb_s1u_teid, bearer->sgw_s1u_teid); rv = ogs_gtp2_f_teid_to_ip(sgw_s1u_teid, &bearer->sgw_s1u_ip); ogs_assert(rv == OGS_OK); @@ -272,94 +321,130 @@ void mme_s11_handle_create_session_response( nas_eps_send_attach_accept(mme_ue)); } - } else { + } else if (create_action == OGS_GTP_CREATE_IN_UPLINK_NAS_TRANSPORT) { ogs_assert(OGS_PDU_SESSION_TYPE_IS_VALID(session->paa.session_type)); ogs_assert(OGS_OK == nas_eps_send_activate_default_bearer_context_request( bearer, create_action)); + } else if (create_action == OGS_GTP_CREATE_IN_PATH_SWITCH_REQUEST) { + ogs_error("OK"); + } else { + ogs_fatal("Invalid Create Session Action[%d]", create_action); + ogs_assert_if_reached(); } } void mme_s11_handle_modify_bearer_response( - ogs_gtp_xact_t *xact, mme_ue_t *mme_ue_from_teid, + ogs_gtp_xact_t *xact, sgw_ue_t *sgw_ue, ogs_gtp2_modify_bearer_response_t *rsp) { int rv; uint8_t cause_value = 0; + int modify_action = 0; + ogs_gtp2_cause_t *cause = NULL; - mme_ue_t *mme_ue = mme_ue_from_teid; - mme_sess_t *sess = NULL; - mme_bearer_t *bearer = NULL; + mme_ue_t *mme_ue = NULL; - ogs_assert(xact); ogs_assert(rsp); ogs_debug("Modify Bearer Response"); - cause_value = OGS_GTP2_CAUSE_REQUEST_ACCEPTED; - - if (!mme_ue) { - ogs_warn("No Context in TEID"); - bearer = xact->data; - ogs_assert(bearer); - sess = bearer->sess; - ogs_assert(sess); - mme_ue = sess->mme_ue; - ogs_assert(mme_ue); - } + /******************** + * Check Transaction + ********************/ + ogs_assert(xact); + mme_ue = xact->data; + ogs_assert(mme_ue); + modify_action = xact->modify_action; rv = ogs_gtp_xact_commit(xact); ogs_expect_or_return(rv == OGS_OK); - if (rsp->cause.presence) { - ogs_gtp2_cause_t *cause = rsp->cause.data; - ogs_assert(cause); + /************************ + * Check SGW-UE Context + ************************/ + cause_value = OGS_GTP2_CAUSE_REQUEST_ACCEPTED; - cause_value = cause->value; - if (cause_value != OGS_GTP2_CAUSE_REQUEST_ACCEPTED) - ogs_warn("GTP Failed [CAUSE:%d]", cause_value); - } else { + if (!sgw_ue) { + ogs_error("No Context in TEID"); + cause_value = OGS_GTP2_CAUSE_CONTEXT_NOT_FOUND; + } + + if (cause_value != OGS_GTP2_CAUSE_REQUEST_ACCEPTED) { + mme_send_delete_session_or_mme_ue_context_release(mme_ue); + return; + } + + /***************************************** + * Check Mandatory/Conditional IE Missing + *****************************************/ + ogs_assert(cause_value == OGS_GTP2_CAUSE_REQUEST_ACCEPTED); + + if (rsp->cause.presence == 0) { ogs_error("No Cause"); cause_value = OGS_GTP2_CAUSE_MANDATORY_IE_MISSING; } if (cause_value != OGS_GTP2_CAUSE_REQUEST_ACCEPTED) { - if (mme_ue_from_teid && mme_ue) - mme_send_delete_session_or_mme_ue_context_release(mme_ue); + mme_send_delete_session_or_mme_ue_context_release(mme_ue); return; } + /******************** + * Check Cause Value + ********************/ + ogs_assert(cause_value == OGS_GTP2_CAUSE_REQUEST_ACCEPTED); + + cause = rsp->cause.data; + ogs_assert(cause); + cause_value = cause->value; + if (cause_value != OGS_GTP2_CAUSE_REQUEST_ACCEPTED) { + ogs_error("GTP Failed [CAUSE:%d]", cause_value); + mme_send_delete_session_or_mme_ue_context_release(mme_ue); + return; + } + + /******************** + * Check ALL Context + ********************/ + ogs_assert(mme_ue); + ogs_assert(sgw_ue); + ogs_debug(" MME_S11_TEID[%d] SGW_S11_TEID[%d]", - mme_ue->mme_s11_teid, mme_ue->sgw_s11_teid); + sgw_ue->mme_s11_teid, sgw_ue->sgw_s11_teid); - GTP_COUNTER_CHECK(mme_ue, GTP_COUNTER_MODIFY_BEARER_BY_PATH_SWITCH, - ogs_assert(OGS_OK == - s1ap_send_path_switch_ack(mme_ue)); - ); - - GTP_COUNTER_CHECK(mme_ue, GTP_COUNTER_MODIFY_BEARER_BY_E_RAB_MODIFICATION, - ogs_assert(OGS_OK == - s1ap_send_e_rab_modification_confirm(mme_ue)); - ); + switch (modify_action) { + case OGS_GTP_MODIFY_IN_PATH_SWITCH_REQUEST: + ogs_assert(OGS_OK == s1ap_send_path_switch_ack(mme_ue)); + break; + case OGS_GTP_MODIFY_IN_E_RAB_MODIFICATION: + ogs_assert(OGS_OK == s1ap_send_e_rab_modification_confirm(mme_ue)); + break; + default: + break; + } } void mme_s11_handle_delete_session_response( - ogs_gtp_xact_t *xact, mme_ue_t *mme_ue_from_teid, + ogs_gtp_xact_t *xact, sgw_ue_t *sgw_ue, ogs_gtp2_delete_session_response_t *rsp) { int rv; uint8_t cause_value = 0; int action = 0; - mme_ue_t *mme_ue = mme_ue_from_teid; + mme_ue_t *mme_ue = NULL; mme_sess_t *sess = NULL; - ogs_assert(xact); ogs_assert(rsp); - action = xact->delete_action; - ogs_assert(action); ogs_debug("Delete Session Response"); + /******************** + * Check Transaction + ********************/ + ogs_assert(xact); + action = xact->delete_action; + ogs_assert(action); sess = xact->data; ogs_assert(sess); mme_ue = sess->mme_ue; @@ -368,17 +453,33 @@ void mme_s11_handle_delete_session_response( rv = ogs_gtp_xact_commit(xact); ogs_expect_or_return(rv == OGS_OK); + /************************ + * Check SGW-UE Context + ************************/ + if (!sgw_ue) + ogs_error("No Context in TEID"); + + /******************** + * Check Cause Value + ********************/ if (rsp->cause.presence) { ogs_gtp2_cause_t *cause = rsp->cause.data; ogs_assert(cause); cause_value = cause->value; if (cause_value != OGS_GTP2_CAUSE_REQUEST_ACCEPTED) - ogs_warn("GTP Failed [CAUSE:%d] - Ignored", cause_value); + ogs_error("GTP Failed [CAUSE:%d] - Ignored", cause_value); } - ogs_debug(" MME_S11_TEID[%d] SGW_S11_TEID[%d]", - mme_ue->mme_s11_teid, mme_ue->sgw_s11_teid); + /******************** + * Check ALL Context + ********************/ + ogs_assert(mme_ue); + ogs_assert(sess); + + if (sgw_ue) + ogs_debug(" MME_S11_TEID[%d] SGW_S11_TEID[%d]", + sgw_ue->mme_s11_teid, sgw_ue->sgw_s11_teid); if (action == OGS_GTP_DELETE_SEND_AUTHENTICATION_REQUEST) { if (mme_sess_count(mme_ue) == 1) /* Last Session */ { @@ -418,7 +519,7 @@ void mme_s11_handle_delete_session_response( S1AP_Cause_PR_nas, S1AP_CauseNas_normal_release, S1AP_UE_CTX_REL_UE_CONTEXT_REMOVE, 0)); } else - ogs_warn("ENB-S1 Context has already been removed"); + ogs_error("ENB-S1 Context has already been removed"); } } else if (action == OGS_GTP_DELETE_HANDLE_PDN_CONNECTIVITY_REQUEST) { @@ -452,13 +553,14 @@ void mme_s11_handle_delete_session_response( } void mme_s11_handle_create_bearer_request( - ogs_gtp_xact_t *xact, mme_ue_t *mme_ue, + ogs_gtp_xact_t *xact, sgw_ue_t *sgw_ue, ogs_gtp2_create_bearer_request_t *req) { int rv; uint8_t cause_value = 0; mme_bearer_t *bearer = NULL, *default_bearer = NULL; mme_sess_t *sess = NULL; + mme_ue_t *mme_ue = NULL; ogs_gtp2_f_teid_t *sgw_s1u_teid = NULL; ogs_gtp2_bearer_qos_t bearer_qos; @@ -468,12 +570,44 @@ void mme_s11_handle_create_bearer_request( ogs_debug("Create Bearer Response"); + /*********************** + * Check SGW-UE Context + ***********************/ cause_value = OGS_GTP2_CAUSE_REQUEST_ACCEPTED; - if (req->linked_eps_bearer_id.presence == 0) { - ogs_error("No Linked EBI"); - cause_value = OGS_GTP2_CAUSE_MANDATORY_IE_MISSING; + if (!sgw_ue) { + ogs_error("No Context in TEID"); + cause_value = OGS_GTP2_CAUSE_CONTEXT_NOT_FOUND; + } else { + mme_ue = sgw_ue->mme_ue; + ogs_assert(mme_ue); + + if (req->linked_eps_bearer_id.presence == 0) { + ogs_error("No Linked EBI"); + cause_value = OGS_GTP2_CAUSE_MANDATORY_IE_MISSING; + } + + if (cause_value == OGS_GTP2_CAUSE_REQUEST_ACCEPTED) { + sess = mme_sess_find_by_ebi(mme_ue, req->linked_eps_bearer_id.u8); + if (!sess) { + ogs_error("No Context for Linked EPS Bearer ID[%d]", + req->linked_eps_bearer_id.u8); + cause_value = OGS_GTP2_CAUSE_CONTEXT_NOT_FOUND; + } + } } + + if (cause_value != OGS_GTP2_CAUSE_REQUEST_ACCEPTED) { + ogs_gtp2_send_error_message(xact, sgw_ue ? sgw_ue->sgw_s11_teid : 0, + OGS_GTP2_CREATE_BEARER_RESPONSE_TYPE, cause_value); + return; + } + + /***************************************** + * Check Mandatory/Conditional IE Missing + *****************************************/ + ogs_assert(cause_value == OGS_GTP2_CAUSE_REQUEST_ACCEPTED); + if (req->bearer_contexts.presence == 0) { ogs_error("No Bearer"); cause_value = OGS_GTP2_CAUSE_MANDATORY_IE_MISSING; @@ -484,7 +618,7 @@ void mme_s11_handle_create_bearer_request( } if (req->bearer_contexts.s1_u_enodeb_f_teid.presence == 0) { ogs_error("No GTP TEID"); - cause_value = OGS_GTP2_CAUSE_MANDATORY_IE_MISSING; + cause_value = OGS_GTP2_CAUSE_CONDITIONAL_IE_MISSING; } if (req->bearer_contexts.bearer_level_qos.presence == 0) { ogs_error("No QoS"); @@ -495,29 +629,26 @@ void mme_s11_handle_create_bearer_request( cause_value = OGS_GTP2_CAUSE_MANDATORY_IE_MISSING; } - if (mme_ue && cause_value == OGS_GTP2_CAUSE_REQUEST_ACCEPTED) { - sess = mme_sess_find_by_ebi(mme_ue, req->linked_eps_bearer_id.u8); - if (sess) bearer = mme_bearer_add(sess); - } - - if (!bearer) { - ogs_warn("No Context"); - cause_value = OGS_GTP2_CAUSE_CONTEXT_NOT_FOUND; - } - if (cause_value != OGS_GTP2_CAUSE_REQUEST_ACCEPTED) { - ogs_gtp2_send_error_message(xact, mme_ue ? mme_ue->sgw_s11_teid : 0, + ogs_gtp2_send_error_message(xact, sgw_ue ? sgw_ue->sgw_s11_teid : 0, OGS_GTP2_CREATE_BEARER_RESPONSE_TYPE, cause_value); return; } + /******************** + * Check ALL Context + ********************/ + ogs_assert(mme_ue); + ogs_assert(sgw_ue); + + ogs_assert(sess); + bearer = mme_bearer_add(sess); + ogs_assert(bearer); + ogs_debug(" MME_S11_TEID[%d] SGW_S11_TEID[%d]", - mme_ue->mme_s11_teid, mme_ue->sgw_s11_teid); + sgw_ue->mme_s11_teid, sgw_ue->sgw_s11_teid); /* Set PTI */ - ogs_assert(bearer); - sess = bearer->sess; - ogs_assert(sess); sess->pti = OGS_NAS_PROCEDURE_TRANSACTION_IDENTITY_UNASSIGNED; if (req->procedure_transaction_id.presence) { sess->pti = req->procedure_transaction_id.u8; @@ -590,12 +721,13 @@ void mme_s11_handle_create_bearer_request( } void mme_s11_handle_update_bearer_request( - ogs_gtp_xact_t *xact, mme_ue_t *mme_ue, + ogs_gtp_xact_t *xact, sgw_ue_t *sgw_ue, ogs_gtp2_update_bearer_request_t *req) { uint8_t cause_value = 0; mme_bearer_t *bearer = NULL; mme_sess_t *sess = NULL; + mme_ue_t *mme_ue = NULL; ogs_gtp2_bearer_qos_t bearer_qos; ogs_assert(xact); @@ -603,41 +735,57 @@ void mme_s11_handle_update_bearer_request( ogs_debug("Update Bearer Request"); + /*********************** + * Check SGW-UE Context + ***********************/ cause_value = OGS_GTP2_CAUSE_REQUEST_ACCEPTED; - if (req->bearer_contexts.presence == 0) { - ogs_error("No Bearer"); - cause_value = OGS_GTP2_CAUSE_MANDATORY_IE_MISSING; - } - if (req->bearer_contexts.eps_bearer_id.presence == 0) { - ogs_error("No EPS Bearer ID"); - cause_value = OGS_GTP2_CAUSE_MANDATORY_IE_MISSING; - } - - if (mme_ue && cause_value == OGS_GTP2_CAUSE_REQUEST_ACCEPTED) { - bearer = mme_bearer_find_by_ue_ebi(mme_ue, - req->bearer_contexts.eps_bearer_id.u8); - } - - if (!bearer) { - ogs_warn("No Context"); + if (!sgw_ue) { + ogs_error("No Context in TEID"); cause_value = OGS_GTP2_CAUSE_CONTEXT_NOT_FOUND; + } else { + mme_ue = sgw_ue->mme_ue; + ogs_assert(mme_ue); + + if (req->bearer_contexts.presence == 0) { + ogs_error("No Bearer"); + cause_value = OGS_GTP2_CAUSE_MANDATORY_IE_MISSING; + } + if (req->bearer_contexts.eps_bearer_id.presence == 0) { + ogs_error("No EPS Bearer ID"); + cause_value = OGS_GTP2_CAUSE_MANDATORY_IE_MISSING; + } + + if (cause_value == OGS_GTP2_CAUSE_REQUEST_ACCEPTED) { + bearer = mme_bearer_find_by_ue_ebi(mme_ue, + req->bearer_contexts.eps_bearer_id.u8); + if (!bearer) { + ogs_error("No Context"); + cause_value = OGS_GTP2_CAUSE_CONTEXT_NOT_FOUND; + } + } } if (cause_value != OGS_GTP2_CAUSE_REQUEST_ACCEPTED) { - ogs_gtp2_send_error_message(xact, mme_ue ? mme_ue->sgw_s11_teid : 0, + ogs_gtp2_send_error_message(xact, sgw_ue ? sgw_ue->sgw_s11_teid : 0, OGS_GTP2_UPDATE_BEARER_RESPONSE_TYPE, cause_value); return; } - ogs_debug(" MME_S11_TEID[%d] SGW_S11_TEID[%d]", - mme_ue->mme_s11_teid, mme_ue->sgw_s11_teid); - - /* Set PTI */ + /******************** + * Check ALL Context + ********************/ ogs_assert(mme_ue); + ogs_assert(sgw_ue); + ogs_assert(bearer); sess = bearer->sess; ogs_assert(sess); + + ogs_debug(" MME_S11_TEID[%d] SGW_S11_TEID[%d]", + sgw_ue->mme_s11_teid, sgw_ue->sgw_s11_teid); + + /* Set PTI */ sess->pti = OGS_NAS_PROCEDURE_TRANSACTION_IDENTITY_UNASSIGNED; if (req->procedure_transaction_id.presence) { sess->pti = req->procedure_transaction_id.u8; @@ -691,7 +839,7 @@ void mme_s11_handle_update_bearer_request( req->bearer_contexts.tft.presence)); } } else { - ogs_warn("[IGNORE] Update Bearer Request : " + ogs_error("[IGNORE] Update Bearer Request : " "Both QoS and TFT is NULL"); if (xact->xid & OGS_GTP_CMD_XACT_ID) { @@ -708,78 +856,102 @@ void mme_s11_handle_update_bearer_request( } void mme_s11_handle_delete_bearer_request( - ogs_gtp_xact_t *xact, mme_ue_t *mme_ue, + ogs_gtp_xact_t *xact, sgw_ue_t *sgw_ue, ogs_gtp2_delete_bearer_request_t *req) { + uint8_t cause_value = 0; + mme_bearer_t *bearer = NULL; mme_sess_t *sess = NULL; + mme_ue_t *mme_ue = NULL; ogs_assert(xact); ogs_assert(req); ogs_debug("Delete Bearer Request"); - if (mme_ue && req->linked_eps_bearer_id.presence == 1) { - /* - * << Linked EPS Bearer ID >> - * - * 1. SMF sends Delete Bearer Request(DEFAULT BEARER) to SGW/MME. - * 2. MME sends Delete Bearer Response to SGW/SMF. - * - * OR - * - * 1. SMF sends Delete Bearer Request(DEFAULT BEARER) to ePDG. - * 2. ePDG sends Delete Bearer Response(DEFAULT BEARER) to SMF. - */ - bearer = mme_bearer_find_by_ue_ebi( - mme_ue, req->linked_eps_bearer_id.u8); - if (!bearer) - ogs_error("Cannot find Bearer [%d]", req->linked_eps_bearer_id.u8); - } else if (mme_ue && req->eps_bearer_ids.presence == 1) { - /* - * << EPS Bearer IDs >> - * - * 1. MME sends Bearer Resource Command to SGW/SMF. - * 2. SMF sends Delete Bearer Request(DEDICATED BEARER) to SGW/MME. - * 3. MME sends Delete Bearer Response(DEDICATED BEARER) to SGW/SMF. - * - * OR - * - * 1. SMF sends Delete Bearer Request(DEDICATED BEARER) to SGW/MME. - * 2. MME sends Delete Bearer Response(DEDICATED BEARER) to SGW/SMF. - */ - bearer = mme_bearer_find_by_ue_ebi( - mme_ue, req->eps_bearer_ids.u8); - if (!bearer) - ogs_error("Cannot find Bearer [%d]", req->eps_bearer_ids.u8); + /*********************** + * Check SGW-UE Context + ***********************/ + cause_value = OGS_GTP2_CAUSE_REQUEST_ACCEPTED; + + if (!sgw_ue) { + ogs_error("No Context in TEID"); + cause_value = OGS_GTP2_CAUSE_CONTEXT_NOT_FOUND; } else { - ogs_error("No Linked EBI or EPS Bearer ID"); + mme_ue = sgw_ue->mme_ue; + ogs_assert(mme_ue); + + if (req->linked_eps_bearer_id.presence == 1) { + /* + * << Linked EPS Bearer ID >> + * + * 1. SMF sends Delete Bearer Request(DEFAULT BEARER) to SGW/MME. + * 2. MME sends Delete Bearer Response to SGW/SMF. + * + * OR + * + * 1. SMF sends Delete Bearer Request(DEFAULT BEARER) to ePDG. + * 2. ePDG sends Delete Bearer Response(DEFAULT BEARER) to SMF. + */ + bearer = mme_bearer_find_by_ue_ebi( + mme_ue, req->linked_eps_bearer_id.u8); + if (!bearer) { + ogs_error("Cannot find Bearer [%d]", + req->linked_eps_bearer_id.u8); + cause_value = OGS_GTP2_CAUSE_CONTEXT_NOT_FOUND; + } + } else if (req->eps_bearer_ids.presence == 1) { + /* + * << EPS Bearer IDs >> + * + * 1. MME sends Bearer Resource Command to SGW/SMF. + * 2. SMF sends Delete Bearer Request(DEDICATED BEARER) to SGW/MME. + * 3. MME sends Delete Bearer Response(DEDICATED BEARER) to SGW/SMF. + * + * OR + * + * 1. SMF sends Delete Bearer Request(DEDICATED BEARER) to SGW/MME. + * 2. MME sends Delete Bearer Response(DEDICATED BEARER) to SGW/SMF. + */ + bearer = mme_bearer_find_by_ue_ebi(mme_ue, req->eps_bearer_ids.u8); + if (!bearer) { + ogs_error("Cannot find Bearer [%d]", req->eps_bearer_ids.u8); + cause_value = OGS_GTP2_CAUSE_CONTEXT_NOT_FOUND; + } + } else { + ogs_error("No Linked EBI or EPS Bearer ID"); + cause_value = OGS_GTP2_CAUSE_MANDATORY_IE_MISSING; + } } - if (!bearer) { - ogs_error("No Context"); - ogs_gtp2_send_error_message(xact, mme_ue ? mme_ue->sgw_s11_teid : 0, + if (cause_value != OGS_GTP2_CAUSE_REQUEST_ACCEPTED) { + ogs_gtp2_send_error_message(xact, sgw_ue ? sgw_ue->sgw_s11_teid : 0, OGS_GTP2_DELETE_BEARER_RESPONSE_TYPE, OGS_GTP2_CAUSE_CONTEXT_NOT_FOUND); return; } + /******************** + * Check ALL Context + ********************/ ogs_assert(mme_ue); + ogs_assert(sgw_ue); - ogs_debug(" MME_S11_TEID[%d] SGW_S11_TEID[%d]", - mme_ue->mme_s11_teid, mme_ue->sgw_s11_teid); - - /* Set PTI */ ogs_assert(bearer); sess = bearer->sess; ogs_assert(sess); + + ogs_debug(" MME_S11_TEID[%d] SGW_S11_TEID[%d]", + sgw_ue->mme_s11_teid, sgw_ue->sgw_s11_teid); + + /* Set PTI */ sess->pti = OGS_NAS_PROCEDURE_TRANSACTION_IDENTITY_UNASSIGNED; if (req->procedure_transaction_id.presence) { sess->pti = req->procedure_transaction_id.u8; ogs_debug(" PTI[%d]", sess->pti); } - ogs_assert(bearer); /* * Save Transaction. It will be handled after EMM-attached * @@ -799,7 +971,7 @@ void mme_s11_handle_delete_bearer_request( } void mme_s11_handle_release_access_bearers_response( - ogs_gtp_xact_t *xact, mme_ue_t *mme_ue_from_teid, + ogs_gtp_xact_t *xact, sgw_ue_t *sgw_ue, ogs_gtp2_release_access_bearers_response_t *rsp) { int rv; @@ -807,38 +979,52 @@ void mme_s11_handle_release_access_bearers_response( int action = 0; enb_ue_t *enb_ue = NULL; - mme_ue_t *mme_ue = mme_ue_from_teid; + mme_ue_t *mme_ue = NULL;; mme_sess_t *sess = NULL; mme_bearer_t *bearer = NULL; - ogs_assert(xact); ogs_assert(rsp); - action = xact->release_action; - ogs_assert(action); ogs_debug("Release Access Bearers Response"); - if (!mme_ue) { - ogs_warn("No Context in TEID"); - mme_ue = xact->data; - ogs_assert(mme_ue); - } + /******************** + * Check Transaction + ********************/ + ogs_assert(xact); + action = xact->release_action; + ogs_assert(action); + mme_ue = xact->data; + ogs_assert(mme_ue); rv = ogs_gtp_xact_commit(xact); ogs_expect_or_return(rv == OGS_OK); + /*********************** + * Check SGW-UE Context + ***********************/ + if (!sgw_ue) + ogs_error("No Context in TEID"); + + /******************** + * Check Cause Value + ********************/ if (rsp->cause.presence) { ogs_gtp2_cause_t *cause = rsp->cause.data; ogs_assert(cause); cause_value = cause->value; if (cause_value != OGS_GTP2_CAUSE_REQUEST_ACCEPTED) - ogs_warn("GTP Failed [CAUSE:%d]", cause_value); + ogs_error("GTP Failed [CAUSE:%d]", cause_value); } + /******************** + * Check ALL Context + ********************/ ogs_assert(mme_ue); - ogs_debug(" MME_S11_TEID[%d] SGW_S11_TEID[%d]", - mme_ue->mme_s11_teid, mme_ue->sgw_s11_teid); + + if (sgw_ue) + ogs_debug(" MME_S11_TEID[%d] SGW_S11_TEID[%d]", + sgw_ue->mme_s11_teid, sgw_ue->sgw_s11_teid); ogs_list_for_each(&mme_ue->sess_list, sess) { ogs_list_for_each(&sess->bearer_list, bearer) { @@ -854,17 +1040,17 @@ void mme_s11_handle_release_access_bearers_response( S1AP_Cause_PR_nas, S1AP_CauseNas_normal_release, S1AP_UE_CTX_REL_S1_REMOVE_AND_UNLINK, 0)); } else { - ogs_warn("ENB-S1 Context has already been removed"); + ogs_error("ENB-S1 Context has already been removed"); } } else if (action == OGS_GTP_RELEASE_S1_CONTEXT_REMOVE_BY_LO_CONNREFUSED) { enb_ue = enb_ue_cycle(mme_ue->enb_ue); - mme_ue_deassociate(mme_ue); + enb_ue_unlink(mme_ue); if (enb_ue) { enb_ue_remove(enb_ue); } else { - ogs_warn("ENB-S1 Context has already been removed"); + ogs_error("ENB-S1 Context has already been removed"); } /* @@ -883,7 +1069,7 @@ void mme_s11_handle_release_access_bearers_response( } else if (action == OGS_GTP_RELEASE_S1_CONTEXT_REMOVE_BY_RESET_ALL) { enb_ue = enb_ue_cycle(mme_ue->enb_ue); - mme_ue_deassociate(mme_ue); + enb_ue_unlink(mme_ue); if (enb_ue) { mme_enb_t *enb = enb_ue->enb; @@ -895,7 +1081,7 @@ void mme_s11_handle_release_access_bearers_response( ogs_assert(OGS_OK == s1ap_send_s1_reset_ack(enb, NULL)); } else { - ogs_warn("ENB-S1 Context has already been removed"); + ogs_error("ENB-S1 Context has already been removed"); } } else if (action == OGS_GTP_RELEASE_S1_CONTEXT_REMOVE_BY_RESET_PARTIAL) { @@ -903,7 +1089,7 @@ void mme_s11_handle_release_access_bearers_response( enb_ue = enb_ue_cycle(mme_ue->enb_ue); - mme_ue_deassociate(mme_ue); + enb_ue_unlink(mme_ue); if (enb_ue) { mme_enb_t *enb = enb_ue->enb; @@ -929,7 +1115,7 @@ void mme_s11_handle_release_access_bearers_response( /* Clear S1-Reset Ack Buffer */ enb->s1_reset_ack = NULL; } else { - ogs_warn("ENB-S1 Context has already been removed"); + ogs_error("ENB-S1 Context has already been removed"); } } else { @@ -939,53 +1125,63 @@ void mme_s11_handle_release_access_bearers_response( } void mme_s11_handle_downlink_data_notification( - ogs_gtp_xact_t *xact, mme_ue_t *mme_ue, + ogs_gtp_xact_t *xact, sgw_ue_t *sgw_ue, ogs_gtp2_downlink_data_notification_t *noti) { uint8_t cause_value = 0; mme_bearer_t *bearer = NULL; + mme_ue_t *mme_ue = NULL; ogs_assert(xact); ogs_assert(noti); ogs_debug("Downlink Data Notification"); + /************************ + * Check SGW-UE Context + ************************/ cause_value = OGS_GTP2_CAUSE_REQUEST_ACCEPTED; - if (noti->eps_bearer_id.presence == 0) { - ogs_error("No Bearer ID"); - cause_value = OGS_GTP2_CAUSE_MANDATORY_IE_MISSING; - } - - if (!mme_ue) { + if (!sgw_ue) { ogs_error("No UE Context"); cause_value = OGS_GTP2_CAUSE_CONTEXT_NOT_FOUND; - } + } else { + mme_ue = sgw_ue->mme_ue; + ogs_assert(mme_ue); - if (cause_value == OGS_GTP2_CAUSE_REQUEST_ACCEPTED) { - bearer = mme_bearer_find_by_ue_ebi(mme_ue, noti->eps_bearer_id.u8); - if (!bearer) - ogs_error("No Context for EPS Bearer ID[%d]", - noti->eps_bearer_id.u8); - } + if (noti->eps_bearer_id.presence == 0) { + ogs_error("No Bearer ID"); + cause_value = OGS_GTP2_CAUSE_MANDATORY_IE_MISSING; + } - if (!bearer) { - ogs_error("No Bearer Context"); - cause_value = OGS_GTP2_CAUSE_CONTEXT_NOT_FOUND; + if (cause_value == OGS_GTP2_CAUSE_REQUEST_ACCEPTED) { + bearer = mme_bearer_find_by_ue_ebi(mme_ue, noti->eps_bearer_id.u8); + if (!bearer) { + ogs_error("No Context for EPS Bearer ID[%d]", + noti->eps_bearer_id.u8); + cause_value = OGS_GTP2_CAUSE_CONTEXT_NOT_FOUND; + } + } } if (cause_value != OGS_GTP2_CAUSE_REQUEST_ACCEPTED) { - ogs_gtp2_send_error_message(xact, mme_ue ? mme_ue->sgw_s11_teid : 0, + ogs_gtp2_send_error_message(xact, sgw_ue ? sgw_ue->sgw_s11_teid : 0, OGS_GTP2_DOWNLINK_DATA_NOTIFICATION_ACKNOWLEDGE_TYPE, OGS_GTP2_CAUSE_CONTEXT_NOT_FOUND); return; } + /******************** + * Check ALL Context + ********************/ ogs_assert(mme_ue); + ogs_assert(sgw_ue); + ogs_assert(bearer); + ogs_debug(" MME_S11_TEID[%d] SGW_S11_TEID[%d]", - mme_ue->mme_s11_teid, mme_ue->sgw_s11_teid); + sgw_ue->mme_s11_teid, sgw_ue->sgw_s11_teid); /* * Save Transaction. It will be handled after ECM-Connected @@ -1067,58 +1263,93 @@ void mme_s11_handle_downlink_data_notification( } void mme_s11_handle_create_indirect_data_forwarding_tunnel_response( - ogs_gtp_xact_t *xact, mme_ue_t *mme_ue_from_teid, + ogs_gtp_xact_t *xact, sgw_ue_t *sgw_ue, ogs_gtp2_create_indirect_data_forwarding_tunnel_response_t *rsp) { int rv; uint8_t cause_value = 0; - mme_ue_t *mme_ue = mme_ue_from_teid; + ogs_gtp2_cause_t *cause = NULL; + mme_ue_t *mme_ue = NULL; mme_bearer_t *bearer = NULL; enb_ue_t *source_ue = NULL; int i; ogs_gtp2_f_teid_t *teid = NULL; - ogs_assert(xact); ogs_assert(rsp); ogs_debug("Create Indirect Data Forwarding Tunnel Response"); - if (!mme_ue) { - ogs_warn("No Context in TEID"); - mme_ue = xact->data; - ogs_assert(mme_ue); - } + /******************** + * Check Transaction + ********************/ + ogs_assert(xact); + mme_ue = xact->data; + ogs_assert(mme_ue); rv = ogs_gtp_xact_commit(xact); ogs_expect_or_return(rv == OGS_OK); - if (rsp->cause.presence) { - ogs_gtp2_cause_t *cause = rsp->cause.data; - ogs_assert(cause); + /************************ + * Check SGW-UE Context + ************************/ + cause_value = OGS_GTP2_CAUSE_REQUEST_ACCEPTED; - cause_value = cause->value; - if (cause_value != OGS_GTP2_CAUSE_REQUEST_ACCEPTED) - ogs_warn("GTP Failed [CAUSE:%d]", cause_value); + if (!sgw_ue) { + ogs_error("No Context in TEID"); + cause_value = OGS_GTP2_CAUSE_CONTEXT_NOT_FOUND; } - ogs_assert(mme_ue); - ogs_debug(" MME_S11_TEID[%d] SGW_S11_TEID[%d]", - mme_ue->mme_s11_teid, mme_ue->sgw_s11_teid); - if (cause_value != OGS_GTP2_CAUSE_REQUEST_ACCEPTED) { - if (mme_ue_from_teid && mme_ue) - mme_send_delete_session_or_mme_ue_context_release(mme_ue); + mme_send_delete_session_or_mme_ue_context_release(mme_ue); return; } + /***************************************** + * Check Mandatory/Conditional IE Missing + *****************************************/ + ogs_assert(cause_value == OGS_GTP2_CAUSE_REQUEST_ACCEPTED); + + if (rsp->cause.presence == 0) { + ogs_error("No Cause"); + cause_value = OGS_GTP2_CAUSE_MANDATORY_IE_MISSING; + } + + if (cause_value != OGS_GTP2_CAUSE_REQUEST_ACCEPTED) { + mme_send_delete_session_or_mme_ue_context_release(mme_ue); + return; + } + + /******************** + * Check Cause Value + ********************/ + ogs_assert(cause_value == OGS_GTP2_CAUSE_REQUEST_ACCEPTED); + + cause = rsp->cause.data; + ogs_assert(cause); + cause_value = cause->value; + if (cause_value != OGS_GTP2_CAUSE_REQUEST_ACCEPTED) { + ogs_error("GTP Failed [CAUSE:%d]", cause_value); + mme_send_delete_session_or_mme_ue_context_release(mme_ue); + return; + } + + /******************** + * Check ALL Context + ********************/ + ogs_assert(mme_ue); + ogs_assert(sgw_ue); + + ogs_debug(" MME_S11_TEID[%d] SGW_S11_TEID[%d]", + sgw_ue->mme_s11_teid, sgw_ue->sgw_s11_teid); + for (i = 0; rsp->bearer_contexts[i].presence; i++) { if (rsp->bearer_contexts[i].eps_bearer_id.presence == 0) { ogs_error("No EBI"); return; } - bearer = mme_bearer_find_by_ue_ebi(mme_ue, + bearer = mme_bearer_find_by_ue_ebi(mme_ue, rsp->bearer_contexts[i].eps_bearer_id.u8); ogs_expect_or_return(bearer); @@ -1143,52 +1374,87 @@ void mme_s11_handle_create_indirect_data_forwarding_tunnel_response( source_ue = enb_ue_cycle(mme_ue->enb_ue); ogs_assert(source_ue); - ogs_assert(OGS_OK == - s1ap_send_handover_command(source_ue)); + ogs_assert(OGS_OK == s1ap_send_handover_command(source_ue)); } void mme_s11_handle_delete_indirect_data_forwarding_tunnel_response( - ogs_gtp_xact_t *xact, mme_ue_t *mme_ue_from_teid, + ogs_gtp_xact_t *xact, sgw_ue_t *sgw_ue, ogs_gtp2_delete_indirect_data_forwarding_tunnel_response_t *rsp) { int rv; uint8_t cause_value = 0; + ogs_gtp2_cause_t *cause = NULL; int action = 0; - mme_ue_t *mme_ue = mme_ue_from_teid; + mme_ue_t *mme_ue = NULL; - ogs_assert(xact); - action = xact->delete_indirect_action; - ogs_assert(action); ogs_assert(rsp); ogs_debug("Delete Indirect Data Forwarding Tunnel Response"); - if (!mme_ue) { - ogs_warn("No Context in TEID"); - mme_ue = xact->data; - ogs_assert(mme_ue); - } + /******************** + * Check Transaction + ********************/ + ogs_assert(xact); + action = xact->delete_indirect_action; + ogs_assert(action); + mme_ue = xact->data; + ogs_assert(mme_ue); rv = ogs_gtp_xact_commit(xact); ogs_expect_or_return(rv == OGS_OK); - if (rsp->cause.presence) { - ogs_gtp2_cause_t *cause = rsp->cause.data; - ogs_assert(cause); + /************************ + * Check SGW-UE Context + ************************/ + cause_value = OGS_GTP2_CAUSE_REQUEST_ACCEPTED; - cause_value = cause->value; - if (cause_value != OGS_GTP2_CAUSE_REQUEST_ACCEPTED) - ogs_warn("GTP Failed [CAUSE:%d]", cause_value); + if (!sgw_ue) { + ogs_error("No Context in TEID"); + cause_value = OGS_GTP2_CAUSE_CONTEXT_NOT_FOUND; } if (cause_value != OGS_GTP2_CAUSE_REQUEST_ACCEPTED) { - if (mme_ue_from_teid && mme_ue) - mme_send_delete_session_or_mme_ue_context_release(mme_ue); + mme_send_delete_session_or_mme_ue_context_release(mme_ue); return; } + /***************************************** + * Check Mandatory/Conditional IE Missing + *****************************************/ + ogs_assert(cause_value == OGS_GTP2_CAUSE_REQUEST_ACCEPTED); + + if (rsp->cause.presence == 0) { + ogs_error("No Cause"); + cause_value = OGS_GTP2_CAUSE_MANDATORY_IE_MISSING; + } + + if (cause_value != OGS_GTP2_CAUSE_REQUEST_ACCEPTED) { + mme_send_delete_session_or_mme_ue_context_release(mme_ue); + return; + } + + /******************** + * Check Cause Value + ********************/ + ogs_assert(cause_value == OGS_GTP2_CAUSE_REQUEST_ACCEPTED); + + cause = rsp->cause.data; + ogs_assert(cause); + cause_value = cause->value; + if (cause_value != OGS_GTP2_CAUSE_REQUEST_ACCEPTED) { + ogs_error("GTP Failed [CAUSE:%d]", cause_value); + mme_send_delete_session_or_mme_ue_context_release(mme_ue); + return; + } + + /******************** + * Check ALL Context + ********************/ + ogs_assert(mme_ue); + ogs_assert(sgw_ue); + ogs_debug(" MME_S11_TEID[%d] SGW_S11_TEID[%d]", - mme_ue->mme_s11_teid, mme_ue->sgw_s11_teid); + sgw_ue->mme_s11_teid, sgw_ue->sgw_s11_teid); mme_ue_clear_indirect_tunnel(mme_ue); @@ -1204,7 +1470,7 @@ void mme_s11_handle_delete_indirect_data_forwarding_tunnel_response( } void mme_s11_handle_bearer_resource_failure_indication( - ogs_gtp_xact_t *xact, mme_ue_t *mme_ue_from_teid, + ogs_gtp_xact_t *xact, sgw_ue_t *sgw_ue, ogs_gtp2_bearer_resource_failure_indication_t *ind) { int rv; @@ -1212,24 +1478,30 @@ void mme_s11_handle_bearer_resource_failure_indication( mme_bearer_t *bearer = NULL; mme_sess_t *sess = NULL; - mme_ue_t *mme_ue = mme_ue_from_teid; + mme_ue_t *mme_ue = NULL; + ogs_debug("Bearer Resource Failure Indication"); + + /******************** + * Check Transaction + ********************/ ogs_assert(xact); bearer = xact->data; ogs_assert(ind); sess = bearer->sess; ogs_assert(sess); - if (!mme_ue) { - ogs_warn("No Context in TEID"); - mme_ue = sess->mme_ue; - ogs_assert(mme_ue); - } - - ogs_debug("Bearer Resource Failure Indication"); + mme_ue = sess->mme_ue; + ogs_assert(mme_ue); rv = ogs_gtp_xact_commit(xact); ogs_expect_or_return(rv == OGS_OK); + if (!sgw_ue) + ogs_error("No Context in TEID"); + + /******************** + * Check Cause Value + ********************/ if (ind->cause.presence) { ogs_gtp2_cause_t *cause = ind->cause.data; ogs_assert(cause); @@ -1240,16 +1512,22 @@ void mme_s11_handle_bearer_resource_failure_indication( ogs_error("No Cause"); } + /******************** + * Check ALL Context + ********************/ ogs_assert(mme_ue); - ogs_debug(" MME_S11_TEID[%d] SGW_S11_TEID[%d]", - mme_ue->mme_s11_teid, mme_ue->sgw_s11_teid); + + if (sgw_ue) + ogs_debug(" MME_S11_TEID[%d] SGW_S11_TEID[%d]", + sgw_ue->mme_s11_teid, sgw_ue->sgw_s11_teid); ogs_assert(OGS_OK == nas_eps_send_bearer_resource_modification_reject( mme_ue, sess->pti, esm_cause_from_gtp(cause_value))); - if (cause_value == OGS_GTP2_CAUSE_CONTEXT_NOT_FOUND) { - ogs_warn("No Bearer"); + if (!sgw_ue || + cause_value == OGS_GTP2_CAUSE_CONTEXT_NOT_FOUND) { + ogs_error("No Bearer"); mme_bearer_remove(bearer); } } diff --git a/src/mme/mme-s11-handler.h b/src/mme/mme-s11-handler.h index 63126bcbc..faa06a57b 100644 --- a/src/mme/mme-s11-handler.h +++ b/src/mme/mme-s11-handler.h @@ -31,39 +31,39 @@ void mme_s11_handle_echo_request( void mme_s11_handle_echo_response( ogs_gtp_xact_t *xact, ogs_gtp2_echo_response_t *rsp); void mme_s11_handle_create_session_response( - ogs_gtp_xact_t *xact, mme_ue_t *mme_ue, + ogs_gtp_xact_t *xact, sgw_ue_t *sgw_ue, ogs_gtp2_create_session_response_t *rsp); void mme_s11_handle_modify_bearer_response( - ogs_gtp_xact_t *xact, mme_ue_t *mme_ue, + ogs_gtp_xact_t *xact, sgw_ue_t *sgw_ue, ogs_gtp2_modify_bearer_response_t *rsp); void mme_s11_handle_delete_session_response( - ogs_gtp_xact_t *xact, mme_ue_t *mme_ue, + ogs_gtp_xact_t *xact, sgw_ue_t *sgw_ue, ogs_gtp2_delete_session_response_t *rsp); void mme_s11_handle_create_bearer_request( - ogs_gtp_xact_t *xact, mme_ue_t *mme_ue, + ogs_gtp_xact_t *xact, sgw_ue_t *sgw_ue, ogs_gtp2_create_bearer_request_t *rsp); void mme_s11_handle_update_bearer_request( - ogs_gtp_xact_t *xact, mme_ue_t *mme_ue, + ogs_gtp_xact_t *xact, sgw_ue_t *sgw_ue, ogs_gtp2_update_bearer_request_t *rsp); void mme_s11_handle_delete_bearer_request( - ogs_gtp_xact_t *xact, mme_ue_t *mme_ue, + ogs_gtp_xact_t *xact, sgw_ue_t *sgw_ue, ogs_gtp2_delete_bearer_request_t *rsp); void mme_s11_handle_release_access_bearers_response( - ogs_gtp_xact_t *xact, mme_ue_t *mme_ue, + ogs_gtp_xact_t *xact, sgw_ue_t *sgw_ue, ogs_gtp2_release_access_bearers_response_t *rsp); void mme_s11_handle_downlink_data_notification( - ogs_gtp_xact_t *xact, mme_ue_t *mme_ue, + ogs_gtp_xact_t *xact, sgw_ue_t *sgw_ue, ogs_gtp2_downlink_data_notification_t *noti); void mme_s11_handle_create_indirect_data_forwarding_tunnel_response( - ogs_gtp_xact_t *xact, mme_ue_t *mme_ue, + ogs_gtp_xact_t *xact, sgw_ue_t *sgw_ue, ogs_gtp2_create_indirect_data_forwarding_tunnel_response_t *rsp); void mme_s11_handle_delete_indirect_data_forwarding_tunnel_response( - ogs_gtp_xact_t *xact, mme_ue_t *mme_ue, + ogs_gtp_xact_t *xact, sgw_ue_t *sgw_ue, ogs_gtp2_delete_indirect_data_forwarding_tunnel_response_t *rsp); void mme_s11_handle_bearer_resource_failure_indication( - ogs_gtp_xact_t *xact, mme_ue_t *mme_ue, + ogs_gtp_xact_t *xact, sgw_ue_t *sgw_ue, ogs_gtp2_bearer_resource_failure_indication_t *ind); #ifdef __cplusplus diff --git a/src/mme/mme-sm.c b/src/mme/mme-sm.c index 224211510..b9c42337c 100644 --- a/src/mme/mme-sm.c +++ b/src/mme/mme-sm.c @@ -113,6 +113,7 @@ void mme_state_operational(ogs_fsm_t *s, mme_event_t *e) ogs_nas_eps_message_t nas_message; enb_ue_t *enb_ue = NULL; + sgw_ue_t *sgw_ue = NULL; mme_ue_t *mme_ue = NULL; mme_bearer_t *bearer = NULL; @@ -338,7 +339,7 @@ void mme_state_operational(ogs_fsm_t *s, mme_event_t *e) S1AP_Cause_PR_nas, S1AP_CauseNas_normal_release, S1AP_UE_CTX_REL_S1_CONTEXT_REMOVE, 0)); } - mme_ue_associate_enb_ue(mme_ue, enb_ue); + enb_ue_associate_mme_ue(enb_ue, mme_ue); } ogs_assert(mme_ue); @@ -551,13 +552,12 @@ void mme_state_operational(ogs_fsm_t *s, mme_event_t *e) */ if (gtp_message.h.teid_presence && gtp_message.h.teid != 0) { /* Cause is not "Context not found" */ - mme_ue = mme_ue_find_by_teid(gtp_message.h.teid); + sgw_ue = sgw_ue_find_by_mme_s11_teid(gtp_message.h.teid); } - if (mme_ue) { - gnode = mme_ue->gnode; + if (sgw_ue) { + gnode = sgw_ue->gnode; ogs_assert(gnode); - } else { gnode = e->gnode; ogs_assert(gnode); @@ -578,57 +578,49 @@ void mme_state_operational(ogs_fsm_t *s, mme_event_t *e) break; case OGS_GTP2_CREATE_SESSION_RESPONSE_TYPE: mme_s11_handle_create_session_response( - xact, mme_ue, >p_message.create_session_response); + xact, sgw_ue, >p_message.create_session_response); break; case OGS_GTP2_MODIFY_BEARER_RESPONSE_TYPE: mme_s11_handle_modify_bearer_response( - xact, mme_ue, >p_message.modify_bearer_response); + xact, sgw_ue, >p_message.modify_bearer_response); break; case OGS_GTP2_DELETE_SESSION_RESPONSE_TYPE: mme_s11_handle_delete_session_response( - xact, mme_ue, >p_message.delete_session_response); + xact, sgw_ue, >p_message.delete_session_response); break; case OGS_GTP2_CREATE_BEARER_REQUEST_TYPE: mme_s11_handle_create_bearer_request( - xact, mme_ue, >p_message.create_bearer_request); + xact, sgw_ue, >p_message.create_bearer_request); break; case OGS_GTP2_UPDATE_BEARER_REQUEST_TYPE: mme_s11_handle_update_bearer_request( - xact, mme_ue, >p_message.update_bearer_request); + xact, sgw_ue, >p_message.update_bearer_request); break; case OGS_GTP2_DELETE_BEARER_REQUEST_TYPE: mme_s11_handle_delete_bearer_request( - xact, mme_ue, >p_message.delete_bearer_request); + xact, sgw_ue, >p_message.delete_bearer_request); break; case OGS_GTP2_RELEASE_ACCESS_BEARERS_RESPONSE_TYPE: mme_s11_handle_release_access_bearers_response( - xact, mme_ue, >p_message.release_access_bearers_response); + xact, sgw_ue, >p_message.release_access_bearers_response); break; case OGS_GTP2_DOWNLINK_DATA_NOTIFICATION_TYPE: - if (!mme_ue) { - if (gtp_message.h.teid_presence) - ogs_warn("No Context : TEID[%d]", gtp_message.h.teid); - else - ogs_warn("No Context : No TEID"); - - break; - } mme_s11_handle_downlink_data_notification( - xact, mme_ue, >p_message.downlink_data_notification); + xact, sgw_ue, >p_message.downlink_data_notification); break; case OGS_GTP2_CREATE_INDIRECT_DATA_FORWARDING_TUNNEL_RESPONSE_TYPE: mme_s11_handle_create_indirect_data_forwarding_tunnel_response( - xact, mme_ue, + xact, sgw_ue, >p_message.create_indirect_data_forwarding_tunnel_response); break; case OGS_GTP2_DELETE_INDIRECT_DATA_FORWARDING_TUNNEL_RESPONSE_TYPE: mme_s11_handle_delete_indirect_data_forwarding_tunnel_response( - xact, mme_ue, + xact, sgw_ue, >p_message.delete_indirect_data_forwarding_tunnel_response); break; case OGS_GTP2_BEARER_RESOURCE_FAILURE_INDICATION_TYPE: mme_s11_handle_bearer_resource_failure_indication( - xact, mme_ue, + xact, sgw_ue, >p_message.bearer_resource_failure_indication); break; default: diff --git a/src/mme/mme-timer.c b/src/mme/mme-timer.c index 7cfcfe08c..97a75cc7e 100644 --- a/src/mme/mme-timer.c +++ b/src/mme/mme-timer.c @@ -23,38 +23,41 @@ static mme_timer_cfg_t g_mme_timer_cfg[MAX_NUM_OF_MME_TIMER] = { /* Paging procedure for EPS services initiated */ - [MME_TIMER_T3413] = + [MME_TIMER_T3413] = { .max_count = 2, .duration = ogs_time_from_sec(2) }, /* DETACH REQUEST sent */ - [MME_TIMER_T3422] = + [MME_TIMER_T3422] = { .max_count = 4, .duration = ogs_time_from_sec(3) }, /* ATTACH ACCEPT sent * TRACKING AREA UPDATE ACCEPT sent with GUTI * TRACKING AREA UPDATE ACCEPT sent with TMSI * GUTI REALLOCATION COMMAND sent */ - [MME_TIMER_T3450] = + [MME_TIMER_T3450] = { .max_count = 4, .duration = ogs_time_from_sec(6) }, /* AUTHENTICATION REQUEST sent * SECURITY MODE COMMAND sent */ - [MME_TIMER_T3460] = + [MME_TIMER_T3460] = { .max_count = 4, .duration = ogs_time_from_sec(3) }, /* IDENTITY REQUEST sent */ - [MME_TIMER_T3470] = + [MME_TIMER_T3470] = { .max_count = 4, .duration = ogs_time_from_sec(3) }, /* ESM INFORMATION REQUEST sent */ - [MME_TIMER_T3489] = + [MME_TIMER_T3489] = { .max_count = 2, .duration = ogs_time_from_sec(4) }, - [MME_TIMER_SGS_CLI_CONN_TO_SRV] = + [MME_TIMER_SGS_CLI_CONN_TO_SRV] = { .duration = ogs_time_from_sec(3) }, [MME_TIMER_S1_HOLDING] = { .duration = ogs_time_from_sec(30) }, + + [MME_TIMER_S11_HOLDING] = + { .duration = ogs_time_from_msec(300) }, }; static void emm_timer_event_send( @@ -89,7 +92,9 @@ const char *mme_timer_get_name(mme_timer_e id) return "MME_TIMER_SGS_CLI_CONN_TO_SRV"; case MME_TIMER_S1_HOLDING: return "MME_TIMER_S1_HOLDING"; - default: + case MME_TIMER_S11_HOLDING: + return "MME_TIMER_S11_HOLDING"; + default: break; } @@ -216,3 +221,24 @@ void mme_timer_s1_holding_timer_expire(void *data) mme_event_free(e); } } + +void mme_timer_s11_holding_timer_expire(void *data) +{ + int rv; + mme_event_t *e = NULL; + sgw_ue_t *sgw_ue = NULL; + + ogs_assert(data); + sgw_ue = data; + + e = mme_event_new(MME_EVT_S11_TIMER); + + e->timer_id = MME_TIMER_S11_HOLDING; + e->sgw_ue = sgw_ue; + + rv = ogs_queue_push(ogs_app()->queue, e); + if (rv != OGS_OK) { + ogs_warn("ogs_queue_push() failed:%d", (int)rv); + mme_event_free(e); + } +} diff --git a/src/mme/mme-timer.h b/src/mme/mme-timer.h index ef2e7984f..e60056304 100644 --- a/src/mme/mme-timer.h +++ b/src/mme/mme-timer.h @@ -40,6 +40,8 @@ typedef enum { MME_TIMER_T3470, MME_TIMER_T3489, + MME_TIMER_S11_HOLDING, + MME_TIMER_SGS_CLI_CONN_TO_SRV, MAX_NUM_OF_MME_TIMER, @@ -66,6 +68,7 @@ void mme_timer_t3489_expire(void *data); void mme_timer_sgs_cli_conn_to_srv(void *data); void mme_timer_s1_holding_timer_expire(void *data); +void mme_timer_s11_holding_timer_expire(void *data); #ifdef __cplusplus } diff --git a/src/mme/s1ap-handler.c b/src/mme/s1ap-handler.c index b0dfeb6d9..a44c8e7d6 100644 --- a/src/mme/s1ap-handler.c +++ b/src/mme/s1ap-handler.c @@ -126,7 +126,7 @@ void s1ap_handle_s1_setup_request(mme_enb_t *enb, ogs_s1ap_message_t *message) S1AP_SupportedTAs_Item_t *SupportedTAs_Item = NULL; S1AP_TAC_t *tAC = NULL; - SupportedTAs_Item = + SupportedTAs_Item = (S1AP_SupportedTAs_Item_t *)SupportedTAs->list.array[i]; ogs_assert(SupportedTAs_Item); tAC = &SupportedTAs_Item->tAC; @@ -140,7 +140,7 @@ void s1ap_handle_s1_setup_request(mme_enb_t *enb, ogs_s1ap_message_t *message) memcpy(&enb->supported_ta_list[enb->num_of_supported_ta_list].tac, tAC->buf, sizeof(uint16_t)); - enb->supported_ta_list[enb->num_of_supported_ta_list].tac = + enb->supported_ta_list[enb->num_of_supported_ta_list].tac = be16toh(enb->supported_ta_list [enb->num_of_supported_ta_list].tac); memcpy(&enb->supported_ta_list @@ -288,7 +288,7 @@ void s1ap_handle_initial_ue_message(mme_enb_t *enb, ogs_s1ap_message_t *message) mme_ue->current.guti.mme_gid, mme_ue->current.guti.mme_code, mme_ue->current.guti.m_tmsi, - MME_UE_HAVE_IMSI(mme_ue) + MME_UE_HAVE_IMSI(mme_ue) ? mme_ue->imsi_bcd : "Unknown"); /* If NAS(mme_ue_t) has already been associated with @@ -311,7 +311,7 @@ void s1ap_handle_initial_ue_message(mme_enb_t *enb, ogs_s1ap_message_t *message) S1AP_Cause_PR_nas, S1AP_CauseNas_normal_release, S1AP_UE_CTX_REL_S1_CONTEXT_REMOVE, 0)); } - mme_ue_associate_enb_ue(mme_ue, enb_ue); + enb_ue_associate_mme_ue(enb_ue, mme_ue); } } } @@ -349,7 +349,7 @@ void s1ap_handle_initial_ue_message(mme_enb_t *enb, ogs_s1ap_message_t *message) sizeof(enb_ue->saved.tai.plmn_id)); memcpy(&enb_ue->saved.tai.tac, tAC->buf, sizeof(enb_ue->saved.tai.tac)); enb_ue->saved.tai.tac = be16toh(enb_ue->saved.tai.tac); - + pLMNidentity = &EUTRAN_CGI->pLMNidentity; ogs_assert(pLMNidentity && pLMNidentity->size == sizeof(ogs_plmn_id_t)); cell_ID = &EUTRAN_CGI->cell_ID; @@ -690,6 +690,10 @@ void s1ap_handle_initial_context_setup_response( ogs_expect_or_return(mme_ue); if (E_RABSetupListCtxtSURes) { + int uli_presence = 0; + + ogs_list_init(&mme_ue->bearer_to_modify_list); + for (i = 0; i < E_RABSetupListCtxtSURes->list.count; i++) { S1AP_E_RABSetupItemCtxtSUResIEs_t *item = NULL; S1AP_E_RABSetupItemCtxtSURes_t *e_rab = NULL; @@ -745,15 +749,19 @@ void s1ap_handle_initial_context_setup_response( if (OGS_FSM_CHECK(&bearer->sm, esm_state_active)) { ogs_debug(" NAS_EPS Type[%d]", mme_ue->nas_eps.type); - int uli_presence = 0; if (mme_ue->nas_eps.type != MME_EPS_TYPE_ATTACH_REQUEST) { ogs_debug(" ### ULI PRESENT ###"); uli_presence = 1; } - ogs_assert(OGS_OK == - mme_gtp_send_modify_bearer_request(bearer, uli_presence)); + ogs_list_add(&mme_ue->bearer_to_modify_list, + &bearer->to_modify_node); } } + + if (ogs_list_count(&mme_ue->bearer_to_modify_list)) { + ogs_assert(OGS_OK == + mme_gtp_send_modify_bearer_request(mme_ue, uli_presence, 0)); + } } if (mme_ue->nas_eps.type != MME_EPS_TYPE_ATTACH_REQUEST) @@ -1213,12 +1221,15 @@ void s1ap_handle_e_rab_setup_response( ogs_debug(" Linked-EBI[%d]", linked_bearer->ebi); if (bearer->ebi == linked_bearer->ebi) { - ogs_assert(OGS_OK == - mme_gtp_send_modify_bearer_request(bearer, 0)); + ogs_list_init(&mme_ue->bearer_to_modify_list); + ogs_list_add(&mme_ue->bearer_to_modify_list, + &bearer->to_modify_node); + ogs_assert(OGS_OK == + mme_gtp_send_modify_bearer_request(mme_ue, 0, 0)); } else { - ogs_assert(OGS_OK == - mme_gtp_send_create_bearer_response( - bearer, OGS_GTP2_CAUSE_REQUEST_ACCEPTED)); + ogs_assert(OGS_OK == + mme_gtp_send_create_bearer_response( + bearer, OGS_GTP2_CAUSE_REQUEST_ACCEPTED)); } } } @@ -1240,7 +1251,7 @@ void s1ap_handle_e_rab_setup_response( } ogs_debug("RAB_ID: %d", (int)item->e_RAB_ID); - ogs_debug(" Cause[Group:%d Cause:%d]", + ogs_debug(" Cause[Group:%d Cause:%d]", (int)item->cause.present, (int)item->cause.choice.radioNetwork); } } @@ -1455,7 +1466,7 @@ void s1ap_handle_ue_context_release_action(enb_ue_t *enb_ue) * An assert occurs when a NAS message retransmission occurs. * * Because there is no `enb_ue` context. - * + * * Therefore, before removing enb_ue, all Timers must be stopped * to prevent retransmission of NAS messages. */ @@ -1471,7 +1482,7 @@ void s1ap_handle_ue_context_release_action(enb_ue_t *enb_ue) ogs_debug(" Action: S1 normal release"); enb_ue_remove(enb_ue); ogs_expect_or_return(mme_ue); - mme_ue_deassociate(mme_ue); + enb_ue_unlink(mme_ue); break; case S1AP_UE_CTX_REL_UE_CONTEXT_REMOVE: ogs_debug(" Action: UE context remove"); @@ -1484,7 +1495,7 @@ void s1ap_handle_ue_context_release_action(enb_ue_t *enb_ue) case S1AP_UE_CTX_REL_S1_HANDOVER_COMPLETE: ogs_debug(" Action: S1 handover complete"); - source_ue_deassociate_target_ue(enb_ue); + enb_ue_source_deassociate_target(enb_ue); enb_ue_remove(enb_ue); ogs_expect_or_return(mme_ue); @@ -1502,7 +1513,7 @@ void s1ap_handle_ue_context_release_action(enb_ue_t *enb_ue) case S1AP_UE_CTX_REL_S1_HANDOVER_CANCEL: ogs_warn(" Action: S1 handover cancel"); - source_ue_deassociate_target_ue(enb_ue); + enb_ue_source_deassociate_target(enb_ue); enb_ue_remove(enb_ue); ogs_expect_or_return(mme_ue); @@ -1524,7 +1535,7 @@ void s1ap_handle_ue_context_release_action(enb_ue_t *enb_ue) case S1AP_UE_CTX_REL_S1_HANDOVER_FAILURE: ogs_warn(" Action: S1 handover failure"); - source_ue_deassociate_target_ue(enb_ue); + enb_ue_source_deassociate_target(enb_ue); enb_ue_remove(enb_ue); ogs_expect_or_return(mme_ue); @@ -1538,7 +1549,7 @@ void s1ap_handle_ue_context_release_action(enb_ue_t *enb_ue) ogs_debug(" Action: S1 paging"); enb_ue_remove(enb_ue); ogs_expect_or_return(mme_ue); - mme_ue_deassociate(mme_ue); + enb_ue_unlink(mme_ue); ogs_assert(OGS_OK == s1ap_send_paging(mme_ue, S1AP_CNDomain_ps)); break; @@ -1639,6 +1650,8 @@ void s1ap_handle_e_rab_modification_indication( mme_ue = enb_ue->mme_ue; ogs_expect_or_return(mme_ue); + ogs_list_init(&mme_ue->bearer_to_modify_list); + for (i = 0; i < E_RABToBeModifiedListBearerModInd->list.count; i++) { S1AP_E_RABToBeModifiedItemBearerModIndIEs_t *item = NULL; S1AP_E_RABToBeModifiedItemBearerModInd_t *e_rab = NULL; @@ -1689,11 +1702,12 @@ void s1ap_handle_e_rab_modification_indication( return; } - GTP_COUNTER_INCREMENT( - mme_ue, GTP_COUNTER_MODIFY_BEARER_BY_E_RAB_MODIFICATION); + ogs_list_add(&mme_ue->bearer_to_modify_list, &bearer->to_modify_node); + } - ogs_assert(OGS_OK == - mme_gtp_send_modify_bearer_request(bearer, 0)); + if (ogs_list_count(&mme_ue->bearer_to_modify_list)) { + ogs_assert(OGS_OK == mme_gtp_send_modify_bearer_request( + mme_ue, 0, OGS_GTP_MODIFY_IN_E_RAB_MODIFICATION)); } } @@ -1727,6 +1741,8 @@ void s1ap_handle_path_switch_request( mme_ue_t *mme_ue = NULL; ogs_pkbuf_t *s1apbuf = NULL; + sgw_relocation_e relocation; + ogs_assert(enb); ogs_assert(enb->sctp.sock); @@ -1839,6 +1855,17 @@ void s1ap_handle_path_switch_request( mme_ue = enb_ue->mme_ue; ogs_expect_or_return(mme_ue); + if (!SECURITY_CONTEXT_IS_VALID(mme_ue)) { + ogs_error("No Security Context"); + s1apbuf = s1ap_build_path_switch_failure( + *ENB_UE_S1AP_ID, *MME_UE_S1AP_ID, + S1AP_Cause_PR_nas, S1AP_CauseNas_authentication_failure); + ogs_expect_or_return(s1apbuf); + + s1ap_send_to_enb_ue(enb_ue, s1apbuf); + return; + } + ogs_info(" OLD TAI[PLMN_ID:%06x,TAC:%d]", ogs_plmn_id_hexdump(&mme_ue->tai.plmn_id), mme_ue->tai.tac); @@ -1855,12 +1882,12 @@ void s1ap_handle_path_switch_request( ogs_info(" NEW ENB_UE_S1AP_ID[%d] MME_UE_S1AP_ID[%d]", enb_ue->enb_ue_s1ap_id, enb_ue->mme_ue_s1ap_id); - memcpy(&enb_ue->saved.tai.plmn_id, pLMNidentity->buf, + memcpy(&enb_ue->saved.tai.plmn_id, pLMNidentity->buf, sizeof(enb_ue->saved.tai.plmn_id)); memcpy(&enb_ue->saved.tai.tac, tAC->buf, sizeof(enb_ue->saved.tai.tac)); enb_ue->saved.tai.tac = be16toh(enb_ue->saved.tai.tac); - memcpy(&enb_ue->saved.e_cgi.plmn_id, pLMNidentity->buf, + memcpy(&enb_ue->saved.e_cgi.plmn_id, pLMNidentity->buf, sizeof(enb_ue->saved.e_cgi.plmn_id)); memcpy(&enb_ue->saved.e_cgi.cell_id, cell_ID->buf, sizeof(enb_ue->saved.e_cgi.cell_id)); @@ -1896,77 +1923,89 @@ void s1ap_handle_path_switch_request( mme_ue->ue_network_capability.eia = eia >> 9; mme_ue->ue_network_capability.eia0 = eia0; - if (!SECURITY_CONTEXT_IS_VALID(mme_ue)) { - ogs_error("No Security Context"); - s1apbuf = s1ap_build_path_switch_failure( - *ENB_UE_S1AP_ID, *MME_UE_S1AP_ID, - S1AP_Cause_PR_nas, S1AP_CauseNas_authentication_failure); - ogs_expect_or_return(s1apbuf); - - s1ap_send_to_enb_ue(enb_ue, s1apbuf); - return; - } - /* Update Security Context (NextHop) */ mme_ue->nhcc++; ogs_kdf_nh_enb(mme_ue->kasme, mme_ue->nh, mme_ue->nh); - for (i = 0; i < E_RABToBeSwitchedDLList->list.count; i++) { - S1AP_E_RABToBeSwitchedDLItemIEs_t *item = NULL; - S1AP_E_RABToBeSwitchedDLItem_t *e_rab = NULL; +#if 0 + relocation = sgw_ue_check_if_relocated(mme_ue); +#else + relocation = SGW_WITHOUT_RELOCATION; +#endif + if (relocation == SGW_WITHOUT_RELOCATION) { - mme_bearer_t *bearer = NULL; + ogs_list_init(&mme_ue->bearer_to_modify_list); - item = (S1AP_E_RABToBeSwitchedDLItemIEs_t *) - E_RABToBeSwitchedDLList->list.array[i]; - if (!item) { - ogs_error("No S1AP_E_RABToBeSwitchedDLItemIEs_t"); - ogs_assert(OGS_OK == - s1ap_send_error_indication2(mme_ue, - S1AP_Cause_PR_protocol, S1AP_CauseProtocol_semantic_error)); - return; + for (i = 0; i < E_RABToBeSwitchedDLList->list.count; i++) { + S1AP_E_RABToBeSwitchedDLItemIEs_t *item = NULL; + S1AP_E_RABToBeSwitchedDLItem_t *e_rab = NULL; + + mme_bearer_t *bearer = NULL; + + item = (S1AP_E_RABToBeSwitchedDLItemIEs_t *) + E_RABToBeSwitchedDLList->list.array[i]; + if (!item) { + ogs_error("No S1AP_E_RABToBeSwitchedDLItemIEs_t"); + ogs_assert(OGS_OK == + s1ap_send_error_indication2(mme_ue, + S1AP_Cause_PR_protocol, S1AP_CauseProtocol_semantic_error)); + return; + } + + e_rab = &item->value.choice.E_RABToBeSwitchedDLItem; + if (!e_rab) { + ogs_error("No E_RABToBeSwitchedDLItem"); + ogs_assert(OGS_OK == + s1ap_send_error_indication2(mme_ue, + S1AP_Cause_PR_protocol, S1AP_CauseProtocol_semantic_error)); + return; + } + + bearer = mme_bearer_find_by_ue_ebi(mme_ue, e_rab->e_RAB_ID); + if (!bearer) { + ogs_error("No Bearer [%d]", (int)e_rab->e_RAB_ID); + ogs_assert(OGS_OK == + s1ap_send_error_indication2(mme_ue, + S1AP_Cause_PR_radioNetwork, + S1AP_CauseRadioNetwork_unknown_E_RAB_ID)); + return; + } + + memcpy(&bearer->enb_s1u_teid, e_rab->gTP_TEID.buf, + sizeof(bearer->enb_s1u_teid)); + bearer->enb_s1u_teid = be32toh(bearer->enb_s1u_teid); + rv = ogs_asn_BIT_STRING_to_ip( + &e_rab->transportLayerAddress, &bearer->enb_s1u_ip); + if (rv != OGS_OK) { + ogs_error("No transportLayerAddress [%d]", + (int)e_rab->e_RAB_ID); + ogs_assert(OGS_OK == + s1ap_send_error_indication2(mme_ue, + S1AP_Cause_PR_protocol, + S1AP_CauseProtocol_abstract_syntax_error_falsely_constructed_message)); + return; + } + + ogs_list_add( + &mme_ue->bearer_to_modify_list, &bearer->to_modify_node); } - e_rab = &item->value.choice.E_RABToBeSwitchedDLItem; - if (!e_rab) { - ogs_error("No E_RABToBeSwitchedDLItem"); - ogs_assert(OGS_OK == - s1ap_send_error_indication2(mme_ue, - S1AP_Cause_PR_protocol, S1AP_CauseProtocol_semantic_error)); - return; + if (ogs_list_count(&mme_ue->bearer_to_modify_list)) { + ogs_assert(OGS_OK == mme_gtp_send_modify_bearer_request( + mme_ue, 1, OGS_GTP_MODIFY_IN_PATH_SWITCH_REQUEST)); } + } else if (relocation == SGW_WITH_RELOCATION) { + mme_sess_t *sess = NULL; - bearer = mme_bearer_find_by_ue_ebi(mme_ue, e_rab->e_RAB_ID); - if (!bearer) { - ogs_error("No Bearer [%d]", (int)e_rab->e_RAB_ID); + ogs_list_for_each(&mme_ue->sess_list, sess) { ogs_assert(OGS_OK == - s1ap_send_error_indication2(mme_ue, - S1AP_Cause_PR_radioNetwork, - S1AP_CauseRadioNetwork_unknown_E_RAB_ID)); - return; + mme_gtp_send_create_session_request( + sess, OGS_GTP_CREATE_IN_PATH_SWITCH_REQUEST)); } - - memcpy(&bearer->enb_s1u_teid, e_rab->gTP_TEID.buf, - sizeof(bearer->enb_s1u_teid)); - bearer->enb_s1u_teid = be32toh(bearer->enb_s1u_teid); - rv = ogs_asn_BIT_STRING_to_ip( - &e_rab->transportLayerAddress, &bearer->enb_s1u_ip); - if (rv != OGS_OK) { - ogs_error("No transportLayerAddress [%d]", - (int)e_rab->e_RAB_ID); - ogs_assert(OGS_OK == - s1ap_send_error_indication2(mme_ue, - S1AP_Cause_PR_protocol, - S1AP_CauseProtocol_abstract_syntax_error_falsely_constructed_message)); - return; - } - - GTP_COUNTER_INCREMENT( - mme_ue, GTP_COUNTER_MODIFY_BEARER_BY_PATH_SWITCH); - - ogs_assert(OGS_OK == - mme_gtp_send_modify_bearer_request(bearer, 1)); + } else if (relocation == SGW_HAS_ALREADY_BEEN_RELOCATED) { + ogs_error("SGW has already been relocated"); } + } void s1ap_handle_enb_configuration_transfer( @@ -2211,18 +2250,19 @@ void s1ap_handle_handover_required(mme_enb_t *enb, ogs_s1ap_message_t *message) mme_ue = source_ue->mme_ue; ogs_expect_or_return(mme_ue); - source_ue->handover_type = *HandoverType; - - if (SECURITY_CONTEXT_IS_VALID(mme_ue)) { - mme_ue->nhcc++; - ogs_kdf_nh_enb(mme_ue->kasme, mme_ue->nh, mme_ue->nh); - } else { + if (!SECURITY_CONTEXT_IS_VALID(mme_ue)) { + ogs_error("No Security Context"); ogs_assert(OGS_OK == s1ap_send_handover_preparation_failure(source_ue, S1AP_Cause_PR_nas, S1AP_CauseNas_authentication_failure)); return; } + source_ue->handover_type = *HandoverType; + + mme_ue->nhcc++; + ogs_kdf_nh_enb(mme_ue->kasme, mme_ue->nh, mme_ue->nh); + ogs_assert(OGS_OK == s1ap_send_handover_request( source_ue, target_enb, HandoverType, Cause, @@ -2381,7 +2421,7 @@ void s1ap_handle_handover_request_ack( return; } - memcpy(&bearer->target_s1u_teid, e_rab->gTP_TEID.buf, + memcpy(&bearer->target_s1u_teid, e_rab->gTP_TEID.buf, sizeof(bearer->target_s1u_teid)); bearer->target_s1u_teid = be32toh(bearer->target_s1u_teid); rv = ogs_asn_BIT_STRING_to_ip( @@ -2399,7 +2439,7 @@ void s1ap_handle_handover_request_ack( if (e_rab->dL_transportLayerAddress && e_rab->dL_gTP_TEID) { ogs_assert(e_rab->dL_gTP_TEID->buf); ogs_assert(e_rab->dL_transportLayerAddress->buf); - memcpy(&bearer->enb_dl_teid, e_rab->dL_gTP_TEID->buf, + memcpy(&bearer->enb_dl_teid, e_rab->dL_gTP_TEID->buf, sizeof(bearer->enb_dl_teid)); bearer->enb_dl_teid = be32toh(bearer->enb_dl_teid); rv = ogs_asn_BIT_STRING_to_ip( @@ -2418,7 +2458,7 @@ void s1ap_handle_handover_request_ack( if (e_rab->uL_TransportLayerAddress && e_rab->uL_GTP_TEID) { ogs_assert(e_rab->uL_GTP_TEID->buf); ogs_assert(e_rab->uL_TransportLayerAddress->buf); - memcpy(&bearer->enb_ul_teid, e_rab->uL_GTP_TEID->buf, + memcpy(&bearer->enb_ul_teid, e_rab->uL_GTP_TEID->buf, sizeof(bearer->enb_ul_teid)); bearer->enb_ul_teid = be32toh(bearer->enb_ul_teid); rv = ogs_asn_BIT_STRING_to_ip( @@ -2876,15 +2916,15 @@ void s1ap_handle_handover_notification( 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); - mme_ue_associate_enb_ue(mme_ue, target_ue); + enb_ue_associate_mme_ue(target_ue, mme_ue); - memcpy(&target_ue->saved.tai.plmn_id, pLMNidentity->buf, + memcpy(&target_ue->saved.tai.plmn_id, pLMNidentity->buf, sizeof(target_ue->saved.tai.plmn_id)); memcpy(&target_ue->saved.tai.tac, tAC->buf, sizeof(target_ue->saved.tai.tac)); target_ue->saved.tai.tac = be16toh(target_ue->saved.tai.tac); - memcpy(&target_ue->saved.e_cgi.plmn_id, pLMNidentity->buf, + memcpy(&target_ue->saved.e_cgi.plmn_id, pLMNidentity->buf, sizeof(target_ue->saved.e_cgi.plmn_id)); memcpy(&target_ue->saved.e_cgi.cell_id, cell_ID->buf, sizeof(target_ue->saved.e_cgi.cell_id)); @@ -2916,16 +2956,23 @@ void s1ap_handle_handover_notification( S1AP_UE_CTX_REL_S1_HANDOVER_COMPLETE, ogs_app()->time.handover.duration)); + ogs_list_init(&mme_ue->bearer_to_modify_list); + 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)); - ogs_assert(OGS_OK == - mme_gtp_send_modify_bearer_request(bearer, 1)); + ogs_list_add( + &mme_ue->bearer_to_modify_list, &bearer->to_modify_node); + } } + + if (ogs_list_count(&mme_ue->bearer_to_modify_list)) { + ogs_assert(OGS_OK == mme_gtp_send_modify_bearer_request(mme_ue, 1, 0)); + } } void s1ap_handle_s1_reset( diff --git a/src/mme/s1ap-path.c b/src/mme/s1ap-path.c index d6e1fd1ac..fbe2e7495 100644 --- a/src/mme/s1ap-path.c +++ b/src/mme/s1ap-path.c @@ -91,7 +91,7 @@ int s1ap_delayed_send_to_enb_ue( { ogs_assert(enb_ue); ogs_assert(pkbuf); - + if (duration) { mme_event_t *e = NULL; @@ -140,7 +140,7 @@ int s1ap_send_to_esm( return rv; } - + int s1ap_send_to_nas(enb_ue_t *enb_ue, S1AP_ProcedureCode_t procedureCode, S1AP_NAS_PDU_t *nasPdu) { @@ -154,7 +154,7 @@ int s1ap_send_to_nas(enb_ue_t *enb_ue, ogs_assert(enb_ue); ogs_assert(nasPdu); - /* The Packet Buffer(pkbuf_t) for NAS message MUST make a HEADROOM. + /* The Packet Buffer(pkbuf_t) for NAS message MUST make a HEADROOM. * When calculating AES_CMAC, we need to use the headroom of the packet. */ nasbuf = ogs_pkbuf_alloc(NULL, OGS_NAS_HEADROOM+nasPdu->size); ogs_assert(nasbuf); @@ -372,7 +372,7 @@ int s1ap_send_paging(mme_ue_t *mme_ue, S1AP_CNDomain_t cn_domain) } /* Start T3413 */ - ogs_timer_start(mme_ue->t3413.timer, + ogs_timer_start(mme_ue->t3413.timer, mme_timer_cfg(MME_TIMER_T3413)->duration); return OGS_OK; @@ -510,7 +510,7 @@ int s1ap_send_handover_request( ogs_info(" Target : ENB_UE_S1AP_ID[Unknown] MME_UE_S1AP_ID[%d]", target_ue->mme_ue_s1ap_id); - source_ue_associate_target_ue(source_ue, target_ue); + enb_ue_source_associate_target(source_ue, target_ue); s1apbuf = s1ap_build_handover_request( target_ue, handovertype, cause, diff --git a/src/sgwc/context.c b/src/sgwc/context.c index 088fae03b..c8091d471 100644 --- a/src/sgwc/context.c +++ b/src/sgwc/context.c @@ -473,6 +473,32 @@ sgwc_sess_t *sgwc_sess_cycle(sgwc_sess_t *sess) return ogs_pool_cycle(&sgwc_sess_pool, sess); } +int sgwc_sess_pfcp_xact_count( + sgwc_ue_t *sgwc_ue, uint8_t pfcp_type, uint64_t modify_flags) +{ + sgwc_sess_t *sess = NULL; + int xact_count = 0; + + ogs_assert(sgwc_ue); + + ogs_list_for_each(&sgwc_ue->sess_list, sess) { + ogs_pfcp_node_t *pfcp_node = sess->pfcp_node; + ogs_pfcp_xact_t *pfcp_xact = NULL; + ogs_assert(pfcp_node); + ogs_list_for_each(&pfcp_node->local_list, pfcp_xact) { + if (sess != pfcp_xact->data) + continue; + if (pfcp_type && pfcp_type != pfcp_xact->seq[0].type) + continue; + if (modify_flags && modify_flags != pfcp_xact->modify_flags) + continue; + xact_count++; + } + } + + return xact_count; +} + sgwc_bearer_t *sgwc_bearer_add(sgwc_sess_t *sess) { sgwc_bearer_t *bearer = NULL; diff --git a/src/sgwc/context.h b/src/sgwc/context.h index d621268eb..524208a87 100644 --- a/src/sgwc/context.h +++ b/src/sgwc/context.h @@ -81,19 +81,6 @@ typedef struct sgwc_sess_s { uint64_t sgwc_sxa_seid; /* SGW-C SEID is dervied from INDEX */ uint64_t sgwu_sxa_seid; /* SGW-U SEID is received from Peer */ - /* - * PFCP modification request is set to FALSE - * PFCP modifitation response is set to TRUE - * - * For example, when SGW-C is received Release Access Bearers Request, - * it is used to check if all sessions are deactivated. - */ - struct { - bool release_access_bearers; - bool create_indirect_tunnel; - bool delete_indirect_tunnel; - } state; - /* APN Configuration */ ogs_session_t session; @@ -108,6 +95,7 @@ typedef struct sgwc_sess_s { typedef struct sgwc_bearer_s { ogs_lnode_t lnode; + ogs_lnode_t to_modify_node; uint8_t ebi; @@ -167,6 +155,11 @@ sgwc_sess_t *sgwc_sess_find_by_apn(sgwc_ue_t *sgwc_ue, char *apn); sgwc_sess_t *sgwc_sess_find_by_ebi(sgwc_ue_t *sgwc_ue, uint8_t ebi); sgwc_sess_t *sgwc_sess_cycle(sgwc_sess_t *sess); +#define SESSION_SYNC_DONE(__sGWC, __tYPE, __fLAGS) \ + (sgwc_sess_pfcp_xact_count(__sGWC, __tYPE, __fLAGS) == 0) +int sgwc_sess_pfcp_xact_count( + sgwc_ue_t *sgwc_ue, uint8_t pfcp_type, uint64_t modify_flags); + sgwc_bearer_t *sgwc_bearer_add(sgwc_sess_t *sess); int sgwc_bearer_remove(sgwc_bearer_t *bearer); void sgwc_bearer_remove_all(sgwc_sess_t *sess); diff --git a/src/sgwc/pfcp-path.c b/src/sgwc/pfcp-path.c index 42c924332..c8290ef15 100644 --- a/src/sgwc/pfcp-path.c +++ b/src/sgwc/pfcp-path.c @@ -132,7 +132,7 @@ int sgwc_pfcp_open(void) ogs_list_for_each(&ogs_pfcp_self()->pfcp_list, node) { sock = ogs_pfcp_server(node); if (!sock) return OGS_ERROR; - + node->poll = ogs_pollset_add(ogs_app()->pollset, OGS_POLLIN, sock->fd, pfcp_recv_cb, sock); ogs_assert(node->poll); @@ -216,18 +216,69 @@ int sgwc_pfcp_send_session_establishment_request( h.type = OGS_PFCP_SESSION_ESTABLISHMENT_REQUEST_TYPE; h.seid = sess->sgwu_sxa_seid; - sxabuf = sgwc_sxa_build_session_establishment_request(h.type, sess); - ogs_expect_or_return_val(sxabuf, OGS_ERROR); - - xact = ogs_pfcp_xact_local_create( - sess->pfcp_node, &h, sxabuf, sess_timeout, sess); + xact = ogs_pfcp_xact_local_create(sess->pfcp_node, sess_timeout, sess); ogs_expect_or_return_val(xact, OGS_ERROR); + xact->assoc_xact = gtp_xact; if (gtpbuf) { xact->gtpbuf = ogs_pkbuf_copy(gtpbuf); ogs_expect_or_return_val(xact->gtpbuf, OGS_ERROR); } + sxabuf = sgwc_sxa_build_session_establishment_request(h.type, sess); + ogs_expect_or_return_val(sxabuf, OGS_ERROR); + + rv = ogs_pfcp_xact_update_tx(xact, &h, sxabuf); + ogs_expect_or_return_val(rv == OGS_OK, OGS_ERROR); + + rv = ogs_pfcp_xact_commit(xact); + ogs_expect(rv == OGS_OK); + + return rv; +} + +ogs_pfcp_xact_t *sgwc_pfcp_xact_create( + sgwc_sess_t *sess, ogs_gtp_xact_t *gtp_xact, + ogs_pkbuf_t *gtpbuf, uint64_t flags) +{ + ogs_pfcp_xact_t *xact = NULL; + + ogs_assert(sess); + + xact = ogs_pfcp_xact_local_create(sess->pfcp_node, sess_timeout, sess); + ogs_expect_or_return_val(xact, NULL); + + xact->assoc_xact = gtp_xact; + xact->modify_flags = flags | OGS_PFCP_MODIFY_SESSION; + if (gtpbuf) { + xact->gtpbuf = ogs_pkbuf_copy(gtpbuf); + ogs_expect_or_return_val(xact->gtpbuf, NULL); + } + + return xact; +} + +int sgwc_pfcp_xact_commit(ogs_pfcp_xact_t *xact) +{ + int rv; + sgwc_sess_t *sess = NULL; + ogs_pkbuf_t *sxabuf = NULL; + ogs_pfcp_header_t h; + + ogs_assert(xact); + sess = xact->data; + ogs_assert(sess); + + memset(&h, 0, sizeof(ogs_pfcp_header_t)); + h.type = OGS_PFCP_SESSION_MODIFICATION_REQUEST_TYPE; + h.seid = sess->sgwu_sxa_seid; + + sxabuf = sgwc_sxa_build_session_modification_request(h.type, sess, xact); + ogs_expect_or_return_val(sxabuf, OGS_ERROR); + + rv = ogs_pfcp_xact_update_tx(xact, &h, sxabuf); + ogs_expect_or_return_val(rv == OGS_OK, OGS_ERROR); + rv = ogs_pfcp_xact_commit(xact); ogs_expect(rv == OGS_OK); @@ -238,39 +289,18 @@ int sgwc_pfcp_send_sess_modification_request( sgwc_sess_t *sess, ogs_gtp_xact_t *gtp_xact, ogs_pkbuf_t *gtpbuf, uint64_t flags) { - int rv; - ogs_pkbuf_t *sxabuf = NULL; - ogs_pfcp_header_t h; ogs_pfcp_xact_t *xact = NULL; - - OGS_LIST(pdr_to_create_list); + sgwc_bearer_t *bearer = NULL; ogs_assert(sess); - memset(&h, 0, sizeof(ogs_pfcp_header_t)); - h.type = OGS_PFCP_SESSION_MODIFICATION_REQUEST_TYPE; - h.seid = sess->sgwu_sxa_seid; - - sxabuf = sgwc_sxa_build_sess_modification_request( - h.type, sess, flags, &pdr_to_create_list); - ogs_expect_or_return_val(sxabuf, OGS_ERROR); - - xact = ogs_pfcp_xact_local_create( - sess->pfcp_node, &h, sxabuf, sess_timeout, sess); + xact = sgwc_pfcp_xact_create(sess, gtp_xact, gtpbuf, flags); ogs_expect_or_return_val(xact, OGS_ERROR); - xact->assoc_xact = gtp_xact; - xact->modify_flags = flags | OGS_PFCP_MODIFY_SESSION; - if (gtpbuf) { - xact->gtpbuf = ogs_pkbuf_copy(gtpbuf); - ogs_expect_or_return_val(xact->gtpbuf, OGS_ERROR); - } - ogs_list_copy(&xact->pdr_to_create_list, &pdr_to_create_list); + ogs_list_for_each(&sess->bearer_list, bearer) + ogs_list_add(&xact->bearer_to_modify_list, &bearer->to_modify_node); - rv = ogs_pfcp_xact_commit(xact); - ogs_expect(rv == OGS_OK); - - return rv; + return sgwc_pfcp_xact_commit(xact); } int sgwc_pfcp_send_bearer_modification_request( @@ -283,23 +313,13 @@ int sgwc_pfcp_send_bearer_modification_request( ogs_pfcp_xact_t *xact = NULL; sgwc_sess_t *sess = NULL; - OGS_LIST(pdr_to_create_list); - ogs_assert(bearer); sess = bearer->sess; ogs_assert(sess); - memset(&h, 0, sizeof(ogs_pfcp_header_t)); - h.type = OGS_PFCP_SESSION_MODIFICATION_REQUEST_TYPE; - h.seid = sess->sgwu_sxa_seid; - - sxabuf = sgwc_sxa_build_bearer_modification_request( - h.type, bearer, flags, &pdr_to_create_list); - ogs_expect_or_return_val(sxabuf, OGS_ERROR); - - xact = ogs_pfcp_xact_local_create( - sess->pfcp_node, &h, sxabuf, bearer_timeout, bearer); + xact = ogs_pfcp_xact_local_create(sess->pfcp_node, bearer_timeout, bearer); ogs_expect_or_return_val(xact, OGS_ERROR); + xact->assoc_xact = gtp_xact; xact->modify_flags = flags; if (gtpbuf) { @@ -307,7 +327,17 @@ int sgwc_pfcp_send_bearer_modification_request( ogs_expect_or_return_val(xact->gtpbuf, OGS_ERROR); } - ogs_list_copy(&xact->pdr_to_create_list, &pdr_to_create_list); + ogs_list_add(&xact->bearer_to_modify_list, &bearer->to_modify_node); + + memset(&h, 0, sizeof(ogs_pfcp_header_t)); + h.type = OGS_PFCP_SESSION_MODIFICATION_REQUEST_TYPE; + h.seid = sess->sgwu_sxa_seid; + + sxabuf = sgwc_sxa_build_session_modification_request(h.type, sess, xact); + ogs_expect_or_return_val(sxabuf, OGS_ERROR); + + rv = ogs_pfcp_xact_update_tx(xact, &h, sxabuf); + ogs_expect_or_return_val(rv == OGS_OK, OGS_ERROR); rv = ogs_pfcp_xact_commit(xact); ogs_expect(rv == OGS_OK); @@ -329,18 +359,21 @@ int sgwc_pfcp_send_session_deletion_request( h.type = OGS_PFCP_SESSION_DELETION_REQUEST_TYPE; h.seid = sess->sgwu_sxa_seid; - sxabuf = sgwc_sxa_build_session_deletion_request(h.type, sess); - ogs_expect_or_return_val(sxabuf, OGS_ERROR); - - xact = ogs_pfcp_xact_local_create( - sess->pfcp_node, &h, sxabuf, sess_timeout, sess); + xact = ogs_pfcp_xact_local_create(sess->pfcp_node, sess_timeout, sess); ogs_expect_or_return_val(xact, OGS_ERROR); + xact->assoc_xact = gtp_xact; if (gtpbuf) { xact->gtpbuf = ogs_pkbuf_copy(gtpbuf); ogs_expect_or_return_val(xact->gtpbuf, OGS_ERROR); } + sxabuf = sgwc_sxa_build_session_deletion_request(h.type, sess); + ogs_expect_or_return_val(sxabuf, OGS_ERROR); + + rv = ogs_pfcp_xact_update_tx(xact, &h, sxabuf); + ogs_expect_or_return_val(rv == OGS_OK, OGS_ERROR); + rv = ogs_pfcp_xact_commit(xact); ogs_expect(rv == OGS_OK); diff --git a/src/sgwc/pfcp-path.h b/src/sgwc/pfcp-path.h index 1ee3d32e8..daef6b695 100644 --- a/src/sgwc/pfcp-path.h +++ b/src/sgwc/pfcp-path.h @@ -31,9 +31,26 @@ void sgwc_pfcp_close(void); int sgwc_pfcp_send_session_establishment_request( sgwc_sess_t *sess, ogs_gtp_xact_t *gtp_xact, ogs_pkbuf_t *gtpbuf); + +/* + * sgwc_pfcp_xact_create()/sgwc_pfcp_xact_commit() can only be used + * with sgwc_pfcp_send_sess_modification_request() + * + * You should not use the following functions + * - sgwc_pfcp_send_session_establishment_request() + * - sgwc_pfcp_send_bearer_modification_request() + * - sgwc_pfcp_send_session_deletion_request() + * - sgwc_pfcp_send_session_report_response() + */ +ogs_pfcp_xact_t *sgwc_pfcp_xact_create( + sgwc_sess_t *sess, ogs_gtp_xact_t *gtp_xact, + ogs_pkbuf_t *gtpbuf, uint64_t flags); +int sgwc_pfcp_xact_commit(ogs_pfcp_xact_t *xact); + int sgwc_pfcp_send_sess_modification_request( sgwc_sess_t *sess, ogs_gtp_xact_t *gtp_xact, ogs_pkbuf_t *gtpbuf, uint64_t flags); + int sgwc_pfcp_send_bearer_modification_request( sgwc_bearer_t *bearer, ogs_gtp_xact_t *gtp_xact, ogs_pkbuf_t *gtpbuf, uint64_t flags); diff --git a/src/sgwc/s11-handler.c b/src/sgwc/s11-handler.c index 1f8ce72b0..bd3ba3b0b 100644 --- a/src/sgwc/s11-handler.c +++ b/src/sgwc/s11-handler.c @@ -39,7 +39,7 @@ static void sess_timeout(ogs_gtp_xact_t *xact, void *data) case OGS_GTP2_DELETE_SESSION_REQUEST_TYPE: ogs_error("[%s] No Delete Session Response", sgwc_ue->imsi_bcd); if (!sgwc_sess_cycle(sess)) { - ogs_warn("[%s] Session has already been removed", + ogs_error("[%s] Session has already been removed", sgwc_ue->imsi_bcd); break; } @@ -125,6 +125,7 @@ void sgwc_s11_handle_create_session_request( uint16_t decoded; ogs_gtp2_f_teid_t *mme_s11_teid = NULL; + ogs_gtp2_f_teid_t *pgw_s5c_teid = NULL; ogs_gtp2_uli_t uli; ogs_gtp2_bearer_qos_t bearer_qos; char apn[OGS_MAX_APN_LEN+1]; @@ -137,8 +138,28 @@ void sgwc_s11_handle_create_session_request( ogs_debug("Create Session Request"); + /************************ + * Check SGWC-UE Context + ************************/ cause_value = OGS_GTP2_CAUSE_REQUEST_ACCEPTED; + if (!sgwc_ue) { + ogs_error("No Context"); + cause_value = OGS_GTP2_CAUSE_CONTEXT_NOT_FOUND; + } + + if (cause_value != OGS_GTP2_CAUSE_REQUEST_ACCEPTED) { + ogs_gtp_send_error_message( + s11_xact, sgwc_ue ? sgwc_ue->mme_s11_teid : 0, + OGS_GTP2_CREATE_SESSION_RESPONSE_TYPE, cause_value); + return; + } + + /***************************************** + * Check Mandatory/Conditional IE Missing + *****************************************/ + ogs_assert(cause_value == OGS_GTP2_CAUSE_REQUEST_ACCEPTED); + if (req->imsi.presence == 0) { ogs_error("No IMSI"); cause_value = OGS_GTP2_CAUSE_CONDITIONAL_IE_MISSING; @@ -168,11 +189,6 @@ void sgwc_s11_handle_create_session_request( cause_value = OGS_GTP2_CAUSE_CONDITIONAL_IE_MISSING; } - if (!sgwc_ue) { - ogs_warn("No Context"); - cause_value = OGS_GTP2_CAUSE_CONTEXT_NOT_FOUND; - } - if (cause_value != OGS_GTP2_CAUSE_REQUEST_ACCEPTED) { ogs_gtp_send_error_message( s11_xact, sgwc_ue ? sgwc_ue->mme_s11_teid : 0, @@ -254,6 +270,11 @@ void sgwc_s11_handle_create_session_request( ogs_assert(mme_s11_teid); sgwc_ue->mme_s11_teid = be32toh(mme_s11_teid->teid); + /* Receive Control Plane(UL) : PGW-S5C */ + pgw_s5c_teid = req->pgw_s5_s8_address_for_control_plane_or_pmip.data; + ogs_assert(pgw_s5c_teid); + sess->pgw_s5c_teid = be32toh(pgw_s5c_teid->teid); + ogs_debug(" MME_S11_TEID[%d] SGW_S11_TEID[%d]", sgwc_ue->mme_s11_teid, sgwc_ue->sgw_s11_teid); @@ -265,9 +286,12 @@ void sgwc_s11_handle_modify_bearer_request( sgwc_ue_t *sgwc_ue, ogs_gtp_xact_t *s11_xact, ogs_pkbuf_t *gtpbuf, ogs_gtp2_message_t *message) { - int rv; + int i = 0; uint16_t decoded; - uint64_t flags = 0; + uint8_t cause_value = 0; + + OGS_LIST(pfcp_xact_list); + ogs_pfcp_xact_t *pfcp_xact = NULL; sgwc_sess_t *sess = NULL; sgwc_bearer_t *bearer = NULL; @@ -278,7 +302,6 @@ void sgwc_s11_handle_modify_bearer_request( ogs_gtp2_modify_bearer_request_t *req = NULL; - ogs_gtp2_cause_t cause; ogs_gtp2_uli_t uli; ogs_gtp2_f_teid_t *enb_s1u_teid = NULL; @@ -289,64 +312,119 @@ void sgwc_s11_handle_modify_bearer_request( ogs_debug("Modify Bearer Request"); - memset(&cause, 0, sizeof(cause)); - cause.value = OGS_GTP2_CAUSE_REQUEST_ACCEPTED; - - if (req->bearer_contexts_to_be_modified.presence == 0) { - ogs_error("No Bearer"); - cause.value = OGS_GTP2_CAUSE_MANDATORY_IE_MISSING; - } - if (req->bearer_contexts_to_be_modified.eps_bearer_id.presence == 0) { - ogs_error("No EPS Bearer ID"); - cause.value = OGS_GTP2_CAUSE_MANDATORY_IE_MISSING; - } - if (req->bearer_contexts_to_be_modified.s1_u_enodeb_f_teid.presence == 0) { - ogs_error("No eNB TEID"); - cause.value = OGS_GTP2_CAUSE_MANDATORY_IE_MISSING; - } + /************************ + * Check SGWC-UE Context + ************************/ + cause_value = OGS_GTP2_CAUSE_REQUEST_ACCEPTED; if (!sgwc_ue) { ogs_error("No Context"); - cause.value = OGS_GTP2_CAUSE_CONTEXT_NOT_FOUND; + cause_value = OGS_GTP2_CAUSE_CONTEXT_NOT_FOUND; } - if (cause.value == OGS_GTP2_CAUSE_REQUEST_ACCEPTED) { - bearer = sgwc_bearer_find_by_ue_ebi(sgwc_ue, - req->bearer_contexts_to_be_modified.eps_bearer_id.u8); - if (!bearer) - ogs_error("Unknown EPS Bearer ID[%d]", - req->bearer_contexts_to_be_modified.eps_bearer_id.u8); - } - - if (!bearer) { - ogs_warn("No Context"); - cause.value = OGS_GTP2_CAUSE_CONTEXT_NOT_FOUND; - } - - if (cause.value != OGS_GTP2_CAUSE_REQUEST_ACCEPTED) { + if (cause_value != OGS_GTP2_CAUSE_REQUEST_ACCEPTED) { ogs_gtp_send_error_message( s11_xact, sgwc_ue ? sgwc_ue->mme_s11_teid : 0, - OGS_GTP2_MODIFY_BEARER_RESPONSE_TYPE, cause.value); + OGS_GTP2_MODIFY_BEARER_RESPONSE_TYPE, cause_value); return; } - ogs_assert(bearer); - sess = bearer->sess; - ogs_assert(sess); + /***************************************** + * Check Mandatory/Conditional IE Missing + *****************************************/ + ogs_assert(cause_value == OGS_GTP2_CAUSE_REQUEST_ACCEPTED); - dl_tunnel = sgwc_dl_tunnel_in_bearer(bearer); - ogs_assert(dl_tunnel); + for (i = 0; i < 8 /* Max number of Bearer Contexts in Message */ ; i++) { + ogs_pfcp_xact_t *current_xact = NULL; - /* Data Plane(DL) : eNB-S1U */ - enb_s1u_teid = req->bearer_contexts_to_be_modified.s1_u_enodeb_f_teid.data; - dl_tunnel->remote_teid = be32toh(enb_s1u_teid->teid); + if (req->bearer_contexts_to_be_modified[i].presence == 0) { + cause_value = OGS_GTP2_CAUSE_MANDATORY_IE_MISSING; + break; + } + if (req->bearer_contexts_to_be_modified[i].eps_bearer_id. + presence == 0) { + cause_value = OGS_GTP2_CAUSE_MANDATORY_IE_MISSING; + break; + } + if (req->bearer_contexts_to_be_modified[i].s1_u_enodeb_f_teid. + presence == 0) { + cause_value = OGS_GTP2_CAUSE_MANDATORY_IE_MISSING; + break; + } - rv = ogs_gtp2_f_teid_to_ip(enb_s1u_teid, &remote_ip); - if (rv != OGS_OK) { + bearer = sgwc_bearer_find_by_ue_ebi(sgwc_ue, + req->bearer_contexts_to_be_modified[i].eps_bearer_id.u8); + if (!bearer) { + ogs_error("Unknown EPS Bearer ID[%d]", + req->bearer_contexts_to_be_modified[i].eps_bearer_id.u8); + cause_value = OGS_GTP2_CAUSE_CONTEXT_NOT_FOUND; + break; + } + + sess = bearer->sess; + ogs_assert(sess); + + ogs_list_for_each_entry(&pfcp_xact_list, pfcp_xact, tmpnode) { + if (sess == pfcp_xact->data) { + current_xact = pfcp_xact; + break; + } + } + + if (!current_xact) { + current_xact = sgwc_pfcp_xact_create(sess, s11_xact, gtpbuf, + OGS_PFCP_MODIFY_DL_ONLY|OGS_PFCP_MODIFY_ACTIVATE); + ogs_assert(current_xact); + + ogs_list_add(&pfcp_xact_list, ¤t_xact->tmpnode); + } + + dl_tunnel = sgwc_dl_tunnel_in_bearer(bearer); + ogs_assert(dl_tunnel); + + /* Data Plane(DL) : eNB-S1U */ + enb_s1u_teid = + req->bearer_contexts_to_be_modified[i].s1_u_enodeb_f_teid.data; + dl_tunnel->remote_teid = be32toh(enb_s1u_teid->teid); + + ogs_assert(OGS_OK == ogs_gtp2_f_teid_to_ip(enb_s1u_teid, &remote_ip)); + + memset(&zero_ip, 0, sizeof(ogs_ip_t)); + + if (memcmp(&dl_tunnel->remote_ip, &zero_ip, sizeof(ogs_ip_t)) != 0 && + memcmp(&dl_tunnel->remote_ip, &remote_ip, sizeof(ogs_ip_t)) != 0) { + + ogs_assert(sess->pfcp_node); + + /* eNB IP is changed during handover */ + if (sess->pfcp_node->up_function_features.empu) { + current_xact->modify_flags |= OGS_PFCP_MODIFY_END_MARKER; + } else { + ogs_error("SGW-U does not support End Marker"); + } + } + + memcpy(&dl_tunnel->remote_ip, &remote_ip, sizeof(ogs_ip_t)); + + far = dl_tunnel->far; + ogs_assert(far); + + far->apply_action = OGS_PFCP_APPLY_ACTION_FORW; + + ogs_assert(OGS_OK == + ogs_pfcp_ip_to_outer_header_creation(&dl_tunnel->remote_ip, + &far->outer_header_creation, &far->outer_header_creation_len)); + far->outer_header_creation.teid = dl_tunnel->remote_teid; + + ogs_list_add(¤t_xact->bearer_to_modify_list, + &bearer->to_modify_node); + } + + if (i == 0) { + ogs_error("No Bearer"); ogs_gtp_send_error_message( s11_xact, sgwc_ue ? sgwc_ue->mme_s11_teid : 0, - OGS_GTP2_MODIFY_BEARER_RESPONSE_TYPE, - OGS_GTP2_CAUSE_MANDATORY_IE_MISSING); + OGS_GTP2_MODIFY_BEARER_RESPONSE_TYPE, cause_value); return; } @@ -369,43 +447,13 @@ void sgwc_s11_handle_modify_bearer_request( sgwc_ue->e_cgi.cell_id); } - flags = (OGS_PFCP_MODIFY_DL_ONLY|OGS_PFCP_MODIFY_ACTIVATE); - - memset(&zero_ip, 0, sizeof(ogs_ip_t)); - - if (memcmp(&dl_tunnel->remote_ip, &zero_ip, sizeof(ogs_ip_t)) != 0 && - memcmp(&dl_tunnel->remote_ip, &remote_ip, sizeof(ogs_ip_t)) != 0) { - - ogs_assert(sess->pfcp_node); - - /* eNB IP is changed during handover */ - if (sess->pfcp_node->up_function_features.empu) { - flags |= OGS_PFCP_MODIFY_END_MARKER; - } else { - ogs_error("SGW-U does not support End Marker"); - } - } - - memcpy(&dl_tunnel->remote_ip, &remote_ip, sizeof(ogs_ip_t)); - - far = dl_tunnel->far; - ogs_assert(far); - - far->apply_action = OGS_PFCP_APPLY_ACTION_FORW; - - ogs_assert(OGS_OK == - ogs_pfcp_ip_to_outer_header_creation(&dl_tunnel->remote_ip, - &far->outer_header_creation, &far->outer_header_creation_len)); - far->outer_header_creation.teid = dl_tunnel->remote_teid; - ogs_debug(" MME_S11_TEID[%d] SGW_S11_TEID[%d]", sgwc_ue->mme_s11_teid, sgwc_ue->sgw_s11_teid); ogs_debug(" ENB_S1U_TEID[%d] SGW_S1U_TEID[%d]", dl_tunnel->remote_teid, dl_tunnel->local_teid); - ogs_assert(OGS_OK == - sgwc_pfcp_send_bearer_modification_request( - bearer, s11_xact, gtpbuf, flags)); + ogs_list_for_each_entry(&pfcp_xact_list, pfcp_xact, tmpnode) + sgwc_pfcp_xact_commit(pfcp_xact); } void sgwc_s11_handle_delete_session_request( @@ -426,33 +474,28 @@ void sgwc_s11_handle_delete_session_request( ogs_debug("Delete Session Request"); + /************************ + * Check SGWC-UE Context + ************************/ cause_value = OGS_GTP2_CAUSE_REQUEST_ACCEPTED; - if (req->linked_eps_bearer_id.presence == 0) { - ogs_error("No EPS Bearer ID"); - cause_value = OGS_GTP2_CAUSE_MANDATORY_IE_MISSING; - } - if (!sgwc_ue) { ogs_error("No Context"); cause_value = OGS_GTP2_CAUSE_CONTEXT_NOT_FOUND; - } + } else { + if (req->linked_eps_bearer_id.presence == 0) { + ogs_error("No EPS Bearer ID"); + cause_value = OGS_GTP2_CAUSE_MANDATORY_IE_MISSING; + } - if (cause_value == OGS_GTP2_CAUSE_REQUEST_ACCEPTED) { - sess = sgwc_sess_find_by_ebi(sgwc_ue, req->linked_eps_bearer_id.u8); - if (!sess) - ogs_error("Unknown EPS Bearer [IMSI:%s, EBI:%d]", - sgwc_ue->imsi_bcd, req->linked_eps_bearer_id.u8); - } - - if (!sess) { - ogs_error("No Context"); - cause_value = OGS_GTP2_CAUSE_CONTEXT_NOT_FOUND; - } - - if (!sess->gnode) { - ogs_error("No GTP Node"); - cause_value = OGS_GTP2_CAUSE_CONTEXT_NOT_FOUND; + if (cause_value == OGS_GTP2_CAUSE_REQUEST_ACCEPTED) { + sess = sgwc_sess_find_by_ebi(sgwc_ue, req->linked_eps_bearer_id.u8); + if (!sess) { + ogs_error("Unknown EPS Bearer [IMSI:%s, EBI:%d]", + sgwc_ue->imsi_bcd, req->linked_eps_bearer_id.u8); + cause_value = OGS_GTP2_CAUSE_CONTEXT_NOT_FOUND; + } + } } if (cause_value != OGS_GTP2_CAUSE_REQUEST_ACCEPTED) { @@ -462,6 +505,9 @@ void sgwc_s11_handle_delete_session_request( return; } + /******************** + * Check ALL Context + ********************/ ogs_assert(sgwc_ue); ogs_assert(sess); ogs_assert(sess->gnode); @@ -491,6 +537,7 @@ void sgwc_s11_handle_create_bearer_response( ogs_pkbuf_t *gtpbuf, ogs_gtp2_message_t *message) { int rv; + ogs_gtp2_cause_t *cause = NULL; uint8_t cause_value; uint16_t decoded; @@ -505,36 +552,18 @@ void sgwc_s11_handle_create_bearer_response( ogs_gtp2_f_teid_t *sgw_s1u_teid = NULL, *enb_s1u_teid = NULL; ogs_gtp2_uli_t uli; - ogs_assert(s11_xact); - s5c_xact = s11_xact->assoc_xact; - ogs_assert(s5c_xact); ogs_assert(message); rsp = &message->create_bearer_response; ogs_assert(rsp); ogs_debug("Create Bearer Response"); - cause_value = OGS_GTP2_CAUSE_REQUEST_ACCEPTED; - - rv = ogs_gtp_xact_commit(s11_xact); - ogs_expect(rv == OGS_OK); - - if (rsp->bearer_contexts.presence == 0) { - ogs_error("No Bearer"); - cause_value = OGS_GTP2_CAUSE_MANDATORY_IE_MISSING; - } - if (rsp->bearer_contexts.eps_bearer_id.presence == 0) { - ogs_error("No EPS Bearer ID"); - cause_value = OGS_GTP2_CAUSE_MANDATORY_IE_MISSING; - } - if (rsp->bearer_contexts.s1_u_enodeb_f_teid.presence == 0) { - ogs_error("No eNB TEID"); - cause_value = OGS_GTP2_CAUSE_MANDATORY_IE_MISSING; - } - if (rsp->bearer_contexts.s4_u_sgsn_f_teid.presence == 0) { - ogs_error("No SGW TEID"); - cause_value = OGS_GTP2_CAUSE_MANDATORY_IE_MISSING; - } + /******************** + * Check Transaction + ********************/ + ogs_assert(s11_xact); + s5c_xact = s11_xact->assoc_xact; + ogs_assert(s5c_xact); if (s11_xact->xid & OGS_GTP_CMD_XACT_ID) /* MME received Bearer Resource Modification Request */ @@ -546,37 +575,59 @@ void sgwc_s11_handle_create_bearer_response( sess = bearer->sess; ogs_assert(sess); + rv = ogs_gtp_xact_commit(s11_xact); + ogs_expect(rv == OGS_OK); + + /************************ + * Check SGWC-UE Context + ************************/ + cause_value = OGS_GTP2_CAUSE_REQUEST_ACCEPTED; + if (!sgwc_ue) { - ogs_warn("No Context in TEID"); - - sgwc_ue = sess->sgwc_ue; - ogs_assert(sgwc_ue); - + ogs_error("No Context in TEID"); cause_value = OGS_GTP2_CAUSE_CONTEXT_NOT_FOUND; } - if (rsp->cause.presence) { - ogs_gtp2_cause_t *cause = rsp->cause.data; - ogs_assert(cause); + if (cause_value != OGS_GTP2_CAUSE_REQUEST_ACCEPTED) { + ogs_assert(OGS_OK == + sgwc_pfcp_send_bearer_modification_request( + bearer, NULL, NULL, + OGS_PFCP_MODIFY_UL_ONLY|OGS_PFCP_MODIFY_REMOVE)); + ogs_gtp_send_error_message(s5c_xact, sess ? sess->pgw_s5c_teid : 0, + OGS_GTP2_CREATE_BEARER_RESPONSE_TYPE, cause_value); + return; + } - cause_value = cause->value; - if (cause_value == OGS_GTP2_CAUSE_REQUEST_ACCEPTED) { - if (rsp->bearer_contexts.cause.presence) { - cause = rsp->bearer_contexts.cause.data; - ogs_assert(cause); + /***************************************** + * Check Mandatory/Conditional IE Missing + *****************************************/ + ogs_assert(cause_value == OGS_GTP2_CAUSE_REQUEST_ACCEPTED); - cause_value = cause->value; - } else { - ogs_error("No Cause"); - cause_value = OGS_GTP2_CAUSE_MANDATORY_IE_MISSING; - } - } else { - ogs_warn("GTP Failed [CAUSE:%d]", cause_value); - } - } else { + if (rsp->bearer_contexts.presence == 0) { + ogs_error("No Bearer"); + cause_value = OGS_GTP2_CAUSE_MANDATORY_IE_MISSING; + } + if (rsp->bearer_contexts.eps_bearer_id.presence == 0) { + ogs_error("No EPS Bearer ID"); + cause_value = OGS_GTP2_CAUSE_MANDATORY_IE_MISSING; + } + if (rsp->bearer_contexts.s1_u_enodeb_f_teid.presence == 0) { + ogs_error("No eNB TEID"); + cause_value = OGS_GTP2_CAUSE_CONDITIONAL_IE_MISSING; + } + if (rsp->bearer_contexts.s4_u_sgsn_f_teid.presence == 0) { + ogs_error("No SGW TEID"); + cause_value = OGS_GTP2_CAUSE_CONDITIONAL_IE_MISSING; + } + + if (rsp->cause.presence == 0) { ogs_error("No Cause"); cause_value = OGS_GTP2_CAUSE_MANDATORY_IE_MISSING; } + if (rsp->bearer_contexts.cause.presence == 0) { + ogs_error("No Bearer Cause"); + cause_value = OGS_GTP2_CAUSE_MANDATORY_IE_MISSING; + } if (cause_value != OGS_GTP2_CAUSE_REQUEST_ACCEPTED) { ogs_assert(OGS_OK == @@ -588,6 +639,32 @@ void sgwc_s11_handle_create_bearer_response( return; } + /******************** + * Check Cause Value + ********************/ + ogs_assert(cause_value == OGS_GTP2_CAUSE_REQUEST_ACCEPTED); + + cause = rsp->bearer_contexts.cause.data; + ogs_assert(cause); + cause_value = cause->value; + if (cause_value != OGS_GTP2_CAUSE_REQUEST_ACCEPTED) { + ogs_error("GTP Failed [CAUSE:%d]", cause_value); + ogs_assert(OGS_OK == + sgwc_pfcp_send_bearer_modification_request( + bearer, NULL, NULL, + OGS_PFCP_MODIFY_UL_ONLY|OGS_PFCP_MODIFY_REMOVE)); + ogs_gtp_send_error_message(s5c_xact, sess ? sess->pgw_s5c_teid : 0, + OGS_GTP2_CREATE_BEARER_RESPONSE_TYPE, cause_value); + return; + } + + /******************** + * Check ALL Context + ********************/ + ogs_assert(sgwc_ue); + ogs_assert(sess); + ogs_assert(bearer); + /* Correlate with SGW-S1U-TEID */ sgw_s1u_teid = rsp->bearer_contexts.s4_u_sgsn_f_teid.data; ogs_assert(sgw_s1u_teid); @@ -608,13 +685,8 @@ void sgwc_s11_handle_create_bearer_response( ogs_debug(" ENB_S1U_TEID[%d] SGW_S1U_TEID[%d]", dl_tunnel->remote_teid, dl_tunnel->local_teid); - rv = ogs_gtp2_f_teid_to_ip(enb_s1u_teid, &dl_tunnel->remote_ip); - if (rv != OGS_OK) { - ogs_gtp_send_error_message(s5c_xact, sess ? sess->pgw_s5c_teid : 0, - OGS_GTP2_CREATE_BEARER_RESPONSE_TYPE, - OGS_GTP2_CAUSE_MANDATORY_IE_MISSING); - return; - } + ogs_assert(OGS_OK == + ogs_gtp2_f_teid_to_ip(enb_s1u_teid, &dl_tunnel->remote_ip)); far = dl_tunnel->far; ogs_assert(far); @@ -656,6 +728,7 @@ void sgwc_s11_handle_update_bearer_response( ogs_pkbuf_t *gtpbuf, ogs_gtp2_message_t *message) { int rv; + ogs_gtp2_cause_t *cause = NULL; uint8_t cause_value; ogs_pkbuf_t *pkbuf = NULL; ogs_gtp_xact_t *s5c_xact = NULL; @@ -663,28 +736,18 @@ void sgwc_s11_handle_update_bearer_response( sgwc_bearer_t *bearer = NULL; ogs_gtp2_update_bearer_response_t *rsp = NULL; - ogs_assert(s11_xact); - s5c_xact = s11_xact->assoc_xact; - ogs_assert(s5c_xact); ogs_assert(message); rsp = &message->update_bearer_response; ogs_assert(rsp); ogs_debug("Update Bearer Response"); - cause_value = OGS_GTP2_CAUSE_REQUEST_ACCEPTED; - - rv = ogs_gtp_xact_commit(s11_xact); - ogs_expect(rv == OGS_OK); - - if (rsp->bearer_contexts.presence == 0) { - ogs_error("No Bearer"); - cause_value = OGS_GTP2_CAUSE_MANDATORY_IE_MISSING; - } - if (rsp->bearer_contexts.eps_bearer_id.presence == 0) { - ogs_error("No EPS Bearer ID"); - cause_value = OGS_GTP2_CAUSE_MANDATORY_IE_MISSING; - } + /******************** + * Check Transaction + ********************/ + ogs_assert(s11_xact); + s5c_xact = s11_xact->assoc_xact; + ogs_assert(s5c_xact); if (s11_xact->xid & OGS_GTP_CMD_XACT_ID) /* MME received Bearer Resource Modification Request */ @@ -696,37 +759,47 @@ void sgwc_s11_handle_update_bearer_response( sess = bearer->sess; ogs_assert(sess); + rv = ogs_gtp_xact_commit(s11_xact); + ogs_expect(rv == OGS_OK); + + /************************ + * Check SGWC-UE Context + ************************/ + cause_value = OGS_GTP2_CAUSE_REQUEST_ACCEPTED; + if (!sgwc_ue) { - ogs_warn("No Context in TEID"); - - sgwc_ue = sess->sgwc_ue; - ogs_assert(sgwc_ue); - + ogs_error("No Context in TEID"); cause_value = OGS_GTP2_CAUSE_CONTEXT_NOT_FOUND; } - if (rsp->cause.presence) { - ogs_gtp2_cause_t *cause = rsp->cause.data; - ogs_assert(cause); + if (cause_value != OGS_GTP2_CAUSE_REQUEST_ACCEPTED) { + ogs_gtp_send_error_message(s5c_xact, sess ? sess->pgw_s5c_teid : 0, + OGS_GTP2_UPDATE_BEARER_RESPONSE_TYPE, cause_value); + return; + } - cause_value = cause->value; - if (cause_value == OGS_GTP2_CAUSE_REQUEST_ACCEPTED) { - if (rsp->bearer_contexts.cause.presence) { - cause = rsp->bearer_contexts.cause.data; - ogs_assert(cause); + /***************************************** + * Check Mandatory/Conditional IE Missing + *****************************************/ + ogs_assert(cause_value == OGS_GTP2_CAUSE_REQUEST_ACCEPTED); - cause_value = cause->value; - } else { - ogs_error("No Cause"); - cause_value = OGS_GTP2_CAUSE_MANDATORY_IE_MISSING; - } - } else { - ogs_warn("GTP Failed [CAUSE:%d]", cause_value); - } - } else { + if (rsp->bearer_contexts.presence == 0) { + ogs_error("No Bearer"); + cause_value = OGS_GTP2_CAUSE_MANDATORY_IE_MISSING; + } + if (rsp->bearer_contexts.eps_bearer_id.presence == 0) { + ogs_error("No EPS Bearer ID"); + cause_value = OGS_GTP2_CAUSE_MANDATORY_IE_MISSING; + } + + if (rsp->cause.presence == 0) { ogs_error("No Cause"); cause_value = OGS_GTP2_CAUSE_MANDATORY_IE_MISSING; } + if (rsp->bearer_contexts.cause.presence == 0) { + ogs_error("No Bearer Cause"); + cause_value = OGS_GTP2_CAUSE_MANDATORY_IE_MISSING; + } if (cause_value != OGS_GTP2_CAUSE_REQUEST_ACCEPTED) { ogs_gtp_send_error_message(s5c_xact, sess ? sess->pgw_s5c_teid : 0, @@ -734,6 +807,37 @@ void sgwc_s11_handle_update_bearer_response( return; } + /******************** + * Check Cause Value + ********************/ + ogs_assert(cause_value == OGS_GTP2_CAUSE_REQUEST_ACCEPTED); + + cause = rsp->bearer_contexts.cause.data; + ogs_assert(cause); + cause_value = cause->value; + if (cause_value != OGS_GTP2_CAUSE_REQUEST_ACCEPTED) { + ogs_error("GTP Failed [Bearer-CAUSE:%d]", cause_value); + ogs_gtp_send_error_message(s5c_xact, sess ? sess->pgw_s5c_teid : 0, + OGS_GTP2_UPDATE_BEARER_RESPONSE_TYPE, cause_value); + return; + } + + cause = rsp->cause.data; + ogs_assert(cause); + cause_value = cause->value; + if (cause_value != OGS_GTP2_CAUSE_REQUEST_ACCEPTED) { + ogs_error("GTP Failed [CAUSE:%d]", cause_value); + ogs_gtp_send_error_message(s5c_xact, sess ? sess->pgw_s5c_teid : 0, + OGS_GTP2_UPDATE_BEARER_RESPONSE_TYPE, cause_value); + return; + } + + /******************** + * Check ALL Context + ********************/ + ogs_assert(sgwc_ue); + ogs_assert(sess); + ogs_debug(" MME_S11_TEID[%d] SGW_S11_TEID[%d]", sgwc_ue->mme_s11_teid, sgwc_ue->sgw_s11_teid); ogs_debug(" SGW_S5C_TEID[0x%x] PGW_S5C_TEID[0x%x]", @@ -764,16 +868,18 @@ void sgwc_s11_handle_delete_bearer_response( sgwc_bearer_t *bearer = NULL; ogs_gtp2_delete_bearer_response_t *rsp = NULL; - ogs_assert(s11_xact); - s5c_xact = s11_xact->assoc_xact; - ogs_assert(s5c_xact); ogs_assert(message); rsp = &message->delete_bearer_response; ogs_assert(rsp); ogs_debug("Delete Bearer Response"); - cause_value = OGS_GTP2_CAUSE_REQUEST_ACCEPTED; + /******************** + * Check Transaction + ********************/ + ogs_assert(s11_xact); + s5c_xact = s11_xact->assoc_xact; + ogs_assert(s5c_xact); if (s11_xact->xid & OGS_GTP_CMD_XACT_ID) /* MME received Bearer Resource Modification Request */ @@ -781,19 +887,20 @@ void sgwc_s11_handle_delete_bearer_response( else bearer = s11_xact->data; - rv = ogs_gtp_xact_commit(s11_xact); - ogs_expect(rv == OGS_OK); - ogs_assert(bearer); sess = bearer->sess; ogs_assert(sess); + rv = ogs_gtp_xact_commit(s11_xact); + ogs_expect(rv == OGS_OK); + + /************************ + * Check SGWC-UE Context + ************************/ + cause_value = OGS_GTP2_CAUSE_REQUEST_ACCEPTED; + if (!sgwc_ue) { - ogs_warn("No Context in TEID"); - - sgwc_ue = sess->sgwc_ue; - ogs_assert(sgwc_ue); - + ogs_error("No Context in TEID"); cause_value = OGS_GTP2_CAUSE_CONTEXT_NOT_FOUND; } @@ -820,7 +927,6 @@ void sgwc_s11_handle_delete_bearer_response( } } else { ogs_error("No Cause"); - cause_value = OGS_GTP2_CAUSE_MANDATORY_IE_MISSING; } ogs_assert(OGS_OK == @@ -840,11 +946,9 @@ void sgwc_s11_handle_delete_bearer_response( */ if (rsp->bearer_contexts.presence == 0) { ogs_error("No Bearer"); - cause_value = OGS_GTP2_CAUSE_MANDATORY_IE_MISSING; } if (rsp->bearer_contexts.eps_bearer_id.presence == 0) { ogs_error("No EPS Bearer ID"); - cause_value = OGS_GTP2_CAUSE_MANDATORY_IE_MISSING; } if (rsp->cause.presence) { @@ -857,21 +961,24 @@ void sgwc_s11_handle_delete_bearer_response( cause = rsp->bearer_contexts.cause.data; ogs_assert(cause); - cause_value = cause->value; + if (cause_value == OGS_GTP2_CAUSE_REQUEST_ACCEPTED) { + } else { + ogs_error("GTP Failed [CAUSE:%d]", cause_value); + } } else { ogs_error("No Cause"); - cause_value = OGS_GTP2_CAUSE_MANDATORY_IE_MISSING; } } else { - ogs_warn("GTP Failed [CAUSE:%d]", cause_value); + ogs_error("GTP Failed [CAUSE:%d]", cause_value); } } else { ogs_error("No Cause"); - cause_value = OGS_GTP2_CAUSE_MANDATORY_IE_MISSING; } - ogs_debug(" MME_S11_TEID[%d] SGW_S11_TEID[%d]", - sgwc_ue->mme_s11_teid, sgwc_ue->sgw_s11_teid); + if (sgwc_ue) { + ogs_debug(" MME_S11_TEID[%d] SGW_S11_TEID[%d]", + sgwc_ue->mme_s11_teid, sgwc_ue->sgw_s11_teid); + } ogs_debug(" SGW_S5C_TEID[0x%x] PGW_S5C_TEID[0x%x]", sess->sgw_s5c_teid, sess->pgw_s5c_teid); @@ -886,9 +993,9 @@ void sgwc_s11_handle_release_access_bearers_request( ogs_pkbuf_t *gtpbuf, ogs_gtp2_message_t *message) { sgwc_sess_t *sess = NULL; + uint8_t cause_value; ogs_gtp2_release_access_bearers_request_t *req = NULL; - ogs_gtp2_cause_t cause; ogs_assert(s11_xact); ogs_assert(message); @@ -897,21 +1004,26 @@ void sgwc_s11_handle_release_access_bearers_request( ogs_debug("Release Access Bearers Request"); - memset(&cause, 0, sizeof(cause)); - cause.value = OGS_GTP2_CAUSE_REQUEST_ACCEPTED; + /************************ + * Check SGWC-UE Context + ************************/ + cause_value = OGS_GTP2_CAUSE_REQUEST_ACCEPTED; if (!sgwc_ue) { - ogs_warn("No Context"); - cause.value = OGS_GTP2_CAUSE_CONTEXT_NOT_FOUND; + ogs_error("No Context"); + cause_value = OGS_GTP2_CAUSE_CONTEXT_NOT_FOUND; } - if (cause.value != OGS_GTP2_CAUSE_REQUEST_ACCEPTED) { + if (cause_value != OGS_GTP2_CAUSE_REQUEST_ACCEPTED) { ogs_gtp_send_error_message( s11_xact, sgwc_ue ? sgwc_ue->mme_s11_teid : 0, - OGS_GTP2_RELEASE_ACCESS_BEARERS_RESPONSE_TYPE, cause.value); + OGS_GTP2_RELEASE_ACCESS_BEARERS_RESPONSE_TYPE, cause_value); return; } + /******************** + * Check ALL Context + ********************/ ogs_assert(sgwc_ue); ogs_debug(" MME_S11_TEID[%d] SGW_S11_TEID[%d]", @@ -919,7 +1031,6 @@ void sgwc_s11_handle_release_access_bearers_request( ogs_list_for_each(&sgwc_ue->sess_list, sess) { - sess->state.release_access_bearers = false; ogs_assert(OGS_OK == sgwc_pfcp_send_sess_modification_request( sess, s11_xact, gtpbuf, @@ -939,23 +1050,25 @@ void sgwc_s11_handle_downlink_data_notification_ack( ogs_gtp2_downlink_data_notification_acknowledge_t *ack = NULL; - ogs_assert(s11_xact); ogs_assert(message); ack = &message->downlink_data_notification_acknowledge; ogs_assert(ack); + /******************** + * Check Transaction + ********************/ + ogs_assert(s11_xact); bearer = s11_xact->data; ogs_assert(bearer); sess = bearer->sess; ogs_assert(sess); - sgwc_ue = sess->sgwc_ue; - ogs_assert(sgwc_ue); - - cause_value = OGS_GTP2_CAUSE_REQUEST_ACCEPTED; rv = ogs_gtp_xact_commit(s11_xact); ogs_expect(rv == OGS_OK); + /************************ + * Check SGWC-UE Context + ************************/ if (ack->cause.presence) { ogs_gtp2_cause_t *cause = ack->cause.data; ogs_assert(cause); @@ -969,8 +1082,10 @@ void sgwc_s11_handle_downlink_data_notification_ack( } ogs_debug("Downlink Data Notification Acknowledge"); - ogs_debug(" MME_S11_TEID[%d] SGW_S11_TEID[%d]", - sgwc_ue->mme_s11_teid, sgwc_ue->sgw_s11_teid); + if (sgwc_ue) { + ogs_debug(" MME_S11_TEID[%d] SGW_S11_TEID[%d]", + sgwc_ue->mme_s11_teid, sgwc_ue->sgw_s11_teid); + } } void sgwc_s11_handle_create_indirect_data_forwarding_tunnel_request( @@ -985,8 +1100,8 @@ void sgwc_s11_handle_create_indirect_data_forwarding_tunnel_request( ogs_pfcp_far_t *far = NULL; ogs_gtp2_create_indirect_data_forwarding_tunnel_request_t *req = NULL; - ogs_gtp2_cause_t cause; ogs_gtp2_f_teid_t *req_teid = NULL; + uint8_t cause_value = 0; ogs_assert(s11_xact); ogs_assert(message); @@ -995,22 +1110,29 @@ void sgwc_s11_handle_create_indirect_data_forwarding_tunnel_request( ogs_debug("Create Indirect Data Forwarding Tunnel Request"); - memset(&cause, 0, sizeof(cause)); - cause.value = OGS_GTP2_CAUSE_REQUEST_ACCEPTED; + /************************ + * Check SGWC-UE Context + ************************/ + cause_value = OGS_GTP2_CAUSE_REQUEST_ACCEPTED; if (!sgwc_ue) { - ogs_warn("No Context"); - cause.value = OGS_GTP2_CAUSE_CONTEXT_NOT_FOUND; + ogs_error("No Context"); + cause_value = OGS_GTP2_CAUSE_CONTEXT_NOT_FOUND; } - if (cause.value != OGS_GTP2_CAUSE_REQUEST_ACCEPTED) { + if (cause_value != OGS_GTP2_CAUSE_REQUEST_ACCEPTED) { ogs_gtp_send_error_message( s11_xact, sgwc_ue ? sgwc_ue->mme_s11_teid : 0, OGS_GTP2_CREATE_INDIRECT_DATA_FORWARDING_TUNNEL_RESPONSE_TYPE, - cause.value); + cause_value); return; } + /******************** + * Check ALL Context + ********************/ + ogs_assert(sgwc_ue); + ogs_debug(" MME_S11_TEID[%d] SGW_S11_TEID[%d]", sgwc_ue->mme_s11_teid, sgwc_ue->sgw_s11_teid); @@ -1101,7 +1223,6 @@ void sgwc_s11_handle_create_indirect_data_forwarding_tunnel_request( ogs_list_for_each(&sgwc_ue->sess_list, sess) { - sess->state.create_indirect_tunnel = false; ogs_assert(OGS_OK == sgwc_pfcp_send_sess_modification_request( sess, s11_xact, gtpbuf, @@ -1114,29 +1235,33 @@ void sgwc_s11_handle_delete_indirect_data_forwarding_tunnel_request( ogs_pkbuf_t *gtpbuf, ogs_gtp2_message_t *recv_message) { sgwc_sess_t *sess = NULL; - - ogs_gtp2_cause_t cause; + uint8_t cause_value = 0; ogs_assert(s11_xact); ogs_debug("Delete Indirect Data Forwarding Tunnel Request"); - memset(&cause, 0, sizeof(cause)); - cause.value = OGS_GTP2_CAUSE_REQUEST_ACCEPTED; + /************************ + * Check SGWC-UE Context + ************************/ + cause_value = OGS_GTP2_CAUSE_REQUEST_ACCEPTED; if (!sgwc_ue) { - ogs_warn("No Context"); - cause.value = OGS_GTP2_CAUSE_CONTEXT_NOT_FOUND; + ogs_error("No Context"); + cause_value = OGS_GTP2_CAUSE_CONTEXT_NOT_FOUND; } - if (cause.value != OGS_GTP2_CAUSE_REQUEST_ACCEPTED) { + if (cause_value != OGS_GTP2_CAUSE_REQUEST_ACCEPTED) { ogs_gtp_send_error_message( s11_xact, sgwc_ue ? sgwc_ue->mme_s11_teid : 0, OGS_GTP2_DELETE_INDIRECT_DATA_FORWARDING_TUNNEL_RESPONSE_TYPE, - cause.value); + cause_value); return; } + /******************** + * Check ALL Context + ********************/ ogs_assert(sgwc_ue); ogs_debug(" MME_S11_TEID[%d] SGW_S11_TEID[%d]", @@ -1144,7 +1269,6 @@ void sgwc_s11_handle_delete_indirect_data_forwarding_tunnel_request( ogs_list_for_each(&sgwc_ue->sess_list, sess) { - sess->state.delete_indirect_tunnel = false; ogs_assert(OGS_OK == sgwc_pfcp_send_sess_modification_request( sess, s11_xact, gtpbuf, @@ -1168,45 +1292,38 @@ void sgwc_s11_handle_bearer_resource_command( ogs_assert(s11_xact); ogs_assert(message); + cmd = &message->bearer_resource_command; + ogs_assert(cmd); ogs_debug("Bearer Resource Command"); - cmd = &message->bearer_resource_command; + /************************ + * Check SGWC-UE Context + ************************/ cause_value = OGS_GTP2_CAUSE_REQUEST_ACCEPTED; - if (cmd->procedure_transaction_id.presence == 0) { - ogs_error("No PTI"); - cause_value = OGS_GTP2_CAUSE_MANDATORY_IE_MISSING; - } - if (cmd->traffic_aggregate_description.presence == 0) { - ogs_error("No Traffic aggregate description(TAD)"); - cause_value = OGS_GTP2_CAUSE_MANDATORY_IE_MISSING; - } - if (cmd->linked_eps_bearer_id.presence == 0) { - ogs_error("No Linked EPS Bearer ID"); - cause_value = OGS_GTP2_CAUSE_MANDATORY_IE_MISSING; - } - if (!sgwc_ue) { - ogs_warn("No Context"); + ogs_error("No Context"); cause_value = OGS_GTP2_CAUSE_CONTEXT_NOT_FOUND; - } + } else { + if (cmd->linked_eps_bearer_id.presence == 0) { + ogs_error("No Linked EPS Bearer ID"); + cause_value = OGS_GTP2_CAUSE_MANDATORY_IE_MISSING; + } - if (cause_value == OGS_GTP2_CAUSE_REQUEST_ACCEPTED) { - uint8_t ebi = cmd->linked_eps_bearer_id.u8; + if (cause_value == OGS_GTP2_CAUSE_REQUEST_ACCEPTED) { + uint8_t ebi = cmd->linked_eps_bearer_id.u8; - if (cmd->eps_bearer_id.presence) - ebi = cmd->eps_bearer_id.u8; + if (cmd->eps_bearer_id.presence) + ebi = cmd->eps_bearer_id.u8; - bearer = sgwc_bearer_find_by_ue_ebi(sgwc_ue, ebi); - if (!bearer) - ogs_error("No Context for Linked EPS Bearer ID[%d]", - cmd->linked_eps_bearer_id.u8); - } - - if (!bearer) { - ogs_error("No context"); - cause_value = OGS_GTP2_CAUSE_CONTEXT_NOT_FOUND; + bearer = sgwc_bearer_find_by_ue_ebi(sgwc_ue, ebi); + if (!bearer) { + ogs_error("No Context for Linked EPS Bearer ID[%d:%d]", + cmd->linked_eps_bearer_id.u8, ebi); + cause_value = OGS_GTP2_CAUSE_CONTEXT_NOT_FOUND; + } + } } if (cause_value != OGS_GTP2_CAUSE_REQUEST_ACCEPTED) { @@ -1216,10 +1333,36 @@ void sgwc_s11_handle_bearer_resource_command( return; } + /***************************************** + * Check Mandatory/Conditional IE Missing + *****************************************/ + ogs_assert(cause_value == OGS_GTP2_CAUSE_REQUEST_ACCEPTED); + + if (cmd->procedure_transaction_id.presence == 0) { + ogs_error("No PTI"); + cause_value = OGS_GTP2_CAUSE_MANDATORY_IE_MISSING; + } + if (cmd->traffic_aggregate_description.presence == 0) { + ogs_error("No Traffic aggregate description(TAD)"); + cause_value = OGS_GTP2_CAUSE_MANDATORY_IE_MISSING; + } + + if (cause_value != OGS_GTP2_CAUSE_REQUEST_ACCEPTED) { + ogs_gtp_send_error_message( + s11_xact, sgwc_ue ? sgwc_ue->mme_s11_teid : 0, + OGS_GTP2_BEARER_RESOURCE_FAILURE_INDICATION_TYPE, cause_value); + return; + } + + /******************** + * Check ALL Context + ********************/ ogs_assert(bearer); sess = bearer->sess; ogs_assert(sess); ogs_assert(sess->gnode); + ogs_assert(sgwc_ue); + ogs_debug(" MME_S11_TEID[%d] SGW_S11_TEID[%d]", sgwc_ue->mme_s11_teid, sgwc_ue->sgw_s11_teid); ogs_debug(" SGW_S5C_TEID[0x%x] PGW_S5C_TEID[0x%x]", diff --git a/src/sgwc/s5c-handler.c b/src/sgwc/s5c-handler.c index 570d746dc..9e7e12131 100644 --- a/src/sgwc/s5c-handler.c +++ b/src/sgwc/s5c-handler.c @@ -45,7 +45,8 @@ static void bearer_timeout(ogs_gtp_xact_t *xact, void *data) case OGS_GTP2_DELETE_BEARER_REQUEST_TYPE: ogs_error("[%s] No Delete Bearer Response", sgwc_ue->imsi_bcd); if (!sgwc_bearer_cycle(bearer)) { - ogs_warn("[%s] Bearer has already been removed", sgwc_ue->imsi_bcd); + ogs_error("[%s] Bearer has already been removed", + sgwc_ue->imsi_bcd); break; } ogs_assert(OGS_OK == @@ -63,9 +64,8 @@ void sgwc_s5c_handle_create_session_response( ogs_pkbuf_t *gtpbuf, ogs_gtp2_message_t *message) { int rv; - ogs_gtp2_cause_t *cause = NULL; - ogs_gtp2_cause_t *bearer_cause = NULL; uint8_t cause_value; + ogs_gtp2_cause_t *cause = NULL; sgwc_ue_t *sgwc_ue = NULL; sgwc_bearer_t *bearer = NULL; @@ -78,9 +78,6 @@ void sgwc_s5c_handle_create_session_response( ogs_gtp2_create_session_response_t *rsp = NULL; ogs_gtp_xact_t *s11_xact = NULL; - ogs_assert(s5c_xact); - s11_xact = s5c_xact->assoc_xact; - ogs_assert(s11_xact); ogs_assert(gtpbuf); ogs_assert(message); rsp = &message->create_session_response; @@ -88,25 +85,38 @@ void sgwc_s5c_handle_create_session_response( ogs_debug("Create Session Response"); - /*************************** + /******************** + * Check Transaction + ********************/ + ogs_assert(s5c_xact); + s11_xact = s5c_xact->assoc_xact; + ogs_assert(s11_xact); + + rv = ogs_gtp_xact_commit(s5c_xact); + ogs_expect(rv == OGS_OK); + + /************************ * Check Session Context - ***************************/ + ************************/ cause_value = OGS_GTP2_CAUSE_REQUEST_ACCEPTED; if (!sess) { - ogs_warn("No Context in TEID"); - sess = s5c_xact->data; - ogs_assert(sess); - + ogs_error("No Context in TEID"); cause_value = OGS_GTP2_CAUSE_CONTEXT_NOT_FOUND; } else { sgwc_ue = sess->sgwc_ue; ogs_assert(sgwc_ue); + if (rsp->bearer_contexts_created.presence == 0) { + ogs_error("No Bearer"); + cause_value = OGS_GTP2_CAUSE_MANDATORY_IE_MISSING; + } if (rsp->bearer_contexts_created.eps_bearer_id.presence == 0) { ogs_error("No EPS Bearer ID"); cause_value = OGS_GTP2_CAUSE_MANDATORY_IE_MISSING; - } else { + } + + if (cause_value == OGS_GTP2_CAUSE_REQUEST_ACCEPTED) { bearer = sgwc_bearer_find_by_sess_ebi(sess, rsp->bearer_contexts_created.eps_bearer_id.u8); if (!bearer) { @@ -117,9 +127,6 @@ void sgwc_s5c_handle_create_session_response( } } - rv = ogs_gtp_xact_commit(s5c_xact); - ogs_expect(rv == OGS_OK); - if (cause_value != OGS_GTP2_CAUSE_REQUEST_ACCEPTED) { ogs_gtp_send_error_message( s11_xact, sgwc_ue ? sgwc_ue->mme_s11_teid : 0, @@ -127,24 +134,11 @@ void sgwc_s5c_handle_create_session_response( return; } - /*************************** - * Check Manatory IE Missing - ***************************/ + /***************************************** + * Check Mandatory/Conditional IE Missing + *****************************************/ ogs_assert(cause_value == OGS_GTP2_CAUSE_REQUEST_ACCEPTED); - if (rsp->bearer_contexts_created.cause.presence == 0) { - ogs_error("No EPS Bearer Cause"); - cause_value = OGS_GTP2_CAUSE_MANDATORY_IE_MISSING; - } - if (rsp->bearer_contexts_created.presence == 0) { - ogs_error("No Bearer"); - cause_value = OGS_GTP2_CAUSE_MANDATORY_IE_MISSING; - } - if (rsp->bearer_contexts_created.eps_bearer_id.presence == 0) { - ogs_error("No EPS Bearer ID"); - ogs_assert_if_reached(); - } - if (rsp->pgw_s5_s8__s2a_s2b_f_teid_for_pmip_based_interface_or_for_gtp_based_control_plane_interface.presence == 0) { ogs_error("No GTP TEID"); cause_value = OGS_GTP2_CAUSE_CONDITIONAL_IE_MISSING; @@ -153,31 +147,15 @@ void sgwc_s5c_handle_create_session_response( ogs_error("No GTP TEID"); cause_value = OGS_GTP2_CAUSE_CONDITIONAL_IE_MISSING; } - - if (rsp->cause.presence == 0) { - ogs_error("No Cause"); - cause_value = OGS_GTP2_CAUSE_MANDATORY_IE_MISSING; - } - - if (rsp->bearer_contexts_created.cause.presence == 0) { - ogs_error("No Bearer Cause"); - cause_value = OGS_GTP2_CAUSE_MANDATORY_IE_MISSING; - } - if (rsp->pdn_address_allocation.presence) { ogs_paa_t paa; memcpy(&paa, rsp->pdn_address_allocation.data, ogs_min(sizeof(paa), rsp->pdn_address_allocation.len)); - if (paa.session_type == OGS_PDU_SESSION_TYPE_IPV4) { - /* Nothing */ - } else if (paa.session_type == OGS_PDU_SESSION_TYPE_IPV6) { - /* Nothing */ - } else if (paa.session_type == OGS_PDU_SESSION_TYPE_IPV4V6) { - /* Nothing */ - } else { + + if (!OGS_PDU_SESSION_TYPE_IS_VALID(paa.session_type)) { ogs_error("Unknown PDN Type %u", paa.session_type); - cause_value = OGS_GTP2_CAUSE_CONDITIONAL_IE_MISSING; + cause_value = OGS_GTP2_CAUSE_MANDATORY_IE_INCORRECT; } } else { @@ -185,6 +163,15 @@ void sgwc_s5c_handle_create_session_response( cause_value = OGS_GTP2_CAUSE_CONDITIONAL_IE_MISSING; } + if (rsp->cause.presence == 0) { + ogs_error("No Cause"); + cause_value = OGS_GTP2_CAUSE_MANDATORY_IE_MISSING; + } + if (rsp->bearer_contexts_created.cause.presence == 0) { + ogs_error("No Bearer Cause"); + cause_value = OGS_GTP2_CAUSE_MANDATORY_IE_MISSING; + } + if (cause_value != OGS_GTP2_CAUSE_REQUEST_ACCEPTED) { ogs_gtp_send_error_message( s11_xact, sgwc_ue ? sgwc_ue->mme_s11_teid : 0, @@ -192,14 +179,14 @@ void sgwc_s5c_handle_create_session_response( return; } - /*************************** + /******************** * Check Cause Value - ***************************/ + ********************/ ogs_assert(cause_value == OGS_GTP2_CAUSE_REQUEST_ACCEPTED); - bearer_cause = rsp->bearer_contexts_created.cause.data; - ogs_assert(bearer_cause); - cause_value = bearer_cause->value; + cause = rsp->bearer_contexts_created.cause.data; + ogs_assert(cause); + cause_value = cause->value; if (cause_value != OGS_GTP2_CAUSE_REQUEST_ACCEPTED) { ogs_error("GTP Failed [Bearer-CAUSE:%d]", cause_value); ogs_gtp_send_error_message( @@ -224,6 +211,11 @@ void sgwc_s5c_handle_create_session_response( return; } + /******************** + * Check ALL Context + ********************/ + ogs_assert(sgwc_ue); + ogs_assert(sess); ogs_assert(bearer); ul_tunnel = sgwc_ul_tunnel_in_bearer(bearer); ogs_assert(ul_tunnel); @@ -275,6 +267,7 @@ void sgwc_s5c_handle_delete_session_response( ogs_pkbuf_t *gtpbuf, ogs_gtp2_message_t *message) { int rv; + ogs_gtp2_cause_t *cause = NULL; uint8_t cause_value; sgwc_ue_t *sgwc_ue = NULL; @@ -282,43 +275,81 @@ void sgwc_s5c_handle_delete_session_response( ogs_gtp_xact_t *s11_xact = NULL; ogs_gtp2_delete_session_response_t *rsp = NULL; - ogs_assert(s5c_xact); - s11_xact = s5c_xact->assoc_xact; - ogs_assert(s11_xact); ogs_assert(message); rsp = &message->delete_session_response; ogs_assert(rsp); ogs_debug("Delete Session Response"); - cause_value = OGS_GTP2_CAUSE_REQUEST_ACCEPTED; - - if (!sess) { - ogs_warn("No Context in TEID"); - sess = s5c_xact->data; - ogs_assert(sess); - } + /******************** + * Check Transaction + ********************/ + ogs_assert(s5c_xact); + s11_xact = s5c_xact->assoc_xact; + ogs_assert(s11_xact); rv = ogs_gtp_xact_commit(s5c_xact); ogs_expect(rv == OGS_OK); - sgwc_ue = sess->sgwc_ue; - ogs_assert(sgwc_ue); + /************************ + * Check Session Context + ************************/ + cause_value = OGS_GTP2_CAUSE_REQUEST_ACCEPTED; - if (rsp->cause.presence) { - ogs_gtp2_cause_t *cause = rsp->cause.data; - ogs_assert(cause); - - cause_value = cause->value; + if (!sess) { + ogs_error("No Context in TEID"); + cause_value = OGS_GTP2_CAUSE_CONTEXT_NOT_FOUND; } else { + sgwc_ue = sess->sgwc_ue; + ogs_assert(sgwc_ue); + } + + if (cause_value != OGS_GTP2_CAUSE_REQUEST_ACCEPTED) { + ogs_gtp_send_error_message( + s11_xact, sgwc_ue ? sgwc_ue->mme_s11_teid : 0, + OGS_GTP2_DELETE_SESSION_RESPONSE_TYPE, cause_value); + return; + } + + /***************************************** + * Check Mandatory/Conditional IE Missing + *****************************************/ + ogs_assert(cause_value == OGS_GTP2_CAUSE_REQUEST_ACCEPTED); + + if (rsp->cause.presence == 0) { ogs_error("No Cause"); cause_value = OGS_GTP2_CAUSE_MANDATORY_IE_MISSING; } if (cause_value != OGS_GTP2_CAUSE_REQUEST_ACCEPTED) { - ogs_warn("GTP Failed [CAUSE:%d]", cause_value); + ogs_gtp_send_error_message( + s11_xact, sgwc_ue ? sgwc_ue->mme_s11_teid : 0, + OGS_GTP2_DELETE_SESSION_RESPONSE_TYPE, cause_value); + return; } + /******************** + * Check Cause Value + ********************/ + ogs_assert(cause_value == OGS_GTP2_CAUSE_REQUEST_ACCEPTED); + + cause = rsp->cause.data; + ogs_assert(cause); + cause_value = cause->value; + if (cause_value != OGS_GTP2_CAUSE_REQUEST_ACCEPTED) { + ogs_error("GTP Failed [CAUSE:%d]", cause_value); + ogs_gtp_send_error_message( + s11_xact, sgwc_ue ? sgwc_ue->mme_s11_teid : 0, + OGS_GTP2_DELETE_SESSION_RESPONSE_TYPE, cause_value); + return; + } + + /******************** + * Check ALL Context + ********************/ + ogs_assert(sess); + ogs_assert(sgwc_ue); + /* Remove a pgw session */ ogs_debug(" MME_S11_TEID[%d] SGW_S11_TEID[%d]", sgwc_ue->mme_s11_teid, sgwc_ue->sgw_s11_teid); @@ -338,6 +369,7 @@ void sgwc_s5c_handle_modify_bearer_response( ogs_pkbuf_t *gtpbuf, ogs_gtp2_message_t *message) { int rv; + ogs_gtp2_cause_t *cause = NULL; uint8_t cause_value; sgwc_ue_t *sgwc_ue = NULL; @@ -346,35 +378,48 @@ void sgwc_s5c_handle_modify_bearer_response( ogs_gtp_xact_t *s11_xact = NULL; ogs_gtp2_modify_bearer_response_t *rsp = NULL; - ogs_assert(s5c_xact); - s11_xact = s5c_xact->assoc_xact; - ogs_assert(s11_xact); ogs_assert(message); rsp = &message->modify_bearer_response; ogs_assert(rsp); ogs_debug("Modify Bearer Response"); - cause_value = OGS_GTP2_CAUSE_REQUEST_ACCEPTED; - - if (!sess) { - ogs_warn("No Context in TEID"); - sess = s5c_xact->data; - ogs_assert(sess); - } + /******************** + * Check Transaction + ********************/ + ogs_assert(s5c_xact); + s11_xact = s5c_xact->assoc_xact; + ogs_assert(s11_xact); rv = ogs_gtp_xact_commit(s5c_xact); ogs_expect(rv == OGS_OK); - sgwc_ue = sess->sgwc_ue; - ogs_assert(sgwc_ue); + /************************ + * Check Session Context + ************************/ + cause_value = OGS_GTP2_CAUSE_REQUEST_ACCEPTED; - if (rsp->cause.presence) { - ogs_gtp2_cause_t *cause = rsp->cause.data; - ogs_assert(cause); - - cause_value = cause->value; + if (!sess) { + ogs_error("No Context in TEID"); + cause_value = OGS_GTP2_CAUSE_CONTEXT_NOT_FOUND; } else { + sgwc_ue = sess->sgwc_ue; + ogs_assert(sgwc_ue); + } + + if (cause_value != OGS_GTP2_CAUSE_REQUEST_ACCEPTED) { + ogs_gtp_send_error_message( + s11_xact, sgwc_ue ? sgwc_ue->mme_s11_teid : 0, + OGS_GTP2_MODIFY_BEARER_RESPONSE_TYPE, cause_value); + return; + } + + /***************************************** + * Check Mandatory/Conditional IE Missing + *****************************************/ + ogs_assert(cause_value == OGS_GTP2_CAUSE_REQUEST_ACCEPTED); + + if (rsp->cause.presence == 0) { ogs_error("No Cause"); cause_value = OGS_GTP2_CAUSE_MANDATORY_IE_MISSING; } @@ -386,6 +431,28 @@ void sgwc_s5c_handle_modify_bearer_response( return; } + /******************** + * Check Cause Value + ********************/ + ogs_assert(cause_value == OGS_GTP2_CAUSE_REQUEST_ACCEPTED); + + cause = rsp->cause.data; + ogs_assert(cause); + cause_value = cause->value; + if (cause_value != OGS_GTP2_CAUSE_REQUEST_ACCEPTED) { + ogs_error("GTP Failed [CAUSE:%d]", cause_value); + ogs_gtp_send_error_message( + s11_xact, sgwc_ue ? sgwc_ue->mme_s11_teid : 0, + OGS_GTP2_MODIFY_BEARER_RESPONSE_TYPE, cause_value); + return; + } + + /******************** + * Check ALL Context + ********************/ + ogs_assert(sgwc_ue); + ogs_assert(sess); + ogs_debug(" MME_S11_TEID[%d] SGW_S11_TEID[%d]", sgwc_ue->mme_s11_teid, sgwc_ue->sgw_s11_teid); ogs_debug(" SGW_S5C_TEID[0x%x] PGW_S5C_TEID[0x%x]", @@ -419,15 +486,41 @@ void sgwc_s5c_handle_create_bearer_request( ogs_gtp2_create_bearer_request_t *req = NULL; ogs_gtp2_f_teid_t *pgw_s5u_teid = NULL; - ogs_assert(s5c_xact); ogs_assert(message); req = &message->create_bearer_request; ogs_assert(req); ogs_debug("Create Bearer Request"); + /******************** + * Check Transaction + ********************/ + ogs_assert(s5c_xact); + + /************************ + * Check Session Context + ************************/ cause_value = OGS_GTP2_CAUSE_REQUEST_ACCEPTED; + if (!sess) { + ogs_error("No Context in TEID"); + cause_value = OGS_GTP2_CAUSE_CONTEXT_NOT_FOUND; + } else { + sgwc_ue = sess->sgwc_ue; + ogs_assert(sgwc_ue); + } + + if (cause_value != OGS_GTP2_CAUSE_REQUEST_ACCEPTED) { + ogs_gtp_send_error_message(s5c_xact, sess ? sess->pgw_s5c_teid : 0, + OGS_GTP2_CREATE_BEARER_RESPONSE_TYPE, cause_value); + return; + } + + /***************************************** + * Check Mandatory/Conditional IE Missing + *****************************************/ + ogs_assert(cause_value == OGS_GTP2_CAUSE_REQUEST_ACCEPTED); + if (req->linked_eps_bearer_id.presence == 0) { ogs_error("No Linked EBI"); cause_value = OGS_GTP2_CAUSE_MANDATORY_IE_MISSING; @@ -442,12 +535,7 @@ void sgwc_s5c_handle_create_bearer_request( } if (req->bearer_contexts.s4_u_sgsn_f_teid.presence == 0) { ogs_error("No GTP TEID"); - cause_value = OGS_GTP2_CAUSE_MANDATORY_IE_MISSING; - } - - if (!sess) { - ogs_warn("No Context"); - cause_value = OGS_GTP2_CAUSE_CONTEXT_NOT_FOUND; + cause_value = OGS_GTP2_CAUSE_CONDITIONAL_IE_MISSING; } if (cause_value != OGS_GTP2_CAUSE_REQUEST_ACCEPTED) { @@ -456,7 +544,10 @@ void sgwc_s5c_handle_create_bearer_request( return; } - sgwc_ue = sess->sgwc_ue; + /******************** + * Check ALL Context + ********************/ + ogs_assert(sess); ogs_assert(sgwc_ue); bearer = sgwc_bearer_add(sess); @@ -512,39 +603,47 @@ void sgwc_s5c_handle_update_bearer_request( sgwc_ue_t *sgwc_ue = NULL; sgwc_bearer_t *bearer = NULL; - ogs_assert(s5c_xact); ogs_assert(message); req = &message->update_bearer_request; ogs_assert(req); ogs_debug("Update Bearer Request"); + /******************** + * Check Transaction + ********************/ + ogs_assert(s5c_xact); + + /************************ + * Check Session Context + ************************/ cause_value = OGS_GTP2_CAUSE_REQUEST_ACCEPTED; - if (req->bearer_contexts.presence == 0) { - ogs_error("No Bearer"); - cause_value = OGS_GTP2_CAUSE_MANDATORY_IE_MISSING; - } - if (req->bearer_contexts.eps_bearer_id.presence == 0) { - ogs_error("No EPS Bearer ID"); - cause_value = OGS_GTP2_CAUSE_MANDATORY_IE_MISSING; - } - if (!sess) { - ogs_warn("No Context"); + ogs_error("No Context in TEID"); cause_value = OGS_GTP2_CAUSE_CONTEXT_NOT_FOUND; - } + } else { + sgwc_ue = sess->sgwc_ue; + ogs_assert(sgwc_ue); - if (cause_value == OGS_GTP2_CAUSE_REQUEST_ACCEPTED) { - bearer = sgwc_bearer_find_by_sess_ebi( - sess, req->bearer_contexts.eps_bearer_id.u8); - if (!bearer) - ogs_error("No Context for EPS Bearer ID[%d]", + if (req->bearer_contexts.presence == 0) { + ogs_error("No Bearer"); + cause_value = OGS_GTP2_CAUSE_MANDATORY_IE_MISSING; + } + if (req->bearer_contexts.eps_bearer_id.presence == 0) { + ogs_error("No EPS Bearer ID"); + cause_value = OGS_GTP2_CAUSE_MANDATORY_IE_MISSING; + } + + if (cause_value == OGS_GTP2_CAUSE_REQUEST_ACCEPTED) { + bearer = sgwc_bearer_find_by_sess_ebi(sess, req->bearer_contexts.eps_bearer_id.u8); - } - if (!bearer) { - ogs_warn("No Context"); - cause_value = OGS_GTP2_CAUSE_CONTEXT_NOT_FOUND; + if (!bearer) { + ogs_error("No Context for EPS Bearer ID[%d]", + req->bearer_contexts.eps_bearer_id.u8); + cause_value = OGS_GTP2_CAUSE_CONTEXT_NOT_FOUND; + } + } } if (cause_value != OGS_GTP2_CAUSE_REQUEST_ACCEPTED) { @@ -553,9 +652,11 @@ void sgwc_s5c_handle_update_bearer_request( return; } + /******************** + * Check ALL Context + ********************/ ogs_assert(sess); ogs_assert(bearer); - sgwc_ue = sess->sgwc_ue; ogs_assert(sgwc_ue); ogs_assert(sgwc_ue->gnode); @@ -601,66 +702,78 @@ void sgwc_s5c_handle_delete_bearer_request( sgwc_ue_t *sgwc_ue = NULL; sgwc_bearer_t *bearer = NULL; - ogs_assert(s5c_xact); ogs_assert(message); req = &message->delete_bearer_request; ogs_assert(req); ogs_debug("Delete Bearer Request"); + /******************** + * Check Transaction + ********************/ + ogs_assert(s5c_xact); + + /************************ + * Check Session Context + ************************/ cause_value = OGS_GTP2_CAUSE_REQUEST_ACCEPTED; - if (req->linked_eps_bearer_id.presence == 0 && - req->eps_bearer_ids.presence == 0) { - ogs_error("No Linked EBI or EPS Bearer ID"); - cause_value = OGS_GTP2_CAUSE_CONTEXT_NOT_FOUND; - } - if (!sess) { - ogs_warn("No Context"); + ogs_error("No Context in TEID"); cause_value = OGS_GTP2_CAUSE_CONTEXT_NOT_FOUND; - } + } else { + sgwc_ue = sess->sgwc_ue; + ogs_assert(sgwc_ue); - if (cause_value == OGS_GTP2_CAUSE_REQUEST_ACCEPTED) { - uint8_t ebi; + if (req->linked_eps_bearer_id.presence == 0 && + req->eps_bearer_ids.presence == 0) { + ogs_error("No Linked EBI or EPS Bearer ID"); + cause_value = OGS_GTP2_CAUSE_CONTEXT_NOT_FOUND; + } - if (req->linked_eps_bearer_id.presence) { - /* - * << Linked EPS Bearer ID >> - * - * 1. SMF sends Delete Bearer Request(DEFAULT BEARER) to SGW/MME. - * 2. MME sends Delete Bearer Response to SGW/SMF. - * - * OR - * - * 1. SMF sends Delete Bearer Request(DEFAULT BEARER) to ePDG. - * 2. ePDG sends Delete Bearer Response(DEFAULT BEARER) to SMF. - */ - ebi = req->linked_eps_bearer_id.u8; - } else if (req->eps_bearer_ids.presence) { - /* - * << EPS Bearer IDs >> - * - * 1. MME sends Bearer Resource Command to SGW/SMF. - * 2. SMF sends Delete Bearer Request(DEDICATED BEARER) to SGW/MME. - * 3. MME sends Delete Bearer Response(DEDICATED BEARER) to SGW/SMF. - * - * OR - * - * 1. SMF sends Delete Bearer Request(DEDICATED BEARER) to SGW/MME. - * 2. MME sends Delete Bearer Response(DEDICATED BEARER) to SGW/SMF. - */ - ebi = req->eps_bearer_ids.u8; - } else - ogs_assert_if_reached(); + if (cause_value == OGS_GTP2_CAUSE_REQUEST_ACCEPTED) { + uint8_t ebi; - bearer = sgwc_bearer_find_by_sess_ebi(sess, ebi); - if (!bearer) - ogs_error("No Context for EPS Bearer ID[%d]", ebi); - } - if (!bearer) { - ogs_warn("No Context"); - cause_value = OGS_GTP2_CAUSE_CONTEXT_NOT_FOUND; + if (req->linked_eps_bearer_id.presence) { + /* + * << Linked EPS Bearer ID >> + * + * 1. SMF sends Delete Bearer Request(DEFAULT BEARER) to SGW/MME. + * 2. MME sends Delete Bearer Response to SGW/SMF. + * + * OR + * + * 1. SMF sends Delete Bearer Request(DEFAULT BEARER) to ePDG. + * 2. ePDG sends Delete Bearer Response(DEFAULT BEARER) to SMF. + */ + ebi = req->linked_eps_bearer_id.u8; + } else if (req->eps_bearer_ids.presence) { + /* + * << EPS Bearer IDs >> + * + * 1. MME sends Bearer Resource Command to SGW/SMF. + * 2. SMF sends Delete Bearer Request(DEDICATED BEARER) + * to SGW/MME. + * 3. MME sends Delete Bearer Response(DEDICATED BEARER) + * to SGW/SMF. + * + * OR + * + * 1. SMF sends Delete Bearer Request(DEDICATED BEARER) + * to SGW/MME. + * 2. MME sends Delete Bearer Response(DEDICATED BEARER) + * to SGW/SMF. + */ + ebi = req->eps_bearer_ids.u8; + } else + ogs_assert_if_reached(); + + bearer = sgwc_bearer_find_by_sess_ebi(sess, ebi); + if (!bearer) { + ogs_error("No Context for EPS Bearer ID[%d]", ebi); + cause_value = OGS_GTP2_CAUSE_CONTEXT_NOT_FOUND; + } + } } if (cause_value != OGS_GTP2_CAUSE_REQUEST_ACCEPTED) { @@ -669,9 +782,11 @@ void sgwc_s5c_handle_delete_bearer_request( return; } + /******************** + * Check ALL Context + ********************/ ogs_assert(sess); ogs_assert(bearer); - sgwc_ue = sess->sgwc_ue; ogs_assert(sgwc_ue); ogs_assert(sgwc_ue->gnode); @@ -732,23 +847,33 @@ void sgwc_s5c_handle_bearer_resource_failure_indication( sgwc_ue_t *sgwc_ue = NULL; - ogs_assert(s5c_xact); - s11_xact = s5c_xact->assoc_xact; - ogs_assert(s11_xact); ogs_assert(message); ind = &message->bearer_resource_failure_indication; ogs_assert(ind); ogs_debug("Bearer Resource Failure Indication"); + /******************** + * Check Transaction + ********************/ + ogs_assert(s5c_xact); + s11_xact = s5c_xact->assoc_xact; + ogs_assert(s11_xact); + + /************************ + * Check Session Context + ************************/ if (!sess) { - ogs_warn("No Context"); + ogs_error("No Context in TEID"); cause_value = OGS_GTP2_CAUSE_CONTEXT_NOT_FOUND; } else { sgwc_ue = sess->sgwc_ue; ogs_assert(sgwc_ue); } + /******************** + * Check Cause Value + ********************/ if (ind->cause.presence) { ogs_gtp2_cause_t *cause = ind->cause.data; ogs_assert(cause); diff --git a/src/sgwc/sxa-build.c b/src/sgwc/sxa-build.c index 03858ecc9..2dae7a3d2 100644 --- a/src/sgwc/sxa-build.c +++ b/src/sgwc/sxa-build.c @@ -105,17 +105,17 @@ ogs_pkbuf_t *sgwc_sxa_build_session_establishment_request( return pkbuf; } -ogs_pkbuf_t *sgwc_sxa_build_sess_modification_request( - uint8_t type, sgwc_sess_t *sess, uint64_t modify_flags, - ogs_list_t *pdr_to_create_list) +ogs_pkbuf_t *sgwc_sxa_build_session_modification_request( + uint8_t type, sgwc_sess_t *sess, ogs_pfcp_xact_t *xact) { ogs_pfcp_message_t pfcp_message; ogs_pfcp_session_modification_request_t *req = NULL; + ogs_pkbuf_t *pkbuf = NULL; + ogs_pfcp_pdr_t *pdr = NULL; ogs_pfcp_far_t *far = NULL; - ogs_pkbuf_t *pkbuf = NULL; - sgwc_bearer_t *bearer = NULL; sgwc_tunnel_t *tunnel = NULL; + sgwc_bearer_t *bearer = NULL; int num_of_remove_pdr = 0; int num_of_remove_far = 0; @@ -123,18 +123,30 @@ ogs_pkbuf_t *sgwc_sxa_build_sess_modification_request( int num_of_create_far = 0; int num_of_update_far = 0; + uint64_t modify_flags = 0; + ogs_debug("Session Modification Request"); + ogs_assert(sess); + ogs_assert(xact); + modify_flags = xact->modify_flags; ogs_assert(modify_flags); req = &pfcp_message.pfcp_session_modification_request; memset(&pfcp_message, 0, sizeof(ogs_pfcp_message_t)); + num_of_remove_pdr = 0; + num_of_remove_far = 0; + num_of_create_pdr = 0; + num_of_create_far = 0; + num_of_update_far = 0; + if (modify_flags & OGS_PFCP_MODIFY_CREATE) { ogs_pfcp_pdrbuf_init(); } - ogs_list_for_each(&sess->bearer_list, bearer) { + ogs_list_for_each_entry( + &xact->bearer_to_modify_list, bearer, to_modify_node) { ogs_list_for_each(&bearer->tunnel_list, tunnel) { if (((modify_flags & (OGS_PFCP_MODIFY_DL_ONLY| @@ -180,136 +192,7 @@ ogs_pkbuf_t *sgwc_sxa_build_sess_modification_request( } else ogs_assert_if_reached(); - } else { - if (modify_flags & OGS_PFCP_MODIFY_CREATE) { - pdr = tunnel->pdr; - if (pdr) { - ogs_pfcp_build_create_pdr( - &req->create_pdr[num_of_create_pdr], - num_of_create_pdr, pdr); - num_of_create_pdr++; - - ogs_assert(pdr_to_create_list); - ogs_list_add(pdr_to_create_list, - &pdr->to_create_node); - } else - ogs_assert_if_reached(); - - far = tunnel->far; - if (far) { - ogs_pfcp_build_create_far( - &req->create_far[num_of_create_far], - num_of_create_far, far); - - num_of_create_far++; - } else - ogs_assert_if_reached(); - } - if (modify_flags & OGS_PFCP_MODIFY_DEACTIVATE) { - far = tunnel->far; - if (far) { - ogs_pfcp_build_update_far_deactivate( - &req->update_far[num_of_update_far], - num_of_update_far, far); - - num_of_update_far++; - } else - ogs_assert_if_reached(); - } - } - } - - } - } - - pfcp_message.h.type = type; - pkbuf = ogs_pfcp_build_msg(&pfcp_message); - - if (modify_flags & OGS_PFCP_MODIFY_CREATE) { - ogs_pfcp_pdrbuf_clear(); - } - - return pkbuf; -} - -ogs_pkbuf_t *sgwc_sxa_build_bearer_modification_request( - uint8_t type, sgwc_bearer_t *bearer, uint64_t modify_flags, - ogs_list_t *pdr_to_create_list) -{ - ogs_pfcp_message_t pfcp_message; - ogs_pfcp_session_modification_request_t *req = NULL; - sgwc_tunnel_t *tunnel = NULL; - ogs_pfcp_pdr_t *pdr = 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; - - sgwc_sess_t *sess = NULL; - - ogs_debug("Session Modification Request"); - ogs_assert(bearer); - sess = bearer->sess; - ogs_assert(sess); - ogs_assert(modify_flags); - - req = &pfcp_message.pfcp_session_modification_request; - memset(&pfcp_message, 0, sizeof(ogs_pfcp_message_t)); - - if (modify_flags & OGS_PFCP_MODIFY_CREATE) { - ogs_pfcp_pdrbuf_init(); - } - - ogs_list_for_each(&bearer->tunnel_list, tunnel) { - if (((modify_flags & - (OGS_PFCP_MODIFY_DL_ONLY| - OGS_PFCP_MODIFY_UL_ONLY| - OGS_PFCP_MODIFY_INDIRECT)) == 0) || - - ((modify_flags & OGS_PFCP_MODIFY_DL_ONLY) && - (tunnel->interface_type == OGS_GTP2_F_TEID_S5_S8_SGW_GTP_U)) || - - ((modify_flags & OGS_PFCP_MODIFY_UL_ONLY) && - (tunnel->interface_type == OGS_GTP2_F_TEID_S1_U_SGW_GTP_U)) || - - (((modify_flags & OGS_PFCP_MODIFY_INDIRECT) && - ((tunnel->interface_type == - OGS_GTP2_F_TEID_SGW_GTP_U_FOR_DL_DATA_FORWARDING) || - (tunnel->interface_type == - OGS_GTP2_F_TEID_SGW_GTP_U_FOR_UL_DATA_FORWARDING))))) { - - if (modify_flags & OGS_PFCP_MODIFY_REMOVE) { - pdr = tunnel->pdr; - if (pdr) { - ogs_pfcp_tlv_remove_pdr_t *message = - &req->remove_pdr[num_of_remove_pdr]; - - message->presence = 1; - message->pdr_id.presence = 1; - message->pdr_id.u16 = pdr->id; - - num_of_remove_pdr++; - } else - ogs_assert_if_reached(); - - far = tunnel->far; - if (far) { - ogs_pfcp_tlv_remove_far_t *message = - &req->remove_far[num_of_remove_far]; - - message->presence = 1; - message->far_id.presence = 1; - message->far_id.u32 = far->id; - - num_of_remove_far++; - } else - ogs_assert_if_reached(); - - } else { - if (modify_flags & OGS_PFCP_MODIFY_CREATE) { + } else if (modify_flags & OGS_PFCP_MODIFY_CREATE) { pdr = tunnel->pdr; if (pdr) { ogs_pfcp_build_create_pdr( @@ -317,8 +200,8 @@ ogs_pkbuf_t *sgwc_sxa_build_bearer_modification_request( num_of_create_pdr, pdr); num_of_create_pdr++; - ogs_assert(pdr_to_create_list); - ogs_list_add(pdr_to_create_list, &pdr->to_create_node); + ogs_list_add(&xact->pdr_to_create_list, + &pdr->to_create_node); } else ogs_assert_if_reached(); @@ -331,9 +214,17 @@ ogs_pkbuf_t *sgwc_sxa_build_bearer_modification_request( num_of_create_far++; } else ogs_assert_if_reached(); - } + } else if (modify_flags & OGS_PFCP_MODIFY_DEACTIVATE) { + far = tunnel->far; + if (far) { + ogs_pfcp_build_update_far_deactivate( + &req->update_far[num_of_update_far], + num_of_update_far, far); - if (modify_flags & OGS_PFCP_MODIFY_ACTIVATE) { + num_of_update_far++; + } else + ogs_assert_if_reached(); + } else if (modify_flags & OGS_PFCP_MODIFY_ACTIVATE) { far = tunnel->far; if (far) { if (modify_flags & OGS_PFCP_MODIFY_END_MARKER) { diff --git a/src/sgwc/sxa-build.h b/src/sgwc/sxa-build.h index 6ef7e9965..e51ba089e 100644 --- a/src/sgwc/sxa-build.h +++ b/src/sgwc/sxa-build.h @@ -28,12 +28,8 @@ extern "C" { ogs_pkbuf_t *sgwc_sxa_build_session_establishment_request( uint8_t type, sgwc_sess_t *sess); -ogs_pkbuf_t *sgwc_sxa_build_sess_modification_request( - uint8_t type, sgwc_sess_t *sess, uint64_t modify_flags, - ogs_list_t *pdr_to_create_list); -ogs_pkbuf_t *sgwc_sxa_build_bearer_modification_request( - uint8_t type, sgwc_bearer_t *bearer, uint64_t modify_flags, - ogs_list_t *pdr_to_create_list); +ogs_pkbuf_t *sgwc_sxa_build_session_modification_request( + uint8_t type, sgwc_sess_t *sess, ogs_pfcp_xact_t *xact); ogs_pkbuf_t *sgwc_sxa_build_session_deletion_request( uint8_t type, sgwc_sess_t *sess); diff --git a/src/sgwc/sxa-handler.c b/src/sgwc/sxa-handler.c index 4728c103e..d7477f71d 100644 --- a/src/sgwc/sxa-handler.c +++ b/src/sgwc/sxa-handler.c @@ -126,14 +126,15 @@ static void bearer_timeout(ogs_gtp_xact_t *xact, void *data) void sgwc_sxa_handle_session_establishment_response( sgwc_sess_t *sess, ogs_pfcp_xact_t *pfcp_xact, - ogs_gtp2_message_t *gtp_message, + ogs_gtp2_message_t *recv_message, ogs_pfcp_session_establishment_response_t *pfcp_rsp) { - int rv, len = 0; + int rv; uint8_t cause_value = 0; ogs_pfcp_f_seid_t *up_f_seid = NULL; + int sgw_s5c_len, sgw_s5u_len; ogs_gtp2_f_teid_t sgw_s5c_teid, sgw_s5u_teid; ogs_gtp2_f_teid_t *pgw_s5c_teid = NULL; @@ -144,17 +145,19 @@ void sgwc_sxa_handle_session_establishment_response( sgwc_bearer_t *bearer = NULL; sgwc_tunnel_t *dl_tunnel = NULL; - ogs_gtp2_create_session_request_t *gtp_req = NULL; + ogs_gtp2_create_session_request_t *create_session_request = NULL; ogs_pkbuf_t *pkbuf = NULL; + ogs_gtp2_indication_t *indication = NULL; + ogs_debug("Session Establishment Response"); ogs_assert(pfcp_xact); ogs_assert(pfcp_rsp); - ogs_assert(gtp_message); + ogs_assert(recv_message); - gtp_req = >p_message->create_session_request; - ogs_assert(gtp_req); + create_session_request = &recv_message->create_session_request; + ogs_assert(create_session_request); s11_xact = pfcp_xact->assoc_xact; ogs_assert(s11_xact); @@ -270,18 +273,16 @@ void sgwc_sxa_handle_session_establishment_response( sgw_s5c_teid.teid = htobe32(sess->sgw_s5c_teid); rv = ogs_gtp2_sockaddr_to_f_teid( ogs_gtp_self()->gtpc_addr, ogs_gtp_self()->gtpc_addr6, - &sgw_s5c_teid, &len); + &sgw_s5c_teid, &sgw_s5c_len); ogs_assert(rv == OGS_OK); - gtp_req->sender_f_teid_for_control_plane.presence = 1; - gtp_req->sender_f_teid_for_control_plane.data = &sgw_s5c_teid; - gtp_req->sender_f_teid_for_control_plane.len = len; ogs_debug(" SGW_S5C_TEID[0x%x] PGW_S5C_TEID[0x%x]", sess->sgw_s5c_teid, sess->pgw_s5c_teid); ogs_debug(" SGW_S5U_TEID[%d] PGW_S5U_TEID[%d]", dl_tunnel->local_teid, dl_tunnel->remote_teid); - pgw_s5c_teid = gtp_req->pgw_s5_s8_address_for_control_plane_or_pmip.data; + pgw_s5c_teid = create_session_request-> + pgw_s5_s8_address_for_control_plane_or_pmip.data; ogs_assert(pgw_s5c_teid); pgw = ogs_gtp_node_find_by_f_teid(&sgwc_self()->pgw_s5c_list, pgw_s5c_teid); @@ -298,32 +299,101 @@ void sgwc_sxa_handle_session_establishment_response( /* Setup GTP Node */ OGS_SETUP_GTP_NODE(sess, pgw); - /* Remove PGW-S5C */ - gtp_req->pgw_s5_s8_address_for_control_plane_or_pmip.presence = 0; - /* Data Plane(DL) : SGW-S5U */ memset(&sgw_s5u_teid, 0, sizeof(ogs_gtp2_f_teid_t)); sgw_s5u_teid.teid = htobe32(dl_tunnel->local_teid); sgw_s5u_teid.interface_type = dl_tunnel->interface_type; ogs_assert(dl_tunnel->local_addr || dl_tunnel->local_addr6); rv = ogs_gtp2_sockaddr_to_f_teid( - dl_tunnel->local_addr, dl_tunnel->local_addr6, &sgw_s5u_teid, &len); + dl_tunnel->local_addr, dl_tunnel->local_addr6, + &sgw_s5u_teid, &sgw_s5u_len); ogs_assert(rv == OGS_OK); - gtp_req->bearer_contexts_to_be_created.s5_s8_u_sgw_f_teid.presence = 1; - gtp_req->bearer_contexts_to_be_created.s5_s8_u_sgw_f_teid.data = - &sgw_s5u_teid; - gtp_req->bearer_contexts_to_be_created.s5_s8_u_sgw_f_teid.len = len; - gtp_message->h.type = OGS_GTP2_CREATE_SESSION_REQUEST_TYPE; - gtp_message->h.teid = sess->pgw_s5c_teid; + /* Check Indication */ + if (create_session_request->indication_flags.presence && + create_session_request->indication_flags.data && + create_session_request->indication_flags.len) { + indication = create_session_request->indication_flags.data; + } - pkbuf = ogs_gtp2_build_msg(gtp_message); - ogs_expect_or_return(pkbuf); + if (indication && indication->operation_indication) { + ogs_gtp2_message_t send_message; + ogs_gtp2_modify_bearer_request_t *modify_bearer_request = + &send_message.modify_bearer_request; - ogs_assert(sess->gnode); - s5c_xact = ogs_gtp_xact_local_create( - sess->gnode, >p_message->h, pkbuf, sess_timeout, sess); - ogs_expect_or_return(s5c_xact); + /* + * Operation Indication: + * This flag shall be set to 1 on the S4/S11 interface + * for a TAU/RAU procedure with SGW relocation, Enhanced + * SRNS Relocation with SGW relocation, X2-based handovers + * with SGW relocation and MME triggered Serving GW relocation + */ + memset(&send_message, 0, sizeof(ogs_gtp2_message_t)); + + send_message.h.type = OGS_GTP2_MODIFY_BEARER_REQUEST_TYPE; + send_message.h.teid = sess->pgw_s5c_teid; + + /* Send Control Plane(DL) : SGW-S5C */ + modify_bearer_request->sender_f_teid_for_control_plane.presence = 1; + modify_bearer_request->sender_f_teid_for_control_plane. + data = &sgw_s5c_teid; + modify_bearer_request->sender_f_teid_for_control_plane. + len = sgw_s5c_len; + + /* Bearer Context : EBI */ + modify_bearer_request->bearer_contexts_to_be_modified[0].presence = 1; + modify_bearer_request->bearer_contexts_to_be_modified[0]. + eps_bearer_id.presence = 1; + modify_bearer_request->bearer_contexts_to_be_modified[0]. + eps_bearer_id.u8 = bearer->ebi; + + /* Data Plane(DL) : SGW-S5U */ + modify_bearer_request->bearer_contexts_to_be_modified[0]. + s4_u_sgsn_f_teid.presence = 1; + modify_bearer_request->bearer_contexts_to_be_modified[0]. + s4_u_sgsn_f_teid.data = &sgw_s5u_teid; + modify_bearer_request->bearer_contexts_to_be_modified[0]. + s4_u_sgsn_f_teid.len = sgw_s5u_len; + + pkbuf = ogs_gtp2_build_msg(&send_message); + ogs_expect_or_return(pkbuf); + + ogs_assert(sess->gnode); + s5c_xact = ogs_gtp_xact_local_create( + sess->gnode, &send_message.h, pkbuf, sess_timeout, sess); + ogs_expect_or_return(s5c_xact); + } else { + /* Create Session Request */ + recv_message->h.type = OGS_GTP2_CREATE_SESSION_REQUEST_TYPE; + recv_message->h.teid = sess->pgw_s5c_teid; + + /* Send Control Plane(DL) : SGW-S5C */ + create_session_request->sender_f_teid_for_control_plane.presence = 1; + create_session_request->sender_f_teid_for_control_plane. + data = &sgw_s5c_teid; + create_session_request->sender_f_teid_for_control_plane. + len = sgw_s5c_len; + + /* Remove PGW-S5C */ + create_session_request->pgw_s5_s8_address_for_control_plane_or_pmip. + presence = 0; + + /* Bearer Contexts */ + create_session_request->bearer_contexts_to_be_created. + s5_s8_u_sgw_f_teid.presence = 1; + create_session_request->bearer_contexts_to_be_created. + s5_s8_u_sgw_f_teid.data = &sgw_s5u_teid; + create_session_request->bearer_contexts_to_be_created. + s5_s8_u_sgw_f_teid.len = sgw_s5u_len; + + pkbuf = ogs_gtp2_build_msg(recv_message); + ogs_expect_or_return(pkbuf); + + ogs_assert(sess->gnode); + s5c_xact = ogs_gtp_xact_local_create( + sess->gnode, &recv_message->h, pkbuf, sess_timeout, sess); + ogs_expect_or_return(s5c_xact); + } ogs_gtp_xact_associate(s11_xact, s5c_xact); @@ -541,20 +611,15 @@ void sgwc_sxa_handle_session_modification_response( */ 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; + ogs_pfcp_xact_commit(pfcp_xact); - 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; - } + ogs_assert(flags & OGS_PFCP_MODIFY_SESSION); + if (SESSION_SYNC_DONE(sgwc_ue, + OGS_PFCP_SESSION_MODIFICATION_REQUEST_TYPE, flags)) { - if (delete_indirect_tunnel_is_done == true) { sgwc_tunnel_t *tunnel = NULL, *next_tunnel = NULL; ogs_gtp2_delete_indirect_data_forwarding_tunnel_response_t *gtp_rsp = NULL; @@ -603,6 +668,8 @@ void sgwc_sxa_handle_session_modification_response( } else { s5c_xact = pfcp_xact->assoc_xact; + ogs_pfcp_xact_commit(pfcp_xact); + if (s5c_xact) { ogs_assert(recv_message); recv_message->h.type = OGS_GTP2_DELETE_BEARER_RESPONSE_TYPE; @@ -629,6 +696,8 @@ void sgwc_sxa_handle_session_modification_response( s5c_xact = pfcp_xact->assoc_xact; ogs_assert(s5c_xact); + ogs_pfcp_xact_commit(pfcp_xact); + ogs_assert(recv_message); gtp_req = &recv_message->create_bearer_request; ogs_assert(gtp_req); @@ -673,6 +742,8 @@ void sgwc_sxa_handle_session_modification_response( s5c_xact = pfcp_xact->assoc_xact; ogs_assert(s5c_xact); + ogs_pfcp_xact_commit(pfcp_xact); + ogs_assert(recv_message); gtp_rsp = &recv_message->create_bearer_response; ogs_assert(gtp_rsp); @@ -720,20 +791,15 @@ void sgwc_sxa_handle_session_modification_response( ogs_expect(rv == OGS_OK); } else if (flags & OGS_PFCP_MODIFY_INDIRECT) { - bool create_indirect_tunnel_is_done; - s11_xact = pfcp_xact->assoc_xact; ogs_assert(s11_xact); - sess->state.create_indirect_tunnel = true; + ogs_pfcp_xact_commit(pfcp_xact); - create_indirect_tunnel_is_done = true; - ogs_list_for_each(&sgwc_ue->sess_list, sess) { - if (sess->state.create_indirect_tunnel == false) - create_indirect_tunnel_is_done = false; - } + ogs_assert(flags & OGS_PFCP_MODIFY_SESSION); + if (SESSION_SYNC_DONE(sgwc_ue, + OGS_PFCP_SESSION_MODIFICATION_REQUEST_TYPE, flags)) { - if (create_indirect_tunnel_is_done == true) { sgwc_tunnel_t *tunnel = NULL; ogs_gtp2_create_indirect_data_forwarding_tunnel_request_t @@ -853,6 +919,8 @@ void sgwc_sxa_handle_session_modification_response( s11_xact = pfcp_xact->assoc_xact; ogs_assert(s11_xact); + ogs_pfcp_xact_commit(pfcp_xact); + if (flags & OGS_PFCP_MODIFY_UL_ONLY) { ogs_gtp2_create_session_response_t *gtp_rsp = NULL; ogs_gtp2_f_teid_t sgw_s11_teid; @@ -902,51 +970,56 @@ void sgwc_sxa_handle_session_modification_response( ogs_expect(rv == OGS_OK); } else if (flags & OGS_PFCP_MODIFY_DL_ONLY) { - ogs_gtp2_modify_bearer_request_t *gtp_req = NULL; - ogs_gtp2_modify_bearer_response_t *gtp_rsp = NULL; +#if 0 /* FIXME */ + ogs_assert(flags & OGS_PFCP_MODIFY_SESSION); +#endif + if (SESSION_SYNC_DONE(sgwc_ue, + OGS_PFCP_SESSION_MODIFICATION_REQUEST_TYPE, flags)) { + ogs_gtp2_modify_bearer_request_t *gtp_req = NULL; + ogs_gtp2_modify_bearer_response_t *gtp_rsp = NULL; - ogs_gtp2_indication_t *indication = NULL; + ogs_gtp2_indication_t *indication = NULL; - ogs_assert(recv_message); - gtp_req = &recv_message->modify_bearer_request; - ogs_assert(gtp_req); + ogs_assert(recv_message); + gtp_req = &recv_message->modify_bearer_request; + ogs_assert(gtp_req); - if (gtp_req->indication_flags.presence && - gtp_req->indication_flags.data && - gtp_req->indication_flags.len) { - indication = gtp_req->indication_flags.data; - } + if (gtp_req->indication_flags.presence && + gtp_req->indication_flags.data && + gtp_req->indication_flags.len) { + indication = gtp_req->indication_flags.data; + } - if (indication && indication->handover_indication) { - recv_message->h.type = OGS_GTP2_MODIFY_BEARER_REQUEST_TYPE; - recv_message->h.teid = sess->pgw_s5c_teid; + if (indication && indication->handover_indication) { + recv_message->h.type = OGS_GTP2_MODIFY_BEARER_REQUEST_TYPE; + recv_message->h.teid = sess->pgw_s5c_teid; - pkbuf = ogs_gtp2_build_msg(recv_message); - ogs_expect_or_return(pkbuf); + pkbuf = ogs_gtp2_build_msg(recv_message); + ogs_expect_or_return(pkbuf); - ogs_assert(sess->gnode); - s5c_xact = ogs_gtp_xact_local_create( - sess->gnode, &recv_message->h, pkbuf, - sess_timeout, sess); - ogs_expect_or_return(s5c_xact); + ogs_assert(sess->gnode); + s5c_xact = ogs_gtp_xact_local_create( + sess->gnode, &recv_message->h, pkbuf, + sess_timeout, sess); + ogs_expect_or_return(s5c_xact); - ogs_gtp_xact_associate(s11_xact, s5c_xact); + ogs_gtp_xact_associate(s11_xact, s5c_xact); - rv = ogs_gtp_xact_commit(s5c_xact); - ogs_expect(rv == OGS_OK); + rv = ogs_gtp_xact_commit(s5c_xact); + ogs_expect(rv == OGS_OK); - } else { - gtp_rsp = &send_message.modify_bearer_response; - ogs_assert(gtp_rsp); + } else { + gtp_rsp = &send_message.modify_bearer_response; + ogs_assert(gtp_rsp); - memset(&send_message, 0, sizeof(ogs_gtp2_message_t)); + memset(&send_message, 0, sizeof(ogs_gtp2_message_t)); - memset(&cause, 0, sizeof(cause)); - cause.value = OGS_GTP2_CAUSE_REQUEST_ACCEPTED; + memset(&cause, 0, sizeof(cause)); + cause.value = OGS_GTP2_CAUSE_REQUEST_ACCEPTED; - gtp_rsp->cause.presence = 1; - gtp_rsp->cause.data = &cause; - gtp_rsp->cause.len = sizeof(cause); + gtp_rsp->cause.presence = 1; + gtp_rsp->cause.data = &cause; + gtp_rsp->cause.len = sizeof(cause); /* Copy Bearer-Contexts-Modified from Modify-Bearer-Request * @@ -961,67 +1034,89 @@ void sgwc_sxa_handle_session_modification_response( * both an IPv4 address and an IPv6 address * (see also subclause 8.22 "F-TEID"). */ - gtp_rsp->bearer_contexts_modified.presence = 1; - gtp_rsp->bearer_contexts_modified.eps_bearer_id.presence = 1; - gtp_rsp->bearer_contexts_modified.eps_bearer_id.u8 = - gtp_req->bearer_contexts_to_be_modified.eps_bearer_id.u8; - gtp_rsp->bearer_contexts_modified. - s1_u_enodeb_f_teid.presence = 1; - gtp_rsp->bearer_contexts_modified.s1_u_enodeb_f_teid.data = - gtp_req->bearer_contexts_to_be_modified. - s1_u_enodeb_f_teid.data; - gtp_rsp->bearer_contexts_modified.s1_u_enodeb_f_teid.len = - gtp_req->bearer_contexts_to_be_modified. - s1_u_enodeb_f_teid.len; + for (i = 0; i < OGS_BEARER_PER_UE; i++) { + if (gtp_req->bearer_contexts_to_be_modified[i]. + presence == 0) + break; + if (gtp_req->bearer_contexts_to_be_modified[i]. + eps_bearer_id.presence == 0) + break; + if (gtp_req->bearer_contexts_to_be_modified[i]. + s1_u_enodeb_f_teid.presence == 0) + break; - gtp_rsp->bearer_contexts_modified.cause.presence = 1; - gtp_rsp->bearer_contexts_modified.cause.len = sizeof(cause); - gtp_rsp->bearer_contexts_modified.cause.data = &cause; + gtp_rsp->bearer_contexts_modified[i].presence = 1; + gtp_rsp->bearer_contexts_modified[i].eps_bearer_id. + presence = 1; + gtp_rsp->bearer_contexts_modified[i].eps_bearer_id.u8 = + gtp_req->bearer_contexts_to_be_modified[i]. + eps_bearer_id.u8; + gtp_rsp->bearer_contexts_modified[i]. + s1_u_enodeb_f_teid.presence = 1; + gtp_rsp->bearer_contexts_modified[i]. + s1_u_enodeb_f_teid.data = + gtp_req->bearer_contexts_to_be_modified[i]. + s1_u_enodeb_f_teid.data; + gtp_rsp->bearer_contexts_modified[i]. + s1_u_enodeb_f_teid.len = + gtp_req->bearer_contexts_to_be_modified[i]. + s1_u_enodeb_f_teid.len; - send_message.h.type = OGS_GTP2_MODIFY_BEARER_RESPONSE_TYPE; - send_message.h.teid = sgwc_ue->mme_s11_teid; + gtp_rsp->bearer_contexts_modified[i].cause.presence = 1; + gtp_rsp->bearer_contexts_modified[i].cause.len = + sizeof(cause); + gtp_rsp->bearer_contexts_modified[i].cause.data = + &cause; + } - pkbuf = ogs_gtp2_build_msg(&send_message); - ogs_expect_or_return(pkbuf); + send_message.h.type = OGS_GTP2_MODIFY_BEARER_RESPONSE_TYPE; + send_message.h.teid = sgwc_ue->mme_s11_teid; - rv = ogs_gtp_xact_update_tx(s11_xact, &send_message.h, pkbuf); - ogs_expect_or_return(rv == OGS_OK); + pkbuf = ogs_gtp2_build_msg(&send_message); + ogs_expect_or_return(pkbuf); - rv = ogs_gtp_xact_commit(s11_xact); - ogs_expect(rv == OGS_OK); + 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 { ogs_fatal("Invalid modify_flags[0x%llx]", (long long)flags); ogs_assert_if_reached(); } + } else if (flags & OGS_PFCP_MODIFY_DEACTIVATE) { - bool release_access_bearers_is_done; + if (flags & OGS_PFCP_MODIFY_ERROR_INDICATION) { + /* It's faked method for receiving `bearer` context */ + bearer = pfcp_xact->assoc_xact; + ogs_assert(bearer); - sess->state.release_access_bearers = true; - - release_access_bearers_is_done = true; - ogs_list_for_each(&sgwc_ue->sess_list, sess) { - if (sess->state.release_access_bearers == false) - release_access_bearers_is_done = false; - } - - if (release_access_bearers_is_done == true) { - if (flags & OGS_PFCP_MODIFY_ERROR_INDICATION) { - /* It's faked method for receiving `bearer` context */ - bearer = pfcp_xact->assoc_xact; - ogs_assert(bearer); + ogs_pfcp_xact_commit(pfcp_xact); + ogs_assert(flags & OGS_PFCP_MODIFY_SESSION); + if (SESSION_SYNC_DONE(sgwc_ue, + OGS_PFCP_SESSION_MODIFICATION_REQUEST_TYPE, flags)) { ogs_assert(OGS_OK == sgwc_gtp_send_downlink_data_notification( OGS_GTP2_CAUSE_ERROR_INDICATION_RECEIVED, bearer)); + } + + } else { + s11_xact = pfcp_xact->assoc_xact; + ogs_assert(s11_xact); + + ogs_pfcp_xact_commit(pfcp_xact); + + ogs_assert(flags & OGS_PFCP_MODIFY_SESSION); + if (SESSION_SYNC_DONE(sgwc_ue, + OGS_PFCP_SESSION_MODIFICATION_REQUEST_TYPE, flags)) { - } else { ogs_gtp2_release_access_bearers_response_t *gtp_rsp = NULL; - s11_xact = pfcp_xact->assoc_xact; - ogs_assert(s11_xact); - gtp_rsp = &send_message.release_access_bearers_response; ogs_assert(gtp_rsp); @@ -1052,8 +1147,6 @@ void sgwc_sxa_handle_session_modification_response( ogs_fatal("Invalid modify_flags[0x%llx]", (long long)flags); ogs_assert_if_reached(); } - - ogs_pfcp_xact_commit(pfcp_xact); } void sgwc_sxa_handle_session_deletion_response( @@ -1256,8 +1349,6 @@ void sgwc_sxa_handle_session_report_request( ogs_list_for_each(&sgwc_ue->sess_list, sess) { - sess->state.release_access_bearers = false; - ogs_assert(OGS_OK == sgwc_pfcp_send_sess_modification_request(sess, /* We only use the `assoc_xact` parameter temporarily here diff --git a/src/sgwu/pfcp-path.c b/src/sgwu/pfcp-path.c index 775f95ed4..4feb127d2 100644 --- a/src/sgwu/pfcp-path.c +++ b/src/sgwu/pfcp-path.c @@ -132,7 +132,7 @@ int sgwu_pfcp_open(void) ogs_list_for_each(&ogs_pfcp_self()->pfcp_list, node) { sock = ogs_pfcp_server(node); if (!sock) return OGS_ERROR; - + node->poll = ogs_pollset_add(ogs_app()->pollset, OGS_POLLIN, sock->fd, pfcp_recv_cb, sock); ogs_assert(node->poll); @@ -274,15 +274,17 @@ int sgwu_pfcp_send_session_report_request( h.type = OGS_PFCP_SESSION_REPORT_REQUEST_TYPE; h.seid = sess->sgwc_sxa_seid; + xact = ogs_pfcp_xact_local_create(sess->pfcp_node, sess_timeout, sess); + ogs_expect_or_return_val(xact, OGS_ERROR); + sxabuf = ogs_pfcp_build_session_report_request(h.type, report); ogs_expect_or_return_val(sxabuf, OGS_ERROR); - xact = ogs_pfcp_xact_local_create( - sess->pfcp_node, &h, sxabuf, sess_timeout, sess); - ogs_expect_or_return_val(xact, OGS_ERROR); + rv = ogs_pfcp_xact_update_tx(xact, &h, sxabuf); + ogs_expect_or_return_val(rv == OGS_OK, OGS_ERROR); rv = ogs_pfcp_xact_commit(xact); ogs_expect(rv == OGS_OK); return rv; -} \ No newline at end of file +} diff --git a/src/smf/n4-build.c b/src/smf/n4-build.c index 0f4d1f087..402d1b5d1 100644 --- a/src/smf/n4-build.c +++ b/src/smf/n4-build.c @@ -111,8 +111,7 @@ 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, - ogs_list_t *pdr_to_create_list) + uint8_t type, smf_sess_t *sess, ogs_pfcp_xact_t *xact) { ogs_pfcp_pdr_t *pdr = NULL; ogs_pfcp_urr_t *urr = NULL; @@ -128,8 +127,12 @@ ogs_pkbuf_t *smf_n4_build_session_modification_request( int num_of_create_far = 0; int num_of_update_far = 0; + uint64_t modify_flags = 0; + ogs_debug("Session Modification Request"); ogs_assert(sess); + ogs_assert(xact); + modify_flags = xact->modify_flags; ogs_assert(modify_flags); req = &pfcp_message.pfcp_session_modification_request; @@ -181,8 +184,7 @@ ogs_pkbuf_t *smf_n4_build_session_modification_request( num_of_create_pdr, pdr); num_of_create_pdr++; - ogs_assert(pdr_to_create_list); - ogs_list_add(pdr_to_create_list, &pdr->to_create_node); + ogs_list_add(&xact->pdr_to_create_list, &pdr->to_create_node); ogs_pfcp_build_create_far( &req->create_far[num_of_create_far], @@ -237,8 +239,7 @@ ogs_pkbuf_t *smf_n4_build_session_modification_request( } ogs_pkbuf_t *smf_n4_build_qos_flow_modification_request( - uint8_t type, smf_bearer_t *qos_flow, uint64_t modify_flags, - ogs_list_t *pdr_to_create_list) + uint8_t type, smf_bearer_t *qos_flow, ogs_pfcp_xact_t *xact) { ogs_pfcp_message_t pfcp_message; ogs_pfcp_session_modification_request_t *req = NULL; @@ -247,10 +248,15 @@ ogs_pkbuf_t *smf_n4_build_qos_flow_modification_request( smf_sess_t *sess = NULL; + uint64_t modify_flags = 0; + ogs_debug("QoS Flow Modification Request"); + ogs_assert(qos_flow); sess = qos_flow->sess; ogs_assert(sess); + ogs_assert(xact); + modify_flags = xact->modify_flags; ogs_assert(modify_flags); req = &pfcp_message.pfcp_session_modification_request; @@ -324,8 +330,7 @@ ogs_pkbuf_t *smf_n4_build_qos_flow_modification_request( &req->create_pdr[i], i, qos_flow->dl_pdr); i++; - ogs_assert(pdr_to_create_list); - ogs_list_add(pdr_to_create_list, + ogs_list_add(&xact->pdr_to_create_list, &qos_flow->dl_pdr->to_create_node); } if (qos_flow->ul_pdr) { @@ -333,8 +338,7 @@ ogs_pkbuf_t *smf_n4_build_qos_flow_modification_request( &req->create_pdr[i], i, qos_flow->ul_pdr); i++; - ogs_assert(pdr_to_create_list); - ogs_list_add(pdr_to_create_list, + ogs_list_add(&xact->pdr_to_create_list, &qos_flow->ul_pdr->to_create_node); } diff --git a/src/smf/n4-build.h b/src/smf/n4-build.h index b1dfd3de5..19a62a283 100644 --- a/src/smf/n4-build.h +++ b/src/smf/n4-build.h @@ -29,11 +29,9 @@ extern "C" { ogs_pkbuf_t *smf_n4_build_session_establishment_request( uint8_t type, smf_sess_t *sess); ogs_pkbuf_t *smf_n4_build_session_modification_request( - uint8_t type, smf_sess_t *sess, uint64_t modify_flags, - ogs_list_t *pdr_to_create_list); + uint8_t type, smf_sess_t *sess, ogs_pfcp_xact_t *xact); ogs_pkbuf_t *smf_n4_build_qos_flow_modification_request( - uint8_t type, smf_bearer_t *qos_flow, uint64_t modify_flags, - ogs_list_t *pdr_to_create_list); + uint8_t type, smf_bearer_t *qos_flow, ogs_pfcp_xact_t *xact); ogs_pkbuf_t *smf_n4_build_session_deletion_request( uint8_t type, smf_sess_t *sess); diff --git a/src/smf/n4-handler.c b/src/smf/n4-handler.c index cc885cbf6..e4a6ace10 100644 --- a/src/smf/n4-handler.c +++ b/src/smf/n4-handler.c @@ -252,11 +252,11 @@ void smf_5gc_n4_handle_session_modification_response( OGS_LIST(pdr_to_create_list); + ogs_debug("Session Modification Response [5gc]"); + ogs_assert(xact); ogs_assert(rsp); - ogs_debug("Session Modification Response [5gc]"); - flags = xact->modify_flags; ogs_assert(flags); @@ -1017,8 +1017,19 @@ void smf_epc_n4_handle_session_modification_response( linked_bearer, gtp_pti, gtp_cause)); } else { /* - * 1. SMF sends Delete Bearer Request(DEDICATED BEARER) to SGW/MME. - * 2. MME sends Delete Bearer Response(DEDICATED BEARER) to SGW/SMF. + * 1. RX : Session-Termination Request + * 2. GX : Re-Auth-Request(Charging-Rule-Remove) + * 3. RX : Session-Termination Answer + * 4. PFCP Session Modification Request(Buffering) + * 5. PFCP Session Modification Answer(Buffering) + * 6. SMF sends Delete Bearer Request(DEDICATED BEARER) to SGW/MME. + * 7. E-RABReleaseCommand + Deactivate EPS bearer context request + * 8. E-RABReleaseResponse + * 9. UplinkNASTransport + Deactivate EPS bearer context accept + * 10. MME sends Delete Bearer Response(DEDICATED BEARER) to SGW-C + * 11. PFCP Session Modification Request/Response(Remove PDR/FAR) + * 12. SGW-C sends Delete Bearer Response(DECIATED BEARER) to SMF + * 13. PFCP Session Modification Request/Response(Remove PDR/FAR) */ ogs_assert(bearer); diff --git a/src/smf/pfcp-path.c b/src/smf/pfcp-path.c index b2c449f43..a113c25e7 100644 --- a/src/smf/pfcp-path.c +++ b/src/smf/pfcp-path.c @@ -134,7 +134,7 @@ int smf_pfcp_open(void) ogs_list_for_each(&ogs_pfcp_self()->pfcp_list, node) { sock = ogs_pfcp_server(node); if (!sock) return OGS_ERROR; - + node->poll = ogs_pollset_add(ogs_app()->pollset, OGS_POLLIN, sock->fd, pfcp_recv_cb, sock); ogs_assert(node->poll); @@ -309,13 +309,16 @@ int smf_5gc_pfcp_send_session_establishment_request( h.type = OGS_PFCP_SESSION_ESTABLISHMENT_REQUEST_TYPE; h.seid = sess->upf_n4_seid; + xact = ogs_pfcp_xact_local_create(sess->pfcp_node, sess_5gc_timeout, sess); + ogs_expect_or_return_val(xact, OGS_ERROR); + + xact->assoc_stream = stream; + n4buf = smf_n4_build_session_establishment_request(h.type, sess); ogs_expect_or_return_val(n4buf, OGS_ERROR); - xact = ogs_pfcp_xact_local_create( - sess->pfcp_node, &h, n4buf, sess_5gc_timeout, sess); - ogs_expect_or_return_val(xact, OGS_ERROR); - xact->assoc_stream = stream; + rv = ogs_pfcp_xact_update_tx(xact, &h, n4buf); + ogs_expect_or_return_val(rv == OGS_OK, OGS_ERROR); rv = ogs_pfcp_xact_commit(xact); ogs_expect(rv == OGS_OK); @@ -331,8 +334,6 @@ int smf_5gc_pfcp_send_session_modification_request( ogs_pkbuf_t *n4buf = NULL; ogs_pfcp_header_t h; ogs_pfcp_xact_t *xact = NULL; - - OGS_LIST(pdr_to_create_list); ogs_assert(sess); if ((flags & OGS_PFCP_MODIFY_ERROR_INDICATION) == 0) @@ -342,17 +343,17 @@ int smf_5gc_pfcp_send_session_modification_request( h.type = OGS_PFCP_SESSION_MODIFICATION_REQUEST_TYPE; h.seid = sess->upf_n4_seid; - n4buf = smf_n4_build_session_modification_request( - h.type, sess, flags, &pdr_to_create_list); - ogs_expect_or_return_val(n4buf, OGS_ERROR); - - xact = ogs_pfcp_xact_local_create( - sess->pfcp_node, &h, n4buf, sess_5gc_timeout, sess); + xact = ogs_pfcp_xact_local_create(sess->pfcp_node, sess_5gc_timeout, sess); ogs_expect_or_return_val(xact, OGS_ERROR); + xact->assoc_stream = stream; xact->modify_flags = flags | OGS_PFCP_MODIFY_SESSION; - ogs_list_copy(&xact->pdr_to_create_list, &pdr_to_create_list); + n4buf = smf_n4_build_session_modification_request(h.type, sess, xact); + ogs_expect_or_return_val(n4buf, OGS_ERROR); + + rv = ogs_pfcp_xact_update_tx(xact, &h, n4buf); + ogs_expect_or_return_val(rv == OGS_OK, OGS_ERROR); if (duration) { ogs_pfcp_xact_delayed_commit(xact, duration); @@ -375,8 +376,6 @@ int smf_5gc_pfcp_send_qos_flow_modification_request(smf_bearer_t *qos_flow, ogs_pfcp_xact_t *xact = NULL; smf_sess_t *sess = NULL; - OGS_LIST(pdr_to_create_list); - ogs_assert(qos_flow); sess = qos_flow->sess; ogs_assert(sess); @@ -385,18 +384,18 @@ int smf_5gc_pfcp_send_qos_flow_modification_request(smf_bearer_t *qos_flow, h.type = OGS_PFCP_SESSION_MODIFICATION_REQUEST_TYPE; h.seid = sess->upf_n4_seid; - n4buf = smf_n4_build_qos_flow_modification_request( - h.type, qos_flow, flags, &pdr_to_create_list); - ogs_expect_or_return_val(n4buf, OGS_ERROR); - xact = ogs_pfcp_xact_local_create( - sess->pfcp_node, &h, n4buf, qos_flow_5gc_timeout, qos_flow); + sess->pfcp_node, qos_flow_5gc_timeout, qos_flow); ogs_expect_or_return_val(xact, OGS_ERROR); xact->assoc_stream = stream; xact->modify_flags = flags; - ogs_list_copy(&xact->pdr_to_create_list, &pdr_to_create_list); + n4buf = smf_n4_build_qos_flow_modification_request(h.type, qos_flow, xact); + ogs_expect_or_return_val(n4buf, OGS_ERROR); + + rv = ogs_pfcp_xact_update_tx(xact, &h, n4buf); + ogs_expect_or_return_val(rv == OGS_OK, OGS_ERROR); rv = ogs_pfcp_xact_commit(xact); ogs_expect(rv == OGS_OK); @@ -419,14 +418,17 @@ int smf_5gc_pfcp_send_session_deletion_request( h.type = OGS_PFCP_SESSION_DELETION_REQUEST_TYPE; h.seid = sess->upf_n4_seid; + xact = ogs_pfcp_xact_local_create(sess->pfcp_node, sess_5gc_timeout, sess); + ogs_expect_or_return_val(xact, OGS_ERROR); + + xact->assoc_stream = stream; + xact->delete_trigger = trigger; + n4buf = smf_n4_build_session_deletion_request(h.type, sess); ogs_expect_or_return_val(n4buf, OGS_ERROR); - xact = ogs_pfcp_xact_local_create( - sess->pfcp_node, &h, n4buf, sess_5gc_timeout, sess); - ogs_expect_or_return_val(xact, OGS_ERROR); - xact->assoc_stream = stream; - xact->delete_trigger = trigger; + rv = ogs_pfcp_xact_update_tx(xact, &h, n4buf); + ogs_expect_or_return_val(rv == OGS_OK, OGS_ERROR); rv = ogs_pfcp_xact_commit(xact); ogs_expect(rv == OGS_OK); @@ -448,16 +450,18 @@ int smf_epc_pfcp_send_session_establishment_request( h.type = OGS_PFCP_SESSION_ESTABLISHMENT_REQUEST_TYPE; h.seid = sess->upf_n4_seid; - n4buf = smf_n4_build_session_establishment_request(h.type, sess); - ogs_expect_or_return_val(n4buf, OGS_ERROR); - - xact = ogs_pfcp_xact_local_create( - sess->pfcp_node, &h, n4buf, sess_epc_timeout, sess); + xact = ogs_pfcp_xact_local_create(sess->pfcp_node, sess_epc_timeout, sess); ogs_expect_or_return_val(xact, OGS_ERROR); xact->epc = true; /* EPC PFCP transaction */ xact->assoc_xact = gtp_xact; + n4buf = smf_n4_build_session_establishment_request(h.type, sess); + ogs_expect_or_return_val(n4buf, OGS_ERROR); + + rv = ogs_pfcp_xact_update_tx(xact, &h, n4buf); + ogs_expect_or_return_val(rv == OGS_OK, OGS_ERROR); + rv = ogs_pfcp_xact_commit(xact); ogs_expect(rv == OGS_OK); @@ -473,20 +477,13 @@ int smf_epc_pfcp_send_session_modification_request( ogs_pfcp_header_t h; ogs_pfcp_xact_t *xact = NULL; - OGS_LIST(pdr_to_create_list); - ogs_assert(sess); memset(&h, 0, sizeof(ogs_pfcp_header_t)); h.type = OGS_PFCP_SESSION_MODIFICATION_REQUEST_TYPE; h.seid = sess->upf_n4_seid; - n4buf = smf_n4_build_session_modification_request( - h.type, sess, flags, &pdr_to_create_list); - ogs_expect_or_return_val(n4buf, OGS_ERROR); - - xact = ogs_pfcp_xact_local_create( - sess->pfcp_node, &h, n4buf, sess_epc_timeout, sess); + xact = ogs_pfcp_xact_local_create(sess->pfcp_node, sess_epc_timeout, sess); ogs_expect_or_return_val(xact, OGS_ERROR); xact->epc = true; /* EPC PFCP transaction */ @@ -496,7 +493,11 @@ int smf_epc_pfcp_send_session_modification_request( xact->gtp_pti = gtp_pti; xact->gtp_cause = gtp_cause; - ogs_list_copy(&xact->pdr_to_create_list, &pdr_to_create_list); + n4buf = smf_n4_build_session_modification_request(h.type, sess, xact); + ogs_expect_or_return_val(n4buf, OGS_ERROR); + + rv = ogs_pfcp_xact_update_tx(xact, &h, n4buf); + ogs_expect_or_return_val(rv == OGS_OK, OGS_ERROR); rv = ogs_pfcp_xact_commit(xact); ogs_expect(rv == OGS_OK); @@ -514,8 +515,6 @@ int smf_epc_pfcp_send_bearer_modification_request( ogs_pfcp_xact_t *xact = NULL; smf_sess_t *sess = NULL; - OGS_LIST(pdr_to_create_list); - ogs_assert(bearer); sess = bearer->sess; ogs_assert(sess); @@ -524,12 +523,8 @@ int smf_epc_pfcp_send_bearer_modification_request( h.type = OGS_PFCP_SESSION_MODIFICATION_REQUEST_TYPE; h.seid = sess->upf_n4_seid; - n4buf = smf_n4_build_qos_flow_modification_request( - h.type, bearer, flags, &pdr_to_create_list); - ogs_expect_or_return_val(n4buf, OGS_ERROR); - xact = ogs_pfcp_xact_local_create( - sess->pfcp_node, &h, n4buf, bearer_epc_timeout, bearer); + sess->pfcp_node, bearer_epc_timeout, bearer); ogs_expect_or_return_val(xact, OGS_ERROR); xact->epc = true; /* EPC PFCP transaction */ @@ -539,7 +534,11 @@ int smf_epc_pfcp_send_bearer_modification_request( xact->gtp_pti = gtp_pti; xact->gtp_cause = gtp_cause; - ogs_list_copy(&xact->pdr_to_create_list, &pdr_to_create_list); + n4buf = smf_n4_build_qos_flow_modification_request(h.type, bearer, xact); + ogs_expect_or_return_val(n4buf, OGS_ERROR); + + rv = ogs_pfcp_xact_update_tx(xact, &h, n4buf); + ogs_expect_or_return_val(rv == OGS_OK, OGS_ERROR); rv = ogs_pfcp_xact_commit(xact); ogs_expect(rv == OGS_OK); @@ -561,11 +560,7 @@ int smf_epc_pfcp_send_session_deletion_request( h.type = OGS_PFCP_SESSION_DELETION_REQUEST_TYPE; h.seid = sess->upf_n4_seid; - n4buf = smf_n4_build_session_deletion_request(h.type, sess); - ogs_expect_or_return_val(n4buf, OGS_ERROR); - - xact = ogs_pfcp_xact_local_create( - sess->pfcp_node, &h, n4buf, sess_epc_timeout, sess); + xact = ogs_pfcp_xact_local_create(sess->pfcp_node, sess_epc_timeout, sess); ogs_expect_or_return_val(xact, OGS_ERROR); xact->epc = true; /* EPC PFCP transaction */ @@ -593,6 +588,12 @@ int smf_epc_pfcp_send_session_deletion_request( */ xact->assoc_xact = gtp_xact; + n4buf = smf_n4_build_session_deletion_request(h.type, sess); + ogs_expect_or_return_val(n4buf, OGS_ERROR); + + rv = ogs_pfcp_xact_update_tx(xact, &h, n4buf); + ogs_expect_or_return_val(rv == OGS_OK, OGS_ERROR); + rv = ogs_pfcp_xact_commit(xact); ogs_expect(rv == OGS_OK); diff --git a/src/smf/s5c-build.c b/src/smf/s5c-build.c index f4bd5ebba..25203dbbb 100644 --- a/src/smf/s5c-build.c +++ b/src/smf/s5c-build.c @@ -263,19 +263,19 @@ ogs_pkbuf_t *smf_s5c_build_modify_bearer_response( rsp->cause.data = &cause; rsp->cause.len = sizeof(cause); - rsp->bearer_contexts_modified.presence = 1; - rsp->bearer_contexts_modified.eps_bearer_id.presence = 1; - rsp->bearer_contexts_modified.eps_bearer_id.u8 = - req->bearer_contexts_to_be_modified.eps_bearer_id.u8; - rsp->bearer_contexts_modified.s1_u_enodeb_f_teid.presence = 1; - rsp->bearer_contexts_modified.s1_u_enodeb_f_teid.data = - req->bearer_contexts_to_be_modified.s1_u_enodeb_f_teid.data; - rsp->bearer_contexts_modified.s1_u_enodeb_f_teid.len = - req->bearer_contexts_to_be_modified.s1_u_enodeb_f_teid.len; + rsp->bearer_contexts_modified[0].presence = 1; + rsp->bearer_contexts_modified[0].eps_bearer_id.presence = 1; + rsp->bearer_contexts_modified[0].eps_bearer_id.u8 = + req->bearer_contexts_to_be_modified[0].eps_bearer_id.u8; + rsp->bearer_contexts_modified[0].s1_u_enodeb_f_teid.presence = 1; + rsp->bearer_contexts_modified[0].s1_u_enodeb_f_teid.data = + req->bearer_contexts_to_be_modified[0].s1_u_enodeb_f_teid.data; + rsp->bearer_contexts_modified[0].s1_u_enodeb_f_teid.len = + req->bearer_contexts_to_be_modified[0].s1_u_enodeb_f_teid.len; - rsp->bearer_contexts_modified.cause.presence = 1; - rsp->bearer_contexts_modified.cause.len = sizeof(cause); - rsp->bearer_contexts_modified.cause.data = &cause; + rsp->bearer_contexts_modified[0].cause.presence = 1; + rsp->bearer_contexts_modified[0].cause.len = sizeof(cause); + rsp->bearer_contexts_modified[0].cause.data = &cause; /* build */ gtp_message.h.type = type; diff --git a/src/smf/s5c-handler.c b/src/smf/s5c-handler.c index 2cd2cdd61..62e13df25 100644 --- a/src/smf/s5c-handler.c +++ b/src/smf/s5c-handler.c @@ -212,16 +212,6 @@ uint8_t smf_s5c_handle_create_session_request( sess->ipv4 ? OGS_INET_NTOP(&sess->ipv4->addr, buf1) : "", sess->ipv6 ? OGS_INET6_NTOP(&sess->ipv6->addr, buf2) : ""); - /* Remove all previous bearer */ - smf_bearer_remove_all(sess); - - /* Setup Default Bearer */ - bearer = smf_bearer_add(sess); - ogs_assert(bearer); - - /* Set Bearer EBI */ - bearer->ebi = req->bearer_contexts_to_be_created.eps_bearer_id.u8; - /* Control Plane(DL) : SGW-S5C */ sgw_s5c_teid = req->sender_f_teid_for_control_plane.data; ogs_assert(sgw_s5c_teid); @@ -232,6 +222,16 @@ uint8_t smf_s5c_handle_create_session_request( ogs_debug(" SGW_S5C_TEID[0x%x] SMF_N4_TEID[0x%x]", sess->sgw_s5c_teid, sess->smf_n4_teid); + /* Remove all previous bearer */ + smf_bearer_remove_all(sess); + + /* Setup Default Bearer */ + bearer = smf_bearer_add(sess); + ogs_assert(bearer); + + /* Set Bearer EBI */ + bearer->ebi = req->bearer_contexts_to_be_created.eps_bearer_id.u8; + switch (sess->gtp_rat_type) { case OGS_GTP2_RAT_TYPE_EUTRAN: sgw_s5u_teid = req->bearer_contexts_to_be_created. @@ -350,10 +350,13 @@ void smf_s5c_handle_modify_bearer_request( ogs_assert(xact); ogs_assert(req); + /************************ + * Check Session Context + ************************/ cause_value = OGS_GTP2_CAUSE_REQUEST_ACCEPTED; if (!sess) { - ogs_warn("No Context"); + ogs_error("No Context"); cause_value = OGS_GTP2_CAUSE_CONTEXT_NOT_FOUND; } @@ -363,16 +366,53 @@ void smf_s5c_handle_modify_bearer_request( return; } + /******************** + * Check ALL Context + ********************/ ogs_assert(sess); smf_ue = sess->smf_ue; ogs_assert(smf_ue); - ogs_debug(" SGW_S5C_TEID[0x%x] SMF_N4_TEID[0x%x]", - sess->sgw_s5c_teid, sess->smf_n4_teid); + /* Control Plane(DL) : SGW-S5C */ + if (req->sender_f_teid_for_control_plane.presence == 1) { + ogs_gtp2_f_teid_t *sgw_s5c_teid = + req->sender_f_teid_for_control_plane.data; + ogs_assert(sgw_s5c_teid); + sess->sgw_s5c_teid = be32toh(sgw_s5c_teid->teid); + rv = ogs_gtp2_f_teid_to_ip(sgw_s5c_teid, &sess->sgw_s5c_ip); + ogs_assert(rv == OGS_OK); - /* TODO: Update remote GTP-U IP addr + TEID in the UPF through PFCP, similar - * to what is done in smf_gn_handle_update_pdp_context_request() - */ + ogs_debug(" SGW_S5C_TEID[0x%x] SMF_N4_TEID[0x%x]", + sess->sgw_s5c_teid, sess->smf_n4_teid); + } + +#if 0 /* TODO */ + switch (sess->gtp_rat_type) { + case OGS_GTP2_RAT_TYPE_EUTRAN: + sgw_s5u_teid = req->bearer_contexts_to_be_created. + s5_s8_u_sgw_f_teid.data; + ogs_assert(sgw_s5u_teid); + bearer->sgw_s5u_teid = be32toh(sgw_s5u_teid->teid); + rv = ogs_gtp2_f_teid_to_ip(sgw_s5u_teid, &bearer->sgw_s5u_ip); + ogs_assert(rv == OGS_OK); + + break; + case OGS_GTP2_RAT_TYPE_WLAN: + sgw_s5u_teid = req->bearer_contexts_to_be_created. + s2b_u_epdg_f_teid_5.data; + ogs_assert(sgw_s5u_teid); + bearer->sgw_s5u_teid = be32toh(sgw_s5u_teid->teid); + rv = ogs_gtp2_f_teid_to_ip(sgw_s5u_teid, &bearer->sgw_s5u_ip); + ogs_assert(rv == OGS_OK); + break; + default: + ogs_error("Unknown RAT Type [%d]", sess->gtp_rat_type); + ogs_assert_if_reached(); + } + + ogs_debug(" SGW_S5U_TEID[0x%x] PGW_S5U_TEID[0x%x]", + bearer->sgw_s5u_teid, bearer->pgw_s5u_teid); +#endif memset(&h, 0, sizeof(ogs_gtp2_header_t)); h.type = OGS_GTP2_MODIFY_BEARER_RESPONSE_TYPE; @@ -414,23 +454,49 @@ void smf_s5c_handle_create_bearer_response( { int rv; uint8_t cause_value; + ogs_gtp2_cause_t *cause = NULL; ogs_gtp2_f_teid_t *sgw_s5u_teid, *pgw_s5u_teid; smf_bearer_t *bearer = NULL; ogs_pfcp_far_t *dl_far = NULL; - ogs_assert(xact); ogs_assert(rsp); - bearer = xact->data; - ogs_assert(bearer); - ogs_debug("Create Bearer Response"); - cause_value = OGS_GTP2_CAUSE_REQUEST_ACCEPTED; + /******************** + * Check Transaction + ********************/ + ogs_assert(xact); + bearer = xact->data; + ogs_assert(bearer); rv = ogs_gtp_xact_commit(xact); ogs_expect(rv == OGS_OK); + /************************ + * Check Session Context + ************************/ + cause_value = OGS_GTP2_CAUSE_REQUEST_ACCEPTED; + + if (!sess) { + ogs_error("No Context in TEID"); + cause_value = OGS_GTP2_CAUSE_CONTEXT_NOT_FOUND; + } + + if (cause_value != OGS_GTP2_CAUSE_REQUEST_ACCEPTED) { + ogs_assert(OGS_OK == + smf_epc_pfcp_send_bearer_modification_request( + bearer, NULL, OGS_PFCP_MODIFY_REMOVE, + OGS_NAS_PROCEDURE_TRANSACTION_IDENTITY_UNASSIGNED, + OGS_GTP2_CAUSE_UNDEFINED_VALUE)); + return; + } + + /***************************************** + * Check Mandatory/Conditional IE Missing + *****************************************/ + ogs_assert(cause_value == OGS_GTP2_CAUSE_REQUEST_ACCEPTED); + if (rsp->bearer_contexts.presence == 0) { ogs_error("No Bearer"); cause_value = OGS_GTP2_CAUSE_MANDATORY_IE_MISSING; @@ -458,42 +524,19 @@ void smf_s5c_handle_create_bearer_response( if (!pgw_s5u_teid) { ogs_error("No PGW TEID"); - cause_value = OGS_GTP2_CAUSE_MANDATORY_IE_MISSING; + cause_value = OGS_GTP2_CAUSE_CONDITIONAL_IE_MISSING; } if (!sgw_s5u_teid) { ogs_error("No SGW TEID"); + cause_value = OGS_GTP2_CAUSE_CONDITIONAL_IE_MISSING; + } + + if (rsp->cause.presence == 0) { + ogs_error("No Cause"); cause_value = OGS_GTP2_CAUSE_MANDATORY_IE_MISSING; } - - if (!sess) { - ogs_warn("No Context in TEID"); - - sess = bearer->sess; - ogs_assert(sess); - - cause_value = OGS_GTP2_CAUSE_CONTEXT_NOT_FOUND; - } - - if (rsp->cause.presence) { - ogs_gtp2_cause_t *cause = rsp->cause.data; - ogs_assert(cause); - - cause_value = cause->value; - if (cause_value == OGS_GTP2_CAUSE_REQUEST_ACCEPTED) { - if (rsp->bearer_contexts.cause.presence) { - cause = rsp->bearer_contexts.cause.data; - ogs_assert(cause); - - cause_value = cause->value; - } else { - ogs_error("No Cause"); - cause_value = OGS_GTP2_CAUSE_MANDATORY_IE_MISSING; - } - } else { - ogs_warn("GTP Failed [CAUSE:%d]", cause_value); - } - } else { - ogs_error("No Cause"); + if (rsp->bearer_contexts.cause.presence == 0) { + ogs_error("No Bearer Cause"); cause_value = OGS_GTP2_CAUSE_MANDATORY_IE_MISSING; } @@ -506,6 +549,43 @@ void smf_s5c_handle_create_bearer_response( return; } + /******************** + * Check Cause Value + ********************/ + ogs_assert(cause_value == OGS_GTP2_CAUSE_REQUEST_ACCEPTED); + + cause = rsp->bearer_contexts.cause.data; + ogs_assert(cause); + cause_value = cause->value; + if (cause_value != OGS_GTP2_CAUSE_REQUEST_ACCEPTED) { + ogs_error("GTP Failed [Bearer-CAUSE:%d]", cause_value); + ogs_assert(OGS_OK == + smf_epc_pfcp_send_bearer_modification_request( + bearer, NULL, OGS_PFCP_MODIFY_REMOVE, + OGS_NAS_PROCEDURE_TRANSACTION_IDENTITY_UNASSIGNED, + OGS_GTP2_CAUSE_UNDEFINED_VALUE)); + return; + } + + cause = rsp->cause.data; + ogs_assert(cause); + cause_value = cause->value; + if (cause_value != OGS_GTP2_CAUSE_REQUEST_ACCEPTED) { + ogs_error("GTP Failed [CAUSE:%d]", cause_value); + ogs_assert(OGS_OK == + smf_epc_pfcp_send_bearer_modification_request( + bearer, NULL, OGS_PFCP_MODIFY_REMOVE, + OGS_NAS_PROCEDURE_TRANSACTION_IDENTITY_UNASSIGNED, + OGS_GTP2_CAUSE_UNDEFINED_VALUE)); + return; + } + + /******************** + * Check ALL Context + ********************/ + ogs_assert(bearer); + ogs_assert(sess); + /* Find the Bearer by PGW-S5U-TEID */ ogs_assert(pgw_s5u_teid); bearer = smf_bearer_find_by_pgw_s5u_teid(sess, be32toh(pgw_s5u_teid->teid)); @@ -549,25 +629,46 @@ void smf_s5c_handle_update_bearer_response( { int rv; uint8_t cause_value; + ogs_gtp2_cause_t *cause = NULL; uint64_t gtp_flags = 0; uint64_t pfcp_flags = 0; smf_bearer_t *bearer = NULL; - ogs_assert(xact); ogs_assert(rsp); - gtp_flags = xact->update_flags; - ogs_assert(gtp_flags); - - bearer = xact->data; - ogs_assert(bearer); ogs_debug("Update Bearer Response"); - cause_value = OGS_GTP2_CAUSE_REQUEST_ACCEPTED; + /******************** + * Check Transaction + ********************/ + ogs_assert(xact); + gtp_flags = xact->update_flags; + ogs_assert(gtp_flags); + bearer = xact->data; + ogs_assert(bearer); rv = ogs_gtp_xact_commit(xact); ogs_expect(rv == OGS_OK); + /************************ + * Check Session Context + ************************/ + cause_value = OGS_GTP2_CAUSE_REQUEST_ACCEPTED; + + if (!sess) { + ogs_error("No Context in TEID"); + cause_value = OGS_GTP2_CAUSE_CONTEXT_NOT_FOUND; + } + + if (cause_value != OGS_GTP2_CAUSE_REQUEST_ACCEPTED) { + return; + } + + /***************************************** + * Check Mandatory/Conditional IE Missing + *****************************************/ + ogs_assert(cause_value == OGS_GTP2_CAUSE_REQUEST_ACCEPTED); + if (rsp->bearer_contexts.presence == 0) { ogs_error("No Bearer"); cause_value = OGS_GTP2_CAUSE_MANDATORY_IE_MISSING; @@ -577,45 +678,49 @@ void smf_s5c_handle_update_bearer_response( cause_value = OGS_GTP2_CAUSE_MANDATORY_IE_MISSING; } - if (!sess) { - ogs_warn("No Context in TEID"); - - sess = bearer->sess; - ogs_assert(sess); - - cause_value = OGS_GTP2_CAUSE_CONTEXT_NOT_FOUND; - } - - if (rsp->cause.presence) { - ogs_gtp2_cause_t *cause = rsp->cause.data; - ogs_assert(cause); - - cause_value = cause->value; - if (cause_value == OGS_GTP2_CAUSE_REQUEST_ACCEPTED) { - if (rsp->bearer_contexts.cause.presence) { - cause = rsp->bearer_contexts.cause.data; - ogs_assert(cause); - - cause_value = cause->value; - } else { - ogs_error("No Cause"); - cause_value = OGS_GTP2_CAUSE_MANDATORY_IE_MISSING; - } - } else { - ogs_warn("GTP Failed [CAUSE:%d]", cause_value); - } - } else { + if (rsp->cause.presence == 0) { ogs_error("No Cause"); cause_value = OGS_GTP2_CAUSE_MANDATORY_IE_MISSING; } - - ogs_debug(" SGW_S5C_TEID[0x%x] SMF_N4_TEID[0x%x]", - sess->sgw_s5c_teid, sess->smf_n4_teid); + if (rsp->bearer_contexts.cause.presence == 0) { + ogs_error("No Bearer Cause"); + cause_value = OGS_GTP2_CAUSE_MANDATORY_IE_MISSING; + } if (cause_value != OGS_GTP2_CAUSE_REQUEST_ACCEPTED) { return; } + /******************** + * Check Cause Value + ********************/ + ogs_assert(cause_value == OGS_GTP2_CAUSE_REQUEST_ACCEPTED); + + cause = rsp->bearer_contexts.cause.data; + ogs_assert(cause); + cause_value = cause->value; + if (cause_value != OGS_GTP2_CAUSE_REQUEST_ACCEPTED) { + ogs_error("GTP Failed [Bearer-CAUSE:%d]", cause_value); + return; + } + + cause = rsp->cause.data; + ogs_assert(cause); + cause_value = cause->value; + if (cause_value != OGS_GTP2_CAUSE_REQUEST_ACCEPTED) { + ogs_error("GTP Failed [CAUSE:%d]", cause_value); + return; + } + + /******************** + * Check ALL Context + ********************/ + ogs_assert(sess); + ogs_assert(bearer); + + ogs_debug(" SGW_S5C_TEID[0x%x] SMF_N4_TEID[0x%x]", + sess->sgw_s5c_teid, sess->smf_n4_teid); + ogs_debug("Update Bearer Response : SGW[0x%x] --> SMF[0x%x]", sess->sgw_s5c_teid, sess->smf_n4_teid); @@ -646,27 +751,32 @@ bool smf_s5c_handle_delete_bearer_response( uint8_t cause_value; smf_bearer_t *bearer = NULL; - ogs_assert(xact); ogs_assert(rsp); ogs_debug("Delete Bearer Response"); - cause_value = OGS_GTP2_CAUSE_REQUEST_ACCEPTED; - + /******************** + * Check Transaction + ********************/ + ogs_assert(xact); bearer = xact->data; ogs_assert(bearer); rv = ogs_gtp_xact_commit(xact); ogs_expect(rv == OGS_OK); - if (!sess) { - ogs_warn("No Context in TEID"); + /************************ + * Check Session Context + ************************/ + if (!sess) + ogs_error("No Context in TEID"); - sess = bearer->sess; - ogs_assert(sess); - - cause_value = OGS_GTP2_CAUSE_CONTEXT_NOT_FOUND; - } + /******************** + * Check ALL Context + ********************/ + ogs_assert(bearer); + sess = bearer->sess; + ogs_assert(sess); if (rsp->linked_eps_bearer_id.presence) { /* @@ -689,7 +799,6 @@ bool smf_s5c_handle_delete_bearer_response( } } else { ogs_error("No Cause"); - cause_value = OGS_GTP2_CAUSE_MANDATORY_IE_MISSING; } /* Release entire session: */ return true; @@ -724,17 +833,18 @@ bool smf_s5c_handle_delete_bearer_response( cause = rsp->bearer_contexts.cause.data; ogs_assert(cause); - cause_value = cause->value; + if (cause_value == OGS_GTP2_CAUSE_REQUEST_ACCEPTED) { + } else { + ogs_error("GTP Failed [CAUSE:%d]", cause_value); + } } else { ogs_error("No Cause"); - cause_value = OGS_GTP2_CAUSE_MANDATORY_IE_MISSING; } } else { - ogs_warn("GTP Failed [CAUSE:%d]", cause_value); + ogs_error("GTP Failed [CAUSE:%d]", cause_value); } } else { ogs_error("No Cause"); - cause_value = OGS_GTP2_CAUSE_MANDATORY_IE_MISSING; } ogs_debug(" SGW_S5C_TEID[0x%x] SMF_N4_TEID[0x%x]", @@ -865,15 +975,50 @@ void smf_s5c_handle_bearer_resource_command( int tft_delete = 0; ogs_assert(xact); - ogs_assert(sess); ogs_assert(cmd); - ogs_debug("[PGW] Bearer Resource Command"); - ogs_debug(" SGW_S5C_TEID[0x%x] PGW_S5C_TEID[0x%x]", - sess->sgw_s5c_teid, sess->smf_n4_teid); + ogs_debug("Bearer Resource Command"); + /************************ + * Check Session Context + ************************/ cause_value = OGS_GTP2_CAUSE_REQUEST_ACCEPTED; + if (!sess) { + ogs_error("No Context"); + cause_value = OGS_GTP2_CAUSE_CONTEXT_NOT_FOUND; + } else { + if (cmd->linked_eps_bearer_id.presence == 0) { + ogs_error("No EPS Bearer ID"); + cause_value = OGS_GTP2_CAUSE_MANDATORY_IE_MISSING; + } + + if (cause_value == OGS_GTP2_CAUSE_REQUEST_ACCEPTED) { + uint8_t ebi = cmd->linked_eps_bearer_id.u8; + + if (cmd->eps_bearer_id.presence) + ebi = cmd->eps_bearer_id.u8; + + bearer = smf_bearer_find_by_ebi(sess, ebi); + if (!bearer) { + ogs_error("No Context for Linked EPS Bearer ID[%d:%d]", + cmd->linked_eps_bearer_id.u8, ebi); + cause_value = OGS_GTP2_CAUSE_CONTEXT_NOT_FOUND; + } + } + } + + if (cause_value != OGS_GTP2_CAUSE_REQUEST_ACCEPTED) { + ogs_gtp2_send_error_message(xact, sess ? sess->sgw_s5c_teid : 0, + OGS_GTP2_BEARER_RESOURCE_FAILURE_INDICATION_TYPE, cause_value); + return; + } + + /***************************************** + * Check Mandatory/Conditional IE Missing + *****************************************/ + ogs_assert(cause_value == OGS_GTP2_CAUSE_REQUEST_ACCEPTED); + if (cmd->procedure_transaction_id.presence == 0) { ogs_error("No PTI"); cause_value = OGS_GTP2_CAUSE_MANDATORY_IE_MISSING; @@ -888,35 +1033,20 @@ void smf_s5c_handle_bearer_resource_command( cause_value = OGS_GTP2_CAUSE_MANDATORY_IE_MISSING; } - if (!sess) { - ogs_warn("No Context"); - cause_value = OGS_GTP2_CAUSE_CONTEXT_NOT_FOUND; - } - - if (cause_value == OGS_GTP2_CAUSE_REQUEST_ACCEPTED) { - uint8_t ebi = cmd->linked_eps_bearer_id.u8; - - if (cmd->eps_bearer_id.presence) - ebi = cmd->eps_bearer_id.u8; - - bearer = smf_bearer_find_by_ebi(sess, ebi); - if (!bearer) - ogs_error("No Context for Linked EPS Bearer ID[%d]", - cmd->linked_eps_bearer_id.u8); - } - - if (!bearer) { - ogs_error("No Context"); - cause_value = OGS_GTP2_CAUSE_CONTEXT_NOT_FOUND; - } - if (cause_value != OGS_GTP2_CAUSE_REQUEST_ACCEPTED) { ogs_gtp2_send_error_message(xact, sess ? sess->sgw_s5c_teid : 0, OGS_GTP2_BEARER_RESOURCE_FAILURE_INDICATION_TYPE, cause_value); return; } + /******************** + * Check ALL Context + ********************/ ogs_assert(bearer); + ogs_assert(sess); + + ogs_debug(" SGW_S5C_TEID[0x%x] PGW_S5C_TEID[0x%x]", + sess->sgw_s5c_teid, sess->smf_n4_teid); decoded = ogs_gtp2_parse_tft(&tft, &cmd->traffic_aggregate_description); ogs_assert(cmd->traffic_aggregate_description.len == decoded); diff --git a/src/smf/smf-sm.c b/src/smf/smf-sm.c index 8c4b7f07d..f4ab787ab 100644 --- a/src/smf/smf-sm.c +++ b/src/smf/smf-sm.c @@ -732,7 +732,10 @@ void smf_state_operational(ogs_fsm_t *s, smf_event_t *e) ogs_sbi_xact_remove(sbi_xact); sess = smf_sess_cycle(sess); - ogs_assert(sess); + if (!sess) { + ogs_error("Session has already been removed"); + break; + } smf_ue = sess->smf_ue; ogs_assert(smf_ue); smf_ue = smf_ue_cycle(smf_ue); diff --git a/src/upf/pfcp-path.c b/src/upf/pfcp-path.c index 5ca27e9ab..29bed3af4 100644 --- a/src/upf/pfcp-path.c +++ b/src/upf/pfcp-path.c @@ -277,12 +277,14 @@ int upf_pfcp_send_session_report_request( h.type = OGS_PFCP_SESSION_REPORT_REQUEST_TYPE; h.seid = sess->smf_n4_seid; + xact = ogs_pfcp_xact_local_create(sess->pfcp_node, sess_timeout, sess); + ogs_expect_or_return_val(xact, OGS_ERROR); + n4buf = ogs_pfcp_build_session_report_request(h.type, report); ogs_expect_or_return_val(n4buf, OGS_ERROR); - xact = ogs_pfcp_xact_local_create( - sess->pfcp_node, &h, n4buf, sess_timeout, sess); - ogs_expect_or_return_val(xact, OGS_ERROR); + rv = ogs_pfcp_xact_update_tx(xact, &h, n4buf); + ogs_expect_or_return_val(rv == OGS_OK, OGS_ERROR); rv = ogs_pfcp_xact_commit(xact); ogs_expect(rv == OGS_OK);