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 B26931FF09C for ; Mon, 02 Nov 2026 16:20:08 +0100 (CET) Received: from gate001.proxmox.com (localhost.localdomain [127.0.0.1]) by gate001.proxmox.com (Proxmox) with ESMTP id 8706A21B41; Mon, 02 Nov 2026 16:19:19 +0100 (CET) From: Hannes Laimer To: pve-devel@lists.proxmox.com Subject: [PATCH qemu-server v5 10/15] network: sdn: keep the DHCP backends current on guest NICs Date: Mon, 2 Nov 2026 16:18:37 +0100 Message-ID: <20261102151842.1605234-11-h.laimer@proxmox.com> X-Mailer: git-send-email 2.47.3 In-Reply-To: <20261102151842.1605234-1-h.laimer@proxmox.com> References: <20261102151842.1605234-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: 1793632736142 X-SPAM-LEVEL: Spam detection results: 0 AWL 0.346 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: OAN44QFC3TSD6UT2AZNNVWBOLBHM3HLL X-Message-ID-Hash: OAN44QFC3TSD6UT2AZNNVWBOLBHM3HLL 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 DHCP backend that serves the guest's tap itself has to hear of every plug and removal of that tap. The plug now carries the NIC's MAC, so the backend can look up the NIC's record. Removing a tap now goes through the SDN layer as well, so the backend drops its entry for that tap. A bridge change allocated the NIC's address in the new vnet, but unlike a start or a hotplug it never pushed the mapping to the backend of that vnet's zone. It now does. Signed-off-by: Hannes Laimer --- Notes: v5: * the resume push moved to the IPAM series src/PVE/CLI/qm.pm | 4 ++-- src/PVE/QemuServer.pm | 4 ++++ src/PVE/QemuServer/Network.pm | 4 ++-- src/test/hotplug/net-change-bridge.conf.expected | 3 ++- src/usr/pve-bridge | 8 +++++++- src/usr/pve-bridgedown | 4 ++-- 6 files changed, 19 insertions(+), 8 deletions(-) diff --git a/src/PVE/CLI/qm.pm b/src/PVE/CLI/qm.pm index b903c1f1085f..6c53581ab686 100755 --- a/src/PVE/CLI/qm.pm +++ b/src/PVE/CLI/qm.pm @@ -22,7 +22,7 @@ use PVE::GuestHelpers; use PVE::GuestImport::OVF; use PVE::INotify; use PVE::JSONSchema qw(get_standard_option); -use PVE::Network; +use PVE::Network::SDN::Zones; use PVE::RPCEnvironment; use PVE::SafeSyslog; use PVE::Tools qw(extract_param file_get_contents); @@ -1143,7 +1143,7 @@ __PACKAGE__->register_method({ foreach my $opt (keys %$conf) { next if $opt !~ m/^net(\d+)$/; my $interface = $1; - PVE::Network::tap_unplug("tap${vmid}i${interface}"); + PVE::Network::SDN::Zones::tap_unplug("tap${vmid}i${interface}"); } } diff --git a/src/PVE/QemuServer.pm b/src/PVE/QemuServer.pm index b4a1a38da940..4b4c5db499c9 100644 --- a/src/PVE/QemuServer.pm +++ b/src/PVE/QemuServer.pm @@ -4984,6 +4984,9 @@ sub vmconfig_update_net { PVE::Network::SDN::Vnets::add_next_free_cidr( $newnet->{bridge}, $conf->{name}, $newnet->{macaddr}, $vmid, undef, 1, ); + PVE::Network::SDN::Vnets::add_dhcp_mapping( + $newnet->{bridge}, $newnet->{macaddr}, $vmid, $conf->{name}, + ); } PVE::QemuServer::Network::tap_plug( @@ -4993,6 +4996,7 @@ sub vmconfig_update_net { $newnet->{firewall}, $newnet->{trunks}, $newnet->{rate}, + { mac => $newnet->{macaddr} }, ); } elsif (safe_num_ne($oldnet->{rate}, $newnet->{rate})) { diff --git a/src/PVE/QemuServer/Network.pm b/src/PVE/QemuServer/Network.pm index 88a2290672e6..5da8599ecab5 100644 --- a/src/PVE/QemuServer/Network.pm +++ b/src/PVE/QemuServer/Network.pm @@ -363,10 +363,10 @@ sub delete_ifaces_ipams_ips { } sub tap_plug { - my ($iface, $bridge, $tag, $firewall, $trunks, $rate) = @_; + my ($iface, $bridge, $tag, $firewall, $trunks, $rate, $opts) = @_; $firewall = $firewall && PVE::Firewall::Helpers::needs_fwbr($bridge); - PVE::Network::SDN::Zones::tap_plug($iface, $bridge, $tag, $firewall, $trunks, $rate); + PVE::Network::SDN::Zones::tap_plug($iface, $bridge, $tag, $firewall, $trunks, $rate, $opts); } sub get_nets_host_mtu { diff --git a/src/test/hotplug/net-change-bridge.conf.expected b/src/test/hotplug/net-change-bridge.conf.expected index a745b2e58e50..61d0f5b2d102 100644 --- a/src/test/hotplug/net-change-bridge.conf.expected +++ b/src/test/hotplug/net-change-bridge.conf.expected @@ -2,5 +2,6 @@ net tap_unplug ["tap8006i0"] qmp set_link {"name":"net0","up":false} sdn del_ips_from_mac ["vmbr0","A2:C0:43:77:08:A0","hotplug"] sdn add_next_free_cidr ["vmbr1","hotplug","A2:C0:43:77:08:A0","8006",null,1] -net tap_plug ["tap8006i0","vmbr1","100",null,null,null] +sdn add_dhcp_mapping ["vmbr1","A2:C0:43:77:08:A0","8006","hotplug"] +net tap_plug ["tap8006i0","vmbr1","100",null,null,null,{"mac":"A2:C0:43:77:08:A0"}] qmp set_link {"name":"net0","up":true} diff --git a/src/usr/pve-bridge b/src/usr/pve-bridge index c7260c6b5a82..20724271f9a4 100755 --- a/src/usr/pve-bridge +++ b/src/usr/pve-bridge @@ -43,7 +43,13 @@ die "unable to parse network config '$netid'\n" if !$net; PVE::Network::SDN::Vnets::add_dhcp_mapping($net->{bridge}, $net->{macaddr}, $vmid, $conf->{name}); PVE::Network::SDN::Zones::tap_create($iface, $net->{bridge}); PVE::QemuServer::Network::tap_plug( - $iface, $net->{bridge}, $net->{tag}, $net->{firewall}, $net->{trunks}, $net->{rate}, + $iface, + $net->{bridge}, + $net->{tag}, + $net->{firewall}, + $net->{trunks}, + $net->{rate}, + { mac => $net->{macaddr} }, ); exit 0; diff --git a/src/usr/pve-bridgedown b/src/usr/pve-bridgedown index e867b640207a..79a3722bd46a 100755 --- a/src/usr/pve-bridgedown +++ b/src/usr/pve-bridgedown @@ -2,7 +2,7 @@ use strict; use warnings; -use PVE::Network; +use PVE::Network::SDN::Zones; my $iface = shift; @@ -11,6 +11,6 @@ die "no interface specified\n" if !$iface; die "got strange interface name '$iface'\n" if $iface !~ m/^tap(\d+)i(\d+)$/; -PVE::Network::tap_unplug($iface); +PVE::Network::SDN::Zones::tap_unplug($iface); exit 0; -- 2.47.3