[ovs-dev] [PATCH 1/4] datapath-windows: Base code for developing the Hyper-V switch entension.
Saurabh Shah
ssaurabh at vmware.com
Tue Jun 24 00:34:56 UTC 2014
This is the "Hyper-V Extensible Switch extension filter driver" sample code
available at:
http://code.msdn.microsoft.com/windowshardware/Hyper-V-Extensible-Virtual-e4b31fbb
The sample code is licensed under Microsoft Limited Public License version
1.1. The license is available here -
http://msdn.microsoft.com/en-us/cc300389.aspx (Exhibit B).
Our core Hyper-V switch extension builds on top of this sample code to develop
the forwarding engine.
Signed-off-by: Eitan Eliahu <eliahue at vmware.com>
Signed-off-by: Guolin Yang <gyang at vmware.com>
Signed-off-by: Linda Sun <lsun at vmware.com>
Signed-off-by: Nithin Raju <nithin at vmware.com>
Signed-off-by: Saurabh Shah <ssaurabh at vmware.com>
---
AUTHORS | 2 +
COPYING | 4 +
datapath-windows/base/SxApi.h | 1196 +++++++++++++++++++++++++++++++
datapath-windows/base/SxBase.c | 1395 ++++++++++++++++++++++++++++++++++++
datapath-windows/base/SxBase.h | 168 +++++
datapath-windows/base/SxLibrary.c | 839 ++++++++++++++++++++++
datapath-windows/base/SxLibrary.h | 464 ++++++++++++
datapath-windows/base/precomp.h | 11 +
datapath-windows/base/precompsrc.c | 1 +
debian/copyright.in | 74 ++
10 files changed, 4154 insertions(+)
create mode 100644 datapath-windows/base/SxApi.h
create mode 100644 datapath-windows/base/SxBase.c
create mode 100644 datapath-windows/base/SxBase.h
create mode 100644 datapath-windows/base/SxLibrary.c
create mode 100644 datapath-windows/base/SxLibrary.h
create mode 100644 datapath-windows/base/precomp.h
create mode 100644 datapath-windows/base/precompsrc.c
diff --git a/AUTHORS b/AUTHORS
index 08646d3..11ccdc7 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -46,6 +46,7 @@ Duffie Cooley dcooley at nicira.com
Ed Maste emaste at freebsd.org
Edouard Bourguignon madko at linuxed.net
Edward Tomasz Napierała trasz at freebsd.org
+Eitan Eliahu eliahue at vmware.com
Ethan Jackson ethan at nicira.com
Flavio Leitner fbl at redhat.com
Francesco Fusco ffusco at redhat.com
@@ -93,6 +94,7 @@ Murphy McCauley murphy.mccauley at gmail.com
Natasha Gude natasha at nicira.com
Neil McKee neil.mckee at inmon.com
Neil Zhu zhuj at centecnetworks.com
+Nithin Raju nithin at vmware.com
Padmanabhan Krishnan kprad1 at yahoo.com
Paraneetharan Chandrasekaran paraneetharanc at gmail.com
Paul Fazzone pfazzone at nicira.com
diff --git a/COPYING b/COPYING
index 9d6fc48..06adace 100644
--- a/COPYING
+++ b/COPYING
@@ -91,3 +91,7 @@ Foundation License, version 2:
8. By copying, installing or otherwise using Python, Licensee
agrees to be bound by the terms and conditions of this License
Agreement.
+
+Files unders datapath-windows/base are licensed under Microsoft Limited Public
+License version 1.1, that is available at:
+http://msdn.microsoft.com/en-us/cc300389.aspx (Exhibit B).
diff --git a/datapath-windows/base/SxApi.h b/datapath-windows/base/SxApi.h
new file mode 100644
index 0000000..6ee52c9
--- /dev/null
+++ b/datapath-windows/base/SxApi.h
@@ -0,0 +1,1196 @@
+/*++
+
+Copyright (c) Microsoft Corporation. All Rights Reserved.
+
+Module Name:
+
+ SxApi.h
+
+Abstract:
+
+ This file contains the API that must be implemented to
+ create a switch extension using the SxBase library.
+
+
+--*/
+
+//
+// The major version of NDIS the driver is using.
+// For NDIS 6.30, use NDIS_FILTER_MAJOR_VERSION.
+//
+extern UCHAR SxExtMajorNdisVersion;
+
+//
+// The minor version of NDIS the driver is using.
+// For NDIS 6.30, use NDIS_FILTER_MINOR_VERSION.
+//
+extern UCHAR SxExtMinorNdisVersion;
+
+//
+// The friendly name of the extension.
+//
+extern PWCHAR SxExtFriendlyName;
+
+//
+// The unique name of the extension.
+//
+extern PWCHAR SxExtUniqueName;
+
+//
+// The service name of the extension from the INF.
+//
+extern PWCHAR SxExtServiceName;
+
+//
+// The memory pool tag using in the extension.
+//
+extern ULONG SxExtAllocationTag;
+
+//
+// The request ID used to identify OIDs initiated from this extension.
+//
+extern ULONG SxExtOidRequestId;
+
+
+/*++
+
+SxExtInitialize
+
+Routine Description:
+ This function is called from the SxBase Library during DriverEntry.
+ An extension should allocate/initalize all global data in this function.
+
+Arguments:
+ NULL
+
+Return Value:
+ NDIS_STATUS_SUCCESS succeeds driver entry.
+
+ NDIS_STATUS_*** fails driver entry.
+
+--*/
+NDIS_STATUS
+SxExtInitialize();
+
+
+/*++
+
+SxExtUninitialize
+
+Routine Description:
+ This function is called from the SxBase Library during DriverUnload.
+ An extension should free/reset all global data in this function.
+
+Arguments:
+ NULL
+
+Return Value:
+ VOID
+
+--*/
+VOID
+SxExtUninitialize();
+
+
+/*++
+
+SxExtCreateSwitch
+
+Routine Description:
+ This function is called when an extension binds to a new switch.
+ All switch specific data should be allocated during this function.
+ OIDs cannot be sent from this function, and both the control
+ and data paths are inactive.
+
+Arguments:
+ Switch - the Switch Object currently being created
+
+ ExtensionContext - Extension context specific to the switch being
+ createf. This context will be passed back to the
+ extension for all function calls in SxApi
+
+Return Value:
+ NDIS_STATUS_SUCCESS succeeds switch creation.
+
+ NDIS_STATUS_RESOURCES fails switch creation because of insufficient
+ resources.
+
+ NDIS_STATUS_FAILURE fails switch creation.
+
+--*/
+NDIS_STATUS
+SxExtCreateSwitch(
+ _In_ PSX_SWITCH_OBJECT Switch,
+ _Outptr_result_maybenull_ PNDIS_HANDLE *ExtensionContext
+ );
+
+
+/*++
+
+SxExtDeleteSwitch
+
+Routine Description:
+ This function is called when an extension binds to a new switch.
+ All switch specific data should be allocated/initialized during
+ this function.
+
+Arguments:
+ Switch - the Switch being deleted
+
+ ExtensionContext - The extension context allocated in SxExtCreateSwitch
+ for the switch being deleted.
+
+Return Value:
+ VOID
+
+--*/
+VOID
+SxExtDeleteSwitch(
+ _In_ PSX_SWITCH_OBJECT Switch,
+ _In_ NDIS_HANDLE ExtensionContext
+ );
+
+
+/*++
+
+SxExtActivateSwitch
+
+Routine Description:
+ This function is called to activate a switch. The function can be called
+ while the switch is Running or Paused and should be used to bootstrap
+ the switch if it was not Active when it was created.
+
+Arguments:
+ Switch - the Switch being activated
+
+ ExtensionContext - The extension context allocated in SxExtCreateSwitch
+ for the switch being restarted.
+
+Return Value:
+ VOID
+
+--*/
+VOID
+SxExtActivateSwitch(
+ _In_ PSX_SWITCH_OBJECT Switch,
+ _In_ NDIS_HANDLE ExtensionContext
+ );
+
+
+/*++
+
+SxExtRestartSwitch
+
+Routine Description:
+ This function is called to restart a switch from a paused state.
+
+Arguments:
+ Switch - the Switch being restarted
+
+ ExtensionContext - The extension context allocated in SxExtCreateSwitch
+ for the switch being restarted.
+
+Return Value:
+ NDIS_STATUS_SUCCESS succeeds switch restart.
+
+ NDIS_STATUS_RESOURCES fails switch restart because of insufficient
+ resources.
+
+ NDIS_STATUS_FAILURE fails switch restart.
+
+--*/
+NDIS_STATUS
+SxExtRestartSwitch(
+ _In_ PSX_SWITCH_OBJECT Switch,
+ _In_ NDIS_HANDLE ExtensionContext
+ );
+
+
+/*++
+
+SxExtPauseSwitch
+
+Routine Description:
+ This function is called to pause a switch from a running state.
+
+Arguments:
+ Switch - the Switch being paused
+
+ ExtensionContext - The extension context allocated in SxExtCreateSwitch
+ for the switch being paused
+
+Return Value:
+ VOID
+
+--*/
+VOID
+SxExtPauseSwitch(
+ _In_ PSX_SWITCH_OBJECT Switch,
+ _In_ NDIS_HANDLE ExtensionContext
+ );
+
+
+/*++
+
+SxExtCreatePort
+
+Routine Description:
+ This function is called to create a new port on a switch.
+
+Arguments:
+ Switch - the Switch context
+
+ ExtensionContext - The extension context allocated in SxExtCreateSwitch
+ for the switch
+
+ Port - the Port being created
+
+Return Value:
+ NDIS_STATUS_SUCCESS to succeed port creation
+
+ NDIS_STATUS_*** to fail port creation
+
+--*/
+NDIS_STATUS
+SxExtCreatePort(
+ _In_ PSX_SWITCH_OBJECT Switch,
+ _In_ NDIS_HANDLE ExtensionContext,
+ _In_ PNDIS_SWITCH_PORT_PARAMETERS Port
+ );
+
+
+/*++
+
+SxExtUpdatePort
+
+Routine Description:
+ This function is called to update an already created port.
+
+Arguments:
+ Switch - the Switch context
+
+ ExtensionContext - The extension context allocated in SxExtCreateSwitch
+ for the switch
+
+ Port - the port being updated
+
+Return Value:
+ VOID
+
+--*/
+VOID
+SxExtUpdatePort(
+ _In_ PSX_SWITCH_OBJECT Switch,
+ _In_ NDIS_HANDLE ExtensionContext,
+ _In_ PNDIS_SWITCH_PORT_PARAMETERS Port
+ );
+
+
+/*++
+
+SxExtCreateNic
+
+Routine Description:
+ This function is called to create a new NIC to be connected
+ to a switch.
+ The extension may allocate context for this NIC, and traffic may
+ start to flow from this NIC, but it may not be used as a destination
+ until SxExtConnectNic has been called.
+
+Arguments:
+ Switch - the Switch context
+
+ ExtensionContext - The extension context allocated in SxExtCreateSwitch
+ for the switch
+
+ Nic - the NIC being created
+
+Return Value:
+ NDIS_STATUS_SUCCESS to succeed NIC creation
+
+ NDIS_STATUS_*** to fail NIC creation
+
+--*/
+NDIS_STATUS
+SxExtCreateNic(
+ _In_ PSX_SWITCH_OBJECT Switch,
+ _In_ NDIS_HANDLE ExtensionContext,
+ _In_ PNDIS_SWITCH_NIC_PARAMETERS Nic
+ );
+
+
+/*++
+
+SxExtConnectNic
+
+Routine Description:
+ This function is called to connect a NIC to a switch.
+ After returning from this function the extension can use this NIC
+ as a destination.
+
+Arguments:
+ Switch - the Switch context
+
+ ExtensionContext - The extension context allocated in SxExtCreateSwitch
+ for the switch
+
+ Nic - the NIC being connected
+
+Return Value:
+ VOID
+
+--*/
+VOID
+SxExtConnectNic(
+ _In_ PSX_SWITCH_OBJECT Switch,
+ _In_ NDIS_HANDLE ExtensionContext,
+ _In_ PNDIS_SWITCH_NIC_PARAMETERS Nic
+ );
+
+
+/*++
+
+SxExtUpdateNic
+
+Routine Description:
+ This function is called to update an already created NIC.
+
+Arguments:
+ Switch - the Switch context
+
+ ExtensionContext - The extension context allocated in SxExtCreateSwitch
+ for the switch
+
+ Nic - the NIC being updated
+
+Return Value:
+ VOID
+
+--*/
+VOID
+SxExtUpdateNic(
+ _In_ PSX_SWITCH_OBJECT Switch,
+ _In_ NDIS_HANDLE ExtensionContext,
+ _In_ PNDIS_SWITCH_NIC_PARAMETERS Nic
+ );
+
+
+/*++
+
+SxExtDisconnectNic
+
+Routine Description:
+ This function is called to disconnect a NIC from a switch.
+ After returning from this function the extension cannot use
+ this NIC as a destination.
+
+Arguments:
+ Switch - the Switch context
+
+ ExtensionContext - The extension context allocated in SxExtCreateSwitch
+ for the switch
+
+ Nic - the NIC being disconnected
+
+Return Value:
+ VOID
+
+--*/
+VOID
+SxExtDisconnectNic(
+ _In_ PSX_SWITCH_OBJECT Switch,
+ _In_ NDIS_HANDLE ExtensionContext,
+ _In_ PNDIS_SWITCH_NIC_PARAMETERS Nic
+ );
+
+
+/*++
+
+SxExtDeleteNic
+
+Routine Description:
+ This function is called to delete a NIC from a switch.
+ No futher traffic/control will be recieved for this NIC.
+
+Arguments:
+ Switch - the Switch context
+
+ ExtensionContext - The extension context allocated in SxExtCreateSwitch
+ for the switch
+
+ Nic - the NIC being deleted
+
+Return Value:
+ VOID
+
+--*/
+VOID
+SxExtDeleteNic(
+ _In_ PSX_SWITCH_OBJECT Switch,
+ _In_ NDIS_HANDLE ExtensionContext,
+ _In_ PNDIS_SWITCH_NIC_PARAMETERS Nic
+ );
+
+
+/*++
+
+SxExtTeardownPort
+
+Routine Description:
+ This function is called to start deletion of a port on a switch.
+ Upon recieving this call, no further references may be taken
+ on the given port.
+
+Arguments:
+ Switch - the Switch context
+
+ ExtensionContext - The extension context allocated in SxExtCreateSwitch
+ for the switch
+
+ Port - the Port being deleted
+
+Return Value:
+ VOID
+
+--*/
+VOID
+SxExtTeardownPort(
+ _In_ PSX_SWITCH_OBJECT Switch,
+ _In_ NDIS_HANDLE ExtensionContext,
+ _In_ PNDIS_SWITCH_PORT_PARAMETERS Port
+ );
+
+
+/*++
+
+SxExtDeletePort
+
+Routine Description:
+ This function is called to finish deletion of a port on a switch.
+ Upon recieving this call, no traffic/control will be recieved
+ for this port.
+
+Arguments:
+ Switch - the Switch context
+
+ ExtensionContext - The extension context allocated in SxExtCreateSwitch
+ for the switch
+
+ Port - the Port being deleted
+
+Return Value:
+ VOID
+
+--*/
+VOID
+SxExtDeletePort(
+ _In_ PSX_SWITCH_OBJECT Switch,
+ _In_ NDIS_HANDLE ExtensionContext,
+ _In_ PNDIS_SWITCH_PORT_PARAMETERS Port
+ );
+
+
+/*++
+
+SxExtSaveNic
+
+Routine Description:
+ This function is called to retrieve save data for a given NIC.
+ This function will be called until all extensions have finished
+ saving data.
+
+ An new save for this NIC will not start until SxExtSaveNicComplete
+ has been received.
+
+ If returning NDIS_STATUS_SUCCESS from this function, and
+ BytesWritten > 0 you must write to the ExtensionId,
+ ExtensionFriendlyName, SaveDataSize and SaveData fields in
+ SaveState. SxExtUniqueName MUST be written to ExtensionId.
+ SxExtFriendlyName should be written to ExtensionFriendlyName.
+
+ If returning NDIS_STATUS_SUCCESS with BytesWritten == 0,
+ DO NOT write any data to any fields.
+
+Arguments:
+ Switch - the Switch context
+
+ ExtensionContext - The extension context allocated in SxExtCreateSwitch
+ for the switch
+
+ SaveState - the save information and buffer to save to
+
+ BytesWritten - the # of bytes written to the save buffer
+
+ BytesNeeded - the length of the save buffer needed
+
+Return Value:
+ NDIS_STATUS_SUCCESS - if the buffer was successfully written, or not
+ needed and BytesWritten is set to 0
+
+ NDIS_STATUS_BUFFER_TOO_SHORT - if the buffer is too short for the
+ necessary save, write the length needed
+ in BytesNeeded
+
+ NDIS_STATUS_*** - to fail the save operation
+
+--*/
+NDIS_STATUS
+SxExtSaveNic(
+ _In_ PSX_SWITCH_OBJECT Switch,
+ _In_ NDIS_HANDLE ExtensionContext,
+ _Inout_ PNDIS_SWITCH_NIC_SAVE_STATE SaveState,
+ _Out_ PULONG BytesWritten,
+ _Out_ PULONG BytesNeeded
+ );
+
+
+/*++
+
+SxExtSaveNicComplete
+
+Routine Description:
+ This function is called to notify the extension that saving
+ the given NIC has been completed by all extensions.
+
+Arguments:
+ Switch - the Switch context
+
+ ExtensionContext - The extension context allocated in SxExtCreateSwitch
+ for the switch
+
+ SaveState - the save information
+
+Return Value:
+ VOID
+
+--*/
+VOID
+SxExtSaveNicComplete(
+ _In_ PSX_SWITCH_OBJECT Switch,
+ _In_ NDIS_HANDLE ExtensionContext,
+ _In_ PNDIS_SWITCH_NIC_SAVE_STATE SaveState
+ );
+
+
+/*++
+
+SxExtNicRestore
+
+Routine Description:
+ This function is called to restore previously saved data.
+
+Arguments:
+ Switch - the Switch context
+
+ ExtensionContext - The extension context allocated in SxExtCreateSwitch
+ for the switch
+
+ SaveState - the save information
+
+ BytesRestored - the number of bytes restored from the saved data
+
+Return Value:
+ NDIS_STATUS_SUCCESS - if this data belongs to this extension, and was
+ successfully restored (BytesRestored written)
+ OR
+ this data does not belong to this extension
+ (BytesRestored == 0)
+
+ NDIS_STATUS_*** - there was an error while attempting to restore
+ this data
+
+--*/
+NDIS_STATUS
+SxExtNicRestore(
+ _In_ PSX_SWITCH_OBJECT Switch,
+ _In_ NDIS_HANDLE ExtensionContext,
+ _In_ PNDIS_SWITCH_NIC_SAVE_STATE SaveState,
+ _Out_ PULONG BytesRestored
+ );
+
+
+/*++
+
+SxExtNicRestoreComplete
+
+Routine Description:
+ This function is called to signify the end of a restore operation.
+
+Arguments:
+ Switch - the Switch context
+
+ ExtensionContext - The extension context allocated in SxExtCreateSwitch
+ for the switch
+
+ SaveState - the save information
+
+Return Value:
+ VOID
+
+--*/
+VOID
+SxExtNicRestoreComplete(
+ _In_ PSX_SWITCH_OBJECT Switch,
+ _In_ NDIS_HANDLE ExtensionContext,
+ _In_ PNDIS_SWITCH_NIC_SAVE_STATE SaveState
+ );
+
+
+/*++
+
+SxExtAddSwitchProperty
+
+Routine Description:
+ This function is called to add a property on the given switch.
+
+Arguments:
+ Switch - the Switch context
+
+ ExtensionContext - The extension context allocated in SxExtCreateSwitch
+ for the switch
+
+ SwitchProperty - the property to be applied
+
+Return Value:
+ NDIS_STATUS_NOT_SUPPORTED - if the policy is not consumed by this extension
+
+ NDIS_STATUS_SUCCESS - if the policy is consumed by this extension, and
+ can successfully be enforced
+
+ STATUS_DATA_NOT_ACCEPTED - if the policy is consumed by this
+ extension, but cannot be enforced
+
+ NDIS_STATUS_*** - if the policy is consumed by this extension, and
+ setting the valid policy failed
+
+--*/
+NDIS_STATUS
+SxExtAddSwitchProperty(
+ _In_ PSX_SWITCH_OBJECT Switch,
+ _In_ NDIS_HANDLE ExtensionContext,
+ _In_ PNDIS_SWITCH_PROPERTY_PARAMETERS SwitchProperty
+ );
+
+
+/*++
+
+SxExtUpdateSwitchProperty
+
+Routine Description:
+ This function is called to update a property on the given switch.
+
+Arguments:
+ Switch - the Switch context
+
+ ExtensionContext - The extension context allocated in SxExtCreateSwitch
+ for the switch
+
+ SwitchProperty - the property to be updated
+
+Return Value:
+ NDIS_STATUS_NOT_SUPPORTED - if the policy is not consumed by this extension
+
+ NDIS_STATUS_SUCCESS - if the policy is consumed by this extension, and
+ can successfully be enforced
+
+ STATUS_DATA_NOT_ACCEPTED - if the policy is consumed by this
+ extension, but cannot be enforced
+
+ NDIS_STATUS_*** - if the policy is consumed by this extension, and
+ setting the valid policy failed
+
+--*/
+NDIS_STATUS
+SxExtUpdateSwitchProperty(
+ _In_ PSX_SWITCH_OBJECT Switch,
+ _In_ NDIS_HANDLE ExtensionContext,
+ _In_ PNDIS_SWITCH_PROPERTY_PARAMETERS SwitchProperty
+ );
+
+
+/*++
+
+SxExtDeleteSwitchProperty
+
+Routine Description:
+ This function is called to delete a property on the given switch.
+
+Arguments:
+ Switch - the Switch context
+
+ ExtensionContext - The extension context allocated in SxExtCreateSwitch
+ for the switch
+
+ SwitchProperty - the property to be deleted
+
+Return Value:
+ TRUE - if the policy belongs to this extension
+
+ FALSE - otherwise
+
+--*/
+BOOLEAN
+SxExtDeleteSwitchProperty(
+ _In_ PSX_SWITCH_OBJECT Switch,
+ _In_ NDIS_HANDLE ExtensionContext,
+ _In_ PNDIS_SWITCH_PROPERTY_DELETE_PARAMETERS SwitchProperty
+ );
+
+
+/*++
+
+SxExtAddPortProperty
+
+Routine Description:
+ This function is called to add a property on the given port,
+ on the given switch.
+
+Arguments:
+ Switch - the Switch context
+
+ ExtensionContext - The extension context allocated in SxExtCreateSwitch
+ for the switch
+
+ PortProperty - the property to be applied
+
+Return Value:
+ NDIS_STATUS_NOT_SUPPORTED - if the policy is not consumed by this extension
+
+ NDIS_STATUS_SUCCESS - if the policy is consumed by this extension, and
+ can successfully be enforced
+
+ STATUS_DATA_NOT_ACCEPTED - if the policy is consumed by this
+ extension, but cannot be enforced
+
+ NDIS_STATUS_*** - if the policy is consumed by this extension, and
+ setting the valid policy failed
+
+--*/
+NDIS_STATUS
+SxExtAddPortProperty(
+ _In_ PSX_SWITCH_OBJECT Switch,
+ _In_ NDIS_HANDLE ExtensionContext,
+ _In_ PNDIS_SWITCH_PORT_PROPERTY_PARAMETERS PortProperty
+ );
+
+
+/*++
+
+SxExtUpdatePortProperty
+
+Routine Description:
+ This function is called to update a property on the given port,
+ on the given switch.
+
+Arguments:
+ Switch - the Switch context
+
+ ExtensionContext - The extension context allocated in SxExtCreateSwitch
+ for the switch
+
+ PortProperty - the property to be applied
+
+Return Value:
+ NDIS_STATUS_NOT_SUPPORTED - if the policy is not consumed by this extension
+
+ NDIS_STATUS_SUCCESS - if the policy is consumed by this extension, and
+ can successfully be enforced
+
+ STATUS_DATA_NOT_ACCEPTED - if the policy is consumed by this
+ extension, but cannot be enforced
+
+ NDIS_STATUS_*** - if the policy is consumed by this extension, and
+ setting the valid policy failed
+
+--*/
+NDIS_STATUS
+SxExtUpdatePortProperty(
+ _In_ PSX_SWITCH_OBJECT Switch,
+ _In_ NDIS_HANDLE ExtensionContext,
+ _In_ PNDIS_SWITCH_PORT_PROPERTY_PARAMETERS PortProperty
+ );
+
+
+/*++
+
+SxExtDeletePortProperty
+
+Routine Description:
+ This function is called to delete a property on the given port,
+ on the given switch.
+
+Arguments:
+ Switch - the Switch context
+
+ ExtensionContext - The extension context allocated in SxExtCreateSwitch
+ for the switch
+
+ SwitchProperty - the property to be deleted
+
+Return Value:
+ TRUE - if the policy is not consumed by this extension
+
+ FALSE - otherwise
+
+--*/
+BOOLEAN
+SxExtDeletePortProperty(
+ _In_ PSX_SWITCH_OBJECT Switch,
+ _In_ NDIS_HANDLE ExtensionContext,
+ _In_ PNDIS_SWITCH_PORT_PROPERTY_DELETE_PARAMETERS PortProperty
+ );
+
+
+/*++
+
+SxExtQuerySwitchFeatureStatus
+
+Routine Description:
+ This function is called to query the status of a custom property
+ on the given switch.
+
+Arguments:
+ Switch - the Switch context
+
+ ExtensionContext - The extension context allocated in SxExtCreateSwitch
+ for the switch
+
+ SwitchFeatureStatus - the property buffer
+
+ BytesNeeded - if SwitchFeatureStatus is too small, this should be set
+ to the size buffer needed
+
+Return Value:
+ TRUE - return true if this property belongs to this extension, if
+ BytesNeeded > 0, the buffer will be reallocated and
+ this function will be called again
+
+ FALSE - otherwise
+
+--*/
+BOOLEAN
+SxExtQuerySwitchFeatureStatus(
+ _In_ PSX_SWITCH_OBJECT Switch,
+ _In_ NDIS_HANDLE ExtensionContext,
+ _Inout_ PNDIS_SWITCH_FEATURE_STATUS_PARAMETERS SwitchFeatureStatus,
+ _Inout_ PULONG BytesNeeded
+ );
+
+
+/*++
+
+SxExtQueryPortFeatureStatus
+
+Routine Description:
+ This function is called to query the status of a custom property
+ on the given port, on the given switch.
+
+Arguments:
+ Switch - the Switch context
+
+ ExtensionContext - The extension context allocated in SxExtCreateSwitch
+ for the switch
+
+ PortFeatureStatus - the property buffer
+
+ BytesNeeded - if PortFeatureStatus is too small, this should be set
+ to the size buffer needed
+
+Return Value:
+ TRUE - return true if this property belongs to this extension, if
+ BytesNeeded > 0, the buffer will be reallocated and
+ this function will be called again
+
+ FALSE - otherwise
+
+--*/
+BOOLEAN
+SxExtQueryPortFeatureStatus(
+ _In_ PSX_SWITCH_OBJECT Switch,
+ _In_ NDIS_HANDLE ExtensionContext,
+ _Inout_ PNDIS_SWITCH_PORT_FEATURE_STATUS_PARAMETERS PortFeatureStatus,
+ _Inout_ PULONG BytesNeeded
+ );
+
+
+/*++
+
+SxExtProcessNicRequest
+
+Routine Description:
+ This function is called upon the reciept of an OID_SWITCH_NIC_REQUEST
+ to the extension.
+ If an extension wishes to redirect the OID, it must return a valid
+ DestinationPortId and DestinationNicIndex, which it has taken a
+ reference on.
+ If an extension wishes to set source information, it must return
+ a valid SourcePortId and SourceNicIndex, which it has taken a
+ reference on.
+ The extension can change the OidRequest if it needs to.
+
+ !! This function should only be used by forwarding extensions. !!
+
+Arguments:
+ Switch - the Switch context
+
+ ExtensionContext - The extension context allocated in SxExtCreateSwitch
+ for the switch
+
+ OidRequest - the OID wrapped by the NIC request
+
+ SourcePortId - the source PortId to set
+
+ SourceNicIndex - the source NicIndex to set
+
+ DestinationPortId - the destination PortId to set
+
+ DestinationNicIndex - the destination NicIndex to set
+
+Return Value:
+ NDIS_STATUS_SUCCESS - sends OID
+
+ NDIS_STATUS_*** - complete OID with given status
+
+--*/
+NDIS_STATUS
+SxExtProcessNicRequest(
+ _In_ PSX_SWITCH_OBJECT Switch,
+ _In_ NDIS_HANDLE ExtensionContext,
+ _Inout_ PNDIS_OID_REQUEST OidRequest,
+ _Inout_ PNDIS_SWITCH_PORT_ID SourcePortId,
+ _Inout_ PNDIS_SWITCH_NIC_INDEX SourceNicIndex,
+ _Inout_ PNDIS_SWITCH_PORT_ID DestinationPortId,
+ _Inout_ PNDIS_SWITCH_NIC_INDEX DestinationNicIndex
+ );
+
+
+/*++
+
+SxExtProcessNicRequestComplete
+
+Routine Description:
+ This function is called upon the completion of an OID_SWITCH_NIC_REQUEST
+ that this extension has previously altered.
+ The extension must derefernce all NICs it had previously taken references
+ on.
+ If the OidRequest buffer was changed (along with underlying buffers),
+ the previous data must be replaced.
+
+Arguments:
+ Switch - the Switch context
+
+ ExtensionContext - The extension context allocated in SxExtCreateSwitch
+ for the switch
+
+ NicOidRequest - the OID buffer, encapsulated with source/destination info
+
+ Status - the status the OID completed with
+
+Return Value:
+ NDIS_STATUS - the status to complete the OID request with
+
+--*/
+NDIS_STATUS
+SxExtProcessNicRequestComplete(
+ _In_ PSX_SWITCH_OBJECT Switch,
+ _In_ NDIS_HANDLE ExtensionContext,
+ _Inout_ PNDIS_OID_REQUEST OidRequest,
+ _In_ NDIS_SWITCH_PORT_ID SourcePortId,
+ _In_ NDIS_SWITCH_NIC_INDEX SourceNicIndex,
+ _In_ NDIS_SWITCH_PORT_ID DestinationPortId,
+ _In_ NDIS_SWITCH_NIC_INDEX DestinationNicIndex,
+ _In_ NDIS_STATUS Status
+ );
+
+
+/*++
+
+SxExtProcessNicStatus
+
+Routine Description:
+ This function is called upon the reciept of an NDIS_STATUS_SWITCH_NIC_STATUS
+ to the extension.
+ If the extension wishes to modify the status indication, it should
+ send its own status indication using NdisFIndicateStatus and return a
+ failure status.
+ If the extension wishes to drop the status indiction, it should return
+ failure status, though this should be done very sparingly and carefully.
+
+ !! This function should only be used by forwarding extensions. !!
+
+Arguments:
+ Switch - the Switch context
+
+ ExtensionContext - The extension context allocated in SxExtCreateSwitch
+ for the switch
+
+ StatusIndication - the indication wrapped by the NIC status indication
+
+ SourcePortId - the source PortId of the indication
+
+ SourceNicIndex - the source NicIndex of the indication
+
+Return Value:
+ NDIS_STATUS_SUCCESS - return to continue forwarding this indication
+
+ NDIS_STATUS_*** - if the extension wants to modify the status
+ if modifying the status the extension should indicate
+ its own modified status using
+ SxLibIssueNicStatusIndicationUnsafe as soon as possible
+
+--*/
+NDIS_STATUS
+SxExtProcessNicStatus(
+ _In_ PSX_SWITCH_OBJECT Switch,
+ _In_ NDIS_HANDLE ExtensionContext,
+ _In_ PNDIS_STATUS_INDICATION StatusIndication,
+ _In_ NDIS_SWITCH_PORT_ID SourcePortId,
+ _In_ NDIS_SWITCH_NIC_INDEX SourceNicIndex
+ );
+
+
+/*++
+
+SxExtStartNetBufferListsIngress
+
+Routine Description:
+ This function is called upon the receipt on an NBL on ingress.
+ The extension should call SxLibSendNetBufferListsIngress to continue
+ the send of the NBL on ingress.
+ The extension should call SxLibCompleteNetBufferListsIngress to
+ drop the NBL.
+ This function may also be call from egress to inject an NBL.
+
+Arguments:
+ Switch - the Switch context
+
+ ExtensionContext - The extension context allocated in SxExtCreateSwitch
+ for the switch
+
+ NetBufferLists - the NBL to be sent
+
+ SendFlags - the send flags from NDIS, equivalent to NDIS send flags for
+ NdisFSendNetBufferLists
+
+Return Value:
+ VOID
+
+--*/
+VOID
+SxExtStartNetBufferListsIngress(
+ _In_ PSX_SWITCH_OBJECT Switch,
+ _In_ NDIS_HANDLE ExtensionContext,
+ _In_ PNET_BUFFER_LIST NetBufferLists,
+ _In_ ULONG SendFlags
+ );
+
+
+/*++
+
+SxExtStartNetBufferListsEgress
+
+Routine Description:
+ This function is called upon the receipt on an NBL on egress.
+ The extension should call SxLibSendNetBufferListsEgress to continue
+ the send of the NBL on egress.
+ The extension should call SxLibSendNetBufferListsEgressComplete to
+ drop the NBL.
+
+Arguments:
+ Switch - the Switch context
+
+ ExtensionContext - The extension context allocated in SxExtCreateSwitch
+ for the switch
+
+ NetBufferLists - the NBL to be sent
+
+ NumberOfNetBufferLists - the number of NBLs in NetBufferLists
+
+ ReceiveFlags - the receive flags from NDIS, equivalent to NDIS receive flags for
+ NdisFIndicateReceiveNetBufferLists
+
+Return Value:
+ VOID
+
+--*/
+VOID
+SxExtStartNetBufferListsEgress(
+ _In_ PSX_SWITCH_OBJECT Switch,
+ _In_ NDIS_HANDLE ExtensionContext,
+ _In_ PNET_BUFFER_LIST NetBufferLists,
+ _In_ ULONG NumberOfNetBufferLists,
+ _In_ ULONG ReceiveFlags
+ );
+
+
+/*++
+
+SxExtStartCompleteNetBufferListsEgress
+
+Routine Description:
+ This function is called upon the completion of an NBL on egress.
+ The extension must call SxLibCompleteNetBufferListsEgress
+ once it has finished processing the NBL.
+
+Arguments:
+ Switch - the Switch context
+
+ ExtensionContext - The extension context allocated in SxExtCreateSwitch
+ for the switch
+
+ NetBufferLists - the NBL being completed
+
+ ReturnFlags - the return flags from NDIS, equivalent to NDIS return flags for
+ NdisFReturnNetBufferLists
+
+Return Value:
+ VOID
+
+--*/
+VOID
+SxExtStartCompleteNetBufferListsEgress(
+ _In_ PSX_SWITCH_OBJECT Switch,
+ _In_ NDIS_HANDLE ExtensionContext,
+ _In_ PNET_BUFFER_LIST NetBufferLists,
+ _In_ ULONG ReturnFlags
+ );
+
+
+/*++
+
+SxExtStartCompleteNetBufferListsIngress
+
+Routine Description:
+ This function is called upon the completion of an NBL on ingress.
+ The extension must call SxLibCompleteNetBufferListsIngress
+ once it has finished processing the NBL.
+
+ If there are NBLs injected by this extension in NetBufferLists,
+ the extension must NOT call SxLibCompleteNetBufferListsIngress, and
+ instead call SxLibCompletedInjectedNetBufferLists with the number
+ of injected NBLs completed.
+
+Arguments:
+ Switch - the Switch context
+
+ ExtensionContext - The extension context allocated in SxExtCreateSwitch
+ for the switch
+
+ NetBufferLists - the NBL being completed
+
+ SendCompleteFlags - the send complete flags from NDIS, equivalent to
+ NDIS send complete flags for
+ NdisFSendNetBufferListsComplete
+
+Return Value:
+ VOID
+
+--*/
+VOID
+SxExtStartCompleteNetBufferListsIngress(
+ _In_ PSX_SWITCH_OBJECT Switch,
+ _In_ NDIS_HANDLE ExtensionContext,
+ _In_ PNET_BUFFER_LIST NetBufferLists,
+ _In_ ULONG SendCompleteFlags
+ );
+
diff --git a/datapath-windows/base/SxBase.c b/datapath-windows/base/SxBase.c
new file mode 100644
index 0000000..57fabd8
--- /dev/null
+++ b/datapath-windows/base/SxBase.c
@@ -0,0 +1,1395 @@
+/*++
+
+Copyright (c) Microsoft Corporation. All Rights Reserved.
+
+Module Name:
+
+ SxBase.c
+
+Abstract:
+
+ This file contains the common code for building a switch extension. This
+ file includes all the standard NDIS handling and exposes a function based
+ interface for the control path and data path. This also has reusable code
+ for basic operations such as pause/resume handling etc.
+
+
+--*/
+
+#include "precomp.h"
+
+ULONG SxDebugLevel;
+NDIS_HANDLE SxDriverHandle = NULL;
+NDIS_HANDLE SxDriverObject;
+NDIS_SPIN_LOCK SxExtensionListLock;
+LIST_ENTRY SxExtensionList;
+
+NDIS_STRING SxExtensionFriendlyName;
+NDIS_STRING SxExtensionGuid;
+
+NDIS_STATUS
+SxpNdisProcessSetOid(
+ __in PSX_SWITCH_OBJECT Switch,
+ __inout PNDIS_OID_REQUEST OidRequest,
+ __out PBOOLEAN Complete
+ );
+
+NDIS_STATUS
+SxpNdisProcessMethodOid(
+ __in PSX_SWITCH_OBJECT Switch,
+ __inout PNDIS_OID_REQUEST OidRequest,
+ __out PBOOLEAN Complete,
+ __out PULONG BytesNeeded
+ );
+
+
+//
+// DriverEntry
+// http://msdn.microsoft.com/en-us/library/ff544113(v=VS.85).aspx
+//
+_Use_decl_annotations_
+NTSTATUS
+DriverEntry(
+ PDRIVER_OBJECT DriverObject,
+ PUNICODE_STRING RegistryPath
+ )
+{
+ NDIS_STATUS status;
+ NDIS_FILTER_DRIVER_CHARACTERISTICS fChars;
+ NDIS_STRING serviceName;
+
+ UNREFERENCED_PARAMETER(RegistryPath);
+
+ //
+ // Initialize extension specific data.
+ //
+ status = SxExtInitialize();
+ if (status != NDIS_STATUS_SUCCESS)
+ {
+ goto Cleanup;
+ }
+
+ RtlInitUnicodeString(&serviceName, SxExtServiceName);
+ RtlInitUnicodeString(&SxExtensionFriendlyName, SxExtFriendlyName);
+ RtlInitUnicodeString(&SxExtensionGuid, SxExtUniqueName);
+ SxDriverObject = DriverObject;
+
+ NdisZeroMemory(&fChars, sizeof(NDIS_FILTER_DRIVER_CHARACTERISTICS));
+ fChars.Header.Type = NDIS_OBJECT_TYPE_FILTER_DRIVER_CHARACTERISTICS;
+ fChars.Header.Size = sizeof(NDIS_FILTER_DRIVER_CHARACTERISTICS);
+ fChars.Header.Revision = NDIS_FILTER_CHARACTERISTICS_REVISION_2;
+ fChars.MajorNdisVersion = SxExtMajorNdisVersion;
+ fChars.MinorNdisVersion = SxExtMinorNdisVersion;
+ fChars.MajorDriverVersion = 1;
+ fChars.MinorDriverVersion = 0;
+ fChars.Flags = 0;
+ fChars.FriendlyName = SxExtensionFriendlyName;
+ fChars.UniqueName = SxExtensionGuid;
+ fChars.ServiceName = serviceName;
+
+ fChars.SetOptionsHandler = SxNdisSetOptions;
+ fChars.SetFilterModuleOptionsHandler = SxNdisSetFilterModuleOptions;
+
+ fChars.AttachHandler = SxNdisAttach;
+ fChars.DetachHandler = SxNdisDetach;
+ fChars.PauseHandler = SxNdisPause;
+ fChars.RestartHandler = SxNdisRestart;
+
+ fChars.SendNetBufferListsHandler = SxNdisSendNetBufferLists;
+ fChars.SendNetBufferListsCompleteHandler = SxNdisSendNetBufferListsComplete;
+ fChars.CancelSendNetBufferListsHandler = SxNdisCancelSendNetBufferLists;
+ fChars.ReceiveNetBufferListsHandler = SxNdisReceiveNetBufferLists;
+ fChars.ReturnNetBufferListsHandler = SxNdisReturnNetBufferLists;
+
+ fChars.OidRequestHandler = SxNdisOidRequest;
+ fChars.OidRequestCompleteHandler = SxNdisOidRequestComplete;
+ fChars.CancelOidRequestHandler = SxNdisCancelOidRequest;
+
+ fChars.NetPnPEventHandler = SxNdisNetPnPEvent;
+ fChars.StatusHandler = SxNdisStatus;
+
+ NdisAllocateSpinLock(&SxExtensionListLock);
+ InitializeListHead(&SxExtensionList);
+
+ DriverObject->DriverUnload = SxNdisUnload;
+
+ status = NdisFRegisterFilterDriver(DriverObject,
+ (NDIS_HANDLE)SxDriverObject,
+ &fChars,
+ &SxDriverHandle);
+
+Cleanup:
+
+ if (status != NDIS_STATUS_SUCCESS)
+ {
+ if (SxDriverHandle != NULL)
+ {
+ NdisFDeregisterFilterDriver(SxDriverHandle);
+ SxDriverHandle = NULL;
+ }
+
+ NdisFreeSpinLock(&SxExtensionListLock);
+
+ SxExtUninitialize();
+ }
+
+ return status;
+}
+
+
+//
+// Unload Routine
+// http://msdn.microsoft.com/en-us/library/ff564886(v=VS.85).aspx
+//
+_Use_decl_annotations_
+VOID
+SxNdisUnload(
+ PDRIVER_OBJECT DriverObject
+ )
+{
+ UNREFERENCED_PARAMETER(DriverObject);
+
+ SxExtUninitialize();
+
+ NdisFDeregisterFilterDriver(SxDriverHandle);
+ NdisFreeSpinLock(&SxExtensionListLock);
+}
+
+
+//
+// FilterSetOptions Function
+// http://msdn.microsoft.com/en-us/library/ff549972(v=VS.85).aspx
+//
+_Use_decl_annotations_
+NDIS_STATUS
+SxNdisSetOptions(
+ NDIS_HANDLE NdisDriverHandle,
+ NDIS_HANDLE DriverContext
+ )
+{
+ UNREFERENCED_PARAMETER(NdisDriverHandle);
+ UNREFERENCED_PARAMETER(DriverContext);
+ return NDIS_STATUS_SUCCESS;
+}
+
+
+//
+// FilterSetModuleOptions Function
+// http://msdn.microsoft.com/en-us/library/ff549970(v=VS.85).aspx
+//
+_Use_decl_annotations_
+NDIS_STATUS
+SxNdisSetFilterModuleOptions(
+ NDIS_HANDLE FilterModuleContext
+ )
+{
+ UNREFERENCED_PARAMETER(FilterModuleContext);
+ return NDIS_STATUS_SUCCESS;
+}
+
+
+//
+// FilterAttach Function
+// http://msdn.microsoft.com/en-us/library/ff549905(v=VS.85).aspx
+//
+_Use_decl_annotations_
+NDIS_STATUS
+SxNdisAttach(
+ NDIS_HANDLE NdisFilterHandle,
+ NDIS_HANDLE SxDriverContext,
+ PNDIS_FILTER_ATTACH_PARAMETERS AttachParameters
+ )
+{
+ NDIS_STATUS status;
+ NDIS_FILTER_ATTRIBUTES sxAttributes;
+ ULONG switchObjectSize;
+ NDIS_SWITCH_CONTEXT switchContext;
+ NDIS_SWITCH_OPTIONAL_HANDLERS switchHandler;
+ PSX_SWITCH_OBJECT switchObject;
+
+ UNREFERENCED_PARAMETER(SxDriverContext);
+
+ DEBUGP(DL_TRACE, ("===>SxAttach: NdisFilterHandle %p\n", NdisFilterHandle));
+
+ status = NDIS_STATUS_SUCCESS;
+ switchObject = NULL;
+
+ NT_ASSERT(SxDriverContext == (NDIS_HANDLE)SxDriverObject);
+
+ if (AttachParameters->MiniportMediaType != NdisMedium802_3)
+ {
+ status = NDIS_STATUS_INVALID_PARAMETER;
+ goto Cleanup;
+ }
+
+ switchHandler.Header.Type = NDIS_OBJECT_TYPE_SWITCH_OPTIONAL_HANDLERS;
+ switchHandler.Header.Size = NDIS_SIZEOF_SWITCH_OPTIONAL_HANDLERS_REVISION_1;
+ switchHandler.Header.Revision = NDIS_SWITCH_OPTIONAL_HANDLERS_REVISION_1;
+
+ status = NdisFGetOptionalSwitchHandlers(NdisFilterHandle,
+ &switchContext,
+ &switchHandler);
+
+ if (status != NDIS_STATUS_SUCCESS)
+ {
+ DEBUGP(DL_ERROR,
+ ("SxAttach: Extension is running in non-switch environment.\n"));
+ goto Cleanup;
+ }
+
+ switchObjectSize = sizeof(SX_SWITCH_OBJECT);
+ switchObject = ExAllocatePoolWithTag(NonPagedPoolNx,
+ switchObjectSize,
+ SxExtAllocationTag);
+
+ if (switchObject == NULL)
+ {
+ status = NDIS_STATUS_RESOURCES;
+ goto Cleanup;
+ }
+
+ RtlZeroMemory(switchObject, switchObjectSize);
+
+ //
+ // Initialize NDIS related information.
+ //
+ switchObject->NdisFilterHandle = NdisFilterHandle;
+ switchObject->NdisSwitchContext = switchContext;
+ RtlCopyMemory(&switchObject->NdisSwitchHandlers,
+ &switchHandler,
+ sizeof(NDIS_SWITCH_OPTIONAL_HANDLERS));
+
+ //
+ // Let the extension create its own context.
+ //
+ status = SxExtCreateSwitch(switchObject,
+ &(switchObject->ExtensionContext));
+
+ if (status != NDIS_STATUS_SUCCESS)
+ {
+ goto Cleanup;
+ }
+
+ //
+ // Register the object with NDIS because NDIS passes this object when it
+ // calls into the driver.
+ //
+ NdisZeroMemory(&sxAttributes, sizeof(NDIS_FILTER_ATTRIBUTES));
+ sxAttributes.Header.Revision = NDIS_FILTER_ATTRIBUTES_REVISION_1;
+ sxAttributes.Header.Size = sizeof(NDIS_FILTER_ATTRIBUTES);
+ sxAttributes.Header.Type = NDIS_OBJECT_TYPE_FILTER_ATTRIBUTES;
+ sxAttributes.Flags = 0;
+
+ NDIS_DECLARE_FILTER_MODULE_CONTEXT(SX_SWITCH_OBJECT);
+ status = NdisFSetAttributes(NdisFilterHandle, switchObject, &sxAttributes);
+
+ if (status != NDIS_STATUS_SUCCESS)
+ {
+ DEBUGP(DL_ERROR, ("SxBase: Failed to set attributes.\n"));
+ goto Cleanup;
+ }
+
+ switchObject->ControlFlowState = SxSwitchAttached;
+ switchObject->DataFlowState = SxSwitchPaused;
+
+ NdisAcquireSpinLock(&SxExtensionListLock);
+ InsertHeadList(&SxExtensionList, &switchObject->Link);
+ NdisReleaseSpinLock(&SxExtensionListLock);
+
+Cleanup:
+
+ if (status != NDIS_STATUS_SUCCESS)
+ {
+ if (switchObject != NULL)
+ {
+ ExFreePool(switchObject);
+ }
+ }
+
+ DEBUGP(DL_TRACE, ("<===SxAttach: status %x\n", status));
+
+ return status;
+}
+
+
+//
+// FilterDetach Function
+// http://msdn.microsoft.com/en-us/library/ff549918(v=VS.85).aspx
+//
+_Use_decl_annotations_
+VOID
+SxNdisDetach(
+ NDIS_HANDLE FilterModuleContext
+ )
+{
+ PSX_SWITCH_OBJECT switchObject = (PSX_SWITCH_OBJECT)FilterModuleContext;
+
+ DEBUGP(DL_TRACE, ("===>SxDetach: SxInstance %p\n", FilterModuleContext));
+
+ //
+ // The extension must be in paused state.
+ //
+ NT_ASSERT(switchObject->DataFlowState == SxSwitchPaused);
+ switchObject->ControlFlowState = SxSwitchDetached;
+
+ KeMemoryBarrier();
+
+ while(switchObject->PendingOidCount > 0)
+ {
+ NdisMSleep(1000);
+ }
+
+ SxExtDeleteSwitch(switchObject, switchObject->ExtensionContext);
+
+ NdisAcquireSpinLock(&SxExtensionListLock);
+ RemoveEntryList(&switchObject->Link);
+ NdisReleaseSpinLock(&SxExtensionListLock);
+
+ ExFreePool(switchObject);
+
+ //
+ // Alway return success.
+ //
+ DEBUGP(DL_TRACE, ("<===SxDetach Successfully\n"));
+
+ return;
+}
+
+
+//
+// FilterRestart Function
+// http://msdn.microsoft.com/en-us/library/ff549962(v=VS.85).aspx
+//
+_Use_decl_annotations_
+NDIS_STATUS
+SxNdisPause(
+ NDIS_HANDLE FilterModuleContext,
+ PNDIS_FILTER_PAUSE_PARAMETERS PauseParameters
+ )
+{
+ PSX_SWITCH_OBJECT switchObject = (PSX_SWITCH_OBJECT)(FilterModuleContext);
+
+ UNREFERENCED_PARAMETER(PauseParameters);
+
+ DEBUGP(DL_TRACE,
+ ("===>NDISLWF SxPause: SxInstance %p\n", FilterModuleContext));
+
+ SxExtPauseSwitch(switchObject, switchObject->ExtensionContext);
+
+ //
+ // Set the flag that the filter is going to pause.
+ //
+ NT_ASSERT(switchObject->DataFlowState == SxSwitchRunning);
+ switchObject->DataFlowState = SxSwitchPaused;
+
+ KeMemoryBarrier();
+
+ while(switchObject->PendingInjectedNblCount > 0)
+ {
+ NdisMSleep(1000);
+ }
+
+ DEBUGP(DL_TRACE, ("<===SxPause: status %x\n", NDIS_STATUS_SUCCESS));
+
+ return NDIS_STATUS_SUCCESS;
+}
+
+
+//
+// FilterPause Function
+// http://msdn.microsoft.com/en-us/library/ff549957(v=VS.85).aspx
+//
+_Use_decl_annotations_
+NDIS_STATUS
+SxNdisRestart(
+ NDIS_HANDLE FilterModuleContext,
+ PNDIS_FILTER_RESTART_PARAMETERS RestartParameters
+ )
+{
+ PSX_SWITCH_OBJECT switchObject = (PSX_SWITCH_OBJECT)FilterModuleContext;
+ NDIS_STATUS status = NDIS_STATUS_SUCCESS;
+
+ UNREFERENCED_PARAMETER(RestartParameters);
+
+ DEBUGP(DL_TRACE,
+ ("===>SxRestart: FilterModuleContext %p\n", FilterModuleContext));
+
+ status = SxExtRestartSwitch(switchObject,
+ switchObject->ExtensionContext);
+ if (status != NDIS_STATUS_SUCCESS)
+ {
+ status = NDIS_STATUS_RESOURCES;
+ goto Cleanup;
+ }
+
+ NT_ASSERT(switchObject->DataFlowState == SxSwitchPaused);
+ switchObject->DataFlowState = SxSwitchRunning;
+
+ DEBUGP(DL_TRACE,
+ ("<===SxRestart: FilterModuleContext %p, status %x\n",
+ FilterModuleContext,
+ NDIS_STATUS_SUCCESS));
+
+Cleanup:
+ return status;
+}
+
+
+//
+// FilterOidRequest Function
+// http://msdn.microsoft.com/en-us/library/ff549954(v=VS.85).aspx
+//
+_Use_decl_annotations_
+NDIS_STATUS
+SxNdisOidRequest(
+ NDIS_HANDLE FilterModuleContext,
+ PNDIS_OID_REQUEST OidRequest
+ )
+{
+ PSX_SWITCH_OBJECT switchObject = (PSX_SWITCH_OBJECT)FilterModuleContext;
+ NDIS_STATUS status;
+ PNDIS_OID_REQUEST clonedRequest=NULL;
+ PVOID *cloneRequestContext;
+ BOOLEAN completeOid = FALSE;
+ ULONG bytesNeeded = 0;
+
+ status = NDIS_STATUS_SUCCESS;
+
+ DEBUGP(DL_TRACE, ("===>SxOidRequest: OidRequest %p.\n", OidRequest));
+
+ NdisInterlockedIncrement(&switchObject->PendingOidCount);
+
+ status = NdisAllocateCloneOidRequest(switchObject->NdisFilterHandle,
+ OidRequest,
+ SxExtAllocationTag,
+ &clonedRequest);
+ if (status != NDIS_STATUS_SUCCESS)
+ {
+ DEBUGP(DL_WARN, ("FilerOidRequest: Cannot Clone OidRequest\n"));
+ goto Cleanup;
+ }
+
+ cloneRequestContext = (PVOID*)(&clonedRequest->SourceReserved[0]);
+ *cloneRequestContext = OidRequest;
+
+ switch (clonedRequest->RequestType)
+ {
+ case NdisRequestSetInformation:
+ status = SxpNdisProcessSetOid(switchObject,
+ clonedRequest,
+ &completeOid);
+ break;
+
+ case NdisRequestMethod:
+ status = SxpNdisProcessMethodOid(switchObject,
+ clonedRequest,
+ &completeOid,
+ &bytesNeeded);
+
+ break;
+ }
+
+ if (completeOid)
+ {
+ NdisFreeCloneOidRequest(switchObject->NdisFilterHandle, clonedRequest);
+ OidRequest->DATA.METHOD_INFORMATION.BytesNeeded = bytesNeeded;
+ NdisInterlockedDecrement(&switchObject->PendingOidCount);
+ goto Cleanup;
+ }
+
+ status = NdisFOidRequest(switchObject->NdisFilterHandle, clonedRequest);
+
+ if (status != NDIS_STATUS_PENDING)
+ {
+ SxNdisOidRequestComplete(switchObject, clonedRequest, status);
+
+ //
+ // We must still return status as pending because we complete the
+ // request using NdisFOidRequestComplete() in SxOidRequestComplete().
+ //
+ status = NDIS_STATUS_PENDING;
+ }
+
+Cleanup:
+
+ DEBUGP(DL_TRACE, ("<===SxOidRequest: status %8x.\n", status));
+ return status;
+}
+
+
+//
+// FilterCancelOidRequest Function
+// http://msdn.microsoft.com/en-us/library/ff549911(v=VS.85).aspx
+//
+_Use_decl_annotations_
+VOID
+SxNdisCancelOidRequest(
+ NDIS_HANDLE FilterModuleContext,
+ PVOID RequestId
+ )
+{
+ UNREFERENCED_PARAMETER(FilterModuleContext);
+ UNREFERENCED_PARAMETER(RequestId);
+}
+
+
+//
+// FilterOidRequestComplete Function
+// http://msdn.microsoft.com/en-us/library/ff549956(v=VS.85).aspx
+//
+_Use_decl_annotations_
+VOID
+SxNdisOidRequestComplete(
+ NDIS_HANDLE FilterModuleContext,
+ PNDIS_OID_REQUEST NdisOidRequest,
+ NDIS_STATUS Status
+ )
+{
+ PSX_SWITCH_OBJECT switchObject = (PSX_SWITCH_OBJECT)FilterModuleContext;
+ PNDIS_OID_REQUEST originalRequest;
+ PVOID *oidRequestContext;
+ PNDIS_SWITCH_NIC_OID_REQUEST nicOidRequestBuf;
+ PNDIS_OBJECT_HEADER header;
+
+ DEBUGP(DL_TRACE,
+ ("===>SxOidRequestComplete, NdisOidRequest %p.\n", NdisOidRequest));
+
+ oidRequestContext = (PVOID*)(&NdisOidRequest->SourceReserved[0]);
+ originalRequest = (*oidRequestContext);
+
+ //
+ // This is the internal request
+ //
+ if (originalRequest == NULL)
+ {
+ SxpNdisCompleteInternalOidRequest(switchObject, NdisOidRequest, Status);
+ goto Cleanup;
+ }
+
+ //
+ // Copy the information from the returned request to the original request
+ //
+ switch(NdisOidRequest->RequestType)
+ {
+ case NdisRequestMethod:
+ originalRequest->DATA.METHOD_INFORMATION.OutputBufferLength =
+ NdisOidRequest->DATA.METHOD_INFORMATION.OutputBufferLength;
+ originalRequest->DATA.METHOD_INFORMATION.BytesRead =
+ NdisOidRequest->DATA.METHOD_INFORMATION.BytesRead;
+ originalRequest->DATA.METHOD_INFORMATION.BytesNeeded =
+ NdisOidRequest->DATA.METHOD_INFORMATION.BytesNeeded;
+ originalRequest->DATA.METHOD_INFORMATION.BytesWritten =
+ NdisOidRequest->DATA.METHOD_INFORMATION.BytesWritten;
+
+ if (NdisOidRequest->DATA.METHOD_INFORMATION.Oid == OID_SWITCH_NIC_REQUEST &&
+ switchObject->OldNicRequest != NULL)
+ {
+ nicOidRequestBuf = NdisOidRequest->DATA.METHOD_INFORMATION.InformationBuffer;
+ Status = SxExtProcessNicRequestComplete(switchObject,
+ switchObject->ExtensionContext,
+ nicOidRequestBuf->OidRequest,
+ nicOidRequestBuf->SourcePortId,
+ nicOidRequestBuf->SourceNicIndex,
+ nicOidRequestBuf->DestinationPortId,
+ nicOidRequestBuf->DestinationNicIndex,
+ Status);
+
+ originalRequest->DATA.METHOD_INFORMATION.InformationBuffer =
+ switchObject->OldNicRequest;
+ switchObject->OldNicRequest = NULL;
+ ExFreePoolWithTag(nicOidRequestBuf, SxExtAllocationTag);
+ }
+
+ break;
+
+ case NdisRequestSetInformation:
+ header = originalRequest->DATA.SET_INFORMATION.InformationBuffer;
+
+ originalRequest->DATA.SET_INFORMATION.BytesRead =
+ NdisOidRequest->DATA.SET_INFORMATION.BytesRead;
+ originalRequest->DATA.SET_INFORMATION.BytesNeeded =
+ NdisOidRequest->DATA.SET_INFORMATION.BytesNeeded;
+
+ if (NdisOidRequest->DATA.METHOD_INFORMATION.Oid == OID_SWITCH_PORT_CREATE &&
+ Status != NDIS_STATUS_SUCCESS)
+ {
+ SxExtDeletePort(switchObject,
+ switchObject->ExtensionContext,
+ (PNDIS_SWITCH_PORT_PARAMETERS)header);
+ }
+ else if (NdisOidRequest->DATA.METHOD_INFORMATION.Oid == OID_SWITCH_PORT_CREATE &&
+ Status != NDIS_STATUS_SUCCESS)
+ {
+ SxExtDeleteNic(switchObject,
+ switchObject->ExtensionContext,
+ (PNDIS_SWITCH_NIC_PARAMETERS)header);
+
+ }
+
+ break;
+
+ case NdisRequestQueryInformation:
+ case NdisRequestQueryStatistics:
+ default:
+ originalRequest->DATA.QUERY_INFORMATION.BytesWritten =
+ NdisOidRequest->DATA.QUERY_INFORMATION.BytesWritten;
+ originalRequest->DATA.QUERY_INFORMATION.BytesNeeded =
+ NdisOidRequest->DATA.QUERY_INFORMATION.BytesNeeded;
+ break;
+ }
+
+ (*oidRequestContext) = NULL;
+
+ NdisFreeCloneOidRequest(switchObject->NdisFilterHandle, NdisOidRequest);
+
+ NdisFOidRequestComplete(switchObject->NdisFilterHandle,
+ originalRequest,
+ Status);
+
+ DEBUGP(DL_TRACE, ("<===SxOidRequestComplete.\n"));
+
+Cleanup:
+ NdisInterlockedDecrement(&switchObject->PendingOidCount);
+}
+
+
+//
+// FilterSendNetBufferLists Function
+// http://msdn.microsoft.com/en-us/library/ff549966(v=VS.85).aspx
+//
+_Use_decl_annotations_
+VOID
+SxNdisSendNetBufferLists(
+ NDIS_HANDLE FilterModuleContext,
+ PNET_BUFFER_LIST NetBufferLists,
+ NDIS_PORT_NUMBER PortNumber,
+ ULONG SendFlags
+ )
+{
+ PSX_SWITCH_OBJECT switchObject = (PSX_SWITCH_OBJECT)FilterModuleContext;
+
+ UNREFERENCED_PARAMETER(PortNumber);
+
+ SxExtStartNetBufferListsIngress(switchObject,
+ switchObject->ExtensionContext,
+ NetBufferLists,
+ SendFlags);
+}
+
+
+//
+// FilterSendNetBufferListsComplete Function
+// http://msdn.microsoft.com/en-us/library/ff549967(v=VS.85).aspx
+//
+_Use_decl_annotations_
+VOID
+SxNdisSendNetBufferListsComplete(
+ NDIS_HANDLE FilterModuleContext,
+ PNET_BUFFER_LIST NetBufferLists,
+ ULONG SendCompleteFlags
+ )
+{
+ PSX_SWITCH_OBJECT switchObject = (PSX_SWITCH_OBJECT)FilterModuleContext;
+
+ SxExtStartCompleteNetBufferListsIngress(switchObject,
+ switchObject->ExtensionContext,
+ NetBufferLists,
+ SendCompleteFlags);
+}
+
+
+//
+// FilterReceiveNetBufferLists Function
+// http://msdn.microsoft.com/en-us/library/ff549960(v=VS.85).aspx
+//
+_Use_decl_annotations_
+VOID
+SxNdisReceiveNetBufferLists(
+ NDIS_HANDLE FilterModuleContext,
+ PNET_BUFFER_LIST NetBufferLists,
+ NDIS_PORT_NUMBER PortNumber,
+ ULONG NumberOfNetBufferLists,
+ ULONG ReceiveFlags
+ )
+{
+ PSX_SWITCH_OBJECT switchObject = (PSX_SWITCH_OBJECT)FilterModuleContext;
+
+ UNREFERENCED_PARAMETER(PortNumber);
+
+ SxExtStartNetBufferListsEgress(switchObject,
+ switchObject->ExtensionContext,
+ NetBufferLists,
+ NumberOfNetBufferLists,
+ ReceiveFlags);
+}
+
+
+//
+// FilterReturnNetBufferLists Function
+// http://msdn.microsoft.com/en-us/library/ff549964(v=VS.85).aspx
+//
+_Use_decl_annotations_
+VOID
+SxNdisReturnNetBufferLists(
+ NDIS_HANDLE FilterModuleContext,
+ PNET_BUFFER_LIST NetBufferLists,
+ ULONG ReturnFlags
+ )
+{
+ PSX_SWITCH_OBJECT switchObject = (PSX_SWITCH_OBJECT)FilterModuleContext;
+
+ SxExtStartCompleteNetBufferListsEgress(switchObject,
+ switchObject->ExtensionContext,
+ NetBufferLists,
+ ReturnFlags);
+}
+
+
+//
+// FilterCancelSendNetBufferLists Function
+// http://msdn.microsoft.com/en-us/library/ff549915(v=VS.85).aspx
+//
+_Use_decl_annotations_
+VOID
+SxNdisCancelSendNetBufferLists(
+ NDIS_HANDLE FilterModuleContext,
+ PVOID CancelId
+ )
+{
+ UNREFERENCED_PARAMETER(FilterModuleContext);
+ UNREFERENCED_PARAMETER(CancelId);
+}
+
+
+//
+// FilterNetPnPEvent Function
+// http://msdn.microsoft.com/en-us/library/ff549952(v=vs.85).aspx
+//
+_Use_decl_annotations_
+NDIS_STATUS
+SxNdisNetPnPEvent(
+ NDIS_HANDLE FilterModuleContext,
+ PNET_PNP_EVENT_NOTIFICATION NetPnPEvent
+ )
+{
+ PSX_SWITCH_OBJECT switchObject = (PSX_SWITCH_OBJECT)FilterModuleContext;
+
+ if (NetPnPEvent->NetPnPEvent.NetEvent == NetEventSwitchActivate)
+ {
+ //
+ // Switch Activation must be passed along regardless of successful
+ // initialization.
+ //
+ SxExtActivateSwitch(switchObject,
+ switchObject->ExtensionContext);
+ }
+
+ return NdisFNetPnPEvent(switchObject->NdisFilterHandle,
+ NetPnPEvent);
+}
+
+
+//
+// FilterStatus Function
+// http://msdn.microsoft.com/en-us/library/ff549973(v=VS.85).aspx
+//
+_Use_decl_annotations_
+VOID
+SxNdisStatus(
+ NDIS_HANDLE FilterModuleContext,
+ PNDIS_STATUS_INDICATION StatusIndication
+ )
+{
+ NDIS_STATUS status = NDIS_STATUS_SUCCESS;
+ PSX_SWITCH_OBJECT switchObject = (PSX_SWITCH_OBJECT)FilterModuleContext;
+ PNDIS_SWITCH_NIC_STATUS_INDICATION nicIndication;
+ PNDIS_STATUS_INDICATION originalIndication;
+
+ if (StatusIndication->Header.Type != NDIS_OBJECT_TYPE_STATUS_INDICATION ||
+ StatusIndication->Header.Revision != NDIS_STATUS_INDICATION_REVISION_1 ||
+ StatusIndication->Header.Size < NDIS_SIZEOF_STATUS_INDICATION_REVISION_1)
+ {
+ goto Cleanup;
+ }
+
+ //
+ // Only NDIS_STATUS_SWITCH_NIC_STAUTUS indications need to be processed
+ // by switch extensions.
+ //
+ if (StatusIndication->StatusCode != NDIS_STATUS_SWITCH_NIC_STATUS)
+ {
+ goto Cleanup;
+ }
+
+ nicIndication = StatusIndication->StatusBuffer;
+
+ if (nicIndication->Header.Type != NDIS_OBJECT_TYPE_STATUS_INDICATION ||
+ nicIndication->Header.Revision != NDIS_SWITCH_NIC_STATUS_INDICATION_REVISION_1 ||
+ nicIndication->Header.Size < NDIS_SIZEOF_SWITCH_NIC_STATUS_REVISION_1)
+ {
+ goto Cleanup;
+ }
+
+ originalIndication = nicIndication->StatusIndication;
+
+ status = SxExtProcessNicStatus(switchObject,
+ switchObject->ExtensionContext,
+ originalIndication,
+ nicIndication->SourcePortId,
+ nicIndication->SourceNicIndex);
+
+Cleanup:
+ if (status == NDIS_STATUS_SUCCESS)
+ {
+ NdisFIndicateStatus(switchObject->NdisFilterHandle,
+ StatusIndication);
+ }
+
+ return;
+
+}
+
+
+NDIS_STATUS
+SxpNdisProcessSetOid(
+ __in PSX_SWITCH_OBJECT Switch,
+ __inout PNDIS_OID_REQUEST OidRequest,
+ __out PBOOLEAN Complete
+ )
+{
+ NDIS_STATUS status = NDIS_STATUS_SUCCESS;
+ NDIS_OID oid = OidRequest->DATA.SET_INFORMATION.Oid;
+ PNDIS_OBJECT_HEADER header;
+ ULONG bytesRestored = 0;
+
+ *Complete = FALSE;
+
+ header = OidRequest->DATA.SET_INFORMATION.InformationBuffer;
+
+ if (OidRequest->DATA.SET_INFORMATION.InformationBufferLength != 0 &&
+ OidRequest->DATA.SET_INFORMATION.InformationBufferLength <
+ sizeof(NDIS_OBJECT_HEADER))
+ {
+ status = NDIS_STATUS_NOT_SUPPORTED;
+ *Complete = TRUE;
+ goto Cleanup;
+ }
+
+ if (OidRequest->DATA.SET_INFORMATION.InformationBufferLength == 0)
+ {
+ *Complete = FALSE;
+ goto Cleanup;
+ }
+
+ switch(oid)
+ {
+ case OID_SWITCH_PROPERTY_ADD:
+ case OID_SWITCH_PROPERTY_UPDATE:
+ if (header->Type != NDIS_OBJECT_TYPE_DEFAULT ||
+ header->Revision < NDIS_SWITCH_PROPERTY_PARAMETERS_REVISION_1 ||
+ header->Size < NDIS_SIZEOF_NDIS_SWITCH_PROPERTY_PARAMETERS_REVISION_1)
+ {
+ status = NDIS_STATUS_NOT_SUPPORTED;
+ *Complete = TRUE;
+ goto Cleanup;
+ }
+
+ if (oid == OID_SWITCH_PROPERTY_ADD)
+ {
+ status = SxExtAddSwitchProperty(Switch,
+ Switch->ExtensionContext,
+ (PNDIS_SWITCH_PROPERTY_PARAMETERS)header);
+ }
+ else
+ {
+ status = SxExtUpdateSwitchProperty(Switch,
+ Switch->ExtensionContext,
+ (PNDIS_SWITCH_PROPERTY_PARAMETERS)header);
+ }
+
+ if (status == NDIS_STATUS_NOT_SUPPORTED)
+ {
+ status = NDIS_STATUS_SUCCESS;
+ }
+ else
+ {
+ *Complete = TRUE;
+ goto Cleanup;
+ }
+
+ break;
+ case OID_SWITCH_PROPERTY_DELETE:
+ if (header->Type != NDIS_OBJECT_TYPE_DEFAULT ||
+ header->Revision < NDIS_SWITCH_PROPERTY_DELETE_PARAMETERS_REVISION_1 ||
+ header->Size < NDIS_SIZEOF_NDIS_SWITCH_PROPERTY_DELETE_PARAMETERS_REVISION_1)
+ {
+ status = NDIS_STATUS_NOT_SUPPORTED;
+ *Complete = TRUE;
+ goto Cleanup;
+ }
+
+ *Complete = SxExtDeleteSwitchProperty(Switch,
+ Switch->ExtensionContext,
+ (PNDIS_SWITCH_PROPERTY_DELETE_PARAMETERS)header);
+
+ break;
+
+ case OID_SWITCH_PORT_PROPERTY_ADD:
+ case OID_SWITCH_PORT_PROPERTY_UPDATE:
+ if (header->Type != NDIS_OBJECT_TYPE_DEFAULT ||
+ header->Revision < NDIS_SWITCH_PORT_PROPERTY_PARAMETERS_REVISION_1 ||
+ header->Size < NDIS_SIZEOF_NDIS_SWITCH_PORT_PROPERTY_PARAMETERS_REVISION_1)
+ {
+ status = NDIS_STATUS_NOT_SUPPORTED;
+ *Complete = TRUE;
+ goto Cleanup;
+ }
+
+ if (oid == OID_SWITCH_PORT_PROPERTY_ADD)
+ {
+ status = SxExtAddPortProperty(Switch,
+ Switch->ExtensionContext,
+ (PNDIS_SWITCH_PORT_PROPERTY_PARAMETERS)header);
+ }
+ else
+ {
+ status = SxExtUpdatePortProperty(Switch,
+ Switch->ExtensionContext,
+ (PNDIS_SWITCH_PORT_PROPERTY_PARAMETERS)header);
+ }
+
+ if (status == NDIS_STATUS_NOT_SUPPORTED)
+ {
+ status = NDIS_STATUS_SUCCESS;
+ }
+ else
+ {
+ *Complete = TRUE;
+ goto Cleanup;
+ }
+
+ break;
+
+ case OID_SWITCH_PORT_PROPERTY_DELETE:
+ if (header->Type != NDIS_OBJECT_TYPE_DEFAULT ||
+ header->Revision < NDIS_SWITCH_PORT_PROPERTY_DELETE_PARAMETERS_REVISION_1 ||
+ header->Size < NDIS_SIZEOF_NDIS_SWITCH_PORT_PROPERTY_DELETE_PARAMETERS_REVISION_1)
+ {
+ status = NDIS_STATUS_NOT_SUPPORTED;
+ *Complete = TRUE;
+ goto Cleanup;
+ }
+
+ *Complete = SxExtDeletePortProperty(Switch,
+ Switch->ExtensionContext,
+ (PNDIS_SWITCH_PORT_PROPERTY_DELETE_PARAMETERS)header);
+
+ break;
+
+ case OID_SWITCH_PORT_CREATE:
+ case OID_SWITCH_PORT_UPDATED:
+ case OID_SWITCH_PORT_TEARDOWN:
+ case OID_SWITCH_PORT_DELETE:
+ if (header->Type != NDIS_OBJECT_TYPE_DEFAULT ||
+ header->Revision < NDIS_SWITCH_PORT_PARAMETERS_REVISION_1 ||
+ header->Size < NDIS_SIZEOF_NDIS_SWITCH_PORT_PARAMETERS_REVISION_1)
+ {
+ status = NDIS_STATUS_NOT_SUPPORTED;
+ *Complete = TRUE;
+ goto Cleanup;
+ }
+
+ if (oid == OID_SWITCH_PORT_CREATE)
+ {
+ status = SxExtCreatePort(Switch,
+ Switch->ExtensionContext,
+ (PNDIS_SWITCH_PORT_PARAMETERS)header);
+
+ if (status != NDIS_STATUS_SUCCESS)
+ {
+ *Complete = TRUE;
+ }
+ }
+ else if (oid == OID_SWITCH_PORT_UPDATED)
+ {
+ SxExtUpdatePort(Switch,
+ Switch->ExtensionContext,
+ (PNDIS_SWITCH_PORT_PARAMETERS)header);
+ }
+ else if (oid == OID_SWITCH_PORT_TEARDOWN)
+ {
+ SxExtTeardownPort(Switch,
+ Switch->ExtensionContext,
+ (PNDIS_SWITCH_PORT_PARAMETERS)header);
+ }
+ else
+ {
+ SxExtDeletePort(Switch,
+ Switch->ExtensionContext,
+ (PNDIS_SWITCH_PORT_PARAMETERS)header);
+ }
+
+ break;
+
+ case OID_SWITCH_NIC_CREATE:
+ case OID_SWITCH_NIC_CONNECT:
+ case OID_SWITCH_NIC_UPDATED:
+ case OID_SWITCH_NIC_DISCONNECT:
+ case OID_SWITCH_NIC_DELETE:
+ if (header->Type != NDIS_OBJECT_TYPE_DEFAULT ||
+ header->Revision < NDIS_SWITCH_NIC_PARAMETERS_REVISION_1 ||
+ header->Size < NDIS_SIZEOF_NDIS_SWITCH_NIC_PARAMETERS_REVISION_1)
+ {
+ status = NDIS_STATUS_NOT_SUPPORTED;
+ *Complete = TRUE;
+ goto Cleanup;
+ }
+
+ if (oid == OID_SWITCH_NIC_CREATE)
+ {
+ status = SxExtCreateNic(Switch,
+ Switch->ExtensionContext,
+ (PNDIS_SWITCH_NIC_PARAMETERS)header);
+ if (status != NDIS_STATUS_SUCCESS)
+ {
+ *Complete = TRUE;
+ }
+ }
+ else if (oid == OID_SWITCH_NIC_CONNECT)
+ {
+ SxExtConnectNic(Switch,
+ Switch->ExtensionContext,
+ (PNDIS_SWITCH_NIC_PARAMETERS)header);
+ }
+ else if (oid == OID_SWITCH_NIC_UPDATED)
+ {
+ SxExtUpdateNic(Switch,
+ Switch->ExtensionContext,
+ (PNDIS_SWITCH_NIC_PARAMETERS)header);
+ }
+ else if (oid == OID_SWITCH_NIC_DISCONNECT)
+ {
+ SxExtDisconnectNic(Switch,
+ Switch->ExtensionContext,
+ (PNDIS_SWITCH_NIC_PARAMETERS)header);
+ }
+ else
+ {
+ SxExtDeleteNic(Switch,
+ Switch->ExtensionContext,
+ (PNDIS_SWITCH_NIC_PARAMETERS)header);
+ }
+
+ break;
+
+ case OID_SWITCH_NIC_RESTORE:
+ if (header->Type != NDIS_OBJECT_TYPE_DEFAULT ||
+ header->Revision < NDIS_SWITCH_NIC_SAVE_STATE_REVISION_1 ||
+ header->Size < NDIS_SIZEOF_NDIS_SWITCH_NIC_SAVE_STATE_REVISION_1)
+ {
+ status = NDIS_STATUS_NOT_SUPPORTED;
+ goto Cleanup;
+ }
+
+ status = SxExtNicRestore(Switch,
+ Switch->ExtensionContext,
+ (PNDIS_SWITCH_NIC_SAVE_STATE)header,
+ &bytesRestored);
+
+ if (status != NDIS_STATUS_SUCCESS)
+ {
+ *Complete = TRUE;
+ }
+ else if (bytesRestored > 0)
+ {
+ *Complete = TRUE;
+ }
+
+ break;
+
+ case OID_SWITCH_NIC_SAVE_COMPLETE:
+ if (header->Type != NDIS_OBJECT_TYPE_DEFAULT ||
+ header->Revision < NDIS_SWITCH_NIC_SAVE_STATE_REVISION_1 ||
+ header->Size < NDIS_SIZEOF_NDIS_SWITCH_NIC_SAVE_STATE_REVISION_1)
+ {
+ status = NDIS_STATUS_NOT_SUPPORTED;
+ *Complete = TRUE;
+ goto Cleanup;
+ }
+
+ SxExtSaveNicComplete(Switch,
+ Switch->ExtensionContext,
+ (PNDIS_SWITCH_NIC_SAVE_STATE)header);
+
+ break;
+
+ case OID_SWITCH_NIC_RESTORE_COMPLETE:
+ if (header->Type != NDIS_OBJECT_TYPE_DEFAULT ||
+ header->Revision < NDIS_SWITCH_NIC_SAVE_STATE_REVISION_1 ||
+ header->Size < NDIS_SIZEOF_NDIS_SWITCH_NIC_SAVE_STATE_REVISION_1)
+ {
+ status = NDIS_STATUS_NOT_SUPPORTED;
+ *Complete = TRUE;
+ goto Cleanup;
+ }
+
+ SxExtNicRestoreComplete(Switch,
+ Switch->ExtensionContext,
+ (PNDIS_SWITCH_NIC_SAVE_STATE)header);
+
+ break;
+
+ default:
+ break;
+ }
+
+Cleanup:
+ return status;
+}
+
+
+NDIS_STATUS
+SxpNdisProcessMethodOid(
+ __in PSX_SWITCH_OBJECT Switch,
+ __inout PNDIS_OID_REQUEST OidRequest,
+ __out PBOOLEAN Complete,
+ __out PULONG BytesNeeded
+ )
+{
+ NDIS_STATUS status = NDIS_STATUS_SUCCESS;
+ NDIS_OID oid = OidRequest->DATA.SET_INFORMATION.Oid;
+ PNDIS_OBJECT_HEADER header;
+ PNDIS_SWITCH_NIC_OID_REQUEST nicOidRequest;
+ PNDIS_SWITCH_NIC_OID_REQUEST newNicOidRequest = NULL;
+ NDIS_SWITCH_PORT_ID destPort, sourcePort;
+ NDIS_SWITCH_NIC_INDEX destNic, sourceNic;
+ ULONG bytesWritten = 0;
+ ULONG bytesNeeded = 0;
+
+ *Complete = FALSE;
+ *BytesNeeded = 0;
+
+ header = OidRequest->DATA.METHOD_INFORMATION.InformationBuffer;
+
+ switch(oid)
+ {
+ case OID_SWITCH_FEATURE_STATUS_QUERY:
+ if (header->Type != NDIS_OBJECT_TYPE_DEFAULT ||
+ header->Revision < NDIS_SWITCH_FEATURE_STATUS_PARAMETERS_REVISION_1 ||
+ header->Size < NDIS_SIZEOF_NDIS_SWITCH_FEATURE_STATUS_PARAMETERS_REVISION_1)
+ {
+ status = NDIS_STATUS_NOT_SUPPORTED;
+ *Complete = TRUE;
+ goto Cleanup;
+ }
+
+ *Complete = SxExtQuerySwitchFeatureStatus(Switch,
+ Switch->ExtensionContext,
+ (PNDIS_SWITCH_FEATURE_STATUS_PARAMETERS)header,
+ BytesNeeded);
+
+ if (*BytesNeeded > 0)
+ {
+ status = NDIS_STATUS_BUFFER_TOO_SHORT;
+ }
+
+ break;
+
+ case OID_SWITCH_PORT_FEATURE_STATUS_QUERY:
+ if (header->Type != NDIS_OBJECT_TYPE_DEFAULT ||
+ header->Revision < NDIS_SWITCH_FEATURE_STATUS_PARAMETERS_REVISION_1 ||
+ header->Size < NDIS_SIZEOF_NDIS_SWITCH_FEATURE_STATUS_PARAMETERS_REVISION_1)
+ {
+ status = NDIS_STATUS_NOT_SUPPORTED;
+ *Complete = TRUE;
+ goto Cleanup;
+ }
+
+ *Complete = SxExtQueryPortFeatureStatus(Switch,
+ Switch->ExtensionContext,
+ (PNDIS_SWITCH_PORT_FEATURE_STATUS_PARAMETERS)header,
+ BytesNeeded);
+
+ if (*BytesNeeded > 0)
+ {
+ status = NDIS_STATUS_BUFFER_TOO_SHORT;
+ }
+
+ break;
+
+ case OID_SWITCH_NIC_REQUEST:
+ if (header->Type != NDIS_OBJECT_TYPE_DEFAULT ||
+ header->Revision < NDIS_SWITCH_NIC_OID_REQUEST_REVISION_1 ||
+ header->Size < NDIS_SIZEOF_NDIS_SWITCH_NIC_OID_REQUEST_REVISION_1)
+ {
+ status = NDIS_STATUS_NOT_SUPPORTED;
+ *Complete = TRUE;
+ goto Cleanup;
+ }
+
+ nicOidRequest = (PNDIS_SWITCH_NIC_OID_REQUEST)header;
+
+ sourcePort = nicOidRequest->SourcePortId;
+ sourceNic = nicOidRequest->SourceNicIndex;
+ destPort = nicOidRequest->DestinationPortId;
+ destNic = nicOidRequest->DestinationNicIndex;
+
+ status = SxExtProcessNicRequest(Switch,
+ Switch->ExtensionContext,
+ nicOidRequest->OidRequest,
+ &sourcePort,
+ &sourceNic,
+ &destPort,
+ &destNic);
+
+ if (status != NDIS_STATUS_SUCCESS)
+ {
+ *Complete = TRUE;
+ goto Cleanup;
+ }
+
+ if (sourcePort != nicOidRequest->SourcePortId ||
+ sourceNic != nicOidRequest->SourceNicIndex ||
+ destPort != nicOidRequest->DestinationPortId ||
+ destNic != nicOidRequest->DestinationNicIndex)
+ {
+ ASSERT(Switch->OldNicRequest == NULL);
+ Switch->OldNicRequest = nicOidRequest;
+
+ newNicOidRequest = (PNDIS_SWITCH_NIC_OID_REQUEST)ExAllocatePoolWithTag(
+ NonPagedPoolNx,
+ sizeof(NDIS_SWITCH_NIC_OID_REQUEST),
+ SxExtAllocationTag);
+
+ if (newNicOidRequest == NULL)
+ {
+ status = NDIS_STATUS_RESOURCES;
+ *Complete = TRUE;
+ goto Cleanup;
+ }
+
+ newNicOidRequest->Header = nicOidRequest->Header;
+ newNicOidRequest->SourcePortId = sourcePort;
+ newNicOidRequest->SourceNicIndex = sourceNic;
+ newNicOidRequest->DestinationPortId = destPort;
+ newNicOidRequest->DestinationNicIndex = destNic;
+ newNicOidRequest->OidRequest = nicOidRequest->OidRequest;
+
+ OidRequest->DATA.METHOD_INFORMATION.InformationBuffer = newNicOidRequest;
+ }
+
+ break;
+
+ case OID_SWITCH_NIC_SAVE:
+ if (header->Type != NDIS_OBJECT_TYPE_DEFAULT ||
+ header->Revision < NDIS_SWITCH_NIC_SAVE_STATE_REVISION_1 ||
+ header->Size < NDIS_SIZEOF_NDIS_SWITCH_NIC_SAVE_STATE_REVISION_1)
+ {
+ status = NDIS_STATUS_NOT_SUPPORTED;
+ *Complete = TRUE;
+ goto Cleanup;
+ }
+
+ status = SxExtSaveNic(Switch,
+ Switch->ExtensionContext,
+ (PNDIS_SWITCH_NIC_SAVE_STATE)header,
+ &bytesWritten,
+ &bytesNeeded);
+
+ if (status == NDIS_STATUS_SUCCESS &&
+ bytesWritten > 0)
+ {
+ *Complete = TRUE;
+ }
+ else if (status == NDIS_STATUS_BUFFER_TOO_SHORT)
+ {
+ *BytesNeeded = ((PNDIS_SWITCH_NIC_SAVE_STATE)header)->SaveDataOffset +
+ bytesNeeded;
+ *Complete = TRUE;
+ }
+ else if (status != NDIS_STATUS_SUCCESS)
+ {
+ *Complete = TRUE;
+ }
+
+ break;
+
+ default:
+ break;
+ }
+
+Cleanup:
+ return status;
+}
+
+
+VOID
+SxpNdisCompleteInternalOidRequest(
+ __in PSX_SWITCH_OBJECT Switch,
+ __in PNDIS_OID_REQUEST NdisRequest,
+ __in NDIS_STATUS Status
+ )
+/*++
+
+Routine Description:
+
+ NDIS entry point indicating completion of a pended NDIS_OID_REQUEST.
+
+Arguments:
+
+ Switch - pointer to switch object.
+
+ NdisRequest - pointer to NDIS request
+
+ Status - Status of request completion
+
+Return Value:
+
+ None
+
+--*/
+{
+ PSX_OID_REQUEST oidRequest;
+ ULONG bytesNeeded;
+
+ UNREFERENCED_PARAMETER(Switch);
+
+ bytesNeeded = 0;
+ oidRequest = NULL;
+
+ switch (NdisRequest->RequestType)
+ {
+ case NdisRequestSetInformation:
+ bytesNeeded = NdisRequest->DATA.SET_INFORMATION.BytesNeeded;
+ break;
+
+ case NdisRequestQueryInformation:
+ bytesNeeded = NdisRequest->DATA.QUERY_INFORMATION.BytesNeeded;
+ break;
+
+ case NdisRequestMethod:
+ bytesNeeded = NdisRequest->DATA.METHOD_INFORMATION.BytesNeeded;
+ break;
+ }
+
+ //
+ // Get at the request context.
+ //
+ oidRequest = CONTAINING_RECORD(NdisRequest, SX_OID_REQUEST, NdisOidRequest);
+
+ //
+ // Save away the completion status.
+ //
+ oidRequest->Status = Status;
+
+ //
+ // Save bytesNeeded
+ //
+ oidRequest->BytesNeeded = bytesNeeded;
+
+ //
+ // Wake up the thread blocked for this request to complete.
+ //
+ NdisSetEvent(&oidRequest->ReqEvent);
+}
+
diff --git a/datapath-windows/base/SxBase.h b/datapath-windows/base/SxBase.h
new file mode 100644
index 0000000..98bcf01
--- /dev/null
+++ b/datapath-windows/base/SxBase.h
@@ -0,0 +1,168 @@
+/*++
+
+Copyright (c) Microsoft Corporation. All Rights Reserved.
+
+Module Name:
+
+ SxBase.c
+
+Abstract:
+
+ This file contains the common code for building a switch extension. This
+ file includes all the standard NDIS handling and exposes a function based
+ interface for the control path and data path. This also has reusable code
+ for basic operations such as pause/resume handling etc.
+
+
+--*/
+
+extern NDIS_STRING SxExtensionFriendlyName;
+extern NDIS_STRING SxExtensionGuid;
+
+typedef enum _SX_SWITCH_DATAFLOW_STATE
+{
+ SxSwitchPaused,
+ SxSwitchRunning
+} SX_SWITCH_DATAFLOW_STATE, *PSX_SWITCH_DATAFLOW_STATE;
+
+typedef enum _SX_SWITCH_CONTROFLOW_STATE
+{
+ SxSwitchUnknown,
+ SxSwitchAttached,
+ SxSwitchDetached
+} SX_SWITCH_CONTROLFLOW_STATE, *PSX_SWITCH_CONTROLFLOW_STATE;
+
+typedef struct _SX_SWITCH_OBJECT
+{
+ //
+ // The Link *must* always be the first field.
+ //
+ LIST_ENTRY Link;
+
+ //
+ // The extension context is the context used in the specific logic
+ // of this extension.
+ // This is allocated and returned in SxExtSwitchCreate
+ //
+ PNDIS_HANDLE ExtensionContext;
+
+ //
+ // Ndis related fields.
+ //
+ NDIS_HANDLE NdisFilterHandle;
+ NDIS_SWITCH_CONTEXT NdisSwitchContext;
+ NDIS_SWITCH_OPTIONAL_HANDLERS NdisSwitchHandlers;
+
+ //
+ // Switch state.
+ //
+ SX_SWITCH_DATAFLOW_STATE DataFlowState;
+ SX_SWITCH_CONTROLFLOW_STATE ControlFlowState;
+
+ //
+ // Management fields.
+ //
+ volatile LONG PendingInjectedNblCount;
+ volatile LONG PendingOidCount;
+
+ //
+ // Control Path Management.
+ //
+ PNDIS_SWITCH_NIC_OID_REQUEST OldNicRequest;
+
+} SX_SWITCH_OBJECT, *PSX_SWITCH_OBJECT;
+
+typedef struct _SX_OID_REQUEST
+{
+ NDIS_OID_REQUEST NdisOidRequest;
+ NDIS_EVENT ReqEvent;
+ NDIS_STATUS Status;
+ ULONG BytesNeeded;
+
+} SX_OID_REQUEST, *PSX_OID_REQUEST;
+
+typedef struct _FILTER_DEVICE_EXTENSION
+{
+ ULONG Signature;
+ NDIS_HANDLE Handle;
+} FILTER_DEVICE_EXTENSION, *PFILTER_DEVICE_EXTENSION;
+
+
+//
+// Function prototypes
+//
+DRIVER_INITIALIZE DriverEntry;
+
+DRIVER_UNLOAD SxNdisUnload;
+
+FILTER_SET_OPTIONS SxNdisSetOptions;
+
+FILTER_SET_MODULE_OPTIONS SxNdisSetFilterModuleOptions;
+
+FILTER_ATTACH SxNdisAttach;
+
+FILTER_DETACH SxNdisDetach;
+
+FILTER_PAUSE SxNdisPause;
+
+FILTER_RESTART SxNdisRestart;
+
+FILTER_OID_REQUEST SxNdisOidRequest;
+
+FILTER_CANCEL_OID_REQUEST SxNdisCancelOidRequest;
+
+FILTER_OID_REQUEST_COMPLETE SxNdisOidRequestComplete;
+
+FILTER_SEND_NET_BUFFER_LISTS SxNdisSendNetBufferLists;
+
+FILTER_RETURN_NET_BUFFER_LISTS SxNdisReturnNetBufferLists;
+
+FILTER_SEND_NET_BUFFER_LISTS_COMPLETE SxNdisSendNetBufferListsComplete;
+
+FILTER_RECEIVE_NET_BUFFER_LISTS SxNdisReceiveNetBufferLists;
+
+FILTER_CANCEL_SEND_NET_BUFFER_LISTS SxNdisCancelSendNetBufferLists;
+
+FILTER_STATUS SxNdisStatus;
+
+FILTER_NET_PNP_EVENT SxNdisNetPnPEvent;
+
+VOID
+SxpNdisCompleteInternalOidRequest(
+ __in PSX_SWITCH_OBJECT Switch,
+ __in PNDIS_OID_REQUEST NdisRequest,
+ __in NDIS_STATUS Status
+ );
+
+
+//
+// Some debug stuff.
+//
+#define DL_EXTRA_LOUD 20
+#define DL_VERY_LOUD 10
+#define DL_LOUD 8
+#define DL_INFO 6
+#define DL_TRACE 5
+#define DL_WARN 4
+#define DL_ERROR 2
+#define DL_FATAL 0
+
+#if DBG
+
+extern ULONG SxDebugLevel;
+
+#define DEBUGP(lev, stmt) \
+ { \
+ if ((lev) <= SxDebugLevel) \
+ { \
+ DbgPrint("%S: ",SxExtServiceName); DbgPrint stmt; \
+ } \
+ }
+
+#else
+
+#define DEBUGP(lev, stmt)
+
+#endif
+
+
diff --git a/datapath-windows/base/SxLibrary.c b/datapath-windows/base/SxLibrary.c
new file mode 100644
index 0000000..5beb73d
--- /dev/null
+++ b/datapath-windows/base/SxLibrary.c
@@ -0,0 +1,839 @@
+/*++
+
+Copyright (c) Microsoft Corporation. All Rights Reserved.
+
+Module Name:
+
+ SxLibrary.c
+
+Abstract:
+
+ This file contains the common library functions that can be used
+ by any extension using the SxBase library.
+
+
+--*/
+
+#include "precomp.h"
+
+VOID
+SxLibSendNetBufferListsIngress(
+ _In_ PSX_SWITCH_OBJECT Switch,
+ _In_ PNET_BUFFER_LIST NetBufferLists,
+ _In_ ULONG SendFlags,
+ _In_ ULONG NumInjectedNetBufferLists
+ )
+{
+ BOOLEAN dispatch;
+ BOOLEAN sameSource;
+ ULONG sendCompleteFlags;
+ PNDIS_SWITCH_FORWARDING_DETAIL_NET_BUFFER_LIST_INFO fwdDetail;
+ PNET_BUFFER_LIST curNbl, nextNbl;
+ ULONG numNbls = 0;
+ PNET_BUFFER_LIST dropNbl = NULL;
+ PNET_BUFFER_LIST *curDropNbl = &dropNbl;
+ NDIS_SWITCH_PORT_ID curSourcePort;
+ NDIS_STRING filterReason;
+
+ dispatch = NDIS_TEST_SEND_AT_DISPATCH_LEVEL(SendFlags);
+ sameSource = NDIS_TEST_SEND_FLAG(SendFlags, NDIS_SEND_FLAGS_SWITCH_SINGLE_SOURCE);
+
+ InterlockedAdd(&Switch->PendingInjectedNblCount, NumInjectedNetBufferLists);
+ KeMemoryBarrier();
+
+ if (Switch->DataFlowState != SxSwitchRunning)
+ {
+ RtlInitUnicodeString(&filterReason, L"Extension Paused");
+
+ sendCompleteFlags = (dispatch) ? NDIS_SEND_COMPLETE_FLAGS_DISPATCH_LEVEL : 0;
+ sendCompleteFlags |= (sameSource) ? NDIS_SEND_COMPLETE_FLAGS_SWITCH_SINGLE_SOURCE : 0;
+
+ fwdDetail = NET_BUFFER_LIST_SWITCH_FORWARDING_DETAIL(NetBufferLists);
+
+ if (sameSource)
+ {
+ for (curNbl = NetBufferLists; curNbl != NULL; curNbl = curNbl->Next)
+ {
+ ++numNbls;
+ }
+
+ Switch->NdisSwitchHandlers.ReportFilteredNetBufferLists(
+ Switch->NdisSwitchContext,
+ &SxExtensionGuid,
+ &SxExtensionFriendlyName,
+ fwdDetail->SourcePortId,
+ NDIS_SWITCH_REPORT_FILTERED_NBL_FLAGS_IS_INCOMING,
+ numNbls,
+ NetBufferLists,
+ &filterReason);
+
+ SxExtStartCompleteNetBufferListsIngress(Switch,
+ Switch->ExtensionContext,
+ NetBufferLists,
+ sendCompleteFlags);
+ }
+ else
+ {
+ curSourcePort = fwdDetail->SourcePortId;
+ for (curNbl = NetBufferLists; curNbl != NULL; curNbl = nextNbl)
+ {
+ nextNbl = curNbl->Next;
+ curNbl->Next = NULL;
+
+ fwdDetail = NET_BUFFER_LIST_SWITCH_FORWARDING_DETAIL(curNbl);
+
+ if(curSourcePort == fwdDetail->SourcePortId)
+ {
+ *curDropNbl = curNbl;
+ curDropNbl = &(curNbl->Next);
+ ++numNbls;
+ }
+ else
+ {
+ Switch->NdisSwitchHandlers.ReportFilteredNetBufferLists(
+ Switch->NdisSwitchContext,
+ &SxExtensionGuid,
+ &SxExtensionFriendlyName,
+ curSourcePort,
+ NDIS_SWITCH_REPORT_FILTERED_NBL_FLAGS_IS_INCOMING,
+ numNbls,
+ dropNbl,
+ &filterReason);
+
+ SxExtStartCompleteNetBufferListsIngress(Switch,
+ Switch->ExtensionContext,
+ dropNbl,
+ sendCompleteFlags);
+
+ numNbls = 1;
+ dropNbl = curNbl;
+ curDropNbl = &(curNbl->Next);
+ curSourcePort = fwdDetail->SourcePortId;
+ }
+ }
+
+ Switch->NdisSwitchHandlers.ReportFilteredNetBufferLists(
+ Switch->NdisSwitchContext,
+ &SxExtensionGuid,
+ &SxExtensionFriendlyName,
+ curSourcePort,
+ NDIS_SWITCH_REPORT_FILTERED_NBL_FLAGS_IS_INCOMING,
+ numNbls,
+ dropNbl,
+ &filterReason);
+
+ SxExtStartCompleteNetBufferListsIngress(Switch,
+ Switch->ExtensionContext,
+ dropNbl,
+ sendCompleteFlags);
+ }
+
+ goto Cleanup;
+ }
+
+ NdisFSendNetBufferLists(Switch->NdisFilterHandle,
+ NetBufferLists,
+ NDIS_DEFAULT_PORT_NUMBER,
+ SendFlags);
+
+Cleanup:
+ return;
+}
+
+
+VOID
+SxLibSendNetBufferListsEgress(
+ _In_ PSX_SWITCH_OBJECT Switch,
+ _In_ PNET_BUFFER_LIST NetBufferLists,
+ _In_ ULONG NumberOfNetBufferLists,
+ _In_ ULONG ReceiveFlags
+ )
+{
+ BOOLEAN dispatch, sameSource;
+ NDIS_SWITCH_PORT_ID sourcePortId;
+ PNDIS_SWITCH_FORWARDING_DETAIL_NET_BUFFER_LIST_INFO fwdDetail;
+ ULONG returnFlags;
+ NDIS_SWITCH_PORT_ID curSourcePort;
+ PNET_BUFFER_LIST curNbl, nextNbl;
+ ULONG numNbls;
+ PNET_BUFFER_LIST dropNbl = NULL;
+ PNET_BUFFER_LIST *curDropNbl = &dropNbl;
+ NDIS_STRING filterReason;
+
+ dispatch = NDIS_TEST_RECEIVE_AT_DISPATCH_LEVEL(ReceiveFlags);
+ sameSource = NDIS_TEST_RECEIVE_FLAG(ReceiveFlags, NDIS_RECEIVE_FLAGS_SWITCH_SINGLE_SOURCE);
+
+ if (Switch->DataFlowState != SxSwitchRunning)
+ {
+ RtlInitUnicodeString(&filterReason, L"Extension Paused");
+
+ returnFlags = (dispatch) ? NDIS_RETURN_FLAGS_DISPATCH_LEVEL : 0;
+ returnFlags |= NDIS_RETURN_FLAGS_SWITCH_SINGLE_SOURCE;
+
+ fwdDetail = NET_BUFFER_LIST_SWITCH_FORWARDING_DETAIL(NetBufferLists);
+
+ if (sameSource)
+ {
+ sourcePortId = fwdDetail->SourcePortId;
+
+ Switch->NdisSwitchHandlers.ReportFilteredNetBufferLists(
+ Switch->NdisSwitchContext,
+ &SxExtensionGuid,
+ &SxExtensionFriendlyName,
+ sourcePortId,
+ NDIS_SWITCH_REPORT_FILTERED_NBL_FLAGS_IS_INCOMING,
+ NumberOfNetBufferLists,
+ NetBufferLists,
+ &filterReason);
+
+ SxExtStartCompleteNetBufferListsEgress(Switch,
+ Switch->ExtensionContext,
+ NetBufferLists,
+ returnFlags);
+ }
+ else
+ {
+ curSourcePort = fwdDetail->SourcePortId;
+ numNbls = 0;
+ for (curNbl = NetBufferLists; curNbl != NULL; curNbl = nextNbl)
+ {
+ nextNbl = curNbl->Next;
+ curNbl->Next = NULL;
+
+ fwdDetail = NET_BUFFER_LIST_SWITCH_FORWARDING_DETAIL(curNbl);
+
+ if(curSourcePort == fwdDetail->SourcePortId)
+ {
+ *curDropNbl = curNbl;
+ curDropNbl = &(curNbl->Next);
+ ++numNbls;
+ }
+ else
+ {
+ Switch->NdisSwitchHandlers.ReportFilteredNetBufferLists(
+ Switch->NdisSwitchContext,
+ &SxExtensionGuid,
+ &SxExtensionFriendlyName,
+ curSourcePort,
+ NDIS_SWITCH_REPORT_FILTERED_NBL_FLAGS_IS_INCOMING,
+ numNbls,
+ dropNbl,
+ &filterReason);
+
+ SxExtStartCompleteNetBufferListsEgress(Switch,
+ Switch->ExtensionContext,
+ dropNbl,
+ returnFlags);
+
+ numNbls = 1;
+ dropNbl = curNbl;
+ curDropNbl = &(curNbl->Next);
+ curSourcePort = fwdDetail->SourcePortId;
+ }
+ }
+
+ Switch->NdisSwitchHandlers.ReportFilteredNetBufferLists(
+ Switch->NdisSwitchContext,
+ &SxExtensionGuid,
+ &SxExtensionFriendlyName,
+ curSourcePort,
+ NDIS_SWITCH_REPORT_FILTERED_NBL_FLAGS_IS_INCOMING,
+ numNbls,
+ dropNbl,
+ &filterReason);
+
+ SxExtStartCompleteNetBufferListsEgress(Switch,
+ Switch->ExtensionContext,
+ dropNbl,
+ returnFlags);
+ }
+
+ goto Cleanup;
+ }
+
+ NdisFIndicateReceiveNetBufferLists(Switch->NdisFilterHandle,
+ NetBufferLists,
+ NDIS_DEFAULT_PORT_NUMBER,
+ NumberOfNetBufferLists,
+ ReceiveFlags);
+
+Cleanup:
+ return;
+}
+
+VOID
+SxLibCompleteNetBufferListsEgress(
+ _In_ PSX_SWITCH_OBJECT Switch,
+ _In_ PNET_BUFFER_LIST NetBufferLists,
+ _In_ ULONG ReturnFlags
+ )
+{
+ NdisFReturnNetBufferLists(Switch->NdisFilterHandle,
+ NetBufferLists,
+ ReturnFlags);
+}
+
+
+VOID
+SxLibCompleteNetBufferListsIngress(
+ _In_ PSX_SWITCH_OBJECT Switch,
+ _In_ PNET_BUFFER_LIST NetBufferLists,
+ _In_ ULONG SendCompleteFlags
+ )
+{
+ NdisFSendNetBufferListsComplete(Switch->NdisFilterHandle,
+ NetBufferLists,
+ SendCompleteFlags);
+}
+
+VOID
+SxLibCompletedInjectedNetBufferLists(
+ _In_ PSX_SWITCH_OBJECT Switch,
+ _In_ ULONG NumInjectedNetBufferLists
+ )
+{
+ LONG subtract = -(LONG)NumInjectedNetBufferLists;
+ InterlockedAdd(&Switch->PendingInjectedNblCount, subtract);
+}
+
+
+NDIS_STATUS
+SxLibIssueOidRequest(
+ _In_ PSX_SWITCH_OBJECT Switch,
+ _In_ NDIS_REQUEST_TYPE RequestType,
+ _In_ NDIS_OID Oid,
+ _In_opt_ PVOID InformationBuffer,
+ _In_ ULONG InformationBufferLength,
+ _In_ ULONG OutputBufferLength,
+ _In_ ULONG MethodId,
+ _In_ UINT Timeout,
+ _Out_ PULONG BytesNeeded
+ )
+{
+ NDIS_STATUS status;
+ PSX_OID_REQUEST oidRequest;
+ PNDIS_OID_REQUEST ndisOidRequest;
+ ULONG bytesNeeded;
+ BOOLEAN asyncCompletion;
+
+ status = NDIS_STATUS_SUCCESS;
+ oidRequest = NULL;
+ bytesNeeded = 0;
+ asyncCompletion = FALSE;
+
+ NdisInterlockedIncrement(&Switch->PendingOidCount);
+
+ if (Switch->ControlFlowState != SxSwitchAttached)
+ {
+ status = NDIS_STATUS_CLOSING;
+ goto Cleanup;
+ }
+
+ //
+ // Dynamically allocate filter request so that we can handle asynchronous
+ // completion.
+ //
+ oidRequest = (PSX_OID_REQUEST)ExAllocatePoolWithTag(NonPagedPoolNx,
+ sizeof(SX_OID_REQUEST),
+ SxExtAllocationTag);
+ if (oidRequest == NULL)
+ {
+ goto Cleanup;
+ }
+
+ NdisZeroMemory(oidRequest, sizeof(SX_OID_REQUEST));
+ ndisOidRequest = &oidRequest->NdisOidRequest;
+ NdisInitializeEvent(&oidRequest->ReqEvent);
+
+ ndisOidRequest->Header.Type = NDIS_OBJECT_TYPE_OID_REQUEST;
+ ndisOidRequest->Header.Revision = NDIS_OID_REQUEST_REVISION_1;
+ ndisOidRequest->Header.Size = sizeof(NDIS_OID_REQUEST);
+ ndisOidRequest->RequestType = RequestType;
+ ndisOidRequest->Timeout = Timeout;
+
+ switch (RequestType)
+ {
+ case NdisRequestQueryInformation:
+ ndisOidRequest->DATA.QUERY_INFORMATION.Oid = Oid;
+ ndisOidRequest->DATA.QUERY_INFORMATION.InformationBuffer =
+ InformationBuffer;
+ ndisOidRequest->DATA.QUERY_INFORMATION.InformationBufferLength =
+ InformationBufferLength;
+ break;
+
+ case NdisRequestSetInformation:
+ ndisOidRequest->DATA.SET_INFORMATION.Oid = Oid;
+ ndisOidRequest->DATA.SET_INFORMATION.InformationBuffer =
+ InformationBuffer;
+ ndisOidRequest->DATA.SET_INFORMATION.InformationBufferLength =
+ InformationBufferLength;
+ break;
+
+ case NdisRequestMethod:
+ ndisOidRequest->DATA.METHOD_INFORMATION.Oid = Oid;
+ ndisOidRequest->DATA.METHOD_INFORMATION.MethodId = MethodId;
+ ndisOidRequest->DATA.METHOD_INFORMATION.InformationBuffer =
+ InformationBuffer;
+ ndisOidRequest->DATA.METHOD_INFORMATION.InputBufferLength =
+ InformationBufferLength;
+ ndisOidRequest->DATA.METHOD_INFORMATION.OutputBufferLength =
+ OutputBufferLength;
+ break;
+
+ default:
+ NT_ASSERT(FALSE);
+ break;
+ }
+
+ ndisOidRequest->RequestId = (PVOID)SxExtOidRequestId;
+ status = NdisFOidRequest(Switch->NdisFilterHandle, ndisOidRequest);
+
+ if (status == NDIS_STATUS_PENDING)
+ {
+ asyncCompletion = TRUE;
+ NdisWaitEvent(&oidRequest->ReqEvent, 0);
+ }
+ else
+ {
+ SxpNdisCompleteInternalOidRequest(Switch, ndisOidRequest, status);
+ }
+
+ bytesNeeded = oidRequest->BytesNeeded;
+ status = oidRequest->Status;
+
+Cleanup:
+
+ if (BytesNeeded != NULL)
+ {
+ *BytesNeeded = bytesNeeded;
+ }
+
+ if (!asyncCompletion)
+ {
+ NdisInterlockedDecrement(&Switch->PendingOidCount);
+ }
+
+ if (oidRequest != NULL)
+ {
+ ExFreePoolWithTag(oidRequest, SxExtAllocationTag);
+ }
+
+ return status;
+}
+
+
+NDIS_STATUS
+SxLibGetSwitchParametersUnsafe(
+ _In_ PSX_SWITCH_OBJECT Switch,
+ _Out_ PNDIS_SWITCH_PARAMETERS SwitchParameters
+ )
+{
+ NDIS_STATUS status;
+
+ SwitchParameters->Header.Revision = NDIS_SWITCH_PARAMETERS_REVISION_1;
+ SwitchParameters->Header.Type = NDIS_OBJECT_TYPE_DEFAULT;
+ SwitchParameters->Header.Size = sizeof(NDIS_SWITCH_PARAMETERS);
+
+ status = SxLibIssueOidRequest(Switch,
+ NdisRequestQueryInformation,
+ OID_SWITCH_PARAMETERS,
+ SwitchParameters,
+ sizeof(NDIS_SWITCH_PARAMETERS),
+ 0,
+ 0,
+ 0,
+ NULL);
+
+ return status;
+}
+
+
+NDIS_STATUS
+SxLibGetPortArrayUnsafe(
+ _In_ PSX_SWITCH_OBJECT Switch,
+ _Out_ PNDIS_SWITCH_PORT_ARRAY *PortArray
+ )
+{
+ NDIS_STATUS status = NDIS_STATUS_SUCCESS;
+ ULONG BytesNeeded = 0;
+ PNDIS_SWITCH_PORT_ARRAY portArray = NULL;
+ ULONG arrayLength = 0;
+
+ do
+ {
+ if (portArray != NULL)
+ {
+ ExFreePoolWithTag(portArray, SxExtAllocationTag);
+ }
+
+ if (BytesNeeded != 0)
+ {
+ arrayLength = BytesNeeded;
+ portArray = ExAllocatePoolWithTag(NonPagedPoolNx,
+ arrayLength,
+ SxExtAllocationTag);
+
+ if (portArray == NULL)
+ {
+ status = NDIS_STATUS_RESOURCES;
+ goto Cleanup;
+ }
+
+ portArray->Header.Revision = NDIS_SWITCH_PORT_ARRAY_REVISION_1;
+ portArray->Header.Type = NDIS_OBJECT_TYPE_DEFAULT;
+ portArray->Header.Size = (USHORT)arrayLength;
+ }
+
+ status = SxLibIssueOidRequest(Switch,
+ NdisRequestQueryInformation,
+ OID_SWITCH_PORT_ARRAY,
+ portArray,
+ arrayLength,
+ 0,
+ 0,
+ 0,
+ &BytesNeeded);
+
+ } while(status == NDIS_STATUS_INVALID_LENGTH);
+
+ *PortArray = portArray;
+Cleanup:
+ if (status != NDIS_STATUS_SUCCESS &&
+ portArray != NULL)
+ {
+ ExFreePoolWithTag(portArray, SxExtAllocationTag);
+ }
+
+ return status;
+}
+
+
+NDIS_STATUS
+SxLibGetNicArrayUnsafe(
+ _In_ PSX_SWITCH_OBJECT Switch,
+ _Out_ PNDIS_SWITCH_NIC_ARRAY *NicArray
+ )
+{
+ NDIS_STATUS status = NDIS_STATUS_SUCCESS;
+ ULONG BytesNeeded = 0;
+ PNDIS_SWITCH_NIC_ARRAY nicArray = NULL;
+ ULONG arrayLength = 0;
+
+ do
+ {
+ if (nicArray != NULL)
+ {
+ ExFreePoolWithTag(nicArray, SxExtAllocationTag);
+ }
+
+ if (BytesNeeded != 0)
+ {
+ arrayLength = BytesNeeded;
+ nicArray = ExAllocatePoolWithTag(NonPagedPoolNx,
+ arrayLength,
+ SxExtAllocationTag);
+
+ if (nicArray == NULL)
+ {
+ status = NDIS_STATUS_RESOURCES;
+ goto Cleanup;
+ }
+
+ nicArray->Header.Revision = NDIS_SWITCH_PORT_ARRAY_REVISION_1;
+ nicArray->Header.Type = NDIS_OBJECT_TYPE_DEFAULT;
+ nicArray->Header.Size = (USHORT)arrayLength;
+ }
+
+ status = SxLibIssueOidRequest(Switch,
+ NdisRequestQueryInformation,
+ OID_SWITCH_NIC_ARRAY,
+ nicArray,
+ arrayLength,
+ 0,
+ 0,
+ 0,
+ &BytesNeeded);
+
+ } while(status == NDIS_STATUS_INVALID_LENGTH);
+
+ *NicArray = nicArray;
+Cleanup:
+ if (status != NDIS_STATUS_SUCCESS &&
+ nicArray != NULL)
+ {
+ ExFreePoolWithTag(nicArray, SxExtAllocationTag);
+ }
+
+ return status;
+}
+
+
+NDIS_STATUS
+SxLibGetSwitchPropertyUnsafe(
+ _In_ PSX_SWITCH_OBJECT Switch,
+ _In_ NDIS_SWITCH_PROPERTY_TYPE PropertyType,
+ _In_opt_ PNDIS_SWITCH_OBJECT_ID PropertyId,
+ _Outptr_ PNDIS_SWITCH_PROPERTY_ENUM_PARAMETERS *SwitchPropertyEnumParameters
+ )
+{
+ NDIS_STATUS status = NDIS_STATUS_SUCCESS;
+ NDIS_SWITCH_PROPERTY_ENUM_PARAMETERS propertyParameters;
+ ULONG bytesNeeded = 0;
+ PNDIS_SWITCH_PROPERTY_ENUM_PARAMETERS outputBuffer = NULL;
+ USHORT outputBufferLength = sizeof(NDIS_SWITCH_PROPERTY_ENUM_PARAMETERS);
+
+ propertyParameters.Header.Type = NDIS_OBJECT_TYPE_DEFAULT;
+ propertyParameters.Header.Revision = NDIS_SWITCH_PROPERTY_ENUM_PARAMETERS_REVISION_1;
+
+ propertyParameters.PropertyType = PropertyType;
+ propertyParameters.SerializationVersion = NDIS_SWITCH_OBJECT_SERIALIZATION_VERSION_1;
+
+ //
+ // For Built-in properties, the ID is unnecessary.
+ //
+ if (PropertyId != NULL)
+ {
+ NdisMoveMemory(&propertyParameters.PropertyId,
+ PropertyId,
+ sizeof(NDIS_SWITCH_OBJECT_ID));
+ }
+ else
+ {
+ ASSERT(PropertyType != NdisSwitchPropertyTypeCustom);
+ }
+
+ outputBuffer = ExAllocatePoolWithTag(NonPagedPoolNx,
+ outputBufferLength,
+ SxExtAllocationTag);
+
+ if (outputBuffer == NULL)
+ {
+ status = NDIS_STATUS_RESOURCES;
+ goto Cleanup;
+ }
+
+ do
+ {
+ if (bytesNeeded != 0)
+ {
+ ExFreePoolWithTag(outputBuffer, SxExtAllocationTag);
+
+ outputBufferLength = (USHORT)bytesNeeded;
+ outputBuffer = ExAllocatePoolWithTag(NonPagedPoolNx,
+ outputBufferLength,
+ SxExtAllocationTag);
+
+ if (outputBuffer == NULL)
+ {
+ status = NDIS_STATUS_RESOURCES;
+ goto Cleanup;
+ }
+ }
+
+ if(outputBufferLength >= sizeof(propertyParameters))
+ {
+ NdisMoveMemory(outputBuffer, &propertyParameters, sizeof(propertyParameters));
+
+ }
+
+ status = SxLibIssueOidRequest(Switch,
+ NdisRequestMethod,
+ OID_SWITCH_PROPERTY_ENUM,
+ outputBuffer,
+ sizeof(propertyParameters),
+ outputBufferLength,
+ 0,
+ 0,
+ &bytesNeeded);
+
+ } while(status == NDIS_STATUS_INVALID_LENGTH);
+
+Cleanup:
+ if (status != NDIS_STATUS_SUCCESS &&
+ outputBuffer != NULL)
+ {
+ ExFreePoolWithTag(outputBuffer, SxExtAllocationTag);
+ outputBuffer = NULL;
+ }
+
+ *SwitchPropertyEnumParameters = outputBuffer;
+
+ return status;
+}
+
+
+NDIS_STATUS
+SxLibGetPortPropertyUnsafe(
+ _In_ PSX_SWITCH_OBJECT Switch,
+ _In_ NDIS_SWITCH_PORT_ID PortId,
+ _In_ NDIS_SWITCH_PORT_PROPERTY_TYPE PropertyType,
+ _In_opt_ PNDIS_SWITCH_OBJECT_ID PropertyId,
+ _Outptr_ PNDIS_SWITCH_PORT_PROPERTY_ENUM_PARAMETERS *PortPropertyEnumParameters
+ )
+{
+ NDIS_STATUS status = NDIS_STATUS_SUCCESS;
+ NDIS_SWITCH_PORT_PROPERTY_ENUM_PARAMETERS propertyParameters;
+ ULONG bytesNeeded = 0;
+ PNDIS_SWITCH_PORT_PROPERTY_ENUM_PARAMETERS outputBuffer = NULL;
+ USHORT outputBufferLength = sizeof(NDIS_SWITCH_PORT_PROPERTY_ENUM_PARAMETERS);
+
+ propertyParameters.Header.Type = NDIS_OBJECT_TYPE_DEFAULT;
+ propertyParameters.Header.Revision = NDIS_SWITCH_PORT_PROPERTY_ENUM_PARAMETERS_REVISION_1;
+
+ propertyParameters.PortId = PortId;
+ propertyParameters.PropertyType = PropertyType;
+ propertyParameters.SerializationVersion = NDIS_SWITCH_OBJECT_SERIALIZATION_VERSION_1;
+
+ //
+ // For Built-in properties, the ID is unnecessary.
+ //
+ if (PropertyId != NULL)
+ {
+ NdisMoveMemory(&propertyParameters.PropertyId,
+ PropertyId,
+ sizeof(NDIS_SWITCH_OBJECT_ID));
+ }
+ else
+ {
+ ASSERT(PropertyType != NdisSwitchPortPropertyTypeCustom);
+ }
+
+ outputBuffer = ExAllocatePoolWithTag(NonPagedPoolNx,
+ outputBufferLength,
+ SxExtAllocationTag);
+
+ if (outputBuffer == NULL)
+ {
+ status = NDIS_STATUS_RESOURCES;
+ goto Cleanup;
+ }
+
+ do
+ {
+ if (bytesNeeded != 0)
+ {
+ ExFreePoolWithTag(outputBuffer, SxExtAllocationTag);
+
+ outputBufferLength = (USHORT)bytesNeeded;
+ outputBuffer = ExAllocatePoolWithTag(NonPagedPoolNx,
+ outputBufferLength,
+ SxExtAllocationTag);
+
+ if (outputBuffer == NULL)
+ {
+ status = NDIS_STATUS_RESOURCES;
+ goto Cleanup;
+ }
+ }
+
+ if(outputBufferLength >= sizeof(propertyParameters))
+ {
+ outputBuffer->Header.Size = outputBufferLength;
+ NdisMoveMemory(outputBuffer, &propertyParameters, sizeof(propertyParameters));
+ }
+
+ status = SxLibIssueOidRequest(Switch,
+ NdisRequestMethod,
+ OID_SWITCH_PORT_PROPERTY_ENUM,
+ outputBuffer,
+ sizeof(propertyParameters),
+ outputBufferLength,
+ 0,
+ 0,
+ &bytesNeeded);
+
+ } while(status == NDIS_STATUS_INVALID_LENGTH);
+
+Cleanup:
+ if (status != NDIS_STATUS_SUCCESS &&
+ outputBuffer != NULL)
+ {
+ ExFreePoolWithTag(outputBuffer, SxExtAllocationTag);
+ outputBuffer = NULL;
+ }
+
+ *PortPropertyEnumParameters = outputBuffer;
+
+ return status;
+}
+
+
+VOID
+SxLibRevokeVfUnsafe(
+ _In_ PSX_SWITCH_OBJECT Switch,
+ _In_ NDIS_SWITCH_PORT_ID PortId
+ )
+{
+ SxLibIssueNicStatusIndicationUnsafe(Switch,
+ NDIS_STATUS_SWITCH_PORT_REMOVE_VF,
+ PortId,
+ NDIS_SWITCH_DEFAULT_NIC_INDEX,
+ TRUE,
+ NULL,
+ 0);
+}
+
+
+VOID
+SxLibIssueNicStatusIndicationUnsafe(
+ _In_ PSX_SWITCH_OBJECT Switch,
+ _In_ NDIS_STATUS StatusCode,
+ _In_ NDIS_SWITCH_PORT_ID PortId,
+ _In_ NDIS_SWITCH_NIC_INDEX NicIndex,
+ _In_ BOOLEAN IsDestination,
+ _In_opt_ PVOID StatusBuffer,
+ _In_ ULONG StatusBufferSize
+ )
+{
+ NDIS_STATUS_INDICATION statusIndication;
+ NDIS_STATUS_INDICATION wrappedIndication;
+ NDIS_SWITCH_NIC_STATUS_INDICATION nicIndication;
+
+ NdisZeroMemory(&wrappedIndication, sizeof(wrappedIndication));
+
+ wrappedIndication.Header.Type = NDIS_OBJECT_TYPE_STATUS_INDICATION;
+ wrappedIndication.Header.Revision = NDIS_STATUS_INDICATION_REVISION_1;
+ wrappedIndication.Header.Size = NDIS_SIZEOF_STATUS_INDICATION_REVISION_1;
+
+ wrappedIndication.SourceHandle = Switch->NdisFilterHandle;
+ wrappedIndication.PortNumber = NDIS_DEFAULT_PORT_NUMBER;
+
+ wrappedIndication.StatusCode = StatusCode;
+ wrappedIndication.StatusBuffer = StatusBuffer;
+ wrappedIndication.StatusBufferSize = StatusBufferSize;
+
+ NdisZeroMemory(&nicIndication, sizeof(nicIndication));
+
+ nicIndication.Header.Type = NDIS_OBJECT_TYPE_DEFAULT;
+ nicIndication.Header.Revision = NDIS_SWITCH_NIC_STATUS_INDICATION_REVISION_1;
+ nicIndication.Header.Size = NDIS_SIZEOF_SWITCH_NIC_STATUS_REVISION_1;
+ nicIndication.StatusIndication = &wrappedIndication;
+
+ if (IsDestination)
+ {
+ nicIndication.DestinationPortId = PortId;
+ nicIndication.DestinationNicIndex = NicIndex;
+ }
+ else
+ {
+ nicIndication.SourcePortId = PortId;
+ nicIndication.SourceNicIndex = NicIndex;
+ }
+
+ NdisZeroMemory(&statusIndication, sizeof(statusIndication));
+
+ statusIndication.Header.Type = NDIS_OBJECT_TYPE_STATUS_INDICATION;
+ statusIndication.Header.Revision = NDIS_STATUS_INDICATION_REVISION_1;
+ statusIndication.Header.Size = NDIS_SIZEOF_STATUS_INDICATION_REVISION_1;
+
+ statusIndication.SourceHandle = Switch->NdisFilterHandle;
+ statusIndication.PortNumber = NDIS_DEFAULT_PORT_NUMBER;
+
+ statusIndication.StatusCode = NDIS_STATUS_SWITCH_NIC_STATUS;
+ statusIndication.StatusBuffer = &nicIndication;
+ statusIndication.StatusBufferSize = sizeof(nicIndication);
+
+ NdisFIndicateStatus(Switch->NdisFilterHandle,
+ &statusIndication);
+}
+
diff --git a/datapath-windows/base/SxLibrary.h b/datapath-windows/base/SxLibrary.h
new file mode 100644
index 0000000..b5f9b14
--- /dev/null
+++ b/datapath-windows/base/SxLibrary.h
@@ -0,0 +1,464 @@
+/*++
+
+Copyright (c) Microsoft Corporation. All Rights Reserved.
+
+Module Name:
+
+ SxLibrary.h
+
+Abstract:
+
+ This file contains the common library function headers that can be
+ used by any extension using the SxBase library.
+
+
+--*/
+
+
+/*++
+
+SxLibSendNetBufferListsIngress
+
+Routine Description:
+ This function is called to forward NBLs on ingress.
+ The extension MUST call this function, or call
+ SxLibCompleteNetBufferListsIngress for every NBL in NetBufferLists,
+ recieved in SxExtStartNetBufferListsIngress.
+
+ This function can also be called to inject NBLs.
+ If there are NBLs in NetBufferLists that are initiated by the
+ extension, NumInjectedNetBufferLists must be the number of new NBLs.
+
+Arguments:
+
+ Switch - the Switch context
+
+ NetBufferLists - the NBLs to send
+
+ SendFlags - the SendFlags equivalent to NDIS flags for
+ NdisFSendNetBufferLists
+
+ NumInjectedNetBufferLists - the number of NBLs in NetBufferLists initiated
+ by the extension
+
+Return Value:
+ VOID
+
+--*/
+VOID
+SxLibSendNetBufferListsIngress(
+ _In_ PSX_SWITCH_OBJECT Switch,
+ _In_ PNET_BUFFER_LIST NetBufferLists,
+ _In_ ULONG SendFlags,
+ _In_ ULONG NumInjectedNetBufferLists
+ );
+
+
+/*++
+
+SxLibSendNetBufferListsEgress
+
+Routine Description:
+ This function is called to forward NBLs on egress.
+ The extension MUST call this function, or call
+ SxLibCompleteNetBufferListsEgress for every NBL in NetBufferLists
+ recieved in SxExtStartNetBufferListsEgress.
+
+Arguments:
+
+ Switch - the Switch context
+
+ NetBufferLists - the NBLs to send
+
+ NumberOfNetBufferLists - the number of NBLs in NetBufferLists
+
+ ReceiveFlags - the ReceiveFlags equivalent to NDIS flags for
+ NdisFIndicateReceiveNetBufferLists
+
+Return Value:
+ VOID
+
+--*/
+VOID
+SxLibSendNetBufferListsEgress(
+ _In_ PSX_SWITCH_OBJECT Switch,
+ _In_ PNET_BUFFER_LIST NetBufferLists,
+ _In_ ULONG NumberOfNetBufferLists,
+ _In_ ULONG ReceiveFlags
+ );
+
+
+/*++
+
+SxLibCompleteNetBufferListsEgress
+
+Routine Description:
+ This function is called to complete NBLs on egress.
+ The extension MUST call this function for all NBLs recieved
+ in SxExtStartCompleteNetBufferListsEgress.
+
+Arguments:
+
+ Switch - the Switch context
+
+ NetBufferLists - the NBLs to send
+
+ ReturnFlags - the ReceiveFlags equivalent to NDIS flags for
+ NdisFReturnNetBufferLists
+
+Return Value:
+ VOID
+
+--*/
+VOID
+SxLibCompleteNetBufferListsEgress(
+ _In_ PSX_SWITCH_OBJECT Switch,
+ _In_ PNET_BUFFER_LIST NetBufferLists,
+ _In_ ULONG ReturnFlags
+ );
+
+/*++
+
+SxLibCompleteNetBufferListsIngress
+
+Routine Description:
+ This function is called to complete NBLs on ingress.
+ The extension MUST call this function, or
+ SxLibCompletedInjectedNetBufferLists for all NBLs recieved in
+ SxExtStartCompleteNetBufferListsEgress.
+
+Arguments:
+
+ Switch - the Switch context
+
+ NetBufferLists - the NBLs to send
+
+ SendCompleteFlags - the ReceiveFlags equivalent to NDIS flags for
+ NdisFSendNetBufferListsComplete
+
+Return Value:
+ VOID
+
+--*/
+VOID
+SxLibCompleteNetBufferListsIngress(
+ _In_ PSX_SWITCH_OBJECT Switch,
+ _In_ PNET_BUFFER_LIST NetBufferLists,
+ _In_ ULONG SendCompleteFlags
+ );
+
+
+/*++
+
+SxLibCompletedInjectedNetBufferLists
+
+Routine Description:
+ This function is called after completing NBLs injected
+ by the extension.
+
+Arguments:
+
+ Switch - the Switch context
+
+ NumInjectedNetBufferLists - the number of NBLs completed
+
+Return Value:
+ VOID
+
+--*/
+VOID
+SxLibCompletedInjectedNetBufferLists(
+ _In_ PSX_SWITCH_OBJECT Switch,
+ _In_ ULONG NumInjectedNetBufferLists
+ );
+
+
+/*++
+
+SxLibIssueOidRequest
+
+Routine Description:
+
+ Utility routine that forms and sends an NDIS_OID_REQUEST to the
+ miniport, waits for it to complete, and returns status
+ to the caller.
+
+ NOTE: this assumes that the calling routine ensures validity
+ of the filter handle until this returns.
+
+ This function can only be called at PASSIVE_LEVEL.
+
+Arguments:
+
+ Switch - pointer to our switch object.
+
+ RequestType - NdisRequest[Set|Query|method]Information.
+
+ Oid - the object being set/queried.
+
+ InformationBuffer - data for the request.
+
+ InformationBufferLength - length of the above.
+
+ OutputBufferLength - valid only for method request.
+
+ MethodId - valid only for method request.
+
+ Timeout - The timeout in seconds for the OID.
+
+ BytesNeeded - place to return bytes read/written.
+
+Return Value:
+
+ NDIS_STATUS_***
+
+--*/
+NDIS_STATUS
+SxLibIssueOidRequest(
+ _In_ PSX_SWITCH_OBJECT SxSwitch,
+ _In_ NDIS_REQUEST_TYPE RequestType,
+ _In_ NDIS_OID Oid,
+ _In_opt_ PVOID InformationBuffer,
+ _In_ ULONG InformationBufferLength,
+ _In_ ULONG OutputBufferLength,
+ _In_ ULONG MethodId,
+ _In_ UINT Timeout,
+ _Out_ PULONG BytesNeeded
+ );
+
+
+/*++
+
+SxLibGetSwitchParametersUnsafe
+
+Routine Description:
+ This function is called to get the current state of the switch.
+
+Arguments:
+
+ Switch - the Switch context
+
+ SwitchParameters - the returned switch parameters
+
+Return Value:
+ NDIS_STATUS_SUCCESS - if SwitchParameters was successfully returned
+
+ NDIS_STATUS_*** - otherwise
+
+--*/
+NDIS_STATUS
+SxLibGetSwitchParametersUnsafe(
+ _In_ PSX_SWITCH_OBJECT Switch,
+ _Out_ PNDIS_SWITCH_PARAMETERS SwitchParameters
+ );
+
+
+/*++
+
+SxLibGetPortArrayUnsafe
+
+Routine Description:
+ This function is called to get the current array
+ of ports.
+
+ NOTE: It is necessary to synchonize this with SxExtPortCreate
+ and SxExtPortTeardown.
+
+Arguments:
+
+ Switch - the Switch context
+
+ PortArray - the returned port array
+
+Return Value:
+ NDIS_STATUS_SUCCESS - if PortArray was successfully allocated
+ and returned
+
+ NDIS_STATUS_*** - otherwise
+
+--*/
+NDIS_STATUS
+SxLibGetPortArrayUnsafe(
+ _In_ PSX_SWITCH_OBJECT Switch,
+ _Out_ PNDIS_SWITCH_PORT_ARRAY *PortArray
+ );
+
+
+/*++
+
+SxLibGetNicArrayUnsafe
+
+Routine Description:
+ This function is called to get the current array
+ of NICs.
+
+ NOTE: It is necessary to synchonize this with SxExtNicConnect
+ and SxExtNicDisconnect.
+
+Arguments:
+
+ Switch - the Switch context
+
+ NicArray - the returned NIC array
+
+Return Value:
+ NDIS_STATUS_SUCCESS - if NicArray was successfully allocated
+ and returned
+
+ NDIS_STATUS_*** - otherwise
+
+--*/
+NDIS_STATUS
+SxLibGetNicArrayUnsafe(
+ _In_ PSX_SWITCH_OBJECT SxSwitch,
+ _Out_ PNDIS_SWITCH_NIC_ARRAY *NicArray
+ );
+
+/*++
+
+SxLibGetSwitchPropertyUnsafe
+
+Routine Description:
+ This function is called to get the current array of the switch
+ property queried.
+
+ NOTE: It is necessary to synchonize this with SxExtAddSwitchProperty
+ and SxExtDeleteSwitchProperty.
+
+Arguments:
+
+ Switch - the Switch context
+
+ PropertyType - the PropertyType to query for
+
+ PropertyId - the GUID of the property (from mof file)
+
+ PropertyVersion - the version of the property
+
+ SwitchPropertyEnumParameters - the returned property enum
+
+Return Value:
+ NDIS_STATUS_SUCCESS - if SwitchPropertyEnumParameters was
+ successfully allocated and returned
+
+ NDIS_STATUS_*** - otherwise
+
+--*/
+NDIS_STATUS
+SxLibGetSwitchPropertyUnsafe(
+ _In_ PSX_SWITCH_OBJECT Switch,
+ _In_ NDIS_SWITCH_PROPERTY_TYPE PropertyType,
+ _In_opt_ PNDIS_SWITCH_OBJECT_ID PropertyId,
+ _Outptr_ PNDIS_SWITCH_PROPERTY_ENUM_PARAMETERS *SwitchPropertyEnumParameters
+ );
+
+/*++
+
+SxLibGetPortPropertyUnsafe
+
+Routine Description:
+ This function is called to get the current array of the switch
+ property queried.
+
+ NOTE: It is necessary to synchonize this with SxExtAddPortProperty
+ and SxExtDeletePortProperty.
+
+Arguments:
+
+ Switch - the Switch context
+
+ PortId - the port to query from
+
+ PropertyType - the PropertyType to query for
+
+ PropertyId - the GUID of the property (from mof file)
+
+ PortPropertyEnumParameters - the returned property enum
+
+Return Value:
+ NDIS_STATUS_SUCCESS - if PortPropertyEnumParameters was
+ successfully allocated and returned
+
+ NDIS_STATUS_*** - otherwise
+
+--*/
+NDIS_STATUS
+SxLibGetPortPropertyUnsafe(
+ _In_ PSX_SWITCH_OBJECT Switch,
+ _In_ NDIS_SWITCH_PORT_ID PortId,
+ _In_ NDIS_SWITCH_PORT_PROPERTY_TYPE PropertyType,
+ _In_opt_ PNDIS_SWITCH_OBJECT_ID PropertyId,
+ _Outptr_ PNDIS_SWITCH_PORT_PROPERTY_ENUM_PARAMETERS *PortPropertyEnumParameters
+ );
+
+/*++
+
+SxLibRevokeVfUnsafe
+
+Routine Description:
+ This function is called revoke the VF assignment for the
+ given VM.
+
+ NOTE: This must be synchonized with SxExtNicConnect and
+ SxExtNicDisconnect for the PortId given, and ReferenceSwitchNic
+ must have been successfully called.
+
+Arguments:
+
+ Switch - the Switch context
+
+ PortId - the port the VM is connected to
+
+Return Value:
+ VOID
+
+--*/
+VOID
+SxLibRevokeVfUnsafe(
+ _In_ PSX_SWITCH_OBJECT Switch,
+ _In_ NDIS_SWITCH_PORT_ID PortId
+ );
+
+/*++
+
+SxLibIssueNicStatusIndicationUnsafe
+
+Routine Description:
+ This function is called issue a NIC status indication.
+
+ NOTE: This must be synchonized with SxExtNicConnect and
+ SxExtNicDisconnect for the PortId given, and ReferenceSwitchNic
+ must have been successfully called.
+
+Arguments:
+
+ Switch - the Switch context
+
+ StatusCode - the status code to indicate
+
+ PortId - the port to indicate to/from
+
+ NicIndex - the nic index to indicate to/from
+
+ IsDestination - TRUE if PortId/NicIndex is destination info
+ FALSE if PortId/NicIndex is source info
+
+ StatusBuffer - the StatusBuffer for the indication
+
+ StatusBufferSize - the size of StatusBuffer
+
+Return Value:
+ VOID
+
+--*/
+VOID
+SxLibIssueNicStatusIndicationUnsafe(
+ _In_ PSX_SWITCH_OBJECT Switch,
+ _In_ NDIS_STATUS StatusCode,
+ _In_ NDIS_SWITCH_PORT_ID PortId,
+ _In_ NDIS_SWITCH_NIC_INDEX NicIndex,
+ _In_ BOOLEAN IsDestination,
+ _In_opt_ PVOID StatusBuffer,
+ _In_ ULONG StatusBufferSize
+ );
+
diff --git a/datapath-windows/base/precomp.h b/datapath-windows/base/precomp.h
new file mode 100644
index 0000000..2b75778
--- /dev/null
+++ b/datapath-windows/base/precomp.h
@@ -0,0 +1,11 @@
+//
+// Copyright (c) Microsoft Corporation. All Rights Reserved.
+//
+
+#include <ndis.h>
+#include <netiodef.h>
+#include <intsafe.h>
+#include <ntintsafe.h>
+#include "SxBase.h"
+#include "SxApi.h"
+#include "SxLibrary.h"
diff --git a/datapath-windows/base/precompsrc.c b/datapath-windows/base/precompsrc.c
new file mode 100644
index 0000000..5944cf5
--- /dev/null
+++ b/datapath-windows/base/precompsrc.c
@@ -0,0 +1 @@
+#include "precomp.h"
\ No newline at end of file
diff --git a/debian/copyright.in b/debian/copyright.in
index 89cd2d2..9ef763e 100644
--- a/debian/copyright.in
+++ b/debian/copyright.in
@@ -17,6 +17,7 @@ Upstream Copyright Holders:
Copyright (C) 2000 The NetBSD Foundation, Inc.
Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
Copyright (c) 1982, 1986, 1990, 1993 The Regents of the University of California.
+ Copyright (c) Microsoft Corporation. All Rights Reserved.
License:
@@ -204,6 +205,9 @@ License:
gives unlimited permission to copy and/or distribute it,
with or without modifications, as long as this notice is preserved.
+* The files unders datapath-windows/base are licensed under Microsoft Limited
+ Public License version 1.1.
+
* All other components of this package are licensed under
The Apache License Version 2.0.
@@ -700,3 +704,73 @@ Phone: (415) 283-3260
URL: www.inmon.com
Email: info at inmon.com
+----------------------------------------------------------------------
+
+Retrieved from http://msdn.microsoft.com/en-us/cc300389.aspx#MLPL, 2014-06-18:
+
+Microsoft Limited Public License
+
+This license governs use of code marked as “sample” or “example” available on
+this web site without a license agreement, as provided under the section above
+titled “NOTICE SPECIFIC TO SOFTWARE AVAILABLE ON THIS WEB SITE.” If you use
+such code (the “software”), you accept this license. If you do not accept the
+license, do not use the software.
+
+1. Definitions
+
+The terms “reproduce,” “reproduction,” “derivative works,” and “distribution”
+have the same meaning here as under U.S. copyright law.
+
+A “contribution” is the original software, or any additions or changes to the
+software.
+
+A “contributor” is any person that distributes its contribution under this
+license.
+
+“Licensed patents” are a contributor’s patent claims that read directly on its
+contribution.
+
+2. Grant of Rights
+
+(A) Copyright Grant - Subject to the terms of this license, including the
+license conditions and limitations in section 3, each contributor grants you a
+non-exclusive, worldwide, royalty-free copyright license to reproduce its
+contribution, prepare derivative works of its contribution, and distribute its
+contribution or any derivative works that you create.
+
+(B) Patent Grant - Subject to the terms of this license, including the license
+conditions and limitations in section 3, each contributor grants you a
+non-exclusive, worldwide, royalty-free license under its licensed patents to
+make, have made, use, sell, offer for sale, import, and/or otherwise dispose of
+its contribution in the software or derivative works of the contribution in the
+software.
+
+3. Conditions and Limitations
+
+(A) No Trademark License- This license does not grant you rights to use any
+contributors’ name, logo, or trademarks.
+
+(B) If you bring a patent claim against any contributor over patents that you
+claim are infringed by the software, your patent license from such contributor
+to the software ends automatically.
+
+(C) If you distribute any portion of the software, you must retain all
+copyright, patent, trademark, and attribution notices that are present in the
+software.
+
+(D) If you distribute any portion of the software in source code form, you may
+do so only under this license by including a complete copy of this license with
+ your distribution. If you distribute any portion of the software in
+ compiled or object code form, you may only do so under a license that
+ complies with this license.
+
+ (E) The software is licensed “as-is.” You bear the risk of using it. The
+ contributors give no express warranties, guarantees or conditions. You may
+ have additional consumer rights under your local laws which this license
+ cannot change. To the extent permitted under your local laws, the
+ contributors exclude the implied warranties of merchantability, fitness for
+ a particular purpose and non-infringement.
+
+ (F) Platform Limitation - The licenses granted in sections 2(A) and 2(B)
+ extend only to the software or derivative works that you create that run on
+ a Microsoft Windows operating system product.
--
1.7.9.5
More information about the dev
mailing list