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)
312 unserialize_integer (m, &l, sizeof (l));
314 serialize_error (&m->header,
315 clib_error_create ("bad vector length %d", l));
316 p = v = _vec_resize ((void *) 0, l, (uword) l * elt_bytes, header_bytes,
321 u32 n = clib_min (SERIALIZE_VECTOR_CHUNK_SIZE, l);
322 unserialize (m, f, p, n);
324 p += SERIALIZE_VECTOR_CHUNK_SIZE * elt_bytes;
330 unserialize_aligned_vector (serialize_main_t * m, va_list * va)
332 void **vec = va_arg (*va, void **);
333 u32 elt_bytes = va_arg (*va, u32);
334 serialize_function_t *f = va_arg (*va, serialize_function_t *);
335 u32 align = va_arg (*va, u32);
337 *vec = unserialize_vector_ha (m, elt_bytes,
338 /* header_bytes */ 0,
345 unserialize_vector (serialize_main_t * m, va_list * va)
347 void **vec = va_arg (*va, void **);
348 u32 elt_bytes = va_arg (*va, u32);
349 serialize_function_t *f = va_arg (*va, serialize_function_t *);
351 *vec = unserialize_vector_ha (m, elt_bytes,
352 /* header_bytes */ 0,
359 serialize_bitmap (serialize_main_t * m, uword * b)
364 n_u32s = l * sizeof (b[0]) / sizeof (u32);
365 serialize_integer (m, n_u32s, sizeof (n_u32s));
367 /* Send 32 bit words, low-order word first on 64 bit. */
368 for (i = 0; i < l; i++)
370 serialize_integer (m, b[i], sizeof (u32));
371 if (BITS (uword) == 64)
372 serialize_integer (m, (u64) b[i] >> (u64) 32, sizeof (u32));
377 unserialize_bitmap (serialize_main_t * m)
382 unserialize_integer (m, &n_u32s, sizeof (n_u32s));
386 i = (n_u32s * sizeof (u32) + sizeof (b[0]) - 1) / sizeof (b[0]);
388 for (i = 0; i < n_u32s; i++)
391 unserialize_integer (m, &data, sizeof (u32));
393 /* Low-word is first on 64 bit. */
394 if (BITS (uword) == 64)
397 b[i / 2] |= (u64) data << (u64) 0;
399 b[i / 2] |= (u64) data << (u64) 32;
411 serialize_pool (serialize_main_t * m, va_list * va)
413 void *pool = va_arg (*va, void *);
414 u32 elt_bytes = va_arg (*va, u32);
415 serialize_function_t *f = va_arg (*va, serialize_function_t *);
420 serialize_integer (m, l, sizeof (u32));
423 p = pool_header (pool);
425 /* No need to send free bitmap. Need to send index vector
426 to guarantee that unserialized pool will be identical. */
427 vec_serialize (m, p->free_indices, serialize_vec_32);
429 pool_foreach_region (lo, hi, pool,
430 serialize (m, f, pool + lo * elt_bytes, hi - lo));
434 unserialize_pool_helper (serialize_main_t * m,
435 u32 elt_bytes, u32 align, serialize_function_t * f)
441 unserialize_integer (m, &l, sizeof (l));
447 v = _vec_resize ((void *) 0, l, (uword) l * elt_bytes, sizeof (p[0]),
451 vec_unserialize (m, &p->free_indices, unserialize_vec_32);
453 /* Construct free bitmap. */
455 for (i = 0; i < vec_len (p->free_indices); i++)
456 p->free_bitmap = clib_bitmap_ori (p->free_bitmap, p->free_indices[i]);
458 pool_foreach_region (lo, hi, v,
459 unserialize (m, f, v + lo * elt_bytes, hi - lo));
465 unserialize_pool (serialize_main_t * m, va_list * va)
467 void **result = va_arg (*va, void **);
468 u32 elt_bytes = va_arg (*va, u32);
469 serialize_function_t *f = va_arg (*va, serialize_function_t *);
470 *result = unserialize_pool_helper (m, elt_bytes, /* align */ 0, f);
474 unserialize_aligned_pool (serialize_main_t * m, va_list * va)
476 void **result = va_arg (*va, void **);
477 u32 elt_bytes = va_arg (*va, u32);
478 u32 align = va_arg (*va, u32);
479 serialize_function_t *f = va_arg (*va, serialize_function_t *);
480 *result = unserialize_pool_helper (m, elt_bytes, align, f);
484 serialize_vec_heap_elt (serialize_main_t * m, va_list * va)
486 heap_elt_t *e = va_arg (*va, heap_elt_t *);
487 u32 i, n = va_arg (*va, u32);
488 for (i = 0; i < n; i++)
490 serialize_integer (m, e[i].offset, sizeof (e[i].offset));
491 serialize_integer (m, e[i].next, sizeof (e[i].next));
492 serialize_integer (m, e[i].prev, sizeof (e[i].prev));
497 unserialize_vec_heap_elt (serialize_main_t * m, va_list * va)
499 heap_elt_t *e = va_arg (*va, heap_elt_t *);
500 u32 i, n = va_arg (*va, u32);
501 for (i = 0; i < n; i++)
503 unserialize_integer (m, &e[i].offset, sizeof (e[i].offset));
504 unserialize_integer (m, &e[i].next, sizeof (e[i].next));
505 unserialize_integer (m, &e[i].prev, sizeof (e[i].prev));
510 serialize_heap (serialize_main_t * m, va_list * va)
512 void *heap = va_arg (*va, void *);
513 serialize_function_t *f = va_arg (*va, serialize_function_t *);
518 serialize_integer (m, l, sizeof (u32));
522 h = heap_header (heap);
524 #define foreach_serialize_heap_header_integer \
525 _ (head) _ (tail) _ (used_count) _ (max_len) _ (flags) _ (elt_bytes)
527 #define _(f) serialize_integer (m, h->f, sizeof (h->f));
528 foreach_serialize_heap_header_integer;
531 serialize_integer (m, vec_len (h->free_lists), sizeof (u32));
532 for (i = 0; i < vec_len (h->free_lists); i++)
533 vec_serialize (m, h->free_lists[i], serialize_vec_32);
535 vec_serialize (m, h->elts, serialize_vec_heap_elt);
536 vec_serialize (m, h->small_free_elt_free_index, serialize_vec_32);
537 vec_serialize (m, h->free_elts, serialize_vec_32);
539 /* Serialize data in heap. */
542 e = h->elts + h->head;
543 end = h->elts + h->tail;
546 if (!heap_is_free (e))
548 void *v = heap + heap_offset (e) * h->elt_bytes;
549 u32 n = heap_elt_size (heap, e);
550 serialize (m, f, v, n);
560 unserialize_heap (serialize_main_t * m, va_list * va)
562 void **result = va_arg (*va, void **);
563 serialize_function_t *f = va_arg (*va, serialize_function_t *);
568 unserialize_integer (m, &vl, sizeof (u32));
575 clib_memset (&h, 0, sizeof (h));
576 #define _(f) unserialize_integer (m, &h.f, sizeof (h.f));
577 foreach_serialize_heap_header_integer;
580 unserialize_integer (m, &fl, sizeof (u32));
581 vec_resize (h.free_lists, fl);
583 for (i = 0; i < vec_len (h.free_lists); i++)
584 vec_unserialize (m, &h.free_lists[i], unserialize_vec_32);
586 vec_unserialize (m, &h.elts, unserialize_vec_heap_elt);
587 vec_unserialize (m, &h.small_free_elt_free_index, unserialize_vec_32);
588 vec_unserialize (m, &h.free_elts, unserialize_vec_32);
590 /* Re-construct used elt bitmap. */
594 vec_foreach (e, h.elts)
596 if (!heap_is_free (e))
597 h.used_elt_bitmap = clib_bitmap_ori (h.used_elt_bitmap, e - h.elts);
601 heap = *result = _heap_new (vl, h.elt_bytes);
602 heap_header (heap)[0] = h;
604 /* Unserialize data in heap. */
608 end = h.elts + h.tail;
611 if (!heap_is_free (e))
613 void *v = heap + heap_offset (e) * h.elt_bytes;
614 u32 n = heap_elt_size (heap, e);
615 unserialize (m, f, v, n);
625 serialize_magic (serialize_main_t * m, void *magic, u32 magic_bytes)
628 serialize_integer (m, magic_bytes, sizeof (magic_bytes));
629 p = serialize_get (m, magic_bytes);
630 clib_memcpy_fast (p, magic, magic_bytes);
634 unserialize_check_magic (serialize_main_t * m, void *magic, u32 magic_bytes)
639 unserialize_integer (m, &l, sizeof (l));
640 if (l != magic_bytes)
643 serialize_error_return (m, "bad magic number");
645 d = serialize_get (m, magic_bytes);
646 if (memcmp (magic, d, magic_bytes))
651 va_serialize (serialize_main_t * sm, va_list * va)
653 serialize_main_header_t *m = &sm->header;
654 serialize_function_t *f = va_arg (*va, serialize_function_t *);
655 clib_error_t *error = 0;
657 m->recursion_level += 1;
658 if (m->recursion_level == 1)
660 uword r = clib_setjmp (&m->error_longjmp, 0);
661 error = uword_to_pointer (r, clib_error_t *);
667 m->recursion_level -= 1;
672 serialize (serialize_main_t * m, ...)
678 error = va_serialize (m, &va);
684 unserialize (serialize_main_t * m, ...)
690 error = va_serialize (m, &va);
696 serialize_write_not_inline (serialize_main_header_t * m,
697 serialize_stream_t * s,
698 uword n_bytes_to_write, uword flags)
700 uword cur_bi, n_left_b, n_left_o;
702 ASSERT (s->current_buffer_index <= s->n_buffer_bytes);
703 cur_bi = s->current_buffer_index;
704 n_left_b = s->n_buffer_bytes - cur_bi;
705 n_left_o = vec_len (s->overflow_buffer);
707 /* Prepend overflow buffer if present. */
710 if (n_left_o > 0 && n_left_b > 0)
712 uword n = clib_min (n_left_b, n_left_o);
713 clib_memcpy_fast (s->buffer + cur_bi, s->overflow_buffer, n);
718 _vec_len (s->overflow_buffer) = 0;
720 vec_delete (s->overflow_buffer, n, 0);
723 /* Call data function when buffer is complete. Data function should
724 dispatch with current buffer and give us a new one to write more
728 s->current_buffer_index = cur_bi;
729 m->data_function (m, s);
730 cur_bi = s->current_buffer_index;
731 n_left_b = s->n_buffer_bytes - cur_bi;
734 while (n_left_o > 0);
736 if (n_left_o > 0 || n_left_b < n_bytes_to_write)
739 vec_add2 (s->overflow_buffer, r, n_bytes_to_write);
744 s->current_buffer_index = cur_bi + n_bytes_to_write;
745 return s->buffer + cur_bi;
750 serialize_read_not_inline (serialize_main_header_t * m,
751 serialize_stream_t * s,
752 uword n_bytes_to_read, uword flags)
754 uword cur_bi, cur_oi, n_left_b, n_left_o, n_left_to_read;
756 ASSERT (s->current_buffer_index <= s->n_buffer_bytes);
758 cur_bi = s->current_buffer_index;
759 cur_oi = s->current_overflow_index;
761 n_left_b = s->n_buffer_bytes - cur_bi;
762 n_left_o = vec_len (s->overflow_buffer) - cur_oi;
764 /* Read from overflow? */
765 if (n_left_o >= n_bytes_to_read)
767 s->current_overflow_index = cur_oi + n_bytes_to_read;
768 return vec_elt_at_index (s->overflow_buffer, cur_oi);
771 /* Reset overflow buffer. */
772 if (n_left_o == 0 && s->overflow_buffer)
774 s->current_overflow_index = 0;
775 _vec_len (s->overflow_buffer) = 0;
778 n_left_to_read = n_bytes_to_read;
779 while (n_left_to_read > 0)
783 /* If we don't have enough data between overflow and normal buffer
784 call read function. */
785 if (n_left_o + n_left_b < n_bytes_to_read)
787 /* Save any left over buffer in overflow vector. */
790 vec_add (s->overflow_buffer, s->buffer + cur_bi, n_left_b);
791 n_left_o += n_left_b;
792 n_left_to_read -= n_left_b;
793 /* Advance buffer to end --- even if
794 SERIALIZE_FLAG_NO_ADVANCE_CURRENT_BUFFER_INDEX is set. */
795 cur_bi = s->n_buffer_bytes;
799 if (m->data_function)
801 m->data_function (m, s);
802 cur_bi = s->current_buffer_index;
803 n_left_b = s->n_buffer_bytes - cur_bi;
807 /* For first time through loop return if we have enough data
808 in normal buffer and overflow vector is empty. */
810 && n_left_to_read == n_bytes_to_read && n_left_b >= n_left_to_read)
812 s->current_buffer_index = cur_bi + n_bytes_to_read;
813 return s->buffer + cur_bi;
816 if (!m->data_function || serialize_stream_is_end_of_stream (s))
818 /* This can happen for a peek at end of file.
819 Pad overflow buffer with 0s. */
820 vec_resize (s->overflow_buffer, n_left_to_read);
821 n_left_o += n_left_to_read;
826 /* Copy from buffer to overflow vector. */
827 n = clib_min (n_left_to_read, n_left_b);
828 vec_add (s->overflow_buffer, s->buffer + cur_bi, n);
836 s->current_buffer_index = cur_bi;
837 s->current_overflow_index = cur_oi + n_bytes_to_read;
838 return vec_elt_at_index (s->overflow_buffer, cur_oi);
842 serialize_read_write_not_inline (serialize_main_header_t * m,
843 serialize_stream_t * s,
844 uword n_bytes, uword flags)
846 return (((flags & SERIALIZE_FLAG_IS_READ) ? serialize_read_not_inline :
847 serialize_write_not_inline) (m, s, n_bytes, flags));
851 serialize_read_write_close (serialize_main_header_t * m,
852 serialize_stream_t * s, uword flags)
854 if (serialize_stream_is_end_of_stream (s))
857 if (flags & SERIALIZE_FLAG_IS_WRITE)
858 /* "Write" 0 bytes to flush overflow vector. */
859 serialize_write_not_inline (m, s, /* n bytes */ 0, flags);
861 serialize_stream_set_end_of_stream (s);
863 /* Call it one last time to flush buffer and close. */
864 m->data_function (m, s);
866 vec_free (s->overflow_buffer);
870 serialize_close (serialize_main_t * m)
872 serialize_read_write_close (&m->header, &m->stream,
873 SERIALIZE_FLAG_IS_WRITE);
877 unserialize_close (serialize_main_t * m)
879 serialize_read_write_close (&m->header, &m->stream, SERIALIZE_FLAG_IS_READ);
883 serialize_open_data (serialize_main_t * m, u8 * data, uword n_data_bytes)
885 clib_memset (m, 0, sizeof (m[0]));
886 m->stream.buffer = data;
887 m->stream.n_buffer_bytes = n_data_bytes;
891 unserialize_open_data (serialize_main_t * m, u8 * data, uword n_data_bytes)
893 serialize_open_data (m, data, n_data_bytes);
897 serialize_vector_write (serialize_main_header_t * m, serialize_stream_t * s)
899 if (!serialize_stream_is_end_of_stream (s))
901 /* Double buffer size. */
902 uword l = vec_len (s->buffer);
903 vec_resize (s->buffer, l > 0 ? l : 64);
904 s->n_buffer_bytes = vec_len (s->buffer);
909 serialize_open_vector (serialize_main_t * m, u8 * vector)
911 clib_memset (m, 0, sizeof (m[0]));
912 m->header.data_function = serialize_vector_write;
913 m->stream.buffer = vector;
914 m->stream.current_buffer_index = 0;
915 m->stream.n_buffer_bytes = vec_len (vector);
919 serialize_close_vector (serialize_main_t * m)
921 serialize_stream_t *s = &m->stream;
924 serialize_close (m); /* frees overflow buffer */
927 _vec_len (s->buffer) = s->current_buffer_index;
929 clib_memset (m, 0, sizeof (m[0]));
934 serialize_multiple_1 (serialize_main_t * m,
935 void *data, uword data_stride, uword n_data)
939 uword n_left = n_data;
943 p = serialize_get (m, 4 * sizeof (d[0]));
944 p[0] = d[0 * data_stride];
945 p[1] = d[1 * data_stride];
946 p[2] = d[2 * data_stride];
947 p[3] = d[3 * data_stride];
949 d += 4 * data_stride;
954 p = serialize_get (m, n_left * sizeof (p[0]));
959 d += 1 * data_stride;
966 serialize_multiple_2 (serialize_main_t * m,
967 void *data, uword data_stride, uword n_data)
971 uword n_left = n_data;
975 p = serialize_get (m, 4 * sizeof (p[0]));
976 clib_mem_unaligned (p + 0, u16) =
977 clib_host_to_net_mem_u16 (d + 0 * data_stride);
978 clib_mem_unaligned (p + 1, u16) =
979 clib_host_to_net_mem_u16 (d + 1 * data_stride);
980 clib_mem_unaligned (p + 2, u16) =
981 clib_host_to_net_mem_u16 (d + 2 * data_stride);
982 clib_mem_unaligned (p + 3, u16) =
983 clib_host_to_net_mem_u16 (d + 3 * data_stride);
985 d += 4 * data_stride;
990 p = serialize_get (m, n_left * sizeof (p[0]));
993 clib_mem_unaligned (p + 0, u16) =
994 clib_host_to_net_mem_u16 (d + 0 * data_stride);
996 d += 1 * data_stride;
1003 serialize_multiple_4 (serialize_main_t * m,
1004 void *data, uword data_stride, uword n_data)
1008 uword n_left = n_data;
1012 p = serialize_get (m, 4 * sizeof (p[0]));
1013 clib_mem_unaligned (p + 0, u32) =
1014 clib_host_to_net_mem_u32 (d + 0 * data_stride);
1015 clib_mem_unaligned (p + 1, u32) =
1016 clib_host_to_net_mem_u32 (d + 1 * data_stride);
1017 clib_mem_unaligned (p + 2, u32) =
1018 clib_host_to_net_mem_u32 (d + 2 * data_stride);
1019 clib_mem_unaligned (p + 3, u32) =
1020 clib_host_to_net_mem_u32 (d + 3 * data_stride);
1022 d += 4 * data_stride;
1027 p = serialize_get (m, n_left * sizeof (p[0]));
1030 clib_mem_unaligned (p + 0, u32) =
1031 clib_host_to_net_mem_u32 (d + 0 * data_stride);
1033 d += 1 * data_stride;
1040 unserialize_multiple_1 (serialize_main_t * m,
1041 void *data, uword data_stride, uword n_data)
1045 uword n_left = n_data;
1049 p = unserialize_get (m, 4 * sizeof (d[0]));
1050 d[0 * data_stride] = p[0];
1051 d[1 * data_stride] = p[1];
1052 d[2 * data_stride] = p[2];
1053 d[3 * data_stride] = p[3];
1055 d += 4 * data_stride;
1060 p = unserialize_get (m, n_left * sizeof (p[0]));
1065 d += 1 * data_stride;
1072 unserialize_multiple_2 (serialize_main_t * m,
1073 void *data, uword data_stride, uword n_data)
1077 uword n_left = n_data;
1081 p = unserialize_get (m, 4 * sizeof (p[0]));
1082 clib_mem_unaligned (d + 0 * data_stride, u16) =
1083 clib_net_to_host_mem_u16 (p + 0);
1084 clib_mem_unaligned (d + 1 * data_stride, u16) =
1085 clib_net_to_host_mem_u16 (p + 1);
1086 clib_mem_unaligned (d + 2 * data_stride, u16) =
1087 clib_net_to_host_mem_u16 (p + 2);
1088 clib_mem_unaligned (d + 3 * data_stride, u16) =
1089 clib_net_to_host_mem_u16 (p + 3);
1091 d += 4 * data_stride;
1096 p = unserialize_get (m, n_left * sizeof (p[0]));
1099 clib_mem_unaligned (d + 0 * data_stride, u16) =
1100 clib_net_to_host_mem_u16 (p + 0);
1102 d += 1 * data_stride;
1109 unserialize_multiple_4 (serialize_main_t * m,
1110 void *data, uword data_stride, uword n_data)
1114 uword n_left = n_data;
1118 p = unserialize_get (m, 4 * sizeof (p[0]));
1119 clib_mem_unaligned (d + 0 * data_stride, u32) =
1120 clib_net_to_host_mem_u32 (p + 0);
1121 clib_mem_unaligned (d + 1 * data_stride, u32) =
1122 clib_net_to_host_mem_u32 (p + 1);
1123 clib_mem_unaligned (d + 2 * data_stride, u32) =
1124 clib_net_to_host_mem_u32 (p + 2);
1125 clib_mem_unaligned (d + 3 * data_stride, u32) =
1126 clib_net_to_host_mem_u32 (p + 3);
1128 d += 4 * data_stride;
1133 p = unserialize_get (m, n_left * sizeof (p[0]));
1136 clib_mem_unaligned (d + 0 * data_stride, u32) =
1137 clib_net_to_host_mem_u32 (p + 0);
1139 d += 1 * data_stride;
1151 clib_file_write (serialize_main_header_t * m, serialize_stream_t * s)
1155 fd = s->data_function_opaque;
1156 n = write (fd, s->buffer, s->current_buffer_index);
1159 if (!unix_error_is_fatal (errno))
1162 serialize_error (m, clib_error_return_unix (0, "write"));
1164 if (n == s->current_buffer_index)
1165 _vec_len (s->buffer) = 0;
1167 vec_delete (s->buffer, n, 0);
1168 s->current_buffer_index = vec_len (s->buffer);
1172 clib_file_read (serialize_main_header_t * m, serialize_stream_t * s)
1176 fd = s->data_function_opaque;
1177 n = read (fd, s->buffer, vec_len (s->buffer));
1180 if (!unix_error_is_fatal (errno))
1183 serialize_error (m, clib_error_return_unix (0, "read"));
1186 serialize_stream_set_end_of_stream (s);
1187 s->current_buffer_index = 0;
1188 s->n_buffer_bytes = n;
1192 serialize_open_clib_file_descriptor_helper (serialize_main_t * m, int fd,
1195 clib_memset (m, 0, sizeof (m[0]));
1196 vec_resize (m->stream.buffer, 4096);
1200 m->stream.n_buffer_bytes = vec_len (m->stream.buffer);
1201 _vec_len (m->stream.buffer) = 0;
1204 m->header.data_function = is_read ? clib_file_read : clib_file_write;
1205 m->stream.data_function_opaque = fd;
1209 serialize_open_clib_file_descriptor (serialize_main_t * m, int fd)
1211 serialize_open_clib_file_descriptor_helper (m, fd, /* is_read */ 0);
1215 unserialize_open_clib_file_descriptor (serialize_main_t * m, int fd)
1217 serialize_open_clib_file_descriptor_helper (m, fd, /* is_read */ 1);
1220 static clib_error_t *
1221 serialize_open_clib_file_helper (serialize_main_t * m, char *file,
1226 mode = is_read ? O_RDONLY : O_RDWR | O_CREAT | O_TRUNC;
1227 fd = open (file, mode, 0666);
1229 return clib_error_return_unix (0, "open `%s'", file);
1231 serialize_open_clib_file_descriptor_helper (m, fd, is_read);
1236 serialize_open_clib_file (serialize_main_t * m, char *file)
1238 return serialize_open_clib_file_helper (m, file, /* is_read */ 0);
1242 unserialize_open_clib_file (serialize_main_t * m, char *file)
1244 return serialize_open_clib_file_helper (m, file, /* is_read */ 1);
1247 #endif /* CLIB_UNIX */
1250 * fd.io coding-style-patch-verification: ON
1253 * eval: (c-set-style "gnu")