FD.io VPP  v16.06
Vector Packet Processing
serialize.c
Go to the documentation of this file.
1 /*
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:
6  *
7  * http://www.apache.org/licenses/LICENSE-2.0
8  *
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.
14  */
15 /*
16  Copyright (c) 2005 Eliot Dresselhaus
17 
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:
25 
26  The above copyright notice and this permission notice shall be
27  included in all copies or substantial portions of the Software.
28 
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.
36 */
37 
38 /* Turn data structures into byte streams for saving or transport. */
39 
40 #include <vppinfra/heap.h>
41 #include <vppinfra/pool.h>
42 #include <vppinfra/serialize.h>
43 
44 void serialize_64 (serialize_main_t * m, va_list * va)
45 {
46  u64 x = va_arg (*va, u64);
47  u32 lo, hi;
48  lo = x;
49  hi = x >> 32;
50  serialize_integer (m, lo, sizeof (lo));
51  serialize_integer (m, hi, sizeof (hi));
52 }
53 
54 void serialize_32 (serialize_main_t * m, va_list * va)
55 {
56  u32 x = va_arg (*va, u32);
57  serialize_integer (m, x, sizeof (x));
58 }
59 
60 void serialize_16 (serialize_main_t * m, va_list * va)
61 {
62  u32 x = va_arg (*va, u32);
63  serialize_integer (m, x, sizeof (u16));
64 }
65 
66 void serialize_8 (serialize_main_t * m, va_list * va)
67 {
68  u32 x = va_arg (*va, u32);
69  serialize_integer (m, x, sizeof (u8));
70 }
71 
72 void unserialize_64 (serialize_main_t * m, va_list * va)
73 {
74  u64 * x = va_arg (*va, u64 *);
75  u32 lo, hi;
76  unserialize_integer (m, &lo, sizeof (lo));
77  unserialize_integer (m, &hi, sizeof (hi));
78  *x = ((u64) hi << 32) | (u64) lo;
79 }
80 
81 void unserialize_32 (serialize_main_t * m, va_list * va)
82 {
83  u32 * x = va_arg (*va, u32 *);
84  unserialize_integer (m, x, sizeof (x[0]));
85 }
86 
87 void unserialize_16 (serialize_main_t * m, va_list * va)
88 {
89  u16 * x = va_arg (*va, u16 *);
90  u32 t;
91  unserialize_integer (m, &t, sizeof (x[0]));
92  x[0] = t;
93 }
94 
95 void unserialize_8 (serialize_main_t * m, va_list * va)
96 {
97  u8 * x = va_arg (*va, u8 *);
98  u32 t;
99  unserialize_integer (m, &t, sizeof (x[0]));
100  x[0] = t;
101 }
102 
103 void serialize_f64 (serialize_main_t * m, va_list * va)
104 {
105  f64 x = va_arg (*va, f64);
106  union { f64 f; u64 i; } y;
107  y.f = x;
108  serialize (m, serialize_64, y.i);
109 }
110 
111 void serialize_f32 (serialize_main_t * m, va_list * va)
112 {
113  f32 x = va_arg (*va, f64);
114  union { f32 f; u32 i; } y;
115  y.f = x;
116  serialize_integer (m, y.i, sizeof (y.i));
117 }
118 
119 void unserialize_f64 (serialize_main_t * m, va_list * va)
120 {
121  f64 * x = va_arg (*va, f64 *);
122  union { f64 f; u64 i; } y;
123  unserialize (m, unserialize_64, &y.i);
124  *x = y.f;
125 }
126 
127 void unserialize_f32 (serialize_main_t * m, va_list * va)
128 {
129  f32 * x = va_arg (*va, f32 *);
130  union { f32 f; u32 i; } y;
131  unserialize_integer (m, &y.i, sizeof (y.i));
132  *x = y.f;
133 }
134 
136 {
137  u32 len = s ? strlen (s) : 0;
138  void * p;
139 
141  if (len > 0)
142  {
143  p = serialize_get (m, len);
144  clib_memcpy (p, s, len);
145  }
146 }
147 
149 {
150  char * p, * r = 0;
151  u32 len;
152 
154 
155  /*
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.
159  */
160  if (len > 0 && len != 0xFFFFFFFF)
161  {
162  r = vec_new (char, len + 1);
163  p = unserialize_get (m, len);
164  clib_memcpy (r, p, len);
165 
166  /* Null terminate. */
167  r[len] = 0;
168  }
169  *s = r;
170 }
171 
172 /* vec_serialize/vec_unserialize helper functions for basic vector types. */
173 void serialize_vec_8 (serialize_main_t * m, va_list * va)
174 {
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));
179 }
180 
181 void unserialize_vec_8 (serialize_main_t * m, va_list * va)
182 {
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);
187 }
188 
189 #define _(n_bits) \
190  void serialize_vec_##n_bits (serialize_main_t * m, va_list * va) \
191  { \
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])); \
195  \
196  while (n >= 4) \
197  { \
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]); \
202  s += 4; \
203  p += 4; \
204  n -= 4; \
205  } \
206  \
207  while (n >= 1) \
208  { \
209  p[0] = clib_host_to_net_u##n_bits (s[0]); \
210  s += 1; \
211  p += 1; \
212  n -= 1; \
213  } \
214  } \
215  \
216  void unserialize_vec_##n_bits (serialize_main_t * m, va_list * va) \
217  { \
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])); \
221  \
222  while (n >= 4) \
223  { \
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]); \
228  s += 4; \
229  p += 4; \
230  n -= 4; \
231  } \
232  \
233  while (n >= 1) \
234  { \
235  s[0] = clib_net_to_host_mem_u##n_bits (&p[0]); \
236  s += 1; \
237  p += 1; \
238  n -= 1; \
239  } \
240  }
241 
242 _ (16);
243 _ (32);
244 _ (64);
245 
246 #undef _
247 
248 #define SERIALIZE_VECTOR_CHUNK_SIZE 64
249 
250 void serialize_vector (serialize_main_t * m, va_list * va)
251 {
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);
256  void * p = vec;
257 
258  serialize_integer (m, l, sizeof (l));
259 
260  /* Serialize vector in chunks for cache locality. */
261  while (l != 0)
262  {
264  serialize (m, f, p, n);
265  l -= n;
266  p += SERIALIZE_VECTOR_CHUNK_SIZE * elt_bytes;
267  }
268 }
269 
270 void *
272  u32 elt_bytes,
273  u32 header_bytes,
274  u32 align,
275  u32 max_length,
277 {
278  void * v, * p;
279  u32 l;
280 
281  unserialize_integer (m, &l, sizeof (l));
282  if (l > max_length)
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);
285 
286  while (l != 0)
287  {
289  unserialize (m, f, p, n);
290  l -= n;
291  p += SERIALIZE_VECTOR_CHUNK_SIZE * elt_bytes;
292  }
293  return v;
294 }
295 
297 {
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);
302 
303  *vec = unserialize_vector_ha (m, elt_bytes,
304  /* header_bytes */ 0,
305  /* align */ align,
306  /* max_length */ ~0,
307  f);
308 }
309 
310 void unserialize_vector (serialize_main_t * m, va_list * va)
311 {
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 *);
315 
316  *vec = unserialize_vector_ha (m, elt_bytes,
317  /* header_bytes */ 0,
318  /* align */ 0,
319  /* max_length */ ~0,
320  f);
321 }
322 
324 {
325  u32 l, i, n_u32s;
326 
327  l = vec_len (b);
328  n_u32s = l * sizeof (b[0]) / sizeof (u32);
329  serialize_integer (m, n_u32s, sizeof (n_u32s));
330 
331  /* Send 32 bit words, low-order word first on 64 bit. */
332  for (i = 0; i < l; i++)
333  {
334  serialize_integer (m, b[i], sizeof (u32));
335  if (BITS (uword) == 64)
336  serialize_integer (m, (u64) b[i] >> (u64) 32, sizeof (u32));
337  }
338 }
339 
341 {
342  uword * b = 0;
343  u32 i, n_u32s;
344 
345  unserialize_integer (m, &n_u32s, sizeof (n_u32s));
346  if (n_u32s == 0)
347  return b;
348 
349  i = (n_u32s * sizeof (u32) + sizeof (b[0]) - 1) / sizeof (b[0]);
350  vec_resize (b, i);
351  for (i = 0; i < n_u32s; i++)
352  {
353  u32 data;
354  unserialize_integer (m, &data, sizeof (u32));
355 
356  /* Low-word is first on 64 bit. */
357  if (BITS (uword) == 64)
358  {
359  if ((i % 2) == 0)
360  b[i/2] |= (u64) data << (u64) 0;
361  else
362  b[i/2] |= (u64) data << (u64) 32;
363  }
364  else
365  {
366  b[i] = data;
367  }
368  }
369 
370  return b;
371 }
372 
373 void serialize_pool (serialize_main_t * m, va_list * va)
374 {
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 *);
378  u32 l, lo, hi;
379  pool_header_t * p;
380 
381  l = vec_len (pool);
382  serialize_integer (m, l, sizeof (u32));
383  if (l == 0)
384  return;
385  p = pool_header (pool);
386 
387  /* No need to send free bitmap. Need to send index vector
388  to guarantee that unserialized pool will be identical. */
390 
391  pool_foreach_region (lo, hi, pool,
392  serialize (m, f, pool + lo*elt_bytes, hi - lo));
393 }
394 
395 static void *
397  u32 elt_bytes, u32 align,
399 {
400  void * v;
401  u32 i, l, lo, hi;
402  pool_header_t * p;
403 
404  unserialize_integer (m, &l, sizeof (l));
405  if (l == 0)
406  {
407  return 0;
408  }
409 
410  v = _vec_resize (0, l, l*elt_bytes, sizeof (p[0]), align);
411  p = pool_header (v);
412 
414 
415  /* Construct free bitmap. */
416  p->free_bitmap = 0;
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]);
419 
420  pool_foreach_region (lo, hi, v,
421  unserialize (m, f, v + lo*elt_bytes, hi - lo));
422 
423  return v;
424 }
425 
426 void unserialize_pool (serialize_main_t * m, va_list * va)
427 {
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);
432 }
433 
435 {
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);
441 }
442 
443 static void serialize_vec_heap_elt (serialize_main_t * m, va_list * va)
444 {
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++)
448  {
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));
452  }
453 }
454 
455 static void unserialize_vec_heap_elt (serialize_main_t * m, va_list * va)
456 {
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++)
460  {
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));
464  }
465 }
466 
467 void serialize_heap (serialize_main_t * m, va_list * va)
468 {
469  void * heap = va_arg (*va, void *);
470  serialize_function_t * f = va_arg (*va, serialize_function_t *);
471  u32 i, l;
472  heap_header_t * h;
473 
474  l = vec_len (heap);
475  serialize_integer (m, l, sizeof (u32));
476  if (l == 0)
477  return;
478 
479  h = heap_header (heap);
480 
481 #define foreach_serialize_heap_header_integer \
482  _ (head) _ (tail) _ (used_count) _ (max_len) _ (flags) _ (elt_bytes)
483 
484 #define _(f) serialize_integer (m, h->f, sizeof (h->f));
486 #undef _
487 
488  serialize_integer (m, vec_len (h->free_lists), sizeof (u32));
489  for (i = 0; i < vec_len (h->free_lists); i++)
491 
495 
496  /* Serialize data in heap. */
497  {
498  heap_elt_t * e, * end;
499  e = h->elts + h->head;
500  end = h->elts + h->tail;
501  while (1)
502  {
503  if (! heap_is_free (e))
504  {
505  void * v = heap + heap_offset (e) * h->elt_bytes;
506  u32 n = heap_elt_size (heap, e);
507  serialize (m, f, v, n);
508  }
509  if (e == end)
510  break;
511  e = heap_next (e);
512  }
513  }
514 }
515 
516 void unserialize_heap (serialize_main_t * m, va_list * va)
517 {
518  void ** result = va_arg (*va, void **);
519  serialize_function_t * f = va_arg (*va, serialize_function_t *);
520  u32 i, vl, fl;
521  heap_header_t h;
522  void * heap;
523 
524  unserialize_integer (m, &vl, sizeof (u32));
525  if (vl == 0)
526  {
527  *result = 0;
528  return;
529  }
530 
531  memset (&h, 0, sizeof (h));
532 #define _(f) unserialize_integer (m, &h.f, sizeof (h.f));
534 #undef _
535 
536  unserialize_integer (m, &fl, sizeof (u32));
537  vec_resize (h.free_lists, fl);
538 
539  for (i = 0; i < vec_len (h.free_lists); i++)
541 
545 
546  /* Re-construct used elt bitmap. */
547  if (CLIB_DEBUG > 0)
548  {
549  heap_elt_t * e;
550  vec_foreach (e, h.elts)
551  {
552  if (! heap_is_free (e))
553  h.used_elt_bitmap = clib_bitmap_ori (h.used_elt_bitmap, e - h.elts);
554  }
555  }
556 
557  heap = *result = _heap_new (vl, h.elt_bytes);
558  heap_header (heap)[0] = h;
559 
560  /* Unserialize data in heap. */
561  {
562  heap_elt_t * e, * end;
563  e = h.elts + h.head;
564  end = h.elts + h.tail;
565  while (1)
566  {
567  if (! heap_is_free (e))
568  {
569  void * v = heap + heap_offset (e) * h.elt_bytes;
570  u32 n = heap_elt_size (heap, e);
571  unserialize (m, f, v, n);
572  }
573  if (e == end)
574  break;
575  e = heap_next (e);
576  }
577  }
578 }
579 
580 void serialize_magic (serialize_main_t * m, void * magic, u32 magic_bytes)
581 {
582  void * p;
583  serialize_integer (m, magic_bytes, sizeof (magic_bytes));
584  p = serialize_get (m, magic_bytes);
585  clib_memcpy (p, magic, magic_bytes);
586 }
587 
589  u32 magic_bytes)
590 {
591  u32 l;
592  void * d;
593 
594  unserialize_integer (m, &l, sizeof (l));
595  if (l != magic_bytes)
596  {
597  bad:
598  serialize_error_return (m, "bad magic number");
599  }
600  d = serialize_get (m, magic_bytes);
601  if (memcmp (magic, d, magic_bytes))
602  goto bad;
603 }
604 
605 clib_error_t *
606 va_serialize (serialize_main_t * sm, va_list * va)
607 {
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;
611 
612  m->recursion_level += 1;
613  if (m->recursion_level == 1)
614  {
615  uword r = clib_setjmp (&m->error_longjmp, 0);
616  error = uword_to_pointer (r, clib_error_t *);
617  }
618 
619  if (! error)
620  f (sm, va);
621 
622  m->recursion_level -= 1;
623  return error;
624 }
625 
626 clib_error_t *
628 {
629  clib_error_t * error;
630  va_list va;
631 
632  va_start (va, m);
633  error = va_serialize (m, &va);
634  va_end (va);
635  return error;
636 }
637 
638 clib_error_t *
640 {
641  clib_error_t * error;
642  va_list va;
643 
644  va_start (va, m);
645  error = va_serialize (m, &va);
646  va_end (va);
647  return error;
648 }
649 
651  serialize_stream_t * s,
652  uword n_bytes_to_write,
653  uword flags)
654 {
655  uword cur_bi, n_left_b, n_left_o;
656 
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);
661 
662  /* Prepend overflow buffer if present. */
663  do {
664  if (n_left_o > 0 && n_left_b > 0)
665  {
666  uword n = clib_min (n_left_b, n_left_o);
667  clib_memcpy (s->buffer + cur_bi, s->overflow_buffer, n);
668  cur_bi += n;
669  n_left_b -= n;
670  n_left_o -= n;
671  if (n_left_o == 0)
672  _vec_len (s->overflow_buffer) = 0;
673  else
674  vec_delete (s->overflow_buffer, n, 0);
675  }
676 
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
679  data into. */
680  if (n_left_b == 0)
681  {
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;
686  }
687  } while (n_left_o > 0);
688 
689  if (n_left_o > 0 || n_left_b < n_bytes_to_write)
690  {
691  u8 * r;
692  vec_add2 (s->overflow_buffer, r, n_bytes_to_write);
693  return r;
694  }
695  else
696  {
697  s->current_buffer_index = cur_bi + n_bytes_to_write;
698  return s->buffer + cur_bi;
699  }
700 }
701 
703  serialize_stream_t * s,
704  uword n_bytes_to_read,
705  uword flags)
706 {
707  uword cur_bi, cur_oi, n_left_b, n_left_o, n_left_to_read;
708 
710 
711  cur_bi = s->current_buffer_index;
712  cur_oi = s->current_overflow_index;
713 
714  n_left_b = s->n_buffer_bytes - cur_bi;
715  n_left_o = vec_len (s->overflow_buffer) - cur_oi;
716 
717  /* Read from overflow? */
718  if (n_left_o >= n_bytes_to_read)
719  {
720  s->current_overflow_index = cur_oi + n_bytes_to_read;
721  return vec_elt_at_index (s->overflow_buffer, cur_oi);
722  }
723 
724  /* Reset overflow buffer. */
725  if (n_left_o == 0 && s->overflow_buffer)
726  {
727  s->current_overflow_index = 0;
728  _vec_len (s->overflow_buffer) = 0;
729  }
730 
731  n_left_to_read = n_bytes_to_read;
732  while (n_left_to_read > 0)
733  {
734  uword n;
735 
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)
739  {
740  /* Save any left over buffer in overflow vector. */
741  if (n_left_b > 0)
742  {
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;
749  n_left_b = 0;
750  }
751 
752  if (m->data_function)
753  {
754  m->data_function (m, s);
755  cur_bi = s->current_buffer_index;
756  n_left_b = s->n_buffer_bytes - cur_bi;
757  }
758  }
759 
760  /* For first time through loop return if we have enough data
761  in normal buffer and overflow vector is empty. */
762  if (n_left_o == 0
763  && n_left_to_read == n_bytes_to_read
764  && n_left_b >= n_left_to_read)
765  {
766  s->current_buffer_index = cur_bi + n_bytes_to_read;
767  return s->buffer + cur_bi;
768  }
769 
770  if (! m->data_function
772  {
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;
777  n_left_to_read = 0;
778  }
779  else
780  {
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);
784  cur_bi += n;
785  n_left_b -= n;
786  n_left_o += n;
787  n_left_to_read -= n;
788  }
789  }
790 
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);
794 }
795 
797  serialize_stream_t * s,
798  uword n_bytes,
799  uword flags)
800 {
802  (m, s, n_bytes, flags));
803 }
804 
806 {
808  return;
809 
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);
813 
815 
816  /* Call it one last time to flush buffer and close. */
817  m->data_function (m, s);
818 
820 }
821 
824 
827 
828 void serialize_open_data (serialize_main_t * m, u8 * data, uword n_data_bytes)
829 {
830  memset (m, 0, sizeof (m[0]));
831  m->stream.buffer = data;
832  m->stream.n_buffer_bytes = n_data_bytes;
833 }
834 
835 void unserialize_open_data (serialize_main_t * m, u8 * data, uword n_data_bytes)
836 { serialize_open_data (m, data, n_data_bytes); }
837 
839 {
841  {
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);
846  }
847 }
848 
850 {
851  memset (m, 0, sizeof (m[0]));
853  m->stream.buffer = vector;
855  m->stream.n_buffer_bytes = vec_len (vector);
856 }
857 
859 {
860  serialize_stream_t * s = &m->stream;
861  void * result;
862 
863  serialize_close (m); /* frees overflow buffer */
864 
865  if (s->buffer)
866  _vec_len (s->buffer) = s->current_buffer_index;
867  result = s->buffer;
868  memset (m, 0, sizeof (m[0]));
869  return result;
870 }
871 
872 void
874  void * data,
875  uword data_stride,
876  uword n_data)
877 {
878  u8 * d = data;
879  u8 * p;
880  uword n_left = n_data;
881 
882  while (n_left >= 4)
883  {
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];
889  n_left -= 4;
890  d += 4 * data_stride;
891  }
892 
893  if (n_left > 0)
894  {
895  p = serialize_get (m, n_left * sizeof (p[0]));
896  while (n_left > 0)
897  {
898  p[0] = d[0];
899  p += 1;
900  d += 1 * data_stride;
901  n_left -= 1;
902  }
903  }
904 }
905 
906 void
908  void * data,
909  uword data_stride,
910  uword n_data)
911 {
912  void * d = data;
913  u16 * p;
914  uword n_left = n_data;
915 
916  while (n_left >= 4)
917  {
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);
923  n_left -= 4;
924  d += 4 * data_stride;
925  }
926 
927  if (n_left > 0)
928  {
929  p = serialize_get (m, n_left * sizeof (p[0]));
930  while (n_left > 0)
931  {
932  clib_mem_unaligned (p + 0, u16) = clib_host_to_net_mem_u16 (d + 0 * data_stride);
933  p += 1;
934  d += 1 * data_stride;
935  n_left -= 1;
936  }
937  }
938 }
939 
940 void
942  void * data,
943  uword data_stride,
944  uword n_data)
945 {
946  void * d = data;
947  u32 * p;
948  uword n_left = n_data;
949 
950  while (n_left >= 4)
951  {
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);
957  n_left -= 4;
958  d += 4 * data_stride;
959  }
960 
961  if (n_left > 0)
962  {
963  p = serialize_get (m, n_left * sizeof (p[0]));
964  while (n_left > 0)
965  {
966  clib_mem_unaligned (p + 0, u32) = clib_host_to_net_mem_u32 (d + 0 * data_stride);
967  p += 1;
968  d += 1 * data_stride;
969  n_left -= 1;
970  }
971  }
972 }
973 
974 void
976  void * data,
977  uword data_stride,
978  uword n_data)
979 {
980  u8 * d = data;
981  u8 * p;
982  uword n_left = n_data;
983 
984  while (n_left >= 4)
985  {
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];
991  n_left -= 4;
992  d += 4 * data_stride;
993  }
994 
995  if (n_left > 0)
996  {
997  p = unserialize_get (m, n_left * sizeof (p[0]));
998  while (n_left > 0)
999  {
1000  d[0] = p[0];
1001  p += 1;
1002  d += 1 * data_stride;
1003  n_left -= 1;
1004  }
1005  }
1006 }
1007 
1008 void
1010  void * data,
1011  uword data_stride,
1012  uword n_data)
1013 {
1014  void * d = data;
1015  u16 * p;
1016  uword n_left = n_data;
1017 
1018  while (n_left >= 4)
1019  {
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);
1025  n_left -= 4;
1026  d += 4 * data_stride;
1027  }
1028 
1029  if (n_left > 0)
1030  {
1031  p = unserialize_get (m, n_left * sizeof (p[0]));
1032  while (n_left > 0)
1033  {
1034  clib_mem_unaligned (d + 0 * data_stride, u16) = clib_net_to_host_mem_u16 (p + 0);
1035  p += 1;
1036  d += 1 * data_stride;
1037  n_left -= 1;
1038  }
1039  }
1040 }
1041 
1042 void
1044  void * data,
1045  uword data_stride,
1046  uword n_data)
1047 {
1048  void * d = data;
1049  u32 * p;
1050  uword n_left = n_data;
1051 
1052  while (n_left >= 4)
1053  {
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);
1059  n_left -= 4;
1060  d += 4 * data_stride;
1061  }
1062 
1063  if (n_left > 0)
1064  {
1065  p = unserialize_get (m, n_left * sizeof (p[0]));
1066  while (n_left > 0)
1067  {
1068  clib_mem_unaligned (d + 0 * data_stride, u32) = clib_net_to_host_mem_u32 (p + 0);
1069  p += 1;
1070  d += 1 * data_stride;
1071  n_left -= 1;
1072  }
1073  }
1074 }
1075 
1076 #ifdef CLIB_UNIX
1077 
1078 #include <unistd.h>
1079 #include <fcntl.h>
1080 
1082 {
1083  int fd, n;
1084 
1085  fd = s->data_function_opaque;
1086  n = write (fd, s->buffer, s->current_buffer_index);
1087  if (n < 0)
1088  {
1089  if (! unix_error_is_fatal (errno))
1090  n = 0;
1091  else
1092  serialize_error (m, clib_error_return_unix (0, "write"));
1093  }
1094  if (n == s->current_buffer_index)
1095  _vec_len (s->buffer) = 0;
1096  else
1097  vec_delete (s->buffer, n, 0);
1099 }
1100 
1102 {
1103  int fd, n;
1104 
1105  fd = s->data_function_opaque;
1106  n = read (fd, s->buffer, vec_len (s->buffer));
1107  if (n < 0)
1108  {
1109  if (! unix_error_is_fatal (errno))
1110  n = 0;
1111  else
1112  serialize_error (m, clib_error_return_unix (0, "read"));
1113  }
1114  else if (n == 0)
1116  s->current_buffer_index = 0;
1117  s->n_buffer_bytes = n;
1118 }
1119 
1120 static void
1122 {
1123  memset (m, 0, sizeof (m[0]));
1124  vec_resize (m->stream.buffer, 4096);
1125 
1126  if (! is_read)
1127  {
1129  _vec_len (m->stream.buffer) = 0;
1130  }
1131 
1133  m->stream.data_function_opaque = fd;
1134 }
1135 
1137 { serialize_open_unix_file_descriptor_helper (m, fd, /* is_read */ 0); }
1138 
1140 { serialize_open_unix_file_descriptor_helper (m, fd, /* is_read */ 1); }
1141 
1142 static clib_error_t *
1144 {
1145  int fd, mode;
1146 
1147  mode = is_read ? O_RDONLY : O_RDWR | O_CREAT | O_TRUNC;
1148  fd = open (file, mode, 0666);
1149  if (fd < 0)
1150  return clib_error_return_unix (0, "open `%s'", file);
1151 
1153  return 0;
1154 }
1155 
1156 clib_error_t *
1158 { return serialize_open_unix_file_helper (m, file, /* is_read */ 0); }
1159 
1160 clib_error_t *
1162 { return serialize_open_unix_file_helper (m, file, /* is_read */ 1); }
1163 
1164 #endif /* CLIB_UNIX */
vmrglw vmrglh hi
static void serialize_vector_write(serialize_main_header_t *m, serialize_stream_t *s)
Definition: serialize.c:838
sll srl srl sll sra u16x4 i
Definition: vector_sse2.h:267
#define clib_min(x, y)
Definition: clib.h:295
void serialize_f32(serialize_main_t *m, va_list *va)
Definition: serialize.c:111
void unserialize_check_magic(serialize_main_t *m, void *magic, u32 magic_bytes)
Definition: serialize.c:588
u32 current_overflow_index
Definition: serialize.h:68
#define serialize_error_return(m, args...)
Definition: serialize.h:103
void serialize_bitmap(serialize_main_t *m, uword *b)
Definition: serialize.c:323
void serialize_multiple_4(serialize_main_t *m, void *data, uword data_stride, uword n_data)
Definition: serialize.c:941
#define vec_serialize(m, v, f)
Definition: serialize.h:367
serialize_main_header_t header
Definition: serialize.h:137
#define vec_unserialize(m, v, f)
Definition: serialize.h:370
always_inline void serialize_likely_small_unsigned_integer(serialize_main_t *m, u64 x)
Definition: serialize.h:198
u32 * free_indices
Definition: pool.h:54
u32 tail
Definition: heap.h:129
void unserialize_32(serialize_main_t *m, va_list *va)
Definition: serialize.c:81
void unserialize_multiple_2(serialize_main_t *m, void *data, uword data_stride, uword n_data)
Definition: serialize.c:1009
void serialize_f64(serialize_main_t *m, va_list *va)
Definition: serialize.c:103
#define vec_add2(V, P, N)
Add N elements to end of vector V, return pointer to new elements in P.
Definition: vec.h:519
static clib_error_t * serialize_open_unix_file_helper(serialize_main_t *m, char *file, uword is_read)
Definition: serialize.c:1143
u32 head
Definition: heap.h:129
add_epi add_epi sub_epi sub_epi adds_epu subs_epu i16x8 y
Definition: vector_sse2.h:231
uword clib_setjmp(clib_longjmp_t *save, uword return_value_not_taken)
static void unix_file_read(serialize_main_header_t *m, serialize_stream_t *s)
Definition: serialize.c:1101
always_inline heap_elt_t * heap_next(heap_elt_t *e)
Definition: heap.h:89
#define vec_add(V, E, N)
Add N elements to end of vector V (no header, unspecified alignment)
Definition: vec.h:557
always_inline uword heap_is_free(heap_elt_t *e)
Definition: heap.h:83
float f32
Definition: types.h:141
u32 * free_elts
Definition: heap.h:118
always_inline heap_header_t * heap_header(void *v)
Definition: heap.h:145
#define SERIALIZE_VECTOR_CHUNK_SIZE
Definition: serialize.c:248
#define foreach_serialize_heap_header_integer
void * unserialize_vector_ha(serialize_main_t *m, u32 elt_bytes, u32 header_bytes, u32 align, u32 max_length, serialize_function_t *f)
Definition: serialize.c:271
clib_error_t * serialize_open_unix_file(serialize_main_t *m, char *file)
Definition: serialize.c:1157
always_inline void serialize_stream_set_end_of_stream(serialize_stream_t *s)
Definition: serialize.h:79
clib_error_t * unserialize_open_unix_file(serialize_main_t *m, char *file)
Definition: serialize.c:1161
void unserialize_open_data(serialize_main_t *m, u8 *data, uword n_data_bytes)
Definition: serialize.c:835
#define vec_new(T, N)
Create new vector of given type and length (unspecified alignment, no header).
Definition: vec.h:268
void unserialize_heap(serialize_main_t *m, va_list *va)
Definition: serialize.c:516
always_inline void unserialize_integer(serialize_main_t *m, void *x, u32 n_bytes)
Definition: serialize.h:181
#define vec_elt_at_index(v, i)
Get vector value at index i checking that i is in bounds.
void unserialize_aligned_vector(serialize_main_t *m, va_list *va)
Definition: serialize.c:296
unsigned long u64
Definition: types.h:89
#define vec_resize(V, N)
Resize a vector (no header, unspecified alignment) Add N elements to end of given vector V...
Definition: vec.h:199
always_inline uword heap_offset(heap_elt_t *e)
Definition: heap.h:86
static void * serialize_read_not_inline(serialize_main_header_t *m, serialize_stream_t *s, uword n_bytes_to_read, uword flags)
Definition: serialize.c:702
uword * used_elt_bitmap
Definition: heap.h:126
void serialize_16(serialize_main_t *m, va_list *va)
Definition: serialize.c:60
always_inline void serialize_error(serialize_main_header_t *m, clib_error_t *error)
Definition: serialize.h:100
#define SERIALIZE_FLAG_IS_READ
Definition: serialize.h:110
void unserialize_vec_8(serialize_main_t *m, va_list *va)
Definition: serialize.c:181
serialize_function_t serialize_vec_32
Definition: serialize.h:361
always_inline uword serialize_stream_is_end_of_stream(serialize_stream_t *s)
Definition: serialize.h:83
void serialize_open_data(serialize_main_t *m, u8 *data, uword n_data_bytes)
Definition: serialize.c:828
void serialize_pool(serialize_main_t *m, va_list *va)
Definition: serialize.c:373
void unserialize_multiple_4(serialize_main_t *m, void *data, uword data_stride, uword n_data)
Definition: serialize.c:1043
u32 vl(void *v)
Definition: pfhash.c:22
#define clib_error_return_unix(e, args...)
Definition: error.h:115
heap_elt_t * elts
Definition: heap.h:111
void unserialize_8(serialize_main_t *m, va_list *va)
Definition: serialize.c:95
always_inline void * unserialize_get(serialize_main_t *m, uword n_bytes)
Definition: serialize.h:157
void serialize_8(serialize_main_t *m, va_list *va)
Definition: serialize.c:66
#define clib_error_create(args...)
Definition: error.h:109
always_inline word unix_error_is_fatal(word error)
Definition: error.h:130
static void serialize_read_write_close(serialize_main_header_t *m, serialize_stream_t *s, uword flags)
Definition: serialize.c:805
void unserialize_open_unix_file_descriptor(serialize_main_t *m, int fd)
Definition: serialize.c:1139
void unserialize_cstring(serialize_main_t *m, char **s)
Definition: serialize.c:148
void * serialize_read_write_not_inline(serialize_main_header_t *m, serialize_stream_t *s, uword n_bytes, uword flags)
Definition: serialize.c:796
#define uword_to_pointer(u, type)
Definition: types.h:134
u32 elt_bytes
Definition: heap.h:134
serialize_stream_t stream
Definition: serialize.h:138
clib_error_t * serialize(serialize_main_t *m,...)
Definition: serialize.c:627
u32 current_buffer_index
Definition: serialize.h:61
void serialize_open_vector(serialize_main_t *m, u8 *vector)
Definition: serialize.c:849
#define vec_free(V)
Free vector&#39;s memory (no header).
Definition: vec.h:298
#define clib_memcpy(a, b, c)
Definition: string.h:63
serialize_data_function_t * data_function
Definition: serialize.h:90
always_inline void serialize_integer(serialize_main_t *m, u64 x, u32 n_bytes)
Definition: serialize.h:165
void unserialize_close(serialize_main_t *m)
Definition: serialize.c:825
static void serialize_vec_heap_elt(serialize_main_t *m, va_list *va)
Definition: serialize.c:443
uword data_function_opaque
Definition: serialize.h:73
u32 * small_free_elt_free_index
Definition: heap.h:115
void serialize_multiple_2(serialize_main_t *m, void *data, uword data_stride, uword n_data)
Definition: serialize.c:907
void serialize_magic(serialize_main_t *m, void *magic, u32 magic_bytes)
Definition: serialize.c:580
void unserialize_16(serialize_main_t *m, va_list *va)
Definition: serialize.c:87
void serialize_vec_8(serialize_main_t *m, va_list *va)
Definition: serialize.c:173
#define ASSERT(truth)
void unserialize_aligned_pool(serialize_main_t *m, va_list *va)
Definition: serialize.c:434
unsigned int u32
Definition: types.h:88
void unserialize_multiple_1(serialize_main_t *m, void *data, uword data_stride, uword n_data)
Definition: serialize.c:975
void serialize_open_unix_file_descriptor(serialize_main_t *m, int fd)
Definition: serialize.c:1136
#define vec_delete(V, N, M)
Delete N elements starting at element M.
Definition: vec.h:743
void serialize_close(serialize_main_t *m)
Definition: serialize.c:822
#define pool_foreach_region(LO, HI, POOL, BODY)
Definition: pool.h:260
clib_error_t * unserialize(serialize_main_t *m,...)
Definition: serialize.c:639
always_inline pool_header_t * pool_header(void *v)
Definition: pool.h:62
u64 uword
Definition: types.h:112
void serialize_cstring(serialize_main_t *m, char *s)
Definition: serialize.c:135
static void unserialize_vec_heap_elt(serialize_main_t *m, va_list *va)
Definition: serialize.c:455
uword * free_bitmap
Definition: pool.h:51
void serialize_32(serialize_main_t *m, va_list *va)
Definition: serialize.c:54
static void * serialize_write_not_inline(serialize_main_header_t *m, serialize_stream_t *s, uword n_bytes_to_write, uword flags)
Definition: serialize.c:650
unsigned short u16
Definition: types.h:57
void unserialize_f64(serialize_main_t *m, va_list *va)
Definition: serialize.c:119
void unserialize_vector(serialize_main_t *m, va_list *va)
Definition: serialize.c:310
void unserialize_f32(serialize_main_t *m, va_list *va)
Definition: serialize.c:127
uword * unserialize_bitmap(serialize_main_t *m)
Definition: serialize.c:340
#define vec_len(v)
Number of elements in vector (rvalue-only, NULL tolerant)
double f64
Definition: types.h:140
void( serialize_function_t)(serialize_main_t *m, va_list *va)
Definition: serialize.h:154
unsigned char u8
Definition: types.h:56
void serialize_heap(serialize_main_t *m, va_list *va)
Definition: serialize.c:467
void serialize_vector(serialize_main_t *m, va_list *va)
Definition: serialize.c:250
always_inline uword heap_elt_size(void *v, heap_elt_t *e)
Definition: heap.h:95
static void serialize_open_unix_file_descriptor_helper(serialize_main_t *m, int fd, uword is_read)
Definition: serialize.c:1121
static void unix_file_write(serialize_main_header_t *m, serialize_stream_t *s)
Definition: serialize.c:1081
clib_error_t * va_serialize(serialize_main_t *sm, va_list *va)
Definition: serialize.c:606
void unserialize_pool(serialize_main_t *m, va_list *va)
Definition: serialize.c:426
static void * unserialize_pool_helper(serialize_main_t *m, u32 elt_bytes, u32 align, serialize_function_t *f)
Definition: serialize.c:396
#define SERIALIZE_FLAG_IS_WRITE
Definition: serialize.h:111
#define clib_mem_unaligned(pointer, type)
Definition: types.h:153
#define vec_foreach(var, vec)
Vector iterator.
always_inline void * serialize_get(serialize_main_t *m, uword n_bytes)
Definition: serialize.h:161
void * serialize_close_vector(serialize_main_t *m)
Definition: serialize.c:858
always_inline u64 unserialize_likely_small_unsigned_integer(serialize_main_t *m)
Definition: serialize.h:234
void unserialize_64(serialize_main_t *m, va_list *va)
Definition: serialize.c:72
u32 flags
Definition: vhost-user.h:73
#define BITS(x)
Definition: clib.h:58
void serialize_64(serialize_main_t *m, va_list *va)
Definition: serialize.c:44
void serialize_multiple_1(serialize_main_t *m, void *data, uword data_stride, uword n_data)
Definition: serialize.c:873
clib_longjmp_t error_longjmp
Definition: serialize.h:96
serialize_function_t unserialize_vec_32
Definition: serialize.h:361
u32 ** free_lists
Definition: heap.h:121