Skip to content

Commit 69c7af7

Browse files
committed
pfcp: Support Session Report Request (URR)
Initial support to sollicited URR request by remote SMF. Support asynchronous request report. Signed-off-by: Alexandre Cassen <acassen@gmail.com>
1 parent 6746db5 commit 69c7af7

21 files changed

+486
-66
lines changed

lib/inet_server.c

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -179,14 +179,14 @@ inet_http_read(struct inet_cnx *c)
179179
char *buffer = c->buffer_in;
180180
ssize_t nbytes, offset = 0;
181181

182-
memset(buffer, 0, INET_BUFFER_SIZE);
182+
memset(buffer, 0, DEFAULT_PKT_BUFFER_SIZE);
183183
c->buffer_in_size = 0;
184184

185185
next_rcv:
186186
if (__test_bit(INET_FL_STOP_BIT, &w->flags))
187187
return -1;
188188

189-
nbytes = read(c->fd, buffer + offset, INET_BUFFER_SIZE - offset);
189+
nbytes = read(c->fd, buffer + offset, DEFAULT_PKT_BUFFER_SIZE - offset);
190190

191191
/* data are ready ? */
192192
if (nbytes == -1 || nbytes == 0) {
@@ -203,11 +203,11 @@ inet_http_read(struct inet_cnx *c)
203203
return offset;
204204
}
205205

206-
if (offset < INET_BUFFER_SIZE)
206+
if (offset < DEFAULT_PKT_BUFFER_SIZE)
207207
goto next_rcv;
208208

209-
c->buffer_in_size = INET_BUFFER_SIZE;
210-
return INET_BUFFER_SIZE;
209+
c->buffer_in_size = DEFAULT_PKT_BUFFER_SIZE;
210+
return DEFAULT_PKT_BUFFER_SIZE;
211211
}
212212

213213
void *
@@ -620,7 +620,7 @@ inet_server_init(struct inet_server *s, int type)
620620
if (fd < 0)
621621
return -1;
622622
s->fd = fd;
623-
s->pbuff = pkt_buffer_alloc(INET_BUFFER_SIZE);
623+
s->pbuff = pkt_buffer_alloc(DEFAULT_PKT_BUFFER_SIZE);
624624
s->seed = time(NULL);
625625
srand(s->seed);
626626
break;

lib/inet_server.h

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,6 @@
3131

3232
/* Default values */
3333
#define INET_SRV_THREAD_CNT_DEFAULT 5
34-
#define INET_BUFFER_SIZE 4096
3534
#define INET_SOCKBUF_SIZE (64 * 1024)
3635

3736
/* Default TCP timer */
@@ -58,9 +57,9 @@ struct inet_cnx {
5857
struct inet_worker *worker;
5958
void *arg;
6059

61-
char buffer_in[INET_BUFFER_SIZE];
60+
char buffer_in[DEFAULT_PKT_BUFFER_SIZE];
6261
ssize_t buffer_in_size;
63-
char buffer_out[INET_BUFFER_SIZE];
62+
char buffer_out[DEFAULT_PKT_BUFFER_SIZE];
6463
ssize_t buffer_out_size;
6564

6665
unsigned long flags;

lib/pkt_buffer.c

Lines changed: 27 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -101,30 +101,46 @@ pkt_free(struct pkt *p)
101101
}
102102

103103
struct pkt *
104-
pkt_queue_get(struct pkt_queue *q)
104+
__pkt_queue_get(struct pkt_queue *q)
105105
{
106106
struct pkt *pkt;
107107

108-
pthread_mutex_lock(&q->mutex);
109-
if (list_empty(&q->queue)) {
110-
pthread_mutex_unlock(&q->mutex);
108+
if (list_empty(&q->queue))
111109
return pkt_alloc(DEFAULT_PKT_BUFFER_SIZE);
112-
}
113110

114111
pkt = list_first_entry(&q->queue, struct pkt, next);
115112
list_del_init(&pkt->next);
116-
pthread_mutex_unlock(&q->mutex);
113+
__sync_sub_and_fetch(&q->size, 1);
117114
pkt_buffer_reset(pkt->pbuff);
118115
return pkt;
119116
}
120117

118+
struct pkt *
119+
pkt_queue_get(struct pkt_queue *q)
120+
{
121+
struct pkt *pkt;
122+
123+
pthread_mutex_lock(&q->mutex);
124+
pkt = __pkt_queue_get(q);
125+
pthread_mutex_unlock(&q->mutex);
126+
127+
return pkt;
128+
}
129+
121130
int
122131
__pkt_queue_put(struct pkt_queue *q, struct pkt *p)
123132
{
124133
if (!p)
125134
return -1;
126135

136+
/* leak prevention */
137+
if (q->size >= q->max_size) {
138+
pkt_free(p);
139+
return -1;
140+
}
141+
127142
list_add_tail(&p->next, &q->queue);
143+
__sync_add_and_fetch(&q->size, 1);
128144
return 0;
129145
}
130146

@@ -138,10 +154,11 @@ pkt_queue_put(struct pkt_queue *q, struct pkt *p)
138154
}
139155

140156
int
141-
pkt_queue_init(struct pkt_queue *q)
157+
pkt_queue_init(struct pkt_queue *q, int max_size)
142158
{
143159
INIT_LIST_HEAD(&q->queue);
144160
pthread_mutex_init(&q->mutex, NULL);
161+
q->max_size = max_size;
145162
return 0;
146163
}
147164

@@ -150,6 +167,9 @@ pkt_queue_destroy(struct pkt_queue *q)
150167
{
151168
struct pkt *pkt, *_pkt;
152169

170+
if (__sync_add_and_fetch(&q->size, 0) == 0)
171+
return 0;
172+
153173
pthread_mutex_lock(&q->mutex);
154174
list_for_each_entry_safe(pkt, _pkt, &q->queue, next) {
155175
list_head_del(&pkt->next);

lib/pkt_buffer.h

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828

2929
/* defines */
3030
#define DEFAULT_PKT_BUFFER_SIZE 4096
31+
#define DEFAULT_PKT_QUEUE_SIZE 128
3132

3233
/* pkt related */
3334
struct pkt_buffer {
@@ -53,6 +54,8 @@ struct mpkt {
5354
struct pkt_queue {
5455
pthread_mutex_t mutex;
5556
struct list_head queue;
57+
int size;
58+
int max_size;
5659
};
5760

5861
static inline unsigned int pkt_buffer_len(struct pkt_buffer *b)
@@ -109,9 +112,12 @@ static inline void pkt_buffer_put_end(struct pkt_buffer *b, unsigned int offset)
109112
ssize_t pkt_send(int fd, struct pkt_queue *q, struct pkt *p);
110113
ssize_t pkt_recv(int fd, struct pkt *p);
111114
void pkt_queue_run(struct pkt_queue *q, int (*run) (struct pkt *, void *), void *arg);
115+
struct pkt *__pkt_queue_get(struct pkt_queue *q);
112116
struct pkt *pkt_queue_get(struct pkt_queue *q);
113117
int __pkt_queue_put(struct pkt_queue *q, struct pkt *p);
114118
int pkt_queue_put(struct pkt_queue *, struct pkt *p);
119+
int pkt_queue_init(struct pkt_queue *q, int max_size);
120+
int pkt_queue_destroy(struct pkt_queue *q);
115121
int mpkt_dump(struct mpkt *p, int count);
116122
int mpkt_recv(int fd, struct mpkt *mp);
117123
int mpkt_init(struct mpkt *p, unsigned int vlen);
@@ -122,8 +128,6 @@ int __pkt_queue_mget(struct pkt_queue *q, struct mpkt *mp);
122128
int pkt_queue_mget(struct pkt_queue *q, struct mpkt *mp);
123129
int __pkt_queue_mput(struct pkt_queue *q, struct mpkt *mp);
124130
int pkt_queue_mput(struct pkt_queue *q, struct mpkt *mp);
125-
int pkt_queue_init(struct pkt_queue *q);
126-
int pkt_queue_destroy(struct pkt_queue *q);
127131
ssize_t pkt_buffer_send(int fd, struct pkt_buffer *b, struct sockaddr_storage *addr);
128132
int pkt_buffer_put_zero(struct pkt_buffer *pkt, unsigned int size);
129133
int pkt_buffer_pad(struct pkt_buffer *b, unsigned int size);

src/gtp_request.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ gtp_request_json_parse_cmd(struct inet_cnx *c, struct json_node *json)
7171
goto end;
7272
}
7373

74-
gtp_apn_extract_str_ni(apn_str, strlen(apn_str), c->buffer_out, INET_BUFFER_SIZE);
74+
gtp_apn_extract_str_ni(apn_str, strlen(apn_str), c->buffer_out, DEFAULT_PKT_BUFFER_SIZE);
7575
apn = gtp_apn_get(c->buffer_out);
7676
if (!apn) {
7777
jsonw_string_field(jwriter, "Error", "Unknown Access-Point-Name");

src/pfcp/include/pfcp_ie.h

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222

2323
#include <stdint.h>
2424
#include <netinet/in.h>
25+
#include <stdbool.h>
2526
#include <endian.h>
2627

2728
#include "pfcp_metrics.h"
@@ -283,7 +284,6 @@ enum pfcp_ie_type {
283284
PFCP_IE_USER_PLANE_PATH_FAILURE_REPORT = 102,
284285
PFCP_IE_UPDATE_DUPLICATING_PARAMETERS = 105,
285286
PFCP_IE_AGGREGATED_URRS = 118,
286-
PFCP_IE_ADDITIONAL_USAGE_REPORT_INFORMATION = 126,
287287
PFCP_IE_CREATE_TRAFFIC_ENDPOINT = 127,
288288
PFCP_IE_CREATED_TRAFFIC_ENDPOINT = 128,
289289
PFCP_IE_UPDATE_TRAFFIC_ENDPOINT = 129,
@@ -596,6 +596,7 @@ struct pfcp_ie_redirect_information {
596596
} __attribute__((packed));
597597

598598
/* Report Type IE */
599+
#define PFCP_IE_REPORT_TYPE_USAR 0x02
599600
struct pfcp_ie_report_type {
600601
struct pfcp_ie h;
601602
union {
@@ -3479,7 +3480,14 @@ int pfcp_ie_put_created_te(struct pkt_buffer *pbuff, const uint8_t id,
34793480
const uint32_t teid,
34803481
const struct in_addr *t_ipv4, const struct in6_addr *t_ipv6,
34813482
const struct in_addr *ue_ipv4, const struct in6_addr *ue_ipv6);
3482-
int pfcp_ie_put_usage_report(struct pkt_buffer *pbuff, uint32_t id,
3483-
uint32_t start_time, uint32_t end_time,
3484-
struct pfcp_metrics_pkt *uplink,
3485-
struct pfcp_metrics_pkt *downlink);
3483+
int pfcp_ie_put_usage_report_deletion(struct pkt_buffer *pbuff, uint32_t id,
3484+
uint32_t start_time, uint32_t end_time, uint32_t seqn,
3485+
struct pfcp_metrics_pkt *uplink,
3486+
struct pfcp_metrics_pkt *downlink);
3487+
int pfcp_ie_put_usage_report_request(struct pkt_buffer *pbuff, uint32_t query_urr_ref,
3488+
uint32_t id, uint32_t start_time, uint32_t end_time,
3489+
uint32_t seqn, struct pfcp_metrics_pkt *uplink,
3490+
struct pfcp_metrics_pkt *downlink);
3491+
int pfcp_ie_put_report_type(struct pkt_buffer *pbuff, uint8_t type);
3492+
int pfcp_ie_put_additional_usage_reports_info(struct pkt_buffer *pbuff, bool auri,
3493+
uint16_t nr_reports);

src/pfcp/include/pfcp_metrics.h

Lines changed: 33 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -44,10 +44,38 @@ struct pfcp_metrics_pkt {
4444
uint64_t bytes;
4545
};
4646

47+
static inline int pfcp_metrics_pkt_is_null(struct pfcp_metrics_pkt *p)
48+
{
49+
return !p->count && !p->bytes;
50+
}
51+
52+
static inline int __attribute__((pure))
53+
pfcp_metrics_pkt_cmp(struct pfcp_metrics_pkt *a, struct pfcp_metrics_pkt *b)
54+
{
55+
if (a->bytes > b->bytes)
56+
return 1;
57+
if (a->bytes < b->bytes)
58+
return -1;
59+
if (a->count > b->count)
60+
return 1;
61+
if (a->count < b->count)
62+
return -1;
63+
return 0;
64+
}
65+
66+
static inline void
67+
pfcp_metrics_pkt_cpy(struct pfcp_metrics_pkt *a, struct pfcp_metrics_pkt *b)
68+
{
69+
a->bytes = b->bytes;
70+
a->count = b->count;
71+
}
72+
4773

4874
/* Prototypes */
49-
int pfcp_metrics_rx(struct pfcp_metrics_msg *, uint8_t);
50-
int pfcp_metrics_rx_notsup(struct pfcp_metrics_msg *, uint8_t);
51-
int pfcp_metrics_tx(struct pfcp_metrics_msg *, uint8_t);
52-
int pfcp_metrics_tx_notsup(struct pfcp_metrics_msg *, uint8_t);
53-
int pfcp_metrics_pkt_update(struct pfcp_metrics_pkt *, ssize_t);
75+
int pfcp_metrics_rx(struct pfcp_metrics_msg *m, uint8_t msg_types);
76+
int pfcp_metrics_rx_notsup(struct pfcp_metrics_msg *m, uint8_t msg_types);
77+
int pfcp_metrics_tx(struct pfcp_metrics_msg *m, uint8_t msg_types);
78+
int pfcp_metrics_tx_notsup(struct pfcp_metrics_msg *m, uint8_t msg_types);
79+
int pfcp_metrics_pkt_update(struct pfcp_metrics_pkt *m, ssize_t nbytes);
80+
void pfcp_metrics_pkt_sub(struct pfcp_metrics_pkt *a, struct pfcp_metrics_pkt *b,
81+
struct pfcp_metrics_pkt *r);

src/pfcp/include/pfcp_msg.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -262,7 +262,7 @@ struct pfcp_session_modification_request {
262262
/* Optional IEs */
263263
struct pfcp_ie_f_seid *cp_f_seid;
264264
struct pfcp_ie_pfcpsmreq_flags *pfcpsmreq_flags;
265-
struct pfcp_ie_query_urr *query_urr;
265+
struct pfcp_ie_query_urr **query_urr;
266266
struct pfcp_ie_fq_csid *pgw_c_fq_csid;
267267
struct pfcp_ie_fq_csid *sgw_c_fq_csid;
268268
struct pfcp_ie_fq_csid *mme_fq_csid;
@@ -302,6 +302,7 @@ struct pfcp_session_modification_request {
302302
struct pfcp_ie_update_mar **update_mar;
303303
struct pfcp_ie_update_srr **update_srr;
304304
/* Counters */
305+
int nr_query_urr;
305306
int nr_remove_pdr;
306307
int nr_remove_far;
307308
int nr_remove_urr;
@@ -430,6 +431,8 @@ struct pfcp_msg {
430431
/* Prototypes */
431432
int pfcp_msg_hlen(struct pkt_buffer *pbuff);
432433
int pfcp_msg_reset_hlen(struct pkt_buffer *pbuff);
434+
int pfcp_msg_header_init(struct pkt_buffer *pbuff, uint8_t msg_type,
435+
uint64_t seid, uint32_t seqn);
433436
int pfcp_msg_parse(struct pfcp_msg *msg, struct pkt_buffer *pbuff);
434437
struct pfcp_msg *pfcp_msg_alloc(int scheme);
435438
void pfcp_msg_free(struct pfcp_msg *msg);

src/pfcp/include/pfcp_server.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,8 @@ enum pfcp_server_flags {
3232
struct pfcp_server {
3333
struct inet_server s;
3434
struct pfcp_msg *msg;
35+
struct pkt_queue pkt_q;
36+
uint32_t seqn;
3537
void *ctx; /* context back-pointer */
3638

3739
/* metrics */

src/pfcp/include/pfcp_session.h

Lines changed: 23 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -104,16 +104,19 @@ struct urr {
104104
uint64_t volume_threshold_ul;
105105
uint64_t volume_threshold_dl;
106106

107-
/* Linked urr */
107+
/* parent/Linked urr */
108+
struct urr *parent_urr;
108109
uint32_t linked_urr_id;
109110
struct urr *linked_urr;
110111

111112
/* metrics */
112113
uint32_t seqn;
113114
uint32_t start_time;
114115
uint32_t end_time;
115-
struct pfcp_metrics_pkt uplink;
116-
struct pfcp_metrics_pkt downlink;
116+
struct pfcp_metrics_pkt ul;
117+
struct pfcp_metrics_pkt dl;
118+
struct pfcp_metrics_pkt last_report_ul;
119+
struct pfcp_metrics_pkt last_report_dl;
117120
};
118121

119122
struct pdr {
@@ -150,6 +153,12 @@ struct fwd_rule {
150153

151154

152155
/* PFCP session */
156+
struct pfcp_report {
157+
struct sockaddr_storage addr;
158+
uint32_t query_urr_ref;
159+
uint32_t urr_id[PFCP_MAX_NR_ELEM];
160+
};
161+
153162
struct pfcp_session {
154163
uint64_t seid;
155164
struct f_seid remote_seid;
@@ -159,6 +168,12 @@ struct pfcp_session {
159168
struct qer qer[PFCP_MAX_NR_ELEM];
160169
struct urr urr[PFCP_MAX_NR_ELEM];
161170
struct traffic_endpoint te[PFCP_MAX_NR_ELEM];
171+
int nr_pdr;
172+
int nr_far;
173+
int nr_qer;
174+
int nr_urr;
175+
int nr_te;
176+
162177
struct ue_ip_address ue_ip;
163178
int teid_cnt;
164179

@@ -172,6 +187,9 @@ struct pfcp_session {
172187
/* eBPF forwarding rules related */
173188
struct list_head fwd_rules;
174189

190+
/* Reporting context */
191+
struct pfcp_report report;
192+
175193
/* Expiration handling */
176194
char tmp_str[64];
177195
struct tm creation_time;
@@ -212,6 +230,6 @@ int pfcp_session_put_created_pdr(struct pkt_buffer *pbuff,
212230
struct pfcp_session *s);
213231
int pfcp_session_put_created_traffic_endpoint(struct pkt_buffer *pbuff,
214232
struct pfcp_session *s);
215-
int pfcp_session_put_usage_report(struct pkt_buffer *pbuff,
216-
struct pfcp_session *s);
233+
int pfcp_session_put_usage_report_deletion(struct pkt_buffer *pbuff,
234+
struct pfcp_session *s);
217235
int pfcp_session_bpf_action(struct pfcp_session *s, int action);

0 commit comments

Comments
 (0)