Skip to content

Commit 3ec4c58

Browse files
author
Richard Drinkwater
committed
ON-16037: added functions to read stats for interfaces
1 parent ebb51d9 commit 3ec4c58

File tree

5 files changed

+237
-21
lines changed

5 files changed

+237
-21
lines changed

src/include/zf/zf.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
#include <zf/types.h>
2626
#include <zf/zf_alts.h>
2727
#include <zf/zf_ds.h>
28+
#include <zf/zf_stats.h>
2829

2930
#undef __IN_ZF_TOP_H__
3031
#endif /* __ZF_TOP_H__ */

src/include/zf/zf_stats.h

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
/* SPDX-License-Identifier: MIT */
2+
/* SPDX-FileCopyrightText: (c) Advanced Micro Devices, Inc. */
3+
/**************************************************************************\
4+
*//*! \file
5+
** \brief TCPDirect stats API
6+
*//*
7+
\**************************************************************************/
8+
9+
#ifndef __ZF_STATS_H__
10+
#define __ZF_STATS_H__
11+
12+
#ifndef __IN_ZF_TOP_H__
13+
# error "Please include zf.h to use TCPDirect."
14+
#endif
15+
16+
#include <etherfabric/vi.h>
17+
18+
typedef ef_vi_stats_field_layout zf_stats_field_layout;
19+
typedef ef_vi_stats_layout zf_stats_layout;
20+
21+
/*! \brief */
22+
typedef struct {
23+
/** Number of underlying interfaces present in stack */
24+
int num_intfs;
25+
/** Size of memory needed to query the stats in bytes */
26+
int total_data_size;
27+
/** Array of layouts, one per interface */
28+
zf_stats_layout** layout;
29+
} zf_layout_collection;
30+
31+
/*! \brief Allocate and retrieve layout for available statistics
32+
**
33+
** \param stack The stack to query.
34+
** \param collection Pointer to an zf_layout_collection, that is allocated and
35+
** updated on return with the layout for available
36+
** statistics. This must be released when no longer needed
37+
** using zf_stats_free_layout_collection().
38+
**
39+
** \return Zero on success or negative error code.
40+
**
41+
** Retrieve layout for available statistics.
42+
*/
43+
ZF_LIBENTRY int
44+
zf_stats_alloc_layout_collection(struct zf_stack* stack,
45+
zf_layout_collection** collection);
46+
47+
/*! \brief Release the layout allocated by zf_stats_alloc_query_layout().
48+
**
49+
** \param collection Pointer to an zf_layout_collection that was allocated
50+
** using zf_stats_alloc_layout_collection().
51+
*/
52+
ZF_LIBENTRY void
53+
zf_stats_free_layout_collection(zf_layout_collection* collection);
54+
55+
/*! \brief Retrieve a set of statistic values
56+
**
57+
** \param stack The stack to query.
58+
** \param data Pointer to a buffer, into which the statistics are
59+
** retrieved.
60+
** The size of this buffer must be equal to the value of
61+
** total_data_size in the zf_layout_collection structure.
62+
** \param collection Pointer to a zf_layout_collection, that was allocated for
63+
** this stack by zf_stats_alloc_layout_collection.
64+
** \param do_reset True to reset the statistics after retrieving them.
65+
**
66+
** \return zero or a negative error code.
67+
**
68+
** Retrieve a set of statistic values.
69+
**
70+
** If do_reset is true, the statistics are reset after reading.
71+
*/
72+
ZF_LIBENTRY int zf_stats_query(struct zf_stack* stack, void* data,
73+
zf_layout_collection* collection,
74+
int do_reset);
75+
76+
#endif /* __ZF_STATS_H__ */
77+
/** @} */

src/lib/zf/Makefile.inc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
PUBLIC_LIB_SRCS := zf.c log.c attr.c stack.c pool.c udp_rx.c rx.c udp_tx.c \
55
muxer.c tcp.c tcp_in.c tcp_out.c tcp_core.c rx_table.c zf_alts.c \
66
lazy_alloc.c x86.c timers.c cplane.c zf_tcp.c zf_stackdump.c \
7-
dshm.c zf_alt_buffer_model.c zf_ds.c bond.c tx_warm.c
7+
dshm.c zf_alt_buffer_model.c zf_ds.c bond.c tx_warm.c zf_stats.c
88

99
# Source files that are not distributed, living in private/.
1010
PRIVATE_LIB_SRCS := stack_fast.c stack_alloc.c tcp_fast.c reactor.c

src/lib/zf/zf_stats.c

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
/* SPDX-License-Identifier: MIT */
2+
/* SPDX-FileCopyrightText: (c) Advanced Micro Devices, Inc. */
3+
#include <zf_internal/zf_stack.h>
4+
5+
int
6+
zf_stats_alloc_layout_collection(struct zf_stack* stack,
7+
zf_layout_collection** collection)
8+
{
9+
int i, rc = 0;
10+
int num_nics = stack->nics_n;
11+
zf_layout_collection* c;
12+
13+
c = (zf_layout_collection*) malloc(sizeof(*c));
14+
if( c == NULL )
15+
return -ENOMEM;
16+
17+
c->layout = (zf_stats_layout**) malloc(sizeof(*c->layout) * num_nics);
18+
if( c->layout == NULL ) {
19+
free(c);
20+
return -ENOMEM;
21+
}
22+
c->num_intfs = num_nics;
23+
c->total_data_size = 0;
24+
25+
for( i = 0; i < num_nics && rc == 0; i++ ) {
26+
ef_vi* vi = &stack->nic[i].vi;
27+
rc = ef_vi_stats_query_layout(vi,
28+
(const ef_vi_stats_layout** const) &c->layout[i]);
29+
if( rc == 0 )
30+
c->total_data_size += c->layout[i]->evsl_data_size;
31+
}
32+
33+
34+
if( rc < 0 ) {
35+
zf_stats_free_layout_collection(c);
36+
return rc;
37+
}
38+
*collection = c;
39+
return 0;
40+
}
41+
42+
43+
void
44+
zf_stats_free_layout_collection(zf_layout_collection* collection)
45+
{
46+
free(collection->layout);
47+
free(collection);
48+
}
49+
50+
51+
int
52+
zf_stats_query(struct zf_stack* stack, void* data,
53+
zf_layout_collection* collection, int do_reset)
54+
{
55+
int i, rc = 0;
56+
int num_intfs = stack->nics_n;
57+
char* pData = (char*)data;
58+
59+
assert(num_intfs == collection->num_intfs);
60+
61+
for( i = 0; i < num_intfs && rc == 0; i++ ) {
62+
ef_vi* vi = &stack->nic[i].vi;
63+
rc = ef_vi_stats_query(vi, vi->dh, (void*)pData, do_reset);
64+
pData += collection->layout[i]->evsl_data_size;
65+
}
66+
67+
return rc;
68+
}

src/tests/zf_apps/zfsink.c

Lines changed: 90 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ struct resources {
3434

3535
static bool cfg_quiet = false;
3636
static bool cfg_rx_timestamping = false;
37+
static bool cfg_intf_stats = false;
3738
static struct resources res;
3839

3940
/* Mutex to protect printing from different threads */
@@ -52,6 +53,7 @@ static void usage_msg(FILE* f)
5253
fprintf(f, " -r Enable rx timestamping\n");
5354
fprintf(f, " -q Quiet -- do not emit progress messages\n");
5455
fprintf(f, " -p Print zf attributes after stack startup\n");
56+
fprintf(f, " -s Print interfaces drop stats\n");
5557
}
5658

5759

@@ -61,18 +63,6 @@ static void usage_err(void)
6163
exit(1);
6264
}
6365

64-
65-
static void vlog(const char* fmt, ...)
66-
{
67-
va_list args;
68-
va_start(args, fmt);
69-
pthread_mutex_lock(&printf_mutex);
70-
vprintf(fmt, args);
71-
pthread_mutex_unlock(&printf_mutex);
72-
va_end(args);
73-
}
74-
75-
7666
static void try_recv(struct zfur* ur)
7767
{
7868
struct {
@@ -98,10 +88,12 @@ static void try_recv(struct zfur* ur)
9888
struct timespec ts;
9989
int rc = zfur_pkt_get_timestamp(ur, &rd.msg, &ts, 0, &flags);
10090

91+
pthread_mutex_lock(&printf_mutex);
10192
if( rc == 0 )
102-
vlog("Hardware timestamp: %lld.%.9ld\n", ts.tv_sec, ts.tv_nsec);
93+
printf("Hardware timestamp: %ld.%.9ld\n", ts.tv_sec, ts.tv_nsec);
10394
else
104-
vlog("Error retrieving timestamp! Return code: %d\n", rc);
95+
printf("Error retrieving timestamp! Return code: %d\n", rc);
96+
pthread_mutex_unlock(&printf_mutex);
10597
}
10698

10799
zfur_zc_recv_done(ur, &rd.msg);
@@ -243,14 +235,72 @@ void print_attrs(struct zf_attr* attr)
243235
}
244236

245237

246-
static void monitor()
238+
static void zf_stats_header_print(struct zf_stack* stack,
239+
zf_layout_collection* stats_collection)
240+
{
241+
int i;
242+
243+
if( stats_collection->num_intfs > 1 )
244+
printf("\n#");
245+
246+
/* only display names for the first NIC and assume others are the same */
247+
for( i = 0; i < stats_collection->layout[0]->evsl_fields_num; ++i )
248+
printf(" %10s", stats_collection->layout[0]->evsl_fields[i].evsfl_name);
249+
}
250+
251+
252+
static void zf_stats_print(struct zf_stack* stack, uint8_t* stats_data,
253+
zf_layout_collection* stats_collection)
254+
{
255+
int i, n, n_pad;
256+
uint8_t* cur_data = stats_data;
257+
const zf_stats_layout * layout;
258+
259+
for( n = 0; n < stats_collection->num_intfs; n++ ) {
260+
if( stats_collection->num_intfs > 1 )
261+
printf("\n ");
262+
263+
layout = stats_collection->layout[n];
264+
for( i = 0; i < layout->evsl_fields_num; ++i ) {
265+
const zf_stats_field_layout* f = &layout->evsl_fields[i];
266+
n_pad = strlen(f->evsfl_name);
267+
if( n_pad < 10 )
268+
n_pad = 10;
269+
switch( f->evsfl_size ) {
270+
case sizeof(uint32_t):
271+
printf(" %*d", n_pad, *(uint32_t*)(cur_data + f->evsfl_offset));
272+
break;
273+
default:
274+
printf(" %*s", n_pad, ".");
275+
};
276+
}
277+
cur_data += layout->evsl_data_size;
278+
}
279+
}
280+
281+
282+
static void monitor(struct zf_stack* stack)
247283
{
248284
uint64_t now_bytes, prev_bytes;
249285
struct timeval start, end;
250286
uint64_t prev_pkts, now_pkts;
251287
int ms, pkt_rate, mbps;
252288

253-
vlog("#%9s %16s %16s", "pkt-rate", "bandwidth(Mbps)", "total-pkts\n");
289+
zf_layout_collection* stats_collection;
290+
uint8_t* stats_data = NULL;
291+
292+
pthread_mutex_lock(&printf_mutex);
293+
printf("#%9s %16s %16s", "pkt-rate", "bandwidth(Mbps)", "total-pkts");
294+
295+
if( cfg_intf_stats ) {
296+
ZF_TEST(zf_stats_alloc_layout_collection(stack, &stats_collection) == 0);
297+
zf_stats_header_print(stack, stats_collection);
298+
299+
ZF_TEST((stats_data = malloc(stats_collection->total_data_size)) != NULL);
300+
}
301+
302+
printf("\n");
303+
pthread_mutex_unlock(&printf_mutex);
254304

255305
prev_pkts = res.n_rx_pkts;
256306
prev_bytes = res.n_rx_bytes;
@@ -265,18 +315,35 @@ static void monitor()
265315
ms += (end.tv_usec - start.tv_usec) / 1000;
266316
pkt_rate = (int) ((now_pkts - prev_pkts) * 1000 / ms);
267317
mbps = (int) ((now_bytes - prev_bytes) * 8 / 1000 / ms);
268-
vlog("%10d %16d %16"PRIu64"\n", pkt_rate, mbps, now_pkts);
318+
319+
if( cfg_intf_stats )
320+
zf_stats_query(stack, stats_data, stats_collection, 1);
321+
322+
pthread_mutex_lock(&printf_mutex);
323+
printf("%10d %16d %16"PRIu64, pkt_rate, mbps, now_pkts);
324+
325+
if( cfg_intf_stats )
326+
zf_stats_print(stack, stats_data, stats_collection);
327+
328+
printf("\n");
269329
fflush(stdout);
330+
pthread_mutex_unlock(&printf_mutex);
331+
270332
prev_pkts = now_pkts;
271333
prev_bytes = now_bytes;
272334
start = end;
273335
}
336+
337+
if( cfg_intf_stats ) {
338+
free(stats_data);
339+
zf_stats_free_layout_collection(stats_collection);
340+
}
274341
}
275342

276343

277344
static void* monitor_fn(void* arg)
278345
{
279-
monitor();
346+
monitor( (struct zf_stack*)arg );
280347
return NULL;
281348
}
282349

@@ -289,7 +356,7 @@ int main(int argc, char* argv[])
289356
bool cfg_print_attrs = false;
290357

291358
int c;
292-
while( (c = getopt(argc, argv, "hmrwqp")) != -1 )
359+
while( (c = getopt(argc, argv, "hmrwqps")) != -1 )
293360
switch( c ) {
294361
case 'h':
295362
usage_msg(stdout);
@@ -309,6 +376,9 @@ int main(int argc, char* argv[])
309376
case 'p':
310377
cfg_print_attrs = true;
311378
break;
379+
case 's':
380+
cfg_intf_stats = true;
381+
break;
312382
case '?':
313383
exit(1);
314384
default:
@@ -374,7 +444,7 @@ int main(int argc, char* argv[])
374444
res.n_rx_pkts = 0;
375445

376446
if( ! cfg_quiet )
377-
ZF_TRY(pthread_create(&thread_id, NULL, monitor_fn, NULL) == 0);
447+
ZF_TRY(pthread_create(&thread_id, NULL, monitor_fn, stack) == 0);
378448

379449
if( cfg_waitable_fd )
380450
ev_loop_waitable_fd(stack, muxer);

0 commit comments

Comments
 (0)