mirror of
https://github.com/open5gs/open5gs.git
synced 2026-04-26 10:30:41 +00:00
[HR] Implement handling of UE-initiated PDU Session Modification (#2194)
This commit consolidates the entire ue-mod feature branch into a single update on top of the latest home-routed code.
This commit is contained in:
parent
932101b919
commit
94cf8ee0e0
32 changed files with 2989 additions and 870 deletions
|
|
@ -332,7 +332,7 @@ af:
|
|||
port: 7777
|
||||
client:
|
||||
scp:
|
||||
- uri: http://127.0.0.200:7777
|
||||
- uri: http://127.0.2.200:7777
|
||||
|
||||
udr:
|
||||
sbi:
|
||||
|
|
|
|||
|
|
@ -332,7 +332,7 @@ af:
|
|||
port: 7777
|
||||
client:
|
||||
scp:
|
||||
- uri: http://127.0.0.200:7777
|
||||
- uri: http://127.0.3.200:7777
|
||||
|
||||
udr:
|
||||
sbi:
|
||||
|
|
|
|||
|
|
@ -327,7 +327,7 @@ af:
|
|||
port: 7777
|
||||
client:
|
||||
scp:
|
||||
- uri: http://127.0.0.200:7777
|
||||
- uri: http://127.0.1.200:7777
|
||||
|
||||
udr:
|
||||
sbi:
|
||||
|
|
|
|||
|
|
@ -332,7 +332,7 @@ af:
|
|||
port: 7777
|
||||
client:
|
||||
scp:
|
||||
- uri: http://127.0.0.200:7777
|
||||
- uri: http://127.0.2.200:7777
|
||||
|
||||
udr:
|
||||
sbi:
|
||||
|
|
|
|||
|
|
@ -327,7 +327,7 @@ af:
|
|||
port: 7777
|
||||
client:
|
||||
scp:
|
||||
- uri: http://127.0.0.200:7777
|
||||
- uri: http://127.0.3.200:7777
|
||||
|
||||
udr:
|
||||
sbi:
|
||||
|
|
|
|||
|
|
@ -332,7 +332,7 @@ af:
|
|||
port: 7777
|
||||
client:
|
||||
scp:
|
||||
- uri: http://127.0.0.200:7777
|
||||
- uri: http://127.0.1.200:7777
|
||||
|
||||
udr:
|
||||
sbi:
|
||||
|
|
|
|||
|
|
@ -332,7 +332,7 @@ af:
|
|||
port: 7777
|
||||
client:
|
||||
scp:
|
||||
- uri: http://127.0.0.200:7777
|
||||
- uri: http://127.0.2.200:7777
|
||||
|
||||
udr:
|
||||
sbi:
|
||||
|
|
|
|||
|
|
@ -332,7 +332,7 @@ af:
|
|||
port: 7777
|
||||
client:
|
||||
scp:
|
||||
- uri: http://127.0.0.200:7777
|
||||
- uri: http://127.0.3.200:7777
|
||||
|
||||
udr:
|
||||
sbi:
|
||||
|
|
|
|||
|
|
@ -327,7 +327,7 @@ af:
|
|||
port: 7777
|
||||
client:
|
||||
scp:
|
||||
- uri: http://127.0.0.200:7777
|
||||
- uri: http://127.0.1.200:7777
|
||||
|
||||
udr:
|
||||
sbi:
|
||||
|
|
|
|||
|
|
@ -102,21 +102,22 @@ typedef struct ogs_pfcp_xact_s {
|
|||
#define OGS_PFCP_MODIFY_QOS_DELETE ((uint64_t)1<<16)
|
||||
#define OGS_PFCP_MODIFY_OUTER_HEADER_REMOVAL ((uint64_t)1<<17)
|
||||
#define OGS_PFCP_MODIFY_ACTIVATE ((uint64_t)1<<18)
|
||||
#define OGS_PFCP_MODIFY_DEACTIVATE ((uint64_t)1<<19)
|
||||
#define OGS_PFCP_MODIFY_END_MARKER ((uint64_t)1<<20)
|
||||
#define OGS_PFCP_MODIFY_ERROR_INDICATION ((uint64_t)1<<21)
|
||||
#define OGS_PFCP_MODIFY_XN_HANDOVER ((uint64_t)1<<22)
|
||||
#define OGS_PFCP_MODIFY_N2_HANDOVER ((uint64_t)1<<23)
|
||||
#define OGS_PFCP_MODIFY_HANDOVER_CANCEL ((uint64_t)1<<24)
|
||||
#define OGS_PFCP_MODIFY_HOME_ROUTED_ROAMING ((uint64_t)1<<25)
|
||||
#define OGS_PFCP_MODIFY_URR ((uint64_t)1<<26) /* type of trigger */
|
||||
#define OGS_PFCP_MODIFY_URR_MEAS_METHOD ((uint64_t)1<<27)
|
||||
#define OGS_PFCP_MODIFY_URR_REPORT_TRIGGER ((uint64_t)1<<28)
|
||||
#define OGS_PFCP_MODIFY_URR_QUOTA_VALIDITY_TIME ((uint64_t)1<<29)
|
||||
#define OGS_PFCP_MODIFY_URR_VOLUME_QUOTA ((uint64_t)1<<30)
|
||||
#define OGS_PFCP_MODIFY_URR_TIME_QUOTA ((uint64_t)1<<31)
|
||||
#define OGS_PFCP_MODIFY_URR_VOLUME_THRESH ((uint64_t)1<<32)
|
||||
#define OGS_PFCP_MODIFY_URR_TIME_THRESH ((uint64_t)1<<33)
|
||||
#define OGS_PFCP_MODIFY_FROM_ACTIVATING ((uint64_t)1<<19)
|
||||
#define OGS_PFCP_MODIFY_DEACTIVATE ((uint64_t)1<<20)
|
||||
#define OGS_PFCP_MODIFY_END_MARKER ((uint64_t)1<<21)
|
||||
#define OGS_PFCP_MODIFY_ERROR_INDICATION ((uint64_t)1<<22)
|
||||
#define OGS_PFCP_MODIFY_XN_HANDOVER ((uint64_t)1<<23)
|
||||
#define OGS_PFCP_MODIFY_N2_HANDOVER ((uint64_t)1<<24)
|
||||
#define OGS_PFCP_MODIFY_HANDOVER_CANCEL ((uint64_t)1<<25)
|
||||
#define OGS_PFCP_MODIFY_HOME_ROUTED_ROAMING ((uint64_t)1<<26)
|
||||
#define OGS_PFCP_MODIFY_URR ((uint64_t)1<<27) /* type of trigger */
|
||||
#define OGS_PFCP_MODIFY_URR_MEAS_METHOD ((uint64_t)1<<28)
|
||||
#define OGS_PFCP_MODIFY_URR_REPORT_TRIGGER ((uint64_t)1<<29)
|
||||
#define OGS_PFCP_MODIFY_URR_QUOTA_VALIDITY_TIME ((uint64_t)1<<30)
|
||||
#define OGS_PFCP_MODIFY_URR_VOLUME_QUOTA ((uint64_t)1<<31)
|
||||
#define OGS_PFCP_MODIFY_URR_TIME_QUOTA ((uint64_t)1<<32)
|
||||
#define OGS_PFCP_MODIFY_URR_VOLUME_THRESH ((uint64_t)1<<33)
|
||||
#define OGS_PFCP_MODIFY_URR_TIME_THRESH ((uint64_t)1<<34)
|
||||
uint64_t modify_flags;
|
||||
|
||||
#define OGS_PFCP_DELETE_TRIGGER_LOCAL_INITIATED 1
|
||||
|
|
|
|||
|
|
@ -92,12 +92,9 @@ ogs_sbi_request_t *amf_npcf_am_policy_control_build_create(
|
|||
ogs_error("No ueLocation.nr_location");
|
||||
goto end;
|
||||
}
|
||||
ueLocation.nr_location->ue_location_timestamp =
|
||||
ogs_sbi_gmtime_string(amf_ue->ue_location_timestamp);
|
||||
if (!ueLocation.nr_location->ue_location_timestamp) {
|
||||
ogs_error("No ueLocation.nr_location->ue_location_timestamp");
|
||||
goto end;
|
||||
}
|
||||
if (amf_ue->ue_location_timestamp)
|
||||
ueLocation.nr_location->ue_location_timestamp =
|
||||
ogs_sbi_gmtime_string(amf_ue->ue_location_timestamp);
|
||||
PolicyAssociationRequest.user_loc = &ueLocation;
|
||||
|
||||
PolicyAssociationRequest.time_zone =
|
||||
|
|
|
|||
|
|
@ -160,12 +160,9 @@ ogs_sbi_request_t *amf_nsmf_pdusession_build_create_sm_context(
|
|||
ogs_error("No ueLocation.nr_location");
|
||||
goto end;
|
||||
}
|
||||
ueLocation.nr_location->ue_location_timestamp =
|
||||
ogs_sbi_gmtime_string(amf_ue->ue_location_timestamp);
|
||||
if (!ueLocation.nr_location->ue_location_timestamp) {
|
||||
ogs_error("No ue_location_timestamp");
|
||||
goto end;
|
||||
}
|
||||
if (amf_ue->ue_location_timestamp)
|
||||
ueLocation.nr_location->ue_location_timestamp =
|
||||
ogs_sbi_gmtime_string(amf_ue->ue_location_timestamp);
|
||||
|
||||
SmContextCreateData.ue_location = &ueLocation;
|
||||
SmContextCreateData.ue_time_zone = ogs_sbi_timezone_string(ogs_timezone());
|
||||
|
|
@ -391,12 +388,9 @@ ogs_sbi_request_t *amf_nsmf_pdusession_build_update_sm_context(
|
|||
ogs_error("No ueLocation.nr_location");
|
||||
goto end;
|
||||
}
|
||||
ueLocation.nr_location->ue_location_timestamp =
|
||||
ogs_sbi_gmtime_string(amf_ue->ue_location_timestamp);
|
||||
if (!ueLocation.nr_location->ue_location_timestamp) {
|
||||
ogs_error("No ueLocation.nr_location->ue_location_timestamp");
|
||||
goto end;
|
||||
}
|
||||
if (amf_ue->ue_location_timestamp)
|
||||
ueLocation.nr_location->ue_location_timestamp =
|
||||
ogs_sbi_gmtime_string(amf_ue->ue_location_timestamp);
|
||||
|
||||
SmContextUpdateData.ue_location = &ueLocation;
|
||||
}
|
||||
|
|
@ -490,12 +484,9 @@ ogs_sbi_request_t *amf_nsmf_pdusession_build_release_sm_context(
|
|||
ogs_error("No ueLocation.nr_location");
|
||||
goto end;
|
||||
}
|
||||
ueLocation.nr_location->ue_location_timestamp =
|
||||
ogs_sbi_gmtime_string(amf_ue->ue_location_timestamp);
|
||||
if (!ueLocation.nr_location->ue_location_timestamp) {
|
||||
ogs_error("No ueLocation.nr_location->ue_location_timestamp");
|
||||
goto end;
|
||||
}
|
||||
if (amf_ue->ue_location_timestamp)
|
||||
ueLocation.nr_location->ue_location_timestamp =
|
||||
ogs_sbi_gmtime_string(amf_ue->ue_location_timestamp);
|
||||
|
||||
SmContextReleaseData.ue_location = &ueLocation;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -90,10 +90,6 @@ bool nssf_nnrf_nsselection_handle_get_from_amf_or_vnssf(
|
|||
nssf_home_t *home = nssf_home_find(
|
||||
&recvmsg->param.home_plmn_id, &recvmsg->param.home_snssai);
|
||||
if (!home) {
|
||||
int r, i;
|
||||
nssf_nnssf_nsselection_param_t param;
|
||||
ogs_sbi_discovery_option_t *h_discovery_option = NULL;
|
||||
|
||||
home = nssf_home_add(
|
||||
&recvmsg->param.home_plmn_id, &recvmsg->param.home_snssai);
|
||||
if (!home) {
|
||||
|
|
@ -105,6 +101,12 @@ bool nssf_nnrf_nsselection_handle_get_from_amf_or_vnssf(
|
|||
recvmsg->param.home_snssai.sd.v);
|
||||
goto cleanup;
|
||||
}
|
||||
}
|
||||
|
||||
if (!home->nrf_id || !home->nsi_id) {
|
||||
int r, i;
|
||||
nssf_nnssf_nsselection_param_t param;
|
||||
ogs_sbi_discovery_option_t *h_discovery_option = NULL;
|
||||
|
||||
h_discovery_option = ogs_sbi_discovery_option_new();
|
||||
ogs_assert(h_discovery_option);
|
||||
|
|
|
|||
|
|
@ -1867,8 +1867,8 @@ void smf_sess_remove(smf_sess_t *sess)
|
|||
if (sess->v_smf.client)
|
||||
ogs_sbi_client_remove(sess->v_smf.client);
|
||||
|
||||
if (sess->n1smbuf)
|
||||
ogs_pkbuf_free(sess->n1smbuf);
|
||||
if (sess->n1SmBufFromUe)
|
||||
ogs_pkbuf_free(sess->n1SmBufFromUe);
|
||||
|
||||
OGS_NAS_CLEAR_DATA(&sess->h_smf_extended_protocol_configuration_options);
|
||||
sess->h_smf_gsm_cause = 0;
|
||||
|
|
@ -1876,6 +1876,10 @@ void smf_sess_remove(smf_sess_t *sess)
|
|||
CLEAR_QOS_FLOWS_SETUP_LIST(sess->h_smf_qos_flows_setup_list);
|
||||
CLEAR_QOS_FLOWS_ADD_MOD_REQUEST_LIST(
|
||||
sess->h_smf_qos_flows_add_mod_request_list);
|
||||
CLEAR_QOS_FLOWS_REL_REQUEST_LIST(sess->h_smf_qos_flows_rel_request_list);
|
||||
|
||||
if (sess->pending_modification_xact)
|
||||
ogs_sbi_xact_remove(sess->pending_modification_xact);
|
||||
|
||||
/* Free SBI object memory */
|
||||
ogs_sbi_object_free(&sess->sbi);
|
||||
|
|
|
|||
|
|
@ -78,14 +78,25 @@ typedef struct smf_nsmf_pdusession_param_s {
|
|||
int gsm_cause;
|
||||
|
||||
struct {
|
||||
ED3(uint8_t ue_location:1;,
|
||||
ED4(uint8_t serving_network:1;,
|
||||
uint8_t ue_location:1;,
|
||||
uint8_t ue_timezone:1;,
|
||||
uint8_t spare:6;)
|
||||
uint8_t spare:4;)
|
||||
};
|
||||
|
||||
uint32_t dl_teid;
|
||||
ogs_ip_t dl_ip;
|
||||
|
||||
OpenAPI_access_type_e an_type;
|
||||
OpenAPI_rat_type_e rat_type;
|
||||
|
||||
OpenAPI_up_cnx_state_e up_cnx_state;
|
||||
|
||||
#define QOS_RULE_CODE_FROM_PFCP_FLAGS(pfcp_flags) \
|
||||
(pfcp_flags & OGS_PFCP_MODIFY_CREATE) ? \
|
||||
OGS_NAS_QOS_CODE_CREATE_NEW_QOS_RULE : \
|
||||
(pfcp_flags & OGS_PFCP_MODIFY_REMOVE) ? \
|
||||
OGS_NAS_QOS_CODE_DELETE_EXISTING_QOS_RULE : \
|
||||
(pfcp_flags & OGS_PFCP_MODIFY_TFT_NEW) ? \
|
||||
OGS_NAS_QOS_CODE_CREATE_NEW_QOS_RULE : \
|
||||
(pfcp_flags & OGS_PFCP_MODIFY_TFT_ADD) ? \
|
||||
|
|
@ -98,46 +109,16 @@ typedef struct smf_nsmf_pdusession_param_s {
|
|||
#define QOS_RULE_FLOW_DESCRIPTION_CODE_FROM_PFCP_FLAGS(pfcp_flags) \
|
||||
(pfcp_flags & OGS_PFCP_MODIFY_CREATE) ? \
|
||||
OGS_NAS_CREATE_NEW_QOS_FLOW_DESCRIPTION : \
|
||||
(pfcp_flags & OGS_PFCP_MODIFY_REMOVE) ? \
|
||||
OGS_NAS_DELETE_NEW_QOS_FLOW_DESCRIPTION : \
|
||||
(pfcp_flags & OGS_PFCP_MODIFY_QOS_MODIFY) ? \
|
||||
OGS_NAS_MODIFY_NEW_QOS_FLOW_DESCRIPTION : 0
|
||||
uint8_t qos_flow_description_code;
|
||||
|
||||
uint64_t pfcp_flags;
|
||||
|
||||
} smf_nsmf_pdusession_param_t;
|
||||
|
||||
/* HR flag bit */
|
||||
#define SMF_UECM_FLAG_HR (1 << 7)
|
||||
|
||||
/* Base states (low bits only) */
|
||||
#define SMF_UECM_STATE_NONE 0
|
||||
#define SMF_UECM_STATE_REGISTERED 1
|
||||
#define SMF_UECM_STATE_DEREG_BY_AMF 2
|
||||
#define SMF_UECM_STATE_DEREG_BY_N1N2 3
|
||||
|
||||
/* HR variants (OR base state with HR flag) */
|
||||
#define SMF_UECM_STATE_REGISTERED_HR \
|
||||
(SMF_UECM_STATE_REGISTERED | SMF_UECM_FLAG_HR)
|
||||
#define SMF_UECM_STATE_DEREG_BY_AMF_HR \
|
||||
(SMF_UECM_STATE_DEREG_BY_AMF | SMF_UECM_FLAG_HR)
|
||||
#define SMF_UECM_STATE_DEREG_BY_N1N2_HR \
|
||||
(SMF_UECM_STATE_DEREG_BY_N1N2 | SMF_UECM_FLAG_HR)
|
||||
|
||||
/**
|
||||
* Return true if the PDU session anchor SMF is in the HPLMN
|
||||
* (Home-Routed Roaming, HR)
|
||||
*/
|
||||
static inline bool smf_uecm_anchor_in_hplmn(int state)
|
||||
{
|
||||
return !!(state & SMF_UECM_FLAG_HR);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if the PDU session anchor SMF is in the VPLMN
|
||||
* (Non-Roaming or Local Break-Out Roaming, LBO)
|
||||
*/
|
||||
static inline bool smf_uecm_anchor_in_vplmn(int state)
|
||||
{
|
||||
return !(state & SMF_UECM_FLAG_HR);
|
||||
}
|
||||
|
||||
typedef struct smf_context_s {
|
||||
smf_ctf_config_t ctf_config;
|
||||
const char* diam_conf_path; /* SMF Diameter conf path */
|
||||
|
|
@ -502,6 +483,7 @@ typedef struct smf_sess_s {
|
|||
OpenAPI_qos_flow_setup_item_free(qosFlowSetupItem); \
|
||||
} \
|
||||
OpenAPI_list_free((__lIST)); \
|
||||
(__lIST) = NULL; \
|
||||
} while(0)
|
||||
OpenAPI_list_t *h_smf_qos_flows_setup_list;
|
||||
#define CLEAR_QOS_FLOWS_ADD_MOD_REQUEST_LIST(__lIST) \
|
||||
|
|
@ -515,8 +497,23 @@ typedef struct smf_sess_s {
|
|||
qosFlowAddModifyRequestItem); \
|
||||
} \
|
||||
OpenAPI_list_free((__lIST)); \
|
||||
(__lIST) = NULL; \
|
||||
} while(0)
|
||||
OpenAPI_list_t *h_smf_qos_flows_add_mod_request_list;
|
||||
#define CLEAR_QOS_FLOWS_REL_REQUEST_LIST(__lIST) \
|
||||
do { \
|
||||
OpenAPI_lnode_t *node = NULL; \
|
||||
OpenAPI_list_for_each((__lIST), node) { \
|
||||
OpenAPI_qos_flow_release_request_item_t \
|
||||
*qosFlowReleaseRequestItem = node->data; \
|
||||
if (qosFlowReleaseRequestItem) \
|
||||
OpenAPI_qos_flow_release_request_item_free( \
|
||||
qosFlowReleaseRequestItem); \
|
||||
} \
|
||||
OpenAPI_list_free((__lIST)); \
|
||||
(__lIST) = NULL; \
|
||||
} while(0)
|
||||
OpenAPI_list_t *h_smf_qos_flows_rel_request_list;
|
||||
|
||||
#define HOME_ROUTED_ROAMING_IN_HSMF(__sESS) \
|
||||
((__sESS) && (__sESS)->vsmf_pdu_session_uri)
|
||||
|
|
@ -529,7 +526,7 @@ typedef struct smf_sess_s {
|
|||
* Keeps the n1SmMsg Content (n1smbuf) in the context of the V-SMF
|
||||
* for use when creating the n1SmBufFromUe to send to the H-SMF.
|
||||
*/
|
||||
ogs_pkbuf_t *n1smbuf;
|
||||
ogs_pkbuf_t *n1SmBufFromUe;
|
||||
|
||||
/* PCF ID */
|
||||
char *pcf_id;
|
||||
|
|
@ -677,14 +674,43 @@ typedef struct smf_sess_s {
|
|||
|
||||
ogs_pool_id_t smf_ue_id;
|
||||
|
||||
OpenAPI_resource_status_e resource_status;
|
||||
bool n1_released;
|
||||
bool n2_released;
|
||||
ogs_pool_id_t amf_update_request_stream_id;
|
||||
ogs_pool_id_t n1_n2_modified_stream_id;
|
||||
ogs_pool_id_t n1_n2_released_stream_id;
|
||||
/*
|
||||
* Section 4.3.3.3 'UE or network requested PDU Session Modification
|
||||
* (home-routed roaming)'
|
||||
* - Step 1a: Nsmf_PDUSession_UpdateSMContext Request (AMF -> V-SMF):
|
||||
* - Step 4a: Nsmf_PDUSession_UpdateSMContext Response (V-SMF -> AMF):
|
||||
*/
|
||||
ogs_pool_id_t amf_to_vsmf_modify_stream_id;
|
||||
/*
|
||||
* Section 4.3.3.3 'UE or network requested PDU Session Modification
|
||||
* (home-routed roaming)'
|
||||
* - Step 3: Nsmf_PDUSession_UpdateSMContext Request (V-SMF -> H-SMF):
|
||||
* - Step 15: Nsmf_PDUSession_UpdateSMContext Response (V-SMF -> H-SMF):
|
||||
*/
|
||||
ogs_pool_id_t vsmf_to_hsmf_modify_stream_id;
|
||||
/*
|
||||
* Section 4.3.4.3 'UE or network requested PDU Session Release for
|
||||
* Home-routed Roaming'
|
||||
* - Step 1a: Nsmf_PDUSession_UpdateSMContext Request (AMF -> V-SMF):
|
||||
* - Step 5b: Nsmf_PDUSession_UpdateSMContext Response (V-SMF -> AMF):
|
||||
*/
|
||||
ogs_pool_id_t amf_to_vsmf_release_stream_id;
|
||||
/*
|
||||
* Section 4.3.4.3 'UE or network requested PDU Session Release for
|
||||
* Home-routed Roaming'
|
||||
* - Step 3a: Nsmf_PDUSession_UpdateSMContext Request (V-SMF -> H-SMF):
|
||||
* - Step 14: Nsmf_PDUSession_UpdateSMContext Response (V-SMF -> H-SMF):
|
||||
*/
|
||||
ogs_pool_id_t vsmf_to_hsmf_release_stream_id;
|
||||
|
||||
smf_nsmf_pdusession_param_t nsmf_param;
|
||||
|
||||
bool establishment_accept_sent;
|
||||
ogs_sbi_xact_t *pending_modification_xact;
|
||||
|
||||
} smf_sess_t;
|
||||
|
||||
void smf_context_init(void);
|
||||
|
|
|
|||
|
|
@ -270,6 +270,8 @@ ogs_pkbuf_t *gsm_build_pdu_session_establishment_accept(smf_sess_t *sess)
|
|||
pkbuf = ogs_nas_5gs_plain_encode(&message);
|
||||
ogs_assert(pkbuf);
|
||||
|
||||
sess->establishment_accept_sent = true;
|
||||
|
||||
cleanup:
|
||||
if (authorized_qos_rules->buffer)
|
||||
ogs_free(authorized_qos_rules->buffer);
|
||||
|
|
@ -326,8 +328,8 @@ ogs_pkbuf_t *gsm_build_pdu_session_modification_command(
|
|||
ogs_nas_qos_flow_description_t
|
||||
qos_flow_description[OGS_NAS_MAX_NUM_OF_QOS_FLOW_DESCRIPTION];
|
||||
|
||||
OpenAPI_qos_flow_add_modify_request_item_t *qosFlowAddModifyRequestItem =
|
||||
NULL;
|
||||
OpenAPI_qos_flow_add_modify_request_item_t *qosFlowAddModRequestItem = NULL;
|
||||
OpenAPI_qos_flow_release_request_item_t *qosFlowRelRequestItem = NULL;
|
||||
OpenAPI_lnode_t *node = NULL;
|
||||
int num, len;
|
||||
|
||||
|
|
@ -352,24 +354,44 @@ ogs_pkbuf_t *gsm_build_pdu_session_modification_command(
|
|||
num = 0;
|
||||
OpenAPI_list_for_each(
|
||||
sess->h_smf_qos_flows_add_mod_request_list, node) {
|
||||
qosFlowAddModifyRequestItem = node->data;
|
||||
if (qosFlowAddModifyRequestItem) {
|
||||
qosFlowAddModRequestItem = node->data;
|
||||
if (qosFlowAddModRequestItem &&
|
||||
qosFlowAddModRequestItem->qos_rules) {
|
||||
ogs_nas_qos_rules_t qos_rules;
|
||||
|
||||
len = ogs_base64_decode_len(
|
||||
qosFlowAddModifyRequestItem->qos_rules);
|
||||
qosFlowAddModRequestItem->qos_rules);
|
||||
ogs_assert(len);
|
||||
qos_rules.buffer = ogs_calloc(1, len);
|
||||
ogs_assert(qos_rules.buffer);
|
||||
qos_rules.length =
|
||||
ogs_base64_decode_binary(
|
||||
qos_rules.buffer,
|
||||
qosFlowAddModifyRequestItem->qos_rules);
|
||||
qos_rules.length = ogs_base64_decode_binary(
|
||||
qos_rules.buffer, qosFlowAddModRequestItem->qos_rules);
|
||||
ogs_assert(qos_rules.length);
|
||||
|
||||
ogs_assert(1 ==
|
||||
ogs_nas_parse_qos_rules(
|
||||
&qos_rule[num], &qos_rules));
|
||||
ogs_nas_parse_qos_rules(&qos_rule[num], &qos_rules));
|
||||
|
||||
ogs_free(qos_rules.buffer);
|
||||
|
||||
num++;
|
||||
}
|
||||
}
|
||||
|
||||
OpenAPI_list_for_each(sess->h_smf_qos_flows_rel_request_list, node) {
|
||||
qosFlowRelRequestItem = node->data;
|
||||
if (qosFlowRelRequestItem && qosFlowRelRequestItem->qos_rules) {
|
||||
ogs_nas_qos_rules_t qos_rules;
|
||||
|
||||
len = ogs_base64_decode_len(qosFlowRelRequestItem->qos_rules);
|
||||
ogs_assert(len);
|
||||
qos_rules.buffer = ogs_calloc(1, len);
|
||||
ogs_assert(qos_rules.buffer);
|
||||
qos_rules.length = ogs_base64_decode_binary(
|
||||
qos_rules.buffer, qosFlowRelRequestItem->qos_rules);
|
||||
ogs_assert(qos_rules.length);
|
||||
|
||||
ogs_assert(1 ==
|
||||
ogs_nas_parse_qos_rules(&qos_rule[num], &qos_rules));
|
||||
|
||||
ogs_free(qos_rules.buffer);
|
||||
|
||||
|
|
@ -419,24 +441,53 @@ ogs_pkbuf_t *gsm_build_pdu_session_modification_command(
|
|||
num = 0;
|
||||
OpenAPI_list_for_each(
|
||||
sess->h_smf_qos_flows_add_mod_request_list, node) {
|
||||
qosFlowAddModifyRequestItem = node->data;
|
||||
if (qosFlowAddModifyRequestItem) {
|
||||
qosFlowAddModRequestItem = node->data;
|
||||
if (qosFlowAddModRequestItem &&
|
||||
qosFlowAddModRequestItem->qos_flow_description) {
|
||||
ogs_nas_qos_flow_descriptions_t qos_flow_descriptions;
|
||||
|
||||
len = ogs_base64_decode_len(
|
||||
qosFlowAddModifyRequestItem->qos_flow_description);
|
||||
qosFlowAddModRequestItem->qos_flow_description);
|
||||
ogs_assert(len);
|
||||
qos_flow_descriptions.buffer = ogs_calloc(1, len);
|
||||
ogs_assert(qos_flow_descriptions.buffer);
|
||||
qos_flow_descriptions.length =
|
||||
ogs_base64_decode_binary(
|
||||
qos_flow_descriptions.length = ogs_base64_decode_binary(
|
||||
qos_flow_descriptions.buffer,
|
||||
qosFlowAddModifyRequestItem->qos_flow_description);
|
||||
qosFlowAddModRequestItem->qos_flow_description);
|
||||
ogs_assert(qos_flow_descriptions.length);
|
||||
|
||||
ogs_assert(1 ==
|
||||
ogs_nas_parse_qos_flow_descriptions(
|
||||
&qos_flow_description[num], &qos_flow_descriptions));
|
||||
&qos_flow_description[num],
|
||||
&qos_flow_descriptions));
|
||||
|
||||
ogs_free(qos_flow_descriptions.buffer);
|
||||
|
||||
num++;
|
||||
}
|
||||
}
|
||||
|
||||
OpenAPI_list_for_each(
|
||||
sess->h_smf_qos_flows_rel_request_list, node) {
|
||||
qosFlowRelRequestItem = node->data;
|
||||
if (qosFlowRelRequestItem &&
|
||||
qosFlowRelRequestItem->qos_flow_description) {
|
||||
ogs_nas_qos_flow_descriptions_t qos_flow_descriptions;
|
||||
|
||||
len = ogs_base64_decode_len(
|
||||
qosFlowRelRequestItem->qos_flow_description);
|
||||
ogs_assert(len);
|
||||
qos_flow_descriptions.buffer = ogs_calloc(1, len);
|
||||
ogs_assert(qos_flow_descriptions.buffer);
|
||||
qos_flow_descriptions.length = ogs_base64_decode_binary(
|
||||
qos_flow_descriptions.buffer,
|
||||
qosFlowRelRequestItem->qos_flow_description);
|
||||
ogs_assert(qos_flow_descriptions.length);
|
||||
|
||||
ogs_assert(1 ==
|
||||
ogs_nas_parse_qos_flow_descriptions(
|
||||
&qos_flow_description[num],
|
||||
&qos_flow_descriptions));
|
||||
|
||||
ogs_free(qos_flow_descriptions.buffer);
|
||||
|
||||
|
|
|
|||
|
|
@ -211,22 +211,250 @@ static int reconfigure_packet_filter(
|
|||
} \
|
||||
} while(0);
|
||||
|
||||
int gsm_handle_pdu_session_modification_qos_rules(
|
||||
smf_sess_t *sess,
|
||||
ogs_nas_qos_rules_t *requested_qos_rules,
|
||||
uint64_t *pfcp_flags)
|
||||
{
|
||||
smf_ue_t *smf_ue = NULL;
|
||||
int i, j, num_of_rule = 0;
|
||||
|
||||
ogs_nas_qos_rule_t qos_rule[OGS_NAS_MAX_NUM_OF_QOS_RULE];
|
||||
|
||||
ogs_assert(requested_qos_rules);
|
||||
ogs_assert(pfcp_flags);
|
||||
|
||||
ogs_assert(sess);
|
||||
smf_ue = smf_ue_find_by_id(sess->smf_ue_id);
|
||||
ogs_assert(smf_ue);
|
||||
|
||||
num_of_rule = ogs_nas_parse_qos_rules(qos_rule, requested_qos_rules);
|
||||
if (!num_of_rule) {
|
||||
ogs_error("[%s:%d] Invalid modification request",
|
||||
smf_ue->supi, sess->psi);
|
||||
return OGS_ERROR;
|
||||
}
|
||||
|
||||
for (i = 0; i < num_of_rule; i++) {
|
||||
smf_pf_t *pf = NULL;
|
||||
smf_bearer_t *qos_flow =
|
||||
smf_qos_flow_find_by_qfi(sess, qos_rule[i].identifier);
|
||||
if (!qos_flow) {
|
||||
ogs_error("No Qos Flow");
|
||||
continue;
|
||||
}
|
||||
|
||||
ogs_list_init(&qos_flow->pf_to_add_list);
|
||||
|
||||
if (qos_rule[i].code == OGS_NAS_QOS_CODE_DELETE_EXISTING_QOS_RULE) {
|
||||
smf_pf_remove_all(qos_flow);
|
||||
|
||||
*pfcp_flags |= OGS_PFCP_MODIFY_REMOVE;
|
||||
qos_flow_find_or_add(&sess->qos_flow_to_modify_list,
|
||||
qos_flow, to_modify_node);
|
||||
} else if (qos_rule[i].code ==
|
||||
OGS_NAS_QOS_CODE_CREATE_NEW_QOS_RULE ||
|
||||
qos_rule[i].code ==
|
||||
OGS_NAS_QOS_CODE_MODIFY_EXISTING_QOS_RULE_AND_ADD_PACKET_FILTERS ||
|
||||
qos_rule[i].code ==
|
||||
OGS_NAS_QOS_CODE_MODIFY_EXISTING_QOS_RULE_AND_REPLACE_ALL_PACKET_FILTERS) {
|
||||
|
||||
if (qos_rule[i].code == OGS_NAS_QOS_CODE_CREATE_NEW_QOS_RULE ||
|
||||
qos_rule[i].code == OGS_NAS_QOS_CODE_MODIFY_EXISTING_QOS_RULE_AND_REPLACE_ALL_PACKET_FILTERS)
|
||||
smf_pf_remove_all(qos_flow);
|
||||
|
||||
for (j = 0; j < qos_rule[i].num_of_packet_filter &&
|
||||
j < OGS_MAX_NUM_OF_FLOW_IN_NAS; j++) {
|
||||
|
||||
pf = smf_pf_add(qos_flow);
|
||||
ogs_assert(pf);
|
||||
|
||||
ogs_assert(
|
||||
reconfigure_packet_filter(pf, &qos_rule[i], i) > 0);
|
||||
/*
|
||||
* Refer to lib/ipfw/ogs-ipfw.h
|
||||
* Issue #338
|
||||
*
|
||||
* <DOWNLINK/BI-DIRECTIONAL>
|
||||
* TFT : Local <UE_IP> <UE_PORT> REMOTE <P-CSCF_RTP_IP> <P-CSCF_RTP_PORT>
|
||||
* -->
|
||||
* RULE : Source <P-CSCF_RTP_IP> <P-CSCF_RTP_PORT> Destination <UE_IP> <UE_PORT>
|
||||
*
|
||||
* <UPLINK>
|
||||
* TFT : Local <UE_IP> <UE_PORT> REMOTE <P-CSCF_RTP_IP> <P-CSCF_RTP_PORT>
|
||||
* -->
|
||||
* RULE : Source <UE_IP> <UE_PORT> Destination <P-CSCF_RTP_IP> <P-CSCF_RTP_PORT>
|
||||
*/
|
||||
if (pf->direction == OGS_FLOW_DOWNLINK_ONLY)
|
||||
ogs_ipfw_rule_swap(&pf->ipfw_rule);
|
||||
|
||||
if (pf->flow_description)
|
||||
ogs_free(pf->flow_description);
|
||||
|
||||
/*
|
||||
* Issue #338
|
||||
*
|
||||
* <DOWNLINK/BI-DIRECTIONAL>
|
||||
* RULE : Source <P-CSCF_RTP_IP> <P-CSCF_RTP_PORT> Destination <UE_IP> <UE_PORT>
|
||||
* -->
|
||||
* GX : permit out from <P-CSCF_RTP_IP> <P-CSCF_RTP_PORT> to <UE_IP> <UE_PORT>
|
||||
* PFCP : permit out from <P-CSCF_RTP_IP> <P-CSCF_RTP_PORT> to <UE_IP> <UE_PORT>
|
||||
*
|
||||
* <UPLINK>
|
||||
* RULE : Source <UE_IP> <UE_PORT> Destination <P-CSCF_RTP_IP> <P-CSCF_RTP_PORT>
|
||||
* -->
|
||||
* GX : permit out from <P-CSCF_RTP_IP> <P-CSCF_RTP_PORT> to <UE_IP> <UE_PORT>
|
||||
* PFCP : permit out from <P-CSCF_RTP_IP> <P-CSCF_RTP_PORT> to <UE_IP> <UE_PORT>
|
||||
*/
|
||||
if (pf->direction == OGS_FLOW_UPLINK_ONLY) {
|
||||
ogs_ipfw_rule_t tmp;
|
||||
ogs_ipfw_copy_and_swap(&tmp, &pf->ipfw_rule);
|
||||
pf->flow_description =
|
||||
ogs_ipfw_encode_flow_description(&tmp);
|
||||
ogs_assert(pf->flow_description);
|
||||
} else {
|
||||
pf->flow_description =
|
||||
ogs_ipfw_encode_flow_description(&pf->ipfw_rule);
|
||||
ogs_assert(pf->flow_description);
|
||||
}
|
||||
|
||||
if (qos_rule[i].code ==
|
||||
OGS_NAS_QOS_CODE_CREATE_NEW_QOS_RULE) {
|
||||
*pfcp_flags |= OGS_PFCP_MODIFY_TFT_NEW;
|
||||
} else if (qos_rule[i].code ==
|
||||
OGS_NAS_QOS_CODE_MODIFY_EXISTING_QOS_RULE_AND_ADD_PACKET_FILTERS) {
|
||||
*pfcp_flags |= OGS_PFCP_MODIFY_TFT_ADD;
|
||||
} else if (qos_rule[i].code ==
|
||||
OGS_NAS_QOS_CODE_MODIFY_EXISTING_QOS_RULE_AND_REPLACE_ALL_PACKET_FILTERS) {
|
||||
*pfcp_flags |= OGS_PFCP_MODIFY_TFT_REPLACE;
|
||||
} else
|
||||
ogs_assert_if_reached();
|
||||
|
||||
qos_flow_find_or_add(&sess->qos_flow_to_modify_list,
|
||||
qos_flow, to_modify_node);
|
||||
|
||||
ogs_list_add(
|
||||
&qos_flow->pf_to_add_list, &pf->to_add_node);
|
||||
}
|
||||
} else if (qos_rule[i].code ==
|
||||
OGS_NAS_QOS_CODE_MODIFY_EXISTING_QOS_RULE_AND_DELETE_PACKET_FILTERS) {
|
||||
|
||||
qos_flow->num_of_pf_to_delete = 0;
|
||||
for (j = 0; j < qos_rule[i].num_of_packet_filter &&
|
||||
j < OGS_MAX_NUM_OF_FLOW_IN_NAS; j++) {
|
||||
|
||||
pf = smf_pf_find_by_identifier(
|
||||
qos_flow, qos_rule[i].pf[j].identifier);
|
||||
if (pf) {
|
||||
qos_flow->pf_to_delete
|
||||
[qos_flow->num_of_pf_to_delete++] =
|
||||
qos_rule[i].pf[j].identifier;
|
||||
smf_pf_remove(pf);
|
||||
}
|
||||
}
|
||||
|
||||
if (ogs_list_count(&qos_flow->pf_list)) {
|
||||
*pfcp_flags |= OGS_PFCP_MODIFY_TFT_DELETE;
|
||||
qos_flow_find_or_add(&sess->qos_flow_to_modify_list,
|
||||
qos_flow, to_modify_node);
|
||||
} else {
|
||||
*pfcp_flags |= OGS_PFCP_MODIFY_REMOVE;
|
||||
qos_flow_find_or_add(&sess->qos_flow_to_modify_list,
|
||||
qos_flow, to_modify_node);
|
||||
}
|
||||
}
|
||||
|
||||
if (*pfcp_flags &
|
||||
(OGS_PFCP_MODIFY_TFT_NEW|OGS_PFCP_MODIFY_TFT_ADD|
|
||||
OGS_PFCP_MODIFY_TFT_REPLACE|OGS_PFCP_MODIFY_TFT_DELETE))
|
||||
smf_bearer_tft_update(qos_flow);
|
||||
}
|
||||
|
||||
return OGS_OK;
|
||||
}
|
||||
|
||||
int gsm_handle_pdu_session_modification_qos_flow_descriptions(
|
||||
smf_sess_t *sess,
|
||||
ogs_nas_qos_flow_descriptions_t *requested_qos_flow_descriptions,
|
||||
uint64_t *pfcp_flags)
|
||||
{
|
||||
smf_ue_t *smf_ue = NULL;
|
||||
int i, j, num_of_description = 0;
|
||||
|
||||
ogs_nas_qos_flow_description_t
|
||||
qos_flow_description[OGS_NAS_MAX_NUM_OF_QOS_FLOW_DESCRIPTION];
|
||||
|
||||
ogs_assert(requested_qos_flow_descriptions);
|
||||
ogs_assert(pfcp_flags);
|
||||
|
||||
ogs_assert(sess);
|
||||
smf_ue = smf_ue_find_by_id(sess->smf_ue_id);
|
||||
ogs_assert(smf_ue);
|
||||
|
||||
num_of_description = ogs_nas_parse_qos_flow_descriptions(
|
||||
qos_flow_description, requested_qos_flow_descriptions);
|
||||
if (!num_of_description) {
|
||||
ogs_error("[%s:%d] Invalid modification request",
|
||||
smf_ue->supi, sess->psi);
|
||||
return OGS_ERROR;
|
||||
}
|
||||
|
||||
for (i = 0; i < num_of_description; i++) {
|
||||
smf_bearer_t *qos_flow =
|
||||
smf_qos_flow_find_by_qfi(
|
||||
sess, qos_flow_description[i].identifier);
|
||||
if (!qos_flow) {
|
||||
ogs_error("No Qos Flow");
|
||||
continue;
|
||||
}
|
||||
|
||||
for (j = 0; j < qos_flow_description[i].num_of_parameter; j++) {
|
||||
switch(qos_flow_description[i].param[j].identifier) {
|
||||
case OGS_NAX_QOS_FLOW_PARAMETER_ID_5QI:
|
||||
/* Nothing */
|
||||
break;
|
||||
case OGS_NAX_QOS_FLOW_PARAMETER_ID_GFBR_UPLINK:
|
||||
qos_flow->qos.gbr.uplink = ogs_nas_bitrate_to_uint64(
|
||||
&qos_flow_description[i].param[j].br);
|
||||
break;
|
||||
case OGS_NAX_QOS_FLOW_PARAMETER_ID_GFBR_DOWNLINK:
|
||||
qos_flow->qos.gbr.downlink = ogs_nas_bitrate_to_uint64(
|
||||
&qos_flow_description[i].param[j].br);
|
||||
break;
|
||||
case OGS_NAX_QOS_FLOW_PARAMETER_ID_MFBR_UPLINK:
|
||||
qos_flow->qos.mbr.uplink = ogs_nas_bitrate_to_uint64(
|
||||
&qos_flow_description[i].param[j].br);
|
||||
break;
|
||||
case OGS_NAX_QOS_FLOW_PARAMETER_ID_MFBR_DOWNLINK:
|
||||
qos_flow->qos.mbr.downlink = ogs_nas_bitrate_to_uint64(
|
||||
&qos_flow_description[i].param[j].br);
|
||||
break;
|
||||
default:
|
||||
ogs_fatal("Unknown qos_flow parameter identifier [%d]",
|
||||
qos_flow_description[i].param[i].identifier);
|
||||
ogs_assert_if_reached();
|
||||
}
|
||||
}
|
||||
|
||||
*pfcp_flags |= OGS_PFCP_MODIFY_QOS_MODIFY;
|
||||
qos_flow_find_or_add(&sess->qos_flow_to_modify_list,
|
||||
qos_flow, to_modify_node);
|
||||
|
||||
if (*pfcp_flags & OGS_PFCP_MODIFY_QOS_MODIFY)
|
||||
smf_bearer_qos_update(qos_flow);
|
||||
}
|
||||
|
||||
return OGS_OK;
|
||||
}
|
||||
|
||||
int gsm_handle_pdu_session_modification_request(
|
||||
smf_sess_t *sess, ogs_sbi_stream_t *stream,
|
||||
ogs_nas_5gs_pdu_session_modification_request_t *
|
||||
pdu_session_modification_request)
|
||||
{
|
||||
int i, j;
|
||||
|
||||
int rv;
|
||||
uint64_t pfcp_flags = 0;
|
||||
|
||||
smf_bearer_t *qos_flow = NULL;
|
||||
smf_pf_t *pf = NULL;
|
||||
|
||||
ogs_nas_qos_rule_t qos_rule[OGS_NAS_MAX_NUM_OF_QOS_RULE];
|
||||
ogs_nas_qos_flow_description_t
|
||||
qos_flow_description[OGS_NAS_MAX_NUM_OF_QOS_FLOW_DESCRIPTION];
|
||||
|
||||
ogs_nas_qos_rules_t *requested_qos_rules =
|
||||
&pdu_session_modification_request->requested_qos_rules;
|
||||
ogs_nas_qos_flow_descriptions_t *requested_qos_flow_descriptions =
|
||||
|
|
@ -250,197 +478,23 @@ int gsm_handle_pdu_session_modification_request(
|
|||
|
||||
if (pdu_session_modification_request->presencemask &
|
||||
OGS_NAS_5GS_PDU_SESSION_MODIFICATION_REQUEST_REQUESTED_QOS_RULES_PRESENT) {
|
||||
int num_of_rule = 0;
|
||||
|
||||
num_of_rule = ogs_nas_parse_qos_rules(qos_rule, requested_qos_rules);
|
||||
if (!num_of_rule) {
|
||||
ogs_error("[%s:%d] Invalid modification request",
|
||||
smf_ue->supi, sess->psi);
|
||||
rv = gsm_handle_pdu_session_modification_qos_rules(
|
||||
sess, requested_qos_rules, &pfcp_flags);
|
||||
if (rv != OGS_OK) {
|
||||
ogs_error("gsm_handle_pdu_session_modification_qos_rules() failed");
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
for (i = 0; i < num_of_rule; i++) {
|
||||
qos_flow = smf_qos_flow_find_by_qfi(
|
||||
sess, qos_rule[i].identifier);
|
||||
if (!qos_flow) {
|
||||
ogs_error("No Qos Flow");
|
||||
continue;
|
||||
}
|
||||
|
||||
ogs_list_init(&qos_flow->pf_to_add_list);
|
||||
|
||||
if (qos_rule[i].code == OGS_NAS_QOS_CODE_DELETE_EXISTING_QOS_RULE) {
|
||||
smf_pf_remove_all(qos_flow);
|
||||
|
||||
pfcp_flags |= OGS_PFCP_MODIFY_REMOVE;
|
||||
qos_flow_find_or_add(&sess->qos_flow_to_modify_list,
|
||||
qos_flow, to_modify_node);
|
||||
} else if (qos_rule[i].code ==
|
||||
OGS_NAS_QOS_CODE_CREATE_NEW_QOS_RULE ||
|
||||
qos_rule[i].code ==
|
||||
OGS_NAS_QOS_CODE_MODIFY_EXISTING_QOS_RULE_AND_ADD_PACKET_FILTERS ||
|
||||
qos_rule[i].code ==
|
||||
OGS_NAS_QOS_CODE_MODIFY_EXISTING_QOS_RULE_AND_REPLACE_ALL_PACKET_FILTERS) {
|
||||
|
||||
if (qos_rule[i].code == OGS_NAS_QOS_CODE_CREATE_NEW_QOS_RULE ||
|
||||
qos_rule[i].code == OGS_NAS_QOS_CODE_MODIFY_EXISTING_QOS_RULE_AND_REPLACE_ALL_PACKET_FILTERS)
|
||||
smf_pf_remove_all(qos_flow);
|
||||
|
||||
for (j = 0; j < qos_rule[i].num_of_packet_filter &&
|
||||
j < OGS_MAX_NUM_OF_FLOW_IN_NAS; j++) {
|
||||
|
||||
pf = smf_pf_add(qos_flow);
|
||||
ogs_assert(pf);
|
||||
|
||||
ogs_assert(
|
||||
reconfigure_packet_filter(pf, &qos_rule[i], i) > 0);
|
||||
/*
|
||||
* Refer to lib/ipfw/ogs-ipfw.h
|
||||
* Issue #338
|
||||
*
|
||||
* <DOWNLINK/BI-DIRECTIONAL>
|
||||
* TFT : Local <UE_IP> <UE_PORT> REMOTE <P-CSCF_RTP_IP> <P-CSCF_RTP_PORT>
|
||||
* -->
|
||||
* RULE : Source <P-CSCF_RTP_IP> <P-CSCF_RTP_PORT> Destination <UE_IP> <UE_PORT>
|
||||
*
|
||||
* <UPLINK>
|
||||
* TFT : Local <UE_IP> <UE_PORT> REMOTE <P-CSCF_RTP_IP> <P-CSCF_RTP_PORT>
|
||||
* -->
|
||||
* RULE : Source <UE_IP> <UE_PORT> Destination <P-CSCF_RTP_IP> <P-CSCF_RTP_PORT>
|
||||
*/
|
||||
if (pf->direction == OGS_FLOW_DOWNLINK_ONLY)
|
||||
ogs_ipfw_rule_swap(&pf->ipfw_rule);
|
||||
|
||||
if (pf->flow_description)
|
||||
ogs_free(pf->flow_description);
|
||||
|
||||
/*
|
||||
* Issue #338
|
||||
*
|
||||
* <DOWNLINK/BI-DIRECTIONAL>
|
||||
* RULE : Source <P-CSCF_RTP_IP> <P-CSCF_RTP_PORT> Destination <UE_IP> <UE_PORT>
|
||||
* -->
|
||||
* GX : permit out from <P-CSCF_RTP_IP> <P-CSCF_RTP_PORT> to <UE_IP> <UE_PORT>
|
||||
* PFCP : permit out from <P-CSCF_RTP_IP> <P-CSCF_RTP_PORT> to <UE_IP> <UE_PORT>
|
||||
*
|
||||
* <UPLINK>
|
||||
* RULE : Source <UE_IP> <UE_PORT> Destination <P-CSCF_RTP_IP> <P-CSCF_RTP_PORT>
|
||||
* -->
|
||||
* GX : permit out from <P-CSCF_RTP_IP> <P-CSCF_RTP_PORT> to <UE_IP> <UE_PORT>
|
||||
* PFCP : permit out from <P-CSCF_RTP_IP> <P-CSCF_RTP_PORT> to <UE_IP> <UE_PORT>
|
||||
*/
|
||||
if (pf->direction == OGS_FLOW_UPLINK_ONLY) {
|
||||
ogs_ipfw_rule_t tmp;
|
||||
ogs_ipfw_copy_and_swap(&tmp, &pf->ipfw_rule);
|
||||
pf->flow_description =
|
||||
ogs_ipfw_encode_flow_description(&tmp);
|
||||
ogs_assert(pf->flow_description);
|
||||
} else {
|
||||
pf->flow_description =
|
||||
ogs_ipfw_encode_flow_description(&pf->ipfw_rule);
|
||||
ogs_assert(pf->flow_description);
|
||||
}
|
||||
|
||||
if (qos_rule[i].code ==
|
||||
OGS_NAS_QOS_CODE_CREATE_NEW_QOS_RULE) {
|
||||
pfcp_flags |= OGS_PFCP_MODIFY_TFT_NEW;
|
||||
} else if (qos_rule[i].code ==
|
||||
OGS_NAS_QOS_CODE_MODIFY_EXISTING_QOS_RULE_AND_ADD_PACKET_FILTERS) {
|
||||
pfcp_flags |= OGS_PFCP_MODIFY_TFT_ADD;
|
||||
} else if (qos_rule[i].code ==
|
||||
OGS_NAS_QOS_CODE_MODIFY_EXISTING_QOS_RULE_AND_REPLACE_ALL_PACKET_FILTERS) {
|
||||
pfcp_flags |= OGS_PFCP_MODIFY_TFT_REPLACE;
|
||||
} else
|
||||
ogs_assert_if_reached();
|
||||
|
||||
qos_flow_find_or_add(&sess->qos_flow_to_modify_list,
|
||||
qos_flow, to_modify_node);
|
||||
|
||||
ogs_list_add(
|
||||
&qos_flow->pf_to_add_list, &pf->to_add_node);
|
||||
}
|
||||
} else if (qos_rule[i].code ==
|
||||
OGS_NAS_QOS_CODE_MODIFY_EXISTING_QOS_RULE_AND_DELETE_PACKET_FILTERS) {
|
||||
|
||||
qos_flow->num_of_pf_to_delete = 0;
|
||||
for (j = 0; j < qos_rule[i].num_of_packet_filter &&
|
||||
j < OGS_MAX_NUM_OF_FLOW_IN_NAS; j++) {
|
||||
|
||||
pf = smf_pf_find_by_identifier(
|
||||
qos_flow, qos_rule[i].pf[j].identifier);
|
||||
if (pf) {
|
||||
qos_flow->pf_to_delete
|
||||
[qos_flow->num_of_pf_to_delete++] =
|
||||
qos_rule[i].pf[j].identifier;
|
||||
smf_pf_remove(pf);
|
||||
}
|
||||
}
|
||||
|
||||
if (ogs_list_count(&qos_flow->pf_list)) {
|
||||
pfcp_flags |= OGS_PFCP_MODIFY_TFT_DELETE;
|
||||
qos_flow_find_or_add(&sess->qos_flow_to_modify_list,
|
||||
qos_flow, to_modify_node);
|
||||
} else {
|
||||
pfcp_flags |= OGS_PFCP_MODIFY_REMOVE;
|
||||
qos_flow_find_or_add(&sess->qos_flow_to_modify_list,
|
||||
qos_flow, to_modify_node);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (pdu_session_modification_request->presencemask &
|
||||
OGS_NAS_5GS_PDU_SESSION_MODIFICATION_REQUEST_REQUESTED_QOS_FLOW_DESCRIPTIONS_PRESENT) {
|
||||
int num_of_description = 0;
|
||||
|
||||
num_of_description = ogs_nas_parse_qos_flow_descriptions(
|
||||
qos_flow_description, requested_qos_flow_descriptions);
|
||||
if (!num_of_description) {
|
||||
ogs_error("[%s:%d] Invalid modification request",
|
||||
smf_ue->supi, sess->psi);
|
||||
rv = gsm_handle_pdu_session_modification_qos_flow_descriptions(
|
||||
sess, requested_qos_flow_descriptions, &pfcp_flags);
|
||||
if (rv != OGS_OK) {
|
||||
ogs_error("gsm_handle_pdu_session_modification_"
|
||||
"qos_flow_descriptions() failed");
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
for (i = 0; i < num_of_description; i++) {
|
||||
qos_flow = smf_qos_flow_find_by_qfi(
|
||||
sess, qos_flow_description[i].identifier);
|
||||
if (!qos_flow) {
|
||||
ogs_error("No Qos Flow");
|
||||
continue;
|
||||
}
|
||||
|
||||
for (j = 0; j < qos_flow_description[i].num_of_parameter; j++) {
|
||||
switch(qos_flow_description[i].param[j].identifier) {
|
||||
case OGS_NAX_QOS_FLOW_PARAMETER_ID_5QI:
|
||||
/* Nothing */
|
||||
break;
|
||||
case OGS_NAX_QOS_FLOW_PARAMETER_ID_GFBR_UPLINK:
|
||||
qos_flow->qos.gbr.uplink = ogs_nas_bitrate_to_uint64(
|
||||
&qos_flow_description[i].param[j].br);
|
||||
break;
|
||||
case OGS_NAX_QOS_FLOW_PARAMETER_ID_GFBR_DOWNLINK:
|
||||
qos_flow->qos.gbr.downlink = ogs_nas_bitrate_to_uint64(
|
||||
&qos_flow_description[i].param[j].br);
|
||||
break;
|
||||
case OGS_NAX_QOS_FLOW_PARAMETER_ID_MFBR_UPLINK:
|
||||
qos_flow->qos.mbr.uplink = ogs_nas_bitrate_to_uint64(
|
||||
&qos_flow_description[i].param[j].br);
|
||||
break;
|
||||
case OGS_NAX_QOS_FLOW_PARAMETER_ID_MFBR_DOWNLINK:
|
||||
qos_flow->qos.mbr.downlink = ogs_nas_bitrate_to_uint64(
|
||||
&qos_flow_description[i].param[j].br);
|
||||
break;
|
||||
default:
|
||||
ogs_fatal("Unknown qos_flow parameter identifier [%d]",
|
||||
qos_flow_description[i].param[i].identifier);
|
||||
ogs_assert_if_reached();
|
||||
}
|
||||
}
|
||||
|
||||
pfcp_flags |= OGS_PFCP_MODIFY_QOS_MODIFY;
|
||||
qos_flow_find_or_add(&sess->qos_flow_to_modify_list,
|
||||
qos_flow, to_modify_node);
|
||||
}
|
||||
}
|
||||
|
||||
if (ogs_list_count(&sess->qos_flow_to_modify_list) != 1) {
|
||||
|
|
@ -463,14 +517,6 @@ int gsm_handle_pdu_session_modification_request(
|
|||
|
||||
ogs_assert((pfcp_flags & OGS_PFCP_MODIFY_REMOVE) == 0);
|
||||
|
||||
if (pfcp_flags &
|
||||
(OGS_PFCP_MODIFY_TFT_NEW|OGS_PFCP_MODIFY_TFT_ADD|
|
||||
OGS_PFCP_MODIFY_TFT_REPLACE|OGS_PFCP_MODIFY_TFT_DELETE))
|
||||
smf_bearer_tft_update(qos_flow);
|
||||
|
||||
if (pfcp_flags & OGS_PFCP_MODIFY_QOS_MODIFY)
|
||||
smf_bearer_qos_update(qos_flow);
|
||||
|
||||
} else {
|
||||
ogs_fatal("Unknown PFCP-Flags : [0x%llx]", (long long)pfcp_flags);
|
||||
ogs_assert_if_reached();
|
||||
|
|
|
|||
|
|
@ -31,6 +31,15 @@ int gsm_handle_pdu_session_establishment_request(
|
|||
ogs_nas_5gs_pdu_session_establishment_request_t *
|
||||
pdu_session_establishment_request);
|
||||
|
||||
int gsm_handle_pdu_session_modification_qos_rules(
|
||||
smf_sess_t *sess,
|
||||
ogs_nas_qos_rules_t *requested_qos_rules,
|
||||
uint64_t *pfcp_flags);
|
||||
int gsm_handle_pdu_session_modification_qos_flow_descriptions(
|
||||
smf_sess_t *sess,
|
||||
ogs_nas_qos_flow_descriptions_t *requested_qos_flow_descriptions,
|
||||
uint64_t *pfcp_flags);
|
||||
|
||||
int gsm_handle_pdu_session_modification_request(
|
||||
smf_sess_t *sess, ogs_sbi_stream_t *stream,
|
||||
ogs_nas_5gs_pdu_session_modification_request_t *
|
||||
|
|
|
|||
1313
src/smf/gsm-sm.c
1313
src/smf/gsm-sm.c
File diff suppressed because it is too large
Load diff
|
|
@ -410,14 +410,93 @@ void smf_5gc_n4_handle_session_modification_response(
|
|||
if (flags & OGS_PFCP_MODIFY_HOME_ROUTED_ROAMING) {
|
||||
if (flags & OGS_PFCP_MODIFY_ACTIVATE) {
|
||||
if (flags & OGS_PFCP_MODIFY_DL_ONLY) {
|
||||
if (sess->up_cnx_state == OpenAPI_up_cnx_state_ACTIVATING) {
|
||||
sess->up_cnx_state = OpenAPI_up_cnx_state_ACTIVATED;
|
||||
smf_sbi_send_sm_context_updated_data_up_cnx_state(
|
||||
sess, stream, OpenAPI_up_cnx_state_ACTIVATED);
|
||||
} else {
|
||||
/*
|
||||
* UE-requested PDU Session Modification(ACTIVATED)
|
||||
*
|
||||
* 1. V: OGS_PFCP_MODIFY_HOME_ROUTED_ROAMING|OGS_PFCP_MODIFY_DL_ONLY|
|
||||
* OGS_PFCP_MODIFY_OUTER_HEADER_REMOVAL|OGS_PFCP_MODIFY_ACTIVATE
|
||||
* 2. V: if (sess->up_cnx_state == OpenAPI_up_cnx_state_ACTIVATING)
|
||||
* pfcp_flags |= OGS_PFCP_MODIFY_FROM_ACTIVATING;
|
||||
* 3. V*: flags & OGS_PFCP_MODIFY_FROM_ACTIVATING ?
|
||||
* SMF_UPDATE_STATE_HR_ACTIVATED_FROM_ACTIVATING :
|
||||
* SMF_UPDATE_STATE_HR_ACTIVATED_FROM_NON_ACTIVATING,
|
||||
* 4. V*: OpenAPI_request_indication_UE_REQ_PDU_SES_MOD
|
||||
* 5. V*: smf_nsmf_pdusession_build_hsmf_update_data
|
||||
* 6. H: smf_nsmf_handle_update_data_in_hsmf
|
||||
* 7. H: OpenAPI_request_indication_UE_REQ_PDU_SES_MOD
|
||||
* 8. H: OGS_PFCP_MODIFY_HOME_ROUTED_ROAMING|OGS_PFCP_MODIFY_DL_ONLY|
|
||||
* OGS_PFCP_MODIFY_ACTIVATE
|
||||
* 9. H*: ogs_sbi_send_http_status_no_content
|
||||
* 10. V: case SMF_UPDATE_STATE_HR_ACTIVATED_FROM_ACTIVATING:
|
||||
* sess->up_cnx_state = OpenAPI_up_cnx_state_ACTIVATED;
|
||||
* smf_sbi_send_sm_context_updated_data_up_cnx_state(
|
||||
* OpenAPI_up_cnx_state_ACTIVATED);
|
||||
* case SMF_UPDATE_STATE_HR_ACTIVATED_FROM_NON_ACTIVATING:
|
||||
* ogs_sbi_send_http_status_no_content
|
||||
*/
|
||||
if (HOME_ROUTED_ROAMING_IN_VSMF(sess)) {
|
||||
ogs_assert(stream);
|
||||
|
||||
sess->nsmf_param.request_indication =
|
||||
OpenAPI_request_indication_UE_REQ_PDU_SES_MOD;
|
||||
|
||||
sess->nsmf_param.up_cnx_state =
|
||||
OpenAPI_up_cnx_state_ACTIVATED;
|
||||
|
||||
sess->nsmf_param.serving_network = true;
|
||||
|
||||
ogs_assert(OGS_OK ==
|
||||
ogs_sockaddr_to_ip(
|
||||
sess->local_dl_addr, sess->local_dl_addr6,
|
||||
&sess->nsmf_param.dl_ip));
|
||||
sess->nsmf_param.dl_teid = sess->local_dl_teid;
|
||||
|
||||
sess->nsmf_param.an_type = sess->an_type;
|
||||
sess->nsmf_param.rat_type = sess->sbi_rat_type;
|
||||
|
||||
r = smf_sbi_discover_and_send(
|
||||
OGS_SBI_SERVICE_TYPE_NSMF_PDUSESSION, NULL,
|
||||
smf_nsmf_pdusession_build_hsmf_update_data,
|
||||
sess, stream,
|
||||
flags & OGS_PFCP_MODIFY_FROM_ACTIVATING ?
|
||||
SMF_UPDATE_STATE_ACTIVATED_FROM_ACTIVATING :
|
||||
SMF_UPDATE_STATE_ACTIVATED_FROM_NON_ACTIVATING,
|
||||
NULL);
|
||||
ogs_expect(r == OGS_OK);
|
||||
ogs_assert(r != OGS_ERROR);
|
||||
} else if (HOME_ROUTED_ROAMING_IN_HSMF(sess)) {
|
||||
/*
|
||||
* Network-requested PDU Session Modification
|
||||
*
|
||||
* 1. H: OpenAPI_request_indication_NW_REQ_PDU_SES_MOD
|
||||
* QOS_RULE_CODE_FROM_PFCP_FLAGS
|
||||
* QOS_RULE_FLOW_DESCRIPTION_CODE_FROM_PFCP_FLAGS
|
||||
* 2. H: smf_nsmf_pdusession_build_vsmf_update_data
|
||||
* 3. V: smf_nsmf_handle_update_data_in_vsmf
|
||||
* 4. V: gsm_build_pdu_session_modification_command+
|
||||
* ngap_build_pdu_session_resource_modify_request_transfer
|
||||
* 5. V: OpenAPI_n2_sm_info_type_PDU_RES_MOD_RSP
|
||||
* if (sess->up_cnx_state == OpenAPI_up_cnx_state_ACTIVATING)
|
||||
* sess->up_cnx_state = OpenAPI_up_cnx_state_ACTIVATED;
|
||||
* smf_sbi_send_sm_context_updated_data_up_cnx_state(
|
||||
* OpenAPI_up_cnx_state_ACTIVATED)
|
||||
* else
|
||||
* ogs_sbi_send_http_status_no_content(stream)
|
||||
* 6. V: ogs_sbi_send_http_status_no_content(stream)
|
||||
* OGS_NAS_5GS_PDU_SESSION_MODIFICATION_COMPLETE:
|
||||
* ogs_sbi_send_http_status_no_content(n1_n2_modified_stream));
|
||||
* 7. V: case OGS_EVENT_SBI_CLIENT
|
||||
* CASE(OGS_SBI_RESOURCE_NAME_VSMF_PDU_SESSIONS)
|
||||
* 8. H: OGS_PFCP_MODIFY_HOME_ROUTED_ROAMING|
|
||||
* OGS_PFCP_MODIFY_DL_ONLY|OGS_PFCP_MODIFY_ACTIVATE
|
||||
* 9. H*: ogs_sbi_send_http_status_no_content
|
||||
*/
|
||||
if (stream)
|
||||
ogs_assert(true ==
|
||||
ogs_sbi_send_http_status_no_content(stream));
|
||||
ogs_sbi_send_http_status_no_content(stream));
|
||||
} else {
|
||||
ogs_fatal("Invalid flags [0x%llx]", (long long)flags);
|
||||
ogs_assert_if_reached();
|
||||
}
|
||||
} else if (flags & OGS_PFCP_MODIFY_UL_ONLY) {
|
||||
smf_n1_n2_message_transfer_param_t param;
|
||||
|
|
@ -433,66 +512,252 @@ void smf_5gc_n4_handle_session_modification_response(
|
|||
ogs_assert(param.n2smbuf);
|
||||
|
||||
smf_namf_comm_send_n1_n2_message_transfer(sess, NULL, ¶m);
|
||||
|
||||
if (sess->pending_modification_xact) {
|
||||
if (ogs_sbi_discover_and_send(
|
||||
sess->pending_modification_xact) != OGS_OK) {
|
||||
ogs_error("ogs_sbi_discover_and_send() failed");
|
||||
ogs_sbi_xact_remove(sess->pending_modification_xact);
|
||||
}
|
||||
|
||||
sess->pending_modification_xact = NULL;
|
||||
}
|
||||
} else {
|
||||
ogs_fatal("Invalid flags [0x%llx]", (long long)flags);
|
||||
ogs_assert_if_reached();
|
||||
}
|
||||
} else if (flags & OGS_PFCP_MODIFY_DEACTIVATE) {
|
||||
ogs_assert(trigger);
|
||||
if (flags & OGS_PFCP_MODIFY_DL_ONLY) {
|
||||
/*
|
||||
* UE-requested PDU Session Modification(DEACTIVATED)
|
||||
*
|
||||
* For Home Routed Roaming, delegate PFCP deactivation to H-SMF by
|
||||
* sending UP_CNX_STATE=DEACTIVATED via HsmfUpdateData.
|
||||
*
|
||||
* 1. V: OpenAPI_request_indication_UE_REQ_PDU_SES_MOD
|
||||
* 2. V: smf_nsmf_pdusession_build_hsmf_update_data
|
||||
* SMF_UPDATE_STATE_HR_DEACTIVATED
|
||||
* 3. H: smf_nsmf_handle_update_data_in_hsmf
|
||||
* 4. H: OpenAPI_request_indication_UE_REQ_PDU_SES_MOD
|
||||
* 5. H: OGS_PFCP_MODIFY_HOME_ROUTED_ROAMING|OGS_PFCP_MODIFY_DL_ONLY|
|
||||
* OGS_PFCP_MODIFY_DEACTIVATE
|
||||
* 6. H*: ogs_sbi_send_http_status_no_content
|
||||
* 7. V: case SMF_UPDATE_STATE_HR_DEACTIVATED:
|
||||
* 8. V: smf_sbi_send_sm_context_updated_data_up_cnx_state(
|
||||
* OpenAPI_up_cnx_state_DEACTIVATED)
|
||||
*/
|
||||
ogs_assert(true == ogs_sbi_send_http_status_no_content(stream));
|
||||
} else if (flags & OGS_PFCP_MODIFY_UL_ONLY) {
|
||||
ogs_assert(trigger);
|
||||
|
||||
if (trigger == OGS_PFCP_DELETE_TRIGGER_UE_REQUESTED) {
|
||||
r = smf_sbi_discover_and_send(
|
||||
OGS_SBI_SERVICE_TYPE_NSMF_PDUSESSION, NULL,
|
||||
smf_nsmf_pdusession_build_hsmf_update_data,
|
||||
sess, stream, trigger, NULL);
|
||||
ogs_expect(r == OGS_OK);
|
||||
ogs_assert(r != OGS_ERROR);
|
||||
} else if (trigger ==
|
||||
OGS_PFCP_DELETE_TRIGGER_AMF_UPDATE_SM_CONTEXT) {
|
||||
r = smf_sbi_discover_and_send(
|
||||
OGS_SBI_SERVICE_TYPE_NSMF_PDUSESSION, NULL,
|
||||
smf_nsmf_pdusession_build_hsmf_update_data,
|
||||
sess, stream, trigger, NULL);
|
||||
ogs_expect(r == OGS_OK);
|
||||
ogs_assert(r != OGS_ERROR);
|
||||
} else if (trigger ==
|
||||
OGS_PFCP_DELETE_TRIGGER_AMF_RELEASE_SM_CONTEXT) {
|
||||
r = smf_sbi_discover_and_send(
|
||||
OGS_SBI_SERVICE_TYPE_NSMF_PDUSESSION, NULL,
|
||||
smf_nsmf_pdusession_build_release_data,
|
||||
sess, stream, trigger, NULL);
|
||||
ogs_expect(r == OGS_OK);
|
||||
ogs_assert(r != OGS_ERROR);
|
||||
if (trigger == OGS_PFCP_DELETE_TRIGGER_UE_REQUESTED) {
|
||||
/*
|
||||
* UE-requested PDU Session Release
|
||||
*
|
||||
* 1. V: OGS_PFCP_MODIFY_HOME_ROUTED_ROAMING|OGS_PFCP_MODIFY_UL_ONLY|
|
||||
* OGS_PFCP_MODIFY_DEACTIVATE
|
||||
* 2. V: OGS_PFCP_DELETE_TRIGGER_UE_REQUESTED
|
||||
* 3. V*: OpenAPI_request_indication_UE_REQ_PDU_SES_REL
|
||||
* 4. V*: smf_nsmf_pdusession_build_hsmf_update_data
|
||||
* 5. H: smf_nsmf_handle_update_data_in_hsmf
|
||||
* 6. H: OpenAPI_request_indication_UE_REQ_PDU_SES_REL
|
||||
* 6. H: e->h.sbi.state = OGS_PFCP_DELETE_TRIGGER_UE_REQUESTED
|
||||
* 7. H: ogs_sbi_send_http_status_no_content
|
||||
* 8. H: OGS_FSM_TRAN(s, smf_gsm_state_wait_pfcp_deletion)
|
||||
* 9. H: smf_nsmf_pdusession_build_vsmf_update_data
|
||||
* 10. H: OGS_FSM_TRAN(s, smf_gsm_state_wait_5gc_n1_n2_release);
|
||||
* 11. V: smf_nsmf_handle_update_data_in_vsmf
|
||||
* 12. V: OpenAPI_request_indication_UE_REQ_PDU_SES_REL
|
||||
* 13. V: e->h.sbi.state = OGS_PFCP_DELETE_TRIGGER_UE_REQUESTED
|
||||
* 14. V: OGS_FSM_TRAN(s, smf_gsm_state_wait_pfcp_deletion)
|
||||
* 15. V: ngap_build_pdu_session_resource_release_command_transfer+
|
||||
* gsm_build_pdu_session_release_command
|
||||
* 16 V: OGS_FSM_TRAN(&sess->sm, smf_gsm_state_wait_5gc_n1_n2_release)
|
||||
17. V: case OpenAPI_n2_sm_info_type_PDU_RES_REL_RSP:
|
||||
case OGS_NAS_5GS_PDU_SESSION_RELEASE_COMPLETE:
|
||||
* 18. V: ogs_sbi_send_http_status_no_content(n1_n2_released_stream)
|
||||
* 19. V: OGS_FSM_TRAN(s, smf_gsm_state_5gc_session_will_deregister);
|
||||
* 20. H: case OGS_EVENT_SBI_CLIENT:
|
||||
* 21. H: CASE(OGS_SBI_RESOURCE_NAME_VSMF_PDU_SESSIONS)
|
||||
* 22. H: smf_sbi_cleanup_session(SMF_UECM_STATE_DEREG_BY_N1N2_HR
|
||||
* SMF_SBI_CLEANUP_MODE_POLICY_FIRST);
|
||||
* 23. H: smf_sbi_send_status_notify+SMF_SESS_CLEAR(sess)
|
||||
* 24. V: case OGS_EVENT_SBI_SERVER:
|
||||
* 25. V: CASE(OGS_SBI_RESOURCE_NAME_VSMF_PDU_SESSIONS)
|
||||
* 26. V: ogs_sbi_send_http_status_no_content+
|
||||
* smf_sbi_send_sm_context_status_notify
|
||||
* 27. V: OGS_FSM_TRAN(s, smf_gsm_state_session_will_release);
|
||||
*/
|
||||
sess->nsmf_param.request_indication =
|
||||
OpenAPI_request_indication_UE_REQ_PDU_SES_REL;
|
||||
|
||||
r = smf_sbi_discover_and_send(
|
||||
OGS_SBI_SERVICE_TYPE_NSMF_PDUSESSION, NULL,
|
||||
smf_nsmf_pdusession_build_hsmf_update_data,
|
||||
sess, stream, trigger, NULL);
|
||||
ogs_expect(r == OGS_OK);
|
||||
ogs_assert(r != OGS_ERROR);
|
||||
} else if (trigger ==
|
||||
OGS_PFCP_DELETE_TRIGGER_AMF_UPDATE_SM_CONTEXT) {
|
||||
/*
|
||||
* Network-requested PDU Session Release(DUPLICATED)
|
||||
*
|
||||
* 1. V: OGS_PFCP_MODIFY_HOME_ROUTED_ROAMING|OGS_PFCP_MODIFY_UL_ONLY|
|
||||
* OGS_PFCP_MODIFY_DEACTIVATE
|
||||
* 2. V: OGS_PFCP_DELETE_TRIGGER_AMF_UPDATE_SM_CONTEXT,
|
||||
* 3. V*: OpenAPI_request_indication_NW_REQ_PDU_SES_REL
|
||||
* 4. V*: smf_nsmf_pdusession_build_hsmf_update_data
|
||||
* 5. H: smf_nsmf_handle_update_data_in_hsmf
|
||||
* 6. H: OpenAPI_request_indication_NW_REQ_PDU_SES_REL
|
||||
* 6. H: e->h.sbi.state = OGS_PFCP_DELETE_TRIGGER_AMF_UPDATE_SM_CONTEXT
|
||||
* 7. H: ogs_sbi_send_http_status_no_content
|
||||
* 8. H: OGS_FSM_TRAN(s, smf_gsm_state_wait_pfcp_deletion)
|
||||
* 9. H: smf_sbi_cleanup_session(SMF_UECM_STATE_DEREG_BY_AMF_HR
|
||||
* SMF_SBI_CLEANUP_MODE_POLICY_FIRST);
|
||||
* 10. H: OGS_FSM_TRAN(s, smf_gsm_state_5gc_session_will_deregister);
|
||||
* 11. H: SMF_SESS_CLEAR(sess)
|
||||
* 12. V: e->h.sbi.state = OGS_PFCP_DELETE_TRIGGER_AMF_UPDATE_SM_CONTEXT
|
||||
* 13. V: OGS_FSM_TRAN(s, smf_gsm_state_wait_pfcp_deletion)
|
||||
* 14. V: ogs_sbi_send_http_status_no_content
|
||||
* 15. V: OGS_FSM_TRAN(s, smf_gsm_state_session_will_release);
|
||||
*/
|
||||
sess->nsmf_param.request_indication =
|
||||
OpenAPI_request_indication_NW_REQ_PDU_SES_REL;
|
||||
|
||||
r = smf_sbi_discover_and_send(
|
||||
OGS_SBI_SERVICE_TYPE_NSMF_PDUSESSION, NULL,
|
||||
smf_nsmf_pdusession_build_hsmf_update_data,
|
||||
sess, stream, trigger, NULL);
|
||||
ogs_expect(r == OGS_OK);
|
||||
ogs_assert(r != OGS_ERROR);
|
||||
} else if (trigger ==
|
||||
OGS_PFCP_DELETE_TRIGGER_AMF_RELEASE_SM_CONTEXT) {
|
||||
/*
|
||||
* Network-requested PDU Session Release
|
||||
*
|
||||
* 1. V: smf_nsmf_handle_release_sm_context
|
||||
* 2. V: OGS_PFCP_MODIFY_HOME_ROUTED_ROAMING|OGS_PFCP_MODIFY_UL_ONLY|
|
||||
* OGS_PFCP_MODIFY_DEACTIVATE
|
||||
* 3. V: OGS_PFCP_DELETE_TRIGGER_AMF_RELEASE_SM_CONTEXT
|
||||
* 4. V*: smf_nsmf_pdusession_build_release_data
|
||||
* 5. H: smf_nsmf_handle_release_data_in_hsmf
|
||||
* 6. H: e->h.sbi.state = OGS_PFCP_DELETE_TRIGGER_AMF_RELEASE_SM_CONTEXT
|
||||
* 7. H: OGS_FSM_TRAN(s, smf_gsm_state_wait_pfcp_deletion)
|
||||
* 8. H: ogs_sbi_send_http_status_no_content
|
||||
* 9. H: smf_sbi_cleanup_session(SMF_UECM_STATE_DEREG_BY_AMF_HR
|
||||
* SMF_SBI_CLEANUP_MODE_POLICY_FIRST);
|
||||
* 10. H: OGS_FSM_TRAN(s, smf_gsm_state_5gc_session_will_deregister);
|
||||
* 11. H: SMF_SESS_CLEAR(sess)
|
||||
* 12. V: smf_nsmf_handle_release_data_in_hsmf
|
||||
* 13. V: e->h.sbi.state = OGS_PFCP_DELETE_TRIGGER_AMF_RELEASE_SM_CONTEXT
|
||||
* 14. V: OGS_FSM_TRAN(s, smf_gsm_state_wait_pfcp_deletion)
|
||||
* 15. V: ogs_sbi_send_http_status_no_content
|
||||
* 16. V: OGS_FSM_TRAN(s, smf_gsm_state_session_will_release);
|
||||
*/
|
||||
r = smf_sbi_discover_and_send(
|
||||
OGS_SBI_SERVICE_TYPE_NSMF_PDUSESSION, NULL,
|
||||
smf_nsmf_pdusession_build_release_data,
|
||||
sess, stream, trigger, NULL);
|
||||
ogs_expect(r == OGS_OK);
|
||||
ogs_assert(r != OGS_ERROR);
|
||||
} else {
|
||||
ogs_fatal("Invalid delete trigger[%d]", trigger);
|
||||
ogs_assert_if_reached();
|
||||
}
|
||||
} else {
|
||||
ogs_fatal("Invalid delete trigger[%d]", trigger);
|
||||
ogs_fatal("Invalid flags [0x%llx]", (long long)flags);
|
||||
ogs_assert_if_reached();
|
||||
}
|
||||
} else if (flags & OGS_PFCP_MODIFY_CREATE) {
|
||||
if (flags & OGS_PFCP_MODIFY_NETWORK_REQUESTED) {
|
||||
memset(&sess->nsmf_param, 0, sizeof(sess->nsmf_param));
|
||||
} else if (
|
||||
(flags & OGS_PFCP_MODIFY_REMOVE) ||
|
||||
(flags & OGS_PFCP_MODIFY_CREATE) ||
|
||||
(flags &
|
||||
(OGS_PFCP_MODIFY_TFT_NEW|OGS_PFCP_MODIFY_TFT_ADD|
|
||||
OGS_PFCP_MODIFY_TFT_REPLACE|OGS_PFCP_MODIFY_TFT_DELETE|
|
||||
OGS_PFCP_MODIFY_QOS_MODIFY))) {
|
||||
/*
|
||||
* UE or Network requested PDU Session Modification
|
||||
*
|
||||
* 1. H*: OpenAPI_request_indication_NW_REQ_PDU_SES_MOD
|
||||
* QOS_RULE_CODE_FROM_PFCP_FLAGS
|
||||
* QOS_RULE_FLOW_DESCRIPTION_CODE_FROM_PFCP_FLAGS
|
||||
* 2. H*: smf_nsmf_pdusession_build_vsmf_update_data
|
||||
* 3. V: smf_nsmf_handle_update_data_in_vsmf
|
||||
* 4. V: gsm_build_pdu_session_modification_command+
|
||||
* ngap_build_pdu_session_resource_modify_request_transfer
|
||||
* 5. V: OpenAPI_n2_sm_info_type_PDU_RES_MOD_RSP
|
||||
* if (sess->up_cnx_state == OpenAPI_up_cnx_state_ACTIVATING)
|
||||
* sess->up_cnx_state = OpenAPI_up_cnx_state_ACTIVATED;
|
||||
* smf_sbi_send_sm_context_updated_data_up_cnx_state(
|
||||
* OpenAPI_up_cnx_state_ACTIVATED)
|
||||
* else
|
||||
* ogs_sbi_send_http_status_no_content(stream)
|
||||
* 6. V: ogs_sbi_send_http_status_no_content(stream)
|
||||
* OGS_NAS_5GS_PDU_SESSION_MODIFICATION_COMPLETE:
|
||||
* ogs_sbi_send_http_status_no_content(n1_n2_modified_stream));
|
||||
* 7. V: case OGS_EVENT_SBI_CLIENT
|
||||
* CASE(OGS_SBI_RESOURCE_NAME_VSMF_PDU_SESSIONS)
|
||||
* 8. H: OGS_PFCP_MODIFY_HOME_ROUTED_ROAMING|
|
||||
* OGS_PFCP_MODIFY_DL_ONLY|OGS_PFCP_MODIFY_ACTIVATE
|
||||
*/
|
||||
int state = 0;
|
||||
|
||||
/* Network Requested PDU Session Modification */
|
||||
memset(&sess->nsmf_param, 0, sizeof(sess->nsmf_param));
|
||||
if (flags & OGS_PFCP_MODIFY_NETWORK_REQUESTED) {
|
||||
sess->nsmf_param.request_indication =
|
||||
OpenAPI_request_indication_NW_REQ_PDU_SES_MOD;
|
||||
sess->nsmf_param.qos_rule_code =
|
||||
QOS_RULE_CODE_FROM_PFCP_FLAGS(flags);
|
||||
sess->nsmf_param.qos_flow_description_code =
|
||||
QOS_RULE_FLOW_DESCRIPTION_CODE_FROM_PFCP_FLAGS(flags);
|
||||
|
||||
r = smf_sbi_discover_and_send(
|
||||
OGS_SBI_SERVICE_TYPE_NSMF_PDUSESSION, NULL,
|
||||
smf_nsmf_pdusession_build_vsmf_update_data,
|
||||
sess, NULL, 0, NULL);
|
||||
ogs_expect(r == OGS_OK);
|
||||
ogs_assert(r != OGS_ERROR);
|
||||
|
||||
} else if (flags & OGS_PFCP_MODIFY_UE_REQUESTED) {
|
||||
sess->nsmf_param.request_indication =
|
||||
OpenAPI_request_indication_UE_REQ_PDU_SES_MOD;
|
||||
} else {
|
||||
ogs_fatal("Invalid PDR-Create flags [0x%llx]",
|
||||
(long long)flags);
|
||||
ogs_fatal("Invalid flags [0x%llx]", (long long)flags);
|
||||
ogs_assert_if_reached();
|
||||
}
|
||||
sess->nsmf_param.qos_rule_code =
|
||||
QOS_RULE_CODE_FROM_PFCP_FLAGS(flags);
|
||||
sess->nsmf_param.qos_flow_description_code =
|
||||
QOS_RULE_FLOW_DESCRIPTION_CODE_FROM_PFCP_FLAGS(flags);
|
||||
|
||||
if (flags & OGS_PFCP_MODIFY_REMOVE) {
|
||||
if (flags & OGS_PFCP_MODIFY_INDIRECT) {
|
||||
ogs_fatal("Invalid flags [0x%llx]", (long long)flags);
|
||||
ogs_assert_if_reached();
|
||||
}
|
||||
|
||||
state = SMF_REMOVE_STATE_NONE;
|
||||
} else if (flags & OGS_PFCP_MODIFY_CREATE) {
|
||||
state = SMF_CREATE_STATE_NONE;
|
||||
} else if (flags &
|
||||
(OGS_PFCP_MODIFY_TFT_NEW|OGS_PFCP_MODIFY_TFT_ADD|
|
||||
OGS_PFCP_MODIFY_TFT_REPLACE|OGS_PFCP_MODIFY_TFT_DELETE|
|
||||
OGS_PFCP_MODIFY_QOS_MODIFY)) {
|
||||
state = SMF_UPDATE_STATE_NONE;
|
||||
}
|
||||
|
||||
r = smf_sbi_discover_and_send(
|
||||
OGS_SBI_SERVICE_TYPE_NSMF_PDUSESSION, NULL,
|
||||
smf_nsmf_pdusession_build_vsmf_update_data,
|
||||
sess, NULL, state, NULL);
|
||||
ogs_expect(r == OGS_OK);
|
||||
ogs_assert(r != OGS_ERROR);
|
||||
|
||||
if (state == SMF_REMOVE_STATE_NONE) {
|
||||
smf_bearer_t *next = NULL;
|
||||
ogs_list_for_each_entry_safe(&sess->qos_flow_to_modify_list,
|
||||
next, qos_flow, to_modify_node) {
|
||||
smf_sess_t *sess = smf_sess_find_by_id(qos_flow->sess_id);
|
||||
ogs_assert(sess);
|
||||
smf_metrics_inst_by_5qi_add(
|
||||
&sess->serving_plmn_id,
|
||||
&sess->s_nssai,
|
||||
sess->session.qos.index,
|
||||
SMF_METR_GAUGE_SM_QOSFLOWNBR, -1);
|
||||
smf_bearer_remove(qos_flow);
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
ogs_fatal("Invalid flags [%lld]", (long long)flags);
|
||||
ogs_fatal("Invalid flags [0x%llx]", (long long)flags);
|
||||
ogs_assert_if_reached();
|
||||
}
|
||||
} else if (flags & OGS_PFCP_MODIFY_ACTIVATE) {
|
||||
|
|
|
|||
|
|
@ -66,9 +66,17 @@ bool smf_namf_comm_handle_n1_n2_message_transfer(
|
|||
if (recvmsg->res_status == OGS_SBI_HTTP_STATUS_OK) {
|
||||
if (N1N2MessageTransferRspData->cause ==
|
||||
OpenAPI_n1_n2_message_transfer_cause_N1_N2_TRANSFER_INITIATED) {
|
||||
if (stream)
|
||||
sess->n1_n2_modified_stream_id =
|
||||
if (stream) {
|
||||
if (sess->vsmf_to_hsmf_modify_stream_id >=
|
||||
OGS_MIN_POOL_ID &&
|
||||
sess->vsmf_to_hsmf_modify_stream_id <=
|
||||
OGS_MAX_POOL_ID)
|
||||
ogs_error("N1 N2 modified stream ID [%d]"
|
||||
"has not been used yet",
|
||||
sess->vsmf_to_hsmf_modify_stream_id);
|
||||
sess->vsmf_to_hsmf_modify_stream_id =
|
||||
ogs_sbi_id_from_stream(stream);
|
||||
}
|
||||
} else {
|
||||
ogs_error("Not implemented [cause:%d]",
|
||||
N1N2MessageTransferRspData->cause);
|
||||
|
|
@ -82,6 +90,18 @@ bool smf_namf_comm_handle_n1_n2_message_transfer(
|
|||
sess, recvmsg->http.location);
|
||||
else
|
||||
ogs_error("No HTTP Location");
|
||||
|
||||
if (stream) {
|
||||
if (sess->vsmf_to_hsmf_modify_stream_id >=
|
||||
OGS_MIN_POOL_ID &&
|
||||
sess->vsmf_to_hsmf_modify_stream_id <=
|
||||
OGS_MAX_POOL_ID)
|
||||
ogs_error("N1 N2 modified stream ID [%d]"
|
||||
"has not been used yet",
|
||||
sess->vsmf_to_hsmf_modify_stream_id);
|
||||
sess->vsmf_to_hsmf_modify_stream_id =
|
||||
ogs_sbi_id_from_stream(stream);
|
||||
}
|
||||
} else {
|
||||
ogs_error("Not implemented [cause:%d]",
|
||||
N1N2MessageTransferRspData->cause);
|
||||
|
|
@ -173,9 +193,16 @@ bool smf_namf_comm_handle_n1_n2_message_transfer(
|
|||
smf_namf_comm_send_n1_n2_message_transfer(sess, NULL, ¶m);
|
||||
} else if (N1N2MessageTransferRspData->cause ==
|
||||
OpenAPI_n1_n2_message_transfer_cause_N1_N2_TRANSFER_INITIATED) {
|
||||
if (stream)
|
||||
sess->n1_n2_released_stream_id =
|
||||
if (stream) {
|
||||
if (sess->vsmf_to_hsmf_release_stream_id >=
|
||||
OGS_MIN_POOL_ID &&
|
||||
sess->vsmf_to_hsmf_release_stream_id <= OGS_MAX_POOL_ID)
|
||||
ogs_error("N1 N2 released stream ID [%d]"
|
||||
"has not been used yet",
|
||||
sess->vsmf_to_hsmf_release_stream_id);
|
||||
sess->vsmf_to_hsmf_release_stream_id =
|
||||
ogs_sbi_id_from_stream(stream);
|
||||
}
|
||||
} else {
|
||||
ogs_error("Not implemented [cause:%d]",
|
||||
N1N2MessageTransferRspData->cause);
|
||||
|
|
|
|||
|
|
@ -399,10 +399,10 @@ ogs_pkbuf_t *ngap_build_pdu_session_resource_modify_request_transfer(
|
|||
OpenAPI_list_for_each(
|
||||
sess->h_smf_qos_flows_add_mod_request_list, node) {
|
||||
OpenAPI_qos_flow_add_modify_request_item_t
|
||||
*qosFlowAddModifyRequestItem = node->data;
|
||||
if (qosFlowAddModifyRequestItem) {
|
||||
*qosFlowAddModRequestItem = node->data;
|
||||
if (qosFlowAddModRequestItem) {
|
||||
OpenAPI_qos_flow_profile_t *qosFlowProfile =
|
||||
qosFlowAddModifyRequestItem->qos_flow_profile;
|
||||
qosFlowAddModRequestItem->qos_flow_profile;
|
||||
if (qosFlowProfile) {
|
||||
ogs_qos_t qos;
|
||||
|
||||
|
|
@ -469,12 +469,12 @@ ogs_pkbuf_t *ngap_build_pdu_session_resource_modify_request_transfer(
|
|||
QosFlowAddOrModifyRequestItem);
|
||||
|
||||
QosFlowAddOrModifyRequestItem->qosFlowIdentifier =
|
||||
qosFlowAddModifyRequestItem->qfi;
|
||||
qosFlowAddModRequestItem->qfi;
|
||||
|
||||
QosFlowAddOrModifyRequestItem->qosFlowLevelQosParameters =
|
||||
CALLOC(1, sizeof(NGAP_QosFlowLevelQosParameters_t));
|
||||
ogs_assert(
|
||||
QosFlowAddOrModifyRequestItem->qosFlowLevelQosParameters);
|
||||
ogs_assert(QosFlowAddOrModifyRequestItem->
|
||||
qosFlowLevelQosParameters);
|
||||
|
||||
fill_qos_level_parameters(
|
||||
QosFlowAddOrModifyRequestItem->
|
||||
|
|
@ -537,20 +537,43 @@ ogs_pkbuf_t *ngap_build_pdu_session_resource_release_request_transfer(
|
|||
|
||||
QosFlowListWithCause = &ie->value.choice.QosFlowListWithCause;
|
||||
|
||||
ogs_list_for_each_entry(
|
||||
&sess->qos_flow_to_modify_list, qos_flow, to_modify_node) {
|
||||
/* Home-Routed V-SMF: QoS flow */
|
||||
if (HOME_ROUTED_ROAMING_IN_VSMF(sess)) {
|
||||
OpenAPI_lnode_t *node = NULL;
|
||||
OpenAPI_list_for_each(sess->h_smf_qos_flows_rel_request_list, node) {
|
||||
OpenAPI_qos_flow_release_request_item_t
|
||||
*qosFlowRelRequestItem = node->data;
|
||||
if (qosFlowRelRequestItem) {
|
||||
|
||||
QosFlowWithCauseItem = CALLOC(1, sizeof(*QosFlowWithCauseItem));
|
||||
ASN_SEQUENCE_ADD(&QosFlowListWithCause->list, QosFlowWithCauseItem);
|
||||
QosFlowWithCauseItem = CALLOC(1, sizeof(*QosFlowWithCauseItem));
|
||||
ASN_SEQUENCE_ADD(&QosFlowListWithCause->list,
|
||||
QosFlowWithCauseItem);
|
||||
|
||||
qosFlowIdentifier = &QosFlowWithCauseItem->qosFlowIdentifier;
|
||||
qosFlowIdentifier = &QosFlowWithCauseItem->qosFlowIdentifier;
|
||||
|
||||
*qosFlowIdentifier = qos_flow->qfi;
|
||||
*qosFlowIdentifier = qosFlowRelRequestItem->qfi;
|
||||
|
||||
Cause = &QosFlowWithCauseItem->cause;
|
||||
Cause->present = group;
|
||||
Cause->choice.radioNetwork = cause;
|
||||
Cause = &QosFlowWithCauseItem->cause;
|
||||
Cause->present = group;
|
||||
Cause->choice.radioNetwork = cause;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
ogs_list_for_each_entry(
|
||||
&sess->qos_flow_to_modify_list, qos_flow, to_modify_node) {
|
||||
|
||||
QosFlowWithCauseItem = CALLOC(1, sizeof(*QosFlowWithCauseItem));
|
||||
ASN_SEQUENCE_ADD(&QosFlowListWithCause->list, QosFlowWithCauseItem);
|
||||
|
||||
qosFlowIdentifier = &QosFlowWithCauseItem->qosFlowIdentifier;
|
||||
|
||||
*qosFlowIdentifier = qos_flow->qfi;
|
||||
|
||||
Cause = &QosFlowWithCauseItem->cause;
|
||||
Cause->present = group;
|
||||
Cause->choice.radioNetwork = cause;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
return ogs_asn_encode(
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@ int ngap_handle_pdu_session_resource_setup_response_transfer(
|
|||
smf_ue_t *smf_ue = NULL;
|
||||
smf_bearer_t *qos_flow = NULL;
|
||||
|
||||
int rv, i;
|
||||
int rv, i, r;
|
||||
|
||||
uint32_t remote_dl_teid;
|
||||
ogs_ip_t remote_dl_ip;
|
||||
|
|
@ -162,26 +162,81 @@ int ngap_handle_pdu_session_resource_setup_response_transfer(
|
|||
}
|
||||
|
||||
if (far_update) {
|
||||
uint64_t pfcp_flags = OGS_PFCP_MODIFY_DL_ONLY|OGS_PFCP_MODIFY_ACTIVATE;
|
||||
if (HOME_ROUTED_ROAMING_IN_VSMF(sess)) {
|
||||
/*
|
||||
* UE-requested PDU Session Modification(ACTIVATED)
|
||||
*
|
||||
* 1. V: OGS_PFCP_MODIFY_HOME_ROUTED_ROAMING|OGS_PFCP_MODIFY_DL_ONLY|
|
||||
* OGS_PFCP_MODIFY_OUTER_HEADER_REMOVAL|OGS_PFCP_MODIFY_ACTIVATE
|
||||
* 2. V*: if (sess->up_cnx_state == OpenAPI_up_cnx_state_ACTIVATING)
|
||||
* pfcp_flags |= OGS_PFCP_MODIFY_FROM_ACTIVATING;
|
||||
* 3. V: flags & OGS_PFCP_MODIFY_FROM_ACTIVATING ?
|
||||
* SMF_UPDATE_STATE_HR_ACTIVATED_FROM_ACTIVATING :
|
||||
* SMF_UPDATE_STATE_HR_ACTIVATED_FROM_NON_ACTIVATING,
|
||||
* 4. V: OpenAPI_request_indication_UE_REQ_PDU_SES_MOD
|
||||
* 5. V: smf_nsmf_pdusession_build_hsmf_update_data
|
||||
* 6. H: smf_nsmf_handle_update_data_in_hsmf
|
||||
* 7. H: OpenAPI_request_indication_UE_REQ_PDU_SES_MOD
|
||||
* 8. H: OGS_PFCP_MODIFY_HOME_ROUTED_ROAMING|OGS_PFCP_MODIFY_DL_ONLY|
|
||||
* OGS_PFCP_MODIFY_ACTIVATE
|
||||
* 9. H: ogs_sbi_send_http_status_no_content
|
||||
* 10. V: case SMF_UPDATE_STATE_HR_ACTIVATED_FROM_ACTIVATING:
|
||||
* sess->up_cnx_state = OpenAPI_up_cnx_state_ACTIVATED;
|
||||
* smf_sbi_send_sm_context_updated_data_up_cnx_state(
|
||||
* OpenAPI_up_cnx_state_ACTIVATED);
|
||||
* case SMF_UPDATE_STATE_HR_ACTIVATED_FROM_NON_ACTIVATING:
|
||||
* ogs_sbi_send_http_status_no_content
|
||||
*/
|
||||
pfcp_flags |= OGS_PFCP_MODIFY_HOME_ROUTED_ROAMING;
|
||||
pfcp_flags |= OGS_PFCP_MODIFY_OUTER_HEADER_REMOVAL;
|
||||
|
||||
if (sess->up_cnx_state == OpenAPI_up_cnx_state_ACTIVATING)
|
||||
pfcp_flags |= OGS_PFCP_MODIFY_FROM_ACTIVATING;
|
||||
}
|
||||
|
||||
ogs_assert(OGS_OK ==
|
||||
smf_5gc_pfcp_send_all_pdr_modification_request(
|
||||
sess, stream,
|
||||
HOME_ROUTED_ROAMING_IN_VSMF(sess) ?
|
||||
(OGS_PFCP_MODIFY_HOME_ROUTED_ROAMING|
|
||||
OGS_PFCP_MODIFY_DL_ONLY|
|
||||
OGS_PFCP_MODIFY_OUTER_HEADER_REMOVAL|
|
||||
OGS_PFCP_MODIFY_ACTIVATE) :
|
||||
(OGS_PFCP_MODIFY_DL_ONLY|OGS_PFCP_MODIFY_ACTIVATE), 0, 0));
|
||||
sess, stream, pfcp_flags, 0, 0));
|
||||
} else {
|
||||
#if 0 /* Modified by pull request #1729 */
|
||||
/* ACTIVATED Is NOT Included in RESPONSE */
|
||||
ogs_assert(true == ogs_sbi_send_http_status_no_content(stream));
|
||||
#else
|
||||
if (sess->up_cnx_state == OpenAPI_up_cnx_state_ACTIVATING) {
|
||||
sess->up_cnx_state = OpenAPI_up_cnx_state_ACTIVATED;
|
||||
smf_sbi_send_sm_context_updated_data_up_cnx_state(
|
||||
sess, stream, OpenAPI_up_cnx_state_ACTIVATED);
|
||||
if (HOME_ROUTED_ROAMING_IN_VSMF(sess)) {
|
||||
sess->nsmf_param.request_indication =
|
||||
OpenAPI_request_indication_UE_REQ_PDU_SES_MOD;
|
||||
|
||||
sess->nsmf_param.up_cnx_state = OpenAPI_up_cnx_state_ACTIVATED;
|
||||
|
||||
sess->nsmf_param.serving_network = true;
|
||||
|
||||
ogs_assert(OGS_OK ==
|
||||
ogs_sockaddr_to_ip(
|
||||
sess->local_dl_addr, sess->local_dl_addr6,
|
||||
&sess->nsmf_param.dl_ip));
|
||||
sess->nsmf_param.dl_teid = sess->local_dl_teid;
|
||||
|
||||
sess->nsmf_param.an_type = sess->an_type;
|
||||
sess->nsmf_param.rat_type = sess->sbi_rat_type;
|
||||
|
||||
r = smf_sbi_discover_and_send(
|
||||
OGS_SBI_SERVICE_TYPE_NSMF_PDUSESSION, NULL,
|
||||
smf_nsmf_pdusession_build_hsmf_update_data, sess, stream,
|
||||
sess->up_cnx_state == OpenAPI_up_cnx_state_ACTIVATING ?
|
||||
SMF_UPDATE_STATE_ACTIVATED_FROM_ACTIVATING :
|
||||
SMF_UPDATE_STATE_ACTIVATED_FROM_NON_ACTIVATING,
|
||||
NULL);
|
||||
ogs_expect(r == OGS_OK);
|
||||
ogs_assert(r != OGS_ERROR);
|
||||
} else {
|
||||
ogs_assert(true == ogs_sbi_send_http_status_no_content(stream));
|
||||
if (sess->up_cnx_state == OpenAPI_up_cnx_state_ACTIVATING) {
|
||||
sess->up_cnx_state = OpenAPI_up_cnx_state_ACTIVATED;
|
||||
smf_sbi_send_sm_context_updated_data_up_cnx_state(
|
||||
sess, stream, OpenAPI_up_cnx_state_ACTIVATED);
|
||||
} else {
|
||||
ogs_assert(true == ogs_sbi_send_http_status_no_content(stream));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
|
|
|||
|
|
@ -165,12 +165,9 @@ ogs_sbi_request_t *smf_npcf_smpolicycontrol_build_create(
|
|||
ogs_error("ueLocation.nr_location");
|
||||
goto end;
|
||||
}
|
||||
ueLocation.nr_location->ue_location_timestamp =
|
||||
ogs_sbi_gmtime_string(sess->ue_location_timestamp);
|
||||
if (!ueLocation.nr_location->ue_location_timestamp) {
|
||||
ogs_error("ueLocation.nr_location->ue_location_timestamp");
|
||||
goto end;
|
||||
}
|
||||
if (sess->ue_location_timestamp)
|
||||
ueLocation.nr_location->ue_location_timestamp =
|
||||
ogs_sbi_gmtime_string(sess->ue_location_timestamp);
|
||||
|
||||
SmPolicyContextData.user_location_info = &ueLocation;
|
||||
|
||||
|
|
@ -405,12 +402,9 @@ ogs_sbi_request_t *smf_npcf_smpolicycontrol_build_delete(
|
|||
ogs_error("ueLocation.nr_location");
|
||||
goto end;
|
||||
}
|
||||
ueLocation.nr_location->ue_location_timestamp =
|
||||
ogs_sbi_gmtime_string(sess->ue_location_timestamp);
|
||||
if (!ueLocation.nr_location->ue_location_timestamp) {
|
||||
ogs_error("ueLocation.nr_location->ue_location_timestamp");
|
||||
goto end;
|
||||
}
|
||||
if (sess->ue_location_timestamp)
|
||||
ueLocation.nr_location->ue_location_timestamp =
|
||||
ogs_sbi_gmtime_string(sess->ue_location_timestamp);
|
||||
|
||||
SmPolicyDeleteData.user_location_info = &ueLocation;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -166,12 +166,9 @@ ogs_sbi_request_t *smf_nsmf_pdusession_build_create_data(
|
|||
ogs_error("No ueLocation.nr_location");
|
||||
goto end;
|
||||
}
|
||||
ueLocation.nr_location->ue_location_timestamp =
|
||||
ogs_sbi_gmtime_string(sess->ue_location_timestamp);
|
||||
if (!ueLocation.nr_location->ue_location_timestamp) {
|
||||
ogs_error("No ue_location_timestamp");
|
||||
goto end;
|
||||
}
|
||||
if (sess->ue_location_timestamp)
|
||||
ueLocation.nr_location->ue_location_timestamp =
|
||||
ogs_sbi_gmtime_string(sess->ue_location_timestamp);
|
||||
|
||||
PduSessionCreateData.ue_location = &ueLocation;
|
||||
PduSessionCreateData.ue_time_zone = ogs_sbi_timezone_string(ogs_timezone());
|
||||
|
|
@ -211,8 +208,8 @@ ogs_sbi_request_t *smf_nsmf_pdusession_build_create_data(
|
|||
goto end;
|
||||
}
|
||||
|
||||
ogs_assert(sess->n1smbuf);
|
||||
rv = ogs_nas_5gsm_decode(&nas_message, sess->n1smbuf);
|
||||
ogs_assert(sess->n1SmBufFromUe);
|
||||
rv = ogs_nas_5gsm_decode(&nas_message, sess->n1SmBufFromUe);
|
||||
|
||||
if (rv == OGS_OK) {
|
||||
n1SmBufFromUe = gsmue_encode_n1_sm_info(&nas_message);
|
||||
|
|
@ -275,11 +272,11 @@ ogs_sbi_request_t *smf_nsmf_pdusession_build_create_data(
|
|||
} else {
|
||||
ogs_error("gsm_encode_n1_sm_info() failed [%d]", rv);
|
||||
ogs_log_hexdump(OGS_LOG_ERROR,
|
||||
sess->n1smbuf->data, sess->n1smbuf->len);
|
||||
sess->n1SmBufFromUe->data, sess->n1SmBufFromUe->len);
|
||||
}
|
||||
} else {
|
||||
ogs_error("ogs_nas_5gsm_decode() failed [%d]", rv);
|
||||
ogs_log_hexdump(OGS_LOG_ERROR, sess->n1smbuf->data, sess->n1smbuf->len);
|
||||
ogs_log_hexdump(OGS_LOG_ERROR, sess->n1SmBufFromUe->data, sess->n1SmBufFromUe->len);
|
||||
}
|
||||
|
||||
message.PduSessionCreateData = &PduSessionCreateData;
|
||||
|
|
@ -324,9 +321,9 @@ end:
|
|||
if (PduSessionCreateData.ue_time_zone)
|
||||
ogs_free(PduSessionCreateData.ue_time_zone);
|
||||
|
||||
if (sess->n1smbuf) {
|
||||
ogs_pkbuf_free(sess->n1smbuf);
|
||||
sess->n1smbuf = NULL;
|
||||
if (sess->n1SmBufFromUe) {
|
||||
ogs_pkbuf_free(sess->n1SmBufFromUe);
|
||||
sess->n1SmBufFromUe = NULL;
|
||||
}
|
||||
|
||||
if (n1SmBufFromUe)
|
||||
|
|
@ -348,6 +345,7 @@ ogs_sbi_request_t *smf_nsmf_pdusession_build_hsmf_update_data(
|
|||
|
||||
OpenAPI_hsmf_update_data_t HsmfUpdateData;
|
||||
OpenAPI_ng_ap_cause_t ngApCause;
|
||||
OpenAPI_tunnel_info_t vcnTunnelInfo;
|
||||
OpenAPI_user_location_t ueLocation;
|
||||
|
||||
int rv;
|
||||
|
|
@ -368,6 +366,7 @@ ogs_sbi_request_t *smf_nsmf_pdusession_build_hsmf_update_data(
|
|||
|
||||
memset(&HsmfUpdateData, 0, sizeof(HsmfUpdateData));
|
||||
memset(&ngApCause, 0, sizeof(ngApCause));
|
||||
memset(&vcnTunnelInfo, 0, sizeof(vcnTunnelInfo));
|
||||
memset(&ueLocation, 0, sizeof(ueLocation));
|
||||
|
||||
HsmfUpdateData.request_indication = sess->nsmf_param.request_indication;
|
||||
|
|
@ -375,6 +374,8 @@ ogs_sbi_request_t *smf_nsmf_pdusession_build_hsmf_update_data(
|
|||
|
||||
HsmfUpdateData.cause = sess->nsmf_param.cause;
|
||||
|
||||
HsmfUpdateData.up_cnx_state = sess->nsmf_param.up_cnx_state;
|
||||
|
||||
if (sess->nsmf_param.ngap_cause.group) {
|
||||
HsmfUpdateData.ng_ap_cause = &ngApCause;
|
||||
ngApCause.group = sess->nsmf_param.ngap_cause.group;
|
||||
|
|
@ -386,6 +387,32 @@ ogs_sbi_request_t *smf_nsmf_pdusession_build_hsmf_update_data(
|
|||
HsmfUpdateData._5g_mm_cause_value = sess->nsmf_param.gmm_cause;
|
||||
}
|
||||
|
||||
if (sess->nsmf_param.serving_network) {
|
||||
HsmfUpdateData.serving_network =
|
||||
ogs_sbi_build_plmn_id_nid(&sess->nr_tai.plmn_id);
|
||||
if (!HsmfUpdateData.serving_network) {
|
||||
ogs_error("No serving_network");
|
||||
goto end;
|
||||
}
|
||||
}
|
||||
|
||||
if (sess->nsmf_param.dl_ip.ipv4)
|
||||
vcnTunnelInfo.ipv4_addr = ogs_ipv4_to_string(
|
||||
sess->nsmf_param.dl_ip.addr);
|
||||
|
||||
if (sess->nsmf_param.dl_ip.ipv6)
|
||||
vcnTunnelInfo.ipv6_addr = ogs_ipv6addr_to_string(
|
||||
sess->nsmf_param.dl_ip.addr6);
|
||||
|
||||
if (vcnTunnelInfo.ipv4_addr || vcnTunnelInfo.ipv6_addr) {
|
||||
vcnTunnelInfo.gtp_teid = ogs_uint32_to_0string(
|
||||
sess->nsmf_param.dl_teid);
|
||||
HsmfUpdateData.vcn_tunnel_info = &vcnTunnelInfo;
|
||||
}
|
||||
|
||||
HsmfUpdateData.an_type = sess->nsmf_param.an_type;
|
||||
HsmfUpdateData.rat_type = sess->nsmf_param.rat_type;
|
||||
|
||||
if (sess->nsmf_param.ue_location) {
|
||||
ueLocation.nr_location = ogs_sbi_build_nr_location(
|
||||
&sess->nr_tai, &sess->nr_cgi);
|
||||
|
|
@ -393,12 +420,9 @@ ogs_sbi_request_t *smf_nsmf_pdusession_build_hsmf_update_data(
|
|||
ogs_error("No ueLocation.nr_location");
|
||||
goto end;
|
||||
}
|
||||
ueLocation.nr_location->ue_location_timestamp =
|
||||
ogs_sbi_gmtime_string(sess->ue_location_timestamp);
|
||||
if (!ueLocation.nr_location->ue_location_timestamp) {
|
||||
ogs_error("No ue_location_timestamp");
|
||||
goto end;
|
||||
}
|
||||
if (sess->ue_location_timestamp)
|
||||
ueLocation.nr_location->ue_location_timestamp =
|
||||
ogs_sbi_gmtime_string(sess->ue_location_timestamp);
|
||||
|
||||
HsmfUpdateData.ue_location = &ueLocation;
|
||||
}
|
||||
|
|
@ -410,8 +434,8 @@ ogs_sbi_request_t *smf_nsmf_pdusession_build_hsmf_update_data(
|
|||
}
|
||||
}
|
||||
|
||||
if (sess->n1smbuf) {
|
||||
rv = ogs_nas_5gsm_decode(&nas_message, sess->n1smbuf);
|
||||
if (sess->n1SmBufFromUe) {
|
||||
rv = ogs_nas_5gsm_decode(&nas_message, sess->n1SmBufFromUe);
|
||||
|
||||
if (rv == OGS_OK) {
|
||||
n1SmBufFromUe = gsmue_encode_n1_sm_info(&nas_message);
|
||||
|
|
@ -428,12 +452,12 @@ ogs_sbi_request_t *smf_nsmf_pdusession_build_hsmf_update_data(
|
|||
} else {
|
||||
ogs_error("gsm_encode_n1_sm_info() failed [%d]", rv);
|
||||
ogs_log_hexdump(OGS_LOG_ERROR,
|
||||
sess->n1smbuf->data, sess->n1smbuf->len);
|
||||
sess->n1SmBufFromUe->data, sess->n1SmBufFromUe->len);
|
||||
}
|
||||
} else {
|
||||
ogs_error("ogs_nas_5gsm_decode() failed [%d]", rv);
|
||||
ogs_log_hexdump(OGS_LOG_ERROR,
|
||||
sess->n1smbuf->data, sess->n1smbuf->len);
|
||||
sess->n1SmBufFromUe->data, sess->n1SmBufFromUe->len);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -446,6 +470,16 @@ end:
|
|||
if (message.h.uri)
|
||||
ogs_free(message.h.uri);
|
||||
|
||||
if (HsmfUpdateData.serving_network)
|
||||
ogs_sbi_free_plmn_id_nid(HsmfUpdateData.serving_network);
|
||||
|
||||
if (vcnTunnelInfo.ipv4_addr)
|
||||
ogs_free(vcnTunnelInfo.ipv4_addr);
|
||||
if (vcnTunnelInfo.ipv6_addr)
|
||||
ogs_free(vcnTunnelInfo.ipv6_addr);
|
||||
if (vcnTunnelInfo.gtp_teid)
|
||||
ogs_free(vcnTunnelInfo.gtp_teid);
|
||||
|
||||
if (ueLocation.nr_location) {
|
||||
if (ueLocation.nr_location->ue_location_timestamp)
|
||||
ogs_free(ueLocation.nr_location->ue_location_timestamp);
|
||||
|
|
@ -454,9 +488,9 @@ end:
|
|||
if (HsmfUpdateData.ue_time_zone)
|
||||
ogs_free(HsmfUpdateData.ue_time_zone);
|
||||
|
||||
if (sess->n1smbuf) {
|
||||
ogs_pkbuf_free(sess->n1smbuf);
|
||||
sess->n1smbuf = NULL;
|
||||
if (sess->n1SmBufFromUe) {
|
||||
ogs_pkbuf_free(sess->n1SmBufFromUe);
|
||||
sess->n1SmBufFromUe = NULL;
|
||||
}
|
||||
|
||||
return request;
|
||||
|
|
@ -474,8 +508,10 @@ ogs_sbi_request_t *smf_nsmf_pdusession_build_vsmf_update_data(
|
|||
ogs_pkbuf_t *n1SmBufToUe = NULL;
|
||||
|
||||
OpenAPI_list_t *qosFlowsAddModRequestList = NULL;
|
||||
OpenAPI_qos_flow_add_modify_request_item_t *qosFlowAddModifyRequestItem =
|
||||
OpenAPI_qos_flow_add_modify_request_item_t *qosFlowAddModRequestItem =
|
||||
NULL;
|
||||
OpenAPI_list_t *qosFlowsRelRequestList = NULL;
|
||||
OpenAPI_qos_flow_release_request_item_t *qosFlowRelRequestItem = NULL;
|
||||
|
||||
smf_bearer_t *qos_flow = NULL;
|
||||
|
||||
|
|
@ -501,6 +537,8 @@ ogs_sbi_request_t *smf_nsmf_pdusession_build_vsmf_update_data(
|
|||
|
||||
qosFlowsAddModRequestList = OpenAPI_list_create();
|
||||
ogs_assert(qosFlowsAddModRequestList);
|
||||
qosFlowsRelRequestList = OpenAPI_list_create();
|
||||
ogs_assert(qosFlowsRelRequestList);
|
||||
|
||||
int i = 0;
|
||||
|
||||
|
|
@ -513,14 +551,11 @@ ogs_sbi_request_t *smf_nsmf_pdusession_build_vsmf_update_data(
|
|||
OpenAPI_arp_t *Arp = NULL;
|
||||
OpenAPI_gbr_qos_flow_information_t *gbrQosFlowInfo = NULL;
|
||||
|
||||
char *encoded_qos_rules = NULL;
|
||||
char *encoded_qos_flow_description = NULL;
|
||||
|
||||
ogs_assert(i < OGS_MAX_NUM_OF_BEARER);
|
||||
|
||||
qosFlowAddModifyRequestItem =
|
||||
ogs_calloc(1, sizeof(*qosFlowAddModifyRequestItem));
|
||||
ogs_assert(qosFlowAddModifyRequestItem);
|
||||
|
||||
qosFlowAddModifyRequestItem->qfi = qos_flow->qfi;
|
||||
|
||||
if (sess->nsmf_param.qos_rule_code) {
|
||||
ogs_nas_qos_rules_t authorized_qos_rules;
|
||||
ogs_nas_qos_rule_t qos_rule;
|
||||
|
|
@ -541,10 +576,10 @@ ogs_sbi_request_t *smf_nsmf_pdusession_build_vsmf_update_data(
|
|||
}
|
||||
|
||||
enc_len = ogs_base64_encode_len(authorized_qos_rules.length);
|
||||
qosFlowAddModifyRequestItem->qos_rules = ogs_calloc(1, enc_len);
|
||||
ogs_assert(qosFlowAddModifyRequestItem->qos_rules);
|
||||
encoded_qos_rules = ogs_calloc(1, enc_len);
|
||||
ogs_assert(encoded_qos_rules);
|
||||
ogs_base64_encode(
|
||||
qosFlowAddModifyRequestItem->qos_rules,
|
||||
encoded_qos_rules,
|
||||
authorized_qos_rules.buffer,
|
||||
authorized_qos_rules.length);
|
||||
|
||||
|
|
@ -574,15 +609,71 @@ ogs_sbi_request_t *smf_nsmf_pdusession_build_vsmf_update_data(
|
|||
|
||||
enc_len = ogs_base64_encode_len(
|
||||
authorized_qos_flow_descriptions.length);
|
||||
qosFlowAddModifyRequestItem->qos_flow_description =
|
||||
ogs_calloc(1, enc_len);
|
||||
ogs_assert(qosFlowAddModifyRequestItem->qos_flow_description);
|
||||
encoded_qos_flow_description = ogs_calloc(1, enc_len);
|
||||
ogs_assert(encoded_qos_flow_description);
|
||||
ogs_base64_encode(
|
||||
qosFlowAddModifyRequestItem->qos_flow_description,
|
||||
encoded_qos_flow_description,
|
||||
authorized_qos_flow_descriptions.buffer,
|
||||
authorized_qos_flow_descriptions.length);
|
||||
|
||||
ogs_free(authorized_qos_flow_descriptions.buffer);
|
||||
}
|
||||
|
||||
if (sess->nsmf_param.qos_rule_code ==
|
||||
OGS_NAS_QOS_CODE_DELETE_EXISTING_QOS_RULE ||
|
||||
sess->nsmf_param.qos_flow_description_code ==
|
||||
OGS_NAS_DELETE_NEW_QOS_FLOW_DESCRIPTION) {
|
||||
|
||||
if (sess->nsmf_param.qos_rule_code !=
|
||||
OGS_NAS_QOS_CODE_DELETE_EXISTING_QOS_RULE ||
|
||||
sess->nsmf_param.qos_flow_description_code !=
|
||||
OGS_NAS_DELETE_NEW_QOS_FLOW_DESCRIPTION)
|
||||
ogs_error("Invalid qosRule[%d]/qosFlowDesc[%d]",
|
||||
sess->nsmf_param.qos_rule_code,
|
||||
sess->nsmf_param.qos_flow_description_code);
|
||||
|
||||
qosFlowRelRequestItem =
|
||||
ogs_calloc(1, sizeof(*qosFlowRelRequestItem));
|
||||
ogs_assert(qosFlowRelRequestItem);
|
||||
|
||||
qosFlowRelRequestItem->qfi = qos_flow->qfi;
|
||||
|
||||
qosFlowRelRequestItem->qos_rules = encoded_qos_rules;
|
||||
qosFlowRelRequestItem->qos_flow_description =
|
||||
encoded_qos_flow_description;
|
||||
|
||||
OpenAPI_list_add(qosFlowsRelRequestList, qosFlowRelRequestItem);
|
||||
|
||||
} else if (sess->nsmf_param.qos_rule_code ||
|
||||
sess->nsmf_param.qos_flow_description_code) {
|
||||
Arp = ogs_calloc(1, sizeof(*Arp));
|
||||
ogs_assert(Arp);
|
||||
if (qos_flow->qos.arp.pre_emption_capability ==
|
||||
OGS_5GC_PRE_EMPTION_ENABLED)
|
||||
Arp->preempt_cap =
|
||||
OpenAPI_preemption_capability_MAY_PREEMPT;
|
||||
else if (qos_flow->qos.arp.pre_emption_capability ==
|
||||
OGS_5GC_PRE_EMPTION_DISABLED)
|
||||
Arp->preempt_cap =
|
||||
OpenAPI_preemption_capability_NOT_PREEMPT;
|
||||
else {
|
||||
ogs_error("No Arp->preempt_cap");
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (qos_flow->qos.arp.pre_emption_vulnerability ==
|
||||
OGS_5GC_PRE_EMPTION_ENABLED)
|
||||
Arp->preempt_vuln =
|
||||
OpenAPI_preemption_vulnerability_PREEMPTABLE;
|
||||
else if (qos_flow->qos.arp.pre_emption_vulnerability ==
|
||||
OGS_5GC_PRE_EMPTION_DISABLED)
|
||||
Arp->preempt_vuln =
|
||||
OpenAPI_preemption_vulnerability_NOT_PREEMPTABLE;
|
||||
else {
|
||||
ogs_error("No Arp->preempt_vuln");
|
||||
goto end;
|
||||
}
|
||||
Arp->priority_level = qos_flow->qos.arp.priority_level;
|
||||
|
||||
if (qos_flow->qos.mbr.downlink && qos_flow->qos.mbr.uplink &&
|
||||
qos_flow->qos.gbr.downlink && qos_flow->qos.gbr.uplink) {
|
||||
|
|
@ -599,55 +690,47 @@ ogs_sbi_request_t *smf_nsmf_pdusession_build_vsmf_update_data(
|
|||
gbrQosFlowInfo->gua_fbr_dl = ogs_sbi_bitrate_to_string(
|
||||
qos_flow->qos.gbr.downlink, OGS_SBI_BITRATE_BPS);
|
||||
}
|
||||
|
||||
qosFlowProfile = ogs_calloc(1, sizeof(*qosFlowProfile));
|
||||
ogs_assert(qosFlowProfile);
|
||||
qosFlowProfile->arp = Arp;
|
||||
qosFlowProfile->_5qi = qos_flow->qos.index;
|
||||
qosFlowProfile->gbr_qos_flow_info = gbrQosFlowInfo;
|
||||
|
||||
qosFlowAddModRequestItem =
|
||||
ogs_calloc(1, sizeof(*qosFlowAddModRequestItem));
|
||||
ogs_assert(qosFlowAddModRequestItem);
|
||||
|
||||
qosFlowAddModRequestItem->qfi = qos_flow->qfi;
|
||||
|
||||
qosFlowAddModRequestItem->qos_rules = encoded_qos_rules;
|
||||
qosFlowAddModRequestItem->qos_flow_description =
|
||||
encoded_qos_flow_description;
|
||||
|
||||
qosFlowAddModRequestItem->qos_flow_profile = qosFlowProfile;
|
||||
|
||||
OpenAPI_list_add(qosFlowsAddModRequestList,
|
||||
qosFlowAddModRequestItem);
|
||||
} else {
|
||||
ogs_error("Invalid qosRule[%d]/qosFlowDesc[%d]",
|
||||
sess->nsmf_param.qos_rule_code,
|
||||
sess->nsmf_param.qos_flow_description_code);
|
||||
}
|
||||
|
||||
Arp = ogs_calloc(1, sizeof(*Arp));
|
||||
ogs_assert(Arp);
|
||||
if (qos_flow->qos.arp.pre_emption_capability ==
|
||||
OGS_5GC_PRE_EMPTION_ENABLED)
|
||||
Arp->preempt_cap = OpenAPI_preemption_capability_MAY_PREEMPT;
|
||||
else if (qos_flow->qos.arp.pre_emption_capability ==
|
||||
OGS_5GC_PRE_EMPTION_DISABLED)
|
||||
Arp->preempt_cap = OpenAPI_preemption_capability_NOT_PREEMPT;
|
||||
else {
|
||||
ogs_error("No Arp->preempt_cap");
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (qos_flow->qos.arp.pre_emption_vulnerability ==
|
||||
OGS_5GC_PRE_EMPTION_ENABLED)
|
||||
Arp->preempt_vuln =
|
||||
OpenAPI_preemption_vulnerability_PREEMPTABLE;
|
||||
else if (qos_flow->qos.arp.pre_emption_vulnerability ==
|
||||
OGS_5GC_PRE_EMPTION_DISABLED)
|
||||
Arp->preempt_vuln =
|
||||
OpenAPI_preemption_vulnerability_NOT_PREEMPTABLE;
|
||||
else {
|
||||
ogs_error("No Arp->preempt_vuln");
|
||||
goto end;
|
||||
}
|
||||
Arp->priority_level = qos_flow->qos.arp.priority_level;
|
||||
|
||||
qosFlowProfile = ogs_calloc(1, sizeof(*qosFlowProfile));
|
||||
ogs_assert(qosFlowProfile);
|
||||
qosFlowProfile->arp = Arp;
|
||||
qosFlowProfile->_5qi = qos_flow->qos.index;
|
||||
qosFlowProfile->gbr_qos_flow_info = gbrQosFlowInfo;
|
||||
|
||||
qosFlowAddModifyRequestItem->qos_flow_profile = qosFlowProfile;
|
||||
|
||||
OpenAPI_list_add(qosFlowsAddModRequestList,
|
||||
qosFlowAddModifyRequestItem);
|
||||
|
||||
if (qosFlowsAddModRequestList->count)
|
||||
VsmfUpdateData.qos_flows_add_mod_request_list =
|
||||
qosFlowsAddModRequestList;
|
||||
else
|
||||
OpenAPI_list_free(qosFlowsAddModRequestList);
|
||||
|
||||
i++;
|
||||
}
|
||||
|
||||
if (qosFlowsAddModRequestList->count)
|
||||
VsmfUpdateData.qos_flows_add_mod_request_list =
|
||||
qosFlowsAddModRequestList;
|
||||
else
|
||||
OpenAPI_list_free(qosFlowsAddModRequestList);
|
||||
|
||||
if (qosFlowsRelRequestList->count)
|
||||
VsmfUpdateData.qos_flows_rel_request_list = qosFlowsRelRequestList;
|
||||
else
|
||||
OpenAPI_list_free(qosFlowsRelRequestList);
|
||||
|
||||
break;
|
||||
case OpenAPI_request_indication_NW_REQ_PDU_SES_REL:
|
||||
case OpenAPI_request_indication_UE_REQ_PDU_SES_REL:
|
||||
|
|
@ -681,6 +764,7 @@ end:
|
|||
|
||||
CLEAR_QOS_FLOWS_ADD_MOD_REQUEST_LIST(
|
||||
VsmfUpdateData.qos_flows_add_mod_request_list);
|
||||
CLEAR_QOS_FLOWS_REL_REQUEST_LIST(VsmfUpdateData.qos_flows_rel_request_list);
|
||||
|
||||
return request;
|
||||
}
|
||||
|
|
@ -732,12 +816,9 @@ ogs_sbi_request_t *smf_nsmf_pdusession_build_release_data(
|
|||
ogs_error("No ueLocation.nr_location");
|
||||
goto end;
|
||||
}
|
||||
ueLocation.nr_location->ue_location_timestamp =
|
||||
ogs_sbi_gmtime_string(sess->ue_location_timestamp);
|
||||
if (!ueLocation.nr_location->ue_location_timestamp) {
|
||||
ogs_error("No ue_location_timestamp");
|
||||
goto end;
|
||||
}
|
||||
if (sess->ue_location_timestamp)
|
||||
ueLocation.nr_location->ue_location_timestamp =
|
||||
ogs_sbi_gmtime_string(sess->ue_location_timestamp);
|
||||
|
||||
ReleaseData.ue_location = &ueLocation;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@
|
|||
#include "ngap-path.h"
|
||||
#include "pfcp-path.h"
|
||||
#include "local-path.h"
|
||||
#include "gsm-handler.h"
|
||||
#include "nsmf-handler.h"
|
||||
|
||||
bool smf_nsmf_handle_create_sm_context(
|
||||
|
|
@ -42,6 +43,7 @@ bool smf_nsmf_handle_create_sm_context(
|
|||
char *fqdn = NULL;
|
||||
uint16_t fqdn_port = 0;
|
||||
ogs_sockaddr_t *addr = NULL, *addr6 = NULL;
|
||||
char *home_network_domain = NULL;
|
||||
|
||||
OpenAPI_sm_context_create_data_t *SmContextCreateData = NULL;
|
||||
OpenAPI_nr_location_t *NrLocation = NULL;
|
||||
|
|
@ -351,65 +353,63 @@ bool smf_nsmf_handle_create_sm_context(
|
|||
* the full DNN in LBO and non-roaming scenarios. If the Operator Identifier
|
||||
* is absent, the serving core network operator shall be assumed.
|
||||
*/
|
||||
if (SmContextCreateData->dnn) {
|
||||
char *home_network_domain =
|
||||
ogs_home_network_domain_from_fqdn(SmContextCreateData->dnn);
|
||||
home_network_domain =
|
||||
ogs_home_network_domain_from_fqdn(SmContextCreateData->dnn);
|
||||
|
||||
if (home_network_domain) {
|
||||
char dnn_network_identifer[OGS_MAX_DNN_LEN+1];
|
||||
uint16_t mcc = 0, mnc = 0;
|
||||
if (home_network_domain) {
|
||||
char dnn_network_identifer[OGS_MAX_DNN_LEN+1];
|
||||
uint16_t mcc = 0, mnc = 0;
|
||||
|
||||
ogs_assert(home_network_domain > SmContextCreateData->dnn);
|
||||
ogs_assert(home_network_domain > SmContextCreateData->dnn);
|
||||
|
||||
ogs_cpystrn(dnn_network_identifer, SmContextCreateData->dnn,
|
||||
ogs_min(OGS_MAX_DNN_LEN,
|
||||
home_network_domain - SmContextCreateData->dnn));
|
||||
ogs_cpystrn(dnn_network_identifer, SmContextCreateData->dnn,
|
||||
ogs_min(OGS_MAX_DNN_LEN,
|
||||
home_network_domain - SmContextCreateData->dnn));
|
||||
|
||||
if (sess->session.name)
|
||||
ogs_free(sess->session.name);
|
||||
sess->session.name = ogs_strdup(dnn_network_identifer);
|
||||
ogs_assert(sess->session.name);
|
||||
if (sess->session.name)
|
||||
ogs_free(sess->session.name);
|
||||
sess->session.name = ogs_strdup(dnn_network_identifer);
|
||||
ogs_assert(sess->session.name);
|
||||
|
||||
if (sess->full_dnn)
|
||||
ogs_free(sess->full_dnn);
|
||||
sess->full_dnn = ogs_strdup(SmContextCreateData->dnn);
|
||||
ogs_assert(sess->full_dnn);
|
||||
if (sess->full_dnn)
|
||||
ogs_free(sess->full_dnn);
|
||||
sess->full_dnn = ogs_strdup(SmContextCreateData->dnn);
|
||||
ogs_assert(sess->full_dnn);
|
||||
|
||||
mcc = ogs_plmn_id_mcc_from_fqdn(sess->full_dnn);
|
||||
mnc = ogs_plmn_id_mnc_from_fqdn(sess->full_dnn);
|
||||
mcc = ogs_plmn_id_mcc_from_fqdn(sess->full_dnn);
|
||||
mnc = ogs_plmn_id_mnc_from_fqdn(sess->full_dnn);
|
||||
|
||||
/*
|
||||
* To generate the Home PLMN ID of the SMF-UE,
|
||||
* the length of the MNC is obtained
|
||||
* by comparing the MNC part of the SUPI and full-DNN.
|
||||
*/
|
||||
if (mcc && mnc &&
|
||||
strncmp(smf_ue->supi, "imsi-", strlen("imsi-")) == 0) {
|
||||
int mnc_len = 0;
|
||||
char buf[OGS_PLMNIDSTRLEN];
|
||||
/*
|
||||
* To generate the Home PLMN ID of the SMF-UE,
|
||||
* the length of the MNC is obtained
|
||||
* by comparing the MNC part of the SUPI and full-DNN.
|
||||
*/
|
||||
if (mcc && mnc &&
|
||||
strncmp(smf_ue->supi, "imsi-", strlen("imsi-")) == 0) {
|
||||
int mnc_len = 0;
|
||||
char buf[OGS_PLMNIDSTRLEN];
|
||||
|
||||
ogs_snprintf(buf, OGS_PLMNIDSTRLEN, "%03d%02d", mcc, mnc);
|
||||
if (strncmp(smf_ue->supi + 5, buf, strlen(buf)) == 0)
|
||||
mnc_len = 2;
|
||||
ogs_snprintf(buf, OGS_PLMNIDSTRLEN, "%03d%02d", mcc, mnc);
|
||||
if (strncmp(smf_ue->supi + 5, buf, strlen(buf)) == 0)
|
||||
mnc_len = 2;
|
||||
|
||||
ogs_snprintf(buf, OGS_PLMNIDSTRLEN, "%03d%03d", mcc, mnc);
|
||||
if (strncmp(smf_ue->supi + 5, buf, strlen(buf)) == 0)
|
||||
mnc_len = 3;
|
||||
ogs_snprintf(buf, OGS_PLMNIDSTRLEN, "%03d%03d", mcc, mnc);
|
||||
if (strncmp(smf_ue->supi + 5, buf, strlen(buf)) == 0)
|
||||
mnc_len = 3;
|
||||
|
||||
/* Change Home PLMN for VPLMN */
|
||||
if (mnc_len == 2 || mnc_len == 3)
|
||||
ogs_plmn_id_build(&sess->home_plmn_id, mcc, mnc, mnc_len);
|
||||
}
|
||||
} else {
|
||||
if (sess->session.name)
|
||||
ogs_free(sess->session.name);
|
||||
sess->session.name = ogs_strdup(SmContextCreateData->dnn);
|
||||
ogs_assert(sess->session.name);
|
||||
|
||||
if (sess->full_dnn)
|
||||
ogs_free(sess->full_dnn);
|
||||
sess->full_dnn = NULL;
|
||||
/* Change Home PLMN for VPLMN */
|
||||
if (mnc_len == 2 || mnc_len == 3)
|
||||
ogs_plmn_id_build(&sess->home_plmn_id, mcc, mnc, mnc_len);
|
||||
}
|
||||
} else {
|
||||
if (sess->session.name)
|
||||
ogs_free(sess->session.name);
|
||||
sess->session.name = ogs_strdup(SmContextCreateData->dnn);
|
||||
ogs_assert(sess->session.name);
|
||||
|
||||
if (sess->full_dnn)
|
||||
ogs_free(sess->full_dnn);
|
||||
sess->full_dnn = NULL;
|
||||
}
|
||||
|
||||
ogs_assert(SmContextCreateData->serving_nf_id);
|
||||
|
|
@ -598,9 +598,9 @@ bool smf_nsmf_handle_create_sm_context(
|
|||
ul_pdr->precedence = OGS_PFCP_DEFAULT_PDR_PRECEDENCE;
|
||||
|
||||
/* Save N1 SM Message and send it to H-SMF */
|
||||
if (sess->n1smbuf) ogs_pkbuf_free(sess->n1smbuf);
|
||||
sess->n1smbuf = ogs_pkbuf_copy(n1smbuf);
|
||||
ogs_assert(sess->n1smbuf);
|
||||
if (sess->n1SmBufFromUe) ogs_pkbuf_free(sess->n1SmBufFromUe);
|
||||
sess->n1SmBufFromUe = ogs_pkbuf_copy(n1smbuf);
|
||||
ogs_assert(sess->n1SmBufFromUe);
|
||||
|
||||
ogs_assert(OGS_OK ==
|
||||
smf_5gc_pfcp_send_session_establishment_request(sess, NULL, 0));
|
||||
|
|
@ -611,7 +611,7 @@ bool smf_nsmf_handle_create_sm_context(
|
|||
bool smf_nsmf_handle_update_sm_context(
|
||||
smf_sess_t *sess, ogs_sbi_stream_t *stream, ogs_sbi_message_t *message)
|
||||
{
|
||||
int i;
|
||||
int r;
|
||||
smf_ue_t *smf_ue = NULL;
|
||||
|
||||
ogs_sbi_message_t sendmsg;
|
||||
|
|
@ -644,6 +644,12 @@ bool smf_nsmf_handle_update_sm_context(
|
|||
|
||||
memset(&sess->nsmf_param, 0, sizeof(sess->nsmf_param));
|
||||
|
||||
/* Remove N1 SM Message From UE */
|
||||
if (sess->n1SmBufFromUe) {
|
||||
ogs_pkbuf_free(sess->n1SmBufFromUe);
|
||||
sess->n1SmBufFromUe = NULL;
|
||||
}
|
||||
|
||||
if (SmContextUpdateData->ue_location &&
|
||||
SmContextUpdateData->ue_location->nr_location) {
|
||||
OpenAPI_nr_location_t *NrLocation =
|
||||
|
|
@ -703,47 +709,24 @@ bool smf_nsmf_handle_update_sm_context(
|
|||
ogs_assert(gsm_header);
|
||||
sess->pti = gsm_header->procedure_transaction_identity;
|
||||
|
||||
switch (gsm_header->message_type) {
|
||||
case OGS_NAS_5GS_PDU_SESSION_RELEASE_REQUEST:
|
||||
if (HOME_ROUTED_ROAMING_IN_VSMF(sess)) {
|
||||
if (HOME_ROUTED_ROAMING_IN_VSMF(sess)) {
|
||||
switch (gsm_header->message_type) {
|
||||
case OGS_NAS_5GS_PDU_SESSION_MODIFICATION_REQUEST:
|
||||
case OGS_NAS_5GS_PDU_SESSION_RELEASE_REQUEST:
|
||||
/* Save N1 SM Message and send it to H-SMF */
|
||||
if (sess->n1smbuf) ogs_pkbuf_free(sess->n1smbuf);
|
||||
sess->n1smbuf = ogs_pkbuf_copy(n1smbuf);
|
||||
ogs_assert(sess->n1smbuf);
|
||||
sess->n1SmBufFromUe = ogs_pkbuf_copy(n1smbuf);
|
||||
ogs_assert(sess->n1SmBufFromUe);
|
||||
break;
|
||||
|
||||
/* UE Requested PDU Session Release */
|
||||
sess->nsmf_param.request_indication =
|
||||
OpenAPI_request_indication_UE_REQ_PDU_SES_REL;
|
||||
|
||||
/* Store Stream ID */
|
||||
sess->amf_update_request_stream_id =
|
||||
ogs_sbi_id_from_stream(stream);
|
||||
|
||||
ogs_assert(OGS_OK ==
|
||||
smf_5gc_pfcp_send_all_pdr_modification_request(
|
||||
sess, stream,
|
||||
OGS_PFCP_MODIFY_HOME_ROUTED_ROAMING|
|
||||
OGS_PFCP_MODIFY_UL_ONLY|
|
||||
OGS_PFCP_MODIFY_DEACTIVATE,
|
||||
OGS_PFCP_DELETE_TRIGGER_UE_REQUESTED, 0));
|
||||
} else {
|
||||
n1smbuf = ogs_pkbuf_copy(n1smbuf);
|
||||
ogs_assert(n1smbuf);
|
||||
nas_5gs_send_to_gsm(sess, stream, n1smbuf);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
|
||||
/*
|
||||
* Do not send PFCP Modification on PDU session release complete.
|
||||
* PFCP Modification should only be sent on PDU session release request.
|
||||
*/
|
||||
n1smbuf = ogs_pkbuf_copy(n1smbuf);
|
||||
ogs_assert(n1smbuf);
|
||||
nas_5gs_send_to_gsm(sess, stream, n1smbuf);
|
||||
}
|
||||
|
||||
n1smbuf = ogs_pkbuf_copy(n1smbuf);
|
||||
ogs_assert(n1smbuf);
|
||||
nas_5gs_send_to_gsm(sess, stream, n1smbuf);
|
||||
|
||||
return true;
|
||||
|
||||
} else if (SmContextUpdateData->n2_sm_info) {
|
||||
|
|
@ -779,6 +762,37 @@ bool smf_nsmf_handle_update_sm_context(
|
|||
return false;
|
||||
}
|
||||
|
||||
if (HOME_ROUTED_ROAMING_IN_VSMF(sess)) {
|
||||
/*
|
||||
* UE-requested PDU Session Modification(ACTIVATED)
|
||||
*
|
||||
* 1. V: OGS_PFCP_MODIFY_HOME_ROUTED_ROAMING|OGS_PFCP_MODIFY_DL_ONLY|
|
||||
* OGS_PFCP_MODIFY_OUTER_HEADER_REMOVAL|OGS_PFCP_MODIFY_ACTIVATE
|
||||
* 2. V: if (sess->up_cnx_state == OpenAPI_up_cnx_state_ACTIVATING)
|
||||
* pfcp_flags |= OGS_PFCP_MODIFY_FROM_ACTIVATING;
|
||||
* 3. V: flags & OGS_PFCP_MODIFY_FROM_ACTIVATING ?
|
||||
* SMF_UPDATE_STATE_HR_ACTIVATED_FROM_ACTIVATING :
|
||||
* SMF_UPDATE_STATE_HR_ACTIVATED_FROM_NON_ACTIVATING,
|
||||
* 4. V: OpenAPI_request_indication_UE_REQ_PDU_SES_MOD
|
||||
* 5. V: smf_nsmf_pdusession_build_hsmf_update_data
|
||||
* 6. H: smf_nsmf_handle_update_data_in_hsmf
|
||||
* 7. H: OpenAPI_request_indication_UE_REQ_PDU_SES_MOD
|
||||
* 8. H: OGS_PFCP_MODIFY_HOME_ROUTED_ROAMING|OGS_PFCP_MODIFY_DL_ONLY|
|
||||
* OGS_PFCP_MODIFY_ACTIVATE
|
||||
* 9. H: ogs_sbi_send_http_status_no_content
|
||||
* 10. V: case SMF_UPDATE_STATE_HR_ACTIVATED_FROM_ACTIVATING:
|
||||
* sess->up_cnx_state = OpenAPI_up_cnx_state_ACTIVATED;
|
||||
* smf_sbi_send_sm_context_updated_data_up_cnx_state(
|
||||
* OpenAPI_up_cnx_state_ACTIVATED);
|
||||
* case SMF_UPDATE_STATE_HR_ACTIVATED_FROM_NON_ACTIVATING:
|
||||
* ogs_sbi_send_http_status_no_content
|
||||
*/
|
||||
if (SmContextUpdateData->ue_location)
|
||||
sess->nsmf_param.ue_location = true;
|
||||
if (SmContextUpdateData->ue_time_zone)
|
||||
sess->nsmf_param.ue_timezone = true;
|
||||
}
|
||||
|
||||
/*
|
||||
* NOTE : The pkbuf created in the SBI message will be removed
|
||||
* from ogs_sbi_message_free().
|
||||
|
|
@ -801,28 +815,77 @@ bool smf_nsmf_handle_update_sm_context(
|
|||
********************************************************/
|
||||
if (sess->ngap_state.pdu_session_resource_release ==
|
||||
SMF_NGAP_STATE_DELETE_TRIGGER_UE_REQUESTED) {
|
||||
/*
|
||||
* 1. UE->SMF: PDU session release request
|
||||
* 2. PFCP Session Deletion Request/Response
|
||||
* 3. AMF/SMF->UE : PDUSessionResourceReleaseCommand +
|
||||
* PDU session release command
|
||||
* sess->ngap_state.pdu_session_resource_release is set
|
||||
* to SMF_NGAP_STATE_DELETE_TRIGGER_UE_REQUESTED
|
||||
* 4. UE->AMF/SMF : PDUSessionResourceReleaseResponse
|
||||
*
|
||||
* If UE sends UEContextReleaseRequest to the AMF/SMF,
|
||||
* there is no PFCP context in the SMF/UPF.
|
||||
*
|
||||
* So, PFCP deactivation is skipped.
|
||||
*/
|
||||
/*
|
||||
* If UE initiates PDU Session Release, PFCP context is already removed.
|
||||
* In this case, skip PFCP deactivation and only send UP_CNX_STATE=DEACTIVATED.
|
||||
*
|
||||
* Typical flow:
|
||||
* 1. UE -> SMF: PDU Session Release Request
|
||||
* 2. SMF -> UPF: PFCP Session Deletion
|
||||
* 3. SMF -> UE : ReleaseCommand (NAS + NGAP)
|
||||
* 4. UE -> SMF: PDU Session Release Response
|
||||
*
|
||||
* If UE sends UEContextReleaseRequest after step 4,
|
||||
* PFCP session no longer exists in UPF.
|
||||
*/
|
||||
smf_sbi_send_sm_context_updated_data_up_cnx_state(
|
||||
sess, stream, OpenAPI_up_cnx_state_DEACTIVATED);
|
||||
} else {
|
||||
ogs_assert(OGS_OK ==
|
||||
smf_5gc_pfcp_send_all_pdr_modification_request(
|
||||
sess, stream,
|
||||
OGS_PFCP_MODIFY_DL_ONLY|OGS_PFCP_MODIFY_DEACTIVATE,
|
||||
0, 0));
|
||||
if (HOME_ROUTED_ROAMING_IN_VSMF(sess)) {
|
||||
/*
|
||||
* UE-requested PDU Session Modification(DEACTIVATED)
|
||||
*
|
||||
* For Home Routed Roaming, delegate PFCP deactivation to H-SMF by
|
||||
* sending UP_CNX_STATE=DEACTIVATED via HsmfUpdateData.
|
||||
*
|
||||
* 1. V*: OpenAPI_request_indication_UE_REQ_PDU_SES_MOD
|
||||
* 2. V*: smf_nsmf_pdusession_build_hsmf_update_data
|
||||
* SMF_UPDATE_STATE_HR_DEACTIVATED
|
||||
* 3. H: smf_nsmf_handle_update_data_in_hsmf
|
||||
* 4. H: OpenAPI_request_indication_UE_REQ_PDU_SES_MOD
|
||||
* 5. H: OGS_PFCP_MODIFY_HOME_ROUTED_ROAMING|OGS_PFCP_MODIFY_DL_ONLY|
|
||||
* OGS_PFCP_MODIFY_DEACTIVATE
|
||||
* 6. H: ogs_sbi_send_http_status_no_content
|
||||
* 7. V: case SMF_UPDATE_STATE_HR_DEACTIVATED:
|
||||
* 8. V: smf_sbi_send_sm_context_updated_data_up_cnx_state(
|
||||
* OpenAPI_up_cnx_state_DEACTIVATED)
|
||||
*/
|
||||
sess->nsmf_param.request_indication =
|
||||
OpenAPI_request_indication_UE_REQ_PDU_SES_MOD;
|
||||
|
||||
sess->nsmf_param.up_cnx_state =
|
||||
SmContextUpdateData->up_cnx_state;
|
||||
|
||||
if (SmContextUpdateData->ue_location)
|
||||
sess->nsmf_param.ue_location = true;
|
||||
if (SmContextUpdateData->ue_time_zone)
|
||||
sess->nsmf_param.ue_timezone = true;
|
||||
|
||||
if (SmContextUpdateData->ng_ap_cause) {
|
||||
OpenAPI_ng_ap_cause_t *ngApCause =
|
||||
SmContextUpdateData->ng_ap_cause;
|
||||
sess->nsmf_param.ngap_cause.group = ngApCause->group;
|
||||
sess->nsmf_param.ngap_cause.value = ngApCause->value;
|
||||
}
|
||||
|
||||
r = smf_sbi_discover_and_send(
|
||||
OGS_SBI_SERVICE_TYPE_NSMF_PDUSESSION, NULL,
|
||||
smf_nsmf_pdusession_build_hsmf_update_data,
|
||||
sess, stream, SMF_UPDATE_STATE_DEACTIVATED, NULL);
|
||||
ogs_expect(r == OGS_OK);
|
||||
ogs_assert(r != OGS_ERROR);
|
||||
|
||||
} else {
|
||||
/*
|
||||
* For non-HRR sessions, directly send PFCP PDR modification with
|
||||
* DL-only deactivation to the local UPF.
|
||||
*/
|
||||
ogs_assert(OGS_OK ==
|
||||
smf_5gc_pfcp_send_all_pdr_modification_request(
|
||||
sess, stream,
|
||||
OGS_PFCP_MODIFY_DL_ONLY|OGS_PFCP_MODIFY_DEACTIVATE,
|
||||
0, 0));
|
||||
}
|
||||
}
|
||||
|
||||
} else if (SmContextUpdateData->up_cnx_state ==
|
||||
|
|
@ -831,9 +894,6 @@ bool smf_nsmf_handle_update_sm_context(
|
|||
/*********************************************************
|
||||
* Handle ACTIVATING
|
||||
********************************************************/
|
||||
OpenAPI_sm_context_updated_data_t SmContextUpdatedData;
|
||||
OpenAPI_ref_to_binary_data_t n2SmInfo;
|
||||
|
||||
if (!OGS_FSM_CHECK(&sess->sm, smf_gsm_state_operational)) {
|
||||
/*
|
||||
* TS29.502 5.2.2.3.2.2
|
||||
|
|
@ -879,38 +939,45 @@ bool smf_nsmf_handle_update_sm_context(
|
|||
return false;
|
||||
}
|
||||
|
||||
memset(&sendmsg, 0, sizeof(sendmsg));
|
||||
sendmsg.SmContextUpdatedData = &SmContextUpdatedData;
|
||||
if (HOME_ROUTED_ROAMING_IN_VSMF(sess)) {
|
||||
/*
|
||||
* UE-requested PDU Session Modification(ACTIVATING)
|
||||
*
|
||||
* 1. V*: OpenAPI_request_indication_UE_REQ_PDU_SES_MOD
|
||||
* 2. V*: smf_nsmf_pdusession_build_hsmf_update_data
|
||||
* SMF_UPDATE_STATE_HR_ACTIVATING
|
||||
* 3. H: smf_nsmf_handle_update_data_in_hsmf
|
||||
* 4. H: OpenAPI_request_indication_UE_REQ_PDU_SES_MOD
|
||||
* 5. H: ogs_sbi_send_http_status_no_content
|
||||
* 6. V: ngap_build_pdu_session_resource_setup_request_transfer
|
||||
* 7. V: smf_sbi_send_sm_context_updated_data(
|
||||
* OpenAPI_up_cnx_state_ACTIVATING,
|
||||
* OpenAPI_n2_sm_info_type_PDU_RES_SETUP_REQ, n2smbuf)
|
||||
*/
|
||||
sess->nsmf_param.request_indication =
|
||||
OpenAPI_request_indication_UE_REQ_PDU_SES_MOD;
|
||||
|
||||
memset(&SmContextUpdatedData, 0, sizeof(SmContextUpdatedData));
|
||||
SmContextUpdatedData.up_cnx_state = OpenAPI_up_cnx_state_ACTIVATING;
|
||||
SmContextUpdatedData.n2_sm_info_type =
|
||||
OpenAPI_n2_sm_info_type_PDU_RES_SETUP_REQ;
|
||||
SmContextUpdatedData.n2_sm_info = &n2SmInfo;
|
||||
sess->nsmf_param.up_cnx_state =
|
||||
SmContextUpdateData->up_cnx_state;
|
||||
|
||||
memset(&n2SmInfo, 0, sizeof(n2SmInfo));
|
||||
n2SmInfo.content_id = (char *)OGS_SBI_CONTENT_NGAP_SM_ID;
|
||||
r = smf_sbi_discover_and_send(
|
||||
OGS_SBI_SERVICE_TYPE_NSMF_PDUSESSION, NULL,
|
||||
smf_nsmf_pdusession_build_hsmf_update_data,
|
||||
sess, stream, SMF_UPDATE_STATE_ACTIVATING, NULL);
|
||||
ogs_expect(r == OGS_OK);
|
||||
ogs_assert(r != OGS_ERROR);
|
||||
|
||||
sendmsg.num_of_part = 0;
|
||||
} else {
|
||||
ogs_pkbuf_t *n2smbuf =
|
||||
ngap_build_pdu_session_resource_setup_request_transfer(
|
||||
sess);
|
||||
ogs_assert(n2smbuf);
|
||||
|
||||
sendmsg.part[sendmsg.num_of_part].pkbuf =
|
||||
ngap_build_pdu_session_resource_setup_request_transfer(sess);
|
||||
if (sendmsg.part[sendmsg.num_of_part].pkbuf) {
|
||||
sendmsg.part[sendmsg.num_of_part].content_id =
|
||||
(char *)OGS_SBI_CONTENT_NGAP_SM_ID;
|
||||
sendmsg.part[sendmsg.num_of_part].content_type =
|
||||
(char *)OGS_SBI_CONTENT_NGAP_TYPE;
|
||||
sendmsg.num_of_part++;
|
||||
smf_sbi_send_sm_context_updated_data(
|
||||
sess, stream,
|
||||
OpenAPI_up_cnx_state_ACTIVATING, 0, NULL,
|
||||
OpenAPI_n2_sm_info_type_PDU_RES_SETUP_REQ, n2smbuf);
|
||||
}
|
||||
|
||||
response = ogs_sbi_build_response(&sendmsg, OGS_SBI_HTTP_STATUS_OK);
|
||||
ogs_assert(response);
|
||||
ogs_assert(true == ogs_sbi_server_send_response(stream, response));
|
||||
|
||||
for (i = 0; i < sendmsg.num_of_part; i++)
|
||||
if (sendmsg.part[i].pkbuf)
|
||||
ogs_pkbuf_free(sendmsg.part[i].pkbuf);
|
||||
|
||||
} else {
|
||||
char *strerror = ogs_msprintf("[%s:%d] Invalid upCnxState [%d]",
|
||||
smf_ue->supi, sess->psi, SmContextUpdateData->up_cnx_state);
|
||||
|
|
@ -1037,16 +1104,28 @@ bool smf_nsmf_handle_update_sm_context(
|
|||
|
||||
} else {
|
||||
if (HOME_ROUTED_ROAMING_IN_VSMF(sess)) {
|
||||
/* Network Initiated PDU Session Release */
|
||||
sess->nsmf_param.request_indication =
|
||||
OpenAPI_request_indication_NW_REQ_PDU_SES_REL;
|
||||
|
||||
/* Remove N1 SM Message */
|
||||
if (sess->n1smbuf) {
|
||||
ogs_pkbuf_free(sess->n1smbuf);
|
||||
sess->n1smbuf = NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Network-requested PDU Session Release(DUPLICATED)
|
||||
*
|
||||
* 1. V*: OGS_PFCP_MODIFY_HOME_ROUTED_ROAMING|OGS_PFCP_MODIFY_UL_ONLY|
|
||||
* OGS_PFCP_MODIFY_DEACTIVATE
|
||||
* 2. V*: OGS_PFCP_DELETE_TRIGGER_AMF_UPDATE_SM_CONTEXT,
|
||||
* 3. V: OpenAPI_request_indication_NW_REQ_PDU_SES_REL
|
||||
* 4. V: smf_nsmf_pdusession_build_hsmf_update_data
|
||||
* 5. H: smf_nsmf_handle_update_data_in_hsmf
|
||||
* 6. H: OpenAPI_request_indication_NW_REQ_PDU_SES_REL
|
||||
* 6. H: e->h.sbi.state = OGS_PFCP_DELETE_TRIGGER_AMF_UPDATE_SM_CONTEXT
|
||||
* 7. H: ogs_sbi_send_http_status_no_content
|
||||
* 8. H: OGS_FSM_TRAN(s, smf_gsm_state_wait_pfcp_deletion)
|
||||
* 9. H: smf_sbi_cleanup_session(SMF_UECM_STATE_DEREG_BY_AMF_HR
|
||||
* SMF_SBI_CLEANUP_MODE_POLICY_FIRST);
|
||||
* 10. H: OGS_FSM_TRAN(s, smf_gsm_state_5gc_session_will_deregister);
|
||||
* 11. H: SMF_SESS_CLEAR(sess)
|
||||
* 12. V: e->h.sbi.state = OGS_PFCP_DELETE_TRIGGER_AMF_UPDATE_SM_CONTEXT
|
||||
* 13. V: OGS_FSM_TRAN(s, smf_gsm_state_wait_pfcp_deletion)
|
||||
* 14. V: ogs_sbi_send_http_status_no_content
|
||||
* 15. V: OGS_FSM_TRAN(s, smf_gsm_state_session_will_release);
|
||||
*/
|
||||
ogs_assert(OGS_OK ==
|
||||
smf_5gc_pfcp_send_all_pdr_modification_request(
|
||||
sess, stream,
|
||||
|
|
@ -1164,6 +1243,8 @@ bool smf_nsmf_handle_create_data_in_hsmf(
|
|||
char *fqdn = NULL;
|
||||
uint16_t fqdn_port = 0;
|
||||
ogs_sockaddr_t *addr = NULL, *addr6 = NULL;
|
||||
char *home_network_domain = NULL;
|
||||
|
||||
OpenAPI_pdu_session_create_data_t *PduSessionCreateData = NULL;
|
||||
OpenAPI_nr_location_t *NrLocation = NULL;
|
||||
OpenAPI_snssai_t *sNssai = NULL;
|
||||
|
|
@ -1232,6 +1313,38 @@ bool smf_nsmf_handle_create_data_in_hsmf(
|
|||
return false;
|
||||
}
|
||||
|
||||
home_network_domain =
|
||||
ogs_home_network_domain_from_fqdn(PduSessionCreateData->dnn);
|
||||
|
||||
if (home_network_domain) {
|
||||
char dnn_network_identifer[OGS_MAX_DNN_LEN+1];
|
||||
|
||||
ogs_assert(home_network_domain > PduSessionCreateData->dnn);
|
||||
|
||||
ogs_cpystrn(dnn_network_identifer, PduSessionCreateData->dnn,
|
||||
ogs_min(OGS_MAX_DNN_LEN,
|
||||
home_network_domain - PduSessionCreateData->dnn));
|
||||
|
||||
if (sess->session.name)
|
||||
ogs_free(sess->session.name);
|
||||
sess->session.name = ogs_strdup(dnn_network_identifer);
|
||||
ogs_assert(sess->session.name);
|
||||
|
||||
if (sess->full_dnn)
|
||||
ogs_free(sess->full_dnn);
|
||||
sess->full_dnn = ogs_strdup(PduSessionCreateData->dnn);
|
||||
ogs_assert(sess->full_dnn);
|
||||
} else {
|
||||
if (sess->session.name)
|
||||
ogs_free(sess->session.name);
|
||||
sess->session.name = ogs_strdup(PduSessionCreateData->dnn);
|
||||
ogs_assert(sess->session.name);
|
||||
|
||||
if (sess->full_dnn)
|
||||
ogs_free(sess->full_dnn);
|
||||
sess->full_dnn = NULL;
|
||||
}
|
||||
|
||||
sNssai = PduSessionCreateData->s_nssai;
|
||||
if (!sNssai) {
|
||||
ogs_error("[%s:%d] No sNssai", smf_ue->supi, sess->psi);
|
||||
|
|
@ -1374,7 +1487,9 @@ bool smf_nsmf_handle_create_data_in_hsmf(
|
|||
if (sess->remote_dl_ip.ipv4 && sess->remote_dl_ip.ipv6)
|
||||
sess->remote_dl_ip.len = OGS_IPV4V6_LEN;
|
||||
|
||||
sess->remote_dl_teid = ogs_uint64_from_string_hexadecimal(vcnTunnelInfo->gtp_teid);
|
||||
if (vcnTunnelInfo->gtp_teid)
|
||||
sess->remote_dl_teid =
|
||||
ogs_uint64_from_string_hexadecimal(vcnTunnelInfo->gtp_teid);
|
||||
ogs_debug("vcnTunnelInfo->ipv4 = 0x%x", sess->remote_dl_ip.addr);
|
||||
ogs_log_hexdump(OGS_LOG_DEBUG, sess->remote_dl_ip.addr6, OGS_IPV6_LEN);
|
||||
ogs_debug("vcnTunnelInfo->gtp_teid = 0x%x", sess->remote_dl_teid);
|
||||
|
|
@ -1763,10 +1878,14 @@ bool smf_nsmf_handle_created_data_in_vsmf(
|
|||
if (sess->remote_ul_ip.ipv4 && sess->remote_ul_ip.ipv6)
|
||||
sess->remote_ul_ip.len = OGS_IPV4V6_LEN;
|
||||
|
||||
sess->remote_ul_teid = ogs_uint64_from_string_hexadecimal(hcnTunnelInfo->gtp_teid);
|
||||
ogs_debug("hcnTunnelInfo->ipv4 = 0x%x", sess->remote_ul_ip.addr);
|
||||
ogs_log_hexdump(OGS_LOG_DEBUG, sess->remote_ul_ip.addr6, OGS_IPV6_LEN);
|
||||
ogs_debug("hcnTunnelInfo->gtp_teid = 0x%x", sess->remote_ul_teid);
|
||||
if (hcnTunnelInfo->gtp_teid) {
|
||||
sess->remote_ul_teid =
|
||||
ogs_uint64_from_string_hexadecimal(hcnTunnelInfo->gtp_teid);
|
||||
ogs_debug("hcnTunnelInfo->ipv4 = 0x%x", sess->remote_ul_ip.addr);
|
||||
ogs_log_hexdump(OGS_LOG_DEBUG,
|
||||
sess->remote_ul_ip.addr6, OGS_IPV6_LEN);
|
||||
ogs_debug("hcnTunnelInfo->gtp_teid = 0x%x", sess->remote_ul_teid);
|
||||
}
|
||||
|
||||
dl_pdr = qos_flow->dl_pdr;
|
||||
ogs_assert(dl_pdr);
|
||||
|
|
@ -2015,11 +2134,16 @@ bool smf_nsmf_handle_update_data_in_hsmf(
|
|||
|
||||
OpenAPI_hsmf_update_data_t *HsmfUpdateData = NULL;
|
||||
|
||||
OpenAPI_plmn_id_nid_t *servingNetwork = NULL;
|
||||
OpenAPI_tunnel_info_t *vcnTunnelInfo = NULL;
|
||||
OpenAPI_ref_to_binary_data_t *n1SmInfoFromUe = NULL;
|
||||
|
||||
ogs_nas_5gs_message_t nas_message;
|
||||
ogs_pkbuf_t *n1SmBufFromUe = NULL;
|
||||
|
||||
ogs_nas_5gs_pdu_session_modification_request_t
|
||||
*pdu_session_modification_request = NULL;
|
||||
|
||||
ogs_assert(stream);
|
||||
ogs_assert(message);
|
||||
ogs_assert(sess);
|
||||
|
|
@ -2051,27 +2175,57 @@ bool smf_nsmf_handle_update_data_in_hsmf(
|
|||
|
||||
sess->nsmf_param.request_indication = HsmfUpdateData->request_indication;
|
||||
|
||||
n1SmInfoFromUe = HsmfUpdateData->n1_sm_info_from_ue;
|
||||
if (n1SmInfoFromUe) {
|
||||
n1SmBufFromUe = ogs_sbi_find_part_by_content_id(
|
||||
message, n1SmInfoFromUe->content_id);
|
||||
sess->nsmf_param.up_cnx_state = HsmfUpdateData->up_cnx_state;
|
||||
|
||||
if (n1SmBufFromUe) {
|
||||
rv = gsmue_decode_n1_sm_info(&nas_message, n1SmBufFromUe);
|
||||
vcnTunnelInfo = HsmfUpdateData->vcn_tunnel_info;
|
||||
if (vcnTunnelInfo) {
|
||||
if (vcnTunnelInfo->ipv4_addr) {
|
||||
rv = ogs_ipv4_from_string(
|
||||
&sess->nsmf_param.dl_ip.addr, vcnTunnelInfo->ipv4_addr);
|
||||
if (rv != OGS_OK) {
|
||||
ogs_error("[%s:%d] cannot decode N1 SM Content [%s]",
|
||||
smf_ue->supi, sess->psi, n1SmInfoFromUe->content_id);
|
||||
ogs_log_hexdump(OGS_LOG_ERROR,
|
||||
n1SmBufFromUe->data, n1SmBufFromUe->len);
|
||||
ogs_error("ogs_ipv4_from_string() [%s] failed",
|
||||
vcnTunnelInfo->ipv4_addr);
|
||||
smf_sbi_send_hsmf_update_error(stream,
|
||||
OGS_SBI_HTTP_STATUS_BAD_REQUEST, OGS_SBI_APP_ERRNO_NULL,
|
||||
OGS_5GSM_CAUSE_SEMANTICALLY_INCORRECT_MESSAGE,
|
||||
"cannot decode N1 SM Content", smf_ue->supi, NULL);
|
||||
OGS_5GSM_CAUSE_INVALID_MANDATORY_INFORMATION,
|
||||
"ogs_ipv4_from_string() failed",
|
||||
vcnTunnelInfo->ipv4_addr, NULL);
|
||||
return false;
|
||||
}
|
||||
sess->nsmf_param.dl_ip.ipv4 = 1;
|
||||
sess->nsmf_param.dl_ip.len = OGS_IPV4_LEN;
|
||||
}
|
||||
if (vcnTunnelInfo->ipv6_addr) {
|
||||
rv = ogs_ipv6addr_from_string(
|
||||
sess->nsmf_param.dl_ip.addr6, vcnTunnelInfo->ipv6_addr);
|
||||
if (rv != OGS_OK) {
|
||||
ogs_error("ogs_ipv6addr_from_string() [%s] failed",
|
||||
vcnTunnelInfo->ipv6_addr);
|
||||
smf_sbi_send_hsmf_update_error(stream,
|
||||
OGS_SBI_HTTP_STATUS_BAD_REQUEST, OGS_SBI_APP_ERRNO_NULL,
|
||||
OGS_5GSM_CAUSE_INVALID_MANDATORY_INFORMATION,
|
||||
"ogs_ipv6addr_from_string() failed",
|
||||
vcnTunnelInfo->ipv6_addr, NULL);
|
||||
return false;
|
||||
}
|
||||
sess->nsmf_param.dl_ip.ipv6 = 1;
|
||||
sess->nsmf_param.dl_ip.len = OGS_IPV6_LEN;
|
||||
}
|
||||
if (sess->remote_dl_ip.ipv4 && sess->remote_dl_ip.ipv6)
|
||||
sess->remote_dl_ip.len = OGS_IPV4V6_LEN;
|
||||
|
||||
if (vcnTunnelInfo->gtp_teid)
|
||||
sess->nsmf_param.dl_teid =
|
||||
ogs_uint64_from_string_hexadecimal(vcnTunnelInfo->gtp_teid);
|
||||
}
|
||||
|
||||
sess->nsmf_param.an_type = HsmfUpdateData->an_type;
|
||||
sess->nsmf_param.rat_type = HsmfUpdateData->rat_type;
|
||||
|
||||
servingNetwork = HsmfUpdateData->serving_network;
|
||||
if (servingNetwork && servingNetwork->mcc && servingNetwork->mnc)
|
||||
sess->nsmf_param.serving_network = true;
|
||||
|
||||
if (HsmfUpdateData->ue_location &&
|
||||
HsmfUpdateData->ue_location->nr_location) {
|
||||
OpenAPI_nr_location_t *NrLocation =
|
||||
|
|
@ -2108,6 +2262,76 @@ bool smf_nsmf_handle_update_data_in_hsmf(
|
|||
sess->nsmf_param.gmm_cause = HsmfUpdateData->_5g_mm_cause_value;
|
||||
sess->nsmf_param.cause = HsmfUpdateData->cause;
|
||||
|
||||
n1SmInfoFromUe = HsmfUpdateData->n1_sm_info_from_ue;
|
||||
if (n1SmInfoFromUe) {
|
||||
n1SmBufFromUe = ogs_sbi_find_part_by_content_id(
|
||||
message, n1SmInfoFromUe->content_id);
|
||||
|
||||
if (n1SmBufFromUe) {
|
||||
rv = gsmue_decode_n1_sm_info(&nas_message, n1SmBufFromUe);
|
||||
if (rv != OGS_OK) {
|
||||
ogs_error("[%s:%d] cannot decode N1 SM Content [%s]",
|
||||
smf_ue->supi, sess->psi, n1SmInfoFromUe->content_id);
|
||||
ogs_log_hexdump(OGS_LOG_ERROR,
|
||||
n1SmBufFromUe->data, n1SmBufFromUe->len);
|
||||
smf_sbi_send_hsmf_update_error(stream,
|
||||
OGS_SBI_HTTP_STATUS_BAD_REQUEST, OGS_SBI_APP_ERRNO_NULL,
|
||||
OGS_5GSM_CAUSE_SEMANTICALLY_INCORRECT_MESSAGE,
|
||||
"cannot decode N1 SM Content", smf_ue->supi, NULL);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
switch(nas_message.gsm.h.message_type) {
|
||||
case OGS_NAS_5GS_PDU_SESSION_MODIFICATION_REQUEST:
|
||||
pdu_session_modification_request =
|
||||
&nas_message.gsm.pdu_session_modification_request;
|
||||
|
||||
if (pdu_session_modification_request->presencemask &
|
||||
(OGS_NAS_5GS_PDU_SESSION_MODIFICATION_REQUEST_REQUESTED_QOS_RULES_PRESENT|
|
||||
OGS_NAS_5GS_PDU_SESSION_MODIFICATION_REQUEST_REQUESTED_QOS_FLOW_DESCRIPTIONS_PRESENT))
|
||||
ogs_list_init(&sess->qos_flow_to_modify_list);
|
||||
|
||||
if (pdu_session_modification_request->presencemask &
|
||||
OGS_NAS_5GS_PDU_SESSION_MODIFICATION_REQUEST_REQUESTED_QOS_RULES_PRESENT) {
|
||||
rv = gsm_handle_pdu_session_modification_qos_rules(
|
||||
sess,
|
||||
&pdu_session_modification_request->requested_qos_rules,
|
||||
&sess->nsmf_param.pfcp_flags);
|
||||
if (rv != OGS_OK) {
|
||||
ogs_error("[%s:%d] Invalid requested_qos_rules",
|
||||
smf_ue->supi, sess->psi);
|
||||
smf_sbi_send_hsmf_update_error(stream,
|
||||
OGS_SBI_HTTP_STATUS_BAD_REQUEST, OGS_SBI_APP_ERRNO_NULL,
|
||||
OGS_5GSM_CAUSE_INVALID_MANDATORY_INFORMATION,
|
||||
"Invalid requested_qos_rules", smf_ue->supi, NULL);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (pdu_session_modification_request->presencemask &
|
||||
OGS_NAS_5GS_PDU_SESSION_MODIFICATION_REQUEST_REQUESTED_QOS_FLOW_DESCRIPTIONS_PRESENT) {
|
||||
rv = gsm_handle_pdu_session_modification_qos_flow_descriptions(
|
||||
sess,
|
||||
&pdu_session_modification_request->
|
||||
requested_qos_flow_descriptions,
|
||||
&sess->nsmf_param.pfcp_flags);
|
||||
if (rv != OGS_OK) {
|
||||
ogs_error("[%s:%d] Invalid requested_qos_flow_descriptions",
|
||||
smf_ue->supi, sess->psi);
|
||||
smf_sbi_send_hsmf_update_error(stream,
|
||||
OGS_SBI_HTTP_STATUS_BAD_REQUEST, OGS_SBI_APP_ERRNO_NULL,
|
||||
OGS_5GSM_CAUSE_INVALID_MANDATORY_INFORMATION,
|
||||
"Invalid qos_flow_descriptions", smf_ue->supi, NULL);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
@ -2120,6 +2344,7 @@ bool smf_nsmf_handle_update_data_in_vsmf(
|
|||
OpenAPI_vsmf_update_data_t *VsmfUpdateData = NULL;
|
||||
|
||||
OpenAPI_list_t *qosFlowsAddModRequestList = NULL;
|
||||
OpenAPI_list_t *qosFlowsRelRequestList = NULL;
|
||||
OpenAPI_qos_flow_profile_t *qosFlowProfile = NULL;
|
||||
OpenAPI_lnode_t *node = NULL;
|
||||
|
||||
|
|
@ -2196,15 +2421,13 @@ bool smf_nsmf_handle_update_data_in_vsmf(
|
|||
src = node->data;
|
||||
if (!src ||
|
||||
!src->qfi ||
|
||||
!src->qos_rules ||
|
||||
!src->qos_flow_description ||
|
||||
!src->qos_flow_profile) {
|
||||
ogs_error("[%s:%d] No src [%d:%s:%s]",
|
||||
!(src->qos_flow_description || src->qos_flow_profile)) {
|
||||
ogs_error("[%s:%d] No src [%d:%s:%p]",
|
||||
smf_ue->supi, sess->psi, src->qfi,
|
||||
src->qos_rules ?
|
||||
src->qos_rules : "NULL",
|
||||
src->qos_flow_description ?
|
||||
src->qos_flow_description : "NULL");
|
||||
src->qos_flow_description : "NULL",
|
||||
src->qos_flow_profile ?
|
||||
src->qos_flow_profile : NULL);
|
||||
smf_sbi_send_vsmf_update_error(stream,
|
||||
OGS_SBI_HTTP_STATUS_BAD_REQUEST, OGS_SBI_APP_ERRNO_NULL,
|
||||
OGS_5GSM_CAUSE_INVALID_MANDATORY_INFORMATION,
|
||||
|
|
@ -2249,18 +2472,125 @@ bool smf_nsmf_handle_update_data_in_vsmf(
|
|||
else
|
||||
OpenAPI_list_free(qosFlowsAddModRequestList);
|
||||
|
||||
CLEAR_QOS_FLOWS_REL_REQUEST_LIST(
|
||||
sess->h_smf_qos_flows_rel_request_list);
|
||||
|
||||
qosFlowsRelRequestList = OpenAPI_list_create();
|
||||
ogs_assert(qosFlowsRelRequestList);
|
||||
OpenAPI_list_for_each(VsmfUpdateData->qos_flows_rel_request_list, node) {
|
||||
OpenAPI_qos_flow_release_request_item_t *dst = NULL, *src = NULL;
|
||||
|
||||
src = node->data;
|
||||
if (!src ||
|
||||
!src->qfi ||
|
||||
!src->qos_rules ||
|
||||
!src->qos_flow_description) {
|
||||
ogs_error("[%s:%d] No src [%d:%s:%s]",
|
||||
smf_ue->supi, sess->psi, src->qfi,
|
||||
src->qos_rules ?
|
||||
src->qos_rules : "NULL",
|
||||
src->qos_flow_description ?
|
||||
src->qos_flow_description : "NULL");
|
||||
smf_sbi_send_vsmf_update_error(stream,
|
||||
OGS_SBI_HTTP_STATUS_BAD_REQUEST, OGS_SBI_APP_ERRNO_NULL,
|
||||
OGS_5GSM_CAUSE_INVALID_MANDATORY_INFORMATION,
|
||||
"No src", smf_ue->supi, NULL);
|
||||
return false;
|
||||
}
|
||||
|
||||
dst = OpenAPI_qos_flow_release_request_item_copy(dst, src);
|
||||
ogs_assert(dst);
|
||||
OpenAPI_list_add(qosFlowsRelRequestList, dst);
|
||||
}
|
||||
|
||||
if (qosFlowsRelRequestList->count)
|
||||
sess->h_smf_qos_flows_rel_request_list = qosFlowsRelRequestList;
|
||||
else
|
||||
OpenAPI_list_free(qosFlowsRelRequestList);
|
||||
|
||||
sess->pti = OGS_NAS_PROCEDURE_TRANSACTION_IDENTITY_UNASSIGNED;
|
||||
|
||||
/*
|
||||
* Network-requested PDU Session Modification
|
||||
*
|
||||
* 1. H: OpenAPI_request_indication_NW_REQ_PDU_SES_MOD
|
||||
* QOS_RULE_CODE_FROM_PFCP_FLAGS
|
||||
* QOS_RULE_FLOW_DESCRIPTION_CODE_FROM_PFCP_FLAGS
|
||||
* 2. H: smf_nsmf_pdusession_build_vsmf_update_data
|
||||
* 3. V: smf_nsmf_handle_update_data_in_vsmf
|
||||
* 4. V*: gsm_build_pdu_session_modification_command+
|
||||
* ngap_build_pdu_session_resource_modify_request_transfer
|
||||
* 5. V: OpenAPI_n2_sm_info_type_PDU_RES_MOD_RSP
|
||||
* if (sess->up_cnx_state == OpenAPI_up_cnx_state_ACTIVATING)
|
||||
* sess->up_cnx_state = OpenAPI_up_cnx_state_ACTIVATED;
|
||||
* smf_sbi_send_sm_context_updated_data_up_cnx_state(
|
||||
* OpenAPI_up_cnx_state_ACTIVATED)
|
||||
* else
|
||||
* ogs_sbi_send_http_status_no_content(stream)
|
||||
* 6. V: ogs_sbi_send_http_status_no_content(stream)
|
||||
* OGS_NAS_5GS_PDU_SESSION_MODIFICATION_COMPLETE:
|
||||
* ogs_sbi_send_http_status_no_content(n1_n2_modified_stream));
|
||||
* 7. V: case OGS_EVENT_SBI_CLIENT
|
||||
* CASE(OGS_SBI_RESOURCE_NAME_VSMF_PDU_SESSIONS)
|
||||
* 8. H: OGS_PFCP_MODIFY_HOME_ROUTED_ROAMING|
|
||||
* OGS_PFCP_MODIFY_DL_ONLY|OGS_PFCP_MODIFY_ACTIVATE
|
||||
*/
|
||||
memset(¶m, 0, sizeof(param));
|
||||
|
||||
param.state = SMF_NETWORK_REQUESTED_QOS_FLOW_MODIFICATION;
|
||||
param.n1smbuf = gsm_build_pdu_session_modification_command(sess, 0, 0);
|
||||
ogs_assert(param.n1smbuf);
|
||||
param.n2smbuf =
|
||||
ngap_build_pdu_session_resource_modify_request_transfer(sess,
|
||||
qosFlowProfile->gbr_qos_flow_info ? true : false);
|
||||
ogs_assert(param.n2smbuf);
|
||||
|
||||
smf_namf_comm_send_n1_n2_message_transfer(sess, stream, ¶m);
|
||||
if (sess->h_smf_qos_flows_rel_request_list) {
|
||||
param.n2smbuf =
|
||||
ngap_build_pdu_session_resource_release_request_transfer(
|
||||
sess, NGAP_Cause_PR_nas, NGAP_CauseNas_normal_release);
|
||||
ogs_assert(param.n2smbuf);
|
||||
} else if (sess->h_smf_qos_flows_add_mod_request_list) {
|
||||
param.n2smbuf =
|
||||
ngap_build_pdu_session_resource_modify_request_transfer(sess,
|
||||
qosFlowProfile->gbr_qos_flow_info ? true : false);
|
||||
ogs_assert(param.n2smbuf);
|
||||
} else
|
||||
ogs_error("No LIST");
|
||||
|
||||
if (sess->nsmf_param.request_indication ==
|
||||
OpenAPI_request_indication_NW_REQ_PDU_SES_MOD) {
|
||||
if (sess->establishment_accept_sent == true) {
|
||||
smf_namf_comm_send_n1_n2_message_transfer(sess, stream, ¶m);
|
||||
} else {
|
||||
if (sess->pending_modification_xact)
|
||||
ogs_sbi_xact_remove(sess->pending_modification_xact);
|
||||
|
||||
sess->pending_modification_xact =
|
||||
smf_namf_comm_create_n1_n2_message_xact(
|
||||
sess, stream, ¶m);
|
||||
}
|
||||
} else if (sess->nsmf_param.request_indication ==
|
||||
OpenAPI_request_indication_UE_REQ_PDU_SES_MOD) {
|
||||
ogs_sbi_stream_t *amf_to_vsmf_modify_stream = NULL;
|
||||
if (sess->amf_to_vsmf_modify_stream_id >= OGS_MIN_POOL_ID &&
|
||||
sess->amf_to_vsmf_modify_stream_id <= OGS_MAX_POOL_ID)
|
||||
amf_to_vsmf_modify_stream =
|
||||
ogs_sbi_stream_find_by_id(
|
||||
sess->amf_to_vsmf_modify_stream_id);
|
||||
|
||||
if (amf_to_vsmf_modify_stream) {
|
||||
smf_sbi_send_sm_context_updated_data_n1_n2_message(
|
||||
sess, amf_to_vsmf_modify_stream, param.n1smbuf,
|
||||
OpenAPI_n2_sm_info_type_PDU_RES_MOD_REQ, param.n2smbuf);
|
||||
|
||||
sess->amf_to_vsmf_modify_stream_id = OGS_INVALID_POOL_ID;
|
||||
|
||||
if (sess->vsmf_to_hsmf_modify_stream_id >= OGS_MIN_POOL_ID &&
|
||||
sess->vsmf_to_hsmf_modify_stream_id <= OGS_MAX_POOL_ID)
|
||||
ogs_error("N1 N2 modified stream ID [%d]"
|
||||
"has not been used yet",
|
||||
sess->vsmf_to_hsmf_modify_stream_id);
|
||||
sess->vsmf_to_hsmf_modify_stream_id =
|
||||
ogs_sbi_id_from_stream(stream);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case OpenAPI_request_indication_UE_REQ_PDU_SES_REL:
|
||||
|
|
|
|||
|
|
@ -236,14 +236,13 @@ int smf_sbi_discover_and_send(
|
|||
return OGS_OK;
|
||||
}
|
||||
|
||||
void smf_namf_comm_send_n1_n2_message_transfer(
|
||||
ogs_sbi_xact_t *smf_namf_comm_create_n1_n2_message_xact(
|
||||
smf_sess_t *sess, ogs_sbi_stream_t *stream,
|
||||
smf_n1_n2_message_transfer_param_t *param)
|
||||
{
|
||||
smf_ue_t *smf_ue = NULL;
|
||||
ogs_sbi_xact_t *xact = NULL;
|
||||
ogs_sbi_discovery_option_t *discovery_option = NULL;
|
||||
int r;
|
||||
|
||||
ogs_assert(sess);
|
||||
smf_ue = smf_ue_find_by_id(sess->smf_ue_id);
|
||||
|
|
@ -264,8 +263,8 @@ void smf_namf_comm_send_n1_n2_message_transfer(
|
|||
(ogs_sbi_build_f)smf_namf_comm_build_n1_n2_message_transfer,
|
||||
sess, param);
|
||||
if (!xact) {
|
||||
ogs_error("smf_namf_comm_send_n1_n2_message_transfer() failed");
|
||||
return;
|
||||
ogs_error("ogs_sbi_xact_add() failed");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
xact->state = param->state;
|
||||
|
|
@ -276,6 +275,27 @@ void smf_namf_comm_send_n1_n2_message_transfer(
|
|||
xact->assoc_stream_id <= OGS_MAX_POOL_ID);
|
||||
}
|
||||
|
||||
return xact;
|
||||
}
|
||||
|
||||
void smf_namf_comm_send_n1_n2_message_transfer(
|
||||
smf_sess_t *sess, ogs_sbi_stream_t *stream,
|
||||
smf_n1_n2_message_transfer_param_t *param)
|
||||
{
|
||||
ogs_sbi_xact_t *xact = NULL;
|
||||
int r;
|
||||
|
||||
ogs_assert(sess);
|
||||
ogs_assert(param);
|
||||
ogs_assert(param->state);
|
||||
ogs_assert(param->n1smbuf || param->n2smbuf);
|
||||
|
||||
xact = smf_namf_comm_create_n1_n2_message_xact(sess, stream, param);
|
||||
if (!xact) {
|
||||
ogs_error("smf_namf_comm_create_n1_n2_message_xact() failed");
|
||||
return;
|
||||
}
|
||||
|
||||
r = ogs_sbi_discover_and_send(xact);
|
||||
if (r != OGS_OK) {
|
||||
ogs_error("smf_namf_comm_send_n1_n2_message_transfer() failed");
|
||||
|
|
|
|||
|
|
@ -36,12 +36,95 @@ void smf_sbi_close(void);
|
|||
|
||||
bool smf_sbi_send_request(
|
||||
ogs_sbi_nf_instance_t *nf_instance, ogs_sbi_xact_t *xact);
|
||||
|
||||
/*
|
||||
* PFCP delete triggers are defined in lib/pfcp/xact.h (values 1–7).
|
||||
* To avoid overlap with OGS_PFCP_DELETE_TRIGGER_*, SMF states use:
|
||||
* - UPDATE_STATE_BASE at 0x10–0x14
|
||||
* - UECM_STATE_BASE at 0x20–0x23
|
||||
* HR flag is bit 7 (0x80).
|
||||
*/
|
||||
|
||||
/* Common HR flag (bit 7) */
|
||||
#define SMF_STATE_HR (1U << 7) /* 0x80 */
|
||||
|
||||
/* Base offset for SMF_CREATE states */
|
||||
#define SMF_CREATE_STATE_BASE 0x10U /* CREATE at 0x10 */
|
||||
|
||||
#define SMF_CREATE_STATE_NONE \
|
||||
(SMF_CREATE_STATE_BASE + 0x00U) /* 0x00 */
|
||||
|
||||
/* Base offset for SMF_UPDATE states */
|
||||
#define SMF_UPDATE_STATE_BASE 0x20U /* UPDATE at 0x20–0x24 */
|
||||
|
||||
/* SMF_UPDATE base states */
|
||||
#define SMF_UPDATE_STATE_NONE \
|
||||
(SMF_UPDATE_STATE_BASE + 0x00U) /* 0x00 */
|
||||
#define SMF_UPDATE_STATE_ACTIVATING \
|
||||
(SMF_UPDATE_STATE_BASE + 0x01U) /* 0x01 */
|
||||
#define SMF_UPDATE_STATE_ACTIVATED_FROM_ACTIVATING \
|
||||
(SMF_UPDATE_STATE_BASE + 0x02U) /* 0x02 */
|
||||
#define SMF_UPDATE_STATE_ACTIVATED_FROM_NON_ACTIVATING \
|
||||
(SMF_UPDATE_STATE_BASE + 0x03U) /* 0x03 */
|
||||
#define SMF_UPDATE_STATE_DEACTIVATED \
|
||||
(SMF_UPDATE_STATE_BASE + 0x04U) /* 0x04 */
|
||||
#define SMF_UPDATE_STATE_UE_REQ_MOD \
|
||||
(SMF_UPDATE_STATE_BASE + 0x05U) /* 0x05 */
|
||||
|
||||
/* Base offset for SMF_REMOVE states */
|
||||
#define SMF_REMOVE_STATE_BASE 0x30U /* REMOVE at 0x30 */
|
||||
|
||||
#define SMF_REMOVE_STATE_NONE \
|
||||
(SMF_REMOVE_STATE_BASE + 0x00U) /* 0x00 */
|
||||
|
||||
/* Base offset for SMF_UECM states */
|
||||
#define SMF_UECM_STATE_BASE 0x40U /* UECM at 0x40–0x43 */
|
||||
|
||||
/* SMF_UECM base states */
|
||||
#define SMF_UECM_STATE_NONE \
|
||||
(SMF_UECM_STATE_BASE + 0x00U) /* 0x20 */
|
||||
#define SMF_UECM_STATE_REGISTERED \
|
||||
(SMF_UECM_STATE_BASE + 0x01U) /* 0x21 */
|
||||
#define SMF_UECM_STATE_DEREG_BY_AMF \
|
||||
(SMF_UECM_STATE_BASE + 0x02U) /* 0x22 */
|
||||
#define SMF_UECM_STATE_DEREG_BY_N1N2 \
|
||||
(SMF_UECM_STATE_BASE + 0x03U) /* 0x23 */
|
||||
|
||||
/* HR variants for SMF_UECM */
|
||||
#define SMF_UECM_STATE_REGISTERED_HR \
|
||||
(SMF_UECM_STATE_REGISTERED | SMF_STATE_HR) /* 0xC1 */
|
||||
#define SMF_UECM_STATE_DEREG_BY_AMF_HR \
|
||||
(SMF_UECM_STATE_DEREG_BY_AMF | SMF_STATE_HR) /* 0xC2 */
|
||||
#define SMF_UECM_STATE_DEREG_BY_N1N2_HR \
|
||||
(SMF_UECM_STATE_DEREG_BY_N1N2 | SMF_STATE_HR) /* 0xC3 */
|
||||
|
||||
int smf_sbi_discover_and_send(
|
||||
ogs_sbi_service_type_e service_type,
|
||||
ogs_sbi_discovery_option_t *discovery_option,
|
||||
ogs_sbi_request_t *(*build)(smf_sess_t *sess, void *data),
|
||||
smf_sess_t *sess, ogs_sbi_stream_t *stream, int state, void *data);
|
||||
|
||||
/**
|
||||
* Return true if the PDU session anchor SMF is in the HPLMN
|
||||
* (Home-Routed Roaming, HR)
|
||||
*/
|
||||
static inline bool smf_uecm_anchor_in_hplmn(int state)
|
||||
{
|
||||
return !!(state & SMF_STATE_HR);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if the PDU session anchor SMF is in the VPLMN
|
||||
* (Non-Roaming or Local Break-Out Roaming, LBO)
|
||||
*/
|
||||
static inline bool smf_uecm_anchor_in_vplmn(int state)
|
||||
{
|
||||
return !(state & SMF_STATE_HR);
|
||||
}
|
||||
|
||||
ogs_sbi_xact_t *smf_namf_comm_create_n1_n2_message_xact(
|
||||
smf_sess_t *sess, ogs_sbi_stream_t *stream,
|
||||
smf_n1_n2_message_transfer_param_t *param);
|
||||
void smf_namf_comm_send_n1_n2_message_transfer(
|
||||
smf_sess_t *sess, ogs_sbi_stream_t *stream,
|
||||
smf_n1_n2_message_transfer_param_t *param);
|
||||
|
|
|
|||
|
|
@ -1145,8 +1145,89 @@ void smf_state_operational(ogs_fsm_t *s, smf_event_t *e)
|
|||
ogs_assert(true == smf_sbi_send_sm_context_status_notify(sess));
|
||||
SMF_SESS_CLEAR(sess);
|
||||
} else if (state == SMF_UECM_STATE_DEREG_BY_AMF_HR) {
|
||||
/*
|
||||
* Network-requested PDU Session Release(DUPLICATED)
|
||||
*
|
||||
* 1. V: OGS_PFCP_MODIFY_HOME_ROUTED_ROAMING|OGS_PFCP_MODIFY_UL_ONLY|
|
||||
* OGS_PFCP_MODIFY_DEACTIVATE
|
||||
* 2. V: OGS_PFCP_DELETE_TRIGGER_AMF_UPDATE_SM_CONTEXT,
|
||||
* 3. V: OpenAPI_request_indication_NW_REQ_PDU_SES_REL
|
||||
* 4. V: smf_nsmf_pdusession_build_hsmf_update_data
|
||||
* 5. H: smf_nsmf_handle_update_data_in_hsmf
|
||||
* 6. H: OpenAPI_request_indication_NW_REQ_PDU_SES_REL
|
||||
* 6. H: e->h.sbi.state = OGS_PFCP_DELETE_TRIGGER_AMF_UPDATE_SM_CONTEXT
|
||||
* 7. H: ogs_sbi_send_http_status_no_content
|
||||
* 8. H: OGS_FSM_TRAN(s, smf_gsm_state_wait_pfcp_deletion)
|
||||
* 9. H: smf_sbi_cleanup_session(SMF_UECM_STATE_DEREG_BY_AMF_HR
|
||||
* SMF_SBI_CLEANUP_MODE_POLICY_FIRST);
|
||||
* 10. H: OGS_FSM_TRAN(s, smf_gsm_state_5gc_session_will_deregister);
|
||||
* 11. H*: SMF_SESS_CLEAR(sess)
|
||||
* 12. V: e->h.sbi.state = OGS_PFCP_DELETE_TRIGGER_AMF_UPDATE_SM_CONTEXT
|
||||
* 13. V: OGS_FSM_TRAN(s, smf_gsm_state_wait_pfcp_deletion)
|
||||
* 14. V: ogs_sbi_send_http_status_no_content
|
||||
* 15. V: OGS_FSM_TRAN(s, smf_gsm_state_session_will_release);
|
||||
*
|
||||
* Network-requested PDU Session Release
|
||||
*
|
||||
* 1. V: smf_nsmf_handle_release_sm_context
|
||||
* 2. V: OGS_PFCP_MODIFY_HOME_ROUTED_ROAMING|OGS_PFCP_MODIFY_UL_ONLY|
|
||||
* OGS_PFCP_MODIFY_DEACTIVATE
|
||||
* 3. V: OGS_PFCP_DELETE_TRIGGER_AMF_RELEASE_SM_CONTEXT
|
||||
* 4. V: smf_nsmf_pdusession_build_release_data
|
||||
* 5. H: smf_nsmf_handle_release_data_in_hsmf
|
||||
* 6. H: e->h.sbi.state = OGS_PFCP_DELETE_TRIGGER_AMF_RELEASE_SM_CONTEXT
|
||||
* 7. H: OGS_FSM_TRAN(s, smf_gsm_state_wait_pfcp_deletion)
|
||||
* 8. H: ogs_sbi_send_http_status_no_content
|
||||
* 9. H: smf_sbi_cleanup_session(SMF_UECM_STATE_DEREG_BY_AMF_HR
|
||||
* SMF_SBI_CLEANUP_MODE_POLICY_FIRST);
|
||||
* 10. H: OGS_FSM_TRAN(s, smf_gsm_state_5gc_session_will_deregister);
|
||||
* 11. H*: SMF_SESS_CLEAR(sess)
|
||||
* 12. V: smf_nsmf_handle_release_data_in_hsmf
|
||||
* 13. V: e->h.sbi.state = OGS_PFCP_DELETE_TRIGGER_AMF_RELEASE_SM_CONTEXT
|
||||
* 14. V: OGS_FSM_TRAN(s, smf_gsm_state_wait_pfcp_deletion)
|
||||
* 15. V: ogs_sbi_send_http_status_no_content
|
||||
* 16. V: OGS_FSM_TRAN(s, smf_gsm_state_session_will_release);
|
||||
*/
|
||||
SMF_SESS_CLEAR(sess);
|
||||
} else if (state == SMF_UECM_STATE_DEREG_BY_N1N2_HR) {
|
||||
/*
|
||||
* UE-requested PDU Session Release
|
||||
*
|
||||
* 1. V: OGS_PFCP_MODIFY_HOME_ROUTED_ROAMING|OGS_PFCP_MODIFY_UL_ONLY|
|
||||
* OGS_PFCP_MODIFY_DEACTIVATE
|
||||
* 2. V: OGS_PFCP_DELETE_TRIGGER_UE_REQUESTED
|
||||
* 3. V: OpenAPI_request_indication_UE_REQ_PDU_SES_REL
|
||||
* 4. V: smf_nsmf_pdusession_build_hsmf_update_data
|
||||
* 5. H: smf_nsmf_handle_update_data_in_hsmf
|
||||
* 6. H: OpenAPI_request_indication_UE_REQ_PDU_SES_REL
|
||||
* 6. H: e->h.sbi.state = OGS_PFCP_DELETE_TRIGGER_UE_REQUESTED
|
||||
* 7. H: ogs_sbi_send_http_status_no_content
|
||||
* 8. H: OGS_FSM_TRAN(s, smf_gsm_state_wait_pfcp_deletion)
|
||||
* 9. H: smf_nsmf_pdusession_build_vsmf_update_data
|
||||
* 10. H: OGS_FSM_TRAN(s, smf_gsm_state_wait_5gc_n1_n2_release);
|
||||
* 11. V: smf_nsmf_handle_update_data_in_vsmf
|
||||
* 12. V: OpenAPI_request_indication_UE_REQ_PDU_SES_REL
|
||||
* 13. V: e->h.sbi.state = OGS_PFCP_DELETE_TRIGGER_UE_REQUESTED
|
||||
* 14. V: OGS_FSM_TRAN(s, smf_gsm_state_wait_pfcp_deletion)
|
||||
* 15. V: ngap_build_pdu_session_resource_release_command_transfer+
|
||||
* gsm_build_pdu_session_release_command
|
||||
* 16 V: OGS_FSM_TRAN(&sess->sm, smf_gsm_state_wait_5gc_n1_n2_release)
|
||||
* 17. V: ogs_sbi_send_http_status_no_content(stream)
|
||||
* 18. V: case OpenAPI_n2_sm_info_type_PDU_RES_REL_RSP:
|
||||
* case OGS_NAS_5GS_PDU_SESSION_RELEASE_COMPLETE:
|
||||
* 19. V: ogs_sbi_send_http_status_no_content(n1_n2_released_stream)
|
||||
* 20. V: OGS_FSM_TRAN(s, smf_gsm_state_5gc_session_will_deregister);
|
||||
* 21. H: case OGS_EVENT_SBI_CLIENT:
|
||||
* 22. H: CASE(OGS_SBI_RESOURCE_NAME_VSMF_PDU_SESSIONS)
|
||||
* 23. H: smf_sbi_cleanup_session(SMF_UECM_STATE_DEREG_BY_N1N2_HR
|
||||
* SMF_SBI_CLEANUP_MODE_POLICY_FIRST);
|
||||
* 24. H*: smf_sbi_send_status_notify+SMF_SESS_CLEAR(sess)
|
||||
* 25. V: case OGS_EVENT_SBI_SERVER:
|
||||
* 26. V: CASE(OGS_SBI_RESOURCE_NAME_VSMF_PDU_SESSIONS)
|
||||
* 27. V: ogs_sbi_send_http_status_no_content+
|
||||
* smf_sbi_send_sm_context_status_notify
|
||||
* 28. V: OGS_FSM_TRAN(s, smf_gsm_state_session_will_release);
|
||||
*/
|
||||
ogs_assert(true == smf_sbi_send_status_notify(sess));
|
||||
SMF_SESS_CLEAR(sess);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1886,7 +1886,7 @@ bson_t *test_db_new_session(test_ue_t *test_ue)
|
|||
"pre_emption_capability", BCON_INT32(1),
|
||||
"}",
|
||||
"}",
|
||||
#if 1
|
||||
#if 0
|
||||
"lbo_roaming_allowed", BCON_BOOL(true),
|
||||
#else
|
||||
"lbo_roaming_allowed", BCON_BOOL(false),
|
||||
|
|
@ -1953,7 +1953,7 @@ bson_t *test_db_new_session(test_ue_t *test_ue)
|
|||
"description", BCON_UTF8("permit out udp from 10.200.136.98/32 1-65535 to assigned 50021"), "}",
|
||||
"]",
|
||||
"}", "]",
|
||||
#if 1
|
||||
#if 0
|
||||
"lbo_roaming_allowed", BCON_BOOL(true),
|
||||
#else
|
||||
"lbo_roaming_allowed", BCON_BOOL(false),
|
||||
|
|
@ -2025,6 +2025,11 @@ bson_t *test_db_new_ims(test_ue_t *test_ue)
|
|||
"pre_emption_capability", BCON_INT32(1),
|
||||
"}",
|
||||
"}",
|
||||
#if 0
|
||||
"lbo_roaming_allowed", BCON_BOOL(true),
|
||||
#else
|
||||
"lbo_roaming_allowed", BCON_BOOL(false),
|
||||
#endif
|
||||
"}",
|
||||
"{",
|
||||
"name", BCON_UTF8("ims"),
|
||||
|
|
@ -2109,7 +2114,7 @@ bson_t *test_db_new_ims(test_ue_t *test_ue)
|
|||
"}",
|
||||
"}",
|
||||
"]",
|
||||
#if 1
|
||||
#if 0
|
||||
"lbo_roaming_allowed", BCON_BOOL(true),
|
||||
#else
|
||||
"lbo_roaming_allowed", BCON_BOOL(false),
|
||||
|
|
|
|||
|
|
@ -3966,6 +3966,25 @@ static void test7_func(abts_case *tc, void *data)
|
|||
test_ue_remove(test_ue);
|
||||
}
|
||||
|
||||
/*
|
||||
* Disable test8_func when running Home Routed Roaming tests,
|
||||
* to prevent V-SMF from skipping Update Response (step 14)
|
||||
* and avoid subsequent SBI timeout and PFCP No Context errors.
|
||||
*/
|
||||
#define HOME_ROUTED_ROAMING_TEST 0
|
||||
|
||||
#if !HOME_ROUTED_ROAMING_TEST
|
||||
/**
|
||||
* test8_func:
|
||||
* - Simulates absence of N2 Resource Release Ack (step 8)
|
||||
* and PDU Session Release Accept (step 11) from gNB/UE.
|
||||
* - In Home Routed Roaming, V-SMF will not send the
|
||||
* Nsmf_PDUSession_Update Response (step 14), causing
|
||||
* the SBI client to timeout after 10 seconds.
|
||||
* - Subsequent deregistration triggers a PFCP deactivation
|
||||
* modification, but UPF has no session, leading to
|
||||
* a No Context error.
|
||||
*/
|
||||
static void test8_func(abts_case *tc, void *data)
|
||||
{
|
||||
int rv;
|
||||
|
|
@ -4327,12 +4346,19 @@ static void test8_func(abts_case *tc, void *data)
|
|||
/* Clear Test UE Context */
|
||||
test_ue_remove(test_ue);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
abts_suite *test_af(abts_suite *suite)
|
||||
{
|
||||
suite = ADD_SUITE(suite)
|
||||
|
||||
/**
|
||||
* abts_suite test_af:
|
||||
* - Always run test1_func through test7_func.
|
||||
* - Conditionally include test8_func based on
|
||||
* HOME_ROUTED_ROAMING_TEST flag.
|
||||
*/
|
||||
abts_run_test(suite, test1_func, NULL);
|
||||
abts_run_test(suite, test2_func, NULL);
|
||||
abts_run_test(suite, test3_func, NULL);
|
||||
|
|
@ -4340,7 +4366,9 @@ abts_suite *test_af(abts_suite *suite)
|
|||
abts_run_test(suite, test5_func, NULL);
|
||||
abts_run_test(suite, test6_func, NULL);
|
||||
abts_run_test(suite, test7_func, NULL);
|
||||
#if !HOME_ROUTED_ROAMING_TEST
|
||||
abts_run_test(suite, test8_func, NULL);
|
||||
#endif
|
||||
|
||||
return suite;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1367,6 +1367,8 @@ static void test4_func(abts_case *tc, void *data)
|
|||
|
||||
bson_t *doc = NULL;
|
||||
|
||||
NGAP_ProcedureCode_t ngap_procedure_code;
|
||||
|
||||
/* Setup Test UE & Session Context */
|
||||
memset(&mobile_identity_suci, 0, sizeof(mobile_identity_suci));
|
||||
|
||||
|
|
@ -1551,23 +1553,62 @@ static void test4_func(abts_case *tc, void *data)
|
|||
rv = testgnb_ngap_send(ngap, sendbuf);
|
||||
ABTS_INT_EQUAL(tc, OGS_OK, rv);
|
||||
|
||||
/* Receive PDUSessionResourceSetupRequest +
|
||||
/*
|
||||
* Receive PDUSessionResourceSetupRequest +
|
||||
* DL NAS transport +
|
||||
* PDU session establishment accept */
|
||||
* PDU session establishment accept
|
||||
*
|
||||
* OR
|
||||
*
|
||||
* Receive PDUSessionResourceModifyRequest +
|
||||
* DL NAS transport +
|
||||
* PDU session modification command
|
||||
*/
|
||||
recvbuf = testgnb_ngap_read(ngap);
|
||||
ABTS_PTR_NOTNULL(tc, recvbuf);
|
||||
testngap_recv(test_ue, recvbuf);
|
||||
ABTS_INT_EQUAL(tc,
|
||||
NGAP_ProcedureCode_id_PDUSessionResourceSetup,
|
||||
test_ue->ngap_procedure_code);
|
||||
|
||||
/* Receive PDU session establishment accept */
|
||||
ngap_procedure_code = test_ue->ngap_procedure_code;
|
||||
|
||||
/*
|
||||
* Receive PDUSessionResourceSetupRequest +
|
||||
* DL NAS transport +
|
||||
* PDU session establishment accept
|
||||
*
|
||||
* OR
|
||||
*
|
||||
* Receive PDUSessionResourceModifyRequest +
|
||||
* DL NAS transport +
|
||||
* PDU session modification command
|
||||
*/
|
||||
recvbuf = testgnb_ngap_read(ngap);
|
||||
ABTS_PTR_NOTNULL(tc, recvbuf);
|
||||
testngap_recv(test_ue, recvbuf);
|
||||
|
||||
ngap_procedure_code += test_ue->ngap_procedure_code;
|
||||
|
||||
/*
|
||||
* Receive PDUSessionResourceSetupRequest +
|
||||
* DL NAS transport +
|
||||
* PDU session establishment accept
|
||||
*
|
||||
* OR
|
||||
*
|
||||
* Receive PDUSessionResourceModifyRequest +
|
||||
* DL NAS transport +
|
||||
* PDU session modification command
|
||||
*/
|
||||
recvbuf = testgnb_ngap_read(ngap);
|
||||
ABTS_PTR_NOTNULL(tc, recvbuf);
|
||||
testngap_recv(test_ue, recvbuf);
|
||||
|
||||
ngap_procedure_code += test_ue->ngap_procedure_code;
|
||||
|
||||
ABTS_INT_EQUAL(tc,
|
||||
NGAP_ProcedureCode_id_PDUSessionResourceSetup,
|
||||
test_ue->ngap_procedure_code);
|
||||
NGAP_ProcedureCode_id_PDUSessionResourceSetup +
|
||||
NGAP_ProcedureCode_id_PDUSessionResourceSetup +
|
||||
NGAP_ProcedureCode_id_PDUSessionResourceModify,
|
||||
ngap_procedure_code);
|
||||
|
||||
/* Send GTP-U ICMP Packet */
|
||||
qos_flow1 = test_qos_flow_find_by_qfi(sess5, 1);
|
||||
|
|
@ -1601,16 +1642,6 @@ static void test4_func(abts_case *tc, void *data)
|
|||
ABTS_PTR_NOTNULL(tc, recvbuf);
|
||||
ogs_pkbuf_free(recvbuf);
|
||||
|
||||
/* Receive PDUSessionResourceModifyRequest +
|
||||
* DL NAS transport +
|
||||
* PDU session modification command */
|
||||
recvbuf = testgnb_ngap_read(ngap);
|
||||
ABTS_PTR_NOTNULL(tc, recvbuf);
|
||||
testngap_recv(test_ue, recvbuf);
|
||||
ABTS_INT_EQUAL(tc,
|
||||
NGAP_ProcedureCode_id_PDUSessionResourceModify,
|
||||
test_ue->ngap_procedure_code);
|
||||
|
||||
/* Send PDU session resource modify response */
|
||||
qos_flow2 = test_qos_flow_find_by_qfi(sess6, 2);
|
||||
ogs_assert(qos_flow2);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue