Previously the frr config generation and writing was only done in the evpn plugin. This means that it was not possible to create a standalone bgp and isis plugin without an evpn plugin in place. (The config would just never be written.) To fix this, factor out the frr generation and writing into a separate module and check if a frr-type-plugin is being used. This also paves the way for the fabrics, which would get the config from rust and then use this frr helper.
Signed-off-by: Gabriel Goller <g.gol...@proxmox.com> --- src/PVE/Network/SDN/Controllers.pm | 47 ++- src/PVE/Network/SDN/Controllers/BgpPlugin.pm | 18 +- src/PVE/Network/SDN/Controllers/EvpnPlugin.pm | 289 +---------------- src/PVE/Network/SDN/Controllers/Frr.pm | 296 ++++++++++++++++++ src/PVE/Network/SDN/Controllers/IsisPlugin.pm | 18 +- src/PVE/Network/SDN/Controllers/Makefile | 2 +- src/PVE/Network/SDN/Zones/EvpnPlugin.pm | 15 + 7 files changed, 383 insertions(+), 302 deletions(-) create mode 100644 src/PVE/Network/SDN/Controllers/Frr.pm diff --git a/src/PVE/Network/SDN/Controllers.pm b/src/PVE/Network/SDN/Controllers.pm index fd7ad54ac38c..43f154b7338e 100644 --- a/src/PVE/Network/SDN/Controllers.pm +++ b/src/PVE/Network/SDN/Controllers.pm @@ -12,6 +12,7 @@ use PVE::Cluster qw(cfs_read_file cfs_write_file cfs_lock_file); use PVE::Network::SDN::Vnets; use PVE::Network::SDN::Zones; +use PVE::Network::SDN::Controllers::Frr; use PVE::Network::SDN::Controllers::EvpnPlugin; use PVE::Network::SDN::Controllers::BgpPlugin; use PVE::Network::SDN::Controllers::IsisPlugin; @@ -148,10 +149,22 @@ sub reload_controller { return if !$controller_cfg; + my $frr_reload = 0; + foreach my $id (keys %{$controller_cfg->{ids}}) { my $plugin_config = $controller_cfg->{ids}->{$id}; - my $plugin = PVE::Network::SDN::Controllers::Plugin->lookup($plugin_config->{type}); - $plugin->reload_controller(); + my $type = $plugin_config->{type}; + my @frr_types = ("bgp", "isis", "evpn"); + if (grep {$type} @frr_types) { + $frr_reload = 1; + } else { + my $plugin = PVE::Network::SDN::Controllers::Plugin->lookup($type); + $plugin->reload_controller(); + } + } + + if ($frr_reload) { + PVE::Network::SDN::Controllers::Frr::reload_controller(); } } @@ -161,12 +174,22 @@ sub generate_controller_rawconfig { my $cfg = PVE::Network::SDN::running_config(); my $controller_cfg = $cfg->{controllers}; return if !$controller_cfg; + my $frr_generate = 0; my $rawconfig = ""; foreach my $id (keys %{$controller_cfg->{ids}}) { my $plugin_config = $controller_cfg->{ids}->{$id}; - my $plugin = PVE::Network::SDN::Controllers::Plugin->lookup($plugin_config->{type}); - $rawconfig .= $plugin->generate_controller_rawconfig($plugin_config, $config); + my $type = $plugin_config->{type}; + my @frr_types = ("bgp", "isis", "evpn"); + if (grep {$type} @frr_types) { + $frr_generate = 1; + } else { + my $plugin = PVE::Network::SDN::Controllers::Plugin->lookup($type); + $rawconfig .= $plugin->generate_controller_rawconfig($plugin_config, $config); + } + } + if ($frr_generate) { + $rawconfig .= PVE::Network::SDN::Controllers::Frr::generate_controller_rawconfig($config); } return $rawconfig; } @@ -178,10 +201,22 @@ sub write_controller_config { my $controller_cfg = $cfg->{controllers}; return if !$controller_cfg; + my $frr_reload = 0; + foreach my $id (keys %{$controller_cfg->{ids}}) { my $plugin_config = $controller_cfg->{ids}->{$id}; - my $plugin = PVE::Network::SDN::Controllers::Plugin->lookup($plugin_config->{type}); - $plugin->write_controller_config($plugin_config, $config); + my $type = $plugin_config->{type}; + my @frr_types = ("bgp", "isis", "evpn"); + if (grep {$type} @frr_types) { + $frr_reload = 1; + } else { + my $plugin = PVE::Network::SDN::Controllers::Plugin->lookup($type); + $plugin->write_controller_config($plugin_config, $config); + } + } + + if ($frr_reload) { + PVE::Network::SDN::Controllers::Frr::write_controller_config($config); } } diff --git a/src/PVE/Network/SDN/Controllers/BgpPlugin.pm b/src/PVE/Network/SDN/Controllers/BgpPlugin.pm index 53963e5ad7f4..a4d3e9990647 100644 --- a/src/PVE/Network/SDN/Controllers/BgpPlugin.pm +++ b/src/PVE/Network/SDN/Controllers/BgpPlugin.pm @@ -7,6 +7,7 @@ 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::Frr; use PVE::Network::SDN::Controllers::Plugin; use PVE::Network::SDN::Zones::Plugin; use Net::IP; @@ -164,19 +165,22 @@ sub on_update_hook { } } +sub reload_controller { + my ($class) = @_; + #return PVE::Network::SDN::Controllers::Frr::reload_controller($class); + die "implemented in the Frr helper"; +} + sub generate_controller_rawconfig { my ($class, $plugin_config, $config) = @_; - return ""; + #return PVE::Network::SDN::Controllers::Frr::generate_controller_rawconfig($class, $plugin_config, $config); + die "implemented in the Frr helper"; } sub write_controller_config { my ($class, $plugin_config, $config) = @_; - return; -} - -sub reload_controller { - my ($class) = @_; - return; + #return PVE::Network::SDN::Controllers::Frr::write_controller_config($class, $plugin_config, $config); + die "implemented in the Frr helper"; } 1; diff --git a/src/PVE/Network/SDN/Controllers/EvpnPlugin.pm b/src/PVE/Network/SDN/Controllers/EvpnPlugin.pm index c245ea29cf90..6f875cb5dbf9 100644 --- a/src/PVE/Network/SDN/Controllers/EvpnPlugin.pm +++ b/src/PVE/Network/SDN/Controllers/EvpnPlugin.pm @@ -9,6 +9,7 @@ use PVE::Tools qw(run_command file_set_contents file_get_contents); use PVE::RESTEnvironment qw(log_warn); use PVE::Network::SDN::Controllers::Plugin; +use PVE::Network::SDN::Controllers::Frr; use PVE::Network::SDN::Zones::Plugin; use Net::IP; @@ -109,6 +110,7 @@ sub generate_controller_config { push @controller_config, "neighbor VTEP route-map MAP_VTEP_IN in"; push @controller_config, "neighbor VTEP route-map MAP_VTEP_OUT out"; push @controller_config, "advertise-all-vni"; + # https://datatracker.ietf.org/doc/html/rfc8365#section-5.1.2.1 push @controller_config, "autort as $autortas" if $autortas; push(@{$bgp->{"address-family"}->{"l2vpn evpn"}}, @controller_config); @@ -195,7 +197,7 @@ sub generate_controller_zone_config { push @controller_config, "no bgp hard-administrative-reset"; push @controller_config, "no bgp graceful-restart notification"; -# push @controller_config, "!"; + #push @controller_config, "!"; push(@{$config->{frr}->{router}->{"bgp $asn vrf $vrf"}->{""}}, @controller_config); if ($autortas) { @@ -204,7 +206,6 @@ sub generate_controller_zone_config { } if ($is_gateway) { - $config->{frr_prefix_list}->{'only_default'}->{1} = "permit 0.0.0.0/0"; $config->{frr_prefix_list_v6}->{'only_default_v6'}->{1} = "permit ::/0"; @@ -356,291 +357,17 @@ sub find_isis_controller { return $res; } -sub generate_frr_recurse{ - my ($final_config, $content, $parentkey, $level) = @_; - - my $keylist = {}; - $keylist->{'address-family'} = 1; - $keylist->{router} = 1; - - my $exitkeylist = {}; - $exitkeylist->{'address-family'} = 1; - - my $simple_exitkeylist = {}; - $simple_exitkeylist->{router} = 1; - - # FIXME: make this generic - my $paddinglevel = undef; - if ($level == 1 || $level == 2) { - $paddinglevel = $level - 1; - } elsif ($level == 3 || $level == 4) { - $paddinglevel = $level - 2; - } - - my $padding = ""; - $padding = ' ' x ($paddinglevel) if $paddinglevel; - - if (ref $content eq 'HASH') { - foreach my $key (sort keys %$content) { - next if $key eq 'vrf'; - if ($parentkey && defined($keylist->{$parentkey})) { - push @{$final_config}, $padding."!"; - push @{$final_config}, $padding."$parentkey $key"; - } elsif ($key ne '' && !defined($keylist->{$key})) { - push @{$final_config}, $padding."$key"; - } - - my $option = $content->{$key}; - generate_frr_recurse($final_config, $option, $key, $level+1); - - push @{$final_config}, $padding."exit-$parentkey" if $parentkey && defined($exitkeylist->{$parentkey}); - push @{$final_config}, $padding."exit" if $parentkey && defined($simple_exitkeylist->{$parentkey}); - } - } - - if (ref $content eq 'ARRAY') { - push @{$final_config}, map { $padding . "$_" } @$content; - } -} - -sub generate_frr_vrf { - my ($final_config, $vrfs) = @_; - - return if !$vrfs; - - my @config = (); - - foreach my $id (sort keys %$vrfs) { - my $vrf = $vrfs->{$id}; - push @config, "!"; - push @config, "vrf $id"; - foreach my $rule (@$vrf) { - push @config, " $rule"; - - } - push @config, "exit-vrf"; - } - - push @{$final_config}, @config; -} - -sub generate_frr_simple_list { - my ($final_config, $rules) = @_; - - return if !$rules; - - my @config = (); - push @{$final_config}, "!"; - foreach my $rule (sort @$rules) { - push @{$final_config}, $rule; - } -} - -sub generate_frr_interfaces { - my ($final_config, $interfaces) = @_; - - foreach my $k (sort keys %$interfaces) { - my $iface = $interfaces->{$k}; - push @{$final_config}, "!"; - push @{$final_config}, "interface $k"; - foreach my $rule (sort @$iface) { - push @{$final_config}, " $rule"; - } - } -} - -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++; - next if !defined($seq->{action}); - my @config = (); - push @config, "!"; - push @config, "route-map $id $seq->{action} $order"; - my $rule = $seq->{rule}; - push @config, map { " $_" } @$rule; - push @{$final_config}, @config; - push @{$final_config}, "exit"; - } - } -} - -sub generate_frr_list { - my ($final_config, $lists, $type) = @_; - - my $config = []; - - for my $id (sort keys %$lists) { - my $list = $lists->{$id}; - - for my $seq (sort keys %$list) { - my $rule = $list->{$seq}; - push @$config, "$type $id seq $seq $rule"; - } - } - - if (@$config > 0) { - push @{$final_config}, "!", @$config; - } -} - -sub read_local_frr_config { - if (-e "/etc/frr/frr.conf.local") { - return file_get_contents("/etc/frr/frr.conf.local"); - } -}; - sub generate_controller_rawconfig { my ($class, $plugin_config, $config) = @_; - - my $nodename = PVE::INotify::nodename(); - - my $final_config = []; - push @{$final_config}, "frr version 8.5.2"; - push @{$final_config}, "frr defaults datacenter"; - push @{$final_config}, "hostname $nodename"; - push @{$final_config}, "log syslog informational"; - push @{$final_config}, "service integrated-vtysh-config"; - push @{$final_config}, "!"; - - my $local_conf = read_local_frr_config(); - if ($local_conf) { - parse_merge_frr_local_config($config, $local_conf); - } - - generate_frr_vrf($final_config, $config->{frr}->{vrf}); - generate_frr_interfaces($final_config, $config->{frr_interfaces}); - generate_frr_recurse($final_config, $config->{frr}, undef, 0); - generate_frr_list($final_config, $config->{frr_access_list}, "access-list"); - generate_frr_list($final_config, $config->{frr_prefix_list}, "ip prefix-list"); - generate_frr_list($final_config, $config->{frr_prefix_list_v6}, "ipv6 prefix-list"); - generate_frr_simple_list($final_config, $config->{frr_bgp_community_list}); - generate_frr_routemap($final_config, $config->{frr_routemap}); - generate_frr_simple_list($final_config, $config->{frr_ip_protocol}); - - push @{$final_config}, "!"; - push @{$final_config}, "line vty"; - push @{$final_config}, "!"; - - my $rawconfig = join("\n", @{$final_config}); - - return if !$rawconfig; - return $rawconfig; -} - -sub parse_merge_frr_local_config { - my ($config, $local_conf) = @_; - - my $section = \$config->{""}; - my $router = undef; - my $routemap = undef; - my $routemap_config = (); - my $routemap_action = undef; - - while ($local_conf =~ /^\s*(.+?)\s*$/gm) { - my $line = $1; - $line =~ s/^\s+|\s+$//g; - - if ($line =~ m/^router (.+)$/) { - $router = $1; - $section = \$config->{'frr'}->{'router'}->{$router}->{""}; - next; - } elsif ($line =~ m/^vrf (.+)$/) { - $section = \$config->{'frr'}->{'vrf'}->{$1}; - next; - } elsif ($line =~ m/^interface (.+)$/) { - $section = \$config->{'frr_interfaces'}->{$1}; - next; - } elsif ($line =~ m/^bgp community-list (.+)$/) { - push(@{$config->{'frr_bgp_community_list'}}, $line); - next; - } elsif ($line =~ m/address-family (.+)$/) { - $section = \$config->{'frr'}->{'router'}->{$router}->{'address-family'}->{$1}; - next; - } elsif ($line =~ m/^route-map (.+) (permit|deny) (\d+)/) { - $routemap = $1; - $routemap_config = (); - $routemap_action = $2; - $section = \$config->{'frr_routemap'}->{$routemap}; - next; - } elsif ($line =~ m/^access-list (.+) seq (\d+) (.+)$/) { - $config->{'frr_access_list'}->{$1}->{$2} = $3; - next; - } elsif ($line =~ m/^ip prefix-list (.+) seq (\d+) (.*)$/) { - $config->{'frr_prefix_list'}->{$1}->{$2} = $3; - next; - } elsif ($line =~ m/^ipv6 prefix-list (.+) seq (\d+) (.*)$/) { - $config->{'frr_prefix_list_v6'}->{$1}->{$2} = $3; - next; - } elsif($line =~ m/^exit-address-family$/) { - next; - } elsif($line =~ m/^exit$/) { - if($router) { - $section = \$config->{''}; - $router = undef; - } elsif($routemap) { - push(@{$$section}, { rule => $routemap_config, action => $routemap_action }); - $section = \$config->{''}; - $routemap = undef; - $routemap_action = undef; - $routemap_config = (); - } - next; - } elsif($line =~ m/!/) { - next; - } - - next if !$section; - if($routemap) { - push(@{$routemap_config}, $line); - } else { - push(@{$$section}, $line); - } - } + #return PVE::Network::SDN::Controllers::Frr::generate_controller_rawconfig($class, $plugin_config, $config); + die "implemented in the Frr helper"; } sub write_controller_config { my ($class, $plugin_config, $config) = @_; - - my $rawconfig = $class->generate_controller_rawconfig($plugin_config, $config); - return if !$rawconfig; - return if !-d "/etc/frr"; - - file_set_contents("/etc/frr/frr.conf", $rawconfig); -} - -sub reload_controller { - my ($class) = @_; - - my $conf_file = "/etc/frr/frr.conf"; - my $bin_path = "/usr/lib/frr/frr-reload.py"; - - if (!-e $bin_path) { - log_warn("missing $bin_path. Please install frr-pythontools package"); - return; - } - - my $err = sub { - my $line = shift; - if ($line =~ /ERROR:/) { - warn "$line \n"; - } - }; - - if (-e $conf_file && -e $bin_path) { - eval { - run_command([$bin_path, '--stdout', '--reload', $conf_file], outfunc => {}, errfunc => $err); - }; - if ($@) { - warn "frr reload command fail. Restarting frr."; - eval { run_command(['systemctl', 'restart', 'frr']); }; - } - } + + #return PVE::Network::SDN::Controllers::Frr::write_controller_config($class, $plugin_config, $config); + die "implemented in the Frr helper"; } 1; diff --git a/src/PVE/Network/SDN/Controllers/Frr.pm b/src/PVE/Network/SDN/Controllers/Frr.pm new file mode 100644 index 000000000000..386dcae543e8 --- /dev/null +++ b/src/PVE/Network/SDN/Controllers/Frr.pm @@ -0,0 +1,296 @@ +package PVE::Network::SDN::Controllers::Frr; + +use strict; +use warnings; + +use PVE::RESTEnvironment qw(log_warn); +use PVE::Tools qw(file_get_contents file_set_contents); + +sub read_local_frr_config { + if (-e "/etc/frr/frr.conf.local") { + return file_get_contents("/etc/frr/frr.conf.local"); + } +}; + +sub reload_controller { + my $conf_file = "/etc/frr/frr.conf"; + my $bin_path = "/usr/lib/frr/frr-reload.py"; + + if (!-e $bin_path) { + log_warn("missing $bin_path. Please install frr-pythontools package"); + return; + } + + my $err = sub { + my $line = shift; + if ($line =~ /ERROR:/) { + warn "$line \n"; + } + }; + + if (-e $conf_file && -e $bin_path) { + eval { + run_command([$bin_path, '--stdout', '--reload', $conf_file], outfunc => {}, errfunc => $err); + }; + if ($@) { + warn "frr reload command fail. Restarting frr."; + eval { run_command(['systemctl', 'restart', 'frr']); }; + } + } +} + +sub generate_controller_rawconfig { + my ($config) = @_; + + my $nodename = PVE::INotify::nodename(); + + my $final_config = []; + push @{$final_config}, "frr version 8.5.2"; + push @{$final_config}, "frr defaults datacenter"; + push @{$final_config}, "hostname $nodename"; + push @{$final_config}, "log syslog informational"; + push @{$final_config}, "service integrated-vtysh-config"; + push @{$final_config}, "!"; + + my $local_conf = read_local_frr_config(); + if ($local_conf) { + parse_merge_frr_local_config($config, $local_conf); + } + + generate_frr_vrf($final_config, $config->{frr}->{vrf}); + generate_frr_interfaces($final_config, $config->{frr_interfaces}); + generate_frr_recurse($final_config, $config->{frr}, undef, 0); + generate_frr_list($final_config, $config->{frr_access_list}, "access-list"); + generate_frr_list($final_config, $config->{frr_prefix_list}, "ip prefix-list"); + generate_frr_list($final_config, $config->{frr_prefix_list_v6}, "ipv6 prefix-list"); + generate_frr_simple_list($final_config, $config->{frr_bgp_community_list}); + generate_frr_routemap($final_config, $config->{frr_routemap}); + generate_frr_simple_list($final_config, $config->{frr_ip_protocol}); + + push @{$final_config}, "!"; + push @{$final_config}, "line vty"; + push @{$final_config}, "!"; + + my $rawconfig = join("\n", @{$final_config}); + + return if !$rawconfig; + return $rawconfig; +} + +sub parse_merge_frr_local_config { + my ($config, $local_conf) = @_; + + my $section = \$config->{""}; + my $router = undef; + my $routemap = undef; + my $routemap_config = (); + my $routemap_action = undef; + + while ($local_conf =~ /^\s*(.+?)\s*$/gm) { + my $line = $1; + $line =~ s/^\s+|\s+$//g; + + if ($line =~ m/^router (.+)$/) { + $router = $1; + $section = \$config->{'frr'}->{'router'}->{$router}->{""}; + next; + } elsif ($line =~ m/^vrf (.+)$/) { + $section = \$config->{'frr'}->{'vrf'}->{$1}; + next; + } elsif ($line =~ m/^interface (.+)$/) { + $section = \$config->{'frr_interfaces'}->{$1}; + next; + } elsif ($line =~ m/^bgp community-list (.+)$/) { + push(@{$config->{'frr_bgp_community_list'}}, $line); + next; + } elsif ($line =~ m/address-family (.+)$/) { + $section = \$config->{'frr'}->{'router'}->{$router}->{'address-family'}->{$1}; + next; + } elsif ($line =~ m/^route-map (.+) (permit|deny) (\d+)/) { + $routemap = $1; + $routemap_config = (); + $routemap_action = $2; + $section = \$config->{'frr_routemap'}->{$routemap}; + next; + } elsif ($line =~ m/^access-list (.+) seq (\d+) (.+)$/) { + $config->{'frr_access_list'}->{$1}->{$2} = $3; + next; + } elsif ($line =~ m/^ip prefix-list (.+) seq (\d+) (.*)$/) { + $config->{'frr_prefix_list'}->{$1}->{$2} = $3; + next; + } elsif ($line =~ m/^ipv6 prefix-list (.+) seq (\d+) (.*)$/) { + $config->{'frr_prefix_list_v6'}->{$1}->{$2} = $3; + next; + } elsif($line =~ m/^exit-address-family$/) { + next; + } elsif($line =~ m/^exit$/) { + if($router) { + $section = \$config->{''}; + $router = undef; + } elsif($routemap) { + push(@{$$section}, { rule => $routemap_config, action => $routemap_action }); + $section = \$config->{''}; + $routemap = undef; + $routemap_action = undef; + $routemap_config = (); + } + next; + } elsif($line =~ m/!/) { + next; + } + + next if !$section; + if($routemap) { + push(@{$routemap_config}, $line); + } else { + push(@{$$section}, $line); + } + } +} + +sub write_controller_config { + my ($config) = @_; + + my $rawconfig = generate_controller_rawconfig($config); + return if !$rawconfig; + return if !-d "/etc/frr"; + + file_set_contents("/etc/frr/frr.conf", $rawconfig); +} + + +sub generate_frr_recurse{ + my ($final_config, $content, $parentkey, $level) = @_; + + my $keylist = {}; + $keylist->{'address-family'} = 1; + $keylist->{router} = 1; + + my $exitkeylist = {}; + $exitkeylist->{'address-family'} = 1; + + my $simple_exitkeylist = {}; + $simple_exitkeylist->{router} = 1; + + # FIXME: make this generic + my $paddinglevel = undef; + if ($level == 1 || $level == 2) { + $paddinglevel = $level - 1; + } elsif ($level == 3 || $level == 4) { + $paddinglevel = $level - 2; + } + + my $padding = ""; + $padding = ' ' x ($paddinglevel) if $paddinglevel; + + if (ref $content eq 'HASH') { + foreach my $key (sort keys %$content) { + next if $key eq 'vrf'; + if ($parentkey && defined($keylist->{$parentkey})) { + push @{$final_config}, $padding."!"; + push @{$final_config}, $padding."$parentkey $key"; + } elsif ($key ne '' && !defined($keylist->{$key})) { + push @{$final_config}, $padding."$key"; + } + + my $option = $content->{$key}; + generate_frr_recurse($final_config, $option, $key, $level+1); + + push @{$final_config}, $padding."exit-$parentkey" if $parentkey && defined($exitkeylist->{$parentkey}); + push @{$final_config}, $padding."exit" if $parentkey && defined($simple_exitkeylist->{$parentkey}); + } + } + + if (ref $content eq 'ARRAY') { + push @{$final_config}, map { $padding . "$_" } @$content; + } +} + +sub generate_frr_vrf { + my ($final_config, $vrfs) = @_; + + return if !$vrfs; + + my @config = (); + + foreach my $id (sort keys %$vrfs) { + my $vrf = $vrfs->{$id}; + push @config, "!"; + push @config, "vrf $id"; + foreach my $rule (@$vrf) { + push @config, " $rule"; + + } + push @config, "exit-vrf"; + } + + push @{$final_config}, @config; +} + +sub generate_frr_simple_list { + my ($final_config, $rules) = @_; + + return if !$rules; + + my @config = (); + push @{$final_config}, "!"; + foreach my $rule (sort @$rules) { + push @{$final_config}, $rule; + } +} + +sub generate_frr_list { + my ($final_config, $lists, $type) = @_; + + my $config = []; + + for my $id (sort keys %$lists) { + my $list = $lists->{$id}; + + for my $seq (sort keys %$list) { + my $rule = $list->{$seq}; + push @$config, "$type $id seq $seq $rule"; + } + } + + if (@$config > 0) { + push @{$final_config}, "!", @$config; + } +} + + +sub generate_frr_interfaces { + my ($final_config, $interfaces) = @_; + + foreach my $k (sort keys %$interfaces) { + my $iface = $interfaces->{$k}; + push @{$final_config}, "!"; + push @{$final_config}, "interface $k"; + foreach my $rule (sort @$iface) { + push @{$final_config}, " $rule"; + } + } +} + +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++; + next if !defined($seq->{action}); + my @config = (); + push @config, "!"; + push @config, "route-map $id $seq->{action} $order"; + my $rule = $seq->{rule}; + push @config, map { " $_" } @$rule; + push @{$final_config}, @config; + push @{$final_config}, "exit"; + } + } +} + +1; diff --git a/src/PVE/Network/SDN/Controllers/IsisPlugin.pm b/src/PVE/Network/SDN/Controllers/IsisPlugin.pm index 97c6876db303..50a11742fff6 100644 --- a/src/PVE/Network/SDN/Controllers/IsisPlugin.pm +++ b/src/PVE/Network/SDN/Controllers/IsisPlugin.pm @@ -7,6 +7,7 @@ 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::Frr; use PVE::Network::SDN::Controllers::Plugin; use PVE::Network::SDN::Zones::Plugin; use Net::IP; @@ -113,19 +114,22 @@ sub on_update_hook { } } +sub reload_controller { + my ($class) = @_; + #return PVE::Network::SDN::Controllers::Frr::reload_controller($class); + die "implemented in the Frr helper"; +} + sub generate_controller_rawconfig { my ($class, $plugin_config, $config) = @_; - return ""; + #return PVE::Network::SDN::Controllers::Frr::generate_controller_rawconfig($class, $plugin_config, $config); + die "implemented in the Frr helper"; } sub write_controller_config { my ($class, $plugin_config, $config) = @_; - return; -} - -sub reload_controller { - my ($class) = @_; - return; + #return PVE::Network::SDN::Controllers::Frr::write_controller_config($class, $plugin_config, $config); + die "implemented in the Frr helper"; } 1; diff --git a/src/PVE/Network/SDN/Controllers/Makefile b/src/PVE/Network/SDN/Controllers/Makefile index fd9f881a0ad2..3b0387913cdc 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 IsisPlugin.pm +SOURCES=Plugin.pm FaucetPlugin.pm EvpnPlugin.pm BgpPlugin.pm IsisPlugin.pm Frr.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 4843756a75bd..6212ba0a02d9 100644 --- a/src/PVE/Network/SDN/Zones/EvpnPlugin.pm +++ b/src/PVE/Network/SDN/Zones/EvpnPlugin.pm @@ -323,6 +323,21 @@ sub vnet_update_hook { } } +sub reload_controller { + my ($class) = @_; + die "implemented in the Frr helper"; +} + +sub generate_controller_rawconfig { + my ($class, $config) = @_; + die "implemented in the Frr helper"; +} + +sub write_controller_config { + my ($class, $config) = @_; + die "implemented in the Frr helper"; +} + 1; -- 2.39.5 _______________________________________________ pve-devel mailing list pve-devel@lists.proxmox.com https://lists.proxmox.com/cgi-bin/mailman/listinfo/pve-devel