]> git.proxmox.com Git - mirror_frr.git/blob - sharpd/sharp_logpump.c
Merge pull request #6079 from sarav511/regstop_exp
[mirror_frr.git] / sharpd / sharp_logpump.c
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. */
35 static struct frr_pthread *lpt;
36
37 static unsigned long lp_duration;
38 static unsigned lp_frequency;
39 static unsigned lp_burst;
40 static size_t lp_ctr, lp_expect;
41 static struct rusage lp_rusage;
42 static struct vty *lp_vty;
43
44 extern struct thread_master *master;
45
46 static int logpump_done(struct thread *thread)
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;
70 return 0;
71 }
72
73 static void *logpump_run(void *arg)
74 {
75 struct timespec start, next, now;
76 unsigned long delta, period;
77
78 period = 1000000000L / lp_frequency;
79
80 clock_gettime(CLOCK_MONOTONIC, &start);
81 next = start;
82 do {
83 for (size_t inburst = 0; inburst < lp_burst; inburst++)
84 zlog_debug("log pump: %zu (burst %zu)",
85 lp_ctr++, inburst);
86
87 clock_gettime(CLOCK_MONOTONIC, &now);
88 delta = (now.tv_sec - start.tv_sec) * 1000000000L
89 + (now.tv_nsec - start.tv_nsec);
90
91 next.tv_nsec += period;
92 if (next.tv_nsec > 1000000000L) {
93 next.tv_sec++;
94 next.tv_nsec -= 1000000000L;
95 }
96 #ifdef HAVE_CLOCK_NANOSLEEP
97 clock_nanosleep(CLOCK_MONOTONIC, TIMER_ABSTIME, &next, NULL);
98 #else
99 struct timespec slpdur;
100
101 slpdur.tv_sec = next.tv_sec - now.tv_sec;
102 slpdur.tv_nsec = next.tv_nsec - now.tv_nsec;
103 if (slpdur.tv_nsec < 0) {
104 slpdur.tv_sec--;
105 slpdur.tv_nsec += 1000000000L;
106 }
107
108 nanosleep(&slpdur, NULL);
109 #endif
110 } while (delta < lp_duration);
111
112 #ifdef RUSAGE_THREAD
113 getrusage(RUSAGE_THREAD, &lp_rusage);
114 #else
115 getrusage(RUSAGE_SELF, &lp_rusage);
116 #endif
117
118 thread_add_timer_msec(master, logpump_done, NULL, 0, NULL);
119 return NULL;
120 }
121
122 static int logpump_halt(struct frr_pthread *fpt, void **res)
123 {
124 return 0;
125 }
126
127 /* default frr_pthread attributes */
128 static const struct frr_pthread_attr attr = {
129 .start = logpump_run,
130 .stop = logpump_halt,
131 };
132
133 void sharp_logpump_run(struct vty *vty, unsigned duration, unsigned frequency,
134 unsigned burst)
135 {
136 if (lpt != NULL) {
137 vty_out(vty, "logpump already running\n");
138 return;
139 }
140
141 vty_out(vty, "starting logpump...\n");
142 vty_out(vty, "keep this VTY open and press Enter to see results\n");
143
144 lp_vty = vty;
145 lp_duration = duration * 1000000000UL;
146 lp_frequency = frequency;
147 lp_burst = burst;
148 lp_expect = duration * frequency * burst;
149 lp_ctr = 0;
150
151 lpt = frr_pthread_new(&attr, "logpump", "logpump");
152 frr_pthread_run(lpt, NULL);
153 }