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);
144 clib_memcpy (p, s, 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);
164 clib_memcpy (r, p, 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 clib_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);
186 clib_memcpy (s, p, 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, (uword) l*elt_bytes, header_bytes,
289 u32 n = clib_min (SERIALIZE_VECTOR_CHUNK_SIZE, l);
290 unserialize (m, f, p, n);
292 p += SERIALIZE_VECTOR_CHUNK_SIZE * elt_bytes;
297 void unserialize_aligned_vector (serialize_main_t * m, va_list * va)
299 void ** vec = va_arg (*va, void **);
300 u32 elt_bytes = va_arg (*va, u32);
301 serialize_function_t * f = va_arg (*va, serialize_function_t *);
302 u32 align = va_arg (*va, u32);
304 *vec = unserialize_vector_ha (m, elt_bytes,
305 /* header_bytes */ 0,
311 void unserialize_vector (serialize_main_t * m, va_list * va)
313 void ** vec = va_arg (*va, void **);
314 u32 elt_bytes = va_arg (*va, u32);
315 serialize_function_t * f = va_arg (*va, serialize_function_t *);
317 *vec = unserialize_vector_ha (m, elt_bytes,
318 /* header_bytes */ 0,
324 void serialize_bitmap (serialize_main_t * m, uword * b)
329 n_u32s = l * sizeof (b[0]) / sizeof (u32);
330 serialize_integer (m, n_u32s, sizeof (n_u32s));
332 /* Send 32 bit words, low-order word first on 64 bit. */
333 for (i = 0; i < l; i++)
335 serialize_integer (m, b[i], sizeof (u32));
336 if (BITS (uword) == 64)
337 serialize_integer (m, (u64) b[i] >> (u64) 32, sizeof (u32));
341 uword * unserialize_bitmap (serialize_main_t * m)
346 unserialize_integer (m, &n_u32s, sizeof (n_u32s));
350 i = (n_u32s * sizeof (u32) + sizeof (b[0]) - 1) / sizeof (b[0]);
352 for (i = 0; i < n_u32s; i++)
355 unserialize_integer (m, &data, sizeof (u32));
357 /* Low-word is first on 64 bit. */
358 if (BITS (uword) == 64)
361 b[i/2] |= (u64) data << (u64) 0;
363 b[i/2] |= (u64) data << (u64) 32;
374 void serialize_pool (serialize_main_t * m, va_list * va)
376 void * pool = va_arg (*va, void *);
377 u32 elt_bytes = va_arg (*va, u32);
378 serialize_function_t * f = va_arg (*va, serialize_function_t *);
383 serialize_integer (m, l, sizeof (u32));
386 p = pool_header (pool);
388 /* No need to send free bitmap. Need to send index vector
389 to guarantee that unserialized pool will be identical. */
390 vec_serialize (m, p->free_indices, serialize_vec_32);
392 pool_foreach_region (lo, hi, pool,
393 serialize (m, f, pool + lo*elt_bytes, hi - lo));
397 unserialize_pool_helper (serialize_main_t * m,
398 u32 elt_bytes, u32 align,
399 serialize_function_t * f)
405 unserialize_integer (m, &l, sizeof (l));
411 v = _vec_resize (0, l, (uword) l*elt_bytes, sizeof (p[0]), align);
414 vec_unserialize (m, &p->free_indices, unserialize_vec_32);
416 /* Construct free bitmap. */
418 for (i = 0; i < vec_len (p->free_indices); i++)
419 p->free_bitmap = clib_bitmap_ori (p->free_bitmap, p->free_indices[i]);
421 pool_foreach_region (lo, hi, v,
422 unserialize (m, f, v + lo*elt_bytes, hi - lo));
427 void unserialize_pool (serialize_main_t * m, va_list * va)
429 void ** result = va_arg (*va, void **);
430 u32 elt_bytes = va_arg (*va, u32);
431 serialize_function_t * f = va_arg (*va, serialize_function_t *);
432 *result = unserialize_pool_helper (m, elt_bytes, /* align */ 0, f);
435 void unserialize_aligned_pool (serialize_main_t * m, va_list * va)
437 void ** result = va_arg (*va, void **);
438 u32 elt_bytes = va_arg (*va, u32);
439 u32 align = va_arg (*va, u32);
440 serialize_function_t * f = va_arg (*va, serialize_function_t *);
441 *result = unserialize_pool_helper (m, elt_bytes, align, f);
444 static void serialize_vec_heap_elt (serialize_main_t * m, va_list * va)
446 heap_elt_t * e = va_arg (*va, heap_elt_t *);
447 u32 i, n = va_arg (*va, u32);
448 for (i = 0; i < n; i++)
450 serialize_integer (m, e[i].offset, sizeof (e[i].offset));
451 serialize_integer (m, e[i].next, sizeof (e[i].next));
452 serialize_integer (m, e[i].prev, sizeof (e[i].prev));
456 static void unserialize_vec_heap_elt (serialize_main_t * m, va_list * va)
458 heap_elt_t * e = va_arg (*va, heap_elt_t *);
459 u32 i, n = va_arg (*va, u32);
460 for (i = 0; i < n; i++)
462 unserialize_integer (m, &e[i].offset, sizeof (e[i].offset));
463 unserialize_integer (m, &e[i].next, sizeof (e[i].next));
464 unserialize_integer (m, &e[i].prev, sizeof (e[i].prev));
468 void serialize_heap (serialize_main_t * m, va_list * va)
470 void * heap = va_arg (*va, void *);
471 serialize_function_t * f = va_arg (*va, serialize_function_t *);
476 serialize_integer (m, l, sizeof (u32));
480 h = heap_header (heap);
482 #define foreach_serialize_heap_header_integer \
483 _ (head) _ (tail) _ (used_count) _ (max_len) _ (flags) _ (elt_bytes)
485 #define _(f) serialize_integer (m, h->f, sizeof (h->f));
486 foreach_serialize_heap_header_integer;
489 serialize_integer (m, vec_len (h->free_lists), sizeof (u32));
490 for (i = 0; i < vec_len (h->free_lists); i++)
491 vec_serialize (m, h->free_lists[i], serialize_vec_32);
493 vec_serialize (m, h->elts, serialize_vec_heap_elt);
494 vec_serialize (m, h->small_free_elt_free_index, serialize_vec_32);
495 vec_serialize (m, h->free_elts, serialize_vec_32);
497 /* Serialize data in heap. */
499 heap_elt_t * e, * end;
500 e = h->elts + h->head;
501 end = h->elts + h->tail;
504 if (! heap_is_free (e))
506 void * v = heap + heap_offset (e) * h->elt_bytes;
507 u32 n = heap_elt_size (heap, e);
508 serialize (m, f, v, n);
517 void unserialize_heap (serialize_main_t * m, va_list * va)
519 void ** result = va_arg (*va, void **);
520 serialize_function_t * f = va_arg (*va, serialize_function_t *);
525 unserialize_integer (m, &vl, sizeof (u32));
532 memset (&h, 0, sizeof (h));
533 #define _(f) unserialize_integer (m, &h.f, sizeof (h.f));
534 foreach_serialize_heap_header_integer;
537 unserialize_integer (m, &fl, sizeof (u32));
538 vec_resize (h.free_lists, fl);
540 for (i = 0; i < vec_len (h.free_lists); i++)
541 vec_unserialize (m, &h.free_lists[i], unserialize_vec_32);
543 vec_unserialize (m, &h.elts, unserialize_vec_heap_elt);
544 vec_unserialize (m, &h.small_free_elt_free_index, unserialize_vec_32);
545 vec_unserialize (m, &h.free_elts, unserialize_vec_32);
547 /* Re-construct used elt bitmap. */
551 vec_foreach (e, h.elts)
553 if (! heap_is_free (e))
554 h.used_elt_bitmap = clib_bitmap_ori (h.used_elt_bitmap, e - h.elts);
558 heap = *result = _heap_new (vl, h.elt_bytes);
559 heap_header (heap)[0] = h;
561 /* Unserialize data in heap. */
563 heap_elt_t * e, * end;
565 end = h.elts + h.tail;
568 if (! heap_is_free (e))
570 void * v = heap + heap_offset (e) * h.elt_bytes;
571 u32 n = heap_elt_size (heap, e);
572 unserialize (m, f, v, n);
581 void serialize_magic (serialize_main_t * m, void * magic, u32 magic_bytes)
584 serialize_integer (m, magic_bytes, sizeof (magic_bytes));
585 p = serialize_get (m, magic_bytes);
586 clib_memcpy (p, magic, magic_bytes);
589 void unserialize_check_magic (serialize_main_t * m, void * magic,
595 unserialize_integer (m, &l, sizeof (l));
596 if (l != magic_bytes)
599 serialize_error_return (m, "bad magic number");
601 d = serialize_get (m, magic_bytes);
602 if (memcmp (magic, d, magic_bytes))
607 va_serialize (serialize_main_t * sm, va_list * va)
609 serialize_main_header_t * m = &sm->header;
610 serialize_function_t * f = va_arg (*va, serialize_function_t *);
611 clib_error_t * error = 0;
613 m->recursion_level += 1;
614 if (m->recursion_level == 1)
616 uword r = clib_setjmp (&m->error_longjmp, 0);
617 error = uword_to_pointer (r, clib_error_t *);
623 m->recursion_level -= 1;
628 serialize (serialize_main_t * m, ...)
630 clib_error_t * error;
634 error = va_serialize (m, &va);
640 unserialize (serialize_main_t * m, ...)
642 clib_error_t * error;
646 error = va_serialize (m, &va);
651 static void * serialize_write_not_inline (serialize_main_header_t * m,
652 serialize_stream_t * s,
653 uword n_bytes_to_write,
656 uword cur_bi, n_left_b, n_left_o;
658 ASSERT (s->current_buffer_index <= s->n_buffer_bytes);
659 cur_bi = s->current_buffer_index;
660 n_left_b = s->n_buffer_bytes - cur_bi;
661 n_left_o = vec_len (s->overflow_buffer);
663 /* Prepend overflow buffer if present. */
665 if (n_left_o > 0 && n_left_b > 0)
667 uword n = clib_min (n_left_b, n_left_o);
668 clib_memcpy (s->buffer + cur_bi, s->overflow_buffer, n);
673 _vec_len (s->overflow_buffer) = 0;
675 vec_delete (s->overflow_buffer, n, 0);
678 /* Call data function when buffer is complete. Data function should
679 dispatch with current buffer and give us a new one to write more
683 s->current_buffer_index = cur_bi;
684 m->data_function (m, s);
685 cur_bi = s->current_buffer_index;
686 n_left_b = s->n_buffer_bytes - cur_bi;
688 } while (n_left_o > 0);
690 if (n_left_o > 0 || n_left_b < n_bytes_to_write)
693 vec_add2 (s->overflow_buffer, r, n_bytes_to_write);
698 s->current_buffer_index = cur_bi + n_bytes_to_write;
699 return s->buffer + cur_bi;
703 static void * serialize_read_not_inline (serialize_main_header_t * m,
704 serialize_stream_t * s,
705 uword n_bytes_to_read,
708 uword cur_bi, cur_oi, n_left_b, n_left_o, n_left_to_read;
710 ASSERT (s->current_buffer_index <= s->n_buffer_bytes);
712 cur_bi = s->current_buffer_index;
713 cur_oi = s->current_overflow_index;
715 n_left_b = s->n_buffer_bytes - cur_bi;
716 n_left_o = vec_len (s->overflow_buffer) - cur_oi;
718 /* Read from overflow? */
719 if (n_left_o >= n_bytes_to_read)
721 s->current_overflow_index = cur_oi + n_bytes_to_read;
722 return vec_elt_at_index (s->overflow_buffer, cur_oi);
725 /* Reset overflow buffer. */
726 if (n_left_o == 0 && s->overflow_buffer)
728 s->current_overflow_index = 0;
729 _vec_len (s->overflow_buffer) = 0;
732 n_left_to_read = n_bytes_to_read;
733 while (n_left_to_read > 0)
737 /* If we don't have enough data between overflow and normal buffer
738 call read function. */
739 if (n_left_o + n_left_b < n_bytes_to_read)
741 /* Save any left over buffer in overflow vector. */
744 vec_add (s->overflow_buffer, s->buffer + cur_bi, n_left_b);
745 n_left_o += n_left_b;
746 n_left_to_read -= n_left_b;
747 /* Advance buffer to end --- even if
748 SERIALIZE_FLAG_NO_ADVANCE_CURRENT_BUFFER_INDEX is set. */
749 cur_bi = s->n_buffer_bytes;
753 if (m->data_function)
755 m->data_function (m, s);
756 cur_bi = s->current_buffer_index;
757 n_left_b = s->n_buffer_bytes - cur_bi;
761 /* For first time through loop return if we have enough data
762 in normal buffer and overflow vector is empty. */
764 && n_left_to_read == n_bytes_to_read
765 && n_left_b >= n_left_to_read)
767 s->current_buffer_index = cur_bi + n_bytes_to_read;
768 return s->buffer + cur_bi;
771 if (! m->data_function
772 || serialize_stream_is_end_of_stream (s))
774 /* This can happen for a peek at end of file.
775 Pad overflow buffer with 0s. */
776 vec_resize (s->overflow_buffer, n_left_to_read);
777 n_left_o += n_left_to_read;
782 /* Copy from buffer to overflow vector. */
783 n = clib_min (n_left_to_read, n_left_b);
784 vec_add (s->overflow_buffer, s->buffer + cur_bi, n);
792 s->current_buffer_index = cur_bi;
793 s->current_overflow_index = cur_oi + n_bytes_to_read;
794 return vec_elt_at_index (s->overflow_buffer, cur_oi);
797 void * serialize_read_write_not_inline (serialize_main_header_t * m,
798 serialize_stream_t * s,
802 return (((flags & SERIALIZE_FLAG_IS_READ) ? serialize_read_not_inline : serialize_write_not_inline)
803 (m, s, n_bytes, flags));
806 static void serialize_read_write_close (serialize_main_header_t * m, serialize_stream_t * s, uword flags)
808 if (serialize_stream_is_end_of_stream (s))
811 if (flags & SERIALIZE_FLAG_IS_WRITE)
812 /* "Write" 0 bytes to flush overflow vector. */
813 serialize_write_not_inline (m, s, /* n bytes */ 0, flags);
815 serialize_stream_set_end_of_stream (s);
817 /* Call it one last time to flush buffer and close. */
818 m->data_function (m, s);
820 vec_free (s->overflow_buffer);
823 void serialize_close (serialize_main_t * m)
824 { serialize_read_write_close (&m->header, &m->stream, SERIALIZE_FLAG_IS_WRITE); }
826 void unserialize_close (serialize_main_t * m)
827 { serialize_read_write_close (&m->header, &m->stream, SERIALIZE_FLAG_IS_READ); }
829 void serialize_open_data (serialize_main_t * m, u8 * data, uword n_data_bytes)
831 memset (m, 0, sizeof (m[0]));
832 m->stream.buffer = data;
833 m->stream.n_buffer_bytes = n_data_bytes;
836 void unserialize_open_data (serialize_main_t * m, u8 * data, uword n_data_bytes)
837 { serialize_open_data (m, data, n_data_bytes); }
839 static void serialize_vector_write (serialize_main_header_t * m, serialize_stream_t * s)
841 if (! serialize_stream_is_end_of_stream (s))
843 /* Double buffer size. */
844 uword l = vec_len (s->buffer);
845 vec_resize (s->buffer, l > 0 ? l : 64);
846 s->n_buffer_bytes = vec_len (s->buffer);
850 void serialize_open_vector (serialize_main_t * m, u8 * vector)
852 memset (m, 0, sizeof (m[0]));
853 m->header.data_function = serialize_vector_write;
854 m->stream.buffer = vector;
855 m->stream.current_buffer_index = 0;
856 m->stream.n_buffer_bytes = vec_len (vector);
859 void * serialize_close_vector (serialize_main_t * m)
861 serialize_stream_t * s = &m->stream;
864 serialize_close (m); /* frees overflow buffer */
867 _vec_len (s->buffer) = s->current_buffer_index;
869 memset (m, 0, sizeof (m[0]));
874 serialize_multiple_1 (serialize_main_t * m,
881 uword n_left = n_data;
885 p = serialize_get (m, 4 * sizeof (d[0]));
886 p[0] = d[0 * data_stride];
887 p[1] = d[1 * data_stride];
888 p[2] = d[2 * data_stride];
889 p[3] = d[3 * data_stride];
891 d += 4 * data_stride;
896 p = serialize_get (m, n_left * sizeof (p[0]));
901 d += 1 * data_stride;
908 serialize_multiple_2 (serialize_main_t * m,
915 uword n_left = n_data;
919 p = serialize_get (m, 4 * sizeof (p[0]));
920 clib_mem_unaligned (p + 0, u16) = clib_host_to_net_mem_u16 (d + 0 * data_stride);
921 clib_mem_unaligned (p + 1, u16) = clib_host_to_net_mem_u16 (d + 1 * data_stride);
922 clib_mem_unaligned (p + 2, u16) = clib_host_to_net_mem_u16 (d + 2 * data_stride);
923 clib_mem_unaligned (p + 3, u16) = clib_host_to_net_mem_u16 (d + 3 * data_stride);
925 d += 4 * data_stride;
930 p = serialize_get (m, n_left * sizeof (p[0]));
933 clib_mem_unaligned (p + 0, u16) = clib_host_to_net_mem_u16 (d + 0 * data_stride);
935 d += 1 * data_stride;
942 serialize_multiple_4 (serialize_main_t * m,
949 uword n_left = n_data;
953 p = serialize_get (m, 4 * sizeof (p[0]));
954 clib_mem_unaligned (p + 0, u32) = clib_host_to_net_mem_u32 (d + 0 * data_stride);
955 clib_mem_unaligned (p + 1, u32) = clib_host_to_net_mem_u32 (d + 1 * data_stride);
956 clib_mem_unaligned (p + 2, u32) = clib_host_to_net_mem_u32 (d + 2 * data_stride);
957 clib_mem_unaligned (p + 3, u32) = clib_host_to_net_mem_u32 (d + 3 * data_stride);
959 d += 4 * data_stride;
964 p = serialize_get (m, n_left * sizeof (p[0]));
967 clib_mem_unaligned (p + 0, u32) = clib_host_to_net_mem_u32 (d + 0 * data_stride);
969 d += 1 * data_stride;
976 unserialize_multiple_1 (serialize_main_t * m,
983 uword n_left = n_data;
987 p = unserialize_get (m, 4 * sizeof (d[0]));
988 d[0 * data_stride] = p[0];
989 d[1 * data_stride] = p[1];
990 d[2 * data_stride] = p[2];
991 d[3 * data_stride] = p[3];
993 d += 4 * data_stride;
998 p = unserialize_get (m, n_left * sizeof (p[0]));
1003 d += 1 * data_stride;
1010 unserialize_multiple_2 (serialize_main_t * m,
1017 uword n_left = n_data;
1021 p = unserialize_get (m, 4 * sizeof (p[0]));
1022 clib_mem_unaligned (d + 0 * data_stride, u16) = clib_net_to_host_mem_u16 (p + 0);
1023 clib_mem_unaligned (d + 1 * data_stride, u16) = clib_net_to_host_mem_u16 (p + 1);
1024 clib_mem_unaligned (d + 2 * data_stride, u16) = clib_net_to_host_mem_u16 (p + 2);
1025 clib_mem_unaligned (d + 3 * data_stride, u16) = clib_net_to_host_mem_u16 (p + 3);
1027 d += 4 * data_stride;
1032 p = unserialize_get (m, n_left * sizeof (p[0]));
1035 clib_mem_unaligned (d + 0 * data_stride, u16) = clib_net_to_host_mem_u16 (p + 0);
1037 d += 1 * data_stride;
1044 unserialize_multiple_4 (serialize_main_t * m,
1051 uword n_left = n_data;
1055 p = unserialize_get (m, 4 * sizeof (p[0]));
1056 clib_mem_unaligned (d + 0 * data_stride, u32) = clib_net_to_host_mem_u32 (p + 0);
1057 clib_mem_unaligned (d + 1 * data_stride, u32) = clib_net_to_host_mem_u32 (p + 1);
1058 clib_mem_unaligned (d + 2 * data_stride, u32) = clib_net_to_host_mem_u32 (p + 2);
1059 clib_mem_unaligned (d + 3 * data_stride, u32) = clib_net_to_host_mem_u32 (p + 3);
1061 d += 4 * data_stride;
1066 p = unserialize_get (m, n_left * sizeof (p[0]));
1069 clib_mem_unaligned (d + 0 * data_stride, u32) = clib_net_to_host_mem_u32 (p + 0);
1071 d += 1 * data_stride;
1082 static void unix_file_write (serialize_main_header_t * m, serialize_stream_t * s)
1086 fd = s->data_function_opaque;
1087 n = write (fd, s->buffer, s->current_buffer_index);
1090 if (! unix_error_is_fatal (errno))
1093 serialize_error (m, clib_error_return_unix (0, "write"));
1095 if (n == s->current_buffer_index)
1096 _vec_len (s->buffer) = 0;
1098 vec_delete (s->buffer, n, 0);
1099 s->current_buffer_index = vec_len (s->buffer);
1102 static void unix_file_read (serialize_main_header_t * m, serialize_stream_t * s)
1106 fd = s->data_function_opaque;
1107 n = read (fd, s->buffer, vec_len (s->buffer));
1110 if (! unix_error_is_fatal (errno))
1113 serialize_error (m, clib_error_return_unix (0, "read"));
1116 serialize_stream_set_end_of_stream (s);
1117 s->current_buffer_index = 0;
1118 s->n_buffer_bytes = n;
1122 serialize_open_unix_file_descriptor_helper (serialize_main_t * m, int fd, uword is_read)
1124 memset (m, 0, sizeof (m[0]));
1125 vec_resize (m->stream.buffer, 4096);
1129 m->stream.n_buffer_bytes = vec_len (m->stream.buffer);
1130 _vec_len (m->stream.buffer) = 0;
1133 m->header.data_function = is_read ? unix_file_read : unix_file_write;
1134 m->stream.data_function_opaque = fd;
1137 void serialize_open_unix_file_descriptor (serialize_main_t * m, int fd)
1138 { serialize_open_unix_file_descriptor_helper (m, fd, /* is_read */ 0); }
1140 void unserialize_open_unix_file_descriptor (serialize_main_t * m, int fd)
1141 { serialize_open_unix_file_descriptor_helper (m, fd, /* is_read */ 1); }
1143 static clib_error_t *
1144 serialize_open_unix_file_helper (serialize_main_t * m, char * file, uword is_read)
1148 mode = is_read ? O_RDONLY : O_RDWR | O_CREAT | O_TRUNC;
1149 fd = open (file, mode, 0666);
1151 return clib_error_return_unix (0, "open `%s'", file);
1153 serialize_open_unix_file_descriptor_helper (m, fd, is_read);
1158 serialize_open_unix_file (serialize_main_t * m, char * file)
1159 { return serialize_open_unix_file_helper (m, file, /* is_read */ 0); }
1162 unserialize_open_unix_file (serialize_main_t * m, char * file)
1163 { return serialize_open_unix_file_helper (m, file, /* is_read */ 1); }
1165 #endif /* CLIB_UNIX */