From: Alyssa Ross <hi@alyssa.is>
To: devel@spectrum-os.org
Cc: Yureka Lilian <yureka@cyberchaos.dev>
Subject: [PATCH] release/checks/integration: fix race condition
Date: Thu, 18 Dec 2025 19:58:30 +0100 [thread overview]
Message-ID: <20251218185830.89957-1-hi@alyssa.is> (raw)
By default, IPv6 addresses are in the tentative state and can't be
bound to until the kernel has asychronously done Duplicate Address
Detection. This was the cause of us needing to retry the bind, and
sometimes even that wasn't enough. Since we're in a fresh network
namespace, we know there can't be a duplicate address, so we can add
the address with the IFA_F_NODAD flag to skip this and make the
address available for binding immediately. We can't set that flag
using the ioctl interface we were using before, so switch to netlink.
This is slightly lazy netlink — we hardcode the index of the loopback
address, and don't bother with extended errors — but I think that's
fine for a test where readability is the most important thing.
I've run the test 100 times with this change and didn't see any bind
failures, which is a big improvement over the failure rate I was
seeing before.
Fixes: cdf1891e ("release/checks/integration: Adapt networking test for ipv6")
Signed-off-by: Alyssa Ross <hi@alyssa.is>
---
release/checks/integration/networking.c | 89 +++++++++++++++++++------
1 file changed, 70 insertions(+), 19 deletions(-)
diff --git a/release/checks/integration/networking.c b/release/checks/integration/networking.c
index 68f00b98..7d02f557 100644
--- a/release/checks/integration/networking.c
+++ b/release/checks/integration/networking.c
@@ -12,14 +12,14 @@
#include <arpa/inet.h>
#include <net/if.h>
-#include <sys/ioctl.h>
+#include <sys/socket.h>
+#include <linux/if_addr.h>
#include <linux/ipv6.h>
+#include <linux/rtnetlink.h>
static int setup_server(void)
{
int fd;
- struct ifreq ifr;
- struct in6_ifreq ifr6;
struct sockaddr_in6 addr = {
.sin6_family = AF_INET6,
@@ -27,30 +27,83 @@ static int setup_server(void)
.sin6_addr = { .s6_addr = { 0xfd, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02 } },
};
- sprintf(ifr.ifr_name, "lo");
+ struct {
+ struct nlmsghdr nh;
+ struct ifaddrmsg ifa;
+ struct rtattr attr;
+ struct in6_addr addr;
+ } newaddr_req = {
+ {
+ .nlmsg_len = sizeof newaddr_req,
+ .nlmsg_type = RTM_NEWADDR,
+ .nlmsg_flags = NLM_F_ACK | NLM_F_REQUEST,
+ },
+ {
+ .ifa_family = AF_INET6,
+ .ifa_prefixlen = 128,
+ .ifa_flags = IFA_F_NODAD,
+ .ifa_index = 1,
+ },
+ {
+ .rta_len = sizeof newaddr_req.attr + sizeof newaddr_req.addr,
+ .rta_type = IFA_ADDRESS,
+ },
+ addr.sin6_addr,
+ };
- ifr6.ifr6_ifindex = 1;
- ifr6.ifr6_addr = addr.sin6_addr;
- ifr6.ifr6_prefixlen = 128;
+ struct {
+ struct nlmsghdr nh;
+ struct ifinfomsg ifi;
+ } newlink_req = {
+ {
+ .nlmsg_len = sizeof newlink_req,
+ .nlmsg_type = RTM_NEWLINK,
+ .nlmsg_flags = NLM_F_ACK | NLM_F_REQUEST,
+ },
+ {
+ .ifi_index = 1,
+ .ifi_flags = IFF_UP,
+ .ifi_change = IFF_UP,
+ },
+ };
- if ((fd = socket(AF_INET6, SOCK_STREAM|SOCK_CLOEXEC, 0)) == -1) {
+ struct {
+ struct nlmsghdr nh;
+ struct nlmsgerr err;
+ } res;
+
+ if ((fd = socket(AF_NETLINK, SOCK_DGRAM|SOCK_CLOEXEC, NETLINK_ROUTE)) == -1) {
perror("socket");
exit(EXIT_FAILURE);
}
- if (ioctl(fd, SIOCGIFFLAGS, &ifr) == -1) {
- perror("SIOCGIFFLAGS");
+ if (send(fd, &newaddr_req, sizeof newaddr_req, 0) == -1) {
+ perror("send");
exit(EXIT_FAILURE);
}
- ifr.ifr_flags |= IFF_UP;
- if (ioctl(fd, SIOCSIFFLAGS, &ifr) == -1) {
- perror("SIOCSIFFLAGS");
+ if (recv(fd, &res, sizeof res, 0) == -1) {
+ perror("recv");
exit(EXIT_FAILURE);
}
- if (ioctl(fd, SIOCSIFADDR, &ifr6) == -1) {
- perror("SIOCSIFADDR");
+ if (res.err.error) {
+ fprintf(stderr, "RTM_NEWADDR: %s", strerror(-res.err.error));
+ exit(EXIT_FAILURE);
+ }
+
+ if (send(fd, &newlink_req, sizeof newlink_req, 0) == -1) {
+ perror("send");
+ exit(EXIT_FAILURE);
+ }
+
+ if (recv(fd, &res, sizeof res, 0) == -1) {
+ perror("recv");
+ exit(EXIT_FAILURE);
+ }
+
+ if (res.err.error) {
+ fprintf(stderr, "RTM_NEWLINK: %s", strerror(-res.err.error));
exit(EXIT_FAILURE);
}
@@ -61,11 +114,9 @@ static int setup_server(void)
exit(EXIT_FAILURE);
}
- int tries = 0;
- while (bind(fd, &addr, sizeof addr) == -1) {
+ if (bind(fd, &addr, sizeof addr) == -1) {
perror("bind");
- if (tries++ >= 5)
- exit(EXIT_FAILURE);
+ exit(EXIT_FAILURE);
}
if (listen(fd, 1) == -1) {
base-commit: 77f8d28f076b16a64faef83c5cf374995770ff70
--
2.51.0
next reply other threads:[~2025-12-18 18:59 UTC|newest]
Thread overview: 2+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-12-18 18:58 Alyssa Ross [this message]
2026-01-15 15:53 ` [PATCH] release/checks/integration: fix race condition Alyssa Ross
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20251218185830.89957-1-hi@alyssa.is \
--to=hi@alyssa.is \
--cc=devel@spectrum-os.org \
--cc=yureka@cyberchaos.dev \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
Code repositories for project(s) associated with this public inbox
https://spectrum-os.org/git/crosvm
https://spectrum-os.org/git/doc
https://spectrum-os.org/git/mktuntap
https://spectrum-os.org/git/nixpkgs
https://spectrum-os.org/git/spectrum
https://spectrum-os.org/git/ucspi-vsock
https://spectrum-os.org/git/www
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).