[pve-devel] [PATCH v2 pve-network 10/13] sdn: add generate_frr_config
Alexandre Derumier
aderumier at odiso.com
Thu Aug 29 12:32:51 CEST 2019
Signed-off-by: Alexandre Derumier <aderumier at 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
More information about the pve-devel
mailing list