blob: 6fa44cb82f9a6f8283095bfc60008e8dd105345c [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
Damjan Mariondae1c7e2020-10-17 13:32:25 +0200487__clib_export void
Dave Barachc3799992016-08-15 11:12:27 -0400488elog_alloc (elog_main_t * em, u32 n_events)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700489{
490 if (em->event_ring)
491 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
496 /* Leave an empty ievent at end so we can always speculatively write
497 and event there (possibly a long form event). */
498 vec_resize_aligned (em->event_ring, n_events, CLIB_CACHE_LINE_BYTES);
499}
500
Damjan Mariondae1c7e2020-10-17 13:32:25 +0200501__clib_export void
Dave Barachc3799992016-08-15 11:12:27 -0400502elog_init (elog_main_t * em, u32 n_events)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700503{
Dave Barachb7b92992018-10-17 10:38:51 -0400504 clib_memset (em, 0, sizeof (em[0]));
Ed Warnickecb9cada2015-12-08 15:45:58 -0700505
506 em->lock = 0;
507
508 if (n_events > 0)
509 elog_alloc (em, n_events);
510
511 clib_time_init (&em->cpu_timer);
512
513 em->n_total_events_disable_limit = ~0;
514
515 /* Make track 0. */
516 em->default_track.name = "default";
517 elog_track_register (em, &em->default_track);
518
519 elog_time_now (&em->init_time);
Dave Barach9c8ca8d2019-06-14 12:02:38 -0400520 em->string_table_hash = hash_create_string (0, sizeof (uword));
Ed Warnickecb9cada2015-12-08 15:45:58 -0700521}
522
523/* Returns number of events in ring and start index. */
Dave Barachc3799992016-08-15 11:12:27 -0400524static uword
525elog_event_range (elog_main_t * em, uword * lo)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700526{
527 uword l = em->event_ring_size;
528 u64 i = em->n_total_events;
529
530 /* Ring never wrapped? */
531 if (i <= (u64) l)
532 {
Dave Barachc3799992016-08-15 11:12:27 -0400533 if (lo)
534 *lo = 0;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700535 return i;
536 }
537 else
538 {
Dave Barachc3799992016-08-15 11:12:27 -0400539 if (lo)
540 *lo = i & (l - 1);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700541 return l;
542 }
543}
544
Damjan Mariondae1c7e2020-10-17 13:32:25 +0200545__clib_export elog_event_t *
Dave Barachc3799992016-08-15 11:12:27 -0400546elog_peek_events (elog_main_t * em)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700547{
Dave Barachc3799992016-08-15 11:12:27 -0400548 elog_event_t *e, *f, *es = 0;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700549 uword i, j, n;
550
551 n = elog_event_range (em, &j);
552 for (i = 0; i < n; i++)
553 {
554 vec_add2 (es, e, 1);
555 f = vec_elt_at_index (em->event_ring, j);
556 e[0] = f[0];
557
558 /* Convert absolute time from cycles to seconds from start. */
Dave Barachc3799992016-08-15 11:12:27 -0400559 e->time =
560 (e->time_cycles -
561 em->init_time.cpu) * em->cpu_timer.seconds_per_clock;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700562
563 j = (j + 1) & (em->event_ring_size - 1);
564 }
565
566 return es;
567}
568
569/* Add a formatted string to the string table. */
Damjan Mariondae1c7e2020-10-17 13:32:25 +0200570__clib_export u32
Dave Barachc3799992016-08-15 11:12:27 -0400571elog_string (elog_main_t * em, char *fmt, ...)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700572{
573 u32 offset;
Dave Barach9c8ca8d2019-06-14 12:02:38 -0400574 uword *p;
575 uword len;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700576 va_list va;
577
Steven Luongd31a5982019-05-31 07:34:39 -0700578 elog_lock (em);
Dave Barach9c8ca8d2019-06-14 12:02:38 -0400579 vec_reset_length (em->string_table_tmp);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700580 va_start (va, fmt);
Dave Barach9c8ca8d2019-06-14 12:02:38 -0400581 em->string_table_tmp = va_format (em->string_table_tmp, fmt, &va);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700582 va_end (va);
583
Benoît Ganneb11e4ae2019-07-17 11:45:20 +0200584 /* String table entries MUST be NULL terminated */
585 len = vec_len (em->string_table_tmp);
586 ASSERT (len > 0);
587 if (em->string_table_tmp[len - 1] != 0)
588 vec_add1 (em->string_table_tmp, 0);
589
Dave Barach9c8ca8d2019-06-14 12:02:38 -0400590 /* See if we already have this string in the string table */
591 p = hash_get_mem (em->string_table_hash, em->string_table_tmp);
592
593 /* We already have the string, so give the caller its offset */
594 if (p)
595 {
596 elog_unlock (em);
597 return (p[0]);
598 }
599
Benoît Ganneb11e4ae2019-07-17 11:45:20 +0200600 /* We don't, so add it. */
Dave Barach9c8ca8d2019-06-14 12:02:38 -0400601
602 offset = vec_len (em->string_table);
603 vec_append (em->string_table, em->string_table_tmp);
604
605 hash_set_mem (em->string_table_hash, em->string_table_tmp, offset);
606
607 /* We gave the key to the string table hash, so we can't reuse it! */
608 em->string_table_tmp = 0;
Steven Luongd31a5982019-05-31 07:34:39 -0700609 elog_unlock (em);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700610
611 return offset;
612}
613
Dave Barach6acb7a02020-10-17 17:22:47 -0400614__clib_export elog_event_t *
Dave Barachc3799992016-08-15 11:12:27 -0400615elog_get_events (elog_main_t * em)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700616{
Dave Barach1046b1a2020-10-08 16:04:30 -0400617 vec_free (em->events);
Dave Barachab1a50c2020-10-06 14:08:16 -0400618 em->events = elog_peek_events (em);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700619 return em->events;
620}
621
Dave Barachc3799992016-08-15 11:12:27 -0400622static void
623maybe_fix_string_table_offset (elog_event_t * e,
624 elog_event_type_t * t, u32 offset)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700625{
Dave Barachc3799992016-08-15 11:12:27 -0400626 void *d = (u8 *) e->data;
627 char *a;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700628
629 if (offset == 0)
630 return;
631
632 a = t->format_args;
633
634 while (1)
635 {
636 uword n_bytes = 0, n_digits;
637
638 if (a[0] == 0)
Dave Barachc3799992016-08-15 11:12:27 -0400639 break;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700640
641 /* Don't go past end of event data. */
642 ASSERT (d < (void *) (e->data + sizeof (e->data)));
643
644 n_digits = parse_2digit_decimal (a + 1, &n_bytes);
645 switch (a[0])
646 {
647 case 'T':
Dave Barachc3799992016-08-15 11:12:27 -0400648 ASSERT (n_bytes == 4);
649 clib_mem_unaligned (d, u32) += offset;
650 break;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700651
652 case 'i':
653 case 't':
654 case 'f':
655 case 's':
656 break;
657
658 default:
659 ASSERT (0);
660 break;
661 }
662
663 ASSERT (n_digits > 0 && n_digits <= 2);
664 a += 1 + n_digits;
665 d += n_bytes;
666 }
667}
668
Dave Barachc3799992016-08-15 11:12:27 -0400669static int
670elog_cmp (void *a1, void *a2)
Matus Fabiand2dc3df2015-12-14 10:31:33 -0500671{
Dave Barachc3799992016-08-15 11:12:27 -0400672 elog_event_t *e1 = a1;
673 elog_event_t *e2 = a2;
Matus Fabiand2dc3df2015-12-14 10:31:33 -0500674
Dave Barach903fd512017-04-01 11:07:40 -0400675 if (e1->time < e2->time)
676 return -1;
677
678 if (e1->time > e2->time)
679 return 1;
680
681 return 0;
Matus Fabiand2dc3df2015-12-14 10:31:33 -0500682}
683
Dave Barach903fd512017-04-01 11:07:40 -0400684/*
685 * merge two event logs. Complicated and cranky.
686 */
Dave Barachc3799992016-08-15 11:12:27 -0400687void
Dave Barach903fd512017-04-01 11:07:40 -0400688elog_merge (elog_main_t * dst, u8 * dst_tag, elog_main_t * src, u8 * src_tag,
689 f64 align_tweak)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700690{
Dave Barachc3799992016-08-15 11:12:27 -0400691 elog_event_t *e;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700692 uword l;
693 u32 string_table_offset_for_src_events;
694 u32 track_offset_for_src_tracks;
695 elog_track_t newt;
696 int i;
697
Dave Barachb7b92992018-10-17 10:38:51 -0400698 clib_memset (&newt, 0, sizeof (newt));
Dave Barachf9c231e2016-08-05 10:10:18 -0400699
Dave Barach903fd512017-04-01 11:07:40 -0400700 /* Acquire src and dst events */
Ed Warnickecb9cada2015-12-08 15:45:58 -0700701 elog_get_events (src);
702 elog_get_events (dst);
703
704 string_table_offset_for_src_events = vec_len (dst->string_table);
705 vec_append (dst->string_table, src->string_table);
706
707 l = vec_len (dst->events);
Dave Barach903fd512017-04-01 11:07:40 -0400708 vec_append (dst->events, src->events);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700709
710 /* Prepend the supplied tag (if any) to all dst track names */
711 if (dst_tag)
712 {
Dave Barachc3799992016-08-15 11:12:27 -0400713 for (i = 0; i < vec_len (dst->tracks); i++)
714 {
715 elog_track_t *t = vec_elt_at_index (dst->tracks, i);
716 char *new_name;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700717
Dave Barachc3799992016-08-15 11:12:27 -0400718 new_name = (char *) format (0, "%s:%s%c", dst_tag, t->name, 0);
719 vec_free (t->name);
720 t->name = new_name;
721 }
Ed Warnickecb9cada2015-12-08 15:45:58 -0700722 }
Dave Barachc3799992016-08-15 11:12:27 -0400723
Dave Barach903fd512017-04-01 11:07:40 -0400724 /*
725 * Remember where we started allocating new tracks while merging
726 */
Ed Warnickecb9cada2015-12-08 15:45:58 -0700727 track_offset_for_src_tracks = vec_len (dst->tracks);
Dave Barachc3799992016-08-15 11:12:27 -0400728
Ed Warnickecb9cada2015-12-08 15:45:58 -0700729 /* Copy / tag source tracks */
730 for (i = 0; i < vec_len (src->tracks); i++)
731 {
Dave Barachc3799992016-08-15 11:12:27 -0400732 elog_track_t *t = vec_elt_at_index (src->tracks, i);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700733 if (src_tag)
Dave Barachc3799992016-08-15 11:12:27 -0400734 newt.name = (char *) format (0, "%s:%s%c", src_tag, t->name, 0);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700735 else
Dave Barachc3799992016-08-15 11:12:27 -0400736 newt.name = (char *) format (0, "%s%c", t->name, 0);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700737 (void) elog_track_register (dst, &newt);
738 vec_free (newt.name);
739 }
Dave Barachc3799992016-08-15 11:12:27 -0400740
Ed Warnickecb9cada2015-12-08 15:45:58 -0700741 /* Across all (copied) src events... */
742 for (e = dst->events + l; e < vec_end (dst->events); e++)
743 {
Dave Barache09ae012020-08-19 06:59:53 -0400744 elog_event_type_t *t =
745 vec_elt_at_index (src->event_types, e->event_type);
Dave Barachc3799992016-08-15 11:12:27 -0400746
Ed Warnickecb9cada2015-12-08 15:45:58 -0700747 /* Remap type from src -> dst. */
Dave Barache09ae012020-08-19 06:59:53 -0400748 e->event_type = find_or_create_type (dst, t);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700749
750 /* Remap string table offsets for 'T' format args */
Dave Barachc3799992016-08-15 11:12:27 -0400751 maybe_fix_string_table_offset (e, t,
752 string_table_offset_for_src_events);
753
Ed Warnickecb9cada2015-12-08 15:45:58 -0700754 /* Remap track */
755 e->track += track_offset_for_src_tracks;
756 }
757
758 /* Adjust event times for relative starting times of event streams. */
759 {
760 f64 dt_event, dt_os_nsec, dt_clock_nsec;
761
762 /* Set clock parameters if dst was not generated by unserialize. */
763 if (dst->serialize_time.cpu == 0)
764 {
765 dst->init_time = src->init_time;
766 dst->serialize_time = src->serialize_time;
767 dst->nsec_per_cpu_clock = src->nsec_per_cpu_clock;
768 }
769
Dave Barachc3799992016-08-15 11:12:27 -0400770 dt_os_nsec =
771 elog_time_stamp_diff_os_nsec (&src->init_time, &dst->init_time);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700772
773 dt_event = dt_os_nsec;
Dave Barachc3799992016-08-15 11:12:27 -0400774 dt_clock_nsec =
775 (elog_time_stamp_diff_cpu (&src->init_time, &dst->init_time) * .5 *
776 (dst->nsec_per_cpu_clock + src->nsec_per_cpu_clock));
Ed Warnickecb9cada2015-12-08 15:45:58 -0700777
Dave Barach903fd512017-04-01 11:07:40 -0400778 /*
779 * Heuristic to see if src/dst came from same time source.
780 * If frequencies are "the same" and os clock and cpu clock agree
781 * to within 100e-9 secs about time difference between src/dst
782 * init_time, then we use cpu clock. Otherwise we use OS clock.
783 *
784 * When merging event logs from different systems, time paradoxes
785 * at the O(1ms) level are to be expected. Hence, the "align_tweak"
786 * parameter. If two events logged on different processors are known
787 * to occur in a specific order - and with a reasonably-estimated
788 * interval - supply a non-zero "align_tweak" parameter
789 */
Ed Warnickecb9cada2015-12-08 15:45:58 -0700790 if (fabs (src->nsec_per_cpu_clock - dst->nsec_per_cpu_clock) < 1e-2
791 && fabs (dt_os_nsec - dt_clock_nsec) < 100)
792 dt_event = dt_clock_nsec;
793
794 /* Convert to seconds. */
795 dt_event *= 1e-9;
796
Dave Barach903fd512017-04-01 11:07:40 -0400797 /*
798 * Move the earlier set of events later, to avoid creating
Paul Vinciguerraec11b132018-09-24 05:25:00 -0700799 * events which precede the Big Bang (aka have negative timestamps).
Dave Barach903fd512017-04-01 11:07:40 -0400800 *
801 * Not to any scale, we have something like the following picture:
802 *
803 * DST capture start point
804 * ^
805 * +--- dt_event --+
806 * v
807 * SRC capture start point
808 *
809 * In this case dt_event is positive, src started after dst,
810 * to put src events onto a common timebase we have to move them
811 * forward in time. Naturally, the opposite case is
812 * possible, too: dt_event will be negative, and so we have to
813 * move dst events forward in time by the |dt_event|.
814 * In both cases, we add align_tweak.
815 */
Ed Warnickecb9cada2015-12-08 15:45:58 -0700816 if (dt_event > 0)
817 {
818 /* Src started after dst. */
819 for (e = dst->events + l; e < vec_end (dst->events); e++)
Dave Barach903fd512017-04-01 11:07:40 -0400820 e->time += dt_event + align_tweak;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700821 }
822 else
823 {
824 /* Dst started after src. */
Dave Barach903fd512017-04-01 11:07:40 -0400825 dt_event = -dt_event;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700826 for (e = dst->events + 0; e < dst->events + l; e++)
Dave Barach903fd512017-04-01 11:07:40 -0400827 e->time += dt_event + align_tweak;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700828 }
829 }
830
831 /* Sort events by increasing time. */
Matus Fabiand2dc3df2015-12-14 10:31:33 -0500832 vec_sort_with_function (dst->events, elog_cmp);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700833
Dave Barach903fd512017-04-01 11:07:40 -0400834 dst->n_total_events = vec_len (dst->events);
835
Ed Warnickecb9cada2015-12-08 15:45:58 -0700836 /* Recreate the event ring or the results won't serialize */
837 {
838 int i;
839
840 ASSERT (dst->cpu_timer.seconds_per_clock);
841
842 elog_alloc (dst, vec_len (dst->events));
Dave Barachc3799992016-08-15 11:12:27 -0400843 for (i = 0; i < vec_len (dst->events); i++)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700844 {
Dave Barachc3799992016-08-15 11:12:27 -0400845 elog_event_t *es, *ed;
846
847 es = dst->events + i;
848 ed = dst->event_ring + i;
849
850 ed[0] = es[0];
Ed Warnickecb9cada2015-12-08 15:45:58 -0700851 }
Ed Warnickecb9cada2015-12-08 15:45:58 -0700852 }
853}
854
855static void
856serialize_elog_event (serialize_main_t * m, va_list * va)
857{
Dave Barachc3799992016-08-15 11:12:27 -0400858 elog_main_t *em = va_arg (*va, elog_main_t *);
859 elog_event_t *e = va_arg (*va, elog_event_t *);
Dave Barache09ae012020-08-19 06:59:53 -0400860 elog_event_type_t *t = vec_elt_at_index (em->event_types, e->event_type);
Dave Barachc3799992016-08-15 11:12:27 -0400861 u8 *d = e->data;
862 u8 *p = (u8 *) t->format_args;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700863
Dave Barache09ae012020-08-19 06:59:53 -0400864 serialize_integer (m, e->event_type, sizeof (e->event_type));
Ed Warnickecb9cada2015-12-08 15:45:58 -0700865 serialize_integer (m, e->track, sizeof (e->track));
866 serialize (m, serialize_f64, e->time);
867
868 while (*p)
869 {
870 uword n_digits, n_bytes = 0;
871
872 n_digits = parse_2digit_decimal ((char *) p + 1, &n_bytes);
873
874 switch (p[0])
875 {
876 case 'i':
877 case 't':
878 case 'T':
879 if (n_bytes == 1)
880 serialize_integer (m, d[0], sizeof (u8));
881 else if (n_bytes == 2)
882 serialize_integer (m, clib_mem_unaligned (d, u16), sizeof (u16));
883 else if (n_bytes == 4)
884 serialize_integer (m, clib_mem_unaligned (d, u32), sizeof (u32));
885 else if (n_bytes == 8)
886 serialize (m, serialize_64, clib_mem_unaligned (d, u64));
887 else
888 ASSERT (0);
889 break;
890
891 case 's':
892 serialize_cstring (m, (char *) d);
893 if (n_bytes == 0)
894 n_bytes = strlen ((char *) d) + 1;
895 break;
896
897 case 'f':
898 if (n_bytes == 4)
899 serialize (m, serialize_f32, clib_mem_unaligned (d, f32));
900 else if (n_bytes == 8)
901 serialize (m, serialize_f64, clib_mem_unaligned (d, f64));
902 else
903 ASSERT (0);
904 break;
905
906 default:
907 ASSERT (0);
908 break;
909 }
910
911 p += 1 + n_digits;
912 d += n_bytes;
913 }
914}
915
916static void
917unserialize_elog_event (serialize_main_t * m, va_list * va)
918{
Dave Barachc3799992016-08-15 11:12:27 -0400919 elog_main_t *em = va_arg (*va, elog_main_t *);
920 elog_event_t *e = va_arg (*va, elog_event_t *);
921 elog_event_type_t *t;
922 u8 *p, *d;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700923
924 {
925 u16 tmp[2];
926
Dave Barache09ae012020-08-19 06:59:53 -0400927 unserialize_integer (m, &tmp[0], sizeof (e->event_type));
Ed Warnickecb9cada2015-12-08 15:45:58 -0700928 unserialize_integer (m, &tmp[1], sizeof (e->track));
929
Dave Barache09ae012020-08-19 06:59:53 -0400930 e->event_type = tmp[0];
Ed Warnickecb9cada2015-12-08 15:45:58 -0700931 e->track = tmp[1];
932
933 /* Make sure it fits. */
Dave Barache09ae012020-08-19 06:59:53 -0400934 ASSERT (e->event_type == tmp[0]);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700935 ASSERT (e->track == tmp[1]);
936 }
937
Dave Barache09ae012020-08-19 06:59:53 -0400938 t = vec_elt_at_index (em->event_types, e->event_type);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700939
940 unserialize (m, unserialize_f64, &e->time);
941
942 d = e->data;
943 p = (u8 *) t->format_args;
944
945 while (p && *p)
946 {
947 uword n_digits, n_bytes = 0;
948 u32 tmp;
949
950 n_digits = parse_2digit_decimal ((char *) p + 1, &n_bytes);
951
952 switch (p[0])
953 {
954 case 'i':
955 case 't':
956 case 'T':
957 if (n_bytes == 1)
958 {
959 unserialize_integer (m, &tmp, sizeof (u8));
960 d[0] = tmp;
961 }
962 else if (n_bytes == 2)
963 {
964 unserialize_integer (m, &tmp, sizeof (u16));
965 clib_mem_unaligned (d, u16) = tmp;
966 }
967 else if (n_bytes == 4)
968 {
969 unserialize_integer (m, &tmp, sizeof (u32));
970 clib_mem_unaligned (d, u32) = tmp;
971 }
972 else if (n_bytes == 8)
973 {
974 u64 x;
975 unserialize (m, unserialize_64, &x);
976 clib_mem_unaligned (d, u64) = x;
977 }
978 else
979 ASSERT (0);
980 break;
981
Dave Barachc3799992016-08-15 11:12:27 -0400982 case 's':
983 {
984 char *t;
985 unserialize_cstring (m, &t);
986 if (n_bytes == 0)
987 n_bytes = strlen (t) + 1;
988 clib_memcpy (d, t, clib_min (n_bytes, vec_len (t)));
989 vec_free (t);
990 break;
991 }
Ed Warnickecb9cada2015-12-08 15:45:58 -0700992
993 case 'f':
994 if (n_bytes == 4)
995 {
996 f32 x;
997 unserialize (m, unserialize_f32, &x);
998 clib_mem_unaligned (d, f32) = x;
999 }
1000 else if (n_bytes == 8)
1001 {
1002 f64 x;
1003 unserialize (m, unserialize_f64, &x);
1004 clib_mem_unaligned (d, f64) = x;
1005 }
1006 else
1007 ASSERT (0);
1008 break;
1009
1010 default:
1011 ASSERT (0);
1012 break;
1013 }
1014
1015 p += 1 + n_digits;
1016 d += n_bytes;
1017 }
1018}
1019
1020static void
1021serialize_elog_event_type (serialize_main_t * m, va_list * va)
1022{
Dave Barachc3799992016-08-15 11:12:27 -04001023 elog_event_type_t *t = va_arg (*va, elog_event_type_t *);
Ed Warnickecb9cada2015-12-08 15:45:58 -07001024 int n = va_arg (*va, int);
1025 int i, j;
1026 for (i = 0; i < n; i++)
1027 {
1028 serialize_cstring (m, t[i].format);
1029 serialize_cstring (m, t[i].format_args);
Dave Barachc3799992016-08-15 11:12:27 -04001030 serialize_integer (m, t[i].type_index_plus_one,
1031 sizeof (t->type_index_plus_one));
1032 serialize_integer (m, t[i].n_enum_strings,
1033 sizeof (t[i].n_enum_strings));
Ed Warnickecb9cada2015-12-08 15:45:58 -07001034 for (j = 0; j < t[i].n_enum_strings; j++)
1035 serialize_cstring (m, t[i].enum_strings_vector[j]);
1036 }
1037}
1038
1039static void
1040unserialize_elog_event_type (serialize_main_t * m, va_list * va)
1041{
Dave Barachc3799992016-08-15 11:12:27 -04001042 elog_event_type_t *t = va_arg (*va, elog_event_type_t *);
Ed Warnickecb9cada2015-12-08 15:45:58 -07001043 int n = va_arg (*va, int);
1044 int i, j;
1045 for (i = 0; i < n; i++)
1046 {
1047 unserialize_cstring (m, &t[i].format);
1048 unserialize_cstring (m, &t[i].format_args);
Dave Barachc3799992016-08-15 11:12:27 -04001049 unserialize_integer (m, &t[i].type_index_plus_one,
1050 sizeof (t->type_index_plus_one));
1051 unserialize_integer (m, &t[i].n_enum_strings,
1052 sizeof (t[i].n_enum_strings));
Ed Warnickecb9cada2015-12-08 15:45:58 -07001053 vec_resize (t[i].enum_strings_vector, t[i].n_enum_strings);
1054 for (j = 0; j < t[i].n_enum_strings; j++)
1055 unserialize_cstring (m, &t[i].enum_strings_vector[j]);
1056 }
1057}
1058
1059static void
1060serialize_elog_track (serialize_main_t * m, va_list * va)
1061{
Dave Barachc3799992016-08-15 11:12:27 -04001062 elog_track_t *t = va_arg (*va, elog_track_t *);
Ed Warnickecb9cada2015-12-08 15:45:58 -07001063 int n = va_arg (*va, int);
1064 int i;
1065 for (i = 0; i < n; i++)
1066 {
1067 serialize_cstring (m, t[i].name);
1068 }
1069}
1070
1071static void
1072unserialize_elog_track (serialize_main_t * m, va_list * va)
1073{
Dave Barachc3799992016-08-15 11:12:27 -04001074 elog_track_t *t = va_arg (*va, elog_track_t *);
Ed Warnickecb9cada2015-12-08 15:45:58 -07001075 int n = va_arg (*va, int);
1076 int i;
1077 for (i = 0; i < n; i++)
1078 {
1079 unserialize_cstring (m, &t[i].name);
1080 }
1081}
1082
1083static void
1084serialize_elog_time_stamp (serialize_main_t * m, va_list * va)
1085{
Dave Barachc3799992016-08-15 11:12:27 -04001086 elog_time_stamp_t *st = va_arg (*va, elog_time_stamp_t *);
Ed Warnickecb9cada2015-12-08 15:45:58 -07001087 serialize (m, serialize_64, st->os_nsec);
1088 serialize (m, serialize_64, st->cpu);
1089}
1090
1091static void
1092unserialize_elog_time_stamp (serialize_main_t * m, va_list * va)
1093{
Dave Barachc3799992016-08-15 11:12:27 -04001094 elog_time_stamp_t *st = va_arg (*va, elog_time_stamp_t *);
Ed Warnickecb9cada2015-12-08 15:45:58 -07001095 unserialize (m, unserialize_64, &st->os_nsec);
1096 unserialize (m, unserialize_64, &st->cpu);
1097}
1098
Dave Barachc3799992016-08-15 11:12:27 -04001099static char *elog_serialize_magic = "elog v0";
Ed Warnickecb9cada2015-12-08 15:45:58 -07001100
Damjan Mariondae1c7e2020-10-17 13:32:25 +02001101__clib_export void
Ed Warnickecb9cada2015-12-08 15:45:58 -07001102serialize_elog_main (serialize_main_t * m, va_list * va)
1103{
Dave Barachc3799992016-08-15 11:12:27 -04001104 elog_main_t *em = va_arg (*va, elog_main_t *);
Dave Barach903fd512017-04-01 11:07:40 -04001105 int flush_ring = va_arg (*va, int);
Dave Barachc3799992016-08-15 11:12:27 -04001106 elog_event_t *e;
Ed Warnickecb9cada2015-12-08 15:45:58 -07001107
1108 serialize_magic (m, elog_serialize_magic, strlen (elog_serialize_magic));
1109
1110 serialize_integer (m, em->event_ring_size, sizeof (u32));
1111
1112 elog_time_now (&em->serialize_time);
1113 serialize (m, serialize_elog_time_stamp, &em->serialize_time);
1114 serialize (m, serialize_elog_time_stamp, &em->init_time);
1115
1116 vec_serialize (m, em->event_types, serialize_elog_event_type);
1117 vec_serialize (m, em->tracks, serialize_elog_track);
1118 vec_serialize (m, em->string_table, serialize_vec_8);
1119
1120 /* Free old events (cached) in case they have changed. */
Dave Barach903fd512017-04-01 11:07:40 -04001121 if (flush_ring)
1122 {
1123 vec_free (em->events);
1124 elog_get_events (em);
1125 }
Ed Warnickecb9cada2015-12-08 15:45:58 -07001126
1127 serialize_integer (m, vec_len (em->events), sizeof (u32));
1128
1129 /* SMP logs can easily have local time paradoxes... */
Matus Fabiand2dc3df2015-12-14 10:31:33 -05001130 vec_sort_with_function (em->events, elog_cmp);
Ed Warnickecb9cada2015-12-08 15:45:58 -07001131
Dave Barachc3799992016-08-15 11:12:27 -04001132 vec_foreach (e, em->events) serialize (m, serialize_elog_event, em, e);
Ed Warnickecb9cada2015-12-08 15:45:58 -07001133}
1134
1135void
1136unserialize_elog_main (serialize_main_t * m, va_list * va)
1137{
Dave Barachc3799992016-08-15 11:12:27 -04001138 elog_main_t *em = va_arg (*va, elog_main_t *);
Ed Warnickecb9cada2015-12-08 15:45:58 -07001139 uword i;
1140 u32 rs;
1141
1142 unserialize_check_magic (m, elog_serialize_magic,
1143 strlen (elog_serialize_magic));
1144
1145 unserialize_integer (m, &rs, sizeof (u32));
1146 em->event_ring_size = rs;
1147 elog_init (em, em->event_ring_size);
1148
1149 unserialize (m, unserialize_elog_time_stamp, &em->serialize_time);
1150 unserialize (m, unserialize_elog_time_stamp, &em->init_time);
1151 em->nsec_per_cpu_clock = elog_nsec_per_clock (em);
1152
1153 vec_unserialize (m, &em->event_types, unserialize_elog_event_type);
1154 for (i = 0; i < vec_len (em->event_types); i++)
1155 new_event_type (em, i);
1156
1157 vec_unserialize (m, &em->tracks, unserialize_elog_track);
1158 vec_unserialize (m, &em->string_table, unserialize_vec_8);
1159
1160 {
1161 u32 ne;
Dave Barachc3799992016-08-15 11:12:27 -04001162 elog_event_t *e;
Ed Warnickecb9cada2015-12-08 15:45:58 -07001163
1164 unserialize_integer (m, &ne, sizeof (u32));
1165 vec_resize (em->events, ne);
1166 vec_foreach (e, em->events)
1167 unserialize (m, unserialize_elog_event, em, e);
1168 }
1169}
Dave Barachc3799992016-08-15 11:12:27 -04001170
Dave Barache09ae012020-08-19 06:59:53 -04001171#ifdef CLIB_UNIX
1172clib_error_t *
1173elog_write_file_not_inline (elog_main_t * em, char *clib_file, int flush_ring)
1174{
1175 serialize_main_t m;
1176 clib_error_t *error;
1177
1178 error = serialize_open_clib_file (&m, clib_file);
1179 if (error)
1180 return error;
1181 error = serialize (&m, serialize_elog_main, em, flush_ring);
1182 if (!error)
1183 serialize_close (&m);
1184 return error;
1185}
1186
Dave Barach009fd6a2020-10-20 15:17:50 -04001187__clib_export clib_error_t *
Dave Barache09ae012020-08-19 06:59:53 -04001188elog_read_file_not_inline (elog_main_t * em, char *clib_file)
1189{
1190 serialize_main_t m;
1191 clib_error_t *error;
1192
1193 error = unserialize_open_clib_file (&m, clib_file);
1194 if (error)
1195 return error;
1196 error = unserialize (&m, unserialize_elog_main, em);
1197 if (!error)
1198 unserialize_close (&m);
1199 return error;
1200}
1201#endif /* CLIB_UNIX */
1202
1203
Dave Barachc3799992016-08-15 11:12:27 -04001204/*
1205 * fd.io coding-style-patch-verification: ON
1206 *
1207 * Local Variables:
1208 * eval: (c-set-style "gnu")
1209 * End:
1210 */