forked from acouzens/open5gs
[UPF] Add initial support for URR Usage Report (#1476)
This commit is contained in:
parent
52672cff65
commit
fb8ebcdbea
|
@ -858,3 +858,72 @@ ogs_pkbuf_t *ogs_pfcp_build_session_report_response(
|
||||||
pfcp_message.h.type = type;
|
pfcp_message.h.type = type;
|
||||||
return ogs_pfcp_build_msg(&pfcp_message);
|
return ogs_pfcp_build_msg(&pfcp_message);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ogs_pkbuf_t *ogs_pfcp_build_session_deletion_response( uint8_t type, uint8_t cause,
|
||||||
|
ogs_pfcp_user_plane_report_t *report)
|
||||||
|
{
|
||||||
|
ogs_pfcp_message_t pfcp_message;
|
||||||
|
ogs_pfcp_session_deletion_response_t *rsp = NULL;
|
||||||
|
unsigned int i;
|
||||||
|
|
||||||
|
ogs_debug("PFCP session deletion response");
|
||||||
|
|
||||||
|
rsp = &pfcp_message.pfcp_session_deletion_response;
|
||||||
|
memset(&pfcp_message, 0, sizeof(ogs_pfcp_message_t));
|
||||||
|
|
||||||
|
rsp->cause.presence = 1;
|
||||||
|
rsp->cause.u8 = cause;
|
||||||
|
|
||||||
|
if (report->type.usage_report) {
|
||||||
|
ogs_assert(report->num_of_usage_report > 0);
|
||||||
|
for (i = 0; i < report->num_of_usage_report; i++) {
|
||||||
|
rsp->usage_report[i].presence = 1;
|
||||||
|
rsp->usage_report[i].urr_id.presence = 1;
|
||||||
|
rsp->usage_report[i].urr_id.u32 = report->usage_report[i].id;
|
||||||
|
rsp->usage_report[i].ur_seqn.presence = 1;
|
||||||
|
rsp->usage_report[i].ur_seqn.u32 = report->usage_report[i].seqn;
|
||||||
|
rsp->usage_report[i].usage_report_trigger.presence = 1;
|
||||||
|
rsp->usage_report[i].usage_report_trigger.u24 =
|
||||||
|
(report->usage_report[i].rep_trigger.reptri_5 << 16)
|
||||||
|
| (report->usage_report[i].rep_trigger.reptri_6 << 8)
|
||||||
|
| (report->usage_report[i].rep_trigger.reptri_7);
|
||||||
|
|
||||||
|
if (report->usage_report[i].start_time) {
|
||||||
|
rsp->usage_report[i].start_time.presence = 1;
|
||||||
|
rsp->usage_report[i].start_time.u32 = report->usage_report[i].start_time;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (report->usage_report[i].end_time) {
|
||||||
|
rsp->usage_report[i].end_time.presence = 1;
|
||||||
|
rsp->usage_report[i].end_time.u32 = report->usage_report[i].end_time;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (report->usage_report[i].vol_measurement.flags) {
|
||||||
|
rsp->usage_report[i].volume_measurement.presence = 1;
|
||||||
|
ogs_pfcp_build_volume_measurement(
|
||||||
|
&rsp->usage_report[i].volume_measurement,
|
||||||
|
&report->usage_report[i].vol_measurement,
|
||||||
|
&usage_report_buf.vol_meas,
|
||||||
|
sizeof(usage_report_buf.vol_meas));
|
||||||
|
}
|
||||||
|
|
||||||
|
rsp->usage_report[i].duration_measurement.presence = 1;
|
||||||
|
rsp->usage_report[i].duration_measurement.u32 =
|
||||||
|
report->usage_report[i].dur_measurement;
|
||||||
|
|
||||||
|
if (report->usage_report[i].time_of_first_packet) {
|
||||||
|
rsp->usage_report[i].time_of_first_packet.presence = 1;
|
||||||
|
rsp->usage_report[i].time_of_first_packet.u32 =
|
||||||
|
report->usage_report[i].time_of_first_packet;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (report->usage_report[i].time_of_last_packet) {
|
||||||
|
rsp->usage_report[i].time_of_last_packet.presence = 1;
|
||||||
|
rsp->usage_report[i].time_of_last_packet.u32 =
|
||||||
|
report->usage_report[i].time_of_last_packet;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pfcp_message.h.type = type;
|
||||||
|
return ogs_pfcp_build_msg(&pfcp_message);
|
||||||
|
}
|
||||||
|
|
|
@ -68,6 +68,9 @@ ogs_pkbuf_t *ogs_pfcp_build_session_report_request(
|
||||||
ogs_pkbuf_t *ogs_pfcp_build_session_report_response(
|
ogs_pkbuf_t *ogs_pfcp_build_session_report_response(
|
||||||
uint8_t type, uint8_t cause);
|
uint8_t type, uint8_t cause);
|
||||||
|
|
||||||
|
ogs_pkbuf_t *ogs_pfcp_build_session_deletion_response( uint8_t type, uint8_t cause,
|
||||||
|
ogs_pfcp_user_plane_report_t *report);
|
||||||
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,6 +18,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "context.h"
|
#include "context.h"
|
||||||
|
#include "pfcp-path.h"
|
||||||
|
|
||||||
static upf_context_t self;
|
static upf_context_t self;
|
||||||
|
|
||||||
|
@ -27,6 +28,8 @@ static OGS_POOL(upf_sess_pool, upf_sess_t);
|
||||||
|
|
||||||
static int context_initialized = 0;
|
static int context_initialized = 0;
|
||||||
|
|
||||||
|
static void upf_sess_urr_acc_remove_all(upf_sess_t *sess);
|
||||||
|
|
||||||
void upf_context_init(void)
|
void upf_context_init(void)
|
||||||
{
|
{
|
||||||
ogs_assert(context_initialized == 0);
|
ogs_assert(context_initialized == 0);
|
||||||
|
@ -39,7 +42,8 @@ void upf_context_init(void)
|
||||||
/* Setup UP Function Features */
|
/* Setup UP Function Features */
|
||||||
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_len = 2;
|
ogs_pfcp_self()->up_function_features.mnop = 1;
|
||||||
|
ogs_pfcp_self()->up_function_features_len = 3;
|
||||||
|
|
||||||
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);
|
||||||
|
@ -167,6 +171,8 @@ int upf_sess_remove(upf_sess_t *sess)
|
||||||
{
|
{
|
||||||
ogs_assert(sess);
|
ogs_assert(sess);
|
||||||
|
|
||||||
|
upf_sess_urr_acc_remove_all(sess);
|
||||||
|
|
||||||
ogs_list_remove(&self.sess_list, sess);
|
ogs_list_remove(&self.sess_list, sess);
|
||||||
ogs_pfcp_sess_clear(&sess->pfcp);
|
ogs_pfcp_sess_clear(&sess->pfcp);
|
||||||
|
|
||||||
|
@ -367,3 +373,128 @@ uint8_t upf_sess_set_ue_ip(upf_sess_t *sess,
|
||||||
|
|
||||||
return cause_value;
|
return cause_value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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];
|
||||||
|
/* Increment total & ul octets + pkts */
|
||||||
|
urr_acc->total_octets += size;
|
||||||
|
urr_acc->total_pkts++;
|
||||||
|
if (is_uplink) {
|
||||||
|
urr_acc->dl_octets += size;
|
||||||
|
urr_acc->dl_pkts++;
|
||||||
|
} else {
|
||||||
|
urr_acc->ul_octets += size;
|
||||||
|
urr_acc->ul_pkts++;
|
||||||
|
}
|
||||||
|
|
||||||
|
urr_acc->time_of_last_packet = ogs_time_now();
|
||||||
|
if (urr_acc->time_of_first_packet == 0)
|
||||||
|
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 */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* report struct must be memzeroed before first use of this function.
|
||||||
|
* report->num_of_usage_report must be set by the caller */
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
upf_sess_urr_acc_t *urr_acc = &sess->urr_acc[urr->id];
|
||||||
|
ogs_time_t last_report_timestamp;
|
||||||
|
ogs_time_t now;
|
||||||
|
|
||||||
|
now = ogs_time_now(); /* we need UTC for start_time and end_time */
|
||||||
|
|
||||||
|
if (urr_acc->last_report.timestamp)
|
||||||
|
last_report_timestamp = urr_acc->last_report.timestamp;
|
||||||
|
else
|
||||||
|
last_report_timestamp = ogs_time_from_ntp32(urr_acc->time_threshold_start);
|
||||||
|
|
||||||
|
report->type.usage_report = 1;
|
||||||
|
report->usage_report[idx].id = urr->id;
|
||||||
|
report->usage_report[idx].seqn = urr_acc->report_seqn++;
|
||||||
|
report->usage_report[idx].start_time = urr_acc->time_threshold_start;
|
||||||
|
report->usage_report[idx].end_time = ogs_time_to_ntp32(now);
|
||||||
|
report->usage_report[idx].vol_measurement = (ogs_pfcp_volume_measurement_t){
|
||||||
|
.dlnop = 1,
|
||||||
|
.ulnop = 1,
|
||||||
|
.tonop = 1,
|
||||||
|
.dlvol = 1,
|
||||||
|
.ulvol = 1,
|
||||||
|
.tovol = 1,
|
||||||
|
.total_volume = urr_acc->total_octets - urr_acc->last_report.total_octets,
|
||||||
|
.uplink_volume = urr_acc->ul_octets - urr_acc->last_report.ul_octets,
|
||||||
|
.downlink_volume = urr_acc->dl_octets - urr_acc->last_report.dl_octets,
|
||||||
|
.total_n_packets = urr_acc->total_pkts - urr_acc->last_report.total_pkts,
|
||||||
|
.uplink_n_packets = urr_acc->ul_pkts - urr_acc->last_report.ul_pkts,
|
||||||
|
.downlink_n_packets = urr_acc->dl_pkts - urr_acc->last_report.dl_pkts,
|
||||||
|
};
|
||||||
|
if (now >= last_report_timestamp)
|
||||||
|
report->usage_report[idx].dur_measurement = ((now - last_report_timestamp) + (OGS_USEC_PER_SEC/2)) / OGS_USEC_PER_SEC; /* FIXME: should use MONOTONIC here */
|
||||||
|
/* else memset sets it to 0 */
|
||||||
|
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);
|
||||||
|
|
||||||
|
if (urr->time_threshold > 0 &&
|
||||||
|
report->usage_report[idx].dur_measurement >= urr->time_threshold)
|
||||||
|
report->usage_report[idx].rep_trigger.time_threshold = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void upf_sess_urr_acc_snapshot(upf_sess_t *sess, ogs_pfcp_urr_t *urr)
|
||||||
|
{
|
||||||
|
upf_sess_urr_acc_t *urr_acc = &sess->urr_acc[urr->id];
|
||||||
|
urr_acc->last_report.total_octets = urr_acc->total_octets;
|
||||||
|
urr_acc->last_report.dl_octets = urr_acc->dl_octets;
|
||||||
|
urr_acc->last_report.ul_octets = urr_acc->ul_octets;
|
||||||
|
urr_acc->last_report.total_pkts = urr_acc->total_pkts;
|
||||||
|
urr_acc->last_report.dl_pkts = urr_acc->dl_pkts;
|
||||||
|
urr_acc->last_report.ul_pkts = urr_acc->ul_pkts;
|
||||||
|
urr_acc->last_report.timestamp = ogs_time_now();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void upf_sess_urr_acc_time_threshold_cb(void *data)
|
||||||
|
{
|
||||||
|
ogs_pfcp_urr_t *urr = (ogs_pfcp_urr_t *)data;
|
||||||
|
ogs_pfcp_user_plane_report_t report;
|
||||||
|
ogs_pfcp_sess_t *pfcp_sess = urr->sess;
|
||||||
|
upf_sess_t *sess = UPF_SESS(pfcp_sess);
|
||||||
|
|
||||||
|
ogs_warn("upf_time_threshold_cb() triggered! urr=%p", urr);
|
||||||
|
|
||||||
|
if (urr->rep_triggers.time_threshold) {
|
||||||
|
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_time_threshold_setup(sess, urr);
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
if (!urr_acc->t_time_threshold)
|
||||||
|
urr_acc->t_time_threshold = ogs_timer_add(ogs_app()->timer_mgr,
|
||||||
|
upf_sess_urr_acc_time_threshold_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);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void upf_sess_urr_acc_remove_all(upf_sess_t *sess)
|
||||||
|
{
|
||||||
|
unsigned int i;
|
||||||
|
for (i = 0; i < OGS_ARRAY_SIZE(sess->urr_acc); i++) {
|
||||||
|
if (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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -52,6 +52,32 @@ typedef struct upf_context_s {
|
||||||
ogs_list_t sess_list;
|
ogs_list_t sess_list;
|
||||||
} upf_context_t;
|
} upf_context_t;
|
||||||
|
|
||||||
|
/* Accounting: */
|
||||||
|
typedef struct upf_sess_urr_acc_s {
|
||||||
|
bool reporting_enabled;
|
||||||
|
ogs_timer_t *t_time_threshold; /* Time threshold expiration handler */
|
||||||
|
uint32_t time_threshold_start; /* When t_time_threshold started */
|
||||||
|
ogs_pfcp_urr_ur_seqn_t report_seqn; /* Next seqn to use when reporting */
|
||||||
|
uint64_t total_octets;
|
||||||
|
uint64_t ul_octets;
|
||||||
|
uint64_t dl_octets;
|
||||||
|
uint64_t total_pkts;
|
||||||
|
uint64_t ul_pkts;
|
||||||
|
uint64_t dl_pkts;
|
||||||
|
ogs_time_t time_of_first_packet;
|
||||||
|
ogs_time_t time_of_last_packet;
|
||||||
|
/* Snapshot of measurement when last report was sent: */
|
||||||
|
struct {
|
||||||
|
uint64_t total_octets;
|
||||||
|
uint64_t ul_octets;
|
||||||
|
uint64_t dl_octets;
|
||||||
|
uint64_t total_pkts;
|
||||||
|
uint64_t ul_pkts;
|
||||||
|
uint64_t dl_pkts;
|
||||||
|
ogs_time_t timestamp;
|
||||||
|
} last_report;
|
||||||
|
} upf_sess_urr_acc_t;
|
||||||
|
|
||||||
#define UPF_SESS(pfcp_sess) ogs_container_of(pfcp_sess, upf_sess_t, pfcp)
|
#define UPF_SESS(pfcp_sess) ogs_container_of(pfcp_sess, upf_sess_t, pfcp)
|
||||||
typedef struct upf_sess_s {
|
typedef struct upf_sess_s {
|
||||||
ogs_lnode_t lnode;
|
ogs_lnode_t lnode;
|
||||||
|
@ -68,6 +94,9 @@ typedef struct upf_sess_s {
|
||||||
|
|
||||||
char *gx_sid; /* Gx Session ID */
|
char *gx_sid; /* Gx Session ID */
|
||||||
ogs_pfcp_node_t *pfcp_node;
|
ogs_pfcp_node_t *pfcp_node;
|
||||||
|
|
||||||
|
/* Accounting: */
|
||||||
|
upf_sess_urr_acc_t urr_acc[OGS_MAX_NUM_OF_URR]; /* FIXME: This probably needs to be mved to a hashtable or alike */
|
||||||
} upf_sess_t;
|
} upf_sess_t;
|
||||||
|
|
||||||
void upf_context_init(void);
|
void upf_context_init(void);
|
||||||
|
@ -90,6 +119,12 @@ upf_sess_t *upf_sess_find_by_ipv6(uint32_t *addr6);
|
||||||
uint8_t upf_sess_set_ue_ip(upf_sess_t *sess,
|
uint8_t upf_sess_set_ue_ip(upf_sess_t *sess,
|
||||||
uint8_t session_type, ogs_pfcp_pdr_t *pdr);
|
uint8_t session_type, ogs_pfcp_pdr_t *pdr);
|
||||||
|
|
||||||
|
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_fill_usage_report(upf_sess_t *sess, const ogs_pfcp_urr_t *urr,
|
||||||
|
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_time_threshold_setup(upf_sess_t *sess, ogs_pfcp_urr_t *urr);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -79,6 +79,7 @@ static void _gtpv1_tun_recv_common_cb(
|
||||||
ogs_pfcp_pdr_t *fallback_pdr = NULL;
|
ogs_pfcp_pdr_t *fallback_pdr = NULL;
|
||||||
ogs_pfcp_far_t *far = NULL;
|
ogs_pfcp_far_t *far = NULL;
|
||||||
ogs_pfcp_user_plane_report_t report;
|
ogs_pfcp_user_plane_report_t report;
|
||||||
|
int i;
|
||||||
|
|
||||||
recvbuf = ogs_tun_read(fd, packet_pool);
|
recvbuf = ogs_tun_read(fd, packet_pool);
|
||||||
if (!recvbuf) {
|
if (!recvbuf) {
|
||||||
|
@ -174,6 +175,10 @@ static void _gtpv1_tun_recv_common_cb(
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Increment total & dl octets + pkts */
|
||||||
|
for (i = 0; i < pdr->num_of_urr; i++)
|
||||||
|
upf_sess_urr_acc_add(sess, pdr->urr[i], recvbuf->len, false);
|
||||||
|
|
||||||
ogs_assert(true == ogs_pfcp_up_handle_pdr(pdr, recvbuf, &report));
|
ogs_assert(true == ogs_pfcp_up_handle_pdr(pdr, recvbuf, &report));
|
||||||
|
|
||||||
if (report.type.downlink_data_report) {
|
if (report.type.downlink_data_report) {
|
||||||
|
@ -348,6 +353,7 @@ static void _gtpv1_u_recv_cb(short when, ogs_socket_t fd, void *data)
|
||||||
|
|
||||||
ogs_pfcp_subnet_t *subnet = NULL;
|
ogs_pfcp_subnet_t *subnet = NULL;
|
||||||
ogs_pfcp_dev_t *dev = NULL;
|
ogs_pfcp_dev_t *dev = NULL;
|
||||||
|
int i;
|
||||||
|
|
||||||
ip_h = (struct ip *)pkbuf->data;
|
ip_h = (struct ip *)pkbuf->data;
|
||||||
ogs_assert(ip_h);
|
ogs_assert(ip_h);
|
||||||
|
@ -513,6 +519,10 @@ static void _gtpv1_u_recv_cb(short when, ogs_socket_t fd, void *data)
|
||||||
dev = subnet->dev;
|
dev = subnet->dev;
|
||||||
ogs_assert(dev);
|
ogs_assert(dev);
|
||||||
|
|
||||||
|
/* Increment total & ul octets + pkts */
|
||||||
|
for (i = 0; i < pdr->num_of_urr; i++)
|
||||||
|
upf_sess_urr_acc_add(sess, pdr->urr[i], pkbuf->len, true);
|
||||||
|
|
||||||
if (dev->is_tap) {
|
if (dev->is_tap) {
|
||||||
ogs_assert(eth_type);
|
ogs_assert(eth_type);
|
||||||
eth_type = htobe16(eth_type);
|
eth_type = htobe16(eth_type);
|
||||||
|
|
|
@ -111,18 +111,21 @@ ogs_pkbuf_t *upf_n4_build_session_modification_response(uint8_t type,
|
||||||
ogs_pkbuf_t *upf_n4_build_session_deletion_response(uint8_t type,
|
ogs_pkbuf_t *upf_n4_build_session_deletion_response(uint8_t type,
|
||||||
upf_sess_t *sess)
|
upf_sess_t *sess)
|
||||||
{
|
{
|
||||||
ogs_pfcp_message_t pfcp_message;
|
ogs_pfcp_urr_t *urr = NULL;
|
||||||
ogs_pfcp_session_deletion_response_t *rsp = NULL;
|
ogs_pfcp_user_plane_report_t report;
|
||||||
|
size_t num_of_reports = 0;
|
||||||
ogs_debug("Session Deletion Response");
|
ogs_debug("Session Deletion Response");
|
||||||
|
|
||||||
rsp = &pfcp_message.pfcp_session_deletion_response;
|
memset(&report, 0, sizeof(report));
|
||||||
memset(&pfcp_message, 0, sizeof(ogs_pfcp_message_t));
|
ogs_list_for_each(&sess->pfcp.urr_list, urr) {
|
||||||
|
ogs_assert(num_of_reports < OGS_ARRAY_SIZE(report.usage_report));
|
||||||
|
upf_sess_urr_acc_fill_usage_report(sess, urr, &report, num_of_reports);
|
||||||
|
report.usage_report[num_of_reports].rep_trigger.termination_report = 1;
|
||||||
|
num_of_reports++;
|
||||||
|
upf_sess_urr_acc_snapshot(sess, urr);
|
||||||
|
}
|
||||||
|
report.num_of_usage_report = num_of_reports;
|
||||||
|
|
||||||
/* Cause */
|
return ogs_pfcp_build_session_deletion_response(type, OGS_PFCP_CAUSE_REQUEST_ACCEPTED,
|
||||||
rsp->cause.presence = 1;
|
&report);
|
||||||
rsp->cause.u8 = OGS_PFCP_CAUSE_REQUEST_ACCEPTED;
|
|
||||||
|
|
||||||
pfcp_message.h.type = type;
|
|
||||||
return ogs_pfcp_build_msg(&pfcp_message);
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,6 +22,30 @@
|
||||||
#include "gtp-path.h"
|
#include "gtp-path.h"
|
||||||
#include "n4-handler.h"
|
#include "n4-handler.h"
|
||||||
|
|
||||||
|
static void upf_n4_handle_create_urr(upf_sess_t *sess, ogs_pfcp_tlv_create_urr_t *create_urr_arr,
|
||||||
|
uint8_t *cause_value, uint8_t *offending_ie_value)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
ogs_pfcp_urr_t *urr;
|
||||||
|
|
||||||
|
*cause_value = OGS_PFCP_CAUSE_REQUEST_ACCEPTED;
|
||||||
|
|
||||||
|
for (i = 0; i < OGS_MAX_NUM_OF_URR; i++) {
|
||||||
|
urr = ogs_pfcp_handle_create_urr(&sess->pfcp, &create_urr_arr[i],
|
||||||
|
cause_value, offending_ie_value);
|
||||||
|
if (!urr)
|
||||||
|
return;
|
||||||
|
|
||||||
|
/* TODO: here we should check for Reporting Triggers IMTH=1 instead? */
|
||||||
|
if ((urr->meas_method & OGS_PFCP_MEASUREMENT_METHOD_DURATION) && urr->time_threshold > 0) {
|
||||||
|
/* if ISTM bit set in Measurement Information: */
|
||||||
|
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 */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void upf_n4_handle_session_establishment_request(
|
void upf_n4_handle_session_establishment_request(
|
||||||
upf_sess_t *sess, ogs_pfcp_xact_t *xact,
|
upf_sess_t *sess, ogs_pfcp_xact_t *xact,
|
||||||
ogs_pfcp_session_establishment_request_t *req)
|
ogs_pfcp_session_establishment_request_t *req)
|
||||||
|
@ -67,11 +91,7 @@ void upf_n4_handle_session_establishment_request(
|
||||||
if (cause_value != OGS_PFCP_CAUSE_REQUEST_ACCEPTED)
|
if (cause_value != OGS_PFCP_CAUSE_REQUEST_ACCEPTED)
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
|
|
||||||
for (i = 0; i < OGS_MAX_NUM_OF_URR; i++) {
|
upf_n4_handle_create_urr(sess, &req->create_urr[0], &cause_value, &offending_ie_value);
|
||||||
if (ogs_pfcp_handle_create_urr(&sess->pfcp, &req->create_urr[i],
|
|
||||||
&cause_value, &offending_ie_value) == NULL)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (cause_value != OGS_PFCP_CAUSE_REQUEST_ACCEPTED)
|
if (cause_value != OGS_PFCP_CAUSE_REQUEST_ACCEPTED)
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
|
|
||||||
|
@ -272,11 +292,7 @@ void upf_n4_handle_session_modification_request(
|
||||||
if (cause_value != OGS_PFCP_CAUSE_REQUEST_ACCEPTED)
|
if (cause_value != OGS_PFCP_CAUSE_REQUEST_ACCEPTED)
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
|
|
||||||
for (i = 0; i < OGS_MAX_NUM_OF_URR; i++) {
|
upf_n4_handle_create_urr(sess, &req->create_urr[0], &cause_value, &offending_ie_value);
|
||||||
if (ogs_pfcp_handle_create_urr(&sess->pfcp, &req->create_urr[i],
|
|
||||||
&cause_value, &offending_ie_value) == NULL)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (cause_value != OGS_PFCP_CAUSE_REQUEST_ACCEPTED)
|
if (cause_value != OGS_PFCP_CAUSE_REQUEST_ACCEPTED)
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue