X2 handover with SGW change (#1367, #1459)

This commit is contained in:
Sukchan Lee 2022-05-12 22:52:36 +09:00
parent 11d4be1779
commit 4d2f7726b9
72 changed files with 2146 additions and 1213 deletions

View File

@ -20,7 +20,7 @@
/******************************************************************************* /*******************************************************************************
* This file had been created by gtp-tlv.py script v0.1.0 * This file had been created by gtp-tlv.py script v0.1.0
* Please do not modify this file but regenerate it via script. * Please do not modify this file but regenerate it via script.
* Created on: 2022-04-22 03:19:22.029355 by acetcom * Created on: 2022-05-01 15:20:04.462265 by acetcom
* from 29274-g30.docx * from 29274-g30.docx
******************************************************************************/ ******************************************************************************/
@ -2063,6 +2063,7 @@ ogs_tlv_desc_t ogs_gtp2_tlv_desc_create_session_request =
&ogs_gtp2_tlv_desc_twmi_0, &ogs_gtp2_tlv_desc_twmi_0,
&ogs_gtp2_tlv_desc_pco_0, &ogs_gtp2_tlv_desc_pco_0,
&ogs_gtp2_tlv_desc_bearer_context_0, &ogs_gtp2_tlv_desc_bearer_context_0,
&ogs_tlv_desc_more8,
&ogs_gtp2_tlv_desc_bearer_context_1, &ogs_gtp2_tlv_desc_bearer_context_1,
&ogs_gtp2_tlv_desc_trace_information_0, &ogs_gtp2_tlv_desc_trace_information_0,
&ogs_gtp2_tlv_desc_recovery_0, &ogs_gtp2_tlv_desc_recovery_0,
@ -2128,6 +2129,7 @@ ogs_tlv_desc_t ogs_gtp2_tlv_desc_create_session_response =
&ogs_gtp2_tlv_desc_ebi_0, &ogs_gtp2_tlv_desc_ebi_0,
&ogs_gtp2_tlv_desc_pco_0, &ogs_gtp2_tlv_desc_pco_0,
&ogs_gtp2_tlv_desc_bearer_context_0, &ogs_gtp2_tlv_desc_bearer_context_0,
&ogs_tlv_desc_more8,
&ogs_gtp2_tlv_desc_bearer_context_1, &ogs_gtp2_tlv_desc_bearer_context_1,
&ogs_gtp2_tlv_desc_recovery_0, &ogs_gtp2_tlv_desc_recovery_0,
&ogs_gtp2_tlv_desc_fqdn_0, &ogs_gtp2_tlv_desc_fqdn_0,

View File

@ -20,7 +20,7 @@
/******************************************************************************* /*******************************************************************************
* This file had been created by gtp-tlv.py script v0.1.0 * This file had been created by gtp-tlv.py script v0.1.0
* Please do not modify this file but regenerate it via script. * Please do not modify this file but regenerate it via script.
* Created on: 2022-04-22 03:19:22.024556 by acetcom * Created on: 2022-05-01 15:20:04.456902 by acetcom
* from 29274-g30.docx * from 29274-g30.docx
******************************************************************************/ ******************************************************************************/
@ -758,7 +758,7 @@ typedef struct ogs_gtp2_create_session_request_s {
ogs_gtp2_tlv_ebi_t linked_eps_bearer_id; ogs_gtp2_tlv_ebi_t linked_eps_bearer_id;
ogs_gtp2_tlv_twmi_t trusted_wlan_mode_indication; ogs_gtp2_tlv_twmi_t trusted_wlan_mode_indication;
ogs_gtp2_tlv_pco_t protocol_configuration_options; ogs_gtp2_tlv_pco_t protocol_configuration_options;
ogs_gtp2_tlv_bearer_context_t bearer_contexts_to_be_created; ogs_gtp2_tlv_bearer_context_t bearer_contexts_to_be_created[OGS_BEARER_PER_UE];
ogs_gtp2_tlv_bearer_context_t bearer_contexts_to_be_removed; ogs_gtp2_tlv_bearer_context_t bearer_contexts_to_be_removed;
ogs_gtp2_tlv_trace_information_t trace_information; ogs_gtp2_tlv_trace_information_t trace_information;
ogs_gtp2_tlv_recovery_t recovery; ogs_gtp2_tlv_recovery_t recovery;
@ -818,7 +818,7 @@ typedef struct ogs_gtp2_create_session_response_s {
ogs_gtp2_tlv_ambr_t aggregate_maximum_bit_rate; ogs_gtp2_tlv_ambr_t aggregate_maximum_bit_rate;
ogs_gtp2_tlv_ebi_t linked_eps_bearer_id; ogs_gtp2_tlv_ebi_t linked_eps_bearer_id;
ogs_gtp2_tlv_pco_t protocol_configuration_options; ogs_gtp2_tlv_pco_t protocol_configuration_options;
ogs_gtp2_tlv_bearer_context_t bearer_contexts_created; ogs_gtp2_tlv_bearer_context_t bearer_contexts_created[OGS_BEARER_PER_UE];
ogs_gtp2_tlv_bearer_context_t bearer_contexts_marked_for_removal; ogs_gtp2_tlv_bearer_context_t bearer_contexts_marked_for_removal;
ogs_gtp2_tlv_recovery_t recovery; ogs_gtp2_tlv_recovery_t recovery;
ogs_gtp2_tlv_fqdn_t charging_gateway_name; ogs_gtp2_tlv_fqdn_t charging_gateway_name;
@ -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_f_teid_t sender_f_teid_for_control_plane;
ogs_gtp2_tlv_ambr_t aggregate_maximum_bit_rate; ogs_gtp2_tlv_ambr_t aggregate_maximum_bit_rate;
ogs_gtp2_tlv_delay_value_t delay_downlink_packet_notification_request; ogs_gtp2_tlv_delay_value_t delay_downlink_packet_notification_request;
ogs_gtp2_tlv_bearer_context_t bearer_contexts_to_be_modified[8]; ogs_gtp2_tlv_bearer_context_t bearer_contexts_to_be_modified[OGS_BEARER_PER_UE];
ogs_gtp2_tlv_bearer_context_t bearer_contexts_to_be_removed; ogs_gtp2_tlv_bearer_context_t bearer_contexts_to_be_removed;
ogs_gtp2_tlv_recovery_t recovery; ogs_gtp2_tlv_recovery_t recovery;
ogs_gtp2_tlv_ue_time_zone_t ue_time_zone; 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_ebi_t linked_eps_bearer_id;
ogs_gtp2_tlv_apn_restriction_t apn_restriction; ogs_gtp2_tlv_apn_restriction_t apn_restriction;
ogs_gtp2_tlv_pco_t protocol_configuration_options; ogs_gtp2_tlv_pco_t protocol_configuration_options;
ogs_gtp2_tlv_bearer_context_t bearer_contexts_modified[8]; ogs_gtp2_tlv_bearer_context_t bearer_contexts_modified[OGS_BEARER_PER_UE];
ogs_gtp2_tlv_bearer_context_t bearer_contexts_marked_for_removal; ogs_gtp2_tlv_bearer_context_t bearer_contexts_marked_for_removal;
ogs_gtp2_tlv_change_reporting_action_t change_reporting_action; ogs_gtp2_tlv_change_reporting_action_t change_reporting_action;
ogs_gtp2_tlv_csg_information_reporting_action_t csg_information_reporting_action; ogs_gtp2_tlv_csg_information_reporting_action_t csg_information_reporting_action;
@ -1160,14 +1160,14 @@ typedef struct ogs_gtp2_create_indirect_data_forwarding_tunnel_request_s {
ogs_gtp2_tlv_mei_t me_identity; ogs_gtp2_tlv_mei_t me_identity;
ogs_gtp2_tlv_indication_t indication_flags; ogs_gtp2_tlv_indication_t indication_flags;
ogs_gtp2_tlv_f_teid_t sender_f_teid_for_control_plane; ogs_gtp2_tlv_f_teid_t sender_f_teid_for_control_plane;
ogs_gtp2_tlv_bearer_context_t bearer_contexts[8]; ogs_gtp2_tlv_bearer_context_t bearer_contexts[OGS_BEARER_PER_UE];
ogs_gtp2_tlv_recovery_t recovery; ogs_gtp2_tlv_recovery_t recovery;
} ogs_gtp2_create_indirect_data_forwarding_tunnel_request_t; } ogs_gtp2_create_indirect_data_forwarding_tunnel_request_t;
typedef struct ogs_gtp2_create_indirect_data_forwarding_tunnel_response_s { typedef struct ogs_gtp2_create_indirect_data_forwarding_tunnel_response_s {
ogs_gtp2_tlv_cause_t cause; ogs_gtp2_tlv_cause_t cause;
ogs_gtp2_tlv_f_teid_t sender_f_teid_for_control_plane; ogs_gtp2_tlv_f_teid_t sender_f_teid_for_control_plane;
ogs_gtp2_tlv_bearer_context_t bearer_contexts[8]; ogs_gtp2_tlv_bearer_context_t bearer_contexts[OGS_BEARER_PER_UE];
ogs_gtp2_tlv_recovery_t recovery; ogs_gtp2_tlv_recovery_t recovery;
} ogs_gtp2_create_indirect_data_forwarding_tunnel_response_t; } ogs_gtp2_create_indirect_data_forwarding_tunnel_response_t;

View File

@ -252,6 +252,7 @@ void ogs_gtp2_send_error_message(
tlv = &errmsg.bearer_resource_failure_indication.cause; tlv = &errmsg.bearer_resource_failure_indication.cause;
break; break;
default: default:
ogs_fatal("Invalid message[%d]", type);
ogs_assert_if_reached(); ogs_assert_if_reached();
return; return;
} }

View File

@ -580,9 +580,9 @@ for (k, v) in sorted_msg_list:
if "ies" in msg_list[k]: if "ies" in msg_list[k]:
f.write("typedef struct ogs_gtp2_" + v_lower(k) + "_s {\n") f.write("typedef struct ogs_gtp2_" + v_lower(k) + "_s {\n")
for ies in msg_list[k]["ies"]: 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') 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'): if ((k == 'Create Indirect Data Forwarding Tunnel Request' or k == 'Create Indirect Data Forwarding Tunnel Response') and ies["ie_value"] == 'Bearer Contexts') or (k == 'Create Session Request' and ies["ie_value"] == 'Bearer Contexts to be created') or (k == 'Create Session Response' and ies["ie_value"] == 'Bearer Contexts created') 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 " + \ f.write(" ogs_gtp2_tlv_" + v_lower(ies["ie_type"]) + "_t " + \
v_lower(ies["ie_value"]) + "[8];\n") v_lower(ies["ie_value"]) + "[OGS_BEARER_PER_UE];\n")
else: else:
f.write(" ogs_gtp2_tlv_" + v_lower(ies["ie_type"]) + "_t " + \ f.write(" ogs_gtp2_tlv_" + v_lower(ies["ie_type"]) + "_t " + \
v_lower(ies["ie_value"]) + ";\n") v_lower(ies["ie_value"]) + ";\n")
@ -671,7 +671,7 @@ for (k, v) in sorted_msg_list:
f.write(" 0, 0, 0, 0, {\n") f.write(" 0, 0, 0, 0, {\n")
for ies in msg_list[k]["ies"]: 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"]))) 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') 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'): if ((k == 'Create Indirect Data Forwarding Tunnel Request' or k == 'Create Indirect Data Forwarding Tunnel Response') and ies["ie_value"] == 'Bearer Contexts') or (k == 'Create Session Request' and ies["ie_value"] == 'Bearer Contexts to be created') or (k == 'Create Session Response' and ies["ie_value"] == 'Bearer Contexts created') 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(" &ogs_tlv_desc_more8,\n")
f.write(" NULL,\n") f.write(" NULL,\n")
f.write("}};\n\n") f.write("}};\n\n")

View File

@ -99,6 +99,7 @@ typedef struct ogs_gtp_xact_s {
#define OGS_GTP_DELETE_SEND_UE_CONTEXT_RELEASE_COMMAND 4 #define OGS_GTP_DELETE_SEND_UE_CONTEXT_RELEASE_COMMAND 4
#define OGS_GTP_DELETE_HANDLE_PDN_CONNECTIVITY_REQUEST 5 #define OGS_GTP_DELETE_HANDLE_PDN_CONNECTIVITY_REQUEST 5
#define OGS_GTP_DELETE_UE_CONTEXT_REMOVE 6 #define OGS_GTP_DELETE_UE_CONTEXT_REMOVE 6
#define OGS_GTP_DELETE_IN_PATH_SWITCH_REQUEST 7
int delete_action; int delete_action;
#define OGS_GTP_RELEASE_SEND_UE_CONTEXT_RELEASE_COMMAND 1 #define OGS_GTP_RELEASE_SEND_UE_CONTEXT_RELEASE_COMMAND 1

View File

@ -138,6 +138,7 @@ typedef struct ogs_pfcp_pdr_s {
uint32_t index; uint32_t index;
ogs_lnode_t to_create_node; ogs_lnode_t to_create_node;
ogs_lnode_t to_modify_node;
struct { struct {
struct { struct {

View File

@ -170,7 +170,7 @@ bool ogs_pfcp_up_handle_association_setup_response(
} }
bool ogs_pfcp_up_handle_pdr( bool ogs_pfcp_up_handle_pdr(
ogs_pfcp_pdr_t *pdr, ogs_pkbuf_t *recvbuf, ogs_pfcp_pdr_t *pdr, uint8_t type, ogs_pkbuf_t *recvbuf,
ogs_pfcp_user_plane_report_t *report) ogs_pfcp_user_plane_report_t *report)
{ {
ogs_pfcp_far_t *far = NULL; ogs_pfcp_far_t *far = NULL;
@ -178,6 +178,7 @@ bool ogs_pfcp_up_handle_pdr(
bool buffering; bool buffering;
ogs_assert(recvbuf); ogs_assert(recvbuf);
ogs_assert(type);
ogs_assert(pdr); ogs_assert(pdr);
ogs_assert(report); ogs_assert(report);
@ -198,7 +199,7 @@ bool ogs_pfcp_up_handle_pdr(
if (far->apply_action & OGS_PFCP_APPLY_ACTION_FORW) { if (far->apply_action & OGS_PFCP_APPLY_ACTION_FORW) {
/* Forward packet */ /* Forward packet */
ogs_pfcp_send_g_pdu(pdr, sendbuf); ogs_pfcp_send_g_pdu(pdr, type, sendbuf);
} else if (far->apply_action & OGS_PFCP_APPLY_ACTION_BUFF) { } else if (far->apply_action & OGS_PFCP_APPLY_ACTION_BUFF) {

View File

@ -46,7 +46,7 @@ bool ogs_pfcp_up_handle_association_setup_response(
ogs_pfcp_association_setup_response_t *req); ogs_pfcp_association_setup_response_t *req);
bool ogs_pfcp_up_handle_pdr( bool ogs_pfcp_up_handle_pdr(
ogs_pfcp_pdr_t *pdr, ogs_pkbuf_t *recvbuf, ogs_pfcp_pdr_t *pdr, uint8_t type, ogs_pkbuf_t *recvbuf,
ogs_pfcp_user_plane_report_t *report); ogs_pfcp_user_plane_report_t *report);
bool ogs_pfcp_up_handle_error_indication( bool ogs_pfcp_up_handle_error_indication(
ogs_pfcp_far_t *far, ogs_pfcp_user_plane_report_t *report); ogs_pfcp_far_t *far, ogs_pfcp_user_plane_report_t *report);

View File

@ -283,7 +283,8 @@ int ogs_pfcp_up_send_association_setup_response(ogs_pfcp_xact_t *xact,
return rv; return rv;
} }
void ogs_pfcp_send_g_pdu(ogs_pfcp_pdr_t *pdr, ogs_pkbuf_t *sendbuf) void ogs_pfcp_send_g_pdu(
ogs_pfcp_pdr_t *pdr, uint8_t type, ogs_pkbuf_t *sendbuf)
{ {
ogs_gtp_node_t *gnode = NULL; ogs_gtp_node_t *gnode = NULL;
ogs_pfcp_far_t *far = NULL; ogs_pfcp_far_t *far = NULL;
@ -292,6 +293,7 @@ void ogs_pfcp_send_g_pdu(ogs_pfcp_pdr_t *pdr, ogs_pkbuf_t *sendbuf)
ogs_gtp2_extension_header_t ext_hdesc; ogs_gtp2_extension_header_t ext_hdesc;
ogs_assert(pdr); ogs_assert(pdr);
ogs_assert(type);
ogs_assert(sendbuf); ogs_assert(sendbuf);
far = pdr->far; far = pdr->far;
@ -314,7 +316,7 @@ void ogs_pfcp_send_g_pdu(ogs_pfcp_pdr_t *pdr, ogs_pkbuf_t *sendbuf)
memset(&gtp_hdesc, 0, sizeof(gtp_hdesc)); memset(&gtp_hdesc, 0, sizeof(gtp_hdesc));
memset(&ext_hdesc, 0, sizeof(ext_hdesc)); memset(&ext_hdesc, 0, sizeof(ext_hdesc));
gtp_hdesc.type = OGS_GTPU_MSGTYPE_GPDU; gtp_hdesc.type = type;
gtp_hdesc.teid = far->outer_header_creation.teid; gtp_hdesc.teid = far->outer_header_creation.teid;
if (pdr->qer && pdr->qer->qfi) if (pdr->qer && pdr->qer->qfi)
ext_hdesc.qos_flow_identifier = pdr->qer->qfi; ext_hdesc.qos_flow_identifier = pdr->qer->qfi;
@ -374,7 +376,8 @@ void ogs_pfcp_send_buffered_packet(ogs_pfcp_pdr_t *pdr)
if (far && far->gnode) { if (far && far->gnode) {
if (far->apply_action & OGS_PFCP_APPLY_ACTION_FORW) { if (far->apply_action & OGS_PFCP_APPLY_ACTION_FORW) {
for (i = 0; i < far->num_of_buffered_packet; i++) { for (i = 0; i < far->num_of_buffered_packet; i++) {
ogs_pfcp_send_g_pdu(pdr, far->buffered_packet[i]); ogs_pfcp_send_g_pdu(
pdr, OGS_GTPU_MSGTYPE_GPDU, far->buffered_packet[i]);
} }
far->num_of_buffered_packet = 0; far->num_of_buffered_packet = 0;
} }

View File

@ -78,7 +78,8 @@ int ogs_pfcp_up_send_association_setup_request(ogs_pfcp_node_t *node,
int ogs_pfcp_up_send_association_setup_response(ogs_pfcp_xact_t *xact, int ogs_pfcp_up_send_association_setup_response(ogs_pfcp_xact_t *xact,
uint8_t cause); uint8_t cause);
void ogs_pfcp_send_g_pdu(ogs_pfcp_pdr_t *pdr, ogs_pkbuf_t *sendbuf); void ogs_pfcp_send_g_pdu(
ogs_pfcp_pdr_t *pdr, uint8_t type, ogs_pkbuf_t *sendbuf);
int ogs_pfcp_send_end_marker(ogs_pfcp_pdr_t *pdr); int ogs_pfcp_send_end_marker(ogs_pfcp_pdr_t *pdr);
void ogs_pfcp_send_buffered_packet(ogs_pfcp_pdr_t *pdr); void ogs_pfcp_send_buffered_packet(ogs_pfcp_pdr_t *pdr);

View File

@ -754,7 +754,7 @@ void amf_sess_select_nf(amf_sess_t *sess, OpenAPI_nf_type_e nf_type);
void amf_sess_select_smf(amf_sess_t *sess); void amf_sess_select_smf(amf_sess_t *sess);
#define SESSION_SYNC_DONE(__aMF, __sTATE) \ #define AMF_SESSION_SYNC_DONE(__aMF, __sTATE) \
(amf_sess_xact_state_count(__aMF, __sTATE) == 0) (amf_sess_xact_state_count(__aMF, __sTATE) == 0)
int amf_sess_xact_count(amf_ue_t *amf_ue); int amf_sess_xact_count(amf_ue_t *amf_ue);
int amf_sess_xact_state_count(amf_ue_t *amf_ue, int state); int amf_sess_xact_state_count(amf_ue_t *amf_ue, int state);

View File

@ -223,9 +223,9 @@ int amf_nsmf_pdusession_handle_update_sm_context(
sess, pdu_session_resource_setup_request, sess, pdu_session_resource_setup_request,
ogs_pkbuf_copy(n2smbuf)); ogs_pkbuf_copy(n2smbuf));
if (SESSION_SYNC_DONE(amf_ue, if (AMF_SESSION_SYNC_DONE(amf_ue,
AMF_RELEASE_SM_CONTEXT_REGISTRATION_ACCEPT) && AMF_RELEASE_SM_CONTEXT_REGISTRATION_ACCEPT) &&
SESSION_SYNC_DONE(amf_ue, AMF_SESSION_SYNC_DONE(amf_ue,
AMF_UPDATE_SM_CONTEXT_REGISTRATION_REQUEST)) { AMF_UPDATE_SM_CONTEXT_REGISTRATION_REQUEST)) {
if (!PCF_AM_POLICY_ASSOCIATED(amf_ue)) { if (!PCF_AM_POLICY_ASSOCIATED(amf_ue)) {
@ -247,9 +247,9 @@ int amf_nsmf_pdusession_handle_update_sm_context(
sess, pdu_session_resource_setup_request, sess, pdu_session_resource_setup_request,
ogs_pkbuf_copy(n2smbuf)); ogs_pkbuf_copy(n2smbuf));
if (SESSION_SYNC_DONE(amf_ue, if (AMF_SESSION_SYNC_DONE(amf_ue,
AMF_RELEASE_SM_CONTEXT_SERVICE_ACCEPT) && AMF_RELEASE_SM_CONTEXT_SERVICE_ACCEPT) &&
SESSION_SYNC_DONE(amf_ue, AMF_SESSION_SYNC_DONE(amf_ue,
AMF_UPDATE_SM_CONTEXT_SERVICE_REQUEST)) { AMF_UPDATE_SM_CONTEXT_SERVICE_REQUEST)) {
ogs_assert(OGS_OK == ogs_assert(OGS_OK ==
nas_5gs_send_service_accept(amf_ue)); nas_5gs_send_service_accept(amf_ue));
@ -261,7 +261,7 @@ int amf_nsmf_pdusession_handle_update_sm_context(
AMF_SESS_STORE_N2_TRANSFER( AMF_SESS_STORE_N2_TRANSFER(
sess, handover_request, ogs_pkbuf_copy(n2smbuf)); sess, handover_request, ogs_pkbuf_copy(n2smbuf));
if (SESSION_SYNC_DONE(amf_ue, if (AMF_SESSION_SYNC_DONE(amf_ue,
AMF_UPDATE_SM_CONTEXT_HANDOVER_REQUIRED)) { AMF_UPDATE_SM_CONTEXT_HANDOVER_REQUIRED)) {
ogs_assert(OGS_OK == ogs_assert(OGS_OK ==
ngap_send_handover_request(amf_ue)); ngap_send_handover_request(amf_ue));
@ -367,7 +367,7 @@ int amf_nsmf_pdusession_handle_update_sm_context(
sess, path_switch_request_ack, sess, path_switch_request_ack,
ogs_pkbuf_copy(n2smbuf)); ogs_pkbuf_copy(n2smbuf));
if (SESSION_SYNC_DONE(amf_ue, state)) { if (AMF_SESSION_SYNC_DONE(amf_ue, state)) {
ogs_assert(OGS_OK == ogs_assert(OGS_OK ==
ngap_send_path_switch_ack(sess)); ngap_send_path_switch_ack(sess));
@ -390,7 +390,7 @@ int amf_nsmf_pdusession_handle_update_sm_context(
AMF_SESS_STORE_N2_TRANSFER( AMF_SESS_STORE_N2_TRANSFER(
sess, handover_command, ogs_pkbuf_copy(n2smbuf)); sess, handover_command, ogs_pkbuf_copy(n2smbuf));
if (SESSION_SYNC_DONE(amf_ue, state)) { if (AMF_SESSION_SYNC_DONE(amf_ue, state)) {
ogs_assert(OGS_OK == ogs_assert(OGS_OK ==
ngap_send_handover_command(amf_ue)); ngap_send_handover_command(amf_ue));
@ -497,7 +497,7 @@ int amf_nsmf_pdusession_handle_update_sm_context(
* 6. UEContextReleaseComplete * 6. UEContextReleaseComplete
*/ */
if (SESSION_SYNC_DONE(amf_ue, state)) { if (AMF_SESSION_SYNC_DONE(amf_ue, state)) {
ogs_assert(amf_ue->deactivation.group); ogs_assert(amf_ue->deactivation.group);
ogs_assert(OGS_OK == ogs_assert(OGS_OK ==
@ -573,7 +573,7 @@ int amf_nsmf_pdusession_handle_update_sm_context(
} else if (state == AMF_UPDATE_SM_CONTEXT_HANDOVER_CANCEL) { } else if (state == AMF_UPDATE_SM_CONTEXT_HANDOVER_CANCEL) {
if (SESSION_SYNC_DONE(amf_ue, state)) { if (AMF_SESSION_SYNC_DONE(amf_ue, state)) {
ran_ue_t *source_ue = NULL, *target_ue = NULL; ran_ue_t *source_ue = NULL, *target_ue = NULL;
source_ue = amf_ue->ran_ue; source_ue = amf_ue->ran_ue;
@ -593,7 +593,7 @@ int amf_nsmf_pdusession_handle_update_sm_context(
/* Nothing to do */ /* Nothing to do */
} else if (state == AMF_REMOVE_S1_CONTEXT_BY_LO_CONNREFUSED) { } else if (state == AMF_REMOVE_S1_CONTEXT_BY_LO_CONNREFUSED) {
if (SESSION_SYNC_DONE(amf_ue, state)) { if (AMF_SESSION_SYNC_DONE(amf_ue, state)) {
ran_ue_t *ran_ue = ran_ue_cycle(amf_ue->ran_ue); ran_ue_t *ran_ue = ran_ue_cycle(amf_ue->ran_ue);
amf_ue_deassociate(amf_ue); amf_ue_deassociate(amf_ue);
@ -608,7 +608,7 @@ int amf_nsmf_pdusession_handle_update_sm_context(
} }
} else if (state == AMF_REMOVE_S1_CONTEXT_BY_RESET_ALL) { } else if (state == AMF_REMOVE_S1_CONTEXT_BY_RESET_ALL) {
if (SESSION_SYNC_DONE(amf_ue, state)) { if (AMF_SESSION_SYNC_DONE(amf_ue, state)) {
ran_ue_t *ran_ue = ran_ue_cycle(amf_ue->ran_ue); ran_ue_t *ran_ue = ran_ue_cycle(amf_ue->ran_ue);
amf_ue_deassociate(amf_ue); amf_ue_deassociate(amf_ue);
@ -631,7 +631,7 @@ int amf_nsmf_pdusession_handle_update_sm_context(
} }
} else if (state == AMF_REMOVE_S1_CONTEXT_BY_RESET_PARTIAL) { } else if (state == AMF_REMOVE_S1_CONTEXT_BY_RESET_PARTIAL) {
if (SESSION_SYNC_DONE(amf_ue, state)) { if (AMF_SESSION_SYNC_DONE(amf_ue, state)) {
ran_ue_t *iter = NULL; ran_ue_t *iter = NULL;
ran_ue_t *ran_ue = ran_ue_cycle(amf_ue->ran_ue); ran_ue_t *ran_ue = ran_ue_cycle(amf_ue->ran_ue);
@ -797,9 +797,9 @@ int amf_nsmf_pdusession_handle_release_sm_context(amf_sess_t *sess, int state)
* 2. Release All SM contexts * 2. Release All SM contexts
* 3. Registration accept * 3. Registration accept
*/ */
if (SESSION_SYNC_DONE( if (AMF_SESSION_SYNC_DONE(
amf_ue, AMF_RELEASE_SM_CONTEXT_REGISTRATION_ACCEPT) && amf_ue, AMF_RELEASE_SM_CONTEXT_REGISTRATION_ACCEPT) &&
SESSION_SYNC_DONE( AMF_SESSION_SYNC_DONE(
amf_ue, AMF_UPDATE_SM_CONTEXT_REGISTRATION_REQUEST)) { amf_ue, AMF_UPDATE_SM_CONTEXT_REGISTRATION_REQUEST)) {
if (!PCF_AM_POLICY_ASSOCIATED(amf_ue)) { if (!PCF_AM_POLICY_ASSOCIATED(amf_ue)) {
@ -820,14 +820,14 @@ int amf_nsmf_pdusession_handle_release_sm_context(amf_sess_t *sess, int state)
* 2. Release All SM contexts * 2. Release All SM contexts
* 3. Service accept * 3. Service accept
*/ */
if (SESSION_SYNC_DONE(amf_ue, AMF_RELEASE_SM_CONTEXT_SERVICE_ACCEPT) && if (AMF_SESSION_SYNC_DONE(amf_ue, AMF_RELEASE_SM_CONTEXT_SERVICE_ACCEPT) &&
SESSION_SYNC_DONE(amf_ue, AMF_UPDATE_SM_CONTEXT_SERVICE_REQUEST)) AMF_SESSION_SYNC_DONE(amf_ue, AMF_UPDATE_SM_CONTEXT_SERVICE_REQUEST))
ogs_assert(OGS_OK == ogs_assert(OGS_OK ==
nas_5gs_send_service_accept(amf_ue)); nas_5gs_send_service_accept(amf_ue));
} else { } else {
if (SESSION_SYNC_DONE(amf_ue, state)) { if (AMF_SESSION_SYNC_DONE(amf_ue, state)) {
if (state == AMF_RELEASE_SM_CONTEXT_NG_CONTEXT_REMOVE) { if (state == AMF_RELEASE_SM_CONTEXT_NG_CONTEXT_REMOVE) {
/* /*

View File

@ -119,7 +119,7 @@ void esm_state_inactive(ogs_fsm_t *s, mme_event_t *e)
mme_ue->imsi_bcd, sess->pti, bearer->ebi); mme_ue->imsi_bcd, sess->pti, bearer->ebi);
if (MME_HAVE_SGW_S1U_PATH(sess)) { if (MME_HAVE_SGW_S1U_PATH(sess)) {
ogs_assert(OGS_OK == ogs_assert(OGS_OK ==
mme_gtp_send_delete_session_request(sess, mme_gtp_send_delete_session_request(mme_ue->sgw_ue, sess,
OGS_GTP_DELETE_SEND_DEACTIVATE_BEARER_CONTEXT_REQUEST)); OGS_GTP_DELETE_SEND_DEACTIVATE_BEARER_CONTEXT_REQUEST));
} else { } else {
ogs_assert(OGS_OK == ogs_assert(OGS_OK ==
@ -306,7 +306,7 @@ void esm_state_active(ogs_fsm_t *s, mme_event_t *e)
mme_ue->imsi_bcd, sess->pti, bearer->ebi); mme_ue->imsi_bcd, sess->pti, bearer->ebi);
if (MME_HAVE_SGW_S1U_PATH(sess)) { if (MME_HAVE_SGW_S1U_PATH(sess)) {
ogs_assert(OGS_OK == ogs_assert(OGS_OK ==
mme_gtp_send_delete_session_request(sess, mme_gtp_send_delete_session_request(mme_ue->sgw_ue, sess,
OGS_GTP_DELETE_SEND_DEACTIVATE_BEARER_CONTEXT_REQUEST)); OGS_GTP_DELETE_SEND_DEACTIVATE_BEARER_CONTEXT_REQUEST));
} else { } else {
ogs_assert(OGS_OK == ogs_assert(OGS_OK ==

View File

@ -2039,14 +2039,9 @@ sgw_ue_t *sgw_ue_add(mme_sgw_t *sgw)
ogs_assert(sgw_ue); ogs_assert(sgw_ue);
memset(sgw_ue, 0, sizeof *sgw_ue); memset(sgw_ue, 0, sizeof *sgw_ue);
sgw_ue->index = ogs_pool_index(&sgw_ue_pool, sgw_ue); sgw_ue->t_s11_holding = ogs_timer_add(
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_app()->timer_mgr, mme_timer_s11_holding_timer_expire, sgw_ue);
ogs_assert(sgw_ue->t_gtp2_holding); ogs_assert(sgw_ue->t_s11_holding);
sgw_ue->sgw = sgw; sgw_ue->sgw = sgw;
@ -2065,8 +2060,8 @@ void sgw_ue_remove(sgw_ue_t *sgw_ue)
ogs_list_remove(&sgw->sgw_ue_list, sgw_ue); ogs_list_remove(&sgw->sgw_ue_list, sgw_ue);
ogs_assert(sgw_ue->t_gtp2_holding); ogs_assert(sgw_ue->t_s11_holding);
ogs_timer_delete(sgw_ue->t_gtp2_holding); ogs_timer_delete(sgw_ue->t_s11_holding);
ogs_pool_free(&sgw_ue_pool, sgw_ue); ogs_pool_free(&sgw_ue_pool, sgw_ue);
} }
@ -2092,11 +2087,6 @@ sgw_ue_t *sgw_ue_find(uint32_t index)
return ogs_pool_find(&sgw_ue_pool, 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) sgw_ue_t *sgw_ue_cycle(sgw_ue_t *sgw_ue)
{ {
return ogs_pool_cycle(&sgw_ue_pool, sgw_ue); return ogs_pool_cycle(&sgw_ue_pool, sgw_ue);
@ -2105,7 +2095,7 @@ sgw_ue_t *sgw_ue_cycle(sgw_ue_t *sgw_ue)
sgw_relocation_e sgw_ue_check_if_relocated(mme_ue_t *mme_ue) sgw_relocation_e sgw_ue_check_if_relocated(mme_ue_t *mme_ue)
{ {
enb_ue_t *enb_ue = NULL; enb_ue_t *enb_ue = NULL;
sgw_ue_t *source_ue, *target_ue = NULL; sgw_ue_t *old_source_ue = NULL, *source_ue = NULL, *target_ue = NULL;
mme_sgw_t *current = NULL, *changed = NULL; mme_sgw_t *current = NULL, *changed = NULL;
ogs_assert(mme_ue); ogs_assert(mme_ue);
@ -2120,6 +2110,13 @@ sgw_relocation_e sgw_ue_check_if_relocated(mme_ue_t *mme_ue)
changed = changed_sgw_node(current, enb_ue); changed = changed_sgw_node(current, enb_ue);
if (!changed) return SGW_WITHOUT_RELOCATION; if (!changed) return SGW_WITHOUT_RELOCATION;
/* Check if Old Source UE */
old_source_ue = sgw_ue_cycle(source_ue->source_ue);
if (old_source_ue) {
sgw_ue_source_deassociate_target(old_source_ue);
sgw_ue_remove(old_source_ue);
}
target_ue = sgw_ue_cycle(source_ue->target_ue); target_ue = sgw_ue_cycle(source_ue->target_ue);
if (target_ue) { if (target_ue) {
ogs_error("SGW-UE source has already been associated with target"); ogs_error("SGW-UE source has already been associated with target");
@ -2260,6 +2257,10 @@ mme_ue_t *mme_ue_add(enb_ue_t *enb_ue)
ogs_list_init(&mme_ue->sess_list); 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, * When used for the first time, if last node is set,
* the search is performed from the first SGW in a round-robin manner. * the search is performed from the first SGW in a round-robin manner.
@ -2438,6 +2439,11 @@ 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)); 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_find_by_message(ogs_nas_eps_message_t *message)
{ {
mme_ue_t *mme_ue = NULL; mme_ue_t *mme_ue = NULL;

View File

@ -277,7 +277,6 @@ struct sgw_ue_s {
sgw_ue_t *target_ue; sgw_ue_t *target_ue;
/* UE identity */ /* 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 */ uint32_t sgw_s11_teid; /* SGW-S11-TEID is received from SGW */
/* /*
@ -288,8 +287,8 @@ struct sgw_ue_s {
*/ */
int session_context_will_deleted; int session_context_will_deleted;
/* GTPv2-C Holding timer for removing this context */ /* S11 Holding timer for removing this context */
ogs_timer_t *t_gtp2_holding; ogs_timer_t *t_s11_holding;
/* Related Context */ /* Related Context */
union { union {
@ -351,6 +350,8 @@ struct mme_ue_s {
ogs_nas_eps_guti_t guti; ogs_nas_eps_guti_t guti;
} current, next; } current, next;
uint32_t mme_s11_teid; /* MME-S11-TEID is derived from INDEX */
uint16_t vlr_ostream_id; /* SCTP output stream id for VLR */ uint16_t vlr_ostream_id; /* SCTP output stream id for VLR */
/* UE Info */ /* UE Info */
@ -533,8 +534,8 @@ struct mme_ue_s {
#define MAX_NUM_OF_GTP_COUNTER 16 #define MAX_NUM_OF_GTP_COUNTER 16
#define GTP_COUNTER_MODIFY_BEARER_BY_PATH_SWITCH 1 #define GTP_COUNTER_CREATE_SESSION_BY_PATH_SWITCH 1
#define GTP_COUNTER_MODIFY_BEARER_BY_E_RAB_MODIFICATION 2 #define GTP_COUNTER_DELETE_SESSION_BY_PATH_SWITCH 2
struct { struct {
uint8_t request; uint8_t request;
uint8_t response; uint8_t response;
@ -638,6 +639,8 @@ typedef struct mme_bearer_s {
ogs_ip_t enb_s1u_ip; ogs_ip_t enb_s1u_ip;
uint32_t sgw_s1u_teid; uint32_t sgw_s1u_teid;
ogs_ip_t sgw_s1u_ip; ogs_ip_t sgw_s1u_ip;
uint32_t pgw_s5u_teid;
ogs_ip_t pgw_s5u_ip;
uint32_t target_s1u_teid; /* Target S1U TEID from HO-Req-Ack */ uint32_t target_s1u_teid; /* Target S1U TEID from HO-Req-Ack */
ogs_ip_t target_s1u_ip; /* Target S1U ADDR from HO-Req-Ack */ ogs_ip_t target_s1u_ip; /* Target S1U ADDR from HO-Req-Ack */
@ -734,7 +737,6 @@ sgw_ue_t *sgw_ue_add(mme_sgw_t *sgw);
void sgw_ue_remove(sgw_ue_t *sgw_ue); 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); 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(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); sgw_ue_t *sgw_ue_cycle(sgw_ue_t *sgw_ue);
typedef enum { typedef enum {
@ -758,6 +760,7 @@ 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(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_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_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); 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); int mme_ue_set_imsi(mme_ue_t *mme_ue, char *imsi_bcd);

View File

@ -747,10 +747,10 @@ static void mme_s6a_ula_cb(void *data, struct msg **msg)
if (avpch1) { if (avpch1) {
ret = fd_msg_avp_hdr(avpch1, &hdr); ret = fd_msg_avp_hdr(avpch1, &hdr);
ogs_assert(ret == 0); ogs_assert(ret == 0);
if (hdr->avp_value->os.len) { if (hdr->avp_value->os.data && hdr->avp_value->os.len) {
mme_ue->msisdn_len = hdr->avp_value->os.len; mme_ue->msisdn_len = hdr->avp_value->os.len;
memcpy(mme_ue->msisdn, memcpy(mme_ue->msisdn, hdr->avp_value->os.data,
hdr->avp_value->os.data, mme_ue->msisdn_len); ogs_min(mme_ue->msisdn_len, OGS_MAX_MSISDN_LEN));
ogs_buffer_to_bcd(mme_ue->msisdn, ogs_buffer_to_bcd(mme_ue->msisdn,
mme_ue->msisdn_len, mme_ue->msisdn_bcd); mme_ue->msisdn_len, mme_ue->msisdn_bcd);
} }
@ -769,10 +769,10 @@ static void mme_s6a_ula_cb(void *data, struct msg **msg)
if (avpch1) { if (avpch1) {
ret = fd_msg_avp_hdr(avpch1, &hdr); ret = fd_msg_avp_hdr(avpch1, &hdr);
ogs_assert(ret == 0); ogs_assert(ret == 0);
if (hdr->avp_value->os.len) { if (hdr->avp_value->os.data && hdr->avp_value->os.len) {
mme_ue->a_msisdn_len = hdr->avp_value->os.len; mme_ue->a_msisdn_len = hdr->avp_value->os.len;
memcpy(mme_ue->a_msisdn, memcpy(mme_ue->a_msisdn, hdr->avp_value->os.data,
hdr->avp_value->os.data, mme_ue->a_msisdn_len); ogs_min(mme_ue->a_msisdn_len, OGS_MAX_MSISDN_LEN));
ogs_buffer_to_bcd(mme_ue->a_msisdn, ogs_buffer_to_bcd(mme_ue->a_msisdn,
mme_ue->a_msisdn_len, mme_ue->a_msisdn_bcd); mme_ue->a_msisdn_len, mme_ue->a_msisdn_bcd);
} }

View File

@ -267,27 +267,26 @@ int mme_gtp_send_modify_bearer_request(
return rv; return rv;
} }
int mme_gtp_send_delete_session_request(mme_sess_t *sess, int action) int mme_gtp_send_delete_session_request(
sgw_ue_t *sgw_ue, mme_sess_t *sess, int action)
{ {
int rv; int rv;
ogs_pkbuf_t *s11buf = NULL; ogs_pkbuf_t *s11buf = NULL;
ogs_gtp2_header_t h; ogs_gtp2_header_t h;
ogs_gtp_xact_t *xact = NULL; ogs_gtp_xact_t *xact = NULL;
mme_ue_t *mme_ue = NULL; mme_ue_t *mme_ue = NULL;
sgw_ue_t *sgw_ue = NULL;
ogs_assert(action); ogs_assert(action);
ogs_assert(sess); ogs_assert(sess);
mme_ue = sess->mme_ue; mme_ue = sess->mme_ue;
ogs_assert(mme_ue); ogs_assert(mme_ue);
sgw_ue = mme_ue->sgw_ue;
ogs_assert(sgw_ue); ogs_assert(sgw_ue);
memset(&h, 0, sizeof(ogs_gtp2_header_t)); memset(&h, 0, sizeof(ogs_gtp2_header_t));
h.type = OGS_GTP2_DELETE_SESSION_REQUEST_TYPE; h.type = OGS_GTP2_DELETE_SESSION_REQUEST_TYPE;
h.teid = sgw_ue->sgw_s11_teid; h.teid = sgw_ue->sgw_s11_teid;
s11buf = mme_s11_build_delete_session_request(h.type, sess); s11buf = mme_s11_build_delete_session_request(h.type, sess, action);
ogs_expect_or_return_val(s11buf, OGS_ERROR); ogs_expect_or_return_val(s11buf, OGS_ERROR);
xact = ogs_gtp_xact_local_create(sgw_ue->gnode, &h, s11buf, timeout, sess); xact = ogs_gtp_xact_local_create(sgw_ue->gnode, &h, s11buf, timeout, sess);
@ -330,7 +329,7 @@ void mme_gtp_send_delete_all_sessions(mme_ue_t *mme_ue, int action)
OGS_FSM_CHECK(&bearer->sm, esm_state_pdn_will_disconnect)) { OGS_FSM_CHECK(&bearer->sm, esm_state_pdn_will_disconnect)) {
ogs_warn("PDN will disconnect[EBI:%d]", bearer->ebi); ogs_warn("PDN will disconnect[EBI:%d]", bearer->ebi);
} else { } else {
mme_gtp_send_delete_session_request(sess, action); mme_gtp_send_delete_session_request(sgw_ue, sess, action);
} }
} else { } else {
mme_sess_remove(sess); mme_sess_remove(sess);

View File

@ -32,7 +32,8 @@ void mme_gtp_close(void);
int mme_gtp_send_create_session_request(mme_sess_t *sess, int create_action); int mme_gtp_send_create_session_request(mme_sess_t *sess, int create_action);
int mme_gtp_send_modify_bearer_request( int mme_gtp_send_modify_bearer_request(
mme_ue_t *mme_ue, int uli_presence, int modify_action); mme_ue_t *mme_ue, int uli_presence, int modify_action);
int mme_gtp_send_delete_session_request(mme_sess_t *sess, int action); int mme_gtp_send_delete_session_request(
sgw_ue_t *sgw_ue, mme_sess_t *sess, int action);
void mme_gtp_send_delete_all_sessions(mme_ue_t *mme_ue, int action); void mme_gtp_send_delete_all_sessions(mme_ue_t *mme_ue, int action);
int mme_gtp_send_create_bearer_response( int mme_gtp_send_create_bearer_response(
mme_bearer_t *bearer, uint8_t cause_value); mme_bearer_t *bearer, uint8_t cause_value);

View File

@ -37,9 +37,13 @@ ogs_pkbuf_t *mme_s11_build_create_session_request(
char uli_buf[OGS_GTP2_MAX_ULI_LEN]; char uli_buf[OGS_GTP2_MAX_ULI_LEN];
ogs_gtp2_f_teid_t mme_s11_teid, pgw_s5c_teid; ogs_gtp2_f_teid_t mme_s11_teid, pgw_s5c_teid;
int len; int len;
ogs_gtp2_f_teid_t enb_s1u_teid[OGS_BEARER_PER_UE];
int enb_s1u_len[OGS_BEARER_PER_UE];
ogs_gtp2_f_teid_t pgw_s5u_teid[OGS_BEARER_PER_UE];
int pgw_s5u_len[OGS_BEARER_PER_UE];
ogs_gtp2_ambr_t ambr; ogs_gtp2_ambr_t ambr;
ogs_gtp2_bearer_qos_t bearer_qos; ogs_gtp2_bearer_qos_t bearer_qos;
char bearer_qos_buf[GTP2_BEARER_QOS_LEN]; char bearer_qos_buf[OGS_BEARER_PER_UE][GTP2_BEARER_QOS_LEN];
ogs_gtp2_ue_timezone_t ue_timezone; ogs_gtp2_ue_timezone_t ue_timezone;
struct timeval now; struct timeval now;
struct tm time_exp; struct tm time_exp;
@ -51,8 +55,6 @@ ogs_pkbuf_t *mme_s11_build_create_session_request(
session = sess->session; session = sess->session;
ogs_assert(session); ogs_assert(session);
ogs_assert(session->name); ogs_assert(session->name);
bearer = mme_default_bearer_in_sess(sess);
ogs_assert(bearer);
mme_ue = sess->mme_ue; mme_ue = sess->mme_ue;
ogs_assert(mme_ue); ogs_assert(mme_ue);
sgw_ue = mme_ue->sgw_ue; sgw_ue = mme_ue->sgw_ue;
@ -65,7 +67,7 @@ ogs_pkbuf_t *mme_s11_build_create_session_request(
ogs_debug("Create Session Request"); ogs_debug("Create Session Request");
ogs_debug(" MME_S11_TEID[%d] SGW_S11_TEID[%d]", ogs_debug(" MME_S11_TEID[%d] SGW_S11_TEID[%d]",
sgw_ue->mme_s11_teid, sgw_ue->sgw_s11_teid); mme_ue->mme_s11_teid, sgw_ue->sgw_s11_teid);
memset(&gtp_message, 0, sizeof(ogs_gtp2_message_t)); memset(&gtp_message, 0, sizeof(ogs_gtp2_message_t));
ogs_assert(mme_ue->imsi_len); ogs_assert(mme_ue->imsi_len);
@ -105,7 +107,7 @@ ogs_pkbuf_t *mme_s11_build_create_session_request(
memset(&mme_s11_teid, 0, sizeof(ogs_gtp2_f_teid_t)); 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.interface_type = OGS_GTP2_F_TEID_S11_MME_GTP_C;
mme_s11_teid.teid = htobe32(sgw_ue->mme_s11_teid); mme_s11_teid.teid = htobe32(mme_ue->mme_s11_teid);
rv = ogs_gtp2_sockaddr_to_f_teid( rv = ogs_gtp2_sockaddr_to_f_teid(
ogs_gtp_self()->gtpc_addr, ogs_gtp_self()->gtpc_addr6, ogs_gtp_self()->gtpc_addr, ogs_gtp_self()->gtpc_addr6,
&mme_s11_teid, &len); &mme_s11_teid, &len);
@ -257,20 +259,58 @@ ogs_pkbuf_t *mme_s11_build_create_session_request(
req->protocol_configuration_options.len = sess->ue_pco.length; req->protocol_configuration_options.len = sess->ue_pco.length;
} }
req->bearer_contexts_to_be_created.presence = 1; int i = 0;
req->bearer_contexts_to_be_created.eps_bearer_id.presence = 1; ogs_list_for_each(&sess->bearer_list, bearer) {
req->bearer_contexts_to_be_created.eps_bearer_id.u8 = bearer->ebi; ogs_assert(i < OGS_BEARER_PER_UE);
memset(&bearer_qos, 0, sizeof(bearer_qos)); /* Bearer Context : EBI */
bearer_qos.qci = session->qos.index; req->bearer_contexts_to_be_created[i].presence = 1;
bearer_qos.priority_level = session->qos.arp.priority_level; req->bearer_contexts_to_be_created[i].eps_bearer_id.presence = 1;
bearer_qos.pre_emption_capability = session->qos.arp.pre_emption_capability; req->bearer_contexts_to_be_created[i].eps_bearer_id.u8 = bearer->ebi;
bearer_qos.pre_emption_vulnerability =
session->qos.arp.pre_emption_vulnerability; if (create_action == OGS_GTP_CREATE_IN_PATH_SWITCH_REQUEST) {
req->bearer_contexts_to_be_created.bearer_level_qos.presence = 1;
ogs_gtp2_build_bearer_qos( /* Data Plane(DL) : ENB-S1U */
&req->bearer_contexts_to_be_created.bearer_level_qos, memset(&enb_s1u_teid[i], 0, sizeof(ogs_gtp2_f_teid_t));
&bearer_qos, bearer_qos_buf, GTP2_BEARER_QOS_LEN); 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], &enb_s1u_len[i]));
req->bearer_contexts_to_be_created[i].s1_u_enodeb_f_teid.
presence = 1;
req->bearer_contexts_to_be_created[i].s1_u_enodeb_f_teid.data =
&enb_s1u_teid[i];
req->bearer_contexts_to_be_created[i].s1_u_enodeb_f_teid.len =
enb_s1u_len[i];
/* Data Plane(DL) : PGW-S5U */
memset(&pgw_s5u_teid[i], 0, sizeof(ogs_gtp2_f_teid_t));
pgw_s5u_teid[i].interface_type = OGS_GTP2_F_TEID_S5_S8_PGW_GTP_U;
pgw_s5u_teid[i].teid = htobe32(bearer->pgw_s5u_teid);
ogs_assert(OGS_OK == ogs_gtp2_ip_to_f_teid(
&bearer->pgw_s5u_ip, &pgw_s5u_teid[i], &pgw_s5u_len[i]));
req->bearer_contexts_to_be_created[i].s5_s8_u_sgw_f_teid.
presence = 1;
req->bearer_contexts_to_be_created[i].s5_s8_u_sgw_f_teid.data =
&pgw_s5u_teid[i];
req->bearer_contexts_to_be_created[i].s5_s8_u_sgw_f_teid.len =
pgw_s5u_len[i];
}
memset(&bearer_qos, 0, sizeof(bearer_qos));
bearer_qos.qci = session->qos.index;
bearer_qos.priority_level = session->qos.arp.priority_level;
bearer_qos.pre_emption_capability =
session->qos.arp.pre_emption_capability;
bearer_qos.pre_emption_vulnerability =
session->qos.arp.pre_emption_vulnerability;
req->bearer_contexts_to_be_created[i].bearer_level_qos.presence = 1;
ogs_gtp2_build_bearer_qos(
&req->bearer_contexts_to_be_created[i].bearer_level_qos,
&bearer_qos, bearer_qos_buf[i], GTP2_BEARER_QOS_LEN);
i++;
}
/* UE Time Zone */ /* UE Time Zone */
memset(&ue_timezone, 0, sizeof(ue_timezone)); memset(&ue_timezone, 0, sizeof(ue_timezone));
@ -305,7 +345,7 @@ ogs_pkbuf_t *mme_s11_build_modify_bearer_request(
ogs_gtp2_modify_bearer_request_t *req = NULL; ogs_gtp2_modify_bearer_request_t *req = NULL;
ogs_gtp2_f_teid_t enb_s1u_teid[OGS_BEARER_PER_UE]; ogs_gtp2_f_teid_t enb_s1u_teid[OGS_BEARER_PER_UE];
int len, i; int enb_s1u_len[OGS_BEARER_PER_UE], i;
ogs_gtp2_uli_t uli; ogs_gtp2_uli_t uli;
char uli_buf[OGS_GTP2_MAX_ULI_LEN]; char uli_buf[OGS_GTP2_MAX_ULI_LEN];
@ -326,7 +366,7 @@ ogs_pkbuf_t *mme_s11_build_modify_bearer_request(
req = &gtp_message.modify_bearer_request; req = &gtp_message.modify_bearer_request;
ogs_debug(" MME_S11_TEID[%d] SGW_S11_TEID[%d]", ogs_debug(" MME_S11_TEID[%d] SGW_S11_TEID[%d]",
sgw_ue->mme_s11_teid, sgw_ue->sgw_s11_teid); mme_ue->mme_s11_teid, sgw_ue->sgw_s11_teid);
i = 0; i = 0;
ogs_list_for_each_entry( ogs_list_for_each_entry(
@ -345,12 +385,13 @@ ogs_pkbuf_t *mme_s11_build_modify_bearer_request(
memset(&enb_s1u_teid[i], 0, sizeof(ogs_gtp2_f_teid_t)); 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].interface_type = OGS_GTP2_F_TEID_S1_U_ENODEB_GTP_U;
enb_s1u_teid[i].teid = htobe32(bearer->enb_s1u_teid); enb_s1u_teid[i].teid = htobe32(bearer->enb_s1u_teid);
ogs_assert(OGS_OK == ogs_assert(OGS_OK == ogs_gtp2_ip_to_f_teid(
ogs_gtp2_ip_to_f_teid(&bearer->enb_s1u_ip, &enb_s1u_teid[i], &len)); &bearer->enb_s1u_ip, &enb_s1u_teid[i], &enb_s1u_len[i]));
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.presence = 1;
req->bearer_contexts_to_be_modified[i].s1_u_enodeb_f_teid.data = req->bearer_contexts_to_be_modified[i].s1_u_enodeb_f_teid.data =
&enb_s1u_teid[i]; &enb_s1u_teid[i];
req->bearer_contexts_to_be_modified[i].s1_u_enodeb_f_teid.len = len; req->bearer_contexts_to_be_modified[i].s1_u_enodeb_f_teid.len =
enb_s1u_len[i];
i++; i++;
} }
@ -409,7 +450,7 @@ ogs_pkbuf_t *mme_s11_build_modify_bearer_request(
} }
ogs_pkbuf_t *mme_s11_build_delete_session_request( ogs_pkbuf_t *mme_s11_build_delete_session_request(
uint8_t type, mme_sess_t *sess) uint8_t type, mme_sess_t *sess, int action)
{ {
ogs_gtp2_message_t gtp_message; ogs_gtp2_message_t gtp_message;
ogs_gtp2_delete_session_request_t *req = ogs_gtp2_delete_session_request_t *req =
@ -421,19 +462,14 @@ ogs_pkbuf_t *mme_s11_build_delete_session_request(
mme_bearer_t *bearer = NULL; mme_bearer_t *bearer = NULL;
mme_ue_t *mme_ue = NULL; mme_ue_t *mme_ue = NULL;
sgw_ue_t *sgw_ue = NULL;
ogs_assert(sess); ogs_assert(sess);
mme_ue = sess->mme_ue; mme_ue = sess->mme_ue;
ogs_assert(mme_ue); ogs_assert(mme_ue);
sgw_ue = mme_ue->sgw_ue;
ogs_assert(sgw_ue);
bearer = mme_default_bearer_in_sess(sess); bearer = mme_default_bearer_in_sess(sess);
ogs_assert(bearer); ogs_assert(bearer);
ogs_debug("Delete Session Request"); ogs_debug("Delete Session Request");
ogs_debug(" MME_S11_TEID[%d] SGW_S11_TEID[%d]",
sgw_ue->mme_s11_teid, sgw_ue->sgw_s11_teid);
memset(&gtp_message, 0, sizeof(ogs_gtp2_message_t)); memset(&gtp_message, 0, sizeof(ogs_gtp2_message_t));
@ -453,7 +489,11 @@ ogs_pkbuf_t *mme_s11_build_delete_session_request(
uli_buf, OGS_GTP2_MAX_ULI_LEN); uli_buf, OGS_GTP2_MAX_ULI_LEN);
memset(&indication, 0, sizeof(ogs_gtp2_indication_t)); memset(&indication, 0, sizeof(ogs_gtp2_indication_t));
indication.operation_indication = 1; if (action == OGS_GTP_DELETE_IN_PATH_SWITCH_REQUEST) {
indication.scope_indication = 1;
} else {
indication.operation_indication = 1;
}
req->indication_flags.presence = 1; req->indication_flags.presence = 1;
req->indication_flags.data = &indication; req->indication_flags.data = &indication;
req->indication_flags.len = sizeof(ogs_gtp2_indication_t); req->indication_flags.len = sizeof(ogs_gtp2_indication_t);
@ -490,7 +530,7 @@ ogs_pkbuf_t *mme_s11_build_create_bearer_response(
ogs_debug("Create Bearer Response"); ogs_debug("Create Bearer Response");
ogs_debug(" MME_S11_TEID[%d] SGW_S11_TEID[%d]", ogs_debug(" MME_S11_TEID[%d] SGW_S11_TEID[%d]",
sgw_ue->mme_s11_teid, sgw_ue->sgw_s11_teid); mme_ue->mme_s11_teid, sgw_ue->sgw_s11_teid);
memset(&gtp_message, 0, sizeof(ogs_gtp2_message_t)); memset(&gtp_message, 0, sizeof(ogs_gtp2_message_t));
@ -591,7 +631,7 @@ ogs_pkbuf_t *mme_s11_build_update_bearer_response(
ogs_debug("Update Bearer Response"); ogs_debug("Update Bearer Response");
ogs_debug(" MME_S11_TEID[%d] SGW_S11_TEID[%d]", ogs_debug(" MME_S11_TEID[%d] SGW_S11_TEID[%d]",
sgw_ue->mme_s11_teid, sgw_ue->sgw_s11_teid); mme_ue->mme_s11_teid, sgw_ue->sgw_s11_teid);
memset(&gtp_message, 0, sizeof(ogs_gtp2_message_t)); memset(&gtp_message, 0, sizeof(ogs_gtp2_message_t));
@ -670,7 +710,7 @@ ogs_pkbuf_t *mme_s11_build_delete_bearer_response(
ogs_debug("Delete Bearer Response"); ogs_debug("Delete Bearer Response");
ogs_debug(" MME_S11_TEID[%d] SGW_S11_TEID[%d]", ogs_debug(" MME_S11_TEID[%d] SGW_S11_TEID[%d]",
sgw_ue->mme_s11_teid, sgw_ue->sgw_s11_teid); mme_ue->mme_s11_teid, sgw_ue->sgw_s11_teid);
memset(&gtp_message, 0, sizeof(ogs_gtp2_message_t)); memset(&gtp_message, 0, sizeof(ogs_gtp2_message_t));
@ -824,7 +864,7 @@ ogs_pkbuf_t *mme_s11_build_create_indirect_data_forwarding_tunnel_request(
ogs_debug("Create Indirect Data Forwarding Tunnel Request"); ogs_debug("Create Indirect Data Forwarding Tunnel Request");
ogs_debug(" MME_S11_TEID[%d] SGW_S11_TEID[%d]", ogs_debug(" MME_S11_TEID[%d] SGW_S11_TEID[%d]",
sgw_ue->mme_s11_teid, sgw_ue->sgw_s11_teid); mme_ue->mme_s11_teid, sgw_ue->sgw_s11_teid);
memset(&gtp_message, 0, sizeof(ogs_gtp2_message_t)); memset(&gtp_message, 0, sizeof(ogs_gtp2_message_t));
@ -906,7 +946,7 @@ ogs_pkbuf_t *mme_s11_build_bearer_resource_command(
ogs_debug("Bearer Resource Command"); ogs_debug("Bearer Resource Command");
ogs_debug(" MME_S11_TEID[%d] SGW_S11_TEID[%d]", ogs_debug(" MME_S11_TEID[%d] SGW_S11_TEID[%d]",
sgw_ue->mme_s11_teid, sgw_ue->sgw_s11_teid); mme_ue->mme_s11_teid, sgw_ue->sgw_s11_teid);
ogs_assert(nas_message); ogs_assert(nas_message);
switch (nas_message->esm.h.message_type) { switch (nas_message->esm.h.message_type) {

View File

@ -29,7 +29,7 @@ ogs_pkbuf_t *mme_s11_build_create_session_request(
ogs_pkbuf_t *mme_s11_build_modify_bearer_request( ogs_pkbuf_t *mme_s11_build_modify_bearer_request(
uint8_t type, mme_ue_t *mme_ue, int uli_presense); uint8_t type, mme_ue_t *mme_ue, int uli_presense);
ogs_pkbuf_t *mme_s11_build_delete_session_request( ogs_pkbuf_t *mme_s11_build_delete_session_request(
uint8_t type, mme_sess_t *sess); uint8_t type, mme_sess_t *sess, int action);
ogs_pkbuf_t *mme_s11_build_create_bearer_response( ogs_pkbuf_t *mme_s11_build_create_bearer_response(
uint8_t type, mme_bearer_t *bearer, uint8_t cause_value); uint8_t type, mme_bearer_t *bearer, uint8_t cause_value);
ogs_pkbuf_t *mme_s11_build_update_bearer_response( ogs_pkbuf_t *mme_s11_build_update_bearer_response(

View File

@ -20,6 +20,7 @@
#include "mme-event.h" #include "mme-event.h"
#include "mme-sm.h" #include "mme-sm.h"
#include "mme-context.h" #include "mme-context.h"
#include "mme-timer.h"
#include "s1ap-path.h" #include "s1ap-path.h"
#include "mme-gtp-path.h" #include "mme-gtp-path.h"
@ -77,19 +78,21 @@ void mme_s11_handle_echo_response(
} }
void mme_s11_handle_create_session_response( void mme_s11_handle_create_session_response(
ogs_gtp_xact_t *xact, sgw_ue_t *sgw_ue, ogs_gtp_xact_t *xact, mme_ue_t *mme_ue_from_teid,
ogs_gtp2_create_session_response_t *rsp) ogs_gtp2_create_session_response_t *rsp)
{ {
int rv; int rv, i;
uint8_t cause_value = 0; uint8_t cause_value = 0;
ogs_gtp2_cause_t *cause = NULL; ogs_gtp2_cause_t *cause = NULL;
ogs_gtp2_f_teid_t *sgw_s11_teid = NULL; ogs_gtp2_f_teid_t *sgw_s11_teid = NULL;
ogs_gtp2_f_teid_t *pgw_s5c_teid = NULL; ogs_gtp2_f_teid_t *pgw_s5c_teid = NULL;
ogs_gtp2_f_teid_t *sgw_s1u_teid = NULL; ogs_gtp2_f_teid_t *sgw_s1u_teid = NULL;
ogs_gtp2_f_teid_t *pgw_s5u_teid = NULL;
mme_bearer_t *bearer = NULL; mme_bearer_t *bearer = NULL;
mme_sess_t *sess = NULL; mme_sess_t *sess = NULL;
mme_ue_t *mme_ue = NULL; mme_ue_t *mme_ue = NULL;
sgw_ue_t *source_ue = NULL, *target_ue = NULL;
ogs_session_t *session = NULL; ogs_session_t *session = NULL;
ogs_gtp2_bearer_qos_t bearer_qos; ogs_gtp2_bearer_qos_t bearer_qos;
ogs_gtp2_ambr_t *ambr = NULL; ogs_gtp2_ambr_t *ambr = NULL;
@ -109,38 +112,28 @@ void mme_s11_handle_create_session_response(
ogs_assert(sess); ogs_assert(sess);
mme_ue = sess->mme_ue; mme_ue = sess->mme_ue;
ogs_assert(mme_ue); ogs_assert(mme_ue);
source_ue = sgw_ue_cycle(mme_ue->sgw_ue);
ogs_assert(source_ue);
if (create_action == OGS_GTP_CREATE_IN_PATH_SWITCH_REQUEST) {
target_ue = sgw_ue_cycle(source_ue->target_ue);
ogs_assert(target_ue);
} else {
target_ue = source_ue;
ogs_assert(target_ue);
}
rv = ogs_gtp_xact_commit(xact); rv = ogs_gtp_xact_commit(xact);
ogs_expect_or_return(rv == OGS_OK); ogs_expect_or_return(rv == OGS_OK);
/************************ /************************
* Check SGW-UE Context * Check MME-UE Context
************************/ ************************/
cause_value = OGS_GTP2_CAUSE_REQUEST_ACCEPTED; cause_value = OGS_GTP2_CAUSE_REQUEST_ACCEPTED;
if (!sgw_ue) { if (!mme_ue_from_teid) {
ogs_error("No Context in TEID"); ogs_error("No Context in TEID");
cause_value = OGS_GTP2_CAUSE_CONTEXT_NOT_FOUND; cause_value = OGS_GTP2_CAUSE_CONTEXT_NOT_FOUND;
} else {
if (rsp->bearer_contexts_created.presence == 0) {
ogs_error("No Bearer");
cause_value = OGS_GTP2_CAUSE_MANDATORY_IE_MISSING;
}
if (rsp->bearer_contexts_created.eps_bearer_id.presence == 0) {
ogs_error("No EPS Bearer ID");
cause_value = OGS_GTP2_CAUSE_MANDATORY_IE_MISSING;
}
if (cause_value == OGS_GTP2_CAUSE_REQUEST_ACCEPTED) {
bearer = mme_bearer_find_by_ue_ebi(mme_ue,
rsp->bearer_contexts_created.eps_bearer_id.u8);
if (!bearer) {
ogs_error("No Context for EPS Bearer ID[%d]",
rsp->bearer_contexts_created.eps_bearer_id.u8);
cause_value = OGS_GTP2_CAUSE_CONTEXT_NOT_FOUND;
}
}
} }
if (cause_value != OGS_GTP2_CAUSE_REQUEST_ACCEPTED) { if (cause_value != OGS_GTP2_CAUSE_REQUEST_ACCEPTED) {
@ -162,38 +155,46 @@ void mme_s11_handle_create_session_response(
ogs_error("No S11 TEID"); ogs_error("No S11 TEID");
cause_value = OGS_GTP2_CAUSE_CONDITIONAL_IE_MISSING; cause_value = OGS_GTP2_CAUSE_CONDITIONAL_IE_MISSING;
} }
if (rsp->pgw_s5_s8__s2a_s2b_f_teid_for_pmip_based_interface_or_for_gtp_based_control_plane_interface.presence == 0) {
ogs_error("No S5C TEID");
cause_value = OGS_GTP2_CAUSE_CONDITIONAL_IE_MISSING;
}
if (rsp->bearer_contexts_created.s1_u_enodeb_f_teid.presence == 0) {
ogs_error("No S1U TEID");
cause_value = OGS_GTP2_CAUSE_CONDITIONAL_IE_MISSING;
}
if (rsp->pdn_address_allocation.presence) { if (create_action == OGS_GTP_CREATE_IN_PATH_SWITCH_REQUEST) {
ogs_paa_t paa;
memcpy(&paa, rsp->pdn_address_allocation.data, /* No need S5C TEID in PathSwitchRequest */
rsp->pdn_address_allocation.len);
if (!OGS_PDU_SESSION_TYPE_IS_VALID(paa.session_type)) {
ogs_error("Unknown PDN Type[%u]", paa.session_type);
cause_value = OGS_GTP2_CAUSE_MANDATORY_IE_INCORRECT;
}
} else { } else {
ogs_error("No PDN Address Allocation");
cause_value = OGS_GTP2_CAUSE_CONDITIONAL_IE_MISSING; if (rsp->pgw_s5_s8__s2a_s2b_f_teid_for_pmip_based_interface_or_for_gtp_based_control_plane_interface.presence == 0) {
ogs_error("No S5C TEID");
cause_value = OGS_GTP2_CAUSE_CONDITIONAL_IE_MISSING;
}
}
if (create_action == OGS_GTP_CREATE_IN_PATH_SWITCH_REQUEST) {
/* No need S5C TEID in PathSwitchRequest */
} else {
if (rsp->pdn_address_allocation.presence) {
ogs_paa_t paa;
memcpy(&paa, rsp->pdn_address_allocation.data,
rsp->pdn_address_allocation.len);
if (!OGS_PDU_SESSION_TYPE_IS_VALID(paa.session_type)) {
ogs_error("Unknown PDN Type[%u]", paa.session_type);
cause_value = OGS_GTP2_CAUSE_MANDATORY_IE_INCORRECT;
}
} else {
ogs_error("No PDN Address Allocation");
cause_value = OGS_GTP2_CAUSE_CONDITIONAL_IE_MISSING;
}
} }
if (rsp->cause.presence == 0) { if (rsp->cause.presence == 0) {
ogs_error("No Cause"); ogs_error("No Cause");
cause_value = OGS_GTP2_CAUSE_MANDATORY_IE_MISSING; 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) { if (cause_value != OGS_GTP2_CAUSE_REQUEST_ACCEPTED) {
if (create_action == OGS_GTP_CREATE_IN_ATTACH_REQUEST) { if (create_action == OGS_GTP_CREATE_IN_ATTACH_REQUEST) {
@ -210,18 +211,24 @@ void mme_s11_handle_create_session_response(
********************/ ********************/
ogs_assert(cause_value == OGS_GTP2_CAUSE_REQUEST_ACCEPTED); ogs_assert(cause_value == OGS_GTP2_CAUSE_REQUEST_ACCEPTED);
cause = rsp->bearer_contexts_created.cause.data; for (i = 0; i < OGS_BEARER_PER_UE; i++) {
ogs_assert(cause); if (rsp->bearer_contexts_created[i].cause.presence == 0) {
cause_value = cause->value; break;
if (cause_value != OGS_GTP2_CAUSE_REQUEST_ACCEPTED) { }
ogs_error("GTP Failed [Bearer-CAUSE:%d]", cause_value);
if (create_action == OGS_GTP_CREATE_IN_ATTACH_REQUEST) { cause = rsp->bearer_contexts_created[i].cause.data;
ogs_error("[%s] Attach reject", mme_ue->imsi_bcd); ogs_assert(cause);
ogs_assert(OGS_OK == nas_eps_send_attach_reject(mme_ue, cause_value = cause->value;
EMM_CAUSE_NETWORK_FAILURE, ESM_CAUSE_NETWORK_FAILURE)); if (cause_value != OGS_GTP2_CAUSE_REQUEST_ACCEPTED) {
ogs_error("GTP Failed [Bearer-CAUSE:%d]", cause_value);
if (create_action == OGS_GTP_CREATE_IN_ATTACH_REQUEST) {
ogs_error("[%s] Attach reject", mme_ue->imsi_bcd);
ogs_assert(OGS_OK == nas_eps_send_attach_reject(mme_ue,
EMM_CAUSE_NETWORK_FAILURE, ESM_CAUSE_NETWORK_FAILURE));
}
mme_send_delete_session_or_mme_ue_context_release(mme_ue);
return;
} }
mme_send_delete_session_or_mme_ue_context_release(mme_ue);
return;
} }
cause = rsp->cause.data; cause = rsp->cause.data;
@ -246,25 +253,87 @@ void mme_s11_handle_create_session_response(
/******************** /********************
* Check ALL Context * Check ALL Context
********************/ ********************/
ogs_assert(mme_ue);
ogs_assert(sgw_ue);
ogs_assert(bearer);
sess = bearer->sess;
ogs_assert(sess); ogs_assert(sess);
session = sess->session; session = sess->session;
ogs_assert(session); ogs_assert(session);
ogs_assert(mme_ue);
ogs_assert(source_ue);
ogs_assert(target_ue);
ogs_debug(" MME_S11_TEID[%d] SGW_S11_TEID[%d]",
mme_ue->mme_s11_teid, target_ue->sgw_s11_teid);
for (i = 0; i < OGS_BEARER_PER_UE; i++) {
if (rsp->bearer_contexts_created[i].presence == 0) {
break;
}
if (rsp->bearer_contexts_created[i].eps_bearer_id.presence == 0) {
ogs_error("No EPS Bearer ID");
break;
}
if (rsp->bearer_contexts_created[i].s1_u_enodeb_f_teid.presence == 0) {
ogs_error("No SGW-S1U TEID");
break;
}
if (rsp->bearer_contexts_created[i].s5_s8_u_sgw_f_teid.presence == 0) {
ogs_error("No PGW-S5U TEID");
break;
}
/* EPS Bearer ID */
bearer = mme_bearer_find_by_ue_ebi(mme_ue,
rsp->bearer_contexts_created[i].eps_bearer_id.u8);
if (!bearer) {
mme_send_delete_session_or_mme_ue_context_release(mme_ue);
return;
}
/* Data Plane(UL) : SGW-S1U */
sgw_s1u_teid = rsp->bearer_contexts_created[i].s1_u_enodeb_f_teid.data;
bearer->sgw_s1u_teid = be32toh(sgw_s1u_teid->teid);
ogs_assert(OGS_OK ==
ogs_gtp2_f_teid_to_ip(sgw_s1u_teid, &bearer->sgw_s1u_ip));
/* Data Plane(UL) : PGW-S5U */
pgw_s5u_teid = rsp->bearer_contexts_created[i].s5_s8_u_sgw_f_teid.data;
bearer->pgw_s5u_teid = be32toh(pgw_s5u_teid->teid);
ogs_assert(OGS_OK ==
ogs_gtp2_f_teid_to_ip(pgw_s5u_teid, &bearer->pgw_s5u_ip));
ogs_debug(" ENB_S1U_TEID[%d] SGW_S1U_TEID[%d] PGW_S5U_TEID[%d]",
bearer->enb_s1u_teid, bearer->sgw_s1u_teid, bearer->pgw_s5u_teid);
}
/* Bearer Level QoS */
if (rsp->bearer_contexts_created[0].bearer_level_qos.presence) {
decoded = ogs_gtp2_parse_bearer_qos(&bearer_qos,
&rsp->bearer_contexts_created[0].bearer_level_qos);
ogs_assert(decoded ==
rsp->bearer_contexts_created[0].bearer_level_qos.len);
session->qos.index = bearer_qos.qci;
session->qos.arp.priority_level = bearer_qos.priority_level;
session->qos.arp.pre_emption_capability =
bearer_qos.pre_emption_capability;
session->qos.arp.pre_emption_vulnerability =
bearer_qos.pre_emption_vulnerability;
}
/* Control Plane(UL) : SGW-S11 */ /* Control Plane(UL) : SGW-S11 */
sgw_s11_teid = rsp->sender_f_teid_for_control_plane.data; sgw_s11_teid = rsp->sender_f_teid_for_control_plane.data;
sgw_ue->sgw_s11_teid = be32toh(sgw_s11_teid->teid); target_ue->sgw_s11_teid = be32toh(sgw_s11_teid->teid);
/* Control Plane(UL) : PGW-S5C */ /* Control Plane(UL) : PGW-S5C */
pgw_s5c_teid = rsp->pgw_s5_s8__s2a_s2b_f_teid_for_pmip_based_interface_or_for_gtp_based_control_plane_interface.data; if (rsp->pgw_s5_s8__s2a_s2b_f_teid_for_pmip_based_interface_or_for_gtp_based_control_plane_interface.presence) {
sess->pgw_s5c_teid = be32toh(pgw_s5c_teid->teid); pgw_s5c_teid = rsp->pgw_s5_s8__s2a_s2b_f_teid_for_pmip_based_interface_or_for_gtp_based_control_plane_interface.data;
sess->pgw_s5c_teid = be32toh(pgw_s5c_teid->teid);
}
memcpy(&session->paa, rsp->pdn_address_allocation.data, /* PDN Addresss Allocation */
rsp->pdn_address_allocation.len); if (rsp->pdn_address_allocation.presence) {
memcpy(&session->paa, rsp->pdn_address_allocation.data,
rsp->pdn_address_allocation.len);
}
/* PCO */ /* PCO */
if (rsp->protocol_configuration_options.presence) { if (rsp->protocol_configuration_options.presence) {
@ -273,10 +342,10 @@ void mme_s11_handle_create_session_response(
} }
/* Bearer QoS */ /* Bearer QoS */
if (rsp->bearer_contexts_created.bearer_level_qos.presence) { if (rsp->bearer_contexts_created[0].bearer_level_qos.presence) {
decoded = ogs_gtp2_parse_bearer_qos(&bearer_qos, decoded = ogs_gtp2_parse_bearer_qos(&bearer_qos,
&rsp->bearer_contexts_created.bearer_level_qos); &rsp->bearer_contexts_created[0].bearer_level_qos);
ogs_assert(rsp->bearer_contexts_created.bearer_level_qos.len == ogs_assert(rsp->bearer_contexts_created[0].bearer_level_qos.len ==
decoded); decoded);
session->qos.index = bearer_qos.qci; session->qos.index = bearer_qos.qci;
session->qos.arp.priority_level = bearer_qos.priority_level; session->qos.arp.priority_level = bearer_qos.priority_level;
@ -293,18 +362,6 @@ void mme_s11_handle_create_session_response(
session->ambr.uplink = be32toh(ambr->uplink) * 1000; session->ambr.uplink = be32toh(ambr->uplink) * 1000;
} }
/* Data Plane(UL) : SGW-S1U */
sgw_s1u_teid = rsp->bearer_contexts_created.s1_u_enodeb_f_teid.data;
bearer->sgw_s1u_teid = be32toh(sgw_s1u_teid->teid);
ogs_debug(" MME_S11_TEID[%d] SGW_S11_TEID[%d]",
sgw_ue->mme_s11_teid, sgw_ue->sgw_s11_teid);
ogs_debug(" ENB_S1U_TEID[%d] SGW_S1U_TEID[%d]",
bearer->enb_s1u_teid, bearer->sgw_s1u_teid);
rv = ogs_gtp2_f_teid_to_ip(sgw_s1u_teid, &bearer->sgw_s1u_ip);
ogs_assert(rv == OGS_OK);
if (create_action == OGS_GTP_CREATE_IN_ATTACH_REQUEST) { if (create_action == OGS_GTP_CREATE_IN_ATTACH_REQUEST) {
mme_csmap_t *csmap = mme_csmap_find_by_tai(&mme_ue->tai); mme_csmap_t *csmap = mme_csmap_find_by_tai(&mme_ue->tai);
mme_ue->csmap = csmap; mme_ue->csmap = csmap;
@ -327,7 +384,15 @@ void mme_s11_handle_create_session_response(
nas_eps_send_activate_default_bearer_context_request( nas_eps_send_activate_default_bearer_context_request(
bearer, create_action)); bearer, create_action));
} else if (create_action == OGS_GTP_CREATE_IN_PATH_SWITCH_REQUEST) { } else if (create_action == OGS_GTP_CREATE_IN_PATH_SWITCH_REQUEST) {
ogs_error("OK");
GTP_COUNTER_CHECK(mme_ue, GTP_COUNTER_CREATE_SESSION_BY_PATH_SWITCH,
ogs_timer_start(source_ue->t_s11_holding,
mme_timer_cfg(MME_TIMER_S11_HOLDING)->duration);
sgw_ue_associate_mme_ue(target_ue, mme_ue);
ogs_assert(OGS_OK == s1ap_send_path_switch_ack(mme_ue, true));
);
} else { } else {
ogs_fatal("Invalid Create Session Action[%d]", create_action); ogs_fatal("Invalid Create Session Action[%d]", create_action);
ogs_assert_if_reached(); ogs_assert_if_reached();
@ -335,7 +400,7 @@ void mme_s11_handle_create_session_response(
} }
void mme_s11_handle_modify_bearer_response( void mme_s11_handle_modify_bearer_response(
ogs_gtp_xact_t *xact, sgw_ue_t *sgw_ue, ogs_gtp_xact_t *xact, mme_ue_t *mme_ue_from_teid,
ogs_gtp2_modify_bearer_response_t *rsp) ogs_gtp2_modify_bearer_response_t *rsp)
{ {
int rv; int rv;
@ -344,6 +409,7 @@ void mme_s11_handle_modify_bearer_response(
ogs_gtp2_cause_t *cause = NULL; ogs_gtp2_cause_t *cause = NULL;
mme_ue_t *mme_ue = NULL; mme_ue_t *mme_ue = NULL;
sgw_ue_t *sgw_ue = NULL;
ogs_assert(rsp); ogs_assert(rsp);
@ -353,19 +419,21 @@ void mme_s11_handle_modify_bearer_response(
* Check Transaction * Check Transaction
********************/ ********************/
ogs_assert(xact); ogs_assert(xact);
modify_action = xact->modify_action;
mme_ue = xact->data; mme_ue = xact->data;
ogs_assert(mme_ue); ogs_assert(mme_ue);
modify_action = xact->modify_action; sgw_ue = sgw_ue_cycle(mme_ue->sgw_ue);
ogs_assert(sgw_ue);
rv = ogs_gtp_xact_commit(xact); rv = ogs_gtp_xact_commit(xact);
ogs_expect_or_return(rv == OGS_OK); ogs_expect_or_return(rv == OGS_OK);
/************************ /************************
* Check SGW-UE Context * Check MME-UE Context
************************/ ************************/
cause_value = OGS_GTP2_CAUSE_REQUEST_ACCEPTED; cause_value = OGS_GTP2_CAUSE_REQUEST_ACCEPTED;
if (!sgw_ue) { if (!mme_ue_from_teid) {
ogs_error("No Context in TEID"); ogs_error("No Context in TEID");
cause_value = OGS_GTP2_CAUSE_CONTEXT_NOT_FOUND; cause_value = OGS_GTP2_CAUSE_CONTEXT_NOT_FOUND;
} }
@ -411,11 +479,11 @@ void mme_s11_handle_modify_bearer_response(
ogs_assert(sgw_ue); ogs_assert(sgw_ue);
ogs_debug(" MME_S11_TEID[%d] SGW_S11_TEID[%d]", ogs_debug(" MME_S11_TEID[%d] SGW_S11_TEID[%d]",
sgw_ue->mme_s11_teid, sgw_ue->sgw_s11_teid); mme_ue->mme_s11_teid, sgw_ue->sgw_s11_teid);
switch (modify_action) { switch (modify_action) {
case OGS_GTP_MODIFY_IN_PATH_SWITCH_REQUEST: case OGS_GTP_MODIFY_IN_PATH_SWITCH_REQUEST:
ogs_assert(OGS_OK == s1ap_send_path_switch_ack(mme_ue)); ogs_assert(OGS_OK == s1ap_send_path_switch_ack(mme_ue, false));
break; break;
case OGS_GTP_MODIFY_IN_E_RAB_MODIFICATION: case OGS_GTP_MODIFY_IN_E_RAB_MODIFICATION:
ogs_assert(OGS_OK == s1ap_send_e_rab_modification_confirm(mme_ue)); ogs_assert(OGS_OK == s1ap_send_e_rab_modification_confirm(mme_ue));
@ -426,14 +494,15 @@ void mme_s11_handle_modify_bearer_response(
} }
void mme_s11_handle_delete_session_response( void mme_s11_handle_delete_session_response(
ogs_gtp_xact_t *xact, sgw_ue_t *sgw_ue, ogs_gtp_xact_t *xact, mme_ue_t *mme_ue_from_teid,
ogs_gtp2_delete_session_response_t *rsp) ogs_gtp2_delete_session_response_t *rsp)
{ {
int rv; int rv;
uint8_t cause_value = 0; uint8_t cause_value = 0;
int action = 0; int action = 0;
mme_ue_t *mme_ue = NULL; sgw_ue_t *source_ue = NULL, *target_ue = NULL;
mme_sess_t *sess = NULL; mme_sess_t *sess = NULL;
mme_ue_t *mme_ue = NULL;
ogs_assert(rsp); ogs_assert(rsp);
@ -449,15 +518,26 @@ void mme_s11_handle_delete_session_response(
ogs_assert(sess); ogs_assert(sess);
mme_ue = sess->mme_ue; mme_ue = sess->mme_ue;
ogs_assert(mme_ue); ogs_assert(mme_ue);
target_ue = sgw_ue_cycle(mme_ue->sgw_ue);
ogs_assert(target_ue);
if (action == OGS_GTP_DELETE_IN_PATH_SWITCH_REQUEST) {
source_ue = sgw_ue_cycle(target_ue->source_ue);
ogs_assert(source_ue);
} else {
source_ue = target_ue;
ogs_assert(source_ue);
}
rv = ogs_gtp_xact_commit(xact); rv = ogs_gtp_xact_commit(xact);
ogs_expect_or_return(rv == OGS_OK); ogs_expect_or_return(rv == OGS_OK);
/************************ /************************
* Check SGW-UE Context * Check MME-UE Context
************************/ ************************/
if (!sgw_ue) if (!mme_ue_from_teid) {
ogs_error("No Context in TEID"); ogs_error("No Context in TEID");
}
/******************** /********************
* Check Cause Value * Check Cause Value
@ -474,12 +554,13 @@ void mme_s11_handle_delete_session_response(
/******************** /********************
* Check ALL Context * Check ALL Context
********************/ ********************/
ogs_assert(mme_ue);
ogs_assert(sess); ogs_assert(sess);
ogs_assert(mme_ue);
ogs_assert(target_ue);
ogs_assert(source_ue);
if (sgw_ue) ogs_debug(" MME_S11_TEID[%d] SGW_S11_TEID[%d]",
ogs_debug(" MME_S11_TEID[%d] SGW_S11_TEID[%d]", mme_ue->mme_s11_teid, source_ue->sgw_s11_teid);
sgw_ue->mme_s11_teid, sgw_ue->sgw_s11_teid);
if (action == OGS_GTP_DELETE_SEND_AUTHENTICATION_REQUEST) { if (action == OGS_GTP_DELETE_SEND_AUTHENTICATION_REQUEST) {
if (mme_sess_count(mme_ue) == 1) /* Last Session */ { if (mme_sess_count(mme_ue) == 1) /* Last Session */ {
@ -541,6 +622,20 @@ void mme_s11_handle_delete_session_response(
mme_ue_remove(mme_ue); mme_ue_remove(mme_ue);
return; return;
} else if (action == OGS_GTP_DELETE_IN_PATH_SWITCH_REQUEST) {
/* Don't have to remove Session in X2 Handover with SGW relocation */
ogs_assert(source_ue);
GTP_COUNTER_CHECK(mme_ue, GTP_COUNTER_DELETE_SESSION_BY_PATH_SWITCH,
sgw_ue_source_deassociate_target(source_ue);
sgw_ue_remove(source_ue);
);
return;
} else { } else {
ogs_fatal("Invalid action = %d", action); ogs_fatal("Invalid action = %d", action);
ogs_assert_if_reached(); ogs_assert_if_reached();
@ -553,16 +648,16 @@ void mme_s11_handle_delete_session_response(
} }
void mme_s11_handle_create_bearer_request( void mme_s11_handle_create_bearer_request(
ogs_gtp_xact_t *xact, sgw_ue_t *sgw_ue, ogs_gtp_xact_t *xact, mme_ue_t *mme_ue,
ogs_gtp2_create_bearer_request_t *req) ogs_gtp2_create_bearer_request_t *req)
{ {
int rv;
uint8_t cause_value = 0; uint8_t cause_value = 0;
mme_bearer_t *bearer = NULL, *default_bearer = NULL; mme_bearer_t *bearer = NULL, *default_bearer = NULL;
mme_sess_t *sess = NULL; mme_sess_t *sess = NULL;
mme_ue_t *mme_ue = NULL; sgw_ue_t *sgw_ue = NULL;
ogs_gtp2_f_teid_t *sgw_s1u_teid = NULL; ogs_gtp2_f_teid_t *sgw_s1u_teid = NULL;
ogs_gtp2_f_teid_t *pgw_s5u_teid = NULL;
ogs_gtp2_bearer_qos_t bearer_qos; ogs_gtp2_bearer_qos_t bearer_qos;
ogs_assert(xact); ogs_assert(xact);
@ -571,16 +666,16 @@ void mme_s11_handle_create_bearer_request(
ogs_debug("Create Bearer Response"); ogs_debug("Create Bearer Response");
/*********************** /***********************
* Check SGW-UE Context * Check MME-UE Context
***********************/ ***********************/
cause_value = OGS_GTP2_CAUSE_REQUEST_ACCEPTED; cause_value = OGS_GTP2_CAUSE_REQUEST_ACCEPTED;
if (!sgw_ue) { if (!mme_ue) {
ogs_error("No Context in TEID"); ogs_error("No Context in TEID");
cause_value = OGS_GTP2_CAUSE_CONTEXT_NOT_FOUND; cause_value = OGS_GTP2_CAUSE_CONTEXT_NOT_FOUND;
} else { } else {
mme_ue = sgw_ue->mme_ue; sgw_ue = sgw_ue_cycle(mme_ue->sgw_ue);
ogs_assert(mme_ue); ogs_assert(sgw_ue);
if (req->linked_eps_bearer_id.presence == 0) { if (req->linked_eps_bearer_id.presence == 0) {
ogs_error("No Linked EBI"); ogs_error("No Linked EBI");
@ -617,7 +712,11 @@ void mme_s11_handle_create_bearer_request(
cause_value = OGS_GTP2_CAUSE_MANDATORY_IE_MISSING; cause_value = OGS_GTP2_CAUSE_MANDATORY_IE_MISSING;
} }
if (req->bearer_contexts.s1_u_enodeb_f_teid.presence == 0) { if (req->bearer_contexts.s1_u_enodeb_f_teid.presence == 0) {
ogs_error("No GTP TEID"); ogs_error("No SGW-S1U TEID");
cause_value = OGS_GTP2_CAUSE_CONDITIONAL_IE_MISSING;
}
if (req->bearer_contexts.s4_u_sgsn_f_teid.presence == 0) {
ogs_error("No PGW-S5U TEID");
cause_value = OGS_GTP2_CAUSE_CONDITIONAL_IE_MISSING; cause_value = OGS_GTP2_CAUSE_CONDITIONAL_IE_MISSING;
} }
if (req->bearer_contexts.bearer_level_qos.presence == 0) { if (req->bearer_contexts.bearer_level_qos.presence == 0) {
@ -646,7 +745,7 @@ void mme_s11_handle_create_bearer_request(
ogs_assert(bearer); ogs_assert(bearer);
ogs_debug(" MME_S11_TEID[%d] SGW_S11_TEID[%d]", ogs_debug(" MME_S11_TEID[%d] SGW_S11_TEID[%d]",
sgw_ue->mme_s11_teid, sgw_ue->sgw_s11_teid); mme_ue->mme_s11_teid, sgw_ue->sgw_s11_teid);
/* Set PTI */ /* Set PTI */
sess->pti = OGS_NAS_PROCEDURE_TRANSACTION_IDENTITY_UNASSIGNED; sess->pti = OGS_NAS_PROCEDURE_TRANSACTION_IDENTITY_UNASSIGNED;
@ -658,8 +757,14 @@ void mme_s11_handle_create_bearer_request(
/* Data Plane(UL) : SGW-S1U */ /* Data Plane(UL) : SGW-S1U */
sgw_s1u_teid = req->bearer_contexts.s1_u_enodeb_f_teid.data; sgw_s1u_teid = req->bearer_contexts.s1_u_enodeb_f_teid.data;
bearer->sgw_s1u_teid = be32toh(sgw_s1u_teid->teid); bearer->sgw_s1u_teid = be32toh(sgw_s1u_teid->teid);
rv = ogs_gtp2_f_teid_to_ip(sgw_s1u_teid, &bearer->sgw_s1u_ip); ogs_assert(OGS_OK ==
ogs_assert(rv == OGS_OK); ogs_gtp2_f_teid_to_ip(sgw_s1u_teid, &bearer->sgw_s1u_ip));
/* Data Plane(UL) : PGW-S5U */
pgw_s5u_teid = req->bearer_contexts.s4_u_sgsn_f_teid.data;
bearer->pgw_s5u_teid = be32toh(pgw_s5u_teid->teid);
ogs_assert(OGS_OK ==
ogs_gtp2_f_teid_to_ip(pgw_s5u_teid, &bearer->pgw_s5u_ip));
/* Bearer QoS */ /* Bearer QoS */
ogs_expect_or_return(ogs_gtp2_parse_bearer_qos(&bearer_qos, ogs_expect_or_return(ogs_gtp2_parse_bearer_qos(&bearer_qos,
@ -721,13 +826,13 @@ void mme_s11_handle_create_bearer_request(
} }
void mme_s11_handle_update_bearer_request( void mme_s11_handle_update_bearer_request(
ogs_gtp_xact_t *xact, sgw_ue_t *sgw_ue, ogs_gtp_xact_t *xact, mme_ue_t *mme_ue,
ogs_gtp2_update_bearer_request_t *req) ogs_gtp2_update_bearer_request_t *req)
{ {
uint8_t cause_value = 0; uint8_t cause_value = 0;
mme_bearer_t *bearer = NULL; mme_bearer_t *bearer = NULL;
mme_sess_t *sess = NULL; mme_sess_t *sess = NULL;
mme_ue_t *mme_ue = NULL; sgw_ue_t *sgw_ue = NULL;
ogs_gtp2_bearer_qos_t bearer_qos; ogs_gtp2_bearer_qos_t bearer_qos;
ogs_assert(xact); ogs_assert(xact);
@ -736,16 +841,16 @@ void mme_s11_handle_update_bearer_request(
ogs_debug("Update Bearer Request"); ogs_debug("Update Bearer Request");
/*********************** /***********************
* Check SGW-UE Context * Check MME-UE Context
***********************/ ***********************/
cause_value = OGS_GTP2_CAUSE_REQUEST_ACCEPTED; cause_value = OGS_GTP2_CAUSE_REQUEST_ACCEPTED;
if (!sgw_ue) { if (!mme_ue) {
ogs_error("No Context in TEID"); ogs_error("No Context in TEID");
cause_value = OGS_GTP2_CAUSE_CONTEXT_NOT_FOUND; cause_value = OGS_GTP2_CAUSE_CONTEXT_NOT_FOUND;
} else { } else {
mme_ue = sgw_ue->mme_ue; sgw_ue = sgw_ue_cycle(mme_ue->sgw_ue);
ogs_assert(mme_ue); ogs_assert(sgw_ue);
if (req->bearer_contexts.presence == 0) { if (req->bearer_contexts.presence == 0) {
ogs_error("No Bearer"); ogs_error("No Bearer");
@ -783,7 +888,7 @@ void mme_s11_handle_update_bearer_request(
ogs_assert(sess); ogs_assert(sess);
ogs_debug(" MME_S11_TEID[%d] SGW_S11_TEID[%d]", ogs_debug(" MME_S11_TEID[%d] SGW_S11_TEID[%d]",
sgw_ue->mme_s11_teid, sgw_ue->sgw_s11_teid); mme_ue->mme_s11_teid, sgw_ue->sgw_s11_teid);
/* Set PTI */ /* Set PTI */
sess->pti = OGS_NAS_PROCEDURE_TRANSACTION_IDENTITY_UNASSIGNED; sess->pti = OGS_NAS_PROCEDURE_TRANSACTION_IDENTITY_UNASSIGNED;
@ -856,14 +961,14 @@ void mme_s11_handle_update_bearer_request(
} }
void mme_s11_handle_delete_bearer_request( void mme_s11_handle_delete_bearer_request(
ogs_gtp_xact_t *xact, sgw_ue_t *sgw_ue, ogs_gtp_xact_t *xact, mme_ue_t *mme_ue,
ogs_gtp2_delete_bearer_request_t *req) ogs_gtp2_delete_bearer_request_t *req)
{ {
uint8_t cause_value = 0; uint8_t cause_value = 0;
mme_bearer_t *bearer = NULL; mme_bearer_t *bearer = NULL;
mme_sess_t *sess = NULL; mme_sess_t *sess = NULL;
mme_ue_t *mme_ue = NULL; sgw_ue_t *sgw_ue = NULL;
ogs_assert(xact); ogs_assert(xact);
ogs_assert(req); ogs_assert(req);
@ -871,16 +976,16 @@ void mme_s11_handle_delete_bearer_request(
ogs_debug("Delete Bearer Request"); ogs_debug("Delete Bearer Request");
/*********************** /***********************
* Check SGW-UE Context * Check MME-UE Context
***********************/ ***********************/
cause_value = OGS_GTP2_CAUSE_REQUEST_ACCEPTED; cause_value = OGS_GTP2_CAUSE_REQUEST_ACCEPTED;
if (!sgw_ue) { if (!mme_ue) {
ogs_error("No Context in TEID"); ogs_error("No Context in TEID");
cause_value = OGS_GTP2_CAUSE_CONTEXT_NOT_FOUND; cause_value = OGS_GTP2_CAUSE_CONTEXT_NOT_FOUND;
} else { } else {
mme_ue = sgw_ue->mme_ue; sgw_ue = sgw_ue_cycle(mme_ue->sgw_ue);
ogs_assert(mme_ue); ogs_assert(sgw_ue);
if (req->linked_eps_bearer_id.presence == 1) { if (req->linked_eps_bearer_id.presence == 1) {
/* /*
@ -943,7 +1048,7 @@ void mme_s11_handle_delete_bearer_request(
ogs_assert(sess); ogs_assert(sess);
ogs_debug(" MME_S11_TEID[%d] SGW_S11_TEID[%d]", ogs_debug(" MME_S11_TEID[%d] SGW_S11_TEID[%d]",
sgw_ue->mme_s11_teid, sgw_ue->sgw_s11_teid); mme_ue->mme_s11_teid, sgw_ue->sgw_s11_teid);
/* Set PTI */ /* Set PTI */
sess->pti = OGS_NAS_PROCEDURE_TRANSACTION_IDENTITY_UNASSIGNED; sess->pti = OGS_NAS_PROCEDURE_TRANSACTION_IDENTITY_UNASSIGNED;
@ -971,7 +1076,7 @@ void mme_s11_handle_delete_bearer_request(
} }
void mme_s11_handle_release_access_bearers_response( void mme_s11_handle_release_access_bearers_response(
ogs_gtp_xact_t *xact, sgw_ue_t *sgw_ue, ogs_gtp_xact_t *xact, mme_ue_t *mme_ue_from_teid,
ogs_gtp2_release_access_bearers_response_t *rsp) ogs_gtp2_release_access_bearers_response_t *rsp)
{ {
int rv; int rv;
@ -979,7 +1084,8 @@ void mme_s11_handle_release_access_bearers_response(
int action = 0; int action = 0;
enb_ue_t *enb_ue = NULL; enb_ue_t *enb_ue = NULL;
mme_ue_t *mme_ue = NULL;; sgw_ue_t *sgw_ue = NULL;;
mme_ue_t *mme_ue = NULL;
mme_sess_t *sess = NULL; mme_sess_t *sess = NULL;
mme_bearer_t *bearer = NULL; mme_bearer_t *bearer = NULL;
@ -995,15 +1101,18 @@ void mme_s11_handle_release_access_bearers_response(
ogs_assert(action); ogs_assert(action);
mme_ue = xact->data; mme_ue = xact->data;
ogs_assert(mme_ue); ogs_assert(mme_ue);
sgw_ue = sgw_ue_cycle(mme_ue->sgw_ue);
ogs_assert(sgw_ue);
rv = ogs_gtp_xact_commit(xact); rv = ogs_gtp_xact_commit(xact);
ogs_expect_or_return(rv == OGS_OK); ogs_expect_or_return(rv == OGS_OK);
/*********************** /***********************
* Check SGW-UE Context * Check MME-UE Context
***********************/ ***********************/
if (!sgw_ue) if (!mme_ue_from_teid) {
ogs_error("No Context in TEID"); ogs_error("No Context in TEID");
}
/******************** /********************
* Check Cause Value * Check Cause Value
@ -1021,10 +1130,10 @@ void mme_s11_handle_release_access_bearers_response(
* Check ALL Context * Check ALL Context
********************/ ********************/
ogs_assert(mme_ue); ogs_assert(mme_ue);
ogs_assert(sgw_ue);
if (sgw_ue) ogs_debug(" MME_S11_TEID[%d] SGW_S11_TEID[%d]",
ogs_debug(" MME_S11_TEID[%d] SGW_S11_TEID[%d]", mme_ue->mme_s11_teid, sgw_ue->sgw_s11_teid);
sgw_ue->mme_s11_teid, sgw_ue->sgw_s11_teid);
ogs_list_for_each(&mme_ue->sess_list, sess) { ogs_list_for_each(&mme_ue->sess_list, sess) {
ogs_list_for_each(&sess->bearer_list, bearer) { ogs_list_for_each(&sess->bearer_list, bearer) {
@ -1125,13 +1234,13 @@ void mme_s11_handle_release_access_bearers_response(
} }
void mme_s11_handle_downlink_data_notification( void mme_s11_handle_downlink_data_notification(
ogs_gtp_xact_t *xact, sgw_ue_t *sgw_ue, ogs_gtp_xact_t *xact, mme_ue_t *mme_ue,
ogs_gtp2_downlink_data_notification_t *noti) ogs_gtp2_downlink_data_notification_t *noti)
{ {
uint8_t cause_value = 0; uint8_t cause_value = 0;
mme_bearer_t *bearer = NULL; mme_bearer_t *bearer = NULL;
mme_ue_t *mme_ue = NULL; sgw_ue_t *sgw_ue = NULL;
ogs_assert(xact); ogs_assert(xact);
ogs_assert(noti); ogs_assert(noti);
@ -1139,16 +1248,16 @@ void mme_s11_handle_downlink_data_notification(
ogs_debug("Downlink Data Notification"); ogs_debug("Downlink Data Notification");
/************************ /************************
* Check SGW-UE Context * Check MME-UE Context
************************/ ************************/
cause_value = OGS_GTP2_CAUSE_REQUEST_ACCEPTED; cause_value = OGS_GTP2_CAUSE_REQUEST_ACCEPTED;
if (!sgw_ue) { if (!mme_ue) {
ogs_error("No UE Context"); ogs_error("No UE Context");
cause_value = OGS_GTP2_CAUSE_CONTEXT_NOT_FOUND; cause_value = OGS_GTP2_CAUSE_CONTEXT_NOT_FOUND;
} else { } else {
mme_ue = sgw_ue->mme_ue; sgw_ue = sgw_ue_cycle(mme_ue->sgw_ue);
ogs_assert(mme_ue); ogs_assert(sgw_ue);
if (noti->eps_bearer_id.presence == 0) { if (noti->eps_bearer_id.presence == 0) {
ogs_error("No Bearer ID"); ogs_error("No Bearer ID");
@ -1181,7 +1290,7 @@ void mme_s11_handle_downlink_data_notification(
ogs_assert(bearer); ogs_assert(bearer);
ogs_debug(" MME_S11_TEID[%d] SGW_S11_TEID[%d]", ogs_debug(" MME_S11_TEID[%d] SGW_S11_TEID[%d]",
sgw_ue->mme_s11_teid, sgw_ue->sgw_s11_teid); mme_ue->mme_s11_teid, sgw_ue->sgw_s11_teid);
/* /*
* Save Transaction. It will be handled after ECM-Connected * Save Transaction. It will be handled after ECM-Connected
@ -1263,14 +1372,15 @@ void mme_s11_handle_downlink_data_notification(
} }
void mme_s11_handle_create_indirect_data_forwarding_tunnel_response( void mme_s11_handle_create_indirect_data_forwarding_tunnel_response(
ogs_gtp_xact_t *xact, sgw_ue_t *sgw_ue, ogs_gtp_xact_t *xact, mme_ue_t *mme_ue_from_teid,
ogs_gtp2_create_indirect_data_forwarding_tunnel_response_t *rsp) ogs_gtp2_create_indirect_data_forwarding_tunnel_response_t *rsp)
{ {
int rv; int rv;
uint8_t cause_value = 0; uint8_t cause_value = 0;
ogs_gtp2_cause_t *cause = NULL; ogs_gtp2_cause_t *cause = NULL;
mme_ue_t *mme_ue = NULL; sgw_ue_t *sgw_ue = NULL;
mme_bearer_t *bearer = NULL; mme_bearer_t *bearer = NULL;
mme_ue_t *mme_ue = NULL;
enb_ue_t *source_ue = NULL; enb_ue_t *source_ue = NULL;
int i; int i;
@ -1286,16 +1396,18 @@ void mme_s11_handle_create_indirect_data_forwarding_tunnel_response(
ogs_assert(xact); ogs_assert(xact);
mme_ue = xact->data; mme_ue = xact->data;
ogs_assert(mme_ue); ogs_assert(mme_ue);
sgw_ue = sgw_ue_cycle(mme_ue->sgw_ue);
ogs_assert(sgw_ue);
rv = ogs_gtp_xact_commit(xact); rv = ogs_gtp_xact_commit(xact);
ogs_expect_or_return(rv == OGS_OK); ogs_expect_or_return(rv == OGS_OK);
/************************ /************************
* Check SGW-UE Context * Check MME-UE Context
************************/ ************************/
cause_value = OGS_GTP2_CAUSE_REQUEST_ACCEPTED; cause_value = OGS_GTP2_CAUSE_REQUEST_ACCEPTED;
if (!sgw_ue) { if (!mme_ue_from_teid) {
ogs_error("No Context in TEID"); ogs_error("No Context in TEID");
cause_value = OGS_GTP2_CAUSE_CONTEXT_NOT_FOUND; cause_value = OGS_GTP2_CAUSE_CONTEXT_NOT_FOUND;
} }
@ -1341,7 +1453,7 @@ void mme_s11_handle_create_indirect_data_forwarding_tunnel_response(
ogs_assert(sgw_ue); ogs_assert(sgw_ue);
ogs_debug(" MME_S11_TEID[%d] SGW_S11_TEID[%d]", ogs_debug(" MME_S11_TEID[%d] SGW_S11_TEID[%d]",
sgw_ue->mme_s11_teid, sgw_ue->sgw_s11_teid); mme_ue->mme_s11_teid, sgw_ue->sgw_s11_teid);
for (i = 0; rsp->bearer_contexts[i].presence; i++) { for (i = 0; rsp->bearer_contexts[i].presence; i++) {
if (rsp->bearer_contexts[i].eps_bearer_id.presence == 0) { if (rsp->bearer_contexts[i].eps_bearer_id.presence == 0) {
@ -1378,7 +1490,7 @@ void mme_s11_handle_create_indirect_data_forwarding_tunnel_response(
} }
void mme_s11_handle_delete_indirect_data_forwarding_tunnel_response( void mme_s11_handle_delete_indirect_data_forwarding_tunnel_response(
ogs_gtp_xact_t *xact, sgw_ue_t *sgw_ue, ogs_gtp_xact_t *xact, mme_ue_t *mme_ue_from_teid,
ogs_gtp2_delete_indirect_data_forwarding_tunnel_response_t *rsp) ogs_gtp2_delete_indirect_data_forwarding_tunnel_response_t *rsp)
{ {
int rv; int rv;
@ -1386,6 +1498,7 @@ void mme_s11_handle_delete_indirect_data_forwarding_tunnel_response(
ogs_gtp2_cause_t *cause = NULL; ogs_gtp2_cause_t *cause = NULL;
int action = 0; int action = 0;
mme_ue_t *mme_ue = NULL; mme_ue_t *mme_ue = NULL;
sgw_ue_t *sgw_ue = NULL;
ogs_assert(rsp); ogs_assert(rsp);
@ -1399,16 +1512,18 @@ void mme_s11_handle_delete_indirect_data_forwarding_tunnel_response(
ogs_assert(action); ogs_assert(action);
mme_ue = xact->data; mme_ue = xact->data;
ogs_assert(mme_ue); ogs_assert(mme_ue);
sgw_ue = sgw_ue_cycle(mme_ue->sgw_ue);
ogs_assert(sgw_ue);
rv = ogs_gtp_xact_commit(xact); rv = ogs_gtp_xact_commit(xact);
ogs_expect_or_return(rv == OGS_OK); ogs_expect_or_return(rv == OGS_OK);
/************************ /************************
* Check SGW-UE Context * Check MME-UE Context
************************/ ************************/
cause_value = OGS_GTP2_CAUSE_REQUEST_ACCEPTED; cause_value = OGS_GTP2_CAUSE_REQUEST_ACCEPTED;
if (!sgw_ue) { if (!mme_ue_from_teid) {
ogs_error("No Context in TEID"); ogs_error("No Context in TEID");
cause_value = OGS_GTP2_CAUSE_CONTEXT_NOT_FOUND; cause_value = OGS_GTP2_CAUSE_CONTEXT_NOT_FOUND;
} }
@ -1454,7 +1569,7 @@ void mme_s11_handle_delete_indirect_data_forwarding_tunnel_response(
ogs_assert(sgw_ue); ogs_assert(sgw_ue);
ogs_debug(" MME_S11_TEID[%d] SGW_S11_TEID[%d]", ogs_debug(" MME_S11_TEID[%d] SGW_S11_TEID[%d]",
sgw_ue->mme_s11_teid, sgw_ue->sgw_s11_teid); mme_ue->mme_s11_teid, sgw_ue->sgw_s11_teid);
mme_ue_clear_indirect_tunnel(mme_ue); mme_ue_clear_indirect_tunnel(mme_ue);
@ -1470,7 +1585,7 @@ void mme_s11_handle_delete_indirect_data_forwarding_tunnel_response(
} }
void mme_s11_handle_bearer_resource_failure_indication( void mme_s11_handle_bearer_resource_failure_indication(
ogs_gtp_xact_t *xact, sgw_ue_t *sgw_ue, ogs_gtp_xact_t *xact, mme_ue_t *mme_ue_from_teid,
ogs_gtp2_bearer_resource_failure_indication_t *ind) ogs_gtp2_bearer_resource_failure_indication_t *ind)
{ {
int rv; int rv;
@ -1479,6 +1594,7 @@ void mme_s11_handle_bearer_resource_failure_indication(
mme_bearer_t *bearer = NULL; mme_bearer_t *bearer = NULL;
mme_sess_t *sess = NULL; mme_sess_t *sess = NULL;
mme_ue_t *mme_ue = NULL; mme_ue_t *mme_ue = NULL;
sgw_ue_t *sgw_ue = NULL;
ogs_debug("Bearer Resource Failure Indication"); ogs_debug("Bearer Resource Failure Indication");
@ -1492,11 +1608,13 @@ void mme_s11_handle_bearer_resource_failure_indication(
ogs_assert(sess); ogs_assert(sess);
mme_ue = sess->mme_ue; mme_ue = sess->mme_ue;
ogs_assert(mme_ue); ogs_assert(mme_ue);
sgw_ue = sgw_ue_cycle(mme_ue->sgw_ue);
ogs_assert(sgw_ue);
rv = ogs_gtp_xact_commit(xact); rv = ogs_gtp_xact_commit(xact);
ogs_expect_or_return(rv == OGS_OK); ogs_expect_or_return(rv == OGS_OK);
if (!sgw_ue) if (!mme_ue_from_teid)
ogs_error("No Context in TEID"); ogs_error("No Context in TEID");
/******************** /********************
@ -1516,10 +1634,10 @@ void mme_s11_handle_bearer_resource_failure_indication(
* Check ALL Context * Check ALL Context
********************/ ********************/
ogs_assert(mme_ue); ogs_assert(mme_ue);
ogs_assert(sgw_ue);
if (sgw_ue) ogs_debug(" MME_S11_TEID[%d] SGW_S11_TEID[%d]",
ogs_debug(" MME_S11_TEID[%d] SGW_S11_TEID[%d]", mme_ue->mme_s11_teid, sgw_ue->sgw_s11_teid);
sgw_ue->mme_s11_teid, sgw_ue->sgw_s11_teid);
ogs_assert(OGS_OK == ogs_assert(OGS_OK ==
nas_eps_send_bearer_resource_modification_reject( nas_eps_send_bearer_resource_modification_reject(

View File

@ -31,39 +31,39 @@ void mme_s11_handle_echo_request(
void mme_s11_handle_echo_response( void mme_s11_handle_echo_response(
ogs_gtp_xact_t *xact, ogs_gtp2_echo_response_t *rsp); ogs_gtp_xact_t *xact, ogs_gtp2_echo_response_t *rsp);
void mme_s11_handle_create_session_response( void mme_s11_handle_create_session_response(
ogs_gtp_xact_t *xact, sgw_ue_t *sgw_ue, ogs_gtp_xact_t *xact, mme_ue_t *mme_ue,
ogs_gtp2_create_session_response_t *rsp); ogs_gtp2_create_session_response_t *rsp);
void mme_s11_handle_modify_bearer_response( void mme_s11_handle_modify_bearer_response(
ogs_gtp_xact_t *xact, sgw_ue_t *sgw_ue, ogs_gtp_xact_t *xact, mme_ue_t *mme_ue,
ogs_gtp2_modify_bearer_response_t *rsp); ogs_gtp2_modify_bearer_response_t *rsp);
void mme_s11_handle_delete_session_response( void mme_s11_handle_delete_session_response(
ogs_gtp_xact_t *xact, sgw_ue_t *sgw_ue, ogs_gtp_xact_t *xact, mme_ue_t *mme_ue,
ogs_gtp2_delete_session_response_t *rsp); ogs_gtp2_delete_session_response_t *rsp);
void mme_s11_handle_create_bearer_request( void mme_s11_handle_create_bearer_request(
ogs_gtp_xact_t *xact, sgw_ue_t *sgw_ue, ogs_gtp_xact_t *xact, mme_ue_t *mme_ue,
ogs_gtp2_create_bearer_request_t *rsp); ogs_gtp2_create_bearer_request_t *rsp);
void mme_s11_handle_update_bearer_request( void mme_s11_handle_update_bearer_request(
ogs_gtp_xact_t *xact, sgw_ue_t *sgw_ue, ogs_gtp_xact_t *xact, mme_ue_t *mme_ue,
ogs_gtp2_update_bearer_request_t *rsp); ogs_gtp2_update_bearer_request_t *rsp);
void mme_s11_handle_delete_bearer_request( void mme_s11_handle_delete_bearer_request(
ogs_gtp_xact_t *xact, sgw_ue_t *sgw_ue, ogs_gtp_xact_t *xact, mme_ue_t *mme_ue,
ogs_gtp2_delete_bearer_request_t *rsp); ogs_gtp2_delete_bearer_request_t *rsp);
void mme_s11_handle_release_access_bearers_response( void mme_s11_handle_release_access_bearers_response(
ogs_gtp_xact_t *xact, sgw_ue_t *sgw_ue, ogs_gtp_xact_t *xact, mme_ue_t *mme_ue,
ogs_gtp2_release_access_bearers_response_t *rsp); ogs_gtp2_release_access_bearers_response_t *rsp);
void mme_s11_handle_downlink_data_notification( void mme_s11_handle_downlink_data_notification(
ogs_gtp_xact_t *xact, sgw_ue_t *sgw_ue, ogs_gtp_xact_t *xact, mme_ue_t *mme_ue,
ogs_gtp2_downlink_data_notification_t *noti); ogs_gtp2_downlink_data_notification_t *noti);
void mme_s11_handle_create_indirect_data_forwarding_tunnel_response( void mme_s11_handle_create_indirect_data_forwarding_tunnel_response(
ogs_gtp_xact_t *xact, sgw_ue_t *sgw_ue, ogs_gtp_xact_t *xact, mme_ue_t *mme_ue,
ogs_gtp2_create_indirect_data_forwarding_tunnel_response_t *rsp); ogs_gtp2_create_indirect_data_forwarding_tunnel_response_t *rsp);
void mme_s11_handle_delete_indirect_data_forwarding_tunnel_response( void mme_s11_handle_delete_indirect_data_forwarding_tunnel_response(
ogs_gtp_xact_t *xact, sgw_ue_t *sgw_ue, ogs_gtp_xact_t *xact, mme_ue_t *mme_ue,
ogs_gtp2_delete_indirect_data_forwarding_tunnel_response_t *rsp); ogs_gtp2_delete_indirect_data_forwarding_tunnel_response_t *rsp);
void mme_s11_handle_bearer_resource_failure_indication( void mme_s11_handle_bearer_resource_failure_indication(
ogs_gtp_xact_t *xact, sgw_ue_t *sgw_ue, ogs_gtp_xact_t *xact, mme_ue_t *mme_ue,
ogs_gtp2_bearer_resource_failure_indication_t *ind); ogs_gtp2_bearer_resource_failure_indication_t *ind);
#ifdef __cplusplus #ifdef __cplusplus

View File

@ -521,6 +521,15 @@ void mme_state_operational(ogs_fsm_t *s, mme_event_t *e)
break; break;
} }
gnode = e->gnode;
ogs_assert(gnode);
rv = ogs_gtp_xact_receive(gnode, &gtp_message.h, &xact);
if (rv != OGS_OK) {
ogs_pkbuf_free(pkbuf);
break;
}
/* /*
* 5.5.2 in spec 29.274 * 5.5.2 in spec 29.274
* *
@ -552,21 +561,7 @@ void mme_state_operational(ogs_fsm_t *s, mme_event_t *e)
*/ */
if (gtp_message.h.teid_presence && gtp_message.h.teid != 0) { if (gtp_message.h.teid_presence && gtp_message.h.teid != 0) {
/* Cause is not "Context not found" */ /* Cause is not "Context not found" */
sgw_ue = sgw_ue_find_by_mme_s11_teid(gtp_message.h.teid); mme_ue = mme_ue_find_by_teid(gtp_message.h.teid);
}
if (sgw_ue) {
gnode = sgw_ue->gnode;
ogs_assert(gnode);
} else {
gnode = e->gnode;
ogs_assert(gnode);
}
rv = ogs_gtp_xact_receive(gnode, &gtp_message.h, &xact);
if (rv != OGS_OK) {
ogs_pkbuf_free(pkbuf);
break;
} }
switch (gtp_message.h.type) { switch (gtp_message.h.type) {
@ -578,49 +573,49 @@ void mme_state_operational(ogs_fsm_t *s, mme_event_t *e)
break; break;
case OGS_GTP2_CREATE_SESSION_RESPONSE_TYPE: case OGS_GTP2_CREATE_SESSION_RESPONSE_TYPE:
mme_s11_handle_create_session_response( mme_s11_handle_create_session_response(
xact, sgw_ue, &gtp_message.create_session_response); xact, mme_ue, &gtp_message.create_session_response);
break; break;
case OGS_GTP2_MODIFY_BEARER_RESPONSE_TYPE: case OGS_GTP2_MODIFY_BEARER_RESPONSE_TYPE:
mme_s11_handle_modify_bearer_response( mme_s11_handle_modify_bearer_response(
xact, sgw_ue, &gtp_message.modify_bearer_response); xact, mme_ue, &gtp_message.modify_bearer_response);
break; break;
case OGS_GTP2_DELETE_SESSION_RESPONSE_TYPE: case OGS_GTP2_DELETE_SESSION_RESPONSE_TYPE:
mme_s11_handle_delete_session_response( mme_s11_handle_delete_session_response(
xact, sgw_ue, &gtp_message.delete_session_response); xact, mme_ue, &gtp_message.delete_session_response);
break; break;
case OGS_GTP2_CREATE_BEARER_REQUEST_TYPE: case OGS_GTP2_CREATE_BEARER_REQUEST_TYPE:
mme_s11_handle_create_bearer_request( mme_s11_handle_create_bearer_request(
xact, sgw_ue, &gtp_message.create_bearer_request); xact, mme_ue, &gtp_message.create_bearer_request);
break; break;
case OGS_GTP2_UPDATE_BEARER_REQUEST_TYPE: case OGS_GTP2_UPDATE_BEARER_REQUEST_TYPE:
mme_s11_handle_update_bearer_request( mme_s11_handle_update_bearer_request(
xact, sgw_ue, &gtp_message.update_bearer_request); xact, mme_ue, &gtp_message.update_bearer_request);
break; break;
case OGS_GTP2_DELETE_BEARER_REQUEST_TYPE: case OGS_GTP2_DELETE_BEARER_REQUEST_TYPE:
mme_s11_handle_delete_bearer_request( mme_s11_handle_delete_bearer_request(
xact, sgw_ue, &gtp_message.delete_bearer_request); xact, mme_ue, &gtp_message.delete_bearer_request);
break; break;
case OGS_GTP2_RELEASE_ACCESS_BEARERS_RESPONSE_TYPE: case OGS_GTP2_RELEASE_ACCESS_BEARERS_RESPONSE_TYPE:
mme_s11_handle_release_access_bearers_response( mme_s11_handle_release_access_bearers_response(
xact, sgw_ue, &gtp_message.release_access_bearers_response); xact, mme_ue, &gtp_message.release_access_bearers_response);
break; break;
case OGS_GTP2_DOWNLINK_DATA_NOTIFICATION_TYPE: case OGS_GTP2_DOWNLINK_DATA_NOTIFICATION_TYPE:
mme_s11_handle_downlink_data_notification( mme_s11_handle_downlink_data_notification(
xact, sgw_ue, &gtp_message.downlink_data_notification); xact, mme_ue, &gtp_message.downlink_data_notification);
break; break;
case OGS_GTP2_CREATE_INDIRECT_DATA_FORWARDING_TUNNEL_RESPONSE_TYPE: case OGS_GTP2_CREATE_INDIRECT_DATA_FORWARDING_TUNNEL_RESPONSE_TYPE:
mme_s11_handle_create_indirect_data_forwarding_tunnel_response( mme_s11_handle_create_indirect_data_forwarding_tunnel_response(
xact, sgw_ue, xact, mme_ue,
&gtp_message.create_indirect_data_forwarding_tunnel_response); &gtp_message.create_indirect_data_forwarding_tunnel_response);
break; break;
case OGS_GTP2_DELETE_INDIRECT_DATA_FORWARDING_TUNNEL_RESPONSE_TYPE: case OGS_GTP2_DELETE_INDIRECT_DATA_FORWARDING_TUNNEL_RESPONSE_TYPE:
mme_s11_handle_delete_indirect_data_forwarding_tunnel_response( mme_s11_handle_delete_indirect_data_forwarding_tunnel_response(
xact, sgw_ue, xact, mme_ue,
&gtp_message.delete_indirect_data_forwarding_tunnel_response); &gtp_message.delete_indirect_data_forwarding_tunnel_response);
break; break;
case OGS_GTP2_BEARER_RESOURCE_FAILURE_INDICATION_TYPE: case OGS_GTP2_BEARER_RESOURCE_FAILURE_INDICATION_TYPE:
mme_s11_handle_bearer_resource_failure_indication( mme_s11_handle_bearer_resource_failure_indication(
xact, sgw_ue, xact, mme_ue,
&gtp_message.bearer_resource_failure_indication); &gtp_message.bearer_resource_failure_indication);
break; break;
default: default:
@ -630,6 +625,37 @@ void mme_state_operational(ogs_fsm_t *s, mme_event_t *e)
ogs_pkbuf_free(pkbuf); ogs_pkbuf_free(pkbuf);
break; break;
case MME_EVT_S11_TIMER:
sgw_ue = e->sgw_ue;
ogs_assert(sgw_ue);
mme_ue = sgw_ue->mme_ue;
ogs_assert(mme_ue);
switch (e->timer_id) {
case MME_TIMER_S11_HOLDING:
GTP_COUNTER_CLEAR(mme_ue,
GTP_COUNTER_DELETE_SESSION_BY_PATH_SWITCH);
ogs_list_for_each(&mme_ue->sess_list, sess) {
GTP_COUNTER_INCREMENT(
mme_ue, GTP_COUNTER_DELETE_SESSION_BY_PATH_SWITCH);
ogs_assert(OGS_OK ==
mme_gtp_send_delete_session_request(
sgw_ue, sess,
OGS_GTP_DELETE_IN_PATH_SWITCH_REQUEST));
}
break;
default:
ogs_error("Unknown timer[%s:%d]",
mme_timer_get_name(e->timer_id), e->timer_id);
}
break;
case MME_EVT_SGSAP_LO_SCTP_COMM_UP: case MME_EVT_SGSAP_LO_SCTP_COMM_UP:
sock = e->sock; sock = e->sock;
ogs_assert(sock); ogs_assert(sock);

View File

@ -1556,7 +1556,8 @@ ogs_pkbuf_t *s1ap_build_mme_configuration_transfer(
return ogs_s1ap_encode(&pdu); return ogs_s1ap_encode(&pdu);
} }
ogs_pkbuf_t *s1ap_build_path_switch_ack(mme_ue_t *mme_ue) ogs_pkbuf_t *s1ap_build_path_switch_ack(
mme_ue_t *mme_ue, bool e_rab_to_switched_in_uplink_list)
{ {
S1AP_S1AP_PDU_t pdu; S1AP_S1AP_PDU_t pdu;
S1AP_SuccessfulOutcome_t *successfulOutcome = NULL; S1AP_SuccessfulOutcome_t *successfulOutcome = NULL;
@ -1565,8 +1566,11 @@ ogs_pkbuf_t *s1ap_build_path_switch_ack(mme_ue_t *mme_ue)
S1AP_PathSwitchRequestAcknowledgeIEs_t *ie = NULL; S1AP_PathSwitchRequestAcknowledgeIEs_t *ie = NULL;
S1AP_MME_UE_S1AP_ID_t *MME_UE_S1AP_ID = NULL; S1AP_MME_UE_S1AP_ID_t *MME_UE_S1AP_ID = NULL;
S1AP_ENB_UE_S1AP_ID_t *ENB_UE_S1AP_ID = NULL; S1AP_ENB_UE_S1AP_ID_t *ENB_UE_S1AP_ID = NULL;
S1AP_E_RABToBeSwitchedULList_t *E_RABToBeSwitchedULList = NULL;
S1AP_SecurityContext_t *SecurityContext = NULL; S1AP_SecurityContext_t *SecurityContext = NULL;
mme_sess_t *sess = NULL;
mme_bearer_t *bearer = NULL;
enb_ue_t *enb_ue = NULL; enb_ue_t *enb_ue = NULL;
ogs_assert(mme_ue); ogs_assert(mme_ue);
@ -1608,6 +1612,18 @@ ogs_pkbuf_t *s1ap_build_path_switch_ack(mme_ue_t *mme_ue)
ENB_UE_S1AP_ID = &ie->value.choice.ENB_UE_S1AP_ID; ENB_UE_S1AP_ID = &ie->value.choice.ENB_UE_S1AP_ID;
if (e_rab_to_switched_in_uplink_list == true) {
ie = CALLOC(1, sizeof(S1AP_PathSwitchRequestAcknowledgeIEs_t));
ASN_SEQUENCE_ADD(&PathSwitchRequestAcknowledge->protocolIEs, ie);
ie->id = S1AP_ProtocolIE_ID_id_E_RABToBeSwitchedULList;
ie->criticality = S1AP_Criticality_ignore;
ie->value.present =
S1AP_PathSwitchRequestAcknowledgeIEs__value_PR_E_RABToBeSwitchedULList;
E_RABToBeSwitchedULList = &ie->value.choice.E_RABToBeSwitchedULList;
}
ie = CALLOC(1, sizeof(S1AP_PathSwitchRequestAcknowledgeIEs_t)); ie = CALLOC(1, sizeof(S1AP_PathSwitchRequestAcknowledgeIEs_t));
ASN_SEQUENCE_ADD(&PathSwitchRequestAcknowledge->protocolIEs, ie); ASN_SEQUENCE_ADD(&PathSwitchRequestAcknowledge->protocolIEs, ie);
@ -1624,6 +1640,31 @@ ogs_pkbuf_t *s1ap_build_path_switch_ack(mme_ue_t *mme_ue)
*MME_UE_S1AP_ID = enb_ue->mme_ue_s1ap_id; *MME_UE_S1AP_ID = enb_ue->mme_ue_s1ap_id;
*ENB_UE_S1AP_ID = enb_ue->enb_ue_s1ap_id; *ENB_UE_S1AP_ID = enb_ue->enb_ue_s1ap_id;
if (e_rab_to_switched_in_uplink_list == true) {
ogs_list_for_each(&mme_ue->sess_list, sess) {
ogs_list_for_each(&sess->bearer_list, bearer) {
S1AP_E_RABToBeSwitchedULItemIEs_t *item = NULL;
S1AP_E_RABToBeSwitchedULItem_t *e_rab = NULL;
item = CALLOC(1, sizeof(S1AP_E_RABToBeSwitchedULItemIEs_t));
ASN_SEQUENCE_ADD(&E_RABToBeSwitchedULList->list, item);
item->id = S1AP_ProtocolIE_ID_id_E_RABToBeSwitchedULItem;
item->criticality = S1AP_Criticality_ignore;
item->value.present = S1AP_E_RABToBeSwitchedULItemIEs__value_PR_E_RABToBeSwitchedULItem;
e_rab = &item->value.choice.E_RABToBeSwitchedULItem;
e_rab->e_RAB_ID = bearer->ebi;
ogs_assert(OGS_OK == ogs_asn_ip_to_BIT_STRING(
&bearer->sgw_s1u_ip, &e_rab->transportLayerAddress));
ogs_asn_uint32_to_OCTET_STRING(
bearer->sgw_s1u_teid, &e_rab->gTP_TEID);
}
}
}
SecurityContext->nextHopChainingCount = mme_ue->nhcc; SecurityContext->nextHopChainingCount = mme_ue->nhcc;
SecurityContext->nextHopParameter.size = OGS_SHA256_DIGEST_SIZE; SecurityContext->nextHopParameter.size = OGS_SHA256_DIGEST_SIZE;
SecurityContext->nextHopParameter.buf = SecurityContext->nextHopParameter.buf =

View File

@ -56,7 +56,8 @@ ogs_pkbuf_t *s1ap_build_paging(
ogs_pkbuf_t *s1ap_build_mme_configuration_transfer( ogs_pkbuf_t *s1ap_build_mme_configuration_transfer(
S1AP_SONConfigurationTransfer_t *son_configuration_transfer); S1AP_SONConfigurationTransfer_t *son_configuration_transfer);
ogs_pkbuf_t *s1ap_build_path_switch_ack(mme_ue_t *mme_ue); ogs_pkbuf_t *s1ap_build_path_switch_ack(
mme_ue_t *mme_ue, bool e_rab_to_switched_in_uplink_list);
ogs_pkbuf_t *s1ap_build_path_switch_failure( ogs_pkbuf_t *s1ap_build_path_switch_failure(
uint32_t enb_ue_s1ap_id, uint32_t mme_ue_s1ap_id, uint32_t enb_ue_s1ap_id, uint32_t mme_ue_s1ap_id,
S1AP_Cause_PR group, long cause); S1AP_Cause_PR group, long cause);

View File

@ -1927,69 +1927,64 @@ void s1ap_handle_path_switch_request(
mme_ue->nhcc++; mme_ue->nhcc++;
ogs_kdf_nh_enb(mme_ue->kasme, mme_ue->nh, mme_ue->nh); ogs_kdf_nh_enb(mme_ue->kasme, mme_ue->nh, mme_ue->nh);
#if 0 ogs_list_init(&mme_ue->bearer_to_modify_list);
relocation = sgw_ue_check_if_relocated(mme_ue);
#else
relocation = SGW_WITHOUT_RELOCATION;
#endif
if (relocation == SGW_WITHOUT_RELOCATION) {
ogs_list_init(&mme_ue->bearer_to_modify_list); for (i = 0; i < E_RABToBeSwitchedDLList->list.count; i++) {
S1AP_E_RABToBeSwitchedDLItemIEs_t *item = NULL;
S1AP_E_RABToBeSwitchedDLItem_t *e_rab = NULL;
for (i = 0; i < E_RABToBeSwitchedDLList->list.count; i++) { mme_bearer_t *bearer = NULL;
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];
item = (S1AP_E_RABToBeSwitchedDLItemIEs_t *) if (!item) {
E_RABToBeSwitchedDLList->list.array[i]; ogs_error("No S1AP_E_RABToBeSwitchedDLItemIEs_t");
if (!item) { ogs_assert(OGS_OK ==
ogs_error("No S1AP_E_RABToBeSwitchedDLItemIEs_t"); s1ap_send_error_indication2(mme_ue,
ogs_assert(OGS_OK == S1AP_Cause_PR_protocol, S1AP_CauseProtocol_semantic_error));
s1ap_send_error_indication2(mme_ue, return;
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;
}
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);
}
relocation = sgw_ue_check_if_relocated(mme_ue);
if (relocation == SGW_WITHOUT_RELOCATION) {
if (ogs_list_count(&mme_ue->bearer_to_modify_list)) { if (ogs_list_count(&mme_ue->bearer_to_modify_list)) {
ogs_assert(OGS_OK == mme_gtp_send_modify_bearer_request( ogs_assert(OGS_OK == mme_gtp_send_modify_bearer_request(
mme_ue, 1, OGS_GTP_MODIFY_IN_PATH_SWITCH_REQUEST)); mme_ue, 1, OGS_GTP_MODIFY_IN_PATH_SWITCH_REQUEST));
@ -1998,6 +1993,9 @@ void s1ap_handle_path_switch_request(
mme_sess_t *sess = NULL; mme_sess_t *sess = NULL;
ogs_list_for_each(&mme_ue->sess_list, sess) { ogs_list_for_each(&mme_ue->sess_list, sess) {
GTP_COUNTER_INCREMENT(
mme_ue, GTP_COUNTER_CREATE_SESSION_BY_PATH_SWITCH);
ogs_assert(OGS_OK == ogs_assert(OGS_OK ==
mme_gtp_send_create_session_request( mme_gtp_send_create_session_request(
sess, OGS_GTP_CREATE_IN_PATH_SWITCH_REQUEST)); sess, OGS_GTP_CREATE_IN_PATH_SWITCH_REQUEST));

View File

@ -415,7 +415,8 @@ int s1ap_send_e_rab_modification_confirm(mme_ue_t *mme_ue)
return rv; return rv;
} }
int s1ap_send_path_switch_ack(mme_ue_t *mme_ue) int s1ap_send_path_switch_ack(
mme_ue_t *mme_ue, bool e_rab_to_switched_in_uplink_list)
{ {
int rv; int rv;
ogs_pkbuf_t *s1apbuf = NULL; ogs_pkbuf_t *s1apbuf = NULL;
@ -423,7 +424,8 @@ int s1ap_send_path_switch_ack(mme_ue_t *mme_ue)
ogs_assert(mme_ue); ogs_assert(mme_ue);
ogs_debug("PathSwitchAcknowledge"); ogs_debug("PathSwitchAcknowledge");
s1apbuf = s1ap_build_path_switch_ack(mme_ue); s1apbuf = s1ap_build_path_switch_ack(
mme_ue, e_rab_to_switched_in_uplink_list);
ogs_expect_or_return_val(s1apbuf, OGS_ERROR); ogs_expect_or_return_val(s1apbuf, OGS_ERROR);
rv = nas_eps_send_to_enb(mme_ue, s1apbuf); rv = nas_eps_send_to_enb(mme_ue, s1apbuf);

View File

@ -66,7 +66,8 @@ int s1ap_send_mme_configuration_transfer(
int s1ap_send_e_rab_modification_confirm(mme_ue_t *mme_ue); int s1ap_send_e_rab_modification_confirm(mme_ue_t *mme_ue);
int s1ap_send_path_switch_ack(mme_ue_t *mme_ue); int s1ap_send_path_switch_ack(
mme_ue_t *mme_ue, bool e_rab_to_switched_in_uplink_list);
int s1ap_send_handover_command(enb_ue_t *source_ue); int s1ap_send_handover_command(enb_ue_t *source_ue);
int s1ap_send_handover_preparation_failure( int s1ap_send_handover_preparation_failure(

View File

@ -155,7 +155,7 @@ 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_find_by_ebi(sgwc_ue_t *sgwc_ue, uint8_t ebi);
sgwc_sess_t *sgwc_sess_cycle(sgwc_sess_t *sess); sgwc_sess_t *sgwc_sess_cycle(sgwc_sess_t *sess);
#define SESSION_SYNC_DONE(__sGWC, __tYPE, __fLAGS) \ #define SGWC_SESSION_SYNC_DONE(__sGWC, __tYPE, __fLAGS) \
(sgwc_sess_pfcp_xact_count(__sGWC, __tYPE, __fLAGS) == 0) (sgwc_sess_pfcp_xact_count(__sGWC, __tYPE, __fLAGS) == 0)
int sgwc_sess_pfcp_xact_count( int sgwc_sess_pfcp_xact_count(
sgwc_ue_t *sgwc_ue, uint8_t pfcp_type, uint64_t modify_flags); sgwc_ue_t *sgwc_ue, uint8_t pfcp_type, uint64_t modify_flags);

View File

@ -159,6 +159,37 @@ static void bearer_timeout(ogs_gtp_xact_t *xact, void *data)
} }
} }
int sgwc_gtp_send_create_session_response(
sgwc_sess_t *sess, ogs_gtp_xact_t *xact)
{
int rv;
sgwc_ue_t *sgwc_ue = NULL;
ogs_gtp2_header_t h;
ogs_pkbuf_t *pkbuf = NULL;
ogs_assert(sess);
sgwc_ue = sess->sgwc_ue;
ogs_assert(sgwc_ue);
ogs_assert(xact);
memset(&h, 0, sizeof(ogs_gtp2_header_t));
h.type = OGS_GTP2_CREATE_SESSION_RESPONSE_TYPE;
h.teid = sgwc_ue->mme_s11_teid;
pkbuf = sgwc_s11_build_create_session_response(h.type, sess);
ogs_expect_or_return_val(pkbuf, OGS_ERROR);
rv = ogs_gtp_xact_update_tx(xact, &h, pkbuf);
ogs_expect_or_return_val(rv == OGS_OK, OGS_ERROR);
rv = ogs_gtp_xact_commit(xact);
ogs_expect(rv == OGS_OK);
return rv;
}
int sgwc_gtp_send_downlink_data_notification( int sgwc_gtp_send_downlink_data_notification(
uint8_t cause_value, sgwc_bearer_t *bearer) uint8_t cause_value, sgwc_bearer_t *bearer)
{ {
@ -169,8 +200,8 @@ int sgwc_gtp_send_downlink_data_notification(
ogs_gtp_xact_t *gtp_xact = NULL; ogs_gtp_xact_t *gtp_xact = NULL;
ogs_pkbuf_t *pkbuf = NULL;
ogs_gtp2_header_t h; ogs_gtp2_header_t h;
ogs_pkbuf_t *pkbuf = NULL;
ogs_assert(bearer); ogs_assert(bearer);

View File

@ -29,6 +29,9 @@ extern "C" {
int sgwc_gtp_open(void); int sgwc_gtp_open(void);
void sgwc_gtp_close(void); void sgwc_gtp_close(void);
int sgwc_gtp_send_create_session_response(
sgwc_sess_t *sess, ogs_gtp_xact_t *xact);
int sgwc_gtp_send_downlink_data_notification( int sgwc_gtp_send_downlink_data_notification(
uint8_t cause_value, sgwc_bearer_t *bearer); uint8_t cause_value, sgwc_bearer_t *bearer);

View File

@ -202,6 +202,32 @@ static void bearer_timeout(ogs_pfcp_xact_t *xact, void *data)
} }
} }
int sgwc_pfcp_send_bearer_to_modify_list(
sgwc_sess_t *sess, ogs_pfcp_xact_t *xact)
{
int rv;
ogs_pkbuf_t *sxabuf = NULL;
ogs_pfcp_header_t h;
ogs_assert(sess);
ogs_assert(xact);
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_to_modify_list(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);
return rv;
}
int sgwc_pfcp_send_session_establishment_request( int sgwc_pfcp_send_session_establishment_request(
sgwc_sess_t *sess, ogs_gtp_xact_t *gtp_xact, ogs_pkbuf_t *gtpbuf) sgwc_sess_t *sess, ogs_gtp_xact_t *gtp_xact, ogs_pkbuf_t *gtpbuf)
{ {
@ -212,10 +238,6 @@ int sgwc_pfcp_send_session_establishment_request(
ogs_assert(sess); ogs_assert(sess);
memset(&h, 0, sizeof(ogs_pfcp_header_t));
h.type = OGS_PFCP_SESSION_ESTABLISHMENT_REQUEST_TYPE;
h.seid = sess->sgwu_sxa_seid;
xact = ogs_pfcp_xact_local_create(sess->pfcp_node, sess_timeout, sess); xact = ogs_pfcp_xact_local_create(sess->pfcp_node, sess_timeout, sess);
ogs_expect_or_return_val(xact, OGS_ERROR); ogs_expect_or_return_val(xact, OGS_ERROR);
@ -225,6 +247,10 @@ int sgwc_pfcp_send_session_establishment_request(
ogs_expect_or_return_val(xact->gtpbuf, OGS_ERROR); ogs_expect_or_return_val(xact->gtpbuf, OGS_ERROR);
} }
memset(&h, 0, sizeof(ogs_pfcp_header_t));
h.type = OGS_PFCP_SESSION_ESTABLISHMENT_REQUEST_TYPE;
h.seid = sess->sgwu_sxa_seid;
sxabuf = sgwc_sxa_build_session_establishment_request(h.type, sess); sxabuf = sgwc_sxa_build_session_establishment_request(h.type, sess);
ogs_expect_or_return_val(sxabuf, OGS_ERROR); ogs_expect_or_return_val(sxabuf, OGS_ERROR);
@ -237,55 +263,7 @@ int sgwc_pfcp_send_session_establishment_request(
return rv; return rv;
} }
ogs_pfcp_xact_t *sgwc_pfcp_xact_create( int sgwc_pfcp_send_session_modification_request(
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);
return rv;
}
int sgwc_pfcp_send_sess_modification_request(
sgwc_sess_t *sess, ogs_gtp_xact_t *gtp_xact, sgwc_sess_t *sess, ogs_gtp_xact_t *gtp_xact,
ogs_pkbuf_t *gtpbuf, uint64_t flags) ogs_pkbuf_t *gtpbuf, uint64_t flags)
{ {
@ -294,13 +272,20 @@ int sgwc_pfcp_send_sess_modification_request(
ogs_assert(sess); ogs_assert(sess);
xact = sgwc_pfcp_xact_create(sess, gtp_xact, gtpbuf, flags); xact = ogs_pfcp_xact_local_create(sess->pfcp_node, sess_timeout, sess);
ogs_expect_or_return_val(xact, OGS_ERROR); 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_for_each(&sess->bearer_list, bearer) ogs_list_for_each(&sess->bearer_list, bearer)
ogs_list_add(&xact->bearer_to_modify_list, &bearer->to_modify_node); ogs_list_add(&xact->bearer_to_modify_list, &bearer->to_modify_node);
return sgwc_pfcp_xact_commit(xact); return sgwc_pfcp_send_bearer_to_modify_list(sess, xact);
} }
int sgwc_pfcp_send_bearer_modification_request( int sgwc_pfcp_send_bearer_modification_request(
@ -333,7 +318,7 @@ int sgwc_pfcp_send_bearer_modification_request(
h.type = OGS_PFCP_SESSION_MODIFICATION_REQUEST_TYPE; h.type = OGS_PFCP_SESSION_MODIFICATION_REQUEST_TYPE;
h.seid = sess->sgwu_sxa_seid; h.seid = sess->sgwu_sxa_seid;
sxabuf = sgwc_sxa_build_session_modification_request(h.type, sess, xact); sxabuf = sgwc_sxa_build_bearer_to_modify_list(h.type, sess, xact);
ogs_expect_or_return_val(sxabuf, OGS_ERROR); ogs_expect_or_return_val(sxabuf, OGS_ERROR);
rv = ogs_pfcp_xact_update_tx(xact, &h, sxabuf); rv = ogs_pfcp_xact_update_tx(xact, &h, sxabuf);
@ -355,10 +340,6 @@ int sgwc_pfcp_send_session_deletion_request(
ogs_assert(sess); ogs_assert(sess);
memset(&h, 0, sizeof(ogs_pfcp_header_t));
h.type = OGS_PFCP_SESSION_DELETION_REQUEST_TYPE;
h.seid = sess->sgwu_sxa_seid;
xact = ogs_pfcp_xact_local_create(sess->pfcp_node, sess_timeout, sess); xact = ogs_pfcp_xact_local_create(sess->pfcp_node, sess_timeout, sess);
ogs_expect_or_return_val(xact, OGS_ERROR); ogs_expect_or_return_val(xact, OGS_ERROR);
@ -368,6 +349,10 @@ int sgwc_pfcp_send_session_deletion_request(
ogs_expect_or_return_val(xact->gtpbuf, OGS_ERROR); ogs_expect_or_return_val(xact->gtpbuf, OGS_ERROR);
} }
memset(&h, 0, sizeof(ogs_pfcp_header_t));
h.type = OGS_PFCP_SESSION_DELETION_REQUEST_TYPE;
h.seid = sess->sgwu_sxa_seid;
sxabuf = sgwc_sxa_build_session_deletion_request(h.type, sess); sxabuf = sgwc_sxa_build_session_deletion_request(h.type, sess);
ogs_expect_or_return_val(sxabuf, OGS_ERROR); ogs_expect_or_return_val(sxabuf, OGS_ERROR);

View File

@ -29,31 +29,19 @@ extern "C" {
int sgwc_pfcp_open(void); int sgwc_pfcp_open(void);
void sgwc_pfcp_close(void); void sgwc_pfcp_close(void);
int sgwc_pfcp_send_bearer_to_modify_list(
sgwc_sess_t *sess, ogs_pfcp_xact_t *xact);
int sgwc_pfcp_send_session_establishment_request( int sgwc_pfcp_send_session_establishment_request(
sgwc_sess_t *sess, ogs_gtp_xact_t *gtp_xact, ogs_pkbuf_t *gtpbuf); sgwc_sess_t *sess, ogs_gtp_xact_t *gtp_xact, ogs_pkbuf_t *gtpbuf);
/* int sgwc_pfcp_send_session_modification_request(
* 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, sgwc_sess_t *sess, ogs_gtp_xact_t *gtp_xact,
ogs_pkbuf_t *gtpbuf, uint64_t flags); 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( int sgwc_pfcp_send_bearer_modification_request(
sgwc_bearer_t *bearer, ogs_gtp_xact_t *gtp_xact, sgwc_bearer_t *bearer, ogs_gtp_xact_t *gtp_xact,
ogs_pkbuf_t *gtpbuf, uint64_t flags); ogs_pkbuf_t *gtpbuf, uint64_t flags);
int sgwc_pfcp_send_session_deletion_request( int sgwc_pfcp_send_session_deletion_request(
sgwc_sess_t *sess, ogs_gtp_xact_t *gtp_xact, ogs_pkbuf_t *gtpbuf); sgwc_sess_t *sess, ogs_gtp_xact_t *gtp_xact, ogs_pkbuf_t *gtpbuf);

View File

@ -19,6 +19,118 @@
#include "s11-build.h" #include "s11-build.h"
ogs_pkbuf_t *sgwc_s11_build_create_session_response(
uint8_t type, sgwc_sess_t *sess)
{
int rv, i;
sgwc_bearer_t *bearer = NULL;
sgwc_tunnel_t *ul_tunnel = NULL;
sgwc_ue_t *sgwc_ue = NULL;
ogs_gtp2_message_t gtp_message;
ogs_gtp2_create_session_response_t *rsp = NULL;
ogs_gtp2_cause_t cause;
ogs_gtp2_f_teid_t sgw_s11_teid;
int len;
ogs_gtp2_cause_t bearer_cause[OGS_BEARER_PER_UE];
ogs_gtp2_f_teid_t sgw_s1u_teid[OGS_BEARER_PER_UE];
int sgw_s1u_len[OGS_BEARER_PER_UE];
ogs_gtp2_f_teid_t pgw_s5u_teid[OGS_BEARER_PER_UE];
int pgw_s5u_len[OGS_BEARER_PER_UE];
ogs_debug("[SGWC] Create Session Response");
ogs_assert(sess);
sgwc_ue = sess->sgwc_ue;
ogs_assert(sgwc_ue);
ogs_debug(" SGW_S5C_TEID[0x%x] PGW_S5C_TEID[0x%x]",
sess->sgw_s5c_teid, sess->pgw_s5c_teid);
rsp = &gtp_message.create_session_response;
memset(&gtp_message, 0, sizeof(ogs_gtp2_message_t));
/* Set Cause */
memset(&cause, 0, sizeof(cause));
rsp->cause.presence = 1;
rsp->cause.len = sizeof(cause);
rsp->cause.data = &cause;
cause.value = OGS_GTP2_CAUSE_REQUEST_ACCEPTED;
/* Send Control Plane(UL) : SGW-S11 */
memset(&sgw_s11_teid, 0, sizeof(ogs_gtp2_f_teid_t));
sgw_s11_teid.interface_type = OGS_GTP2_F_TEID_S11_S4_SGW_GTP_C;
sgw_s11_teid.teid = htobe32(sgwc_ue->sgw_s11_teid);
rv = ogs_gtp2_sockaddr_to_f_teid(
ogs_gtp_self()->gtpc_addr, ogs_gtp_self()->gtpc_addr6,
&sgw_s11_teid, &len);
ogs_assert(rv == OGS_OK);
rsp->sender_f_teid_for_control_plane.presence = 1;
rsp->sender_f_teid_for_control_plane.data = &sgw_s11_teid;
rsp->sender_f_teid_for_control_plane.len = len;
i = 0;
ogs_list_for_each(&sess->bearer_list, bearer) {
ogs_assert(i < OGS_BEARER_PER_UE);
/* Bearer EBI */
rsp->bearer_contexts_created[i].presence = 1;
rsp->bearer_contexts_created[i].eps_bearer_id.presence = 1;
rsp->bearer_contexts_created[i].eps_bearer_id.u8 = bearer->ebi;
/* Bearer Cause */
memset(&bearer_cause[i], 0, sizeof(bearer_cause[i]));
rsp->bearer_contexts_created[i].cause.presence = 1;
rsp->bearer_contexts_created[i].cause.len = sizeof(bearer_cause[i]);
rsp->bearer_contexts_created[i].cause.data = &bearer_cause[i];
bearer_cause[i].value = OGS_GTP2_CAUSE_REQUEST_ACCEPTED;
/* Data Plane(UL) */
ul_tunnel = sgwc_ul_tunnel_in_bearer(bearer);
ogs_assert(ul_tunnel);
ogs_debug(" SGW_S1U_TEID[0x%x] PGW_S5U_TEID[0x%x]",
ul_tunnel->local_teid, ul_tunnel->remote_teid);
/* Data Plane(UL) : SGW-S1U */
memset(&sgw_s1u_teid[i], 0, sizeof(ogs_gtp2_f_teid_t));
sgw_s1u_teid[i].interface_type = ul_tunnel->interface_type;
sgw_s1u_teid[i].teid = htobe32(ul_tunnel->local_teid);
ogs_assert(ul_tunnel->local_addr || ul_tunnel->local_addr6);
rv = ogs_gtp2_sockaddr_to_f_teid(
ul_tunnel->local_addr, ul_tunnel->local_addr6,
&sgw_s1u_teid[i], &sgw_s1u_len[i]);
ogs_assert(rv == OGS_OK);
rsp->bearer_contexts_created[i].s1_u_enodeb_f_teid.presence = 1;
rsp->bearer_contexts_created[i].s1_u_enodeb_f_teid.data =
&sgw_s1u_teid[i];
rsp->bearer_contexts_created[i].s1_u_enodeb_f_teid.len =
sgw_s1u_len[i];
/* Data Plane(UL) : PGW-S5U */
memset(&pgw_s5u_teid[i], 0, sizeof(ogs_gtp2_f_teid_t));
pgw_s5u_teid[i].interface_type = OGS_GTP2_F_TEID_S5_S8_PGW_GTP_U;
pgw_s5u_teid[i].teid = htobe32(ul_tunnel->remote_teid);
rv = ogs_gtp2_ip_to_f_teid(&ul_tunnel->remote_ip,
&pgw_s5u_teid[i], &pgw_s5u_len[i]);
ogs_assert(rv == OGS_OK);
rsp->bearer_contexts_created[i].s5_s8_u_sgw_f_teid.presence = 1;
rsp->bearer_contexts_created[i].s5_s8_u_sgw_f_teid.data =
&pgw_s5u_teid[i];
rsp->bearer_contexts_created[i].s5_s8_u_sgw_f_teid.len =
pgw_s5u_len[i];
i++;
}
gtp_message.h.type = type;
return ogs_gtp2_build_msg(&gtp_message);
}
ogs_pkbuf_t *sgwc_s11_build_downlink_data_notification( ogs_pkbuf_t *sgwc_s11_build_downlink_data_notification(
uint8_t cause_value, sgwc_bearer_t *bearer) uint8_t cause_value, sgwc_bearer_t *bearer)
{ {

View File

@ -26,6 +26,9 @@
extern "C" { extern "C" {
#endif #endif
ogs_pkbuf_t *sgwc_s11_build_create_session_response(
uint8_t type, sgwc_sess_t *sess);
ogs_pkbuf_t *sgwc_s11_build_downlink_data_notification( ogs_pkbuf_t *sgwc_s11_build_downlink_data_notification(
uint8_t cause_value, sgwc_bearer_t *bearer); uint8_t cause_value, sgwc_bearer_t *bearer);

View File

@ -22,7 +22,7 @@
#include "s11-handler.h" #include "s11-handler.h"
static void sess_timeout(ogs_gtp_xact_t *xact, void *data) static void gtp_sess_timeout(ogs_gtp_xact_t *xact, void *data)
{ {
sgwc_sess_t *sess = data; sgwc_sess_t *sess = data;
sgwc_ue_t *sgwc_ue = NULL; sgwc_ue_t *sgwc_ue = NULL;
@ -52,7 +52,7 @@ static void sess_timeout(ogs_gtp_xact_t *xact, void *data)
} }
} }
static void bearer_timeout(ogs_gtp_xact_t *xact, void *data) static void gtp_bearer_timeout(ogs_gtp_xact_t *xact, void *data)
{ {
sgwc_bearer_t *bearer = data; sgwc_bearer_t *bearer = data;
sgwc_sess_t *sess = NULL; sgwc_sess_t *sess = NULL;
@ -72,6 +72,29 @@ static void bearer_timeout(ogs_gtp_xact_t *xact, void *data)
sgwc_ue->imsi_bcd, type); sgwc_ue->imsi_bcd, type);
} }
static void pfcp_sess_timeout(ogs_pfcp_xact_t *xact, void *data)
{
uint8_t type;
ogs_assert(xact);
type = xact->seq[0].type;
switch (type) {
case OGS_PFCP_SESSION_ESTABLISHMENT_REQUEST_TYPE:
ogs_error("No PFCP session establishment response");
break;
case OGS_PFCP_SESSION_MODIFICATION_REQUEST_TYPE:
ogs_error("No PFCP session modification response");
break;
case OGS_PFCP_SESSION_DELETION_REQUEST_TYPE:
ogs_error("No PFCP session deletion response");
break;
default:
ogs_error("Not implemented [type:%d]", type);
break;
}
}
/* This code was created in case it will be used later, /* This code was created in case it will be used later,
* and is currently not being used. */ * and is currently not being used. */
static uint8_t pfcp_cause_from_gtp(uint8_t gtp_cause) static uint8_t pfcp_cause_from_gtp(uint8_t gtp_cause)
@ -116,6 +139,7 @@ void sgwc_s11_handle_create_session_request(
sgwc_ue_t *sgwc_ue, ogs_gtp_xact_t *s11_xact, sgwc_ue_t *sgwc_ue, ogs_gtp_xact_t *s11_xact,
ogs_pkbuf_t *gtpbuf, ogs_gtp2_message_t *message) ogs_pkbuf_t *gtpbuf, ogs_gtp2_message_t *message)
{ {
int i;
uint8_t cause_value = 0; uint8_t cause_value = 0;
sgwc_sess_t *sess = NULL; sgwc_sess_t *sess = NULL;
@ -164,15 +188,15 @@ void sgwc_s11_handle_create_session_request(
ogs_error("No IMSI"); ogs_error("No IMSI");
cause_value = OGS_GTP2_CAUSE_CONDITIONAL_IE_MISSING; cause_value = OGS_GTP2_CAUSE_CONDITIONAL_IE_MISSING;
} }
if (req->bearer_contexts_to_be_created.presence == 0) { if (req->bearer_contexts_to_be_created[0].presence == 0) {
ogs_error("No Bearer"); ogs_error("No Bearer");
cause_value = OGS_GTP2_CAUSE_MANDATORY_IE_MISSING; cause_value = OGS_GTP2_CAUSE_MANDATORY_IE_MISSING;
} }
if (req->bearer_contexts_to_be_created.eps_bearer_id.presence == 0) { if (req->bearer_contexts_to_be_created[0].eps_bearer_id.presence == 0) {
ogs_error("No EPS Bearer ID"); ogs_error("No EPS Bearer ID");
cause_value = OGS_GTP2_CAUSE_MANDATORY_IE_MISSING; cause_value = OGS_GTP2_CAUSE_MANDATORY_IE_MISSING;
} }
if (req->bearer_contexts_to_be_created.bearer_level_qos.presence == 0) { if (req->bearer_contexts_to_be_created[0].bearer_level_qos.presence == 0) {
ogs_error("No Bearer QoS"); ogs_error("No Bearer QoS");
cause_value = OGS_GTP2_CAUSE_MANDATORY_IE_MISSING; cause_value = OGS_GTP2_CAUSE_MANDATORY_IE_MISSING;
} }
@ -201,7 +225,7 @@ void sgwc_s11_handle_create_session_request(
req->access_point_name.data, req->access_point_name.data,
ogs_min(req->access_point_name.len, OGS_MAX_APN_LEN))); ogs_min(req->access_point_name.len, OGS_MAX_APN_LEN)));
sess = sgwc_sess_find_by_ebi(sgwc_ue, sess = sgwc_sess_find_by_ebi(sgwc_ue,
req->bearer_contexts_to_be_created.eps_bearer_id.u8); req->bearer_contexts_to_be_created[0].eps_bearer_id.u8);
if (sess) { if (sess) {
ogs_info("OLD Session Release [IMSI:%s,APN:%s]", ogs_info("OLD Session Release [IMSI:%s,APN:%s]",
sgwc_ue->imsi_bcd, sess->session.name); sgwc_ue->imsi_bcd, sess->session.name);
@ -243,27 +267,100 @@ void sgwc_s11_handle_create_session_request(
return; return;
} }
/* Set Bearer QoS */
decoded = ogs_gtp2_parse_bearer_qos(&bearer_qos,
&req->bearer_contexts_to_be_created.bearer_level_qos);
ogs_assert(req->bearer_contexts_to_be_created.bearer_level_qos.len ==
decoded);
sess->session.qos.index = bearer_qos.qci;
sess->session.qos.arp.priority_level = bearer_qos.priority_level;
sess->session.qos.arp.pre_emption_capability =
bearer_qos.pre_emption_capability;
sess->session.qos.arp.pre_emption_vulnerability =
bearer_qos.pre_emption_vulnerability;
/* Remove all previous bearer */ /* Remove all previous bearer */
sgwc_bearer_remove_all(sess); sgwc_bearer_remove_all(sess);
/* Setup Default Bearer */ /* Setup Bearer */
bearer = sgwc_bearer_add(sess); for (i = 0; i < OGS_BEARER_PER_UE; i++) {
ogs_assert(bearer); if (req->bearer_contexts_to_be_created[i].presence == 0)
break;
if (req->bearer_contexts_to_be_created[i].eps_bearer_id.presence == 0) {
ogs_error("No EPS Bearer ID");
break;
}
if (req->bearer_contexts_to_be_created[i].
bearer_level_qos.presence == 0) {
ogs_error("No Bearer QoS");
break;
}
/* Set Bearer EBI */ decoded = ogs_gtp2_parse_bearer_qos(&bearer_qos,
bearer->ebi = req->bearer_contexts_to_be_created.eps_bearer_id.u8; &req->bearer_contexts_to_be_created[i].bearer_level_qos);
ogs_assert(decoded ==
req->bearer_contexts_to_be_created[i].bearer_level_qos.len);
bearer = sgwc_bearer_add(sess);
ogs_assert(bearer);
/* Set Bearer EBI */
bearer->ebi = req->bearer_contexts_to_be_created[i].eps_bearer_id.u8;
if (req->bearer_contexts_to_be_created[i].s1_u_enodeb_f_teid.presence) {
sgwc_tunnel_t *dl_tunnel = NULL;
ogs_pfcp_far_t *far = NULL;
ogs_gtp2_f_teid_t *enb_s1u_teid = NULL;
dl_tunnel = sgwc_dl_tunnel_in_bearer(bearer);
ogs_assert(dl_tunnel);
/* Data Plane(DL) : eNB-S1U */
enb_s1u_teid = req->bearer_contexts_to_be_created[i].
s1_u_enodeb_f_teid.data;
dl_tunnel->remote_teid = be32toh(enb_s1u_teid->teid);
ogs_assert(OGS_OK ==
ogs_gtp2_f_teid_to_ip(enb_s1u_teid, &dl_tunnel->remote_ip));
far = dl_tunnel->far;
ogs_assert(far);
far->apply_action = OGS_PFCP_APPLY_ACTION_FORW;
ogs_assert(OGS_OK == ogs_pfcp_ip_to_outer_header_creation(
&dl_tunnel->remote_ip, &far->outer_header_creation,
&far->outer_header_creation_len));
far->outer_header_creation.teid = dl_tunnel->remote_teid;
}
if (req->bearer_contexts_to_be_created[i].s5_s8_u_sgw_f_teid.presence) {
sgwc_tunnel_t *ul_tunnel = NULL;
ogs_pfcp_far_t *far = NULL;
ogs_gtp2_f_teid_t *pgw_s5u_teid = NULL;
ul_tunnel = sgwc_ul_tunnel_in_bearer(bearer);
ogs_assert(ul_tunnel);
/* Data Plane(UL) : PGW-S5U */
pgw_s5u_teid = req->bearer_contexts_to_be_created[i].
s5_s8_u_sgw_f_teid.data;
ul_tunnel->remote_teid = be32toh(pgw_s5u_teid->teid);
ogs_assert(OGS_OK ==
ogs_gtp2_f_teid_to_ip(pgw_s5u_teid, &ul_tunnel->remote_ip));
far = ul_tunnel->far;
ogs_assert(far);
far->apply_action = OGS_PFCP_APPLY_ACTION_FORW;
ogs_assert(OGS_OK == ogs_pfcp_ip_to_outer_header_creation(
&ul_tunnel->remote_ip, &far->outer_header_creation,
&far->outer_header_creation_len));
far->outer_header_creation.teid = ul_tunnel->remote_teid;
}
/* Set Session QoS from Default Bearer Level QoS */
if (i == 0) {
sess->session.qos.index = bearer_qos.qci;
sess->session.qos.arp.priority_level = bearer_qos.priority_level;
sess->session.qos.arp.pre_emption_capability =
bearer_qos.pre_emption_capability;
sess->session.qos.arp.pre_emption_vulnerability =
bearer_qos.pre_emption_vulnerability;
}
}
/* Receive Control Plane(DL) : MME-S11 */ /* Receive Control Plane(DL) : MME-S11 */
mme_s11_teid = req->sender_f_teid_for_control_plane.data; mme_s11_teid = req->sender_f_teid_for_control_plane.data;
@ -334,7 +431,7 @@ void sgwc_s11_handle_modify_bearer_request(
*****************************************/ *****************************************/
ogs_assert(cause_value == OGS_GTP2_CAUSE_REQUEST_ACCEPTED); ogs_assert(cause_value == OGS_GTP2_CAUSE_REQUEST_ACCEPTED);
for (i = 0; i < 8 /* Max number of Bearer Contexts in Message */ ; i++) { for (i = 0; i < OGS_BEARER_PER_UE; i++) {
ogs_pfcp_xact_t *current_xact = NULL; ogs_pfcp_xact_t *current_xact = NULL;
if (req->bearer_contexts_to_be_modified[i].presence == 0) { if (req->bearer_contexts_to_be_modified[i].presence == 0) {
@ -372,10 +469,18 @@ void sgwc_s11_handle_modify_bearer_request(
} }
if (!current_xact) { if (!current_xact) {
current_xact = sgwc_pfcp_xact_create(sess, s11_xact, gtpbuf, current_xact = ogs_pfcp_xact_local_create(
OGS_PFCP_MODIFY_DL_ONLY|OGS_PFCP_MODIFY_ACTIVATE); sess->pfcp_node, pfcp_sess_timeout, sess);
ogs_assert(current_xact); ogs_assert(current_xact);
current_xact->assoc_xact = s11_xact;
current_xact->modify_flags = OGS_PFCP_MODIFY_SESSION|
OGS_PFCP_MODIFY_DL_ONLY|OGS_PFCP_MODIFY_ACTIVATE;
if (gtpbuf) {
current_xact->gtpbuf = ogs_pkbuf_copy(gtpbuf);
ogs_assert(current_xact->gtpbuf);
}
ogs_list_add(&pfcp_xact_list, &current_xact->tmpnode); ogs_list_add(&pfcp_xact_list, &current_xact->tmpnode);
} }
@ -453,7 +558,7 @@ void sgwc_s11_handle_modify_bearer_request(
dl_tunnel->remote_teid, dl_tunnel->local_teid); dl_tunnel->remote_teid, dl_tunnel->local_teid);
ogs_list_for_each_entry(&pfcp_xact_list, pfcp_xact, tmpnode) ogs_list_for_each_entry(&pfcp_xact_list, pfcp_xact, tmpnode)
sgwc_pfcp_xact_commit(pfcp_xact); sgwc_pfcp_send_bearer_to_modify_list(pfcp_xact->data, pfcp_xact);
} }
void sgwc_s11_handle_delete_session_request( void sgwc_s11_handle_delete_session_request(
@ -465,6 +570,7 @@ void sgwc_s11_handle_delete_session_request(
sgwc_sess_t *sess = NULL; sgwc_sess_t *sess = NULL;
ogs_gtp_xact_t *s5c_xact = NULL; ogs_gtp_xact_t *s5c_xact = NULL;
ogs_gtp2_delete_session_request_t *req = NULL; ogs_gtp2_delete_session_request_t *req = NULL;
ogs_gtp2_indication_t *indication = NULL;
ogs_assert(s11_xact); ogs_assert(s11_xact);
ogs_assert(gtpbuf); ogs_assert(gtpbuf);
@ -505,6 +611,27 @@ void sgwc_s11_handle_delete_session_request(
return; return;
} }
/*****************************************
* Check Mandatory/Conditional IE Missing
*****************************************/
ogs_assert(cause_value == OGS_GTP2_CAUSE_REQUEST_ACCEPTED);
if (req->indication_flags.presence &&
req->indication_flags.data && req->indication_flags.len) {
indication = req->indication_flags.data;
}
if (indication &&
indication->operation_indication == 1 &&
indication->scope_indication == 1) {
ogs_error("Invalid Indication");
ogs_gtp_send_error_message(
s11_xact, sgwc_ue ? sgwc_ue->mme_s11_teid : 0,
OGS_GTP2_DELETE_SESSION_RESPONSE_TYPE,
OGS_GTP2_CAUSE_INVALID_MESSAGE_FORMAT);
return;
}
/******************** /********************
* Check ALL Context * Check ALL Context
********************/ ********************/
@ -516,20 +643,29 @@ void sgwc_s11_handle_delete_session_request(
ogs_debug(" SGW_S5C_TEID[0x%x] PGW_S5C_TEID[0x%x]", ogs_debug(" SGW_S5C_TEID[0x%x] PGW_S5C_TEID[0x%x]",
sess->sgw_s5c_teid, sess->pgw_s5c_teid); sess->sgw_s5c_teid, sess->pgw_s5c_teid);
message->h.type = OGS_GTP2_DELETE_SESSION_REQUEST_TYPE; if (indication &&
message->h.teid = sess->pgw_s5c_teid; indication->operation_indication == 0 &&
indication->scope_indication == 1) {
gtpbuf = ogs_gtp2_build_msg(message); ogs_assert(OGS_OK ==
ogs_expect_or_return(gtpbuf); sgwc_pfcp_send_session_deletion_request(sess, s11_xact, gtpbuf));
s5c_xact = ogs_gtp_xact_local_create( } else {
sess->gnode, &message->h, gtpbuf, sess_timeout, sess); message->h.type = OGS_GTP2_DELETE_SESSION_REQUEST_TYPE;
ogs_expect_or_return(s5c_xact); message->h.teid = sess->pgw_s5c_teid;
ogs_gtp_xact_associate(s11_xact, s5c_xact); gtpbuf = ogs_gtp2_build_msg(message);
ogs_expect_or_return(gtpbuf);
rv = ogs_gtp_xact_commit(s5c_xact); s5c_xact = ogs_gtp_xact_local_create(
ogs_expect(rv == OGS_OK); sess->gnode, &message->h, gtpbuf, gtp_sess_timeout, sess);
ogs_expect_or_return(s5c_xact);
ogs_gtp_xact_associate(s11_xact, s5c_xact);
rv = ogs_gtp_xact_commit(s5c_xact);
ogs_expect(rv == OGS_OK);
}
} }
void sgwc_s11_handle_create_bearer_response( void sgwc_s11_handle_create_bearer_response(
@ -1032,7 +1168,7 @@ void sgwc_s11_handle_release_access_bearers_request(
ogs_list_for_each(&sgwc_ue->sess_list, sess) { ogs_list_for_each(&sgwc_ue->sess_list, sess) {
ogs_assert(OGS_OK == ogs_assert(OGS_OK ==
sgwc_pfcp_send_sess_modification_request( sgwc_pfcp_send_session_modification_request(
sess, s11_xact, gtpbuf, sess, s11_xact, gtpbuf,
OGS_PFCP_MODIFY_DL_ONLY|OGS_PFCP_MODIFY_DEACTIVATE)); OGS_PFCP_MODIFY_DL_ONLY|OGS_PFCP_MODIFY_DEACTIVATE));
} }
@ -1224,7 +1360,7 @@ void sgwc_s11_handle_create_indirect_data_forwarding_tunnel_request(
ogs_list_for_each(&sgwc_ue->sess_list, sess) { ogs_list_for_each(&sgwc_ue->sess_list, sess) {
ogs_assert(OGS_OK == ogs_assert(OGS_OK ==
sgwc_pfcp_send_sess_modification_request( sgwc_pfcp_send_session_modification_request(
sess, s11_xact, gtpbuf, sess, s11_xact, gtpbuf,
OGS_PFCP_MODIFY_INDIRECT|OGS_PFCP_MODIFY_CREATE)); OGS_PFCP_MODIFY_INDIRECT|OGS_PFCP_MODIFY_CREATE));
} }
@ -1270,7 +1406,7 @@ void sgwc_s11_handle_delete_indirect_data_forwarding_tunnel_request(
ogs_list_for_each(&sgwc_ue->sess_list, sess) { ogs_list_for_each(&sgwc_ue->sess_list, sess) {
ogs_assert(OGS_OK == ogs_assert(OGS_OK ==
sgwc_pfcp_send_sess_modification_request( sgwc_pfcp_send_session_modification_request(
sess, s11_xact, gtpbuf, sess, s11_xact, gtpbuf,
OGS_PFCP_MODIFY_INDIRECT| OGS_PFCP_MODIFY_REMOVE)); OGS_PFCP_MODIFY_INDIRECT| OGS_PFCP_MODIFY_REMOVE));
} }
@ -1375,7 +1511,7 @@ void sgwc_s11_handle_bearer_resource_command(
ogs_expect_or_return(pkbuf); ogs_expect_or_return(pkbuf);
s5c_xact = ogs_gtp_xact_local_create( s5c_xact = ogs_gtp_xact_local_create(
sess->gnode, &message->h, pkbuf, bearer_timeout, bearer); sess->gnode, &message->h, pkbuf, gtp_bearer_timeout, bearer);
ogs_expect_or_return(s5c_xact); ogs_expect_or_return(s5c_xact);
ogs_gtp_xact_associate(s11_xact, s5c_xact); ogs_gtp_xact_associate(s11_xact, s5c_xact);

View File

@ -63,7 +63,7 @@ void sgwc_s5c_handle_create_session_response(
sgwc_sess_t *sess, ogs_gtp_xact_t *s5c_xact, sgwc_sess_t *sess, ogs_gtp_xact_t *s5c_xact,
ogs_pkbuf_t *gtpbuf, ogs_gtp2_message_t *message) ogs_pkbuf_t *gtpbuf, ogs_gtp2_message_t *message)
{ {
int rv; int rv, i;
uint8_t cause_value; uint8_t cause_value;
ogs_gtp2_cause_t *cause = NULL; ogs_gtp2_cause_t *cause = NULL;
@ -106,25 +106,6 @@ void sgwc_s5c_handle_create_session_response(
} else { } else {
sgwc_ue = sess->sgwc_ue; sgwc_ue = sess->sgwc_ue;
ogs_assert(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;
}
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) {
ogs_error("No Context for EPS Bearer ID[%d]",
rsp->bearer_contexts_created.eps_bearer_id.u8);
cause_value = OGS_GTP2_CAUSE_CONTEXT_NOT_FOUND;
}
}
} }
if (cause_value != OGS_GTP2_CAUSE_REQUEST_ACCEPTED) { if (cause_value != OGS_GTP2_CAUSE_REQUEST_ACCEPTED) {
@ -143,10 +124,6 @@ void sgwc_s5c_handle_create_session_response(
ogs_error("No GTP TEID"); ogs_error("No GTP TEID");
cause_value = OGS_GTP2_CAUSE_CONDITIONAL_IE_MISSING; cause_value = OGS_GTP2_CAUSE_CONDITIONAL_IE_MISSING;
} }
if (rsp->bearer_contexts_created.s5_s8_u_sgw_f_teid.presence == 0) {
ogs_error("No GTP TEID");
cause_value = OGS_GTP2_CAUSE_CONDITIONAL_IE_MISSING;
}
if (rsp->pdn_address_allocation.presence) { if (rsp->pdn_address_allocation.presence) {
ogs_paa_t paa; ogs_paa_t paa;
@ -165,11 +142,7 @@ void sgwc_s5c_handle_create_session_response(
if (rsp->cause.presence == 0) { if (rsp->cause.presence == 0) {
ogs_error("No Cause"); ogs_error("No Cause");
cause_value = OGS_GTP2_CAUSE_MANDATORY_IE_MISSING; cause_value = OGS_GTP2_CAUSE_CONDITIONAL_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) { if (cause_value != OGS_GTP2_CAUSE_REQUEST_ACCEPTED) {
@ -184,15 +157,21 @@ void sgwc_s5c_handle_create_session_response(
********************/ ********************/
ogs_assert(cause_value == OGS_GTP2_CAUSE_REQUEST_ACCEPTED); ogs_assert(cause_value == OGS_GTP2_CAUSE_REQUEST_ACCEPTED);
cause = rsp->bearer_contexts_created.cause.data; for (i = 0; i < OGS_BEARER_PER_UE; i++) {
ogs_assert(cause); if (rsp->bearer_contexts_created[i].cause.presence == 0) {
cause_value = cause->value; break;
if (cause_value != OGS_GTP2_CAUSE_REQUEST_ACCEPTED) { }
ogs_error("GTP Failed [Bearer-CAUSE:%d]", cause_value);
ogs_gtp_send_error_message( cause = rsp->bearer_contexts_created[i].cause.data;
s11_xact, sgwc_ue ? sgwc_ue->mme_s11_teid : 0, ogs_assert(cause);
OGS_GTP2_CREATE_SESSION_RESPONSE_TYPE, cause_value); cause_value = cause->value;
return; if (cause_value != OGS_GTP2_CAUSE_REQUEST_ACCEPTED) {
ogs_error("GTP Failed [Bearer-CAUSE:%d]", cause_value);
ogs_gtp_send_error_message(
s11_xact, sgwc_ue ? sgwc_ue->mme_s11_teid : 0,
OGS_GTP2_CREATE_SESSION_RESPONSE_TYPE, cause_value);
return;
}
} }
cause = rsp->cause.data; cause = rsp->cause.data;
@ -216,49 +195,75 @@ void sgwc_s5c_handle_create_session_response(
********************/ ********************/
ogs_assert(sgwc_ue); ogs_assert(sgwc_ue);
ogs_assert(sess); ogs_assert(sess);
ogs_assert(bearer);
ul_tunnel = sgwc_ul_tunnel_in_bearer(bearer);
ogs_assert(ul_tunnel);
/* Receive Data Plane(UL) : PGW-S5U */ ogs_debug(" MME_S11_TEID[%d] SGW_S11_TEID[%d]",
pgw_s5u_teid = rsp->bearer_contexts_created.s5_s8_u_sgw_f_teid.data; sgwc_ue->mme_s11_teid, sgwc_ue->sgw_s11_teid);
ogs_assert(pgw_s5u_teid); ogs_debug(" SGW_S5C_TEID[0x%x] PGW_S5C_TEID[0x%x]",
ul_tunnel->remote_teid = be32toh(pgw_s5u_teid->teid); sess->sgw_s5c_teid, sess->pgw_s5c_teid);
rv = ogs_gtp2_f_teid_to_ip(pgw_s5u_teid, &ul_tunnel->remote_ip); for (i = 0; i < OGS_BEARER_PER_UE; i++) {
if (rv != OGS_OK) { if (rsp->bearer_contexts_created[i].presence == 0) {
ogs_gtp_send_error_message( break;
s11_xact, sgwc_ue ? sgwc_ue->mme_s11_teid : 0, }
OGS_GTP2_CREATE_SESSION_RESPONSE_TYPE, if (rsp->bearer_contexts_created[i].eps_bearer_id.presence == 0) {
OGS_GTP2_CAUSE_MANDATORY_IE_MISSING); ogs_error("No EPS Bearer ID");
return; break;
}
if (rsp->bearer_contexts_created[i].s5_s8_u_sgw_f_teid.presence == 0) {
ogs_error("No GTP TEID");
break;
}
/* EPS Bearer ID */
bearer = sgwc_bearer_find_by_sess_ebi(sess,
rsp->bearer_contexts_created[i].eps_bearer_id.u8);
if (!bearer) {
ogs_gtp_send_error_message(
s11_xact, sgwc_ue ? sgwc_ue->mme_s11_teid : 0,
OGS_GTP2_CREATE_SESSION_RESPONSE_TYPE,
OGS_GTP2_CAUSE_MANDATORY_IE_MISSING);
return;
}
ul_tunnel = sgwc_ul_tunnel_in_bearer(bearer);
ogs_assert(ul_tunnel);
ogs_debug(" SGW_S5U_TEID[%d] PGW_S5U_TEID[%d]",
ul_tunnel->local_teid, ul_tunnel->remote_teid);
/* Receive Data Plane(UL) : PGW-S5U */
pgw_s5u_teid = rsp->bearer_contexts_created[i].s5_s8_u_sgw_f_teid.data;
ogs_assert(pgw_s5u_teid);
ul_tunnel->remote_teid = be32toh(pgw_s5u_teid->teid);
rv = ogs_gtp2_f_teid_to_ip(pgw_s5u_teid, &ul_tunnel->remote_ip);
if (rv != OGS_OK) {
ogs_gtp_send_error_message(
s11_xact, sgwc_ue ? sgwc_ue->mme_s11_teid : 0,
OGS_GTP2_CREATE_SESSION_RESPONSE_TYPE,
OGS_GTP2_CAUSE_MANDATORY_IE_MISSING);
return;
}
far = ul_tunnel->far;
ogs_assert(far);
far->apply_action = OGS_PFCP_APPLY_ACTION_FORW;
ogs_assert(OGS_OK ==
ogs_pfcp_ip_to_outer_header_creation(&ul_tunnel->remote_ip,
&far->outer_header_creation, &far->outer_header_creation_len));
far->outer_header_creation.teid = ul_tunnel->remote_teid;
} }
far = ul_tunnel->far;
ogs_assert(far);
far->apply_action = OGS_PFCP_APPLY_ACTION_FORW;
ogs_assert(OGS_OK ==
ogs_pfcp_ip_to_outer_header_creation(&ul_tunnel->remote_ip,
&far->outer_header_creation, &far->outer_header_creation_len));
far->outer_header_creation.teid = ul_tunnel->remote_teid;
/* Receive Control Plane(UL) : PGW-S5C */ /* Receive Control Plane(UL) : PGW-S5C */
pgw_s5c_teid = rsp->pgw_s5_s8__s2a_s2b_f_teid_for_pmip_based_interface_or_for_gtp_based_control_plane_interface.data; pgw_s5c_teid = rsp->pgw_s5_s8__s2a_s2b_f_teid_for_pmip_based_interface_or_for_gtp_based_control_plane_interface.data;
ogs_assert(pgw_s5c_teid); ogs_assert(pgw_s5c_teid);
sess->pgw_s5c_teid = be32toh(pgw_s5c_teid->teid); sess->pgw_s5c_teid = be32toh(pgw_s5c_teid->teid);
ogs_debug(" MME_S11_TEID[%d] SGW_S11_TEID[%d]",
sgwc_ue->mme_s11_teid, sgwc_ue->sgw_s11_teid);
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]",
ul_tunnel->local_teid, ul_tunnel->remote_teid);
ogs_assert(OGS_OK == ogs_assert(OGS_OK ==
sgwc_pfcp_send_bearer_modification_request( sgwc_pfcp_send_session_modification_request(
bearer, s11_xact, gtpbuf, sess, s11_xact, gtpbuf,
OGS_PFCP_MODIFY_UL_ONLY|OGS_PFCP_MODIFY_ACTIVATE)); OGS_PFCP_MODIFY_UL_ONLY|OGS_PFCP_MODIFY_ACTIVATE));
} }
@ -371,6 +376,7 @@ void sgwc_s5c_handle_modify_bearer_response(
int rv; int rv;
ogs_gtp2_cause_t *cause = NULL; ogs_gtp2_cause_t *cause = NULL;
uint8_t cause_value; uint8_t cause_value;
int modify_action;
sgwc_ue_t *sgwc_ue = NULL; sgwc_ue_t *sgwc_ue = NULL;
ogs_pkbuf_t *pkbuf = NULL; ogs_pkbuf_t *pkbuf = NULL;
@ -390,6 +396,7 @@ void sgwc_s5c_handle_modify_bearer_response(
ogs_assert(s5c_xact); ogs_assert(s5c_xact);
s11_xact = s5c_xact->assoc_xact; s11_xact = s5c_xact->assoc_xact;
ogs_assert(s11_xact); ogs_assert(s11_xact);
modify_action = s5c_xact->modify_action;
rv = ogs_gtp_xact_commit(s5c_xact); rv = ogs_gtp_xact_commit(s5c_xact);
ogs_expect(rv == OGS_OK); ogs_expect(rv == OGS_OK);
@ -408,9 +415,14 @@ void sgwc_s5c_handle_modify_bearer_response(
} }
if (cause_value != OGS_GTP2_CAUSE_REQUEST_ACCEPTED) { if (cause_value != OGS_GTP2_CAUSE_REQUEST_ACCEPTED) {
ogs_gtp_send_error_message( if (modify_action == OGS_GTP_MODIFY_IN_PATH_SWITCH_REQUEST)
s11_xact, sgwc_ue ? sgwc_ue->mme_s11_teid : 0, ogs_gtp_send_error_message(
OGS_GTP2_MODIFY_BEARER_RESPONSE_TYPE, cause_value); s11_xact, sgwc_ue ? sgwc_ue->mme_s11_teid : 0,
OGS_GTP2_CREATE_SESSION_RESPONSE_TYPE, cause_value);
else
ogs_gtp_send_error_message(
s11_xact, sgwc_ue ? sgwc_ue->mme_s11_teid : 0,
OGS_GTP2_MODIFY_BEARER_RESPONSE_TYPE, cause_value);
return; return;
} }
@ -425,9 +437,14 @@ void sgwc_s5c_handle_modify_bearer_response(
} }
if (cause_value != OGS_GTP2_CAUSE_REQUEST_ACCEPTED) { if (cause_value != OGS_GTP2_CAUSE_REQUEST_ACCEPTED) {
ogs_gtp_send_error_message( if (modify_action == OGS_GTP_MODIFY_IN_PATH_SWITCH_REQUEST)
s11_xact, sgwc_ue ? sgwc_ue->mme_s11_teid : 0, ogs_gtp_send_error_message(
OGS_GTP2_MODIFY_BEARER_RESPONSE_TYPE, cause_value); s11_xact, sgwc_ue ? sgwc_ue->mme_s11_teid : 0,
OGS_GTP2_CREATE_SESSION_RESPONSE_TYPE, cause_value);
else
ogs_gtp_send_error_message(
s11_xact, sgwc_ue ? sgwc_ue->mme_s11_teid : 0,
OGS_GTP2_MODIFY_BEARER_RESPONSE_TYPE, cause_value);
return; return;
} }
@ -441,9 +458,14 @@ void sgwc_s5c_handle_modify_bearer_response(
cause_value = cause->value; cause_value = cause->value;
if (cause_value != OGS_GTP2_CAUSE_REQUEST_ACCEPTED) { if (cause_value != OGS_GTP2_CAUSE_REQUEST_ACCEPTED) {
ogs_error("GTP Failed [CAUSE:%d]", cause_value); ogs_error("GTP Failed [CAUSE:%d]", cause_value);
ogs_gtp_send_error_message( if (modify_action == OGS_GTP_MODIFY_IN_PATH_SWITCH_REQUEST)
s11_xact, sgwc_ue ? sgwc_ue->mme_s11_teid : 0, ogs_gtp_send_error_message(
OGS_GTP2_MODIFY_BEARER_RESPONSE_TYPE, cause_value); s11_xact, sgwc_ue ? sgwc_ue->mme_s11_teid : 0,
OGS_GTP2_CREATE_SESSION_RESPONSE_TYPE, cause_value);
else
ogs_gtp_send_error_message(
s11_xact, sgwc_ue ? sgwc_ue->mme_s11_teid : 0,
OGS_GTP2_MODIFY_BEARER_RESPONSE_TYPE, cause_value);
return; return;
} }
@ -458,17 +480,22 @@ void sgwc_s5c_handle_modify_bearer_response(
ogs_debug(" SGW_S5C_TEID[0x%x] PGW_S5C_TEID[0x%x]", ogs_debug(" SGW_S5C_TEID[0x%x] PGW_S5C_TEID[0x%x]",
sess->sgw_s5c_teid, sess->pgw_s5c_teid); sess->sgw_s5c_teid, sess->pgw_s5c_teid);
message->h.type = OGS_GTP2_MODIFY_BEARER_RESPONSE_TYPE; if (modify_action == OGS_GTP_MODIFY_IN_PATH_SWITCH_REQUEST) {
message->h.teid = sgwc_ue->mme_s11_teid; ogs_assert(OGS_OK ==
sgwc_gtp_send_create_session_response(sess, s11_xact));
} else {
message->h.type = OGS_GTP2_MODIFY_BEARER_RESPONSE_TYPE;
message->h.teid = sgwc_ue->mme_s11_teid;
pkbuf = ogs_gtp2_build_msg(message); pkbuf = ogs_gtp2_build_msg(message);
ogs_expect_or_return(pkbuf); ogs_expect_or_return(pkbuf);
rv = ogs_gtp_xact_update_tx(s11_xact, &message->h, pkbuf); rv = ogs_gtp_xact_update_tx(s11_xact, &message->h, pkbuf);
ogs_expect_or_return(rv == OGS_OK); ogs_expect_or_return(rv == OGS_OK);
rv = ogs_gtp_xact_commit(s11_xact); rv = ogs_gtp_xact_commit(s11_xact);
ogs_expect(rv == OGS_OK); ogs_expect(rv == OGS_OK);
}
} }
void sgwc_s5c_handle_create_bearer_request( void sgwc_s5c_handle_create_bearer_request(

View File

@ -145,18 +145,8 @@ void sgwc_state_operational(ogs_fsm_t *s, sgwc_event_t *e)
break; break;
} }
if (gtp_message.h.teid_presence && gtp_message.h.teid != 0) { gnode = e->gnode;
/* Cause is not "Context not found" */ ogs_assert(gnode);
sgwc_ue = sgwc_ue_find_by_teid(gtp_message.h.teid);
}
if (sgwc_ue) {
gnode = sgwc_ue->gnode;
ogs_assert(gnode);
} else {
gnode = e->gnode;
ogs_assert(gnode);
}
rv = ogs_gtp_xact_receive(gnode, &gtp_message.h, &gtp_xact); rv = ogs_gtp_xact_receive(gnode, &gtp_message.h, &gtp_xact);
if (rv != OGS_OK) { if (rv != OGS_OK) {
@ -164,6 +154,11 @@ void sgwc_state_operational(ogs_fsm_t *s, sgwc_event_t *e)
break; break;
} }
if (gtp_message.h.teid_presence && gtp_message.h.teid != 0) {
/* Cause is not "Context not found" */
sgwc_ue = sgwc_ue_find_by_teid(gtp_message.h.teid);
}
switch(gtp_message.h.type) { switch(gtp_message.h.type) {
case OGS_GTP2_ECHO_REQUEST_TYPE: case OGS_GTP2_ECHO_REQUEST_TYPE:
sgwc_handle_echo_request(gtp_xact, &gtp_message.echo_request); sgwc_handle_echo_request(gtp_xact, &gtp_message.echo_request);
@ -239,17 +234,8 @@ void sgwc_state_operational(ogs_fsm_t *s, sgwc_event_t *e)
break; break;
} }
if (gtp_message.h.teid_presence && gtp_message.h.teid != 0) { gnode = e->gnode;
sess = sgwc_sess_find_by_teid(gtp_message.h.teid); ogs_assert(gnode);
}
if (sess) {
gnode = sess->gnode;
ogs_assert(gnode);
} else {
gnode = e->gnode;
ogs_assert(gnode);
}
rv = ogs_gtp_xact_receive(gnode, &gtp_message.h, &gtp_xact); rv = ogs_gtp_xact_receive(gnode, &gtp_message.h, &gtp_xact);
if (rv != OGS_OK) { if (rv != OGS_OK) {
@ -257,6 +243,10 @@ void sgwc_state_operational(ogs_fsm_t *s, sgwc_event_t *e)
break; break;
} }
if (gtp_message.h.teid_presence && gtp_message.h.teid != 0) {
sess = sgwc_sess_find_by_teid(gtp_message.h.teid);
}
switch(gtp_message.h.type) { switch(gtp_message.h.type) {
case OGS_GTP2_ECHO_REQUEST_TYPE: case OGS_GTP2_ECHO_REQUEST_TYPE:
sgwc_handle_echo_request(gtp_xact, &gtp_message.echo_request); sgwc_handle_echo_request(gtp_xact, &gtp_message.echo_request);

View File

@ -105,7 +105,7 @@ ogs_pkbuf_t *sgwc_sxa_build_session_establishment_request(
return pkbuf; return pkbuf;
} }
ogs_pkbuf_t *sgwc_sxa_build_session_modification_request( ogs_pkbuf_t *sgwc_sxa_build_bearer_to_modify_list(
uint8_t type, sgwc_sess_t *sess, ogs_pfcp_xact_t *xact) uint8_t type, sgwc_sess_t *sess, ogs_pfcp_xact_t *xact)
{ {
ogs_pfcp_message_t pfcp_message; ogs_pfcp_message_t pfcp_message;
@ -135,12 +135,6 @@ ogs_pkbuf_t *sgwc_sxa_build_session_modification_request(
req = &pfcp_message.pfcp_session_modification_request; req = &pfcp_message.pfcp_session_modification_request;
memset(&pfcp_message, 0, sizeof(ogs_pfcp_message_t)); 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) { if (modify_flags & OGS_PFCP_MODIFY_CREATE) {
ogs_pfcp_pdrbuf_init(); ogs_pfcp_pdrbuf_init();
} }
@ -166,6 +160,7 @@ ogs_pkbuf_t *sgwc_sxa_build_session_modification_request(
OGS_GTP2_F_TEID_SGW_GTP_U_FOR_UL_DATA_FORWARDING))))) { OGS_GTP2_F_TEID_SGW_GTP_U_FOR_UL_DATA_FORWARDING))))) {
if (modify_flags & OGS_PFCP_MODIFY_REMOVE) { if (modify_flags & OGS_PFCP_MODIFY_REMOVE) {
pdr = tunnel->pdr; pdr = tunnel->pdr;
if (pdr) { if (pdr) {
ogs_pfcp_tlv_remove_pdr_t *message = ogs_pfcp_tlv_remove_pdr_t *message =
@ -193,6 +188,7 @@ ogs_pkbuf_t *sgwc_sxa_build_session_modification_request(
ogs_assert_if_reached(); ogs_assert_if_reached();
} else if (modify_flags & OGS_PFCP_MODIFY_CREATE) { } else if (modify_flags & OGS_PFCP_MODIFY_CREATE) {
pdr = tunnel->pdr; pdr = tunnel->pdr;
if (pdr) { if (pdr) {
ogs_pfcp_build_create_pdr( ogs_pfcp_build_create_pdr(
@ -214,7 +210,10 @@ ogs_pkbuf_t *sgwc_sxa_build_session_modification_request(
num_of_create_far++; num_of_create_far++;
} else } else
ogs_assert_if_reached(); ogs_assert_if_reached();
} else if (modify_flags & OGS_PFCP_MODIFY_DEACTIVATE) { }
if (modify_flags & OGS_PFCP_MODIFY_DEACTIVATE) {
far = tunnel->far; far = tunnel->far;
if (far) { if (far) {
ogs_pfcp_build_update_far_deactivate( ogs_pfcp_build_update_far_deactivate(
@ -224,7 +223,9 @@ ogs_pkbuf_t *sgwc_sxa_build_session_modification_request(
num_of_update_far++; num_of_update_far++;
} else } else
ogs_assert_if_reached(); ogs_assert_if_reached();
} else if (modify_flags & OGS_PFCP_MODIFY_ACTIVATE) { } else if (modify_flags & OGS_PFCP_MODIFY_ACTIVATE) {
far = tunnel->far; far = tunnel->far;
if (far) { if (far) {
if (modify_flags & OGS_PFCP_MODIFY_END_MARKER) { if (modify_flags & OGS_PFCP_MODIFY_END_MARKER) {
@ -241,6 +242,7 @@ ogs_pkbuf_t *sgwc_sxa_build_session_modification_request(
tunnel->far->smreq_flags.value = 0; tunnel->far->smreq_flags.value = 0;
} else } else
ogs_assert_if_reached(); ogs_assert_if_reached();
} }
} }
} }

View File

@ -28,7 +28,7 @@ extern "C" {
ogs_pkbuf_t *sgwc_sxa_build_session_establishment_request( ogs_pkbuf_t *sgwc_sxa_build_session_establishment_request(
uint8_t type, sgwc_sess_t *sess); uint8_t type, sgwc_sess_t *sess);
ogs_pkbuf_t *sgwc_sxa_build_session_modification_request( ogs_pkbuf_t *sgwc_sxa_build_bearer_to_modify_list(
uint8_t type, sgwc_sess_t *sess, ogs_pfcp_xact_t *xact); uint8_t type, sgwc_sess_t *sess, ogs_pfcp_xact_t *xact);
ogs_pkbuf_t *sgwc_sxa_build_session_deletion_request( ogs_pkbuf_t *sgwc_sxa_build_session_deletion_request(
uint8_t type, sgwc_sess_t *sess); uint8_t type, sgwc_sess_t *sess);

View File

@ -134,10 +134,15 @@ void sgwc_sxa_handle_session_establishment_response(
ogs_pfcp_f_seid_t *up_f_seid = NULL; ogs_pfcp_f_seid_t *up_f_seid = NULL;
int sgw_s5c_len, sgw_s5u_len; int sgw_s5c_len;
ogs_gtp2_f_teid_t sgw_s5c_teid, sgw_s5u_teid; ogs_gtp2_f_teid_t sgw_s5c_teid;
ogs_gtp2_f_teid_t *pgw_s5c_teid = NULL; ogs_gtp2_f_teid_t *pgw_s5c_teid = NULL;
int i, num_of_sgw_s5u;
uint8_t ebi[OGS_BEARER_PER_UE];
int sgw_s5u_len[OGS_BEARER_PER_UE];
ogs_gtp2_f_teid_t sgw_s5u_teid[OGS_BEARER_PER_UE];
ogs_gtp_xact_t *s11_xact = NULL, *s5c_xact = NULL; ogs_gtp_xact_t *s11_xact = NULL, *s5c_xact = NULL;
ogs_gtp_node_t *pgw = NULL; ogs_gtp_node_t *pgw = NULL;
@ -248,24 +253,44 @@ void sgwc_sxa_handle_session_establishment_response(
ogs_assert(sess); ogs_assert(sess);
bearer = sgwc_default_bearer_in_sess(sess); ogs_debug(" SGW_S5C_TEID[0x%x] PGW_S5C_TEID[0x%x]",
ogs_assert(bearer); sess->sgw_s5c_teid, sess->pgw_s5c_teid);
dl_tunnel = sgwc_dl_tunnel_in_bearer(bearer);
ogs_assert(dl_tunnel);
if (dl_tunnel->local_addr == NULL && dl_tunnel->local_addr6 == NULL) { /* Data Plane(DL) : SGW-S5U */
ogs_error("No UP F-TEID"); i = 0;
ogs_gtp_send_error_message( ogs_list_for_each(&sess->bearer_list, bearer) {
s11_xact, sgwc_ue ? sgwc_ue->mme_s11_teid : 0, ogs_assert(i < OGS_BEARER_PER_UE);
OGS_GTP2_CREATE_SESSION_RESPONSE_TYPE,
OGS_GTP2_CAUSE_GRE_KEY_NOT_FOUND); dl_tunnel = sgwc_dl_tunnel_in_bearer(bearer);
return; ogs_assert(dl_tunnel);
ogs_debug(" SGW_S5U_TEID[%d] PGW_S5U_TEID[%d]",
dl_tunnel->local_teid, dl_tunnel->remote_teid);
if (dl_tunnel->local_addr == NULL && dl_tunnel->local_addr6 == NULL) {
ogs_error("No UP F-TEID");
ogs_gtp_send_error_message(
s11_xact, sgwc_ue ? sgwc_ue->mme_s11_teid : 0,
OGS_GTP2_CREATE_SESSION_RESPONSE_TYPE,
OGS_GTP2_CAUSE_GRE_KEY_NOT_FOUND);
return;
}
ebi[i] = bearer->ebi;
memset(&sgw_s5u_teid[i], 0, sizeof(ogs_gtp2_f_teid_t));
sgw_s5u_teid[i].teid = htobe32(dl_tunnel->local_teid);
sgw_s5u_teid[i].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[i], &sgw_s5u_len[i]);
ogs_assert(rv == OGS_OK);
i++;
} }
/* UP F-SEID */ num_of_sgw_s5u = i;
up_f_seid = pfcp_rsp->up_f_seid.data;
ogs_assert(up_f_seid);
sess->sgwu_sxa_seid = be64toh(up_f_seid->seid);
/* Send Control Plane(DL) : SGW-S5C */ /* Send Control Plane(DL) : SGW-S5C */
memset(&sgw_s5c_teid, 0, sizeof(ogs_gtp2_f_teid_t)); memset(&sgw_s5c_teid, 0, sizeof(ogs_gtp2_f_teid_t));
@ -276,10 +301,10 @@ void sgwc_sxa_handle_session_establishment_response(
&sgw_s5c_teid, &sgw_s5c_len); &sgw_s5c_teid, &sgw_s5c_len);
ogs_assert(rv == OGS_OK); ogs_assert(rv == OGS_OK);
ogs_debug(" SGW_S5C_TEID[0x%x] PGW_S5C_TEID[0x%x]", /* UP F-SEID */
sess->sgw_s5c_teid, sess->pgw_s5c_teid); up_f_seid = pfcp_rsp->up_f_seid.data;
ogs_debug(" SGW_S5U_TEID[%d] PGW_S5U_TEID[%d]", ogs_assert(up_f_seid);
dl_tunnel->local_teid, dl_tunnel->remote_teid); sess->sgwu_sxa_seid = be64toh(up_f_seid->seid);
pgw_s5c_teid = create_session_request-> pgw_s5c_teid = create_session_request->
pgw_s5_s8_address_for_control_plane_or_pmip.data; pgw_s5_s8_address_for_control_plane_or_pmip.data;
@ -299,16 +324,6 @@ void sgwc_sxa_handle_session_establishment_response(
/* Setup GTP Node */ /* Setup GTP Node */
OGS_SETUP_GTP_NODE(sess, pgw); OGS_SETUP_GTP_NODE(sess, pgw);
/* 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, &sgw_s5u_len);
ogs_assert(rv == OGS_OK);
/* Check Indication */ /* Check Indication */
if (create_session_request->indication_flags.presence && if (create_session_request->indication_flags.presence &&
create_session_request->indication_flags.data && create_session_request->indication_flags.data &&
@ -340,20 +355,24 @@ void sgwc_sxa_handle_session_establishment_response(
modify_bearer_request->sender_f_teid_for_control_plane. modify_bearer_request->sender_f_teid_for_control_plane.
len = sgw_s5c_len; len = sgw_s5c_len;
/* Bearer Context : EBI */ for (i = 0; i < num_of_sgw_s5u; i++) {
modify_bearer_request->bearer_contexts_to_be_modified[0].presence = 1; modify_bearer_request->bearer_contexts_to_be_modified[i].
modify_bearer_request->bearer_contexts_to_be_modified[0]. presence = 1;
eps_bearer_id.presence = 1; modify_bearer_request->bearer_contexts_to_be_modified[i].
modify_bearer_request->bearer_contexts_to_be_modified[0]. eps_bearer_id.presence = 1;
eps_bearer_id.u8 = bearer->ebi;
/* Data Plane(DL) : SGW-S5U */ /* Bearer Context : EBI */
modify_bearer_request->bearer_contexts_to_be_modified[0]. modify_bearer_request->bearer_contexts_to_be_modified[i].
s4_u_sgsn_f_teid.presence = 1; eps_bearer_id.u8 = ebi[i];
modify_bearer_request->bearer_contexts_to_be_modified[0].
s4_u_sgsn_f_teid.data = &sgw_s5u_teid; /* Data Plane(DL) : SGW-S5U */
modify_bearer_request->bearer_contexts_to_be_modified[0]. modify_bearer_request->bearer_contexts_to_be_modified[i].
s4_u_sgsn_f_teid.len = sgw_s5u_len; s4_u_sgsn_f_teid.presence = 1;
modify_bearer_request->bearer_contexts_to_be_modified[i].
s4_u_sgsn_f_teid.data = &sgw_s5u_teid[i];
modify_bearer_request->bearer_contexts_to_be_modified[i].
s4_u_sgsn_f_teid.len = sgw_s5u_len[i];
}
pkbuf = ogs_gtp2_build_msg(&send_message); pkbuf = ogs_gtp2_build_msg(&send_message);
ogs_expect_or_return(pkbuf); ogs_expect_or_return(pkbuf);
@ -362,7 +381,11 @@ void sgwc_sxa_handle_session_establishment_response(
s5c_xact = ogs_gtp_xact_local_create( s5c_xact = ogs_gtp_xact_local_create(
sess->gnode, &send_message.h, pkbuf, sess_timeout, sess); sess->gnode, &send_message.h, pkbuf, sess_timeout, sess);
ogs_expect_or_return(s5c_xact); ogs_expect_or_return(s5c_xact);
s5c_xact->modify_action = OGS_GTP_MODIFY_IN_PATH_SWITCH_REQUEST;
} else { } else {
/* Create Session Request */ /* Create Session Request */
recv_message->h.type = OGS_GTP2_CREATE_SESSION_REQUEST_TYPE; recv_message->h.type = OGS_GTP2_CREATE_SESSION_REQUEST_TYPE;
recv_message->h.teid = sess->pgw_s5c_teid; recv_message->h.teid = sess->pgw_s5c_teid;
@ -379,12 +402,14 @@ void sgwc_sxa_handle_session_establishment_response(
presence = 0; presence = 0;
/* Bearer Contexts */ /* Bearer Contexts */
create_session_request->bearer_contexts_to_be_created. for (i = 0; i < num_of_sgw_s5u; i++) {
s5_s8_u_sgw_f_teid.presence = 1; create_session_request->bearer_contexts_to_be_created[i].
create_session_request->bearer_contexts_to_be_created. s5_s8_u_sgw_f_teid.presence = 1;
s5_s8_u_sgw_f_teid.data = &sgw_s5u_teid; create_session_request->bearer_contexts_to_be_created[i].
create_session_request->bearer_contexts_to_be_created. s5_s8_u_sgw_f_teid.data = &sgw_s5u_teid[i];
s5_s8_u_sgw_f_teid.len = sgw_s5u_len; create_session_request->bearer_contexts_to_be_created[i].
s5_s8_u_sgw_f_teid.len = sgw_s5u_len[i];
}
pkbuf = ogs_gtp2_build_msg(recv_message); pkbuf = ogs_gtp2_build_msg(recv_message);
ogs_expect_or_return(pkbuf); ogs_expect_or_return(pkbuf);
@ -617,7 +642,7 @@ void sgwc_sxa_handle_session_modification_response(
ogs_pfcp_xact_commit(pfcp_xact); ogs_pfcp_xact_commit(pfcp_xact);
ogs_assert(flags & OGS_PFCP_MODIFY_SESSION); ogs_assert(flags & OGS_PFCP_MODIFY_SESSION);
if (SESSION_SYNC_DONE(sgwc_ue, if (SGWC_SESSION_SYNC_DONE(sgwc_ue,
OGS_PFCP_SESSION_MODIFICATION_REQUEST_TYPE, flags)) { OGS_PFCP_SESSION_MODIFICATION_REQUEST_TYPE, flags)) {
sgwc_tunnel_t *tunnel = NULL, *next_tunnel = NULL; sgwc_tunnel_t *tunnel = NULL, *next_tunnel = NULL;
@ -702,9 +727,6 @@ void sgwc_sxa_handle_session_modification_response(
gtp_req = &recv_message->create_bearer_request; gtp_req = &recv_message->create_bearer_request;
ogs_assert(gtp_req); ogs_assert(gtp_req);
/* Remove S5U-F-TEID */
gtp_req->bearer_contexts.s4_u_sgsn_f_teid.presence = 0;
/* Send Data Plane(UL) : SGW-S1U */ /* Send Data Plane(UL) : SGW-S1U */
memset(&sgw_s1u_teid, 0, sizeof(ogs_gtp2_f_teid_t)); memset(&sgw_s1u_teid, 0, sizeof(ogs_gtp2_f_teid_t));
sgw_s1u_teid.interface_type = ul_tunnel->interface_type; sgw_s1u_teid.interface_type = ul_tunnel->interface_type;
@ -797,7 +819,7 @@ void sgwc_sxa_handle_session_modification_response(
ogs_pfcp_xact_commit(pfcp_xact); ogs_pfcp_xact_commit(pfcp_xact);
ogs_assert(flags & OGS_PFCP_MODIFY_SESSION); ogs_assert(flags & OGS_PFCP_MODIFY_SESSION);
if (SESSION_SYNC_DONE(sgwc_ue, if (SGWC_SESSION_SYNC_DONE(sgwc_ue,
OGS_PFCP_SESSION_MODIFICATION_REQUEST_TYPE, flags)) { OGS_PFCP_SESSION_MODIFICATION_REQUEST_TYPE, flags)) {
sgwc_tunnel_t *tunnel = NULL; sgwc_tunnel_t *tunnel = NULL;
@ -921,10 +943,12 @@ void sgwc_sxa_handle_session_modification_response(
ogs_pfcp_xact_commit(pfcp_xact); ogs_pfcp_xact_commit(pfcp_xact);
ogs_assert(flags & OGS_PFCP_MODIFY_SESSION);
if (flags & OGS_PFCP_MODIFY_UL_ONLY) { if (flags & OGS_PFCP_MODIFY_UL_ONLY) {
ogs_gtp2_create_session_response_t *gtp_rsp = NULL; ogs_gtp2_create_session_response_t *gtp_rsp = NULL;
ogs_gtp2_f_teid_t sgw_s11_teid; ogs_gtp2_f_teid_t sgw_s11_teid;
ogs_gtp2_f_teid_t sgw_s1u_teid; ogs_gtp2_f_teid_t sgw_s1u_teid[OGS_BEARER_PER_UE];
int sgw_s1u_len[OGS_BEARER_PER_UE];
ogs_assert(recv_message); ogs_assert(recv_message);
gtp_rsp = &recv_message->create_session_response; gtp_rsp = &recv_message->create_session_response;
@ -943,19 +967,30 @@ void sgwc_sxa_handle_session_modification_response(
gtp_rsp->sender_f_teid_for_control_plane.len = len; gtp_rsp->sender_f_teid_for_control_plane.len = len;
/* Send Data Plane(UL) : SGW-S1U */ /* Send Data Plane(UL) : SGW-S1U */
ogs_assert(ul_tunnel); i = 0;
memset(&sgw_s1u_teid, 0, sizeof(ogs_gtp2_f_teid_t)); ogs_list_for_each(&sess->bearer_list, bearer) {
sgw_s1u_teid.interface_type = ul_tunnel->interface_type; ogs_assert(i < OGS_BEARER_PER_UE);
sgw_s1u_teid.teid = htobe32(ul_tunnel->local_teid);
ogs_assert(ul_tunnel->local_addr || ul_tunnel->local_addr6); ul_tunnel = sgwc_ul_tunnel_in_bearer(bearer);
rv = ogs_gtp2_sockaddr_to_f_teid( ogs_assert(ul_tunnel);
ul_tunnel->local_addr, ul_tunnel->local_addr6,
&sgw_s1u_teid, &len); memset(&sgw_s1u_teid[i], 0, sizeof(ogs_gtp2_f_teid_t));
ogs_assert(rv == OGS_OK); sgw_s1u_teid[i].interface_type = ul_tunnel->interface_type;
gtp_rsp->bearer_contexts_created.s1_u_enodeb_f_teid.presence = 1; sgw_s1u_teid[i].teid = htobe32(ul_tunnel->local_teid);
gtp_rsp->bearer_contexts_created.s1_u_enodeb_f_teid.data = ogs_assert(ul_tunnel->local_addr || ul_tunnel->local_addr6);
&sgw_s1u_teid; rv = ogs_gtp2_sockaddr_to_f_teid(
gtp_rsp->bearer_contexts_created.s1_u_enodeb_f_teid.len = len; ul_tunnel->local_addr, ul_tunnel->local_addr6,
&sgw_s1u_teid[i], &sgw_s1u_len[i]);
ogs_assert(rv == OGS_OK);
gtp_rsp->bearer_contexts_created[i].s1_u_enodeb_f_teid.
presence = 1;
gtp_rsp->bearer_contexts_created[i].s1_u_enodeb_f_teid.
data = &sgw_s1u_teid[i];
gtp_rsp->bearer_contexts_created[i].s1_u_enodeb_f_teid.
len = sgw_s1u_len[i];
i++;
}
recv_message->h.type = OGS_GTP2_CREATE_SESSION_RESPONSE_TYPE; recv_message->h.type = OGS_GTP2_CREATE_SESSION_RESPONSE_TYPE;
recv_message->h.teid = sgwc_ue->mme_s11_teid; recv_message->h.teid = sgwc_ue->mme_s11_teid;
@ -970,10 +1005,7 @@ void sgwc_sxa_handle_session_modification_response(
ogs_expect(rv == OGS_OK); ogs_expect(rv == OGS_OK);
} else if (flags & OGS_PFCP_MODIFY_DL_ONLY) { } else if (flags & OGS_PFCP_MODIFY_DL_ONLY) {
#if 0 /* FIXME */ if (SGWC_SESSION_SYNC_DONE(sgwc_ue,
ogs_assert(flags & OGS_PFCP_MODIFY_SESSION);
#endif
if (SESSION_SYNC_DONE(sgwc_ue,
OGS_PFCP_SESSION_MODIFICATION_REQUEST_TYPE, flags)) { OGS_PFCP_SESSION_MODIFICATION_REQUEST_TYPE, flags)) {
ogs_gtp2_modify_bearer_request_t *gtp_req = NULL; ogs_gtp2_modify_bearer_request_t *gtp_req = NULL;
ogs_gtp2_modify_bearer_response_t *gtp_rsp = NULL; ogs_gtp2_modify_bearer_response_t *gtp_rsp = NULL;
@ -1023,7 +1055,7 @@ void sgwc_sxa_handle_session_modification_response(
/* Copy Bearer-Contexts-Modified from Modify-Bearer-Request /* Copy Bearer-Contexts-Modified from Modify-Bearer-Request
* *
* TS 29.274 Table 7.2.7-2 * TS 29.274 Table 7.2.8-2
* NOTE 1: The SGW shall not change its F-TEID for a given interface * NOTE 1: The SGW shall not change its F-TEID for a given interface
* during the Handover, Service Request, E-UTRAN Initial Attach, * during the Handover, Service Request, E-UTRAN Initial Attach,
* UE Requested PDN connectivity and PDP Context Activation procedures. * UE Requested PDN connectivity and PDP Context Activation procedures.
@ -1083,12 +1115,10 @@ void sgwc_sxa_handle_session_modification_response(
ogs_expect(rv == OGS_OK); ogs_expect(rv == OGS_OK);
} }
} }
} else { } else {
ogs_fatal("Invalid modify_flags[0x%llx]", (long long)flags); ogs_fatal("Invalid modify_flags[0x%llx]", (long long)flags);
ogs_assert_if_reached(); ogs_assert_if_reached();
} }
} else if (flags & OGS_PFCP_MODIFY_DEACTIVATE) { } else if (flags & OGS_PFCP_MODIFY_DEACTIVATE) {
if (flags & OGS_PFCP_MODIFY_ERROR_INDICATION) { if (flags & OGS_PFCP_MODIFY_ERROR_INDICATION) {
/* It's faked method for receiving `bearer` context */ /* It's faked method for receiving `bearer` context */
@ -1098,7 +1128,7 @@ void sgwc_sxa_handle_session_modification_response(
ogs_pfcp_xact_commit(pfcp_xact); ogs_pfcp_xact_commit(pfcp_xact);
ogs_assert(flags & OGS_PFCP_MODIFY_SESSION); ogs_assert(flags & OGS_PFCP_MODIFY_SESSION);
if (SESSION_SYNC_DONE(sgwc_ue, if (SGWC_SESSION_SYNC_DONE(sgwc_ue,
OGS_PFCP_SESSION_MODIFICATION_REQUEST_TYPE, flags)) { OGS_PFCP_SESSION_MODIFICATION_REQUEST_TYPE, flags)) {
ogs_assert(OGS_OK == ogs_assert(OGS_OK ==
sgwc_gtp_send_downlink_data_notification( sgwc_gtp_send_downlink_data_notification(
@ -1112,7 +1142,7 @@ void sgwc_sxa_handle_session_modification_response(
ogs_pfcp_xact_commit(pfcp_xact); ogs_pfcp_xact_commit(pfcp_xact);
ogs_assert(flags & OGS_PFCP_MODIFY_SESSION); ogs_assert(flags & OGS_PFCP_MODIFY_SESSION);
if (SESSION_SYNC_DONE(sgwc_ue, if (SGWC_SESSION_SYNC_DONE(sgwc_ue,
OGS_PFCP_SESSION_MODIFICATION_REQUEST_TYPE, flags)) { OGS_PFCP_SESSION_MODIFICATION_REQUEST_TYPE, flags)) {
ogs_gtp2_release_access_bearers_response_t *gtp_rsp = NULL; ogs_gtp2_release_access_bearers_response_t *gtp_rsp = NULL;
@ -1194,6 +1224,15 @@ void sgwc_sxa_handle_session_deletion_response(
goto cleanup; goto cleanup;
} }
if (gtp_message->h.type == OGS_GTP2_DELETE_SESSION_REQUEST_TYPE) {
/*
* X2-based Handover with SGW change
* 1. MME sends Delete Session Request to SGW-C
* 2. SGW-C sends Delete Session Response to MME.
*/
gtp_message->h.type = OGS_GTP2_DELETE_SESSION_RESPONSE_TYPE;
}
switch (gtp_message->h.type) { switch (gtp_message->h.type) {
case OGS_GTP2_DELETE_SESSION_RESPONSE_TYPE: case OGS_GTP2_DELETE_SESSION_RESPONSE_TYPE:
/* /*
@ -1350,7 +1389,7 @@ void sgwc_sxa_handle_session_report_request(
ogs_list_for_each(&sgwc_ue->sess_list, sess) { ogs_list_for_each(&sgwc_ue->sess_list, sess) {
ogs_assert(OGS_OK == ogs_assert(OGS_OK ==
sgwc_pfcp_send_sess_modification_request(sess, sgwc_pfcp_send_session_modification_request(sess,
/* We only use the `assoc_xact` parameter temporarily here /* We only use the `assoc_xact` parameter temporarily here
* to pass the `bearer` context. */ * to pass the `bearer` context. */
(ogs_gtp_xact_t *)bearer, (ogs_gtp_xact_t *)bearer,

View File

@ -133,7 +133,33 @@ static void _gtpv1_u_recv_cb(short when, ogs_socket_t fd, void *data)
ogs_assert(ogs_pkbuf_pull(pkbuf, len)); ogs_assert(ogs_pkbuf_pull(pkbuf, len));
if (gtp_h->type == OGS_GTPU_MSGTYPE_END_MARKER) { if (gtp_h->type == OGS_GTPU_MSGTYPE_END_MARKER) {
/* Nothing */ ogs_pfcp_object_t *pfcp_object = NULL;
ogs_pfcp_pdr_t *pdr = NULL;
ogs_pkbuf_t *sendbuf = NULL;
pfcp_object = ogs_pfcp_object_find_by_teid(teid);
if (!pfcp_object) {
/* TODO : Send Error Indication */
goto cleanup;
}
switch(pfcp_object->type) {
case OGS_PFCP_OBJ_PDR_TYPE:
pdr = (ogs_pfcp_pdr_t *)pfcp_object;
ogs_assert(pdr);
break;
default:
ogs_fatal("Unknown type [%d]", pfcp_object->type);
ogs_assert_if_reached();
}
ogs_assert(pdr);
sendbuf = ogs_pkbuf_copy(pkbuf);
ogs_assert(sendbuf);
/* Forward packet */
ogs_pfcp_send_g_pdu(pdr, gtp_h->type, sendbuf);
} else if (gtp_h->type == OGS_GTPU_MSGTYPE_ERR_IND) { } else if (gtp_h->type == OGS_GTPU_MSGTYPE_ERR_IND) {
ogs_pfcp_far_t *far = NULL; ogs_pfcp_far_t *far = NULL;
@ -209,7 +235,8 @@ static void _gtpv1_u_recv_cb(short when, ogs_socket_t fd, void *data)
} }
ogs_assert(pdr); ogs_assert(pdr);
ogs_assert(true == ogs_pfcp_up_handle_pdr(pdr, pkbuf, &report)); ogs_assert(true == ogs_pfcp_up_handle_pdr(
pdr, gtp_h->type, pkbuf, &report));
if (report.type.downlink_data_report) { if (report.type.downlink_data_report) {
ogs_assert(pdr->sess); ogs_assert(pdr->sess);

View File

@ -394,7 +394,7 @@ void smf_bearer_binding(smf_sess_t *sess)
} }
} }
int smf_gtp_send_create_bearer_request(smf_bearer_t *bearer) int smf_gtp2_send_create_bearer_request(smf_bearer_t *bearer)
{ {
int rv; int rv;

View File

@ -27,7 +27,7 @@ extern "C" {
#endif #endif
void smf_bearer_binding(smf_sess_t *sess); void smf_bearer_binding(smf_sess_t *sess);
int smf_gtp_send_create_bearer_request(smf_bearer_t *bearer); int smf_gtp2_send_create_bearer_request(smf_bearer_t *bearer);
void smf_qos_flow_binding(smf_sess_t *sess); void smf_qos_flow_binding(smf_sess_t *sess);

View File

@ -169,7 +169,7 @@ ED3(uint8_t spare:2;,
typedef struct smf_bearer_s { typedef struct smf_bearer_s {
ogs_lnode_t lnode; /**< A node of list_t */ ogs_lnode_t lnode; /**< A node of list_t */
ogs_lnode_t to_update_node; ogs_lnode_t to_modify_node;
ogs_lnode_t to_delete_node; ogs_lnode_t to_delete_node;
uint32_t index; uint32_t index;
@ -391,6 +391,9 @@ typedef struct smf_sess_s {
ogs_list_t bearer_list; ogs_list_t bearer_list;
ogs_list_t pdr_to_modify_list;
ogs_list_t qos_flow_to_modify_list;
ogs_gtp_node_t *gnode; ogs_gtp_node_t *gnode;
ogs_pfcp_node_t *pfcp_node; ogs_pfcp_node_t *pfcp_node;

View File

@ -364,7 +364,7 @@ void smf_gn_handle_update_pdp_context_request(
sess->sgw_s5c_teid, sess->smf_n4_teid); sess->sgw_s5c_teid, sess->smf_n4_teid);
} }
/* User Plane(DL) : SGW-S5C */ /* User Plane(DL) : SGW-S5U */
bearer->sgw_s5u_teid = req->tunnel_endpoint_identifier_data_i.u32; bearer->sgw_s5u_teid = req->tunnel_endpoint_identifier_data_i.u32;
rv = ogs_gtp1_gsn_addr_to_ip(req->sgsn_address_for_user_traffic.data, rv = ogs_gtp1_gsn_addr_to_ip(req->sgsn_address_for_user_traffic.data,
req->sgsn_address_for_user_traffic.len, req->sgsn_address_for_user_traffic.len,
@ -405,7 +405,7 @@ void smf_gn_handle_update_pdp_context_request(
} }
} }
rv = smf_epc_pfcp_send_session_modification_request(sess, xact, rv = smf_epc_pfcp_send_session_modification_request(sess, xact, NULL,
OGS_PFCP_MODIFY_DL_ONLY|OGS_PFCP_MODIFY_ACTIVATE, OGS_PFCP_MODIFY_DL_ONLY|OGS_PFCP_MODIFY_ACTIVATE,
OGS_NAS_PROCEDURE_TRANSACTION_IDENTITY_UNASSIGNED, OGS_NAS_PROCEDURE_TRANSACTION_IDENTITY_UNASSIGNED,
OGS_GTP1_CAUSE_REACTIACTION_REQUESTED); OGS_GTP1_CAUSE_REACTIACTION_REQUESTED);

View File

@ -307,7 +307,7 @@ int gsm_handle_pdu_session_modification_request(
pfcp_flags |= OGS_PFCP_MODIFY_TFT_REPLACE; pfcp_flags |= OGS_PFCP_MODIFY_TFT_REPLACE;
qos_flow_find_or_add( qos_flow_find_or_add(
&update_list, qos_flow, to_update_node); &update_list, qos_flow, to_modify_node);
ogs_list_add( ogs_list_add(
&qos_flow->pf_to_add_list, &pf->to_add_node); &qos_flow->pf_to_add_list, &pf->to_add_node);
@ -389,7 +389,7 @@ int gsm_handle_pdu_session_modification_request(
ogs_assert_if_reached(); ogs_assert_if_reached();
qos_flow_find_or_add( qos_flow_find_or_add(
&update_list, qos_flow, to_update_node); &update_list, qos_flow, to_modify_node);
ogs_list_add( ogs_list_add(
&qos_flow->pf_to_add_list, &pf->to_add_node); &qos_flow->pf_to_add_list, &pf->to_add_node);
@ -414,7 +414,7 @@ int gsm_handle_pdu_session_modification_request(
if (ogs_list_count(&qos_flow->pf_list)) { if (ogs_list_count(&qos_flow->pf_list)) {
pfcp_flags |= OGS_PFCP_MODIFY_TFT_DELETE; pfcp_flags |= OGS_PFCP_MODIFY_TFT_DELETE;
qos_flow_find_or_add( qos_flow_find_or_add(
&update_list, qos_flow, to_update_node); &update_list, qos_flow, to_modify_node);
} else { } else {
pfcp_flags |= OGS_PFCP_MODIFY_REMOVE; pfcp_flags |= OGS_PFCP_MODIFY_REMOVE;
qos_flow_find_or_add( qos_flow_find_or_add(
@ -469,7 +469,7 @@ int gsm_handle_pdu_session_modification_request(
} }
pfcp_flags |= OGS_PFCP_MODIFY_QOS_MODIFY; pfcp_flags |= OGS_PFCP_MODIFY_QOS_MODIFY;
qos_flow_find_or_add(&update_list, qos_flow, to_update_node); qos_flow_find_or_add(&update_list, qos_flow, to_modify_node);
} }
} }

View File

@ -303,10 +303,14 @@ void smf_gsm_state_initial_wait_pfcp_establishment(ogs_fsm_t *s, smf_event_t *e)
} }
switch (gtp_xact->gtp_version) { switch (gtp_xact->gtp_version) {
case 1: case 1:
ogs_assert(OGS_OK == smf_gtp1_send_create_pdp_context_response(sess, gtp_xact)); ogs_assert(OGS_OK ==
smf_gtp1_send_create_pdp_context_response(
sess, gtp_xact));
break; break;
case 2: case 2:
ogs_assert(OGS_OK == smf_gtp_send_create_session_response(sess, gtp_xact)); ogs_assert(OGS_OK ==
smf_gtp2_send_create_session_response(
sess, gtp_xact));
break; break;
} }
if (sess->gtp_rat_type == OGS_GTP2_RAT_TYPE_WLAN) { if (sess->gtp_rat_type == OGS_GTP2_RAT_TYPE_WLAN) {
@ -319,17 +323,9 @@ void smf_gsm_state_initial_wait_pfcp_establishment(ogs_fsm_t *s, smf_event_t *e)
* PGW-C shall indicate PGW-U to stop counting and stop * PGW-C shall indicate PGW-U to stop counting and stop
* forwarding downlink packets for the affected bearer(s). * forwarding downlink packets for the affected bearer(s).
*/ */
ogs_assert(sess->smf_ue); ogs_assert(OGS_OK ==
smf_sess_t *eutran_sess = smf_sess_find_by_apn( smf_epc_pfcp_send_deactivation(sess,
sess->smf_ue, sess->session.name, OGS_GTP2_RAT_TYPE_EUTRAN); OGS_GTP2_CAUSE_RAT_CHANGED_FROM_3GPP_TO_NON_3GPP));
if (eutran_sess) {
ogs_assert(OGS_OK ==
smf_epc_pfcp_send_session_modification_request(
eutran_sess, NULL,
OGS_PFCP_MODIFY_DL_ONLY|OGS_PFCP_MODIFY_DEACTIVATE,
OGS_NAS_PROCEDURE_TRANSACTION_IDENTITY_UNASSIGNED,
OGS_GTP2_CAUSE_RAT_CHANGED_FROM_3GPP_TO_NON_3GPP));
}
} }
smf_bearer_binding(sess); smf_bearer_binding(sess);
} else { } else {
@ -994,7 +990,7 @@ test_can_proceed:
ogs_assert(OGS_OK == smf_gtp1_send_delete_pdp_context_response(sess, e->gtp_xact)); ogs_assert(OGS_OK == smf_gtp1_send_delete_pdp_context_response(sess, e->gtp_xact));
break; break;
case 2: case 2:
ogs_assert(OGS_OK == smf_gtp_send_delete_session_response(sess, e->gtp_xact)); ogs_assert(OGS_OK == smf_gtp2_send_delete_session_response(sess, e->gtp_xact));
break; break;
} }
} else { } else {

View File

@ -427,7 +427,7 @@ int smf_gtp1_send_update_pdp_context_response(
return rv; return rv;
} }
int smf_gtp_send_create_session_response( int smf_gtp2_send_create_session_response(
smf_sess_t *sess, ogs_gtp_xact_t *xact) smf_sess_t *sess, ogs_gtp_xact_t *xact)
{ {
int rv; int rv;
@ -453,7 +453,36 @@ int smf_gtp_send_create_session_response(
return rv; return rv;
} }
int smf_gtp_send_delete_session_response( int smf_gtp2_send_modify_bearer_response(
smf_sess_t *sess, ogs_gtp_xact_t *xact,
ogs_gtp2_modify_bearer_request_t *req, bool sgw_relocation)
{
int rv;
ogs_gtp2_header_t h;
ogs_pkbuf_t *pkbuf = NULL;
ogs_assert(sess);
ogs_assert(xact);
ogs_assert(req);
memset(&h, 0, sizeof(ogs_gtp2_header_t));
h.type = OGS_GTP2_MODIFY_BEARER_RESPONSE_TYPE;
h.teid = sess->sgw_s5c_teid;
pkbuf = smf_s5c_build_modify_bearer_response(
h.type, sess, req, sgw_relocation);
ogs_expect_or_return_val(pkbuf, OGS_ERROR);
rv = ogs_gtp_xact_update_tx(xact, &h, pkbuf);
ogs_expect_or_return_val(rv == OGS_OK, OGS_ERROR);
rv = ogs_gtp_xact_commit(xact);
ogs_expect(rv == OGS_OK);
return rv;
}
int smf_gtp2_send_delete_session_response(
smf_sess_t *sess, ogs_gtp_xact_t *xact) smf_sess_t *sess, ogs_gtp_xact_t *xact)
{ {
int rv; int rv;
@ -479,7 +508,7 @@ int smf_gtp_send_delete_session_response(
return rv; return rv;
} }
int smf_gtp_send_delete_bearer_request( int smf_gtp2_send_delete_bearer_request(
smf_bearer_t *bearer, uint8_t pti, uint8_t cause_value) smf_bearer_t *bearer, uint8_t pti, uint8_t cause_value)
{ {
int rv; int rv;

View File

@ -38,12 +38,14 @@ int smf_gtp1_send_update_pdp_context_request(
int smf_gtp1_send_update_pdp_context_response( int smf_gtp1_send_update_pdp_context_response(
smf_bearer_t *bearer, ogs_gtp_xact_t *xact); smf_bearer_t *bearer, ogs_gtp_xact_t *xact);
int smf_gtp_send_create_session_response( int smf_gtp2_send_create_session_response(
smf_sess_t *sess, ogs_gtp_xact_t *xact); smf_sess_t *sess, ogs_gtp_xact_t *xact);
int smf_gtp_send_delete_session_response( int smf_gtp2_send_modify_bearer_response(
smf_sess_t *sess, ogs_gtp_xact_t *xact,
ogs_gtp2_modify_bearer_request_t *req, bool sgw_relocation);
int smf_gtp2_send_delete_session_response(
smf_sess_t *sess, ogs_gtp_xact_t *xact); smf_sess_t *sess, ogs_gtp_xact_t *xact);
int smf_gtp2_send_delete_bearer_request(
int smf_gtp_send_delete_bearer_request(
smf_bearer_t *bearer, uint8_t pti, uint8_t cause_value); smf_bearer_t *bearer, uint8_t pti, uint8_t cause_value);
#ifdef __cplusplus #ifdef __cplusplus

View File

@ -91,7 +91,7 @@ void smf_gx_send_ccr(smf_sess_t *sess, ogs_gtp_xact_t *xact,
char buf[OGS_PLMNIDSTRLEN]; char buf[OGS_PLMNIDSTRLEN];
struct sockaddr_in sin; struct sockaddr_in sin;
struct sockaddr_in6 sin6; struct sockaddr_in6 sin6;
uint32_t charing_id; uint32_t charging_id;
ogs_assert(sess); ogs_assert(sess);
@ -636,9 +636,9 @@ void smf_gx_send_ccr(smf_sess_t *sess, ogs_gtp_xact_t *xact,
ogs_diam_gx_access_network_charging_identifier_value, 0, ogs_diam_gx_access_network_charging_identifier_value, 0,
&avpch1); &avpch1);
ogs_assert(ret == 0); ogs_assert(ret == 0);
charing_id = htobe32(sess->charging.id); charging_id = htobe32(sess->charging.id);
val.os.data = (uint8_t *)&charing_id; val.os.data = (uint8_t *)&charging_id;
val.os.len = sizeof(charing_id); val.os.len = sizeof(charging_id);
ret = fd_msg_avp_setvalue (avpch1, &val); ret = fd_msg_avp_setvalue (avpch1, &val);
ogs_assert(ret == 0); ogs_assert(ret == 0);
ret = fd_msg_avp_add (avp, MSG_BRW_LAST_CHILD, avpch1); ret = fd_msg_avp_add (avp, MSG_BRW_LAST_CHILD, avpch1);

View File

@ -174,10 +174,10 @@ void smf_gy_handle_cca_update_request(
/* Send PFCP Session Modification Request if we need to update the params. */ /* Send PFCP Session Modification Request if we need to update the params. */
if (modify_flags) { if (modify_flags) {
modify_flags |= OGS_PFCP_MODIFY_URR|OGS_PFCP_MODIFY_UL_ONLY; modify_flags |= OGS_PFCP_MODIFY_URR|OGS_PFCP_MODIFY_UL_ONLY;
rv = smf_epc_pfcp_send_session_modification_request(sess, pfcp_xact, rv = smf_epc_pfcp_send_session_modification_request(
modify_flags, sess, pfcp_xact, NULL, modify_flags,
OGS_NAS_PROCEDURE_TRANSACTION_IDENTITY_UNASSIGNED, OGS_NAS_PROCEDURE_TRANSACTION_IDENTITY_UNASSIGNED,
OGS_GTP1_CAUSE_REACTIACTION_REQUESTED); OGS_GTP1_CAUSE_REACTIACTION_REQUESTED);
ogs_assert(rv == OGS_OK); ogs_assert(rv == OGS_OK);
} }
} }

View File

@ -110,7 +110,7 @@ ogs_pkbuf_t *smf_n4_build_session_establishment_request(
return pkbuf; return pkbuf;
} }
ogs_pkbuf_t *smf_n4_build_session_modification_request( ogs_pkbuf_t *smf_n4_build_pdr_to_modify_list(
uint8_t type, smf_sess_t *sess, ogs_pfcp_xact_t *xact) uint8_t type, smf_sess_t *sess, ogs_pfcp_xact_t *xact)
{ {
ogs_pfcp_pdr_t *pdr = NULL; ogs_pfcp_pdr_t *pdr = NULL;
@ -142,7 +142,7 @@ ogs_pkbuf_t *smf_n4_build_session_modification_request(
ogs_pfcp_pdrbuf_init(); ogs_pfcp_pdrbuf_init();
} }
ogs_list_for_each(&sess->pfcp.pdr_list, pdr) { ogs_list_for_each_entry(&sess->pdr_to_modify_list, pdr, to_modify_node) {
ogs_pfcp_far_t *far = pdr->far; ogs_pfcp_far_t *far = pdr->far;
ogs_assert(far); ogs_assert(far);
@ -238,22 +238,29 @@ ogs_pkbuf_t *smf_n4_build_session_modification_request(
return pkbuf; return pkbuf;
} }
ogs_pkbuf_t *smf_n4_build_qos_flow_modification_request( ogs_pkbuf_t *smf_n4_build_qos_flow_to_modify_list(
uint8_t type, smf_bearer_t *qos_flow, ogs_pfcp_xact_t *xact) uint8_t type, smf_sess_t *sess, ogs_pfcp_xact_t *xact)
{ {
ogs_pfcp_message_t pfcp_message; ogs_pfcp_message_t pfcp_message;
ogs_pfcp_session_modification_request_t *req = NULL; ogs_pfcp_session_modification_request_t *req = NULL;
ogs_pkbuf_t *pkbuf = NULL; ogs_pkbuf_t *pkbuf = NULL;
int i;
smf_sess_t *sess = NULL; smf_bearer_t *qos_flow = NULL;
int num_of_remove_pdr = 0;
int num_of_remove_far = 0;
int num_of_remove_qer = 0;
int num_of_create_pdr = 0;
int num_of_create_far = 0;
int num_of_create_qer = 0;
int num_of_update_pdr = 0;
int num_of_update_far = 0;
int num_of_update_qer = 0;
uint64_t modify_flags = 0; uint64_t modify_flags = 0;
ogs_debug("QoS Flow Modification Request"); ogs_debug("Bearer Modification Request");
ogs_assert(qos_flow);
sess = qos_flow->sess;
ogs_assert(sess); ogs_assert(sess);
ogs_assert(xact); ogs_assert(xact);
modify_flags = xact->modify_flags; modify_flags = xact->modify_flags;
@ -270,155 +277,163 @@ ogs_pkbuf_t *smf_n4_build_qos_flow_modification_request(
ogs_pfcp_pdrbuf_init(); ogs_pfcp_pdrbuf_init();
} }
if (modify_flags & OGS_PFCP_MODIFY_REMOVE) { ogs_list_for_each_entry(
/* Remove PDR */ &sess->qos_flow_to_modify_list, qos_flow, to_modify_node) {
i = 0;
if (qos_flow->dl_pdr) {
ogs_pfcp_tlv_remove_pdr_t *message = &req->remove_pdr[i];
message->presence = 1; if (modify_flags & OGS_PFCP_MODIFY_REMOVE) {
message->pdr_id.presence = 1; /* Remove PDR */
message->pdr_id.u16 = qos_flow->dl_pdr->id;
i++;
}
if (qos_flow->ul_pdr) {
ogs_pfcp_tlv_remove_pdr_t *message = &req->remove_pdr[i];
message->presence = 1;
message->pdr_id.presence = 1;
message->pdr_id.u16 = qos_flow->ul_pdr->id;
i++;
}
/* Remove FAR */
i = 0;
if (qos_flow->dl_far) {
ogs_pfcp_tlv_remove_far_t *message = &req->remove_far[i];
message->presence = 1;
message->far_id.presence = 1;
message->far_id.u32 = qos_flow->dl_far->id;
i++;
}
if (qos_flow->ul_far) {
ogs_pfcp_tlv_remove_far_t *message = &req->remove_far[i];
message->presence = 1;
message->far_id.presence = 1;
message->far_id.u32 = qos_flow->ul_far->id;
i++;
}
/* Remove QER */
i = 0;
if (qos_flow->qer) {
ogs_pfcp_tlv_remove_qer_t *message = &req->remove_qer[i];
message->presence = 1;
message->qer_id.presence = 1;
message->qer_id.u32 = qos_flow->qer->id;
i++;
}
} else {
if (modify_flags & OGS_PFCP_MODIFY_CREATE) {
/* Create PDR */
i = 0;
if (qos_flow->dl_pdr) { if (qos_flow->dl_pdr) {
ogs_pfcp_build_create_pdr( ogs_pfcp_tlv_remove_pdr_t *message =
&req->create_pdr[i], i, qos_flow->dl_pdr); &req->remove_pdr[num_of_remove_pdr];
i++;
ogs_list_add(&xact->pdr_to_create_list, message->presence = 1;
&qos_flow->dl_pdr->to_create_node); message->pdr_id.presence = 1;
message->pdr_id.u16 = qos_flow->dl_pdr->id;
num_of_remove_pdr++;
} }
if (qos_flow->ul_pdr) { if (qos_flow->ul_pdr) {
ogs_pfcp_build_create_pdr( ogs_pfcp_tlv_remove_pdr_t *message =
&req->create_pdr[i], i, qos_flow->ul_pdr); &req->remove_pdr[num_of_remove_pdr];
i++;
ogs_list_add(&xact->pdr_to_create_list, message->presence = 1;
&qos_flow->ul_pdr->to_create_node); message->pdr_id.presence = 1;
message->pdr_id.u16 = qos_flow->ul_pdr->id;
num_of_remove_pdr++;
} }
/* Create FAR */ /* Remove FAR */
i = 0;
if (qos_flow->dl_far) { if (qos_flow->dl_far) {
ogs_pfcp_build_create_far( ogs_pfcp_tlv_remove_far_t *message =
&req->create_far[i], i, qos_flow->dl_far); &req->remove_far[num_of_remove_far];
i++;
message->presence = 1;
message->far_id.presence = 1;
message->far_id.u32 = qos_flow->dl_far->id;
num_of_remove_far++;
} }
if (qos_flow->ul_far) { if (qos_flow->ul_far) {
ogs_pfcp_build_create_far( ogs_pfcp_tlv_remove_far_t *message =
&req->create_far[i], i, qos_flow->ul_far); &req->remove_far[num_of_remove_far];
i++;
message->presence = 1;
message->far_id.presence = 1;
message->far_id.u32 = qos_flow->ul_far->id;
num_of_remove_far++;
} }
/* Create QER */ /* Remove QER */
i = 0;
if (qos_flow->qer) { if (qos_flow->qer) {
ogs_pfcp_build_create_qer( ogs_pfcp_tlv_remove_qer_t *message =
&req->create_qer[i], i, qos_flow->qer); &req->remove_qer[num_of_remove_qer];
i++;
message->presence = 1;
message->qer_id.presence = 1;
message->qer_id.u32 = qos_flow->qer->id;
num_of_remove_qer++;
} }
}
if (modify_flags &
(OGS_PFCP_MODIFY_TFT_NEW|OGS_PFCP_MODIFY_TFT_ADD|
OGS_PFCP_MODIFY_TFT_REPLACE|OGS_PFCP_MODIFY_TFT_DELETE|
OGS_PFCP_MODIFY_EPC_TFT_UPDATE)) {
/* Update PDR */ } else {
i = 0; if (modify_flags & OGS_PFCP_MODIFY_CREATE) {
if (qos_flow->dl_pdr) {
ogs_pfcp_build_update_pdr(
&req->update_pdr[i], i, qos_flow->dl_pdr);
i++;
}
if (qos_flow->ul_pdr) {
ogs_pfcp_build_update_pdr(
&req->update_pdr[i], i, qos_flow->ul_pdr);
i++;
}
}
if (modify_flags & OGS_PFCP_MODIFY_ACTIVATE
|| modify_flags & OGS_PFCP_MODIFY_UL_ONLY) {
/* Update FAR - Only DL */
i = 0;
if (qos_flow->dl_far) {
if (qos_flow->dl_far->apply_action &
OGS_PFCP_APPLY_ACTION_FORW) {
if (modify_flags & OGS_PFCP_MODIFY_END_MARKER) { /* Create PDR */
qos_flow->dl_far-> if (qos_flow->dl_pdr) {
smreq_flags.send_end_marker_packets = 1; ogs_pfcp_build_create_pdr(
} &req->create_pdr[num_of_create_pdr],
num_of_create_pdr, qos_flow->dl_pdr);
num_of_create_pdr++;
ogs_pfcp_build_update_far_activate( ogs_list_add(&xact->pdr_to_create_list,
&req->update_far[i], i, qos_flow->dl_far); &qos_flow->dl_pdr->to_create_node);
i++; }
if (qos_flow->ul_pdr) {
ogs_pfcp_build_create_pdr(
&req->create_pdr[num_of_create_pdr],
num_of_create_pdr, qos_flow->ul_pdr);
num_of_create_pdr++;
/* Clear all FAR flags */ ogs_list_add(&xact->pdr_to_create_list,
qos_flow->dl_far->smreq_flags.value = 0; &qos_flow->ul_pdr->to_create_node);
}
/* Create FAR */
if (qos_flow->dl_far) {
ogs_pfcp_build_create_far(
&req->create_far[num_of_create_far],
num_of_create_far, qos_flow->dl_far);
num_of_create_far++;
}
if (qos_flow->ul_far) {
ogs_pfcp_build_create_far(
&req->create_far[num_of_create_far],
num_of_create_far, qos_flow->ul_far);
num_of_create_far++;
}
/* Create QER */
if (qos_flow->qer) {
ogs_pfcp_build_create_qer(
&req->create_qer[num_of_create_qer],
num_of_create_qer, qos_flow->qer);
num_of_create_qer++;
} }
} }
} else if (modify_flags & OGS_PFCP_MODIFY_DEACTIVATE) { if (modify_flags &
i = 0; (OGS_PFCP_MODIFY_TFT_NEW|OGS_PFCP_MODIFY_TFT_ADD|
if (qos_flow->dl_far) { OGS_PFCP_MODIFY_TFT_REPLACE|OGS_PFCP_MODIFY_TFT_DELETE|
ogs_pfcp_build_update_far_deactivate( OGS_PFCP_MODIFY_EPC_TFT_UPDATE)) {
&req->update_far[i], i, qos_flow->dl_far);
i++; /* Update PDR */
if (qos_flow->dl_pdr) {
ogs_pfcp_build_update_pdr(
&req->update_pdr[num_of_update_pdr],
num_of_update_pdr, qos_flow->dl_pdr);
num_of_update_pdr++;
}
if (qos_flow->ul_pdr) {
ogs_pfcp_build_update_pdr(
&req->update_pdr[num_of_update_pdr],
num_of_update_pdr, qos_flow->ul_pdr);
num_of_update_pdr++;
}
} }
} if (modify_flags & OGS_PFCP_MODIFY_ACTIVATE) {
if (modify_flags & /* Update FAR - Only DL */
(OGS_PFCP_MODIFY_QOS_MODIFY| if (qos_flow->dl_far) {
OGS_PFCP_MODIFY_EPC_QOS_UPDATE)) { if (qos_flow->dl_far->apply_action &
/* Update QER */ OGS_PFCP_APPLY_ACTION_FORW) {
i = 0;
if (qos_flow->qer) { if (modify_flags & OGS_PFCP_MODIFY_END_MARKER) {
ogs_pfcp_build_update_qer( qos_flow->dl_far->
&req->update_qer[i], i, qos_flow->qer); smreq_flags.send_end_marker_packets = 1;
i++; }
ogs_pfcp_build_update_far_activate(
&req->update_far[num_of_update_far],
num_of_update_far, qos_flow->dl_far);
num_of_update_far++;
/* Clear all FAR flags */
qos_flow->dl_far->smreq_flags.value = 0;
}
}
} else if (modify_flags & OGS_PFCP_MODIFY_DEACTIVATE) {
if (qos_flow->dl_far) {
ogs_pfcp_build_update_far_deactivate(
&req->update_far[num_of_update_far],
num_of_update_far, qos_flow->dl_far);
num_of_update_far++;
}
}
if (modify_flags &
(OGS_PFCP_MODIFY_QOS_MODIFY|
OGS_PFCP_MODIFY_EPC_QOS_UPDATE)) {
/* Update QER */
if (qos_flow->qer) {
ogs_pfcp_build_update_qer(
&req->update_qer[num_of_update_qer],
num_of_update_qer, qos_flow->qer);
num_of_update_qer++;
}
} }
} }
} }

View File

@ -28,10 +28,10 @@ extern "C" {
ogs_pkbuf_t *smf_n4_build_session_establishment_request( ogs_pkbuf_t *smf_n4_build_session_establishment_request(
uint8_t type, smf_sess_t *sess); uint8_t type, smf_sess_t *sess);
ogs_pkbuf_t *smf_n4_build_session_modification_request( ogs_pkbuf_t *smf_n4_build_pdr_to_modify_list(
uint8_t type, smf_sess_t *sess, ogs_pfcp_xact_t *xact);
ogs_pkbuf_t *smf_n4_build_qos_flow_to_modify_list(
uint8_t type, smf_sess_t *sess, ogs_pfcp_xact_t *xact); 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, ogs_pfcp_xact_t *xact);
ogs_pkbuf_t *smf_n4_build_session_deletion_request( ogs_pkbuf_t *smf_n4_build_session_deletion_request(
uint8_t type, smf_sess_t *sess); uint8_t type, smf_sess_t *sess);

View File

@ -823,6 +823,7 @@ uint8_t smf_epc_n4_handle_session_establishment_response(
void smf_epc_n4_handle_session_modification_response( void smf_epc_n4_handle_session_modification_response(
smf_sess_t *sess, ogs_pfcp_xact_t *xact, smf_sess_t *sess, ogs_pfcp_xact_t *xact,
ogs_gtp2_message_t *recv_message,
ogs_pfcp_session_modification_response_t *rsp) ogs_pfcp_session_modification_response_t *rsp)
{ {
int i; int i;
@ -940,7 +941,7 @@ void smf_epc_n4_handle_session_modification_response(
} else if (flags & OGS_PFCP_MODIFY_CREATE) { } else if (flags & OGS_PFCP_MODIFY_CREATE) {
ogs_assert(bearer); ogs_assert(bearer);
ogs_assert(OGS_OK == smf_gtp_send_create_bearer_request(bearer)); ogs_assert(OGS_OK == smf_gtp2_send_create_bearer_request(bearer));
} else if (flags & OGS_PFCP_MODIFY_DEACTIVATE) { } else if (flags & OGS_PFCP_MODIFY_DEACTIVATE) {
/* /*
@ -1013,7 +1014,7 @@ void smf_epc_n4_handle_session_modification_response(
ogs_assert(linked_bearer); ogs_assert(linked_bearer);
ogs_assert(OGS_OK == ogs_assert(OGS_OK ==
smf_gtp_send_delete_bearer_request( smf_gtp2_send_delete_bearer_request(
linked_bearer, gtp_pti, gtp_cause)); linked_bearer, gtp_pti, gtp_cause));
} else { } else {
/* /*
@ -1034,7 +1035,7 @@ void smf_epc_n4_handle_session_modification_response(
ogs_assert(bearer); ogs_assert(bearer);
ogs_assert(OGS_OK == ogs_assert(OGS_OK ==
smf_gtp_send_delete_bearer_request( smf_gtp2_send_delete_bearer_request(
bearer, bearer,
OGS_NAS_PROCEDURE_TRANSACTION_IDENTITY_UNASSIGNED, OGS_NAS_PROCEDURE_TRANSACTION_IDENTITY_UNASSIGNED,
gtp_cause)); gtp_cause));
@ -1043,12 +1044,36 @@ void smf_epc_n4_handle_session_modification_response(
} else if (flags & OGS_PFCP_MODIFY_ACTIVATE) { } else if (flags & OGS_PFCP_MODIFY_ACTIVATE) {
if (gtp_xact) { if (gtp_xact) {
/* SMF send Update PDP Context Response (GTPv1C) to SGSN */ /* SMF send Update PDP Context Response (GTPv1C) to SGSN */
if (gtp_xact->gtp_version == 1) { if (gtp_xact->gtp_version == 1) {
bearer = gtp_xact->data; bearer = gtp_xact->data;
smf_gtp1_send_update_pdp_context_response(bearer, gtp_xact); smf_gtp1_send_update_pdp_context_response(bearer, gtp_xact);
} else { } else {
/* TODO: SMF send Modify Bearer Response (GTPv2C) to SGWC */
/* SMF send Modify Bearer Response (GTPv2C) to SGW-C */
ogs_gtp2_indication_t *indication = NULL;
ogs_assert(recv_message);
ogs_gtp2_modify_bearer_request_t *gtp_req =
&recv_message->modify_bearer_request;
ogs_assert(OGS_OK == smf_gtp2_send_modify_bearer_response(
sess, gtp_xact, gtp_req, true));
/* Check if Handover from Non-3GPP to 3GPP */
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) {
ogs_assert(OGS_OK == smf_epc_pfcp_send_deactivation(sess,
OGS_GTP2_CAUSE_ACCESS_CHANGED_FROM_NON_3GPP_TO_3GPP));
}
} }
} else { } else {
/* Nothing */ /* Nothing */

View File

@ -41,6 +41,7 @@ uint8_t smf_epc_n4_handle_session_establishment_response(
ogs_pfcp_session_establishment_response_t *rsp); ogs_pfcp_session_establishment_response_t *rsp);
void smf_epc_n4_handle_session_modification_response( void smf_epc_n4_handle_session_modification_response(
smf_sess_t *sess, ogs_pfcp_xact_t *xact, smf_sess_t *sess, ogs_pfcp_xact_t *xact,
ogs_gtp2_message_t *gtp2_message,
ogs_pfcp_session_modification_response_t *rsp); ogs_pfcp_session_modification_response_t *rsp);
uint8_t smf_epc_n4_handle_session_deletion_response( uint8_t smf_epc_n4_handle_session_deletion_response(
smf_sess_t *sess, ogs_pfcp_xact_t *xact, smf_sess_t *sess, ogs_pfcp_xact_t *xact,

View File

@ -294,6 +294,41 @@ static void bearer_epc_timeout(ogs_pfcp_xact_t *xact, void *data)
} }
} }
int smf_pfcp_send_modify_list(
smf_sess_t *sess,
ogs_pkbuf_t *(*modify_list)(
uint8_t type, smf_sess_t *sess, ogs_pfcp_xact_t *xact),
ogs_pfcp_xact_t *xact, ogs_time_t duration)
{
int rv;
ogs_pkbuf_t *n4buf = NULL;
ogs_pfcp_header_t h;
ogs_assert(sess);
ogs_assert(xact);
memset(&h, 0, sizeof(ogs_pfcp_header_t));
h.type = OGS_PFCP_SESSION_MODIFICATION_REQUEST_TYPE;
h.seid = sess->upf_n4_seid;
n4buf = (*modify_list)(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);
return OGS_OK;
} else {
rv = ogs_pfcp_xact_commit(xact);
ogs_expect(rv == OGS_OK);
return rv;
}
}
int smf_5gc_pfcp_send_session_establishment_request( int smf_5gc_pfcp_send_session_establishment_request(
smf_sess_t *sess, ogs_sbi_stream_t *stream) smf_sess_t *sess, ogs_sbi_stream_t *stream)
{ {
@ -305,15 +340,15 @@ int smf_5gc_pfcp_send_session_establishment_request(
ogs_assert(sess); ogs_assert(sess);
ogs_assert(stream); ogs_assert(stream);
memset(&h, 0, sizeof(ogs_pfcp_header_t));
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); xact = ogs_pfcp_xact_local_create(sess->pfcp_node, sess_5gc_timeout, sess);
ogs_expect_or_return_val(xact, OGS_ERROR); ogs_expect_or_return_val(xact, OGS_ERROR);
xact->assoc_stream = stream; xact->assoc_stream = stream;
memset(&h, 0, sizeof(ogs_pfcp_header_t));
h.type = OGS_PFCP_SESSION_ESTABLISHMENT_REQUEST_TYPE;
h.seid = sess->upf_n4_seid;
n4buf = smf_n4_build_session_establishment_request(h.type, sess); n4buf = smf_n4_build_session_establishment_request(h.type, sess);
ogs_expect_or_return_val(n4buf, OGS_ERROR); ogs_expect_or_return_val(n4buf, OGS_ERROR);
@ -331,48 +366,34 @@ int smf_5gc_pfcp_send_session_modification_request(
uint64_t flags, ogs_time_t duration) uint64_t flags, ogs_time_t duration)
{ {
int rv; int rv;
ogs_pkbuf_t *n4buf = NULL;
ogs_pfcp_header_t h;
ogs_pfcp_xact_t *xact = NULL; ogs_pfcp_xact_t *xact = NULL;
ogs_pfcp_pdr_t *pdr = NULL;
ogs_assert(sess); ogs_assert(sess);
if ((flags & OGS_PFCP_MODIFY_ERROR_INDICATION) == 0) if ((flags & OGS_PFCP_MODIFY_ERROR_INDICATION) == 0)
ogs_assert(stream); ogs_assert(stream);
memset(&h, 0, sizeof(ogs_pfcp_header_t));
h.type = OGS_PFCP_SESSION_MODIFICATION_REQUEST_TYPE;
h.seid = sess->upf_n4_seid;
xact = ogs_pfcp_xact_local_create(sess->pfcp_node, 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); ogs_expect_or_return_val(xact, OGS_ERROR);
xact->assoc_stream = stream; xact->assoc_stream = stream;
xact->modify_flags = flags | OGS_PFCP_MODIFY_SESSION; xact->modify_flags = flags | OGS_PFCP_MODIFY_SESSION;
n4buf = smf_n4_build_session_modification_request(h.type, sess, xact); ogs_list_init(&sess->pdr_to_modify_list);
ogs_expect_or_return_val(n4buf, OGS_ERROR); ogs_list_for_each(&sess->pfcp.pdr_list, pdr)
ogs_list_add(&sess->pdr_to_modify_list, &pdr->to_modify_node);
rv = ogs_pfcp_xact_update_tx(xact, &h, n4buf); rv = smf_pfcp_send_modify_list(
ogs_expect_or_return_val(rv == OGS_OK, OGS_ERROR); sess, smf_n4_build_pdr_to_modify_list, xact, duration);
ogs_expect(rv == OGS_OK);
if (duration) { return rv;
ogs_pfcp_xact_delayed_commit(xact, duration);
return OGS_OK;
} else {
rv = ogs_pfcp_xact_commit(xact);
ogs_expect(rv == OGS_OK);
return rv;
}
} }
int smf_5gc_pfcp_send_qos_flow_modification_request(smf_bearer_t *qos_flow, int smf_5gc_pfcp_send_qos_flow_modification_request(smf_bearer_t *qos_flow,
ogs_sbi_stream_t *stream, uint64_t flags) ogs_sbi_stream_t *stream, uint64_t flags)
{ {
int rv; int rv;
ogs_pkbuf_t *n4buf = NULL;
ogs_pfcp_header_t h;
ogs_pfcp_xact_t *xact = NULL; ogs_pfcp_xact_t *xact = NULL;
smf_sess_t *sess = NULL; smf_sess_t *sess = NULL;
@ -380,10 +401,6 @@ int smf_5gc_pfcp_send_qos_flow_modification_request(smf_bearer_t *qos_flow,
sess = qos_flow->sess; sess = qos_flow->sess;
ogs_assert(sess); 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;
xact = ogs_pfcp_xact_local_create( xact = ogs_pfcp_xact_local_create(
sess->pfcp_node, qos_flow_5gc_timeout, qos_flow); sess->pfcp_node, qos_flow_5gc_timeout, qos_flow);
ogs_expect_or_return_val(xact, OGS_ERROR); ogs_expect_or_return_val(xact, OGS_ERROR);
@ -391,13 +408,11 @@ int smf_5gc_pfcp_send_qos_flow_modification_request(smf_bearer_t *qos_flow,
xact->assoc_stream = stream; xact->assoc_stream = stream;
xact->modify_flags = flags; xact->modify_flags = flags;
n4buf = smf_n4_build_qos_flow_modification_request(h.type, qos_flow, xact); ogs_list_init(&sess->qos_flow_to_modify_list);
ogs_expect_or_return_val(n4buf, OGS_ERROR); ogs_list_add(&sess->qos_flow_to_modify_list, &qos_flow->to_modify_node);
rv = ogs_pfcp_xact_update_tx(xact, &h, n4buf); rv = smf_pfcp_send_modify_list(
ogs_expect_or_return_val(rv == OGS_OK, OGS_ERROR); sess, smf_n4_build_qos_flow_to_modify_list, xact, 0);
rv = ogs_pfcp_xact_commit(xact);
ogs_expect(rv == OGS_OK); ogs_expect(rv == OGS_OK);
return rv; return rv;
@ -414,16 +429,16 @@ int smf_5gc_pfcp_send_session_deletion_request(
ogs_assert(sess); ogs_assert(sess);
ogs_assert(trigger); ogs_assert(trigger);
memset(&h, 0, sizeof(ogs_pfcp_header_t));
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); xact = ogs_pfcp_xact_local_create(sess->pfcp_node, sess_5gc_timeout, sess);
ogs_expect_or_return_val(xact, OGS_ERROR); ogs_expect_or_return_val(xact, OGS_ERROR);
xact->assoc_stream = stream; xact->assoc_stream = stream;
xact->delete_trigger = trigger; xact->delete_trigger = trigger;
memset(&h, 0, sizeof(ogs_pfcp_header_t));
h.type = OGS_PFCP_SESSION_DELETION_REQUEST_TYPE;
h.seid = sess->upf_n4_seid;
n4buf = smf_n4_build_session_deletion_request(h.type, sess); n4buf = smf_n4_build_session_deletion_request(h.type, sess);
ogs_expect_or_return_val(n4buf, OGS_ERROR); ogs_expect_or_return_val(n4buf, OGS_ERROR);
@ -446,16 +461,16 @@ int smf_epc_pfcp_send_session_establishment_request(
ogs_assert(sess); ogs_assert(sess);
memset(&h, 0, sizeof(ogs_pfcp_header_t));
h.type = OGS_PFCP_SESSION_ESTABLISHMENT_REQUEST_TYPE;
h.seid = sess->upf_n4_seid;
xact = ogs_pfcp_xact_local_create(sess->pfcp_node, 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); ogs_expect_or_return_val(xact, OGS_ERROR);
xact->epc = true; /* EPC PFCP transaction */ xact->epc = true; /* EPC PFCP transaction */
xact->assoc_xact = gtp_xact; xact->assoc_xact = gtp_xact;
memset(&h, 0, sizeof(ogs_pfcp_header_t));
h.type = OGS_PFCP_SESSION_ESTABLISHMENT_REQUEST_TYPE;
h.seid = sess->upf_n4_seid;
n4buf = smf_n4_build_session_establishment_request(h.type, sess); n4buf = smf_n4_build_session_establishment_request(h.type, sess);
ogs_expect_or_return_val(n4buf, OGS_ERROR); ogs_expect_or_return_val(n4buf, OGS_ERROR);
@ -469,20 +484,15 @@ int smf_epc_pfcp_send_session_establishment_request(
} }
int smf_epc_pfcp_send_session_modification_request( int smf_epc_pfcp_send_session_modification_request(
smf_sess_t *sess, void *gtp_xact, smf_sess_t *sess, void *gtp_xact, ogs_pkbuf_t *gtpbuf,
uint64_t flags, uint8_t gtp_pti, uint8_t gtp_cause) uint64_t flags, uint8_t gtp_pti, uint8_t gtp_cause)
{ {
int rv; int rv;
ogs_pkbuf_t *n4buf = NULL;
ogs_pfcp_header_t h;
ogs_pfcp_xact_t *xact = NULL; ogs_pfcp_xact_t *xact = NULL;
ogs_pfcp_pdr_t *pdr = NULL;
ogs_assert(sess); 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;
xact = ogs_pfcp_xact_local_create(sess->pfcp_node, 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); ogs_expect_or_return_val(xact, OGS_ERROR);
@ -492,14 +502,17 @@ int smf_epc_pfcp_send_session_modification_request(
xact->gtp_pti = gtp_pti; xact->gtp_pti = gtp_pti;
xact->gtp_cause = gtp_cause; xact->gtp_cause = gtp_cause;
if (gtpbuf) {
xact->gtpbuf = ogs_pkbuf_copy(gtpbuf);
ogs_expect_or_return_val(xact->gtpbuf, OGS_ERROR);
}
n4buf = smf_n4_build_session_modification_request(h.type, sess, xact); ogs_list_init(&sess->pdr_to_modify_list);
ogs_expect_or_return_val(n4buf, OGS_ERROR); ogs_list_for_each(&sess->pfcp.pdr_list, pdr)
ogs_list_add(&sess->pdr_to_modify_list, &pdr->to_modify_node);
rv = ogs_pfcp_xact_update_tx(xact, &h, n4buf); rv = smf_pfcp_send_modify_list(
ogs_expect_or_return_val(rv == OGS_OK, OGS_ERROR); sess, smf_n4_build_pdr_to_modify_list, xact, 0);
rv = ogs_pfcp_xact_commit(xact);
ogs_expect(rv == OGS_OK); ogs_expect(rv == OGS_OK);
return rv; return rv;
@ -510,8 +523,6 @@ int smf_epc_pfcp_send_bearer_modification_request(
uint64_t flags, uint8_t gtp_pti, uint8_t gtp_cause) uint64_t flags, uint8_t gtp_pti, uint8_t gtp_cause)
{ {
int rv; int rv;
ogs_pkbuf_t *n4buf = NULL;
ogs_pfcp_header_t h;
ogs_pfcp_xact_t *xact = NULL; ogs_pfcp_xact_t *xact = NULL;
smf_sess_t *sess = NULL; smf_sess_t *sess = NULL;
@ -519,10 +530,6 @@ int smf_epc_pfcp_send_bearer_modification_request(
sess = bearer->sess; sess = bearer->sess;
ogs_assert(sess); 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;
xact = ogs_pfcp_xact_local_create( xact = ogs_pfcp_xact_local_create(
sess->pfcp_node, bearer_epc_timeout, bearer); sess->pfcp_node, bearer_epc_timeout, bearer);
ogs_expect_or_return_val(xact, OGS_ERROR); ogs_expect_or_return_val(xact, OGS_ERROR);
@ -534,13 +541,11 @@ int smf_epc_pfcp_send_bearer_modification_request(
xact->gtp_pti = gtp_pti; xact->gtp_pti = gtp_pti;
xact->gtp_cause = gtp_cause; xact->gtp_cause = gtp_cause;
n4buf = smf_n4_build_qos_flow_modification_request(h.type, bearer, xact); ogs_list_init(&sess->qos_flow_to_modify_list);
ogs_expect_or_return_val(n4buf, OGS_ERROR); ogs_list_add(&sess->qos_flow_to_modify_list, &bearer->to_modify_node);
rv = ogs_pfcp_xact_update_tx(xact, &h, n4buf); rv = smf_pfcp_send_modify_list(
ogs_expect_or_return_val(rv == OGS_OK, OGS_ERROR); sess, smf_n4_build_qos_flow_to_modify_list, xact, 0);
rv = ogs_pfcp_xact_commit(xact);
ogs_expect(rv == OGS_OK); ogs_expect(rv == OGS_OK);
return rv; return rv;
@ -556,10 +561,6 @@ int smf_epc_pfcp_send_session_deletion_request(
ogs_assert(sess); ogs_assert(sess);
memset(&h, 0, sizeof(ogs_pfcp_header_t));
h.type = OGS_PFCP_SESSION_DELETION_REQUEST_TYPE;
h.seid = sess->upf_n4_seid;
xact = ogs_pfcp_xact_local_create(sess->pfcp_node, 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); ogs_expect_or_return_val(xact, OGS_ERROR);
@ -588,6 +589,10 @@ int smf_epc_pfcp_send_session_deletion_request(
*/ */
xact->assoc_xact = gtp_xact; xact->assoc_xact = gtp_xact;
memset(&h, 0, sizeof(ogs_pfcp_header_t));
h.type = OGS_PFCP_SESSION_DELETION_REQUEST_TYPE;
h.seid = sess->upf_n4_seid;
n4buf = smf_n4_build_session_deletion_request(h.type, sess); n4buf = smf_n4_build_session_deletion_request(h.type, sess);
ogs_expect_or_return_val(n4buf, OGS_ERROR); ogs_expect_or_return_val(n4buf, OGS_ERROR);
@ -600,6 +605,60 @@ int smf_epc_pfcp_send_session_deletion_request(
return rv; return rv;
} }
int smf_epc_pfcp_send_deactivation(smf_sess_t *sess, uint8_t gtp_cause)
{
int rv;
smf_ue_t *smf_ue = NULL;
smf_sess_t *eutran_sess = NULL, *wlan_sess = NULL;
ogs_assert(sess);
smf_ue = sess->smf_ue;
ogs_assert(smf_ue);
switch (gtp_cause) {
case OGS_GTP2_CAUSE_ACCESS_CHANGED_FROM_NON_3GPP_TO_3GPP:
/* Handover from Non-3GPP to 3GPP */
wlan_sess = smf_sess_find_by_apn(
smf_ue, sess->session.name, OGS_GTP2_RAT_TYPE_WLAN);
ogs_expect_or_return_val(wlan_sess, OGS_ERROR);
ogs_expect_or_return_val(
ogs_list_first(&wlan_sess->bearer_list), OGS_ERROR);
/* Deactivate WLAN Session */
rv = smf_epc_pfcp_send_session_modification_request(
wlan_sess, NULL, NULL,
OGS_PFCP_MODIFY_DL_ONLY|OGS_PFCP_MODIFY_DEACTIVATE,
OGS_NAS_PROCEDURE_TRANSACTION_IDENTITY_UNASSIGNED,
OGS_GTP2_CAUSE_ACCESS_CHANGED_FROM_NON_3GPP_TO_3GPP);
ogs_expect_or_return_val(rv == OGS_OK, rv);
break;
case OGS_GTP2_CAUSE_RAT_CHANGED_FROM_3GPP_TO_NON_3GPP:
/* Handover from 3GPP to Non-3GPP */
eutran_sess = smf_sess_find_by_apn(
smf_ue, sess->session.name, OGS_GTP2_RAT_TYPE_EUTRAN);
if (eutran_sess) {
ogs_expect_or_return_val(
ogs_list_first(&eutran_sess->bearer_list), OGS_ERROR);
/* Deactivate EUTRAN Session */
rv = smf_epc_pfcp_send_session_modification_request(
eutran_sess, NULL, NULL,
OGS_PFCP_MODIFY_DL_ONLY|OGS_PFCP_MODIFY_DEACTIVATE,
OGS_NAS_PROCEDURE_TRANSACTION_IDENTITY_UNASSIGNED,
OGS_GTP2_CAUSE_RAT_CHANGED_FROM_3GPP_TO_NON_3GPP);
ogs_expect_or_return_val(rv == OGS_OK, rv);
}
break;
default:
ogs_fatal("Invalid GTP-Cause[%d]", gtp_cause);
ogs_assert_if_reached();
}
return OGS_OK;
}
int smf_pfcp_send_session_report_response( int smf_pfcp_send_session_report_response(
ogs_pfcp_xact_t *xact, smf_sess_t *sess, uint8_t cause) ogs_pfcp_xact_t *xact, smf_sess_t *sess, uint8_t cause)
{ {

View File

@ -29,20 +29,27 @@ extern "C" {
int smf_pfcp_open(void); int smf_pfcp_open(void);
void smf_pfcp_close(void); void smf_pfcp_close(void);
int smf_pfcp_send_modify_list(
smf_sess_t *sess,
ogs_pkbuf_t *(*modify_list)(
uint8_t type, smf_sess_t *sess, ogs_pfcp_xact_t *xact),
ogs_pfcp_xact_t *xact, ogs_time_t duration);
int smf_5gc_pfcp_send_session_establishment_request( int smf_5gc_pfcp_send_session_establishment_request(
smf_sess_t *sess, ogs_sbi_stream_t *stream); smf_sess_t *sess, ogs_sbi_stream_t *stream);
int smf_5gc_pfcp_send_session_modification_request( int smf_5gc_pfcp_send_session_modification_request(
smf_sess_t *sess, ogs_sbi_stream_t *stream, smf_sess_t *sess, ogs_sbi_stream_t *stream,
uint64_t flags, ogs_time_t duration); uint64_t flags, ogs_time_t duration);
int smf_5gc_pfcp_send_qos_flow_modification_request(smf_bearer_t *qos_flow, int smf_5gc_pfcp_send_qos_flow_modification_request(
ogs_sbi_stream_t *stream, uint64_t flags); smf_bearer_t *qos_flow, ogs_sbi_stream_t *stream,
uint64_t flags);
int smf_5gc_pfcp_send_session_deletion_request( int smf_5gc_pfcp_send_session_deletion_request(
smf_sess_t *sess, ogs_sbi_stream_t *stream, int trigger); smf_sess_t *sess, ogs_sbi_stream_t *stream, int trigger);
int smf_epc_pfcp_send_session_establishment_request( int smf_epc_pfcp_send_session_establishment_request(
smf_sess_t *sess, void *gtp_xact); smf_sess_t *sess, void *gtp_xact);
int smf_epc_pfcp_send_session_modification_request( int smf_epc_pfcp_send_session_modification_request(
smf_sess_t *sess, void *gtp_xact, smf_sess_t *sess, void *gtp_xact, ogs_pkbuf_t *gtpbuf,
uint64_t flags, uint8_t gtp_pti, uint8_t gtp_cause); uint64_t flags, uint8_t gtp_pti, uint8_t gtp_cause);
int smf_epc_pfcp_send_bearer_modification_request( int smf_epc_pfcp_send_bearer_modification_request(
smf_bearer_t *bearer, void *gtp_xact, smf_bearer_t *bearer, void *gtp_xact,
@ -50,6 +57,8 @@ int smf_epc_pfcp_send_bearer_modification_request(
int smf_epc_pfcp_send_session_deletion_request( int smf_epc_pfcp_send_session_deletion_request(
smf_sess_t *sess, void *gtp_xact); smf_sess_t *sess, void *gtp_xact);
int smf_epc_pfcp_send_deactivation(smf_sess_t *sess, uint8_t gtp_cause);
int smf_pfcp_send_session_report_response( int smf_pfcp_send_session_report_response(
ogs_pfcp_xact_t *xact, smf_sess_t *sess, uint8_t cause); ogs_pfcp_xact_t *xact, smf_sess_t *sess, uint8_t cause);

View File

@ -238,7 +238,8 @@ void smf_pfcp_state_associated(ogs_fsm_t *s, smf_event_t *e)
if (xact->epc) if (xact->epc)
smf_epc_n4_handle_session_modification_response( smf_epc_n4_handle_session_modification_response(
sess, xact, &message->pfcp_session_modification_response); sess, xact, e->gtp2_message,
&message->pfcp_session_modification_response);
else else
smf_5gc_n4_handle_session_modification_response( smf_5gc_n4_handle_session_modification_response(
sess, xact, &message->pfcp_session_modification_response); sess, xact, &message->pfcp_session_modification_response);

View File

@ -32,11 +32,16 @@ ogs_pkbuf_t *smf_s5c_build_create_session_response(
ogs_gtp2_create_session_response_t *rsp = NULL; ogs_gtp2_create_session_response_t *rsp = NULL;
ogs_gtp2_cause_t cause; ogs_gtp2_cause_t cause;
ogs_gtp2_cause_t bearer_cause;
ogs_gtp2_f_teid_t smf_s5c_teid, pgw_s5u_teid; int i;
ogs_gtp2_cause_t bearer_cause[OGS_BEARER_PER_UE];
ogs_gtp2_f_teid_t pgw_s5u_teid[OGS_BEARER_PER_UE];
int pgw_s5u_len[OGS_BEARER_PER_UE];
ogs_gtp2_f_teid_t smf_s5c_teid;
ogs_gtp2_ambr_t ambr; ogs_gtp2_ambr_t ambr;
ogs_gtp2_bearer_qos_t bearer_qos; ogs_gtp2_bearer_qos_t bearer_qos;
char bearer_qos_buf[GTP2_BEARER_QOS_LEN]; char bearer_qos_buf[OGS_BEARER_PER_UE][GTP2_BEARER_QOS_LEN];
int len; int len;
uint8_t pco_buf[OGS_MAX_PCO_LEN]; uint8_t pco_buf[OGS_MAX_PCO_LEN];
int16_t pco_len; int16_t pco_len;
@ -44,13 +49,9 @@ ogs_pkbuf_t *smf_s5c_build_create_session_response(
ogs_debug("[SMF] Create Session Response"); ogs_debug("[SMF] Create Session Response");
ogs_assert(sess); ogs_assert(sess);
bearer = smf_default_bearer_in_sess(sess);
ogs_assert(bearer);
ogs_debug(" SGW_S5C_TEID[0x%x] SMF_N4_TEID[0x%x]", ogs_debug(" SGW_S5C_TEID[0x%x] SMF_N4_TEID[0x%x]",
sess->sgw_s5c_teid, sess->smf_n4_teid); sess->sgw_s5c_teid, sess->smf_n4_teid);
ogs_debug(" SGW_S5U_TEID[0x%x] PGW_S5U_TEID[0x%x]",
bearer->sgw_s5u_teid, bearer->pgw_s5u_teid);
rsp = &gtp_message.create_session_response; rsp = &gtp_message.create_session_response;
memset(&gtp_message, 0, sizeof(ogs_gtp2_message_t)); memset(&gtp_message, 0, sizeof(ogs_gtp2_message_t));
@ -114,7 +115,7 @@ ogs_pkbuf_t *smf_s5c_build_create_session_response(
ogs_error("Unknown RAT Type [%d]", sess->gtp_rat_type); ogs_error("Unknown RAT Type [%d]", sess->gtp_rat_type);
ogs_assert_if_reached(); ogs_assert_if_reached();
} }
/* APN-AMBR /* APN-AMBR
* if PCRF changes APN-AMBR, this should be included. */ * if PCRF changes APN-AMBR, this should be included. */
if (sess->gtp.create_session_response_apn_ambr == true) { if (sess->gtp.create_session_response_apn_ambr == true) {
@ -137,62 +138,78 @@ ogs_pkbuf_t *smf_s5c_build_create_session_response(
rsp->protocol_configuration_options.len = pco_len; rsp->protocol_configuration_options.len = pco_len;
} }
/* Bearer EBI */ i = 0;
rsp->bearer_contexts_created.presence = 1; ogs_list_for_each(&sess->bearer_list, bearer) {
rsp->bearer_contexts_created.eps_bearer_id.presence = 1; ogs_assert(i < OGS_BEARER_PER_UE);
rsp->bearer_contexts_created.eps_bearer_id.u8 = bearer->ebi;
/* Bearer Cause */ ogs_debug(" SGW_S5U_TEID[0x%x] PGW_S5U_TEID[0x%x]",
memset(&bearer_cause, 0, sizeof(bearer_cause)); bearer->sgw_s5u_teid, bearer->pgw_s5u_teid);
rsp->bearer_contexts_created.cause.presence = 1;
rsp->bearer_contexts_created.cause.len = sizeof(bearer_cause);
rsp->bearer_contexts_created.cause.data = &bearer_cause;
bearer_cause.value = OGS_GTP2_CAUSE_REQUEST_ACCEPTED;
/* Bearer QoS /* Bearer EBI */
* if PCRF changes Bearer QoS, this should be included. */ rsp->bearer_contexts_created[i].presence = 1;
if (sess->gtp.create_session_response_bearer_qos == true) { rsp->bearer_contexts_created[i].eps_bearer_id.presence = 1;
memset(&bearer_qos, 0, sizeof(bearer_qos)); rsp->bearer_contexts_created[i].eps_bearer_id.u8 = bearer->ebi;
bearer_qos.qci = sess->session.qos.index;
bearer_qos.priority_level = sess->session.qos.arp.priority_level;
bearer_qos.pre_emption_capability =
sess->session.qos.arp.pre_emption_capability;
bearer_qos.pre_emption_vulnerability =
sess->session.qos.arp.pre_emption_vulnerability;
rsp->bearer_contexts_created.bearer_level_qos.presence = 1; /* Bearer Cause */
ogs_gtp2_build_bearer_qos(&rsp->bearer_contexts_created.bearer_level_qos, memset(&bearer_cause[i], 0, sizeof(bearer_cause[i]));
&bearer_qos, bearer_qos_buf, GTP2_BEARER_QOS_LEN); rsp->bearer_contexts_created[i].cause.presence = 1;
} rsp->bearer_contexts_created[i].cause.len = sizeof(bearer_cause[i]);
rsp->bearer_contexts_created[i].cause.data = &bearer_cause[i];
bearer_cause[i].value = OGS_GTP2_CAUSE_REQUEST_ACCEPTED;
/* Bearer Charging ID */ /* Bearer QoS
rsp->bearer_contexts_created.charging_id.presence = 1; * if PCRF changes Bearer QoS, this should be included. */
rsp->bearer_contexts_created.charging_id.u32 = sess->charging.id; if (sess->gtp.create_session_response_bearer_qos == true) {
memset(&bearer_qos, 0, sizeof(bearer_qos));
bearer_qos.qci = sess->session.qos.index;
bearer_qos.priority_level = sess->session.qos.arp.priority_level;
bearer_qos.pre_emption_capability =
sess->session.qos.arp.pre_emption_capability;
bearer_qos.pre_emption_vulnerability =
sess->session.qos.arp.pre_emption_vulnerability;
/* Data Plane(UL) : SMF-S5U */ rsp->bearer_contexts_created[i].bearer_level_qos.presence = 1;
memset(&pgw_s5u_teid, 0, sizeof(ogs_gtp2_f_teid_t)); ogs_gtp2_build_bearer_qos(
pgw_s5u_teid.teid = htobe32(bearer->pgw_s5u_teid); &rsp->bearer_contexts_created[i].bearer_level_qos,
ogs_assert(bearer->pgw_s5u_addr || bearer->pgw_s5u_addr6); &bearer_qos, bearer_qos_buf[i], GTP2_BEARER_QOS_LEN);
rv = ogs_gtp2_sockaddr_to_f_teid( }
bearer->pgw_s5u_addr, bearer->pgw_s5u_addr6, &pgw_s5u_teid, &len);
ogs_expect_or_return_val(rv == OGS_OK, NULL);
switch (sess->gtp_rat_type) { /* Bearer Charging ID */
case OGS_GTP2_RAT_TYPE_EUTRAN: rsp->bearer_contexts_created[i].charging_id.presence = 1;
pgw_s5u_teid.interface_type = OGS_GTP2_F_TEID_S5_S8_PGW_GTP_U; rsp->bearer_contexts_created[i].charging_id.u32 = sess->charging.id;
rsp->bearer_contexts_created.s5_s8_u_sgw_f_teid.presence = 1;
rsp->bearer_contexts_created.s5_s8_u_sgw_f_teid.data = &pgw_s5u_teid; /* Data Plane(UL) : SMF-S5U */
rsp->bearer_contexts_created.s5_s8_u_sgw_f_teid.len = len; memset(&pgw_s5u_teid[i], 0, sizeof(ogs_gtp2_f_teid_t));
break; pgw_s5u_teid[i].teid = htobe32(bearer->pgw_s5u_teid);
case OGS_GTP2_RAT_TYPE_WLAN: ogs_assert(bearer->pgw_s5u_addr || bearer->pgw_s5u_addr6);
pgw_s5u_teid.interface_type = OGS_GTP2_F_TEID_S2B_U_PGW_GTP_U; rv = ogs_gtp2_sockaddr_to_f_teid(
rsp->bearer_contexts_created.s12_rnc_f_teid.presence = 1; bearer->pgw_s5u_addr, bearer->pgw_s5u_addr6,
rsp->bearer_contexts_created.s12_rnc_f_teid.data = &pgw_s5u_teid; &pgw_s5u_teid[i], &pgw_s5u_len[i]);
rsp->bearer_contexts_created.s12_rnc_f_teid.len = len; ogs_expect_or_return_val(rv == OGS_OK, NULL);
break;
default: switch (sess->gtp_rat_type) {
ogs_error("Unknown RAT Type [%d]", sess->gtp_rat_type); case OGS_GTP2_RAT_TYPE_EUTRAN:
ogs_assert_if_reached(); pgw_s5u_teid[i].interface_type = OGS_GTP2_F_TEID_S5_S8_PGW_GTP_U;
rsp->bearer_contexts_created[i].s5_s8_u_sgw_f_teid.presence = 1;
rsp->bearer_contexts_created[i].s5_s8_u_sgw_f_teid.data =
&pgw_s5u_teid[i];
rsp->bearer_contexts_created[i].s5_s8_u_sgw_f_teid.len =
pgw_s5u_len[i];
break;
case OGS_GTP2_RAT_TYPE_WLAN:
pgw_s5u_teid[i].interface_type = OGS_GTP2_F_TEID_S2B_U_PGW_GTP_U;
rsp->bearer_contexts_created[i].s12_rnc_f_teid.presence = 1;
rsp->bearer_contexts_created[i].s12_rnc_f_teid.data =
&pgw_s5u_teid[i];
rsp->bearer_contexts_created[i].s12_rnc_f_teid.len =
pgw_s5u_len[i];
break;
default:
ogs_error("Unknown RAT Type [%d]", sess->gtp_rat_type);
ogs_assert_if_reached();
}
i++;
} }
gtp_message.h.type = type; gtp_message.h.type = type;
@ -208,7 +225,7 @@ ogs_pkbuf_t *smf_s5c_build_delete_session_response(
ogs_gtp2_cause_t cause; ogs_gtp2_cause_t cause;
uint8_t pco_buf[OGS_MAX_PCO_LEN]; uint8_t pco_buf[OGS_MAX_PCO_LEN];
int16_t pco_len; int16_t pco_len;
/* prepare cause */ /* prepare cause */
memset(&cause, 0, sizeof(cause)); memset(&cause, 0, sizeof(cause));
cause.value = OGS_GTP2_CAUSE_REQUEST_ACCEPTED; cause.value = OGS_GTP2_CAUSE_REQUEST_ACCEPTED;
@ -243,14 +260,21 @@ ogs_pkbuf_t *smf_s5c_build_delete_session_response(
ogs_pkbuf_t *smf_s5c_build_modify_bearer_response( ogs_pkbuf_t *smf_s5c_build_modify_bearer_response(
uint8_t type, smf_sess_t *sess, uint8_t type, smf_sess_t *sess,
ogs_gtp2_modify_bearer_request_t *req) ogs_gtp2_modify_bearer_request_t *req, bool sgw_relocation)
{ {
int i;
ogs_gtp2_message_t gtp_message; ogs_gtp2_message_t gtp_message;
ogs_gtp2_modify_bearer_response_t *rsp = NULL; ogs_gtp2_modify_bearer_response_t *rsp = NULL;
ogs_gtp2_cause_t cause; ogs_gtp2_cause_t cause;
smf_ue_t *smf_ue = NULL;
smf_bearer_t *bearer = NULL;
ogs_assert(sess); ogs_assert(sess);
smf_ue = sess->smf_ue;
ogs_assert(smf_ue);
ogs_assert(req); ogs_assert(req);
rsp = &gtp_message.modify_bearer_response; rsp = &gtp_message.modify_bearer_response;
@ -263,19 +287,42 @@ ogs_pkbuf_t *smf_s5c_build_modify_bearer_response(
rsp->cause.data = &cause; rsp->cause.data = &cause;
rsp->cause.len = sizeof(cause); rsp->cause.len = sizeof(cause);
rsp->bearer_contexts_modified[0].presence = 1; if (sgw_relocation == true) {
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[0].cause.presence = 1; if (smf_ue->msisdn_len) {
rsp->bearer_contexts_modified[0].cause.len = sizeof(cause); rsp->msisdn.presence = 1;
rsp->bearer_contexts_modified[0].cause.data = &cause; rsp->msisdn.len = smf_ue->msisdn_len;
rsp->msisdn.data = smf_ue->msisdn;
}
for (i = 0; i < OGS_BEARER_PER_UE; i++) {
if (req->bearer_contexts_to_be_modified[i].presence == 0)
break;
if (req->bearer_contexts_to_be_modified[i].
eps_bearer_id.presence == 0) {
ogs_error("No EPS Bearer ID");
break;
}
bearer = smf_bearer_find_by_ebi(sess,
req->bearer_contexts_to_be_modified[i].eps_bearer_id.u8);
if (!bearer) {
ogs_error("Unknown EPS Bearer ID[%d]",
req->bearer_contexts_to_be_modified[i].eps_bearer_id.u8);
break;
}
rsp->bearer_contexts_modified[i].presence = 1;
rsp->bearer_contexts_modified[i].eps_bearer_id.presence = 1;
rsp->bearer_contexts_modified[i].eps_bearer_id.u8 =
req->bearer_contexts_to_be_modified[i].eps_bearer_id.u8;
rsp->bearer_contexts_modified[i].charging_id.presence = 1;
rsp->bearer_contexts_modified[i].charging_id.u32 =
sess->charging.id;
}
}
/* build */ /* build */
gtp_message.h.type = type; gtp_message.h.type = type;
@ -310,7 +357,7 @@ ogs_pkbuf_t *smf_s5c_build_create_bearer_request(
req = &gtp_message.create_bearer_request; req = &gtp_message.create_bearer_request;
memset(&gtp_message, 0, sizeof(ogs_gtp2_message_t)); memset(&gtp_message, 0, sizeof(ogs_gtp2_message_t));
/* Linked EBI */ /* Linked EBI */
req->linked_eps_bearer_id.presence = 1; req->linked_eps_bearer_id.presence = 1;
req->linked_eps_bearer_id.u8 = linked_bearer->ebi; req->linked_eps_bearer_id.u8 = linked_bearer->ebi;
@ -336,7 +383,7 @@ ogs_pkbuf_t *smf_s5c_build_create_bearer_request(
memset(&bearer_qos, 0, sizeof(bearer_qos)); memset(&bearer_qos, 0, sizeof(bearer_qos));
bearer_qos.qci = bearer->qos.index; bearer_qos.qci = bearer->qos.index;
bearer_qos.priority_level = bearer->qos.arp.priority_level; bearer_qos.priority_level = bearer->qos.arp.priority_level;
bearer_qos.pre_emption_capability = bearer_qos.pre_emption_capability =
bearer->qos.arp.pre_emption_capability; bearer->qos.arp.pre_emption_capability;
bearer_qos.pre_emption_vulnerability = bearer_qos.pre_emption_vulnerability =
bearer->qos.arp.pre_emption_vulnerability; bearer->qos.arp.pre_emption_vulnerability;
@ -383,7 +430,7 @@ ogs_pkbuf_t *smf_s5c_build_update_bearer_request(
sess->sgw_s5c_teid, sess->smf_n4_teid); sess->sgw_s5c_teid, sess->smf_n4_teid);
req = &gtp_message.update_bearer_request; req = &gtp_message.update_bearer_request;
memset(&gtp_message, 0, sizeof(ogs_gtp2_message_t)); memset(&gtp_message, 0, sizeof(ogs_gtp2_message_t));
/* Bearer EBI */ /* Bearer EBI */
req->bearer_contexts.presence = 1; req->bearer_contexts.presence = 1;
req->bearer_contexts.eps_bearer_id.presence = 1; req->bearer_contexts.eps_bearer_id.presence = 1;
@ -416,7 +463,7 @@ ogs_pkbuf_t *smf_s5c_build_update_bearer_request(
memset(&bearer_qos, 0, sizeof(bearer_qos)); memset(&bearer_qos, 0, sizeof(bearer_qos));
bearer_qos.qci = bearer->qos.index; bearer_qos.qci = bearer->qos.index;
bearer_qos.priority_level = bearer->qos.arp.priority_level; bearer_qos.priority_level = bearer->qos.arp.priority_level;
bearer_qos.pre_emption_capability = bearer_qos.pre_emption_capability =
bearer->qos.arp.pre_emption_capability; bearer->qos.arp.pre_emption_capability;
bearer_qos.pre_emption_vulnerability = bearer_qos.pre_emption_vulnerability =
bearer->qos.arp.pre_emption_vulnerability; bearer->qos.arp.pre_emption_vulnerability;
@ -463,7 +510,7 @@ ogs_pkbuf_t *smf_s5c_build_delete_bearer_request(
sess->sgw_s5c_teid, sess->smf_n4_teid); sess->sgw_s5c_teid, sess->smf_n4_teid);
req = &gtp_message.delete_bearer_request; req = &gtp_message.delete_bearer_request;
memset(&gtp_message, 0, sizeof(ogs_gtp2_message_t)); memset(&gtp_message, 0, sizeof(ogs_gtp2_message_t));
if (bearer->ebi == linked_bearer->ebi) { if (bearer->ebi == linked_bearer->ebi) {
/* /*
* << Linked EPS Bearer ID >> * << Linked EPS Bearer ID >>

View File

@ -33,7 +33,7 @@ ogs_pkbuf_t *smf_s5c_build_delete_session_response(
ogs_pkbuf_t *smf_s5c_build_modify_bearer_response( ogs_pkbuf_t *smf_s5c_build_modify_bearer_response(
uint8_t type, smf_sess_t *sess, uint8_t type, smf_sess_t *sess,
ogs_gtp2_modify_bearer_request_t *req); ogs_gtp2_modify_bearer_request_t *req, bool sgw_relocation);
ogs_pkbuf_t *smf_s5c_build_create_bearer_request( ogs_pkbuf_t *smf_s5c_build_create_bearer_request(
uint8_t type, smf_bearer_t *bearer, ogs_gtp2_tft_t *tft); uint8_t type, smf_bearer_t *bearer, ogs_gtp2_tft_t *tft);

View File

@ -52,7 +52,7 @@ uint8_t smf_s5c_handle_create_session_request(
char buf1[OGS_ADDRSTRLEN]; char buf1[OGS_ADDRSTRLEN];
char buf2[OGS_ADDRSTRLEN]; char buf2[OGS_ADDRSTRLEN];
int rv; int i, rv;
uint8_t cause_value = 0; uint8_t cause_value = 0;
ogs_gtp2_uli_t uli; ogs_gtp2_uli_t uli;
@ -82,15 +82,15 @@ uint8_t smf_s5c_handle_create_session_request(
ogs_error("No TEID"); ogs_error("No TEID");
cause_value = OGS_GTP2_CAUSE_MANDATORY_IE_MISSING; cause_value = OGS_GTP2_CAUSE_MANDATORY_IE_MISSING;
} }
if (req->bearer_contexts_to_be_created.presence == 0) { if (req->bearer_contexts_to_be_created[0].presence == 0) {
ogs_error("No Bearer"); ogs_error("No Bearer");
cause_value = OGS_GTP2_CAUSE_MANDATORY_IE_MISSING; cause_value = OGS_GTP2_CAUSE_MANDATORY_IE_MISSING;
} }
if (req->bearer_contexts_to_be_created.eps_bearer_id.presence == 0) { if (req->bearer_contexts_to_be_created[0].eps_bearer_id.presence == 0) {
ogs_error("No EPS Bearer ID"); ogs_error("No EPS Bearer ID");
cause_value = OGS_GTP2_CAUSE_MANDATORY_IE_MISSING; cause_value = OGS_GTP2_CAUSE_MANDATORY_IE_MISSING;
} }
if (req->bearer_contexts_to_be_created.bearer_level_qos.presence == 0) { if (req->bearer_contexts_to_be_created[0].bearer_level_qos.presence == 0) {
ogs_error("No EPS Bearer QoS"); ogs_error("No EPS Bearer QoS");
cause_value = OGS_GTP2_CAUSE_MANDATORY_IE_MISSING; cause_value = OGS_GTP2_CAUSE_MANDATORY_IE_MISSING;
} }
@ -118,7 +118,7 @@ uint8_t smf_s5c_handle_create_session_request(
} }
switch (sess->gtp_rat_type) { switch (sess->gtp_rat_type) {
case OGS_GTP2_RAT_TYPE_EUTRAN: case OGS_GTP2_RAT_TYPE_EUTRAN:
if (req->bearer_contexts_to_be_created. if (req->bearer_contexts_to_be_created[0].
s5_s8_u_sgw_f_teid.presence == 0) { s5_s8_u_sgw_f_teid.presence == 0) {
ogs_error("No S5/S8 SGW GTP-U TEID"); ogs_error("No S5/S8 SGW GTP-U TEID");
cause_value = OGS_GTP2_CAUSE_MANDATORY_IE_MISSING; cause_value = OGS_GTP2_CAUSE_MANDATORY_IE_MISSING;
@ -133,7 +133,7 @@ uint8_t smf_s5c_handle_create_session_request(
ogs_error("No S6b Diameter Peer"); ogs_error("No S6b Diameter Peer");
cause_value = OGS_GTP2_CAUSE_REMOTE_PEER_NOT_RESPONDING; cause_value = OGS_GTP2_CAUSE_REMOTE_PEER_NOT_RESPONDING;
} }
if (req->bearer_contexts_to_be_created. if (req->bearer_contexts_to_be_created[0].
s2b_u_epdg_f_teid_5.presence == 0) { s2b_u_epdg_f_teid_5.presence == 0) {
ogs_error("No S2b ePDG GTP-U TEID"); ogs_error("No S2b ePDG GTP-U TEID");
cause_value = OGS_GTP2_CAUSE_MANDATORY_IE_MISSING; cause_value = OGS_GTP2_CAUSE_MANDATORY_IE_MISSING;
@ -248,51 +248,68 @@ uint8_t smf_s5c_handle_create_session_request(
/* Remove all previous bearer */ /* Remove all previous bearer */
smf_bearer_remove_all(sess); smf_bearer_remove_all(sess);
/* Setup Default Bearer */ /* Setup Bearer */
bearer = smf_bearer_add(sess); for (i = 0; i < OGS_BEARER_PER_UE; i++) {
ogs_assert(bearer); if (req->bearer_contexts_to_be_created[i].presence == 0)
break;
if (req->bearer_contexts_to_be_created[i].eps_bearer_id.presence == 0) {
ogs_error("No EPS Bearer ID");
break;
}
if (req->bearer_contexts_to_be_created[i].
bearer_level_qos.presence == 0) {
ogs_error("No Bearer QoS");
break;
}
/* Set Bearer EBI */ decoded = ogs_gtp2_parse_bearer_qos(&bearer_qos,
bearer->ebi = req->bearer_contexts_to_be_created.eps_bearer_id.u8; &req->bearer_contexts_to_be_created[i].bearer_level_qos);
ogs_assert(decoded ==
req->bearer_contexts_to_be_created[i].bearer_level_qos.len);
switch (sess->gtp_rat_type) { bearer = smf_bearer_add(sess);
case OGS_GTP2_RAT_TYPE_EUTRAN: ogs_assert(bearer);
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; /* Set Bearer EBI */
case OGS_GTP2_RAT_TYPE_WLAN: bearer->ebi = req->bearer_contexts_to_be_created[i].eps_bearer_id.u8;
sgw_s5u_teid = req->bearer_contexts_to_be_created.
s2b_u_epdg_f_teid_5.data; switch (sess->gtp_rat_type) {
ogs_assert(sgw_s5u_teid); case OGS_GTP2_RAT_TYPE_EUTRAN:
bearer->sgw_s5u_teid = be32toh(sgw_s5u_teid->teid); sgw_s5u_teid = req->bearer_contexts_to_be_created[i].
rv = ogs_gtp2_f_teid_to_ip(sgw_s5u_teid, &bearer->sgw_s5u_ip); s5_s8_u_sgw_f_teid.data;
ogs_assert(rv == OGS_OK); ogs_assert(sgw_s5u_teid);
break; bearer->sgw_s5u_teid = be32toh(sgw_s5u_teid->teid);
default: rv = ogs_gtp2_f_teid_to_ip(sgw_s5u_teid, &bearer->sgw_s5u_ip);
ogs_error("Unknown RAT Type [%d]", sess->gtp_rat_type); ogs_assert(rv == OGS_OK);
ogs_assert_if_reached();
break;
case OGS_GTP2_RAT_TYPE_WLAN:
sgw_s5u_teid = req->bearer_contexts_to_be_created[i].
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);
/* Set Session QoS from Default Bearer Level QoS */
if (i == 0) {
sess->session.qos.index = bearer_qos.qci;
sess->session.qos.arp.priority_level = bearer_qos.priority_level;
sess->session.qos.arp.pre_emption_capability =
bearer_qos.pre_emption_capability;
sess->session.qos.arp.pre_emption_vulnerability =
bearer_qos.pre_emption_vulnerability;
}
} }
ogs_debug(" SGW_S5U_TEID[0x%x] PGW_S5U_TEID[0x%x]",
bearer->sgw_s5u_teid, bearer->pgw_s5u_teid);
/* Set Bearer QoS */
decoded = ogs_gtp2_parse_bearer_qos(&bearer_qos,
&req->bearer_contexts_to_be_created.bearer_level_qos);
ogs_assert(req->bearer_contexts_to_be_created.bearer_level_qos.len ==
decoded);
sess->session.qos.index = bearer_qos.qci;
sess->session.qos.arp.priority_level = bearer_qos.priority_level;
sess->session.qos.arp.pre_emption_capability =
bearer_qos.pre_emption_capability;
sess->session.qos.arp.pre_emption_vulnerability =
bearer_qos.pre_emption_vulnerability;
/* Set AMBR if available */ /* Set AMBR if available */
if (req->aggregate_maximum_bit_rate.presence) { if (req->aggregate_maximum_bit_rate.presence) {
/* /*
@ -324,6 +341,15 @@ uint8_t smf_s5c_handle_create_session_request(
OGS_TLV_STORE_DATA(&sess->gtp.ue_timezone, &req->ue_time_zone); OGS_TLV_STORE_DATA(&sess->gtp.ue_timezone, &req->ue_time_zone);
} }
/* Set MSISDN */
if (req->msisdn.presence && req->msisdn.len && req->msisdn.data) {
smf_ue->msisdn_len = req->msisdn.len;
memcpy(smf_ue->msisdn, req->msisdn.data,
ogs_min(smf_ue->msisdn_len, OGS_MAX_MSISDN_LEN));
ogs_buffer_to_bcd(smf_ue->msisdn,
smf_ue->msisdn_len, smf_ue->msisdn_bcd);
}
return OGS_GTP2_CAUSE_REQUEST_ACCEPTED; return OGS_GTP2_CAUSE_REQUEST_ACCEPTED;
} }
@ -356,17 +382,14 @@ uint8_t smf_s5c_handle_delete_session_request(
void smf_s5c_handle_modify_bearer_request( void smf_s5c_handle_modify_bearer_request(
smf_sess_t *sess, ogs_gtp_xact_t *xact, smf_sess_t *sess, ogs_gtp_xact_t *xact,
ogs_gtp2_modify_bearer_request_t *req) ogs_pkbuf_t *gtpbuf, ogs_gtp2_modify_bearer_request_t *req)
{ {
int rv; int rv, i;
uint8_t cause_value = 0; uint8_t cause_value = 0;
ogs_gtp2_indication_t *indication = NULL; uint64_t flags = 0;
ogs_gtp2_header_t h;
ogs_pkbuf_t *pkbuf = NULL;
smf_ue_t *smf_ue = NULL; smf_ue_t *smf_ue = NULL;
smf_sess_t *wlan_sess = NULL; smf_bearer_t *bearer = NULL;
ogs_debug("Modify Bearer Request"); ogs_debug("Modify Bearer Request");
@ -405,69 +428,109 @@ void smf_s5c_handle_modify_bearer_request(
rv = ogs_gtp2_f_teid_to_ip(sgw_s5c_teid, &sess->sgw_s5c_ip); rv = ogs_gtp2_f_teid_to_ip(sgw_s5c_teid, &sess->sgw_s5c_ip);
ogs_assert(rv == OGS_OK); ogs_assert(rv == OGS_OK);
OGS_SETUP_GTP_NODE(sess, xact->gnode);
ogs_debug(" SGW_S5C_TEID[0x%x] SMF_N4_TEID[0x%x]", ogs_debug(" SGW_S5C_TEID[0x%x] SMF_N4_TEID[0x%x]",
sess->sgw_s5c_teid, sess->smf_n4_teid); sess->sgw_s5c_teid, sess->smf_n4_teid);
} }
#if 0 /* TODO */ /* Check Modify Bearer */
switch (sess->gtp_rat_type) { ogs_list_init(&sess->qos_flow_to_modify_list);
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; for (i = 0; i < OGS_BEARER_PER_UE; i++) {
case OGS_GTP2_RAT_TYPE_WLAN: if (req->bearer_contexts_to_be_modified[i].presence == 0)
sgw_s5u_teid = req->bearer_contexts_to_be_created. break;
s2b_u_epdg_f_teid_5.data; if (req->bearer_contexts_to_be_modified[i].
ogs_assert(sgw_s5u_teid); eps_bearer_id.presence == 0) {
bearer->sgw_s5u_teid = be32toh(sgw_s5u_teid->teid); ogs_error("No EPS Bearer ID");
rv = ogs_gtp2_f_teid_to_ip(sgw_s5u_teid, &bearer->sgw_s5u_ip); break;
ogs_assert(rv == OGS_OK); }
break; /* EPS Bearer ID */
default: bearer = smf_bearer_find_by_ebi(sess,
ogs_error("Unknown RAT Type [%d]", sess->gtp_rat_type); req->bearer_contexts_to_be_modified[i].eps_bearer_id.u8);
ogs_assert_if_reached(); if (!bearer) {
ogs_error("No Bearer Context");
break;
}
if (req->bearer_contexts_to_be_modified[i].s4_u_sgsn_f_teid.presence) {
ogs_pfcp_far_t *far = NULL;
ogs_gtp2_f_teid_t *sgw_s5u_teid = NULL;
ogs_ip_t remote_ip;
ogs_ip_t zero_ip;
/* Data Plane(DL) : SGW-S5U */
sgw_s5u_teid = req->bearer_contexts_to_be_modified[i].
s4_u_sgsn_f_teid.data;
ogs_assert(sgw_s5u_teid);
bearer->sgw_s5u_teid = be32toh(sgw_s5u_teid->teid);
ogs_assert(OGS_OK ==
ogs_gtp2_f_teid_to_ip(sgw_s5u_teid, &remote_ip));
memset(&zero_ip, 0, sizeof(ogs_ip_t));
if (memcmp(&bearer->sgw_s5u_ip, &zero_ip, sizeof(ogs_ip_t)) != 0 &&
memcmp(&bearer->sgw_s5u_ip,
&remote_ip, sizeof(ogs_ip_t)) != 0) {
ogs_assert(sess->pfcp_node);
/* eNB IP is changed during handover */
if (sess->pfcp_node->up_function_features.empu) {
flags |= OGS_PFCP_MODIFY_END_MARKER;
} else {
ogs_error("UPF does not support End Marker");
}
}
memcpy(&bearer->sgw_s5u_ip, &remote_ip, sizeof(ogs_ip_t));
far = bearer->dl_far;
ogs_assert(far);
far->apply_action = OGS_PFCP_APPLY_ACTION_FORW;
ogs_assert(OGS_OK ==
ogs_pfcp_ip_to_outer_header_creation(
&bearer->sgw_s5u_ip,
&far->outer_header_creation,
&far->outer_header_creation_len));
far->outer_header_creation.teid = bearer->sgw_s5u_teid;
ogs_list_add(&sess->qos_flow_to_modify_list,
&bearer->to_modify_node);
ogs_debug(" SGW_S5U_TEID[0x%x] PGW_S5U_TEID[0x%x]",
bearer->sgw_s5u_teid, bearer->pgw_s5u_teid);
}
} }
ogs_debug(" SGW_S5U_TEID[0x%x] PGW_S5U_TEID[0x%x]", if (ogs_list_count(&sess->qos_flow_to_modify_list)) {
bearer->sgw_s5u_teid, bearer->pgw_s5u_teid);
#endif
memset(&h, 0, sizeof(ogs_gtp2_header_t)); /* Need to modify SGW-S5U */
h.type = OGS_GTP2_MODIFY_BEARER_RESPONSE_TYPE; rv = smf_epc_pfcp_send_session_modification_request(sess, xact, gtpbuf,
h.teid = sess->sgw_s5c_teid; flags|OGS_PFCP_MODIFY_DL_ONLY|OGS_PFCP_MODIFY_ACTIVATE,
OGS_NAS_PROCEDURE_TRANSACTION_IDENTITY_UNASSIGNED,
OGS_GTP2_CAUSE_UNDEFINED_VALUE);
ogs_assert(rv == OGS_OK);
pkbuf = smf_s5c_build_modify_bearer_response(h.type, sess, req); } else {
ogs_expect_or_return(pkbuf);
rv = ogs_gtp_xact_update_tx(xact, &h, pkbuf); /* Check if Handover from Non-3GPP to 3GPP */
ogs_expect_or_return(rv == OGS_OK); ogs_gtp2_indication_t *indication = NULL;
rv = ogs_gtp_xact_commit(xact);
ogs_expect(rv == OGS_OK);
if (req->indication_flags.presence &&
req->indication_flags.data && req->indication_flags.len) {
indication = req->indication_flags.data;
}
if (indication && indication->handover_indication) {
ogs_assert(sess->session.name);
wlan_sess = smf_sess_find_by_apn(
smf_ue, sess->session.name, OGS_GTP2_RAT_TYPE_WLAN);
ogs_expect_or_return(wlan_sess);
ogs_expect_or_return(ogs_list_first(&wlan_sess->bearer_list));
ogs_assert(OGS_OK == ogs_assert(OGS_OK ==
smf_epc_pfcp_send_session_modification_request( smf_gtp2_send_modify_bearer_response(sess, xact, req, false));
wlan_sess, NULL,
OGS_PFCP_MODIFY_DL_ONLY|OGS_PFCP_MODIFY_DEACTIVATE, if (req->indication_flags.presence &&
OGS_NAS_PROCEDURE_TRANSACTION_IDENTITY_UNASSIGNED, req->indication_flags.data && req->indication_flags.len) {
OGS_GTP2_CAUSE_ACCESS_CHANGED_FROM_NON_3GPP_TO_3GPP)); indication = req->indication_flags.data;
}
if (indication && indication->handover_indication) {
ogs_assert(OGS_OK == smf_epc_pfcp_send_deactivation(sess,
OGS_GTP2_CAUSE_ACCESS_CHANGED_FROM_NON_3GPP_TO_3GPP));
}
} }
} }

View File

@ -39,7 +39,7 @@ uint8_t smf_s5c_handle_delete_session_request(
ogs_gtp2_delete_session_request_t *req); ogs_gtp2_delete_session_request_t *req);
void smf_s5c_handle_modify_bearer_request( void smf_s5c_handle_modify_bearer_request(
smf_sess_t *sess, ogs_gtp_xact_t *xact, smf_sess_t *sess, ogs_gtp_xact_t *xact,
ogs_gtp2_modify_bearer_request_t *req); ogs_pkbuf_t *gtpbuf, ogs_gtp2_modify_bearer_request_t *req);
void smf_s5c_handle_create_bearer_response( void smf_s5c_handle_create_bearer_response(
smf_sess_t *sess, ogs_gtp_xact_t *xact, smf_sess_t *sess, ogs_gtp_xact_t *xact,
ogs_gtp2_create_bearer_response_t *req); ogs_gtp2_create_bearer_response_t *req);

View File

@ -103,17 +103,8 @@ void smf_state_operational(ogs_fsm_t *s, smf_event_t *e)
} }
e->gtp2_message = &gtp2_message; e->gtp2_message = &gtp2_message;
if (gtp2_message.h.teid != 0) { gnode = e->gnode;
sess = smf_sess_find_by_teid(gtp2_message.h.teid); ogs_assert(gnode);
}
if (sess) {
gnode = sess->gnode;
ogs_assert(gnode);
} else {
gnode = e->gnode;
ogs_assert(gnode);
}
rv = ogs_gtp_xact_receive(gnode, &gtp2_message.h, &gtp_xact); rv = ogs_gtp_xact_receive(gnode, &gtp2_message.h, &gtp_xact);
if (rv != OGS_OK) { if (rv != OGS_OK) {
@ -122,6 +113,10 @@ void smf_state_operational(ogs_fsm_t *s, smf_event_t *e)
} }
e->gtp_xact = gtp_xact; e->gtp_xact = gtp_xact;
if (gtp2_message.h.teid != 0) {
sess = smf_sess_find_by_teid(gtp2_message.h.teid);
}
switch(gtp2_message.h.type) { switch(gtp2_message.h.type) {
case OGS_GTP2_ECHO_REQUEST_TYPE: case OGS_GTP2_ECHO_REQUEST_TYPE:
smf_s5c_handle_echo_request(gtp_xact, &gtp2_message.echo_request); smf_s5c_handle_echo_request(gtp_xact, &gtp2_message.echo_request);
@ -157,7 +152,7 @@ void smf_state_operational(ogs_fsm_t *s, smf_event_t *e)
break; break;
case OGS_GTP2_MODIFY_BEARER_REQUEST_TYPE: case OGS_GTP2_MODIFY_BEARER_REQUEST_TYPE:
smf_s5c_handle_modify_bearer_request( smf_s5c_handle_modify_bearer_request(
sess, gtp_xact, &gtp2_message.modify_bearer_request); sess, gtp_xact, recvbuf, &gtp2_message.modify_bearer_request);
break; break;
case OGS_GTP2_CREATE_BEARER_RESPONSE_TYPE: case OGS_GTP2_CREATE_BEARER_RESPONSE_TYPE:
smf_s5c_handle_create_bearer_response( smf_s5c_handle_create_bearer_response(
@ -202,13 +197,8 @@ void smf_state_operational(ogs_fsm_t *s, smf_event_t *e)
sess = smf_sess_find_by_teid(gtp1_message.h.teid); sess = smf_sess_find_by_teid(gtp1_message.h.teid);
} }
if (sess) { gnode = e->gnode;
gnode = sess->gnode; ogs_assert(gnode);
ogs_assert(gnode);
} else {
gnode = e->gnode;
ogs_assert(gnode);
}
rv = ogs_gtp1_xact_receive(gnode, &gtp1_message.h, &gtp_xact); rv = ogs_gtp1_xact_receive(gnode, &gtp1_message.h, &gtp_xact);
if (rv != OGS_OK) { if (rv != OGS_OK) {
@ -380,6 +370,13 @@ void smf_state_operational(ogs_fsm_t *s, smf_event_t *e)
e->pfcp_message = &pfcp_message; e->pfcp_message = &pfcp_message;
e->pfcp_xact = pfcp_xact; e->pfcp_xact = pfcp_xact;
e->gtp2_message = NULL;
if (pfcp_xact->gtpbuf) {
rv = ogs_gtp2_parse_msg(&gtp2_message, pfcp_xact->gtpbuf);
e->gtp2_message = &gtp2_message;
}
ogs_fsm_dispatch(&pfcp_node->sm, e); ogs_fsm_dispatch(&pfcp_node->sm, e);
if (OGS_FSM_CHECK(&pfcp_node->sm, smf_pfcp_state_exception)) { if (OGS_FSM_CHECK(&pfcp_node->sm, smf_pfcp_state_exception)) {
ogs_error("PFCP state machine exception"); ogs_error("PFCP state machine exception");

View File

@ -179,7 +179,8 @@ static void _gtpv1_tun_recv_common_cb(
for (i = 0; i < pdr->num_of_urr; i++) for (i = 0; i < pdr->num_of_urr; i++)
upf_sess_urr_acc_add(sess, pdr->urr[i], recvbuf->len, false); upf_sess_urr_acc_add(sess, pdr->urr[i], recvbuf->len, false);
ogs_assert(true == ogs_pfcp_up_handle_pdr(pdr, recvbuf, &report)); ogs_assert(true == ogs_pfcp_up_handle_pdr(
pdr, OGS_GTPU_MSGTYPE_GPDU, recvbuf, &report));
if (report.type.downlink_data_report) { if (report.type.downlink_data_report) {
ogs_assert(pdr->sess); ogs_assert(pdr->sess);
@ -539,7 +540,8 @@ static void _gtpv1_u_recv_cb(short when, ogs_socket_t fd, void *data)
ogs_warn("ogs_tun_write() failed"); ogs_warn("ogs_tun_write() failed");
} else if (far->dst_if == OGS_PFCP_INTERFACE_ACCESS) { } else if (far->dst_if == OGS_PFCP_INTERFACE_ACCESS) {
ogs_assert(true == ogs_pfcp_up_handle_pdr(pdr, pkbuf, &report)); ogs_assert(true == ogs_pfcp_up_handle_pdr(
pdr, gtp_h->type, pkbuf, &report));
if (report.type.downlink_data_report) { if (report.type.downlink_data_report) {
ogs_error("Indirect Data Fowarding Buffered"); ogs_error("Indirect Data Fowarding Buffered");
@ -565,7 +567,8 @@ static void _gtpv1_u_recv_cb(short when, ogs_socket_t fd, void *data)
goto cleanup; goto cleanup;
} }
ogs_assert(true == ogs_pfcp_up_handle_pdr(pdr, pkbuf, &report)); ogs_assert(true == ogs_pfcp_up_handle_pdr(
pdr, gtp_h->type, pkbuf, &report));
ogs_assert(report.type.downlink_data_report == 0); ogs_assert(report.type.downlink_data_report == 0);
@ -755,7 +758,8 @@ static void upf_gtp_handle_multicast(ogs_pkbuf_t *recvbuf)
ogs_list_for_each(&sess->pfcp.pdr_list, pdr) { ogs_list_for_each(&sess->pfcp.pdr_list, pdr) {
if (pdr->src_if == OGS_PFCP_INTERFACE_CORE) { if (pdr->src_if == OGS_PFCP_INTERFACE_CORE) {
ogs_assert(true == ogs_assert(true ==
ogs_pfcp_up_handle_pdr(pdr, recvbuf, &report)); ogs_pfcp_up_handle_pdr(pdr,
OGS_GTPU_MSGTYPE_GPDU, recvbuf, &report));
break; break;
} }
} }

View File

@ -43,7 +43,7 @@ int app_initialize(const char *const argv[])
for (i = 0; argv[i]; i++) { for (i = 0; argv[i]; i++) {
if (strcmp("-c", argv[i]) == 0) { if (strcmp("-c", argv[i]) == 0) {
user_config = true; user_config = true;
} }
argv_out[i] = argv[i]; argv_out[i] = argv[i];
} }

View File

@ -400,6 +400,78 @@ void tests1ap_handle_handover_request(
test_ue->mme_ue_s1ap_id = *MME_UE_S1AP_ID; test_ue->mme_ue_s1ap_id = *MME_UE_S1AP_ID;
} }
void tests1ap_handle_path_switch_request_ack(
test_ue_t *test_ue, ogs_s1ap_message_t *message)
{
int rv, i;
char buf[OGS_ADDRSTRLEN];
test_sess_t *sess = NULL;
test_bearer_t *bearer = NULL;
S1AP_S1AP_PDU_t pdu;
S1AP_SuccessfulOutcome_t *successfulOutcome = NULL;
S1AP_PathSwitchRequestAcknowledge_t *PathSwitchRequestAcknowledge = NULL;
S1AP_PathSwitchRequestAcknowledgeIEs_t *ie = NULL;
S1AP_MME_UE_S1AP_ID_t *MME_UE_S1AP_ID = NULL;
S1AP_ENB_UE_S1AP_ID_t *ENB_UE_S1AP_ID = NULL;
S1AP_E_RABToBeSwitchedULList_t *E_RABToBeSwitchedULList = NULL;
ogs_assert(test_ue);
ogs_assert(message);
successfulOutcome = message->choice.successfulOutcome;
ogs_assert(successfulOutcome);
PathSwitchRequestAcknowledge = &successfulOutcome->value.choice.PathSwitchRequestAcknowledge;
ogs_assert(PathSwitchRequestAcknowledge);
for (i = 0; i < PathSwitchRequestAcknowledge->protocolIEs.list.count; i++) {
ie = PathSwitchRequestAcknowledge->protocolIEs.list.array[i];
switch (ie->id) {
case S1AP_ProtocolIE_ID_id_MME_UE_S1AP_ID:
MME_UE_S1AP_ID = &ie->value.choice.MME_UE_S1AP_ID;
break;
case S1AP_ProtocolIE_ID_id_eNB_UE_S1AP_ID:
ENB_UE_S1AP_ID = &ie->value.choice.ENB_UE_S1AP_ID;
break;
case S1AP_ProtocolIE_ID_id_E_RABToBeSwitchedULList:
E_RABToBeSwitchedULList =
&ie->value.choice.E_RABToBeSwitchedULList;
break;
default:
break;
}
}
if (MME_UE_S1AP_ID)
test_ue->mme_ue_s1ap_id = *MME_UE_S1AP_ID;
if (ENB_UE_S1AP_ID)
test_ue->enb_ue_s1ap_id = *ENB_UE_S1AP_ID;
if (E_RABToBeSwitchedULList) {
for (i = 0; i < E_RABToBeSwitchedULList->list.count; i++) {
S1AP_E_RABToBeSwitchedULItemIEs_t *ie2 = NULL;
S1AP_E_RABToBeSwitchedULItem_t *e_rab = NULL;
ie2 = (S1AP_E_RABToBeSwitchedULItemIEs_t *)
E_RABToBeSwitchedULList->list.array[i];
ogs_assert(ie2);
e_rab = &ie2->value.choice.E_RABToBeSwitchedULItem;
bearer = test_bearer_find_by_ue_ebi(test_ue, e_rab->e_RAB_ID);
ogs_assert(bearer);
memcpy(&bearer->sgw_s1u_teid, e_rab->gTP_TEID.buf,
sizeof(bearer->sgw_s1u_teid));
bearer->sgw_s1u_teid = be32toh(bearer->sgw_s1u_teid);
rv = ogs_asn_BIT_STRING_to_ip(
&e_rab->transportLayerAddress, &bearer->sgw_s1u_ip);
ogs_assert(rv == OGS_OK);
}
}
}
void tests1ap_handle_handover_command( void tests1ap_handle_handover_command(
test_ue_t *test_ue, ogs_s1ap_message_t *message) test_ue_t *test_ue, ogs_s1ap_message_t *message)
{ {

View File

@ -38,6 +38,8 @@ void tests1ap_handle_e_rab_modify_request(
void tests1ap_handle_e_rab_release_command( void tests1ap_handle_e_rab_release_command(
test_ue_t *test_ue, ogs_s1ap_message_t *message); test_ue_t *test_ue, ogs_s1ap_message_t *message);
void tests1ap_handle_path_switch_request_ack(
test_ue_t *test_ue, ogs_s1ap_message_t *message);
void tests1ap_handle_handover_request( void tests1ap_handle_handover_request(
test_ue_t *test_ue, ogs_s1ap_message_t *message); test_ue_t *test_ue, ogs_s1ap_message_t *message);
void tests1ap_handle_handover_command( void tests1ap_handle_handover_command(

View File

@ -97,6 +97,7 @@ void tests1ap_recv(test_ue_t *test_ue, ogs_pkbuf_t *pkbuf)
tests1ap_handle_s1_setup_response(pdu); tests1ap_handle_s1_setup_response(pdu);
break; break;
case S1AP_ProcedureCode_id_PathSwitchRequest: case S1AP_ProcedureCode_id_PathSwitchRequest:
tests1ap_handle_path_switch_request_ack(test_ue, pdu);
break; break;
case S1AP_ProcedureCode_id_HandoverPreparation: case S1AP_ProcedureCode_id_HandoverPreparation:
tests1ap_handle_handover_command(test_ue, pdu); tests1ap_handle_handover_command(test_ue, pdu);

View File

@ -27,20 +27,21 @@ ogs_pkbuf_t *test_s2b_build_create_session_request(
test_ue_t *test_ue = NULL; test_ue_t *test_ue = NULL;
test_bearer_t *bearer = NULL; test_bearer_t *bearer = NULL;
ogs_gtp2_message_t gtp_message; 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;
uint8_t msisdn_buf[OGS_MAX_MSISDN_LEN]; uint8_t msisdn_buf[OGS_MAX_MSISDN_LEN];
int msisdn_len; int msisdn_len;
ogs_gtp2_uli_t uli; ogs_gtp2_uli_t uli;
char uli_buf[OGS_GTP2_MAX_ULI_LEN]; char uli_buf[OGS_GTP2_MAX_ULI_LEN];
ogs_gtp2_f_teid_t test_s2b_c_teid, test_s2b_u_teid; ogs_gtp2_f_teid_t test_s2b_c_teid, test_s2b_u_teid[OGS_BEARER_PER_UE];
int len; int len, test_s2b_u_len;
ogs_paa_t paa; ogs_paa_t paa;
ogs_gtp2_ambr_t ambr; ogs_gtp2_ambr_t ambr;
ogs_gtp2_bearer_qos_t bearer_qos; ogs_gtp2_bearer_qos_t bearer_qos;
char bearer_qos_buf[GTP2_BEARER_QOS_LEN]; char bearer_qos_buf[OGS_BEARER_PER_UE][GTP2_BEARER_QOS_LEN];
char apn[OGS_MAX_APN_LEN+1]; char apn[OGS_MAX_APN_LEN+1];
ogs_gtp2_indication_t indication; ogs_gtp2_indication_t indication;
@ -84,7 +85,7 @@ ogs_pkbuf_t *test_s2b_build_create_session_request(
ogs_nas_from_plmn_id(&uli.e_cgi.nas_plmn_id, &test_ue->e_cgi.plmn_id); ogs_nas_from_plmn_id(&uli.e_cgi.nas_plmn_id, &test_ue->e_cgi.plmn_id);
uli.e_cgi.cell_id = test_ue->e_cgi.cell_id; uli.e_cgi.cell_id = test_ue->e_cgi.cell_id;
req->user_location_information.presence = 1; 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); uli_buf, OGS_GTP2_MAX_ULI_LEN);
req->serving_network.presence = 1; req->serving_network.presence = 1;
@ -111,7 +112,7 @@ ogs_pkbuf_t *test_s2b_build_create_session_request(
req->access_point_name.data = apn; req->access_point_name.data = apn;
req->selection_mode.presence = 1; req->selection_mode.presence = 1;
req->selection_mode.u8 = req->selection_mode.u8 =
OGS_GTP2_SELECTION_MODE_MS_OR_NETWORK_PROVIDED_APN; OGS_GTP2_SELECTION_MODE_MS_OR_NETWORK_PROVIDED_APN;
memset(&paa, 0, sizeof(paa)); memset(&paa, 0, sizeof(paa));
@ -128,31 +129,40 @@ ogs_pkbuf_t *test_s2b_build_create_session_request(
req->aggregate_maximum_bit_rate.data = &ambr; req->aggregate_maximum_bit_rate.data = &ambr;
req->aggregate_maximum_bit_rate.len = sizeof(ambr); req->aggregate_maximum_bit_rate.len = sizeof(ambr);
req->bearer_contexts_to_be_created.presence = 1; int i = 0;
req->bearer_contexts_to_be_created.eps_bearer_id.presence = 1; ogs_list_for_each(&sess->bearer_list, bearer) {
req->bearer_contexts_to_be_created.eps_bearer_id.u8 = bearer->ebi; ogs_assert(i < OGS_BEARER_PER_UE);
memset(&test_s2b_u_teid, 0, sizeof(ogs_gtp2_f_teid_t)); req->bearer_contexts_to_be_created[i].presence = 1;
test_s2b_u_teid.teid = htobe32(bearer->enb_s1u_teid); req->bearer_contexts_to_be_created[i].eps_bearer_id.presence = 1;
test_s2b_u_teid.interface_type = OGS_GTP2_F_TEID_S2B_U_EPDG_GTP_U; req->bearer_contexts_to_be_created[i].eps_bearer_id.u8 = bearer->ebi;
ogs_assert(sess->gnode->sock);
rv = ogs_gtp2_sockaddr_to_f_teid(
&sess->gnode->sock->local_addr, NULL, &test_s2b_u_teid, &len);
req->bearer_contexts_to_be_created.s2b_u_epdg_f_teid_5.presence = 1; memset(&test_s2b_u_teid[i], 0, sizeof(ogs_gtp2_f_teid_t));
req->bearer_contexts_to_be_created.s2b_u_epdg_f_teid_5.data = test_s2b_u_teid[i].teid = htobe32(bearer->enb_s1u_teid);
&test_s2b_u_teid; test_s2b_u_teid[i].interface_type = OGS_GTP2_F_TEID_S2B_U_EPDG_GTP_U;
req->bearer_contexts_to_be_created.s2b_u_epdg_f_teid_5.len = len; ogs_assert(sess->gnode->sock);
rv = ogs_gtp2_sockaddr_to_f_teid(
&sess->gnode->sock->local_addr, NULL,
&test_s2b_u_teid[i], &test_s2b_u_len);
memset(&bearer_qos, 0, sizeof(bearer_qos)); req->bearer_contexts_to_be_created[i].s2b_u_epdg_f_teid_5.presence = 1;
bearer_qos.qci = 8; req->bearer_contexts_to_be_created[i].s2b_u_epdg_f_teid_5.data =
bearer_qos.priority_level = 1; &test_s2b_u_teid[i];
bearer_qos.pre_emption_capability = 0; req->bearer_contexts_to_be_created[i].s2b_u_epdg_f_teid_5.len =
bearer_qos.pre_emption_vulnerability = 0; test_s2b_u_len;
req->bearer_contexts_to_be_created.bearer_level_qos.presence = 1;
ogs_gtp2_build_bearer_qos( memset(&bearer_qos, 0, sizeof(bearer_qos));
&req->bearer_contexts_to_be_created.bearer_level_qos, bearer_qos.qci = 8;
&bearer_qos, bearer_qos_buf, GTP2_BEARER_QOS_LEN); bearer_qos.priority_level = 1;
bearer_qos.pre_emption_capability = 0;
bearer_qos.pre_emption_vulnerability = 0;
req->bearer_contexts_to_be_created[i].bearer_level_qos.presence = 1;
ogs_gtp2_build_bearer_qos(
&req->bearer_contexts_to_be_created[i].bearer_level_qos,
&bearer_qos, bearer_qos_buf[i], GTP2_BEARER_QOS_LEN);
i++;
}
req->recovery.presence = 1; req->recovery.presence = 1;
req->recovery.u8 = 66; req->recovery.u8 = 66;

View File

@ -24,7 +24,7 @@ void test_s2b_handle_create_session_response(
ogs_gtp_xact_t *xact, test_sess_t *sess, ogs_gtp_xact_t *xact, test_sess_t *sess,
ogs_gtp2_create_session_response_t *rsp) ogs_gtp2_create_session_response_t *rsp)
{ {
int rv; int rv, i;
uint8_t cause_value; uint8_t cause_value;
test_bearer_t *bearer = NULL; test_bearer_t *bearer = NULL;
@ -58,18 +58,6 @@ void test_s2b_handle_create_session_response(
ogs_error("No S5/S8 TEID"); ogs_error("No S5/S8 TEID");
return; return;
} }
if (rsp->bearer_contexts_created.presence == 0) {
ogs_error("No Bearer Context");
return;
}
if (rsp->bearer_contexts_created.eps_bearer_id.presence == 0) {
ogs_error("No EBI");
return;
}
if (rsp->bearer_contexts_created.s12_rnc_f_teid.presence == 0) {
ogs_error("No S1U TEID");
return;
}
if (rsp->pdn_address_allocation.presence == 0) { if (rsp->pdn_address_allocation.presence == 0) {
ogs_error("No PDN Address Allocation"); ogs_error("No PDN Address Allocation");
return; return;
@ -78,22 +66,37 @@ void test_s2b_handle_create_session_response(
ogs_expect( ogs_expect(
rsp->pdn_address_allocation.data && rsp->pdn_address_allocation.len); rsp->pdn_address_allocation.data && rsp->pdn_address_allocation.len);
bearer = test_bearer_find_by_sess_ebi( for (i = 0; i < OGS_BEARER_PER_UE; i++) {
sess, rsp->bearer_contexts_created.eps_bearer_id.u8); if (rsp->bearer_contexts_created[i].presence == 0) {
ogs_assert(bearer); break;
}
if (rsp->bearer_contexts_created[i].eps_bearer_id.presence == 0) {
ogs_error("No EBI");
break;
}
if (rsp->bearer_contexts_created[i].s12_rnc_f_teid.presence == 0) {
ogs_error("No S1U TEID");
break;
}
bearer = test_bearer_find_by_sess_ebi(
sess, rsp->bearer_contexts_created[i].eps_bearer_id.u8);
ogs_assert(bearer);
smf_s2b_u_teid = rsp->bearer_contexts_created[i].s12_rnc_f_teid.data;
ogs_assert(smf_s2b_u_teid);
bearer->sgw_s1u_teid = be32toh(smf_s2b_u_teid->teid);
ogs_assert(OGS_OK ==
ogs_gtp2_f_teid_to_ip(smf_s2b_u_teid, &bearer->sgw_s1u_ip));
}
smf_s2b_c_teid = rsp->pgw_s5_s8__s2a_s2b_f_teid_for_pmip_based_interface_or_for_gtp_based_control_plane_interface.data; smf_s2b_c_teid = rsp->pgw_s5_s8__s2a_s2b_f_teid_for_pmip_based_interface_or_for_gtp_based_control_plane_interface.data;
ogs_assert(smf_s2b_c_teid); ogs_assert(smf_s2b_c_teid);
sess->smf_s2b_c_teid = be32toh(smf_s2b_c_teid->teid); sess->smf_s2b_c_teid = be32toh(smf_s2b_c_teid->teid);
smf_s2b_u_teid = rsp->bearer_contexts_created.s12_rnc_f_teid.data;
ogs_assert(smf_s2b_u_teid);
bearer->sgw_s1u_teid = be32toh(smf_s2b_u_teid->teid);
ogs_assert(OGS_OK ==
ogs_gtp2_f_teid_to_ip(smf_s2b_u_teid, &bearer->sgw_s1u_ip));
memcpy(&paa, memcpy(&paa,
rsp->pdn_address_allocation.data, rsp->pdn_address_allocation.len); rsp->pdn_address_allocation.data, rsp->pdn_address_allocation.len);

View File

@ -153,18 +153,18 @@ static void gtp_message_test1(abts_case *tc, void *data)
req.protocol_configuration_options.len = req.protocol_configuration_options.len =
ogs_pco_build(pcobuf, OGS_MAX_PCO_LEN, &pco); ogs_pco_build(pcobuf, OGS_MAX_PCO_LEN, &pco);
req.bearer_contexts_to_be_created.presence = 1; req.bearer_contexts_to_be_created[0].presence = 1;
req.bearer_contexts_to_be_created.eps_bearer_id.presence = 1; req.bearer_contexts_to_be_created[0].eps_bearer_id.presence = 1;
req.bearer_contexts_to_be_created.eps_bearer_id.u8 = 5; req.bearer_contexts_to_be_created[0].eps_bearer_id.u8 = 5;
memset(&bearer_qos, 0, sizeof(bearer_qos)); memset(&bearer_qos, 0, sizeof(bearer_qos));
bearer_qos.pre_emption_vulnerability = 1; bearer_qos.pre_emption_vulnerability = 1;
bearer_qos.priority_level = 1; bearer_qos.priority_level = 1;
bearer_qos.pre_emption_capability = 1; bearer_qos.pre_emption_capability = 1;
bearer_qos.qci = 5; bearer_qos.qci = 5;
req.bearer_contexts_to_be_created.bearer_level_qos.presence = 1; req.bearer_contexts_to_be_created[0].bearer_level_qos.presence = 1;
size = ogs_gtp2_build_bearer_qos( size = ogs_gtp2_build_bearer_qos(
&req.bearer_contexts_to_be_created.bearer_level_qos, &req.bearer_contexts_to_be_created[0].bearer_level_qos,
&bearer_qos, bearer_qos_buf, GTP2_BEARER_QOS_LEN); &bearer_qos, bearer_qos_buf, GTP2_BEARER_QOS_LEN);
memset(&ue_timezone, 0, sizeof(ue_timezone)); memset(&ue_timezone, 0, sizeof(ue_timezone));
@ -259,38 +259,43 @@ static void gtp_message_test1(abts_case *tc, void *data)
OGS_PCO_ID_IP_ADDRESS_ALLOCATION_VIA_NAS_SIGNALLING, OGS_PCO_ID_IP_ADDRESS_ALLOCATION_VIA_NAS_SIGNALLING,
pco.ids[2].id); pco.ids[2].id);
ABTS_INT_EQUAL(tc, 0, pco.ids[2].len); ABTS_INT_EQUAL(tc, 0, pco.ids[2].len);
ABTS_INT_EQUAL(tc, 1, req.bearer_contexts_to_be_created.presence); ABTS_INT_EQUAL(tc, 1, req.bearer_contexts_to_be_created[0].presence);
ABTS_INT_EQUAL(tc, 0, req.bearer_contexts_to_be_created[1].presence);
ABTS_INT_EQUAL(tc, 1, req. ABTS_INT_EQUAL(tc, 1, req.
bearer_contexts_to_be_created.eps_bearer_id.presence); bearer_contexts_to_be_created[0].eps_bearer_id.presence);
ABTS_INT_EQUAL(tc, 0, req.
bearer_contexts_to_be_created[1].eps_bearer_id.presence);
ABTS_INT_EQUAL(tc, 0x05, ABTS_INT_EQUAL(tc, 0x05,
req.bearer_contexts_to_be_created.eps_bearer_id.u8); req.bearer_contexts_to_be_created[0].eps_bearer_id.u8);
ABTS_INT_EQUAL(tc, 0, req. ABTS_INT_EQUAL(tc, 0, req.
bearer_contexts_to_be_created.tft.presence); bearer_contexts_to_be_created[0].tft.presence);
ABTS_INT_EQUAL(tc, 0, req. ABTS_INT_EQUAL(tc, 0, req.
bearer_contexts_to_be_created.s1_u_enodeb_f_teid.presence); bearer_contexts_to_be_created[0].s1_u_enodeb_f_teid.presence);
ABTS_INT_EQUAL(tc, 0, req. ABTS_INT_EQUAL(tc, 0, req.
bearer_contexts_to_be_created.s2b_u_epdg_f_teid_5.presence); bearer_contexts_to_be_created[0].s2b_u_epdg_f_teid_5.presence);
ABTS_INT_EQUAL(tc, 0, req. ABTS_INT_EQUAL(tc, 0, req.
bearer_contexts_to_be_created.s2a_u_twan_f_teid_6.presence); bearer_contexts_to_be_created[0].s2a_u_twan_f_teid_6.presence);
ABTS_INT_EQUAL(tc, 1, req. ABTS_INT_EQUAL(tc, 1, req.
bearer_contexts_to_be_created.bearer_level_qos.presence); bearer_contexts_to_be_created[0].bearer_level_qos.presence);
ABTS_INT_EQUAL(tc, 0, req.
bearer_contexts_to_be_created[1].bearer_level_qos.presence);
ABTS_INT_EQUAL(tc, 22, ABTS_INT_EQUAL(tc, 22,
req.bearer_contexts_to_be_created.bearer_level_qos.len); req.bearer_contexts_to_be_created[0].bearer_level_qos.len);
size = ogs_gtp2_parse_bearer_qos(&bearer_qos, size = ogs_gtp2_parse_bearer_qos(&bearer_qos,
&req.bearer_contexts_to_be_created.bearer_level_qos); &req.bearer_contexts_to_be_created[0].bearer_level_qos);
ABTS_INT_EQUAL(tc, 22, size); ABTS_INT_EQUAL(tc, 22, size);
ABTS_INT_EQUAL(tc, 1, bearer_qos.pre_emption_vulnerability); ABTS_INT_EQUAL(tc, 1, bearer_qos.pre_emption_vulnerability);
ABTS_INT_EQUAL(tc, 1, bearer_qos.priority_level); ABTS_INT_EQUAL(tc, 1, bearer_qos.priority_level);
ABTS_INT_EQUAL(tc, 1, bearer_qos.pre_emption_capability); ABTS_INT_EQUAL(tc, 1, bearer_qos.pre_emption_capability);
ABTS_INT_EQUAL(tc, 5, bearer_qos.qci); ABTS_INT_EQUAL(tc, 5, bearer_qos.qci);
ABTS_INT_EQUAL(tc, 0, req. ABTS_INT_EQUAL(tc, 0, req.
bearer_contexts_to_be_created.s11_u_mme_f_teid.presence); bearer_contexts_to_be_created[0].s11_u_mme_f_teid.presence);
ABTS_INT_EQUAL(tc, 0, req. ABTS_INT_EQUAL(tc, 0, req.
bearer_contexts_to_be_created.cause.presence); bearer_contexts_to_be_created[0].cause.presence);
ABTS_INT_EQUAL(tc, 0, req. ABTS_INT_EQUAL(tc, 0, req.
bearer_contexts_to_be_created.transaction_identifier.presence); bearer_contexts_to_be_created[0].transaction_identifier.presence);
ABTS_INT_EQUAL(tc, 0, req. ABTS_INT_EQUAL(tc, 0, req.
bearer_contexts_to_be_created.packet_flow_id.presence); bearer_contexts_to_be_created[0].packet_flow_id.presence);
ABTS_INT_EQUAL(tc, 0, req.bearer_contexts_to_be_removed.presence); ABTS_INT_EQUAL(tc, 0, req.bearer_contexts_to_be_removed.presence);
ABTS_INT_EQUAL(tc, 0, req.recovery.presence); ABTS_INT_EQUAL(tc, 0, req.recovery.presence);
ABTS_INT_EQUAL(tc, 0, req.mme_fq_csid.presence); ABTS_INT_EQUAL(tc, 0, req.mme_fq_csid.presence);