From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from firstgate.proxmox.com (firstgate.proxmox.com [212.224.123.68]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits)) (No client certificate requested) by lists.proxmox.com (Postfix) with ESMTPS id 4B040621E3 for ; Fri, 11 Feb 2022 10:33:54 +0100 (CET) Received: from firstgate.proxmox.com (localhost [127.0.0.1]) by firstgate.proxmox.com (Proxmox) with ESMTP id B79CF268BC for ; Fri, 11 Feb 2022 10:33:53 +0100 (CET) Received: from bastionodiso.odiso.net (bastionodiso.odiso.net [185.151.191.93]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits)) (No client certificate requested) by firstgate.proxmox.com (Proxmox) with ESMTPS id F309C26652 for ; Fri, 11 Feb 2022 10:33:40 +0100 (CET) Received: from kvmformation3.odiso.net (formationkvm3.odiso.net [10.3.94.12]) by bastionodiso.odiso.net (Postfix) with ESMTP id 2C2B416ACAC; Fri, 11 Feb 2022 10:33:34 +0100 (CET) Received: by kvmformation3.odiso.net (Postfix, from userid 0) id 11D101295CE; Fri, 11 Feb 2022 10:33:34 +0100 (CET) From: Alexandre Derumier To: pve-devel@lists.proxmox.com Date: Fri, 11 Feb 2022 10:33:26 +0100 Message-Id: <20220211093331.609127-6-aderumier@odiso.com> X-Mailer: git-send-email 2.30.2 In-Reply-To: <20220211093331.609127-1-aderumier@odiso.com> References: <20220211093331.609127-1-aderumier@odiso.com> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-SPAM-LEVEL: Spam detection results: 0 AWL 0.112 Adjusted score from AWL reputation of From: address BAYES_00 -1.9 Bayes spam probability is 0 to 1% HEADER_FROM_DIFFERENT_DOMAINS 0.248 From and EnvelopeFrom 2nd level mail domains are different KAM_DMARC_STATUS 0.01 Test Rule for DKIM or SPF Failure with Strict Alignment KAM_LAZY_DOMAIN_SECURITY 1 Sending domain does not have any anti-forgery methods NO_DNS_FOR_FROM 0.001 Envelope sender has no MX or A DNS records SPF_HELO_NONE 0.001 SPF: HELO does not publish an SPF Record SPF_NONE 0.001 SPF: sender does not publish an SPF Record T_SCC_BODY_TEXT_LINE -0.01 - Subject: [pve-devel] [PATCH pve-network 05/10] controllers: evpn/bgp : add exitnodes-primary && rework route-map X-BeenThere: pve-devel@lists.proxmox.com X-Mailman-Version: 2.1.29 Precedence: list List-Id: Proxmox VE development discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 11 Feb 2022 09:33:54 -0000 exitnodes-primary option force traffic to a primary node A route-map is used to increase metric on backup nodes. This can be usefull for snat or avoid asymetric routing. Route-map is rework to handle multiple sequences of route map. Signed-off-by: Alexandre Derumier --- PVE/Network/SDN/Controllers/BgpPlugin.pm | 7 ++- PVE/Network/SDN/Controllers/EvpnPlugin.pm | 33 +++++++++- PVE/Network/SDN/Zones/EvpnPlugin.pm | 3 + .../expected_controller_config | 3 + .../expected_controller_config | 3 + .../evpn/ebgp/expected_controller_config | 3 + .../ebgp_loopback/expected_controller_config | 3 + .../evpn/exitnode/expected_controller_config | 3 + .../expected_controller_config | 3 + .../expected_controller_config | 61 +++++++++++++++++++ .../exitnode_primary/expected_sdn_interfaces | 41 +++++++++++++ test/zones/evpn/exitnode_primary/interfaces | 7 +++ test/zones/evpn/exitnode_primary/sdn_config | 26 ++++++++ .../exitnode_snat/expected_controller_config | 3 + .../evpn/ipv4/expected_controller_config | 3 + .../evpn/ipv4ipv6/expected_controller_config | 3 + .../expected_controller_config | 3 + .../evpn/ipv6/expected_controller_config | 3 + .../expected_controller_config | 3 + 19 files changed, 210 insertions(+), 4 deletions(-) create mode 100644 test/zones/evpn/exitnode_primary/expected_controller_config create mode 100644 test/zones/evpn/exitnode_primary/expected_sdn_interfaces create mode 100644 test/zones/evpn/exitnode_primary/interfaces create mode 100644 test/zones/evpn/exitnode_primary/sdn_config diff --git a/PVE/Network/SDN/Controllers/BgpPlugin.pm b/PVE/Network/SDN/Controllers/BgpPlugin.pm index 1e4e708..70c7264 100644 --- a/PVE/Network/SDN/Controllers/BgpPlugin.pm +++ b/PVE/Network/SDN/Controllers/BgpPlugin.pm @@ -122,8 +122,11 @@ sub generate_controller_config { if ($loopback) { push(@{$config->{frr}->{''}}, "ip prefix-list loopbacks_ips seq 10 permit 0.0.0.0/0 le 32"); push(@{$config->{frr}->{''}}, "ip protocol bgp route-map correct_src"); - push(@{$config->{frr}->{'route-map'}->{'correct_src permit 1'}}, "match ip address prefix-list loopbacks_ips"); - push(@{$config->{frr}->{'route-map'}->{'correct_src permit 1'}}, "set src $ifaceip"); + + my $routemap_config = []; + push @{$routemap_config}, "match ip address prefix-list loopbacks_ips"; + push @{$routemap_config}, "set src $ifaceip"; + push(@{$config->{frr_routemap}->{'correct_src'}}, $routemap_config); } return $config; diff --git a/PVE/Network/SDN/Controllers/EvpnPlugin.pm b/PVE/Network/SDN/Controllers/EvpnPlugin.pm index d02bdf7..2b48e9a 100644 --- a/PVE/Network/SDN/Controllers/EvpnPlugin.pm +++ b/PVE/Network/SDN/Controllers/EvpnPlugin.pm @@ -99,11 +99,14 @@ sub generate_controller_config { # address-family l2vpn @controller_config = (); + push @controller_config, "neighbor VTEP route-map MAP_VTEP_OUT out"; push @controller_config, "neighbor VTEP activate"; push @controller_config, "advertise-all-vni"; push @controller_config, "autort as $autortas" if $autortas; push(@{$bgp->{"address-family"}->{"l2vpn evpn"}}, @controller_config); + push(@{$config->{frr_routemap}->{'MAP_VTEP_OUT'}}, []); + return $config; } @@ -115,6 +118,7 @@ sub generate_controller_zone_config { my $vrf = "vrf_$id"; my $vrfvxlan = $plugin_config->{'vrf-vxlan'}; my $exitnodes = $plugin_config->{'exitnodes'}; + my $exitnodes_primary = $plugin_config->{'exitnodes-primary'}; my $advertisesubnets = $plugin_config->{'advertise-subnets'}; my $exitnodes_local_routing = $plugin_config->{'exitnodes-local-routing'}; @@ -152,6 +156,14 @@ sub generate_controller_zone_config { if ($is_gateway) { + if($exitnodes_primary && $exitnodes_primary ne $local_node) { + my $routemap_config = (); + push @{$routemap_config}, "match evpn vni $vrfvxlan"; + push @{$routemap_config}, "match evpn route-type prefix"; + push @{$routemap_config}, "set metric 200"; + unshift(@{$config->{frr_routemap}->{'MAP_VTEP_OUT'}}, $routemap_config); + } + if (!$exitnodes_local_routing) { @controller_config = (); #import /32 routes of evpn network from vrf1 to default vrf (for packet return) @@ -260,7 +272,6 @@ sub sort_frr_config { $order->{'ipv4 unicast'} = 1; $order->{'ipv6 unicast'} = 2; $order->{'l2vpn evpn'} = 3; - $order->{'route-map'} = 200; my $a_val = 100; my $b_val = 100; @@ -286,7 +297,6 @@ sub generate_frr_recurse{ $keylist->{vrf} = 1; $keylist->{'address-family'} = 1; $keylist->{router} = 1; - $keylist->{'route-map'} = 1; my $exitkeylist = {}; $exitkeylist->{vrf} = 1; @@ -324,6 +334,23 @@ sub generate_frr_recurse{ } } +sub generate_frr_routemap { + my ($final_config, $routemaps) = @_; + + foreach my $id (sort keys %$routemaps) { + + my $routemap = $routemaps->{$id}; + my $order = 0; + foreach my $seq (@$routemap) { + $order++; + my @config = (); + push @config, "!"; + push @config, "route-map $id permit $order"; + push @config, map { " $_" } @$seq; + push @{$final_config}, @config; + } + } +} sub generate_controller_rawconfig { my ($class, $plugin_config, $config) = @_; @@ -340,6 +367,7 @@ sub generate_controller_rawconfig { if (-e "/etc/frr/frr.conf.local") { generate_frr_recurse($final_config, $config->{frr}->{vrf}, "vrf", 1); + generate_frr_routemap($final_config, $config->{frr_routemap}); push @{$final_config}, "!"; my $local_conf = file_get_contents("/etc/frr/frr.conf.local"); @@ -347,6 +375,7 @@ sub generate_controller_rawconfig { push @{$final_config}, $local_conf; } else { generate_frr_recurse($final_config, $config->{frr}, undef, 0); + generate_frr_routemap($final_config, $config->{frr_routemap}); } push @{$final_config}, "!"; diff --git a/PVE/Network/SDN/Zones/EvpnPlugin.pm b/PVE/Network/SDN/Zones/EvpnPlugin.pm index 50ea619..62c968c 100644 --- a/PVE/Network/SDN/Zones/EvpnPlugin.pm +++ b/PVE/Network/SDN/Zones/EvpnPlugin.pm @@ -40,6 +40,8 @@ sub properties { description => "Allow exitnodes to connect to evpn guests", optional => 1 }, + 'exitnodes-primary' => get_standard_option('pve-node', { + description => "Force traffic to this exitnode first."}), 'advertise-subnets' => { type => 'boolean', description => "Advertise evpn subnets if you have silent hosts", @@ -60,6 +62,7 @@ sub options { controller => { optional => 0 }, exitnodes => { optional => 1 }, 'exitnodes-local-routing' => { optional => 1 }, + 'exitnodes-primary' => { optional => 1 }, 'advertise-subnets' => { optional => 1 }, 'disable-arp-nd-suppression' => { optional => 1 }, mtu => { optional => 1 }, diff --git a/test/zones/evpn/advertise_subnets/expected_controller_config b/test/zones/evpn/advertise_subnets/expected_controller_config index aa6b3bd..cdaf0d4 100644 --- a/test/zones/evpn/advertise_subnets/expected_controller_config +++ b/test/zones/evpn/advertise_subnets/expected_controller_config @@ -21,6 +21,7 @@ router bgp 65000 neighbor 192.168.0.3 peer-group VTEP ! address-family l2vpn evpn + neighbor VTEP route-map MAP_VTEP_OUT out neighbor VTEP activate advertise-all-vni exit-address-family @@ -40,5 +41,7 @@ router bgp 65000 vrf vrf_myzone advertise ipv6 unicast exit-address-family ! +route-map MAP_VTEP_OUT permit 1 +! line vty ! \ No newline at end of file diff --git a/test/zones/evpn/disable_arp_nd_suppression/expected_controller_config b/test/zones/evpn/disable_arp_nd_suppression/expected_controller_config index c0ca898..e1d425f 100644 --- a/test/zones/evpn/disable_arp_nd_suppression/expected_controller_config +++ b/test/zones/evpn/disable_arp_nd_suppression/expected_controller_config @@ -21,11 +21,14 @@ router bgp 65000 neighbor 192.168.0.3 peer-group VTEP ! address-family l2vpn evpn + neighbor VTEP route-map MAP_VTEP_OUT out neighbor VTEP activate advertise-all-vni exit-address-family ! router bgp 65000 vrf vrf_myzone ! +route-map MAP_VTEP_OUT permit 1 +! line vty ! \ No newline at end of file diff --git a/test/zones/evpn/ebgp/expected_controller_config b/test/zones/evpn/ebgp/expected_controller_config index be3e1af..f6c8f18 100644 --- a/test/zones/evpn/ebgp/expected_controller_config +++ b/test/zones/evpn/ebgp/expected_controller_config @@ -33,6 +33,7 @@ router bgp 65001 exit-address-family ! address-family l2vpn evpn + neighbor VTEP route-map MAP_VTEP_OUT out neighbor VTEP activate advertise-all-vni autort as 65000 @@ -46,5 +47,7 @@ router bgp 65001 vrf vrf_myzone route-target export 65000:1000 exit-address-family ! +route-map MAP_VTEP_OUT permit 1 +! line vty ! \ No newline at end of file diff --git a/test/zones/evpn/ebgp_loopback/expected_controller_config b/test/zones/evpn/ebgp_loopback/expected_controller_config index 01cb2c2..64dff4e 100644 --- a/test/zones/evpn/ebgp_loopback/expected_controller_config +++ b/test/zones/evpn/ebgp_loopback/expected_controller_config @@ -38,6 +38,7 @@ router bgp 65001 exit-address-family ! address-family l2vpn evpn + neighbor VTEP route-map MAP_VTEP_OUT out neighbor VTEP activate advertise-all-vni autort as 65000 @@ -51,6 +52,8 @@ router bgp 65001 vrf vrf_myzone route-target export 65000:1000 exit-address-family ! +route-map MAP_VTEP_OUT permit 1 +! route-map correct_src permit 1 match ip address prefix-list loopbacks_ips set src 192.168.0.1 diff --git a/test/zones/evpn/exitnode/expected_controller_config b/test/zones/evpn/exitnode/expected_controller_config index 57ff6ff..8a535b3 100644 --- a/test/zones/evpn/exitnode/expected_controller_config +++ b/test/zones/evpn/exitnode/expected_controller_config @@ -29,6 +29,7 @@ router bgp 65000 exit-address-family ! address-family l2vpn evpn + neighbor VTEP route-map MAP_VTEP_OUT out neighbor VTEP activate advertise-all-vni exit-address-family @@ -48,5 +49,7 @@ router bgp 65000 vrf vrf_myzone default-originate ipv6 exit-address-family ! +route-map MAP_VTEP_OUT permit 1 +! line vty ! \ No newline at end of file diff --git a/test/zones/evpn/exitnode_local_routing/expected_controller_config b/test/zones/evpn/exitnode_local_routing/expected_controller_config index abd065b..876da86 100644 --- a/test/zones/evpn/exitnode_local_routing/expected_controller_config +++ b/test/zones/evpn/exitnode_local_routing/expected_controller_config @@ -22,6 +22,7 @@ router bgp 65000 neighbor 192.168.0.3 peer-group VTEP ! address-family l2vpn evpn + neighbor VTEP route-map MAP_VTEP_OUT out neighbor VTEP activate advertise-all-vni exit-address-family @@ -33,5 +34,7 @@ router bgp 65000 vrf vrf_myzone default-originate ipv6 exit-address-family ! +route-map MAP_VTEP_OUT permit 1 +! line vty ! \ No newline at end of file diff --git a/test/zones/evpn/exitnode_primary/expected_controller_config b/test/zones/evpn/exitnode_primary/expected_controller_config new file mode 100644 index 0000000..5306645 --- /dev/null +++ b/test/zones/evpn/exitnode_primary/expected_controller_config @@ -0,0 +1,61 @@ +log syslog informational +ip forwarding +ipv6 forwarding +frr defaults datacenter +service integrated-vtysh-config +hostname localhost +! +! +vrf vrf_myzone + vni 1000 +exit-vrf +! +router bgp 65000 + bgp router-id 192.168.0.1 + no bgp default ipv4-unicast + coalesce-time 1000 + neighbor VTEP peer-group + neighbor VTEP remote-as 65000 + neighbor VTEP bfd + neighbor 192.168.0.2 peer-group VTEP + neighbor 192.168.0.3 peer-group VTEP + ! + address-family ipv4 unicast + import vrf vrf_myzone + exit-address-family + ! + address-family ipv6 unicast + import vrf vrf_myzone + exit-address-family + ! + address-family l2vpn evpn + neighbor VTEP route-map MAP_VTEP_OUT out + neighbor VTEP activate + advertise-all-vni + exit-address-family +! +router bgp 65000 vrf vrf_myzone + bgp router-id 192.168.0.1 + ! + address-family ipv4 unicast + redistribute connected + exit-address-family + ! + address-family ipv6 unicast + redistribute connected + exit-address-family + ! + address-family l2vpn evpn + default-originate ipv4 + default-originate ipv6 + exit-address-family +! +route-map MAP_VTEP_OUT permit 1 + match evpn vni 1000 + match evpn route-type prefix + set metric 200 +! +route-map MAP_VTEP_OUT permit 2 +! +line vty +! \ No newline at end of file diff --git a/test/zones/evpn/exitnode_primary/expected_sdn_interfaces b/test/zones/evpn/exitnode_primary/expected_sdn_interfaces new file mode 100644 index 0000000..5ab3084 --- /dev/null +++ b/test/zones/evpn/exitnode_primary/expected_sdn_interfaces @@ -0,0 +1,41 @@ +#version:1 + +auto myvnet +iface myvnet + address 10.0.0.1/24 + 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 del 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 diff --git a/test/zones/evpn/exitnode_primary/interfaces b/test/zones/evpn/exitnode_primary/interfaces new file mode 100644 index 0000000..66bb826 --- /dev/null +++ b/test/zones/evpn/exitnode_primary/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/test/zones/evpn/exitnode_primary/sdn_config b/test/zones/evpn/exitnode_primary/sdn_config new file mode 100644 index 0000000..bfeafc5 --- /dev/null +++ b/test/zones/evpn/exitnode_primary/sdn_config @@ -0,0 +1,26 @@ +{ + version => 1, + vnets => { + ids => { + myvnet => { tag => "100", type => "vnet", zone => "myzone" }, + }, + }, + + zones => { + ids => { myzone => { ipam => "pve", type => "evpn", controller => "evpnctl", 'vrf-vxlan' => 1000, 'exitnodes-primary' => "othernode", exitnodes => { 'localhost' => 1 } } }, + }, + controllers => { + ids => { evpnctl => { type => "evpn", 'peers' => '192.168.0.1,192.168.0.2,192.168.0.3', asn => "65000" } }, + }, + + subnets => { + ids => { 'myzone-10.0.0.0-24' => { + 'type' => 'subnet', + 'vnet' => 'myvnet', + 'gateway' => '10.0.0.1', + } + } + } +} + + diff --git a/test/zones/evpn/exitnode_snat/expected_controller_config b/test/zones/evpn/exitnode_snat/expected_controller_config index 57ff6ff..8a535b3 100644 --- a/test/zones/evpn/exitnode_snat/expected_controller_config +++ b/test/zones/evpn/exitnode_snat/expected_controller_config @@ -29,6 +29,7 @@ router bgp 65000 exit-address-family ! address-family l2vpn evpn + neighbor VTEP route-map MAP_VTEP_OUT out neighbor VTEP activate advertise-all-vni exit-address-family @@ -48,5 +49,7 @@ router bgp 65000 vrf vrf_myzone default-originate ipv6 exit-address-family ! +route-map MAP_VTEP_OUT permit 1 +! line vty ! \ No newline at end of file diff --git a/test/zones/evpn/ipv4/expected_controller_config b/test/zones/evpn/ipv4/expected_controller_config index c0ca898..e1d425f 100644 --- a/test/zones/evpn/ipv4/expected_controller_config +++ b/test/zones/evpn/ipv4/expected_controller_config @@ -21,11 +21,14 @@ router bgp 65000 neighbor 192.168.0.3 peer-group VTEP ! address-family l2vpn evpn + neighbor VTEP route-map MAP_VTEP_OUT out neighbor VTEP activate advertise-all-vni exit-address-family ! router bgp 65000 vrf vrf_myzone ! +route-map MAP_VTEP_OUT permit 1 +! line vty ! \ No newline at end of file diff --git a/test/zones/evpn/ipv4ipv6/expected_controller_config b/test/zones/evpn/ipv4ipv6/expected_controller_config index c0ca898..e1d425f 100644 --- a/test/zones/evpn/ipv4ipv6/expected_controller_config +++ b/test/zones/evpn/ipv4ipv6/expected_controller_config @@ -21,11 +21,14 @@ router bgp 65000 neighbor 192.168.0.3 peer-group VTEP ! address-family l2vpn evpn + neighbor VTEP route-map MAP_VTEP_OUT out neighbor VTEP activate advertise-all-vni exit-address-family ! router bgp 65000 vrf vrf_myzone ! +route-map MAP_VTEP_OUT permit 1 +! line vty ! \ No newline at end of file diff --git a/test/zones/evpn/ipv4ipv6nogateway/expected_controller_config b/test/zones/evpn/ipv4ipv6nogateway/expected_controller_config index c0ca898..e1d425f 100644 --- a/test/zones/evpn/ipv4ipv6nogateway/expected_controller_config +++ b/test/zones/evpn/ipv4ipv6nogateway/expected_controller_config @@ -21,11 +21,14 @@ router bgp 65000 neighbor 192.168.0.3 peer-group VTEP ! address-family l2vpn evpn + neighbor VTEP route-map MAP_VTEP_OUT out neighbor VTEP activate advertise-all-vni exit-address-family ! router bgp 65000 vrf vrf_myzone ! +route-map MAP_VTEP_OUT permit 1 +! line vty ! \ No newline at end of file diff --git a/test/zones/evpn/ipv6/expected_controller_config b/test/zones/evpn/ipv6/expected_controller_config index c0ca898..e1d425f 100644 --- a/test/zones/evpn/ipv6/expected_controller_config +++ b/test/zones/evpn/ipv6/expected_controller_config @@ -21,11 +21,14 @@ router bgp 65000 neighbor 192.168.0.3 peer-group VTEP ! address-family l2vpn evpn + neighbor VTEP route-map MAP_VTEP_OUT out neighbor VTEP activate advertise-all-vni exit-address-family ! router bgp 65000 vrf vrf_myzone ! +route-map MAP_VTEP_OUT permit 1 +! line vty ! \ No newline at end of file diff --git a/test/zones/evpn/multipath_relax/expected_controller_config b/test/zones/evpn/multipath_relax/expected_controller_config index 38cc836..18095ec 100644 --- a/test/zones/evpn/multipath_relax/expected_controller_config +++ b/test/zones/evpn/multipath_relax/expected_controller_config @@ -33,11 +33,14 @@ router bgp 65000 exit-address-family ! address-family l2vpn evpn + neighbor VTEP route-map MAP_VTEP_OUT out neighbor VTEP activate advertise-all-vni exit-address-family ! router bgp 65000 vrf vrf_myzone ! +route-map MAP_VTEP_OUT permit 1 +! line vty ! \ No newline at end of file -- 2.30.2