blob: 89a0e36dcf12b3c1d04f46e38e8c3736b40b3bf6 [file] [log] [blame]
Ed Warnickecb9cada2015-12-08 15:45:58 -07001/*
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
Dave Barachc3799992016-08-15 11:12:27 -040044void
45serialize_64 (serialize_main_t * m, va_list * va)
Ed Warnickecb9cada2015-12-08 15:45:58 -070046{
47 u64 x = va_arg (*va, u64);
48 u32 lo, hi;
49 lo = x;
50 hi = x >> 32;
51 serialize_integer (m, lo, sizeof (lo));
52 serialize_integer (m, hi, sizeof (hi));
53}
54
Dave Barachc3799992016-08-15 11:12:27 -040055void
56serialize_32 (serialize_main_t * m, va_list * va)
Ed Warnickecb9cada2015-12-08 15:45:58 -070057{
58 u32 x = va_arg (*va, u32);
59 serialize_integer (m, x, sizeof (x));
60}
61
Dave Barachc3799992016-08-15 11:12:27 -040062void
63serialize_16 (serialize_main_t * m, va_list * va)
Ed Warnickecb9cada2015-12-08 15:45:58 -070064{
65 u32 x = va_arg (*va, u32);
66 serialize_integer (m, x, sizeof (u16));
67}
68
Dave Barachc3799992016-08-15 11:12:27 -040069void
70serialize_8 (serialize_main_t * m, va_list * va)
Ed Warnickecb9cada2015-12-08 15:45:58 -070071{
72 u32 x = va_arg (*va, u32);
73 serialize_integer (m, x, sizeof (u8));
74}
75
Dave Barachc3799992016-08-15 11:12:27 -040076void
77unserialize_64 (serialize_main_t * m, va_list * va)
Ed Warnickecb9cada2015-12-08 15:45:58 -070078{
Dave Barachc3799992016-08-15 11:12:27 -040079 u64 *x = va_arg (*va, u64 *);
Ed Warnickecb9cada2015-12-08 15:45:58 -070080 u32 lo, hi;
81 unserialize_integer (m, &lo, sizeof (lo));
82 unserialize_integer (m, &hi, sizeof (hi));
83 *x = ((u64) hi << 32) | (u64) lo;
84}
85
Dave Barachc3799992016-08-15 11:12:27 -040086void
87unserialize_32 (serialize_main_t * m, va_list * va)
Ed Warnickecb9cada2015-12-08 15:45:58 -070088{
Dave Barachc3799992016-08-15 11:12:27 -040089 u32 *x = va_arg (*va, u32 *);
Ed Warnickecb9cada2015-12-08 15:45:58 -070090 unserialize_integer (m, x, sizeof (x[0]));
91}
92
Dave Barachc3799992016-08-15 11:12:27 -040093void
94unserialize_16 (serialize_main_t * m, va_list * va)
Ed Warnickecb9cada2015-12-08 15:45:58 -070095{
Dave Barachc3799992016-08-15 11:12:27 -040096 u16 *x = va_arg (*va, u16 *);
Ed Warnickecb9cada2015-12-08 15:45:58 -070097 u32 t;
98 unserialize_integer (m, &t, sizeof (x[0]));
99 x[0] = t;
100}
101
Dave Barachc3799992016-08-15 11:12:27 -0400102void
103unserialize_8 (serialize_main_t * m, va_list * va)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700104{
Dave Barachc3799992016-08-15 11:12:27 -0400105 u8 *x = va_arg (*va, u8 *);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700106 u32 t;
107 unserialize_integer (m, &t, sizeof (x[0]));
108 x[0] = t;
109}
110
Dave Barachc3799992016-08-15 11:12:27 -0400111void
112serialize_f64 (serialize_main_t * m, va_list * va)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700113{
114 f64 x = va_arg (*va, f64);
Dave Barachc3799992016-08-15 11:12:27 -0400115 union
116 {
117 f64 f;
118 u64 i;
119 } y;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700120 y.f = x;
121 serialize (m, serialize_64, y.i);
122}
123
Dave Barachc3799992016-08-15 11:12:27 -0400124void
125serialize_f32 (serialize_main_t * m, va_list * va)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700126{
127 f32 x = va_arg (*va, f64);
Dave Barachc3799992016-08-15 11:12:27 -0400128 union
129 {
130 f32 f;
131 u32 i;
132 } y;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700133 y.f = x;
134 serialize_integer (m, y.i, sizeof (y.i));
135}
136
Dave Barachc3799992016-08-15 11:12:27 -0400137void
138unserialize_f64 (serialize_main_t * m, va_list * va)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700139{
Dave Barachc3799992016-08-15 11:12:27 -0400140 f64 *x = va_arg (*va, f64 *);
141 union
142 {
143 f64 f;
144 u64 i;
145 } y;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700146 unserialize (m, unserialize_64, &y.i);
147 *x = y.f;
148}
149
Dave Barachc3799992016-08-15 11:12:27 -0400150void
151unserialize_f32 (serialize_main_t * m, va_list * va)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700152{
Dave Barachc3799992016-08-15 11:12:27 -0400153 f32 *x = va_arg (*va, f32 *);
154 union
155 {
156 f32 f;
157 u32 i;
158 } y;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700159 unserialize_integer (m, &y.i, sizeof (y.i));
160 *x = y.f;
161}
162
Damjan Mariondae1c7e2020-10-17 13:32:25 +0200163__clib_export void
Dave Barachc3799992016-08-15 11:12:27 -0400164serialize_cstring (serialize_main_t * m, char *s)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700165{
166 u32 len = s ? strlen (s) : 0;
Dave Barachc3799992016-08-15 11:12:27 -0400167 void *p;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700168
169 serialize_likely_small_unsigned_integer (m, len);
Dave Barachc3799992016-08-15 11:12:27 -0400170 if (len > 0)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700171 {
172 p = serialize_get (m, len);
Dave Barach178cf492018-11-13 16:34:13 -0500173 clib_memcpy_fast (p, s, len);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700174 }
175}
176
Damjan Mariondae1c7e2020-10-17 13:32:25 +0200177__clib_export void
Dave Barachc3799992016-08-15 11:12:27 -0400178unserialize_cstring (serialize_main_t * m, char **s)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700179{
Dave Barachc3799992016-08-15 11:12:27 -0400180 char *p, *r = 0;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700181 u32 len;
182
183 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 if (len > 0 && len != 0xFFFFFFFF)
191 {
192 r = vec_new (char, len + 1);
193 p = unserialize_get (m, len);
Dave Barach178cf492018-11-13 16:34:13 -0500194 clib_memcpy_fast (r, p, len);
Dave Barachc3799992016-08-15 11:12:27 -0400195
Ed Warnickecb9cada2015-12-08 15:45:58 -0700196 /* Null terminate. */
197 r[len] = 0;
198 }
199 *s = r;
200}
201
202/* vec_serialize/vec_unserialize helper functions for basic vector types. */
Dave Barachc3799992016-08-15 11:12:27 -0400203void
204serialize_vec_8 (serialize_main_t * m, va_list * va)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700205{
Dave Barachc3799992016-08-15 11:12:27 -0400206 u8 *s = va_arg (*va, u8 *);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700207 u32 n = va_arg (*va, u32);
Dave Barachc3799992016-08-15 11:12:27 -0400208 u8 *p = serialize_get (m, n * sizeof (u8));
Dave Barach178cf492018-11-13 16:34:13 -0500209 clib_memcpy_fast (p, s, n * sizeof (u8));
Ed Warnickecb9cada2015-12-08 15:45:58 -0700210}
211
Dave Barachc3799992016-08-15 11:12:27 -0400212void
213unserialize_vec_8 (serialize_main_t * m, va_list * va)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700214{
Dave Barachc3799992016-08-15 11:12:27 -0400215 u8 *s = va_arg (*va, u8 *);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700216 u32 n = va_arg (*va, u32);
Dave Barachc3799992016-08-15 11:12:27 -0400217 u8 *p = unserialize_get (m, n);
Dave Barach178cf492018-11-13 16:34:13 -0500218 clib_memcpy_fast (s, p, n);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700219}
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
Dave Barachc3799992016-08-15 11:12:27 -0400274_(16);
275_(32);
276_(64);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700277
278#undef _
279
280#define SERIALIZE_VECTOR_CHUNK_SIZE 64
281
Damjan Mariondae1c7e2020-10-17 13:32:25 +0200282__clib_export void
Dave Barachc3799992016-08-15 11:12:27 -0400283serialize_vector (serialize_main_t * m, va_list * va)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700284{
Dave Barachc3799992016-08-15 11:12:27 -0400285 void *vec = va_arg (*va, void *);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700286 u32 elt_bytes = va_arg (*va, u32);
Dave Barachc3799992016-08-15 11:12:27 -0400287 serialize_function_t *f = va_arg (*va, serialize_function_t *);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700288 u32 l = vec_len (vec);
Dave Barachc3799992016-08-15 11:12:27 -0400289 void *p = vec;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700290
291 serialize_integer (m, l, sizeof (l));
292
293 /* Serialize vector in chunks for cache locality. */
294 while (l != 0)
295 {
296 u32 n = clib_min (SERIALIZE_VECTOR_CHUNK_SIZE, l);
297 serialize (m, f, p, n);
298 l -= n;
299 p += SERIALIZE_VECTOR_CHUNK_SIZE * elt_bytes;
300 }
301}
302
303void *
Dave Barachc3799992016-08-15 11:12:27 -0400304unserialize_vector_ha (serialize_main_t * m,
Ed Warnickecb9cada2015-12-08 15:45:58 -0700305 u32 elt_bytes,
306 u32 header_bytes,
Dave Barachc3799992016-08-15 11:12:27 -0400307 u32 align, u32 max_length, serialize_function_t * f)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700308{
Dave Barachc3799992016-08-15 11:12:27 -0400309 void *v, *p;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700310 u32 l;
311
312 unserialize_integer (m, &l, sizeof (l));
313 if (l > max_length)
Dave Barachc3799992016-08-15 11:12:27 -0400314 serialize_error (&m->header,
315 clib_error_create ("bad vector length %d", l));
Damjan Marion2f25ef32018-05-04 20:45:41 +0200316 p = v = _vec_resize ((void *) 0, l, (uword) l * elt_bytes, header_bytes,
Dave Barachc3799992016-08-15 11:12:27 -0400317 /* align */ align);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700318
319 while (l != 0)
320 {
321 u32 n = clib_min (SERIALIZE_VECTOR_CHUNK_SIZE, l);
322 unserialize (m, f, p, n);
323 l -= n;
324 p += SERIALIZE_VECTOR_CHUNK_SIZE * elt_bytes;
325 }
326 return v;
327}
328
Dave Barachc3799992016-08-15 11:12:27 -0400329void
330unserialize_aligned_vector (serialize_main_t * m, va_list * va)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700331{
Dave Barachc3799992016-08-15 11:12:27 -0400332 void **vec = va_arg (*va, void **);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700333 u32 elt_bytes = va_arg (*va, u32);
Dave Barachc3799992016-08-15 11:12:27 -0400334 serialize_function_t *f = va_arg (*va, serialize_function_t *);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700335 u32 align = va_arg (*va, u32);
336
337 *vec = unserialize_vector_ha (m, elt_bytes,
338 /* header_bytes */ 0,
339 /* align */ align,
340 /* max_length */ ~0,
341 f);
342}
343
Damjan Mariondae1c7e2020-10-17 13:32:25 +0200344__clib_export void
Dave Barachc3799992016-08-15 11:12:27 -0400345unserialize_vector (serialize_main_t * m, va_list * va)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700346{
Dave Barachc3799992016-08-15 11:12:27 -0400347 void **vec = va_arg (*va, void **);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700348 u32 elt_bytes = va_arg (*va, u32);
Dave Barachc3799992016-08-15 11:12:27 -0400349 serialize_function_t *f = va_arg (*va, serialize_function_t *);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700350
351 *vec = unserialize_vector_ha (m, elt_bytes,
352 /* header_bytes */ 0,
353 /* align */ 0,
354 /* max_length */ ~0,
355 f);
356}
357
Dave Barachc3799992016-08-15 11:12:27 -0400358void
359serialize_bitmap (serialize_main_t * m, uword * b)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700360{
361 u32 l, i, n_u32s;
362
363 l = vec_len (b);
364 n_u32s = l * sizeof (b[0]) / sizeof (u32);
365 serialize_integer (m, n_u32s, sizeof (n_u32s));
366
367 /* Send 32 bit words, low-order word first on 64 bit. */
368 for (i = 0; i < l; i++)
369 {
370 serialize_integer (m, b[i], sizeof (u32));
371 if (BITS (uword) == 64)
372 serialize_integer (m, (u64) b[i] >> (u64) 32, sizeof (u32));
373 }
374}
375
Dave Barachc3799992016-08-15 11:12:27 -0400376uword *
377unserialize_bitmap (serialize_main_t * m)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700378{
Dave Barachc3799992016-08-15 11:12:27 -0400379 uword *b = 0;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700380 u32 i, n_u32s;
381
382 unserialize_integer (m, &n_u32s, sizeof (n_u32s));
383 if (n_u32s == 0)
384 return b;
385
386 i = (n_u32s * sizeof (u32) + sizeof (b[0]) - 1) / sizeof (b[0]);
387 vec_resize (b, i);
388 for (i = 0; i < n_u32s; i++)
389 {
390 u32 data;
391 unserialize_integer (m, &data, sizeof (u32));
392
393 /* Low-word is first on 64 bit. */
394 if (BITS (uword) == 64)
395 {
396 if ((i % 2) == 0)
Dave Barachc3799992016-08-15 11:12:27 -0400397 b[i / 2] |= (u64) data << (u64) 0;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700398 else
Dave Barachc3799992016-08-15 11:12:27 -0400399 b[i / 2] |= (u64) data << (u64) 32;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700400 }
401 else
402 {
403 b[i] = data;
404 }
405 }
406
407 return b;
408}
409
Dave Barachc3799992016-08-15 11:12:27 -0400410void
411serialize_pool (serialize_main_t * m, va_list * va)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700412{
Dave Barachc3799992016-08-15 11:12:27 -0400413 void *pool = va_arg (*va, void *);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700414 u32 elt_bytes = va_arg (*va, u32);
Dave Barachc3799992016-08-15 11:12:27 -0400415 serialize_function_t *f = va_arg (*va, serialize_function_t *);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700416 u32 l, lo, hi;
Dave Barachc3799992016-08-15 11:12:27 -0400417 pool_header_t *p;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700418
419 l = vec_len (pool);
420 serialize_integer (m, l, sizeof (u32));
421 if (l == 0)
422 return;
423 p = pool_header (pool);
424
425 /* No need to send free bitmap. Need to send index vector
426 to guarantee that unserialized pool will be identical. */
427 vec_serialize (m, p->free_indices, serialize_vec_32);
428
429 pool_foreach_region (lo, hi, pool,
Dave Barachc3799992016-08-15 11:12:27 -0400430 serialize (m, f, pool + lo * elt_bytes, hi - lo));
Ed Warnickecb9cada2015-12-08 15:45:58 -0700431}
432
433static void *
434unserialize_pool_helper (serialize_main_t * m,
Dave Barachc3799992016-08-15 11:12:27 -0400435 u32 elt_bytes, u32 align, serialize_function_t * f)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700436{
Dave Barachc3799992016-08-15 11:12:27 -0400437 void *v;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700438 u32 i, l, lo, hi;
Dave Barachc3799992016-08-15 11:12:27 -0400439 pool_header_t *p;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700440
441 unserialize_integer (m, &l, sizeof (l));
442 if (l == 0)
443 {
444 return 0;
445 }
446
Damjan Marion2f25ef32018-05-04 20:45:41 +0200447 v = _vec_resize ((void *) 0, l, (uword) l * elt_bytes, sizeof (p[0]),
448 align);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700449 p = pool_header (v);
450
451 vec_unserialize (m, &p->free_indices, unserialize_vec_32);
452
453 /* Construct free bitmap. */
454 p->free_bitmap = 0;
455 for (i = 0; i < vec_len (p->free_indices); i++)
456 p->free_bitmap = clib_bitmap_ori (p->free_bitmap, p->free_indices[i]);
457
458 pool_foreach_region (lo, hi, v,
Dave Barachc3799992016-08-15 11:12:27 -0400459 unserialize (m, f, v + lo * elt_bytes, hi - lo));
Ed Warnickecb9cada2015-12-08 15:45:58 -0700460
461 return v;
462}
463
Dave Barachc3799992016-08-15 11:12:27 -0400464void
465unserialize_pool (serialize_main_t * m, va_list * va)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700466{
Dave Barachc3799992016-08-15 11:12:27 -0400467 void **result = va_arg (*va, void **);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700468 u32 elt_bytes = va_arg (*va, u32);
Dave Barachc3799992016-08-15 11:12:27 -0400469 serialize_function_t *f = va_arg (*va, serialize_function_t *);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700470 *result = unserialize_pool_helper (m, elt_bytes, /* align */ 0, f);
471}
472
Dave Barachc3799992016-08-15 11:12:27 -0400473void
474unserialize_aligned_pool (serialize_main_t * m, va_list * va)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700475{
Dave Barachc3799992016-08-15 11:12:27 -0400476 void **result = va_arg (*va, void **);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700477 u32 elt_bytes = va_arg (*va, u32);
478 u32 align = va_arg (*va, u32);
Dave Barachc3799992016-08-15 11:12:27 -0400479 serialize_function_t *f = va_arg (*va, serialize_function_t *);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700480 *result = unserialize_pool_helper (m, elt_bytes, align, f);
481}
482
Dave Barachc3799992016-08-15 11:12:27 -0400483static void
484serialize_vec_heap_elt (serialize_main_t * m, va_list * va)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700485{
Dave Barachc3799992016-08-15 11:12:27 -0400486 heap_elt_t *e = va_arg (*va, heap_elt_t *);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700487 u32 i, n = va_arg (*va, u32);
488 for (i = 0; i < n; i++)
489 {
490 serialize_integer (m, e[i].offset, sizeof (e[i].offset));
491 serialize_integer (m, e[i].next, sizeof (e[i].next));
492 serialize_integer (m, e[i].prev, sizeof (e[i].prev));
493 }
494}
495
Dave Barachc3799992016-08-15 11:12:27 -0400496static void
497unserialize_vec_heap_elt (serialize_main_t * m, va_list * va)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700498{
Dave Barachc3799992016-08-15 11:12:27 -0400499 heap_elt_t *e = va_arg (*va, heap_elt_t *);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700500 u32 i, n = va_arg (*va, u32);
501 for (i = 0; i < n; i++)
502 {
503 unserialize_integer (m, &e[i].offset, sizeof (e[i].offset));
504 unserialize_integer (m, &e[i].next, sizeof (e[i].next));
505 unserialize_integer (m, &e[i].prev, sizeof (e[i].prev));
506 }
507}
508
Dave Barachc3799992016-08-15 11:12:27 -0400509void
510serialize_heap (serialize_main_t * m, va_list * va)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700511{
Dave Barachc3799992016-08-15 11:12:27 -0400512 void *heap = va_arg (*va, void *);
513 serialize_function_t *f = va_arg (*va, serialize_function_t *);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700514 u32 i, l;
Dave Barachc3799992016-08-15 11:12:27 -0400515 heap_header_t *h;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700516
517 l = vec_len (heap);
518 serialize_integer (m, l, sizeof (u32));
519 if (l == 0)
520 return;
521
522 h = heap_header (heap);
523
524#define foreach_serialize_heap_header_integer \
525 _ (head) _ (tail) _ (used_count) _ (max_len) _ (flags) _ (elt_bytes)
526
527#define _(f) serialize_integer (m, h->f, sizeof (h->f));
528 foreach_serialize_heap_header_integer;
529#undef _
530
531 serialize_integer (m, vec_len (h->free_lists), sizeof (u32));
532 for (i = 0; i < vec_len (h->free_lists); i++)
533 vec_serialize (m, h->free_lists[i], serialize_vec_32);
534
535 vec_serialize (m, h->elts, serialize_vec_heap_elt);
536 vec_serialize (m, h->small_free_elt_free_index, serialize_vec_32);
537 vec_serialize (m, h->free_elts, serialize_vec_32);
538
539 /* Serialize data in heap. */
540 {
Dave Barachc3799992016-08-15 11:12:27 -0400541 heap_elt_t *e, *end;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700542 e = h->elts + h->head;
543 end = h->elts + h->tail;
544 while (1)
545 {
Dave Barachc3799992016-08-15 11:12:27 -0400546 if (!heap_is_free (e))
Ed Warnickecb9cada2015-12-08 15:45:58 -0700547 {
Dave Barachc3799992016-08-15 11:12:27 -0400548 void *v = heap + heap_offset (e) * h->elt_bytes;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700549 u32 n = heap_elt_size (heap, e);
550 serialize (m, f, v, n);
551 }
552 if (e == end)
553 break;
554 e = heap_next (e);
555 }
556 }
557}
558
Dave Barachc3799992016-08-15 11:12:27 -0400559void
560unserialize_heap (serialize_main_t * m, va_list * va)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700561{
Dave Barachc3799992016-08-15 11:12:27 -0400562 void **result = va_arg (*va, void **);
563 serialize_function_t *f = va_arg (*va, serialize_function_t *);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700564 u32 i, vl, fl;
565 heap_header_t h;
Dave Barachc3799992016-08-15 11:12:27 -0400566 void *heap;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700567
568 unserialize_integer (m, &vl, sizeof (u32));
569 if (vl == 0)
570 {
571 *result = 0;
572 return;
573 }
574
Dave Barachb7b92992018-10-17 10:38:51 -0400575 clib_memset (&h, 0, sizeof (h));
Ed Warnickecb9cada2015-12-08 15:45:58 -0700576#define _(f) unserialize_integer (m, &h.f, sizeof (h.f));
577 foreach_serialize_heap_header_integer;
578#undef _
579
580 unserialize_integer (m, &fl, sizeof (u32));
581 vec_resize (h.free_lists, fl);
582
583 for (i = 0; i < vec_len (h.free_lists); i++)
584 vec_unserialize (m, &h.free_lists[i], unserialize_vec_32);
585
586 vec_unserialize (m, &h.elts, unserialize_vec_heap_elt);
587 vec_unserialize (m, &h.small_free_elt_free_index, unserialize_vec_32);
588 vec_unserialize (m, &h.free_elts, unserialize_vec_32);
589
590 /* Re-construct used elt bitmap. */
591 if (CLIB_DEBUG > 0)
592 {
Dave Barachc3799992016-08-15 11:12:27 -0400593 heap_elt_t *e;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700594 vec_foreach (e, h.elts)
Dave Barachc3799992016-08-15 11:12:27 -0400595 {
596 if (!heap_is_free (e))
597 h.used_elt_bitmap = clib_bitmap_ori (h.used_elt_bitmap, e - h.elts);
598 }
Ed Warnickecb9cada2015-12-08 15:45:58 -0700599 }
600
601 heap = *result = _heap_new (vl, h.elt_bytes);
602 heap_header (heap)[0] = h;
603
604 /* Unserialize data in heap. */
605 {
Dave Barachc3799992016-08-15 11:12:27 -0400606 heap_elt_t *e, *end;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700607 e = h.elts + h.head;
608 end = h.elts + h.tail;
609 while (1)
610 {
Dave Barachc3799992016-08-15 11:12:27 -0400611 if (!heap_is_free (e))
Ed Warnickecb9cada2015-12-08 15:45:58 -0700612 {
Dave Barachc3799992016-08-15 11:12:27 -0400613 void *v = heap + heap_offset (e) * h.elt_bytes;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700614 u32 n = heap_elt_size (heap, e);
615 unserialize (m, f, v, n);
616 }
617 if (e == end)
618 break;
619 e = heap_next (e);
620 }
621 }
622}
623
Dave Barachc3799992016-08-15 11:12:27 -0400624void
625serialize_magic (serialize_main_t * m, void *magic, u32 magic_bytes)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700626{
Dave Barachc3799992016-08-15 11:12:27 -0400627 void *p;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700628 serialize_integer (m, magic_bytes, sizeof (magic_bytes));
629 p = serialize_get (m, magic_bytes);
Dave Barach178cf492018-11-13 16:34:13 -0500630 clib_memcpy_fast (p, magic, magic_bytes);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700631}
632
Dave Barachc3799992016-08-15 11:12:27 -0400633void
634unserialize_check_magic (serialize_main_t * m, void *magic, u32 magic_bytes)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700635{
636 u32 l;
Dave Barachc3799992016-08-15 11:12:27 -0400637 void *d;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700638
639 unserialize_integer (m, &l, sizeof (l));
640 if (l != magic_bytes)
641 {
642 bad:
643 serialize_error_return (m, "bad magic number");
644 }
645 d = serialize_get (m, magic_bytes);
646 if (memcmp (magic, d, magic_bytes))
647 goto bad;
648}
649
Damjan Mariondae1c7e2020-10-17 13:32:25 +0200650__clib_export clib_error_t *
Ed Warnickecb9cada2015-12-08 15:45:58 -0700651va_serialize (serialize_main_t * sm, va_list * va)
652{
Dave Barachc3799992016-08-15 11:12:27 -0400653 serialize_main_header_t *m = &sm->header;
654 serialize_function_t *f = va_arg (*va, serialize_function_t *);
655 clib_error_t *error = 0;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700656
657 m->recursion_level += 1;
658 if (m->recursion_level == 1)
659 {
660 uword r = clib_setjmp (&m->error_longjmp, 0);
661 error = uword_to_pointer (r, clib_error_t *);
662 }
Dave Barachc3799992016-08-15 11:12:27 -0400663
664 if (!error)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700665 f (sm, va);
666
667 m->recursion_level -= 1;
668 return error;
669}
670
Damjan Mariondae1c7e2020-10-17 13:32:25 +0200671__clib_export clib_error_t *
Ed Warnickecb9cada2015-12-08 15:45:58 -0700672serialize (serialize_main_t * m, ...)
673{
Dave Barachc3799992016-08-15 11:12:27 -0400674 clib_error_t *error;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700675 va_list va;
676
677 va_start (va, m);
678 error = va_serialize (m, &va);
679 va_end (va);
680 return error;
681}
682
Damjan Mariondae1c7e2020-10-17 13:32:25 +0200683__clib_export clib_error_t *
Ed Warnickecb9cada2015-12-08 15:45:58 -0700684unserialize (serialize_main_t * m, ...)
685{
Dave Barachc3799992016-08-15 11:12:27 -0400686 clib_error_t *error;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700687 va_list va;
688
689 va_start (va, m);
690 error = va_serialize (m, &va);
691 va_end (va);
692 return error;
693}
694
Dave Barachc3799992016-08-15 11:12:27 -0400695static void *
696serialize_write_not_inline (serialize_main_header_t * m,
697 serialize_stream_t * s,
698 uword n_bytes_to_write, uword flags)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700699{
700 uword cur_bi, n_left_b, n_left_o;
701
702 ASSERT (s->current_buffer_index <= s->n_buffer_bytes);
703 cur_bi = s->current_buffer_index;
704 n_left_b = s->n_buffer_bytes - cur_bi;
705 n_left_o = vec_len (s->overflow_buffer);
706
707 /* Prepend overflow buffer if present. */
Dave Barachc3799992016-08-15 11:12:27 -0400708 do
709 {
710 if (n_left_o > 0 && n_left_b > 0)
711 {
712 uword n = clib_min (n_left_b, n_left_o);
Dave Barach178cf492018-11-13 16:34:13 -0500713 clib_memcpy_fast (s->buffer + cur_bi, s->overflow_buffer, n);
Dave Barachc3799992016-08-15 11:12:27 -0400714 cur_bi += n;
715 n_left_b -= n;
716 n_left_o -= n;
717 if (n_left_o == 0)
718 _vec_len (s->overflow_buffer) = 0;
719 else
720 vec_delete (s->overflow_buffer, n, 0);
721 }
Ed Warnickecb9cada2015-12-08 15:45:58 -0700722
Dave Barachc3799992016-08-15 11:12:27 -0400723 /* Call data function when buffer is complete. Data function should
724 dispatch with current buffer and give us a new one to write more
725 data into. */
726 if (n_left_b == 0)
727 {
728 s->current_buffer_index = cur_bi;
729 m->data_function (m, s);
730 cur_bi = s->current_buffer_index;
731 n_left_b = s->n_buffer_bytes - cur_bi;
732 }
733 }
734 while (n_left_o > 0);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700735
736 if (n_left_o > 0 || n_left_b < n_bytes_to_write)
737 {
Dave Barachc3799992016-08-15 11:12:27 -0400738 u8 *r;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700739 vec_add2 (s->overflow_buffer, r, n_bytes_to_write);
740 return r;
741 }
742 else
743 {
744 s->current_buffer_index = cur_bi + n_bytes_to_write;
745 return s->buffer + cur_bi;
746 }
747}
748
Dave Barachc3799992016-08-15 11:12:27 -0400749static void *
750serialize_read_not_inline (serialize_main_header_t * m,
751 serialize_stream_t * s,
752 uword n_bytes_to_read, uword flags)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700753{
754 uword cur_bi, cur_oi, n_left_b, n_left_o, n_left_to_read;
755
756 ASSERT (s->current_buffer_index <= s->n_buffer_bytes);
757
758 cur_bi = s->current_buffer_index;
759 cur_oi = s->current_overflow_index;
760
761 n_left_b = s->n_buffer_bytes - cur_bi;
762 n_left_o = vec_len (s->overflow_buffer) - cur_oi;
763
764 /* Read from overflow? */
765 if (n_left_o >= n_bytes_to_read)
766 {
767 s->current_overflow_index = cur_oi + n_bytes_to_read;
768 return vec_elt_at_index (s->overflow_buffer, cur_oi);
769 }
770
771 /* Reset overflow buffer. */
772 if (n_left_o == 0 && s->overflow_buffer)
773 {
774 s->current_overflow_index = 0;
775 _vec_len (s->overflow_buffer) = 0;
776 }
777
778 n_left_to_read = n_bytes_to_read;
779 while (n_left_to_read > 0)
780 {
781 uword n;
782
783 /* If we don't have enough data between overflow and normal buffer
Dave Barachc3799992016-08-15 11:12:27 -0400784 call read function. */
Ed Warnickecb9cada2015-12-08 15:45:58 -0700785 if (n_left_o + n_left_b < n_bytes_to_read)
786 {
787 /* Save any left over buffer in overflow vector. */
788 if (n_left_b > 0)
789 {
790 vec_add (s->overflow_buffer, s->buffer + cur_bi, n_left_b);
791 n_left_o += n_left_b;
792 n_left_to_read -= n_left_b;
793 /* Advance buffer to end --- even if
Dave Barachc3799992016-08-15 11:12:27 -0400794 SERIALIZE_FLAG_NO_ADVANCE_CURRENT_BUFFER_INDEX is set. */
Ed Warnickecb9cada2015-12-08 15:45:58 -0700795 cur_bi = s->n_buffer_bytes;
796 n_left_b = 0;
797 }
798
799 if (m->data_function)
800 {
801 m->data_function (m, s);
802 cur_bi = s->current_buffer_index;
803 n_left_b = s->n_buffer_bytes - cur_bi;
804 }
805 }
806
807 /* For first time through loop return if we have enough data
Dave Barachc3799992016-08-15 11:12:27 -0400808 in normal buffer and overflow vector is empty. */
Ed Warnickecb9cada2015-12-08 15:45:58 -0700809 if (n_left_o == 0
Dave Barachc3799992016-08-15 11:12:27 -0400810 && n_left_to_read == n_bytes_to_read && n_left_b >= n_left_to_read)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700811 {
812 s->current_buffer_index = cur_bi + n_bytes_to_read;
813 return s->buffer + cur_bi;
814 }
815
Dave Barachc3799992016-08-15 11:12:27 -0400816 if (!m->data_function || serialize_stream_is_end_of_stream (s))
Ed Warnickecb9cada2015-12-08 15:45:58 -0700817 {
818 /* This can happen for a peek at end of file.
819 Pad overflow buffer with 0s. */
820 vec_resize (s->overflow_buffer, n_left_to_read);
821 n_left_o += n_left_to_read;
822 n_left_to_read = 0;
823 }
824 else
825 {
826 /* Copy from buffer to overflow vector. */
827 n = clib_min (n_left_to_read, n_left_b);
828 vec_add (s->overflow_buffer, s->buffer + cur_bi, n);
829 cur_bi += n;
830 n_left_b -= n;
831 n_left_o += n;
832 n_left_to_read -= n;
833 }
834 }
Dave Barachc3799992016-08-15 11:12:27 -0400835
Ed Warnickecb9cada2015-12-08 15:45:58 -0700836 s->current_buffer_index = cur_bi;
837 s->current_overflow_index = cur_oi + n_bytes_to_read;
838 return vec_elt_at_index (s->overflow_buffer, cur_oi);
839}
840
Damjan Mariondae1c7e2020-10-17 13:32:25 +0200841__clib_export void *
Dave Barachc3799992016-08-15 11:12:27 -0400842serialize_read_write_not_inline (serialize_main_header_t * m,
843 serialize_stream_t * s,
844 uword n_bytes, uword flags)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700845{
Dave Barachc3799992016-08-15 11:12:27 -0400846 return (((flags & SERIALIZE_FLAG_IS_READ) ? serialize_read_not_inline :
847 serialize_write_not_inline) (m, s, n_bytes, flags));
Ed Warnickecb9cada2015-12-08 15:45:58 -0700848}
849
Dave Barachc3799992016-08-15 11:12:27 -0400850static void
851serialize_read_write_close (serialize_main_header_t * m,
852 serialize_stream_t * s, uword flags)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700853{
854 if (serialize_stream_is_end_of_stream (s))
855 return;
856
857 if (flags & SERIALIZE_FLAG_IS_WRITE)
858 /* "Write" 0 bytes to flush overflow vector. */
859 serialize_write_not_inline (m, s, /* n bytes */ 0, flags);
860
861 serialize_stream_set_end_of_stream (s);
862
863 /* Call it one last time to flush buffer and close. */
864 m->data_function (m, s);
865
866 vec_free (s->overflow_buffer);
867}
868
Damjan Mariondae1c7e2020-10-17 13:32:25 +0200869__clib_export void
Dave Barachc3799992016-08-15 11:12:27 -0400870serialize_close (serialize_main_t * m)
871{
872 serialize_read_write_close (&m->header, &m->stream,
873 SERIALIZE_FLAG_IS_WRITE);
874}
Ed Warnickecb9cada2015-12-08 15:45:58 -0700875
Damjan Mariondae1c7e2020-10-17 13:32:25 +0200876__clib_export void
Dave Barachc3799992016-08-15 11:12:27 -0400877unserialize_close (serialize_main_t * m)
878{
879 serialize_read_write_close (&m->header, &m->stream, SERIALIZE_FLAG_IS_READ);
880}
Ed Warnickecb9cada2015-12-08 15:45:58 -0700881
Damjan Mariondae1c7e2020-10-17 13:32:25 +0200882__clib_export void
Dave Barachc3799992016-08-15 11:12:27 -0400883serialize_open_data (serialize_main_t * m, u8 * data, uword n_data_bytes)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700884{
Dave Barachb7b92992018-10-17 10:38:51 -0400885 clib_memset (m, 0, sizeof (m[0]));
Ed Warnickecb9cada2015-12-08 15:45:58 -0700886 m->stream.buffer = data;
887 m->stream.n_buffer_bytes = n_data_bytes;
888}
889
Damjan Mariondae1c7e2020-10-17 13:32:25 +0200890__clib_export void
Dave Barachc3799992016-08-15 11:12:27 -0400891unserialize_open_data (serialize_main_t * m, u8 * data, uword n_data_bytes)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700892{
Dave Barachc3799992016-08-15 11:12:27 -0400893 serialize_open_data (m, data, n_data_bytes);
894}
895
896static void
897serialize_vector_write (serialize_main_header_t * m, serialize_stream_t * s)
898{
899 if (!serialize_stream_is_end_of_stream (s))
Ed Warnickecb9cada2015-12-08 15:45:58 -0700900 {
901 /* Double buffer size. */
902 uword l = vec_len (s->buffer);
903 vec_resize (s->buffer, l > 0 ? l : 64);
904 s->n_buffer_bytes = vec_len (s->buffer);
905 }
906}
907
Damjan Mariondae1c7e2020-10-17 13:32:25 +0200908__clib_export void
Dave Barachc3799992016-08-15 11:12:27 -0400909serialize_open_vector (serialize_main_t * m, u8 * vector)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700910{
Dave Barachb7b92992018-10-17 10:38:51 -0400911 clib_memset (m, 0, sizeof (m[0]));
Ed Warnickecb9cada2015-12-08 15:45:58 -0700912 m->header.data_function = serialize_vector_write;
913 m->stream.buffer = vector;
914 m->stream.current_buffer_index = 0;
915 m->stream.n_buffer_bytes = vec_len (vector);
916}
Dave Barachc3799992016-08-15 11:12:27 -0400917
Damjan Mariondae1c7e2020-10-17 13:32:25 +0200918__clib_export void *
Dave Barachc3799992016-08-15 11:12:27 -0400919serialize_close_vector (serialize_main_t * m)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700920{
Dave Barachc3799992016-08-15 11:12:27 -0400921 serialize_stream_t *s = &m->stream;
922 void *result;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700923
924 serialize_close (m); /* frees overflow buffer */
925
926 if (s->buffer)
927 _vec_len (s->buffer) = s->current_buffer_index;
928 result = s->buffer;
Dave Barachb7b92992018-10-17 10:38:51 -0400929 clib_memset (m, 0, sizeof (m[0]));
Ed Warnickecb9cada2015-12-08 15:45:58 -0700930 return result;
931}
Dave Barachc3799992016-08-15 11:12:27 -0400932
Ed Warnickecb9cada2015-12-08 15:45:58 -0700933void
934serialize_multiple_1 (serialize_main_t * m,
Dave Barachc3799992016-08-15 11:12:27 -0400935 void *data, uword data_stride, uword n_data)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700936{
Dave Barachc3799992016-08-15 11:12:27 -0400937 u8 *d = data;
938 u8 *p;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700939 uword n_left = n_data;
940
941 while (n_left >= 4)
942 {
943 p = serialize_get (m, 4 * sizeof (d[0]));
944 p[0] = d[0 * data_stride];
945 p[1] = d[1 * data_stride];
946 p[2] = d[2 * data_stride];
947 p[3] = d[3 * data_stride];
948 n_left -= 4;
949 d += 4 * data_stride;
950 }
951
952 if (n_left > 0)
953 {
954 p = serialize_get (m, n_left * sizeof (p[0]));
955 while (n_left > 0)
956 {
957 p[0] = d[0];
958 p += 1;
959 d += 1 * data_stride;
960 n_left -= 1;
961 }
962 }
963}
964
965void
966serialize_multiple_2 (serialize_main_t * m,
Dave Barachc3799992016-08-15 11:12:27 -0400967 void *data, uword data_stride, uword n_data)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700968{
Dave Barachc3799992016-08-15 11:12:27 -0400969 void *d = data;
970 u16 *p;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700971 uword n_left = n_data;
972
973 while (n_left >= 4)
974 {
975 p = serialize_get (m, 4 * sizeof (p[0]));
Dave Barachc3799992016-08-15 11:12:27 -0400976 clib_mem_unaligned (p + 0, u16) =
977 clib_host_to_net_mem_u16 (d + 0 * data_stride);
978 clib_mem_unaligned (p + 1, u16) =
979 clib_host_to_net_mem_u16 (d + 1 * data_stride);
980 clib_mem_unaligned (p + 2, u16) =
981 clib_host_to_net_mem_u16 (d + 2 * data_stride);
982 clib_mem_unaligned (p + 3, u16) =
983 clib_host_to_net_mem_u16 (d + 3 * data_stride);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700984 n_left -= 4;
985 d += 4 * data_stride;
986 }
987
988 if (n_left > 0)
989 {
990 p = serialize_get (m, n_left * sizeof (p[0]));
991 while (n_left > 0)
992 {
Dave Barachc3799992016-08-15 11:12:27 -0400993 clib_mem_unaligned (p + 0, u16) =
994 clib_host_to_net_mem_u16 (d + 0 * data_stride);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700995 p += 1;
996 d += 1 * data_stride;
997 n_left -= 1;
998 }
999 }
1000}
1001
1002void
1003serialize_multiple_4 (serialize_main_t * m,
Dave Barachc3799992016-08-15 11:12:27 -04001004 void *data, uword data_stride, uword n_data)
Ed Warnickecb9cada2015-12-08 15:45:58 -07001005{
Dave Barachc3799992016-08-15 11:12:27 -04001006 void *d = data;
1007 u32 *p;
Ed Warnickecb9cada2015-12-08 15:45:58 -07001008 uword n_left = n_data;
1009
1010 while (n_left >= 4)
1011 {
1012 p = serialize_get (m, 4 * sizeof (p[0]));
Dave Barachc3799992016-08-15 11:12:27 -04001013 clib_mem_unaligned (p + 0, u32) =
1014 clib_host_to_net_mem_u32 (d + 0 * data_stride);
1015 clib_mem_unaligned (p + 1, u32) =
1016 clib_host_to_net_mem_u32 (d + 1 * data_stride);
1017 clib_mem_unaligned (p + 2, u32) =
1018 clib_host_to_net_mem_u32 (d + 2 * data_stride);
1019 clib_mem_unaligned (p + 3, u32) =
1020 clib_host_to_net_mem_u32 (d + 3 * data_stride);
Ed Warnickecb9cada2015-12-08 15:45:58 -07001021 n_left -= 4;
1022 d += 4 * data_stride;
1023 }
1024
1025 if (n_left > 0)
1026 {
1027 p = serialize_get (m, n_left * sizeof (p[0]));
1028 while (n_left > 0)
1029 {
Dave Barachc3799992016-08-15 11:12:27 -04001030 clib_mem_unaligned (p + 0, u32) =
1031 clib_host_to_net_mem_u32 (d + 0 * data_stride);
Ed Warnickecb9cada2015-12-08 15:45:58 -07001032 p += 1;
1033 d += 1 * data_stride;
1034 n_left -= 1;
1035 }
1036 }
1037}
1038
1039void
1040unserialize_multiple_1 (serialize_main_t * m,
Dave Barachc3799992016-08-15 11:12:27 -04001041 void *data, uword data_stride, uword n_data)
Ed Warnickecb9cada2015-12-08 15:45:58 -07001042{
Dave Barachc3799992016-08-15 11:12:27 -04001043 u8 *d = data;
1044 u8 *p;
Ed Warnickecb9cada2015-12-08 15:45:58 -07001045 uword n_left = n_data;
1046
1047 while (n_left >= 4)
1048 {
1049 p = unserialize_get (m, 4 * sizeof (d[0]));
1050 d[0 * data_stride] = p[0];
1051 d[1 * data_stride] = p[1];
1052 d[2 * data_stride] = p[2];
1053 d[3 * data_stride] = p[3];
1054 n_left -= 4;
1055 d += 4 * data_stride;
1056 }
1057
1058 if (n_left > 0)
1059 {
1060 p = unserialize_get (m, n_left * sizeof (p[0]));
1061 while (n_left > 0)
1062 {
1063 d[0] = p[0];
1064 p += 1;
1065 d += 1 * data_stride;
1066 n_left -= 1;
1067 }
1068 }
1069}
1070
1071void
1072unserialize_multiple_2 (serialize_main_t * m,
Dave Barachc3799992016-08-15 11:12:27 -04001073 void *data, uword data_stride, uword n_data)
Ed Warnickecb9cada2015-12-08 15:45:58 -07001074{
Dave Barachc3799992016-08-15 11:12:27 -04001075 void *d = data;
1076 u16 *p;
Ed Warnickecb9cada2015-12-08 15:45:58 -07001077 uword n_left = n_data;
1078
1079 while (n_left >= 4)
1080 {
1081 p = unserialize_get (m, 4 * sizeof (p[0]));
Dave Barachc3799992016-08-15 11:12:27 -04001082 clib_mem_unaligned (d + 0 * data_stride, u16) =
1083 clib_net_to_host_mem_u16 (p + 0);
1084 clib_mem_unaligned (d + 1 * data_stride, u16) =
1085 clib_net_to_host_mem_u16 (p + 1);
1086 clib_mem_unaligned (d + 2 * data_stride, u16) =
1087 clib_net_to_host_mem_u16 (p + 2);
1088 clib_mem_unaligned (d + 3 * data_stride, u16) =
1089 clib_net_to_host_mem_u16 (p + 3);
Ed Warnickecb9cada2015-12-08 15:45:58 -07001090 n_left -= 4;
1091 d += 4 * data_stride;
1092 }
1093
1094 if (n_left > 0)
1095 {
1096 p = unserialize_get (m, n_left * sizeof (p[0]));
1097 while (n_left > 0)
1098 {
Dave Barachc3799992016-08-15 11:12:27 -04001099 clib_mem_unaligned (d + 0 * data_stride, u16) =
1100 clib_net_to_host_mem_u16 (p + 0);
Ed Warnickecb9cada2015-12-08 15:45:58 -07001101 p += 1;
1102 d += 1 * data_stride;
1103 n_left -= 1;
1104 }
1105 }
1106}
1107
1108void
1109unserialize_multiple_4 (serialize_main_t * m,
Dave Barachc3799992016-08-15 11:12:27 -04001110 void *data, uword data_stride, uword n_data)
Ed Warnickecb9cada2015-12-08 15:45:58 -07001111{
Dave Barachc3799992016-08-15 11:12:27 -04001112 void *d = data;
1113 u32 *p;
Ed Warnickecb9cada2015-12-08 15:45:58 -07001114 uword n_left = n_data;
1115
1116 while (n_left >= 4)
1117 {
1118 p = unserialize_get (m, 4 * sizeof (p[0]));
Dave Barachc3799992016-08-15 11:12:27 -04001119 clib_mem_unaligned (d + 0 * data_stride, u32) =
1120 clib_net_to_host_mem_u32 (p + 0);
1121 clib_mem_unaligned (d + 1 * data_stride, u32) =
1122 clib_net_to_host_mem_u32 (p + 1);
1123 clib_mem_unaligned (d + 2 * data_stride, u32) =
1124 clib_net_to_host_mem_u32 (p + 2);
1125 clib_mem_unaligned (d + 3 * data_stride, u32) =
1126 clib_net_to_host_mem_u32 (p + 3);
Ed Warnickecb9cada2015-12-08 15:45:58 -07001127 n_left -= 4;
1128 d += 4 * data_stride;
1129 }
1130
1131 if (n_left > 0)
1132 {
1133 p = unserialize_get (m, n_left * sizeof (p[0]));
1134 while (n_left > 0)
1135 {
Dave Barachc3799992016-08-15 11:12:27 -04001136 clib_mem_unaligned (d + 0 * data_stride, u32) =
1137 clib_net_to_host_mem_u32 (p + 0);
Ed Warnickecb9cada2015-12-08 15:45:58 -07001138 p += 1;
1139 d += 1 * data_stride;
1140 n_left -= 1;
1141 }
1142 }
1143}
1144
1145#ifdef CLIB_UNIX
1146
1147#include <unistd.h>
1148#include <fcntl.h>
1149
Dave Barachc3799992016-08-15 11:12:27 -04001150static void
Dave Barach59b25652017-09-10 15:04:27 -04001151clib_file_write (serialize_main_header_t * m, serialize_stream_t * s)
Ed Warnickecb9cada2015-12-08 15:45:58 -07001152{
1153 int fd, n;
1154
1155 fd = s->data_function_opaque;
1156 n = write (fd, s->buffer, s->current_buffer_index);
1157 if (n < 0)
1158 {
Dave Barachc3799992016-08-15 11:12:27 -04001159 if (!unix_error_is_fatal (errno))
Ed Warnickecb9cada2015-12-08 15:45:58 -07001160 n = 0;
1161 else
1162 serialize_error (m, clib_error_return_unix (0, "write"));
1163 }
1164 if (n == s->current_buffer_index)
1165 _vec_len (s->buffer) = 0;
1166 else
1167 vec_delete (s->buffer, n, 0);
1168 s->current_buffer_index = vec_len (s->buffer);
1169}
1170
Dave Barachc3799992016-08-15 11:12:27 -04001171static void
Dave Barach59b25652017-09-10 15:04:27 -04001172clib_file_read (serialize_main_header_t * m, serialize_stream_t * s)
Ed Warnickecb9cada2015-12-08 15:45:58 -07001173{
1174 int fd, n;
1175
1176 fd = s->data_function_opaque;
1177 n = read (fd, s->buffer, vec_len (s->buffer));
1178 if (n < 0)
1179 {
Dave Barachc3799992016-08-15 11:12:27 -04001180 if (!unix_error_is_fatal (errno))
Ed Warnickecb9cada2015-12-08 15:45:58 -07001181 n = 0;
1182 else
1183 serialize_error (m, clib_error_return_unix (0, "read"));
1184 }
1185 else if (n == 0)
1186 serialize_stream_set_end_of_stream (s);
1187 s->current_buffer_index = 0;
1188 s->n_buffer_bytes = n;
1189}
1190
1191static void
Dave Barach59b25652017-09-10 15:04:27 -04001192serialize_open_clib_file_descriptor_helper (serialize_main_t * m, int fd,
Dave Barachc3799992016-08-15 11:12:27 -04001193 uword is_read)
Ed Warnickecb9cada2015-12-08 15:45:58 -07001194{
Dave Barachb7b92992018-10-17 10:38:51 -04001195 clib_memset (m, 0, sizeof (m[0]));
Ed Warnickecb9cada2015-12-08 15:45:58 -07001196 vec_resize (m->stream.buffer, 4096);
Dave Barachc3799992016-08-15 11:12:27 -04001197
1198 if (!is_read)
Ed Warnickecb9cada2015-12-08 15:45:58 -07001199 {
1200 m->stream.n_buffer_bytes = vec_len (m->stream.buffer);
1201 _vec_len (m->stream.buffer) = 0;
1202 }
1203
Dave Barach59b25652017-09-10 15:04:27 -04001204 m->header.data_function = is_read ? clib_file_read : clib_file_write;
Ed Warnickecb9cada2015-12-08 15:45:58 -07001205 m->stream.data_function_opaque = fd;
1206}
1207
Damjan Mariondae1c7e2020-10-17 13:32:25 +02001208__clib_export void
Dave Barach59b25652017-09-10 15:04:27 -04001209serialize_open_clib_file_descriptor (serialize_main_t * m, int fd)
Dave Barachc3799992016-08-15 11:12:27 -04001210{
Dave Barach59b25652017-09-10 15:04:27 -04001211 serialize_open_clib_file_descriptor_helper (m, fd, /* is_read */ 0);
Dave Barachc3799992016-08-15 11:12:27 -04001212}
Ed Warnickecb9cada2015-12-08 15:45:58 -07001213
Damjan Mariondae1c7e2020-10-17 13:32:25 +02001214__clib_export void
Dave Barach59b25652017-09-10 15:04:27 -04001215unserialize_open_clib_file_descriptor (serialize_main_t * m, int fd)
Dave Barachc3799992016-08-15 11:12:27 -04001216{
Dave Barach59b25652017-09-10 15:04:27 -04001217 serialize_open_clib_file_descriptor_helper (m, fd, /* is_read */ 1);
Dave Barachc3799992016-08-15 11:12:27 -04001218}
Ed Warnickecb9cada2015-12-08 15:45:58 -07001219
1220static clib_error_t *
Dave Barach59b25652017-09-10 15:04:27 -04001221serialize_open_clib_file_helper (serialize_main_t * m, char *file,
Dave Barachc3799992016-08-15 11:12:27 -04001222 uword is_read)
Ed Warnickecb9cada2015-12-08 15:45:58 -07001223{
1224 int fd, mode;
1225
1226 mode = is_read ? O_RDONLY : O_RDWR | O_CREAT | O_TRUNC;
1227 fd = open (file, mode, 0666);
1228 if (fd < 0)
1229 return clib_error_return_unix (0, "open `%s'", file);
1230
Dave Barach59b25652017-09-10 15:04:27 -04001231 serialize_open_clib_file_descriptor_helper (m, fd, is_read);
Ed Warnickecb9cada2015-12-08 15:45:58 -07001232 return 0;
1233}
1234
Damjan Mariondae1c7e2020-10-17 13:32:25 +02001235__clib_export clib_error_t *
Dave Barach59b25652017-09-10 15:04:27 -04001236serialize_open_clib_file (serialize_main_t * m, char *file)
Dave Barachc3799992016-08-15 11:12:27 -04001237{
Dave Barach59b25652017-09-10 15:04:27 -04001238 return serialize_open_clib_file_helper (m, file, /* is_read */ 0);
Dave Barachc3799992016-08-15 11:12:27 -04001239}
Ed Warnickecb9cada2015-12-08 15:45:58 -07001240
Damjan Mariondae1c7e2020-10-17 13:32:25 +02001241__clib_export clib_error_t *
Dave Barach59b25652017-09-10 15:04:27 -04001242unserialize_open_clib_file (serialize_main_t * m, char *file)
Dave Barachc3799992016-08-15 11:12:27 -04001243{
Dave Barach59b25652017-09-10 15:04:27 -04001244 return serialize_open_clib_file_helper (m, file, /* is_read */ 1);
Dave Barachc3799992016-08-15 11:12:27 -04001245}
Ed Warnickecb9cada2015-12-08 15:45:58 -07001246
1247#endif /* CLIB_UNIX */
Dave Barachc3799992016-08-15 11:12:27 -04001248
1249/*
1250 * fd.io coding-style-patch-verification: ON
1251 *
1252 * Local Variables:
1253 * eval: (c-set-style "gnu")
1254 * End:
1255 */