]> git.proxmox.com Git - pve-network.git/blobdiff - PVE/Network/SDN/FrrPlugin.pm
move gateway-nodes option to frr plugin and add gateway-external-peers
[pve-network.git] / PVE / Network / SDN / FrrPlugin.pm
index c318b1d21d66deb36cf70a04ba3a7ef75cf10a2f..8a1f86cfd2cb89dfb553e3b72334be672003f8d9 100644 (file)
@@ -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;
 }