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.

While the setting only takes effect starting with Proxmox VE 9, it is
necessary to add a dummy parameter to the VM start API already in
Proxmox VE 8.

[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.eb...@proxmox.com>
---
 src/PVE/API2/Qemu.pm                      |  6 ++++
 src/PVE/QemuMigrate.pm                    | 37 +++++++++++++++++++++++
 src/test/MigrationTest/QemuMigrateMock.pm |  9 ++++++
 3 files changed, 52 insertions(+)

diff --git a/src/PVE/API2/Qemu.pm b/src/PVE/API2/Qemu.pm
index ce6f362d..d15dbc2e 100644
--- a/src/PVE/API2/Qemu.pm
+++ b/src/PVE/API2/Qemu.pm
@@ -3364,6 +3364,12 @@ __PACKAGE__->register_method({
                 default => 'max(30, vm memory in GiB)',
                 optional => 1,
             },
+            'nets-host-mtu' => {
+                type => 'string',
+                pattern => 'net\d+=\d+(,net\d+=\d+)*',
+                optional => 1,
+                description => "Compat only. Parameter is only used starting 
with Proxmox VE 9.",
+            },
         },
     },
     returns => {
diff --git a/src/PVE/QemuMigrate.pm b/src/PVE/QemuMigrate.pm
index 28d7ac56..f8237692 100644
--- a/src/PVE/QemuMigrate.pm
+++ b/src/PVE/QemuMigrate.pm
@@ -170,6 +170,35 @@ sub target_storage_check_available {
     }
 }
 
+my sub get_nets_host_mtu {
+    my ($self, $vmid) = @_;
+
+    my $conf = $self->{vmconf};
+
+    my $nets_host_mtu = [];
+    for my $opt (sort keys $conf->%*) {
+        next if $opt !~ m/^net(\d+)$/;
+        my $net = PVE::QemuServer::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 = $@) {
+            $self->log('warn', "$opt: could not query host_mtu - $err");
+        } elsif (defined($host_mtu)) {
+            push $nets_host_mtu->@*, "${opt}=${host_mtu}";
+        } else {
+            $self->log('warn', "$opt: got undefined value when querying 
host_mtu");
+        }
+    }
+    return join(',', $nets_host_mtu->@*);
+}
+
 sub prepare {
     my ($self, $vmid) = @_;
 
@@ -959,6 +988,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');
     }
@@ -1144,6 +1177,10 @@ sub phase2 {
         },
     };
 
+    if (my $nets_host_mtu = get_nets_host_mtu($self, $vmid)) {
+        $params->{start_params}->{'nets-host-mtu'} = $nets_host_mtu;
+    }
+
     my ($tunnel_info, $spice_port);
 
     my @online_local_volumes = $self->filter_local_volumes('online');
diff --git a/src/test/MigrationTest/QemuMigrateMock.pm 
b/src/test/MigrationTest/QemuMigrateMock.pm
index f678f9ec..18735ed6 100644
--- a/src/test/MigrationTest/QemuMigrateMock.pm
+++ b/src/test/MigrationTest/QemuMigrateMock.pm
@@ -111,6 +111,15 @@ $qemu_migrate_module->mock(
             return;
         } elsif ($command eq 'migrate_cancel') {
             return;
+        } elsif ($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";
     },
-- 
2.39.5



_______________________________________________
pve-devel mailing list
pve-devel@lists.proxmox.com
https://lists.proxmox.com/cgi-bin/mailman/listinfo/pve-devel

Reply via email to