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
* 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
******************************************************************************/
@ -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_pco_0,
&ogs_gtp2_tlv_desc_bearer_context_0,
&ogs_tlv_desc_more8,
&ogs_gtp2_tlv_desc_bearer_context_1,
&ogs_gtp2_tlv_desc_trace_information_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_pco_0,
&ogs_gtp2_tlv_desc_bearer_context_0,
&ogs_tlv_desc_more8,
&ogs_gtp2_tlv_desc_bearer_context_1,
&ogs_gtp2_tlv_desc_recovery_0,
&ogs_gtp2_tlv_desc_fqdn_0,

View File

@ -20,7 +20,7 @@
/*******************************************************************************
* This file had been created by gtp-tlv.py script v0.1.0
* Please do not modify this file but regenerate it via script.
* Created on: 2022-04-22 03:19:22.024556 by acetcom
* Created on: 2022-05-01 15:20:04.456902 by acetcom
* 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_twmi_t trusted_wlan_mode_indication;
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_trace_information_t trace_information;
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_ebi_t linked_eps_bearer_id;
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_recovery_t recovery;
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_ambr_t aggregate_maximum_bit_rate;
ogs_gtp2_tlv_delay_value_t delay_downlink_packet_notification_request;
ogs_gtp2_tlv_bearer_context_t bearer_contexts_to_be_modified[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_recovery_t recovery;
ogs_gtp2_tlv_ue_time_zone_t ue_time_zone;
@ -884,7 +884,7 @@ typedef struct ogs_gtp2_modify_bearer_response_s {
ogs_gtp2_tlv_ebi_t linked_eps_bearer_id;
ogs_gtp2_tlv_apn_restriction_t apn_restriction;
ogs_gtp2_tlv_pco_t protocol_configuration_options;
ogs_gtp2_tlv_bearer_context_t bearer_contexts_modified[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_change_reporting_action_t change_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_indication_t indication_flags;
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_create_indirect_data_forwarding_tunnel_request_t;
typedef struct ogs_gtp2_create_indirect_data_forwarding_tunnel_response_s {
ogs_gtp2_tlv_cause_t cause;
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_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;
break;
default:
ogs_fatal("Invalid message[%d]", type);
ogs_assert_if_reached();
return;
}

View File

@ -580,9 +580,9 @@ for (k, v) in sorted_msg_list:
if "ies" in msg_list[k]:
f.write("typedef struct ogs_gtp2_" + v_lower(k) + "_s {\n")
for ies in msg_list[k]["ies"]:
if ((k == 'Create Indirect Data Forwarding Tunnel Request' or k == 'Create Indirect Data Forwarding Tunnel Response') and ies["ie_value"] == 'Bearer Contexts') 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 " + \
v_lower(ies["ie_value"]) + "[8];\n")
v_lower(ies["ie_value"]) + "[OGS_BEARER_PER_UE];\n")
else:
f.write(" ogs_gtp2_tlv_" + v_lower(ies["ie_type"]) + "_t " + \
v_lower(ies["ie_value"]) + ";\n")
@ -671,7 +671,7 @@ for (k, v) in sorted_msg_list:
f.write(" 0, 0, 0, 0, {\n")
for ies in msg_list[k]["ies"]:
f.write(" &ogs_gtp2_tlv_desc_%s_%s,\n" % (v_lower(ies["ie_type"]), v_lower(ies["instance"])))
if ((k == 'Create Indirect Data Forwarding Tunnel Request' or k == 'Create Indirect Data Forwarding Tunnel Response') and ies["ie_value"] == 'Bearer Contexts') 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(" NULL,\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_HANDLE_PDN_CONNECTIVITY_REQUEST 5
#define OGS_GTP_DELETE_UE_CONTEXT_REMOVE 6
#define OGS_GTP_DELETE_IN_PATH_SWITCH_REQUEST 7
int delete_action;
#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;
ogs_lnode_t to_create_node;
ogs_lnode_t to_modify_node;
struct {
struct {

View File

@ -170,7 +170,7 @@ bool ogs_pfcp_up_handle_association_setup_response(
}
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_far_t *far = NULL;
@ -178,6 +178,7 @@ bool ogs_pfcp_up_handle_pdr(
bool buffering;
ogs_assert(recvbuf);
ogs_assert(type);
ogs_assert(pdr);
ogs_assert(report);
@ -198,7 +199,7 @@ bool ogs_pfcp_up_handle_pdr(
if (far->apply_action & OGS_PFCP_APPLY_ACTION_FORW) {
/* 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) {

View File

@ -46,7 +46,7 @@ bool ogs_pfcp_up_handle_association_setup_response(
ogs_pfcp_association_setup_response_t *req);
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);
bool ogs_pfcp_up_handle_error_indication(
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;
}
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_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_assert(pdr);
ogs_assert(type);
ogs_assert(sendbuf);
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(&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;
if (pdr->qer && 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->apply_action & OGS_PFCP_APPLY_ACTION_FORW) {
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;
}

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,
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);
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);
#define SESSION_SYNC_DONE(__aMF, __sTATE) \
#define AMF_SESSION_SYNC_DONE(__aMF, __sTATE) \
(amf_sess_xact_state_count(__aMF, __sTATE) == 0)
int amf_sess_xact_count(amf_ue_t *amf_ue);
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,
ogs_pkbuf_copy(n2smbuf));
if (SESSION_SYNC_DONE(amf_ue,
if (AMF_SESSION_SYNC_DONE(amf_ue,
AMF_RELEASE_SM_CONTEXT_REGISTRATION_ACCEPT) &&
SESSION_SYNC_DONE(amf_ue,
AMF_SESSION_SYNC_DONE(amf_ue,
AMF_UPDATE_SM_CONTEXT_REGISTRATION_REQUEST)) {
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,
ogs_pkbuf_copy(n2smbuf));
if (SESSION_SYNC_DONE(amf_ue,
if (AMF_SESSION_SYNC_DONE(amf_ue,
AMF_RELEASE_SM_CONTEXT_SERVICE_ACCEPT) &&
SESSION_SYNC_DONE(amf_ue,
AMF_SESSION_SYNC_DONE(amf_ue,
AMF_UPDATE_SM_CONTEXT_SERVICE_REQUEST)) {
ogs_assert(OGS_OK ==
nas_5gs_send_service_accept(amf_ue));
@ -261,7 +261,7 @@ int amf_nsmf_pdusession_handle_update_sm_context(
AMF_SESS_STORE_N2_TRANSFER(
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)) {
ogs_assert(OGS_OK ==
ngap_send_handover_request(amf_ue));
@ -367,7 +367,7 @@ int amf_nsmf_pdusession_handle_update_sm_context(
sess, path_switch_request_ack,
ogs_pkbuf_copy(n2smbuf));
if (SESSION_SYNC_DONE(amf_ue, state)) {
if (AMF_SESSION_SYNC_DONE(amf_ue, state)) {
ogs_assert(OGS_OK ==
ngap_send_path_switch_ack(sess));
@ -390,7 +390,7 @@ int amf_nsmf_pdusession_handle_update_sm_context(
AMF_SESS_STORE_N2_TRANSFER(
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 ==
ngap_send_handover_command(amf_ue));
@ -497,7 +497,7 @@ int amf_nsmf_pdusession_handle_update_sm_context(
* 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(OGS_OK ==
@ -573,7 +573,7 @@ int amf_nsmf_pdusession_handle_update_sm_context(
} 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;
source_ue = amf_ue->ran_ue;
@ -593,7 +593,7 @@ int amf_nsmf_pdusession_handle_update_sm_context(
/* Nothing to do */
} 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);
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) {
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);
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) {
if (SESSION_SYNC_DONE(amf_ue, state)) {
if (AMF_SESSION_SYNC_DONE(amf_ue, state)) {
ran_ue_t *iter = NULL;
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
* 3. Registration accept
*/
if (SESSION_SYNC_DONE(
if (AMF_SESSION_SYNC_DONE(
amf_ue, AMF_RELEASE_SM_CONTEXT_REGISTRATION_ACCEPT) &&
SESSION_SYNC_DONE(
AMF_SESSION_SYNC_DONE(
amf_ue, AMF_UPDATE_SM_CONTEXT_REGISTRATION_REQUEST)) {
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
* 3. Service accept
*/
if (SESSION_SYNC_DONE(amf_ue, AMF_RELEASE_SM_CONTEXT_SERVICE_ACCEPT) &&
SESSION_SYNC_DONE(amf_ue, AMF_UPDATE_SM_CONTEXT_SERVICE_REQUEST))
if (AMF_SESSION_SYNC_DONE(amf_ue, AMF_RELEASE_SM_CONTEXT_SERVICE_ACCEPT) &&
AMF_SESSION_SYNC_DONE(amf_ue, AMF_UPDATE_SM_CONTEXT_SERVICE_REQUEST))
ogs_assert(OGS_OK ==
nas_5gs_send_service_accept(amf_ue));
} 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) {
/*

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);
if (MME_HAVE_SGW_S1U_PATH(sess)) {
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));
} else {
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);
if (MME_HAVE_SGW_S1U_PATH(sess)) {
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));
} else {
ogs_assert(OGS_OK ==

View File

@ -2039,14 +2039,9 @@ sgw_ue_t *sgw_ue_add(mme_sgw_t *sgw)
ogs_assert(sgw_ue);
memset(sgw_ue, 0, sizeof *sgw_ue);
sgw_ue->index = ogs_pool_index(&sgw_ue_pool, sgw_ue);
ogs_assert(sgw_ue->index > 0 && sgw_ue->index <= ogs_app()->max.ue);
sgw_ue->mme_s11_teid = sgw_ue->index;
sgw_ue->t_gtp2_holding = ogs_timer_add(
sgw_ue->t_s11_holding = ogs_timer_add(
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;
@ -2065,8 +2060,8 @@ void sgw_ue_remove(sgw_ue_t *sgw_ue)
ogs_list_remove(&sgw->sgw_ue_list, sgw_ue);
ogs_assert(sgw_ue->t_gtp2_holding);
ogs_timer_delete(sgw_ue->t_gtp2_holding);
ogs_assert(sgw_ue->t_s11_holding);
ogs_timer_delete(sgw_ue->t_s11_holding);
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);
}
sgw_ue_t *sgw_ue_find_by_mme_s11_teid(uint32_t mme_s11_teid)
{
return sgw_ue_find(mme_s11_teid);
}
sgw_ue_t *sgw_ue_cycle(sgw_ue_t *sgw_ue)
{
return ogs_pool_cycle(&sgw_ue_pool, sgw_ue);
@ -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)
{
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;
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);
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);
if (target_ue) {
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);
mme_ue->mme_s11_teid = ogs_pool_index(&mme_ue_pool, mme_ue);
ogs_assert(mme_ue->mme_s11_teid > 0 &&
mme_ue->mme_s11_teid <= ogs_app()->max.ue);
/*
* When used for the first time, if last node is set,
* the search is performed from the first SGW in a round-robin manner.
@ -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));
}
mme_ue_t *mme_ue_find_by_teid(uint32_t teid)
{
return ogs_pool_find(&mme_ue_pool, teid);
}
mme_ue_t *mme_ue_find_by_message(ogs_nas_eps_message_t *message)
{
mme_ue_t *mme_ue = NULL;

View File

@ -277,7 +277,6 @@ struct sgw_ue_s {
sgw_ue_t *target_ue;
/* UE identity */
uint32_t mme_s11_teid; /* MME-S11-TEID is derived from INDEX */
uint32_t sgw_s11_teid; /* SGW-S11-TEID is received from SGW */
/*
@ -288,8 +287,8 @@ struct sgw_ue_s {
*/
int session_context_will_deleted;
/* GTPv2-C Holding timer for removing this context */
ogs_timer_t *t_gtp2_holding;
/* S11 Holding timer for removing this context */
ogs_timer_t *t_s11_holding;
/* Related Context */
union {
@ -351,6 +350,8 @@ struct mme_ue_s {
ogs_nas_eps_guti_t guti;
} 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 */
/* UE Info */
@ -533,8 +534,8 @@ struct mme_ue_s {
#define MAX_NUM_OF_GTP_COUNTER 16
#define GTP_COUNTER_MODIFY_BEARER_BY_PATH_SWITCH 1
#define GTP_COUNTER_MODIFY_BEARER_BY_E_RAB_MODIFICATION 2
#define GTP_COUNTER_CREATE_SESSION_BY_PATH_SWITCH 1
#define GTP_COUNTER_DELETE_SESSION_BY_PATH_SWITCH 2
struct {
uint8_t request;
uint8_t response;
@ -638,6 +639,8 @@ typedef struct mme_bearer_s {
ogs_ip_t enb_s1u_ip;
uint32_t sgw_s1u_teid;
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 */
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_switch_to_sgw(sgw_ue_t *sgw_ue, mme_sgw_t *new_sgw);
sgw_ue_t *sgw_ue_find(uint32_t index);
sgw_ue_t *sgw_ue_find_by_mme_s11_teid(uint32_t mme_s11_teid);
sgw_ue_t *sgw_ue_cycle(sgw_ue_t *sgw_ue);
typedef enum {
@ -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_bcd(char *imsi_bcd);
mme_ue_t *mme_ue_find_by_guti(ogs_nas_eps_guti_t *nas_guti);
mme_ue_t *mme_ue_find_by_teid(uint32_t teid);
mme_ue_t *mme_ue_find_by_message(ogs_nas_eps_message_t *message);
int mme_ue_set_imsi(mme_ue_t *mme_ue, char *imsi_bcd);

View File

@ -747,10 +747,10 @@ static void mme_s6a_ula_cb(void *data, struct msg **msg)
if (avpch1) {
ret = fd_msg_avp_hdr(avpch1, &hdr);
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;
memcpy(mme_ue->msisdn,
hdr->avp_value->os.data, mme_ue->msisdn_len);
memcpy(mme_ue->msisdn, hdr->avp_value->os.data,
ogs_min(mme_ue->msisdn_len, OGS_MAX_MSISDN_LEN));
ogs_buffer_to_bcd(mme_ue->msisdn,
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) {
ret = fd_msg_avp_hdr(avpch1, &hdr);
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;
memcpy(mme_ue->a_msisdn,
hdr->avp_value->os.data, mme_ue->a_msisdn_len);
memcpy(mme_ue->a_msisdn, hdr->avp_value->os.data,
ogs_min(mme_ue->a_msisdn_len, OGS_MAX_MSISDN_LEN));
ogs_buffer_to_bcd(mme_ue->a_msisdn,
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;
}
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;
ogs_pkbuf_t *s11buf = NULL;
ogs_gtp2_header_t h;
ogs_gtp_xact_t *xact = NULL;
mme_ue_t *mme_ue = NULL;
sgw_ue_t *sgw_ue = NULL;
ogs_assert(action);
ogs_assert(sess);
mme_ue = sess->mme_ue;
ogs_assert(mme_ue);
sgw_ue = mme_ue->sgw_ue;
ogs_assert(sgw_ue);
memset(&h, 0, sizeof(ogs_gtp2_header_t));
h.type = OGS_GTP2_DELETE_SESSION_REQUEST_TYPE;
h.teid = 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);
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_warn("PDN will disconnect[EBI:%d]", bearer->ebi);
} else {
mme_gtp_send_delete_session_request(sess, action);
mme_gtp_send_delete_session_request(sgw_ue, sess, action);
}
} else {
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_modify_bearer_request(
mme_ue_t *mme_ue, int uli_presence, int modify_action);
int mme_gtp_send_delete_session_request(mme_sess_t *sess, int action);
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);
int mme_gtp_send_create_bearer_response(
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];
ogs_gtp2_f_teid_t mme_s11_teid, pgw_s5c_teid;
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_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;
struct timeval now;
struct tm time_exp;
@ -51,8 +55,6 @@ ogs_pkbuf_t *mme_s11_build_create_session_request(
session = sess->session;
ogs_assert(session);
ogs_assert(session->name);
bearer = mme_default_bearer_in_sess(sess);
ogs_assert(bearer);
mme_ue = sess->mme_ue;
ogs_assert(mme_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(" 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));
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));
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(
ogs_gtp_self()->gtpc_addr, ogs_gtp_self()->gtpc_addr6,
&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->bearer_contexts_to_be_created.presence = 1;
req->bearer_contexts_to_be_created.eps_bearer_id.presence = 1;
req->bearer_contexts_to_be_created.eps_bearer_id.u8 = bearer->ebi;
int i = 0;
ogs_list_for_each(&sess->bearer_list, bearer) {
ogs_assert(i < OGS_BEARER_PER_UE);
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.bearer_level_qos.presence = 1;
ogs_gtp2_build_bearer_qos(
&req->bearer_contexts_to_be_created.bearer_level_qos,
&bearer_qos, bearer_qos_buf, GTP2_BEARER_QOS_LEN);
/* Bearer Context : EBI */
req->bearer_contexts_to_be_created[i].presence = 1;
req->bearer_contexts_to_be_created[i].eps_bearer_id.presence = 1;
req->bearer_contexts_to_be_created[i].eps_bearer_id.u8 = bearer->ebi;
if (create_action == OGS_GTP_CREATE_IN_PATH_SWITCH_REQUEST) {
/* Data Plane(DL) : ENB-S1U */
memset(&enb_s1u_teid[i], 0, sizeof(ogs_gtp2_f_teid_t));
enb_s1u_teid[i].interface_type = OGS_GTP2_F_TEID_S1_U_ENODEB_GTP_U;
enb_s1u_teid[i].teid = htobe32(bearer->enb_s1u_teid);
ogs_assert(OGS_OK == ogs_gtp2_ip_to_f_teid(
&bearer->enb_s1u_ip, &enb_s1u_teid[i], &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 */
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_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;
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;
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;
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));
enb_s1u_teid[i].interface_type = OGS_GTP2_F_TEID_S1_U_ENODEB_GTP_U;
enb_s1u_teid[i].teid = htobe32(bearer->enb_s1u_teid);
ogs_assert(OGS_OK ==
ogs_gtp2_ip_to_f_teid(&bearer->enb_s1u_ip, &enb_s1u_teid[i], &len));
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_modified[i].s1_u_enodeb_f_teid.presence = 1;
req->bearer_contexts_to_be_modified[i].s1_u_enodeb_f_teid.data =
&enb_s1u_teid[i];
req->bearer_contexts_to_be_modified[i].s1_u_enodeb_f_teid.len = len;
req->bearer_contexts_to_be_modified[i].s1_u_enodeb_f_teid.len =
enb_s1u_len[i];
i++;
}
@ -409,7 +450,7 @@ ogs_pkbuf_t *mme_s11_build_modify_bearer_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_delete_session_request_t *req =
@ -421,19 +462,14 @@ ogs_pkbuf_t *mme_s11_build_delete_session_request(
mme_bearer_t *bearer = NULL;
mme_ue_t *mme_ue = NULL;
sgw_ue_t *sgw_ue = NULL;
ogs_assert(sess);
mme_ue = sess->mme_ue;
ogs_assert(mme_ue);
sgw_ue = mme_ue->sgw_ue;
ogs_assert(sgw_ue);
bearer = mme_default_bearer_in_sess(sess);
ogs_assert(bearer);
ogs_debug("Delete Session Request");
ogs_debug(" MME_S11_TEID[%d] SGW_S11_TEID[%d]",
sgw_ue->mme_s11_teid, sgw_ue->sgw_s11_teid);
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);
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.data = &indication;
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(" 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));
@ -591,7 +631,7 @@ ogs_pkbuf_t *mme_s11_build_update_bearer_response(
ogs_debug("Update Bearer Response");
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));
@ -670,7 +710,7 @@ ogs_pkbuf_t *mme_s11_build_delete_bearer_response(
ogs_debug("Delete Bearer Response");
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));
@ -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(" 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));
@ -906,7 +946,7 @@ ogs_pkbuf_t *mme_s11_build_bearer_resource_command(
ogs_debug("Bearer Resource Command");
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);
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(
uint8_t type, mme_ue_t *mme_ue, int uli_presense);
ogs_pkbuf_t *mme_s11_build_delete_session_request(
uint8_t type, mme_sess_t *sess);
uint8_t type, mme_sess_t *sess, int action);
ogs_pkbuf_t *mme_s11_build_create_bearer_response(
uint8_t type, mme_bearer_t *bearer, uint8_t cause_value);
ogs_pkbuf_t *mme_s11_build_update_bearer_response(

View File

@ -20,6 +20,7 @@
#include "mme-event.h"
#include "mme-sm.h"
#include "mme-context.h"
#include "mme-timer.h"
#include "s1ap-path.h"
#include "mme-gtp-path.h"
@ -77,19 +78,21 @@ void mme_s11_handle_echo_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)
{
int rv;
int rv, i;
uint8_t cause_value = 0;
ogs_gtp2_cause_t *cause = NULL;
ogs_gtp2_f_teid_t *sgw_s11_teid = NULL;
ogs_gtp2_f_teid_t *pgw_s5c_teid = NULL;
ogs_gtp2_f_teid_t *sgw_s1u_teid = NULL;
ogs_gtp2_f_teid_t *pgw_s5u_teid = NULL;
mme_bearer_t *bearer = NULL;
mme_sess_t *sess = NULL;
mme_ue_t *mme_ue = NULL;
sgw_ue_t *source_ue = NULL, *target_ue = NULL;
ogs_session_t *session = NULL;
ogs_gtp2_bearer_qos_t bearer_qos;
ogs_gtp2_ambr_t *ambr = NULL;
@ -109,38 +112,28 @@ void mme_s11_handle_create_session_response(
ogs_assert(sess);
mme_ue = sess->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);
ogs_expect_or_return(rv == OGS_OK);
/************************
* Check SGW-UE Context
* Check MME-UE Context
************************/
cause_value = OGS_GTP2_CAUSE_REQUEST_ACCEPTED;
if (!sgw_ue) {
if (!mme_ue_from_teid) {
ogs_error("No Context in TEID");
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) {
@ -162,38 +155,46 @@ void mme_s11_handle_create_session_response(
ogs_error("No S11 TEID");
cause_value = OGS_GTP2_CAUSE_CONDITIONAL_IE_MISSING;
}
if (rsp->pgw_s5_s8__s2a_s2b_f_teid_for_pmip_based_interface_or_for_gtp_based_control_plane_interface.presence == 0) {
ogs_error("No S5C TEID");
cause_value = OGS_GTP2_CAUSE_CONDITIONAL_IE_MISSING;
}
if (rsp->bearer_contexts_created.s1_u_enodeb_f_teid.presence == 0) {
ogs_error("No S1U TEID");
cause_value = OGS_GTP2_CAUSE_CONDITIONAL_IE_MISSING;
}
if (rsp->pdn_address_allocation.presence) {
ogs_paa_t paa;
if (create_action == OGS_GTP_CREATE_IN_PATH_SWITCH_REQUEST) {
memcpy(&paa, rsp->pdn_address_allocation.data,
rsp->pdn_address_allocation.len);
/* No need S5C TEID in PathSwitchRequest */
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->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) {
ogs_error("No Cause");
cause_value = OGS_GTP2_CAUSE_MANDATORY_IE_MISSING;
}
if (rsp->bearer_contexts_created.cause.presence == 0) {
ogs_error("No Bearer Cause");
cause_value = OGS_GTP2_CAUSE_MANDATORY_IE_MISSING;
}
if (cause_value != OGS_GTP2_CAUSE_REQUEST_ACCEPTED) {
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);
cause = rsp->bearer_contexts_created.cause.data;
ogs_assert(cause);
cause_value = cause->value;
if (cause_value != OGS_GTP2_CAUSE_REQUEST_ACCEPTED) {
ogs_error("GTP Failed [Bearer-CAUSE:%d]", cause_value);
if (create_action == OGS_GTP_CREATE_IN_ATTACH_REQUEST) {
ogs_error("[%s] Attach reject", mme_ue->imsi_bcd);
ogs_assert(OGS_OK == nas_eps_send_attach_reject(mme_ue,
EMM_CAUSE_NETWORK_FAILURE, ESM_CAUSE_NETWORK_FAILURE));
for (i = 0; i < OGS_BEARER_PER_UE; i++) {
if (rsp->bearer_contexts_created[i].cause.presence == 0) {
break;
}
cause = rsp->bearer_contexts_created[i].cause.data;
ogs_assert(cause);
cause_value = cause->value;
if (cause_value != OGS_GTP2_CAUSE_REQUEST_ACCEPTED) {
ogs_error("GTP Failed [Bearer-CAUSE:%d]", cause_value);
if (create_action == OGS_GTP_CREATE_IN_ATTACH_REQUEST) {
ogs_error("[%s] Attach reject", mme_ue->imsi_bcd);
ogs_assert(OGS_OK == nas_eps_send_attach_reject(mme_ue,
EMM_CAUSE_NETWORK_FAILURE, ESM_CAUSE_NETWORK_FAILURE));
}
mme_send_delete_session_or_mme_ue_context_release(mme_ue);
return;
}
mme_send_delete_session_or_mme_ue_context_release(mme_ue);
return;
}
cause = rsp->cause.data;
@ -246,25 +253,87 @@ void mme_s11_handle_create_session_response(
/********************
* Check ALL Context
********************/
ogs_assert(mme_ue);
ogs_assert(sgw_ue);
ogs_assert(bearer);
sess = bearer->sess;
ogs_assert(sess);
session = sess->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 */
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 */
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);
if (rsp->pgw_s5_s8__s2a_s2b_f_teid_for_pmip_based_interface_or_for_gtp_based_control_plane_interface.presence) {
pgw_s5c_teid = rsp->pgw_s5_s8__s2a_s2b_f_teid_for_pmip_based_interface_or_for_gtp_based_control_plane_interface.data;
sess->pgw_s5c_teid = be32toh(pgw_s5c_teid->teid);
}
memcpy(&session->paa, rsp->pdn_address_allocation.data,
rsp->pdn_address_allocation.len);
/* PDN Addresss Allocation */
if (rsp->pdn_address_allocation.presence) {
memcpy(&session->paa, rsp->pdn_address_allocation.data,
rsp->pdn_address_allocation.len);
}
/* PCO */
if (rsp->protocol_configuration_options.presence) {
@ -273,10 +342,10 @@ void mme_s11_handle_create_session_response(
}
/* 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,
&rsp->bearer_contexts_created.bearer_level_qos);
ogs_assert(rsp->bearer_contexts_created.bearer_level_qos.len ==
&rsp->bearer_contexts_created[0].bearer_level_qos);
ogs_assert(rsp->bearer_contexts_created[0].bearer_level_qos.len ==
decoded);
session->qos.index = bearer_qos.qci;
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;
}
/* 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) {
mme_csmap_t *csmap = mme_csmap_find_by_tai(&mme_ue->tai);
mme_ue->csmap = csmap;
@ -327,7 +384,15 @@ void mme_s11_handle_create_session_response(
nas_eps_send_activate_default_bearer_context_request(
bearer, create_action));
} else if (create_action == OGS_GTP_CREATE_IN_PATH_SWITCH_REQUEST) {
ogs_error("OK");
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 {
ogs_fatal("Invalid Create Session Action[%d]", create_action);
ogs_assert_if_reached();
@ -335,7 +400,7 @@ void mme_s11_handle_create_session_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)
{
int rv;
@ -344,6 +409,7 @@ void mme_s11_handle_modify_bearer_response(
ogs_gtp2_cause_t *cause = NULL;
mme_ue_t *mme_ue = NULL;
sgw_ue_t *sgw_ue = NULL;
ogs_assert(rsp);
@ -353,19 +419,21 @@ void mme_s11_handle_modify_bearer_response(
* Check Transaction
********************/
ogs_assert(xact);
modify_action = xact->modify_action;
mme_ue = xact->data;
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);
ogs_expect_or_return(rv == OGS_OK);
/************************
* Check SGW-UE Context
* Check MME-UE Context
************************/
cause_value = OGS_GTP2_CAUSE_REQUEST_ACCEPTED;
if (!sgw_ue) {
if (!mme_ue_from_teid) {
ogs_error("No Context in TEID");
cause_value = OGS_GTP2_CAUSE_CONTEXT_NOT_FOUND;
}
@ -411,11 +479,11 @@ void mme_s11_handle_modify_bearer_response(
ogs_assert(sgw_ue);
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) {
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;
case OGS_GTP_MODIFY_IN_E_RAB_MODIFICATION:
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(
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)
{
int rv;
uint8_t cause_value = 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_ue_t *mme_ue = NULL;
ogs_assert(rsp);
@ -449,15 +518,26 @@ void mme_s11_handle_delete_session_response(
ogs_assert(sess);
mme_ue = sess->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);
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");
}
/********************
* Check Cause Value
@ -474,12 +554,13 @@ void mme_s11_handle_delete_session_response(
/********************
* Check ALL Context
********************/
ogs_assert(mme_ue);
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]",
sgw_ue->mme_s11_teid, sgw_ue->sgw_s11_teid);
ogs_debug(" MME_S11_TEID[%d] SGW_S11_TEID[%d]",
mme_ue->mme_s11_teid, source_ue->sgw_s11_teid);
if (action == OGS_GTP_DELETE_SEND_AUTHENTICATION_REQUEST) {
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);
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 {
ogs_fatal("Invalid action = %d", action);
ogs_assert_if_reached();
@ -553,16 +648,16 @@ void mme_s11_handle_delete_session_response(
}
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)
{
int rv;
uint8_t cause_value = 0;
mme_bearer_t *bearer = NULL, *default_bearer = NULL;
mme_sess_t *sess = NULL;
mme_ue_t *mme_ue = NULL;
sgw_ue_t *sgw_ue = 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_assert(xact);
@ -571,16 +666,16 @@ void mme_s11_handle_create_bearer_request(
ogs_debug("Create Bearer Response");
/***********************
* Check SGW-UE Context
* Check MME-UE Context
***********************/
cause_value = OGS_GTP2_CAUSE_REQUEST_ACCEPTED;
if (!sgw_ue) {
if (!mme_ue) {
ogs_error("No Context in TEID");
cause_value = OGS_GTP2_CAUSE_CONTEXT_NOT_FOUND;
} else {
mme_ue = sgw_ue->mme_ue;
ogs_assert(mme_ue);
sgw_ue = sgw_ue_cycle(mme_ue->sgw_ue);
ogs_assert(sgw_ue);
if (req->linked_eps_bearer_id.presence == 0) {
ogs_error("No Linked EBI");
@ -617,7 +712,11 @@ void mme_s11_handle_create_bearer_request(
cause_value = OGS_GTP2_CAUSE_MANDATORY_IE_MISSING;
}
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;
}
if (req->bearer_contexts.bearer_level_qos.presence == 0) {
@ -646,7 +745,7 @@ void mme_s11_handle_create_bearer_request(
ogs_assert(bearer);
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 */
sess->pti = OGS_NAS_PROCEDURE_TRANSACTION_IDENTITY_UNASSIGNED;
@ -658,8 +757,14 @@ void mme_s11_handle_create_bearer_request(
/* Data Plane(UL) : SGW-S1U */
sgw_s1u_teid = req->bearer_contexts.s1_u_enodeb_f_teid.data;
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(rv == OGS_OK);
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 = 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 */
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(
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)
{
uint8_t cause_value = 0;
mme_bearer_t *bearer = 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_assert(xact);
@ -736,16 +841,16 @@ void mme_s11_handle_update_bearer_request(
ogs_debug("Update Bearer Request");
/***********************
* Check SGW-UE Context
* Check MME-UE Context
***********************/
cause_value = OGS_GTP2_CAUSE_REQUEST_ACCEPTED;
if (!sgw_ue) {
if (!mme_ue) {
ogs_error("No Context in TEID");
cause_value = OGS_GTP2_CAUSE_CONTEXT_NOT_FOUND;
} else {
mme_ue = sgw_ue->mme_ue;
ogs_assert(mme_ue);
sgw_ue = sgw_ue_cycle(mme_ue->sgw_ue);
ogs_assert(sgw_ue);
if (req->bearer_contexts.presence == 0) {
ogs_error("No Bearer");
@ -783,7 +888,7 @@ void mme_s11_handle_update_bearer_request(
ogs_assert(sess);
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 */
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(
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)
{
uint8_t cause_value = 0;
mme_bearer_t *bearer = NULL;
mme_sess_t *sess = NULL;
mme_ue_t *mme_ue = NULL;
sgw_ue_t *sgw_ue = NULL;
ogs_assert(xact);
ogs_assert(req);
@ -871,16 +976,16 @@ void mme_s11_handle_delete_bearer_request(
ogs_debug("Delete Bearer Request");
/***********************
* Check SGW-UE Context
* Check MME-UE Context
***********************/
cause_value = OGS_GTP2_CAUSE_REQUEST_ACCEPTED;
if (!sgw_ue) {
if (!mme_ue) {
ogs_error("No Context in TEID");
cause_value = OGS_GTP2_CAUSE_CONTEXT_NOT_FOUND;
} else {
mme_ue = sgw_ue->mme_ue;
ogs_assert(mme_ue);
sgw_ue = sgw_ue_cycle(mme_ue->sgw_ue);
ogs_assert(sgw_ue);
if (req->linked_eps_bearer_id.presence == 1) {
/*
@ -943,7 +1048,7 @@ void mme_s11_handle_delete_bearer_request(
ogs_assert(sess);
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 */
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(
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)
{
int rv;
@ -979,7 +1084,8 @@ void mme_s11_handle_release_access_bearers_response(
int action = 0;
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_bearer_t *bearer = NULL;
@ -995,15 +1101,18 @@ void mme_s11_handle_release_access_bearers_response(
ogs_assert(action);
mme_ue = xact->data;
ogs_assert(mme_ue);
sgw_ue = sgw_ue_cycle(mme_ue->sgw_ue);
ogs_assert(sgw_ue);
rv = ogs_gtp_xact_commit(xact);
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");
}
/********************
* Check Cause Value
@ -1021,10 +1130,10 @@ void mme_s11_handle_release_access_bearers_response(
* Check ALL Context
********************/
ogs_assert(mme_ue);
ogs_assert(sgw_ue);
if (sgw_ue)
ogs_debug(" MME_S11_TEID[%d] SGW_S11_TEID[%d]",
sgw_ue->mme_s11_teid, sgw_ue->sgw_s11_teid);
ogs_debug(" MME_S11_TEID[%d] SGW_S11_TEID[%d]",
mme_ue->mme_s11_teid, sgw_ue->sgw_s11_teid);
ogs_list_for_each(&mme_ue->sess_list, sess) {
ogs_list_for_each(&sess->bearer_list, bearer) {
@ -1125,13 +1234,13 @@ void mme_s11_handle_release_access_bearers_response(
}
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)
{
uint8_t cause_value = 0;
mme_bearer_t *bearer = NULL;
mme_ue_t *mme_ue = NULL;
sgw_ue_t *sgw_ue = NULL;
ogs_assert(xact);
ogs_assert(noti);
@ -1139,16 +1248,16 @@ void mme_s11_handle_downlink_data_notification(
ogs_debug("Downlink Data Notification");
/************************
* Check SGW-UE Context
* Check MME-UE Context
************************/
cause_value = OGS_GTP2_CAUSE_REQUEST_ACCEPTED;
if (!sgw_ue) {
if (!mme_ue) {
ogs_error("No UE Context");
cause_value = OGS_GTP2_CAUSE_CONTEXT_NOT_FOUND;
} else {
mme_ue = sgw_ue->mme_ue;
ogs_assert(mme_ue);
sgw_ue = sgw_ue_cycle(mme_ue->sgw_ue);
ogs_assert(sgw_ue);
if (noti->eps_bearer_id.presence == 0) {
ogs_error("No Bearer ID");
@ -1181,7 +1290,7 @@ void mme_s11_handle_downlink_data_notification(
ogs_assert(bearer);
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
@ -1263,14 +1372,15 @@ void mme_s11_handle_downlink_data_notification(
}
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)
{
int rv;
uint8_t cause_value = 0;
ogs_gtp2_cause_t *cause = NULL;
mme_ue_t *mme_ue = NULL;
sgw_ue_t *sgw_ue = NULL;
mme_bearer_t *bearer = NULL;
mme_ue_t *mme_ue = NULL;
enb_ue_t *source_ue = NULL;
int i;
@ -1286,16 +1396,18 @@ void mme_s11_handle_create_indirect_data_forwarding_tunnel_response(
ogs_assert(xact);
mme_ue = xact->data;
ogs_assert(mme_ue);
sgw_ue = sgw_ue_cycle(mme_ue->sgw_ue);
ogs_assert(sgw_ue);
rv = ogs_gtp_xact_commit(xact);
ogs_expect_or_return(rv == OGS_OK);
/************************
* Check SGW-UE Context
* Check MME-UE Context
************************/
cause_value = OGS_GTP2_CAUSE_REQUEST_ACCEPTED;
if (!sgw_ue) {
if (!mme_ue_from_teid) {
ogs_error("No Context in TEID");
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_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++) {
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(
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)
{
int rv;
@ -1386,6 +1498,7 @@ void mme_s11_handle_delete_indirect_data_forwarding_tunnel_response(
ogs_gtp2_cause_t *cause = NULL;
int action = 0;
mme_ue_t *mme_ue = NULL;
sgw_ue_t *sgw_ue = NULL;
ogs_assert(rsp);
@ -1399,16 +1512,18 @@ void mme_s11_handle_delete_indirect_data_forwarding_tunnel_response(
ogs_assert(action);
mme_ue = xact->data;
ogs_assert(mme_ue);
sgw_ue = sgw_ue_cycle(mme_ue->sgw_ue);
ogs_assert(sgw_ue);
rv = ogs_gtp_xact_commit(xact);
ogs_expect_or_return(rv == OGS_OK);
/************************
* Check SGW-UE Context
* Check MME-UE Context
************************/
cause_value = OGS_GTP2_CAUSE_REQUEST_ACCEPTED;
if (!sgw_ue) {
if (!mme_ue_from_teid) {
ogs_error("No Context in TEID");
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_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);
@ -1470,7 +1585,7 @@ void mme_s11_handle_delete_indirect_data_forwarding_tunnel_response(
}
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)
{
int rv;
@ -1479,6 +1594,7 @@ void mme_s11_handle_bearer_resource_failure_indication(
mme_bearer_t *bearer = NULL;
mme_sess_t *sess = NULL;
mme_ue_t *mme_ue = NULL;
sgw_ue_t *sgw_ue = NULL;
ogs_debug("Bearer Resource Failure Indication");
@ -1492,11 +1608,13 @@ void mme_s11_handle_bearer_resource_failure_indication(
ogs_assert(sess);
mme_ue = sess->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);
ogs_expect_or_return(rv == OGS_OK);
if (!sgw_ue)
if (!mme_ue_from_teid)
ogs_error("No Context in TEID");
/********************
@ -1516,10 +1634,10 @@ void mme_s11_handle_bearer_resource_failure_indication(
* Check ALL Context
********************/
ogs_assert(mme_ue);
ogs_assert(sgw_ue);
if (sgw_ue)
ogs_debug(" MME_S11_TEID[%d] SGW_S11_TEID[%d]",
sgw_ue->mme_s11_teid, sgw_ue->sgw_s11_teid);
ogs_debug(" MME_S11_TEID[%d] SGW_S11_TEID[%d]",
mme_ue->mme_s11_teid, sgw_ue->sgw_s11_teid);
ogs_assert(OGS_OK ==
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(
ogs_gtp_xact_t *xact, ogs_gtp2_echo_response_t *rsp);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
#ifdef __cplusplus

View File

@ -521,6 +521,15 @@ void mme_state_operational(ogs_fsm_t *s, mme_event_t *e)
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
*
@ -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) {
/* Cause is not "Context not found" */
sgw_ue = sgw_ue_find_by_mme_s11_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;
mme_ue = mme_ue_find_by_teid(gtp_message.h.teid);
}
switch (gtp_message.h.type) {
@ -578,49 +573,49 @@ void mme_state_operational(ogs_fsm_t *s, mme_event_t *e)
break;
case OGS_GTP2_CREATE_SESSION_RESPONSE_TYPE:
mme_s11_handle_create_session_response(
xact, sgw_ue, &gtp_message.create_session_response);
xact, mme_ue, &gtp_message.create_session_response);
break;
case OGS_GTP2_MODIFY_BEARER_RESPONSE_TYPE:
mme_s11_handle_modify_bearer_response(
xact, sgw_ue, &gtp_message.modify_bearer_response);
xact, mme_ue, &gtp_message.modify_bearer_response);
break;
case OGS_GTP2_DELETE_SESSION_RESPONSE_TYPE:
mme_s11_handle_delete_session_response(
xact, sgw_ue, &gtp_message.delete_session_response);
xact, mme_ue, &gtp_message.delete_session_response);
break;
case OGS_GTP2_CREATE_BEARER_REQUEST_TYPE:
mme_s11_handle_create_bearer_request(
xact, sgw_ue, &gtp_message.create_bearer_request);
xact, mme_ue, &gtp_message.create_bearer_request);
break;
case OGS_GTP2_UPDATE_BEARER_REQUEST_TYPE:
mme_s11_handle_update_bearer_request(
xact, sgw_ue, &gtp_message.update_bearer_request);
xact, mme_ue, &gtp_message.update_bearer_request);
break;
case OGS_GTP2_DELETE_BEARER_REQUEST_TYPE:
mme_s11_handle_delete_bearer_request(
xact, sgw_ue, &gtp_message.delete_bearer_request);
xact, mme_ue, &gtp_message.delete_bearer_request);
break;
case OGS_GTP2_RELEASE_ACCESS_BEARERS_RESPONSE_TYPE:
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;
case OGS_GTP2_DOWNLINK_DATA_NOTIFICATION_TYPE:
mme_s11_handle_downlink_data_notification(
xact, sgw_ue, &gtp_message.downlink_data_notification);
xact, mme_ue, &gtp_message.downlink_data_notification);
break;
case OGS_GTP2_CREATE_INDIRECT_DATA_FORWARDING_TUNNEL_RESPONSE_TYPE:
mme_s11_handle_create_indirect_data_forwarding_tunnel_response(
xact, sgw_ue,
xact, mme_ue,
&gtp_message.create_indirect_data_forwarding_tunnel_response);
break;
case OGS_GTP2_DELETE_INDIRECT_DATA_FORWARDING_TUNNEL_RESPONSE_TYPE:
mme_s11_handle_delete_indirect_data_forwarding_tunnel_response(
xact, sgw_ue,
xact, mme_ue,
&gtp_message.delete_indirect_data_forwarding_tunnel_response);
break;
case OGS_GTP2_BEARER_RESOURCE_FAILURE_INDICATION_TYPE:
mme_s11_handle_bearer_resource_failure_indication(
xact, sgw_ue,
xact, mme_ue,
&gtp_message.bearer_resource_failure_indication);
break;
default:
@ -630,6 +625,37 @@ void mme_state_operational(ogs_fsm_t *s, mme_event_t *e)
ogs_pkbuf_free(pkbuf);
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:
sock = e->sock;
ogs_assert(sock);

View File

@ -1556,7 +1556,8 @@ ogs_pkbuf_t *s1ap_build_mme_configuration_transfer(
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_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_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;
S1AP_SecurityContext_t *SecurityContext = NULL;
mme_sess_t *sess = NULL;
mme_bearer_t *bearer = NULL;
enb_ue_t *enb_ue = NULL;
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;
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));
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;
*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->nextHopParameter.size = OGS_SHA256_DIGEST_SIZE;
SecurityContext->nextHopParameter.buf =

View File

@ -56,7 +56,8 @@ ogs_pkbuf_t *s1ap_build_paging(
ogs_pkbuf_t *s1ap_build_mme_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(
uint32_t enb_ue_s1ap_id, uint32_t mme_ue_s1ap_id,
S1AP_Cause_PR group, long cause);

View File

@ -1927,69 +1927,64 @@ void s1ap_handle_path_switch_request(
mme_ue->nhcc++;
ogs_kdf_nh_enb(mme_ue->kasme, mme_ue->nh, mme_ue->nh);
#if 0
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);
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++) {
S1AP_E_RABToBeSwitchedDLItemIEs_t *item = NULL;
S1AP_E_RABToBeSwitchedDLItem_t *e_rab = NULL;
mme_bearer_t *bearer = NULL;
mme_bearer_t *bearer = NULL;
item = (S1AP_E_RABToBeSwitchedDLItemIEs_t *)
E_RABToBeSwitchedDLList->list.array[i];
if (!item) {
ogs_error("No S1AP_E_RABToBeSwitchedDLItemIEs_t");
ogs_assert(OGS_OK ==
s1ap_send_error_indication2(mme_ue,
S1AP_Cause_PR_protocol, S1AP_CauseProtocol_semantic_error));
return;
}
e_rab = &item->value.choice.E_RABToBeSwitchedDLItem;
if (!e_rab) {
ogs_error("No E_RABToBeSwitchedDLItem");
ogs_assert(OGS_OK ==
s1ap_send_error_indication2(mme_ue,
S1AP_Cause_PR_protocol, S1AP_CauseProtocol_semantic_error));
return;
}
bearer = mme_bearer_find_by_ue_ebi(mme_ue, e_rab->e_RAB_ID);
if (!bearer) {
ogs_error("No Bearer [%d]", (int)e_rab->e_RAB_ID);
ogs_assert(OGS_OK ==
s1ap_send_error_indication2(mme_ue,
S1AP_Cause_PR_radioNetwork,
S1AP_CauseRadioNetwork_unknown_E_RAB_ID));
return;
}
memcpy(&bearer->enb_s1u_teid, e_rab->gTP_TEID.buf,
sizeof(bearer->enb_s1u_teid));
bearer->enb_s1u_teid = be32toh(bearer->enb_s1u_teid);
rv = ogs_asn_BIT_STRING_to_ip(
&e_rab->transportLayerAddress, &bearer->enb_s1u_ip);
if (rv != OGS_OK) {
ogs_error("No transportLayerAddress [%d]",
(int)e_rab->e_RAB_ID);
ogs_assert(OGS_OK ==
s1ap_send_error_indication2(mme_ue,
S1AP_Cause_PR_protocol,
S1AP_CauseProtocol_abstract_syntax_error_falsely_constructed_message));
return;
}
ogs_list_add(
&mme_ue->bearer_to_modify_list, &bearer->to_modify_node);
item = (S1AP_E_RABToBeSwitchedDLItemIEs_t *)
E_RABToBeSwitchedDLList->list.array[i];
if (!item) {
ogs_error("No S1AP_E_RABToBeSwitchedDLItemIEs_t");
ogs_assert(OGS_OK ==
s1ap_send_error_indication2(mme_ue,
S1AP_Cause_PR_protocol, S1AP_CauseProtocol_semantic_error));
return;
}
e_rab = &item->value.choice.E_RABToBeSwitchedDLItem;
if (!e_rab) {
ogs_error("No E_RABToBeSwitchedDLItem");
ogs_assert(OGS_OK ==
s1ap_send_error_indication2(mme_ue,
S1AP_Cause_PR_protocol, S1AP_CauseProtocol_semantic_error));
return;
}
bearer = mme_bearer_find_by_ue_ebi(mme_ue, e_rab->e_RAB_ID);
if (!bearer) {
ogs_error("No Bearer [%d]", (int)e_rab->e_RAB_ID);
ogs_assert(OGS_OK ==
s1ap_send_error_indication2(mme_ue,
S1AP_Cause_PR_radioNetwork,
S1AP_CauseRadioNetwork_unknown_E_RAB_ID));
return;
}
memcpy(&bearer->enb_s1u_teid, e_rab->gTP_TEID.buf,
sizeof(bearer->enb_s1u_teid));
bearer->enb_s1u_teid = be32toh(bearer->enb_s1u_teid);
rv = ogs_asn_BIT_STRING_to_ip(
&e_rab->transportLayerAddress, &bearer->enb_s1u_ip);
if (rv != OGS_OK) {
ogs_error("No transportLayerAddress [%d]",
(int)e_rab->e_RAB_ID);
ogs_assert(OGS_OK ==
s1ap_send_error_indication2(mme_ue,
S1AP_Cause_PR_protocol,
S1AP_CauseProtocol_abstract_syntax_error_falsely_constructed_message));
return;
}
ogs_list_add(
&mme_ue->bearer_to_modify_list, &bearer->to_modify_node);
}
relocation = sgw_ue_check_if_relocated(mme_ue);
if (relocation == SGW_WITHOUT_RELOCATION) {
if (ogs_list_count(&mme_ue->bearer_to_modify_list)) {
ogs_assert(OGS_OK == mme_gtp_send_modify_bearer_request(
mme_ue, 1, OGS_GTP_MODIFY_IN_PATH_SWITCH_REQUEST));
@ -1998,6 +1993,9 @@ void s1ap_handle_path_switch_request(
mme_sess_t *sess = NULL;
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 ==
mme_gtp_send_create_session_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;
}
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;
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_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);
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_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_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_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)
int sgwc_sess_pfcp_xact_count(
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(
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_pkbuf_t *pkbuf = NULL;
ogs_gtp2_header_t h;
ogs_pkbuf_t *pkbuf = NULL;
ogs_assert(bearer);

View File

@ -29,6 +29,9 @@ extern "C" {
int sgwc_gtp_open(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(
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(
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);
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);
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);
}
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);
ogs_expect_or_return_val(sxabuf, OGS_ERROR);
@ -237,55 +263,7 @@ int sgwc_pfcp_send_session_establishment_request(
return rv;
}
ogs_pfcp_xact_t *sgwc_pfcp_xact_create(
sgwc_sess_t *sess, ogs_gtp_xact_t *gtp_xact,
ogs_pkbuf_t *gtpbuf, uint64_t flags)
{
ogs_pfcp_xact_t *xact = NULL;
ogs_assert(sess);
xact = ogs_pfcp_xact_local_create(sess->pfcp_node, sess_timeout, sess);
ogs_expect_or_return_val(xact, NULL);
xact->assoc_xact = gtp_xact;
xact->modify_flags = flags | OGS_PFCP_MODIFY_SESSION;
if (gtpbuf) {
xact->gtpbuf = ogs_pkbuf_copy(gtpbuf);
ogs_expect_or_return_val(xact->gtpbuf, NULL);
}
return xact;
}
int sgwc_pfcp_xact_commit(ogs_pfcp_xact_t *xact)
{
int rv;
sgwc_sess_t *sess = NULL;
ogs_pkbuf_t *sxabuf = NULL;
ogs_pfcp_header_t h;
ogs_assert(xact);
sess = xact->data;
ogs_assert(sess);
memset(&h, 0, sizeof(ogs_pfcp_header_t));
h.type = OGS_PFCP_SESSION_MODIFICATION_REQUEST_TYPE;
h.seid = sess->sgwu_sxa_seid;
sxabuf = sgwc_sxa_build_session_modification_request(h.type, sess, xact);
ogs_expect_or_return_val(sxabuf, OGS_ERROR);
rv = ogs_pfcp_xact_update_tx(xact, &h, sxabuf);
ogs_expect_or_return_val(rv == OGS_OK, OGS_ERROR);
rv = ogs_pfcp_xact_commit(xact);
ogs_expect(rv == OGS_OK);
return rv;
}
int sgwc_pfcp_send_sess_modification_request(
int sgwc_pfcp_send_session_modification_request(
sgwc_sess_t *sess, ogs_gtp_xact_t *gtp_xact,
ogs_pkbuf_t *gtpbuf, uint64_t flags)
{
@ -294,13 +272,20 @@ int sgwc_pfcp_send_sess_modification_request(
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);
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_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(
@ -333,7 +318,7 @@ int sgwc_pfcp_send_bearer_modification_request(
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);
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);
@ -355,10 +340,6 @@ int sgwc_pfcp_send_session_deletion_request(
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);
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);
}
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);
ogs_expect_or_return_val(sxabuf, OGS_ERROR);

View File

@ -29,31 +29,19 @@ extern "C" {
int sgwc_pfcp_open(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(
sgwc_sess_t *sess, ogs_gtp_xact_t *gtp_xact, ogs_pkbuf_t *gtpbuf);
/*
* sgwc_pfcp_xact_create()/sgwc_pfcp_xact_commit() can only be used
* with sgwc_pfcp_send_sess_modification_request()
*
* You should not use the following functions
* - sgwc_pfcp_send_session_establishment_request()
* - sgwc_pfcp_send_bearer_modification_request()
* - sgwc_pfcp_send_session_deletion_request()
* - sgwc_pfcp_send_session_report_response()
*/
ogs_pfcp_xact_t *sgwc_pfcp_xact_create(
int sgwc_pfcp_send_session_modification_request(
sgwc_sess_t *sess, ogs_gtp_xact_t *gtp_xact,
ogs_pkbuf_t *gtpbuf, uint64_t flags);
int sgwc_pfcp_xact_commit(ogs_pfcp_xact_t *xact);
int sgwc_pfcp_send_sess_modification_request(
sgwc_sess_t *sess, ogs_gtp_xact_t *gtp_xact,
ogs_pkbuf_t *gtpbuf, uint64_t flags);
int sgwc_pfcp_send_bearer_modification_request(
sgwc_bearer_t *bearer, ogs_gtp_xact_t *gtp_xact,
ogs_pkbuf_t *gtpbuf, uint64_t flags);
int sgwc_pfcp_send_session_deletion_request(
sgwc_sess_t *sess, ogs_gtp_xact_t *gtp_xact, ogs_pkbuf_t *gtpbuf);

View File

@ -19,6 +19,118 @@
#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(
uint8_t cause_value, sgwc_bearer_t *bearer)
{

View File

@ -26,6 +26,9 @@
extern "C" {
#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(
uint8_t cause_value, sgwc_bearer_t *bearer);

View File

@ -22,7 +22,7 @@
#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_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_sess_t *sess = NULL;
@ -72,6 +72,29 @@ static void bearer_timeout(ogs_gtp_xact_t *xact, void *data)
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,
* and is currently not being used. */
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,
ogs_pkbuf_t *gtpbuf, ogs_gtp2_message_t *message)
{
int i;
uint8_t cause_value = 0;
sgwc_sess_t *sess = NULL;
@ -164,15 +188,15 @@ void sgwc_s11_handle_create_session_request(
ogs_error("No IMSI");
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");
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");
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");
cause_value = OGS_GTP2_CAUSE_MANDATORY_IE_MISSING;
}
@ -201,7 +225,7 @@ void sgwc_s11_handle_create_session_request(
req->access_point_name.data,
ogs_min(req->access_point_name.len, OGS_MAX_APN_LEN)));
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) {
ogs_info("OLD Session Release [IMSI:%s,APN:%s]",
sgwc_ue->imsi_bcd, sess->session.name);
@ -243,27 +267,100 @@ void sgwc_s11_handle_create_session_request(
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 */
sgwc_bearer_remove_all(sess);
/* Setup Default Bearer */
bearer = sgwc_bearer_add(sess);
ogs_assert(bearer);
/* Setup Bearer */
for (i = 0; i < OGS_BEARER_PER_UE; i++) {
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 */
bearer->ebi = req->bearer_contexts_to_be_created.eps_bearer_id.u8;
decoded = ogs_gtp2_parse_bearer_qos(&bearer_qos,
&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 */
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);
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;
if (req->bearer_contexts_to_be_modified[i].presence == 0) {
@ -372,10 +469,18 @@ void sgwc_s11_handle_modify_bearer_request(
}
if (!current_xact) {
current_xact = sgwc_pfcp_xact_create(sess, s11_xact, gtpbuf,
OGS_PFCP_MODIFY_DL_ONLY|OGS_PFCP_MODIFY_ACTIVATE);
current_xact = ogs_pfcp_xact_local_create(
sess->pfcp_node, pfcp_sess_timeout, sess);
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);
}
@ -453,7 +558,7 @@ void sgwc_s11_handle_modify_bearer_request(
dl_tunnel->remote_teid, dl_tunnel->local_teid);
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(
@ -465,6 +570,7 @@ void sgwc_s11_handle_delete_session_request(
sgwc_sess_t *sess = NULL;
ogs_gtp_xact_t *s5c_xact = NULL;
ogs_gtp2_delete_session_request_t *req = NULL;
ogs_gtp2_indication_t *indication = NULL;
ogs_assert(s11_xact);
ogs_assert(gtpbuf);
@ -505,6 +611,27 @@ void sgwc_s11_handle_delete_session_request(
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
********************/
@ -516,20 +643,29 @@ void sgwc_s11_handle_delete_session_request(
ogs_debug(" SGW_S5C_TEID[0x%x] PGW_S5C_TEID[0x%x]",
sess->sgw_s5c_teid, sess->pgw_s5c_teid);
message->h.type = OGS_GTP2_DELETE_SESSION_REQUEST_TYPE;
message->h.teid = sess->pgw_s5c_teid;
if (indication &&
indication->operation_indication == 0 &&
indication->scope_indication == 1) {
gtpbuf = ogs_gtp2_build_msg(message);
ogs_expect_or_return(gtpbuf);
ogs_assert(OGS_OK ==
sgwc_pfcp_send_session_deletion_request(sess, s11_xact, gtpbuf));
s5c_xact = ogs_gtp_xact_local_create(
sess->gnode, &message->h, gtpbuf, sess_timeout, sess);
ogs_expect_or_return(s5c_xact);
} else {
message->h.type = OGS_GTP2_DELETE_SESSION_REQUEST_TYPE;
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);
ogs_expect(rv == OGS_OK);
s5c_xact = ogs_gtp_xact_local_create(
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(
@ -1032,7 +1168,7 @@ void sgwc_s11_handle_release_access_bearers_request(
ogs_list_for_each(&sgwc_ue->sess_list, sess) {
ogs_assert(OGS_OK ==
sgwc_pfcp_send_sess_modification_request(
sgwc_pfcp_send_session_modification_request(
sess, s11_xact, gtpbuf,
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_assert(OGS_OK ==
sgwc_pfcp_send_sess_modification_request(
sgwc_pfcp_send_session_modification_request(
sess, s11_xact, gtpbuf,
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_assert(OGS_OK ==
sgwc_pfcp_send_sess_modification_request(
sgwc_pfcp_send_session_modification_request(
sess, s11_xact, gtpbuf,
OGS_PFCP_MODIFY_INDIRECT| OGS_PFCP_MODIFY_REMOVE));
}
@ -1375,7 +1511,7 @@ void sgwc_s11_handle_bearer_resource_command(
ogs_expect_or_return(pkbuf);
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_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,
ogs_pkbuf_t *gtpbuf, ogs_gtp2_message_t *message)
{
int rv;
int rv, i;
uint8_t cause_value;
ogs_gtp2_cause_t *cause = NULL;
@ -106,25 +106,6 @@ void sgwc_s5c_handle_create_session_response(
} else {
sgwc_ue = sess->sgwc_ue;
ogs_assert(sgwc_ue);
if (rsp->bearer_contexts_created.presence == 0) {
ogs_error("No Bearer");
cause_value = OGS_GTP2_CAUSE_MANDATORY_IE_MISSING;
}
if (rsp->bearer_contexts_created.eps_bearer_id.presence == 0) {
ogs_error("No EPS Bearer ID");
cause_value = OGS_GTP2_CAUSE_MANDATORY_IE_MISSING;
}
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) {
@ -143,10 +124,6 @@ void sgwc_s5c_handle_create_session_response(
ogs_error("No GTP TEID");
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) {
ogs_paa_t paa;
@ -165,11 +142,7 @@ void sgwc_s5c_handle_create_session_response(
if (rsp->cause.presence == 0) {
ogs_error("No Cause");
cause_value = OGS_GTP2_CAUSE_MANDATORY_IE_MISSING;
}
if (rsp->bearer_contexts_created.cause.presence == 0) {
ogs_error("No Bearer Cause");
cause_value = OGS_GTP2_CAUSE_MANDATORY_IE_MISSING;
cause_value = OGS_GTP2_CAUSE_CONDITIONAL_IE_MISSING;
}
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);
cause = rsp->bearer_contexts_created.cause.data;
ogs_assert(cause);
cause_value = cause->value;
if (cause_value != OGS_GTP2_CAUSE_REQUEST_ACCEPTED) {
ogs_error("GTP Failed [Bearer-CAUSE:%d]", cause_value);
ogs_gtp_send_error_message(
s11_xact, sgwc_ue ? sgwc_ue->mme_s11_teid : 0,
OGS_GTP2_CREATE_SESSION_RESPONSE_TYPE, cause_value);
return;
for (i = 0; i < OGS_BEARER_PER_UE; i++) {
if (rsp->bearer_contexts_created[i].cause.presence == 0) {
break;
}
cause = rsp->bearer_contexts_created[i].cause.data;
ogs_assert(cause);
cause_value = cause->value;
if (cause_value != OGS_GTP2_CAUSE_REQUEST_ACCEPTED) {
ogs_error("GTP Failed [Bearer-CAUSE:%d]", cause_value);
ogs_gtp_send_error_message(
s11_xact, sgwc_ue ? sgwc_ue->mme_s11_teid : 0,
OGS_GTP2_CREATE_SESSION_RESPONSE_TYPE, cause_value);
return;
}
}
cause = rsp->cause.data;
@ -216,49 +195,75 @@ void sgwc_s5c_handle_create_session_response(
********************/
ogs_assert(sgwc_ue);
ogs_assert(sess);
ogs_assert(bearer);
ul_tunnel = sgwc_ul_tunnel_in_bearer(bearer);
ogs_assert(ul_tunnel);
/* Receive Data Plane(UL) : PGW-S5U */
pgw_s5u_teid = rsp->bearer_contexts_created.s5_s8_u_sgw_f_teid.data;
ogs_assert(pgw_s5u_teid);
ul_tunnel->remote_teid = be32toh(pgw_s5u_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);
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;
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].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 */
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);
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 ==
sgwc_pfcp_send_bearer_modification_request(
bearer, s11_xact, gtpbuf,
sgwc_pfcp_send_session_modification_request(
sess, s11_xact, gtpbuf,
OGS_PFCP_MODIFY_UL_ONLY|OGS_PFCP_MODIFY_ACTIVATE));
}
@ -371,6 +376,7 @@ void sgwc_s5c_handle_modify_bearer_response(
int rv;
ogs_gtp2_cause_t *cause = NULL;
uint8_t cause_value;
int modify_action;
sgwc_ue_t *sgwc_ue = NULL;
ogs_pkbuf_t *pkbuf = NULL;
@ -390,6 +396,7 @@ void sgwc_s5c_handle_modify_bearer_response(
ogs_assert(s5c_xact);
s11_xact = s5c_xact->assoc_xact;
ogs_assert(s11_xact);
modify_action = s5c_xact->modify_action;
rv = ogs_gtp_xact_commit(s5c_xact);
ogs_expect(rv == OGS_OK);
@ -408,9 +415,14 @@ void sgwc_s5c_handle_modify_bearer_response(
}
if (cause_value != OGS_GTP2_CAUSE_REQUEST_ACCEPTED) {
ogs_gtp_send_error_message(
s11_xact, sgwc_ue ? sgwc_ue->mme_s11_teid : 0,
OGS_GTP2_MODIFY_BEARER_RESPONSE_TYPE, cause_value);
if (modify_action == OGS_GTP_MODIFY_IN_PATH_SWITCH_REQUEST)
ogs_gtp_send_error_message(
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;
}
@ -425,9 +437,14 @@ void sgwc_s5c_handle_modify_bearer_response(
}
if (cause_value != OGS_GTP2_CAUSE_REQUEST_ACCEPTED) {
ogs_gtp_send_error_message(
s11_xact, sgwc_ue ? sgwc_ue->mme_s11_teid : 0,
OGS_GTP2_MODIFY_BEARER_RESPONSE_TYPE, cause_value);
if (modify_action == OGS_GTP_MODIFY_IN_PATH_SWITCH_REQUEST)
ogs_gtp_send_error_message(
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;
}
@ -441,9 +458,14 @@ void sgwc_s5c_handle_modify_bearer_response(
cause_value = cause->value;
if (cause_value != OGS_GTP2_CAUSE_REQUEST_ACCEPTED) {
ogs_error("GTP Failed [CAUSE:%d]", cause_value);
ogs_gtp_send_error_message(
s11_xact, sgwc_ue ? sgwc_ue->mme_s11_teid : 0,
OGS_GTP2_MODIFY_BEARER_RESPONSE_TYPE, cause_value);
if (modify_action == OGS_GTP_MODIFY_IN_PATH_SWITCH_REQUEST)
ogs_gtp_send_error_message(
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;
}
@ -458,17 +480,22 @@ void sgwc_s5c_handle_modify_bearer_response(
ogs_debug(" SGW_S5C_TEID[0x%x] PGW_S5C_TEID[0x%x]",
sess->sgw_s5c_teid, sess->pgw_s5c_teid);
message->h.type = OGS_GTP2_MODIFY_BEARER_RESPONSE_TYPE;
message->h.teid = sgwc_ue->mme_s11_teid;
if (modify_action == OGS_GTP_MODIFY_IN_PATH_SWITCH_REQUEST) {
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);
ogs_expect_or_return(pkbuf);
pkbuf = ogs_gtp2_build_msg(message);
ogs_expect_or_return(pkbuf);
rv = ogs_gtp_xact_update_tx(s11_xact, &message->h, pkbuf);
ogs_expect_or_return(rv == OGS_OK);
rv = ogs_gtp_xact_update_tx(s11_xact, &message->h, pkbuf);
ogs_expect_or_return(rv == OGS_OK);
rv = ogs_gtp_xact_commit(s11_xact);
ogs_expect(rv == OGS_OK);
rv = ogs_gtp_xact_commit(s11_xact);
ogs_expect(rv == OGS_OK);
}
}
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;
}
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);
}
if (sgwc_ue) {
gnode = sgwc_ue->gnode;
ogs_assert(gnode);
} else {
gnode = e->gnode;
ogs_assert(gnode);
}
gnode = e->gnode;
ogs_assert(gnode);
rv = ogs_gtp_xact_receive(gnode, &gtp_message.h, &gtp_xact);
if (rv != OGS_OK) {
@ -164,6 +154,11 @@ void sgwc_state_operational(ogs_fsm_t *s, sgwc_event_t *e)
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) {
case OGS_GTP2_ECHO_REQUEST_TYPE:
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;
}
if (gtp_message.h.teid_presence && gtp_message.h.teid != 0) {
sess = sgwc_sess_find_by_teid(gtp_message.h.teid);
}
if (sess) {
gnode = sess->gnode;
ogs_assert(gnode);
} else {
gnode = e->gnode;
ogs_assert(gnode);
}
gnode = e->gnode;
ogs_assert(gnode);
rv = ogs_gtp_xact_receive(gnode, &gtp_message.h, &gtp_xact);
if (rv != OGS_OK) {
@ -257,6 +243,10 @@ void sgwc_state_operational(ogs_fsm_t *s, sgwc_event_t *e)
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) {
case OGS_GTP2_ECHO_REQUEST_TYPE:
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;
}
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)
{
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;
memset(&pfcp_message, 0, sizeof(ogs_pfcp_message_t));
num_of_remove_pdr = 0;
num_of_remove_far = 0;
num_of_create_pdr = 0;
num_of_create_far = 0;
num_of_update_far = 0;
if (modify_flags & OGS_PFCP_MODIFY_CREATE) {
ogs_pfcp_pdrbuf_init();
}
@ -166,6 +160,7 @@ ogs_pkbuf_t *sgwc_sxa_build_session_modification_request(
OGS_GTP2_F_TEID_SGW_GTP_U_FOR_UL_DATA_FORWARDING))))) {
if (modify_flags & OGS_PFCP_MODIFY_REMOVE) {
pdr = tunnel->pdr;
if (pdr) {
ogs_pfcp_tlv_remove_pdr_t *message =
@ -193,6 +188,7 @@ ogs_pkbuf_t *sgwc_sxa_build_session_modification_request(
ogs_assert_if_reached();
} else if (modify_flags & OGS_PFCP_MODIFY_CREATE) {
pdr = tunnel->pdr;
if (pdr) {
ogs_pfcp_build_create_pdr(
@ -214,7 +210,10 @@ ogs_pkbuf_t *sgwc_sxa_build_session_modification_request(
num_of_create_far++;
} else
ogs_assert_if_reached();
} else if (modify_flags & OGS_PFCP_MODIFY_DEACTIVATE) {
}
if (modify_flags & OGS_PFCP_MODIFY_DEACTIVATE) {
far = tunnel->far;
if (far) {
ogs_pfcp_build_update_far_deactivate(
@ -224,7 +223,9 @@ ogs_pkbuf_t *sgwc_sxa_build_session_modification_request(
num_of_update_far++;
} else
ogs_assert_if_reached();
} else if (modify_flags & OGS_PFCP_MODIFY_ACTIVATE) {
far = tunnel->far;
if (far) {
if (modify_flags & OGS_PFCP_MODIFY_END_MARKER) {
@ -241,6 +242,7 @@ ogs_pkbuf_t *sgwc_sxa_build_session_modification_request(
tunnel->far->smreq_flags.value = 0;
} else
ogs_assert_if_reached();
}
}
}

View File

@ -28,7 +28,7 @@ extern "C" {
ogs_pkbuf_t *sgwc_sxa_build_session_establishment_request(
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);
ogs_pkbuf_t *sgwc_sxa_build_session_deletion_request(
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;
int sgw_s5c_len, sgw_s5u_len;
ogs_gtp2_f_teid_t sgw_s5c_teid, sgw_s5u_teid;
int sgw_s5c_len;
ogs_gtp2_f_teid_t sgw_s5c_teid;
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_node_t *pgw = NULL;
@ -248,24 +253,44 @@ void sgwc_sxa_handle_session_establishment_response(
ogs_assert(sess);
bearer = sgwc_default_bearer_in_sess(sess);
ogs_assert(bearer);
dl_tunnel = sgwc_dl_tunnel_in_bearer(bearer);
ogs_assert(dl_tunnel);
ogs_debug(" SGW_S5C_TEID[0x%x] PGW_S5C_TEID[0x%x]",
sess->sgw_s5c_teid, sess->pgw_s5c_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;
/* Data Plane(DL) : SGW-S5U */
i = 0;
ogs_list_for_each(&sess->bearer_list, bearer) {
ogs_assert(i < OGS_BEARER_PER_UE);
dl_tunnel = sgwc_dl_tunnel_in_bearer(bearer);
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 */
up_f_seid = pfcp_rsp->up_f_seid.data;
ogs_assert(up_f_seid);
sess->sgwu_sxa_seid = be64toh(up_f_seid->seid);
num_of_sgw_s5u = i;
/* Send Control Plane(DL) : SGW-S5C */
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);
ogs_assert(rv == OGS_OK);
ogs_debug(" SGW_S5C_TEID[0x%x] PGW_S5C_TEID[0x%x]",
sess->sgw_s5c_teid, sess->pgw_s5c_teid);
ogs_debug(" SGW_S5U_TEID[%d] PGW_S5U_TEID[%d]",
dl_tunnel->local_teid, dl_tunnel->remote_teid);
/* UP F-SEID */
up_f_seid = pfcp_rsp->up_f_seid.data;
ogs_assert(up_f_seid);
sess->sgwu_sxa_seid = be64toh(up_f_seid->seid);
pgw_s5c_teid = create_session_request->
pgw_s5_s8_address_for_control_plane_or_pmip.data;
@ -299,16 +324,6 @@ void sgwc_sxa_handle_session_establishment_response(
/* Setup GTP Node */
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 */
if (create_session_request->indication_flags.presence &&
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.
len = sgw_s5c_len;
/* Bearer Context : EBI */
modify_bearer_request->bearer_contexts_to_be_modified[0].presence = 1;
modify_bearer_request->bearer_contexts_to_be_modified[0].
eps_bearer_id.presence = 1;
modify_bearer_request->bearer_contexts_to_be_modified[0].
eps_bearer_id.u8 = bearer->ebi;
for (i = 0; i < num_of_sgw_s5u; i++) {
modify_bearer_request->bearer_contexts_to_be_modified[i].
presence = 1;
modify_bearer_request->bearer_contexts_to_be_modified[i].
eps_bearer_id.presence = 1;
/* Data Plane(DL) : SGW-S5U */
modify_bearer_request->bearer_contexts_to_be_modified[0].
s4_u_sgsn_f_teid.presence = 1;
modify_bearer_request->bearer_contexts_to_be_modified[0].
s4_u_sgsn_f_teid.data = &sgw_s5u_teid;
modify_bearer_request->bearer_contexts_to_be_modified[0].
s4_u_sgsn_f_teid.len = sgw_s5u_len;
/* Bearer Context : EBI */
modify_bearer_request->bearer_contexts_to_be_modified[i].
eps_bearer_id.u8 = ebi[i];
/* Data Plane(DL) : SGW-S5U */
modify_bearer_request->bearer_contexts_to_be_modified[i].
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);
ogs_expect_or_return(pkbuf);
@ -362,7 +381,11 @@ void sgwc_sxa_handle_session_establishment_response(
s5c_xact = ogs_gtp_xact_local_create(
sess->gnode, &send_message.h, pkbuf, sess_timeout, sess);
ogs_expect_or_return(s5c_xact);
s5c_xact->modify_action = OGS_GTP_MODIFY_IN_PATH_SWITCH_REQUEST;
} else {
/* Create Session Request */
recv_message->h.type = OGS_GTP2_CREATE_SESSION_REQUEST_TYPE;
recv_message->h.teid = sess->pgw_s5c_teid;
@ -379,12 +402,14 @@ void sgwc_sxa_handle_session_establishment_response(
presence = 0;
/* Bearer Contexts */
create_session_request->bearer_contexts_to_be_created.
s5_s8_u_sgw_f_teid.presence = 1;
create_session_request->bearer_contexts_to_be_created.
s5_s8_u_sgw_f_teid.data = &sgw_s5u_teid;
create_session_request->bearer_contexts_to_be_created.
s5_s8_u_sgw_f_teid.len = sgw_s5u_len;
for (i = 0; i < num_of_sgw_s5u; i++) {
create_session_request->bearer_contexts_to_be_created[i].
s5_s8_u_sgw_f_teid.presence = 1;
create_session_request->bearer_contexts_to_be_created[i].
s5_s8_u_sgw_f_teid.data = &sgw_s5u_teid[i];
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);
ogs_expect_or_return(pkbuf);
@ -617,7 +642,7 @@ void sgwc_sxa_handle_session_modification_response(
ogs_pfcp_xact_commit(pfcp_xact);
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)) {
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;
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 */
memset(&sgw_s1u_teid, 0, sizeof(ogs_gtp2_f_teid_t));
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_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)) {
sgwc_tunnel_t *tunnel = NULL;
@ -921,10 +943,12 @@ void sgwc_sxa_handle_session_modification_response(
ogs_pfcp_xact_commit(pfcp_xact);
ogs_assert(flags & OGS_PFCP_MODIFY_SESSION);
if (flags & OGS_PFCP_MODIFY_UL_ONLY) {
ogs_gtp2_create_session_response_t *gtp_rsp = NULL;
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);
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;
/* Send Data Plane(UL) : SGW-S1U */
ogs_assert(ul_tunnel);
memset(&sgw_s1u_teid, 0, sizeof(ogs_gtp2_f_teid_t));
sgw_s1u_teid.interface_type = ul_tunnel->interface_type;
sgw_s1u_teid.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, &len);
ogs_assert(rv == OGS_OK);
gtp_rsp->bearer_contexts_created.s1_u_enodeb_f_teid.presence = 1;
gtp_rsp->bearer_contexts_created.s1_u_enodeb_f_teid.data =
&sgw_s1u_teid;
gtp_rsp->bearer_contexts_created.s1_u_enodeb_f_teid.len = len;
i = 0;
ogs_list_for_each(&sess->bearer_list, bearer) {
ogs_assert(i < OGS_BEARER_PER_UE);
ul_tunnel = sgwc_ul_tunnel_in_bearer(bearer);
ogs_assert(ul_tunnel);
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);
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.teid = sgwc_ue->mme_s11_teid;
@ -970,10 +1005,7 @@ void sgwc_sxa_handle_session_modification_response(
ogs_expect(rv == OGS_OK);
} else if (flags & OGS_PFCP_MODIFY_DL_ONLY) {
#if 0 /* FIXME */
ogs_assert(flags & OGS_PFCP_MODIFY_SESSION);
#endif
if (SESSION_SYNC_DONE(sgwc_ue,
if (SGWC_SESSION_SYNC_DONE(sgwc_ue,
OGS_PFCP_SESSION_MODIFICATION_REQUEST_TYPE, flags)) {
ogs_gtp2_modify_bearer_request_t *gtp_req = NULL;
ogs_gtp2_modify_bearer_response_t *gtp_rsp = NULL;
@ -1023,7 +1055,7 @@ void sgwc_sxa_handle_session_modification_response(
/* 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
* during the Handover, Service Request, E-UTRAN Initial Attach,
* 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);
}
}
} else {
ogs_fatal("Invalid modify_flags[0x%llx]", (long long)flags);
ogs_assert_if_reached();
}
} else if (flags & OGS_PFCP_MODIFY_DEACTIVATE) {
if (flags & OGS_PFCP_MODIFY_ERROR_INDICATION) {
/* 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_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_assert(OGS_OK ==
sgwc_gtp_send_downlink_data_notification(
@ -1112,7 +1142,7 @@ void sgwc_sxa_handle_session_modification_response(
ogs_pfcp_xact_commit(pfcp_xact);
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_gtp2_release_access_bearers_response_t *gtp_rsp = NULL;
@ -1194,6 +1224,15 @@ void sgwc_sxa_handle_session_deletion_response(
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) {
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_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
* to pass the `bearer` context. */
(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));
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) {
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(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) {
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;

View File

@ -27,7 +27,7 @@ extern "C" {
#endif
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);

View File

@ -169,7 +169,7 @@ ED3(uint8_t spare:2;,
typedef struct smf_bearer_s {
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;
uint32_t index;
@ -391,6 +391,9 @@ typedef struct smf_sess_s {
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_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);
}
/* User Plane(DL) : SGW-S5C */
/* User Plane(DL) : SGW-S5U */
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,
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_NAS_PROCEDURE_TRANSACTION_IDENTITY_UNASSIGNED,
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;
qos_flow_find_or_add(
&update_list, qos_flow, to_update_node);
&update_list, qos_flow, to_modify_node);
ogs_list_add(
&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();
qos_flow_find_or_add(
&update_list, qos_flow, to_update_node);
&update_list, qos_flow, to_modify_node);
ogs_list_add(
&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)) {
pfcp_flags |= OGS_PFCP_MODIFY_TFT_DELETE;
qos_flow_find_or_add(
&update_list, qos_flow, to_update_node);
&update_list, qos_flow, to_modify_node);
} else {
pfcp_flags |= OGS_PFCP_MODIFY_REMOVE;
qos_flow_find_or_add(
@ -469,7 +469,7 @@ int gsm_handle_pdu_session_modification_request(
}
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) {
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;
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;
}
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
* forwarding downlink packets for the affected bearer(s).
*/
ogs_assert(sess->smf_ue);
smf_sess_t *eutran_sess = smf_sess_find_by_apn(
sess->smf_ue, sess->session.name, OGS_GTP2_RAT_TYPE_EUTRAN);
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));
}
ogs_assert(OGS_OK ==
smf_epc_pfcp_send_deactivation(sess,
OGS_GTP2_CAUSE_RAT_CHANGED_FROM_3GPP_TO_NON_3GPP));
}
smf_bearer_binding(sess);
} else {
@ -994,7 +990,7 @@ test_can_proceed:
ogs_assert(OGS_OK == smf_gtp1_send_delete_pdp_context_response(sess, e->gtp_xact));
break;
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;
}
} else {

View File

@ -427,7 +427,7 @@ int smf_gtp1_send_update_pdp_context_response(
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)
{
int rv;
@ -453,7 +453,36 @@ int smf_gtp_send_create_session_response(
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)
{
int rv;
@ -479,7 +508,7 @@ int smf_gtp_send_delete_session_response(
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)
{
int rv;

View File

@ -38,12 +38,14 @@ int smf_gtp1_send_update_pdp_context_request(
int smf_gtp1_send_update_pdp_context_response(
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);
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);
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);
#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];
struct sockaddr_in sin;
struct sockaddr_in6 sin6;
uint32_t charing_id;
uint32_t charging_id;
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,
&avpch1);
ogs_assert(ret == 0);
charing_id = htobe32(sess->charging.id);
val.os.data = (uint8_t *)&charing_id;
val.os.len = sizeof(charing_id);
charging_id = htobe32(sess->charging.id);
val.os.data = (uint8_t *)&charging_id;
val.os.len = sizeof(charging_id);
ret = fd_msg_avp_setvalue (avpch1, &val);
ogs_assert(ret == 0);
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. */
if (modify_flags) {
modify_flags |= OGS_PFCP_MODIFY_URR|OGS_PFCP_MODIFY_UL_ONLY;
rv = smf_epc_pfcp_send_session_modification_request(sess, pfcp_xact,
modify_flags,
OGS_NAS_PROCEDURE_TRANSACTION_IDENTITY_UNASSIGNED,
OGS_GTP1_CAUSE_REACTIACTION_REQUESTED);
rv = smf_epc_pfcp_send_session_modification_request(
sess, pfcp_xact, NULL, modify_flags,
OGS_NAS_PROCEDURE_TRANSACTION_IDENTITY_UNASSIGNED,
OGS_GTP1_CAUSE_REACTIACTION_REQUESTED);
ogs_assert(rv == OGS_OK);
}
}

View File

@ -110,7 +110,7 @@ ogs_pkbuf_t *smf_n4_build_session_establishment_request(
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)
{
ogs_pfcp_pdr_t *pdr = NULL;
@ -142,7 +142,7 @@ ogs_pkbuf_t *smf_n4_build_session_modification_request(
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_assert(far);
@ -238,22 +238,29 @@ ogs_pkbuf_t *smf_n4_build_session_modification_request(
return pkbuf;
}
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_qos_flow_to_modify_list(
uint8_t type, smf_sess_t *sess, ogs_pfcp_xact_t *xact)
{
ogs_pfcp_message_t pfcp_message;
ogs_pfcp_session_modification_request_t *req = NULL;
ogs_pkbuf_t *pkbuf = NULL;
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;
ogs_debug("QoS Flow Modification Request");
ogs_debug("Bearer Modification Request");
ogs_assert(qos_flow);
sess = qos_flow->sess;
ogs_assert(sess);
ogs_assert(xact);
modify_flags = xact->modify_flags;
@ -270,155 +277,163 @@ ogs_pkbuf_t *smf_n4_build_qos_flow_modification_request(
ogs_pfcp_pdrbuf_init();
}
if (modify_flags & OGS_PFCP_MODIFY_REMOVE) {
/* Remove PDR */
i = 0;
if (qos_flow->dl_pdr) {
ogs_pfcp_tlv_remove_pdr_t *message = &req->remove_pdr[i];
ogs_list_for_each_entry(
&sess->qos_flow_to_modify_list, qos_flow, to_modify_node) {
message->presence = 1;
message->pdr_id.presence = 1;
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 (modify_flags & OGS_PFCP_MODIFY_REMOVE) {
/* Remove PDR */
if (qos_flow->dl_pdr) {
ogs_pfcp_build_create_pdr(
&req->create_pdr[i], i, qos_flow->dl_pdr);
i++;
ogs_pfcp_tlv_remove_pdr_t *message =
&req->remove_pdr[num_of_remove_pdr];
ogs_list_add(&xact->pdr_to_create_list,
&qos_flow->dl_pdr->to_create_node);
message->presence = 1;
message->pdr_id.presence = 1;
message->pdr_id.u16 = qos_flow->dl_pdr->id;
num_of_remove_pdr++;
}
if (qos_flow->ul_pdr) {
ogs_pfcp_build_create_pdr(
&req->create_pdr[i], i, qos_flow->ul_pdr);
i++;
ogs_pfcp_tlv_remove_pdr_t *message =
&req->remove_pdr[num_of_remove_pdr];
ogs_list_add(&xact->pdr_to_create_list,
&qos_flow->ul_pdr->to_create_node);
message->presence = 1;
message->pdr_id.presence = 1;
message->pdr_id.u16 = qos_flow->ul_pdr->id;
num_of_remove_pdr++;
}
/* Create FAR */
i = 0;
/* Remove FAR */
if (qos_flow->dl_far) {
ogs_pfcp_build_create_far(
&req->create_far[i], i, qos_flow->dl_far);
i++;
ogs_pfcp_tlv_remove_far_t *message =
&req->remove_far[num_of_remove_far];
message->presence = 1;
message->far_id.presence = 1;
message->far_id.u32 = qos_flow->dl_far->id;
num_of_remove_far++;
}
if (qos_flow->ul_far) {
ogs_pfcp_build_create_far(
&req->create_far[i], i, qos_flow->ul_far);
i++;
ogs_pfcp_tlv_remove_far_t *message =
&req->remove_far[num_of_remove_far];
message->presence = 1;
message->far_id.presence = 1;
message->far_id.u32 = qos_flow->ul_far->id;
num_of_remove_far++;
}
/* Create QER */
i = 0;
/* Remove QER */
if (qos_flow->qer) {
ogs_pfcp_build_create_qer(
&req->create_qer[i], i, qos_flow->qer);
i++;
ogs_pfcp_tlv_remove_qer_t *message =
&req->remove_qer[num_of_remove_qer];
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 */
i = 0;
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) {
} else {
if (modify_flags & OGS_PFCP_MODIFY_CREATE) {
if (modify_flags & OGS_PFCP_MODIFY_END_MARKER) {
qos_flow->dl_far->
smreq_flags.send_end_marker_packets = 1;
}
/* Create PDR */
if (qos_flow->dl_pdr) {
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(
&req->update_far[i], i, qos_flow->dl_far);
i++;
ogs_list_add(&xact->pdr_to_create_list,
&qos_flow->dl_pdr->to_create_node);
}
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 */
qos_flow->dl_far->smreq_flags.value = 0;
ogs_list_add(&xact->pdr_to_create_list,
&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) {
i = 0;
if (qos_flow->dl_far) {
ogs_pfcp_build_update_far_deactivate(
&req->update_far[i], i, qos_flow->dl_far);
i++;
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 */
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_QOS_MODIFY|
OGS_PFCP_MODIFY_EPC_QOS_UPDATE)) {
/* Update QER */
i = 0;
if (qos_flow->qer) {
ogs_pfcp_build_update_qer(
&req->update_qer[i], i, qos_flow->qer);
i++;
if (modify_flags & OGS_PFCP_MODIFY_ACTIVATE) {
/* Update FAR - Only DL */
if (qos_flow->dl_far) {
if (qos_flow->dl_far->apply_action &
OGS_PFCP_APPLY_ACTION_FORW) {
if (modify_flags & OGS_PFCP_MODIFY_END_MARKER) {
qos_flow->dl_far->
smreq_flags.send_end_marker_packets = 1;
}
ogs_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(
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);
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(
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(
smf_sess_t *sess, ogs_pfcp_xact_t *xact,
ogs_gtp2_message_t *recv_message,
ogs_pfcp_session_modification_response_t *rsp)
{
int i;
@ -940,7 +941,7 @@ void smf_epc_n4_handle_session_modification_response(
} else if (flags & OGS_PFCP_MODIFY_CREATE) {
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) {
/*
@ -1013,7 +1014,7 @@ void smf_epc_n4_handle_session_modification_response(
ogs_assert(linked_bearer);
ogs_assert(OGS_OK ==
smf_gtp_send_delete_bearer_request(
smf_gtp2_send_delete_bearer_request(
linked_bearer, gtp_pti, gtp_cause));
} else {
/*
@ -1034,7 +1035,7 @@ void smf_epc_n4_handle_session_modification_response(
ogs_assert(bearer);
ogs_assert(OGS_OK ==
smf_gtp_send_delete_bearer_request(
smf_gtp2_send_delete_bearer_request(
bearer,
OGS_NAS_PROCEDURE_TRANSACTION_IDENTITY_UNASSIGNED,
gtp_cause));
@ -1043,12 +1044,36 @@ void smf_epc_n4_handle_session_modification_response(
} else if (flags & OGS_PFCP_MODIFY_ACTIVATE) {
if (gtp_xact) {
/* SMF send Update PDP Context Response (GTPv1C) to SGSN */
if (gtp_xact->gtp_version == 1) {
bearer = gtp_xact->data;
smf_gtp1_send_update_pdp_context_response(bearer, gtp_xact);
} 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 {
/* Nothing */

View File

@ -41,6 +41,7 @@ uint8_t smf_epc_n4_handle_session_establishment_response(
ogs_pfcp_session_establishment_response_t *rsp);
void smf_epc_n4_handle_session_modification_response(
smf_sess_t *sess, ogs_pfcp_xact_t *xact,
ogs_gtp2_message_t *gtp2_message,
ogs_pfcp_session_modification_response_t *rsp);
uint8_t smf_epc_n4_handle_session_deletion_response(
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(
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(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);
ogs_expect_or_return_val(xact, OGS_ERROR);
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);
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)
{
int rv;
ogs_pkbuf_t *n4buf = NULL;
ogs_pfcp_header_t h;
ogs_pfcp_xact_t *xact = NULL;
ogs_pfcp_pdr_t *pdr = NULL;
ogs_assert(sess);
if ((flags & OGS_PFCP_MODIFY_ERROR_INDICATION) == 0)
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);
ogs_expect_or_return_val(xact, OGS_ERROR);
xact->assoc_stream = stream;
xact->modify_flags = flags | OGS_PFCP_MODIFY_SESSION;
n4buf = smf_n4_build_session_modification_request(h.type, sess, xact);
ogs_expect_or_return_val(n4buf, OGS_ERROR);
ogs_list_init(&sess->pdr_to_modify_list);
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);
ogs_expect_or_return_val(rv == OGS_OK, OGS_ERROR);
rv = smf_pfcp_send_modify_list(
sess, smf_n4_build_pdr_to_modify_list, xact, duration);
ogs_expect(rv == OGS_OK);
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;
}
return rv;
}
int smf_5gc_pfcp_send_qos_flow_modification_request(smf_bearer_t *qos_flow,
ogs_sbi_stream_t *stream, uint64_t flags)
{
int rv;
ogs_pkbuf_t *n4buf = NULL;
ogs_pfcp_header_t h;
ogs_pfcp_xact_t *xact = 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;
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, qos_flow_5gc_timeout, qos_flow);
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->modify_flags = flags;
n4buf = smf_n4_build_qos_flow_modification_request(h.type, qos_flow, xact);
ogs_expect_or_return_val(n4buf, OGS_ERROR);
ogs_list_init(&sess->qos_flow_to_modify_list);
ogs_list_add(&sess->qos_flow_to_modify_list, &qos_flow->to_modify_node);
rv = ogs_pfcp_xact_update_tx(xact, &h, n4buf);
ogs_expect_or_return_val(rv == OGS_OK, OGS_ERROR);
rv = ogs_pfcp_xact_commit(xact);
rv = smf_pfcp_send_modify_list(
sess, smf_n4_build_qos_flow_to_modify_list, xact, 0);
ogs_expect(rv == OGS_OK);
return rv;
@ -414,16 +429,16 @@ int smf_5gc_pfcp_send_session_deletion_request(
ogs_assert(sess);
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);
ogs_expect_or_return_val(xact, OGS_ERROR);
xact->assoc_stream = stream;
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);
ogs_expect_or_return_val(n4buf, OGS_ERROR);
@ -446,16 +461,16 @@ int smf_epc_pfcp_send_session_establishment_request(
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);
ogs_expect_or_return_val(xact, OGS_ERROR);
xact->epc = true; /* EPC PFCP transaction */
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);
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(
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)
{
int rv;
ogs_pkbuf_t *n4buf = NULL;
ogs_pfcp_header_t h;
ogs_pfcp_xact_t *xact = NULL;
ogs_pfcp_pdr_t *pdr = NULL;
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);
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_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_expect_or_return_val(n4buf, OGS_ERROR);
ogs_list_init(&sess->pdr_to_modify_list);
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);
ogs_expect_or_return_val(rv == OGS_OK, OGS_ERROR);
rv = ogs_pfcp_xact_commit(xact);
rv = smf_pfcp_send_modify_list(
sess, smf_n4_build_pdr_to_modify_list, xact, 0);
ogs_expect(rv == OGS_OK);
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)
{
int rv;
ogs_pkbuf_t *n4buf = NULL;
ogs_pfcp_header_t h;
ogs_pfcp_xact_t *xact = NULL;
smf_sess_t *sess = NULL;
@ -519,10 +530,6 @@ int smf_epc_pfcp_send_bearer_modification_request(
sess = bearer->sess;
ogs_assert(sess);
memset(&h, 0, sizeof(ogs_pfcp_header_t));
h.type = OGS_PFCP_SESSION_MODIFICATION_REQUEST_TYPE;
h.seid = sess->upf_n4_seid;
xact = ogs_pfcp_xact_local_create(
sess->pfcp_node, bearer_epc_timeout, bearer);
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_cause = gtp_cause;
n4buf = smf_n4_build_qos_flow_modification_request(h.type, bearer, xact);
ogs_expect_or_return_val(n4buf, OGS_ERROR);
ogs_list_init(&sess->qos_flow_to_modify_list);
ogs_list_add(&sess->qos_flow_to_modify_list, &bearer->to_modify_node);
rv = ogs_pfcp_xact_update_tx(xact, &h, n4buf);
ogs_expect_or_return_val(rv == OGS_OK, OGS_ERROR);
rv = ogs_pfcp_xact_commit(xact);
rv = smf_pfcp_send_modify_list(
sess, smf_n4_build_qos_flow_to_modify_list, xact, 0);
ogs_expect(rv == OGS_OK);
return rv;
@ -556,10 +561,6 @@ int smf_epc_pfcp_send_session_deletion_request(
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);
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;
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);
ogs_expect_or_return_val(n4buf, OGS_ERROR);
@ -600,6 +605,60 @@ int smf_epc_pfcp_send_session_deletion_request(
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(
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);
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(
smf_sess_t *sess, ogs_sbi_stream_t *stream);
int smf_5gc_pfcp_send_session_modification_request(
smf_sess_t *sess, ogs_sbi_stream_t *stream,
uint64_t flags, ogs_time_t duration);
int smf_5gc_pfcp_send_qos_flow_modification_request(smf_bearer_t *qos_flow,
ogs_sbi_stream_t *stream, uint64_t flags);
int smf_5gc_pfcp_send_qos_flow_modification_request(
smf_bearer_t *qos_flow, ogs_sbi_stream_t *stream,
uint64_t flags);
int smf_5gc_pfcp_send_session_deletion_request(
smf_sess_t *sess, ogs_sbi_stream_t *stream, int trigger);
int smf_epc_pfcp_send_session_establishment_request(
smf_sess_t *sess, void *gtp_xact);
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);
int smf_epc_pfcp_send_bearer_modification_request(
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(
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(
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)
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
smf_5gc_n4_handle_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_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_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;
uint8_t pco_buf[OGS_MAX_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_assert(sess);
bearer = smf_default_bearer_in_sess(sess);
ogs_assert(bearer);
ogs_debug(" SGW_S5C_TEID[0x%x] SMF_N4_TEID[0x%x]",
sess->sgw_s5c_teid, sess->smf_n4_teid);
ogs_debug(" SGW_S5U_TEID[0x%x] PGW_S5U_TEID[0x%x]",
bearer->sgw_s5u_teid, bearer->pgw_s5u_teid);
rsp = &gtp_message.create_session_response;
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_assert_if_reached();
}
/* APN-AMBR
* if PCRF changes APN-AMBR, this should be included. */
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;
}
/* Bearer EBI */
rsp->bearer_contexts_created.presence = 1;
rsp->bearer_contexts_created.eps_bearer_id.presence = 1;
rsp->bearer_contexts_created.eps_bearer_id.u8 = bearer->ebi;
i = 0;
ogs_list_for_each(&sess->bearer_list, bearer) {
ogs_assert(i < OGS_BEARER_PER_UE);
/* Bearer Cause */
memset(&bearer_cause, 0, sizeof(bearer_cause));
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;
ogs_debug(" SGW_S5U_TEID[0x%x] PGW_S5U_TEID[0x%x]",
bearer->sgw_s5u_teid, bearer->pgw_s5u_teid);
/* Bearer QoS
* if PCRF changes Bearer QoS, this should be included. */
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;
/* 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;
rsp->bearer_contexts_created.bearer_level_qos.presence = 1;
ogs_gtp2_build_bearer_qos(&rsp->bearer_contexts_created.bearer_level_qos,
&bearer_qos, bearer_qos_buf, GTP2_BEARER_QOS_LEN);
}
/* 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;
/* Bearer Charging ID */
rsp->bearer_contexts_created.charging_id.presence = 1;
rsp->bearer_contexts_created.charging_id.u32 = sess->charging.id;
/* Bearer QoS
* if PCRF changes Bearer QoS, this should be included. */
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 */
memset(&pgw_s5u_teid, 0, sizeof(ogs_gtp2_f_teid_t));
pgw_s5u_teid.teid = htobe32(bearer->pgw_s5u_teid);
ogs_assert(bearer->pgw_s5u_addr || bearer->pgw_s5u_addr6);
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);
rsp->bearer_contexts_created[i].bearer_level_qos.presence = 1;
ogs_gtp2_build_bearer_qos(
&rsp->bearer_contexts_created[i].bearer_level_qos,
&bearer_qos, bearer_qos_buf[i], GTP2_BEARER_QOS_LEN);
}
switch (sess->gtp_rat_type) {
case OGS_GTP2_RAT_TYPE_EUTRAN:
pgw_s5u_teid.interface_type = OGS_GTP2_F_TEID_S5_S8_PGW_GTP_U;
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;
rsp->bearer_contexts_created.s5_s8_u_sgw_f_teid.len = len;
break;
case OGS_GTP2_RAT_TYPE_WLAN:
pgw_s5u_teid.interface_type = OGS_GTP2_F_TEID_S2B_U_PGW_GTP_U;
rsp->bearer_contexts_created.s12_rnc_f_teid.presence = 1;
rsp->bearer_contexts_created.s12_rnc_f_teid.data = &pgw_s5u_teid;
rsp->bearer_contexts_created.s12_rnc_f_teid.len = len;
break;
default:
ogs_error("Unknown RAT Type [%d]", sess->gtp_rat_type);
ogs_assert_if_reached();
/* Bearer Charging ID */
rsp->bearer_contexts_created[i].charging_id.presence = 1;
rsp->bearer_contexts_created[i].charging_id.u32 = sess->charging.id;
/* Data Plane(UL) : SMF-S5U */
memset(&pgw_s5u_teid[i], 0, sizeof(ogs_gtp2_f_teid_t));
pgw_s5u_teid[i].teid = htobe32(bearer->pgw_s5u_teid);
ogs_assert(bearer->pgw_s5u_addr || bearer->pgw_s5u_addr6);
rv = ogs_gtp2_sockaddr_to_f_teid(
bearer->pgw_s5u_addr, bearer->pgw_s5u_addr6,
&pgw_s5u_teid[i], &pgw_s5u_len[i]);
ogs_expect_or_return_val(rv == OGS_OK, NULL);
switch (sess->gtp_rat_type) {
case OGS_GTP2_RAT_TYPE_EUTRAN:
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;
@ -208,7 +225,7 @@ ogs_pkbuf_t *smf_s5c_build_delete_session_response(
ogs_gtp2_cause_t cause;
uint8_t pco_buf[OGS_MAX_PCO_LEN];
int16_t pco_len;
/* prepare cause */
memset(&cause, 0, sizeof(cause));
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(
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_modify_bearer_response_t *rsp = NULL;
ogs_gtp2_cause_t cause;
smf_ue_t *smf_ue = NULL;
smf_bearer_t *bearer = NULL;
ogs_assert(sess);
smf_ue = sess->smf_ue;
ogs_assert(smf_ue);
ogs_assert(req);
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.len = sizeof(cause);
rsp->bearer_contexts_modified[0].presence = 1;
rsp->bearer_contexts_modified[0].eps_bearer_id.presence = 1;
rsp->bearer_contexts_modified[0].eps_bearer_id.u8 =
req->bearer_contexts_to_be_modified[0].eps_bearer_id.u8;
rsp->bearer_contexts_modified[0].s1_u_enodeb_f_teid.presence = 1;
rsp->bearer_contexts_modified[0].s1_u_enodeb_f_teid.data =
req->bearer_contexts_to_be_modified[0].s1_u_enodeb_f_teid.data;
rsp->bearer_contexts_modified[0].s1_u_enodeb_f_teid.len =
req->bearer_contexts_to_be_modified[0].s1_u_enodeb_f_teid.len;
if (sgw_relocation == true) {
rsp->bearer_contexts_modified[0].cause.presence = 1;
rsp->bearer_contexts_modified[0].cause.len = sizeof(cause);
rsp->bearer_contexts_modified[0].cause.data = &cause;
if (smf_ue->msisdn_len) {
rsp->msisdn.presence = 1;
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 */
gtp_message.h.type = type;
@ -310,7 +357,7 @@ ogs_pkbuf_t *smf_s5c_build_create_bearer_request(
req = &gtp_message.create_bearer_request;
memset(&gtp_message, 0, sizeof(ogs_gtp2_message_t));
/* Linked EBI */
req->linked_eps_bearer_id.presence = 1;
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));
bearer_qos.qci = bearer->qos.index;
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.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);
req = &gtp_message.update_bearer_request;
memset(&gtp_message, 0, sizeof(ogs_gtp2_message_t));
/* Bearer EBI */
req->bearer_contexts.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));
bearer_qos.qci = bearer->qos.index;
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.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);
req = &gtp_message.delete_bearer_request;
memset(&gtp_message, 0, sizeof(ogs_gtp2_message_t));
if (bearer->ebi == linked_bearer->ebi) {
/*
* << 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(
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(
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 buf2[OGS_ADDRSTRLEN];
int rv;
int i, rv;
uint8_t cause_value = 0;
ogs_gtp2_uli_t uli;
@ -82,15 +82,15 @@ uint8_t smf_s5c_handle_create_session_request(
ogs_error("No TEID");
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");
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");
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");
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) {
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) {
ogs_error("No S5/S8 SGW GTP-U TEID");
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");
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) {
ogs_error("No S2b ePDG GTP-U TEID");
cause_value = OGS_GTP2_CAUSE_MANDATORY_IE_MISSING;
@ -248,51 +248,68 @@ uint8_t smf_s5c_handle_create_session_request(
/* Remove all previous bearer */
smf_bearer_remove_all(sess);
/* Setup Default Bearer */
bearer = smf_bearer_add(sess);
ogs_assert(bearer);
/* Setup Bearer */
for (i = 0; i < OGS_BEARER_PER_UE; i++) {
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 */
bearer->ebi = req->bearer_contexts_to_be_created.eps_bearer_id.u8;
decoded = ogs_gtp2_parse_bearer_qos(&bearer_qos,
&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) {
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);
bearer = smf_bearer_add(sess);
ogs_assert(bearer);
break;
case OGS_GTP2_RAT_TYPE_WLAN:
sgw_s5u_teid = req->bearer_contexts_to_be_created.
s2b_u_epdg_f_teid_5.data;
ogs_assert(sgw_s5u_teid);
bearer->sgw_s5u_teid = be32toh(sgw_s5u_teid->teid);
rv = ogs_gtp2_f_teid_to_ip(sgw_s5u_teid, &bearer->sgw_s5u_ip);
ogs_assert(rv == OGS_OK);
break;
default:
ogs_error("Unknown RAT Type [%d]", sess->gtp_rat_type);
ogs_assert_if_reached();
/* Set Bearer EBI */
bearer->ebi = req->bearer_contexts_to_be_created[i].eps_bearer_id.u8;
switch (sess->gtp_rat_type) {
case OGS_GTP2_RAT_TYPE_EUTRAN:
sgw_s5u_teid = req->bearer_contexts_to_be_created[i].
s5_s8_u_sgw_f_teid.data;
ogs_assert(sgw_s5u_teid);
bearer->sgw_s5u_teid = be32toh(sgw_s5u_teid->teid);
rv = ogs_gtp2_f_teid_to_ip(sgw_s5u_teid, &bearer->sgw_s5u_ip);
ogs_assert(rv == OGS_OK);
break;
case OGS_GTP2_RAT_TYPE_WLAN:
sgw_s5u_teid = req->bearer_contexts_to_be_created[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 */
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);
}
/* 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;
}
@ -356,17 +382,14 @@ uint8_t smf_s5c_handle_delete_session_request(
void smf_s5c_handle_modify_bearer_request(
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;
ogs_gtp2_indication_t *indication = NULL;
ogs_gtp2_header_t h;
ogs_pkbuf_t *pkbuf = NULL;
uint64_t flags = 0;
smf_ue_t *smf_ue = NULL;
smf_sess_t *wlan_sess = NULL;
smf_bearer_t *bearer = NULL;
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);
ogs_assert(rv == OGS_OK);
OGS_SETUP_GTP_NODE(sess, xact->gnode);
ogs_debug(" SGW_S5C_TEID[0x%x] SMF_N4_TEID[0x%x]",
sess->sgw_s5c_teid, sess->smf_n4_teid);
}
#if 0 /* TODO */
switch (sess->gtp_rat_type) {
case OGS_GTP2_RAT_TYPE_EUTRAN:
sgw_s5u_teid = req->bearer_contexts_to_be_created.
s5_s8_u_sgw_f_teid.data;
ogs_assert(sgw_s5u_teid);
bearer->sgw_s5u_teid = be32toh(sgw_s5u_teid->teid);
rv = ogs_gtp2_f_teid_to_ip(sgw_s5u_teid, &bearer->sgw_s5u_ip);
ogs_assert(rv == OGS_OK);
/* Check Modify Bearer */
ogs_list_init(&sess->qos_flow_to_modify_list);
break;
case OGS_GTP2_RAT_TYPE_WLAN:
sgw_s5u_teid = req->bearer_contexts_to_be_created.
s2b_u_epdg_f_teid_5.data;
ogs_assert(sgw_s5u_teid);
bearer->sgw_s5u_teid = be32toh(sgw_s5u_teid->teid);
rv = ogs_gtp2_f_teid_to_ip(sgw_s5u_teid, &bearer->sgw_s5u_ip);
ogs_assert(rv == OGS_OK);
break;
default:
ogs_error("Unknown RAT Type [%d]", sess->gtp_rat_type);
ogs_assert_if_reached();
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;
}
/* EPS Bearer ID */
bearer = smf_bearer_find_by_ebi(sess,
req->bearer_contexts_to_be_modified[i].eps_bearer_id.u8);
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]",
bearer->sgw_s5u_teid, bearer->pgw_s5u_teid);
#endif
if (ogs_list_count(&sess->qos_flow_to_modify_list)) {
memset(&h, 0, sizeof(ogs_gtp2_header_t));
h.type = OGS_GTP2_MODIFY_BEARER_RESPONSE_TYPE;
h.teid = sess->sgw_s5c_teid;
/* Need to modify SGW-S5U */
rv = smf_epc_pfcp_send_session_modification_request(sess, xact, gtpbuf,
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);
ogs_expect_or_return(pkbuf);
} else {
rv = ogs_gtp_xact_update_tx(xact, &h, pkbuf);
ogs_expect_or_return(rv == OGS_OK);
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));
/* Check if Handover from Non-3GPP to 3GPP */
ogs_gtp2_indication_t *indication = NULL;
ogs_assert(OGS_OK ==
smf_epc_pfcp_send_session_modification_request(
wlan_sess, 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));
smf_gtp2_send_modify_bearer_response(sess, xact, req, false));
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(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);
void smf_s5c_handle_modify_bearer_request(
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(
smf_sess_t *sess, ogs_gtp_xact_t *xact,
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;
if (gtp2_message.h.teid != 0) {
sess = smf_sess_find_by_teid(gtp2_message.h.teid);
}
if (sess) {
gnode = sess->gnode;
ogs_assert(gnode);
} else {
gnode = e->gnode;
ogs_assert(gnode);
}
gnode = e->gnode;
ogs_assert(gnode);
rv = ogs_gtp_xact_receive(gnode, &gtp2_message.h, &gtp_xact);
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;
if (gtp2_message.h.teid != 0) {
sess = smf_sess_find_by_teid(gtp2_message.h.teid);
}
switch(gtp2_message.h.type) {
case OGS_GTP2_ECHO_REQUEST_TYPE:
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;
case OGS_GTP2_MODIFY_BEARER_REQUEST_TYPE:
smf_s5c_handle_modify_bearer_request(
sess, gtp_xact, &gtp2_message.modify_bearer_request);
sess, gtp_xact, recvbuf, &gtp2_message.modify_bearer_request);
break;
case OGS_GTP2_CREATE_BEARER_RESPONSE_TYPE:
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);
}
if (sess) {
gnode = sess->gnode;
ogs_assert(gnode);
} else {
gnode = e->gnode;
ogs_assert(gnode);
}
gnode = e->gnode;
ogs_assert(gnode);
rv = ogs_gtp1_xact_receive(gnode, &gtp1_message.h, &gtp_xact);
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_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);
if (OGS_FSM_CHECK(&pfcp_node->sm, smf_pfcp_state_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++)
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) {
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");
} 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) {
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;
}
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);
@ -755,7 +758,8 @@ static void upf_gtp_handle_multicast(ogs_pkbuf_t *recvbuf)
ogs_list_for_each(&sess->pfcp.pdr_list, pdr) {
if (pdr->src_if == OGS_PFCP_INTERFACE_CORE) {
ogs_assert(true ==
ogs_pfcp_up_handle_pdr(pdr, recvbuf, &report));
ogs_pfcp_up_handle_pdr(pdr,
OGS_GTPU_MSGTYPE_GPDU, recvbuf, &report));
break;
}
}

View File

@ -43,7 +43,7 @@ int app_initialize(const char *const argv[])
for (i = 0; argv[i]; i++) {
if (strcmp("-c", argv[i]) == 0) {
user_config = true;
user_config = true;
}
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;
}
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(
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(
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(
test_ue_t *test_ue, ogs_s1ap_message_t *message);
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);
break;
case S1AP_ProcedureCode_id_PathSwitchRequest:
tests1ap_handle_path_switch_request_ack(test_ue, pdu);
break;
case S1AP_ProcedureCode_id_HandoverPreparation:
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_bearer_t *bearer = NULL;
ogs_gtp2_message_t gtp_message;
ogs_gtp2_create_session_request_t *req = &gtp_message.create_session_request;
ogs_gtp2_create_session_request_t *req =
&gtp_message.create_session_request;
uint8_t msisdn_buf[OGS_MAX_MSISDN_LEN];
int msisdn_len;
ogs_gtp2_uli_t uli;
char uli_buf[OGS_GTP2_MAX_ULI_LEN];
ogs_gtp2_f_teid_t test_s2b_c_teid, test_s2b_u_teid;
int len;
ogs_gtp2_f_teid_t test_s2b_c_teid, test_s2b_u_teid[OGS_BEARER_PER_UE];
int len, test_s2b_u_len;
ogs_paa_t paa;
ogs_gtp2_ambr_t ambr;
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];
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);
uli.e_cgi.cell_id = test_ue->e_cgi.cell_id;
req->user_location_information.presence = 1;
ogs_gtp2_build_uli(&req->user_location_information, &uli,
ogs_gtp2_build_uli(&req->user_location_information, &uli,
uli_buf, OGS_GTP2_MAX_ULI_LEN);
req->serving_network.presence = 1;
@ -111,7 +112,7 @@ ogs_pkbuf_t *test_s2b_build_create_session_request(
req->access_point_name.data = apn;
req->selection_mode.presence = 1;
req->selection_mode.u8 =
req->selection_mode.u8 =
OGS_GTP2_SELECTION_MODE_MS_OR_NETWORK_PROVIDED_APN;
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.len = sizeof(ambr);
req->bearer_contexts_to_be_created.presence = 1;
req->bearer_contexts_to_be_created.eps_bearer_id.presence = 1;
req->bearer_contexts_to_be_created.eps_bearer_id.u8 = bearer->ebi;
int i = 0;
ogs_list_for_each(&sess->bearer_list, bearer) {
ogs_assert(i < OGS_BEARER_PER_UE);
memset(&test_s2b_u_teid, 0, sizeof(ogs_gtp2_f_teid_t));
test_s2b_u_teid.teid = htobe32(bearer->enb_s1u_teid);
test_s2b_u_teid.interface_type = OGS_GTP2_F_TEID_S2B_U_EPDG_GTP_U;
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[i].presence = 1;
req->bearer_contexts_to_be_created[i].eps_bearer_id.presence = 1;
req->bearer_contexts_to_be_created[i].eps_bearer_id.u8 = bearer->ebi;
req->bearer_contexts_to_be_created.s2b_u_epdg_f_teid_5.presence = 1;
req->bearer_contexts_to_be_created.s2b_u_epdg_f_teid_5.data =
&test_s2b_u_teid;
req->bearer_contexts_to_be_created.s2b_u_epdg_f_teid_5.len = len;
memset(&test_s2b_u_teid[i], 0, sizeof(ogs_gtp2_f_teid_t));
test_s2b_u_teid[i].teid = htobe32(bearer->enb_s1u_teid);
test_s2b_u_teid[i].interface_type = OGS_GTP2_F_TEID_S2B_U_EPDG_GTP_U;
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));
bearer_qos.qci = 8;
bearer_qos.priority_level = 1;
bearer_qos.pre_emption_capability = 0;
bearer_qos.pre_emption_vulnerability = 0;
req->bearer_contexts_to_be_created.bearer_level_qos.presence = 1;
ogs_gtp2_build_bearer_qos(
&req->bearer_contexts_to_be_created.bearer_level_qos,
&bearer_qos, bearer_qos_buf, GTP2_BEARER_QOS_LEN);
req->bearer_contexts_to_be_created[i].s2b_u_epdg_f_teid_5.presence = 1;
req->bearer_contexts_to_be_created[i].s2b_u_epdg_f_teid_5.data =
&test_s2b_u_teid[i];
req->bearer_contexts_to_be_created[i].s2b_u_epdg_f_teid_5.len =
test_s2b_u_len;
memset(&bearer_qos, 0, sizeof(bearer_qos));
bearer_qos.qci = 8;
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.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_gtp2_create_session_response_t *rsp)
{
int rv;
int rv, i;
uint8_t cause_value;
test_bearer_t *bearer = NULL;
@ -58,18 +58,6 @@ void test_s2b_handle_create_session_response(
ogs_error("No S5/S8 TEID");
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) {
ogs_error("No PDN Address Allocation");
return;
@ -78,22 +66,37 @@ void test_s2b_handle_create_session_response(
ogs_expect(
rsp->pdn_address_allocation.data && rsp->pdn_address_allocation.len);
bearer = test_bearer_find_by_sess_ebi(
sess, rsp->bearer_contexts_created.eps_bearer_id.u8);
ogs_assert(bearer);
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 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;
ogs_assert(smf_s2b_c_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,
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 =
ogs_pco_build(pcobuf, OGS_MAX_PCO_LEN, &pco);
req.bearer_contexts_to_be_created.presence = 1;
req.bearer_contexts_to_be_created.eps_bearer_id.presence = 1;
req.bearer_contexts_to_be_created.eps_bearer_id.u8 = 5;
req.bearer_contexts_to_be_created[0].presence = 1;
req.bearer_contexts_to_be_created[0].eps_bearer_id.presence = 1;
req.bearer_contexts_to_be_created[0].eps_bearer_id.u8 = 5;
memset(&bearer_qos, 0, sizeof(bearer_qos));
bearer_qos.pre_emption_vulnerability = 1;
bearer_qos.priority_level = 1;
bearer_qos.pre_emption_capability = 1;
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(
&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);
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,
pco.ids[2].id);
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.
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,
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.
bearer_contexts_to_be_created.tft.presence);
bearer_contexts_to_be_created[0].tft.presence);
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.
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.
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.
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,
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,
&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, 1, bearer_qos.pre_emption_vulnerability);
ABTS_INT_EQUAL(tc, 1, bearer_qos.priority_level);
ABTS_INT_EQUAL(tc, 1, bearer_qos.pre_emption_capability);
ABTS_INT_EQUAL(tc, 5, bearer_qos.qci);
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.
bearer_contexts_to_be_created.cause.presence);
bearer_contexts_to_be_created[0].cause.presence);
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.
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.recovery.presence);
ABTS_INT_EQUAL(tc, 0, req.mme_fq_csid.presence);