]> git.proxmox.com Git - mirror_frr.git/blame - sharpd/sharp_logpump.c
Merge pull request #10682 from mjstapp/fix_zebra_doc
[mirror_frr.git] / sharpd / sharp_logpump.c
CommitLineData
aef4a13f
DL
1/*
2 * testing log message generator
3 * Copyright (C) 2019-2020 David Lamparter for NetDEF, Inc.
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License as published by the Free
7 * Software Foundation; either version 2 of the License, or (at your option)
8 * any later version.
9 *
10 * This program is distributed in the hope that it will be useful, but WITHOUT
11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
13 * more details.
14 *
15 * You should have received a copy of the GNU General Public License along
16 * with this program; see the file COPYING; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18 */
19
20#include <zebra.h>
21
22#include "vty.h"
23#include "command.h"
24#include "prefix.h"
25#include "nexthop.h"
26#include "log.h"
27#include "thread.h"
28#include "vrf.h"
29#include "zclient.h"
30#include "frr_pthread.h"
31
32#include "sharpd/sharp_vty.h"
33
34/* this is quite hacky, but then again it's a test tool and it does its job. */
35static struct frr_pthread *lpt;
36
37static unsigned long lp_duration;
38static unsigned lp_frequency;
39static unsigned lp_burst;
40static size_t lp_ctr, lp_expect;
41static struct rusage lp_rusage;
42static struct vty *lp_vty;
43
44extern struct thread_master *master;
45
cc9f21da 46static void logpump_done(struct thread *thread)
aef4a13f
DL
47{
48 double x;
49
50 vty_out(lp_vty, "\nlogpump done\n");
51 vty_out(lp_vty, "%9zu messages written\n", lp_ctr);
52 x = (double)lp_ctr / (double)lp_expect * 100.;
53 vty_out(lp_vty, "%9zu messages targeted = %5.1lf%%\n", lp_expect, x);
54
55 x = lp_rusage.ru_utime.tv_sec * 1000000 + lp_rusage.ru_utime.tv_usec;
56 x /= (double)lp_ctr;
57 vty_out(lp_vty, "%6llu.%06u usr %9.1lfns/msg\n",
58 (unsigned long long)lp_rusage.ru_utime.tv_sec,
59 (unsigned)lp_rusage.ru_utime.tv_usec, x * 1000.);
60
61 x = lp_rusage.ru_stime.tv_sec * 1000000 + lp_rusage.ru_stime.tv_usec;
62 x /= (double)lp_ctr;
63 vty_out(lp_vty, "%6llu.%06u sys %9.1lfns/msg\n",
64 (unsigned long long)lp_rusage.ru_stime.tv_sec,
65 (unsigned)lp_rusage.ru_stime.tv_usec, x * 1000.);
66
67 frr_pthread_stop(lpt, NULL);
68 frr_pthread_destroy(lpt);
69 lpt = NULL;
aef4a13f
DL
70}
71
72static void *logpump_run(void *arg)
73{
74 struct timespec start, next, now;
75 unsigned long delta, period;
76
77 period = 1000000000L / lp_frequency;
78
0bdeb5e5
DL
79 zlog_tls_buffer_init();
80
aef4a13f
DL
81 clock_gettime(CLOCK_MONOTONIC, &start);
82 next = start;
83 do {
84 for (size_t inburst = 0; inburst < lp_burst; inburst++)
85 zlog_debug("log pump: %zu (burst %zu)",
86 lp_ctr++, inburst);
87
88 clock_gettime(CLOCK_MONOTONIC, &now);
89 delta = (now.tv_sec - start.tv_sec) * 1000000000L
90 + (now.tv_nsec - start.tv_nsec);
91
92 next.tv_nsec += period;
93 if (next.tv_nsec > 1000000000L) {
94 next.tv_sec++;
95 next.tv_nsec -= 1000000000L;
96 }
97#ifdef HAVE_CLOCK_NANOSLEEP
98 clock_nanosleep(CLOCK_MONOTONIC, TIMER_ABSTIME, &next, NULL);
99#else
100 struct timespec slpdur;
101
102 slpdur.tv_sec = next.tv_sec - now.tv_sec;
103 slpdur.tv_nsec = next.tv_nsec - now.tv_nsec;
104 if (slpdur.tv_nsec < 0) {
105 slpdur.tv_sec--;
106 slpdur.tv_nsec += 1000000000L;
107 }
108
109 nanosleep(&slpdur, NULL);
110#endif
111 } while (delta < lp_duration);
112
0bdeb5e5
DL
113 zlog_tls_buffer_fini();
114
aef4a13f
DL
115#ifdef RUSAGE_THREAD
116 getrusage(RUSAGE_THREAD, &lp_rusage);
117#else
118 getrusage(RUSAGE_SELF, &lp_rusage);
119#endif
120
121 thread_add_timer_msec(master, logpump_done, NULL, 0, NULL);
122 return NULL;
123}
124
125static int logpump_halt(struct frr_pthread *fpt, void **res)
126{
127 return 0;
128}
129
130/* default frr_pthread attributes */
131static const struct frr_pthread_attr attr = {
132 .start = logpump_run,
133 .stop = logpump_halt,
134};
135
136void sharp_logpump_run(struct vty *vty, unsigned duration, unsigned frequency,
137 unsigned burst)
138{
139 if (lpt != NULL) {
140 vty_out(vty, "logpump already running\n");
141 return;
142 }
143
144 vty_out(vty, "starting logpump...\n");
145 vty_out(vty, "keep this VTY open and press Enter to see results\n");
146
147 lp_vty = vty;
148 lp_duration = duration * 1000000000UL;
149 lp_frequency = frequency;
150 lp_burst = burst;
151 lp_expect = duration * frequency * burst;
152 lp_ctr = 0;
153
154 lpt = frr_pthread_new(&attr, "logpump", "logpump");
155 frr_pthread_run(lpt, NULL);
156}