]> git.proxmox.com Git - pve-network.git/blob - PVE/Network/SDN/Zones/SimplePlugin.pm
controllers: evpn : use frr restart if reload fail
[pve-network.git] / PVE / Network / SDN / Zones / SimplePlugin.pm
1 package PVE::Network::SDN::Zones::SimplePlugin;
2
3 use strict;
4 use warnings;
5 use PVE::Network::SDN::Zones::Plugin;
6 use PVE::Exception qw(raise raise_param_exc);
7 use PVE::Cluster;
8 use PVE::Tools;
9
10 use base('PVE::Network::SDN::Zones::Plugin');
11
12 sub type {
13 return 'simple';
14 }
15
16 sub properties {
17 return {
18 dns => {
19 type => 'string',
20 description => "dns api server",
21 },
22 reversedns => {
23 type => 'string',
24 description => "reverse dns api server",
25 },
26 dnszone => {
27 type => 'string', format => 'dns-name',
28 description => "dns domain zone ex: mydomain.com",
29 }
30 };
31 }
32
33 sub options {
34 return {
35 nodes => { optional => 1},
36 mtu => { optional => 1 },
37 dns => { optional => 1 },
38 reversedns => { optional => 1 },
39 dnszone => { optional => 1 },
40 ipam => { optional => 1 },
41 };
42 }
43
44 # Plugin implementation
45 sub generate_sdn_config {
46 my ($class, $plugin_config, $zoneid, $vnetid, $vnet, $controller, $controller_cfg, $subnet_cfg, $interfaces_config, $config) = @_;
47
48 return $config if$config->{$vnetid}; # nothing to do
49
50 my $mac = $vnet->{mac};
51 my $alias = $vnet->{alias};
52 my $mtu = $plugin_config->{mtu} if $plugin_config->{mtu};
53
54 # vnet bridge
55 my @iface_config = ();
56
57 my $address = {};
58 my $subnets = PVE::Network::SDN::Vnets::get_subnets($vnetid, 1);
59
60 my $ipv4 = undef;
61 my $ipv6 = undef;
62 my $enable_forward_v4 = undef;
63 my $enable_forward_v6 = undef;
64
65 foreach my $subnetid (sort keys %{$subnets}) {
66 my $subnet = $subnets->{$subnetid};
67 my $cidr = $subnet->{cidr};
68 my $mask = $subnet->{mask};
69
70 my $gateway = $subnet->{gateway};
71 if ($gateway) {
72 push @iface_config, "address $gateway/$mask" if !defined($address->{$gateway});
73 $address->{$gateway} = 1;
74 }
75
76 my $iptables = undef;
77 my $checkrouteip = undef;
78 my $ipversion = Net::IP::ip_is_ipv6($gateway) ? 6 : 4;
79
80 if ( $ipversion == 6) {
81 $ipv6 = 1;
82 $iptables = "ip6tables";
83 $checkrouteip = '2001:4860:4860::8888';
84 $enable_forward_v6 = 1 if $gateway;
85 } else {
86 $ipv4 = 1;
87 $iptables = "iptables";
88 $checkrouteip = '8.8.8.8';
89 $enable_forward_v4 = 1 if $gateway;
90 }
91
92 #add route for /32 pointtopoint
93 push @iface_config, "up ip route add $cidr dev $vnetid" if $mask == 32 && $ipversion == 4;
94 if ($subnet->{snat}) {
95 #find outgoing interface
96 my ($outip, $outiface) = PVE::Network::SDN::Zones::Plugin::get_local_route_ip($checkrouteip);
97 if ($outip && $outiface) {
98 #use snat, faster than masquerade
99 push @iface_config, "post-up $iptables -t nat -A POSTROUTING -s '$cidr' -o $outiface -j SNAT --to-source $outip";
100 push @iface_config, "post-down $iptables -t nat -D POSTROUTING -s '$cidr' -o $outiface -j SNAT --to-source $outip";
101 #add conntrack zone once on outgoing interface
102 push @iface_config, "post-up $iptables -t raw -I PREROUTING -i fwbr+ -j CT --zone 1";
103 push @iface_config, "post-down $iptables -t raw -D PREROUTING -i fwbr+ -j CT --zone 1";
104 }
105 }
106 }
107
108 push @iface_config, "hwaddress $mac" if $mac;
109 push @iface_config, "bridge_ports none";
110 push @iface_config, "bridge_stp off";
111 push @iface_config, "bridge_fd 0";
112 if ($vnet->{vlanaware}) {
113 push @iface_config, "bridge-vlan-aware yes";
114 push @iface_config, "bridge-vids 2-4094";
115 }
116 push @iface_config, "mtu $mtu" if $mtu;
117 push @iface_config, "alias $alias" if $alias;
118 push @iface_config, "ip-forward on" if $enable_forward_v4;
119 push @iface_config, "ip6-forward on" if $enable_forward_v6;
120
121 push @{$config->{$vnetid}}, @iface_config;
122
123 return $config;
124 }
125
126 sub status {
127 my ($class, $plugin_config, $zone, $vnetid, $vnet, $status) = @_;
128
129 # ifaces to check
130 my $ifaces = [ $vnetid ];
131 my $err_msg = [];
132 foreach my $iface (@{$ifaces}) {
133 if (!$status->{$iface}->{status}) {
134 push @$err_msg, "missing $iface";
135 } elsif ($status->{$iface}->{status} ne 'pass') {
136 push @$err_msg, "error iface $iface";
137 }
138 }
139 return $err_msg;
140 }
141
142
143 sub vnet_update_hook {
144 my ($class, $vnet_cfg, $vnetid, $zone_cfg) = @_;
145
146 my $vnet = $vnet_cfg->{ids}->{$vnetid};
147 my $tag = $vnet->{tag};
148
149 raise_param_exc({ tag => "vlan tag is not allowed on simple zone"}) if defined($tag);
150
151 if (!defined($vnet->{mac})) {
152 my $dc = PVE::Cluster::cfs_read_file('datacenter.cfg');
153 $vnet->{mac} = PVE::Tools::random_ether_addr($dc->{mac_prefix});
154 }
155 }
156
157 1;
158
159