blob: 1aaac0b2a11648e15338b808ef40016bb687755c [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 * buffer_funcs.h: VLIB buffer related functions/inlines
17 *
18 * Copyright (c) 2008 Eliot Dresselhaus
19 *
20 * Permission is hereby granted, free of charge, to any person obtaining
21 * a copy of this software and associated documentation files (the
22 * "Software"), to deal in the Software without restriction, including
23 * without limitation the rights to use, copy, modify, merge, publish,
24 * distribute, sublicense, and/or sell copies of the Software, and to
25 * permit persons to whom the Software is furnished to do so, subject to
26 * the following conditions:
27 *
28 * The above copyright notice and this permission notice shall be
29 * included in all copies or substantial portions of the Software.
30 *
31 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
32 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
33 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
34 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
35 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
36 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
37 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
38 */
39
40#ifndef included_vlib_buffer_funcs_h
41#define included_vlib_buffer_funcs_h
42
43#include <vppinfra/hash.h>
44
45/** \file
46 vlib buffer access methods.
47*/
48
49
50/** \brief Translate buffer index into buffer pointer
51
52 @param vm - (vlib_main_t *) vlib main data structure pointer
53 @param buffer_index - (u32) buffer index
54 @return - (vlib_buffer_t *) buffer pointer
Dave Barach9b8ffd92016-07-08 08:13:45 -040055*/
Ed Warnickecb9cada2015-12-08 15:45:58 -070056always_inline vlib_buffer_t *
57vlib_get_buffer (vlib_main_t * vm, u32 buffer_index)
58{
Damjan Marion04a7f052017-07-10 15:06:17 +020059 vlib_buffer_main_t *bm = vm->buffer_main;
60 uword offset = ((uword) buffer_index) << CLIB_LOG2_CACHE_LINE_BYTES;
61 ASSERT (offset < bm->buffer_mem_size);
62
63 return uword_to_pointer (bm->buffer_mem_start + offset, void *);
Ed Warnickecb9cada2015-12-08 15:45:58 -070064}
65
66/** \brief Translate buffer pointer into buffer index
67
68 @param vm - (vlib_main_t *) vlib main data structure pointer
Chris Luked4024f52016-09-06 09:32:36 -040069 @param p - (void *) buffer pointer
Ed Warnickecb9cada2015-12-08 15:45:58 -070070 @return - (u32) buffer index
Dave Barach9b8ffd92016-07-08 08:13:45 -040071*/
Damjan Marion04a7f052017-07-10 15:06:17 +020072
Ed Warnickecb9cada2015-12-08 15:45:58 -070073always_inline u32
Dave Barach9b8ffd92016-07-08 08:13:45 -040074vlib_get_buffer_index (vlib_main_t * vm, void *p)
Ed Warnickecb9cada2015-12-08 15:45:58 -070075{
Damjan Marion04a7f052017-07-10 15:06:17 +020076 vlib_buffer_main_t *bm = vm->buffer_main;
77 uword offset = pointer_to_uword (p) - bm->buffer_mem_start;
78 ASSERT (pointer_to_uword (p) >= bm->buffer_mem_start);
79 ASSERT (offset < bm->buffer_mem_size);
Dave Barach9b8ffd92016-07-08 08:13:45 -040080 ASSERT ((offset % (1 << CLIB_LOG2_CACHE_LINE_BYTES)) == 0);
Ed Warnickecb9cada2015-12-08 15:45:58 -070081 return offset >> CLIB_LOG2_CACHE_LINE_BYTES;
82}
83
84/** \brief Get next buffer in buffer linklist, or zero for end of list.
85
86 @param vm - (vlib_main_t *) vlib main data structure pointer
87 @param b - (void *) buffer pointer
88 @return - (vlib_buffer_t *) next buffer, or NULL
Dave Barach9b8ffd92016-07-08 08:13:45 -040089*/
Ed Warnickecb9cada2015-12-08 15:45:58 -070090always_inline vlib_buffer_t *
91vlib_get_next_buffer (vlib_main_t * vm, vlib_buffer_t * b)
92{
93 return (b->flags & VLIB_BUFFER_NEXT_PRESENT
Dave Barach9b8ffd92016-07-08 08:13:45 -040094 ? vlib_get_buffer (vm, b->next_buffer) : 0);
Ed Warnickecb9cada2015-12-08 15:45:58 -070095}
96
Dave Barach9b8ffd92016-07-08 08:13:45 -040097uword vlib_buffer_length_in_chain_slow_path (vlib_main_t * vm,
98 vlib_buffer_t * b_first);
Ed Warnickecb9cada2015-12-08 15:45:58 -070099
100/** \brief Get length in bytes of the buffer chain
101
102 @param vm - (vlib_main_t *) vlib main data structure pointer
103 @param b - (void *) buffer pointer
104 @return - (uword) length of buffer chain
Dave Barach9b8ffd92016-07-08 08:13:45 -0400105*/
Ed Warnickecb9cada2015-12-08 15:45:58 -0700106always_inline uword
107vlib_buffer_length_in_chain (vlib_main_t * vm, vlib_buffer_t * b)
108{
Damjan Marion072401e2017-07-13 18:53:27 +0200109 uword len = b->current_length;
110
111 if (PREDICT_TRUE ((b->flags & VLIB_BUFFER_NEXT_PRESENT) == 0))
112 return len;
113
114 if (PREDICT_TRUE (b->flags & VLIB_BUFFER_TOTAL_LENGTH_VALID))
115 return len + b->total_length_not_including_first_buffer;
116
117 return vlib_buffer_length_in_chain_slow_path (vm, b);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700118}
119
120/** \brief Get length in bytes of the buffer index buffer chain
121
122 @param vm - (vlib_main_t *) vlib main data structure pointer
123 @param bi - (u32) buffer index
124 @return - (uword) length of buffer chain
Dave Barach9b8ffd92016-07-08 08:13:45 -0400125*/
Ed Warnickecb9cada2015-12-08 15:45:58 -0700126always_inline uword
127vlib_buffer_index_length_in_chain (vlib_main_t * vm, u32 bi)
128{
Dave Barach9b8ffd92016-07-08 08:13:45 -0400129 vlib_buffer_t *b = vlib_get_buffer (vm, bi);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700130 return vlib_buffer_length_in_chain (vm, b);
131}
132
133/** \brief Copy buffer contents to memory
134
135 @param vm - (vlib_main_t *) vlib main data structure pointer
Chris Luked4024f52016-09-06 09:32:36 -0400136 @param buffer_index - (u32) buffer index
Ed Warnickecb9cada2015-12-08 15:45:58 -0700137 @param contents - (u8 *) memory, <strong>must be large enough</strong>
138 @return - (uword) length of buffer chain
Dave Barach9b8ffd92016-07-08 08:13:45 -0400139*/
Ed Warnickecb9cada2015-12-08 15:45:58 -0700140always_inline uword
141vlib_buffer_contents (vlib_main_t * vm, u32 buffer_index, u8 * contents)
142{
143 uword content_len = 0;
144 uword l;
Dave Barach9b8ffd92016-07-08 08:13:45 -0400145 vlib_buffer_t *b;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700146
147 while (1)
148 {
149 b = vlib_get_buffer (vm, buffer_index);
150 l = b->current_length;
Damjan Marionf1213b82016-03-13 02:22:06 +0100151 clib_memcpy (contents + content_len, b->data + b->current_data, l);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700152 content_len += l;
Dave Barach9b8ffd92016-07-08 08:13:45 -0400153 if (!(b->flags & VLIB_BUFFER_NEXT_PRESENT))
Ed Warnickecb9cada2015-12-08 15:45:58 -0700154 break;
155 buffer_index = b->next_buffer;
156 }
157
158 return content_len;
159}
160
161/* Return physical address of buffer->data start. */
162always_inline u64
163vlib_get_buffer_data_physical_address (vlib_main_t * vm, u32 buffer_index)
164{
165 return vlib_physmem_offset_to_physical (&vm->physmem_main,
Dave Barach9b8ffd92016-07-08 08:13:45 -0400166 (((uword) buffer_index) <<
Ed Warnickecb9cada2015-12-08 15:45:58 -0700167 CLIB_LOG2_CACHE_LINE_BYTES) +
Dave Barach9b8ffd92016-07-08 08:13:45 -0400168 STRUCT_OFFSET_OF (vlib_buffer_t,
169 data));
Ed Warnickecb9cada2015-12-08 15:45:58 -0700170}
171
172/** \brief Prefetch buffer metadata by buffer index
173 The first 64 bytes of buffer contains most header information
174
175 @param vm - (vlib_main_t *) vlib main data structure pointer
176 @param bi - (u32) buffer index
177 @param type - LOAD, STORE. In most cases, STORE is the right answer
178*/
179/* Prefetch buffer header given index. */
180#define vlib_prefetch_buffer_with_index(vm,bi,type) \
181 do { \
182 vlib_buffer_t * _b = vlib_get_buffer (vm, bi); \
183 vlib_prefetch_buffer_header (_b, type); \
184 } while (0)
185
186#if 0
187/* Iterate over known allocated vlib bufs. You probably do not want
188 * to do this!
189 @param vm the vlib_main_t
190 @param bi found allocated buffer index
191 @param body operation to perform on buffer index
192 function executes body for each allocated buffer index
193 */
194#define vlib_buffer_foreach_allocated(vm,bi,body) \
195do { \
196 vlib_main_t * _vmain = (vm); \
197 vlib_buffer_main_t * _bmain = &_vmain->buffer_main; \
198 hash_pair_t * _vbpair; \
199 hash_foreach_pair(_vbpair, _bmain->buffer_known_hash, ({ \
200 if (VLIB_BUFFER_KNOWN_ALLOCATED == _vbpair->value[0]) { \
201 (bi) = _vbpair->key; \
202 body; \
203 } \
204 })); \
205} while (0)
206#endif
207
Dave Barach9b8ffd92016-07-08 08:13:45 -0400208typedef enum
209{
Ed Warnickecb9cada2015-12-08 15:45:58 -0700210 /* Index is unknown. */
211 VLIB_BUFFER_UNKNOWN,
212
213 /* Index is known and free/allocated. */
214 VLIB_BUFFER_KNOWN_FREE,
215 VLIB_BUFFER_KNOWN_ALLOCATED,
216} vlib_buffer_known_state_t;
217
218always_inline vlib_buffer_known_state_t
219vlib_buffer_is_known (vlib_main_t * vm, u32 buffer_index)
220{
Dave Barach9b8ffd92016-07-08 08:13:45 -0400221 vlib_buffer_main_t *bm = vm->buffer_main;
Damjan Marion586afd72017-04-05 19:18:20 +0200222 ASSERT (vlib_get_thread_index () == 0);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700223
Dave Barach9b8ffd92016-07-08 08:13:45 -0400224 uword *p = hash_get (bm->buffer_known_hash, buffer_index);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700225 return p ? p[0] : VLIB_BUFFER_UNKNOWN;
226}
227
228always_inline void
229vlib_buffer_set_known_state (vlib_main_t * vm,
230 u32 buffer_index,
231 vlib_buffer_known_state_t state)
232{
Dave Barach9b8ffd92016-07-08 08:13:45 -0400233 vlib_buffer_main_t *bm = vm->buffer_main;
Damjan Marion586afd72017-04-05 19:18:20 +0200234 ASSERT (vlib_get_thread_index () == 0);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700235 hash_set (bm->buffer_known_hash, buffer_index, state);
236}
237
238/* Validates sanity of a single buffer.
239 Returns format'ed vector with error message if any. */
Dave Barach9b8ffd92016-07-08 08:13:45 -0400240u8 *vlib_validate_buffer (vlib_main_t * vm, u32 buffer_index,
241 uword follow_chain);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700242
Ed Warnickecb9cada2015-12-08 15:45:58 -0700243/** \brief Allocate buffers into supplied array
244
245 @param vm - (vlib_main_t *) vlib main data structure pointer
246 @param buffers - (u32 * ) buffer index array
247 @param n_buffers - (u32) number of buffers requested
Dave Barach9b8ffd92016-07-08 08:13:45 -0400248 @return - (u32) number of buffers actually allocated, may be
Ed Warnickecb9cada2015-12-08 15:45:58 -0700249 less than the number requested or zero
250*/
Damjan Marion878c6092017-01-04 13:19:27 +0100251always_inline u32
252vlib_buffer_alloc (vlib_main_t * vm, u32 * buffers, u32 n_buffers)
253{
254 vlib_buffer_main_t *bm = vm->buffer_main;
255
256 ASSERT (bm->cb.vlib_buffer_alloc_cb);
257
258 return bm->cb.vlib_buffer_alloc_cb (vm, buffers, n_buffers);
259}
Ed Warnickecb9cada2015-12-08 15:45:58 -0700260
261always_inline u32
262vlib_buffer_round_size (u32 size)
Dave Barach9b8ffd92016-07-08 08:13:45 -0400263{
264 return round_pow2 (size, sizeof (vlib_buffer_t));
265}
Ed Warnickecb9cada2015-12-08 15:45:58 -0700266
Damjan Marion072401e2017-07-13 18:53:27 +0200267always_inline u32
268vlib_buffer_get_free_list_index (vlib_buffer_t * b)
269{
270 return b->flags & VLIB_BUFFER_FREE_LIST_INDEX_MASK;
271}
272
273always_inline void
274vlib_buffer_set_free_list_index (vlib_buffer_t * b, u32 index)
275{
276 /* if there is an need for more free lists we should consider
277 storig data in the 2nd cacheline */
278 ASSERT (VLIB_BUFFER_FREE_LIST_INDEX_MASK & 1);
279 ASSERT (index <= VLIB_BUFFER_FREE_LIST_INDEX_MASK);
280
281 b->flags &= ~VLIB_BUFFER_FREE_LIST_INDEX_MASK;
282 b->flags |= index & VLIB_BUFFER_FREE_LIST_INDEX_MASK;
283}
284
Ed Warnickecb9cada2015-12-08 15:45:58 -0700285/** \brief Allocate buffers from specific freelist into supplied array
286
287 @param vm - (vlib_main_t *) vlib main data structure pointer
288 @param buffers - (u32 * ) buffer index array
289 @param n_buffers - (u32) number of buffers requested
Dave Barach9b8ffd92016-07-08 08:13:45 -0400290 @return - (u32) number of buffers actually allocated, may be
Ed Warnickecb9cada2015-12-08 15:45:58 -0700291 less than the number requested or zero
292*/
Damjan Marion878c6092017-01-04 13:19:27 +0100293always_inline u32
294vlib_buffer_alloc_from_free_list (vlib_main_t * vm,
295 u32 * buffers,
296 u32 n_buffers, u32 free_list_index)
297{
298 vlib_buffer_main_t *bm = vm->buffer_main;
299
300 ASSERT (bm->cb.vlib_buffer_alloc_from_free_list_cb);
301
302 return bm->cb.vlib_buffer_alloc_from_free_list_cb (vm, buffers, n_buffers,
303 free_list_index);
304}
Ed Warnickecb9cada2015-12-08 15:45:58 -0700305
306/** \brief Free buffers
307 Frees the entire buffer chain for each buffer
308
309 @param vm - (vlib_main_t *) vlib main data structure pointer
310 @param buffers - (u32 * ) buffer index array
311 @param n_buffers - (u32) number of buffers to free
312
313*/
Damjan Marion878c6092017-01-04 13:19:27 +0100314always_inline void
315vlib_buffer_free (vlib_main_t * vm,
316 /* pointer to first buffer */
317 u32 * buffers,
318 /* number of buffers to free */
319 u32 n_buffers)
320{
321 vlib_buffer_main_t *bm = vm->buffer_main;
322
323 ASSERT (bm->cb.vlib_buffer_free_cb);
324
325 return bm->cb.vlib_buffer_free_cb (vm, buffers, n_buffers);
326}
Ed Warnickecb9cada2015-12-08 15:45:58 -0700327
328/** \brief Free buffers, does not free the buffer chain for each buffer
329
330 @param vm - (vlib_main_t *) vlib main data structure pointer
331 @param buffers - (u32 * ) buffer index array
332 @param n_buffers - (u32) number of buffers to free
333
334*/
Damjan Marion878c6092017-01-04 13:19:27 +0100335always_inline void
336vlib_buffer_free_no_next (vlib_main_t * vm,
337 /* pointer to first buffer */
338 u32 * buffers,
339 /* number of buffers to free */
340 u32 n_buffers)
341{
342 vlib_buffer_main_t *bm = vm->buffer_main;
343
344 ASSERT (bm->cb.vlib_buffer_free_no_next_cb);
345
346 return bm->cb.vlib_buffer_free_no_next_cb (vm, buffers, n_buffers);
347}
Ed Warnickecb9cada2015-12-08 15:45:58 -0700348
349/** \brief Free one buffer
Dave Barach9b8ffd92016-07-08 08:13:45 -0400350 Shorthand to free a single buffer chain.
Ed Warnickecb9cada2015-12-08 15:45:58 -0700351
352 @param vm - (vlib_main_t *) vlib main data structure pointer
353 @param buffer_index - (u32) buffer index to free
354*/
355always_inline void
356vlib_buffer_free_one (vlib_main_t * vm, u32 buffer_index)
357{
358 vlib_buffer_free (vm, &buffer_index, /* n_buffers */ 1);
359}
360
361/* Add/delete buffer free lists. */
Dave Barach9b8ffd92016-07-08 08:13:45 -0400362u32 vlib_buffer_create_free_list (vlib_main_t * vm, u32 n_data_bytes,
363 char *fmt, ...);
Damjan Marion878c6092017-01-04 13:19:27 +0100364always_inline void
365vlib_buffer_delete_free_list (vlib_main_t * vm, u32 free_list_index)
366{
367 vlib_buffer_main_t *bm = vm->buffer_main;
368
369 ASSERT (bm->cb.vlib_buffer_delete_free_list_cb);
370
371 bm->cb.vlib_buffer_delete_free_list_cb (vm, free_list_index);
372}
Ed Warnickecb9cada2015-12-08 15:45:58 -0700373
374/* Find already existing public free list with given size or create one. */
Dave Barach9b8ffd92016-07-08 08:13:45 -0400375u32 vlib_buffer_get_or_create_free_list (vlib_main_t * vm, u32 n_data_bytes,
376 char *fmt, ...);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700377
Damjan Marion8a6a3b22017-01-17 14:12:42 +0100378/* Merge two free lists */
379void vlib_buffer_merge_free_lists (vlib_buffer_free_list_t * dst,
380 vlib_buffer_free_list_t * src);
381
382/* Make sure we have at least given number of unaligned buffers. */
383void vlib_buffer_free_list_fill_unaligned (vlib_main_t * vm,
384 vlib_buffer_free_list_t *
385 free_list,
386 uword n_unaligned_buffers);
387
388always_inline u32
389vlib_buffer_get_free_list_with_size (vlib_main_t * vm, u32 size)
390{
391 vlib_buffer_main_t *bm = vm->buffer_main;
392
393 size = vlib_buffer_round_size (size);
394 uword *p = hash_get (bm->free_list_by_size, size);
395 return p ? p[0] : ~0;
396}
397
398always_inline vlib_buffer_free_list_t *
399vlib_buffer_get_buffer_free_list (vlib_main_t * vm, vlib_buffer_t * b,
400 u32 * index)
401{
402 vlib_buffer_main_t *bm = vm->buffer_main;
403 u32 i;
404
Damjan Marion072401e2017-07-13 18:53:27 +0200405 *index = i = vlib_buffer_get_free_list_index (b);
Damjan Marion8a6a3b22017-01-17 14:12:42 +0100406 return pool_elt_at_index (bm->buffer_free_list_pool, i);
407}
408
Ed Warnickecb9cada2015-12-08 15:45:58 -0700409always_inline vlib_buffer_free_list_t *
410vlib_buffer_get_free_list (vlib_main_t * vm, u32 free_list_index)
411{
Dave Barach9b8ffd92016-07-08 08:13:45 -0400412 vlib_buffer_main_t *bm = vm->buffer_main;
413 vlib_buffer_free_list_t *f;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700414
415 f = pool_elt_at_index (bm->buffer_free_list_pool, free_list_index);
416
417 /* Sanity: indices must match. */
418 ASSERT (f->index == free_list_index);
419
420 return f;
421}
422
423always_inline u32
424vlib_buffer_free_list_buffer_size (vlib_main_t * vm, u32 free_list_index)
425{
Dave Barach9b8ffd92016-07-08 08:13:45 -0400426 vlib_buffer_free_list_t *f =
427 vlib_buffer_get_free_list (vm, free_list_index);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700428 return f->n_data_bytes;
429}
430
Dave Barach9b8ffd92016-07-08 08:13:45 -0400431void vlib_aligned_memcpy (void *_dst, void *_src, int n_bytes);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700432
433/* Reasonably fast buffer copy routine. */
434always_inline void
435vlib_copy_buffers (u32 * dst, u32 * src, u32 n)
436{
437 while (n >= 4)
438 {
439 dst[0] = src[0];
440 dst[1] = src[1];
441 dst[2] = src[2];
442 dst[3] = src[3];
443 dst += 4;
444 src += 4;
445 n -= 4;
446 }
447 while (n > 0)
448 {
449 dst[0] = src[0];
450 dst += 1;
451 src += 1;
452 n -= 1;
453 }
454}
455
456always_inline void *
457vlib_physmem_alloc_aligned (vlib_main_t * vm, clib_error_t ** error,
458 uword n_bytes, uword alignment)
459{
Dave Barach9b8ffd92016-07-08 08:13:45 -0400460 void *r =
461 vm->os_physmem_alloc_aligned (&vm->physmem_main, n_bytes, alignment);
462 if (!r)
463 *error =
464 clib_error_return (0, "failed to allocate %wd bytes of I/O memory",
465 n_bytes);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700466 else
467 *error = 0;
468 return r;
469}
470
471/* By default allocate I/O memory with cache line alignment. */
472always_inline void *
473vlib_physmem_alloc (vlib_main_t * vm, clib_error_t ** error, uword n_bytes)
Dave Barach9b8ffd92016-07-08 08:13:45 -0400474{
475 return vlib_physmem_alloc_aligned (vm, error, n_bytes,
476 CLIB_CACHE_LINE_BYTES);
477}
Ed Warnickecb9cada2015-12-08 15:45:58 -0700478
479always_inline void
Dave Barach9b8ffd92016-07-08 08:13:45 -0400480vlib_physmem_free (vlib_main_t * vm, void *mem)
481{
482 return vm->os_physmem_free (mem);
483}
Ed Warnickecb9cada2015-12-08 15:45:58 -0700484
485always_inline u64
Dave Barach9b8ffd92016-07-08 08:13:45 -0400486vlib_physmem_virtual_to_physical (vlib_main_t * vm, void *mem)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700487{
Dave Barach9b8ffd92016-07-08 08:13:45 -0400488 vlib_physmem_main_t *pm = &vm->physmem_main;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700489 uword o = pointer_to_uword (mem) - pm->virtual.start;
490 return vlib_physmem_offset_to_physical (pm, o);
491}
492
493/* Append given data to end of buffer, possibly allocating new buffers. */
494u32 vlib_buffer_add_data (vlib_main_t * vm,
495 u32 free_list_index,
Dave Barach9b8ffd92016-07-08 08:13:45 -0400496 u32 buffer_index, void *data, u32 n_data_bytes);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700497
Damjan Marion05ab8cb2016-11-03 20:16:04 +0100498/* duplicate all buffers in chain */
499always_inline vlib_buffer_t *
500vlib_buffer_copy (vlib_main_t * vm, vlib_buffer_t * b)
501{
502 vlib_buffer_t *s, *d, *fd;
503 uword n_alloc, n_buffers = 1;
Damjan Marion67655492016-11-15 12:50:28 +0100504 u32 flag_mask = VLIB_BUFFER_NEXT_PRESENT | VLIB_BUFFER_TOTAL_LENGTH_VALID;
Damjan Marion05ab8cb2016-11-03 20:16:04 +0100505 int i;
506
507 s = b;
508 while (s->flags & VLIB_BUFFER_NEXT_PRESENT)
509 {
510 n_buffers++;
511 s = vlib_get_buffer (vm, s->next_buffer);
512 }
Neale Ranns9d676af2017-03-15 01:28:31 -0700513 u32 new_buffers[n_buffers];
Damjan Marion05ab8cb2016-11-03 20:16:04 +0100514
Damjan Marion05ab8cb2016-11-03 20:16:04 +0100515 n_alloc = vlib_buffer_alloc (vm, new_buffers, n_buffers);
Dave Barach26cd8c12017-02-23 17:11:26 -0500516
517 /* No guarantee that we'll get all the buffers we asked for */
518 if (PREDICT_FALSE (n_alloc < n_buffers))
519 {
520 if (n_alloc > 0)
521 vlib_buffer_free (vm, new_buffers, n_alloc);
Dave Barach26cd8c12017-02-23 17:11:26 -0500522 return 0;
523 }
Damjan Marion05ab8cb2016-11-03 20:16:04 +0100524
525 /* 1st segment */
526 s = b;
527 fd = d = vlib_get_buffer (vm, new_buffers[0]);
Damjan Marion05ab8cb2016-11-03 20:16:04 +0100528 d->current_data = s->current_data;
529 d->current_length = s->current_length;
Damjan Marion67655492016-11-15 12:50:28 +0100530 d->flags = s->flags & flag_mask;
Damjan Marion05ab8cb2016-11-03 20:16:04 +0100531 d->total_length_not_including_first_buffer =
532 s->total_length_not_including_first_buffer;
533 clib_memcpy (d->opaque, s->opaque, sizeof (s->opaque));
Damjan Mariondce05452016-12-01 11:59:33 +0100534 clib_memcpy (vlib_buffer_get_current (d),
535 vlib_buffer_get_current (s), s->current_length);
Damjan Marion05ab8cb2016-11-03 20:16:04 +0100536
537 /* next segments */
538 for (i = 1; i < n_buffers; i++)
539 {
540 /* previous */
541 d->next_buffer = new_buffers[i];
542 /* current */
543 s = vlib_get_buffer (vm, s->next_buffer);
544 d = vlib_get_buffer (vm, new_buffers[i]);
545 d->current_data = s->current_data;
546 d->current_length = s->current_length;
547 clib_memcpy (vlib_buffer_get_current (d),
548 vlib_buffer_get_current (s), s->current_length);
Damjan Marion67655492016-11-15 12:50:28 +0100549 d->flags = s->flags & flag_mask;
Damjan Marion05ab8cb2016-11-03 20:16:04 +0100550 }
551
552 return fd;
553}
554
Damjan Marionc47ed032017-01-25 14:18:03 +0100555/** \brief Create multiple clones of buffer and store them in the supplied array
556
557 @param vm - (vlib_main_t *) vlib main data structure pointer
558 @param src_buffer - (u32) source buffer index
559 @param buffers - (u32 * ) buffer index array
560 @param n_buffers - (u8) number of buffer clones requested
561 @param head_end_offset - (u16) offset relative to current position
562 where packet head ends
563 @return - (u8) number of buffers actually cloned, may be
564 less than the number requested or zero
565*/
566
567always_inline u8
568vlib_buffer_clone (vlib_main_t * vm, u32 src_buffer, u32 * buffers,
569 u8 n_buffers, u16 head_end_offset)
570{
571 u8 i;
572 vlib_buffer_t *s = vlib_get_buffer (vm, src_buffer);
573
574 ASSERT (s->n_add_refs == 0);
575 ASSERT (n_buffers);
576
577 if (s->current_length <= head_end_offset + CLIB_CACHE_LINE_BYTES * 2)
578 {
579 buffers[0] = src_buffer;
580 for (i = 1; i < n_buffers; i++)
581 {
582 vlib_buffer_t *d;
583 d = vlib_buffer_copy (vm, s);
584 if (d == 0)
585 return i;
586 buffers[i] = vlib_get_buffer_index (vm, d);
587
588 }
589 return n_buffers;
590 }
591
592 n_buffers = vlib_buffer_alloc_from_free_list (vm, buffers, n_buffers,
Damjan Marion072401e2017-07-13 18:53:27 +0200593 vlib_buffer_get_free_list_index
594 (s));
Damjan Marionc47ed032017-01-25 14:18:03 +0100595 if (PREDICT_FALSE (n_buffers == 0))
596 {
597 buffers[0] = src_buffer;
598 return 1;
599 }
600
601 for (i = 0; i < n_buffers; i++)
602 {
603 vlib_buffer_t *d = vlib_get_buffer (vm, buffers[i]);
604 d->current_data = s->current_data;
605 d->current_length = head_end_offset;
Damjan Marion072401e2017-07-13 18:53:27 +0200606 vlib_buffer_set_free_list_index (d,
607 vlib_buffer_get_free_list_index (s));
Damjan Marionc47ed032017-01-25 14:18:03 +0100608 d->total_length_not_including_first_buffer =
609 s->total_length_not_including_first_buffer + s->current_length -
610 head_end_offset;
611 d->flags = s->flags | VLIB_BUFFER_NEXT_PRESENT;
612 d->flags &= ~VLIB_BUFFER_EXT_HDR_VALID;
613 clib_memcpy (d->opaque, s->opaque, sizeof (s->opaque));
614 clib_memcpy (vlib_buffer_get_current (d), vlib_buffer_get_current (s),
615 head_end_offset);
616 d->next_buffer = src_buffer;
617 }
618 vlib_buffer_advance (s, head_end_offset);
619 s->n_add_refs = n_buffers - 1;
620 while (s->flags & VLIB_BUFFER_NEXT_PRESENT)
621 {
622 s = vlib_get_buffer (vm, s->next_buffer);
623 s->n_add_refs = n_buffers - 1;
624 }
625
626 return n_buffers;
627}
628
629/** \brief Attach cloned tail to the buffer
630
631 @param vm - (vlib_main_t *) vlib main data structure pointer
632 @param head - (vlib_buffer_t *) head buffer
633 @param tail - (Vlib buffer_t *) tail buffer to clone and attach to head
634*/
635
636always_inline void
637vlib_buffer_attach_clone (vlib_main_t * vm, vlib_buffer_t * head,
638 vlib_buffer_t * tail)
639{
640 ASSERT ((head->flags & VLIB_BUFFER_NEXT_PRESENT) == 0);
Damjan Marion072401e2017-07-13 18:53:27 +0200641 ASSERT (vlib_buffer_get_free_list_index (head) ==
642 vlib_buffer_get_free_list_index (tail));
Damjan Marionc47ed032017-01-25 14:18:03 +0100643
644 head->flags |= VLIB_BUFFER_NEXT_PRESENT;
645 head->flags &= ~VLIB_BUFFER_TOTAL_LENGTH_VALID;
646 head->flags &= ~VLIB_BUFFER_EXT_HDR_VALID;
647 head->flags |= (tail->flags & VLIB_BUFFER_TOTAL_LENGTH_VALID);
648 head->next_buffer = vlib_get_buffer_index (vm, tail);
649 head->total_length_not_including_first_buffer = tail->current_length +
650 tail->total_length_not_including_first_buffer;
651
652next_segment:
653 __sync_add_and_fetch (&tail->n_add_refs, 1);
654
655 if (tail->flags & VLIB_BUFFER_NEXT_PRESENT)
656 {
657 tail = vlib_get_buffer (vm, tail->next_buffer);
658 goto next_segment;
659 }
660}
661
Pierre Pfister328e99b2016-02-12 13:18:42 +0000662/* Initializes the buffer as an empty packet with no chained buffers. */
663always_inline void
Dave Barach9b8ffd92016-07-08 08:13:45 -0400664vlib_buffer_chain_init (vlib_buffer_t * first)
Pierre Pfister328e99b2016-02-12 13:18:42 +0000665{
666 first->total_length_not_including_first_buffer = 0;
667 first->current_length = 0;
668 first->flags &= ~VLIB_BUFFER_NEXT_PRESENT;
669 first->flags |= VLIB_BUFFER_TOTAL_LENGTH_VALID;
Pierre Pfister328e99b2016-02-12 13:18:42 +0000670}
671
672/* The provided next_bi buffer index is appended to the end of the packet. */
673always_inline vlib_buffer_t *
Dave Barach9b8ffd92016-07-08 08:13:45 -0400674vlib_buffer_chain_buffer (vlib_main_t * vm,
675 vlib_buffer_t * first,
676 vlib_buffer_t * last, u32 next_bi)
Pierre Pfister328e99b2016-02-12 13:18:42 +0000677{
Dave Barach9b8ffd92016-07-08 08:13:45 -0400678 vlib_buffer_t *next_buffer = vlib_get_buffer (vm, next_bi);
Pierre Pfister328e99b2016-02-12 13:18:42 +0000679 last->next_buffer = next_bi;
680 last->flags |= VLIB_BUFFER_NEXT_PRESENT;
681 next_buffer->current_length = 0;
682 next_buffer->flags &= ~VLIB_BUFFER_NEXT_PRESENT;
Pierre Pfister328e99b2016-02-12 13:18:42 +0000683 return next_buffer;
684}
685
686/* Increases or decreases the packet length.
687 * It does not allocate or deallocate new buffers.
688 * Therefore, the added length must be compatible
689 * with the last buffer. */
690always_inline void
Dave Barach9b8ffd92016-07-08 08:13:45 -0400691vlib_buffer_chain_increase_length (vlib_buffer_t * first,
692 vlib_buffer_t * last, i32 len)
Pierre Pfister328e99b2016-02-12 13:18:42 +0000693{
694 last->current_length += len;
695 if (first != last)
696 first->total_length_not_including_first_buffer += len;
Pierre Pfister328e99b2016-02-12 13:18:42 +0000697}
698
699/* Copy data to the end of the packet and increases its length.
700 * It does not allocate new buffers.
701 * Returns the number of copied bytes. */
702always_inline u16
Dave Barach9b8ffd92016-07-08 08:13:45 -0400703vlib_buffer_chain_append_data (vlib_main_t * vm,
704 u32 free_list_index,
705 vlib_buffer_t * first,
706 vlib_buffer_t * last, void *data, u16 data_len)
Pierre Pfister328e99b2016-02-12 13:18:42 +0000707{
Dave Barach9b8ffd92016-07-08 08:13:45 -0400708 u32 n_buffer_bytes =
709 vlib_buffer_free_list_buffer_size (vm, free_list_index);
710 ASSERT (n_buffer_bytes >= last->current_length + last->current_data);
711 u16 len = clib_min (data_len,
712 n_buffer_bytes - last->current_length -
713 last->current_data);
714 clib_memcpy (vlib_buffer_get_current (last) + last->current_length, data,
715 len);
716 vlib_buffer_chain_increase_length (first, last, len);
Pierre Pfister328e99b2016-02-12 13:18:42 +0000717 return len;
718}
719
720/* Copy data to the end of the packet and increases its length.
721 * Allocates additional buffers from the free list if necessary.
722 * Returns the number of copied bytes.
723 * 'last' value is modified whenever new buffers are allocated and
724 * chained and points to the last buffer in the chain. */
725u16
Dave Barach9b8ffd92016-07-08 08:13:45 -0400726vlib_buffer_chain_append_data_with_alloc (vlib_main_t * vm,
727 u32 free_list_index,
728 vlib_buffer_t * first,
729 vlib_buffer_t ** last,
730 void *data, u16 data_len);
731void vlib_buffer_chain_validate (vlib_main_t * vm, vlib_buffer_t * first);
Pierre Pfister328e99b2016-02-12 13:18:42 +0000732
Dave Barach9b8ffd92016-07-08 08:13:45 -0400733format_function_t format_vlib_buffer, format_vlib_buffer_and_data,
734 format_vlib_buffer_contents;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700735
Dave Barach9b8ffd92016-07-08 08:13:45 -0400736typedef struct
737{
Ed Warnickecb9cada2015-12-08 15:45:58 -0700738 /* Vector of packet data. */
Dave Barach9b8ffd92016-07-08 08:13:45 -0400739 u8 *packet_data;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700740
Ed Warnickecb9cada2015-12-08 15:45:58 -0700741 /* Number of buffers to allocate in each call to physmem
742 allocator. */
743 u32 min_n_buffers_each_physmem_alloc;
744
745 /* Buffer free list for this template. */
746 u32 free_list_index;
747
Dave Barach9b8ffd92016-07-08 08:13:45 -0400748 u32 *free_buffers;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700749} vlib_packet_template_t;
750
751void vlib_packet_template_get_packet_helper (vlib_main_t * vm,
752 vlib_packet_template_t * t);
753
754void vlib_packet_template_init (vlib_main_t * vm,
755 vlib_packet_template_t * t,
Dave Barach9b8ffd92016-07-08 08:13:45 -0400756 void *packet_data,
Ed Warnickecb9cada2015-12-08 15:45:58 -0700757 uword n_packet_data_bytes,
758 uword min_n_buffers_each_physmem_alloc,
Dave Barach9b8ffd92016-07-08 08:13:45 -0400759 char *fmt, ...);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700760
Dave Barach9b8ffd92016-07-08 08:13:45 -0400761void *vlib_packet_template_get_packet (vlib_main_t * vm,
762 vlib_packet_template_t * t,
763 u32 * bi_result);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700764
765always_inline void
766vlib_packet_template_free (vlib_main_t * vm, vlib_packet_template_t * t)
767{
768 vec_free (t->packet_data);
769}
770
771always_inline u32
772unserialize_vlib_buffer_n_bytes (serialize_main_t * m)
773{
Dave Barach9b8ffd92016-07-08 08:13:45 -0400774 serialize_stream_t *s = &m->stream;
775 vlib_serialize_buffer_main_t *sm
776 = uword_to_pointer (m->stream.data_function_opaque,
777 vlib_serialize_buffer_main_t *);
778 vlib_main_t *vm = sm->vlib_main;
779 u32 n, *f;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700780
781 n = s->n_buffer_bytes - s->current_buffer_index;
782 if (sm->last_buffer != ~0)
783 {
Dave Barach9b8ffd92016-07-08 08:13:45 -0400784 vlib_buffer_t *b = vlib_get_buffer (vm, sm->last_buffer);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700785 while (b->flags & VLIB_BUFFER_NEXT_PRESENT)
786 {
787 b = vlib_get_buffer (vm, b->next_buffer);
788 n += b->current_length;
789 }
790 }
791
Dave Barach9b8ffd92016-07-08 08:13:45 -0400792 /* *INDENT-OFF* */
Ed Warnickecb9cada2015-12-08 15:45:58 -0700793 clib_fifo_foreach (f, sm->rx.buffer_fifo, ({
794 n += vlib_buffer_index_length_in_chain (vm, f[0]);
795 }));
Dave Barach9b8ffd92016-07-08 08:13:45 -0400796/* *INDENT-ON* */
Ed Warnickecb9cada2015-12-08 15:45:58 -0700797
798 return n;
799}
800
Ed Warnickecb9cada2015-12-08 15:45:58 -0700801/* Set a buffer quickly into "uninitialized" state. We want this to
802 be extremely cheap and arrange for all fields that need to be
803 initialized to be in the first 128 bits of the buffer. */
804always_inline void
Damjan Marionbd69a5f2017-02-05 23:44:42 +0100805vlib_buffer_init_for_free_list (vlib_buffer_t * dst,
Ed Warnickecb9cada2015-12-08 15:45:58 -0700806 vlib_buffer_free_list_t * fl)
807{
Damjan Marionbd69a5f2017-02-05 23:44:42 +0100808 vlib_buffer_t *src = &fl->buffer_init_template;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700809
Damjan Marion19010202016-03-24 17:17:47 +0100810 /* Make sure vlib_buffer_t is cacheline aligned and sized */
Dave Barach9b8ffd92016-07-08 08:13:45 -0400811 ASSERT (STRUCT_OFFSET_OF (vlib_buffer_t, cacheline0) == 0);
812 ASSERT (STRUCT_OFFSET_OF (vlib_buffer_t, cacheline1) ==
813 CLIB_CACHE_LINE_BYTES);
814 ASSERT (STRUCT_OFFSET_OF (vlib_buffer_t, cacheline2) ==
815 CLIB_CACHE_LINE_BYTES * 2);
Damjan Marion19010202016-03-24 17:17:47 +0100816
Ed Warnickecb9cada2015-12-08 15:45:58 -0700817 /* Make sure buffer template is sane. */
Damjan Marion072401e2017-07-13 18:53:27 +0200818 ASSERT (fl->index == vlib_buffer_get_free_list_index (src));
Ed Warnickecb9cada2015-12-08 15:45:58 -0700819
Dave Barachf8690282017-03-01 11:38:02 -0500820 clib_memcpy (STRUCT_MARK_PTR (dst, template_start),
821 STRUCT_MARK_PTR (src, template_start),
822 STRUCT_OFFSET_OF (vlib_buffer_t, template_end) -
823 STRUCT_OFFSET_OF (vlib_buffer_t, template_start));
824
825 /* Not in the first 16 octets. */
826 dst->n_add_refs = src->n_add_refs;
827
Ed Warnickecb9cada2015-12-08 15:45:58 -0700828 /* Make sure it really worked. */
Dave Barachf8690282017-03-01 11:38:02 -0500829#define _(f) ASSERT (dst->f == src->f);
Dave Barach9b8ffd92016-07-08 08:13:45 -0400830 _(current_data);
831 _(current_length);
832 _(flags);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700833#undef _
Dave Barachf8690282017-03-01 11:38:02 -0500834 ASSERT (dst->total_length_not_including_first_buffer == 0);
Damjan Marionc47ed032017-01-25 14:18:03 +0100835 ASSERT (dst->n_add_refs == 0);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700836}
837
838always_inline void
Damjan Marion8a6a3b22017-01-17 14:12:42 +0100839vlib_buffer_add_to_free_list (vlib_main_t * vm,
840 vlib_buffer_free_list_t * f,
841 u32 buffer_index, u8 do_init)
842{
843 vlib_buffer_t *b;
844 b = vlib_get_buffer (vm, buffer_index);
845 if (PREDICT_TRUE (do_init))
846 vlib_buffer_init_for_free_list (b, f);
Damjan Marionbd69a5f2017-02-05 23:44:42 +0100847 vec_add1_aligned (f->buffers, buffer_index, CLIB_CACHE_LINE_BYTES);
Damjan Marion8a6a3b22017-01-17 14:12:42 +0100848}
849
850always_inline void
Damjan Marionbd69a5f2017-02-05 23:44:42 +0100851vlib_buffer_init_two_for_free_list (vlib_buffer_t * dst0,
852 vlib_buffer_t * dst1,
Ed Warnickecb9cada2015-12-08 15:45:58 -0700853 vlib_buffer_free_list_t * fl)
854{
Damjan Marionbd69a5f2017-02-05 23:44:42 +0100855 vlib_buffer_t *src = &fl->buffer_init_template;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700856
857 /* Make sure buffer template is sane. */
Damjan Marion072401e2017-07-13 18:53:27 +0200858 ASSERT (fl->index == vlib_buffer_get_free_list_index (src));
Ed Warnickecb9cada2015-12-08 15:45:58 -0700859
Dave Barachf8690282017-03-01 11:38:02 -0500860 clib_memcpy (STRUCT_MARK_PTR (dst0, template_start),
861 STRUCT_MARK_PTR (src, template_start),
862 STRUCT_OFFSET_OF (vlib_buffer_t, template_end) -
863 STRUCT_OFFSET_OF (vlib_buffer_t, template_start));
864
865 clib_memcpy (STRUCT_MARK_PTR (dst1, template_start),
866 STRUCT_MARK_PTR (src, template_start),
867 STRUCT_OFFSET_OF (vlib_buffer_t, template_end) -
868 STRUCT_OFFSET_OF (vlib_buffer_t, template_start));
869
870 /* Not in the first 16 octets. */
871 dst0->n_add_refs = src->n_add_refs;
872 dst1->n_add_refs = src->n_add_refs;
873
Ed Warnickecb9cada2015-12-08 15:45:58 -0700874 /* Make sure it really worked. */
Dave Barachf8690282017-03-01 11:38:02 -0500875#define _(f) ASSERT (dst0->f == src->f); ASSERT( dst1->f == src->f)
Dave Barach9b8ffd92016-07-08 08:13:45 -0400876 _(current_data);
877 _(current_length);
878 _(flags);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700879#undef _
Dave Barachf8690282017-03-01 11:38:02 -0500880
881 ASSERT (dst0->total_length_not_including_first_buffer == 0);
882 ASSERT (dst1->total_length_not_including_first_buffer == 0);
Damjan Marionc47ed032017-01-25 14:18:03 +0100883 ASSERT (dst0->n_add_refs == 0);
884 ASSERT (dst1->n_add_refs == 0);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700885}
886
887#if CLIB_DEBUG > 0
Damjan Marion6a7acc22016-12-19 16:28:36 +0100888extern u32 *vlib_buffer_state_validation_lock;
889extern uword *vlib_buffer_state_validation_hash;
890extern void *vlib_buffer_state_heap;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700891#endif
892
Dave Barach9b8ffd92016-07-08 08:13:45 -0400893static inline void
Ed Warnickecb9cada2015-12-08 15:45:58 -0700894vlib_validate_buffer_in_use (vlib_buffer_t * b, u32 expected)
895{
896#if CLIB_DEBUG > 0
Dave Barach9b8ffd92016-07-08 08:13:45 -0400897 uword *p;
898 void *oldheap;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700899
900 oldheap = clib_mem_set_heap (vlib_buffer_state_heap);
901
902 while (__sync_lock_test_and_set (vlib_buffer_state_validation_lock, 1))
903 ;
904
905 p = hash_get (vlib_buffer_state_validation_hash, b);
906
907 /* If we don't know about b, declare it to be in the expected state */
908 if (!p)
909 {
910 hash_set (vlib_buffer_state_validation_hash, b, expected);
911 goto out;
912 }
Dave Barach9b8ffd92016-07-08 08:13:45 -0400913
Ed Warnickecb9cada2015-12-08 15:45:58 -0700914 if (p[0] != expected)
915 {
Dave Barach9b8ffd92016-07-08 08:13:45 -0400916 void cj_stop (void);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700917 u32 bi;
Dave Barach9b8ffd92016-07-08 08:13:45 -0400918 vlib_main_t *vm = &vlib_global_main;
919
920 cj_stop ();
921
Ed Warnickecb9cada2015-12-08 15:45:58 -0700922 bi = vlib_get_buffer_index (vm, b);
923
924 clib_mem_set_heap (oldheap);
Dave Barach9b8ffd92016-07-08 08:13:45 -0400925 clib_warning ("%.6f buffer %llx (%d): %s, not %s",
926 vlib_time_now (vm), bi,
927 p[0] ? "busy" : "free", expected ? "busy" : "free");
928 os_panic ();
Ed Warnickecb9cada2015-12-08 15:45:58 -0700929 }
Dave Barach9b8ffd92016-07-08 08:13:45 -0400930out:
931 CLIB_MEMORY_BARRIER ();
Ed Warnickecb9cada2015-12-08 15:45:58 -0700932 *vlib_buffer_state_validation_lock = 0;
933 clib_mem_set_heap (oldheap);
934#endif
935}
936
Dave Barach9b8ffd92016-07-08 08:13:45 -0400937static inline void
Ed Warnickecb9cada2015-12-08 15:45:58 -0700938vlib_validate_buffer_set_in_use (vlib_buffer_t * b, u32 expected)
939{
940#if CLIB_DEBUG > 0
Dave Barach9b8ffd92016-07-08 08:13:45 -0400941 void *oldheap;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700942
943 oldheap = clib_mem_set_heap (vlib_buffer_state_heap);
944
945 while (__sync_lock_test_and_set (vlib_buffer_state_validation_lock, 1))
946 ;
947
948 hash_set (vlib_buffer_state_validation_hash, b, expected);
949
Dave Barach9b8ffd92016-07-08 08:13:45 -0400950 CLIB_MEMORY_BARRIER ();
Ed Warnickecb9cada2015-12-08 15:45:58 -0700951 *vlib_buffer_state_validation_lock = 0;
952 clib_mem_set_heap (oldheap);
Dave Barach9b8ffd92016-07-08 08:13:45 -0400953#endif
Ed Warnickecb9cada2015-12-08 15:45:58 -0700954}
955
956#endif /* included_vlib_buffer_funcs_h */
Dave Barach9b8ffd92016-07-08 08:13:45 -0400957
958/*
959 * fd.io coding-style-patch-verification: ON
960 *
961 * Local Variables:
962 * eval: (c-set-style "gnu")
963 * End:
964 */