📄 protocol.c
字号:
// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil -*- (for GNU Emacs)
//
// (c) Microsoft Corporation. All rights reserved.
//
// This file is part of the Microsoft Virtual Ring Routing distribution.
// You should have received a copy of the Microsoft Research Shared Source
// license agreement (MSR-SSLA) for this software; see the file "license.txt".
// If not, please see http://research.microsoft.com/vrr/license.htm,
// or write to Microsoft Research, One Microsoft Way, Redmond, WA 98052-6399.
//
// This file is derived from the Microsoft Research Mesh Connectivity Layer,
// available under the MSR-SSLA license, and downloadable from
// http://research.microsoft.com/mesh/.
//
#include "headers.h"
//* FindPhysicalAdapterFromIndex
//
// Given an index, returns the physical adapter.
//
ProtocolAdapter *
FindPhysicalAdapterFromIndex(MiniportAdapter *VA, uint Index)
{
ProtocolAdapter *PA;
KIRQL OldIrql;
KeAcquireSpinLock(&VA->Lock, &OldIrql);
for (PA = VA->PhysicalAdapters;
PA != NULL;
PA = PA->Next) {
//
// Is this the desired physical adapter?
//
if (PA->Index == Index)
break;
}
KeReleaseSpinLock(&VA->Lock, OldIrql);
return PA;
}
//* FindFirstPhysicalAdapter
//
// Returns the first physical adapter.
//
ProtocolAdapter *
FindFirstPhysicalAdapter(MiniportAdapter *VA, VRRIf *Index)
{
ProtocolAdapter *PA;
KIRQL OldIrql;
uint IFIndex;
KeAcquireSpinLock(&VA->Lock, &OldIrql);
PA = VA->PhysicalAdapters;
if (NULL != PA && NULL != Index) {
VRRASSERT(PA->Index < 0x100); // Must fit in VRRIf.
*Index = (VRRIf)PA->Index;
}
KeReleaseSpinLock(&VA->Lock, OldIrql);
if (NULL == PA) KdPrint(("FindFirstPhysicalAdapter(%u) returns NULL\n",*Index));
return PA;
}
//* FindPhysicalAdapterFromGuid
//
// Given a guid, returns the physical adapter.
//
ProtocolAdapter *
FindPhysicalAdapterFromGuid(MiniportAdapter *VA, const GUID *Guid)
{
ProtocolAdapter *PA;
KIRQL OldIrql;
KeAcquireSpinLock(&VA->Lock, &OldIrql);
for (PA = VA->PhysicalAdapters;
PA != NULL;
PA = PA->Next) {
//
// Is this the desired physical adapter?
//
if (RtlEqualMemory(Guid, &PA->Guid, sizeof(GUID)))
break;
}
KeReleaseSpinLock(&VA->Lock, OldIrql);
return PA;
}
//* ProtocolQueueFull
//
// Returns TRUE if the transmit queue of the specified
// interface is full.
//
boolint
ProtocolQueueFull(MiniportAdapter *VA, VRRIf OutIf)
{
ProtocolAdapter *PA;
PA = FindPhysicalAdapterFromIndex(VA, OutIf);
return (PA != NULL) && (PA->CountSentOutstanding >= PROTOCOL_MAX_QUEUE);
}
//* ProtocolResetStatistics
//
// Resets all counters and statistics gathering for the physical adapter.
//
// The caller must hold a reference for the physical adapter
// or have the virtual adapter locked.
//
void
ProtocolResetStatistics(ProtocolAdapter *PA)
{
PA->PacketsSent = 0;
PA->PacketsReceived = 0;
PA->PacketsReceivedTD = 0;
PA->PacketsReceivedFlat = 0;
PA->CountPacketPoolFailure = 0;
PA->MaxRecvOutstanding = PA->CountRecvOutstanding;
PA->MaxSentOutstanding = PA->MaxSentOutstanding;
}
//* ProtocolRequestHelper
//
// This is a utility routine to submit a general request to an NDIS
// driver. The caller specifes the request code (OID), a buffer and
// a length. This routine allocates a request structure, fills it in,
// and submits the request.
//
NDIS_STATUS
ProtocolRequestHelper(
ProtocolAdapter *PA,
NDIS_REQUEST_TYPE RT, // Type of request to be done (Set or Query).
NDIS_OID OID, // Value to be set/queried.
void *Info, // Pointer to the buffer to be passed.
uint Length, // Length of data in above buffer.
uint *Needed) // Location to fill in with bytes needed in buffer.
{
ProtocolRequest Request;
NDIS_STATUS Status;
// Now fill it in.
Request.ContextOnStack = TRUE;
Request.Request.RequestType = RT;
if (RT == NdisRequestSetInformation) {
Request.Request.DATA.SET_INFORMATION.Oid = OID;
Request.Request.DATA.SET_INFORMATION.InformationBuffer = Info;
Request.Request.DATA.SET_INFORMATION.InformationBufferLength = Length;
} else {
Request.Request.DATA.QUERY_INFORMATION.Oid = OID;
Request.Request.DATA.QUERY_INFORMATION.InformationBuffer = Info;
Request.Request.DATA.QUERY_INFORMATION.InformationBufferLength = Length;
}
//
// Note that we can NOT use PA->Event and PA->Status here.
// There may be multiple concurrent ProtocolRequestHelper calls.
//
KeInitializeEvent(&Request.Event, SynchronizationEvent, FALSE);
NdisRequest(&Status, PA->Handle, &Request.Request);
if (Status == NDIS_STATUS_PENDING) {
(void) KeWaitForSingleObject(&Request.Event, UserRequest,
KernelMode, FALSE, NULL);
Status = Request.Status;
}
if (Needed != NULL)
*Needed = Request.Request.DATA.QUERY_INFORMATION.BytesNeeded;
return Status;
}
//* ProtocolQuery
//
// Returns information about the physical adapter.
//
void
ProtocolQuery(
ProtocolAdapter *PA,
VRR_INFO_PHYSICAL_ADAPTER *Info)
{
NDIS_STATUS Status;
RtlCopyMemory(Info->Address, PA->Address, sizeof(PhysicalAddress));
Info->MTU = PA->MaxFrameSize;
Info->Promiscuous = PA->Promiscuous;
Info->ReceiveOnly = PA->ReceiveOnly;
Info->Channel = PA->Channel;
Info->Bandwidth = PA->Bandwidth;
Info->SupportsQuerySibTable = PA->SupportsQuerySibTable;
Info->PacketsSent = PA->PacketsSent;
Info->PacketsReceived = PA->PacketsReceived;
Info->PacketsReceivedTD = PA->PacketsReceivedTD;
Info->PacketsReceivedFlat = PA->PacketsReceivedFlat;
Info->CountPacketPoolFailure = PA->CountPacketPoolFailure;
Info->CountRecvOutstanding = PA->CountRecvOutstanding;
Info->MaxRecvOutstanding = PA->MaxRecvOutstanding;
Info->CountSentOutstanding = PA->CountSentOutstanding;
Info->MaxSentOutstanding = PA->MaxSentOutstanding;
Info->NDISPacketPoolUsage = NdisPacketPoolUsage(PA->PacketPool);
Status = ProtocolRequestHelper(PA, NdisRequestQueryInformation,
OID_802_11_BSSID,
&Info->W.BSSID, sizeof Info->W.BSSID,
NULL);
if (Status != NDIS_STATUS_SUCCESS)
goto Ethernet;
Info->Type = VRR_PHYSICAL_ADAPTER_802_11;
Status = ProtocolRequestHelper(PA, NdisRequestQueryInformation,
OID_802_11_SSID,
&Info->W.SSID, sizeof Info->W.SSID,
NULL);
if (Status != NDIS_STATUS_SUCCESS) {
KdPrint(("VRR!ProtocolQuery: OID_802_11_SSID: %x\n", Status));
Info->W.SSID.SsidLength = 0;
}
Status = ProtocolRequestHelper(PA, NdisRequestQueryInformation,
OID_802_11_INFRASTRUCTURE_MODE,
&Info->W.Mode, sizeof Info->W.Mode,
NULL);
if (Status != NDIS_STATUS_SUCCESS) {
KdPrint(("VRR!ProtocolQuery: OID_802_11_INFRASTRUCTURE_MODE: %x\n", Status));
Info->W.Mode = (NDIS_802_11_NETWORK_INFRASTRUCTURE) -1;
}
Status = ProtocolRequestHelper(PA, NdisRequestQueryInformation,
OID_802_11_CONFIGURATION,
&Info->W.Radio, sizeof Info->W.Radio,
NULL);
if (Status != NDIS_STATUS_SUCCESS) {
KdPrint(("VRR!ProtocolQuery: OID_802_11_CONFIGURATION: %x\n", Status));
memset(&Info->W.Radio, 0, sizeof Info->W.Radio);
}
Status = ProtocolRequestHelper(PA, NdisRequestQueryInformation,
OID_802_11_POWER_MODE,
&Info->W.PowerMode,
sizeof Info->W.PowerMode,
NULL);
if (Status != NDIS_STATUS_SUCCESS) {
KdPrint(("VRR!ProtocolQuery: OID_802_11_POWER_MODE: %x\n", Status));
Info->W.PowerMode = (NDIS_802_11_POWER_MODE) -1;
}
Status = ProtocolRequestHelper(PA, NdisRequestQueryInformation,
OID_802_11_TX_POWER_LEVEL,
&Info->W.TxPowerLevel,
sizeof Info->W.TxPowerLevel,
NULL);
if (Status != NDIS_STATUS_SUCCESS) {
KdPrint(("VRR!ProtocolQuery: OID_802_11_TX_POWER_LEVEL: %x\n", Status));
Info->W.TxPowerLevel = 0;
}
Status = ProtocolRequestHelper(PA, NdisRequestQueryInformation,
OID_802_11_RTS_THRESHOLD,
&Info->W.RTSThreshold,
sizeof Info->W.RTSThreshold,
NULL);
if (Status != NDIS_STATUS_SUCCESS) {
KdPrint(("VRR!ProtocolQuery: OID_802_11_RTS_THRESHOLDL: %x\n", Status));
Info->W.RTSThreshold = (NDIS_802_11_RTS_THRESHOLD) -1;
}
Status = ProtocolRequestHelper(PA, NdisRequestQueryInformation,
OID_802_11_STATISTICS,
&Info->W.Statistics,
sizeof Info->W.Statistics,
NULL);
if (Status != NDIS_STATUS_SUCCESS) {
KdPrint(("VRR!ProtocolQuery: OID_802_11_STATISTICS: %x\n", Status));
memset(&Info->W.Statistics, 0, sizeof Info->W.Statistics);
}
RtlZeroMemory(&Info->W.GenVendorDescription, sizeof Info->W.GenVendorDescription);
Status = ProtocolRequestHelper(PA, NdisRequestQueryInformation,
OID_GEN_VENDOR_DESCRIPTION,
&Info->W.GenVendorDescription,
sizeof(Info->W.GenVendorDescription) - 1,
NULL);
if (Status != NDIS_STATUS_SUCCESS) {
KdPrint(("VRR!ProtocolQuery: OID_GEN_VENDOR_DESCRIPTION: %x\n", Status));
}
RtlZeroMemory(&Info->AthMSRC,sizeof(MSRC_OID_Info_Adapter));
if (PA->SupportsQuerySibTable == TRUE) {
Status = ProtocolRequestHelper(PA, NdisRequestQueryInformation,
OID_MSRC_QUERY_ADAPTER,
&Info->AthMSRC,
sizeof(MSRC_OID_Info_Adapter),
NULL);
if (Status != NDIS_STATUS_SUCCESS) {
KdPrint(("VRR!ProtocolQuery: OID_MSRC_QUERY_ADAPTER: %x\n", Status));
}
}
return;
Ethernet:
Info->Type = VRR_PHYSICAL_ADAPTER_ETHERNET;
}
//* ProtocolControl
//
// Sets protocol configuration parameters from the structure.
//
// Return values:
// STATUS_INVALID_PARAMETER_3 Bad Channel.
// STATUS_INVALID_PARAMETER_4 Bad Bandwidth.
// STATUS_SUCCESS
//
NTSTATUS
ProtocolControl(
ProtocolAdapter *PA,
VRR_CONTROL_PHYSICAL_ADAPTER *Control)
{
//
// Check parameters before any updates.
//
if (Control->Channel != 0) {
if (Control->Channel >= 256)
return STATUS_INVALID_PARAMETER_3;
}
if (Control->Bandwidth != 0) {
if (((Control->Bandwidth >> 2) >= 1024) ||
((Control->Bandwidth >> 2) == 0))
return STATUS_INVALID_PARAMETER_4;
}
//
// Update the attributes of the physical adapter.
//
ExAcquireFastMutex(&PA->Mutex);
if (Control->ReceiveOnly != (boolint) -1)
PA->ReceiveOnly = Control->ReceiveOnly;
if (Control->Channel != 0) {
PA->Channel = Control->Channel;
PA->ChannelConfigured = TRUE;
}
if (Control->Bandwidth != 0) {
PA->Bandwidth = Control->Bandwidth;
PA->BandwidthConfigured = TRUE;
}
ExReleaseFastMutex(&PA->Mutex);
return STATUS_SUCCESS;
}
//* ProtocolOpenAdapterComplete
//
// Called by NDIS when an NdisOpenAdapter completes.
//
void
ProtocolOpenAdapterComplete(
NDIS_HANDLE Handle, // Binding handle.
NDIS_STATUS Status, // Final status of command.
NDIS_STATUS ErrorStatus) // Extra status for some errors.
{
ProtocolAdapter *PA = (ProtocolAdapter *)Handle;
UNREFERENCED_PARAMETER(ErrorStatus);
KdPrint(("VRR!ProtocolOpenAdapterComplete(VA %p PA %p)\n",
PA->VirtualAdapter, PA));
//
// Signal whoever is waiting and pass the final status.
//
PA->Status = Status;
KeSetEvent(&PA->Event, 0, FALSE);
}
//* ProtocolCloseAdapterComplete
//
// Called by NDIS when an NdisCloseAdapter completes.
//
// At this point, NDIS guarantees that it has no other outstanding
// calls to us.
//
void
ProtocolCloseAdapterComplete(
NDIS_HANDLE Handle, // Binding handle.
NDIS_STATUS Status) // Final status of command.
{
ProtocolAdapter *PA = (ProtocolAdapter *)Handle;
KdPrint(("VRR!ProtocolCloseAdapterComplete(VA %p PA %p)\n",
PA->VirtualAdapter, PA));
//
// Signal whoever is waiting and pass the final status.
//
PA->Status = Status;
KeSetEvent(&PA->Event, 0, FALSE);
}
//* ProtocolTransmitComplete
//
// Called by NDIS when a send completes.
//
void
ProtocolTransmitComplete(
NDIS_HANDLE Handle, // Binding handle.
PNDIS_PACKET Packet, // Packet that was sent.
NDIS_STATUS Status) // Final status of send.
{
ProtocolAdapter *PA = (ProtocolAdapter *)Handle;
VRRASSERT(PC(Packet)->PA == PA);
PrintfNdisStatus(__FUNCTION__,Status,FALSE);
SaveCompletionTime(PA->VirtualAdapter, Packet, Status);
(*PC(Packet)->TransmitComplete)(PA->VirtualAdapter, Packet, Status);
InterlockedDecrement((PLONG)&PA->CountSentOutstanding);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -