use strict;
use warnings;
use PVE::Network::SDN::Controllers::Plugin;
-use PVE::Tools;
+use PVE::Tools qw(run_command);
use PVE::INotify;
use PVE::JSONSchema qw(get_standard_option);
sub properties {
return {
- 'uplink-id' => {
- type => 'integer',
- minimum => 1, maximum => 4096,
- description => 'Uplink interface',
- },
'asn' => {
type => 'integer',
description => "autonomous system number",
sub options {
return {
- 'uplink-id' => { optional => 0 },
'asn' => { optional => 0 },
'peers' => { optional => 0 },
'gateway-nodes' => { optional => 1 },
};
}
+sub get_local_route_ip {
+ my ($targetip) = @_;
+
+ my $ip = undef;
+ my $interface = undef;
+
+ run_command(['/sbin/ip', 'route', 'get', $targetip], outfunc => sub {
+ if ($_[0] =~ m/src ($PVE::Tools::IPRE)/) {
+ $ip = $1;
+ }
+ if ($_[0] =~ m/dev (\S+)/) {
+ $interface = $1;
+ }
+
+ });
+ return ($ip, $interface);
+}
+
+sub find_local_ip_interface {
+ my ($peers) = @_;
+
+ my $network_config = PVE::INotify::read_file('interfaces');
+ my $ifaces = $network_config->{ifaces};
+ #is a local ip member of peers list ?
+ foreach my $address (@{$peers}) {
+ while (my $interface = each %$ifaces) {
+ my $ip = $ifaces->{$interface}->{address};
+ if ($ip && $ip eq $address) {
+ return ($ip, $interface);
+ }
+ }
+ }
+
+ #if peer is remote, find source with ip route
+ foreach my $address (@{$peers}) {
+ my ($ip, $interface) = get_local_route_ip($address);
+ return ($ip, $interface);
+ }
+}
+
# Plugin implementation
sub generate_controller_config {
my ($class, $plugin_config, $controller, $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 = "";
-
- if($uplinks->{$uplink}->{name}) {
- $iface = $uplinks->{$uplink}->{name};
- $ifaceip = PVE::Network::SDN::Controllers::Plugin::get_first_local_ipv4_from_interface($iface);
- }
+ my ($ifaceip, $interface) = find_local_ip_interface(\@peers);
my $is_gateway = undef;
my $local_node = PVE::INotify::nodename();
# do nothing by default
}
-#helpers
-
-#to be move to Network.pm helper
-sub get_first_local_ipv4_from_interface {
- my ($interface) = @_;
-
- my $cmd = ['/sbin/ip', 'address', 'show', 'dev', $interface];
-
- my $IP = "";
-
- my $code = sub {
- my $line = shift;
-
- if ($line =~ m!^\s*inet\s+($PVE::Tools::IPRE)(?:/\d+|\s+peer\s+)!) {
- $IP = $1;
- return;
- }
- };
-
- PVE::Tools::run_command($cmd, outfunc => $code);
-
- return $IP;
-}
-
1;
my $vnet_cfg = PVE::Cluster::cfs_read_file('sdn/vnets.cfg');
my $zone_cfg = PVE::Cluster::cfs_read_file('sdn/zones.cfg');
+ my $controller_cfg = PVE::Cluster::cfs_read_file('sdn/controllers.cfg');
return if !$vnet_cfg && !$zone_cfg;
#read main config for physical interfaces
next if defined($plugin_config->{nodes}) && !$plugin_config->{nodes}->{$nodename};
+ my $controller = undef;
+ if($plugin_config->{controller}) {
+ my $controllerid = $plugin_config->{controller};
+ $controller = $controller_cfg->{ids}->{$controllerid};
+ }
+
my $plugin = PVE::Network::SDN::Zones::Plugin->lookup($plugin_config->{type});
- $plugin->generate_sdn_config($plugin_config, $zone, $id, $vnet, $uplinks, $config);
+ $plugin->generate_sdn_config($plugin_config, $zone, $id, $vnet, $uplinks, $controller, $config);
}
my $raw_network_config = "";
use PVE::Network::SDN::Zones::VxlanPlugin;
use PVE::Tools qw($IPV4RE);
use PVE::INotify;
+use PVE::Network::SDN::Controllers::EvpnPlugin;
use base('PVE::Network::SDN::Zones::VxlanPlugin');
return {
nodes => { optional => 1},
- 'uplink-id' => { optional => 0 },
'vrf-vxlan' => { optional => 0 },
'controller' => { optional => 0 },
};
# Plugin implementation
sub generate_sdn_config {
- my ($class, $plugin_config, $zoneid, $vnetid, $vnet, $uplinks, $config) = @_;
+ my ($class, $plugin_config, $zoneid, $vnetid, $vnet, $uplinks, $controller, $config) = @_;
my $tag = $vnet->{tag};
my $alias = $vnet->{alias};
my $ipv6 = $vnet->{ipv6};
my $mac = $vnet->{mac};
- my $uplink = $plugin_config->{'uplink-id'};
my $vrf = $zoneid;
my $vrfvxlan = $plugin_config->{'vrf-vxlan'};
die "missing vxlan tag" if !$tag;
- my $iface = "uplink$uplink";
- my $ifaceip = "";
- if($uplinks->{$uplink}->{name}) {
- $iface = $uplinks->{$uplink}->{name};
- $ifaceip = PVE::Network::SDN::Zones::Plugin::get_first_local_ipv4_from_interface($iface);
- }
+ my @peers = split(',', $controller->{'peers'});
+ my ($ifaceip, $iface) = PVE::Network::SDN::Controllers::EvpnPlugin::find_local_ip_interface(\@peers);
my $mtu = 1450;
- $mtu = $uplinks->{$uplink}->{mtu} - 50 if $uplinks->{$uplink}->{mtu};
+ $mtu = $uplinks->{$iface}->{mtu} - 50 if $uplinks->{$iface}->{mtu};
$mtu = $vnet->{mtu} if $vnet->{mtu};
#vxlan interface
# Plugin implementation
sub generate_sdn_config {
- my ($class, $plugin_config, $zoneid, $vnetid, $vnet, $uplinks, $config) = @_;
+ my ($class, $plugin_config, $zoneid, $vnetid, $vnet, $uplinks, $controller, $config) = @_;
my $mtu = $vnet->{mtu};
my $uplink = $plugin_config->{'uplink-id'};
}
sub generate_sdn_config {
- my ($class, $plugin_config, $node, $data, $ctime) = @_;
+ my ($class, $plugin_config, $zoneid, $vnetid, $vnet, $uplinks, $controller, $config) = @_;
die "please implement inside plugin";
}
# Plugin implementation
sub generate_sdn_config {
- my ($class, $plugin_config, $zoneid, $vnetid, $vnet, $uplinks, $config) = @_;
+ my ($class, $plugin_config, $zoneid, $vnetid, $vnet, $uplinks, $controller, $config) = @_;
my $tag = $vnet->{tag};
my $zone_tag = $plugin_config->{tag};
# Plugin implementation
sub generate_sdn_config {
- my ($class, $plugin_config, $zoneid, $vnetid, $vnet, $uplinks, $config) = @_;
+ my ($class, $plugin_config, $zoneid, $vnetid, $vnet, $uplinks, $controller, $config) = @_;
my $tag = $vnet->{tag};
my $mtu = $vnet->{mtu};
# Plugin implementation
sub generate_sdn_config {
- my ($class, $plugin_config, $zoneid, $vnetid, $vnet, $uplinks, $config) = @_;
+ my ($class, $plugin_config, $zoneid, $vnetid, $vnet, $uplinks, $controller, $config) = @_;
my $tag = $vnet->{tag};
my $alias = $vnet->{alias};
pvesh create /cluster/sdn/zones/ --zone vxlanunicastzone --type vxlan --uplink-id 1 --unicast-address 192.168.0.1,192.168.0.2,192.168.0.3
#create an controller
-pvesh create /cluster/sdn/controllers/ --controller frrrouter1 --type evpn --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
+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 a layer2 vxlan bgpevpn transportzone
-pvesh create /cluster/sdn/zones/ --zone layer2evpnzone --type evpn --uplink-id 1 --controller frrrouter1
+pvesh create /cluster/sdn/zones/ --zone layer2evpnzone --type evpn --controller frrrouter1
#create a layer3 routable vxlan bgpevpn transportzone
-pvesh create /cluster/sdn/zones/ --zone layer3evpnzone --type evpn --uplink-id 1 --controller frrrouter1 --vrf-vxlan 4000
+pvesh create /cluster/sdn/zones/ --zone layer3evpnzone --type evpn --controller frrrouter1 --vrf-vxlan 4000
#create a vnet in the transportzone