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 (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 (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 (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 (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 (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 (0, l, (uword) l * elt_bytes, sizeof (p[0]), align);
450 vec_unserialize (m, &p->free_indices, unserialize_vec_32);
452 /* Construct free bitmap. */
454 for (i = 0; i < vec_len (p->free_indices); i++)
455 p->free_bitmap = clib_bitmap_ori (p->free_bitmap, p->free_indices[i]);
457 pool_foreach_region (lo, hi, v,
458 unserialize (m, f, v + lo * elt_bytes, hi - lo));
464 unserialize_pool (serialize_main_t * m, va_list * va)
466 void **result = va_arg (*va, void **);
467 u32 elt_bytes = va_arg (*va, u32);
468 serialize_function_t *f = va_arg (*va, serialize_function_t *);
469 *result = unserialize_pool_helper (m, elt_bytes, /* align */ 0, f);
473 unserialize_aligned_pool (serialize_main_t * m, va_list * va)
475 void **result = va_arg (*va, void **);
476 u32 elt_bytes = va_arg (*va, u32);
477 u32 align = va_arg (*va, u32);
478 serialize_function_t *f = va_arg (*va, serialize_function_t *);
479 *result = unserialize_pool_helper (m, elt_bytes, align, f);
483 serialize_vec_heap_elt (serialize_main_t * m, va_list * va)
485 heap_elt_t *e = va_arg (*va, heap_elt_t *);
486 u32 i, n = va_arg (*va, u32);
487 for (i = 0; i < n; i++)
489 serialize_integer (m, e[i].offset, sizeof (e[i].offset));
490 serialize_integer (m, e[i].next, sizeof (e[i].next));
491 serialize_integer (m, e[i].prev, sizeof (e[i].prev));
496 unserialize_vec_heap_elt (serialize_main_t * m, va_list * va)
498 heap_elt_t *e = va_arg (*va, heap_elt_t *);
499 u32 i, n = va_arg (*va, u32);
500 for (i = 0; i < n; i++)
502 unserialize_integer (m, &e[i].offset, sizeof (e[i].offset));
503 unserialize_integer (m, &e[i].next, sizeof (e[i].next));
504 unserialize_integer (m, &e[i].prev, sizeof (e[i].prev));
509 serialize_heap (serialize_main_t * m, va_list * va)
511 void *heap = va_arg (*va, void *);
512 serialize_function_t *f = va_arg (*va, serialize_function_t *);
517 serialize_integer (m, l, sizeof (u32));
521 h = heap_header (heap);
523 #define foreach_serialize_heap_header_integer \
524 _ (head) _ (tail) _ (used_count) _ (max_len) _ (flags) _ (elt_bytes)
526 #define _(f) serialize_integer (m, h->f, sizeof (h->f));
527 foreach_serialize_heap_header_integer;
530 serialize_integer (m, vec_len (h->free_lists), sizeof (u32));
531 for (i = 0; i < vec_len (h->free_lists); i++)
532 vec_serialize (m, h->free_lists[i], serialize_vec_32);
534 vec_serialize (m, h->elts, serialize_vec_heap_elt);
535 vec_serialize (m, h->small_free_elt_free_index, serialize_vec_32);
536 vec_serialize (m, h->free_elts, serialize_vec_32);
538 /* Serialize data in heap. */
541 e = h->elts + h->head;
542 end = h->elts + h->tail;
545 if (!heap_is_free (e))
547 void *v = heap + heap_offset (e) * h->elt_bytes;
548 u32 n = heap_elt_size (heap, e);
549 serialize (m, f, v, n);
559 unserialize_heap (serialize_main_t * m, va_list * va)
561 void **result = va_arg (*va, void **);
562 serialize_function_t *f = va_arg (*va, serialize_function_t *);
567 unserialize_integer (m, &vl, sizeof (u32));
574 memset (&h, 0, sizeof (h));
575 #define _(f) unserialize_integer (m, &h.f, sizeof (h.f));
576 foreach_serialize_heap_header_integer;
579 unserialize_integer (m, &fl, sizeof (u32));
580 vec_resize (h.free_lists, fl);
582 for (i = 0; i < vec_len (h.free_lists); i++)
583 vec_unserialize (m, &h.free_lists[i], unserialize_vec_32);
585 vec_unserialize (m, &h.elts, unserialize_vec_heap_elt);
586 vec_unserialize (m, &h.small_free_elt_free_index, unserialize_vec_32);
587 vec_unserialize (m, &h.free_elts, unserialize_vec_32);
589 /* Re-construct used elt bitmap. */
593 vec_foreach (e, h.elts)
595 if (!heap_is_free (e))
596 h.used_elt_bitmap = clib_bitmap_ori (h.used_elt_bitmap, e - h.elts);
600 heap = *result = _heap_new (vl, h.elt_bytes);
601 heap_header (heap)[0] = h;
603 /* Unserialize data in heap. */
607 end = h.elts + h.tail;
610 if (!heap_is_free (e))
612 void *v = heap + heap_offset (e) * h.elt_bytes;
613 u32 n = heap_elt_size (heap, e);
614 unserialize (m, f, v, n);
624 serialize_magic (serialize_main_t * m, void *magic, u32 magic_bytes)
627 serialize_integer (m, magic_bytes, sizeof (magic_bytes));
628 p = serialize_get (m, magic_bytes);
629 clib_memcpy (p, magic, magic_bytes);
633 unserialize_check_magic (serialize_main_t * m, void *magic, u32 magic_bytes)
638 unserialize_integer (m, &l, sizeof (l));
639 if (l != magic_bytes)
642 serialize_error_return (m, "bad magic number");
644 d = serialize_get (m, magic_bytes);
645 if (memcmp (magic, d, magic_bytes))
650 va_serialize (serialize_main_t * sm, va_list * va)
652 serialize_main_header_t *m = &sm->header;
653 serialize_function_t *f = va_arg (*va, serialize_function_t *);
654 clib_error_t *error = 0;
656 m->recursion_level += 1;
657 if (m->recursion_level == 1)
659 uword r = clib_setjmp (&m->error_longjmp, 0);
660 error = uword_to_pointer (r, clib_error_t *);
666 m->recursion_level -= 1;
671 serialize (serialize_main_t * m, ...)
677 error = va_serialize (m, &va);
683 unserialize (serialize_main_t * m, ...)
689 error = va_serialize (m, &va);
695 serialize_write_not_inline (serialize_main_header_t * m,
696 serialize_stream_t * s,
697 uword n_bytes_to_write, uword flags)
699 uword cur_bi, n_left_b, n_left_o;
701 ASSERT (s->current_buffer_index <= s->n_buffer_bytes);
702 cur_bi = s->current_buffer_index;
703 n_left_b = s->n_buffer_bytes - cur_bi;
704 n_left_o = vec_len (s->overflow_buffer);
706 /* Prepend overflow buffer if present. */
709 if (n_left_o > 0 && n_left_b > 0)
711 uword n = clib_min (n_left_b, n_left_o);
712 clib_memcpy (s->buffer + cur_bi, s->overflow_buffer, n);
717 _vec_len (s->overflow_buffer) = 0;
719 vec_delete (s->overflow_buffer, n, 0);
722 /* Call data function when buffer is complete. Data function should
723 dispatch with current buffer and give us a new one to write more
727 s->current_buffer_index = cur_bi;
728 m->data_function (m, s);
729 cur_bi = s->current_buffer_index;
730 n_left_b = s->n_buffer_bytes - cur_bi;
733 while (n_left_o > 0);
735 if (n_left_o > 0 || n_left_b < n_bytes_to_write)
738 vec_add2 (s->overflow_buffer, r, n_bytes_to_write);
743 s->current_buffer_index = cur_bi + n_bytes_to_write;
744 return s->buffer + cur_bi;
749 serialize_read_not_inline (serialize_main_header_t * m,
750 serialize_stream_t * s,
751 uword n_bytes_to_read, uword flags)
753 uword cur_bi, cur_oi, n_left_b, n_left_o, n_left_to_read;
755 ASSERT (s->current_buffer_index <= s->n_buffer_bytes);
757 cur_bi = s->current_buffer_index;
758 cur_oi = s->current_overflow_index;
760 n_left_b = s->n_buffer_bytes - cur_bi;
761 n_left_o = vec_len (s->overflow_buffer) - cur_oi;
763 /* Read from overflow? */
764 if (n_left_o >= n_bytes_to_read)
766 s->current_overflow_index = cur_oi + n_bytes_to_read;
767 return vec_elt_at_index (s->overflow_buffer, cur_oi);
770 /* Reset overflow buffer. */
771 if (n_left_o == 0 && s->overflow_buffer)
773 s->current_overflow_index = 0;
774 _vec_len (s->overflow_buffer) = 0;
777 n_left_to_read = n_bytes_to_read;
778 while (n_left_to_read > 0)
782 /* If we don't have enough data between overflow and normal buffer
783 call read function. */
784 if (n_left_o + n_left_b < n_bytes_to_read)
786 /* Save any left over buffer in overflow vector. */
789 vec_add (s->overflow_buffer, s->buffer + cur_bi, n_left_b);
790 n_left_o += n_left_b;
791 n_left_to_read -= n_left_b;
792 /* Advance buffer to end --- even if
793 SERIALIZE_FLAG_NO_ADVANCE_CURRENT_BUFFER_INDEX is set. */
794 cur_bi = s->n_buffer_bytes;
798 if (m->data_function)
800 m->data_function (m, s);
801 cur_bi = s->current_buffer_index;
802 n_left_b = s->n_buffer_bytes - cur_bi;
806 /* For first time through loop return if we have enough data
807 in normal buffer and overflow vector is empty. */
809 && n_left_to_read == n_bytes_to_read && n_left_b >= n_left_to_read)
811 s->current_buffer_index = cur_bi + n_bytes_to_read;
812 return s->buffer + cur_bi;
815 if (!m->data_function || serialize_stream_is_end_of_stream (s))
817 /* This can happen for a peek at end of file.
818 Pad overflow buffer with 0s. */
819 vec_resize (s->overflow_buffer, n_left_to_read);
820 n_left_o += n_left_to_read;
825 /* Copy from buffer to overflow vector. */
826 n = clib_min (n_left_to_read, n_left_b);
827 vec_add (s->overflow_buffer, s->buffer + cur_bi, n);
835 s->current_buffer_index = cur_bi;
836 s->current_overflow_index = cur_oi + n_bytes_to_read;
837 return vec_elt_at_index (s->overflow_buffer, cur_oi);
841 serialize_read_write_not_inline (serialize_main_header_t * m,
842 serialize_stream_t * s,
843 uword n_bytes, uword flags)
845 return (((flags & SERIALIZE_FLAG_IS_READ) ? serialize_read_not_inline :
846 serialize_write_not_inline) (m, s, n_bytes, flags));
850 serialize_read_write_close (serialize_main_header_t * m,
851 serialize_stream_t * s, uword flags)
853 if (serialize_stream_is_end_of_stream (s))
856 if (flags & SERIALIZE_FLAG_IS_WRITE)
857 /* "Write" 0 bytes to flush overflow vector. */
858 serialize_write_not_inline (m, s, /* n bytes */ 0, flags);
860 serialize_stream_set_end_of_stream (s);
862 /* Call it one last time to flush buffer and close. */
863 m->data_function (m, s);
865 vec_free (s->overflow_buffer);
869 serialize_close (serialize_main_t * m)
871 serialize_read_write_close (&m->header, &m->stream,
872 SERIALIZE_FLAG_IS_WRITE);
876 unserialize_close (serialize_main_t * m)
878 serialize_read_write_close (&m->header, &m->stream, SERIALIZE_FLAG_IS_READ);
882 serialize_open_data (serialize_main_t * m, u8 * data, uword n_data_bytes)
884 memset (m, 0, sizeof (m[0]));
885 m->stream.buffer = data;
886 m->stream.n_buffer_bytes = n_data_bytes;
890 unserialize_open_data (serialize_main_t * m, u8 * data, uword n_data_bytes)
892 serialize_open_data (m, data, n_data_bytes);
896 serialize_vector_write (serialize_main_header_t * m, serialize_stream_t * s)
898 if (!serialize_stream_is_end_of_stream (s))
900 /* Double buffer size. */
901 uword l = vec_len (s->buffer);
902 vec_resize (s->buffer, l > 0 ? l : 64);
903 s->n_buffer_bytes = vec_len (s->buffer);
908 serialize_open_vector (serialize_main_t * m, u8 * vector)
910 memset (m, 0, sizeof (m[0]));
911 m->header.data_function = serialize_vector_write;
912 m->stream.buffer = vector;
913 m->stream.current_buffer_index = 0;
914 m->stream.n_buffer_bytes = vec_len (vector);
918 serialize_close_vector (serialize_main_t * m)
920 serialize_stream_t *s = &m->stream;
923 serialize_close (m); /* frees overflow buffer */
926 _vec_len (s->buffer) = s->current_buffer_index;
928 memset (m, 0, sizeof (m[0]));
933 serialize_multiple_1 (serialize_main_t * m,
934 void *data, uword data_stride, uword n_data)
938 uword n_left = n_data;
942 p = serialize_get (m, 4 * sizeof (d[0]));
943 p[0] = d[0 * data_stride];
944 p[1] = d[1 * data_stride];
945 p[2] = d[2 * data_stride];
946 p[3] = d[3 * data_stride];
948 d += 4 * data_stride;
953 p = serialize_get (m, n_left * sizeof (p[0]));
958 d += 1 * data_stride;
965 serialize_multiple_2 (serialize_main_t * m,
966 void *data, uword data_stride, uword n_data)
970 uword n_left = n_data;
974 p = serialize_get (m, 4 * sizeof (p[0]));
975 clib_mem_unaligned (p + 0, u16) =
976 clib_host_to_net_mem_u16 (d + 0 * data_stride);
977 clib_mem_unaligned (p + 1, u16) =
978 clib_host_to_net_mem_u16 (d + 1 * data_stride);
979 clib_mem_unaligned (p + 2, u16) =
980 clib_host_to_net_mem_u16 (d + 2 * data_stride);
981 clib_mem_unaligned (p + 3, u16) =
982 clib_host_to_net_mem_u16 (d + 3 * data_stride);
984 d += 4 * data_stride;
989 p = serialize_get (m, n_left * sizeof (p[0]));
992 clib_mem_unaligned (p + 0, u16) =
993 clib_host_to_net_mem_u16 (d + 0 * data_stride);
995 d += 1 * data_stride;
1002 serialize_multiple_4 (serialize_main_t * m,
1003 void *data, uword data_stride, uword n_data)
1007 uword n_left = n_data;
1011 p = serialize_get (m, 4 * sizeof (p[0]));
1012 clib_mem_unaligned (p + 0, u32) =
1013 clib_host_to_net_mem_u32 (d + 0 * data_stride);
1014 clib_mem_unaligned (p + 1, u32) =
1015 clib_host_to_net_mem_u32 (d + 1 * data_stride);
1016 clib_mem_unaligned (p + 2, u32) =
1017 clib_host_to_net_mem_u32 (d + 2 * data_stride);
1018 clib_mem_unaligned (p + 3, u32) =
1019 clib_host_to_net_mem_u32 (d + 3 * data_stride);
1021 d += 4 * data_stride;
1026 p = serialize_get (m, n_left * sizeof (p[0]));
1029 clib_mem_unaligned (p + 0, u32) =
1030 clib_host_to_net_mem_u32 (d + 0 * data_stride);
1032 d += 1 * data_stride;
1039 unserialize_multiple_1 (serialize_main_t * m,
1040 void *data, uword data_stride, uword n_data)
1044 uword n_left = n_data;
1048 p = unserialize_get (m, 4 * sizeof (d[0]));
1049 d[0 * data_stride] = p[0];
1050 d[1 * data_stride] = p[1];
1051 d[2 * data_stride] = p[2];
1052 d[3 * data_stride] = p[3];
1054 d += 4 * data_stride;
1059 p = unserialize_get (m, n_left * sizeof (p[0]));
1064 d += 1 * data_stride;
1071 unserialize_multiple_2 (serialize_main_t * m,
1072 void *data, uword data_stride, uword n_data)
1076 uword n_left = n_data;
1080 p = unserialize_get (m, 4 * sizeof (p[0]));
1081 clib_mem_unaligned (d + 0 * data_stride, u16) =
1082 clib_net_to_host_mem_u16 (p + 0);
1083 clib_mem_unaligned (d + 1 * data_stride, u16) =
1084 clib_net_to_host_mem_u16 (p + 1);
1085 clib_mem_unaligned (d + 2 * data_stride, u16) =
1086 clib_net_to_host_mem_u16 (p + 2);
1087 clib_mem_unaligned (d + 3 * data_stride, u16) =
1088 clib_net_to_host_mem_u16 (p + 3);
1090 d += 4 * data_stride;
1095 p = unserialize_get (m, n_left * sizeof (p[0]));
1098 clib_mem_unaligned (d + 0 * data_stride, u16) =
1099 clib_net_to_host_mem_u16 (p + 0);
1101 d += 1 * data_stride;
1108 unserialize_multiple_4 (serialize_main_t * m,
1109 void *data, uword data_stride, uword n_data)
1113 uword n_left = n_data;
1117 p = unserialize_get (m, 4 * sizeof (p[0]));
1118 clib_mem_unaligned (d + 0 * data_stride, u32) =
1119 clib_net_to_host_mem_u32 (p + 0);
1120 clib_mem_unaligned (d + 1 * data_stride, u32) =
1121 clib_net_to_host_mem_u32 (p + 1);
1122 clib_mem_unaligned (d + 2 * data_stride, u32) =
1123 clib_net_to_host_mem_u32 (p + 2);
1124 clib_mem_unaligned (d + 3 * data_stride, u32) =
1125 clib_net_to_host_mem_u32 (p + 3);
1127 d += 4 * data_stride;
1132 p = unserialize_get (m, n_left * sizeof (p[0]));
1135 clib_mem_unaligned (d + 0 * data_stride, u32) =
1136 clib_net_to_host_mem_u32 (p + 0);
1138 d += 1 * data_stride;
1150 unix_file_write (serialize_main_header_t * m, serialize_stream_t * s)
1154 fd = s->data_function_opaque;
1155 n = write (fd, s->buffer, s->current_buffer_index);
1158 if (!unix_error_is_fatal (errno))
1161 serialize_error (m, clib_error_return_unix (0, "write"));
1163 if (n == s->current_buffer_index)
1164 _vec_len (s->buffer) = 0;
1166 vec_delete (s->buffer, n, 0);
1167 s->current_buffer_index = vec_len (s->buffer);
1171 unix_file_read (serialize_main_header_t * m, serialize_stream_t * s)
1175 fd = s->data_function_opaque;
1176 n = read (fd, s->buffer, vec_len (s->buffer));
1179 if (!unix_error_is_fatal (errno))
1182 serialize_error (m, clib_error_return_unix (0, "read"));
1185 serialize_stream_set_end_of_stream (s);
1186 s->current_buffer_index = 0;
1187 s->n_buffer_bytes = n;
1191 serialize_open_unix_file_descriptor_helper (serialize_main_t * m, int fd,
1194 memset (m, 0, sizeof (m[0]));
1195 vec_resize (m->stream.buffer, 4096);
1199 m->stream.n_buffer_bytes = vec_len (m->stream.buffer);
1200 _vec_len (m->stream.buffer) = 0;
1203 m->header.data_function = is_read ? unix_file_read : unix_file_write;
1204 m->stream.data_function_opaque = fd;
1208 serialize_open_unix_file_descriptor (serialize_main_t * m, int fd)
1210 serialize_open_unix_file_descriptor_helper (m, fd, /* is_read */ 0);
1214 unserialize_open_unix_file_descriptor (serialize_main_t * m, int fd)
1216 serialize_open_unix_file_descriptor_helper (m, fd, /* is_read */ 1);
1219 static clib_error_t *
1220 serialize_open_unix_file_helper (serialize_main_t * m, char *file,
1225 mode = is_read ? O_RDONLY : O_RDWR | O_CREAT | O_TRUNC;
1226 fd = open (file, mode, 0666);
1228 return clib_error_return_unix (0, "open `%s'", file);
1230 serialize_open_unix_file_descriptor_helper (m, fd, is_read);
1235 serialize_open_unix_file (serialize_main_t * m, char *file)
1237 return serialize_open_unix_file_helper (m, file, /* is_read */ 0);
1241 unserialize_open_unix_file (serialize_main_t * m, char *file)
1243 return serialize_open_unix_file_helper (m, file, /* is_read */ 1);
1246 #endif /* CLIB_UNIX */
1249 * fd.io coding-style-patch-verification: ON
1252 * eval: (c-set-style "gnu")