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