]> git.proxmox.com Git - pve-network.git/commitdiff
add evpnplugin (splitted from vxlanplugin)
authorAlexandre Derumier <aderumier@odiso.com>
Mon, 30 Sep 2019 09:03:35 +0000 (11:03 +0200)
committerThomas Lamprecht <t.lamprecht@proxmox.com>
Thu, 17 Oct 2019 17:25:49 +0000 (19:25 +0200)
Signed-off-by: Alexandre Derumier <aderumier@odiso.com>
PVE/API2/Network/SDN.pm
PVE/Network/SDN.pm
PVE/Network/SDN/EvpnPlugin.pm [new file with mode: 0644]
PVE/Network/SDN/Makefile
PVE/Network/SDN/VxlanPlugin.pm
test/documentation.txt

index e4ed5cc6b4158aeb3fb51405081fc14cce824add..cbd393e7b45f2fcbe204264e9356101560ca5a32 100644 (file)
@@ -14,6 +14,7 @@ use PVE::Network::SDN::VnetPlugin;
 use PVE::Network::SDN::FrrPlugin;
 use PVE::Network::SDN::OVSFaucetPlugin;
 use PVE::Network::SDN::FaucetPlugin;
+use PVE::Network::SDN::EvpnPlugin;
 
 use Storable qw(dclone);
 use PVE::JSONSchema qw(get_standard_option);
index 1946bc539da7a3d5b5c144b483bae6c88b8dd582..137f9f934a2850385247b99381ba248d14bb366b 100644 (file)
@@ -15,6 +15,7 @@ use PVE::Network::SDN::VxlanPlugin;
 use PVE::Network::SDN::FrrPlugin;
 use PVE::Network::SDN::OVSFaucetPlugin;
 use PVE::Network::SDN::FaucetPlugin;
+use PVE::Network::SDN::EvpnPlugin;
 
 PVE::Network::SDN::VnetPlugin->register();
 PVE::Network::SDN::VlanPlugin->register();
@@ -22,6 +23,7 @@ PVE::Network::SDN::VxlanPlugin->register();
 PVE::Network::SDN::FrrPlugin->register();
 PVE::Network::SDN::OVSFaucetPlugin->register();
 PVE::Network::SDN::FaucetPlugin->register();
+PVE::Network::SDN::EvpnPlugin->register();
 PVE::Network::SDN::Plugin->init();
 
 
diff --git a/PVE/Network/SDN/EvpnPlugin.pm b/PVE/Network/SDN/EvpnPlugin.pm
new file mode 100644 (file)
index 0000000..f570f2f
--- /dev/null
@@ -0,0 +1,200 @@
+package PVE::Network::SDN::EvpnPlugin;
+
+use strict;
+use warnings;
+use PVE::Network::SDN::Plugin;
+use PVE::Tools qw($IPV4RE);
+use PVE::INotify;
+
+use base('PVE::Network::SDN::VxlanPlugin');
+
+sub type {
+    return 'evpn';
+}
+
+sub plugindata {
+    return {
+        role => 'transport',
+    };
+}
+
+sub properties {
+    return {
+       'vrf' => {
+           description => "vrf name.",
+           type => 'string',  #fixme: format
+       },
+       'vrf-vxlan' => {
+           type => 'integer',
+           description => "l3vni.",
+       },
+       'controller' => {
+           type => 'string',
+           description => "Frr router name",
+       },
+    };
+}
+
+sub options {
+
+    return {
+       'uplink-id' => { optional => 0 },
+        'vxlan-allowed' => { optional => 1 },
+        'vrf' => { 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 $tag = $vnet->{tag};
+    my $alias = $vnet->{alias};
+    my $ipv4 = $vnet->{ipv4};
+    my $ipv6 = $vnet->{ipv6};
+    my $mac = $vnet->{mac};
+
+    my $uplink = $plugin_config->{'uplink-id'};
+    my $vxlanallowed = $plugin_config->{'vxlan-allowed'};
+    my $vrf = $plugin_config->{'vrf'};
+    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::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};
+
+    #vxlan interface
+    my @iface_config = ();
+    push @iface_config, "vxlan-id $tag";
+
+    push @iface_config, "vxlan-local-tunnelip $ifaceip" if $ifaceip;
+    push @iface_config, "bridge-learning off";
+    push @iface_config, "bridge-arp-nd-suppress on";
+
+    push @iface_config, "mtu $mtu" if $mtu;
+    push(@{$config->{"vxlan$vnetid"}}, @iface_config) if !$config->{"vxlan$vnetid"};
+
+    #vnet bridge
+    @iface_config = ();
+    push @iface_config, "address $ipv4" if $ipv4;
+    push @iface_config, "address $ipv6" if $ipv6;
+    push @iface_config, "hwaddress $mac" if $mac;
+    push @iface_config, "bridge_ports vxlan$vnetid";
+    push @iface_config, "bridge_stp off";
+    push @iface_config, "bridge_fd 0";
+    push @iface_config, "mtu $mtu" if $mtu;
+    push @iface_config, "alias $alias" if $alias;
+    push @iface_config, "ip-forward on" if $ipv4;
+    push @iface_config, "ip6-forward on" if $ipv6;
+    push @iface_config, "arp-accept on" if $ipv4||$ipv6;
+    push @iface_config, "vrf $vrf" if $vrf;
+    push(@{$config->{$vnetid}}, @iface_config) if !$config->{$vnetid};
+
+    if ($vrf) {
+       #vrf interface
+       @iface_config = ();
+       push @iface_config, "vrf-table auto";
+       push(@{$config->{$vrf}}, @iface_config) if !$config->{$vrf};
+
+       if ($vrfvxlan) {
+           #l3vni vxlan interface
+           my $iface_vxlan = "vxlan$vrf";
+           @iface_config = ();
+           push @iface_config, "vxlan-id $vrfvxlan";
+           push @iface_config, "vxlan-local-tunnelip $ifaceip" if $ifaceip;
+           push @iface_config, "bridge-learning off";
+           push @iface_config, "bridge-arp-nd-suppress on";
+           push @iface_config, "mtu $mtu" if $mtu;
+           push(@{$config->{$iface_vxlan}}, @iface_config) if !$config->{$iface_vxlan};
+
+           #l3vni bridge
+           my $brvrf = "br$vrf";
+           @iface_config = ();
+           push @iface_config, "bridge-ports $iface_vxlan";
+           push @iface_config, "bridge_stp off";
+           push @iface_config, "bridge_fd 0";
+           push @iface_config, "mtu $mtu" if $mtu;
+           push @iface_config, "vrf $vrf";
+           push(@{$config->{$brvrf}}, @iface_config) if !$config->{$brvrf};
+       }
+    }
+
+    return $config;
+}
+
+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";
+                   }
+               }
+           }
+       }
+    }
+
+    # verify that router exist
+    if (defined($sdn_cfg->{ids}->{$transportid}->{router})) {
+       my $router = $sdn_cfg->{ids}->{$transportid}->{router};
+       if (!defined($sdn_cfg->{ids}->{$router})) {
+           die "router $router don't exist";
+       } else {
+           die "$router is not a router type" if $sdn_cfg->{ids}->{$router}->{type} ne 'frr';
+       }
+
+       #vrf && vrf-vxlan need to be defined with router
+       my $vrf = $sdn_cfg->{ids}->{$transportid}->{vrf};
+       if (!defined($vrf)) {
+           die "missing vrf option";
+       } else {
+           # verify that vrf is not already declared in another transport
+           foreach my $id (keys %{$sdn_cfg->{ids}}) {
+               next if $id eq $transportid;
+               die "vrf $vrf is already declared in $id"
+                       if (defined($sdn_cfg->{ids}->{$id}->{vrf}) && $sdn_cfg->{ids}->{$id}->{vrf} eq $vrf);
+           }
+       }
+
+       my $vrfvxlan = $sdn_cfg->{ids}->{$transportid}->{'vrf-vxlan'};
+       if (!defined($vrfvxlan)) {
+           die "missing vrf-vxlan option";
+       } else {
+           # verify that vrf-vxlan is not already declared in another transport
+           foreach my $id (keys %{$sdn_cfg->{ids}}) {
+               next if $id eq $transportid;
+               die "vrf-vxlan $vrfvxlan is already declared in $id"
+                       if (defined($sdn_cfg->{ids}->{$id}->{'vrf-vxlan'}) && $sdn_cfg->{ids}->{$id}->{'vrf-vxlan'} eq $vrfvxlan);
+           }
+       }
+    }
+}
+
+1;
+
+
index 5bb44dd57df2de10694d5c72efadec2d1429846e..4528dcf58b4a6e13bf7334ba10255fb5208366a9 100644 (file)
@@ -1,4 +1,4 @@
-SOURCES=Plugin.pm VnetPlugin.pm VlanPlugin.pm VxlanPlugin.pm FrrPlugin.pm FaucetPlugin.pm OVSFaucetPlugin.pm
+SOURCES=Plugin.pm VnetPlugin.pm VlanPlugin.pm VxlanPlugin.pm FrrPlugin.pm FaucetPlugin.pm OVSFaucetPlugin.pm EvpnPlugin.pm
 
 
 PERL5DIR=${DESTDIR}/usr/share/perl5
index d39a533f7c4c5c2f3b944c7bc173f0bf4a44aead..5a259b08b376634151c95d50e3498d4286d155bd 100644 (file)
@@ -60,18 +60,6 @@ sub properties {
            description => "Unicast peers address ip list.",
            type => 'string',  format => 'ip-list'
        },
-       'vrf' => {
-           description => "vrf name.",
-           type => 'string',  #fixme: format
-       },
-       'vrf-vxlan' => {
-           type => 'integer',
-           description => "l3vni.",
-       },
-       'controller' => {
-           type => 'string',
-           description => "Frr router name",
-       },
     };
 }
 
@@ -82,9 +70,6 @@ sub options {
         'multicast-address' => { optional => 1 },
         'unicast-address' => { optional => 1 },
         'vxlan-allowed' => { optional => 1 },
-        'vrf' => { optional => 1 },
-        'vrf-vxlan' => { optional => 1 },
-        'controller' => { optional => 1 },
     };
 }
 
@@ -102,8 +87,6 @@ sub generate_sdn_config {
 
     my $uplink = $plugin_config->{'uplink-id'};
     my $vxlanallowed = $plugin_config->{'vxlan-allowed'};
-    my $vrf = $plugin_config->{'vrf'};
-    my $vrfvxlan = $plugin_config->{'vrf-vxlan'};
 
     die "missing vxlan tag" if !$tag;
     my $iface = "uplink$uplink";
@@ -131,10 +114,6 @@ sub generate_sdn_config {
            next if $address eq $ifaceip;
            push @iface_config, "vxlan_remoteip $address";
        }
-    } else {
-       push @iface_config, "vxlan-local-tunnelip $ifaceip" if $ifaceip;
-       push @iface_config, "bridge-learning off";
-       push @iface_config, "bridge-arp-nd-suppress on";
     }
 
     push @iface_config, "mtu $mtu" if $mtu;
@@ -150,41 +129,8 @@ sub generate_sdn_config {
     push @iface_config, "bridge_fd 0";
     push @iface_config, "mtu $mtu" if $mtu;
     push @iface_config, "alias $alias" if $alias;
-    push @iface_config, "ip-forward on" if $ipv4;
-    push @iface_config, "ip6-forward on" if $ipv6;
-    push @iface_config, "arp-accept on" if $ipv4||$ipv6;
-    push @iface_config, "vrf $vrf" if $vrf;
     push(@{$config->{$vnetid}}, @iface_config) if !$config->{$vnetid};
 
-    if ($vrf) {
-       #vrf intreface
-       @iface_config = ();
-       push @iface_config, "vrf-table auto";
-       push(@{$config->{$vrf}}, @iface_config) if !$config->{$vrf};
-
-       if ($vrfvxlan) {
-           #l3vni vxlan interface
-           my $iface_vxlan = "vxlan$vrf";
-           @iface_config = ();
-           push @iface_config, "vxlan-id $vrfvxlan";
-           push @iface_config, "vxlan-local-tunnelip $ifaceip" if $ifaceip;
-           push @iface_config, "bridge-learning off";
-           push @iface_config, "bridge-arp-nd-suppress on";
-           push @iface_config, "mtu $mtu" if $mtu;
-           push(@{$config->{$iface_vxlan}}, @iface_config) if !$config->{$iface_vxlan};
-
-           #l3vni bridge
-           my $brvrf = "br$vrf";
-           @iface_config = ();
-           push @iface_config, "bridge-ports $iface_vxlan";
-           push @iface_config, "bridge_stp off";
-           push @iface_config, "bridge_fd 0";
-           push @iface_config, "mtu $mtu" if $mtu;
-           push @iface_config, "vrf $vrf";
-           push(@{$config->{$brvrf}}, @iface_config) if !$config->{$brvrf};
-       }
-    }
-
     return $config;
 }
 
index 785b21c6b9ee263122a66b6c8f0c2988d3526358..a0d7a236ad64a81bc8f99614d960aae85eb1bd00 100644 (file)
@@ -15,10 +15,10 @@ pvesh create /cluster/sdn/ --sdn vxlanunicastzone --type vxlan --uplink-id 1 --u
 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 --controller frrrouter1
+pvesh create /cluster/sdn/ --sdn layer2evpnzone --type evpn --uplink-id 1 --controller frrrouter1
 
 #create a layer3 routable vxlan bgpevpn transportzone
-pvesh create /cluster/sdn/ --sdn layer3evpnzone --type vxlan --uplink-id 1 --controller frrrouter1 --vrf vrf1 --vrf-vxlan 4000
+pvesh create /cluster/sdn/ --sdn layer3evpnzone --type evpn --uplink-id 1 --controller frrrouter1 --vrf vrf1 --vrf-vxlan 4000
 
 
 #create a vnet in the transportzone