migration: preserve host_mtu for virtio-net devices
The virtual hardware is generated differently (at least for i440fx machines) when host_mtu is set or not set on the netdev command line [0]. When the MTU is the same value as the default 1500, Proxmox VE did not add a host_mtu parameter. This is problematic for migration where host_mtu is present on one end of the migration, but not on the other [1]. Moreover, the effective setting in the guest (state) will still be the host_mtu from the source side, even if a different value is used for host_mtu on the target instance's commandline. This will not lead to an error loading the migration stream in QEMU, but having a larger host_mtu than the bridge MTU is still problematic for certain network traffic like > iperf3 -c 10.10.10.11 -u -l 2k when host_mtu=9000 and bridge MTU=1500. Pass the values from the source to the target during migration to be able to preserve them. [0]: https://bugzilla.redhat.com/show_bug.cgi?id=1449346 [1]: https://forum.proxmox.com/threads/live-vm-migration-fails.169537/post-796379 Signed-off-by: Fiona Ebner <f.ebner@proxmox.com> Reviewed-by: Fabian Grünbichler <f.gruenbichler@proxmox.com> Link: https://lore.proxmox.com/20250904124113.81772-4-f.ebner@proxmox.com
This commit is contained in:
parent
c4d2ee0610
commit
20c91f7f3a
3 changed files with 52 additions and 0 deletions
|
|
@ -998,6 +998,10 @@ sub phase2_start_local_cluster {
|
|||
push @$cmd, '--force-cpu', $start->{forcecpu};
|
||||
}
|
||||
|
||||
if ($start->{'nets-host-mtu'}) {
|
||||
push @$cmd, '--nets-host-mtu', $start->{'nets-host-mtu'};
|
||||
}
|
||||
|
||||
if ($self->{storage_migration}) {
|
||||
push @$cmd, '--targetstorage', ($self->{opts}->{targetstorage} // '1');
|
||||
}
|
||||
|
|
@ -1187,6 +1191,10 @@ sub phase2 {
|
|||
},
|
||||
};
|
||||
|
||||
if (my $nets_host_mtu = PVE::QemuServer::Network::get_nets_host_mtu($vmid, $conf)) {
|
||||
$params->{start_params}->{'nets-host-mtu'} = $nets_host_mtu;
|
||||
}
|
||||
|
||||
my ($tunnel_info, $spice_port);
|
||||
|
||||
my @online_local_volumes = $self->filter_local_volumes('online');
|
||||
|
|
|
|||
|
|
@ -11,6 +11,8 @@ use PVE::Network::SDN::Zones;
|
|||
use PVE::RESTEnvironment qw(log_warn);
|
||||
use PVE::Tools qw($IPV6RE file_read_firstline);
|
||||
|
||||
use PVE::QemuServer::Monitor qw(mon_cmd);
|
||||
|
||||
my $nic_model_list = [
|
||||
'e1000',
|
||||
'e1000-82540em',
|
||||
|
|
@ -330,4 +332,31 @@ sub tap_plug {
|
|||
PVE::Network::SDN::Zones::tap_plug($iface, $bridge, $tag, $firewall, $trunks, $rate);
|
||||
}
|
||||
|
||||
sub get_nets_host_mtu {
|
||||
my ($vmid, $conf) = @_;
|
||||
|
||||
my $nets_host_mtu = [];
|
||||
for my $opt (sort keys $conf->%*) {
|
||||
next if $opt !~ m/^net(\d+)$/;
|
||||
my $net = parse_net($conf->{$opt});
|
||||
next if $net->{model} ne 'virtio';
|
||||
|
||||
my $host_mtu = eval {
|
||||
mon_cmd(
|
||||
$vmid, 'qom-get',
|
||||
path => "/machine/peripheral/$opt",
|
||||
property => 'host_mtu',
|
||||
);
|
||||
};
|
||||
if (my $err = $@) {
|
||||
log_warn("$opt: could not query host_mtu - $err");
|
||||
} elsif (defined($host_mtu)) {
|
||||
push $nets_host_mtu->@*, "${opt}=${host_mtu}";
|
||||
} else {
|
||||
log_warn("$opt: got undefined value when querying host_mtu");
|
||||
}
|
||||
}
|
||||
return join(',', $nets_host_mtu->@*);
|
||||
}
|
||||
|
||||
1;
|
||||
|
|
|
|||
|
|
@ -225,6 +225,21 @@ $qemu_server_machine_module->mock(
|
|||
my $qemu_server_network_module = Test::MockModule->new("PVE::QemuServer::Network");
|
||||
$qemu_server_network_module->mock(
|
||||
del_nets_bridge_fdb => sub { return; },
|
||||
mon_cmd => sub {
|
||||
my ($vmid, $command, %params) = @_;
|
||||
|
||||
if ($command eq 'qom-get') {
|
||||
if (
|
||||
$params{path} =~ m|^/machine/peripheral/net\d+$|
|
||||
&& $params{property} eq 'host_mtu'
|
||||
) {
|
||||
return 1500;
|
||||
}
|
||||
die "mon_cmd (mocked) - implement me: $command for path '$params{path}' property"
|
||||
. " '$params{property}'";
|
||||
}
|
||||
die "mon_cmd (mocked) - implement me: $command";
|
||||
},
|
||||
);
|
||||
|
||||
my $qemu_server_qmphelpers_module = Test::MockModule->new("PVE::QemuServer::QMPHelpers");
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue