From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from gate001.proxmox.com (gate001.proxmox.com [45.144.208.40]) by lore.proxmox.com (Postfix) with ESMTPS id BB5E31FF0DF for ; Thu, 05 Nov 2026 10:36:44 +0100 (CET) Received: from gate001.proxmox.com (localhost.localdomain [127.0.0.1]) by gate001.proxmox.com (Proxmox) with ESMTP id 686F6216FB; Thu, 05 Nov 2026 10:36:04 +0100 (CET) From: Hannes Laimer To: pve-devel@lists.proxmox.com Subject: [PATCH qemu-server v6 10/13] network: sdn: push the DHCP mappings of a guest when it resumes Date: Thu, 5 Nov 2026 10:35:26 +0100 Message-ID: <20261105093529.209052-11-h.laimer@proxmox.com> X-Mailer: git-send-email 2.47.3 In-Reply-To: <20261105093529.209052-1-h.laimer@proxmox.com> References: <20261105093529.209052-1-h.laimer@proxmox.com> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Bm-Milter-Handled: 55990f41-d878-4baa-be0a-ee34c49e34d2 X-Bm-Transport-Timestamp: 1793871344736 X-SPAM-LEVEL: Spam detection results: 0 AWL 0.291 Adjusted score from AWL reputation of From: address DMARC_MISSING 0.1 Missing DMARC policy KAM_DMARC_STATUS 0.01 Test Rule for DKIM or SPF Failure with Strict Alignment (newer systems) RCVD_IN_DNSWL_MED -2.3 Sender listed at https://www.dnswl.org/, medium trust SPF_HELO_NONE 0.001 SPF: HELO does not publish an SPF Record SPF_PASS -0.001 SPF: sender matches SPF record Message-ID-Hash: ZQHK7QFFGNBI2WHE2YIAB4KLUTLVT4QM X-Message-ID-Hash: ZQHK7QFFGNBI2WHE2YIAB4KLUTLVT4QM X-MailFrom: h.laimer@proxmox.com X-Mailman-Rule-Misses: dmarc-mitigation; no-senders; approved; loop; banned-address; emergency; member-moderation; nonmember-moderation; administrivia; implicit-dest; max-recipients; max-size; news-moderation; no-subject; digests; suspicious-header X-Mailman-Version: 3.3.10 Precedence: list List-Id: Proxmox VE development discussion List-Help: List-Owner: List-Post: List-Subscribe: List-Unsubscribe: A mapping edit and a migration of the guest exclude each other, but an edit through a node not yet upgraded takes no lock and writes no reservation, so it can land while the guest is migrated. Every resume now pushes the mapping of each NIC of the guest on the local node before the guest continues, and the last step of a live migration resumes the target after the config moved, so the target serves what the cache vouches for. The push asks the IPAM only when the cache cannot vouch for the address. The push does not wait long for a push holding the reservation file. A failed request fails the task after the guest continued, naming the IPAM's error. An IPAM that does not answer holds the resume up to the request's timeout first, and a slow one for every request the lookup makes. That beats serving the guest a stale address. Signed-off-by: Hannes Laimer --- src/PVE/QemuServer/Network.pm | 18 ++++++++++++++++++ src/PVE/QemuServer/RunState.pm | 8 ++++++++ 2 files changed, 26 insertions(+) diff --git a/src/PVE/QemuServer/Network.pm b/src/PVE/QemuServer/Network.pm index b4893c015646..7ae448ea1369 100644 --- a/src/PVE/QemuServer/Network.pm +++ b/src/PVE/QemuServer/Network.pm @@ -272,6 +272,24 @@ sub add_random_macs { } } +# a resume pushes the current mapping of each NIC. The target of a live +# migration resumes after the config moved and serves the current addresses +# from then on. The push does not wait long for a push holding the +# reservation file +sub add_nets_dhcp_mapping { + my ($conf) = @_; + + my @errors; + for my $opt (keys %$conf) { + next if $opt !~ m/^net\d+$/; + my $net = parse_net($conf->{$opt}, 1) or next; + next if !$net->{bridge} || !$net->{macaddr}; + eval { PVE::Network::SDN::Dhcp::update_mapping($net->{bridge}, $net->{macaddr}, 1) }; + push @errors, $@ if $@; + } + die join('', @errors) if @errors; +} + sub add_nets_bridge_fdb { my ($conf, $vmid) = @_; diff --git a/src/PVE/QemuServer/RunState.pm b/src/PVE/QemuServer/RunState.pm index 889ddd28287b..cf1e1873c39d 100644 --- a/src/PVE/QemuServer/RunState.pm +++ b/src/PVE/QemuServer/RunState.pm @@ -181,8 +181,16 @@ sub vm_resume($vmid, $skiplock = undef, $nocheck = undef) { PVE::QemuServer::Network::add_nets_bridge_fdb($conf, $vmid) if $resume_cmd eq 'cont'; + # a failed push is raised after the guest continued, so the task + # says what went wrong and the guest does not stay paused for it + my $dhcp_err; + if ($resume_cmd eq 'cont') { + eval { PVE::QemuServer::Network::add_nets_dhcp_mapping($conf) }; + $dhcp_err = $@; + } mon_cmd($vmid, $resume_cmd); + die $dhcp_err if $dhcp_err; }, ); } -- 2.47.3