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