Line data Source code
1 : /*
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 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 : /* Turn data structures into byte streams for saving or transport. */
39 :
40 : #include <vppinfra/heap.h>
41 : #include <vppinfra/pool.h>
42 : #include <vppinfra/serialize.h>
43 :
44 : void
45 0 : serialize_64 (serialize_main_t * m, va_list * va)
46 : {
47 0 : u64 x = va_arg (*va, u64);
48 : u32 lo, hi;
49 0 : lo = x;
50 0 : hi = x >> 32;
51 0 : serialize_integer (m, lo, sizeof (lo));
52 0 : serialize_integer (m, hi, sizeof (hi));
53 0 : }
54 :
55 : void
56 0 : serialize_32 (serialize_main_t * m, va_list * va)
57 : {
58 0 : u32 x = va_arg (*va, u32);
59 0 : serialize_integer (m, x, sizeof (x));
60 0 : }
61 :
62 : void
63 0 : serialize_16 (serialize_main_t * m, va_list * va)
64 : {
65 0 : u32 x = va_arg (*va, u32);
66 0 : serialize_integer (m, x, sizeof (u16));
67 0 : }
68 :
69 : void
70 0 : serialize_8 (serialize_main_t * m, va_list * va)
71 : {
72 0 : u32 x = va_arg (*va, u32);
73 0 : serialize_integer (m, x, sizeof (u8));
74 0 : }
75 :
76 : void
77 0 : unserialize_64 (serialize_main_t * m, va_list * va)
78 : {
79 0 : u64 *x = va_arg (*va, u64 *);
80 : u32 lo, hi;
81 0 : unserialize_integer (m, &lo, sizeof (lo));
82 0 : unserialize_integer (m, &hi, sizeof (hi));
83 0 : *x = ((u64) hi << 32) | (u64) lo;
84 0 : }
85 :
86 : void
87 0 : unserialize_32 (serialize_main_t * m, va_list * va)
88 : {
89 0 : u32 *x = va_arg (*va, u32 *);
90 0 : unserialize_integer (m, x, sizeof (x[0]));
91 0 : }
92 :
93 : void
94 0 : unserialize_16 (serialize_main_t * m, va_list * va)
95 : {
96 0 : u16 *x = va_arg (*va, u16 *);
97 : u32 t;
98 0 : unserialize_integer (m, &t, sizeof (x[0]));
99 0 : x[0] = t;
100 0 : }
101 :
102 : void
103 0 : unserialize_8 (serialize_main_t * m, va_list * va)
104 : {
105 0 : u8 *x = va_arg (*va, u8 *);
106 : u32 t;
107 0 : unserialize_integer (m, &t, sizeof (x[0]));
108 0 : x[0] = t;
109 0 : }
110 :
111 : void
112 0 : serialize_f64 (serialize_main_t * m, va_list * va)
113 : {
114 0 : f64 x = va_arg (*va, f64);
115 : union
116 : {
117 : f64 f;
118 : u64 i;
119 : } y;
120 0 : y.f = x;
121 0 : serialize (m, serialize_64, y.i);
122 0 : }
123 :
124 : void
125 0 : serialize_f32 (serialize_main_t * m, va_list * va)
126 : {
127 0 : f32 x = va_arg (*va, f64);
128 : union
129 : {
130 : f32 f;
131 : u32 i;
132 : } y;
133 0 : y.f = x;
134 0 : serialize_integer (m, y.i, sizeof (y.i));
135 0 : }
136 :
137 : void
138 0 : unserialize_f64 (serialize_main_t * m, va_list * va)
139 : {
140 0 : f64 *x = va_arg (*va, f64 *);
141 : union
142 : {
143 : f64 f;
144 : u64 i;
145 : } y;
146 0 : unserialize (m, unserialize_64, &y.i);
147 0 : *x = y.f;
148 0 : }
149 :
150 : void
151 0 : unserialize_f32 (serialize_main_t * m, va_list * va)
152 : {
153 0 : f32 *x = va_arg (*va, f32 *);
154 : union
155 : {
156 : f32 f;
157 : u32 i;
158 : } y;
159 0 : unserialize_integer (m, &y.i, sizeof (y.i));
160 0 : *x = y.f;
161 0 : }
162 :
163 : __clib_export void
164 2839620 : serialize_cstring (serialize_main_t * m, char *s)
165 : {
166 2839620 : u32 len = s ? strlen (s) : 0;
167 : void *p;
168 :
169 2839620 : serialize_likely_small_unsigned_integer (m, len);
170 2839620 : if (len > 0)
171 : {
172 2839620 : p = serialize_get (m, len);
173 2839620 : clib_memcpy_fast (p, s, len);
174 : }
175 2839620 : }
176 :
177 : __clib_export void
178 81827 : unserialize_cstring (serialize_main_t * m, char **s)
179 : {
180 81827 : char *p, *r = 0;
181 : u32 len;
182 :
183 81827 : len = unserialize_likely_small_unsigned_integer (m);
184 :
185 : /*
186 : * Given broken enough data, we could get len = 0xFFFFFFFF.
187 : * Add one, it overflows, we call vec_new (char, 0), then
188 : * memcpy until we bus error.
189 : */
190 81827 : if (len > 0 && len != 0xFFFFFFFF)
191 : {
192 81827 : r = vec_new (char, len + 1);
193 81827 : p = unserialize_get (m, len);
194 81827 : clib_memcpy_fast (r, p, len);
195 :
196 : /* Null terminate. */
197 81827 : r[len] = 0;
198 : }
199 81827 : *s = r;
200 81827 : }
201 :
202 : /* vec_serialize/vec_unserialize helper functions for basic vector types. */
203 : void
204 0 : serialize_vec_8 (serialize_main_t * m, va_list * va)
205 : {
206 0 : u8 *s = va_arg (*va, u8 *);
207 0 : u32 n = va_arg (*va, u32);
208 0 : u8 *p = serialize_get (m, n * sizeof (u8));
209 0 : clib_memcpy_fast (p, s, n * sizeof (u8));
210 0 : }
211 :
212 : void
213 0 : unserialize_vec_8 (serialize_main_t * m, va_list * va)
214 : {
215 0 : u8 *s = va_arg (*va, u8 *);
216 0 : u32 n = va_arg (*va, u32);
217 0 : u8 *p = unserialize_get (m, n);
218 0 : clib_memcpy_fast (s, p, n);
219 0 : }
220 :
221 : #define _(n_bits) \
222 : void serialize_vec_##n_bits (serialize_main_t * m, va_list * va) \
223 : { \
224 : u##n_bits * s = va_arg (*va, u##n_bits *); \
225 : u32 n = va_arg (*va, u32); \
226 : u##n_bits * p = serialize_get (m, n * sizeof (s[0])); \
227 : \
228 : while (n >= 4) \
229 : { \
230 : p[0] = clib_host_to_net_u##n_bits (s[0]); \
231 : p[1] = clib_host_to_net_u##n_bits (s[1]); \
232 : p[2] = clib_host_to_net_u##n_bits (s[2]); \
233 : p[3] = clib_host_to_net_u##n_bits (s[3]); \
234 : s += 4; \
235 : p += 4; \
236 : n -= 4; \
237 : } \
238 : \
239 : while (n >= 1) \
240 : { \
241 : p[0] = clib_host_to_net_u##n_bits (s[0]); \
242 : s += 1; \
243 : p += 1; \
244 : n -= 1; \
245 : } \
246 : } \
247 : \
248 : void unserialize_vec_##n_bits (serialize_main_t * m, va_list * va) \
249 : { \
250 : u##n_bits * s = va_arg (*va, u##n_bits *); \
251 : u32 n = va_arg (*va, u32); \
252 : u##n_bits * p = unserialize_get (m, n * sizeof (s[0])); \
253 : \
254 : while (n >= 4) \
255 : { \
256 : s[0] = clib_net_to_host_mem_u##n_bits (&p[0]); \
257 : s[1] = clib_net_to_host_mem_u##n_bits (&p[1]); \
258 : s[2] = clib_net_to_host_mem_u##n_bits (&p[2]); \
259 : s[3] = clib_net_to_host_mem_u##n_bits (&p[3]); \
260 : s += 4; \
261 : p += 4; \
262 : n -= 4; \
263 : } \
264 : \
265 : while (n >= 1) \
266 : { \
267 : s[0] = clib_net_to_host_mem_u##n_bits (&p[0]); \
268 : s += 1; \
269 : p += 1; \
270 : n -= 1; \
271 : } \
272 : }
273 :
274 0 : _(16);
275 0 : _(32);
276 0 : _(64);
277 :
278 : #undef _
279 :
280 : #define SERIALIZE_VECTOR_CHUNK_SIZE 64
281 :
282 : __clib_export void
283 0 : serialize_vector (serialize_main_t * m, va_list * va)
284 : {
285 0 : void *vec = va_arg (*va, void *);
286 0 : u32 elt_bytes = va_arg (*va, u32);
287 0 : serialize_function_t *f = va_arg (*va, serialize_function_t *);
288 0 : u32 l = vec_len (vec);
289 0 : void *p = vec;
290 :
291 0 : serialize_integer (m, l, sizeof (l));
292 :
293 : /* Serialize vector in chunks for cache locality. */
294 0 : while (l != 0)
295 : {
296 0 : u32 n = clib_min (SERIALIZE_VECTOR_CHUNK_SIZE, l);
297 0 : serialize (m, f, p, n);
298 0 : l -= n;
299 0 : p += SERIALIZE_VECTOR_CHUNK_SIZE * elt_bytes;
300 : }
301 0 : }
302 :
303 : void *
304 0 : unserialize_vector_ha (serialize_main_t * m,
305 : u32 elt_bytes,
306 : u32 header_bytes,
307 : u32 align, u32 max_length, serialize_function_t * f)
308 : {
309 : void *v, *p;
310 : u32 l;
311 0 : vec_attr_t va = { .align = align,
312 : .elt_sz = elt_bytes,
313 : .hdr_sz = header_bytes };
314 :
315 0 : unserialize_integer (m, &l, sizeof (l));
316 0 : if (l > max_length)
317 0 : serialize_error (&m->header,
318 : clib_error_create ("bad vector length %d", l));
319 :
320 0 : p = v = _vec_alloc_internal (l, &va);
321 :
322 0 : while (l != 0)
323 : {
324 0 : u32 n = clib_min (SERIALIZE_VECTOR_CHUNK_SIZE, l);
325 0 : unserialize (m, f, p, n);
326 0 : l -= n;
327 0 : p += SERIALIZE_VECTOR_CHUNK_SIZE * elt_bytes;
328 : }
329 0 : return v;
330 : }
331 :
332 : void
333 0 : unserialize_aligned_vector (serialize_main_t * m, va_list * va)
334 : {
335 0 : void **vec = va_arg (*va, void **);
336 0 : u32 elt_bytes = va_arg (*va, u32);
337 0 : serialize_function_t *f = va_arg (*va, serialize_function_t *);
338 0 : u32 align = va_arg (*va, u32);
339 :
340 0 : *vec = unserialize_vector_ha (m, elt_bytes,
341 : /* header_bytes */ 0,
342 : /* align */ align,
343 : /* max_length */ ~0,
344 : f);
345 0 : }
346 :
347 : __clib_export void
348 0 : unserialize_vector (serialize_main_t * m, va_list * va)
349 : {
350 0 : void **vec = va_arg (*va, void **);
351 0 : u32 elt_bytes = va_arg (*va, u32);
352 0 : serialize_function_t *f = va_arg (*va, serialize_function_t *);
353 :
354 0 : *vec = unserialize_vector_ha (m, elt_bytes,
355 : /* header_bytes */ 0,
356 : /* align */ 0,
357 : /* max_length */ ~0,
358 : f);
359 0 : }
360 :
361 : void
362 0 : serialize_bitmap (serialize_main_t * m, uword * b)
363 : {
364 : u32 l, i, n_u32s;
365 :
366 0 : l = vec_len (b);
367 0 : n_u32s = l * sizeof (b[0]) / sizeof (u32);
368 0 : serialize_integer (m, n_u32s, sizeof (n_u32s));
369 :
370 : /* Send 32 bit words, low-order word first on 64 bit. */
371 0 : for (i = 0; i < l; i++)
372 : {
373 0 : serialize_integer (m, b[i], sizeof (u32));
374 : if (BITS (uword) == 64)
375 0 : serialize_integer (m, (u64) b[i] >> (u64) 32, sizeof (u32));
376 : }
377 0 : }
378 :
379 : uword *
380 0 : unserialize_bitmap (serialize_main_t * m)
381 : {
382 0 : uword *b = 0;
383 : u32 i, n_u32s;
384 :
385 0 : unserialize_integer (m, &n_u32s, sizeof (n_u32s));
386 0 : if (n_u32s == 0)
387 0 : return b;
388 :
389 0 : i = (n_u32s * sizeof (u32) + sizeof (b[0]) - 1) / sizeof (b[0]);
390 0 : vec_resize (b, i);
391 0 : for (i = 0; i < n_u32s; i++)
392 : {
393 : u32 data;
394 0 : unserialize_integer (m, &data, sizeof (u32));
395 :
396 : /* Low-word is first on 64 bit. */
397 : if (BITS (uword) == 64)
398 : {
399 0 : if ((i % 2) == 0)
400 0 : b[i / 2] |= (u64) data << (u64) 0;
401 : else
402 0 : b[i / 2] |= (u64) data << (u64) 32;
403 : }
404 : else
405 : {
406 : b[i] = data;
407 : }
408 : }
409 :
410 0 : return b;
411 : }
412 :
413 : void
414 0 : serialize_pool (serialize_main_t * m, va_list * va)
415 : {
416 0 : void *pool = va_arg (*va, void *);
417 0 : u32 elt_bytes = va_arg (*va, u32);
418 0 : serialize_function_t *f = va_arg (*va, serialize_function_t *);
419 : u32 l, lo, hi;
420 : pool_header_t *p;
421 :
422 0 : l = vec_len (pool);
423 0 : serialize_integer (m, l, sizeof (u32));
424 0 : if (l == 0)
425 0 : return;
426 0 : p = pool_header (pool);
427 :
428 : /* No need to send free bitmap. Need to send index vector
429 : to guarantee that unserialized pool will be identical. */
430 0 : vec_serialize (m, p->free_indices, serialize_vec_32);
431 :
432 0 : pool_foreach_region (lo, hi, pool,
433 : serialize (m, f, pool + lo * elt_bytes, hi - lo));
434 : }
435 :
436 : static void *
437 0 : unserialize_pool_helper (serialize_main_t * m,
438 : u32 elt_bytes, u32 align, serialize_function_t * f)
439 : {
440 : void *v;
441 : u32 i, l, lo, hi;
442 : pool_header_t *p;
443 0 : vec_attr_t va = { .align = align,
444 : .elt_sz = elt_bytes,
445 : .hdr_sz = sizeof (pool_header_t) };
446 :
447 0 : unserialize_integer (m, &l, sizeof (l));
448 0 : if (l == 0)
449 : {
450 0 : return 0;
451 : }
452 :
453 0 : v = _vec_alloc_internal (l, &va);
454 0 : p = pool_header (v);
455 :
456 0 : vec_unserialize (m, &p->free_indices, unserialize_vec_32);
457 :
458 : /* Construct free bitmap. */
459 0 : p->free_bitmap = 0;
460 0 : for (i = 0; i < vec_len (p->free_indices); i++)
461 0 : p->free_bitmap = clib_bitmap_ori (p->free_bitmap, p->free_indices[i]);
462 :
463 0 : pool_foreach_region (lo, hi, v,
464 : unserialize (m, f, v + lo * elt_bytes, hi - lo));
465 :
466 0 : return v;
467 : }
468 :
469 : void
470 0 : unserialize_pool (serialize_main_t * m, va_list * va)
471 : {
472 0 : void **result = va_arg (*va, void **);
473 0 : u32 elt_bytes = va_arg (*va, u32);
474 0 : serialize_function_t *f = va_arg (*va, serialize_function_t *);
475 0 : *result = unserialize_pool_helper (m, elt_bytes, /* align */ 0, f);
476 0 : }
477 :
478 : void
479 0 : unserialize_aligned_pool (serialize_main_t * m, va_list * va)
480 : {
481 0 : void **result = va_arg (*va, void **);
482 0 : u32 elt_bytes = va_arg (*va, u32);
483 0 : u32 align = va_arg (*va, u32);
484 0 : serialize_function_t *f = va_arg (*va, serialize_function_t *);
485 0 : *result = unserialize_pool_helper (m, elt_bytes, align, f);
486 0 : }
487 :
488 : static void
489 0 : serialize_vec_heap_elt (serialize_main_t * m, va_list * va)
490 : {
491 0 : heap_elt_t *e = va_arg (*va, heap_elt_t *);
492 0 : u32 i, n = va_arg (*va, u32);
493 0 : for (i = 0; i < n; i++)
494 : {
495 0 : serialize_integer (m, e[i].offset, sizeof (e[i].offset));
496 0 : serialize_integer (m, e[i].next, sizeof (e[i].next));
497 0 : serialize_integer (m, e[i].prev, sizeof (e[i].prev));
498 : }
499 0 : }
500 :
501 : static void
502 0 : unserialize_vec_heap_elt (serialize_main_t * m, va_list * va)
503 : {
504 0 : heap_elt_t *e = va_arg (*va, heap_elt_t *);
505 0 : u32 i, n = va_arg (*va, u32);
506 0 : for (i = 0; i < n; i++)
507 : {
508 0 : unserialize_integer (m, &e[i].offset, sizeof (e[i].offset));
509 0 : unserialize_integer (m, &e[i].next, sizeof (e[i].next));
510 0 : unserialize_integer (m, &e[i].prev, sizeof (e[i].prev));
511 : }
512 0 : }
513 :
514 : void
515 0 : serialize_heap (serialize_main_t * m, va_list * va)
516 : {
517 0 : void *heap = va_arg (*va, void *);
518 0 : serialize_function_t *f = va_arg (*va, serialize_function_t *);
519 : u32 i, l;
520 : heap_header_t *h;
521 :
522 0 : l = vec_len (heap);
523 0 : serialize_integer (m, l, sizeof (u32));
524 0 : if (l == 0)
525 0 : return;
526 :
527 0 : h = heap_header (heap);
528 :
529 : #define foreach_serialize_heap_header_integer \
530 : _ (head) _ (tail) _ (used_count) _ (max_len) _ (flags) _ (elt_bytes)
531 :
532 : #define _(f) serialize_integer (m, h->f, sizeof (h->f));
533 0 : foreach_serialize_heap_header_integer;
534 : #undef _
535 :
536 0 : serialize_integer (m, vec_len (h->free_lists), sizeof (u32));
537 0 : for (i = 0; i < vec_len (h->free_lists); i++)
538 0 : vec_serialize (m, h->free_lists[i], serialize_vec_32);
539 :
540 0 : vec_serialize (m, h->elts, serialize_vec_heap_elt);
541 0 : vec_serialize (m, h->small_free_elt_free_index, serialize_vec_32);
542 0 : vec_serialize (m, h->free_elts, serialize_vec_32);
543 :
544 : /* Serialize data in heap. */
545 : {
546 : heap_elt_t *e, *end;
547 0 : e = h->elts + h->head;
548 0 : end = h->elts + h->tail;
549 : while (1)
550 : {
551 0 : if (!heap_is_free (e))
552 : {
553 0 : void *v = heap + heap_offset (e) * h->elt_bytes;
554 0 : u32 n = heap_elt_size (heap, e);
555 0 : serialize (m, f, v, n);
556 : }
557 0 : if (e == end)
558 0 : break;
559 0 : e = heap_next (e);
560 : }
561 : }
562 : }
563 :
564 : void
565 0 : unserialize_heap (serialize_main_t * m, va_list * va)
566 : {
567 0 : void **result = va_arg (*va, void **);
568 0 : serialize_function_t *f = va_arg (*va, serialize_function_t *);
569 : u32 i, vl, fl;
570 : heap_header_t h;
571 : void *heap;
572 :
573 0 : unserialize_integer (m, &vl, sizeof (u32));
574 0 : if (vl == 0)
575 : {
576 0 : *result = 0;
577 0 : return;
578 : }
579 :
580 0 : clib_memset (&h, 0, sizeof (h));
581 : #define _(f) unserialize_integer (m, &h.f, sizeof (h.f));
582 0 : foreach_serialize_heap_header_integer;
583 : #undef _
584 :
585 0 : unserialize_integer (m, &fl, sizeof (u32));
586 0 : vec_resize (h.free_lists, fl);
587 :
588 0 : for (i = 0; i < vec_len (h.free_lists); i++)
589 0 : vec_unserialize (m, &h.free_lists[i], unserialize_vec_32);
590 :
591 0 : vec_unserialize (m, &h.elts, unserialize_vec_heap_elt);
592 0 : vec_unserialize (m, &h.small_free_elt_free_index, unserialize_vec_32);
593 0 : vec_unserialize (m, &h.free_elts, unserialize_vec_32);
594 :
595 : /* Re-construct used elt bitmap. */
596 : if (CLIB_DEBUG > 0)
597 : {
598 : heap_elt_t *e;
599 0 : vec_foreach (e, h.elts)
600 : {
601 0 : if (!heap_is_free (e))
602 0 : h.used_elt_bitmap = clib_bitmap_ori (h.used_elt_bitmap, e - h.elts);
603 : }
604 : }
605 :
606 0 : heap = *result = _heap_new (vl, h.elt_bytes);
607 0 : heap_header (heap)[0] = h;
608 :
609 : /* Unserialize data in heap. */
610 : {
611 : heap_elt_t *e, *end;
612 0 : e = h.elts + h.head;
613 0 : end = h.elts + h.tail;
614 : while (1)
615 : {
616 0 : if (!heap_is_free (e))
617 : {
618 0 : void *v = heap + heap_offset (e) * h.elt_bytes;
619 0 : u32 n = heap_elt_size (heap, e);
620 0 : unserialize (m, f, v, n);
621 : }
622 0 : if (e == end)
623 0 : break;
624 0 : e = heap_next (e);
625 : }
626 : }
627 : }
628 :
629 : void
630 0 : serialize_magic (serialize_main_t * m, void *magic, u32 magic_bytes)
631 : {
632 : void *p;
633 0 : serialize_integer (m, magic_bytes, sizeof (magic_bytes));
634 0 : p = serialize_get (m, magic_bytes);
635 0 : clib_memcpy_fast (p, magic, magic_bytes);
636 0 : }
637 :
638 : void
639 0 : unserialize_check_magic (serialize_main_t * m, void *magic, u32 magic_bytes)
640 : {
641 : u32 l;
642 : void *d;
643 :
644 0 : unserialize_integer (m, &l, sizeof (l));
645 0 : if (l != magic_bytes)
646 : {
647 0 : bad:
648 0 : serialize_error_return (m, "bad magic number");
649 : }
650 0 : d = serialize_get (m, magic_bytes);
651 0 : if (memcmp (magic, d, magic_bytes))
652 0 : goto bad;
653 0 : }
654 :
655 : __clib_export clib_error_t *
656 0 : va_serialize (serialize_main_t * sm, va_list * va)
657 : {
658 0 : serialize_main_header_t *m = &sm->header;
659 0 : serialize_function_t *f = va_arg (*va, serialize_function_t *);
660 0 : clib_error_t *error = 0;
661 :
662 0 : m->recursion_level += 1;
663 0 : if (m->recursion_level == 1)
664 : {
665 0 : uword r = clib_setjmp (&m->error_longjmp, 0);
666 0 : error = uword_to_pointer (r, clib_error_t *);
667 : }
668 :
669 0 : if (!error)
670 0 : f (sm, va);
671 :
672 0 : m->recursion_level -= 1;
673 0 : return error;
674 : }
675 :
676 : __clib_export clib_error_t *
677 0 : serialize (serialize_main_t * m, ...)
678 : {
679 : clib_error_t *error;
680 : va_list va;
681 :
682 0 : va_start (va, m);
683 0 : error = va_serialize (m, &va);
684 0 : va_end (va);
685 0 : return error;
686 : }
687 :
688 : __clib_export clib_error_t *
689 0 : unserialize (serialize_main_t * m, ...)
690 : {
691 : clib_error_t *error;
692 : va_list va;
693 :
694 0 : va_start (va, m);
695 0 : error = va_serialize (m, &va);
696 0 : va_end (va);
697 0 : return error;
698 : }
699 :
700 : static void *
701 32617 : serialize_write_not_inline (serialize_main_header_t * m,
702 : serialize_stream_t * s,
703 : uword n_bytes_to_write, uword flags)
704 : {
705 : uword cur_bi, n_left_b, n_left_o;
706 :
707 32617 : ASSERT (s->current_buffer_index <= s->n_buffer_bytes);
708 32617 : cur_bi = s->current_buffer_index;
709 32617 : n_left_b = s->n_buffer_bytes - cur_bi;
710 32617 : n_left_o = vec_len (s->overflow_buffer);
711 :
712 : /* Prepend overflow buffer if present. */
713 : do
714 : {
715 45662 : if (n_left_o > 0 && n_left_b > 0)
716 : {
717 26090 : uword n = clib_min (n_left_b, n_left_o);
718 26090 : clib_memcpy_fast (s->buffer + cur_bi, s->overflow_buffer, n);
719 26090 : cur_bi += n;
720 26090 : n_left_b -= n;
721 26090 : n_left_o -= n;
722 26090 : if (n_left_o == 0)
723 13045 : vec_set_len (s->overflow_buffer, 0);
724 : else
725 13045 : vec_delete (s->overflow_buffer, n, 0);
726 : }
727 :
728 : /* Call data function when buffer is complete. Data function should
729 : dispatch with current buffer and give us a new one to write more
730 : data into. */
731 45662 : if (n_left_b == 0)
732 : {
733 17941 : s->current_buffer_index = cur_bi;
734 17941 : m->data_function (m, s);
735 17941 : cur_bi = s->current_buffer_index;
736 17941 : n_left_b = s->n_buffer_bytes - cur_bi;
737 : }
738 : }
739 45662 : while (n_left_o > 0);
740 :
741 32617 : if (n_left_o > 0 || n_left_b < n_bytes_to_write)
742 : {
743 : u8 *r;
744 13045 : s->current_buffer_index = cur_bi;
745 13045 : vec_add2 (s->overflow_buffer, r, n_bytes_to_write);
746 13045 : return r;
747 : }
748 : else
749 : {
750 19572 : s->current_buffer_index = cur_bi + n_bytes_to_write;
751 19572 : return s->buffer + cur_bi;
752 : }
753 : }
754 :
755 : static void *
756 0 : serialize_read_not_inline (serialize_main_header_t * m,
757 : serialize_stream_t * s,
758 : uword n_bytes_to_read, uword flags)
759 : {
760 : uword cur_bi, cur_oi, n_left_b, n_left_o, n_left_to_read;
761 :
762 0 : ASSERT (s->current_buffer_index <= s->n_buffer_bytes);
763 :
764 0 : cur_bi = s->current_buffer_index;
765 0 : cur_oi = s->current_overflow_index;
766 :
767 0 : n_left_b = s->n_buffer_bytes - cur_bi;
768 0 : n_left_o = vec_len (s->overflow_buffer) - cur_oi;
769 :
770 : /* Read from overflow? */
771 0 : if (n_left_o >= n_bytes_to_read)
772 : {
773 0 : s->current_overflow_index = cur_oi + n_bytes_to_read;
774 0 : return vec_elt_at_index (s->overflow_buffer, cur_oi);
775 : }
776 :
777 : /* Reset overflow buffer. */
778 0 : if (n_left_o == 0 && s->overflow_buffer)
779 : {
780 0 : s->current_overflow_index = 0;
781 0 : vec_set_len (s->overflow_buffer, 0);
782 : }
783 :
784 0 : n_left_to_read = n_bytes_to_read;
785 0 : while (n_left_to_read > 0)
786 : {
787 : uword n;
788 :
789 : /* If we don't have enough data between overflow and normal buffer
790 : call read function. */
791 0 : if (n_left_o + n_left_b < n_bytes_to_read)
792 : {
793 : /* Save any left over buffer in overflow vector. */
794 0 : if (n_left_b > 0)
795 : {
796 0 : vec_add (s->overflow_buffer, s->buffer + cur_bi, n_left_b);
797 0 : n_left_o += n_left_b;
798 0 : n_left_to_read -= n_left_b;
799 : /* Advance buffer to end --- even if
800 : SERIALIZE_FLAG_NO_ADVANCE_CURRENT_BUFFER_INDEX is set. */
801 0 : cur_bi = s->n_buffer_bytes;
802 0 : n_left_b = 0;
803 : }
804 :
805 0 : if (m->data_function)
806 : {
807 0 : m->data_function (m, s);
808 0 : cur_bi = s->current_buffer_index;
809 0 : n_left_b = s->n_buffer_bytes - cur_bi;
810 : }
811 : }
812 :
813 : /* For first time through loop return if we have enough data
814 : in normal buffer and overflow vector is empty. */
815 0 : if (n_left_o == 0
816 0 : && n_left_to_read == n_bytes_to_read && n_left_b >= n_left_to_read)
817 : {
818 0 : s->current_buffer_index = cur_bi + n_bytes_to_read;
819 0 : return s->buffer + cur_bi;
820 : }
821 :
822 0 : if (!m->data_function || serialize_stream_is_end_of_stream (s))
823 : {
824 : /* This can happen for a peek at end of file.
825 : Pad overflow buffer with 0s. */
826 0 : vec_resize (s->overflow_buffer, n_left_to_read);
827 0 : n_left_o += n_left_to_read;
828 0 : n_left_to_read = 0;
829 : }
830 : else
831 : {
832 : /* Copy from buffer to overflow vector. */
833 0 : n = clib_min (n_left_to_read, n_left_b);
834 0 : vec_add (s->overflow_buffer, s->buffer + cur_bi, n);
835 0 : cur_bi += n;
836 0 : n_left_b -= n;
837 0 : n_left_o += n;
838 0 : n_left_to_read -= n;
839 : }
840 : }
841 :
842 0 : s->current_buffer_index = cur_bi;
843 0 : s->current_overflow_index = cur_oi + n_bytes_to_read;
844 0 : return vec_elt_at_index (s->overflow_buffer, cur_oi);
845 : }
846 :
847 : __clib_export void *
848 30986 : serialize_read_write_not_inline (serialize_main_header_t * m,
849 : serialize_stream_t * s,
850 : uword n_bytes, uword flags)
851 : {
852 30986 : return (((flags & SERIALIZE_FLAG_IS_READ) ? serialize_read_not_inline :
853 : serialize_write_not_inline) (m, s, n_bytes, flags));
854 : }
855 :
856 : static void
857 1631 : serialize_read_write_close (serialize_main_header_t * m,
858 : serialize_stream_t * s, uword flags)
859 : {
860 1631 : if (serialize_stream_is_end_of_stream (s))
861 0 : return;
862 :
863 1631 : if (flags & SERIALIZE_FLAG_IS_WRITE)
864 : /* "Write" 0 bytes to flush overflow vector. */
865 1631 : serialize_write_not_inline (m, s, /* n bytes */ 0, flags);
866 :
867 1631 : serialize_stream_set_end_of_stream (s);
868 :
869 : /* Call it one last time to flush buffer and close. */
870 1631 : m->data_function (m, s);
871 :
872 1631 : vec_free (s->overflow_buffer);
873 : }
874 :
875 : __clib_export void
876 1631 : serialize_close (serialize_main_t * m)
877 : {
878 1631 : serialize_read_write_close (&m->header, &m->stream,
879 : SERIALIZE_FLAG_IS_WRITE);
880 1631 : }
881 :
882 : __clib_export void
883 0 : unserialize_close (serialize_main_t * m)
884 : {
885 0 : serialize_read_write_close (&m->header, &m->stream, SERIALIZE_FLAG_IS_READ);
886 0 : }
887 :
888 : __clib_export void
889 47 : serialize_open_data (serialize_main_t * m, u8 * data, uword n_data_bytes)
890 : {
891 47 : clib_memset (m, 0, sizeof (m[0]));
892 47 : m->stream.buffer = data;
893 47 : m->stream.n_buffer_bytes = n_data_bytes;
894 47 : }
895 :
896 : __clib_export void
897 47 : unserialize_open_data (serialize_main_t * m, u8 * data, uword n_data_bytes)
898 : {
899 47 : serialize_open_data (m, data, n_data_bytes);
900 47 : }
901 :
902 : static void
903 19572 : serialize_vector_write (serialize_main_header_t * m, serialize_stream_t * s)
904 : {
905 19572 : if (!serialize_stream_is_end_of_stream (s))
906 : {
907 : /* Double buffer size. */
908 17941 : uword l = vec_len (s->buffer);
909 17941 : vec_resize (s->buffer, l > 0 ? l : 64);
910 17941 : s->n_buffer_bytes = vec_len (s->buffer);
911 : }
912 19572 : }
913 :
914 : __clib_export void
915 1631 : serialize_open_vector (serialize_main_t * m, u8 * vector)
916 : {
917 1631 : clib_memset (m, 0, sizeof (m[0]));
918 1631 : m->header.data_function = serialize_vector_write;
919 1631 : m->stream.buffer = vector;
920 1631 : m->stream.current_buffer_index = 0;
921 1631 : m->stream.n_buffer_bytes = vec_len (vector);
922 1631 : }
923 :
924 : __clib_export void *
925 1631 : serialize_close_vector (serialize_main_t * m)
926 : {
927 1631 : serialize_stream_t *s = &m->stream;
928 : void *result;
929 :
930 1631 : serialize_close (m); /* frees overflow buffer */
931 :
932 1631 : if (s->buffer)
933 1631 : vec_set_len (s->buffer, s->current_buffer_index);
934 1631 : result = s->buffer;
935 1631 : clib_memset (m, 0, sizeof (m[0]));
936 1631 : return result;
937 : }
938 :
939 : __clib_export void
940 0 : serialize_multiple_1 (serialize_main_t *m, void *data, uword data_stride,
941 : uword n_data)
942 : {
943 0 : u8 *d = data;
944 : u8 *p;
945 0 : uword n_left = n_data;
946 :
947 0 : while (n_left >= 4)
948 : {
949 0 : p = serialize_get (m, 4 * sizeof (d[0]));
950 0 : p[0] = d[0 * data_stride];
951 0 : p[1] = d[1 * data_stride];
952 0 : p[2] = d[2 * data_stride];
953 0 : p[3] = d[3 * data_stride];
954 0 : n_left -= 4;
955 0 : d += 4 * data_stride;
956 : }
957 :
958 0 : if (n_left > 0)
959 : {
960 0 : p = serialize_get (m, n_left * sizeof (p[0]));
961 0 : while (n_left > 0)
962 : {
963 0 : p[0] = d[0];
964 0 : p += 1;
965 0 : d += 1 * data_stride;
966 0 : n_left -= 1;
967 : }
968 : }
969 0 : }
970 :
971 : __clib_export void
972 0 : serialize_multiple_2 (serialize_main_t *m, void *data, uword data_stride,
973 : uword n_data)
974 : {
975 0 : void *d = data;
976 : u16 *p;
977 0 : uword n_left = n_data;
978 :
979 0 : while (n_left >= 4)
980 : {
981 0 : p = serialize_get (m, 4 * sizeof (p[0]));
982 0 : clib_mem_unaligned (p + 0, u16) =
983 0 : clib_host_to_net_mem_u16 (d + 0 * data_stride);
984 0 : clib_mem_unaligned (p + 1, u16) =
985 0 : clib_host_to_net_mem_u16 (d + 1 * data_stride);
986 0 : clib_mem_unaligned (p + 2, u16) =
987 0 : clib_host_to_net_mem_u16 (d + 2 * data_stride);
988 0 : clib_mem_unaligned (p + 3, u16) =
989 0 : clib_host_to_net_mem_u16 (d + 3 * data_stride);
990 0 : n_left -= 4;
991 0 : d += 4 * data_stride;
992 : }
993 :
994 0 : if (n_left > 0)
995 : {
996 0 : p = serialize_get (m, n_left * sizeof (p[0]));
997 0 : while (n_left > 0)
998 : {
999 0 : clib_mem_unaligned (p + 0, u16) =
1000 0 : clib_host_to_net_mem_u16 (d + 0 * data_stride);
1001 0 : p += 1;
1002 0 : d += 1 * data_stride;
1003 0 : n_left -= 1;
1004 : }
1005 : }
1006 0 : }
1007 :
1008 : __clib_export void
1009 0 : serialize_multiple_4 (serialize_main_t *m, void *data, uword data_stride,
1010 : uword n_data)
1011 : {
1012 0 : void *d = data;
1013 : u32 *p;
1014 0 : uword n_left = n_data;
1015 :
1016 0 : while (n_left >= 4)
1017 : {
1018 0 : p = serialize_get (m, 4 * sizeof (p[0]));
1019 0 : clib_mem_unaligned (p + 0, u32) =
1020 0 : clib_host_to_net_mem_u32 (d + 0 * data_stride);
1021 0 : clib_mem_unaligned (p + 1, u32) =
1022 0 : clib_host_to_net_mem_u32 (d + 1 * data_stride);
1023 0 : clib_mem_unaligned (p + 2, u32) =
1024 0 : clib_host_to_net_mem_u32 (d + 2 * data_stride);
1025 0 : clib_mem_unaligned (p + 3, u32) =
1026 0 : clib_host_to_net_mem_u32 (d + 3 * data_stride);
1027 0 : n_left -= 4;
1028 0 : d += 4 * data_stride;
1029 : }
1030 :
1031 0 : if (n_left > 0)
1032 : {
1033 0 : p = serialize_get (m, n_left * sizeof (p[0]));
1034 0 : while (n_left > 0)
1035 : {
1036 0 : clib_mem_unaligned (p + 0, u32) =
1037 0 : clib_host_to_net_mem_u32 (d + 0 * data_stride);
1038 0 : p += 1;
1039 0 : d += 1 * data_stride;
1040 0 : n_left -= 1;
1041 : }
1042 : }
1043 0 : }
1044 :
1045 : __clib_export void
1046 0 : unserialize_multiple_1 (serialize_main_t *m, void *data, uword data_stride,
1047 : uword n_data)
1048 : {
1049 0 : u8 *d = data;
1050 : u8 *p;
1051 0 : uword n_left = n_data;
1052 :
1053 0 : while (n_left >= 4)
1054 : {
1055 0 : p = unserialize_get (m, 4 * sizeof (d[0]));
1056 0 : d[0 * data_stride] = p[0];
1057 0 : d[1 * data_stride] = p[1];
1058 0 : d[2 * data_stride] = p[2];
1059 0 : d[3 * data_stride] = p[3];
1060 0 : n_left -= 4;
1061 0 : d += 4 * data_stride;
1062 : }
1063 :
1064 0 : if (n_left > 0)
1065 : {
1066 0 : p = unserialize_get (m, n_left * sizeof (p[0]));
1067 0 : while (n_left > 0)
1068 : {
1069 0 : d[0] = p[0];
1070 0 : p += 1;
1071 0 : d += 1 * data_stride;
1072 0 : n_left -= 1;
1073 : }
1074 : }
1075 0 : }
1076 :
1077 : __clib_export void
1078 0 : unserialize_multiple_2 (serialize_main_t *m, void *data, uword data_stride,
1079 : uword n_data)
1080 : {
1081 0 : void *d = data;
1082 : u16 *p;
1083 0 : uword n_left = n_data;
1084 :
1085 0 : while (n_left >= 4)
1086 : {
1087 0 : p = unserialize_get (m, 4 * sizeof (p[0]));
1088 0 : clib_mem_unaligned (d + 0 * data_stride, u16) =
1089 0 : clib_net_to_host_mem_u16 (p + 0);
1090 0 : clib_mem_unaligned (d + 1 * data_stride, u16) =
1091 0 : clib_net_to_host_mem_u16 (p + 1);
1092 0 : clib_mem_unaligned (d + 2 * data_stride, u16) =
1093 0 : clib_net_to_host_mem_u16 (p + 2);
1094 0 : clib_mem_unaligned (d + 3 * data_stride, u16) =
1095 0 : clib_net_to_host_mem_u16 (p + 3);
1096 0 : n_left -= 4;
1097 0 : d += 4 * data_stride;
1098 : }
1099 :
1100 0 : if (n_left > 0)
1101 : {
1102 0 : p = unserialize_get (m, n_left * sizeof (p[0]));
1103 0 : while (n_left > 0)
1104 : {
1105 0 : clib_mem_unaligned (d + 0 * data_stride, u16) =
1106 0 : clib_net_to_host_mem_u16 (p + 0);
1107 0 : p += 1;
1108 0 : d += 1 * data_stride;
1109 0 : n_left -= 1;
1110 : }
1111 : }
1112 0 : }
1113 :
1114 : __clib_export void
1115 0 : unserialize_multiple_4 (serialize_main_t *m, void *data, uword data_stride,
1116 : uword n_data)
1117 : {
1118 0 : void *d = data;
1119 : u32 *p;
1120 0 : uword n_left = n_data;
1121 :
1122 0 : while (n_left >= 4)
1123 : {
1124 0 : p = unserialize_get (m, 4 * sizeof (p[0]));
1125 0 : clib_mem_unaligned (d + 0 * data_stride, u32) =
1126 0 : clib_net_to_host_mem_u32 (p + 0);
1127 0 : clib_mem_unaligned (d + 1 * data_stride, u32) =
1128 0 : clib_net_to_host_mem_u32 (p + 1);
1129 0 : clib_mem_unaligned (d + 2 * data_stride, u32) =
1130 0 : clib_net_to_host_mem_u32 (p + 2);
1131 0 : clib_mem_unaligned (d + 3 * data_stride, u32) =
1132 0 : clib_net_to_host_mem_u32 (p + 3);
1133 0 : n_left -= 4;
1134 0 : d += 4 * data_stride;
1135 : }
1136 :
1137 0 : if (n_left > 0)
1138 : {
1139 0 : p = unserialize_get (m, n_left * sizeof (p[0]));
1140 0 : while (n_left > 0)
1141 : {
1142 0 : clib_mem_unaligned (d + 0 * data_stride, u32) =
1143 0 : clib_net_to_host_mem_u32 (p + 0);
1144 0 : p += 1;
1145 0 : d += 1 * data_stride;
1146 0 : n_left -= 1;
1147 : }
1148 : }
1149 0 : }
1150 :
1151 : #ifdef CLIB_UNIX
1152 :
1153 : #include <unistd.h>
1154 : #include <fcntl.h>
1155 :
1156 : static void
1157 0 : clib_file_write (serialize_main_header_t * m, serialize_stream_t * s)
1158 : {
1159 : int fd, n;
1160 :
1161 0 : fd = s->data_function_opaque;
1162 0 : n = write (fd, s->buffer, s->current_buffer_index);
1163 0 : if (n < 0)
1164 : {
1165 0 : if (!unix_error_is_fatal (errno))
1166 0 : n = 0;
1167 : else
1168 0 : serialize_error (m, clib_error_return_unix (0, "write"));
1169 : }
1170 0 : if (n == s->current_buffer_index)
1171 0 : vec_set_len (s->buffer, 0);
1172 : else
1173 0 : vec_delete (s->buffer, n, 0);
1174 0 : s->current_buffer_index = vec_len (s->buffer);
1175 0 : }
1176 :
1177 : static void
1178 0 : clib_file_read (serialize_main_header_t * m, serialize_stream_t * s)
1179 : {
1180 : int fd, n;
1181 :
1182 0 : fd = s->data_function_opaque;
1183 0 : n = read (fd, s->buffer, vec_len (s->buffer));
1184 0 : if (n < 0)
1185 : {
1186 0 : if (!unix_error_is_fatal (errno))
1187 0 : n = 0;
1188 : else
1189 0 : serialize_error (m, clib_error_return_unix (0, "read"));
1190 : }
1191 0 : else if (n == 0)
1192 0 : serialize_stream_set_end_of_stream (s);
1193 0 : s->current_buffer_index = 0;
1194 0 : s->n_buffer_bytes = n;
1195 0 : }
1196 :
1197 : static void
1198 0 : serialize_open_clib_file_descriptor_helper (serialize_main_t * m, int fd,
1199 : uword is_read)
1200 : {
1201 0 : clib_memset (m, 0, sizeof (m[0]));
1202 0 : vec_resize (m->stream.buffer, 4096);
1203 :
1204 0 : if (!is_read)
1205 : {
1206 0 : m->stream.n_buffer_bytes = vec_len (m->stream.buffer);
1207 0 : vec_set_len (m->stream.buffer, 0);
1208 : }
1209 :
1210 0 : m->header.data_function = is_read ? clib_file_read : clib_file_write;
1211 0 : m->stream.data_function_opaque = fd;
1212 0 : }
1213 :
1214 : __clib_export void
1215 0 : serialize_open_clib_file_descriptor (serialize_main_t * m, int fd)
1216 : {
1217 0 : serialize_open_clib_file_descriptor_helper (m, fd, /* is_read */ 0);
1218 0 : }
1219 :
1220 : __clib_export void
1221 0 : unserialize_open_clib_file_descriptor (serialize_main_t * m, int fd)
1222 : {
1223 0 : serialize_open_clib_file_descriptor_helper (m, fd, /* is_read */ 1);
1224 0 : }
1225 :
1226 : static clib_error_t *
1227 0 : serialize_open_clib_file_helper (serialize_main_t * m, char *file,
1228 : uword is_read)
1229 : {
1230 : int fd, mode;
1231 :
1232 0 : mode = is_read ? O_RDONLY : O_RDWR | O_CREAT | O_TRUNC;
1233 0 : fd = open (file, mode, 0666);
1234 0 : if (fd < 0)
1235 0 : return clib_error_return_unix (0, "open `%s'", file);
1236 :
1237 0 : serialize_open_clib_file_descriptor_helper (m, fd, is_read);
1238 0 : return 0;
1239 : }
1240 :
1241 : __clib_export clib_error_t *
1242 0 : serialize_open_clib_file (serialize_main_t * m, char *file)
1243 : {
1244 0 : return serialize_open_clib_file_helper (m, file, /* is_read */ 0);
1245 : }
1246 :
1247 : __clib_export clib_error_t *
1248 0 : unserialize_open_clib_file (serialize_main_t * m, char *file)
1249 : {
1250 0 : return serialize_open_clib_file_helper (m, file, /* is_read */ 1);
1251 : }
1252 :
1253 : #endif /* CLIB_UNIX */
1254 :
1255 : /*
1256 : * fd.io coding-style-patch-verification: ON
1257 : *
1258 : * Local Variables:
1259 : * eval: (c-set-style "gnu")
1260 : * End:
1261 : */
|