blob: 56b25e0cfa63e440c23adea6d0fe217ce8423e48 [file] [log] [blame]
Jon Medhurst96b56152014-10-30 18:01:15 +00001/**
Jon Medhurstb1d07442015-05-08 12:04:18 +01002 * Copyright (C) ARM Limited 2013-2015. All rights reserved.
Jon Medhurst96b56152014-10-30 18:01:15 +00003 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation.
7 */
8
9// Define to get format macros from inttypes.h
10#define __STDC_FORMAT_MACROS
11
12#include "NetDriver.h"
13
14#include <inttypes.h>
15
16#include "Logging.h"
17#include "SessionData.h"
18
19class NetCounter : public DriverCounter {
20public:
21 NetCounter(DriverCounter *next, char *const name, int64_t *const value);
22 ~NetCounter();
23
24 int64_t read();
25
26private:
27 int64_t *const mValue;
28 int64_t mPrev;
29
30 // Intentionally unimplemented
31 NetCounter(const NetCounter &);
32 NetCounter &operator=(const NetCounter &);
33};
34
35NetCounter::NetCounter(DriverCounter *next, char *const name, int64_t *const value) : DriverCounter(next, name), mValue(value), mPrev(0) {
36}
37
38NetCounter::~NetCounter() {
39}
40
41int64_t NetCounter::read() {
42 int64_t result = *mValue - mPrev;
43 mPrev = *mValue;
44 return result;
45}
46
47NetDriver::NetDriver() : mBuf(), mReceiveBytes(0), mTransmitBytes(0) {
48}
49
50NetDriver::~NetDriver() {
51}
52
53void NetDriver::readEvents(mxml_node_t *const) {
54 // Only for use with perf
55 if (!gSessionData->perf.isSetup()) {
56 return;
57 }
58
59 setCounters(new NetCounter(getCounters(), strdup("Linux_net_rx"), &mReceiveBytes));
60 setCounters(new NetCounter(getCounters(), strdup("Linux_net_tx"), &mTransmitBytes));
61}
62
63bool NetDriver::doRead() {
64 if (!countersEnabled()) {
65 return true;
66 }
67
68 if (!mBuf.read("/proc/net/dev")) {
69 return false;
70 }
71
72 // Skip the header
73 char *key;
74 if (((key = strchr(mBuf.getBuf(), '\n')) == NULL) ||
75 ((key = strchr(key + 1, '\n')) == NULL)) {
76 return false;
77 }
78 key = key + 1;
79
80 mReceiveBytes = 0;
81 mTransmitBytes = 0;
82
83 char *colon;
84 while ((colon = strchr(key, ':')) != NULL) {
85 char *end = strchr(colon + 1, '\n');
86 if (end != NULL) {
87 *end = '\0';
88 }
89 *colon = '\0';
90
91 int64_t receiveBytes;
92 int64_t transmitBytes;
93 const int count = sscanf(colon + 1, " %" SCNu64 " %*u %*u %*u %*u %*u %*u %*u %" SCNu64, &receiveBytes, &transmitBytes);
94 if (count != 2) {
95 return false;
96 }
97 mReceiveBytes += receiveBytes;
98 mTransmitBytes += transmitBytes;
99
100 if (end == NULL) {
101 break;
102 }
103 key = end + 1;
104 }
105
106 return true;
107}
108
109void NetDriver::start() {
110 if (!doRead()) {
Jon Medhurstb1d07442015-05-08 12:04:18 +0100111 logg->logError("Unable to read network stats");
Jon Medhurst96b56152014-10-30 18:01:15 +0000112 handleException();
113 }
114 // Initialize previous values
115 for (DriverCounter *counter = getCounters(); counter != NULL; counter = counter->getNext()) {
116 if (!counter->isEnabled()) {
117 continue;
118 }
119 counter->read();
120 }
121}
122
123void NetDriver::read(Buffer *const buffer) {
124 if (!doRead()) {
Jon Medhurstb1d07442015-05-08 12:04:18 +0100125 logg->logError("Unable to read network stats");
Jon Medhurst96b56152014-10-30 18:01:15 +0000126 handleException();
127 }
128 super::read(buffer);
129}