blob: 423d8d5ba157115b96ad01a5296681768e17b139 [file] [log] [blame]
Ed Warnickecb9cada2015-12-08 15:45:58 -07001/*
2 * Copyright (c) 2015 Cisco and/or its affiliates.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at:
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15/*
16 Copyright (c) 2005,2009 Eliot Dresselhaus
17
18 Permission is hereby granted, free of charge, to any person obtaining
19 a copy of this software and associated documentation files (the
20 "Software"), to deal in the Software without restriction, including
21 without limitation the rights to use, copy, modify, merge, publish,
22 distribute, sublicense, and/or sell copies of the Software, and to
23 permit persons to whom the Software is furnished to do so, subject to
24 the following conditions:
25
26 The above copyright notice and this permission notice shall be
27 included in all copies or substantial portions of the Software.
28
29 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
30 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
31 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
32 NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
33 LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
34 OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
35 WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
36*/
37
38#include <vppinfra/elog.h>
39#include <vppinfra/cache.h>
40#include <vppinfra/error.h>
41#include <vppinfra/format.h>
42#include <vppinfra/hash.h>
43#include <vppinfra/math.h>
jaszha030455c432019-06-12 16:01:19 -050044#include <vppinfra/lock.h>
Ed Warnickecb9cada2015-12-08 15:45:58 -070045
Dave Barachc3799992016-08-15 11:12:27 -040046static inline void
47elog_lock (elog_main_t * em)
Ed Warnickecb9cada2015-12-08 15:45:58 -070048{
Dave Barachc3799992016-08-15 11:12:27 -040049 if (PREDICT_FALSE (em->lock != 0))
Sirshak Das2f6d7bb2018-10-03 22:53:51 +000050 while (clib_atomic_test_and_set (em->lock))
jaszha030455c432019-06-12 16:01:19 -050051 CLIB_PAUSE ();
Ed Warnickecb9cada2015-12-08 15:45:58 -070052}
53
Dave Barachc3799992016-08-15 11:12:27 -040054static inline void
55elog_unlock (elog_main_t * em)
Ed Warnickecb9cada2015-12-08 15:45:58 -070056{
Dave Barachc3799992016-08-15 11:12:27 -040057 if (PREDICT_FALSE (em->lock != 0))
Dave Barachfb6e59d2016-03-26 18:45:42 -040058 {
jaszha03f25e7cf2019-06-12 16:01:19 -050059 clib_atomic_release (em->lock);
Dave Barachfb6e59d2016-03-26 18:45:42 -040060 }
Ed Warnickecb9cada2015-12-08 15:45:58 -070061}
62
63/* Non-inline version. */
Damjan Mariondae1c7e2020-10-17 13:32:25 +020064__clib_export void *
Ed Warnickecb9cada2015-12-08 15:45:58 -070065elog_event_data (elog_main_t * em,
Dave Barachc3799992016-08-15 11:12:27 -040066 elog_event_type_t * type, elog_track_t * track, u64 cpu_time)
Ed Warnickecb9cada2015-12-08 15:45:58 -070067{
Dave Barachc3799992016-08-15 11:12:27 -040068 return elog_event_data_inline (em, type, track, cpu_time);
69}
Ed Warnickecb9cada2015-12-08 15:45:58 -070070
Dave Barachc3799992016-08-15 11:12:27 -040071static void
72new_event_type (elog_main_t * em, uword i)
73{
74 elog_event_type_t *t = vec_elt_at_index (em->event_types, i);
75
76 if (!em->event_type_by_format)
77 em->event_type_by_format =
78 hash_create_vec ( /* size */ 0, sizeof (u8), sizeof (uword));
Ed Warnickecb9cada2015-12-08 15:45:58 -070079
Dave Barach903fd512017-04-01 11:07:40 -040080 t->type_index_plus_one = i + 1;
Ed Warnickecb9cada2015-12-08 15:45:58 -070081 hash_set_mem (em->event_type_by_format, t->format, i);
82}
83
84static uword
85find_or_create_type (elog_main_t * em, elog_event_type_t * t)
86{
Dave Barachc3799992016-08-15 11:12:27 -040087 uword *p = hash_get_mem (em->event_type_by_format, t->format);
Ed Warnickecb9cada2015-12-08 15:45:58 -070088 uword i;
89
90 if (p)
91 i = p[0];
92 else
93 {
94 i = vec_len (em->event_types);
95 vec_add1 (em->event_types, t[0]);
96 new_event_type (em, i);
97 }
98
99 return i;
100}
101
102/* External function to register types. */
Dave Barachc3799992016-08-15 11:12:27 -0400103word
104elog_event_type_register (elog_main_t * em, elog_event_type_t * t)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700105{
Dave Barachc3799992016-08-15 11:12:27 -0400106 elog_event_type_t *static_type = t;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700107 word l;
108
109 elog_lock (em);
110
Dave Barach12c6fdc2017-06-30 08:46:24 -0400111 /* Multiple simultaneous registration attempts, */
112 if (t->type_index_plus_one > 0)
113 {
114 elog_unlock (em);
115 return t->type_index_plus_one - 1;
116 }
117
Ed Warnickecb9cada2015-12-08 15:45:58 -0700118 l = vec_len (em->event_types);
119
120 t->type_index_plus_one = 1 + l;
121
122 ASSERT (t->format);
123
124 /* If format args are not specified try to be smart about providing defaults
125 so most of the time user does not have to specify them. */
Dave Barachc3799992016-08-15 11:12:27 -0400126 if (!t->format_args)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700127 {
128 uword i, l;
Dave Barachc3799992016-08-15 11:12:27 -0400129 char *this_arg;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700130
131 l = strlen (t->format);
132 for (i = 0; i < l; i++)
133 {
134 if (t->format[i] != '%')
135 continue;
136 if (i + 1 >= l)
137 continue;
Dave Barachc3799992016-08-15 11:12:27 -0400138 if (t->format[i + 1] == '%') /* %% */
Ed Warnickecb9cada2015-12-08 15:45:58 -0700139 continue;
140
Dave Barachc3799992016-08-15 11:12:27 -0400141 switch (t->format[i + 1])
142 {
143 default:
144 case 'd':
145 case 'x':
146 case 'u':
147 this_arg = "i4"; /* size of u32 */
148 break;
149 case 'f':
150 this_arg = "f8"; /* defaults to f64 */
151 break;
152 case 's':
153 this_arg = "s0"; /* defaults to null terminated string. */
154 break;
155 }
Ed Warnickecb9cada2015-12-08 15:45:58 -0700156
Dave Barachc3799992016-08-15 11:12:27 -0400157 t->format_args =
158 (char *) format ((u8 *) t->format_args, "%s", this_arg);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700159 }
160
161 /* Null terminate. */
162 vec_add1 (t->format_args, 0);
Dave Barachc3799992016-08-15 11:12:27 -0400163 }
Ed Warnickecb9cada2015-12-08 15:45:58 -0700164
165 vec_add1 (em->event_types, t[0]);
166
167 t = em->event_types + l;
168
169 /* Make copies of strings for hashing etc. */
170 if (t->function)
171 t->format = (char *) format (0, "%s %s%c", t->function, t->format, 0);
172 else
173 t->format = (char *) format (0, "%s%c", t->format, 0);
174
175 t->format_args = (char *) format (0, "%s%c", t->format_args, 0);
176
177 /* Construct string table. */
178 {
179 uword i;
180 t->n_enum_strings = static_type->n_enum_strings;
181 for (i = 0; i < t->n_enum_strings; i++)
182 {
Dave Barachc3799992016-08-15 11:12:27 -0400183 if (!static_type->enum_strings[i])
Ed Warnickecb9cada2015-12-08 15:45:58 -0700184 static_type->enum_strings[i] = "MISSING";
Dave Barachc3799992016-08-15 11:12:27 -0400185 vec_add1 (t->enum_strings_vector,
186 (char *) format (0, "%s%c", static_type->enum_strings[i],
187 0));
Ed Warnickecb9cada2015-12-08 15:45:58 -0700188 }
189 }
190
191 new_event_type (em, l);
Dave Barachc3799992016-08-15 11:12:27 -0400192 elog_unlock (em);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700193
194 return l;
195}
196
Damjan Mariondae1c7e2020-10-17 13:32:25 +0200197__clib_export word
Dave Barachc3799992016-08-15 11:12:27 -0400198elog_track_register (elog_main_t * em, elog_track_t * t)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700199{
200 word l;
201
202 elog_lock (em);
203
204 l = vec_len (em->tracks);
205
206 t->track_index_plus_one = 1 + l;
207
208 ASSERT (t->name);
209
210 vec_add1 (em->tracks, t[0]);
211
212 t = em->tracks + l;
213
214 t->name = (char *) format (0, "%s%c", t->name, 0);
215
216 elog_unlock (em);
217
218 return l;
219}
220
Dave Barachc3799992016-08-15 11:12:27 -0400221static uword
222parse_2digit_decimal (char *p, uword * number)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700223{
224 uword i = 0;
225 u8 digits[2];
226
227 digits[0] = digits[1] = 0;
228 while (p[i] >= '0' && p[i] <= '9')
229 {
230 if (i >= 2)
231 break;
232 digits[i] = p[i] - '0';
233 i++;
234 }
235
236 if (i >= 1 && i <= 2)
237 {
238 if (i == 1)
239 *number = digits[0];
240 else
241 *number = 10 * digits[0] + digits[1];
242 return i;
243 }
244 else
245 return 0;
246}
247
Dave Barachc3799992016-08-15 11:12:27 -0400248static u8 *
249fixed_format (u8 * s, char *fmt, char *result, uword * result_len)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700250{
Dave Barachc3799992016-08-15 11:12:27 -0400251 char *f = fmt;
252 char *percent;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700253 uword l = 0;
254
255 while (1)
256 {
257 if (f[0] == 0)
258 break;
259 if (f[0] == '%' && f[1] != '%')
260 break;
261 f++;
262 }
263 if (f > fmt)
264 vec_add (s, fmt, f - fmt);
265
266 if (f[0] != '%')
267 goto done;
268
269 /* Skip percent. */
270 percent = f++;
271
272 /* Skip possible +-= justification. */
273 f += f[0] == '+' || f[0] == '-' || f[0] == '=';
274
275 /* Skip possible X.Y width. */
276 while ((f[0] >= '0' && f[0] <= '9') || f[0] == '.')
277 f++;
278
279 /* Skip wlL as in e.g. %Ld. */
280 f += f[0] == 'w' || f[0] == 'l' || f[0] == 'L';
281
282 /* Finally skip format letter. */
283 f += f[0] != 0;
284
285 ASSERT (*result_len > f - percent);
286 l = clib_min (f - percent, *result_len - 1);
Damjan Marionf1213b82016-03-13 02:22:06 +0100287 clib_memcpy (result, percent, l);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700288 result[l] = 0;
289
Dave Barachc3799992016-08-15 11:12:27 -0400290done:
Ed Warnickecb9cada2015-12-08 15:45:58 -0700291 *result_len = f - fmt;
292 return s;
293}
294
Damjan Mariondae1c7e2020-10-17 13:32:25 +0200295__clib_export u8 *
Dave Barachc3799992016-08-15 11:12:27 -0400296format_elog_event (u8 * s, va_list * va)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700297{
Dave Barachc3799992016-08-15 11:12:27 -0400298 elog_main_t *em = va_arg (*va, elog_main_t *);
299 elog_event_t *e = va_arg (*va, elog_event_t *);
300 elog_event_type_t *t;
301 char *a, *f;
302 void *d = (u8 *) e->data;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700303 char arg_format[64];
304
Dave Barache09ae012020-08-19 06:59:53 -0400305 t = vec_elt_at_index (em->event_types, e->event_type);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700306
307 f = t->format;
308 a = t->format_args;
309 while (1)
310 {
311 uword n_bytes = 0, n_digits, f_bytes = 0;
312
313 f_bytes = sizeof (arg_format);
314 s = fixed_format (s, f, arg_format, &f_bytes);
315 f += f_bytes;
316
317 if (a == 0 || a[0] == 0)
318 {
319 /* Format must also be at end. */
320 ASSERT (f[0] == 0);
321 break;
322 }
323
324 /* Don't go past end of event data. */
325 ASSERT (d < (void *) (e->data + sizeof (e->data)));
326
327 n_digits = parse_2digit_decimal (a + 1, &n_bytes);
328 switch (a[0])
329 {
330 case 'i':
331 case 't':
332 case 'T':
333 {
334 u32 i = 0;
335 u64 l = 0;
336
337 if (n_bytes == 1)
338 i = ((u8 *) d)[0];
339 else if (n_bytes == 2)
340 i = clib_mem_unaligned (d, u16);
341 else if (n_bytes == 4)
342 i = clib_mem_unaligned (d, u32);
343 else if (n_bytes == 8)
344 l = clib_mem_unaligned (d, u64);
345 else
346 ASSERT (0);
347 if (a[0] == 't')
348 {
Dave Barachc3799992016-08-15 11:12:27 -0400349 char *e =
350 vec_elt (t->enum_strings_vector, n_bytes == 8 ? l : i);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700351 s = format (s, arg_format, e);
352 }
353 else if (a[0] == 'T')
354 {
Dave Barachc3799992016-08-15 11:12:27 -0400355 char *e =
356 vec_elt_at_index (em->string_table, n_bytes == 8 ? l : i);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700357 s = format (s, arg_format, e);
358 }
359 else if (n_bytes == 8)
360 s = format (s, arg_format, l);
361 else
362 s = format (s, arg_format, i);
363 }
364 break;
365
366 case 'f':
367 {
368 f64 x = 0;
369 if (n_bytes == 4)
370 x = clib_mem_unaligned (d, f32);
371 else if (n_bytes == 8)
372 x = clib_mem_unaligned (d, f64);
373 else
374 ASSERT (0);
375 s = format (s, arg_format, x);
376 }
377 break;
378
379 case 's':
380 s = format (s, arg_format, d);
381 if (n_bytes == 0)
382 n_bytes = strlen (d) + 1;
383 break;
384
385 default:
386 ASSERT (0);
387 break;
388 }
389
390 ASSERT (n_digits > 0 && n_digits <= 2);
391 a += 1 + n_digits;
392 d += n_bytes;
393 }
394
395 return s;
396}
397
Dave Barachc3799992016-08-15 11:12:27 -0400398u8 *
Florin Corasaefbede2018-12-19 13:07:49 -0800399format_elog_track_name (u8 * s, va_list * va)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700400{
Dave Barachc3799992016-08-15 11:12:27 -0400401 elog_main_t *em = va_arg (*va, elog_main_t *);
402 elog_event_t *e = va_arg (*va, elog_event_t *);
403 elog_track_t *t = vec_elt_at_index (em->tracks, e->track);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700404 return format (s, "%s", t->name);
405}
406
Damjan Mariondae1c7e2020-10-17 13:32:25 +0200407__clib_export u8 *
Florin Corasaefbede2018-12-19 13:07:49 -0800408format_elog_track (u8 * s, va_list * args)
409{
410 elog_main_t *em = va_arg (*args, elog_main_t *);
411 f64 dt = va_arg (*args, f64);
412 int track_index = va_arg (*args, int);
413 elog_event_t *e, *es;
414 u8 indent;
415
416 indent = format_get_indent (s) + 1;
417
418 es = elog_peek_events (em);
419 vec_foreach (e, es)
420 {
421 if (e->track != track_index)
422 continue;
Dave Barache09ae012020-08-19 06:59:53 -0400423 s = format (s, "%U%18.9f: %U\n", format_white_space, indent,
424 e->time + dt, format_elog_event, em, e);
Florin Corasaefbede2018-12-19 13:07:49 -0800425 }
426 vec_free (es);
427 return s;
428}
429
Dave Barach07619242020-10-18 06:54:31 -0400430__clib_export char *
Dave Barachb08fe662020-08-20 08:30:39 -0400431format_one_elog_event (void *em_arg, void *ep_arg)
432{
433 elog_main_t *em = (elog_main_t *) em_arg;
434 elog_event_t *ep = (elog_event_t *) ep_arg;
435
436 return (char *) format (0, "%U", format_elog_event, em, ep);
437}
438
Dave Barachc3799992016-08-15 11:12:27 -0400439void
440elog_time_now (elog_time_stamp_t * et)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700441{
442 u64 cpu_time_now, os_time_now_nsec;
Dave Barach903fd512017-04-01 11:07:40 -0400443 struct timespec ts;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700444
445#ifdef CLIB_UNIX
446 {
447#include <sys/syscall.h>
Damjan Marion4dffd1c2018-09-03 12:30:36 +0200448#ifdef __APPLE__
449 clock_gettime (CLOCK_REALTIME, &ts);
450#else
Ed Warnickecb9cada2015-12-08 15:45:58 -0700451 syscall (SYS_clock_gettime, CLOCK_REALTIME, &ts);
Damjan Marion4dffd1c2018-09-03 12:30:36 +0200452#endif
Ed Warnickecb9cada2015-12-08 15:45:58 -0700453 cpu_time_now = clib_cpu_time_now ();
Dave Barach903fd512017-04-01 11:07:40 -0400454 /* Subtract 3/30/2017's worth of seconds to retain precision */
455 os_time_now_nsec = 1e9 * (ts.tv_sec - 1490885108) + ts.tv_nsec;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700456 }
457#else
458 cpu_time_now = clib_cpu_time_now ();
459 os_time_now_nsec = 0;
460#endif
461
462 et->cpu = cpu_time_now;
463 et->os_nsec = os_time_now_nsec;
464}
465
466always_inline i64
Dave Barachc3799992016-08-15 11:12:27 -0400467elog_time_stamp_diff_os_nsec (elog_time_stamp_t * t1, elog_time_stamp_t * t2)
468{
469 return (i64) t1->os_nsec - (i64) t2->os_nsec;
470}
Ed Warnickecb9cada2015-12-08 15:45:58 -0700471
472always_inline i64
Dave Barachc3799992016-08-15 11:12:27 -0400473elog_time_stamp_diff_cpu (elog_time_stamp_t * t1, elog_time_stamp_t * t2)
474{
475 return (i64) t1->cpu - (i64) t2->cpu;
476}
Ed Warnickecb9cada2015-12-08 15:45:58 -0700477
478always_inline f64
479elog_nsec_per_clock (elog_main_t * em)
480{
481 return ((f64) elog_time_stamp_diff_os_nsec (&em->serialize_time,
482 &em->init_time)
483 / (f64) elog_time_stamp_diff_cpu (&em->serialize_time,
484 &em->init_time));
485}
486
Dave Barachbc867c32020-11-25 10:07:09 -0500487static void
488elog_alloc_internal (elog_main_t * em, u32 n_events, int free_ring)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700489{
Dave Barachbc867c32020-11-25 10:07:09 -0500490 if (free_ring && em->event_ring)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700491 vec_free (em->event_ring);
Dave Barachc3799992016-08-15 11:12:27 -0400492
Ed Warnickecb9cada2015-12-08 15:45:58 -0700493 /* Ring size must be a power of 2. */
494 em->event_ring_size = n_events = max_pow2 (n_events);
495
Dave Barachbc867c32020-11-25 10:07:09 -0500496 vec_validate_aligned (em->event_ring, n_events, CLIB_CACHE_LINE_BYTES);
497 _vec_len (em->event_ring) = n_events;
498}
499
500__clib_export void
501elog_alloc (elog_main_t * em, u32 n_events)
502{
503 elog_alloc_internal (em, n_events, 1 /* free ring */ );
504}
505
506__clib_export void
507elog_resize (elog_main_t * em, u32 n_events)
508{
509 elog_alloc_internal (em, n_events, 0 /* do not free ring */ );
Ed Warnickecb9cada2015-12-08 15:45:58 -0700510}
511
Damjan Mariondae1c7e2020-10-17 13:32:25 +0200512__clib_export void
Dave Barachc3799992016-08-15 11:12:27 -0400513elog_init (elog_main_t * em, u32 n_events)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700514{
Dave Barachb7b92992018-10-17 10:38:51 -0400515 clib_memset (em, 0, sizeof (em[0]));
Ed Warnickecb9cada2015-12-08 15:45:58 -0700516
517 em->lock = 0;
518
519 if (n_events > 0)
520 elog_alloc (em, n_events);
521
522 clib_time_init (&em->cpu_timer);
523
524 em->n_total_events_disable_limit = ~0;
525
526 /* Make track 0. */
527 em->default_track.name = "default";
528 elog_track_register (em, &em->default_track);
529
530 elog_time_now (&em->init_time);
Dave Barach9c8ca8d2019-06-14 12:02:38 -0400531 em->string_table_hash = hash_create_string (0, sizeof (uword));
Ed Warnickecb9cada2015-12-08 15:45:58 -0700532}
533
534/* Returns number of events in ring and start index. */
Dave Barachc3799992016-08-15 11:12:27 -0400535static uword
536elog_event_range (elog_main_t * em, uword * lo)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700537{
538 uword l = em->event_ring_size;
539 u64 i = em->n_total_events;
540
541 /* Ring never wrapped? */
542 if (i <= (u64) l)
543 {
Dave Barachc3799992016-08-15 11:12:27 -0400544 if (lo)
545 *lo = 0;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700546 return i;
547 }
548 else
549 {
Dave Barachc3799992016-08-15 11:12:27 -0400550 if (lo)
551 *lo = i & (l - 1);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700552 return l;
553 }
554}
555
Damjan Mariondae1c7e2020-10-17 13:32:25 +0200556__clib_export elog_event_t *
Dave Barachc3799992016-08-15 11:12:27 -0400557elog_peek_events (elog_main_t * em)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700558{
Dave Barachc3799992016-08-15 11:12:27 -0400559 elog_event_t *e, *f, *es = 0;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700560 uword i, j, n;
561
562 n = elog_event_range (em, &j);
563 for (i = 0; i < n; i++)
564 {
565 vec_add2 (es, e, 1);
566 f = vec_elt_at_index (em->event_ring, j);
567 e[0] = f[0];
568
569 /* Convert absolute time from cycles to seconds from start. */
Dave Barachc3799992016-08-15 11:12:27 -0400570 e->time =
571 (e->time_cycles -
572 em->init_time.cpu) * em->cpu_timer.seconds_per_clock;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700573
574 j = (j + 1) & (em->event_ring_size - 1);
575 }
576
577 return es;
578}
579
580/* Add a formatted string to the string table. */
Damjan Mariondae1c7e2020-10-17 13:32:25 +0200581__clib_export u32
Dave Barachc3799992016-08-15 11:12:27 -0400582elog_string (elog_main_t * em, char *fmt, ...)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700583{
584 u32 offset;
Dave Barach9c8ca8d2019-06-14 12:02:38 -0400585 uword *p;
586 uword len;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700587 va_list va;
588
Steven Luongd31a5982019-05-31 07:34:39 -0700589 elog_lock (em);
Dave Barach9c8ca8d2019-06-14 12:02:38 -0400590 vec_reset_length (em->string_table_tmp);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700591 va_start (va, fmt);
Dave Barach9c8ca8d2019-06-14 12:02:38 -0400592 em->string_table_tmp = va_format (em->string_table_tmp, fmt, &va);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700593 va_end (va);
594
Benoît Ganneb11e4ae2019-07-17 11:45:20 +0200595 /* String table entries MUST be NULL terminated */
596 len = vec_len (em->string_table_tmp);
597 ASSERT (len > 0);
598 if (em->string_table_tmp[len - 1] != 0)
599 vec_add1 (em->string_table_tmp, 0);
600
Dave Barach9c8ca8d2019-06-14 12:02:38 -0400601 /* See if we already have this string in the string table */
602 p = hash_get_mem (em->string_table_hash, em->string_table_tmp);
603
604 /* We already have the string, so give the caller its offset */
605 if (p)
606 {
607 elog_unlock (em);
608 return (p[0]);
609 }
610
Benoît Ganneb11e4ae2019-07-17 11:45:20 +0200611 /* We don't, so add it. */
Dave Barach9c8ca8d2019-06-14 12:02:38 -0400612
613 offset = vec_len (em->string_table);
614 vec_append (em->string_table, em->string_table_tmp);
615
616 hash_set_mem (em->string_table_hash, em->string_table_tmp, offset);
617
618 /* We gave the key to the string table hash, so we can't reuse it! */
619 em->string_table_tmp = 0;
Steven Luongd31a5982019-05-31 07:34:39 -0700620 elog_unlock (em);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700621
622 return offset;
623}
624
Dave Barach6acb7a02020-10-17 17:22:47 -0400625__clib_export elog_event_t *
Dave Barachc3799992016-08-15 11:12:27 -0400626elog_get_events (elog_main_t * em)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700627{
Dave Barach1046b1a2020-10-08 16:04:30 -0400628 vec_free (em->events);
Dave Barachab1a50c2020-10-06 14:08:16 -0400629 em->events = elog_peek_events (em);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700630 return em->events;
631}
632
Dave Barachc3799992016-08-15 11:12:27 -0400633static void
634maybe_fix_string_table_offset (elog_event_t * e,
635 elog_event_type_t * t, u32 offset)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700636{
Dave Barachc3799992016-08-15 11:12:27 -0400637 void *d = (u8 *) e->data;
638 char *a;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700639
640 if (offset == 0)
641 return;
642
643 a = t->format_args;
644
645 while (1)
646 {
647 uword n_bytes = 0, n_digits;
648
649 if (a[0] == 0)
Dave Barachc3799992016-08-15 11:12:27 -0400650 break;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700651
652 /* Don't go past end of event data. */
653 ASSERT (d < (void *) (e->data + sizeof (e->data)));
654
655 n_digits = parse_2digit_decimal (a + 1, &n_bytes);
656 switch (a[0])
657 {
658 case 'T':
Dave Barachc3799992016-08-15 11:12:27 -0400659 ASSERT (n_bytes == 4);
660 clib_mem_unaligned (d, u32) += offset;
661 break;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700662
663 case 'i':
664 case 't':
665 case 'f':
666 case 's':
667 break;
668
669 default:
670 ASSERT (0);
671 break;
672 }
673
674 ASSERT (n_digits > 0 && n_digits <= 2);
675 a += 1 + n_digits;
676 d += n_bytes;
677 }
678}
679
Dave Barachc3799992016-08-15 11:12:27 -0400680static int
681elog_cmp (void *a1, void *a2)
Matus Fabiand2dc3df2015-12-14 10:31:33 -0500682{
Dave Barachc3799992016-08-15 11:12:27 -0400683 elog_event_t *e1 = a1;
684 elog_event_t *e2 = a2;
Matus Fabiand2dc3df2015-12-14 10:31:33 -0500685
Dave Barach903fd512017-04-01 11:07:40 -0400686 if (e1->time < e2->time)
687 return -1;
688
689 if (e1->time > e2->time)
690 return 1;
691
692 return 0;
Matus Fabiand2dc3df2015-12-14 10:31:33 -0500693}
694
Dave Barach903fd512017-04-01 11:07:40 -0400695/*
696 * merge two event logs. Complicated and cranky.
697 */
Dave Barachc3799992016-08-15 11:12:27 -0400698void
Dave Barach903fd512017-04-01 11:07:40 -0400699elog_merge (elog_main_t * dst, u8 * dst_tag, elog_main_t * src, u8 * src_tag,
700 f64 align_tweak)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700701{
Dave Barachc3799992016-08-15 11:12:27 -0400702 elog_event_t *e;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700703 uword l;
704 u32 string_table_offset_for_src_events;
705 u32 track_offset_for_src_tracks;
706 elog_track_t newt;
707 int i;
708
Dave Barachb7b92992018-10-17 10:38:51 -0400709 clib_memset (&newt, 0, sizeof (newt));
Dave Barachf9c231e2016-08-05 10:10:18 -0400710
Dave Barach903fd512017-04-01 11:07:40 -0400711 /* Acquire src and dst events */
Ed Warnickecb9cada2015-12-08 15:45:58 -0700712 elog_get_events (src);
713 elog_get_events (dst);
714
715 string_table_offset_for_src_events = vec_len (dst->string_table);
716 vec_append (dst->string_table, src->string_table);
717
718 l = vec_len (dst->events);
Dave Barach903fd512017-04-01 11:07:40 -0400719 vec_append (dst->events, src->events);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700720
721 /* Prepend the supplied tag (if any) to all dst track names */
722 if (dst_tag)
723 {
Dave Barachc3799992016-08-15 11:12:27 -0400724 for (i = 0; i < vec_len (dst->tracks); i++)
725 {
726 elog_track_t *t = vec_elt_at_index (dst->tracks, i);
727 char *new_name;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700728
Dave Barachc3799992016-08-15 11:12:27 -0400729 new_name = (char *) format (0, "%s:%s%c", dst_tag, t->name, 0);
730 vec_free (t->name);
731 t->name = new_name;
732 }
Ed Warnickecb9cada2015-12-08 15:45:58 -0700733 }
Dave Barachc3799992016-08-15 11:12:27 -0400734
Dave Barach903fd512017-04-01 11:07:40 -0400735 /*
736 * Remember where we started allocating new tracks while merging
737 */
Ed Warnickecb9cada2015-12-08 15:45:58 -0700738 track_offset_for_src_tracks = vec_len (dst->tracks);
Dave Barachc3799992016-08-15 11:12:27 -0400739
Ed Warnickecb9cada2015-12-08 15:45:58 -0700740 /* Copy / tag source tracks */
741 for (i = 0; i < vec_len (src->tracks); i++)
742 {
Dave Barachc3799992016-08-15 11:12:27 -0400743 elog_track_t *t = vec_elt_at_index (src->tracks, i);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700744 if (src_tag)
Dave Barachc3799992016-08-15 11:12:27 -0400745 newt.name = (char *) format (0, "%s:%s%c", src_tag, t->name, 0);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700746 else
Dave Barachc3799992016-08-15 11:12:27 -0400747 newt.name = (char *) format (0, "%s%c", t->name, 0);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700748 (void) elog_track_register (dst, &newt);
749 vec_free (newt.name);
750 }
Dave Barachc3799992016-08-15 11:12:27 -0400751
Ed Warnickecb9cada2015-12-08 15:45:58 -0700752 /* Across all (copied) src events... */
753 for (e = dst->events + l; e < vec_end (dst->events); e++)
754 {
Dave Barache09ae012020-08-19 06:59:53 -0400755 elog_event_type_t *t =
756 vec_elt_at_index (src->event_types, e->event_type);
Dave Barachc3799992016-08-15 11:12:27 -0400757
Ed Warnickecb9cada2015-12-08 15:45:58 -0700758 /* Remap type from src -> dst. */
Dave Barache09ae012020-08-19 06:59:53 -0400759 e->event_type = find_or_create_type (dst, t);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700760
761 /* Remap string table offsets for 'T' format args */
Dave Barachc3799992016-08-15 11:12:27 -0400762 maybe_fix_string_table_offset (e, t,
763 string_table_offset_for_src_events);
764
Ed Warnickecb9cada2015-12-08 15:45:58 -0700765 /* Remap track */
766 e->track += track_offset_for_src_tracks;
767 }
768
769 /* Adjust event times for relative starting times of event streams. */
770 {
771 f64 dt_event, dt_os_nsec, dt_clock_nsec;
772
773 /* Set clock parameters if dst was not generated by unserialize. */
774 if (dst->serialize_time.cpu == 0)
775 {
776 dst->init_time = src->init_time;
777 dst->serialize_time = src->serialize_time;
778 dst->nsec_per_cpu_clock = src->nsec_per_cpu_clock;
779 }
780
Dave Barachc3799992016-08-15 11:12:27 -0400781 dt_os_nsec =
782 elog_time_stamp_diff_os_nsec (&src->init_time, &dst->init_time);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700783
784 dt_event = dt_os_nsec;
Dave Barachc3799992016-08-15 11:12:27 -0400785 dt_clock_nsec =
786 (elog_time_stamp_diff_cpu (&src->init_time, &dst->init_time) * .5 *
787 (dst->nsec_per_cpu_clock + src->nsec_per_cpu_clock));
Ed Warnickecb9cada2015-12-08 15:45:58 -0700788
Dave Barach903fd512017-04-01 11:07:40 -0400789 /*
790 * Heuristic to see if src/dst came from same time source.
791 * If frequencies are "the same" and os clock and cpu clock agree
792 * to within 100e-9 secs about time difference between src/dst
793 * init_time, then we use cpu clock. Otherwise we use OS clock.
794 *
795 * When merging event logs from different systems, time paradoxes
796 * at the O(1ms) level are to be expected. Hence, the "align_tweak"
797 * parameter. If two events logged on different processors are known
798 * to occur in a specific order - and with a reasonably-estimated
799 * interval - supply a non-zero "align_tweak" parameter
800 */
Ed Warnickecb9cada2015-12-08 15:45:58 -0700801 if (fabs (src->nsec_per_cpu_clock - dst->nsec_per_cpu_clock) < 1e-2
802 && fabs (dt_os_nsec - dt_clock_nsec) < 100)
803 dt_event = dt_clock_nsec;
804
805 /* Convert to seconds. */
806 dt_event *= 1e-9;
807
Dave Barach903fd512017-04-01 11:07:40 -0400808 /*
809 * Move the earlier set of events later, to avoid creating
Paul Vinciguerraec11b132018-09-24 05:25:00 -0700810 * events which precede the Big Bang (aka have negative timestamps).
Dave Barach903fd512017-04-01 11:07:40 -0400811 *
812 * Not to any scale, we have something like the following picture:
813 *
814 * DST capture start point
815 * ^
816 * +--- dt_event --+
817 * v
818 * SRC capture start point
819 *
820 * In this case dt_event is positive, src started after dst,
821 * to put src events onto a common timebase we have to move them
822 * forward in time. Naturally, the opposite case is
823 * possible, too: dt_event will be negative, and so we have to
824 * move dst events forward in time by the |dt_event|.
825 * In both cases, we add align_tweak.
826 */
Ed Warnickecb9cada2015-12-08 15:45:58 -0700827 if (dt_event > 0)
828 {
829 /* Src started after dst. */
830 for (e = dst->events + l; e < vec_end (dst->events); e++)
Dave Barach903fd512017-04-01 11:07:40 -0400831 e->time += dt_event + align_tweak;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700832 }
833 else
834 {
835 /* Dst started after src. */
Dave Barach903fd512017-04-01 11:07:40 -0400836 dt_event = -dt_event;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700837 for (e = dst->events + 0; e < dst->events + l; e++)
Dave Barach903fd512017-04-01 11:07:40 -0400838 e->time += dt_event + align_tweak;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700839 }
840 }
841
842 /* Sort events by increasing time. */
Matus Fabiand2dc3df2015-12-14 10:31:33 -0500843 vec_sort_with_function (dst->events, elog_cmp);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700844
Dave Barach903fd512017-04-01 11:07:40 -0400845 dst->n_total_events = vec_len (dst->events);
846
Ed Warnickecb9cada2015-12-08 15:45:58 -0700847 /* Recreate the event ring or the results won't serialize */
848 {
849 int i;
850
851 ASSERT (dst->cpu_timer.seconds_per_clock);
852
853 elog_alloc (dst, vec_len (dst->events));
Dave Barachc3799992016-08-15 11:12:27 -0400854 for (i = 0; i < vec_len (dst->events); i++)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700855 {
Dave Barachc3799992016-08-15 11:12:27 -0400856 elog_event_t *es, *ed;
857
858 es = dst->events + i;
859 ed = dst->event_ring + i;
860
861 ed[0] = es[0];
Ed Warnickecb9cada2015-12-08 15:45:58 -0700862 }
Ed Warnickecb9cada2015-12-08 15:45:58 -0700863 }
864}
865
866static void
867serialize_elog_event (serialize_main_t * m, va_list * va)
868{
Dave Barachc3799992016-08-15 11:12:27 -0400869 elog_main_t *em = va_arg (*va, elog_main_t *);
870 elog_event_t *e = va_arg (*va, elog_event_t *);
Dave Barache09ae012020-08-19 06:59:53 -0400871 elog_event_type_t *t = vec_elt_at_index (em->event_types, e->event_type);
Dave Barachc3799992016-08-15 11:12:27 -0400872 u8 *d = e->data;
873 u8 *p = (u8 *) t->format_args;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700874
Dave Barache09ae012020-08-19 06:59:53 -0400875 serialize_integer (m, e->event_type, sizeof (e->event_type));
Ed Warnickecb9cada2015-12-08 15:45:58 -0700876 serialize_integer (m, e->track, sizeof (e->track));
877 serialize (m, serialize_f64, e->time);
878
879 while (*p)
880 {
881 uword n_digits, n_bytes = 0;
882
883 n_digits = parse_2digit_decimal ((char *) p + 1, &n_bytes);
884
885 switch (p[0])
886 {
887 case 'i':
888 case 't':
889 case 'T':
890 if (n_bytes == 1)
891 serialize_integer (m, d[0], sizeof (u8));
892 else if (n_bytes == 2)
893 serialize_integer (m, clib_mem_unaligned (d, u16), sizeof (u16));
894 else if (n_bytes == 4)
895 serialize_integer (m, clib_mem_unaligned (d, u32), sizeof (u32));
896 else if (n_bytes == 8)
897 serialize (m, serialize_64, clib_mem_unaligned (d, u64));
898 else
899 ASSERT (0);
900 break;
901
902 case 's':
903 serialize_cstring (m, (char *) d);
904 if (n_bytes == 0)
905 n_bytes = strlen ((char *) d) + 1;
906 break;
907
908 case 'f':
909 if (n_bytes == 4)
910 serialize (m, serialize_f32, clib_mem_unaligned (d, f32));
911 else if (n_bytes == 8)
912 serialize (m, serialize_f64, clib_mem_unaligned (d, f64));
913 else
914 ASSERT (0);
915 break;
916
917 default:
918 ASSERT (0);
919 break;
920 }
921
922 p += 1 + n_digits;
923 d += n_bytes;
924 }
925}
926
927static void
928unserialize_elog_event (serialize_main_t * m, va_list * va)
929{
Dave Barachc3799992016-08-15 11:12:27 -0400930 elog_main_t *em = va_arg (*va, elog_main_t *);
931 elog_event_t *e = va_arg (*va, elog_event_t *);
932 elog_event_type_t *t;
933 u8 *p, *d;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700934
935 {
936 u16 tmp[2];
937
Dave Barache09ae012020-08-19 06:59:53 -0400938 unserialize_integer (m, &tmp[0], sizeof (e->event_type));
Ed Warnickecb9cada2015-12-08 15:45:58 -0700939 unserialize_integer (m, &tmp[1], sizeof (e->track));
940
Dave Barache09ae012020-08-19 06:59:53 -0400941 e->event_type = tmp[0];
Ed Warnickecb9cada2015-12-08 15:45:58 -0700942 e->track = tmp[1];
943
944 /* Make sure it fits. */
Dave Barache09ae012020-08-19 06:59:53 -0400945 ASSERT (e->event_type == tmp[0]);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700946 ASSERT (e->track == tmp[1]);
947 }
948
Dave Barache09ae012020-08-19 06:59:53 -0400949 t = vec_elt_at_index (em->event_types, e->event_type);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700950
951 unserialize (m, unserialize_f64, &e->time);
952
953 d = e->data;
954 p = (u8 *) t->format_args;
955
956 while (p && *p)
957 {
958 uword n_digits, n_bytes = 0;
959 u32 tmp;
960
961 n_digits = parse_2digit_decimal ((char *) p + 1, &n_bytes);
962
963 switch (p[0])
964 {
965 case 'i':
966 case 't':
967 case 'T':
968 if (n_bytes == 1)
969 {
970 unserialize_integer (m, &tmp, sizeof (u8));
971 d[0] = tmp;
972 }
973 else if (n_bytes == 2)
974 {
975 unserialize_integer (m, &tmp, sizeof (u16));
976 clib_mem_unaligned (d, u16) = tmp;
977 }
978 else if (n_bytes == 4)
979 {
980 unserialize_integer (m, &tmp, sizeof (u32));
981 clib_mem_unaligned (d, u32) = tmp;
982 }
983 else if (n_bytes == 8)
984 {
985 u64 x;
986 unserialize (m, unserialize_64, &x);
987 clib_mem_unaligned (d, u64) = x;
988 }
989 else
990 ASSERT (0);
991 break;
992
Dave Barachc3799992016-08-15 11:12:27 -0400993 case 's':
994 {
995 char *t;
996 unserialize_cstring (m, &t);
997 if (n_bytes == 0)
998 n_bytes = strlen (t) + 1;
999 clib_memcpy (d, t, clib_min (n_bytes, vec_len (t)));
1000 vec_free (t);
1001 break;
1002 }
Ed Warnickecb9cada2015-12-08 15:45:58 -07001003
1004 case 'f':
1005 if (n_bytes == 4)
1006 {
1007 f32 x;
1008 unserialize (m, unserialize_f32, &x);
1009 clib_mem_unaligned (d, f32) = x;
1010 }
1011 else if (n_bytes == 8)
1012 {
1013 f64 x;
1014 unserialize (m, unserialize_f64, &x);
1015 clib_mem_unaligned (d, f64) = x;
1016 }
1017 else
1018 ASSERT (0);
1019 break;
1020
1021 default:
1022 ASSERT (0);
1023 break;
1024 }
1025
1026 p += 1 + n_digits;
1027 d += n_bytes;
1028 }
1029}
1030
1031static void
1032serialize_elog_event_type (serialize_main_t * m, va_list * va)
1033{
Dave Barachc3799992016-08-15 11:12:27 -04001034 elog_event_type_t *t = va_arg (*va, elog_event_type_t *);
Ed Warnickecb9cada2015-12-08 15:45:58 -07001035 int n = va_arg (*va, int);
1036 int i, j;
1037 for (i = 0; i < n; i++)
1038 {
1039 serialize_cstring (m, t[i].format);
1040 serialize_cstring (m, t[i].format_args);
Dave Barachc3799992016-08-15 11:12:27 -04001041 serialize_integer (m, t[i].type_index_plus_one,
1042 sizeof (t->type_index_plus_one));
1043 serialize_integer (m, t[i].n_enum_strings,
1044 sizeof (t[i].n_enum_strings));
Ed Warnickecb9cada2015-12-08 15:45:58 -07001045 for (j = 0; j < t[i].n_enum_strings; j++)
1046 serialize_cstring (m, t[i].enum_strings_vector[j]);
1047 }
1048}
1049
1050static void
1051unserialize_elog_event_type (serialize_main_t * m, va_list * va)
1052{
Dave Barachc3799992016-08-15 11:12:27 -04001053 elog_event_type_t *t = va_arg (*va, elog_event_type_t *);
Ed Warnickecb9cada2015-12-08 15:45:58 -07001054 int n = va_arg (*va, int);
1055 int i, j;
1056 for (i = 0; i < n; i++)
1057 {
1058 unserialize_cstring (m, &t[i].format);
1059 unserialize_cstring (m, &t[i].format_args);
Dave Barachc3799992016-08-15 11:12:27 -04001060 unserialize_integer (m, &t[i].type_index_plus_one,
1061 sizeof (t->type_index_plus_one));
1062 unserialize_integer (m, &t[i].n_enum_strings,
1063 sizeof (t[i].n_enum_strings));
Ed Warnickecb9cada2015-12-08 15:45:58 -07001064 vec_resize (t[i].enum_strings_vector, t[i].n_enum_strings);
1065 for (j = 0; j < t[i].n_enum_strings; j++)
1066 unserialize_cstring (m, &t[i].enum_strings_vector[j]);
1067 }
1068}
1069
1070static void
1071serialize_elog_track (serialize_main_t * m, va_list * va)
1072{
Dave Barachc3799992016-08-15 11:12:27 -04001073 elog_track_t *t = va_arg (*va, elog_track_t *);
Ed Warnickecb9cada2015-12-08 15:45:58 -07001074 int n = va_arg (*va, int);
1075 int i;
1076 for (i = 0; i < n; i++)
1077 {
1078 serialize_cstring (m, t[i].name);
1079 }
1080}
1081
1082static void
1083unserialize_elog_track (serialize_main_t * m, va_list * va)
1084{
Dave Barachc3799992016-08-15 11:12:27 -04001085 elog_track_t *t = va_arg (*va, elog_track_t *);
Ed Warnickecb9cada2015-12-08 15:45:58 -07001086 int n = va_arg (*va, int);
1087 int i;
1088 for (i = 0; i < n; i++)
1089 {
1090 unserialize_cstring (m, &t[i].name);
1091 }
1092}
1093
1094static void
1095serialize_elog_time_stamp (serialize_main_t * m, va_list * va)
1096{
Dave Barachc3799992016-08-15 11:12:27 -04001097 elog_time_stamp_t *st = va_arg (*va, elog_time_stamp_t *);
Ed Warnickecb9cada2015-12-08 15:45:58 -07001098 serialize (m, serialize_64, st->os_nsec);
1099 serialize (m, serialize_64, st->cpu);
1100}
1101
1102static void
1103unserialize_elog_time_stamp (serialize_main_t * m, va_list * va)
1104{
Dave Barachc3799992016-08-15 11:12:27 -04001105 elog_time_stamp_t *st = va_arg (*va, elog_time_stamp_t *);
Ed Warnickecb9cada2015-12-08 15:45:58 -07001106 unserialize (m, unserialize_64, &st->os_nsec);
1107 unserialize (m, unserialize_64, &st->cpu);
1108}
1109
Dave Barachc3799992016-08-15 11:12:27 -04001110static char *elog_serialize_magic = "elog v0";
Ed Warnickecb9cada2015-12-08 15:45:58 -07001111
Damjan Mariondae1c7e2020-10-17 13:32:25 +02001112__clib_export void
Ed Warnickecb9cada2015-12-08 15:45:58 -07001113serialize_elog_main (serialize_main_t * m, va_list * va)
1114{
Dave Barachc3799992016-08-15 11:12:27 -04001115 elog_main_t *em = va_arg (*va, elog_main_t *);
Dave Barach903fd512017-04-01 11:07:40 -04001116 int flush_ring = va_arg (*va, int);
Dave Barachc3799992016-08-15 11:12:27 -04001117 elog_event_t *e;
Ed Warnickecb9cada2015-12-08 15:45:58 -07001118
1119 serialize_magic (m, elog_serialize_magic, strlen (elog_serialize_magic));
1120
1121 serialize_integer (m, em->event_ring_size, sizeof (u32));
1122
1123 elog_time_now (&em->serialize_time);
1124 serialize (m, serialize_elog_time_stamp, &em->serialize_time);
1125 serialize (m, serialize_elog_time_stamp, &em->init_time);
1126
1127 vec_serialize (m, em->event_types, serialize_elog_event_type);
1128 vec_serialize (m, em->tracks, serialize_elog_track);
1129 vec_serialize (m, em->string_table, serialize_vec_8);
1130
1131 /* Free old events (cached) in case they have changed. */
Dave Barach903fd512017-04-01 11:07:40 -04001132 if (flush_ring)
1133 {
1134 vec_free (em->events);
1135 elog_get_events (em);
1136 }
Ed Warnickecb9cada2015-12-08 15:45:58 -07001137
1138 serialize_integer (m, vec_len (em->events), sizeof (u32));
1139
1140 /* SMP logs can easily have local time paradoxes... */
Matus Fabiand2dc3df2015-12-14 10:31:33 -05001141 vec_sort_with_function (em->events, elog_cmp);
Ed Warnickecb9cada2015-12-08 15:45:58 -07001142
Dave Barachc3799992016-08-15 11:12:27 -04001143 vec_foreach (e, em->events) serialize (m, serialize_elog_event, em, e);
Ed Warnickecb9cada2015-12-08 15:45:58 -07001144}
1145
1146void
1147unserialize_elog_main (serialize_main_t * m, va_list * va)
1148{
Dave Barachc3799992016-08-15 11:12:27 -04001149 elog_main_t *em = va_arg (*va, elog_main_t *);
Ed Warnickecb9cada2015-12-08 15:45:58 -07001150 uword i;
1151 u32 rs;
1152
1153 unserialize_check_magic (m, elog_serialize_magic,
1154 strlen (elog_serialize_magic));
1155
1156 unserialize_integer (m, &rs, sizeof (u32));
1157 em->event_ring_size = rs;
1158 elog_init (em, em->event_ring_size);
1159
1160 unserialize (m, unserialize_elog_time_stamp, &em->serialize_time);
1161 unserialize (m, unserialize_elog_time_stamp, &em->init_time);
1162 em->nsec_per_cpu_clock = elog_nsec_per_clock (em);
1163
1164 vec_unserialize (m, &em->event_types, unserialize_elog_event_type);
1165 for (i = 0; i < vec_len (em->event_types); i++)
1166 new_event_type (em, i);
1167
1168 vec_unserialize (m, &em->tracks, unserialize_elog_track);
1169 vec_unserialize (m, &em->string_table, unserialize_vec_8);
1170
1171 {
1172 u32 ne;
Dave Barachc3799992016-08-15 11:12:27 -04001173 elog_event_t *e;
Ed Warnickecb9cada2015-12-08 15:45:58 -07001174
1175 unserialize_integer (m, &ne, sizeof (u32));
1176 vec_resize (em->events, ne);
1177 vec_foreach (e, em->events)
1178 unserialize (m, unserialize_elog_event, em, e);
1179 }
1180}
Dave Barachc3799992016-08-15 11:12:27 -04001181
Dave Barache09ae012020-08-19 06:59:53 -04001182#ifdef CLIB_UNIX
1183clib_error_t *
1184elog_write_file_not_inline (elog_main_t * em, char *clib_file, int flush_ring)
1185{
1186 serialize_main_t m;
1187 clib_error_t *error;
1188
1189 error = serialize_open_clib_file (&m, clib_file);
1190 if (error)
1191 return error;
1192 error = serialize (&m, serialize_elog_main, em, flush_ring);
1193 if (!error)
1194 serialize_close (&m);
1195 return error;
1196}
1197
Dave Barach009fd6a2020-10-20 15:17:50 -04001198__clib_export clib_error_t *
Dave Barache09ae012020-08-19 06:59:53 -04001199elog_read_file_not_inline (elog_main_t * em, char *clib_file)
1200{
1201 serialize_main_t m;
1202 clib_error_t *error;
1203
1204 error = unserialize_open_clib_file (&m, clib_file);
1205 if (error)
1206 return error;
1207 error = unserialize (&m, unserialize_elog_main, em);
1208 if (!error)
1209 unserialize_close (&m);
1210 return error;
1211}
1212#endif /* CLIB_UNIX */
1213
1214
Dave Barachc3799992016-08-15 11:12:27 -04001215/*
1216 * fd.io coding-style-patch-verification: ON
1217 *
1218 * Local Variables:
1219 * eval: (c-set-style "gnu")
1220 * End:
1221 */