~ubuntu-branches/ubuntu/hardy/openvpn/hardy-security

« back to all changes in this revision

Viewing changes to perf.c

  • Committer: Bazaar Package Importer
  • Author(s): Alberto Gonzalez Iniesta
  • Date: 2005-01-05 19:03:11 UTC
  • mfrom: (1.1.1 upstream)
  • Revision ID: james.westby@ubuntu.com-20050105190311-mvqzpuhmlvobg9nh
Tags: 1.99+2.rc6-1
* The 'Three Wise Men' release.
* New upstream release.
* Update README.Debian with comments on changed string remapping.
  Thanks ron@debian.org for noting this first. (Closes: #288669)

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 *  OpenVPN -- An application to securely tunnel IP networks
 
3
 *             over a single TCP/UDP port, with support for SSL/TLS-based
 
4
 *             session authentication and key exchange,
 
5
 *             packet encryption, packet authentication, and
 
6
 *             packet compression.
 
7
 *
 
8
 *  Copyright (C) 2002-2004 James Yonan <jim@yonan.net>
 
9
 *
 
10
 *  This program is free software; you can redistribute it and/or modify
 
11
 *  it under the terms of the GNU General Public License as published by
 
12
 *  the Free Software Foundation; either version 2 of the License, or
 
13
 *  (at your option) any later version.
 
14
 *
 
15
 *  This program is distributed in the hope that it will be useful,
 
16
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 
17
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
18
 *  GNU General Public License for more details.
 
19
 *
 
20
 *  You should have received a copy of the GNU General Public License
 
21
 *  along with this program (see the file COPYING included with this
 
22
 *  distribution); if not, write to the Free Software Foundation, Inc.,
 
23
 *  59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 
24
 */
 
25
 
 
26
#ifdef WIN32
 
27
#include "config-win32.h"
 
28
#else
 
29
#include "config.h"
 
30
#endif
 
31
 
 
32
#include "syshead.h"
 
33
 
 
34
#include "perf.h"
 
35
 
 
36
#ifdef ENABLE_PERFORMANCE_METRICS
 
37
 
 
38
#include "error.h"
 
39
#include "otime.h"
 
40
 
 
41
#include "memdbg.h"
 
42
 
 
43
#ifdef USE_PTHREAD
 
44
#error ENABLE_PERFORMANCE_METRICS is incompatible with USE_PTHREAD
 
45
#endif
 
46
 
 
47
static const char *metric_names[] = {
 
48
  "PERF_BIO_READ_PLAINTEXT",
 
49
  "PERF_BIO_WRITE_PLAINTEXT",
 
50
  "PERF_BIO_READ_CIPHERTEXT",
 
51
  "PERF_BIO_WRITE_CIPHERTEXT",
 
52
  "PERF_TLS_MULTI_PROCESS",
 
53
  "PERF_IO_WAIT",
 
54
  "PERF_EVENT_LOOP",
 
55
  "PERF_MULTI_CREATE_INSTANCE",
 
56
  "PERF_MULTI_CLOSE_INSTANCE",
 
57
  "PERF_MULTI_SHOW_STATS",
 
58
  "PERF_MULTI_BCAST",
 
59
  "PERF_MULTI_MCAST",
 
60
  "PERF_SCRIPT",
 
61
  "PERF_READ_IN_LINK",
 
62
  "PERF_PROC_IN_LINK",
 
63
  "PERF_READ_IN_TUN",
 
64
  "PERF_PROC_IN_TUN",
 
65
  "PERF_PROC_OUT_LINK",
 
66
  "PERF_PROC_OUT_TUN",
 
67
  "PERF_PROC_OUT_TUN_MTCP"
 
68
};
 
69
 
 
70
struct perf
 
71
{
 
72
# define PS_INITIAL            0
 
73
# define PS_METER_RUNNING      1
 
74
# define PS_METER_INTERRUPTED  2
 
75
  int state;
 
76
 
 
77
  struct timeval start;
 
78
  double sofar;
 
79
  double sum;
 
80
  double max;
 
81
  double count;
 
82
};
 
83
 
 
84
struct perf_set
 
85
{
 
86
  int stack_len;
 
87
  int stack[STACK_N];
 
88
  struct perf perf[PERF_N];
 
89
};
 
90
 
 
91
static struct perf_set perf_set;
 
92
 
 
93
static void perf_print_state (int lev);
 
94
 
 
95
static inline int
 
96
get_stack_index (int sdelta)
 
97
{
 
98
  const int sindex = perf_set.stack_len + sdelta;
 
99
  if (sindex >= 0 && sindex < STACK_N)
 
100
    return sindex;
 
101
  else
 
102
    return -1;
 
103
}
 
104
 
 
105
static int
 
106
get_perf_index (int sdelta)
 
107
{
 
108
  const int sindex = get_stack_index (sdelta);
 
109
  if (sindex >= 0)
 
110
    {
 
111
      const int pindex = perf_set.stack[sindex];
 
112
      if (pindex >= 0 && pindex < PERF_N)
 
113
        return pindex;
 
114
      else
 
115
        return -1;
 
116
    }
 
117
  else
 
118
    return -1;
 
119
}
 
120
 
 
121
static struct perf *
 
122
get_perf (int sdelta)
 
123
{
 
124
  const int pindex = get_perf_index (sdelta);
 
125
  if (pindex >= 0)
 
126
    return &perf_set.perf[pindex];
 
127
  else
 
128
    return NULL;
 
129
}
 
130
 
 
131
static void
 
132
push_perf_index (int pindex)
 
133
{
 
134
  const int sindex = get_stack_index (0);
 
135
  const int newlen = get_stack_index (1);
 
136
  if (sindex >= 0 && newlen >= 0
 
137
      && pindex >= 0 && pindex < PERF_N)
 
138
    {
 
139
      int i;
 
140
      for (i = 0; i < sindex; ++i)
 
141
        if (perf_set.stack[i] == pindex)
 
142
          {
 
143
            perf_print_state (M_INFO);
 
144
            msg (M_FATAL, "PERF: push_perf_index %s failed",
 
145
                 metric_names [pindex]); 
 
146
          }
 
147
 
 
148
      perf_set.stack[sindex] = pindex;
 
149
      perf_set.stack_len = newlen;
 
150
    }
 
151
  else
 
152
    msg (M_FATAL, "PERF: push_perf_index: stack push error"); 
 
153
}
 
154
 
 
155
static void
 
156
pop_perf_index (void)
 
157
{
 
158
  const int newlen = get_stack_index (-1);
 
159
  if (newlen >= 0)
 
160
    {
 
161
      perf_set.stack_len = newlen;
 
162
    }
 
163
  else
 
164
    msg (M_FATAL, "PERF: pop_perf_index: stack pop error"); 
 
165
}
 
166
 
 
167
static void
 
168
state_must_be (const struct perf *p, const int wanted)
 
169
{
 
170
  if (p->state != wanted)
 
171
    msg (M_FATAL, "PERF: bad state actual=%d wanted=%d",
 
172
         p->state,
 
173
         wanted);
 
174
}
 
175
 
 
176
static void
 
177
update_sofar (struct perf *p)
 
178
{
 
179
  struct timeval current;
 
180
  ASSERT (!gettimeofday (&current, NULL));
 
181
  p->sofar += (double) tv_subtract (&current, &p->start, 600) / 1000000.0;
 
182
  tv_clear (&p->start);
 
183
}
 
184
 
 
185
static void
 
186
perf_start (struct perf *p)
 
187
{
 
188
  state_must_be (p, PS_INITIAL);
 
189
  ASSERT (!gettimeofday (&p->start, NULL));
 
190
  p->sofar = 0.0;
 
191
  p->state = PS_METER_RUNNING;
 
192
}
 
193
 
 
194
static void
 
195
perf_stop (struct perf *p)
 
196
{
 
197
  state_must_be (p, PS_METER_RUNNING);
 
198
  update_sofar (p);
 
199
  p->sum += p->sofar;
 
200
  if (p->sofar > p->max)
 
201
    p->max = p->sofar;
 
202
  p->count += 1.0;
 
203
  p->sofar = 0.0;
 
204
  p->state = PS_INITIAL;
 
205
}
 
206
 
 
207
static void
 
208
perf_interrupt (struct perf *p)
 
209
{
 
210
  state_must_be (p, PS_METER_RUNNING);
 
211
  update_sofar (p);
 
212
  p->state = PS_METER_INTERRUPTED;
 
213
}
 
214
 
 
215
static void
 
216
perf_resume (struct perf *p)
 
217
{
 
218
  state_must_be (p, PS_METER_INTERRUPTED);
 
219
  ASSERT (!gettimeofday (&p->start, NULL));
 
220
  p->state = PS_METER_RUNNING;
 
221
}
 
222
 
 
223
void
 
224
perf_push (int type)
 
225
{
 
226
  struct perf *prev;
 
227
  struct perf *cur;
 
228
 
 
229
  ASSERT (SIZE(metric_names) == PERF_N);
 
230
  push_perf_index (type);
 
231
 
 
232
  prev = get_perf (-2);
 
233
  cur = get_perf (-1);
 
234
 
 
235
  ASSERT (cur);
 
236
 
 
237
  if (prev)
 
238
    perf_interrupt (prev);
 
239
  perf_start (cur);
 
240
}
 
241
 
 
242
void
 
243
perf_pop (void)
 
244
{
 
245
  struct perf *prev;
 
246
  struct perf *cur;
 
247
 
 
248
  prev = get_perf (-2);
 
249
  cur = get_perf (-1);
 
250
 
 
251
  ASSERT (cur);
 
252
  perf_stop (cur);
 
253
 
 
254
  if (prev)
 
255
    perf_resume (prev);
 
256
 
 
257
  pop_perf_index ();
 
258
}
 
259
 
 
260
void
 
261
perf_output_results (void)
 
262
{
 
263
  int i;
 
264
  msg (M_INFO, "LATENCY PROFILE (mean and max are in milliseconds)");
 
265
  for (i = 0; i < PERF_N; ++i)
 
266
    {
 
267
      struct perf *p = &perf_set.perf[i];
 
268
      if (p->count > 0.0)
 
269
        {
 
270
          const double mean = p->sum / p->count;
 
271
          msg (M_INFO, "%s n=%.0f mean=%.3f max=%.3f", metric_names[i], p->count, mean*1000.0, p->max*1000.0);
 
272
        }
 
273
    }
 
274
}
 
275
 
 
276
static void
 
277
perf_print_state (int lev)
 
278
{
 
279
  struct gc_arena gc = gc_new ();
 
280
  int i;
 
281
  msg (lev, "PERF STATE");
 
282
  msg (lev, "Stack:");
 
283
  for (i = 0; i < perf_set.stack_len; ++i)
 
284
    {
 
285
      const int j = perf_set.stack[i];
 
286
      const struct perf *p = &perf_set.perf[j];
 
287
      msg (lev, "[%d] %s state=%d start=%s sofar=%f sum=%f max=%f count=%f",
 
288
           i,
 
289
           metric_names[j],
 
290
           p->state,
 
291
           tv_string (&p->start, &gc),
 
292
           p->sofar,
 
293
           p->sum,
 
294
           p->max,
 
295
           p->count);
 
296
    }
 
297
  gc_free (&gc);
 
298
}
 
299
 
 
300
#else
 
301
static void dummy(void) {}
 
302
#endif