X-Git-Url: https://git.proxmox.com/?p=pve-common.git;a=blobdiff_plain;f=src%2FPVE%2FNetwork.pm;h=69051b9de048e5a6023902b9898af9cd5ab655b5;hp=405f14ba17afa44e0823f5e9469c60c075e4a1e9;hb=0c0304c0d9a9a753b5d93a6c7b2239059a26d945;hpb=78e912a3b7b3d6f394a43b25ac3cf47144d0aa90 diff --git a/src/PVE/Network.pm b/src/PVE/Network.pm index 405f14b..69051b9 100644 --- a/src/PVE/Network.pm +++ b/src/PVE/Network.pm @@ -2,7 +2,7 @@ package PVE::Network; use strict; use warnings; -use PVE::Tools qw(run_command); +use PVE::Tools qw(run_command lock_file); use PVE::ProcFSTools; use PVE::INotify; use File::Basename; @@ -171,9 +171,20 @@ my $cond_create_bridge = sub { } }; +sub disable_ipv6 { + my ($iface) = @_; + return if !-d '/proc/sys/net/ipv6'; # ipv6 might be completely disabled + my $file = "/proc/sys/net/ipv6/conf/$iface/disable_ipv6"; + open(my $fh, '>', $file) or die "failed to open $file for writing: $!\n"; + print {$fh} "1\n" or die "failed to disable link-local ipv6 for $iface\n"; + close($fh); +} + my $bridge_add_interface = sub { my ($bridge, $iface, $tag, $trunks) = @_; + # drop link local address (it can't be used when on a bridge anyway) + disable_ipv6($iface); system("/sbin/brctl addif $bridge $iface") == 0 || die "can't add interface 'iface' to bridge '$bridge'\n"; @@ -215,6 +226,7 @@ my $ovs_bridge_add_port = sub { $cmd .= " -- set Interface $iface type=internal" if $internal; system($cmd) == 0 || die "can't add ovs port '$iface'\n"; + disable_ipv6($iface); }; my $activate_interface = sub { @@ -232,7 +244,8 @@ sub tap_create { my $bridgemtu = &$read_bridge_mtu($bridge); eval { - PVE::Tools::run_command("/sbin/ifconfig $iface 0.0.0.0 promisc up mtu $bridgemtu"); + disable_ipv6($iface); + PVE::Tools::run_command(['/sbin/ip', 'link', 'set', $iface, 'up', 'promisc', 'on', 'mtu', $bridgemtu]); }; die "interface activation failed\n" if $@; } @@ -252,6 +265,8 @@ sub veth_create { } # up vethpair + disable_ipv6($veth); + disable_ipv6($vethpeer); &$activate_interface($veth); &$activate_interface($vethpeer); } @@ -262,7 +277,7 @@ sub veth_delete { if (-d "/sys/class/net/$veth") { run_command("/sbin/ip link delete dev $veth", outfunc => sub {}, errfunc => sub {}); } - + eval { tap_unplug($veth) }; } my $create_firewall_bridge_linux = sub { @@ -272,6 +287,7 @@ my $create_firewall_bridge_linux = sub { my ($fwbr, $vethfw, $vethfwpeer) = &$compute_fwbr_names($vmid, $devid); &$cond_create_bridge($fwbr); + disable_ipv6($fwbr); &$activate_interface($fwbr); copy_bridge_config($bridge, $fwbr); @@ -292,6 +308,7 @@ my $create_firewall_bridge_ovs = sub { my $bridgemtu = &$read_bridge_mtu($bridge); &$cond_create_bridge($fwbr); + disable_ipv6($fwbr); &$activate_interface($fwbr); &$bridge_add_interface($fwbr, $iface); @@ -300,7 +317,7 @@ my $create_firewall_bridge_ovs = sub { &$activate_interface($ovsintport); # set the same mtu for ovs int port - PVE::Tools::run_command("/sbin/ifconfig $ovsintport mtu $bridgemtu"); + PVE::Tools::run_command(['/sbin/ip', 'link', 'set', $ovsintport, 'mtu', $bridgemtu]); &$bridge_add_interface($fwbr, $ovsintport); }; @@ -410,10 +427,13 @@ sub activate_bridge_vlan_slave { # create vlan on $iface is not already exist if (! -d "/sys/class/net/$ifacevlan") { - system("/sbin/ip link add link $iface name ${iface}.${tag} type vlan id $tag") == 0 || + system("/sbin/ip link add link $iface name $ifacevlan type vlan id $tag") == 0 || die "can't add vlan tag $tag to interface $iface\n"; } + # remove ipv6 link-local address before activation + disable_ipv6($ifacevlan); + # be sure to have the $ifacevlan up &$activate_interface($ifacevlan); @@ -454,23 +474,25 @@ sub activate_bridge_vlan { die "no physical interface on bridge '$bridge'\n" if scalar(@ifaces) == 0; - # add bridgevlan if it doesn't already exist - if (! -d "/sys/class/net/$bridgevlan") { - system("/sbin/brctl addbr $bridgevlan") == 0 || - die "can't add bridge $bridgevlan\n"; - } + lock_network(sub { + # add bridgevlan if it doesn't already exist + if (! -d "/sys/class/net/$bridgevlan") { + system("/sbin/brctl addbr $bridgevlan") == 0 || + die "can't add bridge $bridgevlan\n"; + } - # for each physical interface (eth or bridge) bind them to bridge vlan - foreach my $iface (@ifaces) { - activate_bridge_vlan_slave($bridgevlan, $iface, $tag); - } + # for each physical interface (eth or bridge) bind them to bridge vlan + foreach my $iface (@ifaces) { + activate_bridge_vlan_slave($bridgevlan, $iface, $tag); + } - #fixme: set other bridge flags + #fixme: set other bridge flags - # be sure to have the bridge up - system("/sbin/ip link set $bridgevlan up") == 0 || - die "can't up bridge $bridgevlan\n"; - + # remove ipv6 link-local address before activation + disable_ipv6($bridgevlan); + # be sure to have the bridge up + &$activate_interface($bridgevlan); + }); return $bridgevlan; } @@ -533,4 +555,32 @@ sub is_ip_in_cidr { return $cidr_obj->overlaps($ip_obj) == $Net::IP::IP_B_IN_A_OVERLAP; } + +sub get_local_ip_from_cidr { + my ($cidr) = @_; + + my $cmd = ['/sbin/ip', 'address', 'show', 'to', $cidr, 'up']; + + my $IPs = []; + + my $code = sub { + my $line = shift; + + if ($line =~ m!^\s*inet(?:6)?\s+($PVE::Tools::IPRE)/\d+!) { + push @$IPs, $1; + } + }; + + PVE::Tools::run_command($cmd, outfunc => $code); + + return $IPs; +} + +sub lock_network { + my ($code, @param) = @_; + my $res = lock_file('/var/lock/pve-network.lck', 10, $code, @param); + die $@ if $@; + return $res; +} + 1;