<feed xmlns='http://www.w3.org/2005/Atom'>
<title>passt/vu_common.c, branch podman23739</title>
<subtitle>Plug A Simple Socket Transport</subtitle>
<link rel='alternate' type='text/html' href='https://passt.top/passt/'/>
<entry>
<title>vhost-user: Centralise Ethernet frame padding in vu_collect() and vu_pad()</title>
<updated>2026-05-19T23:21:55+00:00</updated>
<author>
<name>Laurent Vivier</name>
<email>lvivier@redhat.com</email>
</author>
<published>2026-05-13T11:52:18+00:00</published>
<link rel='alternate' type='text/html' href='https://passt.top/passt/commit/?id=db798fc60f4c5869cb53168354e068fb4dabd91a'/>
<id>db798fc60f4c5869cb53168354e068fb4dabd91a</id>
<content type='text'>
The previous per-protocol padding done by vu_pad() in tcp_vu.c and
udp_vu.c was only correct for single-buffer frames: it assumed the
padding area always fell within the first iov, writing past its end
with a plain memset().

It also required each caller to compute MAX(..., ETH_ZLEN + VNET_HLEN)
for vu_collect() and to call vu_pad() at the right point, duplicating
the minimum-size logic across protocols.

Move the Ethernet minimum size enforcement into vu_collect() itself, so
that enough buffer space is always reserved for padding regardless of
the requested frame size.

Rewrite vu_pad() to take a full iovec array and use iov_memset(),
making it safe for multi-buffer (mergeable rx buffer) frames.

In tcp_vu_sock_recv(), replace iov_truncate() with iov_skip_bytes():
now that all consumers receive explicit data lengths, truncating the
iovecs is no longer needed.  In tcp_vu_data_from_sock(), cap each
frame's data length against the remaining bytes actually received from
the socket, so that the last partial frame gets correct headers and
sequence number advancement.

Signed-off-by: Laurent Vivier &lt;lvivier@redhat.com&gt;
Reviewed-by: Jon Maloy &lt;jmaloy@redhat.com&gt;
Reviewed-by: David Gibson &lt;david@gibson.dropbear.id.au&gt;
Signed-off-by: Stefano Brivio &lt;sbrivio@redhat.com&gt;
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
The previous per-protocol padding done by vu_pad() in tcp_vu.c and
udp_vu.c was only correct for single-buffer frames: it assumed the
padding area always fell within the first iov, writing past its end
with a plain memset().

It also required each caller to compute MAX(..., ETH_ZLEN + VNET_HLEN)
for vu_collect() and to call vu_pad() at the right point, duplicating
the minimum-size logic across protocols.

Move the Ethernet minimum size enforcement into vu_collect() itself, so
that enough buffer space is always reserved for padding regardless of
the requested frame size.

Rewrite vu_pad() to take a full iovec array and use iov_memset(),
making it safe for multi-buffer (mergeable rx buffer) frames.

In tcp_vu_sock_recv(), replace iov_truncate() with iov_skip_bytes():
now that all consumers receive explicit data lengths, truncating the
iovecs is no longer needed.  In tcp_vu_data_from_sock(), cap each
frame's data length against the remaining bytes actually received from
the socket, so that the last partial frame gets correct headers and
sequence number advancement.

Signed-off-by: Laurent Vivier &lt;lvivier@redhat.com&gt;
Reviewed-by: Jon Maloy &lt;jmaloy@redhat.com&gt;
Reviewed-by: David Gibson &lt;david@gibson.dropbear.id.au&gt;
Signed-off-by: Stefano Brivio &lt;sbrivio@redhat.com&gt;
</pre>
</div>
</content>
</entry>
<entry>
<title>vu_common: Pass explicit frame length to vu_flush()</title>
<updated>2026-05-19T23:21:47+00:00</updated>
<author>
<name>Laurent Vivier</name>
<email>lvivier@redhat.com</email>
</author>
<published>2026-05-13T11:52:16+00:00</published>
<link rel='alternate' type='text/html' href='https://passt.top/passt/commit/?id=d83470f8b149c1108d884648d58fcdacd9ed781c'/>
<id>d83470f8b149c1108d884648d58fcdacd9ed781c</id>
<content type='text'>
Currently vu_flush() derives the frame size from the iov, but in
preparation for iov arrays that may be larger than the actual frame,
pass the total length (including vnet header) explicitly so that only
the relevant portion is reported to the virtqueue.

Ensure a minimum frame size of ETH_ZLEN + VNET_HLEN to handle short
frames. All elements are still flushed to avoid descriptor leaks,
but trailing elements beyond frame_len will report a zero length.

Signed-off-by: Laurent Vivier &lt;lvivier@redhat.com&gt;
Reviewed-by: David Gibson &lt;david@gibson.dropbear.id.au&gt;
Reviewed-by: Jon Maloy &lt;jmaloy@redhat.com&gt;
Signed-off-by: Stefano Brivio &lt;sbrivio@redhat.com&gt;
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
Currently vu_flush() derives the frame size from the iov, but in
preparation for iov arrays that may be larger than the actual frame,
pass the total length (including vnet header) explicitly so that only
the relevant portion is reported to the virtqueue.

Ensure a minimum frame size of ETH_ZLEN + VNET_HLEN to handle short
frames. All elements are still flushed to avoid descriptor leaks,
but trailing elements beyond frame_len will report a zero length.

Signed-off-by: Laurent Vivier &lt;lvivier@redhat.com&gt;
Reviewed-by: David Gibson &lt;david@gibson.dropbear.id.au&gt;
Reviewed-by: Jon Maloy &lt;jmaloy@redhat.com&gt;
Signed-off-by: Stefano Brivio &lt;sbrivio@redhat.com&gt;
</pre>
</div>
</content>
</entry>
<entry>
<title>pcap: Pass explicit L2 length to pcap_iov()</title>
<updated>2026-05-19T23:21:42+00:00</updated>
<author>
<name>Laurent Vivier</name>
<email>lvivier@redhat.com</email>
</author>
<published>2026-05-13T11:52:15+00:00</published>
<link rel='alternate' type='text/html' href='https://passt.top/passt/commit/?id=533ef11ecb4edd98c7adad3b51c40fdcc2f0671d'/>
<id>533ef11ecb4edd98c7adad3b51c40fdcc2f0671d</id>
<content type='text'>
With vhost-user multibuffer frames, the iov can be larger than the
actual L2 frame. The previous approach of computing L2 length as
iov_size() - offset would overcount and write extra bytes into the
pcap file.

Pass the L2 frame length explicitly to pcap_frame() and pcap_iov(),
and write exactly that many bytes instead of the full iov remainder.

Signed-off-by: Laurent Vivier &lt;lvivier@redhat.com&gt;
Reviewed-by: Jon Maloy &lt;jmaloy@redhat.com&gt;
Reviewed-by: David Gibson &lt;david@gibson.dropbear.id.au&gt;
Signed-off-by: Stefano Brivio &lt;sbrivio@redhat.com&gt;
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
With vhost-user multibuffer frames, the iov can be larger than the
actual L2 frame. The previous approach of computing L2 length as
iov_size() - offset would overcount and write extra bytes into the
pcap file.

Pass the L2 frame length explicitly to pcap_frame() and pcap_iov(),
and write exactly that many bytes instead of the full iov remainder.

Signed-off-by: Laurent Vivier &lt;lvivier@redhat.com&gt;
Reviewed-by: Jon Maloy &lt;jmaloy@redhat.com&gt;
Reviewed-by: David Gibson &lt;david@gibson.dropbear.id.au&gt;
Signed-off-by: Stefano Brivio &lt;sbrivio@redhat.com&gt;
</pre>
</div>
</content>
</entry>
<entry>
<title>vu_common: Move vnethdr setup into vu_flush()</title>
<updated>2026-05-19T23:21:19+00:00</updated>
<author>
<name>Laurent Vivier</name>
<email>lvivier@redhat.com</email>
</author>
<published>2026-05-13T11:52:11+00:00</published>
<link rel='alternate' type='text/html' href='https://passt.top/passt/commit/?id=d3a486858be2aa3e318047929e963cb4c02aa997'/>
<id>d3a486858be2aa3e318047929e963cb4c02aa997</id>
<content type='text'>
Every caller of vu_flush() was calling vu_set_vnethdr() beforehand with
the same pattern.  Move it into vu_flush().

Remove vu_queue_notify() from vu_flush() and let callers invoke it
explicitly.  This allows paths that perform multiple flushes, such as
tcp_vu_send_flag() and tcp_vu_data_from_sock(), to issue a single guest
notification at the end.

Signed-off-by: Laurent Vivier &lt;lvivier@redhat.com&gt;
Reviewed-by: David Gibson &lt;david@gibson.dropbear.id.au&gt;
Reviewed-by: Jon Maloy &lt;jmaloy@redhat.com&gt;
Signed-off-by: Stefano Brivio &lt;sbrivio@redhat.com&gt;
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
Every caller of vu_flush() was calling vu_set_vnethdr() beforehand with
the same pattern.  Move it into vu_flush().

Remove vu_queue_notify() from vu_flush() and let callers invoke it
explicitly.  This allows paths that perform multiple flushes, such as
tcp_vu_send_flag() and tcp_vu_data_from_sock(), to issue a single guest
notification at the end.

Signed-off-by: Laurent Vivier &lt;lvivier@redhat.com&gt;
Reviewed-by: David Gibson &lt;david@gibson.dropbear.id.au&gt;
Reviewed-by: Jon Maloy &lt;jmaloy@redhat.com&gt;
Signed-off-by: Stefano Brivio &lt;sbrivio@redhat.com&gt;
</pre>
</div>
</content>
</entry>
<entry>
<title>vhost_user: Fix assorted minor cppcheck warnings</title>
<updated>2026-03-28T13:35:39+00:00</updated>
<author>
<name>David Gibson</name>
<email>david@gibson.dropbear.id.au</email>
</author>
<published>2026-03-27T04:34:15+00:00</published>
<link rel='alternate' type='text/html' href='https://passt.top/passt/commit/?id=41b0c7bf3147bbc0640a1d64c3b492fe81d04ece'/>
<id>41b0c7bf3147bbc0640a1d64c3b492fe81d04ece</id>
<content type='text'>
This fixes a batch of minor incorrect format specifier and "could be const"
warnings in the vhost_user code.  For some very strange reason, cppcheck
doesn't catch these errors right now, but does after code rearrangements
we're making for the dynamic forwarding update stuff.

Signed-off-by: David Gibson &lt;david@gibson.dropbear.id.au&gt;
Signed-off-by: Stefano Brivio &lt;sbrivio@redhat.com&gt;
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
This fixes a batch of minor incorrect format specifier and "could be const"
warnings in the vhost_user code.  For some very strange reason, cppcheck
doesn't catch these errors right now, but does after code rearrangements
we're making for the dynamic forwarding update stuff.

Signed-off-by: David Gibson &lt;david@gibson.dropbear.id.au&gt;
Signed-off-by: Stefano Brivio &lt;sbrivio@redhat.com&gt;
</pre>
</div>
</content>
</entry>
<entry>
<title>treewide: Spell ASSERT() as assert()</title>
<updated>2026-03-20T20:05:29+00:00</updated>
<author>
<name>David Gibson</name>
<email>david@gibson.dropbear.id.au</email>
</author>
<published>2026-03-19T06:11:43+00:00</published>
<link rel='alternate' type='text/html' href='https://passt.top/passt/commit/?id=bc872d91765dfd6ff34b0e9a34bce410fac1cef3'/>
<id>bc872d91765dfd6ff34b0e9a34bce410fac1cef3</id>
<content type='text'>
The standard library assert(3), at least with glibc, hits our seccomp
filter and dies with SIGSYS before it's able to print a message, making it
near useless.  Therefore, since 7a8ed9459dfe ("Make assertions actually
useful") we've instead used our own implementation, named ASSERT().

This makes our code look slightly odd though - ASSERT() has the same
overall effect as assert(), it's just a different implementation.  More
importantly this makes it awkward to share code between passt/pasta proper
and things that compile in a more typical environment.  We're going to want
that for our upcoming dynamic configuration tool.

Address this by overriding the standard library's assert() implementation
with our own, instead of giving ours its own name.

The standard assert() is supposed to be omitted if NDEBUG is defined,
which ours doesn't do.  Implement that as well, so ours doesn't
unexpectedly differ.  For the -DNDEBUG case we do this by *not* overriding
assert(), since it will be a no-op anyway.  This requires a few places to
add a #include &lt;assert.h&gt; to let us compile (albeit with warnings) when
-DNDEBUG.

Signed-off-by: David Gibson &lt;david@gibson.dropbear.id.au&gt;
[sbrivio: Fix some conflicts and missing conversions as a result of
 applying "vu_common: Move iovec management into vu_collect()" first]
Signed-off-by: Stefano Brivio &lt;sbrivio@redhat.com&gt;
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
The standard library assert(3), at least with glibc, hits our seccomp
filter and dies with SIGSYS before it's able to print a message, making it
near useless.  Therefore, since 7a8ed9459dfe ("Make assertions actually
useful") we've instead used our own implementation, named ASSERT().

This makes our code look slightly odd though - ASSERT() has the same
overall effect as assert(), it's just a different implementation.  More
importantly this makes it awkward to share code between passt/pasta proper
and things that compile in a more typical environment.  We're going to want
that for our upcoming dynamic configuration tool.

Address this by overriding the standard library's assert() implementation
with our own, instead of giving ours its own name.

The standard assert() is supposed to be omitted if NDEBUG is defined,
which ours doesn't do.  Implement that as well, so ours doesn't
unexpectedly differ.  For the -DNDEBUG case we do this by *not* overriding
assert(), since it will be a no-op anyway.  This requires a few places to
add a #include &lt;assert.h&gt; to let us compile (albeit with warnings) when
-DNDEBUG.

Signed-off-by: David Gibson &lt;david@gibson.dropbear.id.au&gt;
[sbrivio: Fix some conflicts and missing conversions as a result of
 applying "vu_common: Move iovec management into vu_collect()" first]
Signed-off-by: Stefano Brivio &lt;sbrivio@redhat.com&gt;
</pre>
</div>
</content>
</entry>
<entry>
<title>vu_common: Move iovec management into vu_collect()</title>
<updated>2026-03-20T19:05:34+00:00</updated>
<author>
<name>Laurent Vivier</name>
<email>lvivier@redhat.com</email>
</author>
<published>2026-03-18T09:19:41+00:00</published>
<link rel='alternate' type='text/html' href='https://passt.top/passt/commit/?id=451fb7600b8dfdf6800abee613f2b4f026fbd150'/>
<id>451fb7600b8dfdf6800abee613f2b4f026fbd150</id>
<content type='text'>
Previously, callers had to pre-initialize virtqueue elements with iovec
entries using vu_set_element() or vu_init_elem() before calling
vu_collect().  This meant each element owned a fixed, pre-assigned iovec
slot.

Move the iovec array into vu_collect() as explicit parameters (in_sg,
max_in_sg, and in_total), letting it pass the remaining iovec capacity
directly to vu_queue_pop().  A running current_iov counter tracks
consumed entries across elements, so multiple elements share a single
iovec pool.  The optional in_total output parameter reports how many iovec
entries were consumed, allowing callers to track usage across multiple
vu_collect() calls.

This removes vu_set_element() and vu_init_elem() which are no longer
needed, and is a prerequisite for multi-buffer support where a single
virtqueue element can use more than one iovec entry.  For now, callers
assert the current single-iovec-per-element invariant until they are
updated to handle multiple iovecs.

Signed-off-by: Laurent Vivier &lt;lvivier@redhat.com&gt;
Reviewed-by: David Gibson &lt;david@gibson.dropbear.id.au&gt;
Signed-off-by: Stefano Brivio &lt;sbrivio@redhat.com&gt;
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
Previously, callers had to pre-initialize virtqueue elements with iovec
entries using vu_set_element() or vu_init_elem() before calling
vu_collect().  This meant each element owned a fixed, pre-assigned iovec
slot.

Move the iovec array into vu_collect() as explicit parameters (in_sg,
max_in_sg, and in_total), letting it pass the remaining iovec capacity
directly to vu_queue_pop().  A running current_iov counter tracks
consumed entries across elements, so multiple elements share a single
iovec pool.  The optional in_total output parameter reports how many iovec
entries were consumed, allowing callers to track usage across multiple
vu_collect() calls.

This removes vu_set_element() and vu_init_elem() which are no longer
needed, and is a prerequisite for multi-buffer support where a single
virtqueue element can use more than one iovec entry.  For now, callers
assert the current single-iovec-per-element invariant until they are
updated to handle multiple iovecs.

Signed-off-by: Laurent Vivier &lt;lvivier@redhat.com&gt;
Reviewed-by: David Gibson &lt;david@gibson.dropbear.id.au&gt;
Signed-off-by: Stefano Brivio &lt;sbrivio@redhat.com&gt;
</pre>
</div>
</content>
</entry>
<entry>
<title>vu_handle_tx: Pass actual remaining out_sg capacity to vu_queue_pop()</title>
<updated>2026-03-20T19:05:26+00:00</updated>
<author>
<name>Laurent Vivier</name>
<email>lvivier@redhat.com</email>
</author>
<published>2026-03-18T09:19:40+00:00</published>
<link rel='alternate' type='text/html' href='https://passt.top/passt/commit/?id=f5391ae1b72680718e90b5ff6d83feec13f55366'/>
<id>f5391ae1b72680718e90b5ff6d83feec13f55366</id>
<content type='text'>
In vu_handle_tx(), pass the actual remaining iovec capacity
(ARRAY_SIZE(out_sg) - out_sg_count) to vu_queue_pop() rather than a
fixed VU_MAX_TX_BUFFER_NB.

This enables dynamic allocation of iovec entries to each element rather
than reserving a fixed number of slots per descriptor.

Signed-off-by: Laurent Vivier &lt;lvivier@redhat.com&gt;
Reviewed-by: David Gibson &lt;david@gibson.dropbear.id.au&gt;
Signed-off-by: Stefano Brivio &lt;sbrivio@redhat.com&gt;
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
In vu_handle_tx(), pass the actual remaining iovec capacity
(ARRAY_SIZE(out_sg) - out_sg_count) to vu_queue_pop() rather than a
fixed VU_MAX_TX_BUFFER_NB.

This enables dynamic allocation of iovec entries to each element rather
than reserving a fixed number of slots per descriptor.

Signed-off-by: Laurent Vivier &lt;lvivier@redhat.com&gt;
Reviewed-by: David Gibson &lt;david@gibson.dropbear.id.au&gt;
Signed-off-by: Stefano Brivio &lt;sbrivio@redhat.com&gt;
</pre>
</div>
</content>
</entry>
<entry>
<title>virtio: Pass iovec arrays as separate parameters to vu_queue_pop()</title>
<updated>2026-03-20T19:05:12+00:00</updated>
<author>
<name>Laurent Vivier</name>
<email>lvivier@redhat.com</email>
</author>
<published>2026-03-18T09:19:39+00:00</published>
<link rel='alternate' type='text/html' href='https://passt.top/passt/commit/?id=b9d076d8af993359ec7cd2eb97572c1fe0675089'/>
<id>b9d076d8af993359ec7cd2eb97572c1fe0675089</id>
<content type='text'>
Currently vu_queue_pop() and vu_queue_map_desc() read the iovec arrays
(in_sg/out_sg) and their sizes (in_num/out_num) from the vu_virtq_element
struct.  This couples the iovec storage to the element, requiring callers
like vu_handle_tx() to pre-initialize the element fields before calling
vu_queue_pop().

Pass the iovec arrays and their maximum sizes as separate parameters
instead.  vu_queue_map_desc() now writes the actual descriptor count
and iovec pointers back into the element after mapping, rather than
using the element as both input and output.

This decouples the iovec storage from the element, which is a
prerequisite for multi-buffer support where a single frame can span
multiple virtqueue elements sharing a common iovec pool.

No functional change.

Signed-off-by: Laurent Vivier &lt;lvivier@redhat.com&gt;
Reviewed-by: David Gibson &lt;david@gibson.dropbear.id.au&gt;
Signed-off-by: Stefano Brivio &lt;sbrivio@redhat.com&gt;
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
Currently vu_queue_pop() and vu_queue_map_desc() read the iovec arrays
(in_sg/out_sg) and their sizes (in_num/out_num) from the vu_virtq_element
struct.  This couples the iovec storage to the element, requiring callers
like vu_handle_tx() to pre-initialize the element fields before calling
vu_queue_pop().

Pass the iovec arrays and their maximum sizes as separate parameters
instead.  vu_queue_map_desc() now writes the actual descriptor count
and iovec pointers back into the element after mapping, rather than
using the element as both input and output.

This decouples the iovec storage from the element, which is a
prerequisite for multi-buffer support where a single frame can span
multiple virtqueue elements sharing a common iovec pool.

No functional change.

Signed-off-by: Laurent Vivier &lt;lvivier@redhat.com&gt;
Reviewed-by: David Gibson &lt;david@gibson.dropbear.id.au&gt;
Signed-off-by: Stefano Brivio &lt;sbrivio@redhat.com&gt;
</pre>
</div>
</content>
</entry>
<entry>
<title>vu_common: Always set num_buffers in virtio-net header</title>
<updated>2026-03-04T17:50:49+00:00</updated>
<author>
<name>Laurent Vivier</name>
<email>lvivier@redhat.com</email>
</author>
<published>2026-03-03T15:17:34+00:00</published>
<link rel='alternate' type='text/html' href='https://passt.top/passt/commit/?id=71a0d6cbbb0f0c936130e28dd33d48a16894491b'/>
<id>71a0d6cbbb0f0c936130e28dd33d48a16894491b</id>
<content type='text'>
Legacy virtio used two different header formats: struct virtio_net_hdr
(10 bytes) when VIRTIO_NET_F_MRG_RXBUF was not negotiated, and
struct virtio_net_hdr_mrg_rxbuf (12 bytes) when it was.  The
num_buffers field only existed in the larger header.

Modern virtio (VIRTIO_F_VERSION_1, i.e. virtio 1.0+) always uses the
12-byte struct virtio_net_hdr_mrg_rxbuf header regardless of whether
VIRTIO_NET_F_MRG_RXBUF is negotiated, so num_buffers is always present
in the header.  passt only supports modern virtio and dies if
VIRTIO_F_VERSION_1 is not negotiated (vhost_user.c), and VNET_HLEN is
unconditionally defined as sizeof(struct virtio_net_hdr_mrg_rxbuf).

The virtio specification (v1.1, section 5.1.6) requires that:

  "The device MUST set num_buffers to 1 if VIRTIO_NET_F_MRG_RXBUF has
   not been negotiated."

vu_set_vnethdr() only set num_buffers when VIRTIO_NET_F_MRG_RXBUF was
negotiated.  When it was not, num_buffers was left uninitialised,
violating the spec.

Since vu_collect() already limits buffer collection to a single element
when VIRTIO_NET_F_MRG_RXBUF is not negotiated, num_buffers passed by
callers is guaranteed to be 1 in that case.  We can therefore
unconditionally set num_buffers, which makes the vdev parameter
unnecessary.

Drop the vdev parameter from vu_set_vnethdr() and update all callers.

Signed-off-by: Laurent Vivier &lt;lvivier@redhat.com&gt;
Reviewed-by: David Gibson &lt;david@gibson.dropbear.id.au&gt;
Signed-off-by: Stefano Brivio &lt;sbrivio@redhat.com&gt;
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
Legacy virtio used two different header formats: struct virtio_net_hdr
(10 bytes) when VIRTIO_NET_F_MRG_RXBUF was not negotiated, and
struct virtio_net_hdr_mrg_rxbuf (12 bytes) when it was.  The
num_buffers field only existed in the larger header.

Modern virtio (VIRTIO_F_VERSION_1, i.e. virtio 1.0+) always uses the
12-byte struct virtio_net_hdr_mrg_rxbuf header regardless of whether
VIRTIO_NET_F_MRG_RXBUF is negotiated, so num_buffers is always present
in the header.  passt only supports modern virtio and dies if
VIRTIO_F_VERSION_1 is not negotiated (vhost_user.c), and VNET_HLEN is
unconditionally defined as sizeof(struct virtio_net_hdr_mrg_rxbuf).

The virtio specification (v1.1, section 5.1.6) requires that:

  "The device MUST set num_buffers to 1 if VIRTIO_NET_F_MRG_RXBUF has
   not been negotiated."

vu_set_vnethdr() only set num_buffers when VIRTIO_NET_F_MRG_RXBUF was
negotiated.  When it was not, num_buffers was left uninitialised,
violating the spec.

Since vu_collect() already limits buffer collection to a single element
when VIRTIO_NET_F_MRG_RXBUF is not negotiated, num_buffers passed by
callers is guaranteed to be 1 in that case.  We can therefore
unconditionally set num_buffers, which makes the vdev parameter
unnecessary.

Drop the vdev parameter from vu_set_vnethdr() and update all callers.

Signed-off-by: Laurent Vivier &lt;lvivier@redhat.com&gt;
Reviewed-by: David Gibson &lt;david@gibson.dropbear.id.au&gt;
Signed-off-by: Stefano Brivio &lt;sbrivio@redhat.com&gt;
</pre>
</div>
</content>
</entry>
</feed>
