<feed xmlns='http://www.w3.org/2005/Atom'>
<title>passt/flow_table.h, branch 2026_05_07.1afd4ed</title>
<subtitle>Plug A Simple Socket Transport</subtitle>
<link rel='alternate' type='text/html' href='https://passt.top/passt/'/>
<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>Add missing includes to headers</title>
<updated>2026-03-04T16:39:57+00:00</updated>
<author>
<name>Peter Foley</name>
<email>pefoley@google.com</email>
</author>
<published>2026-02-23T18:11:19+00:00</published>
<link rel='alternate' type='text/html' href='https://passt.top/passt/commit/?id=adbf5c135f19db5b6751393b7f5cbf516031bde8'/>
<id>adbf5c135f19db5b6751393b7f5cbf516031bde8</id>
<content type='text'>
Support build systems like bazel that check that headers are
self-contained.

Also update includes so that clang-include-cleaner succeeds.

Tested with:
clang-include-cleaner-19 --extra-arg=-D_GNU_SOURCE --extra-arg=-DPAGE_SIZE=4096 --extra-arg=-DVERSION=\"git\" --extra-arg=-DHAS_GETRANDOM *.h *.c

Signed-off-by: Peter Foley &lt;pefoley@google.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>
Support build systems like bazel that check that headers are
self-contained.

Also update includes so that clang-include-cleaner succeeds.

Tested with:
clang-include-cleaner-19 --extra-arg=-D_GNU_SOURCE --extra-arg=-DPAGE_SIZE=4096 --extra-arg=-DVERSION=\"git\" --extra-arg=-DHAS_GETRANDOM *.h *.c

Signed-off-by: Peter Foley &lt;pefoley@google.com&gt;
Signed-off-by: Stefano Brivio &lt;sbrivio@redhat.com&gt;
</pre>
</div>
</content>
</entry>
<entry>
<title>flow, fwd: Optimise forwarding rule lookup using epoll ref when possible</title>
<updated>2026-01-18T11:48:09+00:00</updated>
<author>
<name>David Gibson</name>
<email>david@gibson.dropbear.id.au</email>
</author>
<published>2026-01-16T00:59:26+00:00</published>
<link rel='alternate' type='text/html' href='https://passt.top/passt/commit/?id=4a0d507296ef8c1349669e95fd672539734d9a6c'/>
<id>4a0d507296ef8c1349669e95fd672539734d9a6c</id>
<content type='text'>
Now that listening sockets include a reference to the forwarding rule
which created them we can, in many cases, avoid a linear search of the
forwarding table when we want to find the relevant rule.  Instead we
can take the rule index from the socket's epoll reference, and use
that to immediately find the correct rule.

This is conceptually simple, but requires a moderate amount of
plumbing to get the index from the reference through to the rule
lookup.  We still allow fall back to linear search if we don't have
the index, and this may (rarely) be used in the udp_flush_flow() case,
where we could get packets for one flow on a different flow's socket,
rather than through a listening socket as usual.

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>
Now that listening sockets include a reference to the forwarding rule
which created them we can, in many cases, avoid a linear search of the
forwarding table when we want to find the relevant rule.  Instead we
can take the rule index from the socket's epoll reference, and use
that to immediately find the correct rule.

This is conceptually simple, but requires a moderate amount of
plumbing to get the index from the reference through to the rule
lookup.  We still allow fall back to linear search if we don't have
the index, and this may (rarely) be used in the udp_flush_flow() case,
where we could get packets for one flow on a different flow's socket,
rather than through a listening socket as usual.

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>style: Fix 'Return' comment style</title>
<updated>2025-07-18T17:19:24+00:00</updated>
<author>
<name>Laurent Vivier</name>
<email>lvivier@redhat.com</email>
</author>
<published>2025-06-20T09:36:41+00:00</published>
<link rel='alternate' type='text/html' href='https://passt.top/passt/commit/?id=9e0423e13541e8da657f46dff71e841f40ee7391'/>
<id>9e0423e13541e8da657f46dff71e841f40ee7391</id>
<content type='text'>
We always use imperative (no 'Returns:'), no tab after the ':' and
only one space, the first character is always lowercase.

This is fixed with:

 sed -i "s/Returns:/Return:/;s/Return:    /Return: /;s/Return:  */Return: /;s/Return: \([A-Z]\)/Return: \L\1/" *.[ch]

And manually updated to fix alignment of multiline comment and words
that must keep uppercase (like IPv4, TCP, UDP, Layer-4).

Signed-off-by: Laurent Vivier &lt;lvivier@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>
We always use imperative (no 'Returns:'), no tab after the ':' and
only one space, the first character is always lowercase.

This is fixed with:

 sed -i "s/Returns:/Return:/;s/Return:    /Return: /;s/Return:  */Return: /;s/Return: \([A-Z]\)/Return: \L\1/" *.[ch]

And manually updated to fix alignment of multiline comment and words
that must keep uppercase (like IPv4, TCP, UDP, Layer-4).

Signed-off-by: Laurent Vivier &lt;lvivier@redhat.com&gt;
Signed-off-by: Stefano Brivio &lt;sbrivio@redhat.com&gt;
</pre>
</div>
</content>
</entry>
<entry>
<title>flow: Fix clang error (clang-analyzer-security.PointerSub)</title>
<updated>2025-05-14T15:51:37+00:00</updated>
<author>
<name>Laurent Vivier</name>
<email>lvivier@redhat.com</email>
</author>
<published>2025-05-13T09:41:02+00:00</published>
<link rel='alternate' type='text/html' href='https://passt.top/passt/commit/?id=2d3d69c5c348d18112596bd3fdeed95689c613c8'/>
<id>2d3d69c5c348d18112596bd3fdeed95689c613c8</id>
<content type='text'>
Fixes the following clang-analyzer warning:

flow_table.h:96:25: note: Subtraction of two pointers that do not point into the same array is undefined behavior
   96 |         return (union flow *)f - flowtab;

The `flow_idx()` function is called via `FLOW_IDX()` from
`flow_foreach_slot()`, where `f` is set to `&amp;flowtab[idx].f`.
Therefore, `f` and `flowtab` do point to the same array.

Signed-off-by: Laurent Vivier &lt;lvivier@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>
Fixes the following clang-analyzer warning:

flow_table.h:96:25: note: Subtraction of two pointers that do not point into the same array is undefined behavior
   96 |         return (union flow *)f - flowtab;

The `flow_idx()` function is called via `FLOW_IDX()` from
`flow_foreach_slot()`, where `f` is set to `&amp;flowtab[idx].f`.
Therefore, `f` and `flowtab` do point to the same array.

Signed-off-by: Laurent Vivier &lt;lvivier@redhat.com&gt;
Signed-off-by: Stefano Brivio &lt;sbrivio@redhat.com&gt;
</pre>
</div>
</content>
</entry>
<entry>
<title>udp, udp_flow: Track our specific address on socket interfaces</title>
<updated>2025-04-10T17:46:16+00:00</updated>
<author>
<name>David Gibson</name>
<email>david@gibson.dropbear.id.au</email>
</author>
<published>2025-04-10T07:16:40+00:00</published>
<link rel='alternate' type='text/html' href='https://passt.top/passt/commit/?id=59cc89f4cc018988428637d97745cc4c919126cb'/>
<id>59cc89f4cc018988428637d97745cc4c919126cb</id>
<content type='text'>
So far for UDP flows (like TCP connections) we didn't record our address
(oaddr) in the flow table entry for socket based pifs.  That's because we
didn't have that information when a flow was initiated by a datagram coming
to a "listening" socket with 0.0.0.0 or :: address.  Even when we did have
the information, we didn't record it, to simplify address matching on
lookups.

This meant that in some circumstances we could send replies on a UDP flow
from a different address than the originating request came to, which is
surprising and breaks certain setups.

We now have code in udp_peek_addr() which does determine our address for
incoming UDP datagrams.  We can use that information to properly populate
oaddr in the flow table for flow initiated from a socket.

In order to be able to consistently match datagrams to flows, we must
*always* have a specific oaddr, not an unspecified address (that's how the
flow hash table works).  So, we also need to fill in oaddr correctly for
flows we initiate *to* sockets.  Our forwarding logic doesn't specify
oaddr here, letting the kernel decide based on the routing table.  In this
case we need to call getsockname() after connect()ing the socket to find
which local address the kernel picked.

This adds getsockname() to our seccomp profile for all variants.

Link: https://bugs.passt.top/show_bug.cgi?id=99
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>
So far for UDP flows (like TCP connections) we didn't record our address
(oaddr) in the flow table entry for socket based pifs.  That's because we
didn't have that information when a flow was initiated by a datagram coming
to a "listening" socket with 0.0.0.0 or :: address.  Even when we did have
the information, we didn't record it, to simplify address matching on
lookups.

This meant that in some circumstances we could send replies on a UDP flow
from a different address than the originating request came to, which is
surprising and breaks certain setups.

We now have code in udp_peek_addr() which does determine our address for
incoming UDP datagrams.  We can use that information to properly populate
oaddr in the flow table for flow initiated from a socket.

In order to be able to consistently match datagrams to flows, we must
*always* have a specific oaddr, not an unspecified address (that's how the
flow hash table works).  So, we also need to fill in oaddr correctly for
flows we initiate *to* sockets.  Our forwarding logic doesn't specify
oaddr here, letting the kernel decide based on the routing table.  In this
case we need to call getsockname() after connect()ing the socket to find
which local address the kernel picked.

This adds getsockname() to our seccomp profile for all variants.

Link: https://bugs.passt.top/show_bug.cgi?id=99
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>flow: Clean up and generalise flow traversal macros</title>
<updated>2025-02-19T05:35:36+00:00</updated>
<author>
<name>David Gibson</name>
<email>david@gibson.dropbear.id.au</email>
</author>
<published>2025-02-19T02:28:36+00:00</published>
<link rel='alternate' type='text/html' href='https://passt.top/passt/commit/?id=65e317a8fca4eaf9efbfe642cc7e4322c56aa1f7'/>
<id>65e317a8fca4eaf9efbfe642cc7e4322c56aa1f7</id>
<content type='text'>
The migration code introduced a number of 'foreach' macros to traverse the
flow table.  These aren't inherently tied to migration, so polish up their
naming, move them to flow_table.h and also use in flow_defer_handler()
which is the other place we need to traverse the whole table.

For now we keep foreach_established_tcp_flow() as is.

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>
The migration code introduced a number of 'foreach' macros to traverse the
flow table.  These aren't inherently tied to migration, so polish up their
naming, move them to flow_table.h and also use in flow_defer_handler()
which is the other place we need to traverse the whole table.

For now we keep foreach_established_tcp_flow() as is.

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>tcp: Get bound address for connected inbound sockets too</title>
<updated>2025-02-12T18:48:00+00:00</updated>
<author>
<name>Stefano Brivio</name>
<email>sbrivio@redhat.com</email>
</author>
<published>2025-02-12T07:07:17+00:00</published>
<link rel='alternate' type='text/html' href='https://passt.top/passt/commit/?id=6f122f0171fe4bc235d572945e0bf963e81139ea'/>
<id>6f122f0171fe4bc235d572945e0bf963e81139ea</id>
<content type='text'>
So that we can bind inbound sockets to specific addresses, like we
already do for outbound sockets.

While at it, change the error message in tcp_conn_from_tap() to match
this one.

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>
So that we can bind inbound sockets to specific addresses, like we
already do for outbound sockets.

While at it, change the error message in tcp_conn_from_tap() to match
this one.

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>tcp: Get socket port and address using getsockname() when connecting from guest</title>
<updated>2025-02-04T00:28:04+00:00</updated>
<author>
<name>Stefano Brivio</name>
<email>sbrivio@redhat.com</email>
</author>
<published>2025-01-31T17:27:07+00:00</published>
<link rel='alternate' type='text/html' href='https://passt.top/passt/commit/?id=52e57f9c9a6d8ae4153ac592d01d868b31c10171'/>
<id>52e57f9c9a6d8ae4153ac592d01d868b31c10171</id>
<content type='text'>
For migration only: we need to store 'oport', our socket-side port,
as we establish a connection from the guest, so that we can bind the
same oport as source port in the migration target.

Similar for 'oaddr': this is needed in case the migration target has
additional network interfaces, and we need to make sure our socket is
bound to the equivalent interface as it was on the source.

Use getsockname() to fetch them.

Signed-off-by: Stefano Brivio &lt;sbrivio@redhat.com&gt;
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
For migration only: we need to store 'oport', our socket-side port,
as we establish a connection from the guest, so that we can bind the
same oport as source port in the migration target.

Similar for 'oaddr': this is needed in case the migration target has
additional network interfaces, and we need to make sure our socket is
bound to the equivalent interface as it was on the source.

Use getsockname() to fetch them.

Signed-off-by: Stefano Brivio &lt;sbrivio@redhat.com&gt;
</pre>
</div>
</content>
</entry>
<entry>
<title>flow: Correct type of flowside_at_sidx()</title>
<updated>2024-11-07T11:46:44+00:00</updated>
<author>
<name>David Gibson</name>
<email>david@gibson.dropbear.id.au</email>
</author>
<published>2024-11-05T23:25:21+00:00</published>
<link rel='alternate' type='text/html' href='https://passt.top/passt/commit/?id=f6b546c6e4f036bc569df05cf76eced3f68d6db8'/>
<id>f6b546c6e4f036bc569df05cf76eced3f68d6db8</id>
<content type='text'>
Due to a copy-pasta error, this returns 'PIF_NONE' instead of NULL on the
failure case.  PIF_NONE expands to 0, which turns into NULL, but it's
still confusing, so fix it.  This removes a clang warning.

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>
Due to a copy-pasta error, this returns 'PIF_NONE' instead of NULL on the
failure case.  PIF_NONE expands to 0, which turns into NULL, but it's
still confusing, so fix it.  This removes a clang warning.

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>
</feed>
