From 7638f25336ab2c05edc8b0c306176b356da1a98e Mon Sep 17 00:00:00 2001 From: Alexandre Derumier via pve-devel Date: Fri, 12 Apr 2024 14:57:42 +0200 Subject: [PATCH] fix #5364: bgp|evpn: derivated router-id from mac address for ipv6 underlay for ipv4, we use the iface ipv4 router-id as router-id need to 32bit. That's doesn't work for pure ipv6 underlay network. since https://www.rfc-editor.org/rfc/rfc6286, we can use any 32bit id, it's just need to be unique in the ASN. Simply use the last 4 bytes of iface mac address as unique id changelog V2: add missing test Signed-off-by: Alexandre Derumier Signed-off-by: Thomas Lamprecht --- src/PVE/Network/SDN/Controllers/BgpPlugin.pm | 3 +- src/PVE/Network/SDN/Controllers/EvpnPlugin.pm | 7 ++- src/PVE/Network/SDN/Controllers/Plugin.pm | 21 +++++++++ src/test/run_test_zones.pl | 8 ++++ .../ipv6underlay/expected_controller_config | 45 +++++++++++++++++++ .../evpn/ipv6underlay/expected_sdn_interfaces | 42 +++++++++++++++++ src/test/zones/evpn/ipv6underlay/interfaces | 7 +++ src/test/zones/evpn/ipv6underlay/sdn_config | 27 +++++++++++ 8 files changed, 157 insertions(+), 3 deletions(-) create mode 100644 src/test/zones/evpn/ipv6underlay/expected_controller_config create mode 100644 src/test/zones/evpn/ipv6underlay/expected_sdn_interfaces create mode 100644 src/test/zones/evpn/ipv6underlay/interfaces create mode 100644 src/test/zones/evpn/ipv6underlay/sdn_config diff --git a/src/PVE/Network/SDN/Controllers/BgpPlugin.pm b/src/PVE/Network/SDN/Controllers/BgpPlugin.pm index e001faa..53963e5 100644 --- a/src/PVE/Network/SDN/Controllers/BgpPlugin.pm +++ b/src/PVE/Network/SDN/Controllers/BgpPlugin.pm @@ -74,12 +74,13 @@ sub generate_controller_config { my $bgp = $config->{frr}->{router}->{"bgp $asn"} //= {}; my ($ifaceip, $interface) = PVE::Network::SDN::Zones::Plugin::find_local_ip_interface_peers(\@peers, $loopback); + my $routerid = PVE::Network::SDN::Controllers::Plugin::get_router_id($ifaceip, $interface); my $remoteas = $ebgp ? "external" : $asn; #global options my @controller_config = ( - "bgp router-id $ifaceip", + "bgp router-id $routerid", "no bgp default ipv4-unicast", "coalesce-time 1000" ); diff --git a/src/PVE/Network/SDN/Controllers/EvpnPlugin.pm b/src/PVE/Network/SDN/Controllers/EvpnPlugin.pm index 2b62276..c245ea2 100644 --- a/src/PVE/Network/SDN/Controllers/EvpnPlugin.pm +++ b/src/PVE/Network/SDN/Controllers/EvpnPlugin.pm @@ -70,12 +70,13 @@ sub generate_controller_config { my $bgp = $config->{frr}->{router}->{"bgp $asn"} //= {}; my ($ifaceip, $interface) = PVE::Network::SDN::Zones::Plugin::find_local_ip_interface_peers(\@peers, $loopback); + my $routerid = PVE::Network::SDN::Controllers::Plugin::get_router_id($ifaceip, $interface); my $remoteas = $ebgp ? "external" : $asn; #global options my @controller_config = ( - "bgp router-id $ifaceip", + "bgp router-id $routerid", "no bgp hard-administrative-reset", "no bgp default ipv4-unicast", "coalesce-time 1000", @@ -153,6 +154,8 @@ sub generate_controller_zone_config { return if !$vrf || !$vrfvxlan || !$asn; my ($ifaceip, $interface) = PVE::Network::SDN::Zones::Plugin::find_local_ip_interface_peers(\@peers, $loopback); + my $routerid = PVE::Network::SDN::Controllers::Plugin::get_router_id($ifaceip, $interface); + my $is_gateway = $exitnodes->{$local_node}; # vrf @@ -188,7 +191,7 @@ sub generate_controller_zone_config { #main vrf router @controller_config = (); - push @controller_config, "bgp router-id $ifaceip"; + push @controller_config, "bgp router-id $routerid"; push @controller_config, "no bgp hard-administrative-reset"; push @controller_config, "no bgp graceful-restart notification"; diff --git a/src/PVE/Network/SDN/Controllers/Plugin.pm b/src/PVE/Network/SDN/Controllers/Plugin.pm index c1c2cfd..5579513 100644 --- a/src/PVE/Network/SDN/Controllers/Plugin.pm +++ b/src/PVE/Network/SDN/Controllers/Plugin.pm @@ -118,4 +118,25 @@ sub on_update_hook { # do nothing by default } +#helpers + +sub read_iface_mac { + my ($iface) = @_; + return PVE::Tools::file_read_firstline("/sys/class/net/$iface/master/address"); +} + +sub get_router_id { + my ($ip, $iface) = @_; + + return $ip if Net::IP::ip_is_ipv4($ip); + + #for ipv6, use 4 last bytes of iface mac address as unique id + my $mac = read_iface_mac($iface); + + die "can't autofind a router-id value from ip or mac" if !$mac; + + my @mac_bytes = split(':', $mac); + return hex($mac_bytes[2]).".".hex($mac_bytes[3]).".".hex($mac_bytes[4]).".".hex($mac_bytes[5]); +} + 1; diff --git a/src/test/run_test_zones.pl b/src/test/run_test_zones.pl index 274a119..e506bea 100755 --- a/src/test/run_test_zones.pl +++ b/src/test/run_test_zones.pl @@ -99,6 +99,14 @@ foreach my $test (@tests) { }, ); + my $pve_sdn_controllers_plugin; + $pve_sdn_controllers_plugin = Test::MockModule->new('PVE::Network::SDN::Controllers::Plugin'); + $pve_sdn_controllers_plugin->mock( + read_iface_mac => sub { + return "bc:24:11:1d:69:60"; + }, + ); + my ($first_plugin) = %{$sdn_config->{controllers}->{ids}} if defined $sdn_config->{controllers}; if ($first_plugin) { my $controller_plugin = PVE::Network::SDN::Controllers::Plugin->lookup( diff --git a/src/test/zones/evpn/ipv6underlay/expected_controller_config b/src/test/zones/evpn/ipv6underlay/expected_controller_config new file mode 100644 index 0000000..fffd415 --- /dev/null +++ b/src/test/zones/evpn/ipv6underlay/expected_controller_config @@ -0,0 +1,45 @@ +frr version 8.5.2 +frr defaults datacenter +hostname localhost +log syslog informational +service integrated-vtysh-config +! +! +vrf vrf_myzone + vni 1000 +exit-vrf +! +router bgp 65000 + bgp router-id 17.29.105.96 + no bgp hard-administrative-reset + no bgp default ipv4-unicast + coalesce-time 1000 + no bgp graceful-restart notification + neighbor VTEP peer-group + neighbor VTEP remote-as 65000 + neighbor VTEP bfd + neighbor 2a08:2200:100:1::11 peer-group VTEP + neighbor 2a08:2200:100:1::12 peer-group VTEP + ! + 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 + exit-address-family +exit +! +router bgp 65000 vrf vrf_myzone + bgp router-id 17.29.105.96 + no bgp hard-administrative-reset + no bgp graceful-restart notification +exit +! +route-map MAP_VTEP_IN permit 1 +exit +! +route-map MAP_VTEP_OUT permit 1 +exit +! +line vty +! \ No newline at end of file diff --git a/src/test/zones/evpn/ipv6underlay/expected_sdn_interfaces b/src/test/zones/evpn/ipv6underlay/expected_sdn_interfaces new file mode 100644 index 0000000..3b91f75 --- /dev/null +++ b/src/test/zones/evpn/ipv6underlay/expected_sdn_interfaces @@ -0,0 +1,42 @@ +#version:1 + +auto myvnet +iface myvnet + address 2a08:2142:302:3::1/64 + hwaddress A2:1D:CB:1A:C0:8B + bridge_ports vxlan_myvnet + bridge_stp off + bridge_fd 0 + mtu 1450 + ip6-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 2a08:2200:100:1::10 + bridge-learning off + bridge-arp-nd-suppress on + mtu 1450 + +auto vxlan_myvnet +iface vxlan_myvnet + vxlan-id 100 + vxlan-local-tunnelip 2a08:2200:100:1::10 + bridge-learning off + bridge-arp-nd-suppress on + mtu 1450 diff --git a/src/test/zones/evpn/ipv6underlay/interfaces b/src/test/zones/evpn/ipv6underlay/interfaces new file mode 100644 index 0000000..602179b --- /dev/null +++ b/src/test/zones/evpn/ipv6underlay/interfaces @@ -0,0 +1,7 @@ +auto vmbr0 +iface vmbr0 inet static + address 2a08:2200:100:1::10/64 + gateway 2a08:2200:100:1::1 + bridge-ports eth0 + bridge-stp off + bridge-fd 0 diff --git a/src/test/zones/evpn/ipv6underlay/sdn_config b/src/test/zones/evpn/ipv6underlay/sdn_config new file mode 100644 index 0000000..eb139c0 --- /dev/null +++ b/src/test/zones/evpn/ipv6underlay/sdn_config @@ -0,0 +1,27 @@ +{ + 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' => '2a08:2200:100:1::10,2a08:2200:100:1::11,2a08:2200:100:1::12', asn => "65000" } }, + }, + + subnets => { + ids => { + 'myzone-2a08:2142:302:3::-64' => { + 'type' => 'subnet', + 'vnet' => 'myvnet', + 'gateway' => '2a08:2142:302:3::1', + } + } + } +} + + -- 2.39.2