]> git.proxmox.com Git - pve-network.git/blob - PVE/Network/SDN/VlanPlugin.pm
5a38f596e9df5ac9f7483e5808a5f21014fb9906
[pve-network.git] / PVE / Network / SDN / VlanPlugin.pm
1 package PVE::Network::SDN::VlanPlugin;
2
3 use strict;
4 use warnings;
5 use PVE::Network::SDN::Plugin;
6
7 use base('PVE::Network::SDN::Plugin');
8
9 sub type {
10 return 'vlan';
11 }
12
13 sub plugindata {
14 return {
15 role => 'transport',
16 };
17 }
18
19 PVE::JSONSchema::register_format('pve-sdn-vlanrange', \&pve_verify_sdn_vlanrange);
20 sub pve_verify_sdn_vlanrange {
21 my ($vlanstr) = @_;
22
23 PVE::Network::SDN::Plugin::parse_tag_number_or_range($vlanstr, '4096');
24
25 return $vlanstr;
26 }
27
28 sub properties {
29 return {
30 'uplink-id' => {
31 type => 'integer',
32 minimum => 1, maximum => 4096,
33 description => 'Uplink interface',
34 },
35 'vlan-allowed' => {
36 type => 'string', format => 'pve-sdn-vlanrange',
37 description => "Allowed vlan range",
38 },
39 };
40 }
41
42 sub options {
43
44 return {
45 'uplink-id' => { optional => 0 },
46 'vlan-allowed' => { optional => 1 },
47 };
48 }
49
50 # Plugin implementation
51 sub generate_sdn_config {
52 my ($class, $plugin_config, $zoneid, $vnetid, $vnet, $uplinks, $config) = @_;
53
54 my $tag = $vnet->{tag};
55 my $mtu = $vnet->{mtu};
56 my $alias = $vnet->{alias};
57 my $uplink = $plugin_config->{'uplink-id'};
58
59 die "missing vlan tag" if !$tag;
60
61 my $iface = $uplinks->{$uplink}->{name};
62 $iface = "uplink${uplink}" if !$iface;
63 $iface .= ".$tag";
64
65 #tagged interface
66 my @iface_config = ();
67 push @iface_config, "mtu $mtu" if $mtu;
68 push(@{$config->{$iface}}, @iface_config) if !$config->{$iface};
69
70 #vnet bridge
71 @iface_config = ();
72 push @iface_config, "bridge_ports $iface";
73 push @iface_config, "bridge_stp off";
74 push @iface_config, "bridge_fd 0";
75 push @iface_config, "mtu $mtu" if $mtu;
76 push @iface_config, "alias $alias" if $alias;
77 push(@{$config->{$vnetid}}, @iface_config) if !$config->{$vnetid};
78
79 return $config;
80 }
81
82 sub on_delete_hook {
83 my ($class, $transportid, $sdn_cfg) = @_;
84
85 # verify that no vnet are associated to this transport
86 foreach my $id (keys %{$sdn_cfg->{ids}}) {
87 my $sdn = $sdn_cfg->{ids}->{$id};
88 die "transport $transportid is used by vnet $id"
89 if ($sdn->{type} eq 'vnet' && defined($sdn->{transportzone}) && $sdn->{transportzone} eq $transportid);
90 }
91 }
92
93 sub on_update_hook {
94 my ($class, $transportid, $sdn_cfg) = @_;
95
96 my $transport = $sdn_cfg->{ids}->{$transportid};
97
98 # verify that vlan-allowed don't conflict with another vlan-allowed transport
99
100 # verify that vlan-allowed is matching currently vnet tag in this transport
101 my $vlanallowed = $transport->{'vlan-allowed'};
102 if ($vlanallowed) {
103 foreach my $id (keys %{$sdn_cfg->{ids}}) {
104 my $sdn = $sdn_cfg->{ids}->{$id};
105 if ($sdn->{type} eq 'vnet' && defined($sdn->{tag})) {
106 if(defined($sdn->{transportzone}) && $sdn->{transportzone} eq $transportid) {
107 my $tag = $sdn->{tag};
108 eval {
109 PVE::Network::SDN::Plugin::parse_tag_number_or_range($vlanallowed, '4096', $tag);
110 };
111 if($@) {
112 die "vlan $tag is not allowed in transport $transportid";
113 }
114 }
115 }
116 }
117 }
118 }
119
120 1;
121
122