+ my $used_ports = {};
+
+ foreach my $iface (keys %$ifaces) {
+ my $d = $ifaces->{$iface};
+
+ my $ports = '';
+ foreach my $k (qw(bridge_ports ovs_ports slaves ovs_bonds)) {
+ $ports .= " $d->{$k}" if $d->{$k};
+ }
+
+ foreach my $p (PVE::Tools::split_list($ports)) {
+ die "port '$p' is already used on interface '$used_ports->{$p}'\n"
+ if $used_ports->{$p} && $used_ports->{$p} ne $iface;
+ $used_ports->{$p} = $iface;
+ }
+ }
+
+ # delete unused OVS ports
+ foreach my $iface (keys %$ifaces) {
+ my $d = $ifaces->{$iface};
+ if ($d->{type} eq 'OVSPort' || $d->{type} eq 'OVSIntPort' ||
+ $d->{type} eq 'OVSBond') {
+ my $brname = $used_ports->{$iface};
+ if (!$brname || !$ifaces->{$brname}) {
+ delete $ifaces->{$iface};
+ next;
+ }
+ my $bd = $ifaces->{$brname};
+ if ($bd->{type} ne 'OVSBridge') {
+ delete $ifaces->{$iface};
+ next;
+ }
+ }
+ }
+
+ # create OVS bridge ports
+ foreach my $iface (keys %$ifaces) {
+ my $d = $ifaces->{$iface};
+ if ($d->{type} eq 'OVSBridge' && $d->{ovs_ports}) {
+ foreach my $p (split (/\s+/, $d->{ovs_ports})) {
+ my $n = $ifaces->{$p};
+ die "OVS bridge '$iface' - unable to find port '$p'\n"
+ if !$n;
+ if ($n->{type} eq 'eth') {
+ $n->{type} = 'OVSPort';
+ $n->{ovs_bridge} = $iface;
+ } elsif ($n->{type} eq 'OVSBond' || $n->{type} eq 'OVSPort' ||
+ $n->{type} eq 'OVSIntPort') {
+ $n->{ovs_bridge} = $iface;
+ } else {
+ die "interface '$p' is not defined as OVS port/bond\n";
+ }
+ }
+ }
+ }
+
+ # check OVS bond ports
+ foreach my $iface (keys %$ifaces) {
+ my $d = $ifaces->{$iface};
+ if ($d->{type} eq 'OVSBond' && $d->{ovs_bonds}) {
+ foreach my $p (split (/\s+/, $d->{ovs_bonds})) {
+ my $n = $ifaces->{$p};
+ die "OVS bond '$iface' - unable to find slave '$p'\n"
+ if !$n;
+ die "OVS bond '$iface' - wrong interface type on slave '$p' " .
+ "('$n->{type}' != 'eth')\n" if $n->{type} ne 'eth';
+ }
+ }
+ }
+