<feed xmlns='http://www.w3.org/2005/Atom'>
<title>passt, branch 2026_01_17.81c97f6</title>
<subtitle>Plug A Simple Socket Transport</subtitle>
<link rel='alternate' type='text/html' href='https://passt.top/passt/'/>
<entry>
<title>hooks/pre-push: Use mandoc(1) to get HTML anchors to command-line options</title>
<updated>2026-01-17T14:36:02+00:00</updated>
<author>
<name>Stefano Brivio</name>
<email>sbrivio@redhat.com</email>
</author>
<published>2026-01-17T14:36:02+00:00</published>
<link rel='alternate' type='text/html' href='https://passt.top/passt/commit/?id=81c97f66595f4fab5171ebcb42f43e9f1505b4c4'/>
<id>81c97f66595f4fab5171ebcb42f43e9f1505b4c4</id>
<content type='text'>
It looks like man2html(1) can only build links to sections, not to
TP elements.

Reported-by: Erik Sjölund &lt;erik.sjolund@gmail.com&gt;
Link: https://bugs.passt.top/show_bug.cgi?id=184
Signed-off-by: Stefano Brivio &lt;sbrivio@redhat.com&gt;
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
It looks like man2html(1) can only build links to sections, not to
TP elements.

Reported-by: Erik Sjölund &lt;erik.sjolund@gmail.com&gt;
Link: https://bugs.passt.top/show_bug.cgi?id=184
Signed-off-by: Stefano Brivio &lt;sbrivio@redhat.com&gt;
</pre>
</div>
</content>
</entry>
<entry>
<title>selinux: Enable open permissions on netns directory, operations on container_var_run_t</title>
<updated>2026-01-16T16:22:44+00:00</updated>
<author>
<name>Stefano Brivio</name>
<email>sbrivio@redhat.com</email>
</author>
<published>2026-01-16T15:48:46+00:00</published>
<link rel='alternate' type='text/html' href='https://passt.top/passt/commit/?id=a6d92ca82c9ea0b395aa56c568ee6b6e6d4ac81e'/>
<id>a6d92ca82c9ea0b395aa56c568ee6b6e6d4ac81e</id>
<content type='text'>
Tuomo reports two further SELinux denials after upgrading to a
passt-selinux version that includes the transition to pasta_t for
containers, one I could reproduce:

  denied  { open } for  pid=3343050 comm="pasta.avx2" path="/run/user/1000/netns" dev="tmpfs" ino=51 scontext=unconfined_u:unconfined_r:pasta_t:s0-s0:c0.c1023 tcontext=unconfined_u:object_r:user_tmp_t:s0 tclass=dir permissive=1

which I didn't take care of in the previous commit, d2c5133990a7
("selinux: Enable read and watch permissions on netns directory as
well"), as it didn't appear in my quick test. But I can make pasta use
"open" on the network namespace entry by simply using it to make
connections.

So, for that, add "open" to the existing rule for user_tmp_t:dir.

Then, another one I couldn't reproduce instead:

  denied  { write } for  pid=3589324 comm="pasta.avx2" name="rootless-netns" dev="tmpfs" ino=36 scontext=unconfined_u:unconfined_r:pasta_t:s0-s0:c0.c1023 tcontext=unconfined_u:object_r:container_var_run_t:s0 tclass=dir permissive=0

which, I think, comes from a specific combination of versions of
container-selinux, Podman, and passt-selinux packages, which
prevents the expected type transition on container_var_run_t unless
restorecon is invoked manually, or until a reboot.

Allowing the same permissions on container_var_run_t as we do on
ifconfig_var_run_t is harmless, so do that to prevent this further
denial.

Reported-by: Tuomo Soini &lt;tis@foobar.fi&gt;
Fixes: d2c5133990a7 ("selinux: Enable read and watch permissions on netns directory as well")
Fixes: 7aeda16a7818 ("selinux: Transition to pasta_t in containers")
Signed-off-by: Stefano Brivio &lt;sbrivio@redhat.com&gt;
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
Tuomo reports two further SELinux denials after upgrading to a
passt-selinux version that includes the transition to pasta_t for
containers, one I could reproduce:

  denied  { open } for  pid=3343050 comm="pasta.avx2" path="/run/user/1000/netns" dev="tmpfs" ino=51 scontext=unconfined_u:unconfined_r:pasta_t:s0-s0:c0.c1023 tcontext=unconfined_u:object_r:user_tmp_t:s0 tclass=dir permissive=1

which I didn't take care of in the previous commit, d2c5133990a7
("selinux: Enable read and watch permissions on netns directory as
well"), as it didn't appear in my quick test. But I can make pasta use
"open" on the network namespace entry by simply using it to make
connections.

So, for that, add "open" to the existing rule for user_tmp_t:dir.

Then, another one I couldn't reproduce instead:

  denied  { write } for  pid=3589324 comm="pasta.avx2" name="rootless-netns" dev="tmpfs" ino=36 scontext=unconfined_u:unconfined_r:pasta_t:s0-s0:c0.c1023 tcontext=unconfined_u:object_r:container_var_run_t:s0 tclass=dir permissive=0

which, I think, comes from a specific combination of versions of
container-selinux, Podman, and passt-selinux packages, which
prevents the expected type transition on container_var_run_t unless
restorecon is invoked manually, or until a reboot.

Allowing the same permissions on container_var_run_t as we do on
ifconfig_var_run_t is harmless, so do that to prevent this further
denial.

Reported-by: Tuomo Soini &lt;tis@foobar.fi&gt;
Fixes: d2c5133990a7 ("selinux: Enable read and watch permissions on netns directory as well")
Fixes: 7aeda16a7818 ("selinux: Transition to pasta_t in containers")
Signed-off-by: Stefano Brivio &lt;sbrivio@redhat.com&gt;
</pre>
</div>
</content>
</entry>
<entry>
<title>igmp: Remove apparently unneeded suppression</title>
<updated>2026-01-14T00:07:51+00:00</updated>
<author>
<name>David Gibson</name>
<email>david@gibson.dropbear.id.au</email>
</author>
<published>2026-01-13T03:54:15+00:00</published>
<link rel='alternate' type='text/html' href='https://passt.top/passt/commit/?id=4296a59034b0ebe805221d02554477b899ac9fb3'/>
<id>4296a59034b0ebe805221d02554477b899ac9fb3</id>
<content type='text'>
cppcheck-2.19.1 complains that the unusedFunction suppression in igmp.c
doesn't match.  That seems like a cppcheck bug, because the function
clearly *is* unused.  The function exists because otherwise the compiler
fails because "ISO C forbids an empty translation unit".

mld.c contains an identical unused definition for the same reason, but
without the suppression.  It doesn't seem to have caused unusedFunction
warnings,  so maybe cppcheck counts the non-empty translation unit
requirement as a "use" of the function?

In any case, since omitting the suppression in mld.c seems to be fine, do
the same in igmp.c to stop the complaints.

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>
cppcheck-2.19.1 complains that the unusedFunction suppression in igmp.c
doesn't match.  That seems like a cppcheck bug, because the function
clearly *is* unused.  The function exists because otherwise the compiler
fails because "ISO C forbids an empty translation unit".

mld.c contains an identical unused definition for the same reason, but
without the suppression.  It doesn't seem to have caused unusedFunction
warnings,  so maybe cppcheck counts the non-empty translation unit
requirement as a "use" of the function?

In any case, since omitting the suppression in mld.c seems to be fine, do
the same in igmp.c to stop the complaints.

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>epoll_ctl: Move u64 variant first for safer initialisation</title>
<updated>2026-01-14T00:07:51+00:00</updated>
<author>
<name>David Gibson</name>
<email>david@gibson.dropbear.id.au</email>
</author>
<published>2026-01-13T03:54:14+00:00</published>
<link rel='alternate' type='text/html' href='https://passt.top/passt/commit/?id=fa765d54b048127c77e0699843f4008b026a0e9f'/>
<id>fa765d54b048127c77e0699843f4008b026a0e9f</id>
<content type='text'>
cppcheck-2.19.1 pointed out that an initialiser like:
	union epoll_ref foo = { 0 };
doesn't necessarily zero the whole union, because the first variant listed
may not be the full length.  I don't think this is actually broken in
practice, but I'm not 100% certain about that.

In any case, make it more clearly correct, and stop cppcheck complaining
by moving the @u64 variant to be the first one.

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>
cppcheck-2.19.1 pointed out that an initialiser like:
	union epoll_ref foo = { 0 };
doesn't necessarily zero the whole union, because the first variant listed
may not be the full length.  I don't think this is actually broken in
practice, but I'm not 100% certain about that.

In any case, make it more clearly correct, and stop cppcheck complaining
by moving the @u64 variant to be the first one.

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: Fix more pointers which can be const</title>
<updated>2026-01-14T00:07:51+00:00</updated>
<author>
<name>David Gibson</name>
<email>david@gibson.dropbear.id.au</email>
</author>
<published>2026-01-13T03:54:13+00:00</published>
<link rel='alternate' type='text/html' href='https://passt.top/passt/commit/?id=4af3d83170fd227b177f9861d93391e3d2008d34'/>
<id>4af3d83170fd227b177f9861d93391e3d2008d34</id>
<content type='text'>
Here are some more pointers which can be const, as reported by cppcheck
2.19.1.

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>
Here are some more pointers which can be const, as reported by cppcheck
2.19.1.

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, udp: Make {tcp,udp}_listen() return socket fds</title>
<updated>2026-01-14T00:07:51+00:00</updated>
<author>
<name>David Gibson</name>
<email>david@gibson.dropbear.id.au</email>
</author>
<published>2026-01-13T03:06:14+00:00</published>
<link rel='alternate' type='text/html' href='https://passt.top/passt/commit/?id=a54274d28ba21e09909cc012315ffa078ef41fd8'/>
<id>a54274d28ba21e09909cc012315ffa078ef41fd8</id>
<content type='text'>
{tcp,udp}_listen() currently return 0 on success, rather than the socket
fd they created.  Historically, that was because these functions could
sometimes create multiple sockets.  We've now refactored things to avoid
that, so it makes more sense for them to return the socket on success.

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>
{tcp,udp}_listen() currently return 0 on success, rather than the socket
fd they created.  Historically, that was because these functions could
sometimes create multiple sockets.  We've now refactored things to avoid
that, so it makes more sense for them to return the socket on success.

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, udp, conf: Don't silently ignore listens on unsupported IP versions</title>
<updated>2026-01-14T00:07:51+00:00</updated>
<author>
<name>David Gibson</name>
<email>david@gibson.dropbear.id.au</email>
</author>
<published>2026-01-13T03:06:13+00:00</published>
<link rel='alternate' type='text/html' href='https://passt.top/passt/commit/?id=d5fd945ceb379b695b8d58aeab9363509fcf6587'/>
<id>d5fd945ceb379b695b8d58aeab9363509fcf6587</id>
<content type='text'>
Currently, it's possible to explicitly ask for forwarding from an IPv4
address, while disabling IPv4:
    $ pasta -t 192.0.2.1/12345 -6
or vice versa:
    $ pasta -t 2001:db8::1/12345 -4

Currently, the impossible to implement forwarding option will be silently
ignored.  That's potentially confusing since in a complex setup, it might
not be obvious why the requested forward isn't taking effect.

Specifically, it's ignored at a fairly low level: tcp_listen() and
udp_listen() ignore it and return 0.  Those run kind of late to give a
good error message.  Change the low-level functions to return
-EAFNOSUPPORT.  Most callers of {tcp,udp}_listen() ignore the return code,
so this is a no-op for them.  In the remaining caller,
conf_ports_range_except() check for the case explicitly, and provide a
meaningful error message.

Of itself, this bug is insignificant, but this is a roadblock to having
{tcp,udp}_listen() return socket fds, which in turn is a roadblock to my
flexible forwarding work.  So, might as well fix it.

Link: https://bugs.passt.top/show_bug.cgi?id=186
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>
Currently, it's possible to explicitly ask for forwarding from an IPv4
address, while disabling IPv4:
    $ pasta -t 192.0.2.1/12345 -6
or vice versa:
    $ pasta -t 2001:db8::1/12345 -4

Currently, the impossible to implement forwarding option will be silently
ignored.  That's potentially confusing since in a complex setup, it might
not be obvious why the requested forward isn't taking effect.

Specifically, it's ignored at a fairly low level: tcp_listen() and
udp_listen() ignore it and return 0.  Those run kind of late to give a
good error message.  Change the low-level functions to return
-EAFNOSUPPORT.  Most callers of {tcp,udp}_listen() ignore the return code,
so this is a no-op for them.  In the remaining caller,
conf_ports_range_except() check for the case explicitly, and provide a
meaningful error message.

Of itself, this bug is insignificant, but this is a roadblock to having
{tcp,udp}_listen() return socket fds, which in turn is a roadblock to my
flexible forwarding work.  So, might as well fix it.

Link: https://bugs.passt.top/show_bug.cgi?id=186
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: Introduce flow_epoll_set() to centralize epoll operations</title>
<updated>2026-01-14T00:07:51+00:00</updated>
<author>
<name>Laurent Vivier</name>
<email>lvivier@redhat.com</email>
</author>
<published>2026-01-09T16:54:38+00:00</published>
<link rel='alternate' type='text/html' href='https://passt.top/passt/commit/?id=c0be730f2aa2243a132b3ee40c2bf05ebc84fedf'/>
<id>c0be730f2aa2243a132b3ee40c2bf05ebc84fedf</id>
<content type='text'>
Currently, each flow type (TCP, TCP_SPLICE, PING, UDP) has its own
code to add or modify file descriptors in epoll. This leads to
duplicated boilerplate code across icmp.c, tcp.c, tcp_splice.c, and
udp_flow.c, each setting up epoll_ref unions and calling epoll_ctl()
with flow-type-specific details.

Introduce flow_epoll_set() in flow.c to handle epoll operations for
all flow types in a unified way.

This will be needed to migrate queue pair from an epollfd to another.

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, each flow type (TCP, TCP_SPLICE, PING, UDP) has its own
code to add or modify file descriptors in epoll. This leads to
duplicated boilerplate code across icmp.c, tcp.c, tcp_splice.c, and
udp_flow.c, each setting up epoll_ref unions and calling epoll_ctl()
with flow-type-specific details.

Introduce flow_epoll_set() in flow.c to handle epoll operations for
all flow types in a unified way.

This will be needed to migrate queue pair from an epollfd to another.

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>tcp_splice: Refactor tcp_splice_conn_epoll_events() to per-side computation</title>
<updated>2026-01-14T00:07:51+00:00</updated>
<author>
<name>Laurent Vivier</name>
<email>lvivier@redhat.com</email>
</author>
<published>2026-01-09T16:54:37+00:00</published>
<link rel='alternate' type='text/html' href='https://passt.top/passt/commit/?id=23da651ab08e564b84c532f6f93b0817d2ae850f'/>
<id>23da651ab08e564b84c532f6f93b0817d2ae850f</id>
<content type='text'>
The function tcp_splice_conn_epoll_events() currently takes an array of
struct epoll_event and fills in the .events field for both sides using
flow_foreach_sidei() loops.

This works, but the function is doing two conceptually separate things
at once: computing events for side 0 and computing events for side 1.
The OUT_WAIT handling is particularly subtle, as it has cross-side
effects: when OUT_WAIT(sidei) is set, we add EPOLLOUT to ev[sidei] but
also remove EPOLLIN from ev[!sidei].

Refactor to make the function compute events for a single side at a
time, taking sidei as a parameter and returning uint32_t. This makes
the logic more focused and easier to follow. The cross-side effects of
OUT_WAIT are preserved by checking both OUT_WAIT(sidei) and
OUT_WAIT(!sidei) within each call.

The caller tcp_splice_epoll_ctl() now invokes the function twice, once
for each side, making the two-sided nature of the operation explicit.

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>
The function tcp_splice_conn_epoll_events() currently takes an array of
struct epoll_event and fills in the .events field for both sides using
flow_foreach_sidei() loops.

This works, but the function is doing two conceptually separate things
at once: computing events for side 0 and computing events for side 1.
The OUT_WAIT handling is particularly subtle, as it has cross-side
effects: when OUT_WAIT(sidei) is set, we add EPOLLOUT to ev[sidei] but
also remove EPOLLIN from ev[!sidei].

Refactor to make the function compute events for a single side at a
time, taking sidei as a parameter and returning uint32_t. This makes
the logic more focused and easier to follow. The cross-side effects of
OUT_WAIT are preserved by checking both OUT_WAIT(sidei) and
OUT_WAIT(!sidei) within each call.

The caller tcp_splice_epoll_ctl() now invokes the function twice, once
for each side, making the two-sided nature of the operation explicit.

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>udp_flow: Assign socket to flow inside udp_flow_sock()</title>
<updated>2026-01-14T00:07:51+00:00</updated>
<author>
<name>Laurent Vivier</name>
<email>lvivier@redhat.com</email>
</author>
<published>2026-01-09T16:54:36+00:00</published>
<link rel='alternate' type='text/html' href='https://passt.top/passt/commit/?id=e0fdfccc1c1a56c58a96d7fd6cc5d532cd780b6f'/>
<id>e0fdfccc1c1a56c58a96d7fd6cc5d532cd780b6f</id>
<content type='text'>
Move the assignment of uflow-&gt;s[sidei] from the caller (udp_flow_new())
into udp_flow_sock() itself, placing it after the successful connect().

This is a pure refactoring with no functional change.  The socket fd is
now assigned within udp_flow_sock() where the socket is created, rather
than requiring the caller to capture the return value.  On error paths,
uflow-&gt;s[sidei] remains at its initialized value of -1 rather than being
set to the negative error code, which is semantically cleaner (though
functionally equivalent given the &gt;= 0 check in udp_flow_close()).

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>
Move the assignment of uflow-&gt;s[sidei] from the caller (udp_flow_new())
into udp_flow_sock() itself, placing it after the successful connect().

This is a pure refactoring with no functional change.  The socket fd is
now assigned within udp_flow_sock() where the socket is created, rather
than requiring the caller to capture the return value.  On error paths,
uflow-&gt;s[sidei] remains at its initialized value of -1 rather than being
set to the negative error code, which is semantically cleaner (though
functionally equivalent given the &gt;= 0 check in udp_flow_close()).

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>
