~ubuntu-branches/ubuntu/trusty/bubblemon/trusty

« back to all changes in this revision

Viewing changes to src/netload.c

  • Committer: Bazaar Package Importer
  • Author(s): Eric Dorland
  • Date: 2005-03-10 01:12:22 UTC
  • mfrom: (1.1.1 upstream)
  • Revision ID: james.westby@ubuntu.com-20050310011222-co7htx6t24yimvki
Tags: 2.0.4-1
New upstream release. (Closes: #298798)

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 *  Bubbling Load Monitoring Applet
 
3
 *  Copyright (C) 1999-2004 Johan Walles - walles@mailblocks.com
 
4
 *  http://www.nongnu.org/bubblemon/
 
5
 *
 
6
 *  This program is free software; you can redistribute it and/or modify
 
7
 *  it under the terms of the GNU General Public License as published by
 
8
 *  the Free Software Foundation; either version 2 of the License, or
 
9
 *  (at your option) any later version.
 
10
 *
 
11
 *  This program is distributed in the hope that it will be useful,
 
12
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 
13
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
14
 *  GNU General Public License for more details.
 
15
 *
 
16
 *  You should have received a copy of the GNU General Public License
 
17
 *  along with this program; if not, write to the Free Software
 
18
 *  Foundation, Inc., 59 Temple Street #330, Boston, MA 02111-1307, USA.
 
19
 */
 
20
 
 
21
/*
 
22
 * This is the platform independent network load refinery functions.
 
23
 */
 
24
 
 
25
#include <assert.h>
 
26
#include <stdlib.h>
 
27
#include <string.h>
 
28
 
 
29
#include "netload.h"
 
30
#include "bubblemon.h"
 
31
 
 
32
static int netload_percentage = 0;
 
33
static int receivingUpdates = 0;
 
34
static struct netload_interface *interfaces;
 
35
 
 
36
static struct netload_interface *netload_findInterface(const char *name)
 
37
{
 
38
  struct netload_interface *iter;
 
39
 
 
40
  assert(name != NULL);
 
41
  
 
42
  for (iter = interfaces; iter != NULL; iter = iter->next)
 
43
  {
 
44
    if (strcmp(iter->name, name) == 0)
 
45
    {
 
46
      return iter;
 
47
    }
 
48
  }
 
49
 
 
50
  return NULL;
 
51
}
 
52
 
 
53
static struct netload_interface *netload_forcedFindInterface(const char *name)
 
54
{
 
55
  struct netload_interface *interface;
 
56
 
 
57
  interface = netload_findInterface(name);
 
58
  if (interface == NULL)
 
59
  {
 
60
    interface = (struct netload_interface *)malloc(sizeof(struct netload_interface));
 
61
    assert(interface != NULL);
 
62
 
 
63
    interface->name = strdup(name);
 
64
 
 
65
    interface->currentBytesIn = 0;
 
66
    interface->previousBytesIn = 0;
 
67
    interface->maxBytesInPerSecond = 0;
 
68
 
 
69
    interface->currentBytesOut = 0;
 
70
    interface->previousBytesOut = 0;
 
71
    interface->maxBytesOutPerSecond = 0;
 
72
 
 
73
    interface->isAlive = 0;
 
74
 
 
75
    interface->next = interfaces;
 
76
    interfaces = interface;
 
77
  }
 
78
 
 
79
  return interface;
 
80
}
 
81
 
 
82
void netload_reportBack(const char *name, unsigned long bytesSent, unsigned long bytesReceived)
 
83
{
 
84
  struct netload_interface *interface;
 
85
  
 
86
  assert(receivingUpdates &&
 
87
         "netload_reportBack() called from outside netload_reportNetworkLoad()");
 
88
  
 
89
  // Grab a pointer to the struct holding this interface's data.  If
 
90
  // there is no such struct, construct and initialize a new one.
 
91
  interface = netload_forcedFindInterface(name);
 
92
  
 
93
  // Verify that the interface isn't marked live.  If it is, it means
 
94
  // we have received two reports about the same interface.
 
95
  assert(!interface->isAlive &&
 
96
         "netload_reportBack() called twice on the same interface");
 
97
  
 
98
  // Store the incoming values.
 
99
  interface->previousBytesIn = interface->currentBytesIn;
 
100
  interface->currentBytesIn = bytesReceived;
 
101
  // Newly added interfaces don't get credit for any bytes during the
 
102
  // first iteration
 
103
  if (interface->previousBytesIn == 0)
 
104
  {
 
105
    interface->previousBytesIn = interface->currentBytesIn;
 
106
  }
 
107
  else
 
108
  {
 
109
    // Verify that the counter isn't moving backwards
 
110
    assert(((interface->currentBytesIn - interface->previousBytesIn) < (1 << 30)) &&
 
111
           "Input byte counter is moving backwards");
 
112
  }
 
113
 
 
114
  interface->previousBytesOut = interface->currentBytesOut;
 
115
  interface->currentBytesOut = bytesSent;
 
116
  // Newly added interfaces don't get credit for any bytes during the
 
117
  // first iteration
 
118
  if (interface->previousBytesOut == 0)
 
119
  {
 
120
    interface->previousBytesOut = interface->currentBytesOut;
 
121
  }
 
122
  else
 
123
  {
 
124
    // Verify that the counter isn't moving backwards
 
125
    assert(((interface->currentBytesOut - interface->previousBytesOut) < (1 << 30)) &&
 
126
           "Output byte counter is moving backwards");
 
127
  }
 
128
 
 
129
  // Mark the interface live
 
130
  interface->isAlive = 1;
 
131
}
 
132
 
 
133
static void netload_receiveUpdates()
 
134
{
 
135
  struct netload_interface *iter;
 
136
  
 
137
  // Mark all known interfaces as shut down
 
138
  for (iter = interfaces;
 
139
       iter != NULL;
 
140
       iter = iter->next)
 
141
  {
 
142
    iter->isAlive = 0;
 
143
  }
 
144
 
 
145
  // Ask the platform dependent function to report network loads to us
 
146
  receivingUpdates = 1;
 
147
  netload_reportNetworkLoad();
 
148
  receivingUpdates = 0;
 
149
 
 
150
  // Forget about all interfaces marked as shut down.
 
151
  // Start with interfaces at the start of the list.
 
152
  while (interfaces != NULL && !interfaces->isAlive)
 
153
  {
 
154
    struct netload_interface *nextInterface = interfaces->next;
 
155
    free(interfaces->name);
 
156
    free(interfaces);
 
157
    interfaces = nextInterface;
 
158
  }
 
159
  // Clean out interfaces after the start of the list
 
160
  if (interfaces != NULL)
 
161
  {
 
162
    struct netload_interface *prev;
 
163
    
 
164
    for (prev = interfaces, iter = interfaces->next;
 
165
         iter != NULL;
 
166
         prev = iter, iter = iter->next)
 
167
    {
 
168
      while ((iter != NULL) && !iter->isAlive)
 
169
      {
 
170
        prev->next = iter->next;
 
171
        free(iter->name);
 
172
        free(iter);
 
173
        iter = prev->next;
 
174
      }
 
175
      
 
176
      if (iter == NULL)
 
177
      {
 
178
        break;
 
179
      }
 
180
    }
 
181
  }
 
182
}
 
183
 
 
184
static int netload_calculateLoad(int lastIntervalLength)
 
185
{
 
186
  struct netload_interface *iter;
 
187
  int maxLoad = 0;
 
188
  
 
189
  // For all interfaces
 
190
  for (iter = interfaces; iter != NULL; iter = iter->next)
 
191
  {
 
192
    unsigned long bytesPerSec;
 
193
    int load;
 
194
    
 
195
    // Calculate incoming load
 
196
    bytesPerSec = ((iter->currentBytesIn - iter->previousBytesIn) * 1000) / lastIntervalLength;
 
197
    if (bytesPerSec > iter->maxBytesInPerSecond)
 
198
    {
 
199
      iter->maxBytesInPerSecond = bytesPerSec;
 
200
    }
 
201
    if (iter->maxBytesInPerSecond > 0)
 
202
    {
 
203
      load = (100 * bytesPerSec) / iter->maxBytesInPerSecond;
 
204
    }
 
205
    else
 
206
    {
 
207
      load = 0;
 
208
    }
 
209
    if (load > maxLoad)
 
210
    {
 
211
      maxLoad = load;
 
212
    }
 
213
    
 
214
    // Calculate outgoing load
 
215
    bytesPerSec = ((iter->currentBytesOut - iter->previousBytesOut) * 1000) / lastIntervalLength;
 
216
    if (bytesPerSec > iter->maxBytesOutPerSecond)
 
217
    {
 
218
      iter->maxBytesOutPerSecond = bytesPerSec;
 
219
    }
 
220
    if (iter->maxBytesOutPerSecond > 0)
 
221
    {
 
222
      load = (100 * bytesPerSec) / iter->maxBytesOutPerSecond;
 
223
    }
 
224
    else
 
225
    {
 
226
      load = 0;
 
227
    }
 
228
    if (load > maxLoad)
 
229
    {
 
230
      maxLoad = load;
 
231
    }
 
232
  }
 
233
  
 
234
  // Return the largest percentage
 
235
  return maxLoad;
 
236
}
 
237
 
 
238
void netload_updateLoadstats(int msecsSinceLastCall)
 
239
{
 
240
  static int timeToNextMeasurement = 0;
 
241
  
 
242
  // If enough time has elapsed since the last measurement...
 
243
  timeToNextMeasurement -= msecsSinceLastCall;
 
244
  if (timeToNextMeasurement <= 0)
 
245
  {
 
246
    int intervalLength = NETLOAD_INTERVAL - timeToNextMeasurement;
 
247
 
 
248
    netload_receiveUpdates();
 
249
    
 
250
    netload_percentage = netload_calculateLoad(intervalLength);
 
251
    
 
252
    timeToNextMeasurement += NETLOAD_INTERVAL;
 
253
  }
 
254
}
 
255
 
 
256
int netload_getLoadPercentage(void)
 
257
{
 
258
  assert((netload_percentage >= 0) &&
 
259
         (netload_percentage <= 100));
 
260
 
 
261
  return netload_percentage;
 
262
}