]>
Commit | Line | Data |
---|---|---|
3ee45e4c | 1 | package PVE::Network::SDN::VxlanPlugin; |
7e720d4d AD |
2 | |
3 | use strict; | |
4 | use warnings; | |
86d22462 | 5 | use PVE::Network::SDN::Plugin; |
3ee45e4c | 6 | use PVE::Tools; |
7e720d4d | 7 | |
86d22462 | 8 | use base('PVE::Network::SDN::Plugin'); |
7e720d4d | 9 | |
6bffe819 AD |
10 | PVE::JSONSchema::register_format('pve-sdn-vxlanrange', \&pve_verify_sdn_vxlanrange); |
11 | sub pve_verify_sdn_vxlanrange { | |
7e720d4d AD |
12 | my ($vxlanstr) = @_; |
13 | ||
86d22462 | 14 | PVE::Network::SDN::Plugin::parse_tag_number_or_range($vxlanstr, '16777216'); |
7e720d4d AD |
15 | |
16 | return $vxlanstr; | |
17 | } | |
18 | ||
19 | sub type { | |
3ee45e4c | 20 | return 'vxlan'; |
7e720d4d AD |
21 | } |
22 | ||
23 | sub properties { | |
24 | return { | |
25 | 'vxlan-allowed' => { | |
6bffe819 | 26 | type => 'string', format => 'pve-sdn-vxlanrange', |
7e720d4d AD |
27 | description => "Allowed vlan range", |
28 | }, | |
29 | 'multicast-address' => { | |
30 | description => "Multicast address.", | |
31 | type => 'string', #fixme: format | |
32 | }, | |
3ee45e4c AD |
33 | 'unicast-address' => { |
34 | description => "Unicast peers address ip list.", | |
35 | type => 'string', #fixme: format | |
36 | }, | |
7e720d4d AD |
37 | }; |
38 | } | |
39 | ||
40 | sub options { | |
41 | ||
42 | return { | |
85533e98 | 43 | 'uplink-id' => { optional => 0 }, |
3ee45e4c AD |
44 | 'multicast-address' => { optional => 1 }, |
45 | 'unicast-address' => { optional => 1 }, | |
7e720d4d AD |
46 | 'vxlan-allowed' => { optional => 1 }, |
47 | }; | |
48 | } | |
49 | ||
50 | # Plugin implementation | |
6bffe819 | 51 | sub generate_sdn_config { |
bad3d113 | 52 | my ($class, $plugin_config, $zoneid, $vnetid, $vnet, $uplinks) = @_; |
7e720d4d AD |
53 | |
54 | my $tag = $vnet->{tag}; | |
dc7e431e | 55 | my $alias = $vnet->{alias}; |
7e720d4d | 56 | my $multicastaddress = $plugin_config->{'multicast-address'}; |
3ee45e4c AD |
57 | my @unicastaddress = split(',', $plugin_config->{'unicast-address'}) if $plugin_config->{'unicast-address'}; |
58 | ||
7e720d4d AD |
59 | my $uplink = $plugin_config->{'uplink-id'}; |
60 | my $vxlanallowed = $plugin_config->{'vxlan-allowed'}; | |
61 | ||
62 | die "missing vxlan tag" if !$tag; | |
3ee45e4c AD |
63 | my $iface = "uplink$uplink"; |
64 | my $ifaceip = ""; | |
65 | ||
66 | if($uplinks->{$uplink}->{name}) { | |
67 | $iface = $uplinks->{$uplink}->{name}; | |
68 | $ifaceip = PVE::Network::SDN::Plugin::get_first_local_ipv4_from_interface($iface); | |
69 | } | |
c1ae8486 AD |
70 | |
71 | my $mtu = 1450; | |
72 | $mtu = $uplinks->{$uplink}->{mtu} - 50 if $uplinks->{$uplink}->{mtu}; | |
73 | $mtu = $vnet->{mtu} if $vnet->{mtu}; | |
7e720d4d | 74 | |
7e720d4d | 75 | my $config = "\n"; |
1c793d30 AD |
76 | $config .= "auto vxlan$vnetid\n"; |
77 | $config .= "iface vxlan$vnetid inet manual\n"; | |
4394cbf2 | 78 | $config .= " vxlan-id $tag\n"; |
3ee45e4c AD |
79 | |
80 | if($multicastaddress) { | |
81 | $config .= " vxlan-svcnodeip $multicastaddress\n"; | |
82 | $config .= " vxlan-physdev $iface\n"; | |
83 | } elsif (@unicastaddress) { | |
84 | ||
85 | foreach my $address (@unicastaddress) { | |
86 | next if $address eq $ifaceip; | |
87 | $config .= " vxlan_remoteip $address\n"; | |
88 | } | |
89 | } else { | |
90 | $config .= " vxlan-local-tunnelip $ifaceip\n" if $ifaceip; | |
91 | $config .= " bridge-learning off\n"; | |
92 | $config .= " bridge-arp-nd-suppress on\n"; | |
93 | $config .= " bridge-unicast-flood off\n"; | |
94 | $config .= " bridge-multicast-flood off\n"; | |
95 | } | |
96 | ||
9c2f5e3f | 97 | $config .= " mtu $mtu\n" if $mtu; |
7e720d4d AD |
98 | $config .= "\n"; |
99 | $config .= "auto $vnetid\n"; | |
100 | $config .= "iface $vnetid inet manual\n"; | |
3ee45e4c AD |
101 | $config .= " bridge_ports vxlan$vnetid\n"; |
102 | $config .= " bridge_stp off\n"; | |
103 | $config .= " bridge_fd 0\n"; | |
104 | $config .= " mtu $mtu\n" if $mtu; | |
105 | $config .= " alias $alias\n" if $alias; | |
7e720d4d AD |
106 | |
107 | return $config; | |
108 | } | |
109 | ||
fe0c6b9e | 110 | sub on_delete_hook { |
6bffe819 | 111 | my ($class, $transportid, $sdn_cfg) = @_; |
fe0c6b9e AD |
112 | |
113 | # verify that no vnet are associated to this transport | |
6bffe819 AD |
114 | foreach my $id (keys %{$sdn_cfg->{ids}}) { |
115 | my $sdn = $sdn_cfg->{ids}->{$id}; | |
a8ad2789 | 116 | die "transport $transportid is used by vnet $id" |
6bffe819 | 117 | if ($sdn->{type} eq 'vnet' && defined($sdn->{transportzone}) && $sdn->{transportzone} eq $transportid); |
a8ad2789 | 118 | } |
fe0c6b9e AD |
119 | } |
120 | ||
e8d5906e | 121 | sub on_update_hook { |
6bffe819 | 122 | my ($class, $transportid, $sdn_cfg) = @_; |
c723980e | 123 | |
6bffe819 | 124 | my $transport = $sdn_cfg->{ids}->{$transportid}; |
e8d5906e AD |
125 | |
126 | # verify that vxlan-allowed don't conflict with another vxlan-allowed transport | |
127 | ||
128 | # verify that vxlan-allowed is matching currently vnet tag in this transport | |
c723980e AD |
129 | my $vxlanallowed = $transport->{'vxlan-allowed'}; |
130 | if ($vxlanallowed) { | |
6bffe819 AD |
131 | foreach my $id (keys %{$sdn_cfg->{ids}}) { |
132 | my $sdn = $sdn_cfg->{ids}->{$id}; | |
133 | if ($sdn->{type} eq 'vnet' && defined($sdn->{tag})) { | |
134 | if(defined($sdn->{transportzone}) && $sdn->{transportzone} eq $transportid) { | |
135 | my $tag = $sdn->{tag}; | |
c723980e | 136 | eval { |
86d22462 | 137 | PVE::Network::SDN::Plugin::parse_tag_number_or_range($vxlanallowed, '16777216', $tag); |
c723980e AD |
138 | }; |
139 | if($@) { | |
140 | die "vnet $id - vlan $tag is not allowed in transport $transportid"; | |
141 | } | |
142 | } | |
143 | } | |
144 | } | |
145 | } | |
e8d5906e AD |
146 | } |
147 | ||
7e720d4d AD |
148 | 1; |
149 | ||
150 |