Enhance vlib_buffer_clone to change headroom space for packet

Add function vlib_buffer_clone_at_offset() so that the cloned
packets' 1st buffer will have the original packet header copied
at the specified offset (instead of current_data). This can be
used to increase headroom in the cloned packet to allow large
header encaps in case the stdandard 128B predata is not enough.
The original vlib_buffer_clone() still works the same as before.

Change-Id: I3b50c8ad7e3952568bc141710567c99a3dacddce
Signed-off-by: John Lo <loj@cisco.com>
This commit is contained in:
John Lo
2019-04-01 11:30:07 -04:00
parent ac3b113957
commit f545caada9

View File

@ -1033,6 +1033,31 @@ vlib_buffer_copy_no_chain (vlib_main_t * vm, vlib_buffer_t * b, u32 * di)
return d;
}
/* \brief Move packet from current position to offset position in buffer.
Only work for small packet using one buffer with room to fit the move
@param vm - (vlib_main_t *) vlib main data structure pointer
@param b - (vlib_buffer_t *) pointer to buffer
@param offset - (i16) position to move the packet in buffer
*/
always_inline void
vlib_buffer_move (vlib_main_t * vm, vlib_buffer_t * b, i16 offset)
{
ASSERT ((b->flags & VLIB_BUFFER_NEXT_PRESENT) == 0);
ASSERT (offset + VLIB_BUFFER_PRE_DATA_SIZE >= 0);
ASSERT (offset + b->current_length <
vlib_buffer_get_default_data_size (vm));
u8 *source = vlib_buffer_get_current (b);
b->current_data = offset;
u8 *destination = vlib_buffer_get_current (b);
u16 length = b->current_length;
if (source + length <= destination) /* no overlap */
clib_memcpy_fast (destination, source, length);
else
memmove (destination, source, length);
}
/** \brief Create a maximum of 256 clones of buffer and store them
in the supplied array
@ -1042,12 +1067,14 @@ vlib_buffer_copy_no_chain (vlib_main_t * vm, vlib_buffer_t * b, u32 * di)
@param n_buffers - (u16) number of buffer clones requested (<=256)
@param head_end_offset - (u16) offset relative to current position
where packet head ends
@param offset - (i16) copy packet head at current position if 0,
else at offset position to change headroom space as specified
@return - (u16) number of buffers actually cloned, may be
less than the number requested or zero
*/
always_inline u16
vlib_buffer_clone_256 (vlib_main_t * vm, u32 src_buffer, u32 * buffers,
u16 n_buffers, u16 head_end_offset)
u16 n_buffers, u16 head_end_offset, i16 offset)
{
u16 i;
vlib_buffer_t *s = vlib_get_buffer (vm, src_buffer);
@ -1055,10 +1082,16 @@ vlib_buffer_clone_256 (vlib_main_t * vm, u32 src_buffer, u32 * buffers,
ASSERT (s->ref_count == 1);
ASSERT (n_buffers);
ASSERT (n_buffers <= 256);
ASSERT (offset + VLIB_BUFFER_PRE_DATA_SIZE >= 0);
ASSERT ((offset + head_end_offset) <
vlib_buffer_get_default_data_size (vm));
if (s->current_length <= head_end_offset + CLIB_CACHE_LINE_BYTES * 2)
{
buffers[0] = src_buffer;
if (offset)
vlib_buffer_move (vm, s, offset);
for (i = 1; i < n_buffers; i++)
{
vlib_buffer_t *d;
@ -1071,7 +1104,7 @@ vlib_buffer_clone_256 (vlib_main_t * vm, u32 src_buffer, u32 * buffers,
return n_buffers;
}
if (PREDICT_FALSE (n_buffers == 1))
if (PREDICT_FALSE ((n_buffers == 1) && (offset == 0)))
{
buffers[0] = src_buffer;
return 1;
@ -1083,7 +1116,11 @@ vlib_buffer_clone_256 (vlib_main_t * vm, u32 src_buffer, u32 * buffers,
for (i = 0; i < n_buffers; i++)
{
vlib_buffer_t *d = vlib_get_buffer (vm, buffers[i]);
d->current_data = s->current_data;
if (offset)
d->current_data = offset;
else
d->current_data = s->current_data;
d->current_length = head_end_offset;
ASSERT (d->buffer_pool_index == s->buffer_pool_index);
@ -1122,12 +1159,14 @@ vlib_buffer_clone_256 (vlib_main_t * vm, u32 src_buffer, u32 * buffers,
@param n_buffers - (u16) number of buffer clones requested (<=256)
@param head_end_offset - (u16) offset relative to current position
where packet head ends
@param offset - (i16) copy packet head at current position if 0,
else at offset position to change headroom space as specified
@return - (u16) number of buffers actually cloned, may be
less than the number requested or zero
*/
always_inline u16
vlib_buffer_clone (vlib_main_t * vm, u32 src_buffer, u32 * buffers,
u16 n_buffers, u16 head_end_offset)
vlib_buffer_clone_at_offset (vlib_main_t * vm, u32 src_buffer, u32 * buffers,
u16 n_buffers, u16 head_end_offset, i16 offset)
{
vlib_buffer_t *s = vlib_get_buffer (vm, src_buffer);
u16 n_cloned = 0;
@ -1139,16 +1178,36 @@ vlib_buffer_clone (vlib_main_t * vm, u32 src_buffer, u32 * buffers,
n_cloned += vlib_buffer_clone_256 (vm,
vlib_get_buffer_index (vm, copy),
(buffers + n_cloned),
256, head_end_offset);
256, head_end_offset, offset);
n_buffers -= 256;
}
n_cloned += vlib_buffer_clone_256 (vm, src_buffer,
buffers + n_cloned,
n_buffers, head_end_offset);
n_buffers, head_end_offset, offset);
return n_cloned;
}
/** \brief Create multiple clones of buffer and store them
in the supplied array
@param vm - (vlib_main_t *) vlib main data structure pointer
@param src_buffer - (u32) source buffer index
@param buffers - (u32 * ) buffer index array
@param n_buffers - (u16) number of buffer clones requested (<=256)
@param head_end_offset - (u16) offset relative to current position
where packet head ends
@return - (u16) number of buffers actually cloned, may be
less than the number requested or zero
*/
always_inline u16
vlib_buffer_clone (vlib_main_t * vm, u32 src_buffer, u32 * buffers,
u16 n_buffers, u16 head_end_offset)
{
return vlib_buffer_clone_at_offset (vm, src_buffer, buffers, n_buffers,
head_end_offset, 0);
}
/** \brief Attach cloned tail to the buffer
@param vm - (vlib_main_t *) vlib main data structure pointer