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 vec_add2 (s->overflow_buffer, r, n_bytes_to_write);
749 s->current_buffer_index = cur_bi + n_bytes_to_write;
750 return s->buffer + cur_bi;
755 serialize_read_not_inline (serialize_main_header_t * m,
756 serialize_stream_t * s,
757 uword n_bytes_to_read, uword flags)
759 uword cur_bi, cur_oi, n_left_b, n_left_o, n_left_to_read;
761 ASSERT (s->current_buffer_index <= s->n_buffer_bytes);
763 cur_bi = s->current_buffer_index;
764 cur_oi = s->current_overflow_index;
766 n_left_b = s->n_buffer_bytes - cur_bi;
767 n_left_o = vec_len (s->overflow_buffer) - cur_oi;
769 /* Read from overflow? */
770 if (n_left_o >= n_bytes_to_read)
772 s->current_overflow_index = cur_oi + n_bytes_to_read;
773 return vec_elt_at_index (s->overflow_buffer, cur_oi);
776 /* Reset overflow buffer. */
777 if (n_left_o == 0 && s->overflow_buffer)
779 s->current_overflow_index = 0;
780 vec_set_len (s->overflow_buffer, 0);
783 n_left_to_read = n_bytes_to_read;
784 while (n_left_to_read > 0)
788 /* If we don't have enough data between overflow and normal buffer
789 call read function. */
790 if (n_left_o + n_left_b < n_bytes_to_read)
792 /* Save any left over buffer in overflow vector. */
795 vec_add (s->overflow_buffer, s->buffer + cur_bi, n_left_b);
796 n_left_o += n_left_b;
797 n_left_to_read -= n_left_b;
798 /* Advance buffer to end --- even if
799 SERIALIZE_FLAG_NO_ADVANCE_CURRENT_BUFFER_INDEX is set. */
800 cur_bi = s->n_buffer_bytes;
804 if (m->data_function)
806 m->data_function (m, s);
807 cur_bi = s->current_buffer_index;
808 n_left_b = s->n_buffer_bytes - cur_bi;
812 /* For first time through loop return if we have enough data
813 in normal buffer and overflow vector is empty. */
815 && n_left_to_read == n_bytes_to_read && n_left_b >= n_left_to_read)
817 s->current_buffer_index = cur_bi + n_bytes_to_read;
818 return s->buffer + cur_bi;
821 if (!m->data_function || serialize_stream_is_end_of_stream (s))
823 /* This can happen for a peek at end of file.
824 Pad overflow buffer with 0s. */
825 vec_resize (s->overflow_buffer, n_left_to_read);
826 n_left_o += n_left_to_read;
831 /* Copy from buffer to overflow vector. */
832 n = clib_min (n_left_to_read, n_left_b);
833 vec_add (s->overflow_buffer, s->buffer + cur_bi, n);
841 s->current_buffer_index = cur_bi;
842 s->current_overflow_index = cur_oi + n_bytes_to_read;
843 return vec_elt_at_index (s->overflow_buffer, cur_oi);
847 serialize_read_write_not_inline (serialize_main_header_t * m,
848 serialize_stream_t * s,
849 uword n_bytes, uword flags)
851 return (((flags & SERIALIZE_FLAG_IS_READ) ? serialize_read_not_inline :
852 serialize_write_not_inline) (m, s, n_bytes, flags));
856 serialize_read_write_close (serialize_main_header_t * m,
857 serialize_stream_t * s, uword flags)
859 if (serialize_stream_is_end_of_stream (s))
862 if (flags & SERIALIZE_FLAG_IS_WRITE)
863 /* "Write" 0 bytes to flush overflow vector. */
864 serialize_write_not_inline (m, s, /* n bytes */ 0, flags);
866 serialize_stream_set_end_of_stream (s);
868 /* Call it one last time to flush buffer and close. */
869 m->data_function (m, s);
871 vec_free (s->overflow_buffer);
875 serialize_close (serialize_main_t * m)
877 serialize_read_write_close (&m->header, &m->stream,
878 SERIALIZE_FLAG_IS_WRITE);
882 unserialize_close (serialize_main_t * m)
884 serialize_read_write_close (&m->header, &m->stream, SERIALIZE_FLAG_IS_READ);
888 serialize_open_data (serialize_main_t * m, u8 * data, uword n_data_bytes)
890 clib_memset (m, 0, sizeof (m[0]));
891 m->stream.buffer = data;
892 m->stream.n_buffer_bytes = n_data_bytes;
896 unserialize_open_data (serialize_main_t * m, u8 * data, uword n_data_bytes)
898 serialize_open_data (m, data, n_data_bytes);
902 serialize_vector_write (serialize_main_header_t * m, serialize_stream_t * s)
904 if (!serialize_stream_is_end_of_stream (s))
906 /* Double buffer size. */
907 uword l = vec_len (s->buffer);
908 vec_resize (s->buffer, l > 0 ? l : 64);
909 s->n_buffer_bytes = vec_len (s->buffer);
914 serialize_open_vector (serialize_main_t * m, u8 * vector)
916 clib_memset (m, 0, sizeof (m[0]));
917 m->header.data_function = serialize_vector_write;
918 m->stream.buffer = vector;
919 m->stream.current_buffer_index = 0;
920 m->stream.n_buffer_bytes = vec_len (vector);
924 serialize_close_vector (serialize_main_t * m)
926 serialize_stream_t *s = &m->stream;
929 serialize_close (m); /* frees overflow buffer */
932 vec_set_len (s->buffer, s->current_buffer_index);
934 clib_memset (m, 0, sizeof (m[0]));
939 serialize_multiple_1 (serialize_main_t *m, void *data, uword data_stride,
944 uword n_left = n_data;
948 p = serialize_get (m, 4 * sizeof (d[0]));
949 p[0] = d[0 * data_stride];
950 p[1] = d[1 * data_stride];
951 p[2] = d[2 * data_stride];
952 p[3] = d[3 * data_stride];
954 d += 4 * data_stride;
959 p = serialize_get (m, n_left * sizeof (p[0]));
964 d += 1 * data_stride;
971 serialize_multiple_2 (serialize_main_t *m, void *data, uword data_stride,
976 uword n_left = n_data;
980 p = serialize_get (m, 4 * sizeof (p[0]));
981 clib_mem_unaligned (p + 0, u16) =
982 clib_host_to_net_mem_u16 (d + 0 * data_stride);
983 clib_mem_unaligned (p + 1, u16) =
984 clib_host_to_net_mem_u16 (d + 1 * data_stride);
985 clib_mem_unaligned (p + 2, u16) =
986 clib_host_to_net_mem_u16 (d + 2 * data_stride);
987 clib_mem_unaligned (p + 3, u16) =
988 clib_host_to_net_mem_u16 (d + 3 * data_stride);
990 d += 4 * data_stride;
995 p = serialize_get (m, n_left * sizeof (p[0]));
998 clib_mem_unaligned (p + 0, u16) =
999 clib_host_to_net_mem_u16 (d + 0 * data_stride);
1001 d += 1 * data_stride;
1008 serialize_multiple_4 (serialize_main_t *m, void *data, uword data_stride,
1013 uword n_left = n_data;
1017 p = serialize_get (m, 4 * sizeof (p[0]));
1018 clib_mem_unaligned (p + 0, u32) =
1019 clib_host_to_net_mem_u32 (d + 0 * data_stride);
1020 clib_mem_unaligned (p + 1, u32) =
1021 clib_host_to_net_mem_u32 (d + 1 * data_stride);
1022 clib_mem_unaligned (p + 2, u32) =
1023 clib_host_to_net_mem_u32 (d + 2 * data_stride);
1024 clib_mem_unaligned (p + 3, u32) =
1025 clib_host_to_net_mem_u32 (d + 3 * data_stride);
1027 d += 4 * data_stride;
1032 p = serialize_get (m, n_left * sizeof (p[0]));
1035 clib_mem_unaligned (p + 0, u32) =
1036 clib_host_to_net_mem_u32 (d + 0 * data_stride);
1038 d += 1 * data_stride;
1045 unserialize_multiple_1 (serialize_main_t *m, void *data, uword data_stride,
1050 uword n_left = n_data;
1054 p = unserialize_get (m, 4 * sizeof (d[0]));
1055 d[0 * data_stride] = p[0];
1056 d[1 * data_stride] = p[1];
1057 d[2 * data_stride] = p[2];
1058 d[3 * data_stride] = p[3];
1060 d += 4 * data_stride;
1065 p = unserialize_get (m, n_left * sizeof (p[0]));
1070 d += 1 * data_stride;
1077 unserialize_multiple_2 (serialize_main_t *m, void *data, uword data_stride,
1082 uword n_left = n_data;
1086 p = unserialize_get (m, 4 * sizeof (p[0]));
1087 clib_mem_unaligned (d + 0 * data_stride, u16) =
1088 clib_net_to_host_mem_u16 (p + 0);
1089 clib_mem_unaligned (d + 1 * data_stride, u16) =
1090 clib_net_to_host_mem_u16 (p + 1);
1091 clib_mem_unaligned (d + 2 * data_stride, u16) =
1092 clib_net_to_host_mem_u16 (p + 2);
1093 clib_mem_unaligned (d + 3 * data_stride, u16) =
1094 clib_net_to_host_mem_u16 (p + 3);
1096 d += 4 * data_stride;
1101 p = unserialize_get (m, n_left * sizeof (p[0]));
1104 clib_mem_unaligned (d + 0 * data_stride, u16) =
1105 clib_net_to_host_mem_u16 (p + 0);
1107 d += 1 * data_stride;
1114 unserialize_multiple_4 (serialize_main_t *m, void *data, uword data_stride,
1119 uword n_left = n_data;
1123 p = unserialize_get (m, 4 * sizeof (p[0]));
1124 clib_mem_unaligned (d + 0 * data_stride, u32) =
1125 clib_net_to_host_mem_u32 (p + 0);
1126 clib_mem_unaligned (d + 1 * data_stride, u32) =
1127 clib_net_to_host_mem_u32 (p + 1);
1128 clib_mem_unaligned (d + 2 * data_stride, u32) =
1129 clib_net_to_host_mem_u32 (p + 2);
1130 clib_mem_unaligned (d + 3 * data_stride, u32) =
1131 clib_net_to_host_mem_u32 (p + 3);
1133 d += 4 * data_stride;
1138 p = unserialize_get (m, n_left * sizeof (p[0]));
1141 clib_mem_unaligned (d + 0 * data_stride, u32) =
1142 clib_net_to_host_mem_u32 (p + 0);
1144 d += 1 * data_stride;
1156 clib_file_write (serialize_main_header_t * m, serialize_stream_t * s)
1160 fd = s->data_function_opaque;
1161 n = write (fd, s->buffer, s->current_buffer_index);
1164 if (!unix_error_is_fatal (errno))
1167 serialize_error (m, clib_error_return_unix (0, "write"));
1169 if (n == s->current_buffer_index)
1170 vec_set_len (s->buffer, 0);
1172 vec_delete (s->buffer, n, 0);
1173 s->current_buffer_index = vec_len (s->buffer);
1177 clib_file_read (serialize_main_header_t * m, serialize_stream_t * s)
1181 fd = s->data_function_opaque;
1182 n = read (fd, s->buffer, vec_len (s->buffer));
1185 if (!unix_error_is_fatal (errno))
1188 serialize_error (m, clib_error_return_unix (0, "read"));
1191 serialize_stream_set_end_of_stream (s);
1192 s->current_buffer_index = 0;
1193 s->n_buffer_bytes = n;
1197 serialize_open_clib_file_descriptor_helper (serialize_main_t * m, int fd,
1200 clib_memset (m, 0, sizeof (m[0]));
1201 vec_resize (m->stream.buffer, 4096);
1205 m->stream.n_buffer_bytes = vec_len (m->stream.buffer);
1206 vec_set_len (m->stream.buffer, 0);
1209 m->header.data_function = is_read ? clib_file_read : clib_file_write;
1210 m->stream.data_function_opaque = fd;
1214 serialize_open_clib_file_descriptor (serialize_main_t * m, int fd)
1216 serialize_open_clib_file_descriptor_helper (m, fd, /* is_read */ 0);
1220 unserialize_open_clib_file_descriptor (serialize_main_t * m, int fd)
1222 serialize_open_clib_file_descriptor_helper (m, fd, /* is_read */ 1);
1225 static clib_error_t *
1226 serialize_open_clib_file_helper (serialize_main_t * m, char *file,
1231 mode = is_read ? O_RDONLY : O_RDWR | O_CREAT | O_TRUNC;
1232 fd = open (file, mode, 0666);
1234 return clib_error_return_unix (0, "open `%s'", file);
1236 serialize_open_clib_file_descriptor_helper (m, fd, is_read);
1240 __clib_export clib_error_t *
1241 serialize_open_clib_file (serialize_main_t * m, char *file)
1243 return serialize_open_clib_file_helper (m, file, /* is_read */ 0);
1246 __clib_export clib_error_t *
1247 unserialize_open_clib_file (serialize_main_t * m, char *file)
1249 return serialize_open_clib_file_helper (m, file, /* is_read */ 1);
1252 #endif /* CLIB_UNIX */
1255 * fd.io coding-style-patch-verification: ON
1258 * eval: (c-set-style "gnu")