[GTP2] Fixed handling multi-bearer messages(#1498)

This commit is contained in:
Sukchan Lee 2022-04-29 21:28:16 +09:00
parent 41f743af62
commit de2ecd6400
43 changed files with 2894 additions and 1755 deletions

View File

@ -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 */
/*

View File

@ -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;

View File

@ -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(&gtp_message->h, pkbuf->data - size, size);
memcpy(&gtp2_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(&gtp_message->echo_request,
rv = ogs_tlv_parse_msg(&gtp2_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(&gtp_message->echo_response,
rv = ogs_tlv_parse_msg(&gtp2_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(&gtp_message->create_session_request,
rv = ogs_tlv_parse_msg(&gtp2_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(&gtp_message->create_session_response,
rv = ogs_tlv_parse_msg(&gtp2_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(&gtp_message->modify_bearer_request,
rv = ogs_tlv_parse_msg(&gtp2_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(&gtp_message->modify_bearer_response,
rv = ogs_tlv_parse_msg(&gtp2_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(&gtp_message->delete_session_request,
rv = ogs_tlv_parse_msg(&gtp2_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(&gtp_message->delete_session_response,
rv = ogs_tlv_parse_msg(&gtp2_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(&gtp_message->modify_bearer_command,
rv = ogs_tlv_parse_msg(&gtp2_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(&gtp_message->modify_bearer_failure_indication,
rv = ogs_tlv_parse_msg(&gtp2_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(&gtp_message->delete_bearer_command,
rv = ogs_tlv_parse_msg(&gtp2_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(&gtp_message->delete_bearer_failure_indication,
rv = ogs_tlv_parse_msg(&gtp2_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(&gtp_message->bearer_resource_command,
rv = ogs_tlv_parse_msg(&gtp2_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(&gtp_message->bearer_resource_failure_indication,
rv = ogs_tlv_parse_msg(&gtp2_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(&gtp_message->downlink_data_notification_failure_indication,
rv = ogs_tlv_parse_msg(&gtp2_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(&gtp_message->create_bearer_request,
rv = ogs_tlv_parse_msg(&gtp2_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(&gtp_message->create_bearer_response,
rv = ogs_tlv_parse_msg(&gtp2_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(&gtp_message->update_bearer_request,
rv = ogs_tlv_parse_msg(&gtp2_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(&gtp_message->update_bearer_response,
rv = ogs_tlv_parse_msg(&gtp2_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(&gtp_message->delete_bearer_request,
rv = ogs_tlv_parse_msg(&gtp2_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(&gtp_message->delete_bearer_response,
rv = ogs_tlv_parse_msg(&gtp2_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(&gtp_message->create_indirect_data_forwarding_tunnel_request,
rv = ogs_tlv_parse_msg(&gtp2_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(&gtp_message->create_indirect_data_forwarding_tunnel_response,
rv = ogs_tlv_parse_msg(&gtp2_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(&gtp_message->delete_indirect_data_forwarding_tunnel_request,
rv = ogs_tlv_parse_msg(&gtp2_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(&gtp_message->delete_indirect_data_forwarding_tunnel_response,
rv = ogs_tlv_parse_msg(&gtp2_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(&gtp_message->release_access_bearers_request,
rv = ogs_tlv_parse_msg(&gtp2_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(&gtp_message->release_access_bearers_response,
rv = ogs_tlv_parse_msg(&gtp2_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(&gtp_message->downlink_data_notification,
rv = ogs_tlv_parse_msg(&gtp2_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(&gtp_message->downlink_data_notification_acknowledge,
rv = ogs_tlv_parse_msg(&gtp2_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(&gtp_message->modify_access_bearers_request,
rv = ogs_tlv_parse_msg(&gtp2_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(&gtp_message->modify_access_bearers_response,
rv = ogs_tlv_parse_msg(&gtp2_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,
&gtp_message->echo_request, OGS_TLV_MODE_T1_L2_I1);
&gtp2_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,
&gtp_message->echo_response, OGS_TLV_MODE_T1_L2_I1);
&gtp2_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,
&gtp_message->create_session_request, OGS_TLV_MODE_T1_L2_I1);
&gtp2_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,
&gtp_message->create_session_response, OGS_TLV_MODE_T1_L2_I1);
&gtp2_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,
&gtp_message->modify_bearer_request, OGS_TLV_MODE_T1_L2_I1);
&gtp2_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,
&gtp_message->modify_bearer_response, OGS_TLV_MODE_T1_L2_I1);
&gtp2_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,
&gtp_message->delete_session_request, OGS_TLV_MODE_T1_L2_I1);
&gtp2_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,
&gtp_message->delete_session_response, OGS_TLV_MODE_T1_L2_I1);
&gtp2_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,
&gtp_message->modify_bearer_command, OGS_TLV_MODE_T1_L2_I1);
&gtp2_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,
&gtp_message->modify_bearer_failure_indication, OGS_TLV_MODE_T1_L2_I1);
&gtp2_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,
&gtp_message->delete_bearer_command, OGS_TLV_MODE_T1_L2_I1);
&gtp2_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,
&gtp_message->delete_bearer_failure_indication, OGS_TLV_MODE_T1_L2_I1);
&gtp2_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,
&gtp_message->bearer_resource_command, OGS_TLV_MODE_T1_L2_I1);
&gtp2_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,
&gtp_message->bearer_resource_failure_indication, OGS_TLV_MODE_T1_L2_I1);
&gtp2_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,
&gtp_message->downlink_data_notification_failure_indication, OGS_TLV_MODE_T1_L2_I1);
&gtp2_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,
&gtp_message->create_bearer_request, OGS_TLV_MODE_T1_L2_I1);
&gtp2_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,
&gtp_message->create_bearer_response, OGS_TLV_MODE_T1_L2_I1);
&gtp2_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,
&gtp_message->update_bearer_request, OGS_TLV_MODE_T1_L2_I1);
&gtp2_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,
&gtp_message->update_bearer_response, OGS_TLV_MODE_T1_L2_I1);
&gtp2_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,
&gtp_message->delete_bearer_request, OGS_TLV_MODE_T1_L2_I1);
&gtp2_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,
&gtp_message->delete_bearer_response, OGS_TLV_MODE_T1_L2_I1);
&gtp2_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,
&gtp_message->create_indirect_data_forwarding_tunnel_request, OGS_TLV_MODE_T1_L2_I1);
&gtp2_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,
&gtp_message->create_indirect_data_forwarding_tunnel_response, OGS_TLV_MODE_T1_L2_I1);
&gtp2_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,
&gtp_message->delete_indirect_data_forwarding_tunnel_request, OGS_TLV_MODE_T1_L2_I1);
&gtp2_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,
&gtp_message->delete_indirect_data_forwarding_tunnel_response, OGS_TLV_MODE_T1_L2_I1);
&gtp2_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,
&gtp_message->release_access_bearers_request, OGS_TLV_MODE_T1_L2_I1);
&gtp2_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,
&gtp_message->release_access_bearers_response, OGS_TLV_MODE_T1_L2_I1);
&gtp2_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,
&gtp_message->downlink_data_notification, OGS_TLV_MODE_T1_L2_I1);
&gtp2_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,
&gtp_message->downlink_data_notification_acknowledge, OGS_TLV_MODE_T1_L2_I1);
&gtp2_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,
&gtp_message->modify_access_bearers_request, OGS_TLV_MODE_T1_L2_I1);
&gtp2_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,
&gtp_message->modify_access_bearers_response, OGS_TLV_MODE_T1_L2_I1);
&gtp2_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;
}

View File

@ -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;

View File

@ -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(&gtp2_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()

View File

@ -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);

View File

@ -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);

View File

@ -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,

View File

@ -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);

View File

@ -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 *)

View File

@ -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);

View File

@ -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;

View File

@ -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

View File

@ -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;

View File

@ -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;

View File

@ -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(

View File

@ -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 = &gtp_message.create_session_request;
ogs_gtp2_create_session_request_t *req =
&gtp_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(&gtp_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 = &gtp_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(&gtp_message, 0, sizeof(ogs_gtp2_message_t));
req = &gtp_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 = &gtp_message.delete_session_request;
ogs_gtp2_delete_session_request_t *req =
&gtp_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(&gtp_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 = &gtp_message.create_bearer_response;
ogs_gtp2_create_bearer_response_t *rsp =
&gtp_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(&gtp_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 = &gtp_message.update_bearer_response;
ogs_gtp2_update_bearer_response_t *rsp =
&gtp_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(&gtp_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(&gtp_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 =
&gtp_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 =
&gtp_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 =
&gtp_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(&gtp_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) {

View File

@ -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(

File diff suppressed because it is too large Load Diff

View File

@ -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

View File

@ -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, &gtp_message.create_session_response);
xact, sgw_ue, &gtp_message.create_session_response);
break;
case OGS_GTP2_MODIFY_BEARER_RESPONSE_TYPE:
mme_s11_handle_modify_bearer_response(
xact, mme_ue, &gtp_message.modify_bearer_response);
xact, sgw_ue, &gtp_message.modify_bearer_response);
break;
case OGS_GTP2_DELETE_SESSION_RESPONSE_TYPE:
mme_s11_handle_delete_session_response(
xact, mme_ue, &gtp_message.delete_session_response);
xact, sgw_ue, &gtp_message.delete_session_response);
break;
case OGS_GTP2_CREATE_BEARER_REQUEST_TYPE:
mme_s11_handle_create_bearer_request(
xact, mme_ue, &gtp_message.create_bearer_request);
xact, sgw_ue, &gtp_message.create_bearer_request);
break;
case OGS_GTP2_UPDATE_BEARER_REQUEST_TYPE:
mme_s11_handle_update_bearer_request(
xact, mme_ue, &gtp_message.update_bearer_request);
xact, sgw_ue, &gtp_message.update_bearer_request);
break;
case OGS_GTP2_DELETE_BEARER_REQUEST_TYPE:
mme_s11_handle_delete_bearer_request(
xact, mme_ue, &gtp_message.delete_bearer_request);
xact, sgw_ue, &gtp_message.delete_bearer_request);
break;
case OGS_GTP2_RELEASE_ACCESS_BEARERS_RESPONSE_TYPE:
mme_s11_handle_release_access_bearers_response(
xact, mme_ue, &gtp_message.release_access_bearers_response);
xact, sgw_ue, &gtp_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, &gtp_message.downlink_data_notification);
xact, sgw_ue, &gtp_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,
&gtp_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,
&gtp_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,
&gtp_message.bearer_resource_failure_indication);
break;
default:

View File

@ -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);
}
}

View File

@ -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
}

View File

@ -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(

View File

@ -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,

View File

@ -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;

View File

@ -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);

View File

@ -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);

View File

@ -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);

File diff suppressed because it is too large Load Diff

View File

@ -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);

View File

@ -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) {

View File

@ -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);

View File

@ -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 = &gtp_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, &gtp_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

View File

@ -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;
}
}

View File

@ -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);
}

View File

@ -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);

View File

@ -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);

View File

@ -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);

View File

@ -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;

View File

@ -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);

View File

@ -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);

View File

@ -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);