Using Layer 2 Filtering

Layer 2 filtering is supported in Windows 8 and later versions of Windows.

This WFP feature allows filtering on fields of the layer 2 MAC header. These layers are invoked on a per-packet basis for all packets that are sent or received by the host machine. The layers are invoked prior to packet reassembly on the inbound path and after packet fragmentation on the outbound path. These layers are accessed from an NDIS lightweight filter (LWF) driver.

Note A callout should not inject packets at a layer if it does not already have a corresponding filter at that layer. The injection of the NET_BUFFER_LIST structures should be coordinated with the filter addition and removal so that injection is only performed when the filter exists in the corresponding layer. In addition, providers should not remove filters that belong to other providers.

This section includes the following topics:

Injecting MAC Frames

A callback driver calls the FwpsInjectMacReceiveAsync0 function to reinject a previously absorbed MAC frame (or a clone of the frame) back to the layer 2 inbound data path it was intercepted from, or to inject an invented MAC frame in the inbound data path.

A callback driver calls the FwpsInjectMacSendAsync0 function to reinject a previously absorbed MAC frame (or a clone of the frame) back to the layer 2 outbound data path it was intercepted from, or to inject an invented MAC frame in the outbound data path.

The netBufferLists parameter can be a NET_BUFFER_LIST chain. However the completion function could be invoked multiple times each, completing a segment (or single NET_BUFFER_LIST) of the chain.

Injected frames could get classified again if the packets match the same filter as originally classified. Therefore, as with callouts at IP layers, layer 2 callouts must also protect against infinite packet inspection by calling FwpsQueryPacketInjectionState0.

Also, you must have callouts at the layer where you inject. Otherwise, your injected NET_BUFFER_LIST will not be completed to your completion function, and the NET_BUFFER_LIST will go further up the stack. In this case, the behavior is undefined, because NDIS will try to pass the injected NET_BUFFER_LIST to the next component in the stack.

The NET_BUFFER_LISTStatus member contains the stack injection’s status result. The stack injection’s status result is the status that the stack puts in the NET_BUFFER_LIST after a WFP injection function returns STATUS_SUCCESS. You should use the NT_SUCCESS macro to check the stack injection's status in the Status member. If the Status value is STATUS_SUCCESS, the injection succeeded with no further information. Status member values that are greater than STATUS_SUCCESS mean that the injection succeeded, but there might be more information about the injection that should be considered. Status member values that are less than STATUS_SUCCESS mean that the injection failed for the reason specified in the Status member.

Classifying Chained Network Buffer Lists

By default, a callout driver can only classify network buffer lists individually. However, a callout driver can classify NET_BUFFER_LIST chains for better performance, if it does both of the following:

WFP Layer 2 Layers and Fields

Run-time Filtering Layer Identifiers for virtual switch filtering include:

FWPS_LAYER_INBOUND_MAC_FRAME_ETHERNET

FWPS_LAYER_OUTBOUND_MAC_FRAME_ETHERNET

FWPS_LAYER_INBOUND_MAC_FRAME_NATIVE

FWPS_LAYER_OUTBOUND_MAC_FRAME_NATIVE

Data Field Identifiers for virtual switch filtering include:

FWPS_FIELDS_INBOUND_MAC_FRAME_ETHERNET

FWPS_FIELDS_OUTBOUND_MAC_FRAME_ETHERNET

FWPS_FIELDS_INBOUND_MAC_FRAME_NATIVE

FWPS_FIELDS_OUTBOUND_MAC_FRAME_NATIVE