VLAN creation Windows 10 enterprise and professional

Windows 10 finally introduces builtin VLAN tagging; providing an alternative to the Intel Advanced Network Services or the similar functions of the Broadcom Advanced Control Suite.

  1. Still found to be working as of Anniversary Update in Windows 10 professional and enterprise
  2. As of 2017-11 found due to a hyper-v stop error, that Intel fixed the ANS tagging that necessitated this investigation, so users have the choice of ANS available for tagging, even though use of hyper-v seems more natural.

Also, tagging untrusted networks to the edge, such as user’s “Internet” VLAN, can help protect baseboard management stacks from attack such as:

To set hyper-v vlans up, we needed to install hyper-v within the builtin turn windows features on or off, to get the vSwitch functions, done even if we don't intend running any guests.

Some recent editions of hyper-v may create a builtin switch labelled Default Switch whose configuration is locked as internal, this may be safely be ignored, it is equivalent to the libvirt virbr0 for quick nat based guests, and create another vswitch

The hyper-v GUI only offers the ability to setup one management interface, suggest leaving this one detagged, but you can then use powershell to go and create the other tagged interfaces that we wanted, these show up as vEthernet in the network interfaces GUI.

Importantly, specify -ManagementOS on the extra interfaces, then these appear in the Control Panel for configuring with IP addresses or other use.

  1. Create virtual nics as needed: Add-VMNetworkAdapter
  2. Set which 802.1q tags they have Set-VMNetworkAdapterVlan


I like all host vlan to use the host's own mac address, if there is more than one adapter it may need changing in -StaticMacAddress

  1. Add-VMNetworkAdapter -ManagementOS -Name vlan10 -StaticMacAddress (Get-NetAdapter -Physical | Select -First 1 | %{$_.MacAddress}) -SwitchName "Virtual Switch"
  2. Set-VMNetworkAdapterVlan -ManagementOS -VMNetworkAdapterName vlan10 -Access -VlanId 10
  3. Add-VMNetworkAdapter -ManagementOS -Name vlan20 -StaticMacAddress (Get-NetAdapter -Physical | Select -First 1 | %{$_.MacAddress}) -SwitchName "Virtual Switch"
  4. Set-VMNetworkAdapterVlan -ManagementOS -VMNetworkAdapterName vlan20 -Access -VlanId 20
  5. Add-VMNetworkAdapter -ManagementOS -Name vlan30 -StaticMacAddress (Get-NetAdapter -Physical | Select -First 1 | %{$_.MacAddress}) -SwitchName "Virtual Switch"
  6. Set-VMNetworkAdapterVlan -ManagementOS -VMNetworkAdapterName vlan30 -Access -VlanId 30

After adding extra interfaces, if not using detagged, or leaving it only for AMT and BIOS use, may optionally like to remove the initial interface setup by the GUI, therefore ensuring all active interfaces were created the same way, are not special, and only differ by vlan tag.

Link Aggregation

Windows 10 has the ability to aggregate interfaces, this can be used together with vlans by setting the "team" adapter as the physical interface of the hyper-v switch

Firstly, I can use powershell to make the windows interface names more like systemd: predictable

  1. $hws = Get-NetAdapterHardwareInfo
  2. foreach ( $hw in $hws ) { Rename-NetAdapter -Name $hw.Name -NewName ( "enp" + $hw.Bus + "s" + $hw.Device + "f" + $hw.Function)}

Then use the team function, quite equivalent to a linux bond, usually it is desired to have the vlans running over the team,

  1. Set-VMSwitch -Name "Virtual Switch" -SwitchType Internal
  2. New-NetSwitchTeam -Name team -TeamMembers "enp1s0f0","enp1s0f1"
  3. Set-VMSwitch -Name "Virtual Switch" -NetAdapterName "team"

Windows 10 also has the NetLBFO commands though are said to only function for remote control of windows server, the rough equivalent to the hyper-v example:

  1. New-netlbfoteam -Team network -TeamMember Ethernet
  2. Add-NetLbfoTeamNic -Team network -VlanID 10
  3. Add-NetLbfoTeamNic -Team network -VlanID 20
  4. Add-NetLbfoTeamNic -Team network -VlanID 30

Windows 10 Serial Console

We used to have to hack the system to get SAC on windows 10, highly useful with linux-KVM and maybe AMT

In 2020, since Windows 10 build 2020-04 "2004" it is now a selectable feature, having the added bonus of being able to now call it Supported, with just the one DISM command to perform the steps previously done (though possible to inspect the registry and system32 in the places shown in the w7 link)

  1. dism /online /get-capabilities | findstr SAC
  2. dism /online /add-capability /CapabilityName:Windows.Desktop.EMS-SAC.Tools~~~~
  3. bcdedit /bootems {bootmgr} on
  4. bcdedit /ems {current} on
  5. bcdedit /emssettings EMSPORT:1 EMSBAUDRATE:115200

After reboot we get the SAC> prompt on the serial console 1, this would work for serial ports in the typical address of 3f8h, for virtual ports as on intel AMT there may be more work in making an SPCR table using iasl -T spcr then introducing it to the target os.


Oh yes....

Why use jumboframes? - getting the most performance from your equipment with more data per header.

Despite comments to the contrary, it is not essential that all equipment on the same VLAN understand the exact same frame length, though do be aware of some issues if not.

This mean that although TCP will negotiate via the MSS mechanism about size limits between endpoints, UDP does not so the sender needs to know in advance via the routing table the capabitities of the recipients.

Consequently a great strategy is like, force all the interface mtu limits as high as they will go as this affects reception as well, also do it to ethernet switches, wifi, everywhere, then implement route mtu limits to control what is actually sent out, this may be reduced in preference to work around defects as needed to obtain reliability.

This exploits the robustness principle in that reception is now liberal and systems then can accept and process huge, yet still usually send conservatively, limiting to 1500 if jumboframe behaviour is not validated or not wanting to use, though huge frames maybe could be aborted via a variant of cut-though, to pre-empt with a higher priority frame.

Therefore virtual interfaces such as the linux bridge can see an mtu of 65535 and physical interfaces may see a limit of around 6000-9000 depending on chipset, and atheros wifi tends to get 2304, it may be pulled down if necessary to workaround chipset defects.

Windows Jumboframes

Windows unfortunately does not have route mtu, though if off-net traffic is only/mainly tcp this may not be a big problem unless the remote end believes it is jumbo also, if there are MSS issues then the internet vlan could be pulled down as a last resort.

If using jumboframes with the vlans, updates may undo jumboframe settings, so can schedule a startup task to reset the MTU to maximum such as 9014 via Set-NetAdapterAdvancedProperty, may need testing to check setting is reverted on restart

This may not correct an issue seen 2018 of occasionally limiting mtu to about 2000 on windows, corrected with a system restart, mtu can be set separately on important virtual interfaces to 1500 and leave experimental interfaces and the physical at the larger value.

Vlans, aggregation and virtualisation

Subject to the copyright license, windows itself can be placed in a virtual operating system environment on the licensed computer, instead of being run natively, such as linux-kvm. With the tagging support, tagged frames can pass to the guest.

This has the advantage over an interface per vlan, in that priority labels can flow between host and guest, and it can be easier to add and remove vlans, although both techniques could be used simultaneously.

A piece for virsh/virt-manager

  1. <interface type='ethernet'> use ethernet, instead of bridge, and let systemd-network instead of virt-manager handle actual port add to bridge, unless using an alternative such as macvtap.
  2. <mac address='ac:de:48:23:45:67'/> - example mac address, since virtual-ose only allows one guest tend to use the host main mac address, with the local bit set.
  3. <target dev='windows'/> - used to help systemd find the virtual nic to the guest.
  4. <model type='virtio'/> paravirt for performance
  5. <address type='pci' domain='0x0000' bus='0x01' slot='0x00' function='0x0'/> - these values are used to identfy the nic in the guest especially in the situation where there are several interfaces all with the same mac address, if the guest enables net.ifnames as is very recommended, they form the nicname.
  6. </interface>
How to help networkd find that interface?
Define configuration in /etc/systemd/network/

define /etc/systemd/network/30-windows.link, to detect the virtual interface, and trigger associated .network file.

  1. [Match]
  2. Name=windows

define /etc/systemd/network/30-windows.network, to attach it to a bridge called br and pass tags 10,20,30 tagged to the guest, in this example 40 is detagged.

  1. [Match]
  2. Name=windows
  3. [Network]
  4. Bridge=br
  5. [BridgeVLAN]
  6. VLAN=10
  7. [BridgeVLAN]
  8. VLAN=20
  9. [BridgeVLAN]
  10. VLAN=30
  11. [BridgeVLAN]
  12. VLAN=40
  13. EgressUntagged=40
  14. PVID=40

Possible VLAN alternatives

Windows 10 features application guard and sandbox which allows having a lesser trusted instance of edge in guard and/or windows 10 in sandbox, neither appear to be able to require selected vlans although there may well be windows firewall features for that, and additionally alternatives may play nice with ipsec vpn and not cost MTU

To use these as an isolation it is necessary for the network to be able to tell the difference between data from the guarded/boxed and unguarded/unboxed environment that is prevented to be faked, especially from the guarded environment, so try to find some ways:

For the sandbox, set the IP TTL of the host to 255, as in "GTSM" and require that from the outside for access to management surfaces. Instances of edge or anything else run in the sandbox are thus unable to emit data from the host at IP TTL 255, because of the NAT routing.

For the guard, set the DSCP code point for the host to a high priority network management value, the guarded edge may well have DSCP forced to another value like zero.

DSCP may need Do not use NLA setting then, use the layers from CS7 through to CS0 to signify the trust level associated with the data, so CS6 and CS7 may well used to mark data for management of network switches.