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:
7 * http://www.apache.org/licenses/LICENSE-2.0
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.
16 Copyright (c) 2005 Eliot Dresselhaus
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:
26 The above copyright notice and this permission notice shall be
27 included in all copies or substantial portions of the Software.
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.
38 /* Turn data structures into byte streams for saving or transport. */
40 #include <vppinfra/heap.h>
41 #include <vppinfra/pool.h>
42 #include <vppinfra/serialize.h>
45 serialize_64 (serialize_main_t * m, va_list * va)
47 u64 x = va_arg (*va, u64);
51 serialize_integer (m, lo, sizeof (lo));
52 serialize_integer (m, hi, sizeof (hi));
56 serialize_32 (serialize_main_t * m, va_list * va)
58 u32 x = va_arg (*va, u32);
59 serialize_integer (m, x, sizeof (x));
63 serialize_16 (serialize_main_t * m, va_list * va)
65 u32 x = va_arg (*va, u32);
66 serialize_integer (m, x, sizeof (u16));
70 serialize_8 (serialize_main_t * m, va_list * va)
72 u32 x = va_arg (*va, u32);
73 serialize_integer (m, x, sizeof (u8));
77 unserialize_64 (serialize_main_t * m, va_list * va)
79 u64 *x = va_arg (*va, u64 *);
81 unserialize_integer (m, &lo, sizeof (lo));
82 unserialize_integer (m, &hi, sizeof (hi));
83 *x = ((u64) hi << 32) | (u64) lo;
87 unserialize_32 (serialize_main_t * m, va_list * va)
89 u32 *x = va_arg (*va, u32 *);
90 unserialize_integer (m, x, sizeof (x[0]));
94 unserialize_16 (serialize_main_t * m, va_list * va)
96 u16 *x = va_arg (*va, u16 *);
98 unserialize_integer (m, &t, sizeof (x[0]));
103 unserialize_8 (serialize_main_t * m, va_list * va)
105 u8 *x = va_arg (*va, u8 *);
107 unserialize_integer (m, &t, sizeof (x[0]));
112 serialize_f64 (serialize_main_t * m, va_list * va)
114 f64 x = va_arg (*va, f64);
121 serialize (m, serialize_64, y.i);
125 serialize_f32 (serialize_main_t * m, va_list * va)
127 f32 x = va_arg (*va, f64);
134 serialize_integer (m, y.i, sizeof (y.i));
138 unserialize_f64 (serialize_main_t * m, va_list * va)
140 f64 *x = va_arg (*va, f64 *);
146 unserialize (m, unserialize_64, &y.i);
151 unserialize_f32 (serialize_main_t * m, va_list * va)
153 f32 *x = va_arg (*va, f32 *);
159 unserialize_integer (m, &y.i, sizeof (y.i));
164 serialize_cstring (serialize_main_t * m, char *s)
166 u32 len = s ? strlen (s) : 0;
169 serialize_likely_small_unsigned_integer (m, len);
172 p = serialize_get (m, len);
173 clib_memcpy_fast (p, s, len);
178 unserialize_cstring (serialize_main_t * m, char **s)
183 len = unserialize_likely_small_unsigned_integer (m);
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.
190 if (len > 0 && len != 0xFFFFFFFF)
192 r = vec_new (char, len + 1);
193 p = unserialize_get (m, len);
194 clib_memcpy_fast (r, p, len);
196 /* Null terminate. */
202 /* vec_serialize/vec_unserialize helper functions for basic vector types. */
204 serialize_vec_8 (serialize_main_t * m, va_list * va)
206 u8 *s = va_arg (*va, u8 *);
207 u32 n = va_arg (*va, u32);
208 u8 *p = serialize_get (m, n * sizeof (u8));
209 clib_memcpy_fast (p, s, n * sizeof (u8));
213 unserialize_vec_8 (serialize_main_t * m, va_list * va)
215 u8 *s = va_arg (*va, u8 *);
216 u32 n = va_arg (*va, u32);
217 u8 *p = unserialize_get (m, n);
218 clib_memcpy_fast (s, p, n);
222 void serialize_vec_##n_bits (serialize_main_t * m, va_list * va) \
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])); \
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]); \
241 p[0] = clib_host_to_net_u##n_bits (s[0]); \
248 void unserialize_vec_##n_bits (serialize_main_t * m, va_list * va) \
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])); \
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]); \
267 s[0] = clib_net_to_host_mem_u##n_bits (&p[0]); \
280 #define SERIALIZE_VECTOR_CHUNK_SIZE 64
283 serialize_vector (serialize_main_t * m, va_list * va)
285 void *vec = va_arg (*va, void *);
286 u32 elt_bytes = va_arg (*va, u32);
287 serialize_function_t *f = va_arg (*va, serialize_function_t *);
288 u32 l = vec_len (vec);
291 serialize_integer (m, l, sizeof (l));
293 /* Serialize vector in chunks for cache locality. */
296 u32 n = clib_min (SERIALIZE_VECTOR_CHUNK_SIZE, l);
297 serialize (m, f, p, n);
299 p += SERIALIZE_VECTOR_CHUNK_SIZE * elt_bytes;
304 unserialize_vector_ha (serialize_main_t * m,
307 u32 align, u32 max_length, serialize_function_t * f)
311 vec_attr_t va = { .align = align,
313 .hdr_sz = header_bytes };
315 unserialize_integer (m, &l, sizeof (l));
317 serialize_error (&m->header,
318 clib_error_create ("bad vector length %d", l));
320 p = v = _vec_alloc_internal (l, &va);
324 u32 n = clib_min (SERIALIZE_VECTOR_CHUNK_SIZE, l);
325 unserialize (m, f, p, n);
327 p += SERIALIZE_VECTOR_CHUNK_SIZE * elt_bytes;
333 unserialize_aligned_vector (serialize_main_t * m, va_list * va)
335 void **vec = va_arg (*va, void **);
336 u32 elt_bytes = va_arg (*va, u32);
337 serialize_function_t *f = va_arg (*va, serialize_function_t *);
338 u32 align = va_arg (*va, u32);
340 *vec = unserialize_vector_ha (m, elt_bytes,
341 /* header_bytes */ 0,
348 unserialize_vector (serialize_main_t * m, va_list * va)
350 void **vec = va_arg (*va, void **);
351 u32 elt_bytes = va_arg (*va, u32);
352 serialize_function_t *f = va_arg (*va, serialize_function_t *);
354 *vec = unserialize_vector_ha (m, elt_bytes,
355 /* header_bytes */ 0,
362 serialize_bitmap (serialize_main_t * m, uword * b)
367 n_u32s = l * sizeof (b[0]) / sizeof (u32);
368 serialize_integer (m, n_u32s, sizeof (n_u32s));
370 /* Send 32 bit words, low-order word first on 64 bit. */
371 for (i = 0; i < l; i++)
373 serialize_integer (m, b[i], sizeof (u32));
374 if (BITS (uword) == 64)
375 serialize_integer (m, (u64) b[i] >> (u64) 32, sizeof (u32));
380 unserialize_bitmap (serialize_main_t * m)
385 unserialize_integer (m, &n_u32s, sizeof (n_u32s));
389 i = (n_u32s * sizeof (u32) + sizeof (b[0]) - 1) / sizeof (b[0]);
391 for (i = 0; i < n_u32s; i++)
394 unserialize_integer (m, &data, sizeof (u32));
396 /* Low-word is first on 64 bit. */
397 if (BITS (uword) == 64)
400 b[i / 2] |= (u64) data << (u64) 0;
402 b[i / 2] |= (u64) data << (u64) 32;
414 serialize_pool (serialize_main_t * m, va_list * va)
416 void *pool = va_arg (*va, void *);
417 u32 elt_bytes = va_arg (*va, u32);
418 serialize_function_t *f = va_arg (*va, serialize_function_t *);
423 serialize_integer (m, l, sizeof (u32));
426 p = pool_header (pool);
428 /* No need to send free bitmap. Need to send index vector
429 to guarantee that unserialized pool will be identical. */
430 vec_serialize (m, p->free_indices, serialize_vec_32);
432 pool_foreach_region (lo, hi, pool,
433 serialize (m, f, pool + lo * elt_bytes, hi - lo));
437 unserialize_pool_helper (serialize_main_t * m,
438 u32 elt_bytes, u32 align, serialize_function_t * f)
443 vec_attr_t va = { .align = align,
445 .hdr_sz = sizeof (pool_header_t) };
447 unserialize_integer (m, &l, sizeof (l));
453 v = _vec_alloc_internal (l, &va);
456 vec_unserialize (m, &p->free_indices, unserialize_vec_32);
458 /* Construct free bitmap. */
460 for (i = 0; i < vec_len (p->free_indices); i++)
461 p->free_bitmap = clib_bitmap_ori (p->free_bitmap, p->free_indices[i]);
463 pool_foreach_region (lo, hi, v,
464 unserialize (m, f, v + lo * elt_bytes, hi - lo));
470 unserialize_pool (serialize_main_t * m, va_list * va)
472 void **result = va_arg (*va, void **);
473 u32 elt_bytes = va_arg (*va, u32);
474 serialize_function_t *f = va_arg (*va, serialize_function_t *);
475 *result = unserialize_pool_helper (m, elt_bytes, /* align */ 0, f);
479 unserialize_aligned_pool (serialize_main_t * m, va_list * va)
481 void **result = va_arg (*va, void **);
482 u32 elt_bytes = va_arg (*va, u32);
483 u32 align = va_arg (*va, u32);
484 serialize_function_t *f = va_arg (*va, serialize_function_t *);
485 *result = unserialize_pool_helper (m, elt_bytes, align, f);
489 serialize_vec_heap_elt (serialize_main_t * m, va_list * va)
491 heap_elt_t *e = va_arg (*va, heap_elt_t *);
492 u32 i, n = va_arg (*va, u32);
493 for (i = 0; i < n; i++)
495 serialize_integer (m, e[i].offset, sizeof (e[i].offset));
496 serialize_integer (m, e[i].next, sizeof (e[i].next));
497 serialize_integer (m, e[i].prev, sizeof (e[i].prev));
502 unserialize_vec_heap_elt (serialize_main_t * m, va_list * va)
504 heap_elt_t *e = va_arg (*va, heap_elt_t *);
505 u32 i, n = va_arg (*va, u32);
506 for (i = 0; i < n; i++)
508 unserialize_integer (m, &e[i].offset, sizeof (e[i].offset));
509 unserialize_integer (m, &e[i].next, sizeof (e[i].next));
510 unserialize_integer (m, &e[i].prev, sizeof (e[i].prev));
515 serialize_heap (serialize_main_t * m, va_list * va)
517 void *heap = va_arg (*va, void *);
518 serialize_function_t *f = va_arg (*va, serialize_function_t *);
523 serialize_integer (m, l, sizeof (u32));
527 h = heap_header (heap);
529 #define foreach_serialize_heap_header_integer \
530 _ (head) _ (tail) _ (used_count) _ (max_len) _ (flags) _ (elt_bytes)
532 #define _(f) serialize_integer (m, h->f, sizeof (h->f));
533 foreach_serialize_heap_header_integer;
536 serialize_integer (m, vec_len (h->free_lists), sizeof (u32));
537 for (i = 0; i < vec_len (h->free_lists); i++)
538 vec_serialize (m, h->free_lists[i], serialize_vec_32);
540 vec_serialize (m, h->elts, serialize_vec_heap_elt);
541 vec_serialize (m, h->small_free_elt_free_index, serialize_vec_32);
542 vec_serialize (m, h->free_elts, serialize_vec_32);
544 /* Serialize data in heap. */
547 e = h->elts + h->head;
548 end = h->elts + h->tail;
551 if (!heap_is_free (e))
553 void *v = heap + heap_offset (e) * h->elt_bytes;
554 u32 n = heap_elt_size (heap, e);
555 serialize (m, f, v, n);
565 unserialize_heap (serialize_main_t * m, va_list * va)
567 void **result = va_arg (*va, void **);
568 serialize_function_t *f = va_arg (*va, serialize_function_t *);
573 unserialize_integer (m, &vl, sizeof (u32));
580 clib_memset (&h, 0, sizeof (h));
581 #define _(f) unserialize_integer (m, &h.f, sizeof (h.f));
582 foreach_serialize_heap_header_integer;
585 unserialize_integer (m, &fl, sizeof (u32));
586 vec_resize (h.free_lists, fl);
588 for (i = 0; i < vec_len (h.free_lists); i++)
589 vec_unserialize (m, &h.free_lists[i], unserialize_vec_32);
591 vec_unserialize (m, &h.elts, unserialize_vec_heap_elt);
592 vec_unserialize (m, &h.small_free_elt_free_index, unserialize_vec_32);
593 vec_unserialize (m, &h.free_elts, unserialize_vec_32);
595 /* Re-construct used elt bitmap. */
599 vec_foreach (e, h.elts)
601 if (!heap_is_free (e))
602 h.used_elt_bitmap = clib_bitmap_ori (h.used_elt_bitmap, e - h.elts);
606 heap = *result = _heap_new (vl, h.elt_bytes);
607 heap_header (heap)[0] = h;
609 /* Unserialize data in heap. */
613 end = h.elts + h.tail;
616 if (!heap_is_free (e))
618 void *v = heap + heap_offset (e) * h.elt_bytes;
619 u32 n = heap_elt_size (heap, e);
620 unserialize (m, f, v, n);
630 serialize_magic (serialize_main_t * m, void *magic, u32 magic_bytes)
633 serialize_integer (m, magic_bytes, sizeof (magic_bytes));
634 p = serialize_get (m, magic_bytes);
635 clib_memcpy_fast (p, magic, magic_bytes);
639 unserialize_check_magic (serialize_main_t * m, void *magic, u32 magic_bytes)
644 unserialize_integer (m, &l, sizeof (l));
645 if (l != magic_bytes)
648 serialize_error_return (m, "bad magic number");
650 d = serialize_get (m, magic_bytes);
651 if (memcmp (magic, d, magic_bytes))
655 __clib_export clib_error_t *
656 va_serialize (serialize_main_t * sm, va_list * va)
658 serialize_main_header_t *m = &sm->header;
659 serialize_function_t *f = va_arg (*va, serialize_function_t *);
660 clib_error_t *error = 0;
662 m->recursion_level += 1;
663 if (m->recursion_level == 1)
665 uword r = clib_setjmp (&m->error_longjmp, 0);
666 error = uword_to_pointer (r, clib_error_t *);
672 m->recursion_level -= 1;
676 __clib_export clib_error_t *
677 serialize (serialize_main_t * m, ...)
683 error = va_serialize (m, &va);
688 __clib_export clib_error_t *
689 unserialize (serialize_main_t * m, ...)
695 error = va_serialize (m, &va);
701 serialize_write_not_inline (serialize_main_header_t * m,
702 serialize_stream_t * s,
703 uword n_bytes_to_write, uword flags)
705 uword cur_bi, n_left_b, n_left_o;
707 ASSERT (s->current_buffer_index <= s->n_buffer_bytes);
708 cur_bi = s->current_buffer_index;
709 n_left_b = s->n_buffer_bytes - cur_bi;
710 n_left_o = vec_len (s->overflow_buffer);
712 /* Prepend overflow buffer if present. */
715 if (n_left_o > 0 && n_left_b > 0)
717 uword n = clib_min (n_left_b, n_left_o);
718 clib_memcpy_fast (s->buffer + cur_bi, s->overflow_buffer, n);
723 vec_set_len (s->overflow_buffer, 0);
725 vec_delete (s->overflow_buffer, n, 0);
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
733 s->current_buffer_index = cur_bi;
734 m->data_function (m, s);
735 cur_bi = s->current_buffer_index;
736 n_left_b = s->n_buffer_bytes - cur_bi;
739 while (n_left_o > 0);
741 if (n_left_o > 0 || n_left_b < n_bytes_to_write)
744 s->current_buffer_index = cur_bi;
745 vec_add2 (s->overflow_buffer, r, n_bytes_to_write);
750 s->current_buffer_index = cur_bi + n_bytes_to_write;
751 return s->buffer + cur_bi;
756 serialize_read_not_inline (serialize_main_header_t * m,
757 serialize_stream_t * s,
758 uword n_bytes_to_read, uword flags)
760 uword cur_bi, cur_oi, n_left_b, n_left_o, n_left_to_read;
762 ASSERT (s->current_buffer_index <= s->n_buffer_bytes);
764 cur_bi = s->current_buffer_index;
765 cur_oi = s->current_overflow_index;
767 n_left_b = s->n_buffer_bytes - cur_bi;
768 n_left_o = vec_len (s->overflow_buffer) - cur_oi;
770 /* Read from overflow? */
771 if (n_left_o >= n_bytes_to_read)
773 s->current_overflow_index = cur_oi + n_bytes_to_read;
774 return vec_elt_at_index (s->overflow_buffer, cur_oi);
777 /* Reset overflow buffer. */
778 if (n_left_o == 0 && s->overflow_buffer)
780 s->current_overflow_index = 0;
781 vec_set_len (s->overflow_buffer, 0);
784 n_left_to_read = n_bytes_to_read;
785 while (n_left_to_read > 0)
789 /* If we don't have enough data between overflow and normal buffer
790 call read function. */
791 if (n_left_o + n_left_b < n_bytes_to_read)
793 /* Save any left over buffer in overflow vector. */
796 vec_add (s->overflow_buffer, s->buffer + cur_bi, n_left_b);
797 n_left_o += n_left_b;
798 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 cur_bi = s->n_buffer_bytes;
805 if (m->data_function)
807 m->data_function (m, s);
808 cur_bi = s->current_buffer_index;
809 n_left_b = s->n_buffer_bytes - cur_bi;
813 /* For first time through loop return if we have enough data
814 in normal buffer and overflow vector is empty. */
816 && n_left_to_read == n_bytes_to_read && n_left_b >= n_left_to_read)
818 s->current_buffer_index = cur_bi + n_bytes_to_read;
819 return s->buffer + cur_bi;
822 if (!m->data_function || serialize_stream_is_end_of_stream (s))
824 /* This can happen for a peek at end of file.
825 Pad overflow buffer with 0s. */
826 vec_resize (s->overflow_buffer, n_left_to_read);
827 n_left_o += n_left_to_read;
832 /* Copy from buffer to overflow vector. */
833 n = clib_min (n_left_to_read, n_left_b);
834 vec_add (s->overflow_buffer, s->buffer + cur_bi, n);
842 s->current_buffer_index = cur_bi;
843 s->current_overflow_index = cur_oi + n_bytes_to_read;
844 return vec_elt_at_index (s->overflow_buffer, cur_oi);
848 serialize_read_write_not_inline (serialize_main_header_t * m,
849 serialize_stream_t * s,
850 uword n_bytes, uword flags)
852 return (((flags & SERIALIZE_FLAG_IS_READ) ? serialize_read_not_inline :
853 serialize_write_not_inline) (m, s, n_bytes, flags));
857 serialize_read_write_close (serialize_main_header_t * m,
858 serialize_stream_t * s, uword flags)
860 if (serialize_stream_is_end_of_stream (s))
863 if (flags & SERIALIZE_FLAG_IS_WRITE)
864 /* "Write" 0 bytes to flush overflow vector. */
865 serialize_write_not_inline (m, s, /* n bytes */ 0, flags);
867 serialize_stream_set_end_of_stream (s);
869 /* Call it one last time to flush buffer and close. */
870 m->data_function (m, s);
872 vec_free (s->overflow_buffer);
876 serialize_close (serialize_main_t * m)
878 serialize_read_write_close (&m->header, &m->stream,
879 SERIALIZE_FLAG_IS_WRITE);
883 unserialize_close (serialize_main_t * m)
885 serialize_read_write_close (&m->header, &m->stream, SERIALIZE_FLAG_IS_READ);
889 serialize_open_data (serialize_main_t * m, u8 * data, uword n_data_bytes)
891 clib_memset (m, 0, sizeof (m[0]));
892 m->stream.buffer = data;
893 m->stream.n_buffer_bytes = n_data_bytes;
897 unserialize_open_data (serialize_main_t * m, u8 * data, uword n_data_bytes)
899 serialize_open_data (m, data, n_data_bytes);
903 serialize_vector_write (serialize_main_header_t * m, serialize_stream_t * s)
905 if (!serialize_stream_is_end_of_stream (s))
907 /* Double buffer size. */
908 uword l = vec_len (s->buffer);
909 vec_resize (s->buffer, l > 0 ? l : 64);
910 s->n_buffer_bytes = vec_len (s->buffer);
915 serialize_open_vector (serialize_main_t * m, u8 * vector)
917 clib_memset (m, 0, sizeof (m[0]));
918 m->header.data_function = serialize_vector_write;
919 m->stream.buffer = vector;
920 m->stream.current_buffer_index = 0;
921 m->stream.n_buffer_bytes = vec_len (vector);
925 serialize_close_vector (serialize_main_t * m)
927 serialize_stream_t *s = &m->stream;
930 serialize_close (m); /* frees overflow buffer */
933 vec_set_len (s->buffer, s->current_buffer_index);
935 clib_memset (m, 0, sizeof (m[0]));
940 serialize_multiple_1 (serialize_main_t *m, void *data, uword data_stride,
945 uword n_left = n_data;
949 p = serialize_get (m, 4 * sizeof (d[0]));
950 p[0] = d[0 * data_stride];
951 p[1] = d[1 * data_stride];
952 p[2] = d[2 * data_stride];
953 p[3] = d[3 * data_stride];
955 d += 4 * data_stride;
960 p = serialize_get (m, n_left * sizeof (p[0]));
965 d += 1 * data_stride;
972 serialize_multiple_2 (serialize_main_t *m, void *data, uword data_stride,
977 uword n_left = n_data;
981 p = serialize_get (m, 4 * sizeof (p[0]));
982 clib_mem_unaligned (p + 0, u16) =
983 clib_host_to_net_mem_u16 (d + 0 * data_stride);
984 clib_mem_unaligned (p + 1, u16) =
985 clib_host_to_net_mem_u16 (d + 1 * data_stride);
986 clib_mem_unaligned (p + 2, u16) =
987 clib_host_to_net_mem_u16 (d + 2 * data_stride);
988 clib_mem_unaligned (p + 3, u16) =
989 clib_host_to_net_mem_u16 (d + 3 * data_stride);
991 d += 4 * data_stride;
996 p = serialize_get (m, n_left * sizeof (p[0]));
999 clib_mem_unaligned (p + 0, u16) =
1000 clib_host_to_net_mem_u16 (d + 0 * data_stride);
1002 d += 1 * data_stride;
1009 serialize_multiple_4 (serialize_main_t *m, void *data, uword data_stride,
1014 uword n_left = n_data;
1018 p = serialize_get (m, 4 * sizeof (p[0]));
1019 clib_mem_unaligned (p + 0, u32) =
1020 clib_host_to_net_mem_u32 (d + 0 * data_stride);
1021 clib_mem_unaligned (p + 1, u32) =
1022 clib_host_to_net_mem_u32 (d + 1 * data_stride);
1023 clib_mem_unaligned (p + 2, u32) =
1024 clib_host_to_net_mem_u32 (d + 2 * data_stride);
1025 clib_mem_unaligned (p + 3, u32) =
1026 clib_host_to_net_mem_u32 (d + 3 * data_stride);
1028 d += 4 * data_stride;
1033 p = serialize_get (m, n_left * sizeof (p[0]));
1036 clib_mem_unaligned (p + 0, u32) =
1037 clib_host_to_net_mem_u32 (d + 0 * data_stride);
1039 d += 1 * data_stride;
1046 unserialize_multiple_1 (serialize_main_t *m, void *data, uword data_stride,
1051 uword n_left = n_data;
1055 p = unserialize_get (m, 4 * sizeof (d[0]));
1056 d[0 * data_stride] = p[0];
1057 d[1 * data_stride] = p[1];
1058 d[2 * data_stride] = p[2];
1059 d[3 * data_stride] = p[3];
1061 d += 4 * data_stride;
1066 p = unserialize_get (m, n_left * sizeof (p[0]));
1071 d += 1 * data_stride;
1078 unserialize_multiple_2 (serialize_main_t *m, void *data, uword data_stride,
1083 uword n_left = n_data;
1087 p = unserialize_get (m, 4 * sizeof (p[0]));
1088 clib_mem_unaligned (d + 0 * data_stride, u16) =
1089 clib_net_to_host_mem_u16 (p + 0);
1090 clib_mem_unaligned (d + 1 * data_stride, u16) =
1091 clib_net_to_host_mem_u16 (p + 1);
1092 clib_mem_unaligned (d + 2 * data_stride, u16) =
1093 clib_net_to_host_mem_u16 (p + 2);
1094 clib_mem_unaligned (d + 3 * data_stride, u16) =
1095 clib_net_to_host_mem_u16 (p + 3);
1097 d += 4 * data_stride;
1102 p = unserialize_get (m, n_left * sizeof (p[0]));
1105 clib_mem_unaligned (d + 0 * data_stride, u16) =
1106 clib_net_to_host_mem_u16 (p + 0);
1108 d += 1 * data_stride;
1115 unserialize_multiple_4 (serialize_main_t *m, void *data, uword data_stride,
1120 uword n_left = n_data;
1124 p = unserialize_get (m, 4 * sizeof (p[0]));
1125 clib_mem_unaligned (d + 0 * data_stride, u32) =
1126 clib_net_to_host_mem_u32 (p + 0);
1127 clib_mem_unaligned (d + 1 * data_stride, u32) =
1128 clib_net_to_host_mem_u32 (p + 1);
1129 clib_mem_unaligned (d + 2 * data_stride, u32) =
1130 clib_net_to_host_mem_u32 (p + 2);
1131 clib_mem_unaligned (d + 3 * data_stride, u32) =
1132 clib_net_to_host_mem_u32 (p + 3);
1134 d += 4 * data_stride;
1139 p = unserialize_get (m, n_left * sizeof (p[0]));
1142 clib_mem_unaligned (d + 0 * data_stride, u32) =
1143 clib_net_to_host_mem_u32 (p + 0);
1145 d += 1 * data_stride;
1157 clib_file_write (serialize_main_header_t * m, serialize_stream_t * s)
1161 fd = s->data_function_opaque;
1162 n = write (fd, s->buffer, s->current_buffer_index);
1165 if (!unix_error_is_fatal (errno))
1168 serialize_error (m, clib_error_return_unix (0, "write"));
1170 if (n == s->current_buffer_index)
1171 vec_set_len (s->buffer, 0);
1173 vec_delete (s->buffer, n, 0);
1174 s->current_buffer_index = vec_len (s->buffer);
1178 clib_file_read (serialize_main_header_t * m, serialize_stream_t * s)
1182 fd = s->data_function_opaque;
1183 n = read (fd, s->buffer, vec_len (s->buffer));
1186 if (!unix_error_is_fatal (errno))
1189 serialize_error (m, clib_error_return_unix (0, "read"));
1192 serialize_stream_set_end_of_stream (s);
1193 s->current_buffer_index = 0;
1194 s->n_buffer_bytes = n;
1198 serialize_open_clib_file_descriptor_helper (serialize_main_t * m, int fd,
1201 clib_memset (m, 0, sizeof (m[0]));
1202 vec_resize (m->stream.buffer, 4096);
1206 m->stream.n_buffer_bytes = vec_len (m->stream.buffer);
1207 vec_set_len (m->stream.buffer, 0);
1210 m->header.data_function = is_read ? clib_file_read : clib_file_write;
1211 m->stream.data_function_opaque = fd;
1215 serialize_open_clib_file_descriptor (serialize_main_t * m, int fd)
1217 serialize_open_clib_file_descriptor_helper (m, fd, /* is_read */ 0);
1221 unserialize_open_clib_file_descriptor (serialize_main_t * m, int fd)
1223 serialize_open_clib_file_descriptor_helper (m, fd, /* is_read */ 1);
1226 static clib_error_t *
1227 serialize_open_clib_file_helper (serialize_main_t * m, char *file,
1232 mode = is_read ? O_RDONLY : O_RDWR | O_CREAT | O_TRUNC;
1233 fd = open (file, mode, 0666);
1235 return clib_error_return_unix (0, "open `%s'", file);
1237 serialize_open_clib_file_descriptor_helper (m, fd, is_read);
1241 __clib_export clib_error_t *
1242 serialize_open_clib_file (serialize_main_t * m, char *file)
1244 return serialize_open_clib_file_helper (m, file, /* is_read */ 0);
1247 __clib_export clib_error_t *
1248 unserialize_open_clib_file (serialize_main_t * m, char *file)
1250 return serialize_open_clib_file_helper (m, file, /* is_read */ 1);
1253 #endif /* CLIB_UNIX */
1256 * fd.io coding-style-patch-verification: ON
1259 * eval: (c-set-style "gnu")