Hello,

I noticed that dpdk devices set the VLIB_BUFFER_TOTAL_LENGTH_VALID flag when 
receiving packets, regardless of the value of 
total_length_not_including_first_buffer. Since dpdk only copies one cacheline 
from its vlib_buffer template into the buffer upon receipt of a packet, 
b->total_length_not_including_first_buffer is left unitialized (because it's in 
the second cacheline).


In most cases, this doesn't cause issues — for non-chained buffers the 
vlib_buffer_length_in_chain() function will still return the correct value 
because it only looks at b->current_length.


However, if the buffer is later vlib_buffer_clone()d, the stale 
total_length_not_including_first_buffer value will propagate to the new head of 
the chain, for which vlib_buffer_length_in_chain() will now return a wrong 
value. This can be observed for instance when using BIER, with which replicated 
packets will sometimes have oversized lengths.


An obvious fix for that is to remove the VLIB_BUFFER_TOTAL_LENGTH_VALID flag 
from the buffer_flags_template in dpdk_init(). I'm concerned about the 
performance of this approach though, because vlib_buffer_length_in_chain() will 
then have to go through the slow path for all chained packets, causing 
branches. The other solution would be to, in addition, add something along the 
lines of the following in dpdk_process_rx_burst():

      b[0]->flags |= (!b[0]->total_length_not_including_first_buffer) << 
VLIB_BUFFER_LOG2_TOTAL_LENGTH_VALID;

so as to set the flag in correct packets as early as possible.
This would be branchless code, but would cost a few cycles for every packet 
received by dpdk. Any thoughts?

Also, does anyone know if this can happen with other devices than dpdk?

Best,
Yoann

Reply via email to