LCOV - code coverage report
Current view: top level - vppinfra - serialize.c (source / functions) Hit Total Coverage
Test: coverage-filtered.info Lines: 84 590 14.2 %
Date: 2023-07-05 22:20:52 Functions: 11 66 16.7 %

          Line data    Source code
       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
      45           0 : serialize_64 (serialize_main_t * m, va_list * va)
      46             : {
      47           0 :   u64 x = va_arg (*va, u64);
      48             :   u32 lo, hi;
      49           0 :   lo = x;
      50           0 :   hi = x >> 32;
      51           0 :   serialize_integer (m, lo, sizeof (lo));
      52           0 :   serialize_integer (m, hi, sizeof (hi));
      53           0 : }
      54             : 
      55             : void
      56           0 : serialize_32 (serialize_main_t * m, va_list * va)
      57             : {
      58           0 :   u32 x = va_arg (*va, u32);
      59           0 :   serialize_integer (m, x, sizeof (x));
      60           0 : }
      61             : 
      62             : void
      63           0 : serialize_16 (serialize_main_t * m, va_list * va)
      64             : {
      65           0 :   u32 x = va_arg (*va, u32);
      66           0 :   serialize_integer (m, x, sizeof (u16));
      67           0 : }
      68             : 
      69             : void
      70           0 : serialize_8 (serialize_main_t * m, va_list * va)
      71             : {
      72           0 :   u32 x = va_arg (*va, u32);
      73           0 :   serialize_integer (m, x, sizeof (u8));
      74           0 : }
      75             : 
      76             : void
      77           0 : unserialize_64 (serialize_main_t * m, va_list * va)
      78             : {
      79           0 :   u64 *x = va_arg (*va, u64 *);
      80             :   u32 lo, hi;
      81           0 :   unserialize_integer (m, &lo, sizeof (lo));
      82           0 :   unserialize_integer (m, &hi, sizeof (hi));
      83           0 :   *x = ((u64) hi << 32) | (u64) lo;
      84           0 : }
      85             : 
      86             : void
      87           0 : unserialize_32 (serialize_main_t * m, va_list * va)
      88             : {
      89           0 :   u32 *x = va_arg (*va, u32 *);
      90           0 :   unserialize_integer (m, x, sizeof (x[0]));
      91           0 : }
      92             : 
      93             : void
      94           0 : unserialize_16 (serialize_main_t * m, va_list * va)
      95             : {
      96           0 :   u16 *x = va_arg (*va, u16 *);
      97             :   u32 t;
      98           0 :   unserialize_integer (m, &t, sizeof (x[0]));
      99           0 :   x[0] = t;
     100           0 : }
     101             : 
     102             : void
     103           0 : unserialize_8 (serialize_main_t * m, va_list * va)
     104             : {
     105           0 :   u8 *x = va_arg (*va, u8 *);
     106             :   u32 t;
     107           0 :   unserialize_integer (m, &t, sizeof (x[0]));
     108           0 :   x[0] = t;
     109           0 : }
     110             : 
     111             : void
     112           0 : serialize_f64 (serialize_main_t * m, va_list * va)
     113             : {
     114           0 :   f64 x = va_arg (*va, f64);
     115             :   union
     116             :   {
     117             :     f64 f;
     118             :     u64 i;
     119             :   } y;
     120           0 :   y.f = x;
     121           0 :   serialize (m, serialize_64, y.i);
     122           0 : }
     123             : 
     124             : void
     125           0 : serialize_f32 (serialize_main_t * m, va_list * va)
     126             : {
     127           0 :   f32 x = va_arg (*va, f64);
     128             :   union
     129             :   {
     130             :     f32 f;
     131             :     u32 i;
     132             :   } y;
     133           0 :   y.f = x;
     134           0 :   serialize_integer (m, y.i, sizeof (y.i));
     135           0 : }
     136             : 
     137             : void
     138           0 : unserialize_f64 (serialize_main_t * m, va_list * va)
     139             : {
     140           0 :   f64 *x = va_arg (*va, f64 *);
     141             :   union
     142             :   {
     143             :     f64 f;
     144             :     u64 i;
     145             :   } y;
     146           0 :   unserialize (m, unserialize_64, &y.i);
     147           0 :   *x = y.f;
     148           0 : }
     149             : 
     150             : void
     151           0 : unserialize_f32 (serialize_main_t * m, va_list * va)
     152             : {
     153           0 :   f32 *x = va_arg (*va, f32 *);
     154             :   union
     155             :   {
     156             :     f32 f;
     157             :     u32 i;
     158             :   } y;
     159           0 :   unserialize_integer (m, &y.i, sizeof (y.i));
     160           0 :   *x = y.f;
     161           0 : }
     162             : 
     163             : __clib_export void
     164     2839620 : serialize_cstring (serialize_main_t * m, char *s)
     165             : {
     166     2839620 :   u32 len = s ? strlen (s) : 0;
     167             :   void *p;
     168             : 
     169     2839620 :   serialize_likely_small_unsigned_integer (m, len);
     170     2839620 :   if (len > 0)
     171             :     {
     172     2839620 :       p = serialize_get (m, len);
     173     2839620 :       clib_memcpy_fast (p, s, len);
     174             :     }
     175     2839620 : }
     176             : 
     177             : __clib_export void
     178       81827 : unserialize_cstring (serialize_main_t * m, char **s)
     179             : {
     180       81827 :   char *p, *r = 0;
     181             :   u32 len;
     182             : 
     183       81827 :   len = unserialize_likely_small_unsigned_integer (m);
     184             : 
     185             :   /*
     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.
     189             :    */
     190       81827 :   if (len > 0 && len != 0xFFFFFFFF)
     191             :     {
     192       81827 :       r = vec_new (char, len + 1);
     193       81827 :       p = unserialize_get (m, len);
     194       81827 :       clib_memcpy_fast (r, p, len);
     195             : 
     196             :       /* Null terminate. */
     197       81827 :       r[len] = 0;
     198             :     }
     199       81827 :   *s = r;
     200       81827 : }
     201             : 
     202             : /* vec_serialize/vec_unserialize helper functions for basic vector types. */
     203             : void
     204           0 : serialize_vec_8 (serialize_main_t * m, va_list * va)
     205             : {
     206           0 :   u8 *s = va_arg (*va, u8 *);
     207           0 :   u32 n = va_arg (*va, u32);
     208           0 :   u8 *p = serialize_get (m, n * sizeof (u8));
     209           0 :   clib_memcpy_fast (p, s, n * sizeof (u8));
     210           0 : }
     211             : 
     212             : void
     213           0 : unserialize_vec_8 (serialize_main_t * m, va_list * va)
     214             : {
     215           0 :   u8 *s = va_arg (*va, u8 *);
     216           0 :   u32 n = va_arg (*va, u32);
     217           0 :   u8 *p = unserialize_get (m, n);
     218           0 :   clib_memcpy_fast (s, p, n);
     219           0 : }
     220             : 
     221             : #define _(n_bits)                                                       \
     222             :   void serialize_vec_##n_bits (serialize_main_t * m, va_list * va)      \
     223             :   {                                                                     \
     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]));               \
     227             :                                                                         \
     228             :     while (n >= 4)                                                   \
     229             :       {                                                                 \
     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]);                       \
     234             :         s += 4;                                                         \
     235             :         p += 4;                                                         \
     236             :         n -= 4;                                                         \
     237             :       }                                                                 \
     238             :                                                                         \
     239             :     while (n >= 1)                                                   \
     240             :       {                                                                 \
     241             :         p[0] = clib_host_to_net_u##n_bits (s[0]);                       \
     242             :         s += 1;                                                         \
     243             :         p += 1;                                                         \
     244             :         n -= 1;                                                         \
     245             :       }                                                                 \
     246             :   }                                                                     \
     247             :                                                                         \
     248             :   void unserialize_vec_##n_bits (serialize_main_t * m, va_list * va)    \
     249             :   {                                                                     \
     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]));             \
     253             :                                                                         \
     254             :     while (n >= 4)                                                   \
     255             :       {                                                                 \
     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]);                      \
     260             :         s += 4;                                                         \
     261             :         p += 4;                                                         \
     262             :         n -= 4;                                                         \
     263             :       }                                                                 \
     264             :                                                                         \
     265             :     while (n >= 1)                                                   \
     266             :       {                                                                 \
     267             :         s[0] = clib_net_to_host_mem_u##n_bits (&p[0]);                      \
     268             :         s += 1;                                                         \
     269             :         p += 1;                                                         \
     270             :         n -= 1;                                                         \
     271             :       }                                                                 \
     272             :   }
     273             : 
     274           0 : _(16);
     275           0 : _(32);
     276           0 : _(64);
     277             : 
     278             : #undef _
     279             : 
     280             : #define SERIALIZE_VECTOR_CHUNK_SIZE 64
     281             : 
     282             : __clib_export void
     283           0 : serialize_vector (serialize_main_t * m, va_list * va)
     284             : {
     285           0 :   void *vec = va_arg (*va, void *);
     286           0 :   u32 elt_bytes = va_arg (*va, u32);
     287           0 :   serialize_function_t *f = va_arg (*va, serialize_function_t *);
     288           0 :   u32 l = vec_len (vec);
     289           0 :   void *p = vec;
     290             : 
     291           0 :   serialize_integer (m, l, sizeof (l));
     292             : 
     293             :   /* Serialize vector in chunks for cache locality. */
     294           0 :   while (l != 0)
     295             :     {
     296           0 :       u32 n = clib_min (SERIALIZE_VECTOR_CHUNK_SIZE, l);
     297           0 :       serialize (m, f, p, n);
     298           0 :       l -= n;
     299           0 :       p += SERIALIZE_VECTOR_CHUNK_SIZE * elt_bytes;
     300             :     }
     301           0 : }
     302             : 
     303             : void *
     304           0 : unserialize_vector_ha (serialize_main_t * m,
     305             :                        u32 elt_bytes,
     306             :                        u32 header_bytes,
     307             :                        u32 align, u32 max_length, serialize_function_t * f)
     308             : {
     309             :   void *v, *p;
     310             :   u32 l;
     311           0 :   vec_attr_t va = { .align = align,
     312             :                     .elt_sz = elt_bytes,
     313             :                     .hdr_sz = header_bytes };
     314             : 
     315           0 :   unserialize_integer (m, &l, sizeof (l));
     316           0 :   if (l > max_length)
     317           0 :     serialize_error (&m->header,
     318             :                      clib_error_create ("bad vector length %d", l));
     319             : 
     320           0 :   p = v = _vec_alloc_internal (l, &va);
     321             : 
     322           0 :   while (l != 0)
     323             :     {
     324           0 :       u32 n = clib_min (SERIALIZE_VECTOR_CHUNK_SIZE, l);
     325           0 :       unserialize (m, f, p, n);
     326           0 :       l -= n;
     327           0 :       p += SERIALIZE_VECTOR_CHUNK_SIZE * elt_bytes;
     328             :     }
     329           0 :   return v;
     330             : }
     331             : 
     332             : void
     333           0 : unserialize_aligned_vector (serialize_main_t * m, va_list * va)
     334             : {
     335           0 :   void **vec = va_arg (*va, void **);
     336           0 :   u32 elt_bytes = va_arg (*va, u32);
     337           0 :   serialize_function_t *f = va_arg (*va, serialize_function_t *);
     338           0 :   u32 align = va_arg (*va, u32);
     339             : 
     340           0 :   *vec = unserialize_vector_ha (m, elt_bytes,
     341             :                                 /* header_bytes */ 0,
     342             :                                 /* align */ align,
     343             :                                 /* max_length */ ~0,
     344             :                                 f);
     345           0 : }
     346             : 
     347             : __clib_export void
     348           0 : unserialize_vector (serialize_main_t * m, va_list * va)
     349             : {
     350           0 :   void **vec = va_arg (*va, void **);
     351           0 :   u32 elt_bytes = va_arg (*va, u32);
     352           0 :   serialize_function_t *f = va_arg (*va, serialize_function_t *);
     353             : 
     354           0 :   *vec = unserialize_vector_ha (m, elt_bytes,
     355             :                                 /* header_bytes */ 0,
     356             :                                 /* align */ 0,
     357             :                                 /* max_length */ ~0,
     358             :                                 f);
     359           0 : }
     360             : 
     361             : void
     362           0 : serialize_bitmap (serialize_main_t * m, uword * b)
     363             : {
     364             :   u32 l, i, n_u32s;
     365             : 
     366           0 :   l = vec_len (b);
     367           0 :   n_u32s = l * sizeof (b[0]) / sizeof (u32);
     368           0 :   serialize_integer (m, n_u32s, sizeof (n_u32s));
     369             : 
     370             :   /* Send 32 bit words, low-order word first on 64 bit. */
     371           0 :   for (i = 0; i < l; i++)
     372             :     {
     373           0 :       serialize_integer (m, b[i], sizeof (u32));
     374             :       if (BITS (uword) == 64)
     375           0 :         serialize_integer (m, (u64) b[i] >> (u64) 32, sizeof (u32));
     376             :     }
     377           0 : }
     378             : 
     379             : uword *
     380           0 : unserialize_bitmap (serialize_main_t * m)
     381             : {
     382           0 :   uword *b = 0;
     383             :   u32 i, n_u32s;
     384             : 
     385           0 :   unserialize_integer (m, &n_u32s, sizeof (n_u32s));
     386           0 :   if (n_u32s == 0)
     387           0 :     return b;
     388             : 
     389           0 :   i = (n_u32s * sizeof (u32) + sizeof (b[0]) - 1) / sizeof (b[0]);
     390           0 :   vec_resize (b, i);
     391           0 :   for (i = 0; i < n_u32s; i++)
     392             :     {
     393             :       u32 data;
     394           0 :       unserialize_integer (m, &data, sizeof (u32));
     395             : 
     396             :       /* Low-word is first on 64 bit. */
     397             :       if (BITS (uword) == 64)
     398             :         {
     399           0 :           if ((i % 2) == 0)
     400           0 :             b[i / 2] |= (u64) data << (u64) 0;
     401             :           else
     402           0 :             b[i / 2] |= (u64) data << (u64) 32;
     403             :         }
     404             :       else
     405             :         {
     406             :           b[i] = data;
     407             :         }
     408             :     }
     409             : 
     410           0 :   return b;
     411             : }
     412             : 
     413             : void
     414           0 : serialize_pool (serialize_main_t * m, va_list * va)
     415             : {
     416           0 :   void *pool = va_arg (*va, void *);
     417           0 :   u32 elt_bytes = va_arg (*va, u32);
     418           0 :   serialize_function_t *f = va_arg (*va, serialize_function_t *);
     419             :   u32 l, lo, hi;
     420             :   pool_header_t *p;
     421             : 
     422           0 :   l = vec_len (pool);
     423           0 :   serialize_integer (m, l, sizeof (u32));
     424           0 :   if (l == 0)
     425           0 :     return;
     426           0 :   p = pool_header (pool);
     427             : 
     428             :   /* No need to send free bitmap.  Need to send index vector
     429             :      to guarantee that unserialized pool will be identical. */
     430           0 :   vec_serialize (m, p->free_indices, serialize_vec_32);
     431             : 
     432           0 :   pool_foreach_region (lo, hi, pool,
     433             :                        serialize (m, f, pool + lo * elt_bytes, hi - lo));
     434             : }
     435             : 
     436             : static void *
     437           0 : unserialize_pool_helper (serialize_main_t * m,
     438             :                          u32 elt_bytes, u32 align, serialize_function_t * f)
     439             : {
     440             :   void *v;
     441             :   u32 i, l, lo, hi;
     442             :   pool_header_t *p;
     443           0 :   vec_attr_t va = { .align = align,
     444             :                     .elt_sz = elt_bytes,
     445             :                     .hdr_sz = sizeof (pool_header_t) };
     446             : 
     447           0 :   unserialize_integer (m, &l, sizeof (l));
     448           0 :   if (l == 0)
     449             :     {
     450           0 :       return 0;
     451             :     }
     452             : 
     453           0 :   v = _vec_alloc_internal (l, &va);
     454           0 :   p = pool_header (v);
     455             : 
     456           0 :   vec_unserialize (m, &p->free_indices, unserialize_vec_32);
     457             : 
     458             :   /* Construct free bitmap. */
     459           0 :   p->free_bitmap = 0;
     460           0 :   for (i = 0; i < vec_len (p->free_indices); i++)
     461           0 :     p->free_bitmap = clib_bitmap_ori (p->free_bitmap, p->free_indices[i]);
     462             : 
     463           0 :   pool_foreach_region (lo, hi, v,
     464             :                        unserialize (m, f, v + lo * elt_bytes, hi - lo));
     465             : 
     466           0 :   return v;
     467             : }
     468             : 
     469             : void
     470           0 : unserialize_pool (serialize_main_t * m, va_list * va)
     471             : {
     472           0 :   void **result = va_arg (*va, void **);
     473           0 :   u32 elt_bytes = va_arg (*va, u32);
     474           0 :   serialize_function_t *f = va_arg (*va, serialize_function_t *);
     475           0 :   *result = unserialize_pool_helper (m, elt_bytes, /* align */ 0, f);
     476           0 : }
     477             : 
     478             : void
     479           0 : unserialize_aligned_pool (serialize_main_t * m, va_list * va)
     480             : {
     481           0 :   void **result = va_arg (*va, void **);
     482           0 :   u32 elt_bytes = va_arg (*va, u32);
     483           0 :   u32 align = va_arg (*va, u32);
     484           0 :   serialize_function_t *f = va_arg (*va, serialize_function_t *);
     485           0 :   *result = unserialize_pool_helper (m, elt_bytes, align, f);
     486           0 : }
     487             : 
     488             : static void
     489           0 : serialize_vec_heap_elt (serialize_main_t * m, va_list * va)
     490             : {
     491           0 :   heap_elt_t *e = va_arg (*va, heap_elt_t *);
     492           0 :   u32 i, n = va_arg (*va, u32);
     493           0 :   for (i = 0; i < n; i++)
     494             :     {
     495           0 :       serialize_integer (m, e[i].offset, sizeof (e[i].offset));
     496           0 :       serialize_integer (m, e[i].next, sizeof (e[i].next));
     497           0 :       serialize_integer (m, e[i].prev, sizeof (e[i].prev));
     498             :     }
     499           0 : }
     500             : 
     501             : static void
     502           0 : unserialize_vec_heap_elt (serialize_main_t * m, va_list * va)
     503             : {
     504           0 :   heap_elt_t *e = va_arg (*va, heap_elt_t *);
     505           0 :   u32 i, n = va_arg (*va, u32);
     506           0 :   for (i = 0; i < n; i++)
     507             :     {
     508           0 :       unserialize_integer (m, &e[i].offset, sizeof (e[i].offset));
     509           0 :       unserialize_integer (m, &e[i].next, sizeof (e[i].next));
     510           0 :       unserialize_integer (m, &e[i].prev, sizeof (e[i].prev));
     511             :     }
     512           0 : }
     513             : 
     514             : void
     515           0 : serialize_heap (serialize_main_t * m, va_list * va)
     516             : {
     517           0 :   void *heap = va_arg (*va, void *);
     518           0 :   serialize_function_t *f = va_arg (*va, serialize_function_t *);
     519             :   u32 i, l;
     520             :   heap_header_t *h;
     521             : 
     522           0 :   l = vec_len (heap);
     523           0 :   serialize_integer (m, l, sizeof (u32));
     524           0 :   if (l == 0)
     525           0 :     return;
     526             : 
     527           0 :   h = heap_header (heap);
     528             : 
     529             : #define foreach_serialize_heap_header_integer \
     530             :   _ (head) _ (tail) _ (used_count) _ (max_len) _ (flags) _ (elt_bytes)
     531             : 
     532             : #define _(f) serialize_integer (m, h->f, sizeof (h->f));
     533           0 :   foreach_serialize_heap_header_integer;
     534             : #undef _
     535             : 
     536           0 :   serialize_integer (m, vec_len (h->free_lists), sizeof (u32));
     537           0 :   for (i = 0; i < vec_len (h->free_lists); i++)
     538           0 :     vec_serialize (m, h->free_lists[i], serialize_vec_32);
     539             : 
     540           0 :   vec_serialize (m, h->elts, serialize_vec_heap_elt);
     541           0 :   vec_serialize (m, h->small_free_elt_free_index, serialize_vec_32);
     542           0 :   vec_serialize (m, h->free_elts, serialize_vec_32);
     543             : 
     544             :   /* Serialize data in heap. */
     545             :   {
     546             :     heap_elt_t *e, *end;
     547           0 :     e = h->elts + h->head;
     548           0 :     end = h->elts + h->tail;
     549             :     while (1)
     550             :       {
     551           0 :         if (!heap_is_free (e))
     552             :           {
     553           0 :             void *v = heap + heap_offset (e) * h->elt_bytes;
     554           0 :             u32 n = heap_elt_size (heap, e);
     555           0 :             serialize (m, f, v, n);
     556             :           }
     557           0 :         if (e == end)
     558           0 :           break;
     559           0 :         e = heap_next (e);
     560             :       }
     561             :   }
     562             : }
     563             : 
     564             : void
     565           0 : unserialize_heap (serialize_main_t * m, va_list * va)
     566             : {
     567           0 :   void **result = va_arg (*va, void **);
     568           0 :   serialize_function_t *f = va_arg (*va, serialize_function_t *);
     569             :   u32 i, vl, fl;
     570             :   heap_header_t h;
     571             :   void *heap;
     572             : 
     573           0 :   unserialize_integer (m, &vl, sizeof (u32));
     574           0 :   if (vl == 0)
     575             :     {
     576           0 :       *result = 0;
     577           0 :       return;
     578             :     }
     579             : 
     580           0 :   clib_memset (&h, 0, sizeof (h));
     581             : #define _(f) unserialize_integer (m, &h.f, sizeof (h.f));
     582           0 :   foreach_serialize_heap_header_integer;
     583             : #undef _
     584             : 
     585           0 :   unserialize_integer (m, &fl, sizeof (u32));
     586           0 :   vec_resize (h.free_lists, fl);
     587             : 
     588           0 :   for (i = 0; i < vec_len (h.free_lists); i++)
     589           0 :     vec_unserialize (m, &h.free_lists[i], unserialize_vec_32);
     590             : 
     591           0 :   vec_unserialize (m, &h.elts, unserialize_vec_heap_elt);
     592           0 :   vec_unserialize (m, &h.small_free_elt_free_index, unserialize_vec_32);
     593           0 :   vec_unserialize (m, &h.free_elts, unserialize_vec_32);
     594             : 
     595             :   /* Re-construct used elt bitmap. */
     596             :   if (CLIB_DEBUG > 0)
     597             :     {
     598             :       heap_elt_t *e;
     599           0 :       vec_foreach (e, h.elts)
     600             :       {
     601           0 :         if (!heap_is_free (e))
     602           0 :           h.used_elt_bitmap = clib_bitmap_ori (h.used_elt_bitmap, e - h.elts);
     603             :       }
     604             :     }
     605             : 
     606           0 :   heap = *result = _heap_new (vl, h.elt_bytes);
     607           0 :   heap_header (heap)[0] = h;
     608             : 
     609             :   /* Unserialize data in heap. */
     610             :   {
     611             :     heap_elt_t *e, *end;
     612           0 :     e = h.elts + h.head;
     613           0 :     end = h.elts + h.tail;
     614             :     while (1)
     615             :       {
     616           0 :         if (!heap_is_free (e))
     617             :           {
     618           0 :             void *v = heap + heap_offset (e) * h.elt_bytes;
     619           0 :             u32 n = heap_elt_size (heap, e);
     620           0 :             unserialize (m, f, v, n);
     621             :           }
     622           0 :         if (e == end)
     623           0 :           break;
     624           0 :         e = heap_next (e);
     625             :       }
     626             :   }
     627             : }
     628             : 
     629             : void
     630           0 : serialize_magic (serialize_main_t * m, void *magic, u32 magic_bytes)
     631             : {
     632             :   void *p;
     633           0 :   serialize_integer (m, magic_bytes, sizeof (magic_bytes));
     634           0 :   p = serialize_get (m, magic_bytes);
     635           0 :   clib_memcpy_fast (p, magic, magic_bytes);
     636           0 : }
     637             : 
     638             : void
     639           0 : unserialize_check_magic (serialize_main_t * m, void *magic, u32 magic_bytes)
     640             : {
     641             :   u32 l;
     642             :   void *d;
     643             : 
     644           0 :   unserialize_integer (m, &l, sizeof (l));
     645           0 :   if (l != magic_bytes)
     646             :     {
     647           0 :     bad:
     648           0 :       serialize_error_return (m, "bad magic number");
     649             :     }
     650           0 :   d = serialize_get (m, magic_bytes);
     651           0 :   if (memcmp (magic, d, magic_bytes))
     652           0 :     goto bad;
     653           0 : }
     654             : 
     655             : __clib_export clib_error_t *
     656           0 : va_serialize (serialize_main_t * sm, va_list * va)
     657             : {
     658           0 :   serialize_main_header_t *m = &sm->header;
     659           0 :   serialize_function_t *f = va_arg (*va, serialize_function_t *);
     660           0 :   clib_error_t *error = 0;
     661             : 
     662           0 :   m->recursion_level += 1;
     663           0 :   if (m->recursion_level == 1)
     664             :     {
     665           0 :       uword r = clib_setjmp (&m->error_longjmp, 0);
     666           0 :       error = uword_to_pointer (r, clib_error_t *);
     667             :     }
     668             : 
     669           0 :   if (!error)
     670           0 :     f (sm, va);
     671             : 
     672           0 :   m->recursion_level -= 1;
     673           0 :   return error;
     674             : }
     675             : 
     676             : __clib_export clib_error_t *
     677           0 : serialize (serialize_main_t * m, ...)
     678             : {
     679             :   clib_error_t *error;
     680             :   va_list va;
     681             : 
     682           0 :   va_start (va, m);
     683           0 :   error = va_serialize (m, &va);
     684           0 :   va_end (va);
     685           0 :   return error;
     686             : }
     687             : 
     688             : __clib_export clib_error_t *
     689           0 : unserialize (serialize_main_t * m, ...)
     690             : {
     691             :   clib_error_t *error;
     692             :   va_list va;
     693             : 
     694           0 :   va_start (va, m);
     695           0 :   error = va_serialize (m, &va);
     696           0 :   va_end (va);
     697           0 :   return error;
     698             : }
     699             : 
     700             : static void *
     701       32617 : serialize_write_not_inline (serialize_main_header_t * m,
     702             :                             serialize_stream_t * s,
     703             :                             uword n_bytes_to_write, uword flags)
     704             : {
     705             :   uword cur_bi, n_left_b, n_left_o;
     706             : 
     707       32617 :   ASSERT (s->current_buffer_index <= s->n_buffer_bytes);
     708       32617 :   cur_bi = s->current_buffer_index;
     709       32617 :   n_left_b = s->n_buffer_bytes - cur_bi;
     710       32617 :   n_left_o = vec_len (s->overflow_buffer);
     711             : 
     712             :   /* Prepend overflow buffer if present. */
     713             :   do
     714             :     {
     715       45662 :       if (n_left_o > 0 && n_left_b > 0)
     716             :         {
     717       26090 :           uword n = clib_min (n_left_b, n_left_o);
     718       26090 :           clib_memcpy_fast (s->buffer + cur_bi, s->overflow_buffer, n);
     719       26090 :           cur_bi += n;
     720       26090 :           n_left_b -= n;
     721       26090 :           n_left_o -= n;
     722       26090 :           if (n_left_o == 0)
     723       13045 :             vec_set_len (s->overflow_buffer, 0);
     724             :           else
     725       13045 :             vec_delete (s->overflow_buffer, n, 0);
     726             :         }
     727             : 
     728             :       /* Call data function when buffer is complete.  Data function should
     729             :          dispatch with current buffer and give us a new one to write more
     730             :          data into. */
     731       45662 :       if (n_left_b == 0)
     732             :         {
     733       17941 :           s->current_buffer_index = cur_bi;
     734       17941 :           m->data_function (m, s);
     735       17941 :           cur_bi = s->current_buffer_index;
     736       17941 :           n_left_b = s->n_buffer_bytes - cur_bi;
     737             :         }
     738             :     }
     739       45662 :   while (n_left_o > 0);
     740             : 
     741       32617 :   if (n_left_o > 0 || n_left_b < n_bytes_to_write)
     742             :     {
     743             :       u8 *r;
     744       13045 :       s->current_buffer_index = cur_bi;
     745       13045 :       vec_add2 (s->overflow_buffer, r, n_bytes_to_write);
     746       13045 :       return r;
     747             :     }
     748             :   else
     749             :     {
     750       19572 :       s->current_buffer_index = cur_bi + n_bytes_to_write;
     751       19572 :       return s->buffer + cur_bi;
     752             :     }
     753             : }
     754             : 
     755             : static void *
     756           0 : serialize_read_not_inline (serialize_main_header_t * m,
     757             :                            serialize_stream_t * s,
     758             :                            uword n_bytes_to_read, uword flags)
     759             : {
     760             :   uword cur_bi, cur_oi, n_left_b, n_left_o, n_left_to_read;
     761             : 
     762           0 :   ASSERT (s->current_buffer_index <= s->n_buffer_bytes);
     763             : 
     764           0 :   cur_bi = s->current_buffer_index;
     765           0 :   cur_oi = s->current_overflow_index;
     766             : 
     767           0 :   n_left_b = s->n_buffer_bytes - cur_bi;
     768           0 :   n_left_o = vec_len (s->overflow_buffer) - cur_oi;
     769             : 
     770             :   /* Read from overflow? */
     771           0 :   if (n_left_o >= n_bytes_to_read)
     772             :     {
     773           0 :       s->current_overflow_index = cur_oi + n_bytes_to_read;
     774           0 :       return vec_elt_at_index (s->overflow_buffer, cur_oi);
     775             :     }
     776             : 
     777             :   /* Reset overflow buffer. */
     778           0 :   if (n_left_o == 0 && s->overflow_buffer)
     779             :     {
     780           0 :       s->current_overflow_index = 0;
     781           0 :       vec_set_len (s->overflow_buffer, 0);
     782             :     }
     783             : 
     784           0 :   n_left_to_read = n_bytes_to_read;
     785           0 :   while (n_left_to_read > 0)
     786             :     {
     787             :       uword n;
     788             : 
     789             :       /* If we don't have enough data between overflow and normal buffer
     790             :          call read function. */
     791           0 :       if (n_left_o + n_left_b < n_bytes_to_read)
     792             :         {
     793             :           /* Save any left over buffer in overflow vector. */
     794           0 :           if (n_left_b > 0)
     795             :             {
     796           0 :               vec_add (s->overflow_buffer, s->buffer + cur_bi, n_left_b);
     797           0 :               n_left_o += n_left_b;
     798           0 :               n_left_to_read -= n_left_b;
     799             :               /* Advance buffer to end --- even if
     800             :                  SERIALIZE_FLAG_NO_ADVANCE_CURRENT_BUFFER_INDEX is set. */
     801           0 :               cur_bi = s->n_buffer_bytes;
     802           0 :               n_left_b = 0;
     803             :             }
     804             : 
     805           0 :           if (m->data_function)
     806             :             {
     807           0 :               m->data_function (m, s);
     808           0 :               cur_bi = s->current_buffer_index;
     809           0 :               n_left_b = s->n_buffer_bytes - cur_bi;
     810             :             }
     811             :         }
     812             : 
     813             :       /* For first time through loop return if we have enough data
     814             :          in normal buffer and overflow vector is empty. */
     815           0 :       if (n_left_o == 0
     816           0 :           && n_left_to_read == n_bytes_to_read && n_left_b >= n_left_to_read)
     817             :         {
     818           0 :           s->current_buffer_index = cur_bi + n_bytes_to_read;
     819           0 :           return s->buffer + cur_bi;
     820             :         }
     821             : 
     822           0 :       if (!m->data_function || serialize_stream_is_end_of_stream (s))
     823             :         {
     824             :           /* This can happen for a peek at end of file.
     825             :              Pad overflow buffer with 0s. */
     826           0 :           vec_resize (s->overflow_buffer, n_left_to_read);
     827           0 :           n_left_o += n_left_to_read;
     828           0 :           n_left_to_read = 0;
     829             :         }
     830             :       else
     831             :         {
     832             :           /* Copy from buffer to overflow vector. */
     833           0 :           n = clib_min (n_left_to_read, n_left_b);
     834           0 :           vec_add (s->overflow_buffer, s->buffer + cur_bi, n);
     835           0 :           cur_bi += n;
     836           0 :           n_left_b -= n;
     837           0 :           n_left_o += n;
     838           0 :           n_left_to_read -= n;
     839             :         }
     840             :     }
     841             : 
     842           0 :   s->current_buffer_index = cur_bi;
     843           0 :   s->current_overflow_index = cur_oi + n_bytes_to_read;
     844           0 :   return vec_elt_at_index (s->overflow_buffer, cur_oi);
     845             : }
     846             : 
     847             : __clib_export void *
     848       30986 : serialize_read_write_not_inline (serialize_main_header_t * m,
     849             :                                  serialize_stream_t * s,
     850             :                                  uword n_bytes, uword flags)
     851             : {
     852       30986 :   return (((flags & SERIALIZE_FLAG_IS_READ) ? serialize_read_not_inline :
     853             :            serialize_write_not_inline) (m, s, n_bytes, flags));
     854             : }
     855             : 
     856             : static void
     857        1631 : serialize_read_write_close (serialize_main_header_t * m,
     858             :                             serialize_stream_t * s, uword flags)
     859             : {
     860        1631 :   if (serialize_stream_is_end_of_stream (s))
     861           0 :     return;
     862             : 
     863        1631 :   if (flags & SERIALIZE_FLAG_IS_WRITE)
     864             :     /* "Write" 0 bytes to flush overflow vector. */
     865        1631 :     serialize_write_not_inline (m, s, /* n bytes */ 0, flags);
     866             : 
     867        1631 :   serialize_stream_set_end_of_stream (s);
     868             : 
     869             :   /* Call it one last time to flush buffer and close. */
     870        1631 :   m->data_function (m, s);
     871             : 
     872        1631 :   vec_free (s->overflow_buffer);
     873             : }
     874             : 
     875             : __clib_export void
     876        1631 : serialize_close (serialize_main_t * m)
     877             : {
     878        1631 :   serialize_read_write_close (&m->header, &m->stream,
     879             :                               SERIALIZE_FLAG_IS_WRITE);
     880        1631 : }
     881             : 
     882             : __clib_export void
     883           0 : unserialize_close (serialize_main_t * m)
     884             : {
     885           0 :   serialize_read_write_close (&m->header, &m->stream, SERIALIZE_FLAG_IS_READ);
     886           0 : }
     887             : 
     888             : __clib_export void
     889          47 : serialize_open_data (serialize_main_t * m, u8 * data, uword n_data_bytes)
     890             : {
     891          47 :   clib_memset (m, 0, sizeof (m[0]));
     892          47 :   m->stream.buffer = data;
     893          47 :   m->stream.n_buffer_bytes = n_data_bytes;
     894          47 : }
     895             : 
     896             : __clib_export void
     897          47 : unserialize_open_data (serialize_main_t * m, u8 * data, uword n_data_bytes)
     898             : {
     899          47 :   serialize_open_data (m, data, n_data_bytes);
     900          47 : }
     901             : 
     902             : static void
     903       19572 : serialize_vector_write (serialize_main_header_t * m, serialize_stream_t * s)
     904             : {
     905       19572 :   if (!serialize_stream_is_end_of_stream (s))
     906             :     {
     907             :       /* Double buffer size. */
     908       17941 :       uword l = vec_len (s->buffer);
     909       17941 :       vec_resize (s->buffer, l > 0 ? l : 64);
     910       17941 :       s->n_buffer_bytes = vec_len (s->buffer);
     911             :     }
     912       19572 : }
     913             : 
     914             : __clib_export void
     915        1631 : serialize_open_vector (serialize_main_t * m, u8 * vector)
     916             : {
     917        1631 :   clib_memset (m, 0, sizeof (m[0]));
     918        1631 :   m->header.data_function = serialize_vector_write;
     919        1631 :   m->stream.buffer = vector;
     920        1631 :   m->stream.current_buffer_index = 0;
     921        1631 :   m->stream.n_buffer_bytes = vec_len (vector);
     922        1631 : }
     923             : 
     924             : __clib_export void *
     925        1631 : serialize_close_vector (serialize_main_t * m)
     926             : {
     927        1631 :   serialize_stream_t *s = &m->stream;
     928             :   void *result;
     929             : 
     930        1631 :   serialize_close (m);          /* frees overflow buffer */
     931             : 
     932        1631 :   if (s->buffer)
     933        1631 :     vec_set_len (s->buffer, s->current_buffer_index);
     934        1631 :   result = s->buffer;
     935        1631 :   clib_memset (m, 0, sizeof (m[0]));
     936        1631 :   return result;
     937             : }
     938             : 
     939             : __clib_export void
     940           0 : serialize_multiple_1 (serialize_main_t *m, void *data, uword data_stride,
     941             :                       uword n_data)
     942             : {
     943           0 :   u8 *d = data;
     944             :   u8 *p;
     945           0 :   uword n_left = n_data;
     946             : 
     947           0 :   while (n_left >= 4)
     948             :     {
     949           0 :       p = serialize_get (m, 4 * sizeof (d[0]));
     950           0 :       p[0] = d[0 * data_stride];
     951           0 :       p[1] = d[1 * data_stride];
     952           0 :       p[2] = d[2 * data_stride];
     953           0 :       p[3] = d[3 * data_stride];
     954           0 :       n_left -= 4;
     955           0 :       d += 4 * data_stride;
     956             :     }
     957             : 
     958           0 :   if (n_left > 0)
     959             :     {
     960           0 :       p = serialize_get (m, n_left * sizeof (p[0]));
     961           0 :       while (n_left > 0)
     962             :         {
     963           0 :           p[0] = d[0];
     964           0 :           p += 1;
     965           0 :           d += 1 * data_stride;
     966           0 :           n_left -= 1;
     967             :         }
     968             :     }
     969           0 : }
     970             : 
     971             : __clib_export void
     972           0 : serialize_multiple_2 (serialize_main_t *m, void *data, uword data_stride,
     973             :                       uword n_data)
     974             : {
     975           0 :   void *d = data;
     976             :   u16 *p;
     977           0 :   uword n_left = n_data;
     978             : 
     979           0 :   while (n_left >= 4)
     980             :     {
     981           0 :       p = serialize_get (m, 4 * sizeof (p[0]));
     982           0 :       clib_mem_unaligned (p + 0, u16) =
     983           0 :         clib_host_to_net_mem_u16 (d + 0 * data_stride);
     984           0 :       clib_mem_unaligned (p + 1, u16) =
     985           0 :         clib_host_to_net_mem_u16 (d + 1 * data_stride);
     986           0 :       clib_mem_unaligned (p + 2, u16) =
     987           0 :         clib_host_to_net_mem_u16 (d + 2 * data_stride);
     988           0 :       clib_mem_unaligned (p + 3, u16) =
     989           0 :         clib_host_to_net_mem_u16 (d + 3 * data_stride);
     990           0 :       n_left -= 4;
     991           0 :       d += 4 * data_stride;
     992             :     }
     993             : 
     994           0 :   if (n_left > 0)
     995             :     {
     996           0 :       p = serialize_get (m, n_left * sizeof (p[0]));
     997           0 :       while (n_left > 0)
     998             :         {
     999           0 :           clib_mem_unaligned (p + 0, u16) =
    1000           0 :             clib_host_to_net_mem_u16 (d + 0 * data_stride);
    1001           0 :           p += 1;
    1002           0 :           d += 1 * data_stride;
    1003           0 :           n_left -= 1;
    1004             :         }
    1005             :     }
    1006           0 : }
    1007             : 
    1008             : __clib_export void
    1009           0 : serialize_multiple_4 (serialize_main_t *m, void *data, uword data_stride,
    1010             :                       uword n_data)
    1011             : {
    1012           0 :   void *d = data;
    1013             :   u32 *p;
    1014           0 :   uword n_left = n_data;
    1015             : 
    1016           0 :   while (n_left >= 4)
    1017             :     {
    1018           0 :       p = serialize_get (m, 4 * sizeof (p[0]));
    1019           0 :       clib_mem_unaligned (p + 0, u32) =
    1020           0 :         clib_host_to_net_mem_u32 (d + 0 * data_stride);
    1021           0 :       clib_mem_unaligned (p + 1, u32) =
    1022           0 :         clib_host_to_net_mem_u32 (d + 1 * data_stride);
    1023           0 :       clib_mem_unaligned (p + 2, u32) =
    1024           0 :         clib_host_to_net_mem_u32 (d + 2 * data_stride);
    1025           0 :       clib_mem_unaligned (p + 3, u32) =
    1026           0 :         clib_host_to_net_mem_u32 (d + 3 * data_stride);
    1027           0 :       n_left -= 4;
    1028           0 :       d += 4 * data_stride;
    1029             :     }
    1030             : 
    1031           0 :   if (n_left > 0)
    1032             :     {
    1033           0 :       p = serialize_get (m, n_left * sizeof (p[0]));
    1034           0 :       while (n_left > 0)
    1035             :         {
    1036           0 :           clib_mem_unaligned (p + 0, u32) =
    1037           0 :             clib_host_to_net_mem_u32 (d + 0 * data_stride);
    1038           0 :           p += 1;
    1039           0 :           d += 1 * data_stride;
    1040           0 :           n_left -= 1;
    1041             :         }
    1042             :     }
    1043           0 : }
    1044             : 
    1045             : __clib_export void
    1046           0 : unserialize_multiple_1 (serialize_main_t *m, void *data, uword data_stride,
    1047             :                         uword n_data)
    1048             : {
    1049           0 :   u8 *d = data;
    1050             :   u8 *p;
    1051           0 :   uword n_left = n_data;
    1052             : 
    1053           0 :   while (n_left >= 4)
    1054             :     {
    1055           0 :       p = unserialize_get (m, 4 * sizeof (d[0]));
    1056           0 :       d[0 * data_stride] = p[0];
    1057           0 :       d[1 * data_stride] = p[1];
    1058           0 :       d[2 * data_stride] = p[2];
    1059           0 :       d[3 * data_stride] = p[3];
    1060           0 :       n_left -= 4;
    1061           0 :       d += 4 * data_stride;
    1062             :     }
    1063             : 
    1064           0 :   if (n_left > 0)
    1065             :     {
    1066           0 :       p = unserialize_get (m, n_left * sizeof (p[0]));
    1067           0 :       while (n_left > 0)
    1068             :         {
    1069           0 :           d[0] = p[0];
    1070           0 :           p += 1;
    1071           0 :           d += 1 * data_stride;
    1072           0 :           n_left -= 1;
    1073             :         }
    1074             :     }
    1075           0 : }
    1076             : 
    1077             : __clib_export void
    1078           0 : unserialize_multiple_2 (serialize_main_t *m, void *data, uword data_stride,
    1079             :                         uword n_data)
    1080             : {
    1081           0 :   void *d = data;
    1082             :   u16 *p;
    1083           0 :   uword n_left = n_data;
    1084             : 
    1085           0 :   while (n_left >= 4)
    1086             :     {
    1087           0 :       p = unserialize_get (m, 4 * sizeof (p[0]));
    1088           0 :       clib_mem_unaligned (d + 0 * data_stride, u16) =
    1089           0 :         clib_net_to_host_mem_u16 (p + 0);
    1090           0 :       clib_mem_unaligned (d + 1 * data_stride, u16) =
    1091           0 :         clib_net_to_host_mem_u16 (p + 1);
    1092           0 :       clib_mem_unaligned (d + 2 * data_stride, u16) =
    1093           0 :         clib_net_to_host_mem_u16 (p + 2);
    1094           0 :       clib_mem_unaligned (d + 3 * data_stride, u16) =
    1095           0 :         clib_net_to_host_mem_u16 (p + 3);
    1096           0 :       n_left -= 4;
    1097           0 :       d += 4 * data_stride;
    1098             :     }
    1099             : 
    1100           0 :   if (n_left > 0)
    1101             :     {
    1102           0 :       p = unserialize_get (m, n_left * sizeof (p[0]));
    1103           0 :       while (n_left > 0)
    1104             :         {
    1105           0 :           clib_mem_unaligned (d + 0 * data_stride, u16) =
    1106           0 :             clib_net_to_host_mem_u16 (p + 0);
    1107           0 :           p += 1;
    1108           0 :           d += 1 * data_stride;
    1109           0 :           n_left -= 1;
    1110             :         }
    1111             :     }
    1112           0 : }
    1113             : 
    1114             : __clib_export void
    1115           0 : unserialize_multiple_4 (serialize_main_t *m, void *data, uword data_stride,
    1116             :                         uword n_data)
    1117             : {
    1118           0 :   void *d = data;
    1119             :   u32 *p;
    1120           0 :   uword n_left = n_data;
    1121             : 
    1122           0 :   while (n_left >= 4)
    1123             :     {
    1124           0 :       p = unserialize_get (m, 4 * sizeof (p[0]));
    1125           0 :       clib_mem_unaligned (d + 0 * data_stride, u32) =
    1126           0 :         clib_net_to_host_mem_u32 (p + 0);
    1127           0 :       clib_mem_unaligned (d + 1 * data_stride, u32) =
    1128           0 :         clib_net_to_host_mem_u32 (p + 1);
    1129           0 :       clib_mem_unaligned (d + 2 * data_stride, u32) =
    1130           0 :         clib_net_to_host_mem_u32 (p + 2);
    1131           0 :       clib_mem_unaligned (d + 3 * data_stride, u32) =
    1132           0 :         clib_net_to_host_mem_u32 (p + 3);
    1133           0 :       n_left -= 4;
    1134           0 :       d += 4 * data_stride;
    1135             :     }
    1136             : 
    1137           0 :   if (n_left > 0)
    1138             :     {
    1139           0 :       p = unserialize_get (m, n_left * sizeof (p[0]));
    1140           0 :       while (n_left > 0)
    1141             :         {
    1142           0 :           clib_mem_unaligned (d + 0 * data_stride, u32) =
    1143           0 :             clib_net_to_host_mem_u32 (p + 0);
    1144           0 :           p += 1;
    1145           0 :           d += 1 * data_stride;
    1146           0 :           n_left -= 1;
    1147             :         }
    1148             :     }
    1149           0 : }
    1150             : 
    1151             : #ifdef CLIB_UNIX
    1152             : 
    1153             : #include <unistd.h>
    1154             : #include <fcntl.h>
    1155             : 
    1156             : static void
    1157           0 : clib_file_write (serialize_main_header_t * m, serialize_stream_t * s)
    1158             : {
    1159             :   int fd, n;
    1160             : 
    1161           0 :   fd = s->data_function_opaque;
    1162           0 :   n = write (fd, s->buffer, s->current_buffer_index);
    1163           0 :   if (n < 0)
    1164             :     {
    1165           0 :       if (!unix_error_is_fatal (errno))
    1166           0 :         n = 0;
    1167             :       else
    1168           0 :         serialize_error (m, clib_error_return_unix (0, "write"));
    1169             :     }
    1170           0 :   if (n == s->current_buffer_index)
    1171           0 :     vec_set_len (s->buffer, 0);
    1172             :   else
    1173           0 :     vec_delete (s->buffer, n, 0);
    1174           0 :   s->current_buffer_index = vec_len (s->buffer);
    1175           0 : }
    1176             : 
    1177             : static void
    1178           0 : clib_file_read (serialize_main_header_t * m, serialize_stream_t * s)
    1179             : {
    1180             :   int fd, n;
    1181             : 
    1182           0 :   fd = s->data_function_opaque;
    1183           0 :   n = read (fd, s->buffer, vec_len (s->buffer));
    1184           0 :   if (n < 0)
    1185             :     {
    1186           0 :       if (!unix_error_is_fatal (errno))
    1187           0 :         n = 0;
    1188             :       else
    1189           0 :         serialize_error (m, clib_error_return_unix (0, "read"));
    1190             :     }
    1191           0 :   else if (n == 0)
    1192           0 :     serialize_stream_set_end_of_stream (s);
    1193           0 :   s->current_buffer_index = 0;
    1194           0 :   s->n_buffer_bytes = n;
    1195           0 : }
    1196             : 
    1197             : static void
    1198           0 : serialize_open_clib_file_descriptor_helper (serialize_main_t * m, int fd,
    1199             :                                             uword is_read)
    1200             : {
    1201           0 :   clib_memset (m, 0, sizeof (m[0]));
    1202           0 :   vec_resize (m->stream.buffer, 4096);
    1203             : 
    1204           0 :   if (!is_read)
    1205             :     {
    1206           0 :       m->stream.n_buffer_bytes = vec_len (m->stream.buffer);
    1207           0 :       vec_set_len (m->stream.buffer, 0);
    1208             :     }
    1209             : 
    1210           0 :   m->header.data_function = is_read ? clib_file_read : clib_file_write;
    1211           0 :   m->stream.data_function_opaque = fd;
    1212           0 : }
    1213             : 
    1214             : __clib_export void
    1215           0 : serialize_open_clib_file_descriptor (serialize_main_t * m, int fd)
    1216             : {
    1217           0 :   serialize_open_clib_file_descriptor_helper (m, fd, /* is_read */ 0);
    1218           0 : }
    1219             : 
    1220             : __clib_export void
    1221           0 : unserialize_open_clib_file_descriptor (serialize_main_t * m, int fd)
    1222             : {
    1223           0 :   serialize_open_clib_file_descriptor_helper (m, fd, /* is_read */ 1);
    1224           0 : }
    1225             : 
    1226             : static clib_error_t *
    1227           0 : serialize_open_clib_file_helper (serialize_main_t * m, char *file,
    1228             :                                  uword is_read)
    1229             : {
    1230             :   int fd, mode;
    1231             : 
    1232           0 :   mode = is_read ? O_RDONLY : O_RDWR | O_CREAT | O_TRUNC;
    1233           0 :   fd = open (file, mode, 0666);
    1234           0 :   if (fd < 0)
    1235           0 :     return clib_error_return_unix (0, "open `%s'", file);
    1236             : 
    1237           0 :   serialize_open_clib_file_descriptor_helper (m, fd, is_read);
    1238           0 :   return 0;
    1239             : }
    1240             : 
    1241             : __clib_export clib_error_t *
    1242           0 : serialize_open_clib_file (serialize_main_t * m, char *file)
    1243             : {
    1244           0 :   return serialize_open_clib_file_helper (m, file, /* is_read */ 0);
    1245             : }
    1246             : 
    1247             : __clib_export clib_error_t *
    1248           0 : unserialize_open_clib_file (serialize_main_t * m, char *file)
    1249             : {
    1250           0 :   return serialize_open_clib_file_helper (m, file, /* is_read */ 1);
    1251             : }
    1252             : 
    1253             : #endif /* CLIB_UNIX */
    1254             : 
    1255             : /*
    1256             :  * fd.io coding-style-patch-verification: ON
    1257             :  *
    1258             :  * Local Variables:
    1259             :  * eval: (c-set-style "gnu")
    1260             :  * End:
    1261             :  */

Generated by: LCOV version 1.14