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 2822FBDE1 for ; Wed, 13 Sep 2023 13:39:24 +0200 (CEST) Received: from firstgate.proxmox.com (localhost [127.0.0.1]) by firstgate.proxmox.com (Proxmox) with ESMTP id 111D01D3A3 for ; Wed, 13 Sep 2023 13:38:56 +0200 (CEST) Received: from bastionodiso.odiso.net (bastionodiso.odiso.net [IPv6:2a0a:1580:2000::2d]) (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 for ; Wed, 13 Sep 2023 13:38:54 +0200 (CEST) Received: from kvmformation3.odiso.net (formationkvm3.odiso.net [10.3.94.12]) by bastionodiso.odiso.net (Postfix) with ESMTP id 8ED1D7EB3; Wed, 13 Sep 2023 13:38:46 +0200 (CEST) Received: by kvmformation3.odiso.net (Postfix, from userid 0) id 8D83B19A7A3; Wed, 13 Sep 2023 13:38:46 +0200 (CEST) From: Alexandre Derumier To: pve-devel@lists.proxmox.com Date: Wed, 13 Sep 2023 13:38:45 +0200 Message-Id: <20230913113845.1066417-7-aderumier@odiso.com> X-Mailer: git-send-email 2.39.2 In-Reply-To: <20230913113845.1066417-1-aderumier@odiso.com> References: <20230913113845.1066417-1-aderumier@odiso.com> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-SPAM-LEVEL: Spam detection results: 0 AWL 0.016 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 HEADER_FROM_DIFFERENT_DOMAINS 0.249 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 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 Subject: [pve-devel] [PATCH pve-network 3/3] controllers: add isis router plugin 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: Wed, 13 Sep 2023 11:39:24 -0000 --- src/PVE/Network/SDN/Controllers.pm | 2 + src/PVE/Network/SDN/Controllers/EvpnPlugin.pm | 28 +++- src/PVE/Network/SDN/Controllers/IsisPlugin.pm | 123 ++++++++++++++++++ src/PVE/Network/SDN/Controllers/Makefile | 2 +- src/PVE/Network/SDN/Zones/EvpnPlugin.pm | 10 +- .../evpn/isis/expected_controller_config | 58 +++++++++ .../zones/evpn/isis/expected_sdn_interfaces | 41 ++++++ src/test/zones/evpn/isis/interfaces | 7 + src/test/zones/evpn/isis/sdn_config | 49 +++++++ .../isis_loopback/expected_controller_config | 59 +++++++++ .../isis_loopback/expected_sdn_interfaces | 41 ++++++ src/test/zones/evpn/isis_loopback/interfaces | 12 ++ src/test/zones/evpn/isis_loopback/sdn_config | 50 +++++++ 13 files changed, 476 insertions(+), 6 deletions(-) create mode 100644 src/PVE/Network/SDN/Controllers/IsisPlugin.pm create mode 100644 src/test/zones/evpn/isis/expected_controller_config create mode 100644 src/test/zones/evpn/isis/expected_sdn_interfaces create mode 100644 src/test/zones/evpn/isis/interfaces create mode 100644 src/test/zones/evpn/isis/sdn_config create mode 100644 src/test/zones/evpn/isis_loopback/expected_controller_config create mode 100644 src/test/zones/evpn/isis_loopback/expected_sdn_interfaces create mode 100644 src/test/zones/evpn/isis_loopback/interfaces create mode 100644 src/test/zones/evpn/isis_loopback/sdn_config diff --git a/src/PVE/Network/SDN/Controllers.pm b/src/PVE/Network/SDN/Controllers.pm index a23048e..f5a6b86 100644 --- a/src/PVE/Network/SDN/Controllers.pm +++ b/src/PVE/Network/SDN/Controllers.pm @@ -14,10 +14,12 @@ use PVE::Network::SDN::Zones; use PVE::Network::SDN::Controllers::EvpnPlugin; use PVE::Network::SDN::Controllers::BgpPlugin; +use PVE::Network::SDN::Controllers::IsisPlugin; use PVE::Network::SDN::Controllers::FaucetPlugin; use PVE::Network::SDN::Controllers::Plugin; PVE::Network::SDN::Controllers::EvpnPlugin->register(); PVE::Network::SDN::Controllers::BgpPlugin->register(); +PVE::Network::SDN::Controllers::IsisPlugin->register(); PVE::Network::SDN::Controllers::FaucetPlugin->register(); PVE::Network::SDN::Controllers::Plugin->init(); diff --git a/src/PVE/Network/SDN/Controllers/EvpnPlugin.pm b/src/PVE/Network/SDN/Controllers/EvpnPlugin.pm index f1dd20f..3ac7d7e 100644 --- a/src/PVE/Network/SDN/Controllers/EvpnPlugin.pm +++ b/src/PVE/Network/SDN/Controllers/EvpnPlugin.pm @@ -53,11 +53,15 @@ sub generate_controller_config { my $loopback = undef; my $autortas = undef; my $bgprouter = find_bgp_controller($local_node, $controller_cfg); + my $isisrouter = find_isis_controller($local_node, $controller_cfg); + if ($bgprouter) { $ebgp = 1 if $plugin_config->{'asn'} ne $bgprouter->{asn}; $loopback = $bgprouter->{loopback} if $bgprouter->{loopback}; $asn = $bgprouter->{asn} if $bgprouter->{asn}; $autortas = $plugin_config->{'asn'} if $ebgp; + } elsif ($isisrouter) { + $loopback = $isisrouter->{loopback} if $isisrouter->{loopback}; } return if !$asn; @@ -86,10 +90,8 @@ sub generate_controller_config { push @controller_config, "neighbor VTEP remote-as $remoteas"; push @controller_config, "neighbor VTEP bfd"; - if($ebgp && $loopback) { - push @controller_config, "neighbor VTEP ebgp-multihop 10"; - push @controller_config, "neighbor VTEP update-source $loopback"; - } + push @controller_config, "neighbor VTEP ebgp-multihop 10" if $ebgp && $loopback; + push @controller_config, "neighbor VTEP update-source $loopback" if $loopback; # VTEP peers foreach my $address (@peers) { @@ -136,11 +138,15 @@ sub generate_controller_zone_config { my $loopback = undef; my $autortas = undef; my $bgprouter = find_bgp_controller($local_node, $controller_cfg); + my $isisrouter = find_isis_controller($local_node, $controller_cfg); + if($bgprouter) { $ebgp = 1 if $controller->{'asn'} ne $bgprouter->{asn}; $loopback = $bgprouter->{loopback} if $bgprouter->{loopback}; $asn = $bgprouter->{asn} if $bgprouter->{asn}; $autortas = $controller->{'asn'} if $ebgp; + } elsif ($isisrouter) { + $loopback = $isisrouter->{loopback} if $isisrouter->{loopback}; } return if !$vrf || !$vrfvxlan || !$asn; @@ -306,6 +312,20 @@ sub find_bgp_controller { return $res; } +sub find_isis_controller { + my ($nodename, $controller_cfg) = @_; + + my $res = undef; + foreach my $id (keys %{$controller_cfg->{ids}}) { + my $controller = $controller_cfg->{ids}->{$id}; + next if $controller->{type} ne 'isis'; + next if $controller->{node} ne $nodename; + $res = $controller; + last; + } + return $res; +} + sub generate_frr_recurse{ my ($final_config, $content, $parentkey, $level) = @_; diff --git a/src/PVE/Network/SDN/Controllers/IsisPlugin.pm b/src/PVE/Network/SDN/Controllers/IsisPlugin.pm new file mode 100644 index 0000000..afea82e --- /dev/null +++ b/src/PVE/Network/SDN/Controllers/IsisPlugin.pm @@ -0,0 +1,123 @@ +package PVE::Network::SDN::Controllers::IsisPlugin; + +use strict; +use warnings; + +use PVE::INotify; +use PVE::JSONSchema qw(get_standard_option); +use PVE::Tools qw(run_command file_set_contents file_get_contents); + +use PVE::Network::SDN::Controllers::Plugin; +use PVE::Network::SDN::Zones::Plugin; +use Net::IP; + +use base('PVE::Network::SDN::Controllers::Plugin'); + +sub type { + return 'isis'; +} + +sub properties { + return { + 'isis-domain' => { + description => "ISIS domain.", + type => 'string' + }, + 'isis-ifaces' => { + description => "ISIS interface.", + type => 'string', format => 'pve-iface-list', + }, + 'isis-net' => { + description => "ISIS network entity title.", + type => 'string' + }, + }; +} + +sub options { + return { + 'isis-domain' => { optional => 0 }, + 'isis-net' => { optional => 0 }, + 'isis-ifaces' => { optional => 0 }, + 'node' => { optional => 0 }, + 'loopback' => { optional => 1 }, + }; +} + +# Plugin implementation +sub generate_controller_config { + my ($class, $plugin_config, $controller, $id, $uplinks, $config) = @_; + + my $isis_ifaces = $plugin_config->{'isis-ifaces'}; + my $isis_net = $plugin_config->{'isis-net'}; + my $isis_domain = $plugin_config->{'isis-domain'}; + my $local_node = PVE::INotify::nodename(); + + return if !$isis_ifaces || !$isis_net || !$isis_domain; + return if $local_node ne $plugin_config->{node}; + + my @router_config = ( + "net $isis_net", + "redistribute ipv4 connected level-1", + "redistribute ipv6 connected level-1", + "log-adjacency-changes", + ); + + push(@{$config->{frr}->{router}->{"isis $isis_domain"}}, @router_config); + + my @iface_config = ( + "ip router isis $isis_domain" + ); + + my @ifaces = PVE::Tools::split_list($isis_ifaces); + for my $iface (sort @ifaces) { + push(@{$config->{frr_interfaces}->{$iface}}, @iface_config); + } + + return $config; +} + +sub generate_controller_zone_config { + my ($class, $plugin_config, $controller, $controller_cfg, $id, $uplinks, $config) = @_; + +} + +sub on_delete_hook { + my ($class, $controllerid, $zone_cfg) = @_; + +} + +sub on_update_hook { + my ($class, $controllerid, $controller_cfg) = @_; + + # we can only have 1 bgp controller by node + my $local_node = PVE::INotify::nodename(); + my $controllernb = 0; + foreach my $id (keys %{$controller_cfg->{ids}}) { + next if $id eq $controllerid; + my $controller = $controller_cfg->{ids}->{$id}; + next if $controller->{type} ne "isis"; + next if $controller->{node} ne $local_node; + $controllernb++; + die "only 1 bgp or isis controller can be defined" if $controllernb > 1; + } +} + +sub generate_controller_rawconfig { + my ($class, $plugin_config, $config) = @_; + return ""; +} + +sub write_controller_config { + my ($class, $plugin_config, $config) = @_; + return; +} + +sub reload_controller { + my ($class) = @_; + return; +} + +1; + + diff --git a/src/PVE/Network/SDN/Controllers/Makefile b/src/PVE/Network/SDN/Controllers/Makefile index 11686a3..fd9f881 100644 --- a/src/PVE/Network/SDN/Controllers/Makefile +++ b/src/PVE/Network/SDN/Controllers/Makefile @@ -1,4 +1,4 @@ -SOURCES=Plugin.pm FaucetPlugin.pm EvpnPlugin.pm BgpPlugin.pm +SOURCES=Plugin.pm FaucetPlugin.pm EvpnPlugin.pm BgpPlugin.pm IsisPlugin.pm PERL5DIR=${DESTDIR}/usr/share/perl5 diff --git a/src/PVE/Network/SDN/Zones/EvpnPlugin.pm b/src/PVE/Network/SDN/Zones/EvpnPlugin.pm index b155abc..5df05f9 100644 --- a/src/PVE/Network/SDN/Zones/EvpnPlugin.pm +++ b/src/PVE/Network/SDN/Zones/EvpnPlugin.pm @@ -119,8 +119,16 @@ sub generate_sdn_config { warn "vlan-aware vnet can't be enabled with evpn plugin" if $vnet->{vlanaware}; my @peers = PVE::Tools::split_list($controller->{'peers'}); + + my $loopback = undef; my $bgprouter = PVE::Network::SDN::Controllers::EvpnPlugin::find_bgp_controller($local_node, $controller_cfg); - my $loopback = $bgprouter->{loopback} if $bgprouter->{loopback}; + my $isisrouter = PVE::Network::SDN::Controllers::EvpnPlugin::find_isis_controller($local_node, $controller_cfg); + if ($bgprouter->{loopback}) { + $loopback = $bgprouter->{loopback}; + } elsif ($isisrouter->{loopback}) { + $loopback = $isisrouter->{loopback}; + } + my ($ifaceip, $iface) = PVE::Network::SDN::Zones::Plugin::find_local_ip_interface_peers(\@peers, $loopback); my $is_evpn_gateway = $plugin_config->{'exitnodes'}->{$local_node}; my $exitnodes_local_routing = $plugin_config->{'exitnodes-local-routing'}; diff --git a/src/test/zones/evpn/isis/expected_controller_config b/src/test/zones/evpn/isis/expected_controller_config new file mode 100644 index 0000000..8d1706a --- /dev/null +++ b/src/test/zones/evpn/isis/expected_controller_config @@ -0,0 +1,58 @@ +frr version 8.5.1 +frr defaults datacenter +hostname localhost +log syslog informational +service integrated-vtysh-config +! +! +vrf vrf_myzone + vni 1000 +exit-vrf +! +interface eth0 + ip router isis isis1 +! +interface eth1 + ip router isis isis1 +! +router bgp 65000 + bgp router-id 192.168.0.1 + no bgp hard-administrative-reset + no bgp graceful-restart notification + 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 l2vpn evpn + neighbor VTEP route-map MAP_VTEP_IN in + neighbor VTEP route-map MAP_VTEP_OUT out + neighbor VTEP activate + advertise-all-vni + 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 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 +! +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/isis/expected_sdn_interfaces b/src/test/zones/evpn/isis/expected_sdn_interfaces new file mode 100644 index 0000000..4cf13e0 --- /dev/null +++ b/src/test/zones/evpn/isis/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 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 diff --git a/src/test/zones/evpn/isis/interfaces b/src/test/zones/evpn/isis/interfaces new file mode 100644 index 0000000..2426e0f --- /dev/null +++ b/src/test/zones/evpn/isis/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 \ No newline at end of file diff --git a/src/test/zones/evpn/isis/sdn_config b/src/test/zones/evpn/isis/sdn_config new file mode 100644 index 0000000..5963c18 --- /dev/null +++ b/src/test/zones/evpn/isis/sdn_config @@ -0,0 +1,49 @@ +{ + version => 1, + vnets => { + ids => { + myvnet => { + tag => "100", + type => "vnet", + zone => "myzone", + }, + }, + }, + + zones => { + ids => { + myzone => { + ipam => "pve", + type => "evpn", + controller => "evpnctl", + 'vrf-vxlan' => 1000, + }, + }, + }, + controllers => { + ids => { + evpnctl => { + type => "evpn", + 'peers' => '192.168.0.1,192.168.0.2,192.168.0.3', + asn => "65000", + }, + localhost => { + type => "isis", + 'isis-domain' => 'isis1', + 'isis-ifaces' => 'eth1,eth0', + 'isis-net' => "47.0023.0000.0000.0000.0000.0000.0000.1900.0004.00", + node => "localhost", + }, + }, + }, + + subnets => { + ids => { + 'myzone-10.0.0.0-24' => { + 'type' => 'subnet', + 'vnet' => 'myvnet', + 'gateway' => '10.0.0.1', + }, + }, + }, +} diff --git a/src/test/zones/evpn/isis_loopback/expected_controller_config b/src/test/zones/evpn/isis_loopback/expected_controller_config new file mode 100644 index 0000000..7b034c4 --- /dev/null +++ b/src/test/zones/evpn/isis_loopback/expected_controller_config @@ -0,0 +1,59 @@ +frr version 8.5.1 +frr defaults datacenter +hostname localhost +log syslog informational +service integrated-vtysh-config +! +! +vrf vrf_myzone + vni 1000 +exit-vrf +! +interface eth0 + ip router isis isis1 +! +interface eth1 + ip router isis isis1 +! +router bgp 65000 + bgp router-id 10.0.0.1 + no bgp hard-administrative-reset + no bgp graceful-restart notification + no bgp default ipv4-unicast + coalesce-time 1000 + neighbor VTEP peer-group + neighbor VTEP remote-as 65000 + neighbor VTEP bfd + neighbor VTEP update-source dummy1 + neighbor 10.0.0.2 peer-group VTEP + neighbor 10.0.0.3 peer-group VTEP + ! + address-family l2vpn evpn + neighbor VTEP route-map MAP_VTEP_IN in + neighbor VTEP route-map MAP_VTEP_OUT out + neighbor VTEP activate + advertise-all-vni + exit-address-family +exit +! +router bgp 65000 vrf vrf_myzone + bgp router-id 10.0.0.1 + no bgp hard-administrative-reset + no bgp graceful-restart notification +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 +! +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/isis_loopback/expected_sdn_interfaces b/src/test/zones/evpn/isis_loopback/expected_sdn_interfaces new file mode 100644 index 0000000..e595dc9 --- /dev/null +++ b/src/test/zones/evpn/isis_loopback/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 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 10.0.0.1 + bridge-learning off + bridge-arp-nd-suppress on + mtu 1450 + +auto vxlan_myvnet +iface vxlan_myvnet + vxlan-id 100 + vxlan-local-tunnelip 10.0.0.1 + bridge-learning off + bridge-arp-nd-suppress on + mtu 1450 diff --git a/src/test/zones/evpn/isis_loopback/interfaces b/src/test/zones/evpn/isis_loopback/interfaces new file mode 100644 index 0000000..41ae25f --- /dev/null +++ b/src/test/zones/evpn/isis_loopback/interfaces @@ -0,0 +1,12 @@ +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 + +auto dummy1 +iface dummy1 inet static + address 10.0.0.1/32 + link-type dummy \ No newline at end of file diff --git a/src/test/zones/evpn/isis_loopback/sdn_config b/src/test/zones/evpn/isis_loopback/sdn_config new file mode 100644 index 0000000..786a3e7 --- /dev/null +++ b/src/test/zones/evpn/isis_loopback/sdn_config @@ -0,0 +1,50 @@ +{ + version => 1, + vnets => { + ids => { + myvnet => { + tag => "100", + type => "vnet", + zone => "myzone", + }, + }, + }, + + zones => { + ids => { + myzone => { + ipam => "pve", + type => "evpn", + controller => "evpnctl", + 'vrf-vxlan' => 1000, + }, + }, + }, + controllers => { + ids => { + evpnctl => { + type => "evpn", + 'peers' => '10.0.0.1,10.0.0.2,10.0.0.3', + asn => "65000", + }, + 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', + }, + }, + }, +} -- 2.39.2