dmacvicar / terraform-provider-libvirt

Terraform provider to provision infrastructure with Linux's KVM using libvirt
Apache License 2.0
1.54k stars 457 forks source link

Network MTU is ignored without also setting MTU on interfaces #878

Open The-Loeki opened 2 years ago

The-Loeki commented 2 years ago

Linux distribution

Fedora 34 x86_64

Description of Issue/Question

Setting an MTU on a network and subsequently adding VM's to it leads to both the bridge and VM interface MTU still set to 1500.

Setup

terraform {
  required_providers {
    libvirt = {
      source = "dmacvicar/libvirt"
    }
  }
}
provider libvirt {
  uri = "qemu:///system"
}

locals {
  mtu = 6789
}

resource libvirt_network network {
  name = "chmtu"
  mode = "nat"
  mtu  = local.mtu

  addresses = [
    "10.11.12.0/28",
  ]
}

resource libvirt_domain vm {
  name   = "mtuvm"
  vcpu   = 2
  memory = 2048

  network_interface {
    network_name   = "chmtu"
    wait_for_lease = true
    hostname       = "mtuvm"
  }
}

Steps to Reproduce Issue

On any libvirt with or without the terraform driver, create (just) a network.

The above tf code created an mtu=6789 bridge, virsh net-dumpxml chmtu:

<network>
  <name>chmtu</name>
  <uuid>4e3da54d-5f1e-4292-89b9-f5fa034243c6</uuid>
  <forward mode='nat'>
    <nat>
      <port start='1024' end='65535'/>
    </nat>
  </forward>
  <bridge name='virbr2' stp='on' delay='0'/>
  <mtu size='6789'/>
  <mac address='52:54:00:50:bc:b9'/>
  <dns enable='no'/>
  <ip family='ipv4' address='10.11.12.1' prefix='28'>
    <dhcp>
      <range start='10.11.12.2' end='10.11.12.14'/>
      <host mac='52:54:00:9E:DD:CA' name='mtuvm' ip='10.11.12.7'/>
    </dhcp>
  </ip>
</network>

And a VM intf there virsh dumpxml mtuvm:

<domain type='kvm' id='5'>
  <name>mtuvm</name>
    <interface type='network'>
      <mac address='52:54:00:9e:dd:ca'/>
      <source network='chmtu' portid='4c1d946a-b305-4143-b17d-f15ffa5d1985' bridge='virbr2'/>
      <target dev='vnet4'/>
      <model type='virtio'/>
      <alias name='net0'/>
      <address type='pci' domain='0x0000' bus='0x00' slot='0x03' function='0x0'/>
    </interface>
  </devices>
</domain>

-BUT- ip -l:

12: virbr2: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP mode DEFAULT group default qlen 1000
    link/ether 52:54:00:50:bc:b9 brd ff:ff:ff:ff:ff:ff
13: vnet4: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master virbr2 state UNKNOWN mode DEFAULT group default qlen 1000
    link/ether fe:54:00:9e:dd:ca brd ff:ff:ff:ff:ff:ff

AFAIK this is stock kernel quirk behaviour; an empty bridge will be mtu 1500 no matter what you toss at it. Until you add an interface to it, then it assumes the MTU of that interface.

XSLT workaround fix:

<?xml version="1.0"?>
<xsl:stylesheet version="1.0"
                xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output omit-xml-declaration="yes" indent="yes"/>
  <xsl:template match="node()|@*">
      <xsl:copy>
         <xsl:apply-templates select="node()|@*"/>
      </xsl:copy>
   </xsl:template>

  <xsl:template match="/domain/devices/interface[@type='network']">
    <xsl:copy>
        <xsl:apply-templates select="node()|@*"/>
            <xsl:element name ="mtu">
                <xsl:attribute name="size">${mtu}</xsl:attribute>
            </xsl:element>
    </xsl:copy>
  </xsl:template>

</xsl:stylesheet>
terraform {
  required_providers {
    libvirt = {
      source = "dmacvicar/libvirt"
    }
  }
}
provider libvirt {
  uri = "qemu:///system"
}

locals {
  mtu = 6789
}

resource libvirt_network network {
  name = "chmtu"
  mode = "nat"
  mtu  = local.mtu

  addresses = [
    "10.11.12.0/28",
  ]
}

resource libvirt_domain vm {
  name   = "mtuvm"
  vcpu   = 2
  memory = 2048

  network_interface {
    network_name   = "chmtu"
    hostname       = "mtuvm"
  }
  xml {
    xslt = templatefile("${path.module}/nic-mtu.xsl", {mtu=local.mtu})
  }
}

Results

virsh dumpxml mtuvm

<domain type='kvm' id='6'>
  <name>mtuvm</name>
    <interface type='network'>
      <mac address='52:54:00:3a:f4:44'/>
      <source network='chmtu' portid='95d81659-26b4-4cb3-ba75-79a4ffc4318e' bridge='virbr2'/>
      <target dev='vnet5'/>
      <model type='virtio'/>
      <mtu size='6789'/>
      <alias name='net0'/>
      <address type='pci' domain='0x0000' bus='0x00' slot='0x03' function='0x0'/>
    </interface>
</domain>

ip l

12: virbr2: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 6789 qdisc noqueue state UP mode DEFAULT group default qlen 1000
    link/ether 52:54:00:50:bc:b9 brd ff:ff:ff:ff:ff:ff
14: vnet5: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 6789 qdisc noqueue master virbr2 state UNKNOWN mode DEFAULT group default qlen 1000
    link/ether fe:54:00:3a:f4:44 brd ff:ff:ff:ff:ff:ff