[pve-devel] [PATCH v2 pve-network 4/4] move gateway-nodes option to frr plugin and add gateway-external-peers

Alexandre Derumier aderumier at odiso.com
Mon Sep 9 08:45:53 CEST 2019


It's make more sense, as We use default vrf for routing.
Also add gateway-external-peers to define an external bgp peer.

Signed-off-by: Alexandre Derumier <aderumier at odiso.com>
---
 PVE/Network/SDN.pm             | 24 +++++++++----------
 PVE/Network/SDN/FrrPlugin.pm   | 43 +++++++++++++++++++++++++++++++++-
 PVE/Network/SDN/Plugin.pm      |  2 +-
 PVE/Network/SDN/VxlanPlugin.pm | 13 +++++-----
 test/documentation.txt         |  4 ++--
 5 files changed, 63 insertions(+), 23 deletions(-)

diff --git a/PVE/Network/SDN.pm b/PVE/Network/SDN.pm
index eda5a18..095b223 100644
--- a/PVE/Network/SDN.pm
+++ b/PVE/Network/SDN.pm
@@ -200,23 +200,20 @@ sub generate_frr_config {
     #generate configuration
     my $config = {};
 
-    foreach my $id (keys %{$frr_cfg->{ids}}) {
+    foreach my $id (sort 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);
-	}
+	my $plugin = PVE::Network::SDN::Plugin->lookup($plugin_config->{type});
+	$plugin->generate_frr_config($plugin_config, $plugin_config, $id, $uplinks, $config);
     }
 
-    foreach my $id (keys %{$transport_cfg->{ids}}) {
+    foreach my $id (sort 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 $routerid = $plugin_config->{router};
+	if ($routerid) {
+	    my $router = $frr_cfg->{ids}->{$routerid};
+	    if ($router) {
 		my $plugin = PVE::Network::SDN::Plugin->lookup($plugin_config->{type});
-		$plugin->generate_frr_config($plugin_config, $asn, $id, $uplinks, $config);
+		$plugin->generate_frr_config($plugin_config, $router, $id, $uplinks, $config);
 	    }
 	}
     }
@@ -240,7 +237,8 @@ sub sort_frr_config {
     $order->{''} = 0;
     $order->{'vrf'} = 1;
     $order->{'ipv4 unicast'} = 1;
-    $order->{'l2vpn evpn'} = 2;
+    $order->{'ipv6 unicast'} = 2;
+    $order->{'l2vpn evpn'} = 3;
 
     my $a_val = 100;
     my $b_val = 100;
diff --git a/PVE/Network/SDN/FrrPlugin.pm b/PVE/Network/SDN/FrrPlugin.pm
index c318b1d..8a1f86c 100644
--- a/PVE/Network/SDN/FrrPlugin.pm
+++ b/PVE/Network/SDN/FrrPlugin.pm
@@ -4,6 +4,8 @@ use strict;
 use warnings;
 use PVE::Network::SDN::Plugin;
 use PVE::Tools;
+use PVE::INotify;
+use PVE::JSONSchema qw(get_standard_option);
 
 use base('PVE::Network::SDN::Plugin');
 
@@ -21,6 +23,11 @@ sub properties {
             description => "peers address list.",
             type => 'string',  #fixme: format
         },
+	'gateway-nodes' => get_standard_option('pve-node-list'),
+        'gateway-external-peers' => {
+            description => "upstream bgp peers address list.",
+            type => 'string',  #fixme: format
+        },
     };
 }
 
@@ -30,16 +37,23 @@ sub options {
 	'uplink-id' => { optional => 0 },
         'asn' => { optional => 0 },
         'peers' => { optional => 0 },
+	'gateway-nodes' => { optional => 1 },
+	'gateway-external-peers' => { optional => 1 },
     };
 }
 
 # Plugin implementation
 sub generate_frr_config {
-    my ($class, $plugin_config, $asn, $id, $uplinks, $config) = @_;
+    my ($class, $plugin_config, $router, $id, $uplinks, $config) = @_;
 
     my @peers = split(',', $plugin_config->{'peers'}) if $plugin_config->{'peers'};
 
+    my $asn = $plugin_config->{asn};
     my $uplink = $plugin_config->{'uplink-id'};
+    my $gatewaynodes = $plugin_config->{'gateway-nodes'};
+    my @gatewaypeers = split(',', $plugin_config->{'gateway-external-peers'}) if $plugin_config->{'gateway-external-peers'};
+
+    return if !$asn;
 
     my $iface = "uplink$uplink";
     my $ifaceip = "";
@@ -49,6 +63,12 @@ sub generate_frr_config {
         $ifaceip = PVE::Network::SDN::Plugin::get_first_local_ipv4_from_interface($iface);
     }
 
+    my $is_gateway = undef;
+    my $local_node = PVE::INotify::nodename();
+
+    foreach my $gatewaynode (PVE::Tools::split_list($gatewaynodes)) {
+        $is_gateway = 1 if $gatewaynode eq $local_node;
+    }
 
     my @router_config = ();
 
@@ -61,7 +81,14 @@ sub generate_frr_config {
 	next if $address eq $ifaceip;
 	push @router_config, "neighbor $address remote-as $asn";
     }
+
+    if ($is_gateway) {
+	foreach my $address (@gatewaypeers) {
+	    push @router_config, "neighbor $address remote-as external";
+	}
+    }
     push(@{$config->{router}->{"bgp $asn"}->{""}}, @router_config);
+
     @router_config = ();
     foreach my $address (@peers) {
 	next if $address eq $ifaceip;
@@ -70,6 +97,20 @@ sub generate_frr_config {
     push @router_config, "advertise-all-vni";
     push(@{$config->{router}->{"bgp $asn"}->{"address-family"}->{"l2vpn evpn"}}, @router_config);
 
+    if ($is_gateway) {
+
+        @router_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
+	foreach my $address (@gatewaypeers) {
+	    push @router_config, "neighbor $address activate";
+	}
+        push(@{$config->{router}->{"bgp $asn"}->{"address-family"}->{"ipv4 unicast"}}, @router_config);
+        push(@{$config->{router}->{"bgp $asn"}->{"address-family"}->{"ipv6 unicast"}}, @router_config);
+
+    }
+
     return $config;
 }
 
diff --git a/PVE/Network/SDN/Plugin.pm b/PVE/Network/SDN/Plugin.pm
index 20984fe..1c58049 100644
--- a/PVE/Network/SDN/Plugin.pm
+++ b/PVE/Network/SDN/Plugin.pm
@@ -72,7 +72,7 @@ sub generate_sdn_config {
 }
 
 sub generate_frr_config {
-    my ($class, $plugin_config, $node, $data, $ctime) = @_;
+    my ($class, $plugin_config, $router, $id, $uplinks, $config) = @_;
 
     die "please implement inside plugin";
 }
diff --git a/PVE/Network/SDN/VxlanPlugin.pm b/PVE/Network/SDN/VxlanPlugin.pm
index 3e18de3..d3b923c 100644
--- a/PVE/Network/SDN/VxlanPlugin.pm
+++ b/PVE/Network/SDN/VxlanPlugin.pm
@@ -5,7 +5,6 @@ use warnings;
 use PVE::Network::SDN::Plugin;
 use PVE::Tools;
 use PVE::INotify;
-use PVE::JSONSchema qw(get_standard_option);
 
 use base('PVE::Network::SDN::Plugin');
 
@@ -48,7 +47,6 @@ sub properties {
 	    type => 'string',
 	    description => "Frr router name",
 	},
-	'gateway-nodes' => get_standard_option('pve-node-list'),
     };
 }
 
@@ -62,7 +60,6 @@ sub options {
         'vrf' => { optional => 1 },
         'vrf-vxlan' => { optional => 1 },
         'router' => { optional => 1 },
-        'gateway-nodes' => { optional => 1 },
     };
 }
 
@@ -167,13 +164,14 @@ sub generate_sdn_config {
 }
 
 sub generate_frr_config {
-    my ($class, $plugin_config, $asn, $id, $uplinks, $config) = @_;
+    my ($class, $plugin_config, $router, $id, $uplinks, $config) = @_;
 
     my $vrf = $plugin_config->{'vrf'};
     my $vrfvxlan = $plugin_config->{'vrf-vxlan'};
-    my $gatewaynodes = $plugin_config->{'gateway-nodes'};
+    my $asn = $router->{asn};
+    my $gatewaynodes = $router->{'gateway-nodes'};
 
-    return if !$vrf || !$vrfvxlan;
+    return if !$vrf || !$vrfvxlan || !$asn;
 
     #vrf
     my @router_config = ();
@@ -197,15 +195,18 @@ sub generate_frr_config {
 	#https://github.com/FRRouting/frr/issues/4905
 	push @router_config, "import vrf $vrf";
 	push(@{$config->{router}->{"bgp $asn"}->{"address-family"}->{"ipv4 unicast"}}, @router_config);
+	push(@{$config->{router}->{"bgp $asn"}->{"address-family"}->{"ipv6 unicast"}}, @router_config);
 
 	@router_config = ();
 	#redistribute connected to be able to route to local vms on the gateway
 	push @router_config, "redistribute connected";
 	push(@{$config->{router}->{"bgp $asn vrf $vrf"}->{"address-family"}->{"ipv4 unicast"}}, @router_config);
+	push(@{$config->{router}->{"bgp $asn vrf $vrf"}->{"address-family"}->{"ipv6 unicast"}}, @router_config);
 
 	@router_config = ();
 	#add default originate to announce 0.0.0.0/0 type5 route in evpn
 	push @router_config, "default-originate ipv4";
+	push @router_config, "default-originate ipv6";
 	push(@{$config->{router}->{"bgp $asn vrf $vrf"}->{"address-family"}->{"l2vpn evpn"}}, @router_config);
     }
 
diff --git a/test/documentation.txt b/test/documentation.txt
index d1ae031..ecaf4bd 100644
--- a/test/documentation.txt
+++ b/test/documentation.txt
@@ -12,13 +12,13 @@ pvesh create /cluster/sdn/ --sdn vxlanmulticastzone --type vxlan --uplink-id 1 -
 pvesh create /cluster/sdn/ --sdn vxlanunicastzone --type vxlan --uplink-id 1 --unicast-address 192.168.0.1,192.168.0.2,192.168.0.3
 
 #create a frr router
-pvesh create /cluster/sdn/ --sdn frrrouter1 --type frr --uplink-id 1 --peers 192.168.0.1,192.168.0.2,192.168.0.3 --asn 1234
+pvesh create /cluster/sdn/ --sdn frrrouter1 --type frr --uplink-id 1 --peers 192.168.0.1,192.168.0.2,192.168.0.3 --asn 1234 --gateway-nodes pxnode1,pxnode2 --gateway-external-peers 192.168.0.253,192.168.0.254
 
 #create a layer2 vxlan bgpevpn transportzone
 pvesh create /cluster/sdn/ --sdn layer2evpnzone --type vxlan --uplink-id 1 --router frrrouter1
 
 #create a layer3 routable vxlan bgpevpn transportzone
-pvesh create /cluster/sdn/ --sdn layer3evpnzone --type vxlan --uplink-id 1 --router frrrouter1 --vrf vrf1 --vrf-vxlan 4000 --gateway-nodes pxnode1,pxnode2
+pvesh create /cluster/sdn/ --sdn layer3evpnzone --type vxlan --uplink-id 1 --router frrrouter1 --vrf vrf1 --vrf-vxlan 4000
 
 
 #create a vnet in the transportzone
-- 
2.20.1




More information about the pve-devel mailing list