blob: 95eca96758a87394d979ba9c92e761dcd8a60aeb [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 Marion299571a2022-03-19 00:07:52 +0100316 p = v = _vec_realloc ((void *) 0, l, elt_bytes, header_bytes,
317 /* align */ align, 0);
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 Marion299571a2022-03-19 00:07:52 +0100447 v = _vec_realloc ((void *) 0, l, elt_bytes, sizeof (p[0]), align, 0);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700448 p = pool_header (v);
449
450 vec_unserialize (m, &p->free_indices, unserialize_vec_32);
451
452 /* Construct free bitmap. */
453 p->free_bitmap = 0;
454 for (i = 0; i < vec_len (p->free_indices); i++)
455 p->free_bitmap = clib_bitmap_ori (p->free_bitmap, p->free_indices[i]);
456
457 pool_foreach_region (lo, hi, v,
Dave Barachc3799992016-08-15 11:12:27 -0400458 unserialize (m, f, v + lo * elt_bytes, hi - lo));
Ed Warnickecb9cada2015-12-08 15:45:58 -0700459
460 return v;
461}
462
Dave Barachc3799992016-08-15 11:12:27 -0400463void
464unserialize_pool (serialize_main_t * m, va_list * va)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700465{
Dave Barachc3799992016-08-15 11:12:27 -0400466 void **result = va_arg (*va, void **);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700467 u32 elt_bytes = va_arg (*va, u32);
Dave Barachc3799992016-08-15 11:12:27 -0400468 serialize_function_t *f = va_arg (*va, serialize_function_t *);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700469 *result = unserialize_pool_helper (m, elt_bytes, /* align */ 0, f);
470}
471
Dave Barachc3799992016-08-15 11:12:27 -0400472void
473unserialize_aligned_pool (serialize_main_t * m, va_list * va)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700474{
Dave Barachc3799992016-08-15 11:12:27 -0400475 void **result = va_arg (*va, void **);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700476 u32 elt_bytes = va_arg (*va, u32);
477 u32 align = va_arg (*va, u32);
Dave Barachc3799992016-08-15 11:12:27 -0400478 serialize_function_t *f = va_arg (*va, serialize_function_t *);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700479 *result = unserialize_pool_helper (m, elt_bytes, align, f);
480}
481
Dave Barachc3799992016-08-15 11:12:27 -0400482static void
483serialize_vec_heap_elt (serialize_main_t * m, va_list * va)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700484{
Dave Barachc3799992016-08-15 11:12:27 -0400485 heap_elt_t *e = va_arg (*va, heap_elt_t *);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700486 u32 i, n = va_arg (*va, u32);
487 for (i = 0; i < n; i++)
488 {
489 serialize_integer (m, e[i].offset, sizeof (e[i].offset));
490 serialize_integer (m, e[i].next, sizeof (e[i].next));
491 serialize_integer (m, e[i].prev, sizeof (e[i].prev));
492 }
493}
494
Dave Barachc3799992016-08-15 11:12:27 -0400495static void
496unserialize_vec_heap_elt (serialize_main_t * m, va_list * va)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700497{
Dave Barachc3799992016-08-15 11:12:27 -0400498 heap_elt_t *e = va_arg (*va, heap_elt_t *);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700499 u32 i, n = va_arg (*va, u32);
500 for (i = 0; i < n; i++)
501 {
502 unserialize_integer (m, &e[i].offset, sizeof (e[i].offset));
503 unserialize_integer (m, &e[i].next, sizeof (e[i].next));
504 unserialize_integer (m, &e[i].prev, sizeof (e[i].prev));
505 }
506}
507
Dave Barachc3799992016-08-15 11:12:27 -0400508void
509serialize_heap (serialize_main_t * m, va_list * va)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700510{
Dave Barachc3799992016-08-15 11:12:27 -0400511 void *heap = va_arg (*va, void *);
512 serialize_function_t *f = va_arg (*va, serialize_function_t *);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700513 u32 i, l;
Dave Barachc3799992016-08-15 11:12:27 -0400514 heap_header_t *h;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700515
516 l = vec_len (heap);
517 serialize_integer (m, l, sizeof (u32));
518 if (l == 0)
519 return;
520
521 h = heap_header (heap);
522
523#define foreach_serialize_heap_header_integer \
524 _ (head) _ (tail) _ (used_count) _ (max_len) _ (flags) _ (elt_bytes)
525
526#define _(f) serialize_integer (m, h->f, sizeof (h->f));
527 foreach_serialize_heap_header_integer;
528#undef _
529
530 serialize_integer (m, vec_len (h->free_lists), sizeof (u32));
531 for (i = 0; i < vec_len (h->free_lists); i++)
532 vec_serialize (m, h->free_lists[i], serialize_vec_32);
533
534 vec_serialize (m, h->elts, serialize_vec_heap_elt);
535 vec_serialize (m, h->small_free_elt_free_index, serialize_vec_32);
536 vec_serialize (m, h->free_elts, serialize_vec_32);
537
538 /* Serialize data in heap. */
539 {
Dave Barachc3799992016-08-15 11:12:27 -0400540 heap_elt_t *e, *end;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700541 e = h->elts + h->head;
542 end = h->elts + h->tail;
543 while (1)
544 {
Dave Barachc3799992016-08-15 11:12:27 -0400545 if (!heap_is_free (e))
Ed Warnickecb9cada2015-12-08 15:45:58 -0700546 {
Dave Barachc3799992016-08-15 11:12:27 -0400547 void *v = heap + heap_offset (e) * h->elt_bytes;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700548 u32 n = heap_elt_size (heap, e);
549 serialize (m, f, v, n);
550 }
551 if (e == end)
552 break;
553 e = heap_next (e);
554 }
555 }
556}
557
Dave Barachc3799992016-08-15 11:12:27 -0400558void
559unserialize_heap (serialize_main_t * m, va_list * va)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700560{
Dave Barachc3799992016-08-15 11:12:27 -0400561 void **result = va_arg (*va, void **);
562 serialize_function_t *f = va_arg (*va, serialize_function_t *);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700563 u32 i, vl, fl;
564 heap_header_t h;
Dave Barachc3799992016-08-15 11:12:27 -0400565 void *heap;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700566
567 unserialize_integer (m, &vl, sizeof (u32));
568 if (vl == 0)
569 {
570 *result = 0;
571 return;
572 }
573
Dave Barachb7b92992018-10-17 10:38:51 -0400574 clib_memset (&h, 0, sizeof (h));
Ed Warnickecb9cada2015-12-08 15:45:58 -0700575#define _(f) unserialize_integer (m, &h.f, sizeof (h.f));
576 foreach_serialize_heap_header_integer;
577#undef _
578
579 unserialize_integer (m, &fl, sizeof (u32));
580 vec_resize (h.free_lists, fl);
581
582 for (i = 0; i < vec_len (h.free_lists); i++)
583 vec_unserialize (m, &h.free_lists[i], unserialize_vec_32);
584
585 vec_unserialize (m, &h.elts, unserialize_vec_heap_elt);
586 vec_unserialize (m, &h.small_free_elt_free_index, unserialize_vec_32);
587 vec_unserialize (m, &h.free_elts, unserialize_vec_32);
588
589 /* Re-construct used elt bitmap. */
590 if (CLIB_DEBUG > 0)
591 {
Dave Barachc3799992016-08-15 11:12:27 -0400592 heap_elt_t *e;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700593 vec_foreach (e, h.elts)
Dave Barachc3799992016-08-15 11:12:27 -0400594 {
595 if (!heap_is_free (e))
596 h.used_elt_bitmap = clib_bitmap_ori (h.used_elt_bitmap, e - h.elts);
597 }
Ed Warnickecb9cada2015-12-08 15:45:58 -0700598 }
599
600 heap = *result = _heap_new (vl, h.elt_bytes);
601 heap_header (heap)[0] = h;
602
603 /* Unserialize data in heap. */
604 {
Dave Barachc3799992016-08-15 11:12:27 -0400605 heap_elt_t *e, *end;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700606 e = h.elts + h.head;
607 end = h.elts + h.tail;
608 while (1)
609 {
Dave Barachc3799992016-08-15 11:12:27 -0400610 if (!heap_is_free (e))
Ed Warnickecb9cada2015-12-08 15:45:58 -0700611 {
Dave Barachc3799992016-08-15 11:12:27 -0400612 void *v = heap + heap_offset (e) * h.elt_bytes;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700613 u32 n = heap_elt_size (heap, e);
614 unserialize (m, f, v, n);
615 }
616 if (e == end)
617 break;
618 e = heap_next (e);
619 }
620 }
621}
622
Dave Barachc3799992016-08-15 11:12:27 -0400623void
624serialize_magic (serialize_main_t * m, void *magic, u32 magic_bytes)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700625{
Dave Barachc3799992016-08-15 11:12:27 -0400626 void *p;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700627 serialize_integer (m, magic_bytes, sizeof (magic_bytes));
628 p = serialize_get (m, magic_bytes);
Dave Barach178cf492018-11-13 16:34:13 -0500629 clib_memcpy_fast (p, magic, magic_bytes);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700630}
631
Dave Barachc3799992016-08-15 11:12:27 -0400632void
633unserialize_check_magic (serialize_main_t * m, void *magic, u32 magic_bytes)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700634{
635 u32 l;
Dave Barachc3799992016-08-15 11:12:27 -0400636 void *d;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700637
638 unserialize_integer (m, &l, sizeof (l));
639 if (l != magic_bytes)
640 {
641 bad:
642 serialize_error_return (m, "bad magic number");
643 }
644 d = serialize_get (m, magic_bytes);
645 if (memcmp (magic, d, magic_bytes))
646 goto bad;
647}
648
Damjan Mariondae1c7e2020-10-17 13:32:25 +0200649__clib_export clib_error_t *
Ed Warnickecb9cada2015-12-08 15:45:58 -0700650va_serialize (serialize_main_t * sm, va_list * va)
651{
Dave Barachc3799992016-08-15 11:12:27 -0400652 serialize_main_header_t *m = &sm->header;
653 serialize_function_t *f = va_arg (*va, serialize_function_t *);
654 clib_error_t *error = 0;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700655
656 m->recursion_level += 1;
657 if (m->recursion_level == 1)
658 {
659 uword r = clib_setjmp (&m->error_longjmp, 0);
660 error = uword_to_pointer (r, clib_error_t *);
661 }
Dave Barachc3799992016-08-15 11:12:27 -0400662
663 if (!error)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700664 f (sm, va);
665
666 m->recursion_level -= 1;
667 return error;
668}
669
Damjan Mariondae1c7e2020-10-17 13:32:25 +0200670__clib_export clib_error_t *
Ed Warnickecb9cada2015-12-08 15:45:58 -0700671serialize (serialize_main_t * m, ...)
672{
Dave Barachc3799992016-08-15 11:12:27 -0400673 clib_error_t *error;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700674 va_list va;
675
676 va_start (va, m);
677 error = va_serialize (m, &va);
678 va_end (va);
679 return error;
680}
681
Damjan Mariondae1c7e2020-10-17 13:32:25 +0200682__clib_export clib_error_t *
Ed Warnickecb9cada2015-12-08 15:45:58 -0700683unserialize (serialize_main_t * m, ...)
684{
Dave Barachc3799992016-08-15 11:12:27 -0400685 clib_error_t *error;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700686 va_list va;
687
688 va_start (va, m);
689 error = va_serialize (m, &va);
690 va_end (va);
691 return error;
692}
693
Dave Barachc3799992016-08-15 11:12:27 -0400694static void *
695serialize_write_not_inline (serialize_main_header_t * m,
696 serialize_stream_t * s,
697 uword n_bytes_to_write, uword flags)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700698{
699 uword cur_bi, n_left_b, n_left_o;
700
701 ASSERT (s->current_buffer_index <= s->n_buffer_bytes);
702 cur_bi = s->current_buffer_index;
703 n_left_b = s->n_buffer_bytes - cur_bi;
704 n_left_o = vec_len (s->overflow_buffer);
705
706 /* Prepend overflow buffer if present. */
Dave Barachc3799992016-08-15 11:12:27 -0400707 do
708 {
709 if (n_left_o > 0 && n_left_b > 0)
710 {
711 uword n = clib_min (n_left_b, n_left_o);
Dave Barach178cf492018-11-13 16:34:13 -0500712 clib_memcpy_fast (s->buffer + cur_bi, s->overflow_buffer, n);
Dave Barachc3799992016-08-15 11:12:27 -0400713 cur_bi += n;
714 n_left_b -= n;
715 n_left_o -= n;
716 if (n_left_o == 0)
717 _vec_len (s->overflow_buffer) = 0;
718 else
719 vec_delete (s->overflow_buffer, n, 0);
720 }
Ed Warnickecb9cada2015-12-08 15:45:58 -0700721
Dave Barachc3799992016-08-15 11:12:27 -0400722 /* Call data function when buffer is complete. Data function should
723 dispatch with current buffer and give us a new one to write more
724 data into. */
725 if (n_left_b == 0)
726 {
727 s->current_buffer_index = cur_bi;
728 m->data_function (m, s);
729 cur_bi = s->current_buffer_index;
730 n_left_b = s->n_buffer_bytes - cur_bi;
731 }
732 }
733 while (n_left_o > 0);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700734
735 if (n_left_o > 0 || n_left_b < n_bytes_to_write)
736 {
Dave Barachc3799992016-08-15 11:12:27 -0400737 u8 *r;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700738 vec_add2 (s->overflow_buffer, r, n_bytes_to_write);
739 return r;
740 }
741 else
742 {
743 s->current_buffer_index = cur_bi + n_bytes_to_write;
744 return s->buffer + cur_bi;
745 }
746}
747
Dave Barachc3799992016-08-15 11:12:27 -0400748static void *
749serialize_read_not_inline (serialize_main_header_t * m,
750 serialize_stream_t * s,
751 uword n_bytes_to_read, uword flags)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700752{
753 uword cur_bi, cur_oi, n_left_b, n_left_o, n_left_to_read;
754
755 ASSERT (s->current_buffer_index <= s->n_buffer_bytes);
756
757 cur_bi = s->current_buffer_index;
758 cur_oi = s->current_overflow_index;
759
760 n_left_b = s->n_buffer_bytes - cur_bi;
761 n_left_o = vec_len (s->overflow_buffer) - cur_oi;
762
763 /* Read from overflow? */
764 if (n_left_o >= n_bytes_to_read)
765 {
766 s->current_overflow_index = cur_oi + n_bytes_to_read;
767 return vec_elt_at_index (s->overflow_buffer, cur_oi);
768 }
769
770 /* Reset overflow buffer. */
771 if (n_left_o == 0 && s->overflow_buffer)
772 {
773 s->current_overflow_index = 0;
774 _vec_len (s->overflow_buffer) = 0;
775 }
776
777 n_left_to_read = n_bytes_to_read;
778 while (n_left_to_read > 0)
779 {
780 uword n;
781
782 /* If we don't have enough data between overflow and normal buffer
Dave Barachc3799992016-08-15 11:12:27 -0400783 call read function. */
Ed Warnickecb9cada2015-12-08 15:45:58 -0700784 if (n_left_o + n_left_b < n_bytes_to_read)
785 {
786 /* Save any left over buffer in overflow vector. */
787 if (n_left_b > 0)
788 {
789 vec_add (s->overflow_buffer, s->buffer + cur_bi, n_left_b);
790 n_left_o += n_left_b;
791 n_left_to_read -= n_left_b;
792 /* Advance buffer to end --- even if
Dave Barachc3799992016-08-15 11:12:27 -0400793 SERIALIZE_FLAG_NO_ADVANCE_CURRENT_BUFFER_INDEX is set. */
Ed Warnickecb9cada2015-12-08 15:45:58 -0700794 cur_bi = s->n_buffer_bytes;
795 n_left_b = 0;
796 }
797
798 if (m->data_function)
799 {
800 m->data_function (m, s);
801 cur_bi = s->current_buffer_index;
802 n_left_b = s->n_buffer_bytes - cur_bi;
803 }
804 }
805
806 /* For first time through loop return if we have enough data
Dave Barachc3799992016-08-15 11:12:27 -0400807 in normal buffer and overflow vector is empty. */
Ed Warnickecb9cada2015-12-08 15:45:58 -0700808 if (n_left_o == 0
Dave Barachc3799992016-08-15 11:12:27 -0400809 && n_left_to_read == n_bytes_to_read && n_left_b >= n_left_to_read)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700810 {
811 s->current_buffer_index = cur_bi + n_bytes_to_read;
812 return s->buffer + cur_bi;
813 }
814
Dave Barachc3799992016-08-15 11:12:27 -0400815 if (!m->data_function || serialize_stream_is_end_of_stream (s))
Ed Warnickecb9cada2015-12-08 15:45:58 -0700816 {
817 /* This can happen for a peek at end of file.
818 Pad overflow buffer with 0s. */
819 vec_resize (s->overflow_buffer, n_left_to_read);
820 n_left_o += n_left_to_read;
821 n_left_to_read = 0;
822 }
823 else
824 {
825 /* Copy from buffer to overflow vector. */
826 n = clib_min (n_left_to_read, n_left_b);
827 vec_add (s->overflow_buffer, s->buffer + cur_bi, n);
828 cur_bi += n;
829 n_left_b -= n;
830 n_left_o += n;
831 n_left_to_read -= n;
832 }
833 }
Dave Barachc3799992016-08-15 11:12:27 -0400834
Ed Warnickecb9cada2015-12-08 15:45:58 -0700835 s->current_buffer_index = cur_bi;
836 s->current_overflow_index = cur_oi + n_bytes_to_read;
837 return vec_elt_at_index (s->overflow_buffer, cur_oi);
838}
839
Damjan Mariondae1c7e2020-10-17 13:32:25 +0200840__clib_export void *
Dave Barachc3799992016-08-15 11:12:27 -0400841serialize_read_write_not_inline (serialize_main_header_t * m,
842 serialize_stream_t * s,
843 uword n_bytes, uword flags)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700844{
Dave Barachc3799992016-08-15 11:12:27 -0400845 return (((flags & SERIALIZE_FLAG_IS_READ) ? serialize_read_not_inline :
846 serialize_write_not_inline) (m, s, n_bytes, flags));
Ed Warnickecb9cada2015-12-08 15:45:58 -0700847}
848
Dave Barachc3799992016-08-15 11:12:27 -0400849static void
850serialize_read_write_close (serialize_main_header_t * m,
851 serialize_stream_t * s, uword flags)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700852{
853 if (serialize_stream_is_end_of_stream (s))
854 return;
855
856 if (flags & SERIALIZE_FLAG_IS_WRITE)
857 /* "Write" 0 bytes to flush overflow vector. */
858 serialize_write_not_inline (m, s, /* n bytes */ 0, flags);
859
860 serialize_stream_set_end_of_stream (s);
861
862 /* Call it one last time to flush buffer and close. */
863 m->data_function (m, s);
864
865 vec_free (s->overflow_buffer);
866}
867
Damjan Mariondae1c7e2020-10-17 13:32:25 +0200868__clib_export void
Dave Barachc3799992016-08-15 11:12:27 -0400869serialize_close (serialize_main_t * m)
870{
871 serialize_read_write_close (&m->header, &m->stream,
872 SERIALIZE_FLAG_IS_WRITE);
873}
Ed Warnickecb9cada2015-12-08 15:45:58 -0700874
Damjan Mariondae1c7e2020-10-17 13:32:25 +0200875__clib_export void
Dave Barachc3799992016-08-15 11:12:27 -0400876unserialize_close (serialize_main_t * m)
877{
878 serialize_read_write_close (&m->header, &m->stream, SERIALIZE_FLAG_IS_READ);
879}
Ed Warnickecb9cada2015-12-08 15:45:58 -0700880
Damjan Mariondae1c7e2020-10-17 13:32:25 +0200881__clib_export void
Dave Barachc3799992016-08-15 11:12:27 -0400882serialize_open_data (serialize_main_t * m, u8 * data, uword n_data_bytes)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700883{
Dave Barachb7b92992018-10-17 10:38:51 -0400884 clib_memset (m, 0, sizeof (m[0]));
Ed Warnickecb9cada2015-12-08 15:45:58 -0700885 m->stream.buffer = data;
886 m->stream.n_buffer_bytes = n_data_bytes;
887}
888
Damjan Mariondae1c7e2020-10-17 13:32:25 +0200889__clib_export void
Dave Barachc3799992016-08-15 11:12:27 -0400890unserialize_open_data (serialize_main_t * m, u8 * data, uword n_data_bytes)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700891{
Dave Barachc3799992016-08-15 11:12:27 -0400892 serialize_open_data (m, data, n_data_bytes);
893}
894
895static void
896serialize_vector_write (serialize_main_header_t * m, serialize_stream_t * s)
897{
898 if (!serialize_stream_is_end_of_stream (s))
Ed Warnickecb9cada2015-12-08 15:45:58 -0700899 {
900 /* Double buffer size. */
901 uword l = vec_len (s->buffer);
902 vec_resize (s->buffer, l > 0 ? l : 64);
903 s->n_buffer_bytes = vec_len (s->buffer);
904 }
905}
906
Damjan Mariondae1c7e2020-10-17 13:32:25 +0200907__clib_export void
Dave Barachc3799992016-08-15 11:12:27 -0400908serialize_open_vector (serialize_main_t * m, u8 * vector)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700909{
Dave Barachb7b92992018-10-17 10:38:51 -0400910 clib_memset (m, 0, sizeof (m[0]));
Ed Warnickecb9cada2015-12-08 15:45:58 -0700911 m->header.data_function = serialize_vector_write;
912 m->stream.buffer = vector;
913 m->stream.current_buffer_index = 0;
914 m->stream.n_buffer_bytes = vec_len (vector);
915}
Dave Barachc3799992016-08-15 11:12:27 -0400916
Damjan Mariondae1c7e2020-10-17 13:32:25 +0200917__clib_export void *
Dave Barachc3799992016-08-15 11:12:27 -0400918serialize_close_vector (serialize_main_t * m)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700919{
Dave Barachc3799992016-08-15 11:12:27 -0400920 serialize_stream_t *s = &m->stream;
921 void *result;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700922
923 serialize_close (m); /* frees overflow buffer */
924
925 if (s->buffer)
926 _vec_len (s->buffer) = s->current_buffer_index;
927 result = s->buffer;
Dave Barachb7b92992018-10-17 10:38:51 -0400928 clib_memset (m, 0, sizeof (m[0]));
Ed Warnickecb9cada2015-12-08 15:45:58 -0700929 return result;
930}
Dave Barachc3799992016-08-15 11:12:27 -0400931
Damjan Marion4a251d02021-05-06 17:28:12 +0200932__clib_export void
933serialize_multiple_1 (serialize_main_t *m, void *data, uword data_stride,
934 uword n_data)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700935{
Dave Barachc3799992016-08-15 11:12:27 -0400936 u8 *d = data;
937 u8 *p;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700938 uword n_left = n_data;
939
940 while (n_left >= 4)
941 {
942 p = serialize_get (m, 4 * sizeof (d[0]));
943 p[0] = d[0 * data_stride];
944 p[1] = d[1 * data_stride];
945 p[2] = d[2 * data_stride];
946 p[3] = d[3 * data_stride];
947 n_left -= 4;
948 d += 4 * data_stride;
949 }
950
951 if (n_left > 0)
952 {
953 p = serialize_get (m, n_left * sizeof (p[0]));
954 while (n_left > 0)
955 {
956 p[0] = d[0];
957 p += 1;
958 d += 1 * data_stride;
959 n_left -= 1;
960 }
961 }
962}
963
Damjan Marion4a251d02021-05-06 17:28:12 +0200964__clib_export void
965serialize_multiple_2 (serialize_main_t *m, void *data, uword data_stride,
966 uword n_data)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700967{
Dave Barachc3799992016-08-15 11:12:27 -0400968 void *d = data;
969 u16 *p;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700970 uword n_left = n_data;
971
972 while (n_left >= 4)
973 {
974 p = serialize_get (m, 4 * sizeof (p[0]));
Dave Barachc3799992016-08-15 11:12:27 -0400975 clib_mem_unaligned (p + 0, u16) =
976 clib_host_to_net_mem_u16 (d + 0 * data_stride);
977 clib_mem_unaligned (p + 1, u16) =
978 clib_host_to_net_mem_u16 (d + 1 * data_stride);
979 clib_mem_unaligned (p + 2, u16) =
980 clib_host_to_net_mem_u16 (d + 2 * data_stride);
981 clib_mem_unaligned (p + 3, u16) =
982 clib_host_to_net_mem_u16 (d + 3 * data_stride);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700983 n_left -= 4;
984 d += 4 * data_stride;
985 }
986
987 if (n_left > 0)
988 {
989 p = serialize_get (m, n_left * sizeof (p[0]));
990 while (n_left > 0)
991 {
Dave Barachc3799992016-08-15 11:12:27 -0400992 clib_mem_unaligned (p + 0, u16) =
993 clib_host_to_net_mem_u16 (d + 0 * data_stride);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700994 p += 1;
995 d += 1 * data_stride;
996 n_left -= 1;
997 }
998 }
999}
1000
Damjan Marion4a251d02021-05-06 17:28:12 +02001001__clib_export void
1002serialize_multiple_4 (serialize_main_t *m, void *data, uword data_stride,
1003 uword n_data)
Ed Warnickecb9cada2015-12-08 15:45:58 -07001004{
Dave Barachc3799992016-08-15 11:12:27 -04001005 void *d = data;
1006 u32 *p;
Ed Warnickecb9cada2015-12-08 15:45:58 -07001007 uword n_left = n_data;
1008
1009 while (n_left >= 4)
1010 {
1011 p = serialize_get (m, 4 * sizeof (p[0]));
Dave Barachc3799992016-08-15 11:12:27 -04001012 clib_mem_unaligned (p + 0, u32) =
1013 clib_host_to_net_mem_u32 (d + 0 * data_stride);
1014 clib_mem_unaligned (p + 1, u32) =
1015 clib_host_to_net_mem_u32 (d + 1 * data_stride);
1016 clib_mem_unaligned (p + 2, u32) =
1017 clib_host_to_net_mem_u32 (d + 2 * data_stride);
1018 clib_mem_unaligned (p + 3, u32) =
1019 clib_host_to_net_mem_u32 (d + 3 * data_stride);
Ed Warnickecb9cada2015-12-08 15:45:58 -07001020 n_left -= 4;
1021 d += 4 * data_stride;
1022 }
1023
1024 if (n_left > 0)
1025 {
1026 p = serialize_get (m, n_left * sizeof (p[0]));
1027 while (n_left > 0)
1028 {
Dave Barachc3799992016-08-15 11:12:27 -04001029 clib_mem_unaligned (p + 0, u32) =
1030 clib_host_to_net_mem_u32 (d + 0 * data_stride);
Ed Warnickecb9cada2015-12-08 15:45:58 -07001031 p += 1;
1032 d += 1 * data_stride;
1033 n_left -= 1;
1034 }
1035 }
1036}
1037
Damjan Marion4a251d02021-05-06 17:28:12 +02001038__clib_export void
1039unserialize_multiple_1 (serialize_main_t *m, void *data, uword data_stride,
1040 uword n_data)
Ed Warnickecb9cada2015-12-08 15:45:58 -07001041{
Dave Barachc3799992016-08-15 11:12:27 -04001042 u8 *d = data;
1043 u8 *p;
Ed Warnickecb9cada2015-12-08 15:45:58 -07001044 uword n_left = n_data;
1045
1046 while (n_left >= 4)
1047 {
1048 p = unserialize_get (m, 4 * sizeof (d[0]));
1049 d[0 * data_stride] = p[0];
1050 d[1 * data_stride] = p[1];
1051 d[2 * data_stride] = p[2];
1052 d[3 * data_stride] = p[3];
1053 n_left -= 4;
1054 d += 4 * data_stride;
1055 }
1056
1057 if (n_left > 0)
1058 {
1059 p = unserialize_get (m, n_left * sizeof (p[0]));
1060 while (n_left > 0)
1061 {
1062 d[0] = p[0];
1063 p += 1;
1064 d += 1 * data_stride;
1065 n_left -= 1;
1066 }
1067 }
1068}
1069
Damjan Marion4a251d02021-05-06 17:28:12 +02001070__clib_export void
1071unserialize_multiple_2 (serialize_main_t *m, void *data, uword data_stride,
1072 uword n_data)
Ed Warnickecb9cada2015-12-08 15:45:58 -07001073{
Dave Barachc3799992016-08-15 11:12:27 -04001074 void *d = data;
1075 u16 *p;
Ed Warnickecb9cada2015-12-08 15:45:58 -07001076 uword n_left = n_data;
1077
1078 while (n_left >= 4)
1079 {
1080 p = unserialize_get (m, 4 * sizeof (p[0]));
Dave Barachc3799992016-08-15 11:12:27 -04001081 clib_mem_unaligned (d + 0 * data_stride, u16) =
1082 clib_net_to_host_mem_u16 (p + 0);
1083 clib_mem_unaligned (d + 1 * data_stride, u16) =
1084 clib_net_to_host_mem_u16 (p + 1);
1085 clib_mem_unaligned (d + 2 * data_stride, u16) =
1086 clib_net_to_host_mem_u16 (p + 2);
1087 clib_mem_unaligned (d + 3 * data_stride, u16) =
1088 clib_net_to_host_mem_u16 (p + 3);
Ed Warnickecb9cada2015-12-08 15:45:58 -07001089 n_left -= 4;
1090 d += 4 * data_stride;
1091 }
1092
1093 if (n_left > 0)
1094 {
1095 p = unserialize_get (m, n_left * sizeof (p[0]));
1096 while (n_left > 0)
1097 {
Dave Barachc3799992016-08-15 11:12:27 -04001098 clib_mem_unaligned (d + 0 * data_stride, u16) =
1099 clib_net_to_host_mem_u16 (p + 0);
Ed Warnickecb9cada2015-12-08 15:45:58 -07001100 p += 1;
1101 d += 1 * data_stride;
1102 n_left -= 1;
1103 }
1104 }
1105}
1106
Damjan Marion4a251d02021-05-06 17:28:12 +02001107__clib_export void
1108unserialize_multiple_4 (serialize_main_t *m, void *data, uword data_stride,
1109 uword n_data)
Ed Warnickecb9cada2015-12-08 15:45:58 -07001110{
Dave Barachc3799992016-08-15 11:12:27 -04001111 void *d = data;
1112 u32 *p;
Ed Warnickecb9cada2015-12-08 15:45:58 -07001113 uword n_left = n_data;
1114
1115 while (n_left >= 4)
1116 {
1117 p = unserialize_get (m, 4 * sizeof (p[0]));
Dave Barachc3799992016-08-15 11:12:27 -04001118 clib_mem_unaligned (d + 0 * data_stride, u32) =
1119 clib_net_to_host_mem_u32 (p + 0);
1120 clib_mem_unaligned (d + 1 * data_stride, u32) =
1121 clib_net_to_host_mem_u32 (p + 1);
1122 clib_mem_unaligned (d + 2 * data_stride, u32) =
1123 clib_net_to_host_mem_u32 (p + 2);
1124 clib_mem_unaligned (d + 3 * data_stride, u32) =
1125 clib_net_to_host_mem_u32 (p + 3);
Ed Warnickecb9cada2015-12-08 15:45:58 -07001126 n_left -= 4;
1127 d += 4 * data_stride;
1128 }
1129
1130 if (n_left > 0)
1131 {
1132 p = unserialize_get (m, n_left * sizeof (p[0]));
1133 while (n_left > 0)
1134 {
Dave Barachc3799992016-08-15 11:12:27 -04001135 clib_mem_unaligned (d + 0 * data_stride, u32) =
1136 clib_net_to_host_mem_u32 (p + 0);
Ed Warnickecb9cada2015-12-08 15:45:58 -07001137 p += 1;
1138 d += 1 * data_stride;
1139 n_left -= 1;
1140 }
1141 }
1142}
1143
1144#ifdef CLIB_UNIX
1145
1146#include <unistd.h>
1147#include <fcntl.h>
1148
Dave Barachc3799992016-08-15 11:12:27 -04001149static void
Dave Barach59b25652017-09-10 15:04:27 -04001150clib_file_write (serialize_main_header_t * m, serialize_stream_t * s)
Ed Warnickecb9cada2015-12-08 15:45:58 -07001151{
1152 int fd, n;
1153
1154 fd = s->data_function_opaque;
1155 n = write (fd, s->buffer, s->current_buffer_index);
1156 if (n < 0)
1157 {
Dave Barachc3799992016-08-15 11:12:27 -04001158 if (!unix_error_is_fatal (errno))
Ed Warnickecb9cada2015-12-08 15:45:58 -07001159 n = 0;
1160 else
1161 serialize_error (m, clib_error_return_unix (0, "write"));
1162 }
1163 if (n == s->current_buffer_index)
1164 _vec_len (s->buffer) = 0;
1165 else
1166 vec_delete (s->buffer, n, 0);
1167 s->current_buffer_index = vec_len (s->buffer);
1168}
1169
Dave Barachc3799992016-08-15 11:12:27 -04001170static void
Dave Barach59b25652017-09-10 15:04:27 -04001171clib_file_read (serialize_main_header_t * m, serialize_stream_t * s)
Ed Warnickecb9cada2015-12-08 15:45:58 -07001172{
1173 int fd, n;
1174
1175 fd = s->data_function_opaque;
1176 n = read (fd, s->buffer, vec_len (s->buffer));
1177 if (n < 0)
1178 {
Dave Barachc3799992016-08-15 11:12:27 -04001179 if (!unix_error_is_fatal (errno))
Ed Warnickecb9cada2015-12-08 15:45:58 -07001180 n = 0;
1181 else
1182 serialize_error (m, clib_error_return_unix (0, "read"));
1183 }
1184 else if (n == 0)
1185 serialize_stream_set_end_of_stream (s);
1186 s->current_buffer_index = 0;
1187 s->n_buffer_bytes = n;
1188}
1189
1190static void
Dave Barach59b25652017-09-10 15:04:27 -04001191serialize_open_clib_file_descriptor_helper (serialize_main_t * m, int fd,
Dave Barachc3799992016-08-15 11:12:27 -04001192 uword is_read)
Ed Warnickecb9cada2015-12-08 15:45:58 -07001193{
Dave Barachb7b92992018-10-17 10:38:51 -04001194 clib_memset (m, 0, sizeof (m[0]));
Ed Warnickecb9cada2015-12-08 15:45:58 -07001195 vec_resize (m->stream.buffer, 4096);
Dave Barachc3799992016-08-15 11:12:27 -04001196
1197 if (!is_read)
Ed Warnickecb9cada2015-12-08 15:45:58 -07001198 {
1199 m->stream.n_buffer_bytes = vec_len (m->stream.buffer);
1200 _vec_len (m->stream.buffer) = 0;
1201 }
1202
Dave Barach59b25652017-09-10 15:04:27 -04001203 m->header.data_function = is_read ? clib_file_read : clib_file_write;
Ed Warnickecb9cada2015-12-08 15:45:58 -07001204 m->stream.data_function_opaque = fd;
1205}
1206
Damjan Mariondae1c7e2020-10-17 13:32:25 +02001207__clib_export void
Dave Barach59b25652017-09-10 15:04:27 -04001208serialize_open_clib_file_descriptor (serialize_main_t * m, int fd)
Dave Barachc3799992016-08-15 11:12:27 -04001209{
Dave Barach59b25652017-09-10 15:04:27 -04001210 serialize_open_clib_file_descriptor_helper (m, fd, /* is_read */ 0);
Dave Barachc3799992016-08-15 11:12:27 -04001211}
Ed Warnickecb9cada2015-12-08 15:45:58 -07001212
Damjan Mariondae1c7e2020-10-17 13:32:25 +02001213__clib_export void
Dave Barach59b25652017-09-10 15:04:27 -04001214unserialize_open_clib_file_descriptor (serialize_main_t * m, int fd)
Dave Barachc3799992016-08-15 11:12:27 -04001215{
Dave Barach59b25652017-09-10 15:04:27 -04001216 serialize_open_clib_file_descriptor_helper (m, fd, /* is_read */ 1);
Dave Barachc3799992016-08-15 11:12:27 -04001217}
Ed Warnickecb9cada2015-12-08 15:45:58 -07001218
1219static clib_error_t *
Dave Barach59b25652017-09-10 15:04:27 -04001220serialize_open_clib_file_helper (serialize_main_t * m, char *file,
Dave Barachc3799992016-08-15 11:12:27 -04001221 uword is_read)
Ed Warnickecb9cada2015-12-08 15:45:58 -07001222{
1223 int fd, mode;
1224
1225 mode = is_read ? O_RDONLY : O_RDWR | O_CREAT | O_TRUNC;
1226 fd = open (file, mode, 0666);
1227 if (fd < 0)
1228 return clib_error_return_unix (0, "open `%s'", file);
1229
Dave Barach59b25652017-09-10 15:04:27 -04001230 serialize_open_clib_file_descriptor_helper (m, fd, is_read);
Ed Warnickecb9cada2015-12-08 15:45:58 -07001231 return 0;
1232}
1233
Damjan Mariondae1c7e2020-10-17 13:32:25 +02001234__clib_export clib_error_t *
Dave Barach59b25652017-09-10 15:04:27 -04001235serialize_open_clib_file (serialize_main_t * m, char *file)
Dave Barachc3799992016-08-15 11:12:27 -04001236{
Dave Barach59b25652017-09-10 15:04:27 -04001237 return serialize_open_clib_file_helper (m, file, /* is_read */ 0);
Dave Barachc3799992016-08-15 11:12:27 -04001238}
Ed Warnickecb9cada2015-12-08 15:45:58 -07001239
Damjan Mariondae1c7e2020-10-17 13:32:25 +02001240__clib_export clib_error_t *
Dave Barach59b25652017-09-10 15:04:27 -04001241unserialize_open_clib_file (serialize_main_t * m, char *file)
Dave Barachc3799992016-08-15 11:12:27 -04001242{
Dave Barach59b25652017-09-10 15:04:27 -04001243 return serialize_open_clib_file_helper (m, file, /* is_read */ 1);
Dave Barachc3799992016-08-15 11:12:27 -04001244}
Ed Warnickecb9cada2015-12-08 15:45:58 -07001245
1246#endif /* CLIB_UNIX */
Dave Barachc3799992016-08-15 11:12:27 -04001247
1248/*
1249 * fd.io coding-style-patch-verification: ON
1250 *
1251 * Local Variables:
1252 * eval: (c-set-style "gnu")
1253 * End:
1254 */