Tweak Win2K Server registry to improve TCP/IP performance

Windows 2000's automatic TCP/IP settings aren't always the best choices for network performance. See how you can modify a Win2K Server's registry to optimize TCP/IP.

Windows 2000 Server's TCP/IP Properties Sheet is a little deceptive in giving the impression that basic information, such as an IP address, subnet mask, default gateway, or DNS server, is all that's required to create connections. There's much more to TCP/IP than meets the eye; Windows simply requires a minimal amount of operator input and then establishes a TCP/IP connection based on that information and several preset options.

Unfortunately, an easy configuration doesn't always equal optimal performance. I'm going to show you various registry keys you can modify to increase TCP/IP performance on a Windows 2000 Server.

Modifying the registry is dangerous. Making an incorrect registry change can destroy Windows and/or your applications. Likewise, changing the TCP/IP registry keys can sometimes have an adverse effect on performance. Make a full system backup before you try any of the techniques described in this article. If you decide to tweak TCP/IP, you should make one change at a time (unless otherwise noted). Get a feel for the change that you've made before making any other changes. Some of the registry keys that I'll be showing you can have a rather dramatic effect when changed. To gain optimum results from the changes, you should make them to all of the servers and workstations on your network.

Adjusting the Maximum Transmission Unit size
Of all the registry tweaks that I've found for TCP/IP, perhaps the most useful is the ability to adjust the Maximum Transmission Unit (MTU) size. MTU size dictates the maximum packet size (in bytes) that the TCP/IP transport will attempt to transmit over the underlying network. Networks that use Internet Connection Sharing (ICS) or Point-to-Point Protocol over Ethernet (PPPoE) for their broadband connections must have an MTU size of 1,492 or lower to run efficiently.

An incorrect MTU size can make your network run slowly. Administrators tend to dismiss this problem as low bandwidth on the ISP's end, and that might be a source of the problem. But you'd be surprised at the difference an MTU adjustment can make.

The MTU is such a factor because, by default, Windows 2000 and Windows XP set the MTU size to 1,500. It's been my experience that if a network is running slowly, even the 1,492 value I mentioned earlier is too high. I usually have the best luck by setting the MTU to around 1,454.

You can check the MTU size for your environment by opening a command prompt on your administration workstation and typing
PING -F -I <MTUsize> <gateway>

where MTUsize is the size you want to experiment with and gateway is the gateway of your network. Start out by using an MTU size of 1,454. Doing so will make the command look something like this:
PING -F -I 1454

When you enter the command, the PING will either be successful or it will fail with a message stating that the data must be fragmented. If you receive the error message, decrease the MTU value and keep trying until you find a value that works. If the PING command works the first time, try incrementing the value by five or 10 until you see the error message. You can then narrow down to the appropriate value.

Once you've discovered an MTU size that works, the next trick is to embed the value into the registry. The key's actual location within the registry varies depending on the version of Windows you're using. If you're using Windows NT, the MTU key is located at:

If you're using Windows 2000 or higher, the MTU key is located at:
\Tcpip\Parameters\Interfaces\adapter ID

There's a good chance that the MTU key doesn't presently exist in your system and that you'll have to create it at the specified location. To do so, open the Registry Editor and create a new DWORD value called MTU. The minimum value for this key is 68, and the maximum value is the MTU for the underlying network.

Other MTU-related registry keys
Once you've set the MTU value for a PC or server, you may want to tweak some other MTU-related registry keys.

Remote networks also have an MTU value, which is almost always different from that of the local network. Enabling this registry key tells TCP/IP to try to automatically detect the MTU for all networks along the path to a remote host. Once TCP/IP knows the MTU for all networks along a path, it can avoid using MTU values that that are too high, thus avoiding packet fragmentation and the performance problems that come with it.

The EnablePMTUDiscovery key doesn't exist in the registry unless you create it. However, this feature is enabled by default, so you would normally create this registry key only if you wanted to disable path MTU detection or experiment with turning path MTU detection on and off.

You would create the EnablePMTUDiscovery key at:

If you decide to create the EnablePMTUDiscovery key, the key must be a DWORD key, which is assigned a Boolean value. Assigning the key a value of 1 enables path MTU discovery, while assigning the key a 0 disables it.

If you choose to disable path MTU discovery, TCP/IP uses a default MTU size of 576 bytes for all communications across remote networks. While 576 bytes certainly isn't an optimal packet size, at least you won't have to worry about packet fragmentation. I personally recommend leaving the path MTU discovery feature enabled unless you're having problems reaching remote hosts.

If you're having remote communication trouble, the problem could be related to a black hole router. Black hole routers are configured not to return the Destination Host Unreachable messages that are used by path MTU discovery. Normally, when TCP/IP performs path MTU discovery, the process works by sending out a packet of data with the DF (Don't Fragment) bit set. If the PC sending out the packet receives a Destination Host Unreachable message, it means that the MTU for that particular network may be too high; in this case, TCP/IP will try to use a lower value.

If you want TCP/IP to detect black hole routers, you must create a registry key called EnablePMTUBHDetect beneath:

The key must be a DWORD key with a Boolean value. Setting the key to 1 enables black hole detection, while setting the key to 0 disables black hole detection.

Black hole detection is disabled by default because enabling it increases the number of transmission retries when communicating with a host. This means that a lot of bandwidth can be consumed during the early phases of path MTU detection, and the initial connection to a host may be slower than normal.

The router packet queue
Windows NT, 2000, and XP can each function as routers between networks. By default, the routing function is disabled for security reasons. You can enable packet routing by navigating through the registry to:

and setting the IPEnableRouter key to a Boolean value of 1.

If you choose to enable packet routing, there are several ways to optimize the routing process. The Windows implementation of TCP/IP has a built-in router cache and queue that are active only when the routing function has been enabled.

Earlier, I showed you how to adjust your MTU value. If you've adjusted your MTU size, you may also want to adjust your forward buffer memory. The forward buffer memory controls how much RAM TCP/IP uses for storing packet data in the router packet queue.

Each packet queue data buffer is 256 bytes long. So, if you choose to set this registry key, the number you specify must be a multiple of 256. The default value is 74,240, which will accommodate 50 1,480-byte packets.

To set the number of packet queue data buffers, create a registry key called ForwardBufferMemory beneath:

The key must be a DWORD value that's assigned the number of bytes of memory you want to allocate. The minimum value must never be smaller than your MTU size. Therefore, if your MTU size is 1,454, your minimum ForwardBufferMemory size would also be 1,454. The maximum size is 0xFFFFFFFF. However, I recommend keeping the value at a reasonable size.

For example, if your MTU is set to 1,454, I recommend setting ForwardBufferMemory to 50 to 100 times the MTU size. To keep the math easy, 100 times the MTU size of 1,454 would be 145,400. If you divide 145,400 by 256, you get 567.96875. Since 145,400 isn't evenly divisible by 256, take your answer and round it to the next highest whole number, 568. Now, multiply 568 by 256 to get 145,408. This would be the appropriate ForwardBufferMemory�setting.

In case you're curious, just because each buffer is 256 bytes doesn't mean that your packets must also be 256 bytes long. When a packet length exceeds the buffer length, multiple buffers are used as needed to accommodate the packet. To save space, the packet's IP header is stored separately.

Another registry key that may be of interest to you is the NumForwardPackets key located at:

This registry key determines the number of IP packet headers that are designated for the router packet queue. It's a good idea to set this key to a fairly high value because when all allocated header space is used, TCP/IP will begin to randomly discard packets from the queue.

Like many of the other registry keys that we've looked at so far, the NumForwardPackets key doesn't exist by default. When creating this registry key, you should make the key a DWORD and assign it a number that will represent the maximum number of packet headers to store in the TCP/IP queue. If you choose not to create this registry key, Windows will use a default value of 50.

Setting an optimal value for the NumForwardPackets key can be tricky. The minimum size you should set this value to is the ForwardBufferMemory size divided by the largest IP data size.

The maximum NumForwardPackets value should be based on the ForwardBufferMemory value divided by the maximum IP packet size. Because the maximum IP data buffer size is 256, I recommend determining the maximum NumForwardPackets value by dividing the ForwardBufferMemory by 256. Earlier, I suggested setting the ForwardBufferMemory to 145,408. This means that the highest value you'd want to use would be 568, assuming you had an MTU size of 1,454 and were basing your ForwardBufferMemory size on 100 times the MTU size rounded to the next highest multiple of 256.

As you can see, there's a huge difference between Windows' default value of 50 and my maximum value of 568. I recommend going with the maximum value. Just remember to do the math and pick the true maximum value, rather than just using my numbers. There's no reason you can't use a number below the maximum value as long as you're above the minimum value. But if you go above the maximum value, you're wasting memory.

Keeping a packet alive
We've all seen connections time out when attempting to connect to a slow Web site or other slow resource. The connection times out because TCP/IP's TTL (Time To Live) counter expires.

When you transmit a packet, TCP/IP starts with a predetermined TTL value. The TTL counter is decremented by one every time a packet passes through a router or when one second ticks by. If the packet takes too long to get to its destination or to be acknowledged by the recipient, or if the route to the destination is too far away (too many hops), the packet will expire before being received.

If you have frequent problems with packets expiring too quickly, you can set the TTL to a higher value. The TTL is controlled by a registry key called DefaultTTL. If you want to use this key, you'll have to create it at:

If you choose not to create the DefaultTTL key, Windows will use a default value based on the version of Windows you're using. Windows NT 3.51 and earlier versions have a default TTL value of 32, while Windows 2000 and higher have a default value of 128. If you create this key and set your own TTL value, the value you set should never be lower than the defaults, but it can be as high as 255.

Increasing performance over low-bandwidth connections
TCP/IP was designed in the 1960s to function over long distances and low-bandwidth links. Although available bandwidth has increased dramatically since then, so has the amount of data being pushed through it. Even 40 years after TCP/IP's birth, low bandwidth is still an issue.

You can get the most out of your available bandwidth on a low-bandwidth link by minimizing the amount of overhead required by the TCP/IP protocol. One way to do this is to increase the window size. Increasing the window size increases the amount of data that can be transmitted before an acknowledgement is required from the recipient. Unfortunately, there's a downside to this approach. If a retransmission is required, a lot more data must be retransmitted. However, when everything is working properly, increasing the window size dramatically improves efficiency.

To increase the window size, create a DWORD registry key called TcpWindowSize at:

The number you assign to the key reflects the number of bytes that a sender can transmit before requiring an acknowledgement. For maximum efficiency, the value you select should be a multiple of the TCP maximum segment size (MSS). The default for an Ethernet network is 8,760 (8,192 rounded up to an even multiple of the MSS).

Dig a little deeper
Although you can configure basic TCP/IP properties through Control Panel, there are lots of undocumented TCP/IP settings you can modify only through the registry. As you experiment with the various registry settings, be sure to document your original settings. Incorrectly setting any of the registry keys that I've discussed can bring TCP/IP to a grinding halt.

Editor's Picks