Signed-off-by: Alexandre Derumier <aderum...@odiso.com> --- PVE/Network/SDN.pm | 94 ++++++++++++++++++++++++++++++---- PVE/Network/SDN/FrrPlugin.pm | 15 ++---- PVE/Network/SDN/VlanPlugin.pm | 4 +- PVE/Network/SDN/VxlanPlugin.pm | 55 ++++++++++++++++++-- test/generateconfig.pl | 5 +- 5 files changed, 145 insertions(+), 28 deletions(-)
diff --git a/PVE/Network/SDN.pm b/PVE/Network/SDN.pm index 9d8006e..80a70d8 100644 --- a/PVE/Network/SDN.pm +++ b/PVE/Network/SDN.pm @@ -149,27 +149,103 @@ sub generate_etc_network_config { $plugin->generate_sdn_config($plugin_config, $zone, $id, $vnet, $uplinks, $config); } - my $network_config = $config->{network}; my $raw_network_config = ""; - foreach my $iface (keys %$network_config) { + foreach my $iface (keys %$config) { $raw_network_config .= "\n"; $raw_network_config .= "auto $iface\n"; $raw_network_config .= "iface $iface\n"; - foreach my $option (@{$network_config->{$iface}}) { + foreach my $option (@{$config->{$iface}}) { $raw_network_config .= "\t$option\n"; } } - my $frr_config = $config->{frr}; - my $raw_frr_config = ""; - foreach my $asn (keys %$frr_config) { - $raw_frr_config .= "router bgp $asn"; - foreach my $option (@{$frr_config->{$asn}}) { + return $raw_network_config; +} + +sub generate_frr_config { + + my $sdn_cfg = PVE::Cluster::cfs_read_file('sdn.cfg'); + return if !$sdn_cfg; + + #read main config for physical interfaces + my $current_config_file = "/etc/network/interfaces"; + my $fh = IO::File->new($current_config_file); + my $interfaces_config = PVE::INotify::read_etc_network_interfaces(1,$fh); + $fh->close(); + + #check uplinks + my $uplinks = {}; + foreach my $id (keys %{$interfaces_config->{ifaces}}) { + my $interface = $interfaces_config->{ifaces}->{$id}; + if (my $uplink = $interface->{'uplink-id'}) { + die "uplink-id $uplink is already defined on $uplinks->{$uplink}" if $uplinks->{$uplink}; + $interface->{name} = $id; + $uplinks->{$interface->{'uplink-id'}} = $interface; + } + } + + my $frr_cfg = undef; + my $transport_cfg = undef; + + foreach my $id (keys %{$sdn_cfg->{ids}}) { + if ($sdn_cfg->{ids}->{$id}->{type} eq 'frr') { + $frr_cfg->{ids}->{$id} = $sdn_cfg->{ids}->{$id}; + } elsif ($sdn_cfg->{ids}->{$id}->{type} ne 'vnet') { + $transport_cfg->{ids}->{$id} = $sdn_cfg->{ids}->{$id}; + } + } + + #generate configuration + my $config = {}; + + foreach my $id (keys %{$frr_cfg->{ids}}) { + my $plugin_config = $frr_cfg->{ids}->{$id}; + my $asn = $plugin_config->{asn}; + if ($asn) { + my $plugin = PVE::Network::SDN::Plugin->lookup($plugin_config->{type}); + $plugin->generate_frr_config($plugin_config, $asn, $id, $uplinks, $config); + } + } + + foreach my $id (keys %{$transport_cfg->{ids}}) { + my $plugin_config = $transport_cfg->{ids}->{$id}; + my $router = $plugin_config->{router}; + if ($router) { + my $asn = $frr_cfg->{ids}->{$router}->{asn}; + if ($asn) { + my $plugin = PVE::Network::SDN::Plugin->lookup($plugin_config->{type}); + $plugin->generate_frr_config($plugin_config, $asn, $id, $uplinks, $config); + } + } + } + + my $raw_frr_config = "log syslog informational\n"; + $raw_frr_config .= "!\n"; + + #vrf first + my $vrfconfig = $config->{vrf}; + foreach my $vrf (sort keys %$vrfconfig) { + $raw_frr_config .= "$vrf\n"; + foreach my $option (@{$vrfconfig->{$vrf}}) { $raw_frr_config .= " $option\n"; } + $raw_frr_config .= "!\n"; } - return wantarray ? ($raw_network_config, $raw_frr_config) : $raw_network_config; + #routers + my $routerconfig = $config->{router}; + foreach my $router (sort keys %$routerconfig) { + $raw_frr_config .= "$router\n"; + foreach my $option (@{$routerconfig->{$router}}) { + $raw_frr_config .= " $option\n"; + } + $raw_frr_config .= "!\n"; + } + + $raw_frr_config .= "line vty\n"; + $raw_frr_config .= "!\n"; + + return $raw_frr_config; } sub write_etc_network_config { diff --git a/PVE/Network/SDN/FrrPlugin.pm b/PVE/Network/SDN/FrrPlugin.pm index 80ca417..0ea6d48 100644 --- a/PVE/Network/SDN/FrrPlugin.pm +++ b/PVE/Network/SDN/FrrPlugin.pm @@ -34,27 +34,23 @@ sub options { } # Plugin implementation -sub generate_sdn_config { - my ($class, $plugin_config, $zoneid, $vnetid, $vnet, $uplinks, $config) = @_; +sub generate_frr_config { + my ($class, $plugin_config, $asn, $id, $uplinks, $config) = @_; - my $asn = $plugin_config->{'asn'}; my @peers = split(',', $plugin_config->{'peers'}) if $plugin_config->{'peers'}; my $uplink = $plugin_config->{'uplink-id'}; - die "missing peers" if !$plugin_config->{'peers'}; - my $iface = "uplink$uplink"; my $ifaceip = ""; if($uplinks->{$uplink}->{name}) { $iface = $uplinks->{$uplink}->{name}; - $ifaceip = get_first_local_ipv4_from_interface($iface); + $ifaceip = PVE::Network::SDN::Plugin::get_first_local_ipv4_from_interface($iface); } my @router_config = (); - push @router_config, "router bgp $asn"; push @router_config, "bgp router-id $ifaceip"; push @router_config, "coalesce-time 1000"; @@ -70,11 +66,8 @@ sub generate_sdn_config { } push @router_config, " advertise-all-vni"; push @router_config, "exit-address-family"; - push @router_config, "!"; - push @router_config, "line vty"; - push @router_config, "!"; - push(@{$config->{frr}->{$asn}}, @router_config); + push(@{$config->{router}->{"router bgp $asn"}}, @router_config); return $config; } diff --git a/PVE/Network/SDN/VlanPlugin.pm b/PVE/Network/SDN/VlanPlugin.pm index d2b7475..2af24b7 100644 --- a/PVE/Network/SDN/VlanPlugin.pm +++ b/PVE/Network/SDN/VlanPlugin.pm @@ -77,7 +77,7 @@ sub generate_sdn_config { my @iface_config = (); push @iface_config, "vlan-protocol $vlanprotocol" if $vlanprotocol; push @iface_config, "mtu $mtu" if $mtu; - push(@{$config->{network}->{$iface}}, @iface_config) if !$config->{network}->{$iface}; + push(@{$config->{$iface}}, @iface_config) if !$config->{$iface}; #vnet bridge @iface_config = (); @@ -87,7 +87,7 @@ sub generate_sdn_config { push @iface_config, "bridge-vlan-aware yes" if $vlanaware; push @iface_config, "mtu $mtu" if $mtu; push @iface_config, "alias $alias" if $alias; - push(@{$config->{network}->{$vnetid}}, @iface_config) if !$config->{network}->{$vnetid}; + push(@{$config->{$vnetid}}, @iface_config) if !$config->{$vnetid}; return $config; } diff --git a/PVE/Network/SDN/VxlanPlugin.pm b/PVE/Network/SDN/VxlanPlugin.pm index 6e247a7..99cd2af 100644 --- a/PVE/Network/SDN/VxlanPlugin.pm +++ b/PVE/Network/SDN/VxlanPlugin.pm @@ -42,6 +42,10 @@ sub properties { type => 'integer', description => "l3vni.", }, + 'router' => { + type => 'string', + description => "Frr router name", + }, }; } @@ -54,6 +58,7 @@ sub options { 'vxlan-allowed' => { optional => 1 }, 'vrf' => { optional => 1 }, 'vrf-vxlan' => { optional => 1 }, + 'router' => { optional => 1 }, }; } @@ -107,7 +112,7 @@ sub generate_sdn_config { } push @iface_config, "mtu $mtu" if $mtu; - push(@{$config->{network}->{"vxlan$vnetid"}}, @iface_config) if !$config->{network}->{"vxlan$vnetid"}; + push(@{$config->{"vxlan$vnetid"}}, @iface_config) if !$config->{"vxlan$vnetid"}; #vnet bridge @iface_config = (); @@ -120,13 +125,13 @@ sub generate_sdn_config { push @iface_config, "mtu $mtu" if $mtu; push @iface_config, "alias $alias" if $alias; push @iface_config, "vrf $vrf" if $vrf; - push(@{$config->{network}->{$vnetid}}, @iface_config) if !$config->{network}->{$vnetid}; + push(@{$config->{$vnetid}}, @iface_config) if !$config->{$vnetid}; if ($vrf) { #vrf intreface @iface_config = (); push @iface_config, "vrf-table auto"; - push(@{$config->{network}->{$vrf}}, @iface_config) if !$config->{network}->{$vrf}; + push(@{$config->{$vrf}}, @iface_config) if !$config->{$vrf}; if ($vrfvxlan) { #l3vni vxlan interface @@ -137,7 +142,7 @@ sub generate_sdn_config { push @iface_config, "bridge-learning off"; push @iface_config, "bridge-arp-nd-suppress on"; push @iface_config, "mtu $mtu" if $mtu; - push(@{$config->{network}->{$iface_vxlan}}, @iface_config) if !$config->{network}->{$iface_vxlan}; + push(@{$config->{$iface_vxlan}}, @iface_config) if !$config->{$iface_vxlan}; #l3vni bridge my $brvrf = "br$vrf"; @@ -147,13 +152,53 @@ sub generate_sdn_config { push @iface_config, "bridge_fd 0"; push @iface_config, "mtu $mtu" if $mtu; push @iface_config, "vrf $vrf"; - push(@{$config->{network}->{$brvrf}}, @iface_config) if !$config->{network}->{$brvrf}; + push(@{$config->{$brvrf}}, @iface_config) if !$config->{$brvrf}; } } return $config; } +sub generate_frr_config { + my ($class, $plugin_config, $asn, $id, $uplinks, $config) = @_; + + my $vrf = $plugin_config->{'vrf'}; + my $vrfvxlan = $plugin_config->{'vrf-vxlan'}; + return if !$vrf || !$vrfvxlan; + + my $uplink = $plugin_config->{'uplink-id'}; + + my $iface = "uplink$uplink"; + my $ifaceip = ""; + + if($uplinks->{$uplink}->{name}) { + $iface = $uplinks->{$uplink}->{name}; + $ifaceip = PVE::Network::SDN::Plugin::get_first_local_ipv4_from_interface($iface); + } + + #vrf + my @router_config = (); + push @router_config, "vni $vrfvxlan"; + push @router_config, "exit-vrf"; + push(@{$config->{vrf}->{"vrf $vrf"}}, @router_config); + + + #vrf router + @router_config = (); + push @router_config, "bgp router-id $ifaceip"; + push @router_config, "!"; + push @router_config, "address-family ipv4 unicast"; + push @router_config, " redistribute connected"; + push @router_config, "exit-address-family"; + push @router_config, "!"; + push @router_config, "address-family l2vpn evpn"; + push @router_config, " advertise ipv4 unicast"; + push @router_config, "exit-address-family"; + push(@{$config->{router}->{"router bgp $asn vrf $vrf"}}, @router_config); + + return $config; +} + sub on_delete_hook { my ($class, $transportid, $sdn_cfg) = @_; diff --git a/test/generateconfig.pl b/test/generateconfig.pl index 6d8b80a..6003f94 100644 --- a/test/generateconfig.pl +++ b/test/generateconfig.pl @@ -6,7 +6,10 @@ use PVE::Cluster qw(cfs_read_file); use PVE::Network::SDN; -my ($network_config, $frr_config) = PVE::Network::SDN::generate_etc_network_config(); +my $network_config = PVE::Network::SDN::generate_etc_network_config(); PVE::Network::SDN::write_etc_network_config($network_config); print $network_config; + + +my $frr_config = PVE::Network::SDN::generate_frr_config(); print $frr_config; -- 2.20.1 _______________________________________________ pve-devel mailing list pve-devel@pve.proxmox.com https://pve.proxmox.com/cgi-bin/mailman/listinfo/pve-devel