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 37C3A1FF0A7 for ; Wed, 02 Sep 2026 14:49:29 +0200 (CEST) Received: from gate001.proxmox.com (localhost.localdomain [127.0.0.1]) by gate001.proxmox.com (Proxmox) with ESMTP id 5841E21686; Wed, 02 Sep 2026 14:48:35 +0200 (CEST) From: Hannes Laimer To: pve-devel@lists.proxmox.com Subject: [PATCH pve-network 11/12] tests: cover the ebpf dhcp backend and ipam API mapping pushes Date: Wed, 2 Sep 2026 14:47:38 +0200 Message-ID: <20260902124739.750853-12-h.laimer@proxmox.com> X-Mailer: git-send-email 2.47.3 In-Reply-To: <20260902124739.750853-1-h.laimer@proxmox.com> References: <20260902124739.750853-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: 1788353268425 X-SPAM-LEVEL: Spam detection results: 0 AWL 0.644 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: C6PF3VDRKO5IZBS5X6KRK2M64CUMNW6T X-Message-ID-Hash: C6PF3VDRKO5IZBS5X6KRK2M64CUMNW6T 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: Signed-off-by: Hannes Laimer --- src/test/run_test_vnets_blackbox.pl | 147 ++++++++++++++++++++++++++++ 1 file changed, 147 insertions(+) diff --git a/src/test/run_test_vnets_blackbox.pl b/src/test/run_test_vnets_blackbox.pl index 9f4c424..fd63fd2 100755 --- a/src/test/run_test_vnets_blackbox.pl +++ b/src/test/run_test_vnets_blackbox.pl @@ -46,6 +46,7 @@ sub clear_test_state { vnets_config => {}, macdb => {}, ipamdb => {}, + ebpf_calls => [], ipam_config => { 'ids' => { 'pve' => { @@ -103,6 +104,13 @@ my $mocked_pve_sdn; $mocked_pve_sdn = Test::MockModule->new('PVE::Network::SDN'); $mocked_pve_sdn->mock( cfs_lock_file => $mocked_cfs_lock_file, + running_config => sub { + return { + zones => $test_state->{zones_config}, + vnets => $test_state->{vnets_config}, + subnets => $test_state->{subnets_config}, + }; + }, ); my $mocked_pve_tools = Test::MockModule->new('PVE::Tools'); @@ -224,6 +232,21 @@ $mocked_sdn_dhcp_dnsmasq->mock( update_lease => sub { }, ); +my $mocked_sdn_dhcp = Test::MockModule->new('PVE::Network::SDN::Dhcp'); +$mocked_sdn_dhcp->mock( + notify_guest_node => sub { }, +); + +my $mocked_pve_rs_dhcp = Test::MockModule->new('PVE::RS::SDN::Dhcp'); +$mocked_pve_rs_dhcp->mock( + map { + my $method = $_; + $method => sub { + push $test_state->{ebpf_calls}->@*, { method => $method, args => [@_] }; + }; + } qw(apply attach remove sync update) +); + my $mocked_api_zones = Test::MockModule->new('PVE::API2::Network::SDN::Zones'); $mocked_api_zones->mock( create_etc_interfaces_sdn_dir => sub { }, @@ -330,6 +353,22 @@ sub create_ip { return PVE::API2::Network::SDN::Ips->ipcreate($param); } +sub update_ip { + my ($param) = @_; + return PVE::API2::Network::SDN::Ips->ipupdate($param); +} + +sub delete_ip { + my ($param) = @_; + return PVE::API2::Network::SDN::Ips->ipdelete($param); +} + +sub take_ebpf_calls { + my $calls = $test_state->{ebpf_calls}; + $test_state->{ebpf_calls} = []; + return $calls; +} + sub run_test { my $test = shift; clear_test_state(); @@ -963,4 +1002,112 @@ run_test( 2, ); +# -------------- ebpf dhcp backend +sub test_ebpf_backend { + my $test_name = (split(/::/, (caller(0))[3]))[-1]; + my $zoneid = "TESTZONE"; + my $vnetid = "testvnet"; + my $mac = "da:65:8f:18:9b:6f"; + + create_zone({ + type => "simple", + dhcp => "ebpf", + ipam => "pve", + zone => $zoneid, + }); + + create_vnet({ + type => "vnet", + zone => $zoneid, + vnet => $vnetid, + }); + + create_subnet({ + type => "subnet", + vnet => $vnetid, + subnet => "10.0.0.0/24", + gateway => "10.0.0.1", + 'dhcp-range' => ["start-address=10.0.0.100,end-address=10.0.0.200"], + 'dhcp-lease-time' => 300, + }); + + take_ebpf_calls(); + + # guest start allocates from the range and pushes the record + eval { nic_start($vnetid, $mac, "999", "testhostname"); }; + if ($@) { + fail("$test_name: nic_start: $@"); + return; + } + + my $calls = take_ebpf_calls(); + my $record = sub { + my ($ip) = @_; + return { + mac => $mac, + ip => $ip, + prefixlen => 24, + server_id => "10.0.0.1", + lease => 300, + router => "10.0.0.1", + dns => undef, + mtu => 1500, + }; + }; + + eq_or_diff( + $calls, + [{ method => 'update', args => [[$record->("10.0.0.100")]] }], + "$test_name: guest start pushes the record", + ); + + # a mapping edit through the API replaces the record + update_ip({ + zone => $zoneid, + vnet => $vnetid, + mac => $mac, + ip => "10.0.0.150", + }); + + $calls = take_ebpf_calls(); + eq_or_diff( + $calls, + [ + { method => 'remove', args => [$mac] }, + { method => 'update', args => [[$record->("10.0.0.150")]] }, + ], + "$test_name: mapping edit replaces the record", + ); + + # a full regenerate refreshes the responder and translates into one sync + PVE::Network::SDN::Dhcp::regenerate_config(); + + $calls = take_ebpf_calls(); + eq_or_diff( + $calls, + [ + { method => 'apply', args => [] }, + { method => 'sync', args => [[$record->("10.0.0.150")]] }, + ], + "$test_name: regenerate refreshes the responder and syncs the full record set", + ); + + # deleting the mapping drops the record + delete_ip({ + zone => $zoneid, + vnet => $vnetid, + mac => $mac, + ip => "10.0.0.150", + }); + + $calls = take_ebpf_calls(); + eq_or_diff( + $calls, + [{ method => 'remove', args => [$mac] }], + "$test_name: mapping delete drops the record", + ); +} + +run_test(\&test_ebpf_backend); + done_testing(); -- 2.47.3