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
8 * Copyright (C) 2002-2005 OpenVPN Solutions LLC <info@openvpn.net>
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License version 2
12 * as published by the Free Software Foundation.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program (see the file COPYING included with this
21 * distribution); if not, write to the Free Software Foundation, Inc.,
22 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
26 #include "config-win32.h"
35 #ifdef ENABLE_PERFORMANCE_METRICS
43 #error ENABLE_PERFORMANCE_METRICS is incompatible with USE_PTHREAD
46 static const char *metric_names
[] = {
47 "PERF_BIO_READ_PLAINTEXT",
48 "PERF_BIO_WRITE_PLAINTEXT",
49 "PERF_BIO_READ_CIPHERTEXT",
50 "PERF_BIO_WRITE_CIPHERTEXT",
51 "PERF_TLS_MULTI_PROCESS",
54 "PERF_MULTI_CREATE_INSTANCE",
55 "PERF_MULTI_CLOSE_INSTANCE",
56 "PERF_MULTI_SHOW_STATS",
66 "PERF_PROC_OUT_TUN_MTCP"
72 # define PS_METER_RUNNING 1
73 # define PS_METER_INTERRUPTED 2
87 struct perf perf
[PERF_N
];
90 static struct perf_set perf_set
;
92 static void perf_print_state (int lev
);
95 get_stack_index (int sdelta
)
97 const int sindex
= perf_set
.stack_len
+ sdelta
;
98 if (sindex
>= 0 && sindex
< STACK_N
)
105 get_perf_index (int sdelta
)
107 const int sindex
= get_stack_index (sdelta
);
110 const int pindex
= perf_set
.stack
[sindex
];
111 if (pindex
>= 0 && pindex
< PERF_N
)
121 get_perf (int sdelta
)
123 const int pindex
= get_perf_index (sdelta
);
125 return &perf_set
.perf
[pindex
];
131 push_perf_index (int pindex
)
133 const int sindex
= get_stack_index (0);
134 const int newlen
= get_stack_index (1);
135 if (sindex
>= 0 && newlen
>= 0
136 && pindex
>= 0 && pindex
< PERF_N
)
139 for (i
= 0; i
< sindex
; ++i
)
140 if (perf_set
.stack
[i
] == pindex
)
142 perf_print_state (M_INFO
);
143 msg (M_FATAL
, "PERF: push_perf_index %s failed",
144 metric_names
[pindex
]);
147 perf_set
.stack
[sindex
] = pindex
;
148 perf_set
.stack_len
= newlen
;
151 msg (M_FATAL
, "PERF: push_perf_index: stack push error");
155 pop_perf_index (void)
157 const int newlen
= get_stack_index (-1);
160 perf_set
.stack_len
= newlen
;
163 msg (M_FATAL
, "PERF: pop_perf_index: stack pop error");
167 state_must_be (const struct perf
*p
, const int wanted
)
169 if (p
->state
!= wanted
)
170 msg (M_FATAL
, "PERF: bad state actual=%d wanted=%d",
176 update_sofar (struct perf
*p
)
178 struct timeval current
;
179 ASSERT (!gettimeofday (¤t
, NULL
));
180 p
->sofar
+= (double) tv_subtract (¤t
, &p
->start
, 600) / 1000000.0;
181 tv_clear (&p
->start
);
185 perf_start (struct perf
*p
)
187 state_must_be (p
, PS_INITIAL
);
188 ASSERT (!gettimeofday (&p
->start
, NULL
));
190 p
->state
= PS_METER_RUNNING
;
194 perf_stop (struct perf
*p
)
196 state_must_be (p
, PS_METER_RUNNING
);
199 if (p
->sofar
> p
->max
)
203 p
->state
= PS_INITIAL
;
207 perf_interrupt (struct perf
*p
)
209 state_must_be (p
, PS_METER_RUNNING
);
211 p
->state
= PS_METER_INTERRUPTED
;
215 perf_resume (struct perf
*p
)
217 state_must_be (p
, PS_METER_INTERRUPTED
);
218 ASSERT (!gettimeofday (&p
->start
, NULL
));
219 p
->state
= PS_METER_RUNNING
;
228 ASSERT (SIZE(metric_names
) == PERF_N
);
229 push_perf_index (type
);
231 prev
= get_perf (-2);
237 perf_interrupt (prev
);
247 prev
= get_perf (-2);
260 perf_output_results (void)
263 msg (M_INFO
, "LATENCY PROFILE (mean and max are in milliseconds)");
264 for (i
= 0; i
< PERF_N
; ++i
)
266 struct perf
*p
= &perf_set
.perf
[i
];
269 const double mean
= p
->sum
/ p
->count
;
270 msg (M_INFO
, "%s n=%.0f mean=%.3f max=%.3f", metric_names
[i
], p
->count
, mean
*1000.0, p
->max
*1000.0);
276 perf_print_state (int lev
)
278 struct gc_arena gc
= gc_new ();
280 msg (lev
, "PERF STATE");
282 for (i
= 0; i
< perf_set
.stack_len
; ++i
)
284 const int j
= perf_set
.stack
[i
];
285 const struct perf
*p
= &perf_set
.perf
[j
];
286 msg (lev
, "[%d] %s state=%d start=%s sofar=%f sum=%f max=%f count=%f",
290 tv_string (&p
->start
, &gc
),
300 static void dummy(void) {}