From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from firstgate.proxmox.com (firstgate.proxmox.com [212.224.123.68]) by lore.proxmox.com (Postfix) with ESMTPS id 6AFD11FF13E for ; Fri, 06 Mar 2026 10:26:45 +0100 (CET) Received: from firstgate.proxmox.com (localhost [127.0.0.1]) by firstgate.proxmox.com (Proxmox) with ESMTP id 47C081CB1B; Fri, 6 Mar 2026 10:27:50 +0100 (CET) Message-ID: Date: Fri, 6 Mar 2026 10:27:45 +0100 MIME-Version: 1.0 User-Agent: Mozilla Thunderbird Subject: Re: [PATCH pve-network v3 2/9] test: add test for frr.conf.local merging To: Gabriel Goller , pve-devel@lists.proxmox.com References: <20260305100331.80741-1-g.goller@proxmox.com> <20260305100331.80741-12-g.goller@proxmox.com> Content-Language: en-US From: Stefan Hanreich In-Reply-To: <20260305100331.80741-12-g.goller@proxmox.com> Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 7bit X-SPAM-LEVEL: Spam detection results: 0 AWL 0.723 Adjusted score from AWL reputation of From: address BAYES_00 -1.9 Bayes spam probability is 0 to 1% DMARC_MISSING 0.1 Missing DMARC policy KAM_DMARC_STATUS 0.01 Test Rule for DKIM or SPF Failure with Strict Alignment RCVD_IN_MSPIKE_H2 0.001 Average reputation (+2) 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: ZI6P7Q4RLUUQK3A7RQ32T7ER42FMJAAC X-Message-ID-Hash: ZI6P7Q4RLUUQK3A7RQ32T7ER42FMJAAC X-MailFrom: s.hanreich@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: as we discussed off-list: We should have a section in this test-case for every supported line by the old conf.local parser. One that extends an existing section (if we generate one in the SDN stack) and one that adds a new section of the respective type. E.g. VRFs and ipv6 prefix-lists are completely missing. On 3/5/26 11:04 AM, Gabriel Goller wrote: > Add a test that tests the frr.conf.local merging. This should ensure we > do not run into further regressions. > > Signed-off-by: Gabriel Goller > --- > src/test/run_test_zones.pl | 16 +- > .../expected_controller_config | 148 ++++++++++++++++++ > .../frr_local_merge/expected_sdn_interfaces | 53 +++++++ > .../zones/evpn/frr_local_merge/frr.conf.local | 75 +++++++++ > .../zones/evpn/frr_local_merge/interfaces | 7 + > .../zones/evpn/frr_local_merge/sdn_config | 81 ++++++++++ > 6 files changed, 377 insertions(+), 3 deletions(-) > create mode 100644 src/test/zones/evpn/frr_local_merge/expected_controller_config > create mode 100644 src/test/zones/evpn/frr_local_merge/expected_sdn_interfaces > create mode 100644 src/test/zones/evpn/frr_local_merge/frr.conf.local > create mode 100644 src/test/zones/evpn/frr_local_merge/interfaces > create mode 100644 src/test/zones/evpn/frr_local_merge/sdn_config > > diff --git a/src/test/run_test_zones.pl b/src/test/run_test_zones.pl > index 905b2f42e1dc..806225735e6b 100755 > --- a/src/test/run_test_zones.pl > +++ b/src/test/run_test_zones.pl > @@ -126,12 +126,22 @@ foreach my $test (@tests) { > reload_controller => sub { > return; > }, > - read_local_frr_config => sub { > - return; > - }, > ); > } > > + # Mock read_local_frr_config in PVE::Network::SDN::Frr to support testing frr.conf.local merging > + my $frr_local_config; > + my $frr_local_path = "./$test/frr.conf.local"; > + if (-e $frr_local_path) { > + $frr_local_config = read_file($frr_local_path); > + } > + my $mocked_frr = Test::MockModule->new('PVE::Network::SDN::Frr'); > + $mocked_frr->mock( > + read_local_frr_config => sub { > + return $frr_local_config; > + }, > + ); > + > my $name = $test; > my $expected = read_file("./$test/expected_sdn_interfaces"); > > diff --git a/src/test/zones/evpn/frr_local_merge/expected_controller_config b/src/test/zones/evpn/frr_local_merge/expected_controller_config > new file mode 100644 > index 000000000000..82f36c9e37ec > --- /dev/null > +++ b/src/test/zones/evpn/frr_local_merge/expected_controller_config > @@ -0,0 +1,148 @@ > +frr version 10.4.1 > +frr defaults datacenter > +hostname localhost > +log syslog informational > +service integrated-vtysh-config > +! > +! > +vrf vrf_myzone > + vni 1000 > +exit-vrf > +! > +interface ens19 > + no ip ospf passive > +! > +interface eth0 > + ip router isis isis1 > +! > +interface eth1 > + ip router isis isis1 > + isis circuit-type level-2-only > +! > +interface iface2 > + ip ospf area 0 > +! > +router bgp 65000 > + bgp router-id 192.168.0.1 > + no bgp default ipv4-unicast > + coalesce-time 1000 > + bgp disable-ebgp-connected-route-check > + neighbor BGP peer-group > + neighbor BGP remote-as external > + neighbor BGP bfd > + neighbor 172.16.0.254 peer-group BGP > + neighbor 172.17.0.254 peer-group BGP > + neighbor VTEP peer-group > + neighbor VTEP remote-as 65000 > + neighbor VTEP bfd > + neighbor VTEP update-source dummy1 > + neighbor 192.168.0.2 peer-group VTEP > + neighbor 192.168.0.3 peer-group VTEP > + neighbor 192.168.1.1 remote-as 65001 > + neighbor 192.168.1.1 description "External Peer" > + neighbor VTEP prefix-list MY_PREFIX_LIST out > + neighbor VTEP allowas-in 1 > + neighbor VTEP remote-as 64600 > + no neighbor VTEP peer-group > + ! > + address-family ipv4 unicast > + network 192.168.0.1/32 > + neighbor BGP activate > + neighbor BGP soft-reconfiguration inbound > + neighbor VTEP activate > + exit-address-family > + ! > + address-family l2vpn evpn > + neighbor VTEP activate > + neighbor VTEP route-map MAP_VTEP_IN in > + neighbor VTEP route-map MAP_VTEP_OUT out > + advertise-all-vni > + advertise-svi-ip > + no neighbor VTEP route-map MAP_VTEP_IN in > + neighbor VTEP route-map MAP_VTEP_IN_CUSTOM in > + exit-address-family > +exit > +! > +router bgp 65000 vrf vrf_myzone > + bgp router-id 192.168.0.1 > + no bgp hard-administrative-reset > + no bgp graceful-restart notification > +exit > +! > +router eigrp 1 > + network 10.0.0.0/8 > +exit > +! > +router isis isis1 > + net 47.0023.0000.0000.0000.0000.0000.0000.1900.0004.00 > + redistribute ipv4 connected level-1 > + redistribute ipv6 connected level-1 > + log-adjacency-changes > +exit > +! > +router ospf > + passive-interface default > +exit > +! > +ip prefix-list PL_ALLOW seq 10 permit 10.0.0.0/8 le 24 > +ip prefix-list loopbacks_ips seq 10 permit 0.0.0.0/0 le 32 > +! > +bgp community-list standard CL_LOCAL permit 65000:200 > +! > +route-map CUSTOM_MAP permit 1 > + match ip address prefix-list PL_ALLOW > +exit > +! > +route-map MAP_VTEP_IN permit 1 > +exit > +! > +route-map MAP_VTEP_IN permit 2 > + set community 65000:200 > +exit > +! > +route-map MAP_VTEP_OUT permit 1 > +exit > +! > +route-map MAP_VTEP_OUT permit 2 > + set community 65000:100 > +exit > +! > +route-map MAP_VTEP_OUT permit 3 > + match ip next-hop LOCAL > +exit > +! > +route-map correct_src permit 1 > + match ip address prefix-list loopbacks_ips > + set src 192.168.0.1 > +exit > +! > +route-map correct_src deny 2 > + match ip next-hop NOT_LOCAL > +exit > +! > +ip protocol bgp route-map correct_src > +router ospf > + ospf router-id 172.20.30.1 > +exit > +! > +interface dummy_test > + ip ospf area 0 > + ip ospf passive > +exit > +! > +interface ens19 > + ip ospf area 0 > +exit > +! > +access-list pve_ospf_test_ips permit 172.20.30.0/24 > +! > +route-map pve_ospf permit 100 > + match ip address pve_ospf_test_ips > + set src 172.20.30.1 > +exit > +! > +ip protocol ospf route-map pve_ospf > +! > +! > +line vty > +! > diff --git a/src/test/zones/evpn/frr_local_merge/expected_sdn_interfaces b/src/test/zones/evpn/frr_local_merge/expected_sdn_interfaces > new file mode 100644 > index 000000000000..c7ddf44ef6d3 > --- /dev/null > +++ b/src/test/zones/evpn/frr_local_merge/expected_sdn_interfaces > @@ -0,0 +1,53 @@ > +#version:1 > + > +auto myvnet > +iface myvnet > + address 10.0.0.1/24 > + hwaddress A2:1D:CB:1A:C0:8B > + bridge_ports vxlan_myvnet > + bridge_stp off > + bridge_fd 0 > + mtu 1450 > + ip-forward on > + arp-accept on > + vrf vrf_myzone > + > +auto vrf_myzone > +iface vrf_myzone > + vrf-table auto > + post-up ip route add vrf vrf_myzone unreachable default metric 4278198272 > + > +auto vrfbr_myzone > +iface vrfbr_myzone > + bridge-ports vrfvx_myzone > + bridge_stp off > + bridge_fd 0 > + mtu 1450 > + vrf vrf_myzone > + > +auto vrfvx_myzone > +iface vrfvx_myzone > + vxlan-id 1000 > + vxlan-local-tunnelip 192.168.0.1 > + bridge-learning off > + bridge-arp-nd-suppress on > + mtu 1450 > + > +auto vxlan_myvnet > +iface vxlan_myvnet > + vxlan-id 100 > + vxlan-local-tunnelip 192.168.0.1 > + bridge-learning off > + bridge-arp-nd-suppress on > + mtu 1450 > + > +auto dummy_test > +iface dummy_test inet static > + address 172.20.30.1/32 > + link-type dummy > + ip-forward 1 > + > +auto ens19 > +iface ens19 inet static > + address 172.16.3.10/31 > + ip-forward 1 > diff --git a/src/test/zones/evpn/frr_local_merge/frr.conf.local b/src/test/zones/evpn/frr_local_merge/frr.conf.local > new file mode 100644 > index 000000000000..9003dd47c83b > --- /dev/null > +++ b/src/test/zones/evpn/frr_local_merge/frr.conf.local > @@ -0,0 +1,75 @@ > +! > +! Custom FRR configuration to be merged > +! > +ip nht resolve-via-default > +! > +ip route 192.0.2.0/24 198.51.100.1 > +! > +ip protocol bgp route-map correct_src > +! > +router bgp 65000 > + neighbor 192.168.1.1 remote-as 65001 > + neighbor 192.168.1.1 description "External Peer" > + address-family l2vpn evpn > + advertise-svi-ip > + exit-address-family > + address-family ipv4 unicast > + neighbor VTEP activate > + exit-address-family > +exit > +! > +route-map MAP_VTEP_OUT permit 1 > + set community 65000:100 > +exit > +! > +route-map MAP_VTEP_OUT permit 2 > + match ip next-hop LOCAL > +exit > +! > +route-map correct_src deny 1 > + match ip next-hop NOT_LOCAL > +exit > +! > +route-map MAP_VTEP_IN permit 2 > + set community 65000:200 > +exit > +! > +ip prefix-list PL_ALLOW seq 10 permit 10.0.0.0/8 le 24 > +! > +route-map CUSTOM_MAP permit 10 > + match ip address prefix-list PL_ALLOW > +exit > +! > +bgp community-list standard CL_LOCAL permit 65000:200 > +! > +interface eth1 > + isis circuit-type level-2-only > +exit > +! > +interface iface2 > + ip ospf area 0 > +exit > +! > +interface ens19 > + no ip ospf passive > +exit > +! > +router ospf > + passive-interface default > +exit > +! > +router bgp 65000 > + neighbor VTEP prefix-list MY_PREFIX_LIST out > + neighbor VTEP allowas-in 1 > + neighbor VTEP remote-as 64600 > + no neighbor VTEP peer-group > + address-family l2vpn evpn > + no neighbor VTEP route-map MAP_VTEP_IN in > + neighbor VTEP route-map MAP_VTEP_IN_CUSTOM in > + exit-address-family > +exit > +! > +router eigrp 1 > + network 10.0.0.0/8 > +exit > +! > diff --git a/src/test/zones/evpn/frr_local_merge/interfaces b/src/test/zones/evpn/frr_local_merge/interfaces > new file mode 100644 > index 000000000000..66bb826a44b3 > --- /dev/null > +++ b/src/test/zones/evpn/frr_local_merge/interfaces > @@ -0,0 +1,7 @@ > +auto vmbr0 > +iface vmbr0 inet static > + address 192.168.0.1/24 > + gateway 192.168.0.254 > + bridge-ports eth0 > + bridge-stp off > + bridge-fd 0 > diff --git a/src/test/zones/evpn/frr_local_merge/sdn_config b/src/test/zones/evpn/frr_local_merge/sdn_config > new file mode 100644 > index 000000000000..4f90ab416495 > --- /dev/null > +++ b/src/test/zones/evpn/frr_local_merge/sdn_config > @@ -0,0 +1,81 @@ > +{ > + version => 1, > + vnets => { > + ids => { > + myvnet => { tag => "100", type => "vnet", zone => "myzone" }, > + }, > + }, > + > + zones => { > + ids => { myzone => { ipam => "pve", type => "evpn", controller => "evpnctl", 'vrf-vxlan' => 1000, 'mac' => 'A2:1D:CB:1A:C0:8B' } }, > + }, > + controllers => { > + ids => { > + evpnctl => { > + type => "evpn", > + 'peers' => '192.168.0.1,192.168.0.2,192.168.0.3', > + asn => "65000" > + }, > + bgplocalhost => { > + type => "bgp", > + 'peers' => '172.16.0.254,172.17.0.254', > + ebgp => "1", > + asn => "65000", > + loopback => 'dummy1', > + node => "localhost" > + }, > + localhost => { > + type => "isis", > + 'isis-domain' => 'isis1', > + 'isis-ifaces' => 'eth1,eth0', > + 'isis-net' => "47.0023.0000.0000.0000.0000.0000.0000.1900.0004.00", > + loopback => 'dummy1', > + node => "localhost", > + }, > + }, > + }, > + > + subnets => { > + ids => { > + 'myzone-10.0.0.0-24' => { > + 'type' => 'subnet', > + 'vnet' => 'myvnet', > + 'gateway' => '10.0.0.1', > + } > + } > + }, > + fabrics => { > + ids => { > + test_pathfinder => { > + id => 'test_pathfinder', > + interfaces => [ > + 'name=ens19,ip=172.16.3.20/31' > + ], > + ip => '172.20.30.2', > + type => 'ospf_node' > + }, > + test => { > + ip_prefix => '172.20.30.0/24', > + area => '0', > + type => 'ospf_fabric', > + id => 'test', > + }, > + test_localhost => { > + id => 'test_localhost', > + interfaces => [ > + 'name=ens19,ip=172.16.3.10/31' > + ], > + ip => '172.20.30.1', > + type => 'ospf_node' > + }, > + test_raider => { > + type => 'ospf_node', > + ip => '172.20.30.3', > + id => 'test_raider', > + interfaces => [ > + 'name=ens19,ip=172.16.3.30/31' > + ] > + } > + } > + } > +}