|
Packit |
577717 |
/**
|
|
Packit |
577717 |
* @file linux-net.c
|
|
Packit |
577717 |
*
|
|
Packit |
577717 |
* @author Haihang You
|
|
Packit |
577717 |
* you@cs.utk.edu
|
|
Packit |
577717 |
*
|
|
Packit |
577717 |
* @author Jose Pedro Oliveira
|
|
Packit |
577717 |
* jpo@di.uminho.pt
|
|
Packit |
577717 |
*
|
|
Packit |
577717 |
* @ingroup papi_components
|
|
Packit |
577717 |
*
|
|
Packit |
577717 |
* @brief net component
|
|
Packit |
577717 |
* This file contains the source code for a component that enables
|
|
Packit |
577717 |
* PAPI-C to access network statistics through the /proc file system.
|
|
Packit |
577717 |
* This component will dynamically create a native events table for
|
|
Packit |
577717 |
* all the interfaces listed in /proc/net/dev (16 entries for each
|
|
Packit |
577717 |
* interface).
|
|
Packit |
577717 |
*/
|
|
Packit |
577717 |
|
|
Packit |
577717 |
|
|
Packit |
577717 |
#include <stdlib.h>
|
|
Packit |
577717 |
#include <ctype.h>
|
|
Packit |
577717 |
#include <string.h>
|
|
Packit |
577717 |
#include <net/if.h>
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/* Headers required by PAPI */
|
|
Packit |
577717 |
#include "papi.h"
|
|
Packit |
577717 |
#include "papi_internal.h"
|
|
Packit |
577717 |
#include "papi_vector.h"
|
|
Packit |
577717 |
#include "papi_memory.h"
|
|
Packit |
577717 |
|
|
Packit |
577717 |
#include "linux-net.h"
|
|
Packit |
577717 |
|
|
Packit |
577717 |
|
|
Packit |
577717 |
papi_vector_t _net_vector;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/*********************************************************************
|
|
Packit |
577717 |
* Private
|
|
Packit |
577717 |
********************************************************************/
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/* Network stats refresh latency in usec (default: 1 sec) */
|
|
Packit |
577717 |
#define NET_REFRESH_LATENCY 1000000
|
|
Packit |
577717 |
|
|
Packit |
577717 |
#define NET_PROC_FILE "/proc/net/dev"
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/* /proc/net/dev line size
|
|
Packit |
577717 |
* interface name + 8 RX counters + 8 TX counters + separators
|
|
Packit |
577717 |
*/
|
|
Packit |
577717 |
#define NET_PROC_MAX_LINE (IFNAMSIZ + 16 * (20 + 1) + 16)
|
|
Packit |
577717 |
|
|
Packit |
577717 |
#define NET_INVALID_RESULT -1
|
|
Packit |
577717 |
|
|
Packit |
577717 |
|
|
Packit |
577717 |
static NET_native_event_entry_t * _net_native_events=NULL;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
static int num_events = 0;
|
|
Packit |
577717 |
static int is_initialized = 0;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
static long long _net_register_start[NET_MAX_COUNTERS];
|
|
Packit |
577717 |
static long long _net_register_current[NET_MAX_COUNTERS];
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/* temporary event */
|
|
Packit |
577717 |
struct temp_event {
|
|
Packit |
577717 |
char name[PAPI_MAX_STR_LEN];
|
|
Packit |
577717 |
char description[PAPI_MAX_STR_LEN];
|
|
Packit |
577717 |
struct temp_event *next;
|
|
Packit |
577717 |
};
|
|
Packit |
577717 |
static struct temp_event* root = NULL;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/* /proc/net/dev: network counters by interface */
|
|
Packit |
577717 |
#define NET_INTERFACE_COUNTERS 16
|
|
Packit |
577717 |
|
|
Packit |
577717 |
static const struct net_counters {
|
|
Packit |
577717 |
char *name;
|
|
Packit |
577717 |
char *description;
|
|
Packit |
577717 |
} _net_counter_info[NET_INTERFACE_COUNTERS] = {
|
|
Packit |
577717 |
/* Receive */
|
|
Packit |
577717 |
{ "rx:bytes", "receive bytes"},
|
|
Packit |
577717 |
{ "rx:packets", "receive packets"},
|
|
Packit |
577717 |
{ "rx:errors", "receive errors"},
|
|
Packit |
577717 |
{ "rx:dropped", "receive dropped"},
|
|
Packit |
577717 |
{ "rx:fifo", "receive fifo"},
|
|
Packit |
577717 |
{ "rx:frame", "receive frame"},
|
|
Packit |
577717 |
{ "rx:compressed", "receive compressed"},
|
|
Packit |
577717 |
{ "rx:multicast", "receive multicast"},
|
|
Packit |
577717 |
/* Transmit */
|
|
Packit |
577717 |
{ "tx:bytes", "transmit bytes"},
|
|
Packit |
577717 |
{ "tx:packets", "transmit packets"},
|
|
Packit |
577717 |
{ "tx:errors", "transmit errors"},
|
|
Packit |
577717 |
{ "tx:dropped", "transmit dropped"},
|
|
Packit |
577717 |
{ "tx:fifo", "transmit fifo"},
|
|
Packit |
577717 |
{ "tx:colls", "transmit colls"},
|
|
Packit |
577717 |
{ "tx:carrier", "transmit carrier"},
|
|
Packit |
577717 |
{ "tx:compressed", "transmit compressed"},
|
|
Packit |
577717 |
};
|
|
Packit |
577717 |
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/*********************************************************************
|
|
Packit |
577717 |
*** BEGIN FUNCTIONS USED INTERNALLY SPECIFIC TO THIS COMPONENT ****
|
|
Packit |
577717 |
********************************************************************/
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/*
|
|
Packit |
577717 |
* find all network interfaces listed in /proc/net/dev
|
|
Packit |
577717 |
*/
|
|
Packit |
577717 |
static int
|
|
Packit |
577717 |
generateNetEventList( void )
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
FILE *fin;
|
|
Packit |
577717 |
char line[NET_PROC_MAX_LINE];
|
|
Packit |
577717 |
char *retval, *ifname;
|
|
Packit |
577717 |
int count = 0;
|
|
Packit |
577717 |
struct temp_event *temp;
|
|
Packit |
577717 |
struct temp_event *last = NULL;
|
|
Packit |
577717 |
int i, j;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
fin = fopen(NET_PROC_FILE, "r");
|
|
Packit |
577717 |
if (fin == NULL) {
|
|
Packit |
577717 |
SUBDBG("Can't find %s, are you sure the /proc file-system is mounted?\n",
|
|
Packit |
577717 |
NET_PROC_FILE);
|
|
Packit |
577717 |
return 0;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/* skip the 2 header lines */
|
|
Packit |
577717 |
for (i=0; i<2; i++) {
|
|
Packit |
577717 |
retval = fgets (line, NET_PROC_MAX_LINE, fin);
|
|
Packit |
577717 |
if (retval == NULL) {
|
|
Packit |
577717 |
fclose(fin);
|
|
Packit |
577717 |
SUBDBG("Not enough lines in %s\n", NET_PROC_FILE);
|
|
Packit |
577717 |
return 0;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
while ((fgets (line, NET_PROC_MAX_LINE, fin)) == line) {
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/* split the interface name from the 16 counters */
|
|
Packit |
577717 |
retval = strstr(line, ":");
|
|
Packit |
577717 |
if (retval == NULL) {
|
|
Packit |
577717 |
SUBDBG("Wrong line format <%s>\n", line);
|
|
Packit |
577717 |
continue;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
*retval = '\0';
|
|
Packit |
577717 |
ifname = line;
|
|
Packit |
577717 |
while (isspace(*ifname)) { ifname++; }
|
|
Packit |
577717 |
|
|
Packit |
577717 |
for (j=0; j
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/* keep the interface name around */
|
|
Packit |
577717 |
temp = (struct temp_event *)papi_malloc(sizeof(struct temp_event));
|
|
Packit |
577717 |
if (!temp) {
|
|
Packit |
577717 |
PAPIERROR("out of memory!");
|
|
Packit |
577717 |
fclose(fin);
|
|
Packit |
577717 |
return PAPI_ENOMEM;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
temp->next = NULL;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (root == NULL) {
|
|
Packit |
577717 |
root = temp;
|
|
Packit |
577717 |
} else if (last) {
|
|
Packit |
577717 |
last->next = temp;
|
|
Packit |
577717 |
} else {
|
|
Packit |
577717 |
free(temp);
|
|
Packit |
577717 |
fclose(fin);
|
|
Packit |
577717 |
PAPIERROR("This shouldn't be possible\n");
|
|
Packit |
577717 |
return PAPI_ECMP;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
last = temp;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
snprintf(temp->name, PAPI_MAX_STR_LEN, "%s:%s",
|
|
Packit |
577717 |
ifname, _net_counter_info[j].name);
|
|
Packit |
577717 |
snprintf(temp->description, PAPI_MAX_STR_LEN, "%s %s",
|
|
Packit |
577717 |
ifname, _net_counter_info[j].description);
|
|
Packit |
577717 |
|
|
Packit |
577717 |
count++;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
fclose(fin);
|
|
Packit |
577717 |
|
|
Packit |
577717 |
return count;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
|
|
Packit |
577717 |
static int
|
|
Packit |
577717 |
getInterfaceBaseIndex(const char *ifname)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
int i;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
for ( i=0; i
|
|
Packit |
577717 |
if (strncmp(_net_native_events[i].name, ifname, strlen(ifname)) == 0) {
|
|
Packit |
577717 |
return i;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
return -1; /* Not found */
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
|
|
Packit |
577717 |
static int
|
|
Packit |
577717 |
read_net_counters( long long *values )
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
FILE *fin;
|
|
Packit |
577717 |
char line[NET_PROC_MAX_LINE];
|
|
Packit |
577717 |
char *retval, *ifname, *data;
|
|
Packit |
577717 |
int i, nf, if_bidx;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
fin = fopen(NET_PROC_FILE, "r");
|
|
Packit |
577717 |
if (fin == NULL) {
|
|
Packit |
577717 |
SUBDBG("Can't find %s, are you sure the /proc file-system is mounted?\n",
|
|
Packit |
577717 |
NET_PROC_FILE);
|
|
Packit |
577717 |
return NET_INVALID_RESULT;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/* skip the 2 header lines */
|
|
Packit |
577717 |
for (i=0; i<2; i++) {
|
|
Packit |
577717 |
retval = fgets (line, NET_PROC_MAX_LINE, fin);
|
|
Packit |
577717 |
if (retval == NULL) {
|
|
Packit |
577717 |
SUBDBG("Not enough lines in %s\n", NET_PROC_FILE);
|
|
Packit |
577717 |
fclose(fin);
|
|
Packit |
577717 |
return 0;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
while ((fgets (line, NET_PROC_MAX_LINE, fin)) == line) {
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/* split the interface name from its 16 counters */
|
|
Packit |
577717 |
retval = strstr(line, ":");
|
|
Packit |
577717 |
if (retval == NULL) {
|
|
Packit |
577717 |
SUBDBG("Wrong line format <%s>\n", line);
|
|
Packit |
577717 |
continue;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
*retval = '\0';
|
|
Packit |
577717 |
data = retval + 1;
|
|
Packit |
577717 |
ifname = line;
|
|
Packit |
577717 |
while (isspace(*ifname)) { ifname++; }
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if_bidx = getInterfaceBaseIndex(ifname);
|
|
Packit |
577717 |
if (if_bidx < 0) {
|
|
Packit |
577717 |
SUBDBG("Interface <%s> not found\n", ifname);
|
|
Packit |
577717 |
} else {
|
|
Packit |
577717 |
nf = sscanf( data,
|
|
Packit |
577717 |
"%lld %lld %lld %lld %lld %lld %lld %lld %lld %lld %lld %lld %lld %lld %lld %lld\n",
|
|
Packit |
577717 |
&values[if_bidx + 0], &values[if_bidx + 1],
|
|
Packit |
577717 |
&values[if_bidx + 2], &values[if_bidx + 3],
|
|
Packit |
577717 |
&values[if_bidx + 4], &values[if_bidx + 5],
|
|
Packit |
577717 |
&values[if_bidx + 6], &values[if_bidx + 7],
|
|
Packit |
577717 |
&values[if_bidx + 8], &values[if_bidx + 9],
|
|
Packit |
577717 |
&values[if_bidx + 10], &values[if_bidx + 11],
|
|
Packit |
577717 |
&values[if_bidx + 12], &values[if_bidx + 13],
|
|
Packit |
577717 |
&values[if_bidx + 14], &values[if_bidx + 15]);
|
|
Packit |
577717 |
|
|
Packit |
577717 |
SUBDBG("\nRead "
|
|
Packit |
577717 |
"%lld %lld %lld %lld %lld %lld %lld %lld %lld %lld %lld %lld %lld %lld %lld %lld\n",
|
|
Packit |
577717 |
values[if_bidx + 0], values[if_bidx + 1],
|
|
Packit |
577717 |
values[if_bidx + 2], values[if_bidx + 3],
|
|
Packit |
577717 |
values[if_bidx + 4], values[if_bidx + 5],
|
|
Packit |
577717 |
values[if_bidx + 6], values[if_bidx + 7],
|
|
Packit |
577717 |
values[if_bidx + 8], values[if_bidx + 9],
|
|
Packit |
577717 |
values[if_bidx + 10], values[if_bidx + 11],
|
|
Packit |
577717 |
values[if_bidx + 12], values[if_bidx + 13],
|
|
Packit |
577717 |
values[if_bidx + 14], values[if_bidx + 15]);
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if ( nf != NET_INTERFACE_COUNTERS ) {
|
|
Packit |
577717 |
/* This shouldn't happen */
|
|
Packit |
577717 |
SUBDBG("/proc line with wrong number of fields\n");
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
fclose(fin);
|
|
Packit |
577717 |
|
|
Packit |
577717 |
return 0;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/*********************************************************************
|
|
Packit |
577717 |
*************** BEGIN PAPI's COMPONENT REQUIRED FUNCTIONS *********
|
|
Packit |
577717 |
*********************************************************************/
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/*
|
|
Packit |
577717 |
* This is called whenever a thread is initialized
|
|
Packit |
577717 |
*/
|
|
Packit |
577717 |
static int
|
|
Packit |
577717 |
_net_init_thread( hwd_context_t *ctx )
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
( void ) ctx;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
return PAPI_OK;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/* Initialize hardware counters, setup the function vector table
|
|
Packit |
577717 |
* and get hardware information, this routine is called when the
|
|
Packit |
577717 |
* PAPI process is initialized (IE PAPI_library_init)
|
|
Packit |
577717 |
*/
|
|
Packit |
577717 |
static int
|
|
Packit |
577717 |
_net_init_component( int cidx )
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
int i = 0;
|
|
Packit |
577717 |
struct temp_event *t, *last;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if ( is_initialized )
|
|
Packit |
577717 |
return PAPI_OK;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
memset(_net_register_start, 0,
|
|
Packit |
577717 |
NET_MAX_COUNTERS*sizeof(_net_register_start[0]));
|
|
Packit |
577717 |
memset(_net_register_current, 0,
|
|
Packit |
577717 |
NET_MAX_COUNTERS*sizeof(_net_register_current[0]));
|
|
Packit |
577717 |
|
|
Packit |
577717 |
is_initialized = 1;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/* The network interfaces are listed in /proc/net/dev */
|
|
Packit |
577717 |
num_events = generateNetEventList();
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if ( num_events < 0 ) /* PAPI errors */
|
|
Packit |
577717 |
return num_events;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if ( num_events == 0 ) /* No network interfaces found */
|
|
Packit |
577717 |
return PAPI_OK;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
t = root;
|
|
Packit |
577717 |
_net_native_events = (NET_native_event_entry_t*)
|
|
Packit |
577717 |
papi_malloc(sizeof(NET_native_event_entry_t) * num_events);
|
|
Packit |
577717 |
do {
|
|
Packit |
577717 |
strncpy(_net_native_events[i].name, t->name, PAPI_MAX_STR_LEN-1);
|
|
Packit |
577717 |
_net_native_events[i].name[PAPI_MAX_STR_LEN-1] = '\0';
|
|
Packit |
577717 |
strncpy(_net_native_events[i].description, t->description, PAPI_MAX_STR_LEN-1);
|
|
Packit |
577717 |
_net_native_events[i].description[PAPI_MAX_STR_LEN-1] = '\0';
|
|
Packit |
577717 |
_net_native_events[i].resources.selector = i + 1;
|
|
Packit |
577717 |
last = t;
|
|
Packit |
577717 |
t = t->next;
|
|
Packit |
577717 |
papi_free(last);
|
|
Packit |
577717 |
i++;
|
|
Packit |
577717 |
} while (t != NULL);
|
|
Packit |
577717 |
root = NULL;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/* Export the total number of events available */
|
|
Packit |
577717 |
_net_vector.cmp_info.num_native_events = num_events;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/* Export the component id */
|
|
Packit |
577717 |
_net_vector.cmp_info.CmpIdx = cidx;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
return PAPI_OK;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/*
|
|
Packit |
577717 |
* Control of counters (Reading/Writing/Starting/Stopping/Setup)
|
|
Packit |
577717 |
* functions
|
|
Packit |
577717 |
*/
|
|
Packit |
577717 |
static int
|
|
Packit |
577717 |
_net_init_control_state( hwd_control_state_t *ctl )
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
( void ) ctl;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
return PAPI_OK;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
|
|
Packit |
577717 |
static int
|
|
Packit |
577717 |
_net_start( hwd_context_t *ctx, hwd_control_state_t *ctl )
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
( void ) ctx;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
NET_control_state_t *net_ctl = (NET_control_state_t *) ctl;
|
|
Packit |
577717 |
long long now = PAPI_get_real_usec();
|
|
Packit |
577717 |
|
|
Packit |
577717 |
read_net_counters(_net_register_start);
|
|
Packit |
577717 |
memcpy(_net_register_current, _net_register_start,
|
|
Packit |
577717 |
NET_MAX_COUNTERS * sizeof(_net_register_start[0]));
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/* set initial values to 0 */
|
|
Packit |
577717 |
memset(net_ctl->values, 0, NET_MAX_COUNTERS*sizeof(net_ctl->values[0]));
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/* Set last access time for caching purposes */
|
|
Packit |
577717 |
net_ctl->lastupdate = now;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
return PAPI_OK;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
|
|
Packit |
577717 |
static int
|
|
Packit |
577717 |
_net_read( hwd_context_t *ctx, hwd_control_state_t *ctl,
|
|
Packit |
577717 |
long long ** events, int flags )
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
(void) flags;
|
|
Packit |
577717 |
(void) ctx;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
NET_control_state_t *net_ctl = (NET_control_state_t *) ctl;
|
|
Packit |
577717 |
long long now = PAPI_get_real_usec();
|
|
Packit |
577717 |
int i;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/* Caching
|
|
Packit |
577717 |
* Only read new values from /proc if enough time has passed
|
|
Packit |
577717 |
* since the last read.
|
|
Packit |
577717 |
*/
|
|
Packit |
577717 |
if ( now - net_ctl->lastupdate > NET_REFRESH_LATENCY ) {
|
|
Packit |
577717 |
read_net_counters(_net_register_current);
|
|
Packit |
577717 |
for ( i=0; i
|
|
Packit |
577717 |
net_ctl->values[i] = _net_register_current[i] - _net_register_start[i];
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
net_ctl->lastupdate = now;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
*events = net_ctl->values;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
return PAPI_OK;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
|
|
Packit |
577717 |
static int
|
|
Packit |
577717 |
_net_stop( hwd_context_t *ctx, hwd_control_state_t *ctl )
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
(void) ctx;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
NET_control_state_t *net_ctl = (NET_control_state_t *) ctl;
|
|
Packit |
577717 |
long long now = PAPI_get_real_usec();
|
|
Packit |
577717 |
int i;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
read_net_counters(_net_register_current);
|
|
Packit |
577717 |
for ( i=0; i
|
|
Packit |
577717 |
net_ctl->values[i] = _net_register_current[i] - _net_register_start[i];
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
net_ctl->lastupdate = now;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
return PAPI_OK;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/*
|
|
Packit |
577717 |
* Thread shutdown
|
|
Packit |
577717 |
*/
|
|
Packit |
577717 |
static int
|
|
Packit |
577717 |
_net_shutdown_thread( hwd_context_t *ctx )
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
( void ) ctx;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
return PAPI_OK;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/*
|
|
Packit |
577717 |
* Clean up what was setup in net_init_component().
|
|
Packit |
577717 |
*/
|
|
Packit |
577717 |
static int
|
|
Packit |
577717 |
_net_shutdown_component( void )
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
if ( is_initialized )
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
is_initialized = 0;
|
|
Packit |
577717 |
if (_net_native_events != NULL)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
papi_free(_net_native_events);
|
|
Packit |
577717 |
_net_native_events = NULL;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
return PAPI_OK;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/* This function sets various options in the component
|
|
Packit |
577717 |
* The valid codes being passed in are PAPI_SET_DEFDOM,
|
|
Packit |
577717 |
* PAPI_SET_DOMAIN, PAPI_SETDEFGRN, PAPI_SET_GRANUL and
|
|
Packit |
577717 |
* PAPI_SET_INHERIT
|
|
Packit |
577717 |
*/
|
|
Packit |
577717 |
static int
|
|
Packit |
577717 |
_net_ctl( hwd_context_t *ctx, int code, _papi_int_option_t *option )
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
( void ) ctx;
|
|
Packit |
577717 |
( void ) code;
|
|
Packit |
577717 |
( void ) option;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
return PAPI_OK;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
|
|
Packit |
577717 |
static int
|
|
Packit |
577717 |
_net_update_control_state( hwd_control_state_t *ctl,
|
|
Packit |
577717 |
NativeInfo_t *native, int count, hwd_context_t *ctx )
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
( void ) ctx;
|
|
Packit |
577717 |
( void ) ctl;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
int i, index;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
for ( i = 0; i < count; i++ ) {
|
|
Packit |
577717 |
index = native[i].ni_event;
|
|
Packit |
577717 |
native[i].ni_position = _net_native_events[index].resources.selector - 1;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
return PAPI_OK;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/*
|
|
Packit |
577717 |
* This function has to set the bits needed to count different domains
|
|
Packit |
577717 |
* In particular: PAPI_DOM_USER, PAPI_DOM_KERNEL PAPI_DOM_OTHER
|
|
Packit |
577717 |
* By default return PAPI_EINVAL if none of those are specified
|
|
Packit |
577717 |
* and PAPI_OK with success
|
|
Packit |
577717 |
* PAPI_DOM_USER is only user context is counted
|
|
Packit |
577717 |
* PAPI_DOM_KERNEL is only the Kernel/OS context is counted
|
|
Packit |
577717 |
* PAPI_DOM_OTHER is Exception/transient mode (like user TLB misses)
|
|
Packit |
577717 |
* PAPI_DOM_ALL is all of the domains
|
|
Packit |
577717 |
*/
|
|
Packit |
577717 |
static int
|
|
Packit |
577717 |
_net_set_domain( hwd_control_state_t *ctl, int domain )
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
( void ) ctl;
|
|
Packit |
577717 |
if ( PAPI_DOM_ALL != domain )
|
|
Packit |
577717 |
return PAPI_EINVAL;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
return PAPI_OK;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
|
|
Packit |
577717 |
int
|
|
Packit |
577717 |
_net_reset( hwd_context_t *ctx, hwd_control_state_t *ctl )
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
( void ) ctx;
|
|
Packit |
577717 |
( void ) ctl;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
return PAPI_OK;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/*
|
|
Packit |
577717 |
* Native Event functions
|
|
Packit |
577717 |
*/
|
|
Packit |
577717 |
static int
|
|
Packit |
577717 |
_net_ntv_enum_events( unsigned int *EventCode, int modifier )
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
int index;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
switch ( modifier ) {
|
|
Packit |
577717 |
case PAPI_ENUM_FIRST:
|
|
Packit |
577717 |
if (num_events==0) {
|
|
Packit |
577717 |
return PAPI_ENOEVNT;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
*EventCode = 0;
|
|
Packit |
577717 |
return PAPI_OK;
|
|
Packit |
577717 |
break;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
case PAPI_ENUM_EVENTS:
|
|
Packit |
577717 |
index = *EventCode;
|
|
Packit |
577717 |
if ( index < num_events - 1 ) {
|
|
Packit |
577717 |
*EventCode = *EventCode + 1;
|
|
Packit |
577717 |
return PAPI_OK;
|
|
Packit |
577717 |
} else {
|
|
Packit |
577717 |
return PAPI_ENOEVNT;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
break;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
default:
|
|
Packit |
577717 |
return PAPI_EINVAL;
|
|
Packit |
577717 |
break;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
return PAPI_EINVAL;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/*
|
|
Packit |
577717 |
*
|
|
Packit |
577717 |
*/
|
|
Packit |
577717 |
static int
|
|
Packit |
577717 |
_net_ntv_name_to_code( const char *name, unsigned int *EventCode )
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
int i;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
for ( i=0; i
|
|
Packit |
577717 |
if (strcmp(name, _net_native_events[i].name) == 0) {
|
|
Packit |
577717 |
*EventCode = i;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
return PAPI_OK;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
return PAPI_ENOEVNT;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/*
|
|
Packit |
577717 |
*
|
|
Packit |
577717 |
*/
|
|
Packit |
577717 |
static int
|
|
Packit |
577717 |
_net_ntv_code_to_name( unsigned int EventCode, char *name, int len )
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
int index = EventCode;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if ( index >= 0 && index < num_events ) {
|
|
Packit |
577717 |
strncpy( name, _net_native_events[index].name, len );
|
|
Packit |
577717 |
return PAPI_OK;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
return PAPI_ENOEVNT;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/*
|
|
Packit |
577717 |
*
|
|
Packit |
577717 |
*/
|
|
Packit |
577717 |
static int
|
|
Packit |
577717 |
_net_ntv_code_to_descr( unsigned int EventCode, char *name, int len )
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
int index = EventCode;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if ( index >= 0 && index < num_events ) {
|
|
Packit |
577717 |
strncpy( name, _net_native_events[index].description, len );
|
|
Packit |
577717 |
return PAPI_OK;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
return PAPI_ENOEVNT;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/*
|
|
Packit |
577717 |
*
|
|
Packit |
577717 |
*/
|
|
Packit |
577717 |
static int
|
|
Packit |
577717 |
_net_ntv_code_to_bits( unsigned int EventCode, hwd_register_t *bits )
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
int index = EventCode;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if ( index >= 0 && index < num_events ) {
|
|
Packit |
577717 |
memcpy( ( NET_register_t * ) bits,
|
|
Packit |
577717 |
&( _net_native_events[index].resources ),
|
|
Packit |
577717 |
sizeof ( NET_register_t ) );
|
|
Packit |
577717 |
return PAPI_OK;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
return PAPI_ENOEVNT;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/*
|
|
Packit |
577717 |
*
|
|
Packit |
577717 |
*/
|
|
Packit |
577717 |
papi_vector_t _net_vector = {
|
|
Packit |
577717 |
.cmp_info = {
|
|
Packit |
577717 |
/* default component information (unspecified values are initialized to 0) */
|
|
Packit |
577717 |
.name = "net",
|
|
Packit |
577717 |
.short_name = "net",
|
|
Packit |
577717 |
.version = "4.2.1",
|
|
Packit |
577717 |
.description = "Linux network driver statistics",
|
|
Packit |
577717 |
.num_mpx_cntrs = NET_MAX_COUNTERS,
|
|
Packit |
577717 |
.num_cntrs = NET_MAX_COUNTERS,
|
|
Packit |
577717 |
.default_domain = PAPI_DOM_ALL,
|
|
Packit |
577717 |
.available_domains = PAPI_DOM_ALL,
|
|
Packit |
577717 |
.default_granularity = PAPI_GRN_SYS,
|
|
Packit |
577717 |
.available_granularities = PAPI_GRN_SYS,
|
|
Packit |
577717 |
.hardware_intr_sig = PAPI_INT_SIGNAL,
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/* component specific cmp_info initializations */
|
|
Packit |
577717 |
.fast_real_timer = 0,
|
|
Packit |
577717 |
.fast_virtual_timer = 0,
|
|
Packit |
577717 |
.attach = 0,
|
|
Packit |
577717 |
.attach_must_ptrace = 0,
|
|
Packit |
577717 |
},
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/* sizes of framework-opaque component-private structures */
|
|
Packit |
577717 |
.size = {
|
|
Packit |
577717 |
.context = sizeof ( NET_context_t ),
|
|
Packit |
577717 |
.control_state = sizeof ( NET_control_state_t ),
|
|
Packit |
577717 |
.reg_value = sizeof ( NET_register_t ),
|
|
Packit |
577717 |
.reg_alloc = sizeof ( NET_reg_alloc_t ),
|
|
Packit |
577717 |
},
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/* function pointers in this component */
|
|
Packit |
577717 |
.init_thread = _net_init_thread,
|
|
Packit |
577717 |
.init_component = _net_init_component,
|
|
Packit |
577717 |
.init_control_state = _net_init_control_state,
|
|
Packit |
577717 |
.start = _net_start,
|
|
Packit |
577717 |
.stop = _net_stop,
|
|
Packit |
577717 |
.read = _net_read,
|
|
Packit |
577717 |
.shutdown_thread = _net_shutdown_thread,
|
|
Packit |
577717 |
.shutdown_component = _net_shutdown_component,
|
|
Packit |
577717 |
.ctl = _net_ctl,
|
|
Packit |
577717 |
|
|
Packit |
577717 |
.update_control_state = _net_update_control_state,
|
|
Packit |
577717 |
.set_domain = _net_set_domain,
|
|
Packit |
577717 |
.reset = _net_reset,
|
|
Packit |
577717 |
|
|
Packit |
577717 |
.ntv_enum_events = _net_ntv_enum_events,
|
|
Packit |
577717 |
.ntv_name_to_code = _net_ntv_name_to_code,
|
|
Packit |
577717 |
.ntv_code_to_name = _net_ntv_code_to_name,
|
|
Packit |
577717 |
.ntv_code_to_descr = _net_ntv_code_to_descr,
|
|
Packit |
577717 |
.ntv_code_to_bits = _net_ntv_code_to_bits,
|
|
Packit |
577717 |
};
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/* vim:set ts=4 sw=4 sts=4 et: */
|