use PVE::Network::SDN;
use PVE::Network::SDN::Plugin;
use PVE::Network::SDN::VlanPlugin;
-use PVE::Network::SDN::VxlanMulticastPlugin;
+use PVE::Network::SDN::VxlanPlugin;
use PVE::Network::SDN::VnetPlugin;
use Storable qw(dclone);
use PVE::JSONSchema qw(get_standard_option);
use PVE::Network::SDN::Plugin;
use PVE::Network::SDN::VnetPlugin;
use PVE::Network::SDN::VlanPlugin;
-use PVE::Network::SDN::VxlanMulticastPlugin;
+use PVE::Network::SDN::VxlanPlugin;
PVE::Network::SDN::VnetPlugin->register();
PVE::Network::SDN::VlanPlugin->register();
-PVE::Network::SDN::VxlanMulticastPlugin->register();
+PVE::Network::SDN::VxlanPlugin->register();
PVE::Network::SDN::Plugin->init();
-SOURCES=Plugin.pm VnetPlugin.pm VlanPlugin.pm VxlanMulticastPlugin.pm
+SOURCES=Plugin.pm VnetPlugin.pm VlanPlugin.pm VxlanPlugin.pm
PERL5DIR=${DESTDIR}/usr/share/perl5
return (scalar(@elements) > 1);
}
+#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;
+++ /dev/null
-package PVE::Network::SDN::VxlanMulticastPlugin;
-
-use strict;
-use warnings;
-use PVE::Network::SDN::Plugin;
-
-use base('PVE::Network::SDN::Plugin');
-
-PVE::JSONSchema::register_format('pve-sdn-vxlanrange', \&pve_verify_sdn_vxlanrange);
-sub pve_verify_sdn_vxlanrange {
- my ($vxlanstr) = @_;
-
- PVE::Network::SDN::Plugin::parse_tag_number_or_range($vxlanstr, '16777216');
-
- return $vxlanstr;
-}
-
-sub type {
- return 'vxlanmulticast';
-}
-
-sub properties {
- return {
- 'vxlan-allowed' => {
- type => 'string', format => 'pve-sdn-vxlanrange',
- description => "Allowed vlan range",
- },
- 'multicast-address' => {
- description => "Multicast address.",
- type => 'string', #fixme: format
- },
-
- };
-}
-
-sub options {
-
- return {
- 'uplink-id' => { optional => 0 },
- 'multicast-address' => { optional => 0 },
- 'vxlan-allowed' => { optional => 1 },
- };
-}
-
-# Plugin implementation
-sub generate_sdn_config {
- my ($class, $plugin_config, $zoneid, $vnetid, $vnet, $uplinks) = @_;
-
- my $tag = $vnet->{tag};
- my $alias = $vnet->{alias};
- my $multicastaddress = $plugin_config->{'multicast-address'};
- my $uplink = $plugin_config->{'uplink-id'};
- my $vxlanallowed = $plugin_config->{'vxlan-allowed'};
-
- die "missing vxlan tag" if !$tag;
- my $iface = $uplinks->{$uplink}->{name} ? $uplinks->{$uplink}->{name} : "uplink$uplink";
-
- my $mtu = 1450;
- $mtu = $uplinks->{$uplink}->{mtu} - 50 if $uplinks->{$uplink}->{mtu};
- $mtu = $vnet->{mtu} if $vnet->{mtu};
-
- my $config = "\n";
- $config .= "auto vxlan$vnetid\n";
- $config .= "iface vxlan$vnetid inet manual\n";
- $config .= " vxlan-id $tag\n";
- $config .= " vxlan-svcnodeip $multicastaddress\n" if $multicastaddress;
- $config .= " vxlan-physdev $iface\n" if $iface;
- $config .= " mtu $mtu\n" if $mtu;
- $config .= "\n";
- $config .= "auto $vnetid\n";
- $config .= "iface $vnetid inet manual\n";
- $config .= " bridge_ports vxlan$vnetid\n";
- $config .= " bridge_stp off\n";
- $config .= " bridge_fd 0\n";
- $config .= " mtu $mtu\n" if $mtu;
- $config .= " alias $alias\n" if $alias;
-
- return $config;
-}
-
-sub on_delete_hook {
- my ($class, $transportid, $sdn_cfg) = @_;
-
- # verify that no vnet are associated to this transport
- foreach my $id (keys %{$sdn_cfg->{ids}}) {
- my $sdn = $sdn_cfg->{ids}->{$id};
- die "transport $transportid is used by vnet $id"
- if ($sdn->{type} eq 'vnet' && defined($sdn->{transportzone}) && $sdn->{transportzone} eq $transportid);
- }
-}
-
-sub on_update_hook {
- my ($class, $transportid, $sdn_cfg) = @_;
-
- my $transport = $sdn_cfg->{ids}->{$transportid};
-
- # verify that vxlan-allowed don't conflict with another vxlan-allowed transport
-
- # verify that vxlan-allowed is matching currently vnet tag in this transport
- my $vxlanallowed = $transport->{'vxlan-allowed'};
- if ($vxlanallowed) {
- foreach my $id (keys %{$sdn_cfg->{ids}}) {
- my $sdn = $sdn_cfg->{ids}->{$id};
- if ($sdn->{type} eq 'vnet' && defined($sdn->{tag})) {
- if(defined($sdn->{transportzone}) && $sdn->{transportzone} eq $transportid) {
- my $tag = $sdn->{tag};
- eval {
- PVE::Network::SDN::Plugin::parse_tag_number_or_range($vxlanallowed, '16777216', $tag);
- };
- if($@) {
- die "vnet $id - vlan $tag is not allowed in transport $transportid";
- }
- }
- }
- }
- }
-}
-
-1;
-
-
--- /dev/null
+package PVE::Network::SDN::VxlanPlugin;
+
+use strict;
+use warnings;
+use PVE::Network::SDN::Plugin;
+use PVE::Tools;
+
+use base('PVE::Network::SDN::Plugin');
+
+PVE::JSONSchema::register_format('pve-sdn-vxlanrange', \&pve_verify_sdn_vxlanrange);
+sub pve_verify_sdn_vxlanrange {
+ my ($vxlanstr) = @_;
+
+ PVE::Network::SDN::Plugin::parse_tag_number_or_range($vxlanstr, '16777216');
+
+ return $vxlanstr;
+}
+
+sub type {
+ return 'vxlan';
+}
+
+sub properties {
+ return {
+ 'vxlan-allowed' => {
+ type => 'string', format => 'pve-sdn-vxlanrange',
+ description => "Allowed vlan range",
+ },
+ 'multicast-address' => {
+ description => "Multicast address.",
+ type => 'string', #fixme: format
+ },
+ 'unicast-address' => {
+ description => "Unicast peers address ip list.",
+ type => 'string', #fixme: format
+ },
+ };
+}
+
+sub options {
+
+ return {
+ 'uplink-id' => { optional => 0 },
+ 'multicast-address' => { optional => 1 },
+ 'unicast-address' => { optional => 1 },
+ 'vxlan-allowed' => { optional => 1 },
+ };
+}
+
+# Plugin implementation
+sub generate_sdn_config {
+ my ($class, $plugin_config, $zoneid, $vnetid, $vnet, $uplinks) = @_;
+
+ my $tag = $vnet->{tag};
+ my $alias = $vnet->{alias};
+ my $multicastaddress = $plugin_config->{'multicast-address'};
+ my @unicastaddress = split(',', $plugin_config->{'unicast-address'}) if $plugin_config->{'unicast-address'};
+
+ my $uplink = $plugin_config->{'uplink-id'};
+ my $vxlanallowed = $plugin_config->{'vxlan-allowed'};
+
+ die "missing vxlan tag" if !$tag;
+ my $iface = "uplink$uplink";
+ my $ifaceip = "";
+
+ if($uplinks->{$uplink}->{name}) {
+ $iface = $uplinks->{$uplink}->{name};
+ $ifaceip = PVE::Network::SDN::Plugin::get_first_local_ipv4_from_interface($iface);
+ }
+
+ my $mtu = 1450;
+ $mtu = $uplinks->{$uplink}->{mtu} - 50 if $uplinks->{$uplink}->{mtu};
+ $mtu = $vnet->{mtu} if $vnet->{mtu};
+
+ my $config = "\n";
+ $config .= "auto vxlan$vnetid\n";
+ $config .= "iface vxlan$vnetid inet manual\n";
+ $config .= " vxlan-id $tag\n";
+
+ if($multicastaddress) {
+ $config .= " vxlan-svcnodeip $multicastaddress\n";
+ $config .= " vxlan-physdev $iface\n";
+ } elsif (@unicastaddress) {
+
+ foreach my $address (@unicastaddress) {
+ next if $address eq $ifaceip;
+ $config .= " vxlan_remoteip $address\n";
+ }
+ } else {
+ $config .= " vxlan-local-tunnelip $ifaceip\n" if $ifaceip;
+ $config .= " bridge-learning off\n";
+ $config .= " bridge-arp-nd-suppress on\n";
+ $config .= " bridge-unicast-flood off\n";
+ $config .= " bridge-multicast-flood off\n";
+ }
+
+ $config .= " mtu $mtu\n" if $mtu;
+ $config .= "\n";
+ $config .= "auto $vnetid\n";
+ $config .= "iface $vnetid inet manual\n";
+ $config .= " bridge_ports vxlan$vnetid\n";
+ $config .= " bridge_stp off\n";
+ $config .= " bridge_fd 0\n";
+ $config .= " mtu $mtu\n" if $mtu;
+ $config .= " alias $alias\n" if $alias;
+
+ return $config;
+}
+
+sub on_delete_hook {
+ my ($class, $transportid, $sdn_cfg) = @_;
+
+ # verify that no vnet are associated to this transport
+ foreach my $id (keys %{$sdn_cfg->{ids}}) {
+ my $sdn = $sdn_cfg->{ids}->{$id};
+ die "transport $transportid is used by vnet $id"
+ if ($sdn->{type} eq 'vnet' && defined($sdn->{transportzone}) && $sdn->{transportzone} eq $transportid);
+ }
+}
+
+sub on_update_hook {
+ my ($class, $transportid, $sdn_cfg) = @_;
+
+ my $transport = $sdn_cfg->{ids}->{$transportid};
+
+ # verify that vxlan-allowed don't conflict with another vxlan-allowed transport
+
+ # verify that vxlan-allowed is matching currently vnet tag in this transport
+ my $vxlanallowed = $transport->{'vxlan-allowed'};
+ if ($vxlanallowed) {
+ foreach my $id (keys %{$sdn_cfg->{ids}}) {
+ my $sdn = $sdn_cfg->{ids}->{$id};
+ if ($sdn->{type} eq 'vnet' && defined($sdn->{tag})) {
+ if(defined($sdn->{transportzone}) && $sdn->{transportzone} eq $transportid) {
+ my $tag = $sdn->{tag};
+ eval {
+ PVE::Network::SDN::Plugin::parse_tag_number_or_range($vxlanallowed, '16777216', $tag);
+ };
+ if($@) {
+ die "vnet $id - vlan $tag is not allowed in transport $transportid";
+ }
+ }
+ }
+ }
+ }
+}
+
+1;
+
+