* [pve-devel] [PATCH V2 pve-network 0/4] add ebgp-evpn support
@ 2020-11-25 9:01 Alexandre Derumier
2020-11-25 9:01 ` [pve-devel] [PATCH V2 pve-network 1/4] controllers: improve bgp-evpn Alexandre Derumier
` (4 more replies)
0 siblings, 5 replies; 6+ messages in thread
From: Alexandre Derumier @ 2020-11-25 9:01 UTC (permalink / raw)
To: pve-devel
This add support for a new controller plugin "bgp",
to manage specific bgp section by host.
This is allowing ebgp
(I'll send doc soon)
Also some fixes on pending parser
Changelog V2:
- fix some bug in bgp plugin
Alexandre Derumier (4):
controllers: improve bgp-evpn
zones: evpn : add support for loopback
update test documentation
sdn: fix : pending parser
PVE/API2/Network/SDN/Controllers.pm | 1 +
PVE/API2/Network/SDN/Zones.pm | 12 +-
PVE/Network/SDN.pm | 45 +++++-
PVE/Network/SDN/Controllers.pm | 12 +-
PVE/Network/SDN/Controllers/BgpPlugin.pm | 153 ++++++++++++++++++++
PVE/Network/SDN/Controllers/EvpnPlugin.pm | 122 ++++++++++------
PVE/Network/SDN/Controllers/FaucetPlugin.pm | 4 +-
PVE/Network/SDN/Controllers/Makefile | 2 +-
PVE/Network/SDN/Controllers/Plugin.pm | 9 +-
PVE/Network/SDN/Zones.pm | 2 +-
PVE/Network/SDN/Zones/EvpnPlugin.pm | 12 +-
PVE/Network/SDN/Zones/Plugin.pm | 39 ++---
PVE/Network/SDN/Zones/QinQPlugin.pm | 2 +-
PVE/Network/SDN/Zones/SimplePlugin.pm | 2 +-
PVE/Network/SDN/Zones/VlanPlugin.pm | 2 +-
PVE/Network/SDN/Zones/VxlanPlugin.pm | 2 +-
test/documentation.txt | 14 +-
17 files changed, 336 insertions(+), 99 deletions(-)
create mode 100644 PVE/Network/SDN/Controllers/BgpPlugin.pm
--
2.20.1
^ permalink raw reply [flat|nested] 6+ messages in thread
* [pve-devel] [PATCH V2 pve-network 1/4] controllers: improve bgp-evpn
2020-11-25 9:01 [pve-devel] [PATCH V2 pve-network 0/4] add ebgp-evpn support Alexandre Derumier
@ 2020-11-25 9:01 ` Alexandre Derumier
2020-11-25 9:01 ` [pve-devel] [PATCH V2 pve-network 2/4] zones: evpn : add support for loopback Alexandre Derumier
` (3 subsequent siblings)
4 siblings, 0 replies; 6+ messages in thread
From: Alexandre Derumier @ 2020-11-25 9:01 UTC (permalink / raw)
To: pve-devel
- add new bgp plugin
- add ebgp support
- add loopback support
- move gateway-nodes option to zone as 'exitnodes'
- move external-peers to bgp plugin
---
PVE/API2/Network/SDN/Controllers.pm | 1 +
PVE/Network/SDN/Controllers.pm | 12 +-
PVE/Network/SDN/Controllers/BgpPlugin.pm | 153 ++++++++++++++++++++
PVE/Network/SDN/Controllers/EvpnPlugin.pm | 122 ++++++++++------
PVE/Network/SDN/Controllers/FaucetPlugin.pm | 4 +-
PVE/Network/SDN/Controllers/Makefile | 2 +-
PVE/Network/SDN/Controllers/Plugin.pm | 9 +-
PVE/Network/SDN/Zones/EvpnPlugin.pm | 11 +-
PVE/Network/SDN/Zones/Plugin.pm | 9 +-
9 files changed, 269 insertions(+), 54 deletions(-)
create mode 100644 PVE/Network/SDN/Controllers/BgpPlugin.pm
diff --git a/PVE/API2/Network/SDN/Controllers.pm b/PVE/API2/Network/SDN/Controllers.pm
index 75beb6b..e761b6c 100644
--- a/PVE/API2/Network/SDN/Controllers.pm
+++ b/PVE/API2/Network/SDN/Controllers.pm
@@ -11,6 +11,7 @@ use PVE::Network::SDN::Zones;
use PVE::Network::SDN::Controllers;
use PVE::Network::SDN::Controllers::Plugin;
use PVE::Network::SDN::Controllers::EvpnPlugin;
+use PVE::Network::SDN::Controllers::BgpPlugin;
use PVE::Network::SDN::Controllers::FaucetPlugin;
use Storable qw(dclone);
diff --git a/PVE/Network/SDN/Controllers.pm b/PVE/Network/SDN/Controllers.pm
index f652d7f..9937755 100644
--- a/PVE/Network/SDN/Controllers.pm
+++ b/PVE/Network/SDN/Controllers.pm
@@ -13,9 +13,11 @@ use PVE::Network::SDN::Vnets;
use PVE::Network::SDN::Zones;
use PVE::Network::SDN::Controllers::EvpnPlugin;
+use PVE::Network::SDN::Controllers::BgpPlugin;
use PVE::Network::SDN::Controllers::FaucetPlugin;
use PVE::Network::SDN::Controllers::Plugin;
PVE::Network::SDN::Controllers::EvpnPlugin->register();
+PVE::Network::SDN::Controllers::BgpPlugin->register();
PVE::Network::SDN::Controllers::FaucetPlugin->register();
PVE::Network::SDN::Controllers::Plugin->init();
@@ -95,24 +97,24 @@ sub generate_controller_config {
#generate configuration
my $config = {};
- foreach my $id (keys %{$controller_cfg->{ids}}) {
+ foreach my $id (sort keys %{$controller_cfg->{ids}}) {
my $plugin_config = $controller_cfg->{ids}->{$id};
my $plugin = PVE::Network::SDN::Controllers::Plugin->lookup($plugin_config->{type});
- $plugin->generate_controller_config($plugin_config, $plugin_config, $id, $uplinks, $config);
+ $plugin->generate_controller_config($plugin_config, $controller_cfg, $id, $uplinks, $config);
}
- foreach my $id (keys %{$zone_cfg->{ids}}) {
+ foreach my $id (sort keys %{$zone_cfg->{ids}}) {
my $plugin_config = $zone_cfg->{ids}->{$id};
my $controllerid = $plugin_config->{controller};
next if !$controllerid;
my $controller = $controller_cfg->{ids}->{$controllerid};
if ($controller) {
my $controller_plugin = PVE::Network::SDN::Controllers::Plugin->lookup($controller->{type});
- $controller_plugin->generate_controller_zone_config($plugin_config, $controller, $id, $uplinks, $config);
+ $controller_plugin->generate_controller_zone_config($plugin_config, $controller, $controller_cfg, $id, $uplinks, $config);
}
}
- foreach my $id (keys %{$vnet_cfg->{ids}}) {
+ foreach my $id (sort keys %{$vnet_cfg->{ids}}) {
my $plugin_config = $vnet_cfg->{ids}->{$id};
my $zoneid = $plugin_config->{zone};
next if !$zoneid;
diff --git a/PVE/Network/SDN/Controllers/BgpPlugin.pm b/PVE/Network/SDN/Controllers/BgpPlugin.pm
new file mode 100644
index 0000000..ccc06a8
--- /dev/null
+++ b/PVE/Network/SDN/Controllers/BgpPlugin.pm
@@ -0,0 +1,153 @@
+package PVE::Network::SDN::Controllers::BgpPlugin;
+
+use strict;
+use warnings;
+
+use PVE::INotify;
+use PVE::JSONSchema qw(get_standard_option);
+use PVE::Tools qw(run_command file_set_contents file_get_contents);
+
+use PVE::Network::SDN::Controllers::Plugin;
+use PVE::Network::SDN::Zones::Plugin;
+use Net::IP;
+
+use base('PVE::Network::SDN::Controllers::Plugin');
+
+sub type {
+ return 'bgp';
+}
+
+sub properties {
+ return {
+ ebgp => {
+ type => 'boolean',
+ optional => 1,
+ description => "Enable ebgp. (remote-as external)",
+ },
+ loopback => {
+ description => "source loopback interface.",
+ type => 'string'
+ },
+ node => get_standard_option('pve-node'),
+ };
+}
+
+sub options {
+ return {
+ 'node' => { optional => 0 },
+ 'asn' => { optional => 0 },
+ 'peers' => { optional => 0 },
+ 'ebgp' => { optional => 1 },
+ 'loopback' => { optional => 1 },
+ };
+}
+
+# Plugin implementation
+sub generate_controller_config {
+ my ($class, $plugin_config, $controller, $id, $uplinks, $config) = @_;
+
+ my @peers;
+ @peers = PVE::Tools::split_list($plugin_config->{'peers'}) if $plugin_config->{'peers'};
+
+ my $asn = $plugin_config->{asn};
+ my $ebgp = $plugin_config->{ebgp};
+ my $loopback = $plugin_config->{loopback};
+ my $local_node = PVE::INotify::nodename();
+
+
+ return if !$asn;
+ return if $local_node ne $plugin_config->{node};
+
+ my $bgp = $config->{frr}->{router}->{"bgp $asn"} //= {};
+
+ my ($ifaceip, $interface) = PVE::Network::SDN::Zones::Plugin::find_local_ip_interface_peers(\@peers, $loopback);
+
+ my $remoteas = $ebgp ? "external" : $asn;
+
+ #global options
+ my @controller_config = (
+ "bgp router-id $ifaceip",
+ "no bgp default ipv4-unicast",
+ "coalesce-time 1000",
+ "bgp network import-check"
+ );
+
+ push(@{$bgp->{""}}, @controller_config) if keys %{$bgp} == 0;
+
+ @controller_config = ();
+ if($ebgp) {
+ push @controller_config, "no bgp ebgp-requires-policy";
+ push @controller_config, "bgp disable-ebgp-connected-route-check" if $loopback;
+ }
+
+ #BGP neighbors
+ if(@peers) {
+ push @controller_config, "neighbor BGP peer-group";
+ push @controller_config, "neighbor BGP remote-as $remoteas";
+ push @controller_config, "neighbor BGP bfd";
+ }
+
+ # BGP peers
+ foreach my $address (@peers) {
+ push @controller_config, "neighbor $address peer-group BGP";
+ }
+ push(@{$bgp->{""}}, @controller_config);
+
+ # address-family unicast
+ if (@peers) {
+ my $ipversion = Net::IP::ip_is_ipv6($ifaceip) ? "ipv6" : "ipv4";
+ my $mask = Net::IP::ip_is_ipv6($ifaceip) ? "/128" : "32";
+
+ push(@{$bgp->{"address-family"}->{"$ipversion unicast"}}, "network $ifaceip/$mask") if $loopback;
+ push(@{$bgp->{"address-family"}->{"$ipversion unicast"}}, "neighbor BGP activate");
+ push(@{$bgp->{"address-family"}->{"$ipversion unicast"}}, "neighbor BGP soft-reconfiguration inbound");
+ }
+
+ return $config;
+}
+
+sub generate_controller_zone_config {
+ my ($class, $plugin_config, $controller, $controller_cfg, $id, $uplinks, $config) = @_;
+
+}
+
+sub on_delete_hook {
+ my ($class, $controllerid, $zone_cfg) = @_;
+
+ # verify that zone is associated to this controller
+ foreach my $id (keys %{$zone_cfg->{ids}}) {
+ my $zone = $zone_cfg->{ids}->{$id};
+ die "controller $controllerid is used by $id"
+ if (defined($zone->{controller}) && $zone->{controller} eq $controllerid);
+ }
+}
+
+sub on_update_hook {
+ my ($class, $controllerid, $controller_cfg) = @_;
+
+ # we can only have 1 bgp controller by node
+ my $local_node = PVE::INotify::nodename();
+ my $controllernb = 0;
+ foreach my $id (keys %{$controller_cfg->{ids}}) {
+ next if $id eq $controllerid;
+ my $controller = $controller_cfg->{ids}->{$id};
+ next if $controller->{type} ne "bgp";
+ next if $controller->{node} ne $local_node;
+ $controllernb++;
+ die "only 1 bgp controller can be defined" if $controllernb > 1;
+ }
+}
+
+sub write_controller_config {
+ my ($class, $plugin_config, $config) = @_;
+ return;
+}
+
+sub reload_controller {
+ my ($class) = @_;
+ return;
+}
+
+1;
+
+
diff --git a/PVE/Network/SDN/Controllers/EvpnPlugin.pm b/PVE/Network/SDN/Controllers/EvpnPlugin.pm
index d82de2a..e59c142 100644
--- a/PVE/Network/SDN/Controllers/EvpnPlugin.pm
+++ b/PVE/Network/SDN/Controllers/EvpnPlugin.pm
@@ -9,6 +9,7 @@ use PVE::Tools qw(run_command file_set_contents file_get_contents);
use PVE::Network::SDN::Controllers::Plugin;
use PVE::Network::SDN::Zones::Plugin;
+use Net::IP;
use base('PVE::Network::SDN::Controllers::Plugin');
@@ -26,11 +27,6 @@ sub properties {
description => "peers address list.",
type => 'string', format => 'ip-list'
},
- 'gateway-nodes' => get_standard_option('pve-node-list'),
- 'gateway-external-peers' => {
- description => "upstream bgp peers address list.",
- type => 'string', format => 'ip-list'
- },
};
}
@@ -38,80 +34,97 @@ sub options {
return {
'asn' => { optional => 0 },
'peers' => { optional => 0 },
- 'gateway-nodes' => { optional => 1 },
- 'gateway-external-peers' => { optional => 1 },
};
}
# Plugin implementation
sub generate_controller_config {
- my ($class, $plugin_config, $controller, $id, $uplinks, $config) = @_;
+ my ($class, $plugin_config, $controller_cfg, $id, $uplinks, $config) = @_;
my @peers;
@peers = PVE::Tools::split_list($plugin_config->{'peers'}) if $plugin_config->{'peers'};
+ my $local_node = PVE::INotify::nodename();
+
my $asn = $plugin_config->{asn};
- my $gatewaynodes = $plugin_config->{'gateway-nodes'};
- my @gatewaypeers;
- @gatewaypeers = PVE::Tools::split_list($plugin_config->{'gateway-external-peers'}) if $plugin_config->{'gateway-external-peers'};
+ my $ebgp = undef;
+ my $loopback = undef;
+ my $autortas = undef;
+ my $bgprouter = find_bgp_controller($local_node, $controller_cfg);
+ if($bgprouter) {
+ $ebgp = 1 if $plugin_config->{'asn'} ne $bgprouter->{asn};
+ $loopback = $bgprouter->{loopback} if $bgprouter->{loopback};
+ $asn = $bgprouter->{asn} if $bgprouter->{asn};
+ $autortas = $plugin_config->{'asn'} if $ebgp;
+ }
return if !$asn;
my $bgp = $config->{frr}->{router}->{"bgp $asn"} //= {};
- my ($ifaceip, $interface) = PVE::Network::SDN::Zones::Plugin::find_local_ip_interface_peers(\@peers);
+ my ($ifaceip, $interface) = PVE::Network::SDN::Zones::Plugin::find_local_ip_interface_peers(\@peers, $loopback);
- 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 $remoteas = $ebgp ? "external" : $asn;
+ #global options
my @controller_config = (
"bgp router-id $ifaceip",
"no bgp default ipv4-unicast",
"coalesce-time 1000",
);
+ push(@{$bgp->{""}}, @controller_config) if keys %{$bgp} == 0;
+
+ @controller_config = ();
+
+ #VTEP neighbors
+ push @controller_config, "neighbor VTEP peer-group";
+ push @controller_config, "neighbor VTEP remote-as $remoteas";
+ push @controller_config, "neighbor VTEP bfd";
+
+ if($ebgp && $loopback) {
+ push @controller_config, "neighbor VTEP ebgp-multihop 10";
+ push @controller_config, "neighbor VTEP update-source $loopback";
+ }
+
+ # VTEP peers
foreach my $address (@peers) {
next if $address eq $ifaceip;
- push @controller_config, "neighbor $address remote-as $asn";
+ push @controller_config, "neighbor $address peer-group VTEP";
}
- if ($is_gateway) {
- foreach my $address (@gatewaypeers) {
- push @controller_config, "neighbor $address remote-as external";
- }
- }
push(@{$bgp->{""}}, @controller_config);
+ # address-family l2vpn
@controller_config = ();
- foreach my $address (@peers) {
- next if $address eq $ifaceip;
- push @controller_config, "neighbor $address activate";
- }
+ push @controller_config, "neighbor VTEP activate";
push @controller_config, "advertise-all-vni";
+ push @controller_config, "autort as $autortas" if $autortas;
push(@{$bgp->{"address-family"}->{"l2vpn evpn"}}, @controller_config);
- if ($is_gateway) {
- # import /32 routes of evpn network from vrf1 to default vrf (for packet return)
- @controller_config = map { "neighbor $_ activate" } @gatewaypeers;
-
- push(@{$bgp->{"address-family"}->{"ipv4 unicast"}}, @controller_config);
- push(@{$bgp->{"address-family"}->{"ipv6 unicast"}}, @controller_config);
- }
-
return $config;
}
sub generate_controller_zone_config {
- my ($class, $plugin_config, $controller, $id, $uplinks, $config) = @_;
+ my ($class, $plugin_config, $controller, $controller_cfg, $id, $uplinks, $config) = @_;
+
+ my $local_node = PVE::INotify::nodename();
my $vrf = "vrf_$id";
my $vrfvxlan = $plugin_config->{'vrf-vxlan'};
+ my $exitnodes = $plugin_config->{'exitnodes'};
+
my $asn = $controller->{asn};
- my $gatewaynodes = $controller->{'gateway-nodes'};
+ my $ebgp = undef;
+ my $loopback = undef;
+ my $autortas = undef;
+ my $bgprouter = find_bgp_controller($local_node, $controller_cfg);
+ if($bgprouter) {
+ $ebgp = 1 if $controller->{'asn'} ne $bgprouter->{asn};
+ $loopback = $bgprouter->{loopback} if $bgprouter->{loopback};
+ $asn = $bgprouter->{asn} if $bgprouter->{asn};
+ $autortas = $controller->{'asn'} if $ebgp;
+ }
return if !$vrf || !$vrfvxlan || !$asn;
@@ -120,11 +133,18 @@ sub generate_controller_zone_config {
push @controller_config, "vni $vrfvxlan";
push(@{$config->{frr}->{vrf}->{"$vrf"}}, @controller_config);
- push(@{$config->{frr}->{router}->{"bgp $asn vrf $vrf"}->{""}}, "!");
+ #main vrf router
+ @controller_config = ();
+ push @controller_config, "no bgp ebgp-requires-policy" if $ebgp;
+# push @controller_config, "!";
+ push(@{$config->{frr}->{router}->{"bgp $asn vrf $vrf"}->{""}}, @controller_config);
- my $local_node = PVE::INotify::nodename();
+ if ($autortas) {
+ push(@{$config->{frr}->{router}->{"bgp $asn vrf $vrf"}->{"address-family"}->{"l2vpn evpn"}}, "route-target import $autortas:$vrfvxlan");
+ push(@{$config->{frr}->{router}->{"bgp $asn vrf $vrf"}->{"address-family"}->{"l2vpn evpn"}}, "route-target export $autortas:$vrfvxlan");
+ }
- my $is_gateway = grep { $_ eq $local_node } PVE::Tools::split_list($gatewaynodes);
+ my $is_gateway = grep { $_ eq $local_node } PVE::Tools::split_list($exitnodes);
if ($is_gateway) {
@controller_config = ();
@@ -165,13 +185,31 @@ sub on_update_hook {
# we can only have 1 evpn controller / 1 asn by server
+ my $controllernb = 0;
foreach my $id (keys %{$controller_cfg->{ids}}) {
next if $id eq $controllerid;
my $controller = $controller_cfg->{ids}->{$id};
- die "only 1 evpn controller can be defined" if $controller->{type} eq "evpn";
+ next if $controller->{type} ne "evpn";
+ $controllernb++;
+ die "only 1 global evpn controller can be defined" if $controllernb > 1;
+ }
+}
+
+sub find_bgp_controller {
+ my ($nodename, $controller_cfg) = @_;
+
+ my $controller = undef;
+ foreach my $id (keys %{$controller_cfg->{ids}}) {
+ $controller = $controller_cfg->{ids}->{$id};
+ next if $controller->{type} ne 'bgp';
+ next if $controller->{node} ne $nodename;
+ last;
}
+
+ return $controller;
}
+
sub sort_frr_config {
my $order = {};
$order->{''} = 0;
diff --git a/PVE/Network/SDN/Controllers/FaucetPlugin.pm b/PVE/Network/SDN/Controllers/FaucetPlugin.pm
index dcac6eb..5742187 100644
--- a/PVE/Network/SDN/Controllers/FaucetPlugin.pm
+++ b/PVE/Network/SDN/Controllers/FaucetPlugin.pm
@@ -22,12 +22,12 @@ sub properties {
# Plugin implementation
sub generate_controller_config {
- my ($class, $plugin_config, $controller, $id, $uplinks, $config) = @_;
+ my ($class, $plugin_config, $controller_cfg, $id, $uplinks, $config) = @_;
}
sub generate_controller_zone_config {
- my ($class, $plugin_config, $controller, $id, $uplinks, $config) = @_;
+ my ($class, $plugin_config, $controller, $controller_cfg, $id, $uplinks, $config) = @_;
my $dpid = $plugin_config->{'dp-id'};
my $dphex = printf("%x",$dpid);
diff --git a/PVE/Network/SDN/Controllers/Makefile b/PVE/Network/SDN/Controllers/Makefile
index 3324125..11686a3 100644
--- a/PVE/Network/SDN/Controllers/Makefile
+++ b/PVE/Network/SDN/Controllers/Makefile
@@ -1,4 +1,4 @@
-SOURCES=Plugin.pm FaucetPlugin.pm EvpnPlugin.pm
+SOURCES=Plugin.pm FaucetPlugin.pm EvpnPlugin.pm BgpPlugin.pm
PERL5DIR=${DESTDIR}/usr/share/perl5
diff --git a/PVE/Network/SDN/Controllers/Plugin.pm b/PVE/Network/SDN/Controllers/Plugin.pm
index 06cd576..0c92b17 100644
--- a/PVE/Network/SDN/Controllers/Plugin.pm
+++ b/PVE/Network/SDN/Controllers/Plugin.pm
@@ -70,7 +70,14 @@ sub generate_sdn_config {
}
sub generate_controller_config {
- my ($class, $plugin_config, $controller, $id, $uplinks, $config) = @_;
+ my ($class, $plugin_config, $controller_cfg, $id, $uplinks, $config) = @_;
+
+ die "please implement inside plugin";
+}
+
+
+sub generate_controller_zone_config {
+ my ($class, $plugin_config, $controller, $controller_cfg, $id, $uplinks, $config) = @_;
die "please implement inside plugin";
}
diff --git a/PVE/Network/SDN/Zones/EvpnPlugin.pm b/PVE/Network/SDN/Zones/EvpnPlugin.pm
index 5338a1b..d50ddb9 100644
--- a/PVE/Network/SDN/Zones/EvpnPlugin.pm
+++ b/PVE/Network/SDN/Zones/EvpnPlugin.pm
@@ -4,6 +4,7 @@ use strict;
use warnings;
use PVE::Network::SDN::Zones::VxlanPlugin;
use PVE::Exception qw(raise raise_param_exc);
+use PVE::JSONSchema qw(get_standard_option);
use PVE::Tools qw($IPV4RE);
use PVE::INotify;
use PVE::Cluster;
@@ -27,6 +28,7 @@ sub properties {
type => 'string',
description => "Frr router name",
},
+ 'exitnodes' => get_standard_option('pve-node-list'),
};
}
@@ -35,7 +37,8 @@ sub options {
return {
nodes => { optional => 1},
'vrf-vxlan' => { optional => 0 },
- 'controller' => { optional => 0 },
+ controller => { optional => 0 },
+ exitnodes => { optional => 1 },
mtu => { optional => 1 },
dns => { optional => 1 },
reversedns => { optional => 1 },
@@ -59,10 +62,14 @@ sub generate_sdn_config {
my $local_node = PVE::INotify::nodename();
die "missing vxlan tag" if !$tag;
+ die "missing controller" if !$controller;
warn "vlan-aware vnet can't be enabled with evpn plugin" if $vnet->{vlanaware};
my @peers = PVE::Tools::split_list($controller->{'peers'});
- my ($ifaceip, $iface) = PVE::Network::SDN::Zones::Plugin::find_local_ip_interface_peers(\@peers);
+# my $bgprouter = PVE::Network::SDN::Controllers::EvpnController::find_bgp_controller($local_node, $controller_cfg);
+# my $loopback = $bgprouter->{loopback} if $bgprouter->{loopback};
+ my $loopback = undef;
+ my ($ifaceip, $iface) = PVE::Network::SDN::Zones::Plugin::find_local_ip_interface_peers(\@peers, $loopback);
my $mtu = 1450;
$mtu = $interfaces_config->{$iface}->{mtu} - 50 if $interfaces_config->{$iface}->{mtu};
diff --git a/PVE/Network/SDN/Zones/Plugin.pm b/PVE/Network/SDN/Zones/Plugin.pm
index 6fc13eb..aa795a3 100644
--- a/PVE/Network/SDN/Zones/Plugin.pm
+++ b/PVE/Network/SDN/Zones/Plugin.pm
@@ -274,10 +274,17 @@ sub get_local_route_ip {
sub find_local_ip_interface_peers {
- my ($peers) = @_;
+ my ($peers, $iface) = @_;
my $network_config = PVE::INotify::read_file('interfaces');
my $ifaces = $network_config->{ifaces};
+
+ #if iface is defined, return ip if exist (if not,try to find it on other ifaces)
+ if ($iface) {
+ my $ip = $ifaces->{$iface}->{address};
+ return ($ip,$iface) if $ip;
+ }
+
#is a local ip member of peers list ?
foreach my $address (@{$peers}) {
while (my $interface = each %$ifaces) {
--
2.20.1
^ permalink raw reply [flat|nested] 6+ messages in thread
* [pve-devel] [PATCH V2 pve-network 2/4] zones: evpn : add support for loopback
2020-11-25 9:01 [pve-devel] [PATCH V2 pve-network 0/4] add ebgp-evpn support Alexandre Derumier
2020-11-25 9:01 ` [pve-devel] [PATCH V2 pve-network 1/4] controllers: improve bgp-evpn Alexandre Derumier
@ 2020-11-25 9:01 ` Alexandre Derumier
2020-11-25 9:01 ` [pve-devel] [PATCH V2 pve-network 3/4] update test documentation Alexandre Derumier
` (2 subsequent siblings)
4 siblings, 0 replies; 6+ messages in thread
From: Alexandre Derumier @ 2020-11-25 9:01 UTC (permalink / raw)
To: pve-devel
---
PVE/Network/SDN/Zones.pm | 2 +-
PVE/Network/SDN/Zones/EvpnPlugin.pm | 7 +++----
PVE/Network/SDN/Zones/Plugin.pm | 2 +-
PVE/Network/SDN/Zones/QinQPlugin.pm | 2 +-
PVE/Network/SDN/Zones/SimplePlugin.pm | 2 +-
PVE/Network/SDN/Zones/VlanPlugin.pm | 2 +-
PVE/Network/SDN/Zones/VxlanPlugin.pm | 2 +-
7 files changed, 9 insertions(+), 10 deletions(-)
diff --git a/PVE/Network/SDN/Zones.pm b/PVE/Network/SDN/Zones.pm
index 1f225dc..67d8f18 100644
--- a/PVE/Network/SDN/Zones.pm
+++ b/PVE/Network/SDN/Zones.pm
@@ -131,7 +131,7 @@ sub generate_etc_network_config {
my $plugin = PVE::Network::SDN::Zones::Plugin->lookup($plugin_config->{type});
eval {
- $plugin->generate_sdn_config($plugin_config, $zone, $id, $vnet, $controller, $subnet_cfg, $interfaces_config, $config);
+ $plugin->generate_sdn_config($plugin_config, $zone, $id, $vnet, $controller, $controller_cfg, $subnet_cfg, $interfaces_config, $config);
};
if (my $err = $@) {
warn "zone $zone : vnet $id : $err\n";
diff --git a/PVE/Network/SDN/Zones/EvpnPlugin.pm b/PVE/Network/SDN/Zones/EvpnPlugin.pm
index d50ddb9..14bbf56 100644
--- a/PVE/Network/SDN/Zones/EvpnPlugin.pm
+++ b/PVE/Network/SDN/Zones/EvpnPlugin.pm
@@ -49,7 +49,7 @@ sub options {
# Plugin implementation
sub generate_sdn_config {
- my ($class, $plugin_config, $zoneid, $vnetid, $vnet, $controller, $subnet_cfg, $interfaces_config, $config) = @_;
+ my ($class, $plugin_config, $zoneid, $vnetid, $vnet, $controller, $controller_cfg, $subnet_cfg, $interfaces_config, $config) = @_;
my $tag = $vnet->{tag};
my $alias = $vnet->{alias};
@@ -66,9 +66,8 @@ sub generate_sdn_config {
warn "vlan-aware vnet can't be enabled with evpn plugin" if $vnet->{vlanaware};
my @peers = PVE::Tools::split_list($controller->{'peers'});
-# my $bgprouter = PVE::Network::SDN::Controllers::EvpnController::find_bgp_controller($local_node, $controller_cfg);
-# my $loopback = $bgprouter->{loopback} if $bgprouter->{loopback};
- my $loopback = undef;
+ my $bgprouter = PVE::Network::SDN::Controllers::EvpnPlugin::find_bgp_controller($local_node, $controller_cfg);
+ my $loopback = $bgprouter->{loopback} if $bgprouter->{loopback};
my ($ifaceip, $iface) = PVE::Network::SDN::Zones::Plugin::find_local_ip_interface_peers(\@peers, $loopback);
my $mtu = 1450;
diff --git a/PVE/Network/SDN/Zones/Plugin.pm b/PVE/Network/SDN/Zones/Plugin.pm
index aa795a3..8592e3c 100644
--- a/PVE/Network/SDN/Zones/Plugin.pm
+++ b/PVE/Network/SDN/Zones/Plugin.pm
@@ -98,7 +98,7 @@ sub parse_section_header {
}
sub generate_sdn_config {
- my ($class, $plugin_config, $zoneid, $vnetid, $vnet, $controller, $subnet_cfg, $interfaces_config, $config) = @_;
+ my ($class, $plugin_config, $zoneid, $vnetid, $vnet, $controller, $controller_cfg, $subnet_cfg, $interfaces_config, $config) = @_;
die "please implement inside plugin";
}
diff --git a/PVE/Network/SDN/Zones/QinQPlugin.pm b/PVE/Network/SDN/Zones/QinQPlugin.pm
index 5d40db8..2bd60db 100644
--- a/PVE/Network/SDN/Zones/QinQPlugin.pm
+++ b/PVE/Network/SDN/Zones/QinQPlugin.pm
@@ -49,7 +49,7 @@ sub options {
# Plugin implementation
sub generate_sdn_config {
- my ($class, $plugin_config, $zoneid, $vnetid, $vnet, $controller, $subnet_cfg, $interfaces_config, $config) = @_;
+ my ($class, $plugin_config, $zoneid, $vnetid, $vnet, $controller, $controller_cfg, $subnet_cfg, $interfaces_config, $config) = @_;
my $stag = $plugin_config->{tag};
my $mtu = $plugin_config->{mtu};
diff --git a/PVE/Network/SDN/Zones/SimplePlugin.pm b/PVE/Network/SDN/Zones/SimplePlugin.pm
index c4f4475..ed41e62 100644
--- a/PVE/Network/SDN/Zones/SimplePlugin.pm
+++ b/PVE/Network/SDN/Zones/SimplePlugin.pm
@@ -43,7 +43,7 @@ sub options {
# Plugin implementation
sub generate_sdn_config {
- my ($class, $plugin_config, $zoneid, $vnetid, $vnet, $controller, $subnet_cfg, $interfaces_config, $config) = @_;
+ my ($class, $plugin_config, $zoneid, $vnetid, $vnet, $controller, $controller_cfg, $subnet_cfg, $interfaces_config, $config) = @_;
return $config if$config->{$vnetid}; # nothing to do
diff --git a/PVE/Network/SDN/Zones/VlanPlugin.pm b/PVE/Network/SDN/Zones/VlanPlugin.pm
index 7af9b2c..ca6bd8f 100644
--- a/PVE/Network/SDN/Zones/VlanPlugin.pm
+++ b/PVE/Network/SDN/Zones/VlanPlugin.pm
@@ -43,7 +43,7 @@ sub options {
# Plugin implementation
sub generate_sdn_config {
- my ($class, $plugin_config, $zoneid, $vnetid, $vnet, $controller, $subnet_cfg, $interfaces_config, $config) = @_;
+ my ($class, $plugin_config, $zoneid, $vnetid, $vnet, $controller, $controller_cfg, $subnet_cfg, $interfaces_config, $config) = @_;
my $bridge = $plugin_config->{bridge};
die "can't find bridge $bridge" if !-d "/sys/class/net/$bridge";
diff --git a/PVE/Network/SDN/Zones/VxlanPlugin.pm b/PVE/Network/SDN/Zones/VxlanPlugin.pm
index 1fe16b8..c018d34 100644
--- a/PVE/Network/SDN/Zones/VxlanPlugin.pm
+++ b/PVE/Network/SDN/Zones/VxlanPlugin.pm
@@ -47,7 +47,7 @@ sub options {
# Plugin implementation
sub generate_sdn_config {
- my ($class, $plugin_config, $zoneid, $vnetid, $vnet, $controller, $subnet_cfg, $interfaces_config, $config) = @_;
+ my ($class, $plugin_config, $zoneid, $vnetid, $vnet, $controller, $controller_cfg, $subnet_cfg, $interfaces_config, $config) = @_;
my $tag = $vnet->{tag};
my $alias = $vnet->{alias};
--
2.20.1
^ permalink raw reply [flat|nested] 6+ messages in thread
* [pve-devel] [PATCH V2 pve-network 3/4] update test documentation
2020-11-25 9:01 [pve-devel] [PATCH V2 pve-network 0/4] add ebgp-evpn support Alexandre Derumier
2020-11-25 9:01 ` [pve-devel] [PATCH V2 pve-network 1/4] controllers: improve bgp-evpn Alexandre Derumier
2020-11-25 9:01 ` [pve-devel] [PATCH V2 pve-network 2/4] zones: evpn : add support for loopback Alexandre Derumier
@ 2020-11-25 9:01 ` Alexandre Derumier
2020-11-25 9:01 ` [pve-devel] [PATCH V2 pve-network 4/4] sdn: fix : pending parser Alexandre Derumier
2020-11-25 14:00 ` [pve-devel] applied-series: [PATCH V2 pve-network 0/4] add ebgp-evpn support Thomas Lamprecht
4 siblings, 0 replies; 6+ messages in thread
From: Alexandre Derumier @ 2020-11-25 9:01 UTC (permalink / raw)
To: pve-devel
---
test/documentation.txt | 14 +++++++++-----
1 file changed, 9 insertions(+), 5 deletions(-)
diff --git a/test/documentation.txt b/test/documentation.txt
index 7886966..6ee8ee6 100644
--- a/test/documentation.txt
+++ b/test/documentation.txt
@@ -12,14 +12,18 @@ pvesh create /cluster/sdn/vnets/vnet100/subnets/ --type subnet --subnet 192.168.
#create a layer2 vxlan unicast transportzone
pvesh create /cluster/sdn/zones/ --zone vxlanunicastzone --type vxlan --ipam pve --peers 192.168.0.1,192.168.0.2,192.168.0.3
-#create an controller
-pvesh create /cluster/sdn/controllers/ --controller frrrouter1 --type evpn --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 an evpn controller
+pvesh create /cluster/sdn/controllers/ --controller evpn1 --type evpn --peers 192.168.0.1,192.168.0.2,192.168.0.3 --asn 1234
+
+#add a ebgp peer
+pvesh create /cluster/sdn/controllers/ --controller bgp1 --type bgp --peers 192.168.0.253,192.168.0.254 --asn 1234 --ebgp --node pxnode1
#create a layer2 vxlan bgpevpn transportzone
-pvesh create /cluster/sdn/zones/ --zone layer2evpnzone --type evpn --ipam pve --controller frrrouter1
+pvesh create /cluster/sdn/zones/ --zone layer2evpnzone --type evpn --ipam pve --controller evpn1
+
+#create a layer3 routable vxlan bgpevpn transportzone + exit-nodes
+pvesh create /cluster/sdn/zones/ --zone layer3evpnzone --type evpn --ipam pve --controller evpn1 --vrf-vxlan 4000 --exit-nodes pxnode1,pxnode2
-#create a layer3 routable vxlan bgpevpn transportzone
-pvesh create /cluster/sdn/zones/ --zone layer3evpnzone --type evpn --ipam pve --controller frrrouter1 --vrf-vxlan 4000
#create a vnet in the transportzone
--
2.20.1
^ permalink raw reply [flat|nested] 6+ messages in thread
* [pve-devel] [PATCH V2 pve-network 4/4] sdn: fix : pending parser
2020-11-25 9:01 [pve-devel] [PATCH V2 pve-network 0/4] add ebgp-evpn support Alexandre Derumier
` (2 preceding siblings ...)
2020-11-25 9:01 ` [pve-devel] [PATCH V2 pve-network 3/4] update test documentation Alexandre Derumier
@ 2020-11-25 9:01 ` Alexandre Derumier
2020-11-25 14:00 ` [pve-devel] applied-series: [PATCH V2 pve-network 0/4] add ebgp-evpn support Thomas Lamprecht
4 siblings, 0 replies; 6+ messages in thread
From: Alexandre Derumier @ 2020-11-25 9:01 UTC (permalink / raw)
To: pve-devel
---
PVE/API2/Network/SDN/Zones.pm | 12 +++++++--
PVE/Network/SDN.pm | 45 ++++++++++++++++++++++++++++++---
PVE/Network/SDN/Zones/Plugin.pm | 28 --------------------
3 files changed, 52 insertions(+), 33 deletions(-)
diff --git a/PVE/API2/Network/SDN/Zones.pm b/PVE/API2/Network/SDN/Zones.pm
index 5ae577b..5bbdd36 100644
--- a/PVE/API2/Network/SDN/Zones.pm
+++ b/PVE/API2/Network/SDN/Zones.pm
@@ -38,12 +38,20 @@ my $api_sdn_zones_config = sub {
$scfg->{digest} = $cfg->{digest};
if ($scfg->{nodes}) {
- $scfg->{nodes} = PVE::Network::SDN::Zones::Plugin->encode_value($scfg->{type}, 'nodes', $scfg->{nodes});
+ $scfg->{nodes} = PVE::Network::SDN::encode_value($scfg->{type}, 'nodes', $scfg->{nodes});
+ }
+
+ if ($scfg->{exitnodes}) {
+ $scfg->{exitnodes} = PVE::Network::SDN::encode_value($scfg->{type}, 'exitnodes', $scfg->{exitnodes});
}
my $pending = $scfg->{pending};
if ($pending->{nodes}) {
- $pending->{nodes} = PVE::Network::SDN::Zones::Plugin->encode_value($scfg->{type}, 'nodes', $pending->{nodes});
+ $pending->{nodes} = PVE::Network::SDN::encode_value($scfg->{type}, 'nodes', $pending->{nodes});
+ }
+
+ if ($pending->{exitnodes}) {
+ $pending->{exitnodes} = PVE::Network::SDN::encode_value($scfg->{type}, 'exitnodes', $pending->{exitnodes});
}
return $scfg;
diff --git a/PVE/Network/SDN.pm b/PVE/Network/SDN.pm
index 3cd73ff..c0c5672 100644
--- a/PVE/Network/SDN.pm
+++ b/PVE/Network/SDN.pm
@@ -6,6 +6,8 @@ use warnings;
use Data::Dumper;
use JSON;
+use PVE::JSONSchema;
+
use PVE::Network::SDN::Vnets;
use PVE::Network::SDN::Zones;
use PVE::Network::SDN::Controllers;
@@ -96,7 +98,11 @@ sub pending_config {
$pending->{$id}->{$key} = $running_object->{$key};
if(!keys %{$config_object}) {
$pending->{$id}->{state} = "deleted";
- } elsif ($running_object->{$key} ne $config_object->{$key}) {
+ } elsif (!defined($config_object->{$key})) {
+ $pending->{$id}->{"pending"}->{$key} = 'deleted';
+ $pending->{$id}->{state} = "changed";
+ } elsif (PVE::Network::SDN::encode_value(undef, $key, $running_object->{$key})
+ ne PVE::Network::SDN::encode_value(undef, $key, $config_object->{$key})) {
$pending->{$id}->{state} = "changed";
}
}
@@ -107,8 +113,8 @@ sub pending_config {
my $config_object = $config_objects->{$id};
foreach my $key (sort keys %{$config_object}) {
- my $config_value = $config_object->{$key} if $config_object->{$key};
- my $running_value = $running_object->{$key} if $running_object->{$key};
+ my $config_value = PVE::Network::SDN::encode_value(undef, $key, $config_object->{$key}) if $config_object->{$key};
+ my $running_value = PVE::Network::SDN::encode_value(undef, $key, $running_object->{$key}) if $running_object->{$key};
if($key eq 'type' || $key eq 'vnet') {
$pending->{$id}->{$key} = $config_value;
} else {
@@ -210,5 +216,38 @@ sub generate_controller_config {
PVE::Network::SDN::Controllers::reload_controller() if $reload;
}
+
+sub decode_value {
+ my ($type, $key, $value) = @_;
+
+ if ($key eq 'nodes') {
+ my $res = {};
+
+ foreach my $node (PVE::Tools::split_list($value)) {
+ if (PVE::JSONSchema::pve_verify_node_name($node)) {
+ $res->{$node} = 1;
+ }
+ }
+
+ return $res;
+ }
+
+ return $value;
+}
+
+sub encode_value {
+ my ($type, $key, $value) = @_;
+
+ if ($key eq 'nodes' || $key eq 'exitnodes') {
+ if(ref($value) eq 'HASH') {
+ return join(',', sort keys(%$value));
+ } else {
+ return $value;
+ }
+ }
+
+ return $value;
+}
+
1;
diff --git a/PVE/Network/SDN/Zones/Plugin.pm b/PVE/Network/SDN/Zones/Plugin.pm
index 8592e3c..ebb5c7e 100644
--- a/PVE/Network/SDN/Zones/Plugin.pm
+++ b/PVE/Network/SDN/Zones/Plugin.pm
@@ -55,34 +55,6 @@ sub private {
return $defaultData;
}
-sub decode_value {
- my ($class, $type, $key, $value) = @_;
-
- if ($key eq 'nodes') {
- my $res = {};
-
- foreach my $node (PVE::Tools::split_list($value)) {
- if (PVE::JSONSchema::pve_verify_node_name($node)) {
- $res->{$node} = 1;
- }
- }
-
- return $res;
- }
-
- return $value;
-}
-
-sub encode_value {
- my ($class, $type, $key, $value) = @_;
-
- if ($key eq 'nodes') {
- return join(',', keys(%$value));
- }
-
- return $value;
-}
-
sub parse_section_header {
my ($class, $line) = @_;
--
2.20.1
^ permalink raw reply [flat|nested] 6+ messages in thread
* [pve-devel] applied-series: [PATCH V2 pve-network 0/4] add ebgp-evpn support
2020-11-25 9:01 [pve-devel] [PATCH V2 pve-network 0/4] add ebgp-evpn support Alexandre Derumier
` (3 preceding siblings ...)
2020-11-25 9:01 ` [pve-devel] [PATCH V2 pve-network 4/4] sdn: fix : pending parser Alexandre Derumier
@ 2020-11-25 14:00 ` Thomas Lamprecht
4 siblings, 0 replies; 6+ messages in thread
From: Thomas Lamprecht @ 2020-11-25 14:00 UTC (permalink / raw)
To: Proxmox VE development discussion, Alexandre Derumier
On 25.11.20 10:01, Alexandre Derumier wrote:
> This add support for a new controller plugin "bgp",
> to manage specific bgp section by host.
> This is allowing ebgp
>
> (I'll send doc soon)
>
> Also some fixes on pending parser
>
> Changelog V2:
>
> - fix some bug in bgp plugin
>
> Alexandre Derumier (4):
> controllers: improve bgp-evpn
> zones: evpn : add support for loopback
> update test documentation
> sdn: fix : pending parser
>
> PVE/API2/Network/SDN/Controllers.pm | 1 +
> PVE/API2/Network/SDN/Zones.pm | 12 +-
> PVE/Network/SDN.pm | 45 +++++-
> PVE/Network/SDN/Controllers.pm | 12 +-
> PVE/Network/SDN/Controllers/BgpPlugin.pm | 153 ++++++++++++++++++++
> PVE/Network/SDN/Controllers/EvpnPlugin.pm | 122 ++++++++++------
> PVE/Network/SDN/Controllers/FaucetPlugin.pm | 4 +-
> PVE/Network/SDN/Controllers/Makefile | 2 +-
> PVE/Network/SDN/Controllers/Plugin.pm | 9 +-
> PVE/Network/SDN/Zones.pm | 2 +-
> PVE/Network/SDN/Zones/EvpnPlugin.pm | 12 +-
> PVE/Network/SDN/Zones/Plugin.pm | 39 ++---
> PVE/Network/SDN/Zones/QinQPlugin.pm | 2 +-
> PVE/Network/SDN/Zones/SimplePlugin.pm | 2 +-
> PVE/Network/SDN/Zones/VlanPlugin.pm | 2 +-
> PVE/Network/SDN/Zones/VxlanPlugin.pm | 2 +-
> test/documentation.txt | 14 +-
> 17 files changed, 336 insertions(+), 99 deletions(-)
> create mode 100644 PVE/Network/SDN/Controllers/BgpPlugin.pm
>
applied, thanks!
FYI, I tried to create a somewhat sensible perlcritic config which could be useful.
It shows a few conditionally declared variables (`my $foo = 1 if $bar`) in pve-network,
among other things:
https://pve.proxmox.com/wiki/Perl_Style_Guide#Basic_Linting_with_perlcritic
Maybe it help you (and naturally all others) to avoid a few such possible bugs.
Note, it is not a complete check, e.g., it does not cares a bout a few things
(missing variables or so).
^ permalink raw reply [flat|nested] 6+ messages in thread
end of thread, other threads:[~2020-11-25 14:00 UTC | newest]
Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-11-25 9:01 [pve-devel] [PATCH V2 pve-network 0/4] add ebgp-evpn support Alexandre Derumier
2020-11-25 9:01 ` [pve-devel] [PATCH V2 pve-network 1/4] controllers: improve bgp-evpn Alexandre Derumier
2020-11-25 9:01 ` [pve-devel] [PATCH V2 pve-network 2/4] zones: evpn : add support for loopback Alexandre Derumier
2020-11-25 9:01 ` [pve-devel] [PATCH V2 pve-network 3/4] update test documentation Alexandre Derumier
2020-11-25 9:01 ` [pve-devel] [PATCH V2 pve-network 4/4] sdn: fix : pending parser Alexandre Derumier
2020-11-25 14:00 ` [pve-devel] applied-series: [PATCH V2 pve-network 0/4] add ebgp-evpn support Thomas Lamprecht
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox