[pve-devel] [PATCH pve-network 1/2] generate_frr_config: cleanup hash and ordering

Alexandre Derumier aderumier at odiso.com
Fri Sep 6 15:14:31 CEST 2019


Signed-off-by: Alexandre Derumier <aderumier at odiso.com>
---
 PVE/Network/SDN.pm             | 99 ++++++++++++++++++++++++++--------
 PVE/Network/SDN/FrrPlugin.pm   | 13 +++--
 PVE/Network/SDN/VxlanPlugin.pm | 18 ++-----
 3 files changed, 87 insertions(+), 43 deletions(-)

diff --git a/PVE/Network/SDN.pm b/PVE/Network/SDN.pm
index 1d84a32..d72b94a 100644
--- a/PVE/Network/SDN.pm
+++ b/PVE/Network/SDN.pm
@@ -221,35 +221,88 @@ sub generate_frr_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";
-    }
+    my $final_config = [];
+    push @{$final_config}, "log syslog informational";
 
-    #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";
-    }
+    generate_frr_recurse($final_config, $config, undef, 0);
 
-    $raw_frr_config .= "line vty\n";
-    $raw_frr_config .= "!\n";
+    push @{$final_config}, "!";
+    push @{$final_config}, "line vty";
+    push @{$final_config}, "!";
 
+    my $raw_frr_config = join("\n", @{$final_config});
     return $raw_frr_config;
 }
 
+sub sort_frr_config {
+    my $order = {};
+    $order->{''} = 0;
+    $order->{'vrf'} = 1;
+    $order->{'ipv4 unicast'} = 1;
+    $order->{'l2vpn evpn'} = 2;
+
+    my $a_val = 100;
+    my $b_val = 100;
+
+    $a_val = $order->{$a} if defined($order->{$a});
+    $b_val = $order->{$b} if defined($order->{$b});
+  
+    if($a =~ /bgp (\d+)$/) {
+	$a_val = 2;
+    }
+
+    if($b =~ /bgp (\d+)$/) {
+	$b_val = 2;
+    }
+
+    return $a_val <=> $b_val;
+}
+
+sub generate_frr_recurse{
+   my ($final_config, $content, $parentkey, $level) = @_;
+
+   my $keylist = {};
+   $keylist->{vrf} = 1;
+   $keylist->{'address-family'} = 1;
+   $keylist->{router} = 1;
+
+   my $exitkeylist = {};
+   $exitkeylist->{vrf} = 1;
+   $exitkeylist->{'address-family'} = 1;
+
+   #fix me, 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 ref {}) {
+	foreach my $key (sort sort_frr_config keys %$content) {
+	    if ($parentkey && defined($keylist->{$parentkey})) {
+	 	    push @{$final_config}, $padding."!";
+	 	    push @{$final_config}, $padding."$parentkey $key";
+	    } else {
+	 	    push @{$final_config}, $padding."$key" if $key ne '' && !defined($keylist->{$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});
+	}
+    }
+
+    if (ref $content eq 'ARRAY') {
+	foreach my $value (@$content) {
+	    push @{$final_config}, $padding."$value";
+	}
+    }
+}
 sub write_etc_network_config {
     my ($rawconfig) = @_;
 
diff --git a/PVE/Network/SDN/FrrPlugin.pm b/PVE/Network/SDN/FrrPlugin.pm
index 2559b10..772d7d2 100644
--- a/PVE/Network/SDN/FrrPlugin.pm
+++ b/PVE/Network/SDN/FrrPlugin.pm
@@ -49,6 +49,7 @@ sub generate_frr_config {
         $ifaceip = PVE::Network::SDN::Plugin::get_first_local_ipv4_from_interface($iface);
     }
 
+
     my @router_config = ();
 
     push @router_config, "bgp router-id $ifaceip";
@@ -58,16 +59,14 @@ sub generate_frr_config {
 	next if $address eq $ifaceip;
 	push @router_config, "neighbor $address remote-as $asn";
     }
-    push @router_config, "!";
-    push @router_config, "address-family l2vpn evpn";
+    push(@{$config->{router}->{"bgp $asn"}->{""}}, @router_config);
+    @router_config = ();
     foreach my $address (@peers) {
 	next if $address eq $ifaceip;
-	push @router_config, " neighbor $address activate";
+	push @router_config, "neighbor $address activate";
     }
-    push @router_config, " advertise-all-vni";
-    push @router_config, "exit-address-family";
-
-    push(@{$config->{router}->{"router bgp $asn"}}, @router_config);
+    push @router_config, "advertise-all-vni";
+    push(@{$config->{router}->{"bgp $asn"}->{"address-family"}->{"l2vpn evpn"}}, @router_config);
 
     return $config;
 }
diff --git a/PVE/Network/SDN/VxlanPlugin.pm b/PVE/Network/SDN/VxlanPlugin.pm
index 733412e..9ab0ade 100644
--- a/PVE/Network/SDN/VxlanPlugin.pm
+++ b/PVE/Network/SDN/VxlanPlugin.pm
@@ -178,9 +178,7 @@ sub generate_frr_config {
     #vrf
     my @router_config = ();
     push @router_config, "vni $vrfvxlan";
-    push @router_config, "exit-vrf";
-    push(@{$config->{vrf}->{"vrf $vrf"}}, @router_config);
-
+    push(@{$config->{vrf}->{"$vrf"}}, @router_config);
 
     @router_config = ();
 
@@ -197,20 +195,14 @@ sub generate_frr_config {
 	#import /32 routes of evpn network from vrf1 to default vrf (for packet return)
 	#frr 7.1 tag is bugged -> works fine with 7.1 stable branch(20190829-02-g6ba76bbc1)
 	#https://github.com/FRRouting/frr/issues/4905
-	push @router_config, "!";
-	push @router_config, "address-family ipv4 unicast";
-	push @router_config, " import vrf $vrf";
-	push @router_config, "exit-address-family";
-	push(@{$config->{router}->{"router bgp $asn"}}, @router_config);
+	push @router_config, "import vrf $vrf";
+	push(@{$config->{router}->{"bgp $asn"}->{"address-family"}->{"ipv4 unicast"}}, @router_config);
 
 	@router_config = ();
 
 	#add default originate to announce 0.0.0.0/0 type5 route in evpn
-	push @router_config, "!";
-	push @router_config, "address-family l2vpn evpn";
-	push @router_config, " default-originate ipv4";
-	push @router_config, "exit-address-family";
-	push(@{$config->{router}->{"router bgp $asn vrf $vrf"}}, @router_config);
+	push @router_config, "default-originate ipv4";
+	push(@{$config->{router}->{"bgp $asn vrf $vrf"}->{"address-family"}->{"l2vpn evpn"}}, @router_config);
     }
 
     return $config;
-- 
2.20.1




More information about the pve-devel mailing list