Skip to content

Commit ebf18e1

Browse files
committed
KPI: add stats and show workers gtp-router
Dump the gtp-router workers. The stats include, per direction: - GTPc processed and emit'd types - GTPc processed causes - GTPu processed and emit'd types We get: > show workers gtp-router * plane gtpc ... rx:2126bytes 11pkt | tx:49bytes 3pkt RX: GTP_ECHO_REQUEST_TYPE(1): 2 GTP_CREATE_SESSION_REQUEST_TYPE(32): 7 GTP_MODIFY_BEARER_REQUEST_TYPE(34): 1 GTP_DELETE_BEARER_RESPONSE(100): 1 (not supported) TX: GTP_ECHO_RESPONSE_TYPE(2): 2 GTP_CAUSE_REQUEST_ACCEPTED(16): 3 GTP_CREATE_SESSION_RESPONSE_TYPE(33): 1 GTP_MODIFY_BEARER_RESPONSE_TYPE(35): 1 GTP_DELETE_BEARER_REQUEST(99): 4
1 parent 061227a commit ebf18e1

File tree

4 files changed

+220
-8
lines changed

4 files changed

+220
-8
lines changed

src/gtp_router_hdl.c

+25-8
Original file line numberDiff line numberDiff line change
@@ -278,13 +278,16 @@ gtpc_pkt_put_mei(pkt_buffer_t *pbuff, uint64_t mei)
278278
}
279279

280280
static int
281-
gtpc_pkt_put_cause(pkt_buffer_t *pbuff, uint8_t cause)
281+
gtpc_pkt_put_cause(pkt_buffer_t *pbuff, uint8_t cause, gtp_teid_t *teid)
282282
{
283283
gtp_ie_cause_t *ie;
284284

285285
if (gtpc_pkt_put_ie(pbuff, GTP_IE_CAUSE_TYPE, sizeof(gtp_ie_cause_t)) < 0)
286286
return 1;
287287

288+
/* a tx pkt */
289+
teid->session->w->cause_stats.tx[cause].count++;
290+
288291
ie = (gtp_ie_cause_t *) pbuff->data;
289292
ie->value = cause;
290293
pkt_buffer_put_data(pbuff, sizeof(gtp_ie_cause_t));
@@ -580,7 +583,7 @@ gtpc_pkt_put_bearer_context(pkt_buffer_t *pbuff, gtp_session_t *s, gtp_teid_t *t
580583
pkt_buffer_put_data(pbuff, sizeof(gtp_ie_bearer_context_t));
581584

582585
err = err ? : gtpc_pkt_put_eps_bearer_id(pbuff, apn->eps_bearer_id);
583-
err = err ? : gtpc_pkt_put_cause(pbuff, GTP_CAUSE_REQUEST_ACCEPTED);
586+
err = err ? : gtpc_pkt_put_cause(pbuff, GTP_CAUSE_REQUEST_ACCEPTED, teid);
584587
err = err ? : gtpc_pkt_put_f_teid(pbuff, teid, 2, GTP_TEID_INTERFACE_TYPE_SGW_GTPU);
585588
err = err ? : gtpc_pkt_put_charging_id(pbuff, s->charging_id);
586589
if (err)
@@ -602,6 +605,9 @@ gtpc_build_header(pkt_buffer_t *pbuff, gtp_teid_t *teid, uint8_t type)
602605
{
603606
gtp_hdr_t *h = (gtp_hdr_t *) pbuff->head;
604607

608+
/* a tx pkt */
609+
teid->session->w->msg_stats.tx[type].count++;
610+
605611
h->version = 2;
606612
h->type = type;
607613
h->teid_presence = 1;
@@ -625,7 +631,7 @@ gtpc_build_create_session_response(pkt_buffer_t *pbuff, gtp_session_t *s, gtp_te
625631
gtpc_build_header(pbuff, teid, GTP_CREATE_SESSION_RESPONSE_TYPE);
626632

627633
/* Put IE */
628-
err = err ? : gtpc_pkt_put_cause(pbuff, GTP_CAUSE_REQUEST_ACCEPTED);
634+
err = err ? : gtpc_pkt_put_cause(pbuff, GTP_CAUSE_REQUEST_ACCEPTED, teid);
629635
err = err ? : gtpc_pkt_put_recovery(pbuff);
630636
err = err ? : gtpc_pkt_put_indication(pbuff, apn->indication_flags);
631637
err = err ? : gtpc_pkt_put_pco(pbuff, apn->pco, ipcp);
@@ -656,7 +662,7 @@ gtpc_build_change_notification_response(pkt_buffer_t *pbuff, gtp_session_t *s, g
656662
/* Put IE */
657663
err = err ? : gtpc_pkt_put_imsi(pbuff, s->conn->imsi);
658664
err = err ? : gtpc_pkt_put_mei(pbuff, s->mei);
659-
err = err ? : gtpc_pkt_put_cause(pbuff, GTP_CAUSE_REQUEST_ACCEPTED);
665+
err = err ? : gtpc_pkt_put_cause(pbuff, GTP_CAUSE_REQUEST_ACCEPTED, teid);
660666
if (err) {
661667
log_message(LOG_INFO, "%s(): Error building PKT !?"
662668
, __FUNCTION__);
@@ -678,7 +684,7 @@ gtpc_build_errmsg(pkt_buffer_t *pbuff, gtp_teid_t *teid, uint8_t type, uint8_t c
678684
gtpc_build_header(pbuff, teid, type);
679685

680686
/* Put IE */
681-
err = err ? : gtpc_pkt_put_cause(pbuff, cause);
687+
err = err ? : gtpc_pkt_put_cause(pbuff, cause, teid);
682688
err = err ? : gtpc_pkt_put_recovery(pbuff);
683689
if (err)
684690
return -1;
@@ -705,7 +711,7 @@ gtpc_build_delete_bearer_request(pkt_buffer_t *pbuff, gtp_teid_t *teid, uint8_t
705711
/* Put IE */
706712
err = err ? : gtpc_pkt_put_eps_bearer_id(pbuff, bearer_id);
707713
if (cause)
708-
err = err ? : gtpc_pkt_put_cause(pbuff, cause);
714+
err = err ? : gtpc_pkt_put_cause(pbuff, cause, teid);
709715
if (err)
710716
return -1;
711717

@@ -879,6 +885,9 @@ gtpc_echo_request_hdl(gtp_server_worker_t *w, struct sockaddr_storage *addr)
879885

880886
h->type = GTP_ECHO_RESPONSE_TYPE;
881887

888+
/* it does not use gtpc_build_header(), so count from here */
889+
w->msg_stats.tx[h->type].count++;
890+
882891
return 0;
883892
}
884893

@@ -1281,10 +1290,13 @@ gtpc_router_handle(gtp_server_worker_t *w, struct sockaddr_storage *addr)
12811290
{
12821291
gtp_hdr_t *gtph = (gtp_hdr_t *) w->pbuff->head;
12831292

1284-
if (*(gtpc_msg_hdl[gtph->type].hdl))
1293+
if (*(gtpc_msg_hdl[gtph->type].hdl)) {
1294+
w->msg_stats.rx[gtph->type].count++;
12851295
return (*(gtpc_msg_hdl[gtph->type].hdl)) (w, addr);
1296+
}
12861297

12871298
/* In router mode, silently ignore message we do not support */
1299+
w->msg_stats.rx[gtph->type].unsupported++;
12881300
return -1;
12891301
}
12901302

@@ -1305,6 +1317,8 @@ gtpu_echo_request_hdl(gtp_server_worker_t *w, struct sockaddr_storage *addr)
13051317
pkt_buffer_set_end_pointer(w->pbuff, gtp1_get_header_len(h));
13061318
pkt_buffer_set_data_pointer(w->pbuff, gtp1_get_header_len(h));
13071319

1320+
w->msg_stats.tx[h->type].count++;
1321+
13081322
gtp1_ie_add_tail(w->pbuff, sizeof(gtp1_ie_recovery_t));
13091323
rec = (gtp1_ie_recovery_t *) w->pbuff->data;
13101324
rec->type = GTP1_IE_RECOVERY_TYPE;
@@ -1344,13 +1358,16 @@ gtpu_router_handle(gtp_server_worker_t *w, struct sockaddr_storage *addr)
13441358
if (len < 0)
13451359
return -1;
13461360

1347-
if (*(gtpu_msg_hdl[gtph->type].hdl))
1361+
if (*(gtpu_msg_hdl[gtph->type].hdl)) {
1362+
w->msg_stats.rx[gtph->type].count++;
13481363
return (*(gtpu_msg_hdl[gtph->type].hdl)) (w, addr);
1364+
}
13491365

13501366
/* Not supported */
13511367
log_message(LOG_INFO, "%s(): GTP-U/path-mgt msg_type:0x%.2x from %s not supported..."
13521368
, __FUNCTION__
13531369
, gtph->type
13541370
, inet_sockaddrtos(addr));
1371+
w->msg_stats.rx[gtph->type].unsupported++;
13551372
return -1;
13561373
}

src/gtp_router_vty.c

+183
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
#include <sys/stat.h>
2525
#include <net/if.h>
2626
#include <errno.h>
27+
#include <inttypes.h>
2728

2829
/* local includes */
2930
#include "gtp_guard.h"
@@ -223,6 +224,186 @@ gtp_config_write(vty_t *vty)
223224
return CMD_SUCCESS;
224225
}
225226

227+
/* XXX TODO, extend gtp_server_for_each_worker(gtp_server_t *srv, int (*hdl) (gtp_server_worker_t *)) */
228+
static int
229+
_gtp_server_for_each_worker(gtp_server_t *srv, int (*cb) (gtp_server_worker_t *, void *), void *arg)
230+
{
231+
gtp_server_worker_t *w;
232+
233+
pthread_mutex_lock(&srv->workers_mutex);
234+
list_for_each_entry(w, &srv->workers, next)
235+
(*cb) (w, arg);
236+
pthread_mutex_unlock(&srv->workers_mutex);
237+
return 0;
238+
}
239+
240+
struct vty_server_work_arg {
241+
vty_t *vty;
242+
const gtp_msg_type_map_t *msg_type2str;
243+
};
244+
245+
static int
246+
vty_server_worker(gtp_server_worker_t *w, void *arg)
247+
{
248+
char flags2str[BUFSIZ];
249+
vty_t *vty = ((struct vty_server_work_arg *)arg)->vty;
250+
const gtp_msg_type_map_t *msg_type2str = ((struct vty_server_work_arg *)arg)->msg_type2str;
251+
char fdpath[PATH_MAX];
252+
253+
vty_out(vty, " %s worker %d task 0x%lx fd %d (%s)%s"
254+
" flags:%s%s"
255+
" seed:%d pbuff:%p (len:%d size:%d bytes)%s"
256+
" rx:%"PRIu64"bytes %"PRIu64"pkt | tx:%"PRIu64"bytes %"PRIu64"pkt%s"
257+
, w->pname
258+
, w->id
259+
, w->task
260+
, w->fd, w->fd >= 0 ? gtp_disk_fd2filename(w->fd, fdpath, sizeof(fdpath)) : "none"
261+
, VTY_NEWLINE
262+
, gtp_flags2str(flags2str, sizeof(flags2str), w->flags)
263+
, VTY_NEWLINE
264+
, w->seed , w->pbuff
265+
, pkt_buffer_len(w->pbuff), pkt_buffer_size(w->pbuff)
266+
, VTY_NEWLINE
267+
, w->rx_bytes, w->rx_pkt
268+
, w->tx_bytes, w->tx_pkt
269+
, VTY_NEWLINE);
270+
271+
vty_out(vty, " RX:%s"
272+
, VTY_NEWLINE);
273+
for (int i = 0; i < ARRAY_SIZE(w->msg_stats.rx); i++) {
274+
if (w->msg_stats.rx[i].count != 0)
275+
vty_out(vty, " %s(%d): %d%s"
276+
, msg_type2str
277+
? msg_type2str[i].name
278+
: "null"
279+
, i
280+
, w->msg_stats.rx[i].count
281+
, VTY_NEWLINE);
282+
if (w->msg_stats.rx[i].unsupported != 0)
283+
vty_out(vty, " %s(%d): %d (not supported)%s"
284+
, msg_type2str
285+
? msg_type2str[i].name ? msg_type2str[i].name : "bad type"
286+
: "null"
287+
, i
288+
, w->msg_stats.rx[i].unsupported
289+
, VTY_NEWLINE);
290+
if (w->cause_stats.rx[i].count != 0)
291+
vty_out(vty, " %s(%d): %d%s"
292+
, gtpc_msg_cause2str[i].name ? gtpc_msg_cause2str[i].name : "bad cause"
293+
, i
294+
, w->cause_stats.rx[i].count
295+
, VTY_NEWLINE);
296+
}
297+
vty_out(vty, " TX:%s"
298+
, VTY_NEWLINE);
299+
for (int i = 0; i < ARRAY_SIZE(w->msg_stats.tx); i++) {
300+
if (w->msg_stats.tx[i].count != 0)
301+
vty_out(vty, " %s(%d): %d%s"
302+
, msg_type2str
303+
? msg_type2str[i].name
304+
: "null"
305+
, i
306+
, w->msg_stats.tx[i].count
307+
, VTY_NEWLINE);
308+
if (w->msg_stats.tx[i].unsupported != 0)
309+
vty_out(vty, " %s(%d): %d (not supported)%s"
310+
, msg_type2str
311+
? msg_type2str[i].name ? msg_type2str[i].name : "bad type"
312+
: "null"
313+
, i
314+
, w->msg_stats.tx[i].unsupported
315+
, VTY_NEWLINE);
316+
if (w->cause_stats.tx[i].count != 0)
317+
vty_out(vty, " %s(%d): %d%s"
318+
, gtpc_msg_cause2str[i].name ? gtpc_msg_cause2str[i].name : "bad cause"
319+
, i
320+
, w->cause_stats.tx[i].count
321+
, VTY_NEWLINE);
322+
}
323+
324+
return CMD_SUCCESS;
325+
}
326+
327+
static int
328+
vty_server(vty_t *vty, gtp_server_t *srv, const char *gtplane, const gtp_msg_type_map_t *msg_type2str)
329+
{
330+
char flags2str[BUFSIZ];
331+
332+
vty_out(vty, " %s: %s port %d with %d threads%s"
333+
" flags:0x%lx (%s)%s"
334+
, gtplane
335+
, inet_sockaddrtos(&srv->addr)
336+
, ntohs(inet_sockaddrport(&srv->addr))
337+
, srv->thread_cnt
338+
, VTY_NEWLINE
339+
, srv->flags, gtp_flags2str(flags2str, sizeof(flags2str), srv->flags)
340+
, VTY_NEWLINE);
341+
struct vty_server_work_arg arg = {
342+
.vty = vty,
343+
.msg_type2str = msg_type2str,
344+
};
345+
_gtp_server_for_each_worker(srv, vty_server_worker, &arg);
346+
347+
return CMD_SUCCESS;
348+
}
349+
350+
/* show handlers */
351+
DEFUN(show_workers_gtp_router,
352+
show_workers_gtp_router_cmd,
353+
"show workers gtp-router (*|STRING) [plane (gtpu|gtpc|both)]",
354+
SHOW_STR
355+
"workers tasks\n"
356+
"gtp-router gtpc and gtpu workers\n"
357+
"all workers\n"
358+
"Router name\n"
359+
"GTPu\n"
360+
"GTPc\n"
361+
"both GTPu and GTPc\n")
362+
{
363+
const list_head_t *l = &daemon_data->gtp_router_ctx;
364+
gtp_router_t *ctx;
365+
366+
const char *name = (argc > 0) ? argv[0] : "*";
367+
const char *plane = (argc > 2) ? argv[2] : "both";
368+
369+
list_for_each_entry(ctx, l, next) {
370+
char flags2str[BUFSIZ];
371+
372+
if ((name[0] != '*') && (strcmp(name, ctx->name) != 0))
373+
continue;
374+
375+
vty_out(vty, "gtp-router %s refcnt:%d%s"
376+
" flags:0x%lx (%s)%s"
377+
, ctx->name
378+
, ctx->refcnt
379+
, VTY_NEWLINE
380+
, ctx->flags, gtp_flags2str(flags2str, sizeof(flags2str), ctx->flags)
381+
, VTY_NEWLINE);
382+
383+
if ((strcmp(plane, "both") == 0) ||
384+
(strcmp(plane, "gtpc") == 0)) {
385+
gtp_server_t *srv = &ctx->gtpc;
386+
if (__test_bit(GTP_FL_CTL_BIT, &srv->flags))
387+
vty_server(vty, srv, "gtpc", gtpc_msg_type2str);
388+
else
389+
vty_out(vty, " gtpc: none%s"
390+
, VTY_NEWLINE);
391+
}
392+
393+
if ((strcmp(plane, "both") == 0) ||
394+
(strcmp(plane, "gtpu") == 0)) {
395+
gtp_server_t *srv = &ctx->gtpu;
396+
if (__test_bit(GTP_FL_UPF_BIT, &srv->flags))
397+
vty_server(vty, srv, "gtpu", gtpu_msg_type2str);
398+
else
399+
vty_out(vty, " gtpu: none%s"
400+
, VTY_NEWLINE);
401+
}
402+
}
403+
404+
return CMD_SUCCESS;
405+
}
406+
226407

227408
/*
228409
* VTY init
@@ -239,5 +420,7 @@ gtp_router_vty_init(void)
239420
install_element(GTP_ROUTER_NODE, &gtpc_router_tunnel_endpoint_cmd);
240421
install_element(GTP_ROUTER_NODE, &gtpu_router_tunnel_endpoint_cmd);
241422

423+
install_element(ENABLE_NODE, &show_workers_gtp_router_cmd);
424+
242425
return 0;
243426
}

src/include/gtp_data.h

+5
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,11 @@ typedef struct _data {
9090
unsigned long flags;
9191
} data_t;
9292

93+
typedef struct _gtp_stats {
94+
uint32_t count;
95+
uint32_t unsupported;
96+
} gtp_stats_t;
97+
9398
/* Prototypes */
9499
extern gtp_mirror_rule_t *gtp_mirror_rule_get(const struct sockaddr_storage *, uint8_t, int);
95100
extern gtp_mirror_rule_t *gtp_mirror_rule_add(const struct sockaddr_storage *, uint8_t, int);

src/include/gtp_server.h

+7
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,11 @@
2222
#ifndef _GTP_SERVER_H
2323
#define _GTP_SERVER_H
2424

25+
typedef struct _gtp_server_stats {
26+
gtp_stats_t rx[0xff];
27+
gtp_stats_t tx[0xff];
28+
} gtp_server_stats_t;
29+
2530
/* GTP Switching context */
2631
typedef struct _gtp_server_worker {
2732
char pname[GTP_PNAME];
@@ -37,6 +42,8 @@ typedef struct _gtp_server_worker {
3742
uint64_t tx_bytes;
3843
uint64_t rx_pkt;
3944
uint64_t tx_pkt;
45+
gtp_server_stats_t msg_stats;
46+
gtp_server_stats_t cause_stats;
4047

4148
list_head_t next;
4249

0 commit comments

Comments
 (0)