diff options
| author | Alexandre Derumier <aderumier@odiso.com> | 2023-09-13 13:38:45 +0200 | 
|---|---|---|
| committer | Fabian Grünbichler <f.gruenbichler@proxmox.com> | 2023-10-25 12:50:41 +0200 | 
| commit | 9ce18f80bc9deece323a52e02d92e5fe978698f5 (patch) | |
| tree | 82d2026bec1002352453aceb4ad8b9bee9589ea4 | |
| parent | ced9392063d1cd2ecd93a2e41f5bf00fe3514665 (diff) | |
controllers: add isis router plugin
| -rw-r--r-- | src/PVE/Network/SDN/Controllers.pm | 2 | ||||
| -rw-r--r-- | src/PVE/Network/SDN/Controllers/EvpnPlugin.pm | 28 | ||||
| -rw-r--r-- | src/PVE/Network/SDN/Controllers/IsisPlugin.pm | 123 | ||||
| -rw-r--r-- | src/PVE/Network/SDN/Controllers/Makefile | 2 | ||||
| -rw-r--r-- | src/PVE/Network/SDN/Zones/EvpnPlugin.pm | 10 | ||||
| -rw-r--r-- | src/test/zones/evpn/isis/expected_controller_config | 58 | ||||
| -rw-r--r-- | src/test/zones/evpn/isis/expected_sdn_interfaces | 41 | ||||
| -rw-r--r-- | src/test/zones/evpn/isis/interfaces | 7 | ||||
| -rw-r--r-- | src/test/zones/evpn/isis/sdn_config | 49 | ||||
| -rw-r--r-- | src/test/zones/evpn/isis_loopback/expected_controller_config | 59 | ||||
| -rw-r--r-- | src/test/zones/evpn/isis_loopback/expected_sdn_interfaces | 41 | ||||
| -rw-r--r-- | src/test/zones/evpn/isis_loopback/interfaces | 12 | ||||
| -rw-r--r-- | src/test/zones/evpn/isis_loopback/sdn_config | 50 | 
13 files changed, 476 insertions, 6 deletions
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 645512a..5e9f8ec 100644 --- a/src/PVE/Network/SDN/Zones/EvpnPlugin.pm +++ b/src/PVE/Network/SDN/Zones/EvpnPlugin.pm @@ -120,8 +120,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', +            }, +        }, +    }, +}  | 
