[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [win-pv-devel] [PATCH 2/4] Add frontend code for the new netif control ring
My recent patches to Xen's netif.h specify a control ring that can be used by a frontend driver to configure packet hashing and steering in a backend. This patch adds the necessary code to XENVIF to drive this new ring, however the rest of the code to link this up to new VIF interface functionality (so that it may be used by XENNET) is deferred to a subsequent patch. This patch also pulls in an updated EVTCHN interface from XENBUS and corrects the PDO binding. Signed-off-by: Paul Durrant <paul.durrant@xxxxxxxxxx> --- include/evtchn_interface.h | 36 +- src/xenvif.inf | 6 +- src/xenvif/controller.c | 1336 ++++++++++++++++++++++++++++++++++++++++++ src/xenvif/controller.h | 126 ++++ src/xenvif/frontend.c | 50 +- src/xenvif/frontend.h | 7 + vs2012/xenvif/xenvif.vcxproj | 1 + vs2013/xenvif/xenvif.vcxproj | 1 + 8 files changed, 1549 insertions(+), 14 deletions(-) create mode 100644 src/xenvif/controller.c create mode 100644 src/xenvif/controller.h diff --git a/include/evtchn_interface.h b/include/evtchn_interface.h index 6f8fe42..a9952d6 100644 --- a/include/evtchn_interface.h +++ b/include/evtchn_interface.h @@ -180,6 +180,20 @@ typedef VOID IN PXENBUS_EVTCHN_CHANNEL Channel ); +/*! \typedef XENBUS_EVTCHN_WAIT + \brief Wait for an event to the local end of the channel + + \param Interface The interface header + \param Channel The channel handle + \param Timeout An optional timeout value (similar to KeWaitForSingleObject(), but non-zero values are allowed at DISPATCH_LEVEL). +*/ +typedef NTSTATUS +(*XENBUS_EVTCHN_WAIT)( + IN PINTERFACE Interface, + IN PXENBUS_EVTCHN_CHANNEL Channel, + IN PLARGE_INTEGER Timeout OPTIONAL + ); + /*! \typedef XENBUS_EVTCHN_GET_PORT \brief Get the local port number bound to the channel @@ -276,7 +290,25 @@ struct _XENBUS_EVTCHN_INTERFACE_V4 { XENBUS_EVTCHN_CLOSE EvtchnClose; }; -typedef struct _XENBUS_EVTCHN_INTERFACE_V4 XENBUS_EVTCHN_INTERFACE, *PXENBUS_EVTCHN_INTERFACE; +/*! \struct _XENBUS_EVTCHN_INTERFACE_V5 + \brief EVTCHN interface version 5 + \ingroup interfaces +*/ +struct _XENBUS_EVTCHN_INTERFACE_V5 { + INTERFACE Interface; + XENBUS_EVTCHN_ACQUIRE EvtchnAcquire; + XENBUS_EVTCHN_RELEASE EvtchnRelease; + XENBUS_EVTCHN_OPEN EvtchnOpen; + XENBUS_EVTCHN_BIND EvtchnBind; + XENBUS_EVTCHN_UNMASK EvtchnUnmask; + XENBUS_EVTCHN_SEND EvtchnSend; + XENBUS_EVTCHN_TRIGGER EvtchnTrigger; + XENBUS_EVTCHN_WAIT EvtchnWait; + XENBUS_EVTCHN_GET_PORT EvtchnGetPort; + XENBUS_EVTCHN_CLOSE EvtchnClose; +}; + +typedef struct _XENBUS_EVTCHN_INTERFACE_V5 XENBUS_EVTCHN_INTERFACE, *PXENBUS_EVTCHN_INTERFACE; /*! \def XENBUS_EVTCHN \brief Macro at assist in method invocation @@ -287,7 +319,7 @@ typedef struct _XENBUS_EVTCHN_INTERFACE_V4 XENBUS_EVTCHN_INTERFACE, *PXENBUS_EVT #endif // _WINDLL #define XENBUS_EVTCHN_INTERFACE_VERSION_MIN 1 -#define XENBUS_EVTCHN_INTERFACE_VERSION_MAX 4 +#define XENBUS_EVTCHN_INTERFACE_VERSION_MAX 5 #endif // _XENBUS_EVTCHN_INTERFACE_H diff --git a/src/xenvif.inf b/src/xenvif.inf index 0fa4c98..899260e 100644 --- a/src/xenvif.inf +++ b/src/xenvif.inf @@ -58,9 +58,9 @@ xenvif_coinst_@MAJOR_VERSION@_@MINOR_VERSION@_@MICRO_VERSION@_@BUILD_NUMBER@.dll ; DisplayName Section DeviceID ; ----------- ------- -------- -%XenVifDesc% =XenVif_Inst, XENBUS\VEN_@VENDOR_PREFIX@@VENDOR_DEVICE_ID@&DEV_VIF&REV_08000009 -%XenVifDesc% =XenVif_Inst, XENBUS\VEN_@VENDOR_PREFIX@0001&DEV_VIF&REV_08000009 -%XenVifDesc% =XenVif_Inst, XENBUS\VEN_@VENDOR_PREFIX@0002&DEV_VIF&REV_08000009 +%XenVifDesc% =XenVif_Inst, XENBUS\VEN_@VENDOR_PREFIX@@VENDOR_DEVICE_ID@&DEV_VIF&REV_0800000B +%XenVifDesc% =XenVif_Inst, XENBUS\VEN_@VENDOR_PREFIX@0001&DEV_VIF&REV_0800000B +%XenVifDesc% =XenVif_Inst, XENBUS\VEN_@VENDOR_PREFIX@0002&DEV_VIF&REV_0800000B [XenVif_Inst] CopyFiles=XenVif_Copyfiles diff --git a/src/xenvif/controller.c b/src/xenvif/controller.c new file mode 100644 index 0000000..6c6bb3e --- /dev/null +++ b/src/xenvif/controller.c @@ -0,0 +1,1336 @@ +/* Copyright (c) Citrix Systems Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, + * with or without modification, are permitted provided + * that the following conditions are met: + * + * * Redistributions of source code must retain the above + * copyright notice, this list of conditions and the + * following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the + * following disclaimer in the documetation and/or other + * materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include <ntddk.h> +#include <procgrp.h> +#include <ntstrsafe.h> +#include <stdarg.h> +#include <stdlib.h> +#include <xen.h> + +#include <debug_interface.h> +#include <store_interface.h> +#include <cache_interface.h> +#include <gnttab_interface.h> +#include <evtchn_interface.h> + +#include "pdo.h" +#include "frontend.h" +#include "controller.h" +#include "vif.h" +#include "thread.h" +#include "registry.h" +#include "dbg_print.h" +#include "assert.h" +#include "util.h" + +extern ULONG +NTAPI +RtlRandomEx ( + __inout PULONG Seed + ); + +#define MAXNAMELEN 128 + +struct _XENVIF_CONTROLLER { + PXENVIF_FRONTEND Frontend; + KSPIN_LOCK Lock; + PXENBUS_GNTTAB_CACHE GnttabCache; + PMDL Mdl; + xen_netif_ctrl_front_ring_t Front; + xen_netif_ctrl_sring_t *Shared; + PXENBUS_GNTTAB_ENTRY Entry; + PXENBUS_EVTCHN_CHANNEL Channel; + KDPC Dpc; + ULONG Dpcs; + ULONG Events; + BOOLEAN Connected; + BOOLEAN Enabled; + USHORT RequestId; + struct xen_netif_ctrl_request Request; + struct xen_netif_ctrl_response Response; + XENBUS_GNTTAB_INTERFACE GnttabInterface; + XENBUS_EVTCHN_INTERFACE EvtchnInterface; + XENBUS_STORE_INTERFACE StoreInterface; + XENBUS_DEBUG_INTERFACE DebugInterface; + PXENBUS_DEBUG_CALLBACK DebugCallback; + PXENVIF_THREAD WatchdogThread; +}; + +#define XENVIF_CONTROLLER_TAG 'TNOC' + +static FORCEINLINE PVOID +__ControllerAllocate( + IN ULONG Length + ) +{ + return __AllocatePoolWithTag(NonPagedPool, Length, XENVIF_CONTROLLER_TAG); +} + +static FORCEINLINE VOID +__ControllerFree( + IN PVOID Buffer + ) +{ + __FreePoolWithTag(Buffer, XENVIF_CONTROLLER_TAG); +} + +static FORCEINLINE VOID +__drv_requiresIRQL(DISPATCH_LEVEL) +__ControllerAcquireLock( + IN PXENVIF_CONTROLLER Controller + ) +{ + ASSERT3U(KeGetCurrentIrql(), ==, DISPATCH_LEVEL); + + KeAcquireSpinLockAtDpcLevel(&Controller->Lock); +} + +static FORCEINLINE VOID +__drv_requiresIRQL(DISPATCH_LEVEL) +__ControllerReleaseLock( + IN PXENVIF_CONTROLLER Controller + ) +{ + KeReleaseSpinLockFromDpcLevel(&Controller->Lock); +} + +static VOID +ControllerAcquireLock( + IN PXENVIF_CONTROLLER Controller + ) +{ + __ControllerAcquireLock(Controller); +} + +static VOID +ControllerReleaseLock( + IN PXENVIF_CONTROLLER Controller + ) +{ + __ControllerReleaseLock(Controller); +} + +static FORCEINLINE VOID +__ControllerSend( + IN PXENVIF_CONTROLLER Controller + ) +{ + (VOID) XENBUS_EVTCHN(Send, + &Controller->EvtchnInterface, + Controller->Channel); +} + +VOID +ControllerPoll( + IN PXENVIF_CONTROLLER Controller + ) +{ + RING_IDX rsp_prod; + RING_IDX rsp_cons; + struct xen_netif_ctrl_response *rsp; + + KeMemoryBarrier(); + + rsp_prod = Controller->Shared->rsp_prod; + rsp_cons = Controller->Front.rsp_cons; + + KeMemoryBarrier(); + + if (rsp_cons == rsp_prod) + return; + + rsp = RING_GET_RESPONSE(&Controller->Front, rsp_cons); + rsp_cons++; + + Controller->Response = *rsp; + + KeMemoryBarrier(); + + Controller->Front.rsp_cons = rsp_cons; + Controller->Shared->rsp_event = rsp_cons + 1; +} + +static NTSTATUS +ControllerPutRequest( + IN PXENVIF_CONTROLLER Controller, + IN USHORT Type, + IN ULONG Data0, + IN ULONG Data1, + IN ULONG Data2 + ) +{ + RING_IDX req_prod; + struct xen_netif_ctrl_request *req; + BOOLEAN Notify; + NTSTATUS status; + + status = STATUS_INSUFFICIENT_RESOURCES; + if (RING_FULL(&Controller->Front)) + goto fail1; + + Controller->Request.type = Type; + Controller->Request.id = Controller->RequestId++; + Controller->Request.data[0] = Data0; + Controller->Request.data[1] = Data1; + Controller->Request.data[2] = Data2; + + req_prod = Controller->Front.req_prod_pvt; + + req = RING_GET_REQUEST(&Controller->Front, req_prod); + req_prod++; + + *req = Controller->Request; + + KeMemoryBarrier(); + + Controller->Front.req_prod_pvt = req_prod; + +#pragma warning (push) +#pragma warning (disable:4244) + + // Make the requests visible to the backend + RING_PUSH_REQUESTS_AND_CHECK_NOTIFY(&Controller->Front, Notify); + +#pragma warning (pop) + + if (Notify) + __ControllerSend(Controller); + + return STATUS_SUCCESS; + +fail1: + Error("fail1 (%08x)\n", status); + + return status; +} + +#define TIME_US(_us) ((_us) * 10) +#define TIME_MS(_ms) (TIME_US((_ms) * 1000)) +#define TIME_S(_s) (TIME_MS((_s) * 1000)) +#define TIME_RELATIVE(_t) (-(_t)) + +#define XENVIF_CONTROLLER_POLL_PERIOD 5 + +static NTSTATUS +ControllerGetResponse( + IN PXENVIF_CONTROLLER Controller, + OUT PULONG Data OPTIONAL + ) +{ + LARGE_INTEGER Timeout; + NTSTATUS status; + + Timeout.QuadPart = TIME_RELATIVE(TIME_S(XENVIF_CONTROLLER_POLL_PERIOD)); + + for (;;) { + ControllerPoll(Controller); + KeMemoryBarrier(); + + if (Controller->Response.id == Controller->Request.id) + break; + + status = XENBUS_EVTCHN(Wait, + &Controller->EvtchnInterface, + Controller->Channel, + &Timeout); + if (status == STATUS_TIMEOUT) + Warning("TIMED OUT\n"); + } + + ASSERT3U(Controller->Response.type, ==, Controller->Request.type); + + switch (Controller->Response.status) { + case XEN_NETIF_CTRL_STATUS_SUCCESS: + status = STATUS_SUCCESS; + break; + + case XEN_NETIF_CTRL_STATUS_NOT_SUPPORTED: + status = STATUS_NOT_SUPPORTED; + break; + + case XEN_NETIF_CTRL_STATUS_INVALID_PARAMETER: + status = STATUS_INVALID_PARAMETER; + break; + + case XEN_NETIF_CTRL_STATUS_BUFFER_OVERFLOW: + status = STATUS_BUFFER_OVERFLOW; + break; + + default: + status = STATUS_UNSUCCESSFUL; + break; + } + + if (NT_SUCCESS(status) && Data != NULL) + *Data = Controller->Response.data; + + RtlZeroMemory(&Controller->Request, + sizeof (struct xen_netif_ctrl_request)); + RtlZeroMemory(&Controller->Response, + sizeof (struct xen_netif_ctrl_response)); + + return status; +} + +#define XENVIF_CONTROLLER_WATCHDOG_PERIOD 15 + +static NTSTATUS +ControllerWatchdog( + IN PXENVIF_THREAD Self, + IN PVOID Context + ) +{ + PXENVIF_CONTROLLER Controller = Context; + LARGE_INTEGER Timeout; + RING_IDX rsp_prod; + RING_IDX rsp_cons; + + Trace("====>\n"); + + Timeout.QuadPart = TIME_RELATIVE(TIME_S(XENVIF_CONTROLLER_WATCHDOG_PERIOD)); + + rsp_prod = 0; + rsp_cons = 0; + + for (;;) { + PKEVENT Event; + KIRQL Irql; + + Event = ThreadGetEvent(Self); + + (VOID) KeWaitForSingleObject(Event, + Executive, + KernelMode, + FALSE, + &Timeout); + KeClearEvent(Event); + + if (ThreadIsAlerted(Self)) + break; + + KeRaiseIrql(DISPATCH_LEVEL, &Irql); + __ControllerAcquireLock(Controller); + + if (Controller->Enabled) { + KeMemoryBarrier(); + + if (Controller->Shared->rsp_prod != rsp_prod && + Controller->Front.rsp_cons == rsp_cons) { + XENBUS_DEBUG(Trigger, + &Controller->DebugInterface, + Controller->DebugCallback); + + // Try to move things along + ControllerPoll(Controller); + __ControllerSend(Controller); + } + + KeMemoryBarrier(); + + rsp_prod = Controller->Shared->rsp_prod; + rsp_cons = Controller->Front.rsp_cons; + } + + __ControllerReleaseLock(Controller); + KeLowerIrql(Irql); + } + + Trace("<====\n"); + + return STATUS_SUCCESS; +} + +__drv_maxIRQL(DISPATCH_LEVEL) +__drv_minIRQL(DISPATCH_LEVEL) +__drv_requiresIRQL(DISPATCH_LEVEL) +__drv_sameIRQL +static VOID +ControllerDpc( + IN PKDPC Dpc, + IN PVOID Context, + IN PVOID Argument1, + IN PVOID Argument2 + ) +{ + PXENVIF_CONTROLLER Controller = Context; + + UNREFERENCED_PARAMETER(Dpc); + UNREFERENCED_PARAMETER(Argument1); + UNREFERENCED_PARAMETER(Argument2); + + ASSERT(Controller != NULL); + + __ControllerAcquireLock(Controller); + + if (Controller->Enabled) + ControllerPoll(Controller); + + __ControllerReleaseLock(Controller); +} + +KSERVICE_ROUTINE TransmitterRingEvtchnCallback; + +BOOLEAN +ControllerEvtchnCallback( + IN PKINTERRUPT InterruptObject, + IN PVOID Argument + ) +{ + PXENVIF_CONTROLLER Controller = Argument; + + UNREFERENCED_PARAMETER(InterruptObject); + + ASSERT(Controller != NULL); + + Controller->Events++; + + if (KeInsertQueueDpc(&Controller->Dpc, NULL, NULL)) + Controller->Dpcs++; + + return TRUE; +} + +static VOID +ControllerDebugCallback( + IN PVOID Argument, + IN BOOLEAN Crashing + ) +{ + UNREFERENCED_PARAMETER(Argument); + UNREFERENCED_PARAMETER(Crashing); +} + +NTSTATUS +ControllerInitialize( + IN PXENVIF_FRONTEND Frontend, + OUT PXENVIF_CONTROLLER *Controller + ) +{ + LARGE_INTEGER Now; + ULONG Seed; + NTSTATUS status; + + *Controller = __ControllerAllocate(sizeof (XENVIF_CONTROLLER)); + + status = STATUS_NO_MEMORY; + if (*Controller == NULL) + goto fail1; + + FdoGetDebugInterface(PdoGetFdo(FrontendGetPdo(Frontend)), + &(*Controller)->DebugInterface); + + FdoGetStoreInterface(PdoGetFdo(FrontendGetPdo(Frontend)), + &(*Controller)->StoreInterface); + + FdoGetGnttabInterface(PdoGetFdo(FrontendGetPdo(Frontend)), + &(*Controller)->GnttabInterface); + + FdoGetEvtchnInterface(PdoGetFdo(FrontendGetPdo(Frontend)), + &(*Controller)->EvtchnInterface); + + KeInitializeSpinLock(&(*Controller)->Lock); + KeInitializeDpc(&(*Controller)->Dpc, ControllerDpc, *Controller); + + KeQuerySystemTime(&Now); + Seed = Now.LowPart; + + (*Controller)->RequestId = (USHORT)RtlRandomEx(&Seed); + + status = ThreadCreate(ControllerWatchdog, + *Controller, + &(*Controller)->WatchdogThread); + if (!NT_SUCCESS(status)) + goto fail2; + + (*Controller)->Frontend = Frontend; + + return STATUS_SUCCESS; + +fail2: + Error("fail2\n"); + + RtlZeroMemory(&(*Controller)->Lock, + sizeof (KSPIN_LOCK)); + + RtlZeroMemory(&(*Controller)->GnttabInterface, + sizeof (XENBUS_GNTTAB_INTERFACE)); + + RtlZeroMemory(&(*Controller)->StoreInterface, + sizeof (XENBUS_STORE_INTERFACE)); + + RtlZeroMemory(&(*Controller)->DebugInterface, + sizeof (XENBUS_DEBUG_INTERFACE)); + + RtlZeroMemory(&(*Controller)->EvtchnInterface, + sizeof (XENBUS_EVTCHN_INTERFACE)); + +fail1: + Error("fail1 (%08x)\n", status); + + return status; +} + +NTSTATUS +ControllerConnect( + IN PXENVIF_CONTROLLER Controller + ) +{ + PXENVIF_FRONTEND Frontend; + PCHAR Buffer; + BOOLEAN Feature; + PFN_NUMBER Pfn; + CHAR Name[MAXNAMELEN]; + ULONG Index; + NTSTATUS status; + + Trace("====>\n"); + + Frontend = Controller->Frontend; + + status = XENBUS_DEBUG(Acquire, &Controller->DebugInterface); + if (!NT_SUCCESS(status)) + goto fail1; + + status = XENBUS_STORE(Acquire, &Controller->StoreInterface); + if (!NT_SUCCESS(status)) + goto fail2; + + status = XENBUS_EVTCHN(Acquire, &Controller->EvtchnInterface); + if (!NT_SUCCESS(status)) + goto fail3; + + status = XENBUS_GNTTAB(Acquire, &Controller->GnttabInterface); + if (!NT_SUCCESS(status)) + goto fail4; + + status = XENBUS_STORE(Read, + &Controller->StoreInterface, + NULL, + FrontendGetBackendPath(Frontend), + "feature-ctrl-ring", + &Buffer); + if (!NT_SUCCESS(status)) { + Feature = FALSE; + } else { + Feature = (BOOLEAN)strtol(Buffer, NULL, 2); + + XENBUS_STORE(Free, + &Controller->StoreInterface, + Buffer); + } + + if (!Feature) + goto done; + + status = RtlStringCbPrintfA(Name, + sizeof (Name), + "%s_controller", + FrontendGetPath(Frontend)); + if (!NT_SUCCESS(status)) + goto fail5; + + for (Index = 0; Name[Index] != '\0'; Index++) + if (Name[Index] == '/') + Name[Index] = '_'; + + status = XENBUS_GNTTAB(CreateCache, + &Controller->GnttabInterface, + Name, + 0, + ControllerAcquireLock, + ControllerReleaseLock, + Controller, + &Controller->GnttabCache); + if (!NT_SUCCESS(status)) + goto fail6; + + Controller->Mdl = __AllocatePage(); + + status = STATUS_NO_MEMORY; + if (Controller->Mdl == NULL) + goto fail7; + + Controller->Shared = MmGetSystemAddressForMdlSafe(Controller->Mdl, + NormalPagePriority); + ASSERT(Controller->Shared != NULL); + + SHARED_RING_INIT(Controller->Shared); + FRONT_RING_INIT(&Controller->Front, Controller->Shared, PAGE_SIZE); + ASSERT3P(Controller->Front.sring, ==, Controller->Shared); + + Pfn = MmGetMdlPfnArray(Controller->Mdl)[0]; + + status = XENBUS_GNTTAB(PermitForeignAccess, + &Controller->GnttabInterface, + Controller->GnttabCache, + TRUE, + FrontendGetBackendDomain(Frontend), + Pfn, + FALSE, + &Controller->Entry); + if (!NT_SUCCESS(status)) + goto fail8; + + Controller->Channel = XENBUS_EVTCHN(Open, + &Controller->EvtchnInterface, + XENBUS_EVTCHN_TYPE_UNBOUND, + ControllerEvtchnCallback, + Controller, + FrontendGetBackendDomain(Frontend), + FALSE); + + status = STATUS_UNSUCCESSFUL; + if (Controller->Channel == NULL) + goto fail9; + + XENBUS_EVTCHN(Unmask, + &Controller->EvtchnInterface, + Controller->Channel, + FALSE); + + status = XENBUS_DEBUG(Register, + &Controller->DebugInterface, + __MODULE__ "|CONTROLLER", + ControllerDebugCallback, + Controller, + &Controller->DebugCallback); + if (!NT_SUCCESS(status)) + goto fail10; + + __ControllerAcquireLock(Controller); + + Controller->Connected = TRUE; + + if (KeInsertQueueDpc(&Controller->Dpc, NULL, NULL)) + Controller->Dpcs++; + + __ControllerReleaseLock(Controller); + +done: + Trace("<====\n"); + return STATUS_SUCCESS; + +fail10: + Error("fail10\n"); + + XENBUS_EVTCHN(Close, + &Controller->EvtchnInterface, + Controller->Channel); + Controller->Channel = NULL; + + Controller->Events = 0; + Controller->Dpcs = 0; + +fail9: + Error("fail9\n"); + + (VOID) XENBUS_GNTTAB(RevokeForeignAccess, + &Controller->GnttabInterface, + Controller->GnttabCache, + TRUE, + Controller->Entry); + Controller->Entry = NULL; + +fail8: + Error("fail8\n"); + + RtlZeroMemory(&Controller->Front, + sizeof (struct xen_netif_ctrl_front_ring)); + RtlZeroMemory(Controller->Shared, PAGE_SIZE); + + Controller->Shared = NULL; + __FreePage(Controller->Mdl); + Controller->Mdl = NULL; + +fail7: + Error("fail7\n"); + + XENBUS_GNTTAB(DestroyCache, + &Controller->GnttabInterface, + Controller->GnttabCache); + Controller->GnttabCache = NULL; + +fail6: + Error("fail6\n"); + +fail5: + Error("fail5\n"); + + XENBUS_GNTTAB(Release, &Controller->GnttabInterface); + +fail4: + Error("fail4\n"); + + XENBUS_EVTCHN(Release, &Controller->EvtchnInterface); + +fail3: + Error("fail3\n"); + + XENBUS_STORE(Release, &Controller->StoreInterface); + +fail2: + Error("fail2\n"); + + XENBUS_DEBUG(Release, &Controller->DebugInterface); + +fail1: + Error("fail1 (%08x)\n", status); + + return status; +} + +NTSTATUS +ControllerStoreWrite( + IN PXENVIF_CONTROLLER Controller, + IN PXENBUS_STORE_TRANSACTION Transaction + ) +{ + PXENVIF_FRONTEND Frontend; + ULONG Port; + NTSTATUS status; + + if (!Controller->Connected) + goto done; + + Frontend = Controller->Frontend; + + status = XENBUS_STORE(Printf, + &Controller->StoreInterface, + Transaction, + FrontendGetPath(Frontend), + "ctrl-ring-ref", + "%u", + XENBUS_GNTTAB(GetReference, + &Controller->GnttabInterface, + Controller->Entry)); + if (!NT_SUCCESS(status)) + goto fail1; + + Port = XENBUS_EVTCHN(GetPort, + &Controller->EvtchnInterface, + Controller->Channel); + + status = XENBUS_STORE(Printf, + &Controller->StoreInterface, + Transaction, + FrontendGetPath(Frontend), + "event-channel-ctrl", + "%u", + Port); + if (!NT_SUCCESS(status)) + goto fail2; + +done: + return STATUS_SUCCESS; + +fail2: + Error("fail2\n"); + +fail1: + Error("fail1 (%08x)\n", status); + + return status; +} + +VOID +ControllerEnable( + IN PXENVIF_CONTROLLER Controller + ) +{ + Trace("====>\n"); + + __ControllerAcquireLock(Controller); + + Controller->Enabled = TRUE; + + __ControllerReleaseLock(Controller); + + Trace("<====\n"); +} + +VOID +ControllerDisable( + IN PXENVIF_CONTROLLER Controller + ) +{ + Trace("====>\n"); + + __ControllerAcquireLock(Controller); + + Controller->Enabled = FALSE; + + __ControllerReleaseLock(Controller); + + Trace("<====\n"); +} + +VOID +ControllerDisconnect( + IN PXENVIF_CONTROLLER Controller + ) +{ + Trace("====>\n"); + + __ControllerAcquireLock(Controller); + + if (!Controller->Connected) + goto done; + + Controller->Connected = FALSE; + + __ControllerReleaseLock(Controller); + + XENBUS_DEBUG(Deregister, + &Controller->DebugInterface, + Controller->DebugCallback); + Controller->DebugCallback = NULL; + + XENBUS_EVTCHN(Close, + &Controller->EvtchnInterface, + Controller->Channel); + Controller->Channel = NULL; + + Controller->Events = 0; + Controller->Dpcs = 0; + + (VOID) XENBUS_GNTTAB(RevokeForeignAccess, + &Controller->GnttabInterface, + Controller->GnttabCache, + TRUE, + Controller->Entry); + Controller->Entry = NULL; + + RtlZeroMemory(&Controller->Front, + sizeof (struct xen_netif_ctrl_front_ring)); + RtlZeroMemory(Controller->Shared, PAGE_SIZE); + + Controller->Shared = NULL; + __FreePage(Controller->Mdl); + Controller->Mdl = NULL; + + XENBUS_GNTTAB(DestroyCache, + &Controller->GnttabInterface, + Controller->GnttabCache); + Controller->GnttabCache = NULL; + + XENBUS_GNTTAB(Release, &Controller->GnttabInterface); + + XENBUS_EVTCHN(Release, &Controller->EvtchnInterface); + + XENBUS_STORE(Release, &Controller->StoreInterface); + + XENBUS_DEBUG(Release, &Controller->DebugInterface); + +done: + Trace("<====\n"); +} + +VOID +ControllerTeardown( + IN PXENVIF_CONTROLLER Controller + ) +{ + ASSERT3U(KeGetCurrentIrql(), ==, PASSIVE_LEVEL); + KeFlushQueuedDpcs(); + + Controller->Frontend = NULL; + + ThreadAlert(Controller->WatchdogThread); + ThreadJoin(Controller->WatchdogThread); + Controller->WatchdogThread = NULL; + + Controller->RequestId = 0; + + RtlZeroMemory(&Controller->Dpc, + sizeof (KDPC)); + + RtlZeroMemory(&Controller->Lock, + sizeof (KSPIN_LOCK)); + + RtlZeroMemory(&Controller->GnttabInterface, + sizeof (XENBUS_GNTTAB_INTERFACE)); + + RtlZeroMemory(&Controller->StoreInterface, + sizeof (XENBUS_STORE_INTERFACE)); + + RtlZeroMemory(&Controller->DebugInterface, + sizeof (XENBUS_DEBUG_INTERFACE)); + + RtlZeroMemory(&Controller->EvtchnInterface, + sizeof (XENBUS_EVTCHN_INTERFACE)); + + ASSERT(IsZeroMemory(Controller, sizeof (XENVIF_CONTROLLER))); + __ControllerFree(Controller); +} + +NTSTATUS +ControllerSetHashAlgorithm( + IN PXENVIF_CONTROLLER Controller, + IN ULONG Algorithm + ) +{ + PXENVIF_FRONTEND Frontend; + NTSTATUS status; + + Frontend = Controller->Frontend; + + __ControllerAcquireLock(Controller); + + status = STATUS_NOT_SUPPORTED; + if (!Controller->Connected) + goto fail1; + + status = ControllerPutRequest(Controller, + XEN_NETIF_CTRL_TYPE_SET_HASH_ALGORITHM, + Algorithm, + 0, + 0); + if (!NT_SUCCESS(status)) + goto fail2; + + status = ControllerGetResponse(Controller, NULL); + if (!NT_SUCCESS(status)) + goto fail3; + + __ControllerReleaseLock(Controller); + + return STATUS_SUCCESS; + +fail3: + Error("fail3\n"); + +fail2: + Error("fail2\n"); + +fail1: + Error("fail1 (%08x)\n", status); + + __ControllerReleaseLock(Controller); + + return status; +} + +NTSTATUS +ControllerGetHashFlags( + IN PXENVIF_CONTROLLER Controller, + IN PULONG Flags + ) +{ + PXENVIF_FRONTEND Frontend; + NTSTATUS status; + + Frontend = Controller->Frontend; + + __ControllerAcquireLock(Controller); + + status = STATUS_NOT_SUPPORTED; + if (!Controller->Enabled) + goto fail1; + + status = ControllerPutRequest(Controller, + XEN_NETIF_CTRL_TYPE_GET_HASH_FLAGS, + 0, + 0, + 0); + if (!NT_SUCCESS(status)) + goto fail2; + + status = ControllerGetResponse(Controller, Flags); + if (!NT_SUCCESS(status)) + goto fail3; + + __ControllerReleaseLock(Controller); + + return STATUS_SUCCESS; + +fail3: + Error("fail3\n"); + +fail2: + Error("fail2\n"); + +fail1: + Error("fail1 (%08x)\n", status); + + __ControllerReleaseLock(Controller); + + return status; +} + +NTSTATUS +ControllerSetHashFlags( + IN PXENVIF_CONTROLLER Controller, + IN ULONG Flags + ) +{ + PXENVIF_FRONTEND Frontend; + NTSTATUS status; + + Frontend = Controller->Frontend; + + __ControllerAcquireLock(Controller); + + status = STATUS_NOT_SUPPORTED; + if (!Controller->Connected) + goto fail1; + + status = ControllerPutRequest(Controller, + XEN_NETIF_CTRL_TYPE_SET_HASH_FLAGS, + Flags, + 0, + 0); + if (!NT_SUCCESS(status)) + goto fail2; + + status = ControllerGetResponse(Controller, NULL); + if (!NT_SUCCESS(status)) + goto fail3; + + __ControllerReleaseLock(Controller); + + return STATUS_SUCCESS; + +fail3: + Error("fail3\n"); + +fail2: + Error("fail2\n"); + +fail1: + Error("fail1 (%08x)\n", status); + + __ControllerReleaseLock(Controller); + + return status; +} + +NTSTATUS +ControllerSetHashKey( + IN PXENVIF_CONTROLLER Controller, + IN PUCHAR Key, + IN ULONG Size + ) +{ + PXENVIF_FRONTEND Frontend; + PMDL Mdl; + PUCHAR Buffer; + PFN_NUMBER Pfn; + PXENBUS_GNTTAB_ENTRY Entry; + NTSTATUS status; + + Frontend = Controller->Frontend; + + __ControllerAcquireLock(Controller); + + status = STATUS_NOT_SUPPORTED; + if (!Controller->Enabled) + goto fail1; + + Mdl = __AllocatePage(); + + status = STATUS_NO_MEMORY; + if (Controller->Mdl == NULL) + goto fail2; + + Buffer = MmGetSystemAddressForMdlSafe(Mdl, NormalPagePriority); + ASSERT(Buffer != NULL); + + RtlCopyMemory(Buffer, Key, Size); + + Pfn = MmGetMdlPfnArray(Mdl)[0]; + + status = XENBUS_GNTTAB(PermitForeignAccess, + &Controller->GnttabInterface, + Controller->GnttabCache, + TRUE, + FrontendGetBackendDomain(Frontend), + Pfn, + FALSE, + &Entry); + if (!NT_SUCCESS(status)) + goto fail3; + + status = ControllerPutRequest(Controller, + XEN_NETIF_CTRL_TYPE_SET_HASH_KEY, + XENBUS_GNTTAB(GetReference, + &Controller->GnttabInterface, + Entry), + Size, + 0); + if (!NT_SUCCESS(status)) + goto fail4; + + status = ControllerGetResponse(Controller, NULL); + if (!NT_SUCCESS(status)) + goto fail5; + + (VOID) XENBUS_GNTTAB(RevokeForeignAccess, + &Controller->GnttabInterface, + Controller->GnttabCache, + TRUE, + Entry); + + __FreePage(Mdl); + + __ControllerReleaseLock(Controller); + + return STATUS_SUCCESS; + +fail5: + Error("fail5\n"); + +fail4: + Error("fail4\n"); + + (VOID) XENBUS_GNTTAB(RevokeForeignAccess, + &Controller->GnttabInterface, + Controller->GnttabCache, + TRUE, + Entry); + +fail3: + Error("fail3\n"); + + __FreePage(Mdl); + +fail2: + Error("fail2\n"); + +fail1: + Error("fail1 (%08x)\n", status); + + __ControllerReleaseLock(Controller); + + return status; +} + +NTSTATUS +ControllerGetHashMappingSize( + IN PXENVIF_CONTROLLER Controller, + IN PULONG Size + ) +{ + PXENVIF_FRONTEND Frontend; + NTSTATUS status; + + Frontend = Controller->Frontend; + + __ControllerAcquireLock(Controller); + + status = STATUS_NOT_SUPPORTED; + if (!Controller->Enabled) + goto fail1; + + status = ControllerPutRequest(Controller, + XEN_NETIF_CTRL_TYPE_GET_HASH_MAPPING_SIZE, + 0, + 0, + 0); + if (!NT_SUCCESS(status)) + goto fail2; + + status = ControllerGetResponse(Controller, Size); + if (!NT_SUCCESS(status)) + goto fail3; + + __ControllerReleaseLock(Controller); + + return STATUS_SUCCESS; + +fail3: + Error("fail3\n"); + +fail2: + Error("fail2\n"); + +fail1: + Error("fail1 (%08x)\n", status); + + __ControllerReleaseLock(Controller); + + return status; +} + +NTSTATUS +ControllerSetHashMappingSize( + IN PXENVIF_CONTROLLER Controller, + IN ULONG Size + ) +{ + PXENVIF_FRONTEND Frontend; + NTSTATUS status; + + Frontend = Controller->Frontend; + + __ControllerAcquireLock(Controller); + + status = STATUS_NOT_SUPPORTED; + if (!Controller->Enabled) + goto fail1; + + status = ControllerPutRequest(Controller, + XEN_NETIF_CTRL_TYPE_SET_HASH_MAPPING_SIZE, + Size, + 0, + 0); + if (!NT_SUCCESS(status)) + goto fail2; + + status = ControllerGetResponse(Controller, NULL); + if (!NT_SUCCESS(status)) + goto fail3; + + __ControllerReleaseLock(Controller); + + return STATUS_SUCCESS; + +fail3: + Error("fail3\n"); + +fail2: + Error("fail2\n"); + +fail1: + Error("fail1 (%08x)\n", status); + + __ControllerReleaseLock(Controller); + + return status; +} + +NTSTATUS +ControllerSetHashMapping( + IN PXENVIF_CONTROLLER Controller, + IN PULONG Mapping, + IN ULONG Size, + IN ULONG Offset + ) +{ + PXENVIF_FRONTEND Frontend; + PMDL Mdl; + PUCHAR Buffer; + PFN_NUMBER Pfn; + PXENBUS_GNTTAB_ENTRY Entry; + NTSTATUS status; + + Frontend = Controller->Frontend; + + __ControllerAcquireLock(Controller); + + status = STATUS_NOT_SUPPORTED; + if (!Controller->Enabled) + goto fail1; + + status = STATUS_INVALID_PARAMETER; + if (Size * sizeof (ULONG) > PAGE_SIZE) + goto fail2; + + Mdl = __AllocatePage(); + + status = STATUS_NO_MEMORY; + if (Controller->Mdl == NULL) + goto fail3; + + Buffer = MmGetSystemAddressForMdlSafe(Mdl, NormalPagePriority); + ASSERT(Buffer != NULL); + + RtlCopyMemory(Buffer, Mapping, Size * sizeof (ULONG)); + + Pfn = MmGetMdlPfnArray(Mdl)[0]; + + status = XENBUS_GNTTAB(PermitForeignAccess, + &Controller->GnttabInterface, + Controller->GnttabCache, + TRUE, + FrontendGetBackendDomain(Frontend), + Pfn, + FALSE, + &Entry); + if (!NT_SUCCESS(status)) + goto fail4; + + status = ControllerPutRequest(Controller, + XEN_NETIF_CTRL_TYPE_SET_HASH_MAPPING, + XENBUS_GNTTAB(GetReference, + &Controller->GnttabInterface, + Entry), + Size, + Offset); + if (!NT_SUCCESS(status)) + goto fail5; + + status = ControllerGetResponse(Controller, NULL); + if (!NT_SUCCESS(status)) + goto fail6; + + (VOID) XENBUS_GNTTAB(RevokeForeignAccess, + &Controller->GnttabInterface, + Controller->GnttabCache, + TRUE, + Entry); + + __FreePage(Mdl); + + __ControllerReleaseLock(Controller); + + return STATUS_SUCCESS; + +fail6: + Error("fail6\n"); + +fail5: + Error("fail5\n"); + + (VOID) XENBUS_GNTTAB(RevokeForeignAccess, + &Controller->GnttabInterface, + Controller->GnttabCache, + TRUE, + Entry); + +fail4: + Error("fail4\n"); + + __FreePage(Mdl); + +fail3: + Error("fail3\n"); + +fail2: + Error("fail2\n"); + +fail1: + Error("fail1 (%08x)\n", status); + + __ControllerReleaseLock(Controller); + + return status; +} diff --git a/src/xenvif/controller.h b/src/xenvif/controller.h new file mode 100644 index 0000000..5a7b688 --- /dev/null +++ b/src/xenvif/controller.h @@ -0,0 +1,126 @@ +/* Copyright (c) Citrix Systems Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, + * with or without modification, are permitted provided + * that the following conditions are met: + * + * * Redistributions of source code must retain the above + * copyright notice, this list of conditions and the + * following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the + * following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef _XENVIF_CONTROLLER_H +#define _XENVIF_CONTROLLER_H + +#include <ntddk.h> + +#include <vif_interface.h> + +#include "frontend.h" + +typedef struct _XENVIF_CONTROLLER XENVIF_CONTROLLER, *PXENVIF_CONTROLLER; + +extern NTSTATUS +ControllerInitialize( + IN PXENVIF_FRONTEND Frontend, + OUT PXENVIF_CONTROLLER *Controller + ); + +extern NTSTATUS +ControllerConnect( + IN PXENVIF_CONTROLLER Controller + ); + +extern NTSTATUS +ControllerStoreWrite( + IN PXENVIF_CONTROLLER Controller, + IN PXENBUS_STORE_TRANSACTION Transaction + ); + +extern VOID +ControllerEnable( + IN PXENVIF_CONTROLLER Controller + ); + +extern VOID +ControllerDisable( + IN PXENVIF_CONTROLLER Controller + ); + +extern VOID +ControllerDisconnect( + IN PXENVIF_CONTROLLER Controller + ); + +extern VOID +ControllerTeardown( + IN PXENVIF_CONTROLLER Controller + ); + +extern NTSTATUS +ControllerSetHashAlgorithm( + IN PXENVIF_CONTROLLER Controller, + IN ULONG Algorithm + ); + +extern NTSTATUS +ControllerGetHashFlags( + IN PXENVIF_CONTROLLER Controller, + IN PULONG Flags + ); + +extern NTSTATUS +ControllerSetHashFlags( + IN PXENVIF_CONTROLLER Controller, + IN ULONG Flags + ); + +extern NTSTATUS +ControllerSetHashKey( + IN PXENVIF_CONTROLLER Controller, + IN PUCHAR Key, + IN ULONG Size + ); + +extern NTSTATUS +ControllerGetHashMappingSize( + IN PXENVIF_CONTROLLER Controller, + IN PULONG Size + ); + +extern NTSTATUS +ControllerSetHashMappingSize( + IN PXENVIF_CONTROLLER Controller, + IN ULONG Size + ); + +extern NTSTATUS +ControllerSetHashMapping( + IN PXENVIF_CONTROLLER Controller, + IN PULONG Mapping, + IN ULONG Size, + IN ULONG Offset + ); + + +#endif // _XENVIF_CONTROLLER_H diff --git a/src/xenvif/frontend.c b/src/xenvif/frontend.c index 5a29736..e950552 100644 --- a/src/xenvif/frontend.c +++ b/src/xenvif/frontend.c @@ -76,6 +76,7 @@ struct _XENVIF_FRONTEND { PXENVIF_MAC Mac; PXENVIF_RECEIVER Receiver; PXENVIF_TRANSMITTER Transmitter; + PXENVIF_CONTROLLER Controller; XENBUS_DEBUG_INTERFACE DebugInterface; XENBUS_SUSPEND_INTERFACE SuspendInterface; @@ -323,8 +324,9 @@ FrontendGet ## _Function( \ } DEFINE_FRONTEND_GET_FUNCTION(Mac, PXENVIF_MAC) -DEFINE_FRONTEND_GET_FUNCTION(Transmitter, PXENVIF_TRANSMITTER) DEFINE_FRONTEND_GET_FUNCTION(Receiver, PXENVIF_RECEIVER) +DEFINE_FRONTEND_GET_FUNCTION(Transmitter, PXENVIF_TRANSMITTER) +DEFINE_FRONTEND_GET_FUNCTION(Controller, PXENVIF_CONTROLLER) static BOOLEAN FrontendIsOnline( @@ -1834,6 +1836,10 @@ FrontendConnect( if (!NT_SUCCESS(status)) goto fail6; + status = ControllerConnect(__FrontendGetController(Frontend)); + if (!NT_SUCCESS(status)) + goto fail7; + Attempt = 0; do { PXENBUS_STORE_TRANSACTION Transaction; @@ -1854,6 +1860,11 @@ FrontendConnect( if (!NT_SUCCESS(status)) goto abort; + status = ControllerStoreWrite(__FrontendGetController(Frontend), + Transaction); + if (!NT_SUCCESS(status)) + goto abort; + status = XENBUS_STORE(Printf, &Frontend->StoreInterface, Transaction, @@ -1882,7 +1893,7 @@ abort: } while (status == STATUS_RETRY); if (!NT_SUCCESS(status)) - goto fail7; + goto fail8; State = XenbusStateUnknown; while (State != XenbusStateConnected) { @@ -1920,16 +1931,23 @@ abort: status = STATUS_UNSUCCESSFUL; if (State != XenbusStateConnected) - goto fail8; + goto fail9; + + ControllerEnable(__FrontendGetController(Frontend)); ThreadWake(Frontend->MibThread); Trace("<====\n"); return STATUS_SUCCESS; +fail9: + Error("fail9\n"); + fail8: Error("fail8\n"); + ControllerDisconnect(__FrontendGetController(Frontend)); + fail7: Error("fail7\n"); @@ -1982,6 +2000,9 @@ FrontendDisconnect( { Trace("====>\n"); + ControllerDisable(__FrontendGetController(Frontend)); + + ControllerDisconnect(__FrontendGetController(Frontend)); TransmitterDisconnect(__FrontendGetTransmitter(Frontend)); ReceiverDisconnect(__FrontendGetReceiver(Frontend)); MacDisconnect(__FrontendGetMac(Frontend)); @@ -2453,32 +2474,40 @@ FrontendInitialize( if (!NT_SUCCESS(status)) goto fail8; + status = ControllerInitialize(*Frontend, &(*Frontend)->Controller); + if (!NT_SUCCESS(status)) + goto fail9; + KeInitializeEvent(&(*Frontend)->EjectEvent, NotificationEvent, FALSE); status = ThreadCreate(FrontendEject, *Frontend, &(*Frontend)->EjectThread); if (!NT_SUCCESS(status)) - goto fail9; + goto fail10; status = ThreadCreate(FrontendMib, *Frontend, &(*Frontend)->MibThread); if (!NT_SUCCESS(status)) - goto fail10; + goto fail11; Trace("<====\n"); return STATUS_SUCCESS; -fail10: - Error("fail10\n"); +fail11: + Error("fail11\n"); ThreadAlert((*Frontend)->EjectThread); ThreadJoin((*Frontend)->EjectThread); (*Frontend)->EjectThread = NULL; -fail9: - Error("fail9\n"); +fail10: + Error("fail10\n"); RtlZeroMemory(&(*Frontend)->EjectEvent, sizeof (KEVENT)); + ControllerTeardown(__FrontendGetController(*Frontend)); + (*Frontend)->Controller = NULL; + +fail9: TransmitterTeardown(__FrontendGetTransmitter(*Frontend)); (*Frontend)->Transmitter = NULL; @@ -2575,6 +2604,9 @@ FrontendTeardown( RtlZeroMemory(&Frontend->EjectEvent, sizeof (KEVENT)); + ControllerTeardown(__FrontendGetController(Frontend)); + Frontend->Controller = NULL; + TransmitterTeardown(__FrontendGetTransmitter(Frontend)); Frontend->Transmitter = NULL; diff --git a/src/xenvif/frontend.h b/src/xenvif/frontend.h index 9cac412..65daac4 100644 --- a/src/xenvif/frontend.h +++ b/src/xenvif/frontend.h @@ -165,6 +165,13 @@ FrontendGetTransmitter( IN PXENVIF_FRONTEND Frontend ); +#include "controller.h" + +extern PXENVIF_CONTROLLER +FrontendGetController( + IN PXENVIF_FRONTEND Frontend + ); + extern VOID FrontendQueryStatistic( IN PXENVIF_FRONTEND Frontend, diff --git a/vs2012/xenvif/xenvif.vcxproj b/vs2012/xenvif/xenvif.vcxproj index e3df309..170ab53 100644 --- a/vs2012/xenvif/xenvif.vcxproj +++ b/vs2012/xenvif/xenvif.vcxproj @@ -80,6 +80,7 @@ <ClCompile Include="../../src/xenvif/settings.c" /> <ClCompile Include="../../src/xenvif/thread.c" /> <ClCompile Include="../../src/xenvif/transmitter.c" /> + <ClCompile Include="../../src/xenvif/controller.c" /> <ClCompile Include="../../src/xenvif/vif.c" /> </ItemGroup> <ItemGroup> diff --git a/vs2013/xenvif/xenvif.vcxproj b/vs2013/xenvif/xenvif.vcxproj index 61265a2..9d1dba3 100644 --- a/vs2013/xenvif/xenvif.vcxproj +++ b/vs2013/xenvif/xenvif.vcxproj @@ -83,6 +83,7 @@ <ClCompile Include="../../src/xenvif/settings.c" /> <ClCompile Include="../../src/xenvif/thread.c" /> <ClCompile Include="../../src/xenvif/transmitter.c" /> + <ClCompile Include="../../src/xenvif/controller.c" /> <ClCompile Include="../../src/xenvif/vif.c" /> </ItemGroup> <ItemGroup> -- 2.1.1 _______________________________________________ win-pv-devel mailing list win-pv-devel@xxxxxxxxxxxxxxxxxxxx http://lists.xenproject.org/cgi-bin/mailman/listinfo/win-pv-devel
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |