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>
44 void serialize_64 (serialize_main_t * m, va_list * va)
46 u64 x = va_arg (*va, u64);
50 serialize_integer (m, lo, sizeof (lo));
51 serialize_integer (m, hi, sizeof (hi));
54 void serialize_32 (serialize_main_t * m, va_list * va)
56 u32 x = va_arg (*va, u32);
57 serialize_integer (m, x, sizeof (x));
60 void serialize_16 (serialize_main_t * m, va_list * va)
62 u32 x = va_arg (*va, u32);
63 serialize_integer (m, x, sizeof (u16));
66 void serialize_8 (serialize_main_t * m, va_list * va)
68 u32 x = va_arg (*va, u32);
69 serialize_integer (m, x, sizeof (u8));
72 void unserialize_64 (serialize_main_t * m, va_list * va)
74 u64 * x = va_arg (*va, u64 *);
76 unserialize_integer (m, &lo, sizeof (lo));
77 unserialize_integer (m, &hi, sizeof (hi));
78 *x = ((u64) hi << 32) | (u64) lo;
81 void unserialize_32 (serialize_main_t * m, va_list * va)
83 u32 * x = va_arg (*va, u32 *);
84 unserialize_integer (m, x, sizeof (x[0]));
87 void unserialize_16 (serialize_main_t * m, va_list * va)
89 u16 * x = va_arg (*va, u16 *);
91 unserialize_integer (m, &t, sizeof (x[0]));
95 void unserialize_8 (serialize_main_t * m, va_list * va)
97 u8 * x = va_arg (*va, u8 *);
99 unserialize_integer (m, &t, sizeof (x[0]));
103 void serialize_f64 (serialize_main_t * m, va_list * va)
105 f64 x = va_arg (*va, f64);
106 union { f64 f; u64 i; } y;
108 serialize (m, serialize_64, y.i);
111 void serialize_f32 (serialize_main_t * m, va_list * va)
113 f32 x = va_arg (*va, f64);
114 union { f32 f; u32 i; } y;
116 serialize_integer (m, y.i, sizeof (y.i));
119 void unserialize_f64 (serialize_main_t * m, va_list * va)
121 f64 * x = va_arg (*va, f64 *);
122 union { f64 f; u64 i; } y;
123 unserialize (m, unserialize_64, &y.i);
127 void unserialize_f32 (serialize_main_t * m, va_list * va)
129 f32 * x = va_arg (*va, f32 *);
130 union { f32 f; u32 i; } y;
131 unserialize_integer (m, &y.i, sizeof (y.i));
135 void serialize_cstring (serialize_main_t * m, char * s)
137 u32 len = s ? strlen (s) : 0;
140 serialize_likely_small_unsigned_integer (m, len);
143 p = serialize_get (m, len);
148 void unserialize_cstring (serialize_main_t * m, char ** s)
153 len = unserialize_likely_small_unsigned_integer (m);
156 * Given broken enough data, we could get len = 0xFFFFFFFF.
157 * Add one, it overflows, we call vec_new (char, 0), then
158 * memcpy until we bus error.
160 if (len > 0 && len != 0xFFFFFFFF)
162 r = vec_new (char, len + 1);
163 p = unserialize_get (m, len);
166 /* Null terminate. */
172 /* vec_serialize/vec_unserialize helper functions for basic vector types. */
173 void serialize_vec_8 (serialize_main_t * m, va_list * va)
175 u8 * s = va_arg (*va, u8 *);
176 u32 n = va_arg (*va, u32);
177 u8 * p = serialize_get (m, n * sizeof (u8));
178 memcpy (p, s, n * sizeof (u8));
181 void unserialize_vec_8 (serialize_main_t * m, va_list * va)
183 u8 * s = va_arg (*va, u8 *);
184 u32 n = va_arg (*va, u32);
185 u8 * p = unserialize_get (m, n);
190 void serialize_vec_##n_bits (serialize_main_t * m, va_list * va) \
192 u##n_bits * s = va_arg (*va, u##n_bits *); \
193 u32 n = va_arg (*va, u32); \
194 u##n_bits * p = serialize_get (m, n * sizeof (s[0])); \
198 p[0] = clib_host_to_net_u##n_bits (s[0]); \
199 p[1] = clib_host_to_net_u##n_bits (s[1]); \
200 p[2] = clib_host_to_net_u##n_bits (s[2]); \
201 p[3] = clib_host_to_net_u##n_bits (s[3]); \
209 p[0] = clib_host_to_net_u##n_bits (s[0]); \
216 void unserialize_vec_##n_bits (serialize_main_t * m, va_list * va) \
218 u##n_bits * s = va_arg (*va, u##n_bits *); \
219 u32 n = va_arg (*va, u32); \
220 u##n_bits * p = unserialize_get (m, n * sizeof (s[0])); \
224 s[0] = clib_net_to_host_mem_u##n_bits (&p[0]); \
225 s[1] = clib_net_to_host_mem_u##n_bits (&p[1]); \
226 s[2] = clib_net_to_host_mem_u##n_bits (&p[2]); \
227 s[3] = clib_net_to_host_mem_u##n_bits (&p[3]); \
235 s[0] = clib_net_to_host_mem_u##n_bits (&p[0]); \
248 #define SERIALIZE_VECTOR_CHUNK_SIZE 64
250 void serialize_vector (serialize_main_t * m, va_list * va)
252 void * vec = va_arg (*va, void *);
253 u32 elt_bytes = va_arg (*va, u32);
254 serialize_function_t * f = va_arg (*va, serialize_function_t *);
255 u32 l = vec_len (vec);
258 serialize_integer (m, l, sizeof (l));
260 /* Serialize vector in chunks for cache locality. */
263 u32 n = clib_min (SERIALIZE_VECTOR_CHUNK_SIZE, l);
264 serialize (m, f, p, n);
266 p += SERIALIZE_VECTOR_CHUNK_SIZE * elt_bytes;
271 unserialize_vector_ha (serialize_main_t * m,
276 serialize_function_t * f)
281 unserialize_integer (m, &l, sizeof (l));
283 serialize_error (&m->header, clib_error_create ("bad vector length %d", l));
284 p = v = _vec_resize (0, l, l*elt_bytes, header_bytes, /* align */ align);
288 u32 n = clib_min (SERIALIZE_VECTOR_CHUNK_SIZE, l);
289 unserialize (m, f, p, n);
291 p += SERIALIZE_VECTOR_CHUNK_SIZE * elt_bytes;
296 void unserialize_aligned_vector (serialize_main_t * m, va_list * va)
298 void ** vec = va_arg (*va, void **);
299 u32 elt_bytes = va_arg (*va, u32);
300 serialize_function_t * f = va_arg (*va, serialize_function_t *);
301 u32 align = va_arg (*va, u32);
303 *vec = unserialize_vector_ha (m, elt_bytes,
304 /* header_bytes */ 0,
310 void unserialize_vector (serialize_main_t * m, va_list * va)
312 void ** vec = va_arg (*va, void **);
313 u32 elt_bytes = va_arg (*va, u32);
314 serialize_function_t * f = va_arg (*va, serialize_function_t *);
316 *vec = unserialize_vector_ha (m, elt_bytes,
317 /* header_bytes */ 0,
323 void serialize_bitmap (serialize_main_t * m, uword * b)
328 n_u32s = l * sizeof (b[0]) / sizeof (u32);
329 serialize_integer (m, n_u32s, sizeof (n_u32s));
331 /* Send 32 bit words, low-order word first on 64 bit. */
332 for (i = 0; i < l; i++)
334 serialize_integer (m, b[i], sizeof (u32));
335 if (BITS (uword) == 64)
336 serialize_integer (m, (u64) b[i] >> (u64) 32, sizeof (u32));
340 uword * unserialize_bitmap (serialize_main_t * m)
345 unserialize_integer (m, &n_u32s, sizeof (n_u32s));
349 i = (n_u32s * sizeof (u32) + sizeof (b[0]) - 1) / sizeof (b[0]);
351 for (i = 0; i < n_u32s; i++)
354 unserialize_integer (m, &data, sizeof (u32));
356 /* Low-word is first on 64 bit. */
357 if (BITS (uword) == 64)
360 b[i/2] |= (u64) data << (u64) 0;
362 b[i/2] |= (u64) data << (u64) 32;
373 void serialize_pool (serialize_main_t * m, va_list * va)
375 void * pool = va_arg (*va, void *);
376 u32 elt_bytes = va_arg (*va, u32);
377 serialize_function_t * f = va_arg (*va, serialize_function_t *);
382 serialize_integer (m, l, sizeof (u32));
385 p = pool_header (pool);
387 /* No need to send free bitmap. Need to send index vector
388 to guarantee that unserialized pool will be identical. */
389 vec_serialize (m, p->free_indices, serialize_vec_32);
391 pool_foreach_region (lo, hi, pool,
392 serialize (m, f, pool + lo*elt_bytes, hi - lo));
396 unserialize_pool_helper (serialize_main_t * m,
397 u32 elt_bytes, u32 align,
398 serialize_function_t * f)
404 unserialize_integer (m, &l, sizeof (l));
410 v = _vec_resize (0, l, l*elt_bytes, sizeof (p[0]), align);
413 vec_unserialize (m, &p->free_indices, unserialize_vec_32);
415 /* Construct free bitmap. */
417 for (i = 0; i < vec_len (p->free_indices); i++)
418 p->free_bitmap = clib_bitmap_ori (p->free_bitmap, p->free_indices[i]);
420 pool_foreach_region (lo, hi, v,
421 unserialize (m, f, v + lo*elt_bytes, hi - lo));
426 void unserialize_pool (serialize_main_t * m, va_list * va)
428 void ** result = va_arg (*va, void **);
429 u32 elt_bytes = va_arg (*va, u32);
430 serialize_function_t * f = va_arg (*va, serialize_function_t *);
431 *result = unserialize_pool_helper (m, elt_bytes, /* align */ 0, f);
434 void unserialize_aligned_pool (serialize_main_t * m, va_list * va)
436 void ** result = va_arg (*va, void **);
437 u32 elt_bytes = va_arg (*va, u32);
438 u32 align = va_arg (*va, u32);
439 serialize_function_t * f = va_arg (*va, serialize_function_t *);
440 *result = unserialize_pool_helper (m, elt_bytes, align, f);
443 static void serialize_vec_heap_elt (serialize_main_t * m, va_list * va)
445 heap_elt_t * e = va_arg (*va, heap_elt_t *);
446 u32 i, n = va_arg (*va, u32);
447 for (i = 0; i < n; i++)
449 serialize_integer (m, e[i].offset, sizeof (e[i].offset));
450 serialize_integer (m, e[i].next, sizeof (e[i].next));
451 serialize_integer (m, e[i].prev, sizeof (e[i].prev));
455 static void unserialize_vec_heap_elt (serialize_main_t * m, va_list * va)
457 heap_elt_t * e = va_arg (*va, heap_elt_t *);
458 u32 i, n = va_arg (*va, u32);
459 for (i = 0; i < n; i++)
461 unserialize_integer (m, &e[i].offset, sizeof (e[i].offset));
462 unserialize_integer (m, &e[i].next, sizeof (e[i].next));
463 unserialize_integer (m, &e[i].prev, sizeof (e[i].prev));
467 void serialize_heap (serialize_main_t * m, va_list * va)
469 void * heap = va_arg (*va, void *);
470 serialize_function_t * f = va_arg (*va, serialize_function_t *);
475 serialize_integer (m, l, sizeof (u32));
479 h = heap_header (heap);
481 #define foreach_serialize_heap_header_integer \
482 _ (head) _ (tail) _ (used_count) _ (max_len) _ (flags) _ (elt_bytes)
484 #define _(f) serialize_integer (m, h->f, sizeof (h->f));
485 foreach_serialize_heap_header_integer;
488 serialize_integer (m, vec_len (h->free_lists), sizeof (u32));
489 for (i = 0; i < vec_len (h->free_lists); i++)
490 vec_serialize (m, h->free_lists[i], serialize_vec_32);
492 vec_serialize (m, h->elts, serialize_vec_heap_elt);
493 vec_serialize (m, h->small_free_elt_free_index, serialize_vec_32);
494 vec_serialize (m, h->free_elts, serialize_vec_32);
496 /* Serialize data in heap. */
498 heap_elt_t * e, * end;
499 e = h->elts + h->head;
500 end = h->elts + h->tail;
503 if (! heap_is_free (e))
505 void * v = heap + heap_offset (e) * h->elt_bytes;
506 u32 n = heap_elt_size (heap, e);
507 serialize (m, f, v, n);
516 void unserialize_heap (serialize_main_t * m, va_list * va)
518 void ** result = va_arg (*va, void **);
519 serialize_function_t * f = va_arg (*va, serialize_function_t *);
524 unserialize_integer (m, &vl, sizeof (u32));
531 memset (&h, 0, sizeof (h));
532 #define _(f) unserialize_integer (m, &h.f, sizeof (h.f));
533 foreach_serialize_heap_header_integer;
536 unserialize_integer (m, &fl, sizeof (u32));
537 vec_resize (h.free_lists, fl);
539 for (i = 0; i < vec_len (h.free_lists); i++)
540 vec_unserialize (m, &h.free_lists[i], unserialize_vec_32);
542 vec_unserialize (m, &h.elts, unserialize_vec_heap_elt);
543 vec_unserialize (m, &h.small_free_elt_free_index, unserialize_vec_32);
544 vec_unserialize (m, &h.free_elts, unserialize_vec_32);
546 /* Re-construct used elt bitmap. */
550 vec_foreach (e, h.elts)
552 if (! heap_is_free (e))
553 h.used_elt_bitmap = clib_bitmap_ori (h.used_elt_bitmap, e - h.elts);
557 heap = *result = _heap_new (vl, h.elt_bytes);
558 heap_header (heap)[0] = h;
560 /* Unserialize data in heap. */
562 heap_elt_t * e, * end;
564 end = h.elts + h.tail;
567 if (! heap_is_free (e))
569 void * v = heap + heap_offset (e) * h.elt_bytes;
570 u32 n = heap_elt_size (heap, e);
571 unserialize (m, f, v, n);
580 void serialize_magic (serialize_main_t * m, void * magic, u32 magic_bytes)
583 serialize_integer (m, magic_bytes, sizeof (magic_bytes));
584 p = serialize_get (m, magic_bytes);
585 memcpy (p, magic, magic_bytes);
588 void unserialize_check_magic (serialize_main_t * m, void * magic,
594 unserialize_integer (m, &l, sizeof (l));
595 if (l != magic_bytes)
598 serialize_error_return (m, "bad magic number");
600 d = serialize_get (m, magic_bytes);
601 if (memcmp (magic, d, magic_bytes))
606 va_serialize (serialize_main_t * sm, va_list * va)
608 serialize_main_header_t * m = &sm->header;
609 serialize_function_t * f = va_arg (*va, serialize_function_t *);
610 clib_error_t * error = 0;
612 m->recursion_level += 1;
613 if (m->recursion_level == 1)
615 uword r = clib_setjmp (&m->error_longjmp, 0);
616 error = uword_to_pointer (r, clib_error_t *);
622 m->recursion_level -= 1;
627 serialize (serialize_main_t * m, ...)
629 clib_error_t * error;
633 error = va_serialize (m, &va);
639 unserialize (serialize_main_t * m, ...)
641 clib_error_t * error;
645 error = va_serialize (m, &va);
650 static void * serialize_write_not_inline (serialize_main_header_t * m,
651 serialize_stream_t * s,
652 uword n_bytes_to_write,
655 uword cur_bi, n_left_b, n_left_o;
657 ASSERT (s->current_buffer_index <= s->n_buffer_bytes);
658 cur_bi = s->current_buffer_index;
659 n_left_b = s->n_buffer_bytes - cur_bi;
660 n_left_o = vec_len (s->overflow_buffer);
662 /* Prepend overflow buffer if present. */
664 if (n_left_o > 0 && n_left_b > 0)
666 uword n = clib_min (n_left_b, n_left_o);
667 memcpy (s->buffer + cur_bi, s->overflow_buffer, n);
672 _vec_len (s->overflow_buffer) = 0;
674 vec_delete (s->overflow_buffer, n, 0);
677 /* Call data function when buffer is complete. Data function should
678 dispatch with current buffer and give us a new one to write more
682 s->current_buffer_index = cur_bi;
683 m->data_function (m, s);
684 cur_bi = s->current_buffer_index;
685 n_left_b = s->n_buffer_bytes - cur_bi;
687 } while (n_left_o > 0);
689 if (n_left_o > 0 || n_left_b < n_bytes_to_write)
692 vec_add2 (s->overflow_buffer, r, n_bytes_to_write);
697 s->current_buffer_index = cur_bi + n_bytes_to_write;
698 return s->buffer + cur_bi;
702 static void * serialize_read_not_inline (serialize_main_header_t * m,
703 serialize_stream_t * s,
704 uword n_bytes_to_read,
707 uword cur_bi, cur_oi, n_left_b, n_left_o, n_left_to_read;
709 ASSERT (s->current_buffer_index <= s->n_buffer_bytes);
711 cur_bi = s->current_buffer_index;
712 cur_oi = s->current_overflow_index;
714 n_left_b = s->n_buffer_bytes - cur_bi;
715 n_left_o = vec_len (s->overflow_buffer) - cur_oi;
717 /* Read from overflow? */
718 if (n_left_o >= n_bytes_to_read)
720 s->current_overflow_index = cur_oi + n_bytes_to_read;
721 return vec_elt_at_index (s->overflow_buffer, cur_oi);
724 /* Reset overflow buffer. */
725 if (n_left_o == 0 && s->overflow_buffer)
727 s->current_overflow_index = 0;
728 _vec_len (s->overflow_buffer) = 0;
731 n_left_to_read = n_bytes_to_read;
732 while (n_left_to_read > 0)
736 /* If we don't have enough data between overflow and normal buffer
737 call read function. */
738 if (n_left_o + n_left_b < n_bytes_to_read)
740 /* Save any left over buffer in overflow vector. */
743 vec_add (s->overflow_buffer, s->buffer + cur_bi, n_left_b);
744 n_left_o += n_left_b;
745 n_left_to_read -= n_left_b;
746 /* Advance buffer to end --- even if
747 SERIALIZE_FLAG_NO_ADVANCE_CURRENT_BUFFER_INDEX is set. */
748 cur_bi = s->n_buffer_bytes;
752 if (m->data_function)
754 m->data_function (m, s);
755 cur_bi = s->current_buffer_index;
756 n_left_b = s->n_buffer_bytes - cur_bi;
760 /* For first time through loop return if we have enough data
761 in normal buffer and overflow vector is empty. */
763 && n_left_to_read == n_bytes_to_read
764 && n_left_b >= n_left_to_read)
766 s->current_buffer_index = cur_bi + n_bytes_to_read;
767 return s->buffer + cur_bi;
770 if (! m->data_function
771 || serialize_stream_is_end_of_stream (s))
773 /* This can happen for a peek at end of file.
774 Pad overflow buffer with 0s. */
775 vec_resize (s->overflow_buffer, n_left_to_read);
776 n_left_o += n_left_to_read;
781 /* Copy from buffer to overflow vector. */
782 n = clib_min (n_left_to_read, n_left_b);
783 vec_add (s->overflow_buffer, s->buffer + cur_bi, n);
791 s->current_buffer_index = cur_bi;
792 s->current_overflow_index = cur_oi + n_bytes_to_read;
793 return vec_elt_at_index (s->overflow_buffer, cur_oi);
796 void * serialize_read_write_not_inline (serialize_main_header_t * m,
797 serialize_stream_t * s,
801 return (((flags & SERIALIZE_FLAG_IS_READ) ? serialize_read_not_inline : serialize_write_not_inline)
802 (m, s, n_bytes, flags));
805 static void serialize_read_write_close (serialize_main_header_t * m, serialize_stream_t * s, uword flags)
807 if (serialize_stream_is_end_of_stream (s))
810 if (flags & SERIALIZE_FLAG_IS_WRITE)
811 /* "Write" 0 bytes to flush overflow vector. */
812 serialize_write_not_inline (m, s, /* n bytes */ 0, flags);
814 serialize_stream_set_end_of_stream (s);
816 /* Call it one last time to flush buffer and close. */
817 m->data_function (m, s);
819 vec_free (s->overflow_buffer);
822 void serialize_close (serialize_main_t * m)
823 { serialize_read_write_close (&m->header, &m->stream, SERIALIZE_FLAG_IS_WRITE); }
825 void unserialize_close (serialize_main_t * m)
826 { serialize_read_write_close (&m->header, &m->stream, SERIALIZE_FLAG_IS_READ); }
828 void serialize_open_data (serialize_main_t * m, u8 * data, uword n_data_bytes)
830 memset (m, 0, sizeof (m[0]));
831 m->stream.buffer = data;
832 m->stream.n_buffer_bytes = n_data_bytes;
835 void unserialize_open_data (serialize_main_t * m, u8 * data, uword n_data_bytes)
836 { serialize_open_data (m, data, n_data_bytes); }
838 static void serialize_vector_write (serialize_main_header_t * m, serialize_stream_t * s)
840 if (! serialize_stream_is_end_of_stream (s))
842 /* Double buffer size. */
843 uword l = vec_len (s->buffer);
844 vec_resize (s->buffer, l > 0 ? l : 64);
845 s->n_buffer_bytes = vec_len (s->buffer);
849 void serialize_open_vector (serialize_main_t * m, u8 * vector)
851 memset (m, 0, sizeof (m[0]));
852 m->header.data_function = serialize_vector_write;
853 m->stream.buffer = vector;
854 m->stream.current_buffer_index = 0;
855 m->stream.n_buffer_bytes = vec_len (vector);
858 void * serialize_close_vector (serialize_main_t * m)
860 serialize_stream_t * s = &m->stream;
863 serialize_close (m); /* frees overflow buffer */
866 _vec_len (s->buffer) = s->current_buffer_index;
868 memset (m, 0, sizeof (m[0]));
873 serialize_multiple_1 (serialize_main_t * m,
880 uword n_left = n_data;
884 p = serialize_get (m, 4 * sizeof (d[0]));
885 p[0] = d[0 * data_stride];
886 p[1] = d[1 * data_stride];
887 p[2] = d[2 * data_stride];
888 p[3] = d[3 * data_stride];
890 d += 4 * data_stride;
895 p = serialize_get (m, n_left * sizeof (p[0]));
900 d += 1 * data_stride;
907 serialize_multiple_2 (serialize_main_t * m,
914 uword n_left = n_data;
918 p = serialize_get (m, 4 * sizeof (p[0]));
919 clib_mem_unaligned (p + 0, u16) = clib_host_to_net_mem_u16 (d + 0 * data_stride);
920 clib_mem_unaligned (p + 1, u16) = clib_host_to_net_mem_u16 (d + 1 * data_stride);
921 clib_mem_unaligned (p + 2, u16) = clib_host_to_net_mem_u16 (d + 2 * data_stride);
922 clib_mem_unaligned (p + 3, u16) = clib_host_to_net_mem_u16 (d + 3 * data_stride);
924 d += 4 * data_stride;
929 p = serialize_get (m, n_left * sizeof (p[0]));
932 clib_mem_unaligned (p + 0, u16) = clib_host_to_net_mem_u16 (d + 0 * data_stride);
934 d += 1 * data_stride;
941 serialize_multiple_4 (serialize_main_t * m,
948 uword n_left = n_data;
952 p = serialize_get (m, 4 * sizeof (p[0]));
953 clib_mem_unaligned (p + 0, u32) = clib_host_to_net_mem_u32 (d + 0 * data_stride);
954 clib_mem_unaligned (p + 1, u32) = clib_host_to_net_mem_u32 (d + 1 * data_stride);
955 clib_mem_unaligned (p + 2, u32) = clib_host_to_net_mem_u32 (d + 2 * data_stride);
956 clib_mem_unaligned (p + 3, u32) = clib_host_to_net_mem_u32 (d + 3 * data_stride);
958 d += 4 * data_stride;
963 p = serialize_get (m, n_left * sizeof (p[0]));
966 clib_mem_unaligned (p + 0, u32) = clib_host_to_net_mem_u32 (d + 0 * data_stride);
968 d += 1 * data_stride;
975 unserialize_multiple_1 (serialize_main_t * m,
982 uword n_left = n_data;
986 p = unserialize_get (m, 4 * sizeof (d[0]));
987 d[0 * data_stride] = p[0];
988 d[1 * data_stride] = p[1];
989 d[2 * data_stride] = p[2];
990 d[3 * data_stride] = p[3];
992 d += 4 * data_stride;
997 p = unserialize_get (m, n_left * sizeof (p[0]));
1002 d += 1 * data_stride;
1009 unserialize_multiple_2 (serialize_main_t * m,
1016 uword n_left = n_data;
1020 p = unserialize_get (m, 4 * sizeof (p[0]));
1021 clib_mem_unaligned (d + 0 * data_stride, u16) = clib_net_to_host_mem_u16 (p + 0);
1022 clib_mem_unaligned (d + 1 * data_stride, u16) = clib_net_to_host_mem_u16 (p + 1);
1023 clib_mem_unaligned (d + 2 * data_stride, u16) = clib_net_to_host_mem_u16 (p + 2);
1024 clib_mem_unaligned (d + 3 * data_stride, u16) = clib_net_to_host_mem_u16 (p + 3);
1026 d += 4 * data_stride;
1031 p = unserialize_get (m, n_left * sizeof (p[0]));
1034 clib_mem_unaligned (d + 0 * data_stride, u16) = clib_net_to_host_mem_u16 (p + 0);
1036 d += 1 * data_stride;
1043 unserialize_multiple_4 (serialize_main_t * m,
1050 uword n_left = n_data;
1054 p = unserialize_get (m, 4 * sizeof (p[0]));
1055 clib_mem_unaligned (d + 0 * data_stride, u32) = clib_net_to_host_mem_u32 (p + 0);
1056 clib_mem_unaligned (d + 1 * data_stride, u32) = clib_net_to_host_mem_u32 (p + 1);
1057 clib_mem_unaligned (d + 2 * data_stride, u32) = clib_net_to_host_mem_u32 (p + 2);
1058 clib_mem_unaligned (d + 3 * data_stride, u32) = clib_net_to_host_mem_u32 (p + 3);
1060 d += 4 * data_stride;
1065 p = unserialize_get (m, n_left * sizeof (p[0]));
1068 clib_mem_unaligned (d + 0 * data_stride, u32) = clib_net_to_host_mem_u32 (p + 0);
1070 d += 1 * data_stride;
1081 static void unix_file_write (serialize_main_header_t * m, serialize_stream_t * s)
1085 fd = s->data_function_opaque;
1086 n = write (fd, s->buffer, s->current_buffer_index);
1089 if (! unix_error_is_fatal (errno))
1092 serialize_error (m, clib_error_return_unix (0, "write"));
1094 if (n == s->current_buffer_index)
1095 _vec_len (s->buffer) = 0;
1097 vec_delete (s->buffer, n, 0);
1098 s->current_buffer_index = vec_len (s->buffer);
1101 static void unix_file_read (serialize_main_header_t * m, serialize_stream_t * s)
1105 fd = s->data_function_opaque;
1106 n = read (fd, s->buffer, vec_len (s->buffer));
1109 if (! unix_error_is_fatal (errno))
1112 serialize_error (m, clib_error_return_unix (0, "read"));
1115 serialize_stream_set_end_of_stream (s);
1116 s->current_buffer_index = 0;
1117 s->n_buffer_bytes = n;
1121 serialize_open_unix_file_descriptor_helper (serialize_main_t * m, int fd, uword is_read)
1123 memset (m, 0, sizeof (m[0]));
1124 vec_resize (m->stream.buffer, 4096);
1128 m->stream.n_buffer_bytes = vec_len (m->stream.buffer);
1129 _vec_len (m->stream.buffer) = 0;
1132 m->header.data_function = is_read ? unix_file_read : unix_file_write;
1133 m->stream.data_function_opaque = fd;
1136 void serialize_open_unix_file_descriptor (serialize_main_t * m, int fd)
1137 { serialize_open_unix_file_descriptor_helper (m, fd, /* is_read */ 0); }
1139 void unserialize_open_unix_file_descriptor (serialize_main_t * m, int fd)
1140 { serialize_open_unix_file_descriptor_helper (m, fd, /* is_read */ 1); }
1142 static clib_error_t *
1143 serialize_open_unix_file_helper (serialize_main_t * m, char * file, uword is_read)
1147 mode = is_read ? O_RDONLY : O_RDWR | O_CREAT | O_TRUNC;
1148 fd = open (file, mode, 0666);
1150 return clib_error_return_unix (0, "open `%s'", file);
1152 serialize_open_unix_file_descriptor_helper (m, fd, is_read);
1157 serialize_open_unix_file (serialize_main_t * m, char * file)
1158 { return serialize_open_unix_file_helper (m, file, /* is_read */ 0); }
1161 unserialize_open_unix_file (serialize_main_t * m, char * file)
1162 { return serialize_open_unix_file_helper (m, file, /* is_read */ 1); }
1164 #endif /* CLIB_UNIX */