Network Programming with Winsock Kernel (WSK)

Winsock Kernel (WSK) is the latest network programming interface introduced by the WNDP team in Windows Vista. As evident by its name, WSK can be used by kernel-mode drivers for sending and receiving data over the network. But less evident to many developers, WSK is not an interface for performing network “filtering”. Hence, to clarify a common misconception up front, if all you want is to perform some form of network traffic filtering or interception, then you are strongly advised to look at the Windows Filtering Platform (WFP) interface first. WFP is the one-stop shop for network filtering in Windows Vista.

 

As we have first presented in last year’s Driver DevCon and WinHEC 2005, our main goal with WSK is to provide a programming interface which is easier-to-use and has higher performance relative to its predecessor Transport Driver Interface (TDI) for kernel-mode network applications. Since last year, we have considerably improved the WSK documentation in the Windows Driver Kit (WDK), and have also added a WSK sample driver to the WDK. A preview version of the pre-Beta2 WSK documents and sample is available as described in a previous blog on this site by Mike Flasko.

 

In WinHEC 2006, the session on WSK will be geared more towards the guidelines and best practices to follow in WSK to achieve optimal performance and stability. For those of you planning to attend the WSK session in WinHEC 2006, we encourage you to get familiar with the available WSK documents and the sample prior to the session to get the most out of the presentation. We have identified a number of areas in WSK over the past year based on feedback from both external and internal WSK clients that require more explanation and guidance. These include how to start and stop using WSK (WSK registration and deregistration), IRP handling, building and processing WSK_BUFs, when to use socket callbacks, how to achieve optimal throughput when sending stream data, how transport address security works, and how to use a single IPv6 socket for both IPv6 and IPv4 traffic. We will discuss all of these areas in depth in the WSK session in WinHEC 2006.

 

An important question I would like to address here is when to use WSK. Let’s look at this starting with a Winsock2 application in user-mode. If your Winsock2 application is working fine in the user-mode land, then you have no reason to consider a WSK-based implementation for that application. An important misconception here is to assume that a kernel-mode implementation will automatically provide much better performance than a user-mode implementation, which is not true. Remember also that kernel-mode programming has much stricter requirements in order to ensure a high degree of system stability and robustness; if your kernel-mode code is not rock solid, then moving your application into the kernel will cause more grief than good. Lastly, user-mode Winsock2 interface is a richer higher-level interface while, even though we have made it relatively simple and easy-to-use, WSK is still quite a low-level interface which sometimes requires an intimate familiarity of protocol-specific behavior from its clients to avoid pitfalls. To give a few concrete examples, Winsock2 does have dedicated routines for complex tasks like transmitting a file or connecting by name to remote peers whereas WSK doesn’t. Also as another less obvious example, Winsock2 performs buffering in the send direction, which allows even simple applications using blocking send requests to achieve decent throughput whereas WSK does not perform any “socket-level” buffering, hence requires the application to know about and account for things like Nagling, delayed-ack, bandwidth-delay product, etc to achieve decent throughput.

 

My personal guidance on implementing anything in kernel is to ask this question first: Is there a significant performance, stability, robustness, or security benefit in a kernel-mode implementation for a given functionality that can not otherwise be achieved by a user-mode implementation? This guidance may sound a bit abstract without a concrete example. So, let’s take a look at a real example. The HTTP.sys component in Windows Vista implements a kernel-mode HTTP stack by using the WSK interface. Prior to HTTP.sys, HTTP applications like Internet Information Services (IIS) used to use Winsock2 directly. The move to the HTTP.sys model was driven by several important factors. First, multiple HTTP applications running on the same system often needed to share a single TCP port (e.g. 80). Implementation of this sharing by keeping a clean and secure isolation between multiple HTTP application instances was not straight-forward via Winsock2 in user-mode. HTTP.sys has brought a robust solution to this problem by taking on the responsibility of managing multiple HTTP connections in kernel over a single WSK socket. This allowed applications like IIS to support multiple 3rd party plug-ins running in user-mode, in isolation, and with least-privilege in order to achieve better system stability and security. Second, HTTP.sys has a kernel-mode cache implementation that allows it to satisfy incoming HTTP requests directly in the kernel without making a user-mode transition. A kernel-mode cache for HTTP.sys makes sense due to the static nature of HTTP content. The full benefit of this cache is made possible by receiving and sending data over a WSK socket in kernel directly. This boosts the overall performance. However, note that this performance factor alone can not be the sole reason for implementing an HTTP stack in kernel without the former factor.

 

I hope what was stated so far above gives you a pretty good idea about when to use WSK. As for how to use WSK in the best possible way, we will address that topic in the WSK session in WinHEC 2006. We hope to see all of you there!

 

 

-Osman N. Ertugay