📄 io.c
字号:
uint NextHopsMatch = FALSE;
if (RTE == SentinelRTE(&VA->RT)) {
KeReleaseSpinLock(&VA->RT.Lock, OldIrql);
Status = STATUS_INVALID_PARAMETER_2;
goto Return;
}
//
// Look for RTE matching the query.
//
if (VirtualAddressEqual(Query->EndpointA, RTE->A.Address) &&
Query->PathId == RTE->PathId &&
Query->addr == (uint)RTE) { // gregos: debug then remove
break;
}
}
//
// Return miscellaneous information about the RTE.
//
RtlCopyMemory(Info->EndpointA, RTE->A.Address, sizeof(VirtualAddress));
RtlCopyMemory(Info->EndpointB, RTE->B.Address, sizeof(VirtualAddress));
Info->PathId = RTE->PathId;
KeAcquireSpinLockAtDpcLevel(&VA->NC.Lock);
if (NULL != RTE->A.Next) {
RtlCopyMemory(Info->NextA, RTE->A.Next->VAddress, sizeof(VirtualAddress));
Info->LocIFa = RTE->A.Next->LocIF;
Info->RemIFa = RTE->A.Next->RemIF;
} else {
RtlCopyMemory(Info->NextA, VRR_ADDRESS_UNSPECIFIED, sizeof(VirtualAddress));
Info->LocIFa = VRR_IFID_UNSPECIFIED;
Info->RemIFa = VRR_IFID_UNSPECIFIED;
}
if (NULL != RTE->B.Next) {
RtlCopyMemory(Info->NextB, RTE->B.Next->VAddress, sizeof(VirtualAddress));
Info->LocIFb = RTE->B.Next->LocIF;
Info->RemIFb = RTE->B.Next->RemIF;
} else {
RtlCopyMemory(Info->NextB, VRR_ADDRESS_UNSPECIFIED, sizeof(VirtualAddress));
Info->LocIFb = VRR_IFID_UNSPECIFIED;
Info->RemIFb = VRR_IFID_UNSPECIFIED;
}
KeReleaseSpinLockFromDpcLevel(&VA->NC.Lock);
Info->RefCnt = RTE->RefCnt;
Info->State = RTE->State;
Info->Flags = RTE->Flags;
Info->ETT = RTE->ETT;
Info->Timeout = TIMEOUT_TO_MS(RTE->Timeout);
//
// Return address of the next NTE (or zero).
// Again, ensure enough for uniqueness of next query.
//
if (RTE->Next == SentinelRTE(&VA->RT)) {
RtlZeroMemory(Info->Query.EndpointA, sizeof(VirtualAddress));
}
else {
// Ensure enough here to uniquely identify the next RTE for the next query.
RTE = RTE->Next;
RtlCopyMemory(Info->Query.EndpointA, RTE->A.Address, sizeof(VirtualAddress));
Info->Query.PathId = RTE->PathId;
Info->Query.addr = (uint)RTE;
}
KeReleaseSpinLock(&VA->RT.Lock, OldIrql);
Irp->IoStatus.Information = sizeof *Info;
}
Status = STATUS_SUCCESS;
Return:
#if 0
if (VA != NULL)
ReleaseVA(VA);
#endif
Irp->IoStatus.Status = Status;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return Status;
}
//* ExecCommand
//
// Helper for ioVrrCommand. Attempts the requested command.
//
uchar
ExecCommand(
MiniportAdapter *VA,
uchar OpCode,
uchar Arg)
{
uchar ExecResult = VRR_COMMAND_BAD_OPCODE;
KIRQL OldIrql;
if (OpCode == VRR_COMMAND_BOOT) {
//
// Set self active iff DriverLoadTime expired and not JoiningOnHold.
//
uint JoiningOnHold = IsJoiningOnHold(VA);
Time Now = KeQueryInterruptTime();
if (JoiningOnHold != 0) {
VrrKdPrint("ExecCmd: cannot activate ring while JoiningOnHold!=0", NULL, NULL);
ExecResult = VRR_COMMAND_NOT_READY;
}
else if (VA->DriverLoadTime > Now) {
VrrKdPrint("ExecCmd: cannot activate ring during DriverLoadTime\n",NULL,NULL);
ExecResult = VRR_COMMAND_NOT_READY;
}
else {
VrrKdPrint("ExecCmd: Becoming boot node for ring at user command\n",NULL,NULL);
KeAcquireSpinLock(&VA->NT.Lock, &OldIrql);
SetSelfActive(VA,TRUE); // VRR_COMMAND_BOOT
InterlockedExchange(&VA->BootNode,TRUE);
VA->MsFirstJoinSetupReq = TIME_TO_MS(KeQueryInterruptTime());
KeReleaseSpinLock(&VA->NT.Lock, OldIrql);
ExecResult = VRR_COMMAND_SUCCESS;
}
}
else if (OpCode == VRR_COMMAND_SET_ADDR) {
//
// Not supported on VrrAPI. Ioctl must do this inline.
//
ExecResult = VRR_COMMAND_BAD_OPCODE;
}
else if (OpCode == VRR_COMMAND_ASSERT) {
KdPrint(("ExecCmd: set VrrGlobal.KdBreakPointOnAssert = %i\n",Arg));
VrrGlobal.KdBreakPointOnAssert = Arg;
ExecResult = VRR_COMMAND_SUCCESS;
}
else if (OpCode == VRR_COMMAND_COUNTER_INIT) {
NeighborCache *NC = &VA->NC;
NeighborCacheEntry *NCE;
KdPrint(("ExecCmd: reset counters to zero\n"));
KeAcquireSpinLock(&NC->Lock, &OldIrql);
for (NCE = NC->FirstNCE; NCE != SentinelNCE(NC); NCE = NCE->Next) {
NCE->CountFailRexmit = 0;
NCE->CountFailHelloLoss = 0;
NCE->CountFailQoSEvict = 0;
NCE->CountFailHelloFail = 0;
}
KeReleaseSpinLock(&NC->Lock, OldIrql);
MaintBufResetStatistics(VA);
InterlockedExchange((PLONG)&VA->MsJoinToHeardExpectedVSet,0);
InterlockedExchange((PLONG)&VA->MsJoinToPathsExpectedVSet,0);
InterlockedExchange((PLONG)&VA->CountSRNackSeqT,0);
InterlockedExchange((PLONG)&VA->CountExitRing,0);
InterlockedExchange((PLONG)&VA->CountExitExecCmd,0);
InterlockedExchange((PLONG)&VA->CountExitNCE,0);
InterlockedExchange((PLONG)&VA->CountExitNTE,0);
InterlockedExchange((PLONG)&VA->CountSetActiveT,0);
InterlockedExchange((PLONG)&VA->CountSetActiveF,0);
InterlockedExchange((PLONG)&VA->CountMaxPLE,0);
InterlockedExchange((PLONG)&VA->BootNode,0);
InterlockedExchange((PLONG)&VA->MaxMsgTimeDelay,0);
InterlockedExchange((PLONG)&VA->MaxMsgCountDelayed,0);
InterlockedExchange((PLONG)&VA->CountMsQDropCritical,0);
InterlockedExchange((PLONG)&VA->CountPnRepairSendSetup,0);
InterlockedExchange((PLONG)&VA->CountHopCountExceeded,0);
InterlockedExchange((PLONG)&VA->CountNTECloserThanSelf,0);
InterlockedExchange((PLONG)&VA->CountSendHello,0);
InterlockedExchange((PLONG)&VA->CountSendSetup,0);
InterlockedExchange((PLONG)&VA->CountSendTearDown,0);
InterlockedExchange((PLONG)&VA->CountSendSetupReq,0);
InterlockedExchange((PLONG)&VA->CountSendSetupReqNack,0);
InterlockedExchange((PLONG)&VA->CountFwdSetup,0);
InterlockedExchange((PLONG)&VA->CountFwdTearDown,0);
InterlockedExchange((PLONG)&VA->CountFwdSetupReq,0);
InterlockedExchange((PLONG)&VA->CountMisroutedSetup,0);
InterlockedExchange((PLONG)&VA->CountMisroutedSetupReq,0);
InterlockedExchange((PLONG)&VA->CountMisroutedTearDown,0);
InterlockedExchange((PLONG)&VA->CountSRDropHopCount,0);
InterlockedExchange((PLONG)&VA->CountSRDropLoop,0);
InterlockedExchange((PLONG)&VA->MaxPLESRcAntiRoute,0);
InterlockedExchange((PLONG)&VA->MaxPLESRcAntiRouteRcv,0);
InterlockedExchange((PLONG)&VA->CountFNHSRcAntiRoute,0);
InterlockedExchange((PLONG)&VA->CountFNHsendSRleft,0);
InterlockedExchange((PLONG)&VA->CountFNHsendSRright,0);
InterlockedExchange((PLONG)&VA->CountRecvHello,0);
InterlockedExchange((PLONG)&VA->CountRecvSetup,0);
InterlockedExchange((PLONG)&VA->CountRecvTearDown,0);
InterlockedExchange((PLONG)&VA->CountRecvSetupReq,0);
InterlockedExchange((PLONG)&VA->CountRecvSRleft,0);
InterlockedExchange((PLONG)&VA->CountRecvSRright,0);
InterlockedExchange((PLONG)&VA->CountGenSRleft,0);
InterlockedExchange((PLONG)&VA->CountGenSRright,0);
RtlZeroMemory(VA->AddErrorVSet, sizeof(uint)*VRR_MAX_VSET_SIZE);
RtlZeroMemory(VA->RejExpBypass, sizeof(uint)*REJ_EXP_BYPASS_COUNT);
ExecResult = VRR_COMMAND_SUCCESS;
}
else if (OpCode == VRR_COMMAND_RATE_ADMIT) {
uint RateEvictThreshold = InterlockedCompareExchange(&VA->RateEvictThreshold,0,0);
uint BitsPerSec = MBPS_TO_BPS(Arg);
if (BitsPerSec > RATE_ADMIT_MAX_BPS ||
BitsPerSec < RATE_EVICT_MIN_BPS ||
BitsPerSec <= RateEvictThreshold) {
VrrKdPrint("ExecCmd: reject invalid RateAdmitThreshold", NULL, NULL);
KdPrint((" bps(%u) max(%u) min(%u) RateEvictThreshold(%u)\n",
BitsPerSec,RATE_ADMIT_MAX_BPS,RATE_EVICT_MIN_BPS,RateEvictThreshold));
ExecResult = VRR_COMMAND_BAD_ARG;
}
else {
InterlockedExchange(&VA->RateAdmitThreshold, BitsPerSec);
ExecResult = VRR_COMMAND_SUCCESS;
}
}
else if (OpCode == VRR_COMMAND_RATE_EVICT) {
uint RateAdmitThreshold = InterlockedCompareExchange(&VA->RateAdmitThreshold,0,0);
uint BitsPerSec = MBPS_TO_BPS(Arg);
if (BitsPerSec > RATE_ADMIT_MAX_BPS ||
BitsPerSec < RATE_EVICT_MIN_BPS ||
BitsPerSec >= RateAdmitThreshold) {
VrrKdPrint("ExecCmd: reject invalid RateEvictThreshold", NULL, NULL);
KdPrint((" bps(%u) max(%u) min(%u) RateAdmitThreshold(%u)\n",
BitsPerSec,RATE_ADMIT_MAX_BPS,RATE_EVICT_MIN_BPS,RateAdmitThreshold));
ExecResult = VRR_COMMAND_BAD_ARG;
}
else {
InterlockedExchange(&VA->RateEvictThreshold, BitsPerSec);
ExecResult = VRR_COMMAND_SUCCESS;
}
}
else if (OpCode == VRR_COMMAND_JOIN_HOLD) {
uint JoiningOnHold = IsJoiningOnHold(VA);
Time Now = KeQueryInterruptTime();
if (JoiningOnHold == 0 && Arg != 0) {
VrrKdPrint("ExecCmd: reject invalid JoiningOnHold", NULL, NULL);
ExecResult = VRR_COMMAND_BAD_ARG;
}
else if (VA->DriverLoadTime > Now) {
ExecResult = VRR_COMMAND_NOT_READY;
}
else {
InterlockedExchange(&VA->JoiningOnHold, Arg);
SetVSetChanged(VA);
ExecResult = VRR_COMMAND_SUCCESS;
}
}
else if (OpCode == VRR_COMMAND_RSSI_ADMIT) {
uint RssiEvictThreshold = InterlockedCompareExchange(&VA->RssiEvictThreshold,0,0);
uint Rssi = Arg;
if (Rssi > RSSI_ADMIT_MAX ||
Rssi < RSSI_EVICT_MIN ||
Rssi <= RssiEvictThreshold) {
VrrKdPrint("ExecCmd: reject invalid RssiAdmitThreshold", NULL, NULL);
KdPrint((" bps(%u) max(%u) min(%u) RssiEvictThreshold(%u)\n",
Rssi,RSSI_ADMIT_MAX,RSSI_EVICT_MIN,RssiEvictThreshold));
ExecResult = VRR_COMMAND_BAD_ARG;
}
else {
InterlockedExchange(&VA->RssiAdmitThreshold, Rssi);
ExecResult = VRR_COMMAND_SUCCESS;
}
}
else if (OpCode == VRR_COMMAND_RSSI_EVICT) {
uint RssiAdmitThreshold = InterlockedCompareExchange(&VA->RssiAdmitThreshold,0,0);
uint Rssi = Arg;
if (Rssi > RSSI_ADMIT_MAX ||
Rssi < RSSI_EVICT_MIN ||
Rssi >= RssiAdmitThreshold) {
VrrKdPrint("ExecCmd: reject invalid RssiEvictThreshold", NULL, NULL);
KdPrint((" bps(%u) max(%u) min(%u) RssiAdmitThreshold(%u)\n",
Rssi,RSSI_ADMIT_MAX,RSSI_EVICT_MIN,RssiAdmitThreshold));
ExecResult = VRR_COMMAND_BAD_ARG;
}
else {
InterlockedExchange(&VA->RssiEvictThreshold, Rssi);
ExecResult = VRR_COMMAND_SUCCESS;
}
}
else if (OpCode == VRR_COMMAND_PN_REPAIR) {
InterlockedExchange(&VA->PartitionRepairEnabled, Arg);
ExecResult = VRR_COMMAND_SUCCESS;
}
else if (OpCode == VRR_COMMAND_KDFLUSH) {
int i;
for (i = 0; i < Arg; i++)
VrrTrace(VA, 2, "IO:EX=flush",NULL,NULL,NULL,"This",i,"Max",Arg);
ExecResult = VRR_COMMAND_SUCCESS;
}
else if (OpCode == VRR_COMMAND_RESET) {
VrrTrace(VA,2,"IO:EX=Reset",NULL,NULL,NULL,NULL,0,"Arg",Arg);
FailAllNeigboursAndChangeState(VA,Arg);
InterlockedExchange(&VA->JoiningOnHold, TRUE);
InterlockedIncrement(&VA->CountExitExecCmd);
ExecResult = VRR_COMMAND_SUCCESS;
}
else if (OpCode == VRR_COMMAND_NOISE_LEVEL) {
InterlockedExchange(&VA->VrrTraceNoiseLevel, Arg);
ExecResult = VRR_COMMAND_SUCCESS;
}
else if (OpCode == VRR_COMMAND_BC_RELAY) {
InterlockedExchange(&VA->BroadcastRelay, Arg);
ExecResult = VRR_COMMAND_SUCCESS;
}
else if (OpCode == VRR_COMMAND_TX_DROP_ALL) {
InterlockedExchange(&VA->TxDropAllButHello, Arg);
ExecResult = VRR_COMMAND_SUCCESS;
}
else if (OpCode == VRR_COMMAND_TX_DROP_HELLO) {
InterlockedExchange(&VA->TxDropAllHello, Arg);
ExecResult = VRR_COMMAND_SUCCESS;
}
return ExecResult;
}
//* IoVrrCommand
//
// Simple command interface.
//
NTSTATUS
IoVrrCommand(
IN PIRP Irp,
IN PIO_STACK_LOCATION IrpSp)
{
VRR_COMMAND *Command;
MiniportAdapter *VA = NULL;
KIRQL OldIrql;
NTSTATUS Status = STATUS_UNSUCCESSFUL;
uchar ExecResult = VRR_COMMAND_ERROR;
PAGED_CODE();
Irp->IoStatus.Information = 0;
if (IrpSp->Parameters.DeviceIoControl.InputBufferLength != sizeof *Command) {
Status = STATUS_INVALID_PARAMETER;
goto Return;
}
Command = (VRR_COMMAND *) Irp->AssociatedIrp.SystemBuffer;
//
// Return information about the specified virtual adapter.
//
VA = FindVirtualAdapterFromQuery(&Command->VA);
if (VA == NULL) {
Status = STATUS_INVALID_PARAMETER_1;
goto Return;
}
//
// Attempt to execute the command.
// Do inline those things that aren't supported by ExecCommand.
//
if (Command->OpCode == VRR_COMMAND_SET_ADDR) {
HANDLE KeyHandle;
VrrKdPrint("IoCmd: set VRR Address in registry", Command->ArgAddress, NULL);
Status = STATUS_SUCCESS;
ExecResult = VRR_COMMAND_SUCCESS;
if (IsUnspecified(Command->ArgAddress)) {
VrrKdPrint("IoCmd: reject unspecified address as new VA->Address", NULL, NULL);
Status = STATUS_INVALID_PARAMETER_2;
goto Return;
}
if (IsIEEEGroupAddress(Command->ArgAddress)) {
VrrKdPrint("IoCmd: reject broadcast address as new VA->Address", NULL, NULL);
Status = STATUS_INVALID_PARAMETER_2;
goto Return;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -