From 98dd85971e24f7d4f1326d6014ffc03b8082b75e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20=C4=8Cerm=C3=A1k?= Date: Mon, 9 Mar 2026 15:06:27 +0100 Subject: [PATCH] Reduce number of DNS queries from connectivity checks (#4571) Backport NetworkManager patch (backported alsso in upstream to v1.56.0) to restrict connectivity check lookups to per-link DNS. This reduces the number of DNS queries performed by NetworkManager itself. Note that Supervisor has its own connectivity check routine which is independent on this one, so user may still see more requests in a 10 minute interval. Closes #4560 --- ...nnectivity-check-lookups-to-per-link.patch | 209 ++++++++++++++++++ 1 file changed, 209 insertions(+) create mode 100644 buildroot-external/patches/network-manager/0001-core-restrict-connectivity-check-lookups-to-per-link.patch diff --git a/buildroot-external/patches/network-manager/0001-core-restrict-connectivity-check-lookups-to-per-link.patch b/buildroot-external/patches/network-manager/0001-core-restrict-connectivity-check-lookups-to-per-link.patch new file mode 100644 index 000000000..112cc9e4d --- /dev/null +++ b/buildroot-external/patches/network-manager/0001-core-restrict-connectivity-check-lookups-to-per-link.patch @@ -0,0 +1,209 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Popax21 +Date: Mon, 17 Nov 2025 04:52:23 +0100 +Subject: [PATCH] core: restrict connectivity check lookups to per-link DNS if + available +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Restrict connectivity check DNS lookups to just the relevant link if the link +has a per-link DNS resolver configured. This change was previously discussed as +part of issue +https://gitlab.freedesktop.org/NetworkManager/NetworkManager/-/issues/1836, and +brings NM's behavior back in line with the behavior documented in the man page. + +The connectivity check checks for a per-link DNS resolver by querying +systemd-resolved's `ScopeMask` for the link; this involves a small D-Bus +roundtrip, but is ultimately the more flexible solution since it is also capable +of dealing with per-link DNS configuration stemming from other sources. + +Fixes: e6dac4f0b67e ('core: don't restrict DNS interface when performing connectivity check') + +(cherry picked from commit 6e2de1d2b3118e817f930e19e0ea15cde50e3858) +Upstream: https://gitlab.freedesktop.org/NetworkManager/NetworkManager/-/commit/6e2de1d2b3118e817f930e19e0ea15cde50e3858 +Signed-off-by: Jan Čermák +--- + src/core/nm-connectivity.c | 134 ++++++++++++++++++++++++++++++++----- + 1 file changed, 118 insertions(+), 16 deletions(-) + +diff --git a/src/core/nm-connectivity.c b/src/core/nm-connectivity.c +index 65eec36d6d..5bf333cce7 100644 +--- a/src/core/nm-connectivity.c ++++ b/src/core/nm-connectivity.c +@@ -75,6 +75,8 @@ struct _NMConnectivityCheckHandle { + ConConfig *con_config; + + GCancellable *resolve_cancellable; ++ int resolve_ifindex; ++ GDBusConnection *dbus_connection; + CURLM *curl_mhandle; + CURL *curl_ehandle; + struct curl_slist *request_headers; +@@ -954,6 +956,113 @@ systemd_resolved_resolve_cb(GObject *object, GAsyncResult *res, gpointer user_da + + #define SD_RESOLVED_DNS ((guint64) (1LL << 0)) + ++static void ++systemd_resolved_resolve(NMConnectivityCheckHandle *cb_data) ++{ ++ _LOG2D("start request to '%s' (try resolving '%s' using systemd-resolved with ifindex %d)", ++ cb_data->concheck.con_config->uri, ++ cb_data->concheck.con_config->host, ++ cb_data->concheck.resolve_ifindex); ++ ++ g_dbus_connection_call(cb_data->concheck.dbus_connection, ++ "org.freedesktop.resolve1", ++ "/org/freedesktop/resolve1", ++ "org.freedesktop.resolve1.Manager", ++ "ResolveHostname", ++ g_variant_new("(isit)", ++ (gint32) cb_data->concheck.resolve_ifindex, ++ cb_data->concheck.con_config->host, ++ (gint32) cb_data->addr_family, ++ SD_RESOLVED_DNS), ++ G_VARIANT_TYPE("(a(iiay)st)"), ++ G_DBUS_CALL_FLAGS_NONE, ++ -1, ++ cb_data->concheck.resolve_cancellable, ++ systemd_resolved_resolve_cb, ++ cb_data); ++} ++ ++static void ++systemd_resolved_link_scopes_cb(GObject *object, GAsyncResult *res, gpointer user_data) ++{ ++ NMConnectivityCheckHandle *cb_data; ++ gs_unref_variant GVariant *result = NULL; ++ gs_unref_variant GVariant *value = NULL; ++ gs_free_error GError *error = NULL; ++ guint64 scope_mask = 0; ++ ++ result = g_dbus_connection_call_finish(G_DBUS_CONNECTION(object), res, &error); ++ if (nm_utils_error_is_cancelled(error)) ++ return; ++ ++ cb_data = user_data; ++ ++ if (!result) { ++ _LOG2D("unable to obtain systemd-resolved link ScopesMask for interface %d: %s", ++ cb_data->concheck.resolve_ifindex, ++ error->message); ++ ++ cb_data->concheck.resolve_ifindex = 0; ++ systemd_resolved_resolve(cb_data); ++ return; ++ } ++ ++ g_variant_get(result, "(v)", &value); ++ g_variant_get(value, "t", &scope_mask); ++ ++ if (!(scope_mask & SD_RESOLVED_DNS)) { ++ /* there is no per-link DNS configured / active; query all available / ++ * system DNS resolvers instead of restricting the lookup to just this ++ * one, which would turn up no results. */ ++ _LOG2D("no per-link DNS available (scope mask %" G_GUINT64_FORMAT ++ "); falling back to system-wide lookups", ++ scope_mask); ++ cb_data->concheck.resolve_ifindex = 0; ++ } ++ ++ systemd_resolved_resolve(cb_data); ++} ++ ++static void ++systemd_resolved_get_link_cb(GObject *object, GAsyncResult *res, gpointer user_data) ++{ ++ NMConnectivityCheckHandle *cb_data; ++ gs_unref_variant GVariant *result = NULL; ++ gs_free char *link_path = NULL; ++ gs_free_error GError *error = NULL; ++ ++ result = g_dbus_connection_call_finish(G_DBUS_CONNECTION(object), res, &error); ++ if (nm_utils_error_is_cancelled(error)) ++ return; ++ ++ cb_data = user_data; ++ ++ if (!result) { ++ _LOG2D("unable to obtain systemd-resolved link D-Bus object for interface %d: %s", ++ cb_data->concheck.resolve_ifindex, ++ error->message); ++ ++ cb_data->concheck.resolve_ifindex = 0; ++ systemd_resolved_resolve(cb_data); ++ return; ++ } ++ ++ g_variant_get(result, "(o)", &link_path); ++ ++ g_dbus_connection_call(cb_data->concheck.dbus_connection, ++ "org.freedesktop.resolve1", ++ link_path, ++ "org.freedesktop.DBus.Properties", ++ "Get", ++ g_variant_new("(ss)", "org.freedesktop.resolve1.Link", "ScopesMask"), ++ G_VARIANT_TYPE("(v)"), ++ G_DBUS_CALL_FLAGS_NONE, ++ -1, ++ cb_data->concheck.resolve_cancellable, ++ systemd_resolved_link_scopes_cb, ++ cb_data); ++} ++ + static NMConnectivityState + check_platform_config(NMConnectivity *self, + NMPlatform *platform, +@@ -1067,6 +1176,7 @@ nm_connectivity_check_start(NMConnectivity *self, + } + + cb_data->concheck.resolve_cancellable = g_cancellable_new(); ++ cb_data->concheck.resolve_ifindex = ifindex; + + /* note that we pick up support for systemd-resolved right away when we need it. + * We don't need to remember the setting, because we can (cheaply) check anew +@@ -1089,10 +1199,8 @@ nm_connectivity_check_start(NMConnectivity *self, + has_systemd_resolved = !!nm_dns_manager_get_systemd_resolved(nm_dns_manager_get()); + + if (has_systemd_resolved) { +- GDBusConnection *dbus_connection; +- +- dbus_connection = NM_MAIN_DBUS_CONNECTION_GET; +- if (!dbus_connection) { ++ cb_data->concheck.dbus_connection = NM_MAIN_DBUS_CONNECTION_GET; ++ if (!cb_data->concheck.dbus_connection) { + /* we have no D-Bus connection? That might happen in configure and quit mode. + * + * Anyway, something is very odd, just fail connectivity check. */ +@@ -1103,25 +1211,19 @@ nm_connectivity_check_start(NMConnectivity *self, + return cb_data; + } + +- g_dbus_connection_call(dbus_connection, ++ /* first check whether there has been a per-link DNS configured */ ++ g_dbus_connection_call(cb_data->concheck.dbus_connection, + "org.freedesktop.resolve1", + "/org/freedesktop/resolve1", + "org.freedesktop.resolve1.Manager", +- "ResolveHostname", +- g_variant_new("(isit)", +- 0, +- cb_data->concheck.con_config->host, +- (gint32) cb_data->addr_family, +- SD_RESOLVED_DNS), +- G_VARIANT_TYPE("(a(iiay)st)"), ++ "GetLink", ++ g_variant_new("(i)", ifindex), ++ G_VARIANT_TYPE("(o)"), + G_DBUS_CALL_FLAGS_NONE, + -1, + cb_data->concheck.resolve_cancellable, +- systemd_resolved_resolve_cb, ++ systemd_resolved_get_link_cb, + cb_data); +- _LOG2D("start request to '%s' (try resolving '%s' using systemd-resolved)", +- cb_data->concheck.con_config->uri, +- cb_data->concheck.con_config->host); + return cb_data; + } +