blob: 62bd9797acc6102890610e3cdf8c0cf144c538f8 [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. */
64void *
65elog_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
Dave Barachc3799992016-08-15 11:12:27 -0400197word
198elog_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
Dave Barachc3799992016-08-15 11:12:27 -0400295u8 *
296format_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
Florin Corasaefbede2018-12-19 13:07:49 -0800407u8 *
408format_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 Barachc3799992016-08-15 11:12:27 -0400430void
431elog_time_now (elog_time_stamp_t * et)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700432{
433 u64 cpu_time_now, os_time_now_nsec;
Dave Barach903fd512017-04-01 11:07:40 -0400434 struct timespec ts;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700435
436#ifdef CLIB_UNIX
437 {
438#include <sys/syscall.h>
Damjan Marion4dffd1c2018-09-03 12:30:36 +0200439#ifdef __APPLE__
440 clock_gettime (CLOCK_REALTIME, &ts);
441#else
Ed Warnickecb9cada2015-12-08 15:45:58 -0700442 syscall (SYS_clock_gettime, CLOCK_REALTIME, &ts);
Damjan Marion4dffd1c2018-09-03 12:30:36 +0200443#endif
Ed Warnickecb9cada2015-12-08 15:45:58 -0700444 cpu_time_now = clib_cpu_time_now ();
Dave Barach903fd512017-04-01 11:07:40 -0400445 /* Subtract 3/30/2017's worth of seconds to retain precision */
446 os_time_now_nsec = 1e9 * (ts.tv_sec - 1490885108) + ts.tv_nsec;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700447 }
448#else
449 cpu_time_now = clib_cpu_time_now ();
450 os_time_now_nsec = 0;
451#endif
452
453 et->cpu = cpu_time_now;
454 et->os_nsec = os_time_now_nsec;
455}
456
457always_inline i64
Dave Barachc3799992016-08-15 11:12:27 -0400458elog_time_stamp_diff_os_nsec (elog_time_stamp_t * t1, elog_time_stamp_t * t2)
459{
460 return (i64) t1->os_nsec - (i64) t2->os_nsec;
461}
Ed Warnickecb9cada2015-12-08 15:45:58 -0700462
463always_inline i64
Dave Barachc3799992016-08-15 11:12:27 -0400464elog_time_stamp_diff_cpu (elog_time_stamp_t * t1, elog_time_stamp_t * t2)
465{
466 return (i64) t1->cpu - (i64) t2->cpu;
467}
Ed Warnickecb9cada2015-12-08 15:45:58 -0700468
469always_inline f64
470elog_nsec_per_clock (elog_main_t * em)
471{
472 return ((f64) elog_time_stamp_diff_os_nsec (&em->serialize_time,
473 &em->init_time)
474 / (f64) elog_time_stamp_diff_cpu (&em->serialize_time,
475 &em->init_time));
476}
477
Dave Barachc3799992016-08-15 11:12:27 -0400478void
479elog_alloc (elog_main_t * em, u32 n_events)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700480{
481 if (em->event_ring)
482 vec_free (em->event_ring);
Dave Barachc3799992016-08-15 11:12:27 -0400483
Ed Warnickecb9cada2015-12-08 15:45:58 -0700484 /* Ring size must be a power of 2. */
485 em->event_ring_size = n_events = max_pow2 (n_events);
486
487 /* Leave an empty ievent at end so we can always speculatively write
488 and event there (possibly a long form event). */
489 vec_resize_aligned (em->event_ring, n_events, CLIB_CACHE_LINE_BYTES);
490}
491
Dave Barachc3799992016-08-15 11:12:27 -0400492void
493elog_init (elog_main_t * em, u32 n_events)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700494{
Dave Barachb7b92992018-10-17 10:38:51 -0400495 clib_memset (em, 0, sizeof (em[0]));
Ed Warnickecb9cada2015-12-08 15:45:58 -0700496
497 em->lock = 0;
498
499 if (n_events > 0)
500 elog_alloc (em, n_events);
501
502 clib_time_init (&em->cpu_timer);
503
504 em->n_total_events_disable_limit = ~0;
505
506 /* Make track 0. */
507 em->default_track.name = "default";
508 elog_track_register (em, &em->default_track);
509
510 elog_time_now (&em->init_time);
Dave Barach9c8ca8d2019-06-14 12:02:38 -0400511 em->string_table_hash = hash_create_string (0, sizeof (uword));
Ed Warnickecb9cada2015-12-08 15:45:58 -0700512}
513
514/* Returns number of events in ring and start index. */
Dave Barachc3799992016-08-15 11:12:27 -0400515static uword
516elog_event_range (elog_main_t * em, uword * lo)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700517{
518 uword l = em->event_ring_size;
519 u64 i = em->n_total_events;
520
521 /* Ring never wrapped? */
522 if (i <= (u64) l)
523 {
Dave Barachc3799992016-08-15 11:12:27 -0400524 if (lo)
525 *lo = 0;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700526 return i;
527 }
528 else
529 {
Dave Barachc3799992016-08-15 11:12:27 -0400530 if (lo)
531 *lo = i & (l - 1);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700532 return l;
533 }
534}
535
Dave Barachc3799992016-08-15 11:12:27 -0400536elog_event_t *
537elog_peek_events (elog_main_t * em)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700538{
Dave Barachc3799992016-08-15 11:12:27 -0400539 elog_event_t *e, *f, *es = 0;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700540 uword i, j, n;
541
542 n = elog_event_range (em, &j);
543 for (i = 0; i < n; i++)
544 {
545 vec_add2 (es, e, 1);
546 f = vec_elt_at_index (em->event_ring, j);
547 e[0] = f[0];
548
549 /* Convert absolute time from cycles to seconds from start. */
Dave Barachc3799992016-08-15 11:12:27 -0400550 e->time =
551 (e->time_cycles -
552 em->init_time.cpu) * em->cpu_timer.seconds_per_clock;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700553
554 j = (j + 1) & (em->event_ring_size - 1);
555 }
556
557 return es;
558}
559
560/* Add a formatted string to the string table. */
Dave Barachc3799992016-08-15 11:12:27 -0400561u32
562elog_string (elog_main_t * em, char *fmt, ...)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700563{
564 u32 offset;
Dave Barach9c8ca8d2019-06-14 12:02:38 -0400565 uword *p;
566 uword len;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700567 va_list va;
568
Steven Luongd31a5982019-05-31 07:34:39 -0700569 elog_lock (em);
Dave Barach9c8ca8d2019-06-14 12:02:38 -0400570 vec_reset_length (em->string_table_tmp);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700571 va_start (va, fmt);
Dave Barach9c8ca8d2019-06-14 12:02:38 -0400572 em->string_table_tmp = va_format (em->string_table_tmp, fmt, &va);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700573 va_end (va);
574
Benoît Ganneb11e4ae2019-07-17 11:45:20 +0200575 /* String table entries MUST be NULL terminated */
576 len = vec_len (em->string_table_tmp);
577 ASSERT (len > 0);
578 if (em->string_table_tmp[len - 1] != 0)
579 vec_add1 (em->string_table_tmp, 0);
580
Dave Barach9c8ca8d2019-06-14 12:02:38 -0400581 /* See if we already have this string in the string table */
582 p = hash_get_mem (em->string_table_hash, em->string_table_tmp);
583
584 /* We already have the string, so give the caller its offset */
585 if (p)
586 {
587 elog_unlock (em);
588 return (p[0]);
589 }
590
Benoît Ganneb11e4ae2019-07-17 11:45:20 +0200591 /* We don't, so add it. */
Dave Barach9c8ca8d2019-06-14 12:02:38 -0400592
593 offset = vec_len (em->string_table);
594 vec_append (em->string_table, em->string_table_tmp);
595
596 hash_set_mem (em->string_table_hash, em->string_table_tmp, offset);
597
598 /* We gave the key to the string table hash, so we can't reuse it! */
599 em->string_table_tmp = 0;
Steven Luongd31a5982019-05-31 07:34:39 -0700600 elog_unlock (em);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700601
602 return offset;
603}
604
Dave Barachc3799992016-08-15 11:12:27 -0400605elog_event_t *
606elog_get_events (elog_main_t * em)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700607{
Dave Barachc3799992016-08-15 11:12:27 -0400608 if (!em->events)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700609 em->events = elog_peek_events (em);
610 return em->events;
611}
612
Dave Barachc3799992016-08-15 11:12:27 -0400613static void
614maybe_fix_string_table_offset (elog_event_t * e,
615 elog_event_type_t * t, u32 offset)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700616{
Dave Barachc3799992016-08-15 11:12:27 -0400617 void *d = (u8 *) e->data;
618 char *a;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700619
620 if (offset == 0)
621 return;
622
623 a = t->format_args;
624
625 while (1)
626 {
627 uword n_bytes = 0, n_digits;
628
629 if (a[0] == 0)
Dave Barachc3799992016-08-15 11:12:27 -0400630 break;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700631
632 /* Don't go past end of event data. */
633 ASSERT (d < (void *) (e->data + sizeof (e->data)));
634
635 n_digits = parse_2digit_decimal (a + 1, &n_bytes);
636 switch (a[0])
637 {
638 case 'T':
Dave Barachc3799992016-08-15 11:12:27 -0400639 ASSERT (n_bytes == 4);
640 clib_mem_unaligned (d, u32) += offset;
641 break;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700642
643 case 'i':
644 case 't':
645 case 'f':
646 case 's':
647 break;
648
649 default:
650 ASSERT (0);
651 break;
652 }
653
654 ASSERT (n_digits > 0 && n_digits <= 2);
655 a += 1 + n_digits;
656 d += n_bytes;
657 }
658}
659
Dave Barachc3799992016-08-15 11:12:27 -0400660static int
661elog_cmp (void *a1, void *a2)
Matus Fabiand2dc3df2015-12-14 10:31:33 -0500662{
Dave Barachc3799992016-08-15 11:12:27 -0400663 elog_event_t *e1 = a1;
664 elog_event_t *e2 = a2;
Matus Fabiand2dc3df2015-12-14 10:31:33 -0500665
Dave Barach903fd512017-04-01 11:07:40 -0400666 if (e1->time < e2->time)
667 return -1;
668
669 if (e1->time > e2->time)
670 return 1;
671
672 return 0;
Matus Fabiand2dc3df2015-12-14 10:31:33 -0500673}
674
Dave Barach903fd512017-04-01 11:07:40 -0400675/*
676 * merge two event logs. Complicated and cranky.
677 */
Dave Barachc3799992016-08-15 11:12:27 -0400678void
Dave Barach903fd512017-04-01 11:07:40 -0400679elog_merge (elog_main_t * dst, u8 * dst_tag, elog_main_t * src, u8 * src_tag,
680 f64 align_tweak)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700681{
Dave Barachc3799992016-08-15 11:12:27 -0400682 elog_event_t *e;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700683 uword l;
684 u32 string_table_offset_for_src_events;
685 u32 track_offset_for_src_tracks;
686 elog_track_t newt;
687 int i;
688
Dave Barachb7b92992018-10-17 10:38:51 -0400689 clib_memset (&newt, 0, sizeof (newt));
Dave Barachf9c231e2016-08-05 10:10:18 -0400690
Dave Barach903fd512017-04-01 11:07:40 -0400691 /* Acquire src and dst events */
Ed Warnickecb9cada2015-12-08 15:45:58 -0700692 elog_get_events (src);
693 elog_get_events (dst);
694
695 string_table_offset_for_src_events = vec_len (dst->string_table);
696 vec_append (dst->string_table, src->string_table);
697
698 l = vec_len (dst->events);
Dave Barach903fd512017-04-01 11:07:40 -0400699 vec_append (dst->events, src->events);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700700
701 /* Prepend the supplied tag (if any) to all dst track names */
702 if (dst_tag)
703 {
Dave Barachc3799992016-08-15 11:12:27 -0400704 for (i = 0; i < vec_len (dst->tracks); i++)
705 {
706 elog_track_t *t = vec_elt_at_index (dst->tracks, i);
707 char *new_name;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700708
Dave Barachc3799992016-08-15 11:12:27 -0400709 new_name = (char *) format (0, "%s:%s%c", dst_tag, t->name, 0);
710 vec_free (t->name);
711 t->name = new_name;
712 }
Ed Warnickecb9cada2015-12-08 15:45:58 -0700713 }
Dave Barachc3799992016-08-15 11:12:27 -0400714
Dave Barach903fd512017-04-01 11:07:40 -0400715 /*
716 * Remember where we started allocating new tracks while merging
717 */
Ed Warnickecb9cada2015-12-08 15:45:58 -0700718 track_offset_for_src_tracks = vec_len (dst->tracks);
Dave Barachc3799992016-08-15 11:12:27 -0400719
Ed Warnickecb9cada2015-12-08 15:45:58 -0700720 /* Copy / tag source tracks */
721 for (i = 0; i < vec_len (src->tracks); i++)
722 {
Dave Barachc3799992016-08-15 11:12:27 -0400723 elog_track_t *t = vec_elt_at_index (src->tracks, i);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700724 if (src_tag)
Dave Barachc3799992016-08-15 11:12:27 -0400725 newt.name = (char *) format (0, "%s:%s%c", src_tag, t->name, 0);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700726 else
Dave Barachc3799992016-08-15 11:12:27 -0400727 newt.name = (char *) format (0, "%s%c", t->name, 0);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700728 (void) elog_track_register (dst, &newt);
729 vec_free (newt.name);
730 }
Dave Barachc3799992016-08-15 11:12:27 -0400731
Ed Warnickecb9cada2015-12-08 15:45:58 -0700732 /* Across all (copied) src events... */
733 for (e = dst->events + l; e < vec_end (dst->events); e++)
734 {
Dave Barache09ae012020-08-19 06:59:53 -0400735 elog_event_type_t *t =
736 vec_elt_at_index (src->event_types, e->event_type);
Dave Barachc3799992016-08-15 11:12:27 -0400737
Ed Warnickecb9cada2015-12-08 15:45:58 -0700738 /* Remap type from src -> dst. */
Dave Barache09ae012020-08-19 06:59:53 -0400739 e->event_type = find_or_create_type (dst, t);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700740
741 /* Remap string table offsets for 'T' format args */
Dave Barachc3799992016-08-15 11:12:27 -0400742 maybe_fix_string_table_offset (e, t,
743 string_table_offset_for_src_events);
744
Ed Warnickecb9cada2015-12-08 15:45:58 -0700745 /* Remap track */
746 e->track += track_offset_for_src_tracks;
747 }
748
749 /* Adjust event times for relative starting times of event streams. */
750 {
751 f64 dt_event, dt_os_nsec, dt_clock_nsec;
752
753 /* Set clock parameters if dst was not generated by unserialize. */
754 if (dst->serialize_time.cpu == 0)
755 {
756 dst->init_time = src->init_time;
757 dst->serialize_time = src->serialize_time;
758 dst->nsec_per_cpu_clock = src->nsec_per_cpu_clock;
759 }
760
Dave Barachc3799992016-08-15 11:12:27 -0400761 dt_os_nsec =
762 elog_time_stamp_diff_os_nsec (&src->init_time, &dst->init_time);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700763
764 dt_event = dt_os_nsec;
Dave Barachc3799992016-08-15 11:12:27 -0400765 dt_clock_nsec =
766 (elog_time_stamp_diff_cpu (&src->init_time, &dst->init_time) * .5 *
767 (dst->nsec_per_cpu_clock + src->nsec_per_cpu_clock));
Ed Warnickecb9cada2015-12-08 15:45:58 -0700768
Dave Barach903fd512017-04-01 11:07:40 -0400769 /*
770 * Heuristic to see if src/dst came from same time source.
771 * If frequencies are "the same" and os clock and cpu clock agree
772 * to within 100e-9 secs about time difference between src/dst
773 * init_time, then we use cpu clock. Otherwise we use OS clock.
774 *
775 * When merging event logs from different systems, time paradoxes
776 * at the O(1ms) level are to be expected. Hence, the "align_tweak"
777 * parameter. If two events logged on different processors are known
778 * to occur in a specific order - and with a reasonably-estimated
779 * interval - supply a non-zero "align_tweak" parameter
780 */
Ed Warnickecb9cada2015-12-08 15:45:58 -0700781 if (fabs (src->nsec_per_cpu_clock - dst->nsec_per_cpu_clock) < 1e-2
782 && fabs (dt_os_nsec - dt_clock_nsec) < 100)
783 dt_event = dt_clock_nsec;
784
785 /* Convert to seconds. */
786 dt_event *= 1e-9;
787
Dave Barach903fd512017-04-01 11:07:40 -0400788 /*
789 * Move the earlier set of events later, to avoid creating
Paul Vinciguerraec11b132018-09-24 05:25:00 -0700790 * events which precede the Big Bang (aka have negative timestamps).
Dave Barach903fd512017-04-01 11:07:40 -0400791 *
792 * Not to any scale, we have something like the following picture:
793 *
794 * DST capture start point
795 * ^
796 * +--- dt_event --+
797 * v
798 * SRC capture start point
799 *
800 * In this case dt_event is positive, src started after dst,
801 * to put src events onto a common timebase we have to move them
802 * forward in time. Naturally, the opposite case is
803 * possible, too: dt_event will be negative, and so we have to
804 * move dst events forward in time by the |dt_event|.
805 * In both cases, we add align_tweak.
806 */
Ed Warnickecb9cada2015-12-08 15:45:58 -0700807 if (dt_event > 0)
808 {
809 /* Src started after dst. */
810 for (e = dst->events + l; e < vec_end (dst->events); e++)
Dave Barach903fd512017-04-01 11:07:40 -0400811 e->time += dt_event + align_tweak;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700812 }
813 else
814 {
815 /* Dst started after src. */
Dave Barach903fd512017-04-01 11:07:40 -0400816 dt_event = -dt_event;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700817 for (e = dst->events + 0; e < dst->events + l; e++)
Dave Barach903fd512017-04-01 11:07:40 -0400818 e->time += dt_event + align_tweak;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700819 }
820 }
821
822 /* Sort events by increasing time. */
Matus Fabiand2dc3df2015-12-14 10:31:33 -0500823 vec_sort_with_function (dst->events, elog_cmp);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700824
Dave Barach903fd512017-04-01 11:07:40 -0400825 dst->n_total_events = vec_len (dst->events);
826
Ed Warnickecb9cada2015-12-08 15:45:58 -0700827 /* Recreate the event ring or the results won't serialize */
828 {
829 int i;
830
831 ASSERT (dst->cpu_timer.seconds_per_clock);
832
833 elog_alloc (dst, vec_len (dst->events));
Dave Barachc3799992016-08-15 11:12:27 -0400834 for (i = 0; i < vec_len (dst->events); i++)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700835 {
Dave Barachc3799992016-08-15 11:12:27 -0400836 elog_event_t *es, *ed;
837
838 es = dst->events + i;
839 ed = dst->event_ring + i;
840
841 ed[0] = es[0];
Ed Warnickecb9cada2015-12-08 15:45:58 -0700842 }
Ed Warnickecb9cada2015-12-08 15:45:58 -0700843 }
844}
845
846static void
847serialize_elog_event (serialize_main_t * m, va_list * va)
848{
Dave Barachc3799992016-08-15 11:12:27 -0400849 elog_main_t *em = va_arg (*va, elog_main_t *);
850 elog_event_t *e = va_arg (*va, elog_event_t *);
Dave Barache09ae012020-08-19 06:59:53 -0400851 elog_event_type_t *t = vec_elt_at_index (em->event_types, e->event_type);
Dave Barachc3799992016-08-15 11:12:27 -0400852 u8 *d = e->data;
853 u8 *p = (u8 *) t->format_args;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700854
Dave Barache09ae012020-08-19 06:59:53 -0400855 serialize_integer (m, e->event_type, sizeof (e->event_type));
Ed Warnickecb9cada2015-12-08 15:45:58 -0700856 serialize_integer (m, e->track, sizeof (e->track));
857 serialize (m, serialize_f64, e->time);
858
859 while (*p)
860 {
861 uword n_digits, n_bytes = 0;
862
863 n_digits = parse_2digit_decimal ((char *) p + 1, &n_bytes);
864
865 switch (p[0])
866 {
867 case 'i':
868 case 't':
869 case 'T':
870 if (n_bytes == 1)
871 serialize_integer (m, d[0], sizeof (u8));
872 else if (n_bytes == 2)
873 serialize_integer (m, clib_mem_unaligned (d, u16), sizeof (u16));
874 else if (n_bytes == 4)
875 serialize_integer (m, clib_mem_unaligned (d, u32), sizeof (u32));
876 else if (n_bytes == 8)
877 serialize (m, serialize_64, clib_mem_unaligned (d, u64));
878 else
879 ASSERT (0);
880 break;
881
882 case 's':
883 serialize_cstring (m, (char *) d);
884 if (n_bytes == 0)
885 n_bytes = strlen ((char *) d) + 1;
886 break;
887
888 case 'f':
889 if (n_bytes == 4)
890 serialize (m, serialize_f32, clib_mem_unaligned (d, f32));
891 else if (n_bytes == 8)
892 serialize (m, serialize_f64, clib_mem_unaligned (d, f64));
893 else
894 ASSERT (0);
895 break;
896
897 default:
898 ASSERT (0);
899 break;
900 }
901
902 p += 1 + n_digits;
903 d += n_bytes;
904 }
905}
906
907static void
908unserialize_elog_event (serialize_main_t * m, va_list * va)
909{
Dave Barachc3799992016-08-15 11:12:27 -0400910 elog_main_t *em = va_arg (*va, elog_main_t *);
911 elog_event_t *e = va_arg (*va, elog_event_t *);
912 elog_event_type_t *t;
913 u8 *p, *d;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700914
915 {
916 u16 tmp[2];
917
Dave Barache09ae012020-08-19 06:59:53 -0400918 unserialize_integer (m, &tmp[0], sizeof (e->event_type));
Ed Warnickecb9cada2015-12-08 15:45:58 -0700919 unserialize_integer (m, &tmp[1], sizeof (e->track));
920
Dave Barache09ae012020-08-19 06:59:53 -0400921 e->event_type = tmp[0];
Ed Warnickecb9cada2015-12-08 15:45:58 -0700922 e->track = tmp[1];
923
924 /* Make sure it fits. */
Dave Barache09ae012020-08-19 06:59:53 -0400925 ASSERT (e->event_type == tmp[0]);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700926 ASSERT (e->track == tmp[1]);
927 }
928
Dave Barache09ae012020-08-19 06:59:53 -0400929 t = vec_elt_at_index (em->event_types, e->event_type);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700930
931 unserialize (m, unserialize_f64, &e->time);
932
933 d = e->data;
934 p = (u8 *) t->format_args;
935
936 while (p && *p)
937 {
938 uword n_digits, n_bytes = 0;
939 u32 tmp;
940
941 n_digits = parse_2digit_decimal ((char *) p + 1, &n_bytes);
942
943 switch (p[0])
944 {
945 case 'i':
946 case 't':
947 case 'T':
948 if (n_bytes == 1)
949 {
950 unserialize_integer (m, &tmp, sizeof (u8));
951 d[0] = tmp;
952 }
953 else if (n_bytes == 2)
954 {
955 unserialize_integer (m, &tmp, sizeof (u16));
956 clib_mem_unaligned (d, u16) = tmp;
957 }
958 else if (n_bytes == 4)
959 {
960 unserialize_integer (m, &tmp, sizeof (u32));
961 clib_mem_unaligned (d, u32) = tmp;
962 }
963 else if (n_bytes == 8)
964 {
965 u64 x;
966 unserialize (m, unserialize_64, &x);
967 clib_mem_unaligned (d, u64) = x;
968 }
969 else
970 ASSERT (0);
971 break;
972
Dave Barachc3799992016-08-15 11:12:27 -0400973 case 's':
974 {
975 char *t;
976 unserialize_cstring (m, &t);
977 if (n_bytes == 0)
978 n_bytes = strlen (t) + 1;
979 clib_memcpy (d, t, clib_min (n_bytes, vec_len (t)));
980 vec_free (t);
981 break;
982 }
Ed Warnickecb9cada2015-12-08 15:45:58 -0700983
984 case 'f':
985 if (n_bytes == 4)
986 {
987 f32 x;
988 unserialize (m, unserialize_f32, &x);
989 clib_mem_unaligned (d, f32) = x;
990 }
991 else if (n_bytes == 8)
992 {
993 f64 x;
994 unserialize (m, unserialize_f64, &x);
995 clib_mem_unaligned (d, f64) = x;
996 }
997 else
998 ASSERT (0);
999 break;
1000
1001 default:
1002 ASSERT (0);
1003 break;
1004 }
1005
1006 p += 1 + n_digits;
1007 d += n_bytes;
1008 }
1009}
1010
1011static void
1012serialize_elog_event_type (serialize_main_t * m, va_list * va)
1013{
Dave Barachc3799992016-08-15 11:12:27 -04001014 elog_event_type_t *t = va_arg (*va, elog_event_type_t *);
Ed Warnickecb9cada2015-12-08 15:45:58 -07001015 int n = va_arg (*va, int);
1016 int i, j;
1017 for (i = 0; i < n; i++)
1018 {
1019 serialize_cstring (m, t[i].format);
1020 serialize_cstring (m, t[i].format_args);
Dave Barachc3799992016-08-15 11:12:27 -04001021 serialize_integer (m, t[i].type_index_plus_one,
1022 sizeof (t->type_index_plus_one));
1023 serialize_integer (m, t[i].n_enum_strings,
1024 sizeof (t[i].n_enum_strings));
Ed Warnickecb9cada2015-12-08 15:45:58 -07001025 for (j = 0; j < t[i].n_enum_strings; j++)
1026 serialize_cstring (m, t[i].enum_strings_vector[j]);
1027 }
1028}
1029
1030static void
1031unserialize_elog_event_type (serialize_main_t * m, va_list * va)
1032{
Dave Barachc3799992016-08-15 11:12:27 -04001033 elog_event_type_t *t = va_arg (*va, elog_event_type_t *);
Ed Warnickecb9cada2015-12-08 15:45:58 -07001034 int n = va_arg (*va, int);
1035 int i, j;
1036 for (i = 0; i < n; i++)
1037 {
1038 unserialize_cstring (m, &t[i].format);
1039 unserialize_cstring (m, &t[i].format_args);
Dave Barachc3799992016-08-15 11:12:27 -04001040 unserialize_integer (m, &t[i].type_index_plus_one,
1041 sizeof (t->type_index_plus_one));
1042 unserialize_integer (m, &t[i].n_enum_strings,
1043 sizeof (t[i].n_enum_strings));
Ed Warnickecb9cada2015-12-08 15:45:58 -07001044 vec_resize (t[i].enum_strings_vector, t[i].n_enum_strings);
1045 for (j = 0; j < t[i].n_enum_strings; j++)
1046 unserialize_cstring (m, &t[i].enum_strings_vector[j]);
1047 }
1048}
1049
1050static void
1051serialize_elog_track (serialize_main_t * m, va_list * va)
1052{
Dave Barachc3799992016-08-15 11:12:27 -04001053 elog_track_t *t = va_arg (*va, elog_track_t *);
Ed Warnickecb9cada2015-12-08 15:45:58 -07001054 int n = va_arg (*va, int);
1055 int i;
1056 for (i = 0; i < n; i++)
1057 {
1058 serialize_cstring (m, t[i].name);
1059 }
1060}
1061
1062static void
1063unserialize_elog_track (serialize_main_t * m, va_list * va)
1064{
Dave Barachc3799992016-08-15 11:12:27 -04001065 elog_track_t *t = va_arg (*va, elog_track_t *);
Ed Warnickecb9cada2015-12-08 15:45:58 -07001066 int n = va_arg (*va, int);
1067 int i;
1068 for (i = 0; i < n; i++)
1069 {
1070 unserialize_cstring (m, &t[i].name);
1071 }
1072}
1073
1074static void
1075serialize_elog_time_stamp (serialize_main_t * m, va_list * va)
1076{
Dave Barachc3799992016-08-15 11:12:27 -04001077 elog_time_stamp_t *st = va_arg (*va, elog_time_stamp_t *);
Ed Warnickecb9cada2015-12-08 15:45:58 -07001078 serialize (m, serialize_64, st->os_nsec);
1079 serialize (m, serialize_64, st->cpu);
1080}
1081
1082static void
1083unserialize_elog_time_stamp (serialize_main_t * m, va_list * va)
1084{
Dave Barachc3799992016-08-15 11:12:27 -04001085 elog_time_stamp_t *st = va_arg (*va, elog_time_stamp_t *);
Ed Warnickecb9cada2015-12-08 15:45:58 -07001086 unserialize (m, unserialize_64, &st->os_nsec);
1087 unserialize (m, unserialize_64, &st->cpu);
1088}
1089
Dave Barachc3799992016-08-15 11:12:27 -04001090static char *elog_serialize_magic = "elog v0";
Ed Warnickecb9cada2015-12-08 15:45:58 -07001091
1092void
1093serialize_elog_main (serialize_main_t * m, va_list * va)
1094{
Dave Barachc3799992016-08-15 11:12:27 -04001095 elog_main_t *em = va_arg (*va, elog_main_t *);
Dave Barach903fd512017-04-01 11:07:40 -04001096 int flush_ring = va_arg (*va, int);
Dave Barachc3799992016-08-15 11:12:27 -04001097 elog_event_t *e;
Ed Warnickecb9cada2015-12-08 15:45:58 -07001098
1099 serialize_magic (m, elog_serialize_magic, strlen (elog_serialize_magic));
1100
1101 serialize_integer (m, em->event_ring_size, sizeof (u32));
1102
1103 elog_time_now (&em->serialize_time);
1104 serialize (m, serialize_elog_time_stamp, &em->serialize_time);
1105 serialize (m, serialize_elog_time_stamp, &em->init_time);
1106
1107 vec_serialize (m, em->event_types, serialize_elog_event_type);
1108 vec_serialize (m, em->tracks, serialize_elog_track);
1109 vec_serialize (m, em->string_table, serialize_vec_8);
1110
1111 /* Free old events (cached) in case they have changed. */
Dave Barach903fd512017-04-01 11:07:40 -04001112 if (flush_ring)
1113 {
1114 vec_free (em->events);
1115 elog_get_events (em);
1116 }
Ed Warnickecb9cada2015-12-08 15:45:58 -07001117
1118 serialize_integer (m, vec_len (em->events), sizeof (u32));
1119
1120 /* SMP logs can easily have local time paradoxes... */
Matus Fabiand2dc3df2015-12-14 10:31:33 -05001121 vec_sort_with_function (em->events, elog_cmp);
Ed Warnickecb9cada2015-12-08 15:45:58 -07001122
Dave Barachc3799992016-08-15 11:12:27 -04001123 vec_foreach (e, em->events) serialize (m, serialize_elog_event, em, e);
Ed Warnickecb9cada2015-12-08 15:45:58 -07001124}
1125
1126void
1127unserialize_elog_main (serialize_main_t * m, va_list * va)
1128{
Dave Barachc3799992016-08-15 11:12:27 -04001129 elog_main_t *em = va_arg (*va, elog_main_t *);
Ed Warnickecb9cada2015-12-08 15:45:58 -07001130 uword i;
1131 u32 rs;
1132
1133 unserialize_check_magic (m, elog_serialize_magic,
1134 strlen (elog_serialize_magic));
1135
1136 unserialize_integer (m, &rs, sizeof (u32));
1137 em->event_ring_size = rs;
1138 elog_init (em, em->event_ring_size);
1139
1140 unserialize (m, unserialize_elog_time_stamp, &em->serialize_time);
1141 unserialize (m, unserialize_elog_time_stamp, &em->init_time);
1142 em->nsec_per_cpu_clock = elog_nsec_per_clock (em);
1143
1144 vec_unserialize (m, &em->event_types, unserialize_elog_event_type);
1145 for (i = 0; i < vec_len (em->event_types); i++)
1146 new_event_type (em, i);
1147
1148 vec_unserialize (m, &em->tracks, unserialize_elog_track);
1149 vec_unserialize (m, &em->string_table, unserialize_vec_8);
1150
1151 {
1152 u32 ne;
Dave Barachc3799992016-08-15 11:12:27 -04001153 elog_event_t *e;
Ed Warnickecb9cada2015-12-08 15:45:58 -07001154
1155 unserialize_integer (m, &ne, sizeof (u32));
1156 vec_resize (em->events, ne);
1157 vec_foreach (e, em->events)
1158 unserialize (m, unserialize_elog_event, em, e);
1159 }
1160}
Dave Barachc3799992016-08-15 11:12:27 -04001161
Dave Barache09ae012020-08-19 06:59:53 -04001162#ifdef CLIB_UNIX
1163clib_error_t *
1164elog_write_file_not_inline (elog_main_t * em, char *clib_file, int flush_ring)
1165{
1166 serialize_main_t m;
1167 clib_error_t *error;
1168
1169 error = serialize_open_clib_file (&m, clib_file);
1170 if (error)
1171 return error;
1172 error = serialize (&m, serialize_elog_main, em, flush_ring);
1173 if (!error)
1174 serialize_close (&m);
1175 return error;
1176}
1177
1178clib_error_t *
1179elog_read_file_not_inline (elog_main_t * em, char *clib_file)
1180{
1181 serialize_main_t m;
1182 clib_error_t *error;
1183
1184 error = unserialize_open_clib_file (&m, clib_file);
1185 if (error)
1186 return error;
1187 error = unserialize (&m, unserialize_elog_main, em);
1188 if (!error)
1189 unserialize_close (&m);
1190 return error;
1191}
1192#endif /* CLIB_UNIX */
1193
1194
Dave Barachc3799992016-08-15 11:12:27 -04001195/*
1196 * fd.io coding-style-patch-verification: ON
1197 *
1198 * Local Variables:
1199 * eval: (c-set-style "gnu")
1200 * End:
1201 */