<feed xmlns='http://www.w3.org/2005/Atom'>
<title>passt/netlink.c, branch 2026_05_26.038c51e</title>
<subtitle>Plug A Simple Socket Transport</subtitle>
<link rel='alternate' type='text/html' href='https://passt.top/passt/'/>
<entry>
<title>netlink: Fix comments to variables for netlink sockets and sequence</title>
<updated>2026-05-26T10:15:31+00:00</updated>
<author>
<name>Stefano Brivio</name>
<email>sbrivio@redhat.com</email>
</author>
<published>2026-05-21T17:52:34+00:00</published>
<link rel='alternate' type='text/html' href='https://passt.top/passt/commit/?id=5038f925b028f2faa401b3210327c1de1a24e84b'/>
<id>5038f925b028f2faa401b3210327c1de1a24e84b</id>
<content type='text'>
Commit 3c469013cfaa ("netlink: add subscription on changes in NDP/ARP
table") added the descriptor for the new socket, int nl_sock_neigh,
next to the variables for the existing sockets, without updating the
comment, and before the variable reserved for the sequence number.

That seems to suggest that the sequence number applies to the notifier
socket as well, but that's not the case. Further, the comment didn't
match anymore.

Move the variable declaration for nl_sock_neigh below, and add a
separate comment for it, actually describing it. While at it, fix the
indentation.

Fixes: 3c469013cfaa ("netlink: add subscription on changes in NDP/ARP table")
Signed-off-by: Stefano Brivio &lt;sbrivio@redhat.com&gt;
Reviewed-by: David Gibson &lt;david@gibson.dropbear.id.au&gt;
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
Commit 3c469013cfaa ("netlink: add subscription on changes in NDP/ARP
table") added the descriptor for the new socket, int nl_sock_neigh,
next to the variables for the existing sockets, without updating the
comment, and before the variable reserved for the sequence number.

That seems to suggest that the sequence number applies to the notifier
socket as well, but that's not the case. Further, the comment didn't
match anymore.

Move the variable declaration for nl_sock_neigh below, and add a
separate comment for it, actually describing it. While at it, fix the
indentation.

Fixes: 3c469013cfaa ("netlink: add subscription on changes in NDP/ARP table")
Signed-off-by: Stefano Brivio &lt;sbrivio@redhat.com&gt;
Reviewed-by: David Gibson &lt;david@gibson.dropbear.id.au&gt;
</pre>
</div>
</content>
</entry>
<entry>
<title>netlink: Use regular request/response netlink socket for initial neighbour sync</title>
<updated>2026-05-26T09:51:41+00:00</updated>
<author>
<name>Stefano Brivio</name>
<email>sbrivio@redhat.com</email>
</author>
<published>2026-05-21T17:00:51+00:00</published>
<link rel='alternate' type='text/html' href='https://passt.top/passt/commit/?id=d00255bd3ccc3b19099fb34ab278b06d6be2ca59'/>
<id>d00255bd3ccc3b19099fb34ab278b06d6be2ca59</id>
<content type='text'>
...instead of the one dedicated to the neighbour monitor, because, if
neighbour notifications start coming in before or while we send the
initial request to read out the neighbour tables, messages and
sequence numbers will collide.

For example, if nl_neigh_sync() sends a RTM_GETNEIGH request with
sequence 20, we expect a corresponding reply with sequence 20. But
given that we already used the same socket to subscribe to
notifications, and notifications don't correspond to any specific
request we sent, we might now get a message with sequence 0.

The collision between messages wouldn't actually matter, as we'll
handle anyway any RTM_NEWNEIGH message in the same fashion, but we
need to validate sequence numbers for robustness, and that will fail.

At the same time, we have to subscribe to neighbour notifications
before calling nl_neigh_sync(), because we'll have a race condition
otherwise, as we might miss neighbours that were added before the
notifier is registered.

Use the regular nl_sock for nl_neigh_sync().

Drop the interface index from the request: we won't get any entry
otherwise, because the Linux kernel (as of version 7.0) is unable to
filter on it. Results are now filtered by interface index as we read
them.

Passing along an interface index used to work when nl_neigh_sync()
used the notifier socket, because NETLINK_GET_STRICT_CHK is not set
on it, meaning that results weren't filtered at all (interface and
IP version passed in the request were ignored altogether).

To reproduce the issue fixed here:

* detach a network and user namespace:

  [terminal 0]
  $ unshare -rUn
  # echo $$
  1543307

* attach pasta to it:

  [terminal 1]
  $ ./pasta -f --config-net 1543307 -I enp9s0

* enter that namespace from yet another terminal:

  [terminal 2]
  $ nsenter --preserve-credentials -U -n -t 1543307

* start flooding the MAC address table of this namespace:

  [terminal 1]
  # for i in $(seq 10 99); do for j in $(seq 10 99); do for k in $(seq 10 99); do ip ne add dev enp9s0 10.$i.$j.$k lladdr 00:11:22:$i:$j:$k; done; done; done

* and now start another instance of pasta in this namespace:

  [terminal 2]
  # ./pasta -d --config-net

which will eventually result in pasta exiting with a message like:

  0.0253: netlink: Unexpected sequence number (0 != 34)

Reported-by: Paul Holzinger &lt;pholzing@redhat.com&gt;
Link: https://bugs.passt.top/show_bug.cgi?id=203
Fixes: 3c469013cfaa ("netlink: add subscription on changes in NDP/ARP table")
Signed-off-by: Stefano Brivio &lt;sbrivio@redhat.com&gt;
Reviewed-by: David Gibson &lt;david@gibson.dropbear.id.au&gt;
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
...instead of the one dedicated to the neighbour monitor, because, if
neighbour notifications start coming in before or while we send the
initial request to read out the neighbour tables, messages and
sequence numbers will collide.

For example, if nl_neigh_sync() sends a RTM_GETNEIGH request with
sequence 20, we expect a corresponding reply with sequence 20. But
given that we already used the same socket to subscribe to
notifications, and notifications don't correspond to any specific
request we sent, we might now get a message with sequence 0.

The collision between messages wouldn't actually matter, as we'll
handle anyway any RTM_NEWNEIGH message in the same fashion, but we
need to validate sequence numbers for robustness, and that will fail.

At the same time, we have to subscribe to neighbour notifications
before calling nl_neigh_sync(), because we'll have a race condition
otherwise, as we might miss neighbours that were added before the
notifier is registered.

Use the regular nl_sock for nl_neigh_sync().

Drop the interface index from the request: we won't get any entry
otherwise, because the Linux kernel (as of version 7.0) is unable to
filter on it. Results are now filtered by interface index as we read
them.

Passing along an interface index used to work when nl_neigh_sync()
used the notifier socket, because NETLINK_GET_STRICT_CHK is not set
on it, meaning that results weren't filtered at all (interface and
IP version passed in the request were ignored altogether).

To reproduce the issue fixed here:

* detach a network and user namespace:

  [terminal 0]
  $ unshare -rUn
  # echo $$
  1543307

* attach pasta to it:

  [terminal 1]
  $ ./pasta -f --config-net 1543307 -I enp9s0

* enter that namespace from yet another terminal:

  [terminal 2]
  $ nsenter --preserve-credentials -U -n -t 1543307

* start flooding the MAC address table of this namespace:

  [terminal 1]
  # for i in $(seq 10 99); do for j in $(seq 10 99); do for k in $(seq 10 99); do ip ne add dev enp9s0 10.$i.$j.$k lladdr 00:11:22:$i:$j:$k; done; done; done

* and now start another instance of pasta in this namespace:

  [terminal 2]
  # ./pasta -d --config-net

which will eventually result in pasta exiting with a message like:

  0.0253: netlink: Unexpected sequence number (0 != 34)

Reported-by: Paul Holzinger &lt;pholzing@redhat.com&gt;
Link: https://bugs.passt.top/show_bug.cgi?id=203
Fixes: 3c469013cfaa ("netlink: add subscription on changes in NDP/ARP table")
Signed-off-by: Stefano Brivio &lt;sbrivio@redhat.com&gt;
Reviewed-by: David Gibson &lt;david@gibson.dropbear.id.au&gt;
</pre>
</div>
</content>
</entry>
<entry>
<title>clang-tidy: Squash inconsistent brace warnings in foreach macros</title>
<updated>2026-05-11T22:04:03+00:00</updated>
<author>
<name>David Gibson</name>
<email>david@gibson.dropbear.id.au</email>
</author>
<published>2026-05-11T10:03:18+00:00</published>
<link rel='alternate' type='text/html' href='https://passt.top/passt/commit/?id=a82a2173d4ea41fe4e97d9451f8ed1626b00d612'/>
<id>a82a2173d4ea41fe4e97d9451f8ed1626b00d612</id>
<content type='text'>
clang-tidy, at least as of 22.1.4 complains about if/else statements with
inconsistent braces.  We generally do want consistend bracing per our
coding style.  However, some of our foreach macros generate inconsistent
bracing in a way that can't really be avoided.  Add suppressions to stop
clang-tidy complaining about these.

Signed-off-by: David Gibson &lt;david@gibson.dropbear.id.au&gt;
Reviewed-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>
clang-tidy, at least as of 22.1.4 complains about if/else statements with
inconsistent braces.  We generally do want consistend bracing per our
coding style.  However, some of our foreach macros generate inconsistent
bracing in a way that can't really be avoided.  Add suppressions to stop
clang-tidy complaining about these.

Signed-off-by: David Gibson &lt;david@gibson.dropbear.id.au&gt;
Reviewed-by: Laurent Vivier &lt;lvivier@redhat.com&gt;
Signed-off-by: Stefano Brivio &lt;sbrivio@redhat.com&gt;
</pre>
</div>
</content>
</entry>
<entry>
<title>netlink: erromsg should be const in nl_status()</title>
<updated>2026-05-11T22:03:02+00:00</updated>
<author>
<name>David Gibson</name>
<email>david@gibson.dropbear.id.au</email>
</author>
<published>2026-05-11T10:03:15+00:00</published>
<link rel='alternate' type='text/html' href='https://passt.top/passt/commit/?id=1e6b638b490918386292e79efc8f62311e4a9f2f'/>
<id>1e6b638b490918386292e79efc8f62311e4a9f2f</id>
<content type='text'>
This pointer aliases part of the const nlmsghdr we're passed, so it should
be const.  While we're there, remove an unnecessary explicit cast
(NLMSG_DATA() returns a void *, which implicitly casts to anything).
This also removes a warning on cppcheck 2.20.0 and probably many other
versions.

Signed-off-by: David Gibson &lt;david@gibson.dropbear.id.au&gt;
Reviewed-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>
This pointer aliases part of the const nlmsghdr we're passed, so it should
be const.  While we're there, remove an unnecessary explicit cast
(NLMSG_DATA() returns a void *, which implicitly casts to anything).
This also removes a warning on cppcheck 2.20.0 and probably many other
versions.

Signed-off-by: David Gibson &lt;david@gibson.dropbear.id.au&gt;
Reviewed-by: Laurent Vivier &lt;lvivier@redhat.com&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>netlink: Allow NULL to be passed as addr parameter to nl_addr_get (again)</title>
<updated>2026-03-11T21:11:30+00:00</updated>
<author>
<name>David Gibson</name>
<email>david@gibson.dropbear.id.au</email>
</author>
<published>2026-03-11T04:13:57+00:00</published>
<link rel='alternate' type='text/html' href='https://passt.top/passt/commit/?id=831e98384b057a7e74aa615200752c1d84c017ee'/>
<id>831e98384b057a7e74aa615200752c1d84c017ee</id>
<content type='text'>
A recent fix to nl_addr_get() unfortunately introduced a different problem.
251e676bd0bf removed a test if @addr was non-NULL.  conf_ip6() relied on
being able to pass NULL in order to update the link-local address without
updating the main address (because it was already set by the user).

This means that 'pasta -a 2001:db8::1' will SEGV.  Reverse the incorrect
part of the change to fix this.

Fixes: 251e676bd0bf ("netlink: Return prefix length for IPv6 addresses in nl_addr_get()")
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>
A recent fix to nl_addr_get() unfortunately introduced a different problem.
251e676bd0bf removed a test if @addr was non-NULL.  conf_ip6() relied on
being able to pass NULL in order to update the link-local address without
updating the main address (because it was already set by the user).

This means that 'pasta -a 2001:db8::1' will SEGV.  Reverse the incorrect
part of the change to fix this.

Fixes: 251e676bd0bf ("netlink: Return prefix length for IPv6 addresses in nl_addr_get()")
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>netlink: Return prefix length for IPv6 addresses in nl_addr_get()</title>
<updated>2026-03-10T14:28:11+00:00</updated>
<author>
<name>Jon Maloy</name>
<email>jmaloy@redhat.com</email>
</author>
<published>2026-03-09T19:52:33+00:00</published>
<link rel='alternate' type='text/html' href='https://passt.top/passt/commit/?id=251e676bd0bffe0c3b8bf0e925fbc87b6d4eeb6a'/>
<id>251e676bd0bffe0c3b8bf0e925fbc87b6d4eeb6a</id>
<content type='text'>
nl_addr_get() was not setting the prefix_len output parameter for
IPv6 addresses, only for IPv4. This meant callers always got 0 for
IPv6, forcing them to use a hardcoded default (64).

Fix by assigning *prefix_len even in the IPv6 case.

Signed-off-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>
nl_addr_get() was not setting the prefix_len output parameter for
IPv6 addresses, only for IPv4. This meant callers always got 0 for
IPv6, forcing them to use a hardcoded default (64).

Fix by assigning *prefix_len even in the IPv6 case.

Signed-off-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>epoll_ctl: Extract epoll operations</title>
<updated>2025-10-30T14:32:12+00:00</updated>
<author>
<name>Laurent Vivier</name>
<email>lvivier@redhat.com</email>
</author>
<published>2025-10-21T21:01:11+00:00</published>
<link rel='alternate' type='text/html' href='https://passt.top/passt/commit/?id=965ea66068e653934c0016281df86c17e2a65625'/>
<id>965ea66068e653934c0016281df86c17e2a65625</id>
<content type='text'>
Centralize epoll_add() and epoll_del() helper functions into new
epoll_ctl.c/h files.

This also moves the union epoll_ref definition from passt.h to
epoll_ctl.h where it's more logically placed.

The new epoll_add() helper simplifies adding file descriptors to epoll
by taking an epoll_ref and events, handling error reporting
consistently across all call sites.

Signed-off-by: Laurent Vivier &lt;lvivier@redhat.com&gt;
[sbrivio: Include epoll_ctl.h from netlink.c as it's now needed there]
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>
Centralize epoll_add() and epoll_del() helper functions into new
epoll_ctl.c/h files.

This also moves the union epoll_ref definition from passt.h to
epoll_ctl.h where it's more logically placed.

The new epoll_add() helper simplifies adding file descriptors to epoll
by taking an epoll_ref and events, handling error reporting
consistently across all call sites.

Signed-off-by: Laurent Vivier &lt;lvivier@redhat.com&gt;
[sbrivio: Include epoll_ctl.h from netlink.c as it's now needed there]
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>fwd: Add cache table for ARP/NDP contents</title>
<updated>2025-10-30T11:01:01+00:00</updated>
<author>
<name>Jon Maloy</name>
<email>jmaloy@redhat.com</email>
</author>
<published>2025-10-24T01:29:26+00:00</published>
<link rel='alternate' type='text/html' href='https://passt.top/passt/commit/?id=45869d6f816f8c6162b41188f0d0cc20e98f8bb9'/>
<id>45869d6f816f8c6162b41188f0d0cc20e98f8bb9</id>
<content type='text'>
We add a cache table to keep track of the contents of the kernel ARP
and NDP tables. The table is fed from the just introduced netlink based
neigbour subscription function.

Signed-off-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>
We add a cache table to keep track of the contents of the kernel ARP
and NDP tables. The table is fed from the just introduced netlink based
neigbour subscription function.

Signed-off-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>netlink: add subscription on changes in NDP/ARP table</title>
<updated>2025-10-30T11:00:49+00:00</updated>
<author>
<name>Jon Maloy</name>
<email>jmaloy@redhat.com</email>
</author>
<published>2025-10-24T01:29:25+00:00</published>
<link rel='alternate' type='text/html' href='https://passt.top/passt/commit/?id=3c469013cfaa4ae7a945a6251be4abdcbcae4cc7'/>
<id>3c469013cfaa4ae7a945a6251be4abdcbcae4cc7</id>
<content type='text'>
The solution to bug https://bugs.passt.top/show_bug.cgi?id=120
requires the ability to translate from an IP address to its
corresponding MAC address in cases where those are present in
the ARP or NDP tables.

To keep track of the contents of these tables we add a netlink
based neighbour subscription feature.

Signed-off-by: Jon Maloy &lt;jmaloy@redhat.com&gt;
Reviewed-by: David Gibson &lt;david@gibson.dropbear.id.au&gt;
[sbrivio: Fix format modifier for ndm-&gt;ndm_state, reported by dwg]
Signed-off-by: Stefano Brivio &lt;sbrivio@redhat.com&gt;
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
The solution to bug https://bugs.passt.top/show_bug.cgi?id=120
requires the ability to translate from an IP address to its
corresponding MAC address in cases where those are present in
the ARP or NDP tables.

To keep track of the contents of these tables we add a netlink
based neighbour subscription feature.

Signed-off-by: Jon Maloy &lt;jmaloy@redhat.com&gt;
Reviewed-by: David Gibson &lt;david@gibson.dropbear.id.au&gt;
[sbrivio: Fix format modifier for ndm-&gt;ndm_state, reported by dwg]
Signed-off-by: Stefano Brivio &lt;sbrivio@redhat.com&gt;
</pre>
</div>
</content>
</entry>
</feed>
