Merge pull request #2795 from macmon/fix/net-virtual-iface-deletion

MM-12032 Fix bond/VLAN/bridge not removed from active list on delete
This commit is contained in:
Ilia Ross
2026-08-10 23:00:45 +02:00
committed by GitHub
5 changed files with 129 additions and 9 deletions

View File

@@ -230,12 +230,12 @@ if ($cfg->{'bridge'}) {
# Set bonding parameters
if(($cfg->{'bond'} == 1) && ($gconfig{'os_version'} >= 5)) {
push(@options, [&bonding_option('mode').' '.$cfg->{'mode'}]);
push(@options, [&bonding_option('miimon').' '.$cfg->{'miimon'}]) if ($cfg->{'miimon'});
push(@options, [&bonding_option('updelay').' '.$cfg->{'updelay'}]) if ($cfg->{'updelay'});
push(@options, [&bonding_option('downdelay').' '.$cfg->{'downdelay'}]) if ($cfg->{'downdelay'});
push(@options, [&bonding_option('primary').' '.$cfg->{'primary'}]) if ($cfg->{'primary'});
push(@options, ['slaves '.$cfg->{'partner'}]);
push(@options, [&bonding_option('mode'), $cfg->{'mode'}]);
push(@options, [&bonding_option('miimon'), $cfg->{'miimon'}]) if ($cfg->{'miimon'});
push(@options, [&bonding_option('updelay'), $cfg->{'updelay'}]) if ($cfg->{'updelay'});
push(@options, [&bonding_option('downdelay'), $cfg->{'downdelay'}]) if ($cfg->{'downdelay'});
push(@options, [&bonding_option('primary'), $cfg->{'primary'}]) if ($cfg->{'primary'});
push(@options, ['slaves', $cfg->{'partner'}]);
}
elsif ($cfg->{'bond'} == 1) {
push(@options, ['up', '/sbin/ifenslave '.$cfg->{'name'}." ".

View File

@@ -51,6 +51,10 @@ foreach $d (reverse(@d)) {
else {&unload_module($b->{'name'});}
}
}
# Remove the virtual device after deactivation
if (defined(&destroy_interface_device)) {
&destroy_interface_device($b);
}
}
# Delete config

View File

@@ -329,9 +329,22 @@ if (&has_command("ip") && $a->{'bond'} && $a->{'up'} && !$old) {
}
}
if (($a->{'bond'} || $a->{'vlan'} || !&has_command("ifconfig")) &&
&has_command("ip")) {
# For a real interface, activate or de-activate the link
if (&has_command("ip") && $a->{'bridge'} && $a->{'up'} && !$old) {
# Create the bridge before assigning addresses to it.
my $cmd = "ip link add ".quotemeta($a->{'name'})." type bridge";
my $out = &backquote_logged("$cmd 2>&1");
&error("Failed to create bridge device : $out") if ($?);
if ($a->{'bridgeto'}) {
$cmd = "ip link set dev ".quotemeta($a->{'bridgeto'}).
" master ".quotemeta($a->{'name'});
$out = &backquote_logged("$cmd 2>&1");
&error("Failed to add interface to bridge : $out") if ($?);
}
}
if (&has_command("ip")) {
# Manage link state for all interfaces when ip is used, since ip is also
# used for address assignment below regardless of ifconfig availability.
if ($a->{'virtual'} eq '' && $a->{'up'} && (!$old || !$old->{'up'})) {
# Bring up
my $cmd = "ip link set dev ".quotemeta($devname)." up";
@@ -597,6 +610,20 @@ else {
}
}
# destroy_interface_device(&details)
# Remove a virtual network device (bond, VLAN, bridge) from the kernel.
# Should be called after deactivate_interface when deleting, not just
# deactivating, a virtual interface.
sub destroy_interface_device
{
my ($a) = @_;
if (&has_command("ip") && $a->{'virtual'} eq '' &&
(&use_ifup_command($a) || $a->{'bridge'})) {
&backquote_logged("ip link delete ".
quotemeta($a->{'fullname'} || $a->{'name'})." 2>&1");
}
}
# use_ifup_command(&iface)
# Returns 1 if the ifup command must be used to bring up some interface.
# True on Debian 5.0+ for non-ethernet, typically bonding and VLAN tagged interfaces.

View File

@@ -32,6 +32,10 @@ if ($in{'delete'} || $in{'unapply'}) {
else {
&deactivate_interface($act);
}
# Remove the virtual device after deactivation
if (defined(&destroy_interface_device)) {
&destroy_interface_device($b);
}
}
}

View File

@@ -964,4 +964,89 @@ is_deeply(\@commands,
"cd / ; ifconfig eth0.10 10\\.0\\.0\\.2 netmask 255\\.255\\.255\\.0 up 2>&1" ],
"Linux VLAN interface falls back to vconfig without ip");
# Test: Bond deactivation only brings it down, does not delete device
@commands = ( );
{
no warnings 'redefine';
local *main::has_command = sub {
return $_[0] eq "ip" ? "/sbin/ip" : undef;
};
main::deactivate_interface({
'name' => 'bond0',
'fullname' => 'bond0',
'virtual' => '',
'address' => '10.0.0.2',
'netmask' => '255.255.255.0',
'address6' => [ ],
'netmask6' => [ ],
'up' => 1
});
}
is_deeply(\@commands, [
"ip addr del 10\\.0\\.0\\.2\\/24 dev bond0 2>&1",
"ip link set dev bond0 down 2>&1"
], "Linux bond deactivation removes address and brings link down");
# Test: Bond deletion removes virtual device after deactivation
@commands = ( );
{
no warnings 'redefine';
no warnings 'once';
local $main::gconfig{'os_type'} = 'debian-linux';
local $main::gconfig{'os_version'} = 12;
local *main::has_command = sub {
return $_[0] eq "ip" ? "/sbin/ip" :
$_[0] eq "ifup" ? "/sbin/ifup" : undef;
};
main::deactivate_interface({
'name' => 'bond0',
'fullname' => 'bond0',
'virtual' => '',
'address' => '10.0.0.2',
'netmask' => '255.255.255.0',
'address6' => [ ],
'netmask6' => [ ],
'up' => 1
});
# Simulate delete path: destroy_interface_device after deactivation
my $b = { 'name' => 'bond0', 'fullname' => 'bond0', 'virtual' => '' };
main::destroy_interface_device($b);
}
is_deeply(\@commands, [
"ip addr del 10\\.0\\.0\\.2\\/24 dev bond0 2>&1",
"ip link set dev bond0 down 2>&1",
"ip link delete bond0 2>&1"
], "Linux bond deletion removes device after deactivation");
# Test: VLAN deletion removes virtual device after deactivation
@commands = ( );
{
no warnings 'redefine';
no warnings 'once';
local $main::gconfig{'os_type'} = 'debian-linux';
local $main::gconfig{'os_version'} = 12;
local *main::has_command = sub {
return $_[0] eq "ip" ? "/sbin/ip" :
$_[0] eq "ifup" ? "/sbin/ifup" : undef;
};
main::deactivate_interface({
'name' => 'eth0.10',
'fullname' => 'eth0.10',
'virtual' => '',
'address' => '10.0.10.2',
'netmask' => '255.255.255.0',
'address6' => [ ],
'netmask6' => [ ],
'up' => 1
});
# Simulate delete path: destroy_interface_device after deactivation
my $b = { 'name' => 'eth0.10', 'fullname' => 'eth0.10', 'virtual' => '' };
main::destroy_interface_device($b);
}
is_deeply(\@commands, [
"ip addr del 10\\.0\\.10\\.2\\/24 dev eth0\\.10 2>&1",
"ip link set dev eth0\\.10 down 2>&1",
"ip link delete eth0\\.10 2>&1"
], "Linux VLAN deletion removes device after deactivation");
done_testing();