]> git.proxmox.com Git - mirror_frr.git/blob - sharpd/sharp_logpump.c
bgpd: Refactor subgroup_announce_table() to reuse an existing helpers
[mirror_frr.git] / sharpd / sharp_logpump.c
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3 * testing log message generator
4 * Copyright (C) 2019-2020 David Lamparter for NetDEF, Inc.
5 */
6
7 #include <zebra.h>
8
9 #include "vty.h"
10 #include "command.h"
11 #include "prefix.h"
12 #include "nexthop.h"
13 #include "log.h"
14 #include "frrevent.h"
15 #include "vrf.h"
16 #include "zclient.h"
17 #include "frr_pthread.h"
18
19 #include "sharpd/sharp_vty.h"
20
21 /* this is quite hacky, but then again it's a test tool and it does its job. */
22 static struct frr_pthread *lpt;
23
24 static unsigned long lp_duration;
25 static unsigned lp_frequency;
26 static unsigned lp_burst;
27 static size_t lp_ctr, lp_expect;
28 static struct rusage lp_rusage;
29 static struct vty *lp_vty;
30
31 extern struct event_loop *master;
32
33 static void logpump_done(struct event *thread)
34 {
35 double x;
36
37 vty_out(lp_vty, "\nlogpump done\n");
38 vty_out(lp_vty, "%9zu messages written\n", lp_ctr);
39 x = (double)lp_ctr / (double)lp_expect * 100.;
40 vty_out(lp_vty, "%9zu messages targeted = %5.1lf%%\n", lp_expect, x);
41
42 x = lp_rusage.ru_utime.tv_sec * 1000000 + lp_rusage.ru_utime.tv_usec;
43 x /= (double)lp_ctr;
44 vty_out(lp_vty, "%6llu.%06u usr %9.1lfns/msg\n",
45 (unsigned long long)lp_rusage.ru_utime.tv_sec,
46 (unsigned)lp_rusage.ru_utime.tv_usec, x * 1000.);
47
48 x = lp_rusage.ru_stime.tv_sec * 1000000 + lp_rusage.ru_stime.tv_usec;
49 x /= (double)lp_ctr;
50 vty_out(lp_vty, "%6llu.%06u sys %9.1lfns/msg\n",
51 (unsigned long long)lp_rusage.ru_stime.tv_sec,
52 (unsigned)lp_rusage.ru_stime.tv_usec, x * 1000.);
53
54 frr_pthread_stop(lpt, NULL);
55 frr_pthread_destroy(lpt);
56 lpt = NULL;
57 }
58
59 static void *logpump_run(void *arg)
60 {
61 struct timespec start, next, now;
62 unsigned long delta, period;
63
64 period = 1000000000L / lp_frequency;
65
66 zlog_tls_buffer_init();
67
68 clock_gettime(CLOCK_MONOTONIC, &start);
69 next = start;
70 do {
71 for (size_t inburst = 0; inburst < lp_burst; inburst++)
72 zlog_debug("log pump: %zu (burst %zu)",
73 lp_ctr++, inburst);
74
75 clock_gettime(CLOCK_MONOTONIC, &now);
76 delta = (now.tv_sec - start.tv_sec) * 1000000000L
77 + (now.tv_nsec - start.tv_nsec);
78
79 next.tv_nsec += period;
80 if (next.tv_nsec > 1000000000L) {
81 next.tv_sec++;
82 next.tv_nsec -= 1000000000L;
83 }
84 #ifdef HAVE_CLOCK_NANOSLEEP
85 clock_nanosleep(CLOCK_MONOTONIC, TIMER_ABSTIME, &next, NULL);
86 #else
87 struct timespec slpdur;
88
89 slpdur.tv_sec = next.tv_sec - now.tv_sec;
90 slpdur.tv_nsec = next.tv_nsec - now.tv_nsec;
91 if (slpdur.tv_nsec < 0) {
92 slpdur.tv_sec--;
93 slpdur.tv_nsec += 1000000000L;
94 }
95
96 nanosleep(&slpdur, NULL);
97 #endif
98 } while (delta < lp_duration);
99
100 zlog_tls_buffer_fini();
101
102 #ifdef RUSAGE_THREAD
103 getrusage(RUSAGE_THREAD, &lp_rusage);
104 #else
105 getrusage(RUSAGE_SELF, &lp_rusage);
106 #endif
107
108 event_add_timer_msec(master, logpump_done, NULL, 0, NULL);
109 return NULL;
110 }
111
112 static int logpump_halt(struct frr_pthread *fpt, void **res)
113 {
114 return 0;
115 }
116
117 /* default frr_pthread attributes */
118 static const struct frr_pthread_attr attr = {
119 .start = logpump_run,
120 .stop = logpump_halt,
121 };
122
123 void sharp_logpump_run(struct vty *vty, unsigned duration, unsigned frequency,
124 unsigned burst)
125 {
126 if (lpt != NULL) {
127 vty_out(vty, "logpump already running\n");
128 return;
129 }
130
131 vty_out(vty, "starting logpump...\n");
132 vty_out(vty, "keep this VTY open and press Enter to see results\n");
133
134 lp_vty = vty;
135 lp_duration = duration * 1000000000UL;
136 lp_frequency = frequency;
137 lp_burst = burst;
138 lp_expect = duration * frequency * burst;
139 lp_ctr = 0;
140
141 lpt = frr_pthread_new(&attr, "logpump", "logpump");
142 frr_pthread_run(lpt, NULL);
143 }