From 074d270b1dec3593b26d55219b6601158c098386 Mon Sep 17 00:00:00 2001 From: Alexandre Derumier Date: Mon, 9 Sep 2019 08:45:53 +0200 Subject: [PATCH] move gateway-nodes option to frr plugin and add gateway-external-peers 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 --- 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.39.2