forked from acouzens/open5gs
[PGW] Gy+PFCP improvements (#1555)
* [SMF] Gy,PFCP: Improve {Time,Volume} {Threshold,Quota} handling * [UPF] Implement URR Usage Report for ValidityTime/TimeQuota/TimeThreshold * [UPF] Implement Usage report trigger for Volume Quota/Threshold * [SMF] Set Gy Reporting-Reason based on PFCP Report Trigger
This commit is contained in:
parent
2c2ce143a3
commit
c18e9f32cb
|
@ -44,6 +44,8 @@ extern "C" {
|
||||||
#define OGS_DIAM_GY_AVP_CODE_VALIDITY_TIME (448)
|
#define OGS_DIAM_GY_AVP_CODE_VALIDITY_TIME (448)
|
||||||
#define OGS_DIAM_GY_AVP_CODE_MULTIPLE_SERVICES_CREDIT_CONTROL (456)
|
#define OGS_DIAM_GY_AVP_CODE_MULTIPLE_SERVICES_CREDIT_CONTROL (456)
|
||||||
#define OGS_DIAM_GY_AVP_CODE_SUPPORTED_FEATURES (628)
|
#define OGS_DIAM_GY_AVP_CODE_SUPPORTED_FEATURES (628)
|
||||||
|
#define OGS_DIAM_GY_AVP_CODE_TIME_QUOTA_THRESHOLD (868)
|
||||||
|
#define OGS_DIAM_GY_AVP_CODE_VOLUME_QUOTA_THRESHOLD (869)
|
||||||
#define OGS_DIAM_GY_AVP_CODE_CHARGING_RULE_BASE_NAME (1004)
|
#define OGS_DIAM_GY_AVP_CODE_CHARGING_RULE_BASE_NAME (1004)
|
||||||
#define OGS_DIAM_GY_AVP_CODE_FLOW_INFORMATION (1058)
|
#define OGS_DIAM_GY_AVP_CODE_FLOW_INFORMATION (1058)
|
||||||
#define OGS_DIAM_GY_AVP_CODE_QOS_INFORMATION (1016)
|
#define OGS_DIAM_GY_AVP_CODE_QOS_INFORMATION (1016)
|
||||||
|
@ -182,6 +184,8 @@ typedef struct ogs_diam_gy_message_s {
|
||||||
union {
|
union {
|
||||||
struct {
|
struct {
|
||||||
uint32_t validity_time;
|
uint32_t validity_time;
|
||||||
|
uint32_t time_threshold;
|
||||||
|
uint32_t volume_threshold;
|
||||||
ogs_diam_gy_service_unit_t granted;
|
ogs_diam_gy_service_unit_t granted;
|
||||||
} cca;
|
} cca;
|
||||||
};
|
};
|
||||||
|
|
|
@ -654,7 +654,10 @@ void ogs_pfcp_build_update_urr(
|
||||||
/* No change requested, skip. */
|
/* No change requested, skip. */
|
||||||
if (!(modify_flags & (OGS_PFCP_MODIFY_URR_MEAS_METHOD|
|
if (!(modify_flags & (OGS_PFCP_MODIFY_URR_MEAS_METHOD|
|
||||||
OGS_PFCP_MODIFY_URR_REPORT_TRIGGER|
|
OGS_PFCP_MODIFY_URR_REPORT_TRIGGER|
|
||||||
|
OGS_PFCP_MODIFY_URR_QUOTA_VALIDITY_TIME|
|
||||||
|
OGS_PFCP_MODIFY_URR_VOLUME_QUOTA|
|
||||||
OGS_PFCP_MODIFY_URR_VOLUME_THRESH|
|
OGS_PFCP_MODIFY_URR_VOLUME_THRESH|
|
||||||
|
OGS_PFCP_MODIFY_URR_TIME_QUOTA|
|
||||||
OGS_PFCP_MODIFY_URR_TIME_THRESH)))
|
OGS_PFCP_MODIFY_URR_TIME_THRESH)))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
|
|
@ -449,6 +449,15 @@ int16_t ogs_pfcp_build_volume(ogs_tlv_octet_t *octet,
|
||||||
return octet->len;
|
return octet->len;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ogs_pfcp_parse_usage_report_trigger(
|
||||||
|
ogs_pfcp_usage_report_trigger_t *rep_trig,
|
||||||
|
ogs_pfcp_tlv_usage_report_trigger_t *tlv)
|
||||||
|
{
|
||||||
|
rep_trig->reptri_5 = (tlv->u24 >> 16) & 0xff;
|
||||||
|
rep_trig->reptri_6 = (tlv->u24 >> 8) & 0xff;
|
||||||
|
rep_trig->reptri_7 = (tlv->u24) & 0xff;
|
||||||
|
}
|
||||||
|
|
||||||
int16_t ogs_pfcp_parse_volume(
|
int16_t ogs_pfcp_parse_volume(
|
||||||
ogs_pfcp_volume_threshold_t *volume, ogs_tlv_octet_t *octet)
|
ogs_pfcp_volume_threshold_t *volume, ogs_tlv_octet_t *octet)
|
||||||
{
|
{
|
||||||
|
|
|
@ -1023,6 +1023,10 @@ ED6(uint8_t spare:3;,
|
||||||
};
|
};
|
||||||
} __attribute__ ((packed)) ogs_pfcp_usage_report_trigger_t;
|
} __attribute__ ((packed)) ogs_pfcp_usage_report_trigger_t;
|
||||||
|
|
||||||
|
void ogs_pfcp_parse_usage_report_trigger(
|
||||||
|
ogs_pfcp_usage_report_trigger_t *rep_trig,
|
||||||
|
ogs_pfcp_tlv_usage_report_trigger_t *tlv);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* 8.2.42 Measurement Period
|
* 8.2.42 Measurement Period
|
||||||
*
|
*
|
||||||
|
|
|
@ -102,8 +102,11 @@ typedef struct ogs_pfcp_xact_s {
|
||||||
#define OGS_PFCP_MODIFY_URR ((uint64_t)1<<24) /* type of trigger */
|
#define OGS_PFCP_MODIFY_URR ((uint64_t)1<<24) /* type of trigger */
|
||||||
#define OGS_PFCP_MODIFY_URR_MEAS_METHOD ((uint64_t)1<<25)
|
#define OGS_PFCP_MODIFY_URR_MEAS_METHOD ((uint64_t)1<<25)
|
||||||
#define OGS_PFCP_MODIFY_URR_REPORT_TRIGGER ((uint64_t)1<<26)
|
#define OGS_PFCP_MODIFY_URR_REPORT_TRIGGER ((uint64_t)1<<26)
|
||||||
#define OGS_PFCP_MODIFY_URR_VOLUME_THRESH ((uint64_t)1<<27)
|
#define OGS_PFCP_MODIFY_URR_QUOTA_VALIDITY_TIME ((uint64_t)1<<27)
|
||||||
#define OGS_PFCP_MODIFY_URR_TIME_THRESH ((uint64_t)1<<28)
|
#define OGS_PFCP_MODIFY_URR_VOLUME_QUOTA ((uint64_t)1<<28)
|
||||||
|
#define OGS_PFCP_MODIFY_URR_TIME_QUOTA ((uint64_t)1<<29)
|
||||||
|
#define OGS_PFCP_MODIFY_URR_VOLUME_THRESH ((uint64_t)1<<30)
|
||||||
|
#define OGS_PFCP_MODIFY_URR_TIME_THRESH ((uint64_t)1<<31)
|
||||||
|
|
||||||
uint64_t modify_flags;
|
uint64_t modify_flags;
|
||||||
|
|
||||||
|
|
|
@ -336,6 +336,7 @@ typedef struct smf_sess_s {
|
||||||
uint64_t ul_octets;
|
uint64_t ul_octets;
|
||||||
uint64_t dl_octets;
|
uint64_t dl_octets;
|
||||||
ogs_time_t duration;
|
ogs_time_t duration;
|
||||||
|
uint32_t reporting_reason; /* OGS_DIAM_GY_REPORTING_REASON_* */
|
||||||
/* Snapshot of measurement when last report was sent: */
|
/* Snapshot of measurement when last report was sent: */
|
||||||
struct {
|
struct {
|
||||||
uint64_t ul_octets;
|
uint64_t ul_octets;
|
||||||
|
|
|
@ -24,55 +24,90 @@
|
||||||
#include "gy-handler.h"
|
#include "gy-handler.h"
|
||||||
#include "binding.h"
|
#include "binding.h"
|
||||||
|
|
||||||
static void urr_enable_total_volume_threshold(smf_sess_t *sess, ogs_pfcp_urr_t *urr,
|
static void urr_update_volume(smf_sess_t *sess, ogs_pfcp_urr_t *urr, ogs_diam_gy_message_t *gy_message)
|
||||||
uint64_t total_volume_threshold)
|
|
||||||
{
|
{
|
||||||
ogs_debug("Adding CC Grant total_octets=%" PRIu64, total_volume_threshold);
|
if (gy_message->cca.granted.cc_total_octets_present || gy_message->cca.volume_threshold) {
|
||||||
urr->meas_method |= OGS_PFCP_MEASUREMENT_METHOD_VOLUME;
|
urr->meas_method |= OGS_PFCP_MEASUREMENT_METHOD_VOLUME;
|
||||||
urr->rep_triggers.volume_threshold = 1;
|
ogs_assert(sess->pfcp_node);
|
||||||
urr->vol_threshold.tovol = 1;
|
if (sess->pfcp_node->up_function_features.mnop)
|
||||||
urr->vol_threshold.total_volume = total_volume_threshold;
|
urr->meas_info.mnop = 1;
|
||||||
ogs_assert(sess->pfcp_node);
|
} else {
|
||||||
if (sess->pfcp_node->up_function_features.mnop)
|
urr->meas_method &= ~OGS_PFCP_MEASUREMENT_METHOD_VOLUME;
|
||||||
urr->meas_info.mnop = 1;
|
}
|
||||||
|
|
||||||
|
/* Volume Quota */
|
||||||
|
if (gy_message->cca.granted.cc_total_octets_present) {
|
||||||
|
ogs_debug("Adding Volume Quota total_octets=%" PRIu64, gy_message->cca.granted.cc_total_octets);
|
||||||
|
urr->rep_triggers.volume_quota = 1;
|
||||||
|
urr->vol_quota.tovol = 1;
|
||||||
|
urr->vol_quota.total_volume = gy_message->cca.granted.cc_total_octets;
|
||||||
|
} else {
|
||||||
|
urr->rep_triggers.volume_quota = 0;
|
||||||
|
urr->vol_quota.tovol = 0;
|
||||||
|
urr->vol_quota.total_volume = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Volume Threshold */
|
||||||
|
if (gy_message->cca.volume_threshold) {
|
||||||
|
ogs_debug("Adding Volume Threshold total_octets=%" PRIu32, gy_message->cca.volume_threshold);
|
||||||
|
urr->rep_triggers.volume_threshold = 1;
|
||||||
|
urr->vol_threshold.tovol = 1;
|
||||||
|
urr->vol_threshold.total_volume = gy_message->cca.volume_threshold;
|
||||||
|
} else {
|
||||||
|
urr->rep_triggers.volume_threshold = 0;
|
||||||
|
urr->vol_threshold.tovol = 0;
|
||||||
|
urr->vol_threshold.total_volume = 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void urr_disable_total_volume_threshold(ogs_pfcp_urr_t *urr)
|
static void urr_update_time(smf_sess_t *sess, ogs_pfcp_urr_t *urr, ogs_diam_gy_message_t *gy_message)
|
||||||
{
|
{
|
||||||
urr->meas_method &= ~OGS_PFCP_MEASUREMENT_METHOD_VOLUME;
|
uint32_t time_quota;
|
||||||
urr->rep_triggers.volume_threshold = 0;
|
|
||||||
urr->vol_threshold.tovol = 0;
|
|
||||||
urr->vol_threshold.total_volume = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void urr_update_total_volume_threshold(smf_sess_t *sess, ogs_pfcp_urr_t *urr, ogs_diam_gy_message_t *gy_message)
|
if (sess->pfcp_node->up_function_features.vtime) {
|
||||||
{
|
if (gy_message->cca.validity_time > 0) {
|
||||||
if (gy_message->cca.granted.cc_total_octets_present)
|
urr->rep_triggers.quota_validity_time = 1;
|
||||||
urr_enable_total_volume_threshold(sess, urr, gy_message->cca.granted.cc_total_octets);
|
urr->quota_validity_time = gy_message->cca.validity_time;
|
||||||
else
|
} else {
|
||||||
urr_disable_total_volume_threshold(urr);
|
urr->rep_triggers.quota_validity_time = 0;
|
||||||
}
|
urr->quota_validity_time = 0;
|
||||||
|
}
|
||||||
|
time_quota = gy_message->cca.granted.cc_time_present ? gy_message->cca.granted.cc_time : 0;
|
||||||
|
} else {
|
||||||
|
/* Store Validity Time as Volume Quota (if not longer than Volume Quota) */
|
||||||
|
if (gy_message->cca.validity_time && (gy_message->cca.granted.cc_time_present && gy_message->cca.granted.cc_time > 0))
|
||||||
|
time_quota = (gy_message->cca.validity_time <= gy_message->cca.granted.cc_time) ?
|
||||||
|
gy_message->cca.validity_time : gy_message->cca.granted.cc_time;
|
||||||
|
else if (gy_message->cca.validity_time)
|
||||||
|
time_quota = gy_message->cca.validity_time;
|
||||||
|
else if (gy_message->cca.granted.cc_time_present && gy_message->cca.granted.cc_time > 0)
|
||||||
|
time_quota = gy_message->cca.granted.cc_time;
|
||||||
|
else
|
||||||
|
time_quota = 0;
|
||||||
|
}
|
||||||
|
|
||||||
static void urr_update_time_threshold(ogs_pfcp_urr_t *urr, ogs_diam_gy_message_t *gy_message)
|
if (gy_message->cca.validity_time || time_quota || gy_message->cca.time_threshold) {
|
||||||
{
|
|
||||||
uint32_t time_threshold;
|
|
||||||
if (gy_message->cca.validity_time && (gy_message->cca.granted.cc_time_present && gy_message->cca.granted.cc_time > 0))
|
|
||||||
time_threshold = (gy_message->cca.validity_time <= gy_message->cca.granted.cc_time) ?
|
|
||||||
gy_message->cca.validity_time : gy_message->cca.granted.cc_time;
|
|
||||||
else if (gy_message->cca.validity_time)
|
|
||||||
time_threshold = gy_message->cca.validity_time;
|
|
||||||
else if (gy_message->cca.granted.cc_time_present && gy_message->cca.granted.cc_time > 0)
|
|
||||||
time_threshold = gy_message->cca.granted.cc_time;
|
|
||||||
else
|
|
||||||
time_threshold = 0;
|
|
||||||
if (time_threshold) {
|
|
||||||
ogs_debug("Adding CC Grant time=%" PRIu32, time_threshold);
|
|
||||||
urr->meas_method |= OGS_PFCP_MEASUREMENT_METHOD_DURATION;
|
urr->meas_method |= OGS_PFCP_MEASUREMENT_METHOD_DURATION;
|
||||||
urr->rep_triggers.time_threshold = 1;
|
|
||||||
urr->time_threshold = time_threshold;
|
|
||||||
urr->meas_info.istm = 1;
|
urr->meas_info.istm = 1;
|
||||||
} else {
|
} else {
|
||||||
|
urr->meas_info.istm = 0;
|
||||||
urr->meas_method &= ~OGS_PFCP_MEASUREMENT_METHOD_DURATION;
|
urr->meas_method &= ~OGS_PFCP_MEASUREMENT_METHOD_DURATION;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (time_quota) {
|
||||||
|
ogs_debug("Adding Time Quota secs=%" PRIu32, time_quota);
|
||||||
|
urr->rep_triggers.time_quota = 1;
|
||||||
|
urr->time_quota = time_quota;
|
||||||
|
} else {
|
||||||
|
urr->rep_triggers.time_quota = 0;
|
||||||
|
urr->time_quota = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (gy_message->cca.time_threshold) {
|
||||||
|
ogs_debug("Adding Time Threshold secs=%" PRIu32, gy_message->cca.time_threshold);
|
||||||
|
urr->rep_triggers.time_threshold = 1;
|
||||||
|
urr->time_threshold = gy_message->cca.time_threshold;
|
||||||
|
} else {
|
||||||
urr->rep_triggers.time_threshold = 0;
|
urr->rep_triggers.time_threshold = 0;
|
||||||
urr->time_threshold = 0;
|
urr->time_threshold = 0;
|
||||||
}
|
}
|
||||||
|
@ -105,8 +140,8 @@ uint32_t smf_gy_handle_cca_initial_request(
|
||||||
ogs_assert(bearer->urr);
|
ogs_assert(bearer->urr);
|
||||||
|
|
||||||
/* Configure based on what we received from OCS: */
|
/* Configure based on what we received from OCS: */
|
||||||
urr_update_time_threshold(bearer->urr, gy_message);
|
urr_update_time(sess, bearer->urr, gy_message);
|
||||||
urr_update_total_volume_threshold(sess, bearer->urr, gy_message);
|
urr_update_volume(sess, bearer->urr, gy_message);
|
||||||
|
|
||||||
/* Associate acconting URR each direction PDR: */
|
/* Associate acconting URR each direction PDR: */
|
||||||
ogs_pfcp_pdr_associate_urr(bearer->ul_pdr, bearer->urr);
|
ogs_pfcp_pdr_associate_urr(bearer->ul_pdr, bearer->urr);
|
||||||
|
@ -124,6 +159,9 @@ void smf_gy_handle_cca_update_request(
|
||||||
uint64_t modify_flags = 0;
|
uint64_t modify_flags = 0;
|
||||||
ogs_pfcp_measurement_method_t prev_meas_method;
|
ogs_pfcp_measurement_method_t prev_meas_method;
|
||||||
ogs_pfcp_reporting_triggers_t prev_rep_triggers;
|
ogs_pfcp_reporting_triggers_t prev_rep_triggers;
|
||||||
|
ogs_pfcp_quota_validity_time_t prev_quota_validity_time;
|
||||||
|
ogs_pfcp_volume_quota_t prev_vol_quota;
|
||||||
|
ogs_pfcp_time_quota_t prev_time_quota;
|
||||||
ogs_pfcp_volume_threshold_t prev_vol_threshold;
|
ogs_pfcp_volume_threshold_t prev_vol_threshold;
|
||||||
ogs_pfcp_time_threshold_t prev_time_threshold;
|
ogs_pfcp_time_threshold_t prev_time_threshold;
|
||||||
|
|
||||||
|
@ -151,19 +189,35 @@ void smf_gy_handle_cca_update_request(
|
||||||
ogs_assert(urr);
|
ogs_assert(urr);
|
||||||
prev_meas_method = urr->meas_method;
|
prev_meas_method = urr->meas_method;
|
||||||
prev_rep_triggers = urr->rep_triggers;
|
prev_rep_triggers = urr->rep_triggers;
|
||||||
|
prev_quota_validity_time = urr->quota_validity_time;
|
||||||
|
prev_vol_quota = urr->vol_quota;
|
||||||
|
prev_time_quota = urr->time_quota;
|
||||||
prev_vol_threshold = urr->vol_threshold;
|
prev_vol_threshold = urr->vol_threshold;
|
||||||
prev_time_threshold = urr->time_threshold;
|
prev_time_threshold = urr->time_threshold;
|
||||||
|
|
||||||
urr_update_time_threshold(urr, gy_message);
|
urr_update_time(sess, urr, gy_message);
|
||||||
urr_update_total_volume_threshold(sess, urr, gy_message);
|
urr_update_volume(sess, urr, gy_message);
|
||||||
ogs_pfcp_pdr_associate_urr(bearer->ul_pdr, urr);
|
ogs_pfcp_pdr_associate_urr(bearer->ul_pdr, urr);
|
||||||
|
|
||||||
if (urr->meas_method != prev_meas_method)
|
if (urr->meas_method != prev_meas_method)
|
||||||
modify_flags |= OGS_PFCP_MODIFY_URR_MEAS_METHOD;
|
modify_flags |= OGS_PFCP_MODIFY_URR_MEAS_METHOD;
|
||||||
if (urr->rep_triggers.time_threshold != prev_rep_triggers.time_threshold ||
|
if (urr->rep_triggers.quota_validity_time != prev_rep_triggers.quota_validity_time ||
|
||||||
|
urr->rep_triggers.time_quota != prev_rep_triggers.time_quota ||
|
||||||
|
urr->rep_triggers.volume_quota != prev_rep_triggers.volume_quota ||
|
||||||
|
urr->rep_triggers.time_threshold != prev_rep_triggers.time_threshold ||
|
||||||
urr->rep_triggers.volume_threshold != prev_rep_triggers.volume_threshold)
|
urr->rep_triggers.volume_threshold != prev_rep_triggers.volume_threshold)
|
||||||
modify_flags |= OGS_PFCP_MODIFY_URR_REPORT_TRIGGER;
|
modify_flags |= OGS_PFCP_MODIFY_URR_REPORT_TRIGGER;
|
||||||
|
|
||||||
|
if (urr->quota_validity_time != prev_quota_validity_time)
|
||||||
|
modify_flags |= OGS_PFCP_MODIFY_URR_QUOTA_VALIDITY_TIME;
|
||||||
|
|
||||||
|
if (urr->time_quota != prev_time_quota)
|
||||||
|
modify_flags |= OGS_PFCP_MODIFY_URR_TIME_QUOTA;
|
||||||
|
|
||||||
|
if (urr->vol_quota.tovol != prev_vol_quota.tovol ||
|
||||||
|
urr->vol_quota.total_volume != prev_vol_quota.total_volume)
|
||||||
|
modify_flags |= OGS_PFCP_MODIFY_URR_VOLUME_QUOTA;
|
||||||
|
|
||||||
if (urr->time_threshold != prev_time_threshold)
|
if (urr->time_threshold != prev_time_threshold)
|
||||||
modify_flags |= OGS_PFCP_MODIFY_URR_TIME_THRESH;
|
modify_flags |= OGS_PFCP_MODIFY_URR_TIME_THRESH;
|
||||||
|
|
||||||
|
|
|
@ -114,18 +114,23 @@ static void fill_multiple_services_credit_control_ccr(smf_sess_t *sess,
|
||||||
/* Reporting-Reason, TS 32.299 7.2.175 */
|
/* Reporting-Reason, TS 32.299 7.2.175 */
|
||||||
/* "values THRESHOLD, QUOTA_EXHAUSTED and OTHER_QUOTA_TYPE apply to one
|
/* "values THRESHOLD, QUOTA_EXHAUSTED and OTHER_QUOTA_TYPE apply to one
|
||||||
particular quota type and shall occur only in the Used-Service-Units AVP" */
|
particular quota type and shall occur only in the Used-Service-Units AVP" */
|
||||||
#if 0
|
|
||||||
/* TODO: set when update is triggered by threshold from PFCP URR. Not yet supported. */
|
|
||||||
if (cc_request_type == OGS_DIAM_GY_CC_REQUEST_TYPE_UPDATE_REQUEST) {
|
if (cc_request_type == OGS_DIAM_GY_CC_REQUEST_TYPE_UPDATE_REQUEST) {
|
||||||
ret = fd_msg_avp_new(ogs_diam_gy_reporting_reason, 0, &avpch2);
|
switch (sess->gy.reporting_reason) {
|
||||||
ogs_assert(ret == 0);
|
case OGS_DIAM_GY_REPORTING_REASON_THRESHOLD:
|
||||||
val.u32 = OGS_DIAM_GY_REPORTING_REASON_THRESHOLD;
|
case OGS_DIAM_GY_REPORTING_REASON_QUOTA_EXHAUSTED:
|
||||||
ret = fd_msg_avp_setvalue (avpch2, &val);
|
case OGS_DIAM_GY_REPORTING_REASON_OTHER_QUOTA_TYPE:
|
||||||
ogs_assert(ret == 0);
|
ret = fd_msg_avp_new(ogs_diam_gy_reporting_reason, 0, &avpch2);
|
||||||
ret = fd_msg_avp_add (avpch1, MSG_BRW_LAST_CHILD, avpch2);
|
ogs_assert(ret == 0);
|
||||||
ogs_assert(ret == 0);
|
val.u32 = sess->gy.reporting_reason;
|
||||||
|
ret = fd_msg_avp_setvalue (avpch2, &val);
|
||||||
|
ogs_assert(ret == 0);
|
||||||
|
ret = fd_msg_avp_add (avpch1, MSG_BRW_LAST_CHILD, avpch2);
|
||||||
|
ogs_assert(ret == 0);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Tariff-Change-Usage */
|
/* Tariff-Change-Usage */
|
||||||
|
|
||||||
|
@ -176,19 +181,24 @@ static void fill_multiple_services_credit_control_ccr(smf_sess_t *sess,
|
||||||
*/
|
*/
|
||||||
if (cc_request_type == OGS_DIAM_GY_CC_REQUEST_TYPE_UPDATE_REQUEST ||
|
if (cc_request_type == OGS_DIAM_GY_CC_REQUEST_TYPE_UPDATE_REQUEST ||
|
||||||
cc_request_type == OGS_DIAM_GY_CC_REQUEST_TYPE_TERMINATION_REQUEST) {
|
cc_request_type == OGS_DIAM_GY_CC_REQUEST_TYPE_TERMINATION_REQUEST) {
|
||||||
ret = fd_msg_avp_new(ogs_diam_gy_reporting_reason, 0, &avpch1);
|
switch (sess->gy.reporting_reason) {
|
||||||
ogs_assert(ret == 0);
|
case OGS_DIAM_GY_REPORTING_REASON_QHT:
|
||||||
if (cc_request_type == OGS_DIAM_GY_CC_REQUEST_TYPE_UPDATE_REQUEST) {
|
case OGS_DIAM_GY_REPORTING_REASON_FINAL:
|
||||||
val.u32 = OGS_DIAM_GY_REPORTING_REASON_VALIDITY_TIME;
|
case OGS_DIAM_GY_REPORTING_REASON_FORCED_REAUTHORISATION:
|
||||||
/* TODO: do NOT set when update is triggered by threshold from
|
case OGS_DIAM_GY_REPORTING_REASON_VALIDITY_TIME:
|
||||||
* PFCP URR (not yet supported) */
|
case OGS_DIAM_GY_REPORTING_REASON_RATING_CONDITION_CHANGE:
|
||||||
} else {
|
case OGS_DIAM_GY_REPORTING_REASON_UNUSED_QUOTA_TIMER:
|
||||||
val.u32 = OGS_DIAM_GY_REPORTING_REASON_FINAL;
|
ret = fd_msg_avp_new(ogs_diam_gy_reporting_reason, 0, &avpch1);
|
||||||
|
ogs_assert(ret == 0);
|
||||||
|
val.u32 = sess->gy.reporting_reason;
|
||||||
|
ret = fd_msg_avp_setvalue (avpch1, &val);
|
||||||
|
ogs_assert(ret == 0);
|
||||||
|
ret = fd_msg_avp_add (avp, MSG_BRW_LAST_CHILD, avpch1);
|
||||||
|
ogs_assert(ret == 0);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
ret = fd_msg_avp_setvalue (avpch1, &val);
|
|
||||||
ogs_assert(ret == 0);
|
|
||||||
ret = fd_msg_avp_add (avp, MSG_BRW_LAST_CHILD, avpch1);
|
|
||||||
ogs_assert(ret == 0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ... lots of AVPs ... */
|
/* ... lots of AVPs ... */
|
||||||
|
@ -1056,6 +1066,12 @@ static void smf_gy_cca_cb(void *data, struct msg **msg)
|
||||||
case OGS_DIAM_GY_AVP_CODE_VALIDITY_TIME:
|
case OGS_DIAM_GY_AVP_CODE_VALIDITY_TIME:
|
||||||
gy_message->cca.validity_time = hdr->avp_value->u32;
|
gy_message->cca.validity_time = hdr->avp_value->u32;
|
||||||
break;
|
break;
|
||||||
|
case OGS_DIAM_GY_AVP_CODE_TIME_QUOTA_THRESHOLD:
|
||||||
|
gy_message->cca.time_threshold = hdr->avp_value->u32;
|
||||||
|
break;
|
||||||
|
case OGS_DIAM_GY_AVP_CODE_VOLUME_QUOTA_THRESHOLD:
|
||||||
|
gy_message->cca.volume_threshold = hdr->avp_value->u32;
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
ogs_warn("Not supported(%d)", hdr->avp_code);
|
ogs_warn("Not supported(%d)", hdr->avp_code);
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -1074,6 +1074,7 @@ uint8_t smf_epc_n4_handle_session_deletion_response(
|
||||||
&rsp->usage_report[i];
|
&rsp->usage_report[i];
|
||||||
uint32_t urr_id;
|
uint32_t urr_id;
|
||||||
ogs_pfcp_volume_measurement_t volume;
|
ogs_pfcp_volume_measurement_t volume;
|
||||||
|
ogs_pfcp_usage_report_trigger_t rep_trig;
|
||||||
if (use_rep->presence == 0)
|
if (use_rep->presence == 0)
|
||||||
break;
|
break;
|
||||||
if (use_rep->urr_id.presence == 0)
|
if (use_rep->urr_id.presence == 0)
|
||||||
|
@ -1088,6 +1089,10 @@ uint8_t smf_epc_n4_handle_session_deletion_response(
|
||||||
if (volume.dlvol)
|
if (volume.dlvol)
|
||||||
sess->gy.dl_octets += volume.downlink_volume;
|
sess->gy.dl_octets += volume.downlink_volume;
|
||||||
sess->gy.duration += use_rep->duration_measurement.u32;
|
sess->gy.duration += use_rep->duration_measurement.u32;
|
||||||
|
ogs_pfcp_parse_usage_report_trigger(
|
||||||
|
&rep_trig, &use_rep->usage_report_trigger);
|
||||||
|
sess->gy.reporting_reason =
|
||||||
|
smf_pfcp_urr_usage_report_trigger2diam_gy_reporting_reason(&rep_trig);
|
||||||
}
|
}
|
||||||
|
|
||||||
return OGS_PFCP_CAUSE_REQUEST_ACCEPTED;
|
return OGS_PFCP_CAUSE_REQUEST_ACCEPTED;
|
||||||
|
@ -1237,6 +1242,7 @@ void smf_n4_handle_session_report_request(
|
||||||
&pfcp_req->usage_report[i];
|
&pfcp_req->usage_report[i];
|
||||||
uint32_t urr_id;
|
uint32_t urr_id;
|
||||||
ogs_pfcp_volume_measurement_t volume;
|
ogs_pfcp_volume_measurement_t volume;
|
||||||
|
ogs_pfcp_usage_report_trigger_t rep_trig;
|
||||||
if (use_rep->presence == 0)
|
if (use_rep->presence == 0)
|
||||||
break;
|
break;
|
||||||
if (use_rep->urr_id.presence == 0)
|
if (use_rep->urr_id.presence == 0)
|
||||||
|
@ -1251,6 +1257,10 @@ void smf_n4_handle_session_report_request(
|
||||||
if (volume.dlvol)
|
if (volume.dlvol)
|
||||||
sess->gy.dl_octets += volume.downlink_volume;
|
sess->gy.dl_octets += volume.downlink_volume;
|
||||||
sess->gy.duration += use_rep->duration_measurement.u32;
|
sess->gy.duration += use_rep->duration_measurement.u32;
|
||||||
|
ogs_pfcp_parse_usage_report_trigger(
|
||||||
|
&rep_trig, &use_rep->usage_report_trigger);
|
||||||
|
sess->gy.reporting_reason =
|
||||||
|
smf_pfcp_urr_usage_report_trigger2diam_gy_reporting_reason(&rep_trig);
|
||||||
}
|
}
|
||||||
switch(smf_use_gy_iface()) {
|
switch(smf_use_gy_iface()) {
|
||||||
case 1:
|
case 1:
|
||||||
|
|
|
@ -20,6 +20,45 @@
|
||||||
#include "sbi-path.h"
|
#include "sbi-path.h"
|
||||||
#include "pfcp-path.h"
|
#include "pfcp-path.h"
|
||||||
|
|
||||||
|
/* Converts PFCP "Usage Report" "Report Trigger" bitmask to Gy "Reporting-Reason" AVP enum value.
|
||||||
|
* PFCP: 3GPP TS 29.244 sec 8.2.41
|
||||||
|
* Gy: 3GPP TS 32.299 sec 7.2.175 (OGS_DIAM_GY_REPORTING_REASON_*) */
|
||||||
|
uint32_t smf_pfcp_urr_usage_report_trigger2diam_gy_reporting_reason(ogs_pfcp_usage_report_trigger_t *rep_trigger)
|
||||||
|
{
|
||||||
|
|
||||||
|
if (rep_trigger->termination_report ||
|
||||||
|
rep_trigger->termination_by_up_function_report)
|
||||||
|
return OGS_DIAM_GY_REPORTING_REASON_FINAL;
|
||||||
|
|
||||||
|
if (rep_trigger->time_threshold ||
|
||||||
|
rep_trigger->volume_threshold)
|
||||||
|
return OGS_DIAM_GY_REPORTING_REASON_THRESHOLD;
|
||||||
|
|
||||||
|
if (rep_trigger->time_quota ||
|
||||||
|
rep_trigger->volume_quota ||
|
||||||
|
rep_trigger->event_quota)
|
||||||
|
return OGS_DIAM_GY_REPORTING_REASON_QUOTA_EXHAUSTED;
|
||||||
|
|
||||||
|
if (rep_trigger->quota_validity_time)
|
||||||
|
return OGS_DIAM_GY_REPORTING_REASON_VALIDITY_TIME;
|
||||||
|
|
||||||
|
/* if (rep_trigger->immediate_report ||
|
||||||
|
rep_trigger->dropped_dl_traffic_threshold ||
|
||||||
|
rep_trigger->stop_of_traffic ||
|
||||||
|
rep_trigger->start_of_traffic ||
|
||||||
|
rep_trigger->quota_holding_time ||
|
||||||
|
rep_trigger->periodic_reporting ||
|
||||||
|
rep_trigger->event_threshold ||
|
||||||
|
rep_trigger->mac_addresses_reporting ||
|
||||||
|
rep_trigger->envelope_closure ||
|
||||||
|
rep_trigger->monitoring_time ||
|
||||||
|
rep_trigger->linked_usage_reporting ||
|
||||||
|
rep_trigger->report_the_end_marker_reception ||
|
||||||
|
rep_trigger->ip_multicast_join_leave
|
||||||
|
) */
|
||||||
|
return OGS_DIAM_GY_REPORTING_REASON_UNUSED_QUOTA_TIMER;
|
||||||
|
}
|
||||||
|
|
||||||
static void pfcp_node_fsm_init(ogs_pfcp_node_t *node, bool try_to_assoicate)
|
static void pfcp_node_fsm_init(ogs_pfcp_node_t *node, bool try_to_assoicate)
|
||||||
{
|
{
|
||||||
smf_event_t e;
|
smf_event_t e;
|
||||||
|
|
|
@ -62,6 +62,9 @@ int smf_epc_pfcp_send_deactivation(smf_sess_t *sess, uint8_t gtp_cause);
|
||||||
int smf_pfcp_send_session_report_response(
|
int smf_pfcp_send_session_report_response(
|
||||||
ogs_pfcp_xact_t *xact, smf_sess_t *sess, uint8_t cause);
|
ogs_pfcp_xact_t *xact, smf_sess_t *sess, uint8_t cause);
|
||||||
|
|
||||||
|
uint32_t smf_pfcp_urr_usage_report_trigger2diam_gy_reporting_reason(
|
||||||
|
ogs_pfcp_usage_report_trigger_t *rep_trigger);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -43,7 +43,8 @@ void upf_context_init(void)
|
||||||
ogs_pfcp_self()->up_function_features.ftup = 1;
|
ogs_pfcp_self()->up_function_features.ftup = 1;
|
||||||
ogs_pfcp_self()->up_function_features.empu = 1;
|
ogs_pfcp_self()->up_function_features.empu = 1;
|
||||||
ogs_pfcp_self()->up_function_features.mnop = 1;
|
ogs_pfcp_self()->up_function_features.mnop = 1;
|
||||||
ogs_pfcp_self()->up_function_features_len = 3;
|
ogs_pfcp_self()->up_function_features.vtime = 1;
|
||||||
|
ogs_pfcp_self()->up_function_features_len = 4;
|
||||||
|
|
||||||
ogs_list_init(&self.sess_list);
|
ogs_list_init(&self.sess_list);
|
||||||
ogs_pool_init(&upf_sess_pool, ogs_app()->pool.sess);
|
ogs_pool_init(&upf_sess_pool, ogs_app()->pool.sess);
|
||||||
|
@ -406,6 +407,8 @@ uint8_t upf_sess_set_ue_ip(upf_sess_t *sess,
|
||||||
void upf_sess_urr_acc_add(upf_sess_t *sess, ogs_pfcp_urr_t *urr, size_t size, bool is_uplink)
|
void upf_sess_urr_acc_add(upf_sess_t *sess, ogs_pfcp_urr_t *urr, size_t size, bool is_uplink)
|
||||||
{
|
{
|
||||||
upf_sess_urr_acc_t *urr_acc = &sess->urr_acc[urr->id];
|
upf_sess_urr_acc_t *urr_acc = &sess->urr_acc[urr->id];
|
||||||
|
uint64_t vol;
|
||||||
|
|
||||||
/* Increment total & ul octets + pkts */
|
/* Increment total & ul octets + pkts */
|
||||||
urr_acc->total_octets += size;
|
urr_acc->total_octets += size;
|
||||||
urr_acc->total_pkts++;
|
urr_acc->total_pkts++;
|
||||||
|
@ -421,7 +424,21 @@ void upf_sess_urr_acc_add(upf_sess_t *sess, ogs_pfcp_urr_t *urr, size_t size, bo
|
||||||
if (urr_acc->time_of_first_packet == 0)
|
if (urr_acc->time_of_first_packet == 0)
|
||||||
urr_acc->time_of_first_packet = urr_acc->time_of_last_packet;
|
urr_acc->time_of_first_packet = urr_acc->time_of_last_packet;
|
||||||
|
|
||||||
/* TODO: generate report if volume threshold/quota is reached, eg sess->urr_acc[urr->id].total_octets - sess->urr_acc[urr->id].last_report.total_octets > threshold */
|
/* generate report if volume threshold/quota is reached */
|
||||||
|
vol = urr_acc->total_octets - urr_acc->last_report.total_octets;
|
||||||
|
if ((urr->rep_triggers.volume_quota && urr->vol_quota.tovol && vol >= urr->vol_quota.total_volume) ||
|
||||||
|
(urr->rep_triggers.volume_threshold && urr->vol_threshold.tovol && vol >= urr->vol_threshold.total_volume)) {
|
||||||
|
ogs_pfcp_user_plane_report_t report;
|
||||||
|
memset(&report, 0, sizeof(report));
|
||||||
|
upf_sess_urr_acc_fill_usage_report(sess, urr, &report, 0);
|
||||||
|
report.num_of_usage_report = 1;
|
||||||
|
upf_sess_urr_acc_snapshot(sess, urr);
|
||||||
|
|
||||||
|
ogs_assert(OGS_OK ==
|
||||||
|
upf_pfcp_send_session_report_request(sess, &report));
|
||||||
|
/* Start new report period/iteration: */
|
||||||
|
upf_sess_urr_acc_timers_setup(sess, urr);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* report struct must be memzeroed before first use of this function.
|
/* report struct must be memzeroed before first use of this function.
|
||||||
|
@ -438,12 +455,12 @@ void upf_sess_urr_acc_fill_usage_report(upf_sess_t *sess, const ogs_pfcp_urr_t *
|
||||||
if (urr_acc->last_report.timestamp)
|
if (urr_acc->last_report.timestamp)
|
||||||
last_report_timestamp = urr_acc->last_report.timestamp;
|
last_report_timestamp = urr_acc->last_report.timestamp;
|
||||||
else
|
else
|
||||||
last_report_timestamp = ogs_time_from_ntp32(urr_acc->time_threshold_start);
|
last_report_timestamp = ogs_time_from_ntp32(urr_acc->time_start);
|
||||||
|
|
||||||
report->type.usage_report = 1;
|
report->type.usage_report = 1;
|
||||||
report->usage_report[idx].id = urr->id;
|
report->usage_report[idx].id = urr->id;
|
||||||
report->usage_report[idx].seqn = urr_acc->report_seqn++;
|
report->usage_report[idx].seqn = urr_acc->report_seqn++;
|
||||||
report->usage_report[idx].start_time = urr_acc->time_threshold_start;
|
report->usage_report[idx].start_time = urr_acc->time_start;
|
||||||
report->usage_report[idx].end_time = ogs_time_to_ntp32(now);
|
report->usage_report[idx].end_time = ogs_time_to_ntp32(now);
|
||||||
report->usage_report[idx].vol_measurement = (ogs_pfcp_volume_measurement_t){
|
report->usage_report[idx].vol_measurement = (ogs_pfcp_volume_measurement_t){
|
||||||
.dlnop = 1,
|
.dlnop = 1,
|
||||||
|
@ -465,9 +482,24 @@ void upf_sess_urr_acc_fill_usage_report(upf_sess_t *sess, const ogs_pfcp_urr_t *
|
||||||
report->usage_report[idx].time_of_first_packet = ogs_time_to_ntp32(urr_acc->time_of_first_packet); /* TODO: First since last report? */
|
report->usage_report[idx].time_of_first_packet = ogs_time_to_ntp32(urr_acc->time_of_first_packet); /* TODO: First since last report? */
|
||||||
report->usage_report[idx].time_of_last_packet = ogs_time_to_ntp32(urr_acc->time_of_last_packet);
|
report->usage_report[idx].time_of_last_packet = ogs_time_to_ntp32(urr_acc->time_of_last_packet);
|
||||||
|
|
||||||
|
/* Time triggers: */
|
||||||
|
if (urr->quota_validity_time > 0 &&
|
||||||
|
report->usage_report[idx].dur_measurement >= urr->quota_validity_time)
|
||||||
|
report->usage_report[idx].rep_trigger.quota_validity_time = 1;
|
||||||
|
if (urr->time_quota > 0 &&
|
||||||
|
report->usage_report[idx].dur_measurement >= urr->time_quota)
|
||||||
|
report->usage_report[idx].rep_trigger.time_quota = 1;
|
||||||
if (urr->time_threshold > 0 &&
|
if (urr->time_threshold > 0 &&
|
||||||
report->usage_report[idx].dur_measurement >= urr->time_threshold)
|
report->usage_report[idx].dur_measurement >= urr->time_threshold)
|
||||||
report->usage_report[idx].rep_trigger.time_threshold = 1;
|
report->usage_report[idx].rep_trigger.time_threshold = 1;
|
||||||
|
|
||||||
|
/* Volume triggers: */
|
||||||
|
if (urr->rep_triggers.volume_quota && urr->vol_quota.tovol &&
|
||||||
|
report->usage_report[idx].vol_measurement.total_volume >= urr->vol_quota.total_volume)
|
||||||
|
report->usage_report[idx].rep_trigger.volume_quota = 1;
|
||||||
|
if (urr->rep_triggers.volume_threshold && urr->vol_threshold.tovol &&
|
||||||
|
report->usage_report[idx].vol_measurement.total_volume >= urr->vol_threshold.total_volume)
|
||||||
|
report->usage_report[idx].rep_trigger.volume_threshold = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void upf_sess_urr_acc_snapshot(upf_sess_t *sess, ogs_pfcp_urr_t *urr)
|
void upf_sess_urr_acc_snapshot(upf_sess_t *sess, ogs_pfcp_urr_t *urr)
|
||||||
|
@ -482,7 +514,7 @@ void upf_sess_urr_acc_snapshot(upf_sess_t *sess, ogs_pfcp_urr_t *urr)
|
||||||
urr_acc->last_report.timestamp = ogs_time_now();
|
urr_acc->last_report.timestamp = ogs_time_now();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void upf_sess_urr_acc_time_threshold_cb(void *data)
|
static void upf_sess_urr_acc_timers_cb(void *data)
|
||||||
{
|
{
|
||||||
ogs_pfcp_urr_t *urr = (ogs_pfcp_urr_t *)data;
|
ogs_pfcp_urr_t *urr = (ogs_pfcp_urr_t *)data;
|
||||||
ogs_pfcp_user_plane_report_t report;
|
ogs_pfcp_user_plane_report_t report;
|
||||||
|
@ -491,7 +523,9 @@ static void upf_sess_urr_acc_time_threshold_cb(void *data)
|
||||||
|
|
||||||
ogs_warn("upf_time_threshold_cb() triggered! urr=%p", urr);
|
ogs_warn("upf_time_threshold_cb() triggered! urr=%p", urr);
|
||||||
|
|
||||||
if (urr->rep_triggers.time_threshold) {
|
if (urr->rep_triggers.quota_validity_time ||
|
||||||
|
urr->rep_triggers.time_quota ||
|
||||||
|
urr->rep_triggers.time_threshold) {
|
||||||
memset(&report, 0, sizeof(report));
|
memset(&report, 0, sizeof(report));
|
||||||
upf_sess_urr_acc_fill_usage_report(sess, urr, &report, 0);
|
upf_sess_urr_acc_fill_usage_report(sess, urr, &report, 0);
|
||||||
report.num_of_usage_report = 1;
|
report.num_of_usage_report = 1;
|
||||||
|
@ -501,27 +535,64 @@ static void upf_sess_urr_acc_time_threshold_cb(void *data)
|
||||||
upf_pfcp_send_session_report_request(sess, &report));
|
upf_pfcp_send_session_report_request(sess, &report));
|
||||||
}
|
}
|
||||||
/* Start new report period/iteration: */
|
/* Start new report period/iteration: */
|
||||||
upf_sess_urr_acc_time_threshold_setup(sess, urr);
|
upf_sess_urr_acc_timers_setup(sess, urr);
|
||||||
}
|
}
|
||||||
|
|
||||||
void upf_sess_urr_acc_time_threshold_setup(upf_sess_t *sess, ogs_pfcp_urr_t *urr)
|
static void upf_sess_urr_acc_validity_time_setup(upf_sess_t *sess, ogs_pfcp_urr_t *urr)
|
||||||
{
|
{
|
||||||
upf_sess_urr_acc_t *urr_acc = &sess->urr_acc[urr->id];
|
upf_sess_urr_acc_t *urr_acc = &sess->urr_acc[urr->id];
|
||||||
|
|
||||||
ogs_debug("Installing URR time threshold timer");
|
ogs_debug("Installing URR Quota Validity Time timer");
|
||||||
|
urr_acc->reporting_enabled = true;
|
||||||
|
if (!urr_acc->t_validity_time)
|
||||||
|
urr_acc->t_validity_time = ogs_timer_add(ogs_app()->timer_mgr,
|
||||||
|
upf_sess_urr_acc_timers_cb, urr);
|
||||||
|
ogs_timer_start(urr_acc->t_validity_time, urr->quota_validity_time * OGS_USEC_PER_SEC);
|
||||||
|
}
|
||||||
|
static void upf_sess_urr_acc_time_quota_setup(upf_sess_t *sess, ogs_pfcp_urr_t *urr)
|
||||||
|
{
|
||||||
|
upf_sess_urr_acc_t *urr_acc = &sess->urr_acc[urr->id];
|
||||||
|
|
||||||
|
ogs_debug("Installing URR Time Quota timer");
|
||||||
|
urr_acc->reporting_enabled = true;
|
||||||
|
if (!urr_acc->t_time_quota)
|
||||||
|
urr_acc->t_time_quota = ogs_timer_add(ogs_app()->timer_mgr,
|
||||||
|
upf_sess_urr_acc_timers_cb, urr);
|
||||||
|
ogs_timer_start(urr_acc->t_time_quota, urr->time_quota * OGS_USEC_PER_SEC);
|
||||||
|
}
|
||||||
|
static void upf_sess_urr_acc_time_threshold_setup(upf_sess_t *sess, ogs_pfcp_urr_t *urr)
|
||||||
|
{
|
||||||
|
upf_sess_urr_acc_t *urr_acc = &sess->urr_acc[urr->id];
|
||||||
|
|
||||||
|
ogs_debug("Installing URR Time Threshold timer");
|
||||||
urr_acc->reporting_enabled = true;
|
urr_acc->reporting_enabled = true;
|
||||||
if (!urr_acc->t_time_threshold)
|
if (!urr_acc->t_time_threshold)
|
||||||
urr_acc->t_time_threshold = ogs_timer_add(ogs_app()->timer_mgr,
|
urr_acc->t_time_threshold = ogs_timer_add(ogs_app()->timer_mgr,
|
||||||
upf_sess_urr_acc_time_threshold_cb, urr);
|
upf_sess_urr_acc_timers_cb, urr);
|
||||||
urr_acc->time_threshold_start = ogs_time_ntp32_now();
|
|
||||||
ogs_timer_start(urr_acc->t_time_threshold, urr->time_threshold * OGS_USEC_PER_SEC);
|
ogs_timer_start(urr_acc->t_time_threshold, urr->time_threshold * OGS_USEC_PER_SEC);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void upf_sess_urr_acc_timers_setup(upf_sess_t *sess, ogs_pfcp_urr_t *urr)
|
||||||
|
{
|
||||||
|
upf_sess_urr_acc_t *urr_acc = &sess->urr_acc[urr->id];
|
||||||
|
urr_acc->time_start = ogs_time_ntp32_now();
|
||||||
|
if (urr->rep_triggers.quota_validity_time && urr->quota_validity_time > 0)
|
||||||
|
upf_sess_urr_acc_validity_time_setup(sess, urr);
|
||||||
|
if (urr->rep_triggers.time_quota && urr->time_quota > 0)
|
||||||
|
upf_sess_urr_acc_time_quota_setup(sess, urr);
|
||||||
|
if (urr->rep_triggers.time_threshold && urr->time_threshold > 0)
|
||||||
|
upf_sess_urr_acc_time_threshold_setup(sess, urr);
|
||||||
|
}
|
||||||
|
|
||||||
static void upf_sess_urr_acc_remove_all(upf_sess_t *sess)
|
static void upf_sess_urr_acc_remove_all(upf_sess_t *sess)
|
||||||
{
|
{
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
for (i = 0; i < OGS_ARRAY_SIZE(sess->urr_acc); i++) {
|
for (i = 0; i < OGS_ARRAY_SIZE(sess->urr_acc); i++) {
|
||||||
if (sess->urr_acc[i].t_time_threshold) {
|
if (sess->urr_acc[i].t_time_threshold) {
|
||||||
|
ogs_timer_delete(sess->urr_acc[i].t_validity_time);
|
||||||
|
sess->urr_acc[i].t_validity_time = NULL;
|
||||||
|
ogs_timer_delete(sess->urr_acc[i].t_time_quota);
|
||||||
|
sess->urr_acc[i].t_time_quota = NULL;
|
||||||
ogs_timer_delete(sess->urr_acc[i].t_time_threshold);
|
ogs_timer_delete(sess->urr_acc[i].t_time_threshold);
|
||||||
sess->urr_acc[i].t_time_threshold = NULL;
|
sess->urr_acc[i].t_time_threshold = NULL;
|
||||||
}
|
}
|
||||||
|
|
|
@ -56,8 +56,10 @@ typedef struct upf_context_s {
|
||||||
/* Accounting: */
|
/* Accounting: */
|
||||||
typedef struct upf_sess_urr_acc_s {
|
typedef struct upf_sess_urr_acc_s {
|
||||||
bool reporting_enabled;
|
bool reporting_enabled;
|
||||||
ogs_timer_t *t_time_threshold; /* Time threshold expiration handler */
|
ogs_timer_t *t_validity_time; /* Quota Validity Time expiration handler */
|
||||||
uint32_t time_threshold_start; /* When t_time_threshold started */
|
ogs_timer_t *t_time_quota; /* Time Quota expiration handler */
|
||||||
|
ogs_timer_t *t_time_threshold; /* Time Threshold expiration handler */
|
||||||
|
uint32_t time_start; /* When t_time_* started */
|
||||||
ogs_pfcp_urr_ur_seqn_t report_seqn; /* Next seqn to use when reporting */
|
ogs_pfcp_urr_ur_seqn_t report_seqn; /* Next seqn to use when reporting */
|
||||||
uint64_t total_octets;
|
uint64_t total_octets;
|
||||||
uint64_t ul_octets;
|
uint64_t ul_octets;
|
||||||
|
@ -128,7 +130,7 @@ void upf_sess_urr_acc_add(upf_sess_t *sess, ogs_pfcp_urr_t *urr, size_t size, bo
|
||||||
void upf_sess_urr_acc_fill_usage_report(upf_sess_t *sess, const ogs_pfcp_urr_t *urr,
|
void upf_sess_urr_acc_fill_usage_report(upf_sess_t *sess, const ogs_pfcp_urr_t *urr,
|
||||||
ogs_pfcp_user_plane_report_t *report, unsigned int idx);
|
ogs_pfcp_user_plane_report_t *report, unsigned int idx);
|
||||||
void upf_sess_urr_acc_snapshot(upf_sess_t *sess, ogs_pfcp_urr_t *urr);
|
void upf_sess_urr_acc_snapshot(upf_sess_t *sess, ogs_pfcp_urr_t *urr);
|
||||||
void upf_sess_urr_acc_time_threshold_setup(upf_sess_t *sess, ogs_pfcp_urr_t *urr);
|
void upf_sess_urr_acc_timers_setup(upf_sess_t *sess, ogs_pfcp_urr_t *urr);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
|
|
@ -36,12 +36,9 @@ static void upf_n4_handle_create_urr(upf_sess_t *sess, ogs_pfcp_tlv_create_urr_t
|
||||||
if (!urr)
|
if (!urr)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
/* TODO: here we should check for Reporting Triggers IMTH=1 instead? */
|
/* TODO: enable counters somewhere else if ISTM not set, upon first pkt received */
|
||||||
if ((urr->meas_method & OGS_PFCP_MEASUREMENT_METHOD_DURATION) && urr->time_threshold > 0) {
|
if (urr->meas_info.istm) {
|
||||||
/* if ISTM bit set in Measurement Information: */
|
upf_sess_urr_acc_timers_setup(sess, urr);
|
||||||
if (urr->meas_info.istm) {
|
|
||||||
upf_sess_urr_acc_time_threshold_setup(sess, urr);
|
|
||||||
} /* else: TODO: call upf_sess_urr_acc_time_threshold_setup() upon first pkt received */
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue