Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

New-VMSwitch command overrides interface's MTU #84

Closed
pjh opened this issue Feb 24, 2017 · 10 comments
Closed

New-VMSwitch command overrides interface's MTU #84

pjh opened this issue Feb 24, 2017 · 10 comments

Comments

@pjh
Copy link

pjh commented Feb 24, 2017

I've been experimenting with containers on Windows Server 2016 and I ran into a problem: somewhere during the container networking setup the MTU of my interface was changed. I think I've narrowed it down to the New-VMSwitch command (I believe this command is executed during the default docker network setup). Executing the steps below in powershell as Administrator should reproduce the problem; I just followed them in new Windows Server 2016 VMs on Azure / EC2 / GCE.

cmd /c 'netsh interface ipv4 show subinterfaces'
# Set the MTU to a lower value:
cmd /c 'netsh interface ipv4 set subinterface "Ethernet 2" mtu=1460 store=persistent'

# Install docker to get container and Hyper-V components:
Install-Module -Name DockerMsftProvider -Repository PSGallery -Force
Install-Package -Name docker -ProviderName DockerMsftProvider
Restart-Computer -Force

# Reconnect RDP session. The vEthernet interface for the default container
# always has MTU 1500, rather than taking MTU 1460 from "Ethernet 2":
cmd /c 'netsh interface ipv4 show subinterfaces'

# Remove the existing container network, then reconnect the RDP session:
Stop-Service docker
Get-ContainerNetwork | Remove-ContainerNetwork -Force

# Ethernet 2 is now the only interface again, with MTU 1460:
cmd /c 'netsh interface ipv4 show subinterfaces'

# Create a new VMSwitch, then reconnect the RDP session:
New-VMSwitch -name testMTU -netadaptername "Ethernet 2"

# The only interface is now "vEthernet (testMTU)", with MTU forced to 1500
# instead of 1460:
cmd /c 'netsh interface ipv4 show subinterfaces'

This unexpected MTU change will cause packet fragmentation and potentially other issues (in my case my RDP connection did not work until I lowered the MTU again). Is there a reason that New-VMSwitch overrides the MTU on the Ethernet interface? Can the command be changed to inherit the MTU from the interface?

(Filing this bug here after looking at https://technet.microsoft.com/en-us/windows-server-docs/networking/sdn/contact-sdn-team - hopefully this is the right place.)

@pires
Copy link

pires commented Feb 24, 2017

I can confirm this behavior too.

@kallie-b
Copy link

Ping @dineshgovindasamy

@JMesser81
Copy link
Contributor

ping @dineshgovindasamy, @viaror

@JMesser81
Copy link
Contributor

Thanks for reporting this issue. Can you give us some more details as to why you're reducing MTU size? Are you trying to account for encapsulation overhead (or something similar) in a public cloud environment?

@pjh
Copy link
Author

pjh commented Mar 10, 2017

Yeah, you're exactly right: on Google Compute Engine the maximum guest MTU is 1460 to allow for encapsulation overhead in the cloud network.

@kallie-b
Copy link

Following up internally. Will get back to you as soon as possible.

@JMesser81
Copy link
Contributor

This is currently "by design". Hyper-V VM Switch does not inherit MTU settings from the network adapter. You can decrease MTU after the fact.

In our clouds we are accounting for this by enabling JF (or at least increasing MTU by specifying a specific value) and continue to expose 1514 MTU to the guest.

@pjh
Copy link
Author

pjh commented Aug 16, 2017

Delayed follow-up question: when I run a netsh command like the following to set the MTU, does anyone know where the MTU value gets stored?

netsh interface ipv4 set subinterface "vEthernet (HNS Internal NIC)" mtu=1460 store=persistent

I expected it to end up in the registry, but I searched using regedit and could not find 1460 anywhere. Is there another location in the file system where this value gets saved when set with store=persistent? I tried to search for this information but could not find it.

The reason I'm asking is that when I run a docker container its vEthernet (Container NIC ...) interface is also getting an MTU of 1500, even if I set the host's MTU back to 1460 before running the container. I'm trying to figure out if there's a way to guarantee that both my host and all of my containers will always use MTU 1460 without having to set the value manually in every container I create.**

@JMesser81 @dineshgovindasamy @viaror @kallie-b if you have any information, that would be appreciated!

**It turns out that if I run a container with docker run --rm -it microsoft/nanoserver powershell, change the MTU of the container's vEthernet interface, exit the container and reboot the host, and then run the container again with the same command, the changed MTU gets remembered, which is helpful. I have no idea if this is reliable though and would like to understand where/how netsh persists the value.

@JMesser81
Copy link
Contributor

@pjh - We add the add the adapter at run-time and so it is not persisted. We will look for another way to change the default MTU. Note: it is already reduced to 50B on any container interfaces connected to an overlay network.

@pjh
Copy link
Author

pjh commented Jun 20, 2019

A note for anyone trying to work around this issue, which is still a nuisance over two years later...

For some reason the Set-NetIPInterface PowerShell cmdlet does not work for persistently setting the MTU for a vEthernet interface on a Windows VM, whereas the old netsh commands do work. In a Windows Server 1809 VM, after installing Docker and restarting I have an Ethernet interface and a vEthernet (nat) interface on my VM. If I run these commands and then restart the computer, the MTU of the vEthernet interface returns to 1500 after the restart:

Get-NetIPInterface | Where-Object InterfaceAlias -like "*Ethernet*" |
    Set-NetIPInterface -IncludeAllCompartments -NlMtuBytes 1460 -PolicyStore ActiveStore
Get-NetIPInterface | Where-Object InterfaceAlias -like "*Ethernet*" |
    Set-NetIPInterface -IncludeAllCompartments -NlMtuBytes 1460 -PolicyStore PersistentStore

However, if I run this netsh command then the vEthernet interface's MTU remains at 1460 after restarting:

netsh interface ipv4 set subinterface "vEthernet (nat)" mtu=1460 store=persistent

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants