PAPI 7.1.0.0
Loading...
Searching...
No Matches
linux-net.c
Go to the documentation of this file.
1
21#include <stdlib.h>
22#include <ctype.h>
23#include <string.h>
24#include <net/if.h>
25
26/* Headers required by PAPI */
27#include "papi.h"
28#include "papi_internal.h"
29#include "papi_vector.h"
30#include "papi_memory.h"
31
32#include "linux-net.h"
33
34
36
37/*********************************************************************
38 * Private
39 ********************************************************************/
40
41/* Network stats refresh latency in usec (default: 1 sec) */
42#define NET_REFRESH_LATENCY 1000000
43
44#define NET_PROC_FILE "/proc/net/dev"
45
46/* /proc/net/dev line size
47 * interface name + 8 RX counters + 8 TX counters + separators
48 */
49#define NET_PROC_MAX_LINE (IFNAMSIZ + 16 * (20 + 1) + 16)
50
51#define NET_INVALID_RESULT -1
52
53
54// The following macro follows if a string function has an error. It should
55// never happen; but it is necessary to prevent compiler warnings. We print
56// something just in case there is programmer error in invoking the function.
57#define HANDLE_STRING_ERROR {fprintf(stderr,"%s:%i unexpected string function error.\n",__FILE__,__LINE__); exit(-1);}
58
60
61static int num_events = 0;
62static int is_initialized = 0;
63
66
67/* temporary event */
68struct temp_event {
71 struct temp_event *next;
72};
73static struct temp_event* root = NULL;
74
75/* /proc/net/dev: network counters by interface */
76#define NET_INTERFACE_COUNTERS 16
77
78static const struct net_counters {
79 char *name;
82 /* Receive */
83 { "rx:bytes", "receive bytes"},
84 { "rx:packets", "receive packets"},
85 { "rx:errors", "receive errors"},
86 { "rx:dropped", "receive dropped"},
87 { "rx:fifo", "receive fifo"},
88 { "rx:frame", "receive frame"},
89 { "rx:compressed", "receive compressed"},
90 { "rx:multicast", "receive multicast"},
91 /* Transmit */
92 { "tx:bytes", "transmit bytes"},
93 { "tx:packets", "transmit packets"},
94 { "tx:errors", "transmit errors"},
95 { "tx:dropped", "transmit dropped"},
96 { "tx:fifo", "transmit fifo"},
97 { "tx:colls", "transmit colls"},
98 { "tx:carrier", "transmit carrier"},
99 { "tx:compressed", "transmit compressed"},
101
102
103/*********************************************************************
104 *** BEGIN FUNCTIONS USED INTERNALLY SPECIFIC TO THIS COMPONENT ****
105 ********************************************************************/
106
107/*
108 * find all network interfaces listed in /proc/net/dev
109 */
110static int
112{
113 FILE *fin;
114 char line[NET_PROC_MAX_LINE];
115 char *retval, *ifname;
116 int count = 0;
117 struct temp_event *temp;
118 struct temp_event *last = NULL;
119 int i, j;
120
121 fin = fopen(NET_PROC_FILE, "r");
122 if (fin == NULL) {
123 SUBDBG("Can't find %s, are you sure the /proc file-system is mounted?\n",
126 "Failed to find /proc file-system.");
127 _net_vector.cmp_info.disabled_reason[PAPI_MAX_STR_LEN-1]=0; // force null termination.
128 return 0;
129 }
130
131 /* skip the 2 header lines */
132 for (i=0; i<2; i++) {
133 retval = fgets (line, NET_PROC_MAX_LINE, fin);
134 if (retval == NULL) {
135 fclose(fin);
136 SUBDBG("Not enough lines in %s\n", NET_PROC_FILE);
138 "Not enough lines in '%s'.", NET_PROC_FILE);
139 _net_vector.cmp_info.disabled_reason[PAPI_MAX_STR_LEN-1]=0; // force null termination.
140 return 0;
141 }
142 }
143
144 while ((fgets (line, NET_PROC_MAX_LINE, fin)) == line) {
145
146 /* split the interface name from the 16 counters */
147 retval = strstr(line, ":");
148 if (retval == NULL) {
149 SUBDBG("Wrong line format <%s>\n", line);
150 continue;
151 }
152
153 *retval = '\0';
154 ifname = line;
155 while (isspace(*ifname)) { ifname++; }
156
157 for (j=0; j<NET_INTERFACE_COUNTERS; j++) {
158
159 /* keep the interface name around */
160 temp = (struct temp_event *)papi_malloc(sizeof(struct temp_event));
161 if (!temp) {
162 PAPIERROR("out of memory!");
163 fclose(fin);
165 "%s failed to allocate %lu bytes for temp_event.", __func__, sizeof(struct temp_event));
166 _net_vector.cmp_info.disabled_reason[PAPI_MAX_STR_LEN-1]=0; // force null termination.
167 return PAPI_ENOMEM;
168 }
169 temp->next = NULL;
170
171 if (root == NULL) {
172 root = temp;
173 } else if (last) {
174 last->next = temp;
175 } else {
176 free(temp);
177 fclose(fin);
178 PAPIERROR("This shouldn't be possible\n");
180 "%s Error navigating linked list.", __func__);
181 _net_vector.cmp_info.disabled_reason[PAPI_MAX_STR_LEN-1]=0; // force null termination.
182 return PAPI_ECMP;
183 }
184 last = temp;
185
186 size_t str_len = strlen(ifname) + strlen(_net_counter_info[j].name) + 1;
187 str_len = (str_len > PAPI_MAX_STR_LEN - 1) ? PAPI_MAX_STR_LEN - 1 : str_len;
188 snprintf(temp->name, str_len, "%s:%s",
189 ifname, _net_counter_info[j].name);
190 str_len = strlen(ifname) + strlen(_net_counter_info[j].description) + 1;
191 str_len = (str_len > PAPI_MAX_STR_LEN - 1) ? PAPI_MAX_STR_LEN - 1 : str_len;
192 snprintf(temp->description, str_len, "%s %s",
193 ifname, _net_counter_info[j].description);
194
195 count++;
196 }
197 }
198
199 fclose(fin);
200
201 return count;
202}
203
204
205static int
206getInterfaceBaseIndex(const char *ifname)
207{
208 int i;
209
210 for ( i=0; i<num_events; i+=NET_INTERFACE_COUNTERS ) {
211 if (strncmp(_net_native_events[i].name, ifname, strlen(ifname)) == 0) {
212 return i;
213 }
214 }
215
216 return -1; /* Not found */
217}
218
219
220static int
222{
223 FILE *fin;
224 char line[NET_PROC_MAX_LINE];
225 char *retval, *ifname, *data;
226 int i, nf, if_bidx;
227
228 fin = fopen(NET_PROC_FILE, "r");
229 if (fin == NULL) {
230 SUBDBG("Can't find %s, are you sure the /proc file-system is mounted?\n",
232 return NET_INVALID_RESULT;
233 }
234
235 /* skip the 2 header lines */
236 for (i=0; i<2; i++) {
237 retval = fgets (line, NET_PROC_MAX_LINE, fin);
238 if (retval == NULL) {
239 SUBDBG("Not enough lines in %s\n", NET_PROC_FILE);
240 fclose(fin);
241 return 0;
242 }
243 }
244
245 while ((fgets (line, NET_PROC_MAX_LINE, fin)) == line) {
246
247 /* split the interface name from its 16 counters */
248 retval = strstr(line, ":");
249 if (retval == NULL) {
250 SUBDBG("Wrong line format <%s>\n", line);
251 continue;
252 }
253
254 *retval = '\0';
255 data = retval + 1;
256 ifname = line;
257 while (isspace(*ifname)) { ifname++; }
258
259 if_bidx = getInterfaceBaseIndex(ifname);
260 if (if_bidx < 0) {
261 SUBDBG("Interface <%s> not found\n", ifname);
262 } else {
263 nf = sscanf( data,
264 "%lld %lld %lld %lld %lld %lld %lld %lld %lld %lld %lld %lld %lld %lld %lld %lld\n",
265 &values[if_bidx + 0], &values[if_bidx + 1],
266 &values[if_bidx + 2], &values[if_bidx + 3],
267 &values[if_bidx + 4], &values[if_bidx + 5],
268 &values[if_bidx + 6], &values[if_bidx + 7],
269 &values[if_bidx + 8], &values[if_bidx + 9],
270 &values[if_bidx + 10], &values[if_bidx + 11],
271 &values[if_bidx + 12], &values[if_bidx + 13],
272 &values[if_bidx + 14], &values[if_bidx + 15]);
273
274 SUBDBG("\nRead "
275 "%lld %lld %lld %lld %lld %lld %lld %lld %lld %lld %lld %lld %lld %lld %lld %lld\n",
276 values[if_bidx + 0], values[if_bidx + 1],
277 values[if_bidx + 2], values[if_bidx + 3],
278 values[if_bidx + 4], values[if_bidx + 5],
279 values[if_bidx + 6], values[if_bidx + 7],
280 values[if_bidx + 8], values[if_bidx + 9],
281 values[if_bidx + 10], values[if_bidx + 11],
282 values[if_bidx + 12], values[if_bidx + 13],
283 values[if_bidx + 14], values[if_bidx + 15]);
284
285 if ( nf != NET_INTERFACE_COUNTERS ) {
286 /* This shouldn't happen */
287 SUBDBG("/proc line with wrong number of fields\n");
288 }
289 }
290
291 }
292
293 fclose(fin);
294
295 return 0;
296}
297
298
299/*********************************************************************
300 *************** BEGIN PAPI's COMPONENT REQUIRED FUNCTIONS *********
301 *********************************************************************/
302
303/*
304 * This is called whenever a thread is initialized
305 */
306static int
308{
309 ( void ) ctx;
310
311 return PAPI_OK;
312}
313
314
315/* Initialize hardware counters, setup the function vector table
316 * and get hardware information, this routine is called when the
317 * PAPI process is initialized (IE PAPI_library_init)
318 */
319static int
321{
322 int retval = PAPI_OK;
323 int i = 0;
324 struct temp_event *t, *last;
325
326 if ( is_initialized )
327 goto fn_exit;
328
329 memset(_net_register_start, 0,
331 memset(_net_register_current, 0,
333
334 is_initialized = 1;
335
336 /* The network interfaces are listed in /proc/net/dev */
338
339 if ( num_events < 0 ) { /* disabled_reason already set */
341 goto fn_fail;
342 }
343
344 if ( num_events == 0 ) /* No network interfaces found */
345 goto fn_exit;
346
347 t = root;
350 do {
351 int retlen;
352 retlen = snprintf(_net_native_events[i].name, PAPI_MAX_STR_LEN, "%s", t->name);
353 if (retlen <= 0 || retlen >= PAPI_MAX_STR_LEN) HANDLE_STRING_ERROR;
354 retlen = snprintf(_net_native_events[i].description, PAPI_MAX_STR_LEN, "%s", t->description);
355 if (retlen <= 0 || retlen >= PAPI_MAX_STR_LEN) HANDLE_STRING_ERROR;
357 last = t;
358 t = t->next;
360 i++;
361 } while (t != NULL);
362 root = NULL;
363
364 /* Export the total number of events available */
366
367 /* Export the component id */
369
370 fn_exit:
371 _papi_hwd[cidx]->cmp_info.disabled = retval;
372 return retval;
373 fn_fail:
374 goto fn_exit;
375}
376
377
378/*
379 * Control of counters (Reading/Writing/Starting/Stopping/Setup)
380 * functions
381 */
382static int
384{
385 ( void ) ctl;
386
387 return PAPI_OK;
388}
389
390
391static int
393{
394 ( void ) ctx;
395
396 NET_control_state_t *net_ctl = (NET_control_state_t *) ctl;
397 long long now = PAPI_get_real_usec();
398
402
403 /* set initial values to 0 */
404 memset(net_ctl->values, 0, NET_MAX_COUNTERS*sizeof(net_ctl->values[0]));
405
406 /* Set last access time for caching purposes */
407 net_ctl->lastupdate = now;
408
409 return PAPI_OK;
410}
411
412
413static int
415 long long ** events, int flags )
416{
417 (void) flags;
418 (void) ctx;
419
420 NET_control_state_t *net_ctl = (NET_control_state_t *) ctl;
421 long long now = PAPI_get_real_usec();
422 int i;
423
424 /* Caching
425 * Only read new values from /proc if enough time has passed
426 * since the last read.
427 */
428 if ( now - net_ctl->lastupdate > NET_REFRESH_LATENCY ) {
430 for ( i=0; i<NET_MAX_COUNTERS; i++ ) {
432 }
433 net_ctl->lastupdate = now;
434 }
435 *events = net_ctl->values;
436
437 return PAPI_OK;
438}
439
440
441static int
443{
444 (void) ctx;
445
446 NET_control_state_t *net_ctl = (NET_control_state_t *) ctl;
447 long long now = PAPI_get_real_usec();
448 int i;
449
451 for ( i=0; i<NET_MAX_COUNTERS; i++ ) {
453 }
454 net_ctl->lastupdate = now;
455
456 return PAPI_OK;
457}
458
459
460/*
461 * Thread shutdown
462 */
463static int
465{
466 ( void ) ctx;
467
468 return PAPI_OK;
469}
470
471
472/*
473 * Clean up what was setup in net_init_component().
474 */
475static int
477{
478 if ( is_initialized )
479 {
480 is_initialized = 0;
481 if (_net_native_events != NULL)
482 {
484 _net_native_events = NULL;
485 }
486 }
487
488 return PAPI_OK;
489}
490
491
492/* This function sets various options in the component
493 * The valid codes being passed in are PAPI_SET_DEFDOM,
494 * PAPI_SET_DOMAIN, PAPI_SETDEFGRN, PAPI_SET_GRANUL and
495 * PAPI_SET_INHERIT
496 */
497static int
498_net_ctl( hwd_context_t *ctx, int code, _papi_int_option_t *option )
499{
500 ( void ) ctx;
501 ( void ) code;
502 ( void ) option;
503
504 return PAPI_OK;
505}
506
507
508static int
511{
512 ( void ) ctx;
513 ( void ) ctl;
514
515 int i, index;
516
517 for ( i = 0; i < count; i++ ) {
518 index = native[i].ni_event;
519 native[i].ni_position = _net_native_events[index].resources.selector - 1;
520 }
521
522 return PAPI_OK;
523}
524
525
526/*
527 * This function has to set the bits needed to count different domains
528 * In particular: PAPI_DOM_USER, PAPI_DOM_KERNEL PAPI_DOM_OTHER
529 * By default return PAPI_EINVAL if none of those are specified
530 * and PAPI_OK with success
531 * PAPI_DOM_USER is only user context is counted
532 * PAPI_DOM_KERNEL is only the Kernel/OS context is counted
533 * PAPI_DOM_OTHER is Exception/transient mode (like user TLB misses)
534 * PAPI_DOM_ALL is all of the domains
535 */
536static int
538{
539 ( void ) ctl;
540 if ( PAPI_DOM_ALL != domain )
541 return PAPI_EINVAL;
542
543 return PAPI_OK;
544}
545
546
547int
549{
550 ( void ) ctx;
551 ( void ) ctl;
552
553 return PAPI_OK;
554}
555
556
557/*
558 * Native Event functions
559 */
560static int
561_net_ntv_enum_events( unsigned int *EventCode, int modifier )
562{
563 int index;
564
565 switch ( modifier ) {
566 case PAPI_ENUM_FIRST:
567 if (num_events==0) {
568 return PAPI_ENOEVNT;
569 }
570 *EventCode = 0;
571 return PAPI_OK;
572 break;
573
574 case PAPI_ENUM_EVENTS:
575 index = *EventCode;
576 if ( index < num_events - 1 ) {
577 *EventCode = *EventCode + 1;
578 return PAPI_OK;
579 } else {
580 return PAPI_ENOEVNT;
581 }
582 break;
583
584 default:
585 return PAPI_EINVAL;
586 break;
587 }
588 return PAPI_EINVAL;
589}
590
591
592/*
593 *
594 */
595static int
596_net_ntv_name_to_code( const char *name, unsigned int *EventCode )
597{
598 int i;
599
600 for ( i=0; i<num_events; i++) {
601 if (strcmp(name, _net_native_events[i].name) == 0) {
602 *EventCode = i;
603
604 return PAPI_OK;
605 }
606 }
607
608 return PAPI_ENOEVNT;
609}
610
611
612/*
613 *
614 */
615static int
616_net_ntv_code_to_name( unsigned int EventCode, char *name, int len )
617{
618 int index = EventCode;
619
620 if ( index >= 0 && index < num_events ) {
621 strncpy( name, _net_native_events[index].name, len );
622 return PAPI_OK;
623 }
624
625 return PAPI_ENOEVNT;
626}
627
628
629/*
630 *
631 */
632static int
633_net_ntv_code_to_descr( unsigned int EventCode, char *name, int len )
634{
635 int index = EventCode;
636
637 if ( index >= 0 && index < num_events ) {
638 strncpy( name, _net_native_events[index].description, len );
639 return PAPI_OK;
640 }
641
642 return PAPI_ENOEVNT;
643}
644
645
646/*
647 *
648 */
649static int
650_net_ntv_code_to_bits( unsigned int EventCode, hwd_register_t *bits )
651{
652 int index = EventCode;
653
654 if ( index >= 0 && index < num_events ) {
655 memcpy( ( NET_register_t * ) bits,
656 &( _net_native_events[index].resources ),
657 sizeof ( NET_register_t ) );
658 return PAPI_OK;
659 }
660
661 return PAPI_ENOEVNT;
662}
663
664
665/*
666 *
667 */
669 .cmp_info = {
670 /* default component information (unspecified values are initialized to 0) */
671 .name = "net",
672 .short_name = "net",
673 .version = "4.2.1",
674 .description = "Linux network driver statistics",
675 .num_mpx_cntrs = NET_MAX_COUNTERS,
676 .num_cntrs = NET_MAX_COUNTERS,
677 .default_domain = PAPI_DOM_ALL,
678 .available_domains = PAPI_DOM_ALL,
679 .default_granularity = PAPI_GRN_SYS,
680 .available_granularities = PAPI_GRN_SYS,
681 .hardware_intr_sig = PAPI_INT_SIGNAL,
682
683 /* component specific cmp_info initializations */
684 .fast_real_timer = 0,
685 .fast_virtual_timer = 0,
686 .attach = 0,
687 .attach_must_ptrace = 0,
688 },
689
690 /* sizes of framework-opaque component-private structures */
691 .size = {
692 .context = sizeof ( NET_context_t ),
693 .control_state = sizeof ( NET_control_state_t ),
694 .reg_value = sizeof ( NET_register_t ),
695 .reg_alloc = sizeof ( NET_reg_alloc_t ),
696 },
697
698 /* function pointers in this component */
699 .init_thread = _net_init_thread,
700 .init_component = _net_init_component,
701 .init_control_state = _net_init_control_state,
702 .start = _net_start,
703 .stop = _net_stop,
704 .read = _net_read,
705 .shutdown_thread = _net_shutdown_thread,
706 .shutdown_component = _net_shutdown_component,
707 .ctl = _net_ctl,
708
709 .update_control_state = _net_update_control_state,
710 .set_domain = _net_set_domain,
711 .reset = _net_reset,
712
713 .ntv_enum_events = _net_ntv_enum_events,
714 .ntv_name_to_code = _net_ntv_name_to_code,
715 .ntv_code_to_name = _net_ntv_code_to_name,
716 .ntv_code_to_descr = _net_ntv_code_to_descr,
717 .ntv_code_to_bits = _net_ntv_code_to_bits,
718};
719
720/* vim:set ts=4 sw=4 sts=4 et: */
int i
static long count
get real time counter value in microseconds
struct papi_vectors * _papi_hwd[]
#define PAPI_ENUM_EVENTS
Definition: f90papi.h:224
#define PAPI_OK
Definition: f90papi.h:73
#define PAPI_ENUM_FIRST
Definition: f90papi.h:85
#define PAPI_ENOEVNT
Definition: f90papi.h:139
#define PAPI_EINVAL
Definition: f90papi.h:115
#define PAPI_MAX_STR_LEN
Definition: f90papi.h:77
#define PAPI_ECMP
Definition: f90papi.h:214
#define PAPI_GRN_SYS
Definition: f90papi.h:43
#define PAPI_ENOMEM
Definition: f90papi.h:16
#define PAPI_DOM_ALL
Definition: f90papi.h:261
char events[MAX_EVENTS][BUFSIZ]
static long long values[NUM_EVENTS]
Definition: init_fini.c:10
static struct temp_event * last
static int _net_start(hwd_context_t *ctx, hwd_control_state_t *ctl)
Definition: linux-net.c:392
static int _net_ntv_code_to_descr(unsigned int EventCode, char *name, int len)
Definition: linux-net.c:633
static int num_events
Definition: linux-net.c:61
static long long _net_register_current[NET_MAX_COUNTERS]
Definition: linux-net.c:65
static int _net_ntv_enum_events(unsigned int *EventCode, int modifier)
Definition: linux-net.c:561
#define NET_REFRESH_LATENCY
Definition: linux-net.c:42
static struct temp_event * root
Definition: linux-net.c:73
static int read_net_counters(long long *values)
Definition: linux-net.c:221
#define NET_INTERFACE_COUNTERS
Definition: linux-net.c:76
static int _net_update_control_state(hwd_control_state_t *ctl, NativeInfo_t *native, int count, hwd_context_t *ctx)
Definition: linux-net.c:509
static int _net_init_control_state(hwd_control_state_t *ctl)
Definition: linux-net.c:383
static const struct net_counters _net_counter_info[NET_INTERFACE_COUNTERS]
int _net_reset(hwd_context_t *ctx, hwd_control_state_t *ctl)
Definition: linux-net.c:548
static int _net_stop(hwd_context_t *ctx, hwd_control_state_t *ctl)
Definition: linux-net.c:442
static int _net_ntv_name_to_code(const char *name, unsigned int *EventCode)
Definition: linux-net.c:596
static int is_initialized
Definition: linux-net.c:62
static int _net_ntv_code_to_bits(unsigned int EventCode, hwd_register_t *bits)
Definition: linux-net.c:650
static int generateNetEventList(void)
Definition: linux-net.c:111
#define NET_INVALID_RESULT
Definition: linux-net.c:51
static int _net_set_domain(hwd_control_state_t *ctl, int domain)
Definition: linux-net.c:537
static int getInterfaceBaseIndex(const char *ifname)
Definition: linux-net.c:206
papi_vector_t _net_vector
Definition: linux-net.c:35
static int _net_init_thread(hwd_context_t *ctx)
Definition: linux-net.c:307
#define NET_PROC_FILE
Definition: linux-net.c:44
#define NET_PROC_MAX_LINE
Definition: linux-net.c:49
static int _net_shutdown_component(void)
Definition: linux-net.c:476
static int _net_shutdown_thread(hwd_context_t *ctx)
Definition: linux-net.c:464
static long long _net_register_start[NET_MAX_COUNTERS]
Definition: linux-net.c:64
static int _net_ctl(hwd_context_t *ctx, int code, _papi_int_option_t *option)
Definition: linux-net.c:498
static int _net_init_component(int cidx)
Definition: linux-net.c:320
static int _net_ntv_code_to_name(unsigned int EventCode, char *name, int len)
Definition: linux-net.c:616
static int _net_read(hwd_context_t *ctx, hwd_control_state_t *ctl, long long **events, int flags)
Definition: linux-net.c:414
#define HANDLE_STRING_ERROR
Definition: linux-net.c:57
static NET_native_event_entry_t * _net_native_events
Definition: linux-net.c:59
net component This file contains the source code for a component that enables PAPI-C to access networ...
#define NET_MAX_COUNTERS
Definition: linux-net.h:34
Return codes and api definitions.
#define SUBDBG(format, args...)
Definition: papi_debug.h:64
int fclose(FILE *__stream)
void PAPIERROR(char *format,...)
#define PAPI_INT_SIGNAL
Definition: papi_internal.h:52
#define papi_free(a)
Definition: papi_memory.h:35
#define papi_malloc(a)
Definition: papi_memory.h:34
static int native
static int cidx
const char * name
Definition: rocs.c:225
long long lastupdate
Definition: linux-net.h:69
long long values[NET_MAX_COUNTERS]
Definition: linux-net.h:68
Definition: linux-net.h:53
NET_register_t resources
Definition: linux-net.h:54
unsigned int selector
Definition: linux-net.h:40
char name[PAPI_MAX_STR_LEN]
Definition: papi.h:627
char disabled_reason[PAPI_HUGE_STR_LEN]
Definition: papi.h:634
char * description
Definition: linux-net.c:80
char * name
Definition: linux-net.c:79
PAPI_component_info_t cmp_info
Definition: papi_vector.h:20
char description[PAPI_MAX_STR_LEN]
struct temp_event * next
char name[PAPI_MAX_STR_LEN]
int retval
Definition: zero_fork.c:53