mirror of
https://github.com/open5gs/open5gs.git
synced 2025-10-24 08:33:48 +00:00
[HR] Implement Network-Initiated PDU Session Modification (Home-Routed Roaming) (#2194)
This commit adds support for processing network-initiated PDU Session Modification in a home-routed roaming context, following section 4.3.3.3 of the specification.
This commit is contained in:
@@ -325,6 +325,15 @@ bsf:
|
|||||||
scp:
|
scp:
|
||||||
- uri: http://127.0.0.200:7777
|
- uri: http://127.0.0.200:7777
|
||||||
|
|
||||||
|
af:
|
||||||
|
sbi:
|
||||||
|
server:
|
||||||
|
- address: 127.0.0.16
|
||||||
|
port: 7777
|
||||||
|
client:
|
||||||
|
scp:
|
||||||
|
- uri: http://127.0.0.200:7777
|
||||||
|
|
||||||
udr:
|
udr:
|
||||||
sbi:
|
sbi:
|
||||||
server:
|
server:
|
||||||
|
|||||||
@@ -325,6 +325,15 @@ bsf:
|
|||||||
scp:
|
scp:
|
||||||
- uri: http://127.0.0.200:7777
|
- uri: http://127.0.0.200:7777
|
||||||
|
|
||||||
|
af:
|
||||||
|
sbi:
|
||||||
|
server:
|
||||||
|
- address: 127.0.0.16
|
||||||
|
port: 7777
|
||||||
|
client:
|
||||||
|
scp:
|
||||||
|
- uri: http://127.0.0.200:7777
|
||||||
|
|
||||||
udr:
|
udr:
|
||||||
sbi:
|
sbi:
|
||||||
server:
|
server:
|
||||||
|
|||||||
@@ -320,6 +320,15 @@ bsf:
|
|||||||
scp:
|
scp:
|
||||||
- uri: http://127.0.0.200:7777
|
- uri: http://127.0.0.200:7777
|
||||||
|
|
||||||
|
af:
|
||||||
|
sbi:
|
||||||
|
server:
|
||||||
|
- address: 127.0.0.16
|
||||||
|
port: 7777
|
||||||
|
client:
|
||||||
|
scp:
|
||||||
|
- uri: http://127.0.0.200:7777
|
||||||
|
|
||||||
udr:
|
udr:
|
||||||
sbi:
|
sbi:
|
||||||
server:
|
server:
|
||||||
|
|||||||
@@ -325,6 +325,15 @@ bsf:
|
|||||||
scp:
|
scp:
|
||||||
- uri: http://127.0.0.200:7777
|
- uri: http://127.0.0.200:7777
|
||||||
|
|
||||||
|
af:
|
||||||
|
sbi:
|
||||||
|
server:
|
||||||
|
- address: 127.0.0.16
|
||||||
|
port: 7777
|
||||||
|
client:
|
||||||
|
scp:
|
||||||
|
- uri: http://127.0.0.200:7777
|
||||||
|
|
||||||
udr:
|
udr:
|
||||||
sbi:
|
sbi:
|
||||||
server:
|
server:
|
||||||
|
|||||||
@@ -320,6 +320,15 @@ bsf:
|
|||||||
scp:
|
scp:
|
||||||
- uri: http://127.0.0.200:7777
|
- uri: http://127.0.0.200:7777
|
||||||
|
|
||||||
|
af:
|
||||||
|
sbi:
|
||||||
|
server:
|
||||||
|
- address: 127.0.0.16
|
||||||
|
port: 7777
|
||||||
|
client:
|
||||||
|
scp:
|
||||||
|
- uri: http://127.0.0.200:7777
|
||||||
|
|
||||||
udr:
|
udr:
|
||||||
sbi:
|
sbi:
|
||||||
server:
|
server:
|
||||||
|
|||||||
@@ -325,6 +325,15 @@ bsf:
|
|||||||
scp:
|
scp:
|
||||||
- uri: http://127.0.0.200:7777
|
- uri: http://127.0.0.200:7777
|
||||||
|
|
||||||
|
af:
|
||||||
|
sbi:
|
||||||
|
server:
|
||||||
|
- address: 127.0.0.16
|
||||||
|
port: 7777
|
||||||
|
client:
|
||||||
|
scp:
|
||||||
|
- uri: http://127.0.0.200:7777
|
||||||
|
|
||||||
udr:
|
udr:
|
||||||
sbi:
|
sbi:
|
||||||
server:
|
server:
|
||||||
|
|||||||
@@ -325,6 +325,15 @@ bsf:
|
|||||||
scp:
|
scp:
|
||||||
- uri: http://127.0.0.200:7777
|
- uri: http://127.0.0.200:7777
|
||||||
|
|
||||||
|
af:
|
||||||
|
sbi:
|
||||||
|
server:
|
||||||
|
- address: 127.0.0.16
|
||||||
|
port: 7777
|
||||||
|
client:
|
||||||
|
scp:
|
||||||
|
- uri: http://127.0.0.200:7777
|
||||||
|
|
||||||
udr:
|
udr:
|
||||||
sbi:
|
sbi:
|
||||||
server:
|
server:
|
||||||
|
|||||||
@@ -325,6 +325,15 @@ bsf:
|
|||||||
scp:
|
scp:
|
||||||
- uri: http://127.0.0.200:7777
|
- uri: http://127.0.0.200:7777
|
||||||
|
|
||||||
|
af:
|
||||||
|
sbi:
|
||||||
|
server:
|
||||||
|
- address: 127.0.0.16
|
||||||
|
port: 7777
|
||||||
|
client:
|
||||||
|
scp:
|
||||||
|
- uri: http://127.0.0.200:7777
|
||||||
|
|
||||||
udr:
|
udr:
|
||||||
sbi:
|
sbi:
|
||||||
server:
|
server:
|
||||||
|
|||||||
@@ -320,6 +320,15 @@ bsf:
|
|||||||
scp:
|
scp:
|
||||||
- uri: http://127.0.0.200:7777
|
- uri: http://127.0.0.200:7777
|
||||||
|
|
||||||
|
af:
|
||||||
|
sbi:
|
||||||
|
server:
|
||||||
|
- address: 127.0.0.16
|
||||||
|
port: 7777
|
||||||
|
client:
|
||||||
|
scp:
|
||||||
|
- uri: http://127.0.0.200:7777
|
||||||
|
|
||||||
udr:
|
udr:
|
||||||
sbi:
|
sbi:
|
||||||
server:
|
server:
|
||||||
|
|||||||
@@ -21,6 +21,7 @@
|
|||||||
#include "s5c-build.h"
|
#include "s5c-build.h"
|
||||||
#include "pfcp-path.h"
|
#include "pfcp-path.h"
|
||||||
#include "gtp-path.h"
|
#include "gtp-path.h"
|
||||||
|
#include "sbi-path.h"
|
||||||
|
|
||||||
#include "ipfw/ipfw2.h"
|
#include "ipfw/ipfw2.h"
|
||||||
|
|
||||||
@@ -779,6 +780,9 @@ void smf_qos_flow_binding(smf_sess_t *sess)
|
|||||||
if (ogs_list_count(&sess->qos_flow_to_modify_list)) {
|
if (ogs_list_count(&sess->qos_flow_to_modify_list)) {
|
||||||
ogs_assert(OGS_OK ==
|
ogs_assert(OGS_OK ==
|
||||||
smf_5gc_pfcp_send_qos_flow_list_modification_request(
|
smf_5gc_pfcp_send_qos_flow_list_modification_request(
|
||||||
sess, NULL, pfcp_flags, 0));
|
sess, NULL,
|
||||||
|
HOME_ROUTED_ROAMING_IN_HSMF(sess) ?
|
||||||
|
OGS_PFCP_MODIFY_HOME_ROUTED_ROAMING|pfcp_flags :
|
||||||
|
pfcp_flags, 0));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1865,11 +1865,13 @@ void smf_sess_remove(smf_sess_t *sess)
|
|||||||
if (sess->n1smbuf)
|
if (sess->n1smbuf)
|
||||||
ogs_pkbuf_free(sess->n1smbuf);
|
ogs_pkbuf_free(sess->n1smbuf);
|
||||||
|
|
||||||
OGS_NAS_CLEAR_DATA(&sess->h_smf_authorized_qos_rules);
|
|
||||||
OGS_NAS_CLEAR_DATA(&sess->h_smf_authorized_qos_flow_descriptions);
|
|
||||||
OGS_NAS_CLEAR_DATA(&sess->h_smf_extended_protocol_configuration_options);
|
OGS_NAS_CLEAR_DATA(&sess->h_smf_extended_protocol_configuration_options);
|
||||||
sess->h_smf_gsm_cause = 0;
|
sess->h_smf_gsm_cause = 0;
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
/* Free SBI object memory */
|
/* Free SBI object memory */
|
||||||
ogs_sbi_object_free(&sess->sbi);
|
ogs_sbi_object_free(&sess->sbi);
|
||||||
|
|
||||||
|
|||||||
@@ -82,6 +82,25 @@ typedef struct smf_nsmf_pdusession_param_s {
|
|||||||
uint8_t ue_timezone:1;,
|
uint8_t ue_timezone:1;,
|
||||||
uint8_t spare:6;)
|
uint8_t spare:6;)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#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_TFT_NEW) ? \
|
||||||
|
OGS_NAS_QOS_CODE_CREATE_NEW_QOS_RULE : \
|
||||||
|
(pfcp_flags & OGS_PFCP_MODIFY_TFT_ADD) ? \
|
||||||
|
OGS_NAS_QOS_CODE_MODIFY_EXISTING_QOS_RULE_AND_ADD_PACKET_FILTERS : \
|
||||||
|
(pfcp_flags & OGS_PFCP_MODIFY_TFT_REPLACE) ? \
|
||||||
|
OGS_NAS_QOS_CODE_MODIFY_EXISTING_QOS_RULE_AND_REPLACE_ALL_PACKET_FILTERS : \
|
||||||
|
(pfcp_flags & OGS_PFCP_MODIFY_TFT_DELETE) ? \
|
||||||
|
OGS_NAS_QOS_CODE_MODIFY_EXISTING_QOS_RULE_AND_DELETE_PACKET_FILTERS : 0
|
||||||
|
uint8_t qos_rule_code;
|
||||||
|
#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_QOS_MODIFY) ? \
|
||||||
|
OGS_NAS_MODIFY_NEW_QOS_FLOW_DESCRIPTION : 0
|
||||||
|
uint8_t qos_flow_description_code;
|
||||||
} smf_nsmf_pdusession_param_t;
|
} smf_nsmf_pdusession_param_t;
|
||||||
|
|
||||||
/* HR flag bit */
|
/* HR flag bit */
|
||||||
@@ -469,12 +488,36 @@ typedef struct smf_sess_s {
|
|||||||
char *h_smf_id;
|
char *h_smf_id;
|
||||||
|
|
||||||
/* Saved from H-SMF */
|
/* Saved from H-SMF */
|
||||||
ogs_nas_qos_rules_t h_smf_authorized_qos_rules;
|
|
||||||
ogs_nas_qos_flow_descriptions_t h_smf_authorized_qos_flow_descriptions;
|
|
||||||
ogs_nas_extended_protocol_configuration_options_t
|
ogs_nas_extended_protocol_configuration_options_t
|
||||||
h_smf_extended_protocol_configuration_options;
|
h_smf_extended_protocol_configuration_options;
|
||||||
ogs_nas_5gsm_cause_t h_smf_gsm_cause;
|
ogs_nas_5gsm_cause_t h_smf_gsm_cause;
|
||||||
|
|
||||||
|
/* Saved from H-SMF */
|
||||||
|
#define CLEAR_QOS_FLOWS_SETUP_LIST(__lIST) \
|
||||||
|
do { \
|
||||||
|
OpenAPI_lnode_t *node = NULL; \
|
||||||
|
OpenAPI_list_for_each((__lIST), node) { \
|
||||||
|
OpenAPI_qos_flow_setup_item_t *qosFlowSetupItem = node->data; \
|
||||||
|
if (qosFlowSetupItem) \
|
||||||
|
OpenAPI_qos_flow_setup_item_free(qosFlowSetupItem); \
|
||||||
|
} \
|
||||||
|
OpenAPI_list_free((__lIST)); \
|
||||||
|
} while(0)
|
||||||
|
OpenAPI_list_t *h_smf_qos_flows_setup_list;
|
||||||
|
#define CLEAR_QOS_FLOWS_ADD_MOD_REQUEST_LIST(__lIST) \
|
||||||
|
do { \
|
||||||
|
OpenAPI_lnode_t *node = NULL; \
|
||||||
|
OpenAPI_list_for_each((__lIST), node) { \
|
||||||
|
OpenAPI_qos_flow_add_modify_request_item_t \
|
||||||
|
*qosFlowAddModifyRequestItem = node->data; \
|
||||||
|
if (qosFlowAddModifyRequestItem) \
|
||||||
|
OpenAPI_qos_flow_add_modify_request_item_free( \
|
||||||
|
qosFlowAddModifyRequestItem); \
|
||||||
|
} \
|
||||||
|
OpenAPI_list_free((__lIST)); \
|
||||||
|
} while(0)
|
||||||
|
OpenAPI_list_t *h_smf_qos_flows_add_mod_request_list;
|
||||||
|
|
||||||
#define HOME_ROUTED_ROAMING_IN_HSMF(__sESS) \
|
#define HOME_ROUTED_ROAMING_IN_HSMF(__sESS) \
|
||||||
((__sESS) && (__sESS)->vsmf_pdu_session_uri)
|
((__sESS) && (__sESS)->vsmf_pdu_session_uri)
|
||||||
char *vsmf_pdu_session_uri;
|
char *vsmf_pdu_session_uri;
|
||||||
@@ -637,6 +680,7 @@ typedef struct smf_sess_s {
|
|||||||
bool n1_released;
|
bool n1_released;
|
||||||
bool n2_released;
|
bool n2_released;
|
||||||
ogs_pool_id_t amf_update_request_stream_id;
|
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;
|
ogs_pool_id_t n1_n2_released_stream_id;
|
||||||
|
|
||||||
smf_nsmf_pdusession_param_t nsmf_param;
|
smf_nsmf_pdusession_param_t nsmf_param;
|
||||||
|
|||||||
@@ -51,12 +51,18 @@ ogs_pkbuf_t *gsm_build_pdu_session_establishment_accept(smf_sess_t *sess)
|
|||||||
uint8_t *epco_buf = NULL;
|
uint8_t *epco_buf = NULL;
|
||||||
int16_t epco_len;
|
int16_t epco_len;
|
||||||
|
|
||||||
|
OpenAPI_list_t *qosFlowsSetupList = NULL;
|
||||||
|
OpenAPI_qos_flow_setup_item_t *qosFlowSetupItem = NULL;
|
||||||
|
OpenAPI_lnode_t *node = NULL;
|
||||||
|
int len;
|
||||||
|
|
||||||
selected_pdu_session_type = &pdu_session_establishment_accept->
|
selected_pdu_session_type = &pdu_session_establishment_accept->
|
||||||
selected_pdu_session_type;
|
selected_pdu_session_type;
|
||||||
ogs_assert(selected_pdu_session_type);
|
ogs_assert(selected_pdu_session_type);
|
||||||
authorized_qos_rules = &pdu_session_establishment_accept->
|
authorized_qos_rules = &pdu_session_establishment_accept->
|
||||||
authorized_qos_rules;
|
authorized_qos_rules;
|
||||||
ogs_assert(authorized_qos_rules);
|
ogs_assert(authorized_qos_rules);
|
||||||
|
|
||||||
session_ambr = &pdu_session_establishment_accept->session_ambr;
|
session_ambr = &pdu_session_establishment_accept->session_ambr;
|
||||||
ogs_assert(session_ambr);
|
ogs_assert(session_ambr);
|
||||||
pdu_address = &pdu_session_establishment_accept->pdu_address;
|
pdu_address = &pdu_session_establishment_accept->pdu_address;
|
||||||
@@ -91,16 +97,29 @@ ogs_pkbuf_t *gsm_build_pdu_session_establishment_accept(smf_sess_t *sess)
|
|||||||
selected_pdu_session_type->value = sess->session.session_type;
|
selected_pdu_session_type->value = sess->session.session_type;
|
||||||
|
|
||||||
if (HOME_ROUTED_ROAMING_IN_VSMF(sess)) {
|
if (HOME_ROUTED_ROAMING_IN_VSMF(sess)) {
|
||||||
ogs_assert(sess->h_smf_authorized_qos_rules.buffer);
|
qosFlowsSetupList = sess->h_smf_qos_flows_setup_list;
|
||||||
ogs_assert(sess->h_smf_authorized_qos_rules.length);
|
ogs_assert(qosFlowsSetupList);
|
||||||
OGS_NAS_STORE_DATA(
|
|
||||||
authorized_qos_rules, &sess->h_smf_authorized_qos_rules);
|
node = qosFlowsSetupList->first;
|
||||||
|
ogs_assert(node);
|
||||||
|
qosFlowSetupItem = node->data;
|
||||||
|
ogs_assert(qosFlowSetupItem);
|
||||||
|
|
||||||
|
len = ogs_base64_decode_len(qosFlowSetupItem->qos_rules);
|
||||||
|
ogs_assert(len);
|
||||||
|
authorized_qos_rules->buffer = ogs_calloc(1, len);
|
||||||
|
ogs_assert(authorized_qos_rules->buffer);
|
||||||
|
authorized_qos_rules->length =
|
||||||
|
ogs_base64_decode_binary(
|
||||||
|
authorized_qos_rules->buffer, qosFlowSetupItem->qos_rules);
|
||||||
|
ogs_assert(authorized_qos_rules->length);
|
||||||
|
|
||||||
} else if (HOME_ROUTED_ROAMING_IN_HSMF(sess)) {
|
} else if (HOME_ROUTED_ROAMING_IN_HSMF(sess)) {
|
||||||
ogs_fatal("This should not be invoked from H-SMF during HR-Roaming");
|
ogs_fatal("This should not be invoked from H-SMF during HR-Roaming");
|
||||||
ogs_assert_if_reached();
|
ogs_assert_if_reached();
|
||||||
} else {
|
} else {
|
||||||
memset(qos_rule, 0, sizeof(qos_rule));
|
memset(qos_rule, 0, sizeof(qos_rule));
|
||||||
encode_default_qos_rule(&qos_rule[0], qos_flow);
|
gsm_encode_default_qos_rule(&qos_rule[0], qos_flow);
|
||||||
|
|
||||||
rv = ogs_nas_build_qos_rules(authorized_qos_rules, qos_rule, 1);
|
rv = ogs_nas_build_qos_rules(authorized_qos_rules, qos_rule, 1);
|
||||||
if (rv != OGS_OK) {
|
if (rv != OGS_OK) {
|
||||||
@@ -175,20 +194,29 @@ ogs_pkbuf_t *gsm_build_pdu_session_establishment_accept(smf_sess_t *sess)
|
|||||||
|
|
||||||
/* QoS flow descriptions */
|
/* QoS flow descriptions */
|
||||||
if (HOME_ROUTED_ROAMING_IN_VSMF(sess)) {
|
if (HOME_ROUTED_ROAMING_IN_VSMF(sess)) {
|
||||||
if (sess->h_smf_authorized_qos_flow_descriptions.buffer &&
|
ogs_assert(qosFlowSetupItem);
|
||||||
sess->h_smf_authorized_qos_flow_descriptions.length) {
|
|
||||||
|
if (qosFlowSetupItem->qos_flow_description) {
|
||||||
|
len = ogs_base64_decode_len(qosFlowSetupItem->qos_flow_description);
|
||||||
|
ogs_assert(len);
|
||||||
|
authorized_qos_flow_descriptions->buffer = ogs_calloc(1, len);
|
||||||
|
ogs_assert(authorized_qos_flow_descriptions->buffer);
|
||||||
|
authorized_qos_flow_descriptions->length =
|
||||||
|
ogs_base64_decode_binary(
|
||||||
|
authorized_qos_flow_descriptions->buffer,
|
||||||
|
qosFlowSetupItem->qos_flow_description);
|
||||||
|
ogs_assert(authorized_qos_flow_descriptions->length);
|
||||||
|
|
||||||
pdu_session_establishment_accept->presencemask |=
|
pdu_session_establishment_accept->presencemask |=
|
||||||
OGS_NAS_5GS_PDU_SESSION_ESTABLISHMENT_ACCEPT_AUTHORIZED_QOS_FLOW_DESCRIPTIONS_PRESENT;
|
OGS_NAS_5GS_PDU_SESSION_ESTABLISHMENT_ACCEPT_AUTHORIZED_QOS_FLOW_DESCRIPTIONS_PRESENT;
|
||||||
OGS_NAS_STORE_DATA(
|
|
||||||
authorized_qos_flow_descriptions,
|
|
||||||
&sess->h_smf_authorized_qos_flow_descriptions);
|
|
||||||
}
|
}
|
||||||
} else if (HOME_ROUTED_ROAMING_IN_HSMF(sess)) {
|
} else if (HOME_ROUTED_ROAMING_IN_HSMF(sess)) {
|
||||||
ogs_fatal("This should not be invoked from H-SMF during HR-Roaming");
|
ogs_fatal("This should not be invoked from H-SMF during HR-Roaming");
|
||||||
ogs_assert_if_reached();
|
ogs_assert_if_reached();
|
||||||
} else {
|
} else {
|
||||||
memset(&qos_flow_description, 0, sizeof(qos_flow_description));
|
memset(&qos_flow_description, 0, sizeof(qos_flow_description));
|
||||||
encode_default_qos_flow_description(&qos_flow_description[0], qos_flow);
|
gsm_encode_default_qos_flow_description(
|
||||||
|
&qos_flow_description[0], qos_flow);
|
||||||
|
|
||||||
pdu_session_establishment_accept->presencemask |=
|
pdu_session_establishment_accept->presencemask |=
|
||||||
OGS_NAS_5GS_PDU_SESSION_ESTABLISHMENT_ACCEPT_AUTHORIZED_QOS_FLOW_DESCRIPTIONS_PRESENT;
|
OGS_NAS_5GS_PDU_SESSION_ESTABLISHMENT_ACCEPT_AUTHORIZED_QOS_FLOW_DESCRIPTIONS_PRESENT;
|
||||||
@@ -250,8 +278,6 @@ cleanup:
|
|||||||
if (extended_protocol_configuration_options->buffer)
|
if (extended_protocol_configuration_options->buffer)
|
||||||
ogs_free(extended_protocol_configuration_options->buffer);
|
ogs_free(extended_protocol_configuration_options->buffer);
|
||||||
|
|
||||||
OGS_NAS_CLEAR_DATA(&sess->h_smf_authorized_qos_rules);
|
|
||||||
OGS_NAS_CLEAR_DATA(&sess->h_smf_authorized_qos_flow_descriptions);
|
|
||||||
OGS_NAS_CLEAR_DATA(&sess->h_smf_extended_protocol_configuration_options);
|
OGS_NAS_CLEAR_DATA(&sess->h_smf_extended_protocol_configuration_options);
|
||||||
|
|
||||||
return pkbuf;
|
return pkbuf;
|
||||||
@@ -286,8 +312,7 @@ ogs_pkbuf_t *gsm_build_pdu_session_modification_command(
|
|||||||
{
|
{
|
||||||
ogs_pkbuf_t *pkbuf = NULL;
|
ogs_pkbuf_t *pkbuf = NULL;
|
||||||
smf_bearer_t *qos_flow = NULL;
|
smf_bearer_t *qos_flow = NULL;
|
||||||
ogs_pfcp_pdr_t *dl_pdr = NULL;
|
int rv, i;
|
||||||
int num_of_param, rv, i;
|
|
||||||
|
|
||||||
ogs_nas_5gs_message_t message;
|
ogs_nas_5gs_message_t message;
|
||||||
ogs_nas_5gs_pdu_session_modification_command_t
|
ogs_nas_5gs_pdu_session_modification_command_t
|
||||||
@@ -301,6 +326,11 @@ ogs_pkbuf_t *gsm_build_pdu_session_modification_command(
|
|||||||
ogs_nas_qos_flow_description_t
|
ogs_nas_qos_flow_description_t
|
||||||
qos_flow_description[OGS_NAS_MAX_NUM_OF_QOS_FLOW_DESCRIPTION];
|
qos_flow_description[OGS_NAS_MAX_NUM_OF_QOS_FLOW_DESCRIPTION];
|
||||||
|
|
||||||
|
OpenAPI_qos_flow_add_modify_request_item_t *qosFlowAddModifyRequestItem =
|
||||||
|
NULL;
|
||||||
|
OpenAPI_lnode_t *node = NULL;
|
||||||
|
int num, len;
|
||||||
|
|
||||||
authorized_qos_rules = &pdu_session_modification_command->
|
authorized_qos_rules = &pdu_session_modification_command->
|
||||||
authorized_qos_rules;
|
authorized_qos_rules;
|
||||||
ogs_assert(authorized_qos_rules);
|
ogs_assert(authorized_qos_rules);
|
||||||
@@ -318,7 +348,47 @@ ogs_pkbuf_t *gsm_build_pdu_session_modification_command(
|
|||||||
message.gsm.h.message_type = OGS_NAS_5GS_PDU_SESSION_MODIFICATION_COMMAND;
|
message.gsm.h.message_type = OGS_NAS_5GS_PDU_SESSION_MODIFICATION_COMMAND;
|
||||||
|
|
||||||
/* QoS rule */
|
/* QoS rule */
|
||||||
if (qos_rule_code) {
|
if (HOME_ROUTED_ROAMING_IN_VSMF(sess)) {
|
||||||
|
num = 0;
|
||||||
|
OpenAPI_list_for_each(
|
||||||
|
sess->h_smf_qos_flows_add_mod_request_list, node) {
|
||||||
|
qosFlowAddModifyRequestItem = node->data;
|
||||||
|
if (qosFlowAddModifyRequestItem) {
|
||||||
|
ogs_nas_qos_rules_t qos_rules;
|
||||||
|
|
||||||
|
len = ogs_base64_decode_len(
|
||||||
|
qosFlowAddModifyRequestItem->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);
|
||||||
|
ogs_assert(qos_rules.length);
|
||||||
|
|
||||||
|
ogs_assert(1 ==
|
||||||
|
ogs_nas_parse_qos_rules(
|
||||||
|
&qos_rule[num], &qos_rules));
|
||||||
|
|
||||||
|
ogs_free(qos_rules.buffer);
|
||||||
|
|
||||||
|
num++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (num) {
|
||||||
|
ogs_assert(OGS_OK ==
|
||||||
|
ogs_nas_build_qos_rules(
|
||||||
|
authorized_qos_rules, qos_rule, num));
|
||||||
|
|
||||||
|
pdu_session_modification_command->presencemask |=
|
||||||
|
OGS_NAS_5GS_PDU_SESSION_MODIFICATION_COMMAND_AUTHORIZED_QOS_RULES_PRESENT;
|
||||||
|
}
|
||||||
|
} else if (HOME_ROUTED_ROAMING_IN_HSMF(sess)) {
|
||||||
|
ogs_fatal("This should not be invoked from H-SMF during HR-Roaming");
|
||||||
|
ogs_assert_if_reached();
|
||||||
|
} else if (qos_rule_code) {
|
||||||
|
|
||||||
i = 0;
|
i = 0;
|
||||||
memset(qos_rule, 0, sizeof(qos_rule));
|
memset(qos_rule, 0, sizeof(qos_rule));
|
||||||
@@ -326,28 +396,7 @@ ogs_pkbuf_t *gsm_build_pdu_session_modification_command(
|
|||||||
ogs_list_for_each_entry(
|
ogs_list_for_each_entry(
|
||||||
&sess->qos_flow_to_modify_list, qos_flow, to_modify_node) {
|
&sess->qos_flow_to_modify_list, qos_flow, to_modify_node) {
|
||||||
ogs_assert(i < OGS_MAX_NUM_OF_BEARER);
|
ogs_assert(i < OGS_MAX_NUM_OF_BEARER);
|
||||||
|
gsm_encode_qos_rule(&qos_rule[i], qos_flow, qos_rule_code);
|
||||||
dl_pdr = qos_flow->dl_pdr;
|
|
||||||
ogs_assert(dl_pdr);
|
|
||||||
|
|
||||||
qos_rule[i].identifier = qos_flow->qfi; /* Use QFI in Open5GS */
|
|
||||||
qos_rule[i].code = qos_rule_code;
|
|
||||||
|
|
||||||
if (qos_rule_code != OGS_NAS_QOS_CODE_DELETE_EXISTING_QOS_RULE &&
|
|
||||||
qos_rule_code != OGS_NAS_QOS_CODE_MODIFY_EXISTING_QOS_RULE_WITHOUT_MODIFYING_PACKET_FILTERS)
|
|
||||||
encode_qos_rule_packet_filter(&qos_rule[i], qos_flow);
|
|
||||||
|
|
||||||
if (qos_rule_code != OGS_NAS_QOS_CODE_DELETE_EXISTING_QOS_RULE &&
|
|
||||||
qos_rule_code != OGS_NAS_QOS_CODE_MODIFY_EXISTING_QOS_RULE_AND_DELETE_PACKET_FILTERS &&
|
|
||||||
qos_rule_code != OGS_NAS_QOS_CODE_MODIFY_EXISTING_QOS_RULE_WITHOUT_MODIFYING_PACKET_FILTERS) {
|
|
||||||
ogs_assert(dl_pdr->precedence > 0 && dl_pdr->precedence < 255);
|
|
||||||
/* Use PCC Rule Precedence */
|
|
||||||
qos_rule[i].precedence = dl_pdr->precedence;
|
|
||||||
|
|
||||||
qos_rule[i].flow.segregation = 0;
|
|
||||||
qos_rule[i].flow.identifier = qos_flow->qfi;
|
|
||||||
}
|
|
||||||
|
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -366,7 +415,48 @@ ogs_pkbuf_t *gsm_build_pdu_session_modification_command(
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* QoS flow descriptions */
|
/* QoS flow descriptions */
|
||||||
if (qos_flow_description_code) {
|
if (HOME_ROUTED_ROAMING_IN_VSMF(sess)) {
|
||||||
|
num = 0;
|
||||||
|
OpenAPI_list_for_each(
|
||||||
|
sess->h_smf_qos_flows_add_mod_request_list, node) {
|
||||||
|
qosFlowAddModifyRequestItem = node->data;
|
||||||
|
if (qosFlowAddModifyRequestItem) {
|
||||||
|
ogs_nas_qos_flow_descriptions_t qos_flow_descriptions;
|
||||||
|
|
||||||
|
len = ogs_base64_decode_len(
|
||||||
|
qosFlowAddModifyRequestItem->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,
|
||||||
|
qosFlowAddModifyRequestItem->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);
|
||||||
|
|
||||||
|
num++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (num) {
|
||||||
|
ogs_assert(OGS_OK ==
|
||||||
|
ogs_nas_build_qos_flow_descriptions(
|
||||||
|
authorized_qos_flow_descriptions,
|
||||||
|
qos_flow_description, num));
|
||||||
|
|
||||||
|
pdu_session_modification_command->presencemask |=
|
||||||
|
OGS_NAS_5GS_PDU_SESSION_MODIFICATION_COMMAND_AUTHORIZED_QOS_FLOW_DESCRIPTIONS_PRESENT;
|
||||||
|
}
|
||||||
|
} else if (HOME_ROUTED_ROAMING_IN_HSMF(sess)) {
|
||||||
|
ogs_fatal("This should not be invoked from H-SMF during HR-Roaming");
|
||||||
|
ogs_assert_if_reached();
|
||||||
|
} else if (qos_flow_description_code) {
|
||||||
|
|
||||||
i = 0;
|
i = 0;
|
||||||
memset(&qos_flow_description, 0, sizeof(qos_flow_description));
|
memset(&qos_flow_description, 0, sizeof(qos_flow_description));
|
||||||
@@ -375,67 +465,8 @@ ogs_pkbuf_t *gsm_build_pdu_session_modification_command(
|
|||||||
&sess->qos_flow_to_modify_list, qos_flow, to_modify_node) {
|
&sess->qos_flow_to_modify_list, qos_flow, to_modify_node) {
|
||||||
ogs_assert(i < OGS_MAX_NUM_OF_BEARER);
|
ogs_assert(i < OGS_MAX_NUM_OF_BEARER);
|
||||||
|
|
||||||
qos_flow_description[i].identifier = qos_flow->qfi;
|
gsm_encode_qos_flow_description(
|
||||||
qos_flow_description[i].code = qos_flow_description_code;
|
&qos_flow_description[i], qos_flow, qos_flow_description_code);
|
||||||
|
|
||||||
num_of_param = 0;
|
|
||||||
|
|
||||||
if (qos_flow_description_code !=
|
|
||||||
OGS_NAS_DELETE_NEW_QOS_FLOW_DESCRIPTION) {
|
|
||||||
qos_flow_description[i].E_bit = 1;
|
|
||||||
|
|
||||||
qos_flow_description[i].param[num_of_param].identifier =
|
|
||||||
OGS_NAX_QOS_FLOW_PARAMETER_ID_5QI;
|
|
||||||
qos_flow_description[i].param[num_of_param].len =
|
|
||||||
sizeof(qos_flow_description[i].param[num_of_param].
|
|
||||||
qos_index);
|
|
||||||
qos_flow_description[i].param[num_of_param].qos_index =
|
|
||||||
qos_flow->qos.index;
|
|
||||||
num_of_param++;
|
|
||||||
|
|
||||||
if (qos_flow->qos.gbr.uplink) {
|
|
||||||
qos_flow_description[i].param[num_of_param].identifier =
|
|
||||||
OGS_NAX_QOS_FLOW_PARAMETER_ID_GFBR_UPLINK;
|
|
||||||
qos_flow_description[i].param[num_of_param].len =
|
|
||||||
sizeof(qos_flow_description[i].param[num_of_param].br);
|
|
||||||
ogs_nas_bitrate_from_uint64(
|
|
||||||
&qos_flow_description[i].param[num_of_param].br,
|
|
||||||
qos_flow->qos.gbr.uplink);
|
|
||||||
num_of_param++;
|
|
||||||
}
|
|
||||||
if (qos_flow->qos.gbr.downlink) {
|
|
||||||
qos_flow_description[i].param[num_of_param].identifier =
|
|
||||||
OGS_NAX_QOS_FLOW_PARAMETER_ID_GFBR_DOWNLINK;
|
|
||||||
qos_flow_description[i].param[num_of_param].len =
|
|
||||||
sizeof(qos_flow_description[i].param[num_of_param].br);
|
|
||||||
ogs_nas_bitrate_from_uint64(
|
|
||||||
&qos_flow_description[i].param[num_of_param].br,
|
|
||||||
qos_flow->qos.gbr.downlink);
|
|
||||||
num_of_param++;
|
|
||||||
}
|
|
||||||
if (qos_flow->qos.mbr.uplink) {
|
|
||||||
qos_flow_description[i].param[num_of_param].identifier =
|
|
||||||
OGS_NAX_QOS_FLOW_PARAMETER_ID_MFBR_UPLINK;
|
|
||||||
qos_flow_description[i].param[num_of_param].len =
|
|
||||||
sizeof(qos_flow_description[i].param[num_of_param].br);
|
|
||||||
ogs_nas_bitrate_from_uint64(
|
|
||||||
&qos_flow_description[i].param[num_of_param].br,
|
|
||||||
qos_flow->qos.mbr.uplink);
|
|
||||||
num_of_param++;
|
|
||||||
}
|
|
||||||
if (qos_flow->qos.mbr.downlink) {
|
|
||||||
qos_flow_description[i].param[num_of_param].identifier =
|
|
||||||
OGS_NAX_QOS_FLOW_PARAMETER_ID_MFBR_DOWNLINK;
|
|
||||||
qos_flow_description[i].param[num_of_param].len =
|
|
||||||
sizeof(qos_flow_description[i].param[num_of_param].br);
|
|
||||||
ogs_nas_bitrate_from_uint64(
|
|
||||||
&qos_flow_description[i].param[num_of_param].br,
|
|
||||||
qos_flow->qos.mbr.downlink);
|
|
||||||
num_of_param++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
qos_flow_description[i].num_of_parameter = num_of_param;
|
|
||||||
|
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
@@ -458,14 +489,11 @@ ogs_pkbuf_t *gsm_build_pdu_session_modification_command(
|
|||||||
pkbuf = ogs_nas_5gs_plain_encode(&message);
|
pkbuf = ogs_nas_5gs_plain_encode(&message);
|
||||||
ogs_assert(pkbuf);
|
ogs_assert(pkbuf);
|
||||||
|
|
||||||
if (pdu_session_modification_command->presencemask &
|
cleanup:
|
||||||
OGS_NAS_5GS_PDU_SESSION_MODIFICATION_COMMAND_AUTHORIZED_QOS_RULES_PRESENT) {
|
if (authorized_qos_rules->buffer)
|
||||||
ogs_free(authorized_qos_rules->buffer);
|
ogs_free(authorized_qos_rules->buffer);
|
||||||
}
|
if (authorized_qos_flow_descriptions->buffer)
|
||||||
if (pdu_session_modification_command->presencemask &
|
|
||||||
OGS_NAS_5GS_PDU_SESSION_MODIFICATION_COMMAND_AUTHORIZED_QOS_FLOW_DESCRIPTIONS_PRESENT) {
|
|
||||||
ogs_free(authorized_qos_flow_descriptions->buffer);
|
ogs_free(authorized_qos_flow_descriptions->buffer);
|
||||||
}
|
|
||||||
|
|
||||||
return pkbuf;
|
return pkbuf;
|
||||||
}
|
}
|
||||||
@@ -537,7 +565,7 @@ ogs_pkbuf_t *gsm_build_pdu_session_release_reject(
|
|||||||
return ogs_nas_5gs_plain_encode(&message);
|
return ogs_nas_5gs_plain_encode(&message);
|
||||||
}
|
}
|
||||||
|
|
||||||
void encode_default_qos_rule(
|
void gsm_encode_default_qos_rule(
|
||||||
ogs_nas_qos_rule_t *qos_rule, smf_bearer_t *qos_flow)
|
ogs_nas_qos_rule_t *qos_rule, smf_bearer_t *qos_flow)
|
||||||
{
|
{
|
||||||
ogs_assert(qos_rule);
|
ogs_assert(qos_rule);
|
||||||
@@ -584,7 +612,7 @@ void encode_default_qos_rule(
|
|||||||
qos_rule->flow.identifier = qos_flow->qfi;
|
qos_rule->flow.identifier = qos_flow->qfi;
|
||||||
}
|
}
|
||||||
|
|
||||||
void encode_default_qos_flow_description(
|
void gsm_encode_default_qos_flow_description(
|
||||||
ogs_nas_qos_flow_description_t *qos_flow_description,
|
ogs_nas_qos_flow_description_t *qos_flow_description,
|
||||||
smf_bearer_t *qos_flow)
|
smf_bearer_t *qos_flow)
|
||||||
{
|
{
|
||||||
@@ -609,7 +637,7 @@ void encode_default_qos_flow_description(
|
|||||||
qos_flow_description->num_of_parameter = num_of_param;
|
qos_flow_description->num_of_parameter = num_of_param;
|
||||||
}
|
}
|
||||||
|
|
||||||
void encode_qos_rule_packet_filter(
|
void gsm_encode_qos_rule_packet_filter(
|
||||||
ogs_nas_qos_rule_t *qos_rule, smf_bearer_t *qos_flow)
|
ogs_nas_qos_rule_t *qos_rule, smf_bearer_t *qos_flow)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
@@ -643,3 +671,100 @@ void encode_qos_rule_packet_filter(
|
|||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void gsm_encode_qos_rule(
|
||||||
|
ogs_nas_qos_rule_t *qos_rule,
|
||||||
|
smf_bearer_t *qos_flow, uint8_t qos_rule_code)
|
||||||
|
{
|
||||||
|
ogs_pfcp_pdr_t *dl_pdr = NULL;
|
||||||
|
|
||||||
|
ogs_assert(qos_rule);
|
||||||
|
ogs_assert(qos_flow);
|
||||||
|
ogs_assert(qos_rule_code);
|
||||||
|
|
||||||
|
dl_pdr = qos_flow->dl_pdr;
|
||||||
|
ogs_assert(dl_pdr);
|
||||||
|
|
||||||
|
qos_rule->identifier = qos_flow->qfi;
|
||||||
|
qos_rule->code = qos_rule_code;
|
||||||
|
|
||||||
|
if (qos_rule_code != OGS_NAS_QOS_CODE_DELETE_EXISTING_QOS_RULE &&
|
||||||
|
qos_rule_code != OGS_NAS_QOS_CODE_MODIFY_EXISTING_QOS_RULE_WITHOUT_MODIFYING_PACKET_FILTERS) {
|
||||||
|
gsm_encode_qos_rule_packet_filter(qos_rule, qos_flow);
|
||||||
|
}
|
||||||
|
if (qos_rule_code != OGS_NAS_QOS_CODE_DELETE_EXISTING_QOS_RULE &&
|
||||||
|
qos_rule_code != OGS_NAS_QOS_CODE_MODIFY_EXISTING_QOS_RULE_AND_DELETE_PACKET_FILTERS &&
|
||||||
|
qos_rule_code != OGS_NAS_QOS_CODE_MODIFY_EXISTING_QOS_RULE_WITHOUT_MODIFYING_PACKET_FILTERS)
|
||||||
|
{
|
||||||
|
ogs_assert(dl_pdr->precedence > 0 && dl_pdr->precedence < 255);
|
||||||
|
qos_rule->precedence = dl_pdr->precedence;
|
||||||
|
qos_rule->flow.segregation = 0;
|
||||||
|
qos_rule->flow.identifier = qos_flow->qfi;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void gsm_encode_qos_flow_description(
|
||||||
|
ogs_nas_qos_flow_description_t *qos_flow_description,
|
||||||
|
smf_bearer_t *qos_flow, uint8_t qos_flow_description_code)
|
||||||
|
{
|
||||||
|
int num_of_param = 0;
|
||||||
|
|
||||||
|
ogs_assert(qos_flow_description);
|
||||||
|
ogs_assert(qos_flow);
|
||||||
|
ogs_assert(qos_flow_description_code);
|
||||||
|
|
||||||
|
qos_flow_description->identifier = qos_flow->qfi;
|
||||||
|
qos_flow_description->code = qos_flow_description_code;
|
||||||
|
|
||||||
|
if (qos_flow_description_code != OGS_NAS_DELETE_NEW_QOS_FLOW_DESCRIPTION) {
|
||||||
|
qos_flow_description->E_bit = 1;
|
||||||
|
qos_flow_description->param[num_of_param].identifier =
|
||||||
|
OGS_NAX_QOS_FLOW_PARAMETER_ID_5QI;
|
||||||
|
qos_flow_description->param[num_of_param].len =
|
||||||
|
sizeof(qos_flow_description->param[num_of_param].qos_index);
|
||||||
|
qos_flow_description->param[num_of_param++].qos_index =
|
||||||
|
qos_flow->qos.index;
|
||||||
|
|
||||||
|
if (qos_flow->qos.gbr.uplink) {
|
||||||
|
qos_flow_description->param[num_of_param].identifier =
|
||||||
|
OGS_NAX_QOS_FLOW_PARAMETER_ID_GFBR_UPLINK;
|
||||||
|
qos_flow_description->param[num_of_param].len =
|
||||||
|
sizeof(qos_flow_description->param[num_of_param].br);
|
||||||
|
ogs_nas_bitrate_from_uint64(
|
||||||
|
&qos_flow_description->param[num_of_param].br,
|
||||||
|
qos_flow->qos.gbr.uplink);
|
||||||
|
num_of_param++;
|
||||||
|
}
|
||||||
|
if (qos_flow->qos.gbr.downlink) {
|
||||||
|
qos_flow_description->param[num_of_param].identifier =
|
||||||
|
OGS_NAX_QOS_FLOW_PARAMETER_ID_GFBR_DOWNLINK;
|
||||||
|
qos_flow_description->param[num_of_param].len =
|
||||||
|
sizeof(qos_flow_description->param[num_of_param].br);
|
||||||
|
ogs_nas_bitrate_from_uint64(
|
||||||
|
&qos_flow_description->param[num_of_param].br,
|
||||||
|
qos_flow->qos.gbr.downlink);
|
||||||
|
num_of_param++;
|
||||||
|
}
|
||||||
|
if (qos_flow->qos.mbr.uplink) {
|
||||||
|
qos_flow_description->param[num_of_param].identifier =
|
||||||
|
OGS_NAX_QOS_FLOW_PARAMETER_ID_MFBR_UPLINK;
|
||||||
|
qos_flow_description->param[num_of_param].len =
|
||||||
|
sizeof(qos_flow_description->param[num_of_param].br);
|
||||||
|
ogs_nas_bitrate_from_uint64(
|
||||||
|
&qos_flow_description->param[num_of_param].br,
|
||||||
|
qos_flow->qos.mbr.uplink);
|
||||||
|
num_of_param++;
|
||||||
|
}
|
||||||
|
if (qos_flow->qos.mbr.downlink) {
|
||||||
|
qos_flow_description->param[num_of_param].identifier =
|
||||||
|
OGS_NAX_QOS_FLOW_PARAMETER_ID_MFBR_DOWNLINK;
|
||||||
|
qos_flow_description->param[num_of_param].len =
|
||||||
|
sizeof(qos_flow_description->param[num_of_param].br);
|
||||||
|
ogs_nas_bitrate_from_uint64(
|
||||||
|
&qos_flow_description->param[num_of_param].br,
|
||||||
|
qos_flow->qos.mbr.downlink);
|
||||||
|
num_of_param++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
qos_flow_description->num_of_parameter = num_of_param;
|
||||||
|
}
|
||||||
|
|||||||
@@ -43,14 +43,21 @@ ogs_pkbuf_t *gsm_build_pdu_session_release_reject(
|
|||||||
|
|
||||||
ogs_pkbuf_t *gsm_build_status(smf_sess_t *sess, ogs_nas_5gsm_cause_t cause);
|
ogs_pkbuf_t *gsm_build_status(smf_sess_t *sess, ogs_nas_5gsm_cause_t cause);
|
||||||
|
|
||||||
void encode_default_qos_rule(
|
void gsm_encode_default_qos_rule(
|
||||||
ogs_nas_qos_rule_t *qos_rule, smf_bearer_t *qos_flow);
|
ogs_nas_qos_rule_t *qos_rule, smf_bearer_t *qos_flow);
|
||||||
void encode_default_qos_flow_description(
|
void gsm_encode_default_qos_flow_description(
|
||||||
ogs_nas_qos_flow_description_t *qos_flow_description,
|
ogs_nas_qos_flow_description_t *qos_flow_description,
|
||||||
smf_bearer_t *qos_flow);
|
smf_bearer_t *qos_flow);
|
||||||
void encode_qos_rule_packet_filter(
|
void gsm_encode_qos_rule_packet_filter(
|
||||||
ogs_nas_qos_rule_t *qos_rule, smf_bearer_t *qos_flow);
|
ogs_nas_qos_rule_t *qos_rule, smf_bearer_t *qos_flow);
|
||||||
|
|
||||||
|
void gsm_encode_qos_rule(
|
||||||
|
ogs_nas_qos_rule_t *qos_rule, smf_bearer_t *qos_flow,
|
||||||
|
uint8_t qos_rule_code);
|
||||||
|
void gsm_encode_qos_flow_description(
|
||||||
|
ogs_nas_qos_flow_description_t *qos_flow_description,
|
||||||
|
smf_bearer_t *qos_flow, uint8_t qos_flow_description_code);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
121
src/smf/gsm-sm.c
121
src/smf/gsm-sm.c
@@ -874,6 +874,7 @@ void smf_gsm_state_operational(ogs_fsm_t *s, smf_event_t *e)
|
|||||||
char *strerror = NULL;
|
char *strerror = NULL;
|
||||||
smf_ue_t *smf_ue = NULL;
|
smf_ue_t *smf_ue = NULL;
|
||||||
smf_sess_t *sess = NULL;
|
smf_sess_t *sess = NULL;
|
||||||
|
smf_bearer_t *qos_flow = NULL;
|
||||||
ogs_pkbuf_t *pkbuf = NULL;
|
ogs_pkbuf_t *pkbuf = NULL;
|
||||||
|
|
||||||
ogs_pfcp_xact_t *pfcp_xact = NULL;
|
ogs_pfcp_xact_t *pfcp_xact = NULL;
|
||||||
@@ -1084,24 +1085,34 @@ void smf_gsm_state_operational(ogs_fsm_t *s, smf_event_t *e)
|
|||||||
CASE(OGS_SBI_RESOURCE_NAME_PDU_SESSIONS)
|
CASE(OGS_SBI_RESOURCE_NAME_PDU_SESSIONS)
|
||||||
SWITCH(sbi_message->h.resource.component[2])
|
SWITCH(sbi_message->h.resource.component[2])
|
||||||
CASE(OGS_SBI_RESOURCE_NAME_MODIFY)
|
CASE(OGS_SBI_RESOURCE_NAME_MODIFY)
|
||||||
rc = smf_nsmf_handle_hsmf_update_data(
|
rc = smf_nsmf_handle_update_data_in_hsmf(
|
||||||
sess, stream, sbi_message);
|
sess, stream, sbi_message);
|
||||||
if (rc == true) {
|
if (rc == true) {
|
||||||
ogs_assert(sess->nsmf_param.request_indication);
|
ogs_assert(sess->nsmf_param.request_indication);
|
||||||
|
|
||||||
if (sess->nsmf_param.request_indication ==
|
if (sess->nsmf_param.request_indication ==
|
||||||
OpenAPI_request_indication_UE_REQ_PDU_SES_REL) {
|
OpenAPI_request_indication_NW_REQ_PDU_SES_MOD) {
|
||||||
e->h.sbi.state =
|
ogs_fatal("TODO");
|
||||||
OGS_PFCP_DELETE_TRIGGER_UE_REQUESTED;
|
|
||||||
} else if (sess->nsmf_param.request_indication ==
|
ogs_assert(true ==
|
||||||
OpenAPI_request_indication_NW_REQ_PDU_SES_REL) {
|
ogs_sbi_send_http_status_no_content(
|
||||||
e->h.sbi.state =
|
stream));
|
||||||
OGS_PFCP_DELETE_TRIGGER_AMF_UPDATE_SM_CONTEXT;
|
|
||||||
} else {
|
} else {
|
||||||
ogs_fatal("Not implemented [requestIndication:%d]",
|
if (sess->nsmf_param.request_indication ==
|
||||||
sess->nsmf_param.request_indication);
|
OpenAPI_request_indication_UE_REQ_PDU_SES_REL) {
|
||||||
ogs_assert_if_reached();
|
e->h.sbi.state =
|
||||||
}
|
OGS_PFCP_DELETE_TRIGGER_UE_REQUESTED;
|
||||||
|
} else if (sess->nsmf_param.request_indication ==
|
||||||
|
OpenAPI_request_indication_NW_REQ_PDU_SES_REL) {
|
||||||
|
e->h.sbi.state =
|
||||||
|
OGS_PFCP_DELETE_TRIGGER_AMF_UPDATE_SM_CONTEXT;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
ogs_fatal("Not implemented "
|
||||||
|
"[requestIndication:%d]",
|
||||||
|
sess->nsmf_param.request_indication);
|
||||||
|
ogs_assert_if_reached();
|
||||||
|
}
|
||||||
/*
|
/*
|
||||||
* TS23.502 clause 4.3.4.3 UE or network requested PDU Session Release
|
* TS23.502 clause 4.3.4.3 UE or network requested PDU Session Release
|
||||||
* for Home-routed Roaming.
|
* for Home-routed Roaming.
|
||||||
@@ -1119,12 +1130,14 @@ void smf_gsm_state_operational(ogs_fsm_t *s, smf_event_t *e)
|
|||||||
* - the V-SMF invokes the Nsmf_PDUSession_Update Request towards H-SMF.
|
* - the V-SMF invokes the Nsmf_PDUSession_Update Request towards H-SMF.
|
||||||
* (OpenAPI_cause_REL_DUE_TO_DUPLICATE_SESSION_ID);
|
* (OpenAPI_cause_REL_DUE_TO_DUPLICATE_SESSION_ID);
|
||||||
*/
|
*/
|
||||||
ogs_assert(true ==
|
ogs_assert(true ==
|
||||||
ogs_sbi_send_http_status_no_content(stream));
|
ogs_sbi_send_http_status_no_content(
|
||||||
|
stream));
|
||||||
|
|
||||||
OGS_FSM_TRAN(s, smf_gsm_state_wait_pfcp_deletion);
|
OGS_FSM_TRAN(s, smf_gsm_state_wait_pfcp_deletion);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
ogs_error("smf_nsmf_handle_hsmf_update_data() "
|
ogs_error("smf_nsmf_handle_update_data_in_hsmf() "
|
||||||
"failed");
|
"failed");
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@@ -1150,14 +1163,27 @@ void smf_gsm_state_operational(ogs_fsm_t *s, smf_event_t *e)
|
|||||||
CASE(OGS_SBI_RESOURCE_NAME_VSMF_PDU_SESSIONS)
|
CASE(OGS_SBI_RESOURCE_NAME_VSMF_PDU_SESSIONS)
|
||||||
SWITCH(sbi_message->h.resource.component[2])
|
SWITCH(sbi_message->h.resource.component[2])
|
||||||
CASE(OGS_SBI_RESOURCE_NAME_MODIFY)
|
CASE(OGS_SBI_RESOURCE_NAME_MODIFY)
|
||||||
rc = smf_nsmf_handle_vsmf_update_data(
|
rc = smf_nsmf_handle_update_data_in_vsmf(
|
||||||
sess, stream, sbi_message);
|
sess, stream, sbi_message);
|
||||||
|
|
||||||
if (rc == true) {
|
if (rc == true) {
|
||||||
e->h.sbi.state = OGS_PFCP_DELETE_TRIGGER_UE_REQUESTED;
|
switch (sess->nsmf_param.request_indication) {
|
||||||
OGS_FSM_TRAN(s, smf_gsm_state_wait_pfcp_deletion);
|
case OpenAPI_request_indication_UE_REQ_PDU_SES_MOD:
|
||||||
|
case OpenAPI_request_indication_NW_REQ_PDU_SES_MOD:
|
||||||
|
break;
|
||||||
|
case OpenAPI_request_indication_UE_REQ_PDU_SES_REL:
|
||||||
|
case OpenAPI_request_indication_NW_REQ_PDU_SES_REL:
|
||||||
|
e->h.sbi.state =
|
||||||
|
OGS_PFCP_DELETE_TRIGGER_UE_REQUESTED;
|
||||||
|
OGS_FSM_TRAN(s, smf_gsm_state_wait_pfcp_deletion);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
ogs_error("Unknown request_indication:%d",
|
||||||
|
sess->nsmf_param.request_indication);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
ogs_error("smf_nsmf_handle_vsmf_update_data() failed");
|
ogs_error("smf_nsmf_handle_update_data_in_vsmf() "
|
||||||
|
"failed");
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
DEFAULT
|
DEFAULT
|
||||||
@@ -1202,6 +1228,10 @@ void smf_gsm_state_operational(ogs_fsm_t *s, smf_event_t *e)
|
|||||||
smf_ue = smf_ue_find_by_id(sess->smf_ue_id);
|
smf_ue = smf_ue_find_by_id(sess->smf_ue_id);
|
||||||
ogs_assert(smf_ue);
|
ogs_assert(smf_ue);
|
||||||
|
|
||||||
|
stream_id = OGS_POINTER_TO_UINT(e->h.sbi.data);
|
||||||
|
if (stream_id >= OGS_MIN_POOL_ID && stream_id <= OGS_MAX_POOL_ID)
|
||||||
|
stream = ogs_sbi_stream_find_by_id(stream_id);
|
||||||
|
|
||||||
SWITCH(sbi_message->h.service.name)
|
SWITCH(sbi_message->h.service.name)
|
||||||
CASE(OGS_SBI_SERVICE_NAME_NAMF_COMM)
|
CASE(OGS_SBI_SERVICE_NAME_NAMF_COMM)
|
||||||
SWITCH(sbi_message->h.resource.component[0])
|
SWITCH(sbi_message->h.resource.component[0])
|
||||||
@@ -1241,7 +1271,7 @@ void smf_gsm_state_operational(ogs_fsm_t *s, smf_event_t *e)
|
|||||||
&smf_gsm_state_wait_pfcp_deletion);
|
&smf_gsm_state_wait_pfcp_deletion);
|
||||||
break;
|
break;
|
||||||
DEFAULT
|
DEFAULT
|
||||||
if (smf_nsmf_handle_create_data_in_vsmf(
|
if (smf_nsmf_handle_created_data_in_vsmf(
|
||||||
sess, sbi_message) == false) {
|
sess, sbi_message) == false) {
|
||||||
ogs_error("[%s:%d] create_pdu_session "
|
ogs_error("[%s:%d] create_pdu_session "
|
||||||
"failed() [%d]",
|
"failed() [%d]",
|
||||||
@@ -1259,6 +1289,39 @@ void smf_gsm_state_operational(ogs_fsm_t *s, smf_event_t *e)
|
|||||||
END
|
END
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
CASE(OGS_SBI_RESOURCE_NAME_VSMF_PDU_SESSIONS)
|
||||||
|
SWITCH(sbi_message->h.resource.component[2])
|
||||||
|
CASE(OGS_SBI_RESOURCE_NAME_MODIFY)
|
||||||
|
ogs_list_for_each_entry(
|
||||||
|
&sess->qos_flow_to_modify_list,
|
||||||
|
qos_flow, to_modify_node) {
|
||||||
|
ogs_pfcp_far_t *dl_far = qos_flow->dl_far;
|
||||||
|
ogs_assert(dl_far);
|
||||||
|
|
||||||
|
dl_far->apply_action = OGS_PFCP_APPLY_ACTION_FORW;
|
||||||
|
ogs_assert(OGS_OK ==
|
||||||
|
ogs_pfcp_ip_to_outer_header_creation(
|
||||||
|
&sess->remote_dl_ip,
|
||||||
|
&dl_far->outer_header_creation,
|
||||||
|
&dl_far->outer_header_creation_len));
|
||||||
|
dl_far->outer_header_creation.teid =
|
||||||
|
sess->remote_dl_teid;
|
||||||
|
}
|
||||||
|
|
||||||
|
ogs_assert(OGS_OK ==
|
||||||
|
smf_5gc_pfcp_send_qos_flow_list_modification_request(
|
||||||
|
sess, NULL,
|
||||||
|
OGS_PFCP_MODIFY_HOME_ROUTED_ROAMING|
|
||||||
|
OGS_PFCP_MODIFY_DL_ONLY|
|
||||||
|
OGS_PFCP_MODIFY_ACTIVATE, 0));
|
||||||
|
break;
|
||||||
|
DEFAULT
|
||||||
|
ogs_error("Invalid resource name [%s]",
|
||||||
|
sbi_message->h.resource.component[0]);
|
||||||
|
ogs_assert_if_reached();
|
||||||
|
END
|
||||||
|
break;
|
||||||
|
|
||||||
DEFAULT
|
DEFAULT
|
||||||
ogs_error("Invalid resource name [%s]",
|
ogs_error("Invalid resource name [%s]",
|
||||||
sbi_message->h.resource.component[0]);
|
sbi_message->h.resource.component[0]);
|
||||||
@@ -1302,6 +1365,22 @@ void smf_gsm_state_operational(ogs_fsm_t *s, smf_event_t *e)
|
|||||||
|
|
||||||
case OGS_NAS_5GS_PDU_SESSION_MODIFICATION_COMPLETE:
|
case OGS_NAS_5GS_PDU_SESSION_MODIFICATION_COMPLETE:
|
||||||
ogs_assert(true == ogs_sbi_send_http_status_no_content(stream));
|
ogs_assert(true == ogs_sbi_send_http_status_no_content(stream));
|
||||||
|
if (HOME_ROUTED_ROAMING_IN_VSMF(sess)) {
|
||||||
|
ogs_sbi_stream_t *n1_n2_modified_stream = NULL;
|
||||||
|
if (sess->n1_n2_modified_stream_id >= OGS_MIN_POOL_ID &&
|
||||||
|
sess->n1_n2_modified_stream_id <= OGS_MAX_POOL_ID)
|
||||||
|
n1_n2_modified_stream =
|
||||||
|
ogs_sbi_stream_find_by_id(
|
||||||
|
sess->n1_n2_modified_stream_id);
|
||||||
|
|
||||||
|
if (n1_n2_modified_stream) {
|
||||||
|
ogs_assert(true ==
|
||||||
|
ogs_sbi_send_http_status_no_content(
|
||||||
|
n1_n2_modified_stream));
|
||||||
|
} else
|
||||||
|
ogs_error("No N1-N2 Modifed Stream [%d]",
|
||||||
|
sess->n1_n2_modified_stream_id);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case OGS_NAS_5GS_PDU_SESSION_RELEASE_REQUEST:
|
case OGS_NAS_5GS_PDU_SESSION_RELEASE_REQUEST:
|
||||||
|
|||||||
@@ -1609,6 +1609,23 @@ cleanup:
|
|||||||
return pkbuf;
|
return pkbuf;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ogs_pkbuf_t *gsmue_build_pdu_session_modification_command(smf_sess_t *sess)
|
||||||
|
{
|
||||||
|
ogs_pkbuf_t *pkbuf = NULL;
|
||||||
|
|
||||||
|
ogs_nas_5gs_message_t message;
|
||||||
|
|
||||||
|
ogs_assert(sess);
|
||||||
|
|
||||||
|
memset(&message, 0, sizeof(message));
|
||||||
|
message.gsm.h.message_type = OGS_NAS_5GS_PDU_SESSION_MODIFICATION_COMMAND;
|
||||||
|
|
||||||
|
pkbuf = gsmue_encode_n1_sm_info(&message);
|
||||||
|
ogs_assert(pkbuf);
|
||||||
|
|
||||||
|
return pkbuf;
|
||||||
|
}
|
||||||
|
|
||||||
ogs_pkbuf_t *gsmue_build_pdu_session_release_command(smf_sess_t *sess)
|
ogs_pkbuf_t *gsmue_build_pdu_session_release_command(smf_sess_t *sess)
|
||||||
{
|
{
|
||||||
ogs_pkbuf_t *pkbuf = NULL;
|
ogs_pkbuf_t *pkbuf = NULL;
|
||||||
|
|||||||
@@ -30,6 +30,7 @@ ogs_pkbuf_t *gsmue_encode_n1_sm_info(ogs_nas_5gs_message_t *message);
|
|||||||
int gsmue_decode_n1_sm_info(ogs_nas_5gs_message_t *message, ogs_pkbuf_t *pkbuf);
|
int gsmue_decode_n1_sm_info(ogs_nas_5gs_message_t *message, ogs_pkbuf_t *pkbuf);
|
||||||
|
|
||||||
ogs_pkbuf_t *gsmue_build_pdu_session_establishment_accept(smf_sess_t *sess);
|
ogs_pkbuf_t *gsmue_build_pdu_session_establishment_accept(smf_sess_t *sess);
|
||||||
|
ogs_pkbuf_t *gsmue_build_pdu_session_modification_command(smf_sess_t *sess);
|
||||||
ogs_pkbuf_t *gsmue_build_pdu_session_release_command(smf_sess_t *sess);
|
ogs_pkbuf_t *gsmue_build_pdu_session_release_command(smf_sess_t *sess);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
|
|||||||
@@ -257,7 +257,7 @@ void smf_5gc_n4_handle_session_modification_response(
|
|||||||
smf_sess_t *sess, ogs_pfcp_xact_t *xact,
|
smf_sess_t *sess, ogs_pfcp_xact_t *xact,
|
||||||
ogs_pfcp_session_modification_response_t *rsp)
|
ogs_pfcp_session_modification_response_t *rsp)
|
||||||
{
|
{
|
||||||
int status = 0;
|
int r, status = 0;
|
||||||
uint64_t flags = 0;
|
uint64_t flags = 0;
|
||||||
int trigger = 0;
|
int trigger = 0;
|
||||||
ogs_sbi_stream_t *stream = NULL;
|
ogs_sbi_stream_t *stream = NULL;
|
||||||
@@ -407,35 +407,17 @@ void smf_5gc_n4_handle_session_modification_response(
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (flags & OGS_PFCP_MODIFY_ACTIVATE) {
|
if (flags & OGS_PFCP_MODIFY_HOME_ROUTED_ROAMING) {
|
||||||
if (flags & OGS_PFCP_MODIFY_XN_HANDOVER) {
|
if (flags & OGS_PFCP_MODIFY_ACTIVATE) {
|
||||||
ogs_pkbuf_t *n2smbuf =
|
|
||||||
ngap_build_path_switch_request_ack_transfer(sess);
|
|
||||||
ogs_assert(n2smbuf);
|
|
||||||
|
|
||||||
smf_sbi_send_sm_context_updated_data_n2smbuf(sess, stream,
|
|
||||||
OpenAPI_n2_sm_info_type_PATH_SWITCH_REQ_ACK, n2smbuf);
|
|
||||||
} else if (flags & OGS_PFCP_MODIFY_N2_HANDOVER) {
|
|
||||||
|
|
||||||
if (smf_sess_have_indirect_data_forwarding(sess) == true) {
|
|
||||||
ogs_assert(OGS_OK ==
|
|
||||||
smf_5gc_pfcp_send_all_pdr_modification_request(
|
|
||||||
sess, stream,
|
|
||||||
OGS_PFCP_MODIFY_INDIRECT|OGS_PFCP_MODIFY_REMOVE,
|
|
||||||
0, ogs_local_conf()->time.handover.duration));
|
|
||||||
}
|
|
||||||
|
|
||||||
smf_sbi_send_sm_context_updated_data_ho_state(
|
|
||||||
sess, stream, OpenAPI_ho_state_COMPLETED);
|
|
||||||
} else if (flags & OGS_PFCP_MODIFY_HOME_ROUTED_ROAMING) {
|
|
||||||
if (flags & OGS_PFCP_MODIFY_DL_ONLY) {
|
if (flags & OGS_PFCP_MODIFY_DL_ONLY) {
|
||||||
if (sess->up_cnx_state == OpenAPI_up_cnx_state_ACTIVATING) {
|
if (sess->up_cnx_state == OpenAPI_up_cnx_state_ACTIVATING) {
|
||||||
sess->up_cnx_state = OpenAPI_up_cnx_state_ACTIVATED;
|
sess->up_cnx_state = OpenAPI_up_cnx_state_ACTIVATED;
|
||||||
smf_sbi_send_sm_context_updated_data_up_cnx_state(
|
smf_sbi_send_sm_context_updated_data_up_cnx_state(
|
||||||
sess, stream, OpenAPI_up_cnx_state_ACTIVATED);
|
sess, stream, OpenAPI_up_cnx_state_ACTIVATED);
|
||||||
} else {
|
} else {
|
||||||
ogs_assert(true ==
|
if (stream)
|
||||||
ogs_sbi_send_http_status_no_content(stream));
|
ogs_assert(true ==
|
||||||
|
ogs_sbi_send_http_status_no_content(stream));
|
||||||
}
|
}
|
||||||
} else if (flags & OGS_PFCP_MODIFY_UL_ONLY) {
|
} else if (flags & OGS_PFCP_MODIFY_UL_ONLY) {
|
||||||
smf_n1_n2_message_transfer_param_t param;
|
smf_n1_n2_message_transfer_param_t param;
|
||||||
@@ -455,38 +437,7 @@ void smf_5gc_n4_handle_session_modification_response(
|
|||||||
ogs_fatal("Invalid flags [0x%llx]", (long long)flags);
|
ogs_fatal("Invalid flags [0x%llx]", (long long)flags);
|
||||||
ogs_assert_if_reached();
|
ogs_assert_if_reached();
|
||||||
}
|
}
|
||||||
} else {
|
} else if (flags & OGS_PFCP_MODIFY_DEACTIVATE) {
|
||||||
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 {
|
|
||||||
int r = smf_sbi_discover_and_send(
|
|
||||||
OGS_SBI_SERVICE_TYPE_NUDM_UECM, NULL,
|
|
||||||
smf_nudm_uecm_build_registration,
|
|
||||||
sess, stream, SMF_UECM_STATE_REGISTERED, NULL);
|
|
||||||
ogs_expect(r == OGS_OK);
|
|
||||||
ogs_assert(r != OGS_ERROR);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
} else if (flags & OGS_PFCP_MODIFY_DEACTIVATE) {
|
|
||||||
if (flags & OGS_PFCP_MODIFY_ERROR_INDICATION) {
|
|
||||||
smf_n1_n2_message_transfer_param_t param;
|
|
||||||
|
|
||||||
memset(¶m, 0, sizeof(param));
|
|
||||||
param.state = SMF_ERROR_INDICATON_RECEIVED_FROM_5G_AN;
|
|
||||||
param.n2smbuf =
|
|
||||||
ngap_build_pdu_session_resource_release_command_transfer(
|
|
||||||
sess, SMF_NGAP_STATE_ERROR_INDICATION_RECEIVED_FROM_5G_AN,
|
|
||||||
NGAP_Cause_PR_nas, NGAP_CauseNas_normal_release);
|
|
||||||
ogs_assert(param.n2smbuf);
|
|
||||||
|
|
||||||
param.skip_ind = true;
|
|
||||||
|
|
||||||
smf_namf_comm_send_n1_n2_message_transfer(sess, NULL, ¶m);
|
|
||||||
} else if (flags & OGS_PFCP_MODIFY_HOME_ROUTED_ROAMING) {
|
|
||||||
int r;
|
|
||||||
ogs_assert(trigger);
|
ogs_assert(trigger);
|
||||||
|
|
||||||
if (trigger == OGS_PFCP_DELETE_TRIGGER_UE_REQUESTED) {
|
if (trigger == OGS_PFCP_DELETE_TRIGGER_UE_REQUESTED) {
|
||||||
@@ -516,7 +467,84 @@ void smf_5gc_n4_handle_session_modification_response(
|
|||||||
ogs_fatal("Invalid delete trigger[%d]", trigger);
|
ogs_fatal("Invalid delete trigger[%d]", trigger);
|
||||||
ogs_assert_if_reached();
|
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));
|
||||||
|
|
||||||
|
/* Network Requested PDU Session Modification */
|
||||||
|
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 {
|
||||||
|
ogs_fatal("Invalid PDR-Create flags [0x%llx]",
|
||||||
|
(long long)flags);
|
||||||
|
ogs_assert_if_reached();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
ogs_fatal("Invalid flags [%lld]", (long long)flags);
|
||||||
|
ogs_assert_if_reached();
|
||||||
|
}
|
||||||
|
} else if (flags & OGS_PFCP_MODIFY_ACTIVATE) {
|
||||||
|
if (flags & OGS_PFCP_MODIFY_XN_HANDOVER) {
|
||||||
|
ogs_pkbuf_t *n2smbuf =
|
||||||
|
ngap_build_path_switch_request_ack_transfer(sess);
|
||||||
|
ogs_assert(n2smbuf);
|
||||||
|
|
||||||
|
smf_sbi_send_sm_context_updated_data_n2smbuf(sess, stream,
|
||||||
|
OpenAPI_n2_sm_info_type_PATH_SWITCH_REQ_ACK, n2smbuf);
|
||||||
|
} else if (flags & OGS_PFCP_MODIFY_N2_HANDOVER) {
|
||||||
|
|
||||||
|
if (smf_sess_have_indirect_data_forwarding(sess) == true) {
|
||||||
|
ogs_assert(OGS_OK ==
|
||||||
|
smf_5gc_pfcp_send_all_pdr_modification_request(
|
||||||
|
sess, stream,
|
||||||
|
OGS_PFCP_MODIFY_INDIRECT|OGS_PFCP_MODIFY_REMOVE,
|
||||||
|
0, ogs_local_conf()->time.handover.duration));
|
||||||
|
}
|
||||||
|
|
||||||
|
smf_sbi_send_sm_context_updated_data_ho_state(
|
||||||
|
sess, stream, OpenAPI_ho_state_COMPLETED);
|
||||||
|
} 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);
|
||||||
|
} else {
|
||||||
|
r = smf_sbi_discover_and_send(
|
||||||
|
OGS_SBI_SERVICE_TYPE_NUDM_UECM, NULL,
|
||||||
|
smf_nudm_uecm_build_registration,
|
||||||
|
sess, stream, SMF_UECM_STATE_REGISTERED, NULL);
|
||||||
|
ogs_expect(r == OGS_OK);
|
||||||
|
ogs_assert(r != OGS_ERROR);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} else if (flags & OGS_PFCP_MODIFY_DEACTIVATE) {
|
||||||
|
if (flags & OGS_PFCP_MODIFY_ERROR_INDICATION) {
|
||||||
|
smf_n1_n2_message_transfer_param_t param;
|
||||||
|
|
||||||
|
memset(¶m, 0, sizeof(param));
|
||||||
|
param.state = SMF_ERROR_INDICATON_RECEIVED_FROM_5G_AN;
|
||||||
|
param.n2smbuf =
|
||||||
|
ngap_build_pdu_session_resource_release_command_transfer(
|
||||||
|
sess, SMF_NGAP_STATE_ERROR_INDICATION_RECEIVED_FROM_5G_AN,
|
||||||
|
NGAP_Cause_PR_nas, NGAP_CauseNas_normal_release);
|
||||||
|
ogs_assert(param.n2smbuf);
|
||||||
|
|
||||||
|
param.skip_ind = true;
|
||||||
|
|
||||||
|
smf_namf_comm_send_n1_n2_message_transfer(sess, NULL, ¶m);
|
||||||
} else {
|
} else {
|
||||||
smf_sbi_send_sm_context_updated_data_up_cnx_state(
|
smf_sbi_send_sm_context_updated_data_up_cnx_state(
|
||||||
sess, stream, OpenAPI_up_cnx_state_DEACTIVATED);
|
sess, stream, OpenAPI_up_cnx_state_DEACTIVATED);
|
||||||
@@ -688,23 +716,9 @@ void smf_5gc_n4_handle_session_modification_response(
|
|||||||
uint8_t qos_rule_code = 0;
|
uint8_t qos_rule_code = 0;
|
||||||
uint8_t qos_flow_description_code = 0;
|
uint8_t qos_flow_description_code = 0;
|
||||||
|
|
||||||
if (flags & OGS_PFCP_MODIFY_TFT_NEW) {
|
qos_rule_code = QOS_RULE_CODE_FROM_PFCP_FLAGS(flags);
|
||||||
qos_rule_code = OGS_NAS_QOS_CODE_CREATE_NEW_QOS_RULE;
|
qos_flow_description_code =
|
||||||
} else if (flags & OGS_PFCP_MODIFY_TFT_ADD) {
|
QOS_RULE_FLOW_DESCRIPTION_CODE_FROM_PFCP_FLAGS(flags);
|
||||||
qos_rule_code = OGS_NAS_QOS_CODE_MODIFY_EXISTING_QOS_RULE_AND_ADD_PACKET_FILTERS;
|
|
||||||
} else if (flags & OGS_PFCP_MODIFY_TFT_REPLACE) {
|
|
||||||
qos_rule_code = OGS_NAS_QOS_CODE_MODIFY_EXISTING_QOS_RULE_AND_REPLACE_ALL_PACKET_FILTERS;
|
|
||||||
} else if (flags & OGS_PFCP_MODIFY_TFT_DELETE) {
|
|
||||||
qos_rule_code = OGS_NAS_QOS_CODE_MODIFY_EXISTING_QOS_RULE_AND_DELETE_PACKET_FILTERS;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (flags & OGS_PFCP_MODIFY_QOS_CREATE) {
|
|
||||||
ogs_assert_if_reached();
|
|
||||||
} else if (flags & OGS_PFCP_MODIFY_QOS_MODIFY) {
|
|
||||||
qos_flow_description_code = OGS_NAS_MODIFY_NEW_QOS_FLOW_DESCRIPTION;
|
|
||||||
} else if (flags & OGS_PFCP_MODIFY_QOS_DELETE) {
|
|
||||||
ogs_assert_if_reached();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (flags & OGS_PFCP_MODIFY_NETWORK_REQUESTED) {
|
if (flags & OGS_PFCP_MODIFY_NETWORK_REQUESTED) {
|
||||||
ogs_assert(flags & OGS_PFCP_MODIFY_SESSION);
|
ogs_assert(flags & OGS_PFCP_MODIFY_SESSION);
|
||||||
|
|||||||
@@ -38,6 +38,15 @@ bool smf_namf_comm_handle_n1_n2_message_transfer(
|
|||||||
switch (state) {
|
switch (state) {
|
||||||
case SMF_UE_REQUESTED_PDU_SESSION_ESTABLISHMENT:
|
case SMF_UE_REQUESTED_PDU_SESSION_ESTABLISHMENT:
|
||||||
if (recvmsg->res_status == OGS_SBI_HTTP_STATUS_OK) {
|
if (recvmsg->res_status == OGS_SBI_HTTP_STATUS_OK) {
|
||||||
|
/*
|
||||||
|
* Non-roaming/LBO: start network-triggered PDU Session Modification at step 11
|
||||||
|
* after N1N2 transfer (Establishment Accept) and N2/N4 context sync, ensuring
|
||||||
|
* the session is active on UE, RAN, and SMF before applying QoS updates.
|
||||||
|
*
|
||||||
|
* Home-Routed Roaming: trigger PDU Session Modification at step 13
|
||||||
|
* immediately after H-SMF’s CreateSMContext response and H-UPF N4 setup
|
||||||
|
* to apply QoS updates without waiting for V-SMF or RAN setup.
|
||||||
|
*/
|
||||||
smf_qos_flow_binding(sess);
|
smf_qos_flow_binding(sess);
|
||||||
} else {
|
} else {
|
||||||
ogs_error("[%s:%d] HTTP response error [%d]",
|
ogs_error("[%s:%d] HTTP response error [%d]",
|
||||||
@@ -57,7 +66,9 @@ bool smf_namf_comm_handle_n1_n2_message_transfer(
|
|||||||
if (recvmsg->res_status == OGS_SBI_HTTP_STATUS_OK) {
|
if (recvmsg->res_status == OGS_SBI_HTTP_STATUS_OK) {
|
||||||
if (N1N2MessageTransferRspData->cause ==
|
if (N1N2MessageTransferRspData->cause ==
|
||||||
OpenAPI_n1_n2_message_transfer_cause_N1_N2_TRANSFER_INITIATED) {
|
OpenAPI_n1_n2_message_transfer_cause_N1_N2_TRANSFER_INITIATED) {
|
||||||
/* Nothing */
|
if (stream)
|
||||||
|
sess->n1_n2_modified_stream_id =
|
||||||
|
ogs_sbi_id_from_stream(stream);
|
||||||
} else {
|
} else {
|
||||||
ogs_error("Not implemented [cause:%d]",
|
ogs_error("Not implemented [cause:%d]",
|
||||||
N1N2MessageTransferRspData->cause);
|
N1N2MessageTransferRspData->cause);
|
||||||
|
|||||||
@@ -19,6 +19,68 @@
|
|||||||
|
|
||||||
#include "ngap-build.h"
|
#include "ngap-build.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fill common QoS flow level parameters: 5QI, ARP, and optional GBR/MBR.
|
||||||
|
*/
|
||||||
|
static void fill_qos_level_parameters(
|
||||||
|
NGAP_QosFlowLevelQosParameters_t *params,
|
||||||
|
const ogs_qos_t *qos,
|
||||||
|
bool include_gbr)
|
||||||
|
{
|
||||||
|
NGAP_AllocationAndRetentionPriority_t
|
||||||
|
*allocationAndRetentionPriority = NULL;
|
||||||
|
NGAP_QosCharacteristics_t *qosCharacteristics = NULL;
|
||||||
|
NGAP_NonDynamic5QIDescriptor_t *nonDynamic5QI = NULL;
|
||||||
|
|
||||||
|
/* Allocation and Retention Priority */
|
||||||
|
allocationAndRetentionPriority =
|
||||||
|
¶ms->allocationAndRetentionPriority;
|
||||||
|
|
||||||
|
allocationAndRetentionPriority->priorityLevelARP = qos->arp.priority_level;
|
||||||
|
if (qos->arp.pre_emption_capability == OGS_5GC_PRE_EMPTION_ENABLED)
|
||||||
|
allocationAndRetentionPriority->pre_emptionCapability =
|
||||||
|
NGAP_Pre_emptionCapability_may_trigger_pre_emption;
|
||||||
|
if (qos->arp.pre_emption_vulnerability == OGS_5GC_PRE_EMPTION_ENABLED)
|
||||||
|
allocationAndRetentionPriority->pre_emptionVulnerability =
|
||||||
|
NGAP_Pre_emptionVulnerability_pre_emptable;
|
||||||
|
|
||||||
|
/* Non-Dynamic 5QI Descriptor */
|
||||||
|
qosCharacteristics = ¶ms->qosCharacteristics;
|
||||||
|
qosCharacteristics->choice.nonDynamic5QI = nonDynamic5QI =
|
||||||
|
CALLOC(1, sizeof(struct NGAP_NonDynamic5QIDescriptor));
|
||||||
|
ogs_assert(nonDynamic5QI);
|
||||||
|
qosCharacteristics->present = NGAP_QosCharacteristics_PR_nonDynamic5QI;
|
||||||
|
|
||||||
|
nonDynamic5QI->fiveQI = qos->index;
|
||||||
|
|
||||||
|
/* Optional GBR/MBR Information */
|
||||||
|
if (include_gbr &&
|
||||||
|
qos->mbr.downlink && qos->mbr.uplink &&
|
||||||
|
qos->gbr.downlink && qos->gbr.uplink) {
|
||||||
|
NGAP_GBR_QosInformation_t *gBR_QosInformation =
|
||||||
|
params->gBR_QosInformation = CALLOC(1, sizeof(*gBR_QosInformation));
|
||||||
|
ogs_assert(gBR_QosInformation);
|
||||||
|
|
||||||
|
asn_uint642INTEGER(&gBR_QosInformation->maximumFlowBitRateDL,
|
||||||
|
qos->mbr.downlink);
|
||||||
|
asn_uint642INTEGER(&gBR_QosInformation->maximumFlowBitRateUL,
|
||||||
|
qos->mbr.uplink);
|
||||||
|
asn_uint642INTEGER(&gBR_QosInformation->
|
||||||
|
guaranteedFlowBitRateDL, qos->gbr.downlink);
|
||||||
|
asn_uint642INTEGER(&gBR_QosInformation->
|
||||||
|
guaranteedFlowBitRateUL, qos->gbr.uplink);
|
||||||
|
} else if (include_gbr &&
|
||||||
|
(qos->mbr.downlink || qos->mbr.uplink ||
|
||||||
|
qos->gbr.downlink || qos->gbr.uplink)) {
|
||||||
|
ogs_error("Missing one or more MBR/GBR parameters; "
|
||||||
|
"defaulting to Non-GBR flow ");
|
||||||
|
ogs_error(" MBR[DL:%lld,UL:%lld]",
|
||||||
|
(long long)qos->mbr.downlink, (long long)qos->mbr.uplink);
|
||||||
|
ogs_error(" GBR[DL:%lld,UL:%lld]",
|
||||||
|
(long long)qos->gbr.downlink, (long long)qos->gbr.uplink);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
ogs_pkbuf_t *ngap_build_pdu_session_resource_setup_request_transfer(
|
ogs_pkbuf_t *ngap_build_pdu_session_resource_setup_request_transfer(
|
||||||
smf_sess_t *sess)
|
smf_sess_t *sess)
|
||||||
{
|
{
|
||||||
@@ -36,12 +98,6 @@ ogs_pkbuf_t *ngap_build_pdu_session_resource_setup_request_transfer(
|
|||||||
NGAP_SecurityIndication_t *SecurityIndication = NULL;
|
NGAP_SecurityIndication_t *SecurityIndication = NULL;
|
||||||
NGAP_QosFlowSetupRequestList_t *QosFlowSetupRequestList = NULL;
|
NGAP_QosFlowSetupRequestList_t *QosFlowSetupRequestList = NULL;
|
||||||
NGAP_QosFlowSetupRequestItem_t *QosFlowSetupRequestItem = NULL;
|
NGAP_QosFlowSetupRequestItem_t *QosFlowSetupRequestItem = NULL;
|
||||||
NGAP_QosFlowIdentifier_t *qosFlowIdentifier = NULL;
|
|
||||||
NGAP_QosFlowLevelQosParameters_t *qosFlowLevelQosParameters = NULL;
|
|
||||||
NGAP_QosCharacteristics_t *qosCharacteristics = NULL;
|
|
||||||
NGAP_NonDynamic5QIDescriptor_t *nonDynamic5QI = NULL;
|
|
||||||
NGAP_AllocationAndRetentionPriority_t *allocationAndRetentionPriority;
|
|
||||||
NGAP_GBR_QosInformation_t *gBR_QosInformation = NULL;
|
|
||||||
|
|
||||||
ogs_assert(sess);
|
ogs_assert(sess);
|
||||||
|
|
||||||
@@ -181,7 +237,8 @@ ogs_pkbuf_t *ngap_build_pdu_session_resource_setup_request_transfer(
|
|||||||
|
|
||||||
if (smf_self()->security_indication.
|
if (smf_self()->security_indication.
|
||||||
maximum_integrity_protected_data_rate_downlink) {
|
maximum_integrity_protected_data_rate_downlink) {
|
||||||
NGAP_ProtocolExtensionContainer_11905P297_t *extContainer = NULL;
|
NGAP_ProtocolExtensionContainer_11905P297_t
|
||||||
|
*extContainer = NULL;
|
||||||
NGAP_SecurityIndication_ExtIEs_t *extIe = NULL;
|
NGAP_SecurityIndication_ExtIEs_t *extIe = NULL;
|
||||||
NGAP_MaximumIntegrityProtectedDataRate_t
|
NGAP_MaximumIntegrityProtectedDataRate_t
|
||||||
*MaximumIntegrityProtectedDataRate = NULL;
|
*MaximumIntegrityProtectedDataRate = NULL;
|
||||||
@@ -224,69 +281,83 @@ ogs_pkbuf_t *ngap_build_pdu_session_resource_setup_request_transfer(
|
|||||||
|
|
||||||
QosFlowSetupRequestList = &ie->value.choice.QosFlowSetupRequestList;
|
QosFlowSetupRequestList = &ie->value.choice.QosFlowSetupRequestList;
|
||||||
|
|
||||||
ogs_list_for_each(&sess->bearer_list, qos_flow) {
|
if (HOME_ROUTED_ROAMING_IN_VSMF(sess)) {
|
||||||
|
OpenAPI_list_t *qosFlowsSetupList = NULL;
|
||||||
|
OpenAPI_qos_flow_setup_item_t *qosFlowSetupItem = NULL;
|
||||||
|
OpenAPI_qos_flow_profile_t *qosFlowProfile = NULL;
|
||||||
|
OpenAPI_lnode_t *node = NULL;
|
||||||
|
|
||||||
|
ogs_qos_t qos;
|
||||||
|
|
||||||
|
qosFlowsSetupList = sess->h_smf_qos_flows_setup_list;
|
||||||
|
ogs_assert(qosFlowsSetupList);
|
||||||
|
|
||||||
|
node = qosFlowsSetupList->first;
|
||||||
|
ogs_assert(node);
|
||||||
|
qosFlowSetupItem = node->data;
|
||||||
|
ogs_assert(qosFlowSetupItem);
|
||||||
|
|
||||||
|
qosFlowProfile = qosFlowSetupItem->qos_flow_profile;
|
||||||
|
ogs_assert(qosFlowProfile);
|
||||||
|
|
||||||
|
memset(&qos, 0, sizeof(qos));
|
||||||
|
|
||||||
|
qos.index = qosFlowProfile->_5qi;
|
||||||
|
ogs_assert(qosFlowProfile->arp);
|
||||||
|
qos.arp.priority_level = qosFlowProfile->arp->priority_level;
|
||||||
|
if (qosFlowProfile->arp->preempt_cap ==
|
||||||
|
OpenAPI_preemption_capability_NOT_PREEMPT)
|
||||||
|
qos.arp.pre_emption_capability =
|
||||||
|
OGS_5GC_PRE_EMPTION_DISABLED;
|
||||||
|
else if (qosFlowProfile->arp->preempt_cap ==
|
||||||
|
OpenAPI_preemption_capability_MAY_PREEMPT)
|
||||||
|
qos.arp.pre_emption_capability =
|
||||||
|
OGS_5GC_PRE_EMPTION_ENABLED;
|
||||||
|
else {
|
||||||
|
ogs_error("Invalid preempt_cap [%d]",
|
||||||
|
qosFlowProfile->arp->preempt_cap);
|
||||||
|
ogs_assert_if_reached();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (qosFlowProfile->arp->preempt_vuln ==
|
||||||
|
OpenAPI_preemption_vulnerability_NOT_PREEMPTABLE)
|
||||||
|
qos.arp.pre_emption_vulnerability =
|
||||||
|
OGS_5GC_PRE_EMPTION_DISABLED;
|
||||||
|
else if (qosFlowProfile->arp->preempt_vuln ==
|
||||||
|
OpenAPI_preemption_vulnerability_PREEMPTABLE)
|
||||||
|
qos.arp.pre_emption_vulnerability =
|
||||||
|
OGS_5GC_PRE_EMPTION_ENABLED;
|
||||||
|
else {
|
||||||
|
ogs_error("Invalid preempt_vuln [%d]",
|
||||||
|
qosFlowProfile->arp->preempt_vuln);
|
||||||
|
ogs_assert_if_reached();
|
||||||
|
}
|
||||||
|
|
||||||
QosFlowSetupRequestItem =
|
QosFlowSetupRequestItem =
|
||||||
CALLOC(1, sizeof(struct NGAP_QosFlowSetupRequestItem));
|
CALLOC(1, sizeof(struct NGAP_QosFlowSetupRequestItem));
|
||||||
ogs_assert(QosFlowSetupRequestItem);
|
ogs_assert(QosFlowSetupRequestItem);
|
||||||
ASN_SEQUENCE_ADD(&QosFlowSetupRequestList->list,
|
ASN_SEQUENCE_ADD(&QosFlowSetupRequestList->list,
|
||||||
QosFlowSetupRequestItem);
|
QosFlowSetupRequestItem);
|
||||||
|
|
||||||
qosFlowIdentifier = &QosFlowSetupRequestItem->qosFlowIdentifier;
|
QosFlowSetupRequestItem->qosFlowIdentifier = qosFlowSetupItem->qfi;
|
||||||
qosFlowLevelQosParameters =
|
|
||||||
&QosFlowSetupRequestItem->qosFlowLevelQosParameters;
|
|
||||||
|
|
||||||
allocationAndRetentionPriority =
|
fill_qos_level_parameters(
|
||||||
&qosFlowLevelQosParameters->allocationAndRetentionPriority;
|
&QosFlowSetupRequestItem->qosFlowLevelQosParameters,
|
||||||
qosCharacteristics = &qosFlowLevelQosParameters->qosCharacteristics;
|
&qos, true);
|
||||||
nonDynamic5QI = CALLOC(1, sizeof(struct NGAP_NonDynamic5QIDescriptor));
|
|
||||||
ogs_assert(nonDynamic5QI);
|
|
||||||
qosCharacteristics->choice.nonDynamic5QI = nonDynamic5QI;
|
|
||||||
qosCharacteristics->present = NGAP_QosCharacteristics_PR_nonDynamic5QI;
|
|
||||||
|
|
||||||
*qosFlowIdentifier = qos_flow->qfi;
|
} else {
|
||||||
|
ogs_list_for_each(&sess->bearer_list, qos_flow) {
|
||||||
|
QosFlowSetupRequestItem =
|
||||||
|
CALLOC(1, sizeof(struct NGAP_QosFlowSetupRequestItem));
|
||||||
|
ogs_assert(QosFlowSetupRequestItem);
|
||||||
|
ASN_SEQUENCE_ADD(&QosFlowSetupRequestList->list,
|
||||||
|
QosFlowSetupRequestItem);
|
||||||
|
|
||||||
nonDynamic5QI->fiveQI = qos_flow->qos.index;
|
QosFlowSetupRequestItem->qosFlowIdentifier = qos_flow->qfi;
|
||||||
|
|
||||||
allocationAndRetentionPriority->priorityLevelARP =
|
fill_qos_level_parameters(
|
||||||
qos_flow->qos.arp.priority_level;
|
&QosFlowSetupRequestItem->qosFlowLevelQosParameters,
|
||||||
if (qos_flow->qos.arp.pre_emption_capability ==
|
&qos_flow->qos, true);
|
||||||
OGS_5GC_PRE_EMPTION_ENABLED)
|
|
||||||
allocationAndRetentionPriority->pre_emptionCapability =
|
|
||||||
NGAP_Pre_emptionCapability_may_trigger_pre_emption;
|
|
||||||
if (qos_flow->qos.arp.pre_emption_vulnerability ==
|
|
||||||
OGS_5GC_PRE_EMPTION_ENABLED)
|
|
||||||
allocationAndRetentionPriority->pre_emptionVulnerability =
|
|
||||||
NGAP_Pre_emptionVulnerability_pre_emptable;
|
|
||||||
|
|
||||||
if (qos_flow->qos.mbr.downlink || qos_flow->qos.mbr.uplink ||
|
|
||||||
qos_flow->qos.gbr.downlink || qos_flow->qos.gbr.uplink) {
|
|
||||||
|
|
||||||
if (qos_flow->qos.mbr.downlink && qos_flow->qos.mbr.uplink &&
|
|
||||||
qos_flow->qos.gbr.downlink && qos_flow->qos.gbr.uplink) {
|
|
||||||
|
|
||||||
qosFlowLevelQosParameters->gBR_QosInformation =
|
|
||||||
gBR_QosInformation = CALLOC(1, sizeof(*gBR_QosInformation));
|
|
||||||
ogs_assert(gBR_QosInformation);
|
|
||||||
|
|
||||||
asn_uint642INTEGER(&gBR_QosInformation->maximumFlowBitRateDL,
|
|
||||||
qos_flow->qos.mbr.downlink);
|
|
||||||
asn_uint642INTEGER(&gBR_QosInformation->maximumFlowBitRateUL,
|
|
||||||
qos_flow->qos.mbr.uplink);
|
|
||||||
asn_uint642INTEGER(&gBR_QosInformation->
|
|
||||||
guaranteedFlowBitRateDL, qos_flow->qos.gbr.downlink);
|
|
||||||
asn_uint642INTEGER(&gBR_QosInformation->
|
|
||||||
guaranteedFlowBitRateUL, qos_flow->qos.gbr.uplink);
|
|
||||||
|
|
||||||
} else {
|
|
||||||
ogs_error("Missing one or more MBR/GBR parameters; "
|
|
||||||
"defaulting to Non-GBR flow ");
|
|
||||||
ogs_error(" MBR[DL:%lld,UL:%lld]",
|
|
||||||
(long long)qos_flow->qos.mbr.downlink,
|
|
||||||
(long long)qos_flow->qos.mbr.uplink);
|
|
||||||
ogs_error(" GBR[DL:%lld,UL:%lld]",
|
|
||||||
(long long)qos_flow->qos.gbr.downlink,
|
|
||||||
(long long)qos_flow->qos.gbr.uplink);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -295,7 +366,7 @@ ogs_pkbuf_t *ngap_build_pdu_session_resource_setup_request_transfer(
|
|||||||
}
|
}
|
||||||
|
|
||||||
ogs_pkbuf_t *ngap_build_pdu_session_resource_modify_request_transfer(
|
ogs_pkbuf_t *ngap_build_pdu_session_resource_modify_request_transfer(
|
||||||
smf_sess_t *sess, bool qos_presence)
|
smf_sess_t *sess, bool include_gbr)
|
||||||
{
|
{
|
||||||
NGAP_PDUSessionResourceModifyRequestTransfer_t message;
|
NGAP_PDUSessionResourceModifyRequestTransfer_t message;
|
||||||
|
|
||||||
@@ -303,12 +374,6 @@ ogs_pkbuf_t *ngap_build_pdu_session_resource_modify_request_transfer(
|
|||||||
|
|
||||||
NGAP_QosFlowAddOrModifyRequestList_t *QosFlowAddOrModifyRequestList = NULL;
|
NGAP_QosFlowAddOrModifyRequestList_t *QosFlowAddOrModifyRequestList = NULL;
|
||||||
NGAP_QosFlowAddOrModifyRequestItem_t *QosFlowAddOrModifyRequestItem = NULL;
|
NGAP_QosFlowAddOrModifyRequestItem_t *QosFlowAddOrModifyRequestItem = NULL;
|
||||||
NGAP_QosFlowIdentifier_t *qosFlowIdentifier = NULL;
|
|
||||||
NGAP_QosFlowLevelQosParameters_t *qosFlowLevelQosParameters = NULL;
|
|
||||||
NGAP_QosCharacteristics_t *qosCharacteristics = NULL;
|
|
||||||
NGAP_NonDynamic5QIDescriptor_t *nonDynamic5QI = NULL;
|
|
||||||
NGAP_AllocationAndRetentionPriority_t *allocationAndRetentionPriority;
|
|
||||||
NGAP_GBR_QosInformation_t *gBR_QosInformation;
|
|
||||||
|
|
||||||
smf_bearer_t *qos_flow = NULL;
|
smf_bearer_t *qos_flow = NULL;
|
||||||
|
|
||||||
@@ -318,80 +383,126 @@ ogs_pkbuf_t *ngap_build_pdu_session_resource_modify_request_transfer(
|
|||||||
memset(&message, 0, sizeof(NGAP_PDUSessionResourceModifyRequestTransfer_t));
|
memset(&message, 0, sizeof(NGAP_PDUSessionResourceModifyRequestTransfer_t));
|
||||||
|
|
||||||
ie = CALLOC(1, sizeof(NGAP_PDUSessionResourceModifyRequestTransferIEs_t));
|
ie = CALLOC(1, sizeof(NGAP_PDUSessionResourceModifyRequestTransferIEs_t));
|
||||||
|
ogs_assert(ie);
|
||||||
ASN_SEQUENCE_ADD(&message.protocolIEs, ie);
|
ASN_SEQUENCE_ADD(&message.protocolIEs, ie);
|
||||||
|
|
||||||
ie->id = NGAP_ProtocolIE_ID_id_QosFlowAddOrModifyRequestList;
|
ie->id = NGAP_ProtocolIE_ID_id_QosFlowAddOrModifyRequestList;
|
||||||
ie->criticality = NGAP_Criticality_reject;
|
ie->criticality = NGAP_Criticality_reject;
|
||||||
ie->value.present = NGAP_PDUSessionResourceModifyRequestTransferIEs__value_PR_QosFlowAddOrModifyRequestList;
|
ie->value.present = NGAP_PDUSessionResourceModifyRequestTransferIEs__value_PR_QosFlowAddOrModifyRequestList;
|
||||||
|
|
||||||
QosFlowAddOrModifyRequestList = &ie->value.choice.QosFlowAddOrModifyRequestList;
|
QosFlowAddOrModifyRequestList =
|
||||||
|
&ie->value.choice.QosFlowAddOrModifyRequestList;
|
||||||
|
|
||||||
ogs_list_for_each_entry(
|
/* Home-Routed V-SMF: QoS flow */
|
||||||
&sess->qos_flow_to_modify_list, qos_flow, to_modify_node) {
|
if (HOME_ROUTED_ROAMING_IN_VSMF(sess)) {
|
||||||
|
OpenAPI_lnode_t *node = NULL;
|
||||||
|
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) {
|
||||||
|
OpenAPI_qos_flow_profile_t *qosFlowProfile =
|
||||||
|
qosFlowAddModifyRequestItem->qos_flow_profile;
|
||||||
|
if (qosFlowProfile) {
|
||||||
|
ogs_qos_t qos;
|
||||||
|
|
||||||
QosFlowAddOrModifyRequestItem =
|
memset(&qos, 0, sizeof(qos));
|
||||||
CALLOC(1, sizeof(*QosFlowAddOrModifyRequestItem));
|
|
||||||
ASN_SEQUENCE_ADD(&QosFlowAddOrModifyRequestList->list, QosFlowAddOrModifyRequestItem);
|
|
||||||
|
|
||||||
qosFlowIdentifier = &QosFlowAddOrModifyRequestItem->qosFlowIdentifier;
|
qos.index = qosFlowProfile->_5qi;
|
||||||
|
ogs_assert(qosFlowProfile->arp);
|
||||||
|
qos.arp.priority_level =
|
||||||
|
qosFlowProfile->arp->priority_level;
|
||||||
|
if (qosFlowProfile->arp->preempt_cap ==
|
||||||
|
OpenAPI_preemption_capability_NOT_PREEMPT)
|
||||||
|
qos.arp.pre_emption_capability =
|
||||||
|
OGS_5GC_PRE_EMPTION_DISABLED;
|
||||||
|
else if (qosFlowProfile->arp->preempt_cap ==
|
||||||
|
OpenAPI_preemption_capability_MAY_PREEMPT)
|
||||||
|
qos.arp.pre_emption_capability =
|
||||||
|
OGS_5GC_PRE_EMPTION_ENABLED;
|
||||||
|
else {
|
||||||
|
ogs_error("Invalid preempt_cap [%d]",
|
||||||
|
qosFlowProfile->arp->preempt_cap);
|
||||||
|
ogs_assert_if_reached();
|
||||||
|
}
|
||||||
|
|
||||||
QosFlowAddOrModifyRequestItem->qosFlowLevelQosParameters =
|
if (qosFlowProfile->arp->preempt_vuln ==
|
||||||
qosFlowLevelQosParameters =
|
OpenAPI_preemption_vulnerability_NOT_PREEMPTABLE)
|
||||||
CALLOC(1, sizeof(*qosFlowLevelQosParameters));
|
qos.arp.pre_emption_vulnerability =
|
||||||
|
OGS_5GC_PRE_EMPTION_DISABLED;
|
||||||
|
else if (qosFlowProfile->arp->preempt_vuln ==
|
||||||
|
OpenAPI_preemption_vulnerability_PREEMPTABLE)
|
||||||
|
qos.arp.pre_emption_vulnerability =
|
||||||
|
OGS_5GC_PRE_EMPTION_ENABLED;
|
||||||
|
else {
|
||||||
|
ogs_error("Invalid preempt_vuln [%d]",
|
||||||
|
qosFlowProfile->arp->preempt_vuln);
|
||||||
|
ogs_assert_if_reached();
|
||||||
|
}
|
||||||
|
|
||||||
allocationAndRetentionPriority =
|
if (qosFlowProfile->gbr_qos_flow_info) {
|
||||||
&qosFlowLevelQosParameters->allocationAndRetentionPriority;
|
OpenAPI_gbr_qos_flow_information_t *gbrQosFlowInfo =
|
||||||
qosCharacteristics = &qosFlowLevelQosParameters->qosCharacteristics;
|
qosFlowProfile->gbr_qos_flow_info;
|
||||||
|
if (gbrQosFlowInfo->max_fbr_dl)
|
||||||
|
qos.mbr.downlink =
|
||||||
|
ogs_sbi_bitrate_from_string(
|
||||||
|
gbrQosFlowInfo->max_fbr_dl);
|
||||||
|
if (gbrQosFlowInfo->max_fbr_ul)
|
||||||
|
qos.mbr.uplink =
|
||||||
|
ogs_sbi_bitrate_from_string(
|
||||||
|
gbrQosFlowInfo->max_fbr_ul);
|
||||||
|
if (gbrQosFlowInfo->gua_fbr_dl)
|
||||||
|
qos.gbr.downlink =
|
||||||
|
ogs_sbi_bitrate_from_string(
|
||||||
|
gbrQosFlowInfo->gua_fbr_dl);
|
||||||
|
if (gbrQosFlowInfo->gua_fbr_ul)
|
||||||
|
qos.gbr.uplink =
|
||||||
|
ogs_sbi_bitrate_from_string(
|
||||||
|
gbrQosFlowInfo->gua_fbr_ul);
|
||||||
|
}
|
||||||
|
|
||||||
qosCharacteristics->present = NGAP_QosCharacteristics_PR_nonDynamic5QI;
|
QosFlowAddOrModifyRequestItem =
|
||||||
qosCharacteristics->choice.nonDynamic5QI =
|
CALLOC(1, sizeof(*QosFlowAddOrModifyRequestItem));
|
||||||
nonDynamic5QI = CALLOC(1, sizeof(struct NGAP_NonDynamic5QIDescriptor));
|
ogs_assert(QosFlowAddOrModifyRequestItem);
|
||||||
|
ASN_SEQUENCE_ADD(
|
||||||
|
&QosFlowAddOrModifyRequestList->list,
|
||||||
|
QosFlowAddOrModifyRequestItem);
|
||||||
|
|
||||||
*qosFlowIdentifier = qos_flow->qfi;
|
QosFlowAddOrModifyRequestItem->qosFlowIdentifier =
|
||||||
|
qosFlowAddModifyRequestItem->qfi;
|
||||||
|
|
||||||
nonDynamic5QI->fiveQI = qos_flow->qos.index;
|
QosFlowAddOrModifyRequestItem->qosFlowLevelQosParameters =
|
||||||
|
CALLOC(1, sizeof(NGAP_QosFlowLevelQosParameters_t));
|
||||||
|
ogs_assert(
|
||||||
|
QosFlowAddOrModifyRequestItem->qosFlowLevelQosParameters);
|
||||||
|
|
||||||
allocationAndRetentionPriority->priorityLevelARP =
|
fill_qos_level_parameters(
|
||||||
qos_flow->qos.arp.priority_level;
|
QosFlowAddOrModifyRequestItem->
|
||||||
if (qos_flow->qos.arp.pre_emption_capability ==
|
qosFlowLevelQosParameters, &qos, true);
|
||||||
OGS_5GC_PRE_EMPTION_ENABLED)
|
}
|
||||||
allocationAndRetentionPriority->pre_emptionCapability =
|
|
||||||
NGAP_Pre_emptionCapability_may_trigger_pre_emption;
|
|
||||||
if (qos_flow->qos.arp.pre_emption_vulnerability ==
|
|
||||||
OGS_5GC_PRE_EMPTION_ENABLED)
|
|
||||||
allocationAndRetentionPriority->pre_emptionVulnerability =
|
|
||||||
NGAP_Pre_emptionVulnerability_pre_emptable;
|
|
||||||
|
|
||||||
if (qos_presence == true &&
|
|
||||||
(qos_flow->qos.mbr.downlink || qos_flow->qos.mbr.uplink ||
|
|
||||||
qos_flow->qos.gbr.downlink || qos_flow->qos.gbr.uplink)) {
|
|
||||||
|
|
||||||
if (qos_flow->qos.mbr.downlink && qos_flow->qos.mbr.uplink &&
|
|
||||||
qos_flow->qos.gbr.downlink && qos_flow->qos.gbr.uplink) {
|
|
||||||
|
|
||||||
qosFlowLevelQosParameters->gBR_QosInformation =
|
|
||||||
gBR_QosInformation = CALLOC(1, sizeof(*gBR_QosInformation));
|
|
||||||
|
|
||||||
asn_uint642INTEGER(&gBR_QosInformation->maximumFlowBitRateDL,
|
|
||||||
qos_flow->qos.mbr.downlink);
|
|
||||||
asn_uint642INTEGER(&gBR_QosInformation->maximumFlowBitRateUL,
|
|
||||||
qos_flow->qos.mbr.uplink);
|
|
||||||
asn_uint642INTEGER(&gBR_QosInformation->
|
|
||||||
guaranteedFlowBitRateDL, qos_flow->qos.gbr.downlink);
|
|
||||||
asn_uint642INTEGER(&gBR_QosInformation->
|
|
||||||
guaranteedFlowBitRateUL, qos_flow->qos.gbr.uplink);
|
|
||||||
|
|
||||||
} else {
|
|
||||||
ogs_error("Missing one or more MBR/GBR parameters; "
|
|
||||||
"defaulting to Non-GBR flow ");
|
|
||||||
ogs_error(" MBR[DL:%lld,UL:%lld]",
|
|
||||||
(long long)qos_flow->qos.mbr.downlink,
|
|
||||||
(long long)qos_flow->qos.mbr.uplink);
|
|
||||||
ogs_error(" GBR[DL:%lld,UL:%lld]",
|
|
||||||
(long long)qos_flow->qos.gbr.downlink,
|
|
||||||
(long long)qos_flow->qos.gbr.uplink);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
/* Default: iterate modify-list */
|
||||||
|
ogs_list_for_each_entry(&sess->qos_flow_to_modify_list,
|
||||||
|
qos_flow, to_modify_node) {
|
||||||
|
QosFlowAddOrModifyRequestItem =
|
||||||
|
CALLOC(1, sizeof(*QosFlowAddOrModifyRequestItem));
|
||||||
|
ogs_assert(QosFlowAddOrModifyRequestItem);
|
||||||
|
ASN_SEQUENCE_ADD(
|
||||||
|
&QosFlowAddOrModifyRequestList->list,
|
||||||
|
QosFlowAddOrModifyRequestItem);
|
||||||
|
QosFlowAddOrModifyRequestItem->qosFlowIdentifier = qos_flow->qfi;
|
||||||
|
|
||||||
|
QosFlowAddOrModifyRequestItem->qosFlowLevelQosParameters =
|
||||||
|
CALLOC(1, sizeof(NGAP_QosFlowLevelQosParameters_t));
|
||||||
|
ogs_assert(
|
||||||
|
QosFlowAddOrModifyRequestItem->qosFlowLevelQosParameters);
|
||||||
|
fill_qos_level_parameters(
|
||||||
|
QosFlowAddOrModifyRequestItem->qosFlowLevelQosParameters,
|
||||||
|
&qos_flow->qos, include_gbr);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return ogs_asn_encode(
|
return ogs_asn_encode(
|
||||||
|
|||||||
@@ -30,7 +30,8 @@ ogs_pkbuf_t *ngap_build_pdu_session_resource_setup_request_transfer(
|
|||||||
smf_sess_t *sess);
|
smf_sess_t *sess);
|
||||||
|
|
||||||
ogs_pkbuf_t *ngap_build_pdu_session_resource_modify_request_transfer(
|
ogs_pkbuf_t *ngap_build_pdu_session_resource_modify_request_transfer(
|
||||||
smf_sess_t *sess, bool qos_presence);
|
smf_sess_t *sess, bool include_gbr);
|
||||||
|
|
||||||
ogs_pkbuf_t *ngap_build_pdu_session_resource_release_request_transfer(
|
ogs_pkbuf_t *ngap_build_pdu_session_resource_release_request_transfer(
|
||||||
smf_sess_t *sess, NGAP_Cause_PR group, long cause);
|
smf_sess_t *sess, NGAP_Cause_PR group, long cause);
|
||||||
|
|
||||||
|
|||||||
@@ -26,6 +26,8 @@ int ngap_handle_pdu_session_resource_setup_response_transfer(
|
|||||||
smf_sess_t *sess, ogs_sbi_stream_t *stream, ogs_pkbuf_t *pkbuf)
|
smf_sess_t *sess, ogs_sbi_stream_t *stream, ogs_pkbuf_t *pkbuf)
|
||||||
{
|
{
|
||||||
smf_ue_t *smf_ue = NULL;
|
smf_ue_t *smf_ue = NULL;
|
||||||
|
smf_bearer_t *qos_flow = NULL;
|
||||||
|
|
||||||
int rv, i;
|
int rv, i;
|
||||||
|
|
||||||
uint32_t remote_dl_teid;
|
uint32_t remote_dl_teid;
|
||||||
@@ -103,7 +105,8 @@ int ngap_handle_pdu_session_resource_setup_response_transfer(
|
|||||||
ogs_asn_OCTET_STRING_to_uint32(&gTPTunnel->gTP_TEID, &remote_dl_teid);
|
ogs_asn_OCTET_STRING_to_uint32(&gTPTunnel->gTP_TEID, &remote_dl_teid);
|
||||||
|
|
||||||
/* Need to Update? */
|
/* Need to Update? */
|
||||||
if (memcmp(&sess->remote_dl_ip, &remote_dl_ip, sizeof(sess->remote_dl_ip)) != 0 ||
|
if (memcmp(&sess->remote_dl_ip,
|
||||||
|
&remote_dl_ip, sizeof(sess->remote_dl_ip)) != 0 ||
|
||||||
sess->remote_dl_teid != remote_dl_teid)
|
sess->remote_dl_teid != remote_dl_teid)
|
||||||
far_update = true;
|
far_update = true;
|
||||||
|
|
||||||
@@ -111,36 +114,49 @@ int ngap_handle_pdu_session_resource_setup_response_transfer(
|
|||||||
memcpy(&sess->remote_dl_ip, &remote_dl_ip, sizeof(sess->remote_dl_ip));
|
memcpy(&sess->remote_dl_ip, &remote_dl_ip, sizeof(sess->remote_dl_ip));
|
||||||
sess->remote_dl_teid = remote_dl_teid;
|
sess->remote_dl_teid = remote_dl_teid;
|
||||||
|
|
||||||
associatedQosFlowList = &dLQosFlowPerTNLInformation->associatedQosFlowList;
|
if (HOME_ROUTED_ROAMING_IN_VSMF(sess)) {
|
||||||
for (i = 0; i < associatedQosFlowList->list.count; i++) {
|
ogs_list_for_each(&sess->bearer_list, qos_flow) {
|
||||||
NGAP_AssociatedQosFlowItem_t *associatedQosFlowItem = NULL;
|
ogs_pfcp_far_t *dl_far = qos_flow->dl_far;
|
||||||
associatedQosFlowItem = (NGAP_AssociatedQosFlowItem_t *)
|
ogs_assert(dl_far);
|
||||||
associatedQosFlowList->list.array[i];
|
if (dl_far->apply_action != OGS_PFCP_APPLY_ACTION_FORW) {
|
||||||
|
far_update = true;
|
||||||
|
}
|
||||||
|
|
||||||
if (associatedQosFlowItem) {
|
dl_far->apply_action = OGS_PFCP_APPLY_ACTION_FORW;
|
||||||
smf_bearer_t *qos_flow = smf_qos_flow_find_by_qfi(
|
ogs_assert(OGS_OK ==
|
||||||
sess, associatedQosFlowItem->qosFlowIdentifier);
|
ogs_pfcp_ip_to_outer_header_creation(
|
||||||
|
&sess->remote_dl_ip,
|
||||||
|
&dl_far->outer_header_creation,
|
||||||
|
&dl_far->outer_header_creation_len));
|
||||||
|
dl_far->outer_header_creation.teid = sess->remote_dl_teid;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
associatedQosFlowList =
|
||||||
|
&dLQosFlowPerTNLInformation->associatedQosFlowList;
|
||||||
|
for (i = 0; i < associatedQosFlowList->list.count; i++) {
|
||||||
|
NGAP_AssociatedQosFlowItem_t *associatedQosFlowItem = NULL;
|
||||||
|
associatedQosFlowItem = (NGAP_AssociatedQosFlowItem_t *)
|
||||||
|
associatedQosFlowList->list.array[i];
|
||||||
|
|
||||||
if (qos_flow) {
|
if (associatedQosFlowItem) {
|
||||||
ogs_pfcp_far_t *dl_far = qos_flow->dl_far;
|
qos_flow = smf_qos_flow_find_by_qfi(
|
||||||
ogs_assert(dl_far);
|
sess, associatedQosFlowItem->qosFlowIdentifier);
|
||||||
if (dl_far->apply_action != OGS_PFCP_APPLY_ACTION_FORW) {
|
|
||||||
far_update = true;
|
if (qos_flow) {
|
||||||
|
ogs_pfcp_far_t *dl_far = qos_flow->dl_far;
|
||||||
|
ogs_assert(dl_far);
|
||||||
|
if (dl_far->apply_action != OGS_PFCP_APPLY_ACTION_FORW) {
|
||||||
|
far_update = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
dl_far->apply_action = OGS_PFCP_APPLY_ACTION_FORW;
|
||||||
|
ogs_assert(OGS_OK ==
|
||||||
|
ogs_pfcp_ip_to_outer_header_creation(
|
||||||
|
&sess->remote_dl_ip,
|
||||||
|
&dl_far->outer_header_creation,
|
||||||
|
&dl_far->outer_header_creation_len));
|
||||||
|
dl_far->outer_header_creation.teid = sess->remote_dl_teid;
|
||||||
}
|
}
|
||||||
|
|
||||||
dl_far->apply_action = OGS_PFCP_APPLY_ACTION_FORW;
|
|
||||||
ogs_assert(OGS_OK ==
|
|
||||||
ogs_pfcp_ip_to_outer_header_creation(
|
|
||||||
&sess->remote_dl_ip,
|
|
||||||
&dl_far->outer_header_creation,
|
|
||||||
&dl_far->outer_header_creation_len));
|
|
||||||
dl_far->outer_header_creation.teid = sess->remote_dl_teid;
|
|
||||||
} else {
|
|
||||||
ogs_error("[%s:%d] No QoS flow", smf_ue->supi, sess->psi);
|
|
||||||
smf_sbi_send_sm_context_update_error_log(
|
|
||||||
stream, OGS_SBI_HTTP_STATUS_BAD_REQUEST,
|
|
||||||
"No QoS flow", smf_ue->supi);
|
|
||||||
goto cleanup;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -309,6 +325,21 @@ int ngap_handle_pdu_session_resource_modify_response_transfer(
|
|||||||
|
|
||||||
rv = OGS_ERROR;
|
rv = OGS_ERROR;
|
||||||
|
|
||||||
|
if (HOME_ROUTED_ROAMING_IN_VSMF(sess)) {
|
||||||
|
/* Home Routed Roaming */
|
||||||
|
rv = OGS_OK;
|
||||||
|
|
||||||
|
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));
|
||||||
|
}
|
||||||
|
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
qosFlowAddOrModifyResponseList = message.qosFlowAddOrModifyResponseList;
|
qosFlowAddOrModifyResponseList = message.qosFlowAddOrModifyResponseList;
|
||||||
if (!qosFlowAddOrModifyResponseList) {
|
if (!qosFlowAddOrModifyResponseList) {
|
||||||
/* QosFlow Release */
|
/* QosFlow Release */
|
||||||
|
|||||||
@@ -18,6 +18,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "nsmf-build.h"
|
#include "nsmf-build.h"
|
||||||
|
#include "gsm-build.h"
|
||||||
|
|
||||||
ogs_sbi_request_t *smf_nsmf_pdusession_build_create_data(
|
ogs_sbi_request_t *smf_nsmf_pdusession_build_create_data(
|
||||||
smf_sess_t *sess, void *data)
|
smf_sess_t *sess, void *data)
|
||||||
@@ -472,6 +473,12 @@ ogs_sbi_request_t *smf_nsmf_pdusession_build_vsmf_update_data(
|
|||||||
OpenAPI_ref_to_binary_data_t n1SmInfoToUe;
|
OpenAPI_ref_to_binary_data_t n1SmInfoToUe;
|
||||||
ogs_pkbuf_t *n1SmBufToUe = NULL;
|
ogs_pkbuf_t *n1SmBufToUe = NULL;
|
||||||
|
|
||||||
|
OpenAPI_list_t *qosFlowsAddModRequestList = NULL;
|
||||||
|
OpenAPI_qos_flow_add_modify_request_item_t *qosFlowAddModifyRequestItem =
|
||||||
|
NULL;
|
||||||
|
|
||||||
|
smf_bearer_t *qos_flow = NULL;
|
||||||
|
|
||||||
ogs_assert(sess);
|
ogs_assert(sess);
|
||||||
|
|
||||||
memset(&message, 0, sizeof(message));
|
memset(&message, 0, sizeof(message));
|
||||||
@@ -486,8 +493,172 @@ ogs_sbi_request_t *smf_nsmf_pdusession_build_vsmf_update_data(
|
|||||||
VsmfUpdateData.request_indication = sess->nsmf_param.request_indication;
|
VsmfUpdateData.request_indication = sess->nsmf_param.request_indication;
|
||||||
ogs_assert(VsmfUpdateData.request_indication);
|
ogs_assert(VsmfUpdateData.request_indication);
|
||||||
|
|
||||||
n1SmBufToUe = gsmue_build_pdu_session_release_command(sess);
|
switch (VsmfUpdateData.request_indication) {
|
||||||
ogs_assert(n1SmBufToUe);
|
case OpenAPI_request_indication_UE_REQ_PDU_SES_MOD:
|
||||||
|
case OpenAPI_request_indication_NW_REQ_PDU_SES_MOD:
|
||||||
|
n1SmBufToUe = gsmue_build_pdu_session_modification_command(sess);
|
||||||
|
ogs_assert(n1SmBufToUe);
|
||||||
|
|
||||||
|
qosFlowsAddModRequestList = OpenAPI_list_create();
|
||||||
|
ogs_assert(qosFlowsAddModRequestList);
|
||||||
|
|
||||||
|
int i = 0;
|
||||||
|
|
||||||
|
ogs_list_for_each_entry(
|
||||||
|
&sess->qos_flow_to_modify_list, qos_flow, to_modify_node) {
|
||||||
|
|
||||||
|
int rv, enc_len = 0;
|
||||||
|
|
||||||
|
OpenAPI_qos_flow_profile_t *qosFlowProfile = NULL;
|
||||||
|
OpenAPI_arp_t *Arp = NULL;
|
||||||
|
OpenAPI_gbr_qos_flow_information_t *gbrQosFlowInfo = 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;
|
||||||
|
|
||||||
|
memset(&qos_rule, 0, sizeof(qos_rule));
|
||||||
|
gsm_encode_qos_rule(
|
||||||
|
&qos_rule, qos_flow, sess->nsmf_param.qos_rule_code);
|
||||||
|
|
||||||
|
rv = ogs_nas_build_qos_rules(
|
||||||
|
&authorized_qos_rules, &qos_rule, 1);
|
||||||
|
if (rv != OGS_OK) {
|
||||||
|
ogs_error("ogs_nas_build_qos_rules() failed");
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
if (!authorized_qos_rules.length) {
|
||||||
|
ogs_error("No length");
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
|
||||||
|
enc_len = ogs_base64_encode_len(authorized_qos_rules.length);
|
||||||
|
qosFlowAddModifyRequestItem->qos_rules = ogs_calloc(1, enc_len);
|
||||||
|
ogs_assert(qosFlowAddModifyRequestItem->qos_rules);
|
||||||
|
ogs_base64_encode(
|
||||||
|
qosFlowAddModifyRequestItem->qos_rules,
|
||||||
|
authorized_qos_rules.buffer,
|
||||||
|
authorized_qos_rules.length);
|
||||||
|
|
||||||
|
ogs_free(authorized_qos_rules.buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sess->nsmf_param.qos_flow_description_code) {
|
||||||
|
ogs_nas_qos_flow_descriptions_t
|
||||||
|
authorized_qos_flow_descriptions;
|
||||||
|
ogs_nas_qos_flow_description_t qos_flow_description;
|
||||||
|
|
||||||
|
memset(&qos_flow_description, 0, sizeof(qos_flow_description));
|
||||||
|
gsm_encode_qos_flow_description(
|
||||||
|
&qos_flow_description, qos_flow,
|
||||||
|
sess->nsmf_param.qos_flow_description_code);
|
||||||
|
rv = ogs_nas_build_qos_flow_descriptions(
|
||||||
|
&authorized_qos_flow_descriptions,
|
||||||
|
&qos_flow_description, 1);
|
||||||
|
if (rv != OGS_OK) {
|
||||||
|
ogs_error("ogs_nas_build_qos_flow_descriptions() failed");
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
if (!authorized_qos_flow_descriptions.length) {
|
||||||
|
ogs_error("No length");
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
ogs_base64_encode(
|
||||||
|
qosFlowAddModifyRequestItem->qos_flow_description,
|
||||||
|
authorized_qos_flow_descriptions.buffer,
|
||||||
|
authorized_qos_flow_descriptions.length);
|
||||||
|
|
||||||
|
ogs_free(authorized_qos_flow_descriptions.buffer);
|
||||||
|
|
||||||
|
if (qos_flow->qos.mbr.downlink && qos_flow->qos.mbr.uplink &&
|
||||||
|
qos_flow->qos.gbr.downlink && qos_flow->qos.gbr.uplink) {
|
||||||
|
gbrQosFlowInfo = ogs_calloc(1, sizeof(*gbrQosFlowInfo));
|
||||||
|
ogs_assert(gbrQosFlowInfo);
|
||||||
|
|
||||||
|
gbrQosFlowInfo->max_fbr_ul = ogs_sbi_bitrate_to_string(
|
||||||
|
qos_flow->qos.mbr.uplink, OGS_SBI_BITRATE_BPS);
|
||||||
|
gbrQosFlowInfo->max_fbr_dl = ogs_sbi_bitrate_to_string(
|
||||||
|
qos_flow->qos.mbr.downlink, OGS_SBI_BITRATE_BPS);
|
||||||
|
|
||||||
|
gbrQosFlowInfo->gua_fbr_ul = ogs_sbi_bitrate_to_string(
|
||||||
|
qos_flow->qos.gbr.uplink, OGS_SBI_BITRATE_BPS);
|
||||||
|
gbrQosFlowInfo->gua_fbr_dl = ogs_sbi_bitrate_to_string(
|
||||||
|
qos_flow->qos.gbr.downlink, OGS_SBI_BITRATE_BPS);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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++;
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
case OpenAPI_request_indication_NW_REQ_PDU_SES_REL:
|
||||||
|
case OpenAPI_request_indication_UE_REQ_PDU_SES_REL:
|
||||||
|
n1SmBufToUe = gsmue_build_pdu_session_release_command(sess);
|
||||||
|
ogs_assert(n1SmBufToUe);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
ogs_fatal("Not implemented [request_indication:%d]",
|
||||||
|
VsmfUpdateData.request_indication);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
n1SmInfoToUe.content_id = (char *)OGS_SBI_CONTENT_5GNAS_SM_ID;
|
n1SmInfoToUe.content_id = (char *)OGS_SBI_CONTENT_5GNAS_SM_ID;
|
||||||
VsmfUpdateData.n1_sm_info_to_ue = &n1SmInfoToUe;
|
VsmfUpdateData.n1_sm_info_to_ue = &n1SmInfoToUe;
|
||||||
@@ -508,6 +679,9 @@ end:
|
|||||||
if (message.h.uri)
|
if (message.h.uri)
|
||||||
ogs_free(message.h.uri);
|
ogs_free(message.h.uri);
|
||||||
|
|
||||||
|
CLEAR_QOS_FLOWS_ADD_MOD_REQUEST_LIST(
|
||||||
|
VsmfUpdateData.qos_flows_add_mod_request_list);
|
||||||
|
|
||||||
return request;
|
return request;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1562,7 +1562,7 @@ bool smf_nsmf_handle_create_data_in_hsmf(
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool smf_nsmf_handle_create_data_in_vsmf(
|
bool smf_nsmf_handle_created_data_in_vsmf(
|
||||||
smf_sess_t *sess, ogs_sbi_message_t *recvmsg)
|
smf_sess_t *sess, ogs_sbi_message_t *recvmsg)
|
||||||
{
|
{
|
||||||
int rv;
|
int rv;
|
||||||
@@ -1591,12 +1591,9 @@ bool smf_nsmf_handle_create_data_in_vsmf(
|
|||||||
ogs_ip_t ue_ip;
|
ogs_ip_t ue_ip;
|
||||||
uint8_t prefixlen;
|
uint8_t prefixlen;
|
||||||
|
|
||||||
int len;
|
|
||||||
|
|
||||||
OpenAPI_tunnel_info_t *hcnTunnelInfo = NULL;
|
OpenAPI_tunnel_info_t *hcnTunnelInfo = NULL;
|
||||||
OpenAPI_ambr_t *sessionAmbr = NULL;
|
OpenAPI_ambr_t *sessionAmbr = NULL;
|
||||||
OpenAPI_list_t *qosFlowsSetupList = NULL;
|
OpenAPI_list_t *qosFlowsSetupList = NULL;
|
||||||
OpenAPI_qos_flow_setup_item_t *qosFlowSetupItem = NULL;
|
|
||||||
OpenAPI_qos_flow_profile_t *qosFlowProfile = NULL;
|
OpenAPI_qos_flow_profile_t *qosFlowProfile = NULL;
|
||||||
OpenAPI_lnode_t *node = NULL;
|
OpenAPI_lnode_t *node = NULL;
|
||||||
|
|
||||||
@@ -1818,105 +1815,60 @@ bool smf_nsmf_handle_create_data_in_vsmf(
|
|||||||
&ul_far->outer_header_creation_len));
|
&ul_far->outer_header_creation_len));
|
||||||
ul_far->outer_header_creation.teid = sess->remote_ul_teid;
|
ul_far->outer_header_creation.teid = sess->remote_ul_teid;
|
||||||
|
|
||||||
qosFlowsSetupList = PduSessionCreatedData->qos_flows_setup_list;
|
CLEAR_QOS_FLOWS_SETUP_LIST(sess->h_smf_qos_flows_setup_list);
|
||||||
if (qosFlowsSetupList) {
|
|
||||||
node = qosFlowsSetupList->first;
|
|
||||||
if (node) {
|
|
||||||
qosFlowSetupItem = node->data;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!qosFlowSetupItem ||
|
qosFlowsSetupList = OpenAPI_list_create();
|
||||||
!qosFlowSetupItem->qfi ||
|
ogs_assert(qosFlowsSetupList);
|
||||||
!qosFlowSetupItem->qos_rules ||
|
OpenAPI_list_for_each(
|
||||||
!qosFlowSetupItem->qos_flow_description ||
|
PduSessionCreatedData->qos_flows_setup_list, node) {
|
||||||
!qosFlowSetupItem->qos_flow_profile) {
|
OpenAPI_qos_flow_setup_item_t *dst = NULL, *src = NULL;
|
||||||
ogs_error("[%s:%d] No qosFlowSetupItem [%d:%s:%s]",
|
|
||||||
smf_ue->supi, sess->psi, qosFlowSetupItem->qfi,
|
|
||||||
qosFlowSetupItem->qos_rules ?
|
|
||||||
qosFlowSetupItem->qos_rules : "NULL",
|
|
||||||
qosFlowSetupItem->qos_flow_description ?
|
|
||||||
qosFlowSetupItem->qos_flow_description : "NULL");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
qos_flow->qfi = qosFlowSetupItem->qfi;
|
src = node->data;
|
||||||
|
if (!src ||
|
||||||
OGS_NAS_CLEAR_DATA(&sess->h_smf_authorized_qos_rules);
|
!src->qfi ||
|
||||||
len = ogs_base64_decode_len(qosFlowSetupItem->qos_rules);
|
!src->qos_rules ||
|
||||||
ogs_assert(len);
|
!src->qos_flow_description ||
|
||||||
sess->h_smf_authorized_qos_rules.buffer = ogs_calloc(1, len);
|
!src->qos_flow_profile) {
|
||||||
ogs_assert(sess->h_smf_authorized_qos_rules.buffer);
|
ogs_error("[%s:%d] No src [%d:%s:%s]",
|
||||||
sess->h_smf_authorized_qos_rules.length =
|
smf_ue->supi, sess->psi, src->qfi,
|
||||||
ogs_base64_decode_binary(
|
src->qos_rules ?
|
||||||
sess->h_smf_authorized_qos_rules.buffer,
|
src->qos_rules : "NULL",
|
||||||
qosFlowSetupItem->qos_rules);
|
src->qos_flow_description ?
|
||||||
ogs_assert(sess->h_smf_authorized_qos_rules.length);
|
src->qos_flow_description : "NULL");
|
||||||
|
|
||||||
OGS_NAS_CLEAR_DATA(&sess->h_smf_authorized_qos_flow_descriptions);
|
|
||||||
len = ogs_base64_decode_len(qosFlowSetupItem->qos_flow_description);
|
|
||||||
ogs_assert(len);
|
|
||||||
sess->h_smf_authorized_qos_flow_descriptions.buffer =
|
|
||||||
ogs_calloc(1, len);
|
|
||||||
ogs_assert(sess->h_smf_authorized_qos_flow_descriptions.buffer);
|
|
||||||
sess->h_smf_authorized_qos_flow_descriptions.length =
|
|
||||||
ogs_base64_decode_binary(
|
|
||||||
sess->h_smf_authorized_qos_flow_descriptions.buffer,
|
|
||||||
qosFlowSetupItem->qos_flow_description);
|
|
||||||
ogs_assert(sess->h_smf_authorized_qos_flow_descriptions.length);
|
|
||||||
|
|
||||||
qosFlowProfile = qosFlowSetupItem->qos_flow_profile;
|
|
||||||
ogs_assert(qosFlowProfile);
|
|
||||||
|
|
||||||
if (!qosFlowProfile->_5qi ||
|
|
||||||
!qosFlowProfile->arp ||
|
|
||||||
!qosFlowProfile->arp->priority_level) {
|
|
||||||
ogs_error("[%s:%d] Invalid qosFlowProfile [%d:%p:%d]",
|
|
||||||
smf_ue->supi, sess->psi,
|
|
||||||
qosFlowProfile->_5qi,
|
|
||||||
qosFlowProfile->arp,
|
|
||||||
qosFlowProfile->arp ?
|
|
||||||
qosFlowProfile->arp->priority_level : 0);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
sess->session.qos.index = qosFlowProfile->_5qi;
|
|
||||||
if (qosFlowProfile->arp) {
|
|
||||||
sess->session.qos.arp.priority_level =
|
|
||||||
qosFlowProfile->arp->priority_level;
|
|
||||||
if (qosFlowProfile->arp->preempt_cap ==
|
|
||||||
OpenAPI_preemption_capability_NOT_PREEMPT)
|
|
||||||
sess->session.qos.arp.pre_emption_capability =
|
|
||||||
OGS_5GC_PRE_EMPTION_DISABLED;
|
|
||||||
else if (qosFlowProfile->arp->preempt_cap ==
|
|
||||||
OpenAPI_preemption_capability_MAY_PREEMPT)
|
|
||||||
sess->session.qos.arp.pre_emption_capability =
|
|
||||||
OGS_5GC_PRE_EMPTION_ENABLED;
|
|
||||||
else {
|
|
||||||
ogs_error("[%s:%d] Invalid preempt_cap [%d]",
|
|
||||||
smf_ue->supi, sess->psi,
|
|
||||||
qosFlowProfile->arp->preempt_cap);
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (qosFlowProfile->arp->preempt_vuln ==
|
qosFlowProfile = src->qos_flow_profile;
|
||||||
OpenAPI_preemption_vulnerability_NOT_PREEMPTABLE)
|
if (!qosFlowProfile ||
|
||||||
sess->session.qos.arp.pre_emption_vulnerability =
|
!qosFlowProfile->_5qi ||
|
||||||
OGS_5GC_PRE_EMPTION_DISABLED;
|
!qosFlowProfile->arp ||
|
||||||
else if (qosFlowProfile->arp->preempt_vuln ==
|
!qosFlowProfile->arp->priority_level ||
|
||||||
OpenAPI_preemption_vulnerability_PREEMPTABLE)
|
!(qosFlowProfile->arp->preempt_cap ==
|
||||||
sess->session.qos.arp.pre_emption_vulnerability =
|
OpenAPI_preemption_capability_NOT_PREEMPT ||
|
||||||
OGS_5GC_PRE_EMPTION_ENABLED;
|
qosFlowProfile->arp->preempt_cap ==
|
||||||
else {
|
OpenAPI_preemption_capability_MAY_PREEMPT) ||
|
||||||
ogs_error("[%s:%d] Invalid preempt_vuln [%d]",
|
!(qosFlowProfile->arp->preempt_vuln ==
|
||||||
|
OpenAPI_preemption_vulnerability_NOT_PREEMPTABLE ||
|
||||||
|
qosFlowProfile->arp->preempt_vuln ==
|
||||||
|
OpenAPI_preemption_vulnerability_PREEMPTABLE)) {
|
||||||
|
ogs_error("[%s:%d] Invalid qosFlowProfile [%d:%p:%d]",
|
||||||
smf_ue->supi, sess->psi,
|
smf_ue->supi, sess->psi,
|
||||||
qosFlowProfile->arp->preempt_vuln);
|
qosFlowProfile->_5qi,
|
||||||
|
qosFlowProfile->arp,
|
||||||
|
qosFlowProfile->arp ?
|
||||||
|
qosFlowProfile->arp->priority_level : 0);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
dst = OpenAPI_qos_flow_setup_item_copy(dst, src);
|
||||||
|
ogs_assert(dst);
|
||||||
|
OpenAPI_list_add(qosFlowsSetupList, dst);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Copy Session QoS information to Default QoS Flow */
|
if (qosFlowsSetupList->count)
|
||||||
memcpy(&qos_flow->qos, &sess->session.qos, sizeof(ogs_qos_t));
|
sess->h_smf_qos_flows_setup_list = qosFlowsSetupList;
|
||||||
|
else
|
||||||
|
OpenAPI_list_free(qosFlowsSetupList);
|
||||||
|
|
||||||
sessionAmbr = PduSessionCreatedData->session_ambr;
|
sessionAmbr = PduSessionCreatedData->session_ambr;
|
||||||
if (sessionAmbr) {
|
if (sessionAmbr) {
|
||||||
@@ -1977,7 +1929,7 @@ bool smf_nsmf_handle_create_data_in_vsmf(
|
|||||||
ogs_freeaddrinfo(addr);
|
ogs_freeaddrinfo(addr);
|
||||||
ogs_freeaddrinfo(addr6);
|
ogs_freeaddrinfo(addr6);
|
||||||
|
|
||||||
return OGS_ERROR;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
OGS_SBI_SETUP_CLIENT(&sess->pdu_session, client);
|
OGS_SBI_SETUP_CLIENT(&sess->pdu_session, client);
|
||||||
@@ -2055,7 +2007,7 @@ bool smf_nsmf_handle_create_data_in_vsmf(
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool smf_nsmf_handle_hsmf_update_data(
|
bool smf_nsmf_handle_update_data_in_hsmf(
|
||||||
smf_sess_t *sess, ogs_sbi_stream_t *stream, ogs_sbi_message_t *message)
|
smf_sess_t *sess, ogs_sbi_stream_t *stream, ogs_sbi_message_t *message)
|
||||||
{
|
{
|
||||||
int rv;
|
int rv;
|
||||||
@@ -2159,7 +2111,7 @@ bool smf_nsmf_handle_hsmf_update_data(
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool smf_nsmf_handle_vsmf_update_data(
|
bool smf_nsmf_handle_update_data_in_vsmf(
|
||||||
smf_sess_t *sess, ogs_sbi_stream_t *stream, ogs_sbi_message_t *message)
|
smf_sess_t *sess, ogs_sbi_stream_t *stream, ogs_sbi_message_t *message)
|
||||||
{
|
{
|
||||||
int rv;
|
int rv;
|
||||||
@@ -2167,10 +2119,16 @@ bool smf_nsmf_handle_vsmf_update_data(
|
|||||||
|
|
||||||
OpenAPI_vsmf_update_data_t *VsmfUpdateData = NULL;
|
OpenAPI_vsmf_update_data_t *VsmfUpdateData = NULL;
|
||||||
|
|
||||||
|
OpenAPI_list_t *qosFlowsAddModRequestList = NULL;
|
||||||
|
OpenAPI_qos_flow_profile_t *qosFlowProfile = NULL;
|
||||||
|
OpenAPI_lnode_t *node = NULL;
|
||||||
|
|
||||||
ogs_nas_5gs_message_t nas_message;
|
ogs_nas_5gs_message_t nas_message;
|
||||||
ogs_pkbuf_t *n1SmBufToUe = NULL;
|
ogs_pkbuf_t *n1SmBufToUe = NULL;
|
||||||
OpenAPI_ref_to_binary_data_t *n1SmInfoToUe = NULL;
|
OpenAPI_ref_to_binary_data_t *n1SmInfoToUe = NULL;
|
||||||
|
|
||||||
|
smf_n1_n2_message_transfer_param_t param;
|
||||||
|
|
||||||
ogs_assert(stream);
|
ogs_assert(stream);
|
||||||
ogs_assert(message);
|
ogs_assert(message);
|
||||||
ogs_assert(sess);
|
ogs_assert(sess);
|
||||||
@@ -2223,6 +2181,101 @@ bool smf_nsmf_handle_vsmf_update_data(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
switch (sess->nsmf_param.request_indication) {
|
||||||
|
case OpenAPI_request_indication_UE_REQ_PDU_SES_MOD:
|
||||||
|
case OpenAPI_request_indication_NW_REQ_PDU_SES_MOD:
|
||||||
|
CLEAR_QOS_FLOWS_ADD_MOD_REQUEST_LIST(
|
||||||
|
sess->h_smf_qos_flows_add_mod_request_list);
|
||||||
|
|
||||||
|
qosFlowsAddModRequestList = OpenAPI_list_create();
|
||||||
|
ogs_assert(qosFlowsAddModRequestList);
|
||||||
|
OpenAPI_list_for_each(
|
||||||
|
VsmfUpdateData->qos_flows_add_mod_request_list, node) {
|
||||||
|
OpenAPI_qos_flow_add_modify_request_item_t *dst = NULL, *src = NULL;
|
||||||
|
|
||||||
|
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]",
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
qosFlowProfile = src->qos_flow_profile;
|
||||||
|
if (!qosFlowProfile ||
|
||||||
|
!qosFlowProfile->_5qi ||
|
||||||
|
!qosFlowProfile->arp ||
|
||||||
|
!qosFlowProfile->arp->priority_level ||
|
||||||
|
!(qosFlowProfile->arp->preempt_cap ==
|
||||||
|
OpenAPI_preemption_capability_NOT_PREEMPT ||
|
||||||
|
qosFlowProfile->arp->preempt_cap ==
|
||||||
|
OpenAPI_preemption_capability_MAY_PREEMPT) ||
|
||||||
|
!(qosFlowProfile->arp->preempt_vuln ==
|
||||||
|
OpenAPI_preemption_vulnerability_NOT_PREEMPTABLE ||
|
||||||
|
qosFlowProfile->arp->preempt_vuln ==
|
||||||
|
OpenAPI_preemption_vulnerability_PREEMPTABLE)) {
|
||||||
|
ogs_error("[%s:%d] Invalid qosFlowProfile [%d:%p:%d]",
|
||||||
|
smf_ue->supi, sess->psi,
|
||||||
|
qosFlowProfile->_5qi,
|
||||||
|
qosFlowProfile->arp,
|
||||||
|
qosFlowProfile->arp ?
|
||||||
|
qosFlowProfile->arp->priority_level : 0);
|
||||||
|
smf_sbi_send_vsmf_update_error(stream,
|
||||||
|
OGS_SBI_HTTP_STATUS_BAD_REQUEST, OGS_SBI_APP_ERRNO_NULL,
|
||||||
|
OGS_5GSM_CAUSE_INVALID_MANDATORY_INFORMATION,
|
||||||
|
"Invalid qosFlowProfile", smf_ue->supi, NULL);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
dst = OpenAPI_qos_flow_add_modify_request_item_copy(dst, src);
|
||||||
|
ogs_assert(dst);
|
||||||
|
OpenAPI_list_add(qosFlowsAddModRequestList, dst);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (qosFlowsAddModRequestList->count)
|
||||||
|
sess->h_smf_qos_flows_add_mod_request_list =
|
||||||
|
qosFlowsAddModRequestList;
|
||||||
|
else
|
||||||
|
OpenAPI_list_free(qosFlowsAddModRequestList);
|
||||||
|
|
||||||
|
sess->pti = OGS_NAS_PROCEDURE_TRANSACTION_IDENTITY_UNASSIGNED;
|
||||||
|
|
||||||
|
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);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case OpenAPI_request_indication_UE_REQ_PDU_SES_REL:
|
||||||
|
case OpenAPI_request_indication_NW_REQ_PDU_SES_REL:
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
ogs_error("[%s:%d] Unknown requestIndication [%d]",
|
||||||
|
smf_ue->supi, sess->psi, sess->nsmf_param.request_indication);
|
||||||
|
smf_sbi_send_vsmf_update_error(stream,
|
||||||
|
OGS_SBI_HTTP_STATUS_BAD_REQUEST, OGS_SBI_APP_ERRNO_NULL,
|
||||||
|
OGS_5GSM_CAUSE_INVALID_MANDATORY_INFORMATION,
|
||||||
|
"Unknown requestIndication", smf_ue->supi, NULL);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -35,12 +35,12 @@ bool smf_nsmf_handle_release_sm_context(
|
|||||||
|
|
||||||
bool smf_nsmf_handle_create_data_in_hsmf(
|
bool smf_nsmf_handle_create_data_in_hsmf(
|
||||||
smf_sess_t *sess, ogs_sbi_stream_t *stream, ogs_sbi_message_t *recvmsg);
|
smf_sess_t *sess, ogs_sbi_stream_t *stream, ogs_sbi_message_t *recvmsg);
|
||||||
bool smf_nsmf_handle_create_data_in_vsmf(
|
bool smf_nsmf_handle_created_data_in_vsmf(
|
||||||
smf_sess_t *sess, ogs_sbi_message_t *recvmsg);
|
smf_sess_t *sess, ogs_sbi_message_t *recvmsg);
|
||||||
|
|
||||||
bool smf_nsmf_handle_hsmf_update_data(
|
bool smf_nsmf_handle_update_data_in_hsmf(
|
||||||
smf_sess_t *sess, ogs_sbi_stream_t *stream, ogs_sbi_message_t *message);
|
smf_sess_t *sess, ogs_sbi_stream_t *stream, ogs_sbi_message_t *message);
|
||||||
bool smf_nsmf_handle_vsmf_update_data(
|
bool smf_nsmf_handle_update_data_in_vsmf(
|
||||||
smf_sess_t *sess, ogs_sbi_stream_t *stream, ogs_sbi_message_t *message);
|
smf_sess_t *sess, ogs_sbi_stream_t *stream, ogs_sbi_message_t *message);
|
||||||
|
|
||||||
bool smf_nsmf_handle_release_data_in_hsmf(
|
bool smf_nsmf_handle_release_data_in_hsmf(
|
||||||
|
|||||||
@@ -398,9 +398,8 @@ void smf_sbi_send_pdu_session_created_data(
|
|||||||
OpenAPI_ambr_t sessionAmbr;
|
OpenAPI_ambr_t sessionAmbr;
|
||||||
OpenAPI_list_t *qosFlowsSetupList = NULL;
|
OpenAPI_list_t *qosFlowsSetupList = NULL;
|
||||||
OpenAPI_qos_flow_setup_item_t *qosFlowSetupItem = NULL;
|
OpenAPI_qos_flow_setup_item_t *qosFlowSetupItem = NULL;
|
||||||
OpenAPI_qos_flow_profile_t qosFlowProfile;
|
OpenAPI_qos_flow_profile_t *qosFlowProfile = NULL;
|
||||||
OpenAPI_arp_t Arp;
|
OpenAPI_arp_t *Arp = NULL;
|
||||||
OpenAPI_lnode_t *node = NULL;
|
|
||||||
|
|
||||||
ogs_nas_qos_rule_t qos_rule[OGS_NAS_MAX_NUM_OF_QOS_RULE];
|
ogs_nas_qos_rule_t qos_rule[OGS_NAS_MAX_NUM_OF_QOS_RULE];
|
||||||
ogs_nas_qos_rules_t authorized_qos_rules;
|
ogs_nas_qos_rules_t authorized_qos_rules;
|
||||||
@@ -472,7 +471,7 @@ void smf_sbi_send_pdu_session_created_data(
|
|||||||
ogs_assert(ogs_list_next(qos_flow) == NULL);
|
ogs_assert(ogs_list_next(qos_flow) == NULL);
|
||||||
|
|
||||||
memset(qos_rule, 0, sizeof(qos_rule));
|
memset(qos_rule, 0, sizeof(qos_rule));
|
||||||
encode_default_qos_rule(&qos_rule[0], qos_flow);
|
gsm_encode_default_qos_rule(&qos_rule[0], qos_flow);
|
||||||
|
|
||||||
memset(&authorized_qos_rules, 0, sizeof(authorized_qos_rules));
|
memset(&authorized_qos_rules, 0, sizeof(authorized_qos_rules));
|
||||||
rv = ogs_nas_build_qos_rules(&authorized_qos_rules, qos_rule, 1);
|
rv = ogs_nas_build_qos_rules(&authorized_qos_rules, qos_rule, 1);
|
||||||
@@ -481,8 +480,7 @@ void smf_sbi_send_pdu_session_created_data(
|
|||||||
|
|
||||||
/* QoS flow descriptions */
|
/* QoS flow descriptions */
|
||||||
memset(&qos_flow_description, 0, sizeof(qos_flow_description));
|
memset(&qos_flow_description, 0, sizeof(qos_flow_description));
|
||||||
encode_default_qos_flow_description(&qos_flow_description[0],
|
gsm_encode_default_qos_flow_description(&qos_flow_description[0], qos_flow);
|
||||||
qos_flow);
|
|
||||||
|
|
||||||
memset(&authorized_qos_flow_descriptions, 0,
|
memset(&authorized_qos_flow_descriptions, 0,
|
||||||
sizeof(authorized_qos_flow_descriptions));
|
sizeof(authorized_qos_flow_descriptions));
|
||||||
@@ -521,35 +519,37 @@ void smf_sbi_send_pdu_session_created_data(
|
|||||||
|
|
||||||
ogs_free(authorized_qos_flow_descriptions.buffer);
|
ogs_free(authorized_qos_flow_descriptions.buffer);
|
||||||
|
|
||||||
memset(&Arp, 0, sizeof(Arp));
|
Arp = ogs_calloc(1, sizeof(*Arp));
|
||||||
|
ogs_assert(Arp);
|
||||||
if (qos_flow->qos.arp.pre_emption_capability ==
|
if (qos_flow->qos.arp.pre_emption_capability ==
|
||||||
OGS_5GC_PRE_EMPTION_ENABLED)
|
OGS_5GC_PRE_EMPTION_ENABLED)
|
||||||
Arp.preempt_cap = OpenAPI_preemption_capability_MAY_PREEMPT;
|
Arp->preempt_cap = OpenAPI_preemption_capability_MAY_PREEMPT;
|
||||||
else if (qos_flow->qos.arp.pre_emption_capability ==
|
else if (qos_flow->qos.arp.pre_emption_capability ==
|
||||||
OGS_5GC_PRE_EMPTION_DISABLED)
|
OGS_5GC_PRE_EMPTION_DISABLED)
|
||||||
Arp.preempt_cap = OpenAPI_preemption_capability_NOT_PREEMPT;
|
Arp->preempt_cap = OpenAPI_preemption_capability_NOT_PREEMPT;
|
||||||
else {
|
else {
|
||||||
ogs_fatal("No Arp.preempt_cap");
|
ogs_error("No Arp->preempt_cap");
|
||||||
ogs_assert_if_reached();
|
goto end;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (qos_flow->qos.arp.pre_emption_vulnerability ==
|
if (qos_flow->qos.arp.pre_emption_vulnerability ==
|
||||||
OGS_5GC_PRE_EMPTION_ENABLED)
|
OGS_5GC_PRE_EMPTION_ENABLED)
|
||||||
Arp.preempt_vuln = OpenAPI_preemption_vulnerability_PREEMPTABLE;
|
Arp->preempt_vuln = OpenAPI_preemption_vulnerability_PREEMPTABLE;
|
||||||
else if (qos_flow->qos.arp.pre_emption_vulnerability ==
|
else if (qos_flow->qos.arp.pre_emption_vulnerability ==
|
||||||
OGS_5GC_PRE_EMPTION_DISABLED)
|
OGS_5GC_PRE_EMPTION_DISABLED)
|
||||||
Arp.preempt_vuln = OpenAPI_preemption_vulnerability_NOT_PREEMPTABLE;
|
Arp->preempt_vuln = OpenAPI_preemption_vulnerability_NOT_PREEMPTABLE;
|
||||||
else {
|
else {
|
||||||
ogs_fatal("No Arp.preempt_vuln");
|
ogs_error("No Arp->preempt_vuln");
|
||||||
ogs_assert_if_reached();
|
goto end;
|
||||||
}
|
}
|
||||||
Arp.priority_level = qos_flow->qos.arp.priority_level;
|
Arp->priority_level = qos_flow->qos.arp.priority_level;
|
||||||
|
|
||||||
memset(&qosFlowProfile, 0, sizeof(qosFlowProfile));
|
qosFlowProfile = ogs_calloc(1, sizeof(*qosFlowProfile));
|
||||||
qosFlowProfile.arp = &Arp;
|
ogs_assert(qosFlowProfile);
|
||||||
qosFlowProfile._5qi = qos_flow->qos.index;
|
qosFlowProfile->arp = Arp;
|
||||||
|
qosFlowProfile->_5qi = qos_flow->qos.index;
|
||||||
|
|
||||||
qosFlowSetupItem->qos_flow_profile = &qosFlowProfile;
|
qosFlowSetupItem->qos_flow_profile = qosFlowProfile;
|
||||||
|
|
||||||
OpenAPI_list_add(qosFlowsSetupList, qosFlowSetupItem);
|
OpenAPI_list_add(qosFlowsSetupList, qosFlowSetupItem);
|
||||||
|
|
||||||
@@ -585,9 +585,9 @@ void smf_sbi_send_pdu_session_created_data(
|
|||||||
ue_ipv6_interface_id, sizeof(ue_ipv6_interface_id));
|
ue_ipv6_interface_id, sizeof(ue_ipv6_interface_id));
|
||||||
PduSessionCreatedData.ue_ipv6_interface_id = ue_ipv6_interface_id;
|
PduSessionCreatedData.ue_ipv6_interface_id = ue_ipv6_interface_id;
|
||||||
} else {
|
} else {
|
||||||
ogs_fatal("Invalid sess->session.session_type[%d]",
|
ogs_error("Invalid sess->session.session_type[%d]",
|
||||||
sess->paa.session_type);
|
sess->paa.session_type);
|
||||||
ogs_assert_if_reached();
|
goto end;
|
||||||
}
|
}
|
||||||
|
|
||||||
memset(&sendmsg, 0, sizeof(sendmsg));
|
memset(&sendmsg, 0, sizeof(sendmsg));
|
||||||
@@ -627,6 +627,7 @@ void smf_sbi_send_pdu_session_created_data(
|
|||||||
|
|
||||||
ogs_free(sendmsg.http.location);
|
ogs_free(sendmsg.http.location);
|
||||||
|
|
||||||
|
end:
|
||||||
if (hcnTunnelInfo.ipv4_addr)
|
if (hcnTunnelInfo.ipv4_addr)
|
||||||
ogs_free(hcnTunnelInfo.ipv4_addr);
|
ogs_free(hcnTunnelInfo.ipv4_addr);
|
||||||
if (hcnTunnelInfo.ipv6_addr)
|
if (hcnTunnelInfo.ipv6_addr)
|
||||||
@@ -639,18 +640,7 @@ void smf_sbi_send_pdu_session_created_data(
|
|||||||
if (sessionAmbr.downlink)
|
if (sessionAmbr.downlink)
|
||||||
ogs_free(sessionAmbr.downlink);
|
ogs_free(sessionAmbr.downlink);
|
||||||
|
|
||||||
OpenAPI_list_for_each(
|
CLEAR_QOS_FLOWS_SETUP_LIST(PduSessionCreatedData.qos_flows_setup_list);
|
||||||
PduSessionCreatedData.qos_flows_setup_list, node) {
|
|
||||||
qosFlowSetupItem = node->data;
|
|
||||||
if (qosFlowSetupItem) {
|
|
||||||
if (qosFlowSetupItem->qos_rules)
|
|
||||||
ogs_free(qosFlowSetupItem->qos_rules);
|
|
||||||
if (qosFlowSetupItem->qos_flow_description)
|
|
||||||
ogs_free(qosFlowSetupItem->qos_flow_description);
|
|
||||||
ogs_free(qosFlowSetupItem);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
OpenAPI_list_free(PduSessionCreatedData.qos_flows_setup_list);
|
|
||||||
|
|
||||||
if (PduSessionCreatedData.ue_ipv4_address)
|
if (PduSessionCreatedData.ue_ipv4_address)
|
||||||
ogs_free(PduSessionCreatedData.ue_ipv4_address);
|
ogs_free(PduSessionCreatedData.ue_ipv4_address);
|
||||||
|
|||||||
@@ -31,6 +31,7 @@
|
|||||||
#include "nsmf-handler.h"
|
#include "nsmf-handler.h"
|
||||||
#include "npcf-handler.h"
|
#include "npcf-handler.h"
|
||||||
#include "nsmf-handler.h"
|
#include "nsmf-handler.h"
|
||||||
|
#include "binding.h"
|
||||||
|
|
||||||
void smf_state_initial(ogs_fsm_t *s, smf_event_t *e)
|
void smf_state_initial(ogs_fsm_t *s, smf_event_t *e)
|
||||||
{
|
{
|
||||||
@@ -1048,14 +1049,29 @@ void smf_state_operational(ogs_fsm_t *s, smf_event_t *e)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (state == SMF_UECM_STATE_REGISTERED) {
|
if (state == SMF_UECM_STATE_REGISTERED) {
|
||||||
/* SMF Registration */
|
|
||||||
ogs_assert(stream);
|
ogs_assert(stream);
|
||||||
ogs_assert(true == ogs_sbi_send_http_status_no_content(stream));
|
ogs_assert(true == ogs_sbi_send_http_status_no_content(stream));
|
||||||
|
smf_metrics_inst_by_slice_add(
|
||||||
|
&sess->serving_plmn_id, &sess->s_nssai,
|
||||||
|
SMF_METR_CTR_SM_PDUSESSIONCREATIONSUCC, 1);
|
||||||
} else if (state == SMF_UECM_STATE_REGISTERED_HR) {
|
} else if (state == SMF_UECM_STATE_REGISTERED_HR) {
|
||||||
|
ogs_assert(stream);
|
||||||
smf_sbi_send_pdu_session_created_data(sess, stream);
|
smf_sbi_send_pdu_session_created_data(sess, stream);
|
||||||
smf_metrics_inst_by_slice_add(
|
smf_metrics_inst_by_slice_add(
|
||||||
&sess->serving_plmn_id, &sess->s_nssai,
|
&sess->serving_plmn_id, &sess->s_nssai,
|
||||||
SMF_METR_CTR_SM_PDUSESSIONCREATIONSUCC, 1);
|
SMF_METR_CTR_SM_PDUSESSIONCREATIONSUCC, 1);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Non-roaming/LBO: start network-triggered PDU Session Modification at step 11
|
||||||
|
* after N1N2 transfer (Establishment Accept) and N2/N4 context sync, ensuring
|
||||||
|
* the session is active on UE, RAN, and SMF before applying QoS updates.
|
||||||
|
*
|
||||||
|
* Home-Routed Roaming: trigger PDU Session Modification at step 13
|
||||||
|
* immediately after H-SMF’s CreateSMContext response and H-UPF N4 setup
|
||||||
|
* to apply QoS updates without waiting for V-SMF or RAN setup.
|
||||||
|
*/
|
||||||
|
smf_qos_flow_binding(sess);
|
||||||
|
|
||||||
} else if (state == SMF_UECM_STATE_DEREG_BY_AMF) {
|
} else if (state == SMF_UECM_STATE_DEREG_BY_AMF) {
|
||||||
/*
|
/*
|
||||||
* Handle deregistration states SMF_UECM_STATE_DEREG_BY_AMF and
|
* Handle deregistration states SMF_UECM_STATE_DEREG_BY_AMF and
|
||||||
|
|||||||
@@ -1709,6 +1709,11 @@ bson_t *test_db_new_qos_flow(test_ue_t *test_ue)
|
|||||||
"description", BCON_UTF8("permit out udp from 10.200.136.98/32 1-65535 to assigned 50021"), "}",
|
"description", BCON_UTF8("permit out udp from 10.200.136.98/32 1-65535 to assigned 50021"), "}",
|
||||||
"]",
|
"]",
|
||||||
"}", "]",
|
"}", "]",
|
||||||
|
#if 0
|
||||||
|
"lbo_roaming_allowed", BCON_BOOL(true),
|
||||||
|
#else
|
||||||
|
"lbo_roaming_allowed", BCON_BOOL(false),
|
||||||
|
#endif
|
||||||
"}", "]",
|
"}", "]",
|
||||||
"}", "]",
|
"}", "]",
|
||||||
"security", "{",
|
"security", "{",
|
||||||
@@ -1810,6 +1815,11 @@ bson_t *test_db_new_qos_flow_bi_directional(test_ue_t *test_ue)
|
|||||||
"description", BCON_UTF8("permit out udp from 10.200.136.98/32 23455 to assigned 1-65535"), "}",
|
"description", BCON_UTF8("permit out udp from 10.200.136.98/32 23455 to assigned 1-65535"), "}",
|
||||||
"]",
|
"]",
|
||||||
"}", "]",
|
"}", "]",
|
||||||
|
#if 0
|
||||||
|
"lbo_roaming_allowed", BCON_BOOL(true),
|
||||||
|
#else
|
||||||
|
"lbo_roaming_allowed", BCON_BOOL(false),
|
||||||
|
#endif
|
||||||
"}", "]",
|
"}", "]",
|
||||||
"}", "]",
|
"}", "]",
|
||||||
"security", "{",
|
"security", "{",
|
||||||
@@ -1876,6 +1886,11 @@ bson_t *test_db_new_session(test_ue_t *test_ue)
|
|||||||
"pre_emption_capability", BCON_INT32(1),
|
"pre_emption_capability", BCON_INT32(1),
|
||||||
"}",
|
"}",
|
||||||
"}",
|
"}",
|
||||||
|
#if 1
|
||||||
|
"lbo_roaming_allowed", BCON_BOOL(true),
|
||||||
|
#else
|
||||||
|
"lbo_roaming_allowed", BCON_BOOL(false),
|
||||||
|
#endif
|
||||||
"}",
|
"}",
|
||||||
"{",
|
"{",
|
||||||
"name", BCON_UTF8("ims"),
|
"name", BCON_UTF8("ims"),
|
||||||
@@ -1938,6 +1953,11 @@ 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"), "}",
|
"description", BCON_UTF8("permit out udp from 10.200.136.98/32 1-65535 to assigned 50021"), "}",
|
||||||
"]",
|
"]",
|
||||||
"}", "]",
|
"}", "]",
|
||||||
|
#if 1
|
||||||
|
"lbo_roaming_allowed", BCON_BOOL(true),
|
||||||
|
#else
|
||||||
|
"lbo_roaming_allowed", BCON_BOOL(false),
|
||||||
|
#endif
|
||||||
"}",
|
"}",
|
||||||
"]",
|
"]",
|
||||||
"}", "]",
|
"}", "]",
|
||||||
@@ -2162,6 +2182,11 @@ bson_t *test_db_new_slice_with_same_dnn(test_ue_t *test_ue)
|
|||||||
"pre_emption_capability", BCON_INT32(1),
|
"pre_emption_capability", BCON_INT32(1),
|
||||||
"}",
|
"}",
|
||||||
"}",
|
"}",
|
||||||
|
#if 1
|
||||||
|
"lbo_roaming_allowed", BCON_BOOL(true),
|
||||||
|
#else
|
||||||
|
"lbo_roaming_allowed", BCON_BOOL(false),
|
||||||
|
#endif
|
||||||
"}",
|
"}",
|
||||||
"{",
|
"{",
|
||||||
"name", BCON_UTF8("ims"),
|
"name", BCON_UTF8("ims"),
|
||||||
@@ -2246,6 +2271,11 @@ bson_t *test_db_new_slice_with_same_dnn(test_ue_t *test_ue)
|
|||||||
"}",
|
"}",
|
||||||
"}",
|
"}",
|
||||||
"]",
|
"]",
|
||||||
|
#if 1
|
||||||
|
"lbo_roaming_allowed", BCON_BOOL(true),
|
||||||
|
#else
|
||||||
|
"lbo_roaming_allowed", BCON_BOOL(false),
|
||||||
|
#endif
|
||||||
"}",
|
"}",
|
||||||
"]",
|
"]",
|
||||||
"}",
|
"}",
|
||||||
@@ -2274,6 +2304,11 @@ bson_t *test_db_new_slice_with_same_dnn(test_ue_t *test_ue)
|
|||||||
"pre_emption_capability", BCON_INT32(1),
|
"pre_emption_capability", BCON_INT32(1),
|
||||||
"}",
|
"}",
|
||||||
"}",
|
"}",
|
||||||
|
#if 1
|
||||||
|
"lbo_roaming_allowed", BCON_BOOL(true),
|
||||||
|
#else
|
||||||
|
"lbo_roaming_allowed", BCON_BOOL(false),
|
||||||
|
#endif
|
||||||
"}",
|
"}",
|
||||||
"{",
|
"{",
|
||||||
"name", BCON_UTF8("ims"),
|
"name", BCON_UTF8("ims"),
|
||||||
@@ -2358,6 +2393,11 @@ bson_t *test_db_new_slice_with_same_dnn(test_ue_t *test_ue)
|
|||||||
"}",
|
"}",
|
||||||
"}",
|
"}",
|
||||||
"]",
|
"]",
|
||||||
|
#if 1
|
||||||
|
"lbo_roaming_allowed", BCON_BOOL(true),
|
||||||
|
#else
|
||||||
|
"lbo_roaming_allowed", BCON_BOOL(false),
|
||||||
|
#endif
|
||||||
"}",
|
"}",
|
||||||
"]",
|
"]",
|
||||||
"}",
|
"}",
|
||||||
@@ -2387,6 +2427,11 @@ bson_t *test_db_new_slice_with_same_dnn(test_ue_t *test_ue)
|
|||||||
"pre_emption_capability", BCON_INT32(1),
|
"pre_emption_capability", BCON_INT32(1),
|
||||||
"}",
|
"}",
|
||||||
"}",
|
"}",
|
||||||
|
#if 1
|
||||||
|
"lbo_roaming_allowed", BCON_BOOL(true),
|
||||||
|
#else
|
||||||
|
"lbo_roaming_allowed", BCON_BOOL(false),
|
||||||
|
#endif
|
||||||
"}",
|
"}",
|
||||||
"{",
|
"{",
|
||||||
"name", BCON_UTF8("ims"),
|
"name", BCON_UTF8("ims"),
|
||||||
@@ -2471,6 +2516,11 @@ bson_t *test_db_new_slice_with_same_dnn(test_ue_t *test_ue)
|
|||||||
"}",
|
"}",
|
||||||
"}",
|
"}",
|
||||||
"]",
|
"]",
|
||||||
|
#if 1
|
||||||
|
"lbo_roaming_allowed", BCON_BOOL(true),
|
||||||
|
#else
|
||||||
|
"lbo_roaming_allowed", BCON_BOOL(false),
|
||||||
|
#endif
|
||||||
"}",
|
"}",
|
||||||
"]",
|
"]",
|
||||||
"}",
|
"}",
|
||||||
@@ -2540,6 +2590,11 @@ bson_t *test_db_new_slice_with_different_dnn(test_ue_t *test_ue)
|
|||||||
"pre_emption_capability", BCON_INT32(1),
|
"pre_emption_capability", BCON_INT32(1),
|
||||||
"}",
|
"}",
|
||||||
"}",
|
"}",
|
||||||
|
#if 1
|
||||||
|
"lbo_roaming_allowed", BCON_BOOL(true),
|
||||||
|
#else
|
||||||
|
"lbo_roaming_allowed", BCON_BOOL(false),
|
||||||
|
#endif
|
||||||
"}",
|
"}",
|
||||||
"{",
|
"{",
|
||||||
"name", BCON_UTF8("ims"),
|
"name", BCON_UTF8("ims"),
|
||||||
@@ -2624,6 +2679,11 @@ bson_t *test_db_new_slice_with_different_dnn(test_ue_t *test_ue)
|
|||||||
"}",
|
"}",
|
||||||
"}",
|
"}",
|
||||||
"]",
|
"]",
|
||||||
|
#if 1
|
||||||
|
"lbo_roaming_allowed", BCON_BOOL(true),
|
||||||
|
#else
|
||||||
|
"lbo_roaming_allowed", BCON_BOOL(false),
|
||||||
|
#endif
|
||||||
"}",
|
"}",
|
||||||
"]",
|
"]",
|
||||||
"}",
|
"}",
|
||||||
@@ -2652,6 +2712,11 @@ bson_t *test_db_new_slice_with_different_dnn(test_ue_t *test_ue)
|
|||||||
"pre_emption_capability", BCON_INT32(1),
|
"pre_emption_capability", BCON_INT32(1),
|
||||||
"}",
|
"}",
|
||||||
"}",
|
"}",
|
||||||
|
#if 1
|
||||||
|
"lbo_roaming_allowed", BCON_BOOL(true),
|
||||||
|
#else
|
||||||
|
"lbo_roaming_allowed", BCON_BOOL(false),
|
||||||
|
#endif
|
||||||
"}",
|
"}",
|
||||||
"{",
|
"{",
|
||||||
"name", BCON_UTF8("ims2"),
|
"name", BCON_UTF8("ims2"),
|
||||||
@@ -2736,6 +2801,11 @@ bson_t *test_db_new_slice_with_different_dnn(test_ue_t *test_ue)
|
|||||||
"}",
|
"}",
|
||||||
"}",
|
"}",
|
||||||
"]",
|
"]",
|
||||||
|
#if 1
|
||||||
|
"lbo_roaming_allowed", BCON_BOOL(true),
|
||||||
|
#else
|
||||||
|
"lbo_roaming_allowed", BCON_BOOL(false),
|
||||||
|
#endif
|
||||||
"}",
|
"}",
|
||||||
"]",
|
"]",
|
||||||
"}",
|
"}",
|
||||||
@@ -2765,6 +2835,11 @@ bson_t *test_db_new_slice_with_different_dnn(test_ue_t *test_ue)
|
|||||||
"pre_emption_capability", BCON_INT32(1),
|
"pre_emption_capability", BCON_INT32(1),
|
||||||
"}",
|
"}",
|
||||||
"}",
|
"}",
|
||||||
|
#if 1
|
||||||
|
"lbo_roaming_allowed", BCON_BOOL(true),
|
||||||
|
#else
|
||||||
|
"lbo_roaming_allowed", BCON_BOOL(false),
|
||||||
|
#endif
|
||||||
"}",
|
"}",
|
||||||
"{",
|
"{",
|
||||||
"name", BCON_UTF8("ims3"),
|
"name", BCON_UTF8("ims3"),
|
||||||
@@ -2849,6 +2924,11 @@ bson_t *test_db_new_slice_with_different_dnn(test_ue_t *test_ue)
|
|||||||
"}",
|
"}",
|
||||||
"}",
|
"}",
|
||||||
"]",
|
"]",
|
||||||
|
#if 1
|
||||||
|
"lbo_roaming_allowed", BCON_BOOL(true),
|
||||||
|
#else
|
||||||
|
"lbo_roaming_allowed", BCON_BOOL(false),
|
||||||
|
#endif
|
||||||
"}",
|
"}",
|
||||||
"]",
|
"]",
|
||||||
"}",
|
"}",
|
||||||
@@ -2921,6 +3001,11 @@ bson_t *test_db_new_non3gpp(test_ue_t *test_ue)
|
|||||||
"addr", BCON_UTF8("127.0.0.4"),
|
"addr", BCON_UTF8("127.0.0.4"),
|
||||||
"addr6", BCON_UTF8("::1"),
|
"addr6", BCON_UTF8("::1"),
|
||||||
"}",
|
"}",
|
||||||
|
#if 1
|
||||||
|
"lbo_roaming_allowed", BCON_BOOL(true),
|
||||||
|
#else
|
||||||
|
"lbo_roaming_allowed", BCON_BOOL(false),
|
||||||
|
#endif
|
||||||
"}",
|
"}",
|
||||||
"{",
|
"{",
|
||||||
"name", BCON_UTF8("wlan"),
|
"name", BCON_UTF8("wlan"),
|
||||||
@@ -3005,6 +3090,11 @@ bson_t *test_db_new_non3gpp(test_ue_t *test_ue)
|
|||||||
"}",
|
"}",
|
||||||
"}",
|
"}",
|
||||||
"]",
|
"]",
|
||||||
|
#if 1
|
||||||
|
"lbo_roaming_allowed", BCON_BOOL(true),
|
||||||
|
#else
|
||||||
|
"lbo_roaming_allowed", BCON_BOOL(false),
|
||||||
|
#endif
|
||||||
"}",
|
"}",
|
||||||
"]",
|
"]",
|
||||||
"}", "]",
|
"}", "]",
|
||||||
|
|||||||
Reference in New Issue
Block a user