Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

3994 lines
130 KiB

  1. /*++
  2. Copyright(c) 1999-2000 Microsoft Corporation
  3. Module Name:
  4. brdgfwd.c
  5. Abstract:
  6. Ethernet MAC level bridge.
  7. Forwarding engine section
  8. Author:
  9. Mark Aiken
  10. (original bridge by Jameel Hyder)
  11. Environment:
  12. Kernel mode driver
  13. Revision History:
  14. Feb 2000 - Original version
  15. --*/
  16. #define NDIS_MINIPORT_DRIVER
  17. #define NDIS50_MINIPORT 1
  18. #define NDIS_WDM 1
  19. #pragma warning( push, 3 )
  20. #include <ndis.h>
  21. #include <ntddk.h>
  22. #pragma warning( pop )
  23. #include <netevent.h>
  24. #include "bridge.h"
  25. #include "brdgprot.h"
  26. #include "brdgmini.h"
  27. #include "brdgtbl.h"
  28. #include "brdgfwd.h"
  29. #include "brdgbuf.h"
  30. #include "brdgctl.h"
  31. #include "brdgsta.h"
  32. #include "brdgcomp.h"
  33. // ===========================================================================
  34. //
  35. // CONSTANTS
  36. //
  37. // ===========================================================================
  38. //
  39. // Number of queued packets we will process back-to-back at DISPATCH level before
  40. // dropping back to PASSIVE to let the scheduler run
  41. //
  42. #define MAX_PACKETS_AT_DPC 10
  43. // The STA multicast address
  44. UCHAR STA_MAC_ADDR[ETH_LENGTH_OF_ADDRESS] = { 0x01, 0x80, 0xC2, 0x00, 0x00, 0x00 };
  45. // The flags we change on packet descriptor when sending them. For a fast-track
  46. // send, these flags should be put back the way they were before returning
  47. // the overlying protocol's packet descriptor.
  48. #define CHANGED_PACKET_FLAGS (NDIS_FLAGS_LOOPBACK_ONLY | NDIS_FLAGS_DONT_LOOPBACK)
  49. // ===========================================================================
  50. //
  51. // GLOBALS
  52. //
  53. // ===========================================================================
  54. //
  55. // Pointers to the KTHREAD structure for each active thread
  56. //
  57. PVOID gThreadPtrs[MAXIMUM_PROCESSORS];
  58. //
  59. // The number of created threads
  60. //
  61. UINT gNumThreads = 0L;
  62. // Global kill signal for threads
  63. KEVENT gKillThreads;
  64. //
  65. // These auto-reset events signal the queue-draining threads to re-enumerate the
  66. // adapter list (strobed when the adapter list is changed)
  67. //
  68. KEVENT gThreadsCheckAdapters[MAXIMUM_PROCESSORS];
  69. //
  70. // DEBUG-ONLY: Set this to a particular MAC address to break when receiving a packet
  71. // from that address.
  72. //
  73. #if DBG
  74. BOOLEAN gBreakOnMACAddress = FALSE;
  75. UCHAR gBreakMACAddress[ETH_LENGTH_OF_ADDRESS] = {0, 0, 0, 0, 0, 0};
  76. BOOLEAN gBreakIfNullPPI = FALSE;
  77. #endif
  78. //
  79. // XPSP1: 565471
  80. // We start out with this disabled. Once we know that it's allowed, we re-allow bridging to
  81. // take place.
  82. //
  83. BOOLEAN gBridging = FALSE;
  84. BOOLEAN gPrintPacketTypes = FALSE;
  85. extern BOOLEAN gHaveID;
  86. // ===========================================================================
  87. //
  88. // STATISTICS
  89. //
  90. // ===========================================================================
  91. LARGE_INTEGER gStatTransmittedFrames = { 0L, 0L }; // Local-source frames sent successfully to at least
  92. // one adapter
  93. LARGE_INTEGER gStatTransmittedErrorFrames = { 0L, 0L }; // Local-source frames not sent AT ALL due to errors
  94. LARGE_INTEGER gStatTransmittedBytes = { 0L, 0L }; // Local-source bytes sent successfully to at least
  95. // one adapter
  96. // Breakdown of transmitted frames
  97. LARGE_INTEGER gStatDirectedTransmittedFrames = { 0L, 0L };
  98. LARGE_INTEGER gStatMulticastTransmittedFrames = { 0L, 0L };
  99. LARGE_INTEGER gStatBroadcastTransmittedFrames = { 0L, 0L };
  100. // Breakdown of transmitted bytes
  101. LARGE_INTEGER gStatDirectedTransmittedBytes = { 0L, 0L };
  102. LARGE_INTEGER gStatMulticastTransmittedBytes = { 0L, 0L };
  103. LARGE_INTEGER gStatBroadcastTransmittedBytes = { 0L, 0L };
  104. LARGE_INTEGER gStatIndicatedFrames = { 0L, 0L }; // # of inbound frames indicated up
  105. LARGE_INTEGER gStatIndicatedDroppedFrames = { 0L, 0L }; // # of inbound frames we would have indicated but couldn't
  106. // because of resources / error
  107. LARGE_INTEGER gStatIndicatedBytes = { 0L, 0L }; // # of inbound bytes indicated up
  108. // Breakdown of indicated frames
  109. LARGE_INTEGER gStatDirectedIndicatedFrames = { 0L, 0L };
  110. LARGE_INTEGER gStatMulticastIndicatedFrames = { 0L, 0L };
  111. LARGE_INTEGER gStatBroadcastIndicatedFrames = { 0L, 0L };
  112. // Breakdown of indicated bytes
  113. LARGE_INTEGER gStatDirectedIndicatedBytes = { 0L, 0L };
  114. LARGE_INTEGER gStatMulticastIndicatedBytes = { 0L, 0L };
  115. LARGE_INTEGER gStatBroadcastIndicatedBytes = { 0L, 0L };
  116. //
  117. // The following stats are not reported to NDIS; they're here for our own amusement
  118. //
  119. LARGE_INTEGER gStatReceivedFrames = { 0L, 0L }; // Total # of processed inbound packets
  120. LARGE_INTEGER gStatReceivedBytes = { 0L, 0L }; // Total inbound processed bytes
  121. LARGE_INTEGER gStatReceivedCopyFrames = { 0L, 0L }; // Total # of processed inbound packets WITH COPY
  122. LARGE_INTEGER gStatReceivedCopyBytes = { 0L, 0L }; // Total inbound processed bytes WITH COPY
  123. LARGE_INTEGER gStatReceivedNoCopyFrames = { 0L, 0L }; // Total # of processed inbound packets WITHOUT COPY
  124. LARGE_INTEGER gStatReceivedNoCopyBytes = { 0L, 0L }; // Total inbound processed bytes WITHOUT COPY
  125. // ===========================================================================
  126. //
  127. // PRIVATE PROTOTYPES
  128. //
  129. // ===========================================================================
  130. // Undocumented kernel function
  131. extern KAFFINITY
  132. KeSetAffinityThread (
  133. IN PKTHREAD Thread,
  134. IN KAFFINITY Affinity
  135. );
  136. VOID
  137. BrdgFwdSendOnLink(
  138. IN PADAPT pAdapt,
  139. IN PNDIS_PACKET pPacket
  140. );
  141. VOID
  142. BrdgFwdReleaseBasePacket(
  143. IN PNDIS_PACKET pPacket,
  144. PPACKET_INFO ppi,
  145. PACKET_OWNERSHIP Own,
  146. NDIS_STATUS Status
  147. );
  148. // This is the type of function to be passed to BrdgFwdHandlePacket()
  149. typedef PNDIS_PACKET (*PPACKET_BUILD_FUNC)(PPACKET_INFO*, PADAPT, PVOID, PVOID, UINT, UINT);
  150. NDIS_STATUS
  151. BrdgFwdHandlePacket(
  152. IN PACKET_DIRECTION PacketDirection,
  153. IN PADAPT pTargetAdapt,
  154. IN PADAPT pOriginalAdapt,
  155. IN BOOLEAN bShouldIndicate,
  156. IN NDIS_HANDLE MiniportHandle,
  157. IN PNDIS_PACKET pBasePacket,
  158. IN PPACKET_INFO ppi,
  159. IN PPACKET_BUILD_FUNC pFunc,
  160. IN PVOID Param1,
  161. IN PVOID Param2,
  162. IN UINT Param3,
  163. IN UINT Param4
  164. );
  165. VOID
  166. BrdgFwdWrapPacketForReceive(
  167. IN PNDIS_PACKET pOriginalPacket,
  168. IN PNDIS_PACKET pNewPacket
  169. );
  170. VOID
  171. BrdgFwdWrapPacketForSend(
  172. IN PNDIS_PACKET pOriginalPacket,
  173. IN PNDIS_PACKET pNewPacket
  174. );
  175. // The type of function to pass to BrdgFwdCommonAllocAndWrapPacket
  176. typedef VOID (*PWRAPPER_FUNC)(PNDIS_PACKET, PNDIS_PACKET);
  177. PNDIS_PACKET
  178. BrdgFwdCommonAllocAndWrapPacket(
  179. IN PNDIS_PACKET pBasePacket,
  180. OUT PPACKET_INFO *pppi,
  181. IN PADAPT pTargetAdapt,
  182. IN PWRAPPER_FUNC pFunc
  183. );
  184. VOID
  185. BrdgFwdTransferComplete(
  186. IN NDIS_HANDLE ProtocolBindingContext,
  187. IN PNDIS_PACKET pPacket,
  188. IN NDIS_STATUS Status,
  189. IN UINT BytesTransferred
  190. );
  191. BOOLEAN
  192. BrdgFwdNoCopyFastTrackReceive(
  193. IN PNDIS_PACKET pPacket,
  194. IN PADAPT pAdapt,
  195. IN NDIS_HANDLE MiniportHandle,
  196. IN PUCHAR DstAddr,
  197. OUT BOOLEAN *bRetainPacket
  198. );
  199. PNDIS_PACKET
  200. BrdgFwdMakeCopyBasePacket(
  201. OUT PPACKET_INFO *pppi,
  202. IN PVOID pHeader,
  203. IN PVOID pData,
  204. IN UINT HeaderSize,
  205. IN UINT DataSize,
  206. IN UINT SizeOfPacket,
  207. IN BOOLEAN bCountAsReceived,
  208. IN PADAPT pOwnerAdapt,
  209. PVOID *ppBuf
  210. );
  211. PNDIS_PACKET
  212. BrdgFwdMakeNoCopyBasePacket(
  213. OUT PPACKET_INFO *pppi,
  214. IN PADAPT Target,
  215. IN PVOID Param1,
  216. IN PVOID Param2,
  217. IN UINT Param3,
  218. IN UINT Param4
  219. );
  220. PNDIS_PACKET
  221. BrdgFwdMakeSendBasePacket(
  222. OUT PPACKET_INFO *pppi,
  223. IN PADAPT Target,
  224. IN PVOID Param1,
  225. IN PVOID Param2,
  226. IN UINT Param3,
  227. IN UINT Param4
  228. );
  229. // This is the per-processor queue-draining function
  230. VOID
  231. BrdgFwdProcessQueuedPackets(
  232. IN PVOID Param1
  233. );
  234. // ===========================================================================
  235. //
  236. // INLINES / MACROS
  237. //
  238. // ===========================================================================
  239. //
  240. // Tells us if we're allowed to bridge, or if GPO's are currently disallowing
  241. // bridging
  242. //
  243. __forceinline
  244. BOOLEAN
  245. BrdgFwdBridgingNetworks()
  246. {
  247. return gBridging;
  248. }
  249. //
  250. // Frees a packet that was used to wrap a base packet
  251. //
  252. __forceinline
  253. VOID
  254. BrdgFwdFreeWrapperPacket(
  255. IN PNDIS_PACKET pPacket,
  256. IN PPACKET_INFO ppi,
  257. IN PADAPT pQuotaOwner
  258. )
  259. {
  260. SAFEASSERT( BrdgBufIsWrapperPacket(pPacket) );
  261. BrdgBufUnchainCopyBuffers( pPacket );
  262. BrdgBufFreeWrapperPacket( pPacket, ppi, pQuotaOwner );
  263. }
  264. //
  265. // Frees a base packet that wraps a packet descriptor from an overlying protocol
  266. // or underlying NIC that we were allowed to hang on to
  267. //
  268. __forceinline
  269. VOID
  270. BrdgFwdFreeBaseWrapperPacket(
  271. IN PNDIS_PACKET pPacket,
  272. IN PPACKET_INFO ppi
  273. )
  274. {
  275. SAFEASSERT( BrdgBufIsWrapperPacket(pPacket) );
  276. BrdgBufUnchainCopyBuffers( pPacket );
  277. BrdgBufFreeBaseWrapperPacket( pPacket, ppi );
  278. }
  279. //
  280. // Allocates a new wrapper packet, chains on buffer descriptors so that the new
  281. // packet points to the same data buffers as the old packet, and copies per-packet
  282. // information appropriate for using the new packet for indications
  283. //
  284. __forceinline
  285. PNDIS_PACKET
  286. BrdgFwdAllocAndWrapPacketForReceive(
  287. IN PNDIS_PACKET pPacket,
  288. OUT PPACKET_INFO *pppi,
  289. IN PADAPT pTargetAdapt
  290. )
  291. {
  292. return BrdgFwdCommonAllocAndWrapPacket( pPacket, pppi, pTargetAdapt, BrdgFwdWrapPacketForReceive );
  293. }
  294. //
  295. // Allocates a new wrapper packet, chains on buffer descriptors so that the new
  296. // packet points to the same data buffers as the old packet, and copies per-packet
  297. // information appropriate for using the new packet for transmits
  298. //
  299. __forceinline
  300. PNDIS_PACKET
  301. BrdgFwdAllocAndWrapPacketForSend(
  302. IN PNDIS_PACKET pPacket,
  303. OUT PPACKET_INFO *pppi,
  304. IN PADAPT pTargetAdapt
  305. )
  306. {
  307. return BrdgFwdCommonAllocAndWrapPacket( pPacket, pppi, pTargetAdapt, BrdgFwdWrapPacketForSend );
  308. }
  309. //
  310. // Checks if an address is one of the reserved group addresses for the Spanning Tree Algorithm.
  311. //
  312. __forceinline
  313. BOOLEAN
  314. BrdgFwdIsSTAGroupAddress(
  315. IN PUCHAR pAddr
  316. )
  317. {
  318. return( (pAddr[0] == STA_MAC_ADDR[0]) && (pAddr[1] == STA_MAC_ADDR[1]) &&
  319. (pAddr[2] == STA_MAC_ADDR[2]) && (pAddr[3] == STA_MAC_ADDR[4]) &&
  320. (pAddr[4] == STA_MAC_ADDR[4]) );
  321. }
  322. //
  323. // Checks that PacketDirection has been assigned
  324. //
  325. __forceinline
  326. VOID
  327. BrdgFwdValidatePacketDirection(
  328. IN PACKET_DIRECTION Direction
  329. )
  330. {
  331. SAFEASSERT( (Direction == BrdgPacketInbound) || (Direction == BrdgPacketOutbound) ||
  332. (Direction == BrdgPacketCreatedInBridge) );
  333. }
  334. //
  335. // Queues a packet for deferred processing
  336. //
  337. _inline
  338. VOID
  339. BrdgFwdQueuePacket(
  340. IN PPACKET_Q_INFO ppqi,
  341. IN PADAPT pAdapt
  342. )
  343. {
  344. BOOLEAN bSchedule = FALSE, bIncremented;
  345. // The queue lock protects the bServiceInProgress flag
  346. NdisAcquireSpinLock( &pAdapt->QueueLock );
  347. // Add the packet to the queue
  348. BrdgInsertTailSingleList( &pAdapt->Queue, &ppqi->List );
  349. bIncremented = BrdgIncrementWaitRef( &pAdapt->QueueRefcount );
  350. SAFEASSERT( bIncremented );
  351. if (bIncremented)
  352. {
  353. SAFEASSERT( (ULONG)pAdapt->QueueRefcount.Refcount == pAdapt->Queue.Length );
  354. // Check if anyone is already working on the queue
  355. if( !pAdapt->bServiceInProgress )
  356. {
  357. // Signal the queue event so someone will wake up
  358. pAdapt->bServiceInProgress = TRUE;
  359. bSchedule = TRUE;
  360. }
  361. }
  362. NdisReleaseSpinLock( &pAdapt->QueueLock );
  363. if( bSchedule )
  364. {
  365. KeSetEvent( &pAdapt->QueueEvent, EVENT_INCREMENT, FALSE );
  366. }
  367. }
  368. //
  369. // Decrements a base packet's refcount and calls BrdgFwdReleaseBasePacket if the refcount
  370. // reaches zero
  371. //
  372. _inline
  373. BOOLEAN
  374. BrdgFwdDerefBasePacket(
  375. IN PADAPT pQuotaOwner, // Can be NULL to not count quota
  376. IN PNDIS_PACKET pBasePacket,
  377. IN PPACKET_INFO ppi,
  378. IN NDIS_STATUS Status
  379. )
  380. {
  381. BOOLEAN rc = FALSE;
  382. LONG RefCount;
  383. SAFEASSERT( pBasePacket != NULL );
  384. SAFEASSERT( ppi != NULL );
  385. RefCount = NdisInterlockedDecrement( &ppi->u.BasePacketInfo.RefCount );
  386. SAFEASSERT( RefCount >= 0 );
  387. if( RefCount == 0 )
  388. {
  389. BrdgFwdReleaseBasePacket( pBasePacket, ppi, BrdgBufGetPacketOwnership( pBasePacket ), Status );
  390. rc = TRUE;
  391. }
  392. // Do quota bookkeeping if necessary
  393. if( pQuotaOwner != NULL )
  394. {
  395. BrdgBufReleaseBasePacketQuota( pBasePacket, pQuotaOwner );
  396. }
  397. return rc;
  398. }
  399. //
  400. // Updates statistics to reflect a transmitted packet
  401. //
  402. _inline
  403. VOID
  404. BrdgFwdCountTransmittedPacket(
  405. IN PADAPT pAdapt,
  406. IN PUCHAR DstAddr,
  407. IN ULONG PacketSize
  408. )
  409. {
  410. SAFEASSERT( DstAddr != NULL );
  411. ExInterlockedAddLargeStatistic( &gStatTransmittedFrames, 1L );
  412. ExInterlockedAddLargeStatistic( &gStatTransmittedBytes, PacketSize );
  413. ExInterlockedAddLargeStatistic( &pAdapt->SentFrames, 1L );
  414. ExInterlockedAddLargeStatistic( &pAdapt->SentBytes, PacketSize );
  415. ExInterlockedAddLargeStatistic( &pAdapt->SentLocalFrames, 1L );
  416. ExInterlockedAddLargeStatistic( &pAdapt->SentLocalBytes, PacketSize );
  417. if( ETH_IS_MULTICAST(DstAddr) )
  418. {
  419. ExInterlockedAddLargeStatistic( &gStatMulticastTransmittedFrames, 1L );
  420. ExInterlockedAddLargeStatistic( &gStatMulticastTransmittedBytes, PacketSize );
  421. if( ETH_IS_BROADCAST(DstAddr) )
  422. {
  423. ExInterlockedAddLargeStatistic( &gStatBroadcastTransmittedFrames, 1L );
  424. ExInterlockedAddLargeStatistic( &gStatBroadcastTransmittedBytes, PacketSize );
  425. }
  426. }
  427. else
  428. {
  429. ExInterlockedAddLargeStatistic( &gStatDirectedTransmittedFrames, 1L );
  430. ExInterlockedAddLargeStatistic( &gStatDirectedTransmittedBytes, PacketSize );
  431. }
  432. }
  433. //
  434. // Updates statistics to reflect an indicated packet
  435. //
  436. _inline
  437. VOID
  438. BrdgFwdCountIndicatedPacket(
  439. IN PUCHAR DstAddr,
  440. IN ULONG PacketSize
  441. )
  442. {
  443. ExInterlockedAddLargeStatistic( &gStatIndicatedFrames, 1L );
  444. ExInterlockedAddLargeStatistic( &gStatIndicatedBytes, PacketSize );
  445. if( ETH_IS_MULTICAST(DstAddr) )
  446. {
  447. ExInterlockedAddLargeStatistic( &gStatMulticastIndicatedFrames, 1L );
  448. ExInterlockedAddLargeStatistic( &gStatMulticastIndicatedBytes, PacketSize );
  449. if( ETH_IS_BROADCAST(DstAddr) )
  450. {
  451. ExInterlockedAddLargeStatistic( &gStatBroadcastIndicatedFrames, 1L );
  452. ExInterlockedAddLargeStatistic( &gStatBroadcastIndicatedBytes, PacketSize );
  453. }
  454. }
  455. else
  456. {
  457. ExInterlockedAddLargeStatistic( &gStatDirectedIndicatedFrames, 1L );
  458. ExInterlockedAddLargeStatistic( &gStatDirectedIndicatedBytes, PacketSize );
  459. }
  460. }
  461. //
  462. // Indicates a packet, counting it as such.
  463. //
  464. _inline
  465. VOID
  466. BrdgFwdIndicatePacket(
  467. IN PNDIS_PACKET pPacket,
  468. IN NDIS_HANDLE MiniportHandle
  469. )
  470. {
  471. PVOID pHeader = BrdgBufGetPacketHeader(pPacket);
  472. SAFEASSERT( MiniportHandle != NULL );
  473. if( pHeader != NULL )
  474. {
  475. BrdgFwdCountIndicatedPacket( pHeader, BrdgBufTotalPacketSize(pPacket) );
  476. }
  477. // pHeader can only == NULL under heavy system stress
  478. NdisMIndicateReceivePacket( MiniportHandle, &pPacket, 1 );
  479. }
  480. // ===========================================================================
  481. //
  482. // PUBLIC FUNCTIONS
  483. //
  484. // ===========================================================================
  485. NTSTATUS
  486. BrdgFwdDriverInit()
  487. /*++
  488. Routine Description:
  489. Initialization code.
  490. A return status other than STATUS_SUCCESS causes the driver load to abort.
  491. Any event causing an error return code must be logged.
  492. Must be called at PASSIVE_LEVEL
  493. Arguments:
  494. None
  495. Return Value:
  496. None
  497. --*/
  498. {
  499. INT i;
  500. HANDLE ThreadHandle;
  501. NTSTATUS Status;
  502. SAFEASSERT(CURRENT_IRQL == PASSIVE_LEVEL);
  503. // Initialize our thread synchronization primitives
  504. KeInitializeEvent( &gKillThreads, NotificationEvent, FALSE );
  505. for(i = 0; i < KeNumberProcessors; i++)
  506. {
  507. KeInitializeEvent( &gThreadsCheckAdapters[i], SynchronizationEvent, FALSE );
  508. // Spin up a thread for this processor
  509. Status = PsCreateSystemThread( &ThreadHandle, THREAD_ALL_ACCESS, NULL, NULL, NULL,
  510. BrdgFwdProcessQueuedPackets, (PVOID)(INT_PTR)i );
  511. if(! NT_SUCCESS(Status) )
  512. {
  513. // Abort startup
  514. NdisWriteEventLogEntry( gDriverObject, EVENT_BRIDGE_THREAD_CREATION_FAILED, 0L, 0L, NULL,
  515. sizeof(NTSTATUS), &Status );
  516. DBGPRINT(FWD, ("Failed to create a system thread: %08x\n", Status));
  517. BrdgFwdCleanup();
  518. return Status;
  519. }
  520. // Retrieve a pointer to the thread object and reference it so we can wait for
  521. // its termination safely.
  522. Status = ObReferenceObjectByHandle( ThreadHandle, STANDARD_RIGHTS_ALL, NULL, KernelMode,
  523. &gThreadPtrs[i], NULL );
  524. if(! NT_SUCCESS(Status) )
  525. {
  526. // Abort startup
  527. NdisWriteEventLogEntry( gDriverObject, EVENT_BRIDGE_THREAD_REF_FAILED, 0L, 0L, NULL,
  528. sizeof(NTSTATUS), &Status );
  529. DBGPRINT(FWD, ("Couldn't retrieve a thread pointer: %08x\n", Status));
  530. BrdgFwdCleanup();
  531. return Status;
  532. }
  533. gNumThreads++;
  534. }
  535. return STATUS_SUCCESS;
  536. }
  537. VOID
  538. BrdgFwdCleanup()
  539. /*++
  540. Routine Description:
  541. Unload-time orderly cleanup
  542. This function is guaranteed to be called exactly once
  543. Must be called at < DISPATCH_LEVEL since we wait on an event
  544. Arguments:
  545. None
  546. Return Value:
  547. None
  548. --*/
  549. {
  550. KWAIT_BLOCK WaitBlocks[MAXIMUM_WAIT_OBJECTS];
  551. NTSTATUS Status;
  552. UINT i;
  553. SAFEASSERT(CURRENT_IRQL < DISPATCH_LEVEL);
  554. // Signal the threads to exit
  555. KeSetEvent( &gKillThreads, EVENT_INCREMENT, FALSE );
  556. // Block waiting for all threads to exit
  557. Status = KeWaitForMultipleObjects( gNumThreads, gThreadPtrs, WaitAll, Executive,
  558. KernelMode, FALSE, NULL, WaitBlocks );
  559. if( ! NT_SUCCESS(Status) )
  560. {
  561. // This really shouldn't happen
  562. DBGPRINT(FWD, ("KeWaitForMultipleObjects failed in BrdgFwdCleanup! %08x\n", Status));
  563. SAFEASSERT(FALSE);
  564. }
  565. // Dereference all thread objects to allow them to be destroyed
  566. for( i = 0; i < gNumThreads; i++ )
  567. {
  568. ObDereferenceObject( gThreadPtrs[i] );
  569. }
  570. }
  571. PNDIS_PACKET
  572. BrdgFwdMakeCompatCopyPacket(
  573. IN PNDIS_PACKET pBasePacket,
  574. OUT PUCHAR *pPacketData,
  575. OUT PUINT packetDataSize,
  576. BOOLEAN bCountAsLocalSend
  577. )
  578. /*++
  579. Routine Description:
  580. Allocates a copy packet and fills it with a copy of the data from the given base
  581. packet. Used by the compatibility-mode code to make a copy packet that it can
  582. edit easily
  583. Arguments:
  584. pBasePacket Packet to copy from
  585. pPacketData Receives a pointer to the flat data buffer of the new packet
  586. packetDataSize Receives the size of the copied data
  587. bBasePacketIsInbound TRUE if the packet being copied is outbound from higher-level
  588. protocols; the packet will be counted as a miniport
  589. transmission if / when it is send out an adapter.
  590. FALSE causes the packet to not be counted as a local transmission.
  591. Return Value:
  592. The new packet
  593. --*/
  594. {
  595. PNDIS_PACKET pCopyPacket;
  596. PPACKET_INFO ppi;
  597. UINT copiedBytes;
  598. // Find out how much data is in the base packet
  599. NdisQueryPacket( pBasePacket, NULL, NULL, NULL, packetDataSize );
  600. // Make a base copy packet with no data in it
  601. pCopyPacket = BrdgFwdMakeCopyBasePacket( &ppi, NULL, NULL, 0, 0, *packetDataSize, FALSE, NULL, pPacketData );
  602. if( pCopyPacket == NULL )
  603. {
  604. return NULL;
  605. }
  606. SAFEASSERT( ppi != NULL );
  607. SAFEASSERT( *pPacketData != NULL );
  608. // Set the original direction flags
  609. if( bCountAsLocalSend )
  610. {
  611. ppi->Flags.OriginalDirection = BrdgPacketOutbound;
  612. }
  613. else
  614. {
  615. ppi->Flags.OriginalDirection = BrdgPacketCreatedInBridge;
  616. }
  617. // Copy the data from the base packet to the copy packet
  618. NdisCopyFromPacketToPacket( pCopyPacket, 0, *packetDataSize, pBasePacket, 0, &copiedBytes );
  619. if( copiedBytes != *packetDataSize )
  620. {
  621. // We couldn't copy all the data. Bail out.
  622. THROTTLED_DBGPRINT(FWD, ("Failed to copy into a copy packet for compatibility processing\n"));
  623. BrdgFwdReleaseBasePacket(pCopyPacket, ppi, BrdgBufGetPacketOwnership(pCopyPacket), NDIS_STATUS_RESOURCES);
  624. return NULL;
  625. }
  626. // Put a pointer to the ppi where we expect to find it on completion
  627. *((PPACKET_INFO*)pCopyPacket->ProtocolReserved) = ppi;
  628. *((PPACKET_INFO*)pCopyPacket->MiniportReserved) = ppi;
  629. // Do fixups usually performed by BrdgFwdHandlePacket()
  630. ppi->u.BasePacketInfo.RefCount = 1L;
  631. ppi->u.BasePacketInfo.CompositeStatus = NDIS_STATUS_FAILURE;
  632. // The packet is now ready to be sent. We expect the compatibility code to do its work
  633. // and call BrdgFwdSendPacketForComp() to transmit the packet.
  634. return pCopyPacket;
  635. }
  636. VOID
  637. BrdgFwdSendPacketForCompat(
  638. IN PNDIS_PACKET pPacket,
  639. IN PADAPT pAdapt
  640. )
  641. /*++
  642. Routine Description:
  643. Transmits a packet on behalf of the compatibility-mode module.
  644. The packet must have been previously allocated with BrdgFwdMakeCompatCopyPacket.
  645. Arguments:
  646. pPacket The packet to transmit
  647. pAdapt The adapter to transmit on
  648. Return Value:
  649. None
  650. --*/
  651. {
  652. PPACKET_INFO ppi;
  653. NDIS_STATUS status;
  654. // Make sure the packet hasn't been monkeyed with inappropriately
  655. ppi = *((PPACKET_INFO*)pPacket->ProtocolReserved);
  656. SAFEASSERT( ppi->pOwnerPacket == pPacket );
  657. SAFEASSERT( ppi->Flags.bIsBasePacket );
  658. // Make sure this is a one-shot packet
  659. ppi->u.BasePacketInfo.RefCount = 1L;
  660. // We must do a quota check before sending the packet, as the packet completion
  661. // logic assumes all sent packets have been assigned to their outbound adapters
  662. if( BrdgBufAssignBasePacketQuota(pPacket, pAdapt) )
  663. {
  664. // We passed quota. Transmit the packet.
  665. BrdgFwdSendOnLink( pAdapt, pPacket );
  666. }
  667. else
  668. {
  669. // We didn't pass quota. Fail the transmission.
  670. DBGPRINT(FWD, ("Failed to send a compatibility packet because of quota failure\n"));
  671. status = NDIS_STATUS_RESOURCES;
  672. BrdgFwdReleaseBasePacket(pPacket, ppi, BrdgBufGetPacketOwnership(pPacket), NDIS_STATUS_RESOURCES);
  673. }
  674. }
  675. VOID
  676. BrdgFwdIndicatePacketForCompat(
  677. IN PNDIS_PACKET pPacket
  678. )
  679. /*++
  680. Routine Description:
  681. Indicates a packet on behalf of the compatibility-mode module.
  682. The packet must be a base copy packet that we own.
  683. Arguments:
  684. pPacket The packet to indicate
  685. Return Value:
  686. None
  687. --*/
  688. {
  689. PPACKET_INFO ppi;
  690. NDIS_STATUS status;
  691. NDIS_HANDLE MiniportHandle;
  692. // Make sure the packet is a base packet and isn't out of
  693. // whack
  694. ppi = *((PPACKET_INFO*)pPacket->MiniportReserved);
  695. SAFEASSERT( ppi->pOwnerPacket == pPacket );
  696. SAFEASSERT( ppi->Flags.bIsBasePacket );
  697. // Packets that come to us for indication from the compatibility
  698. // module are our own base packets that haven't had their refcount
  699. // set yet. Set the packet's refcount to 1, since its buffers
  700. // should never be shared.
  701. ppi->u.BasePacketInfo.RefCount = 1L;
  702. MiniportHandle = BrdgMiniAcquireMiniportForIndicate();
  703. if( MiniportHandle != NULL )
  704. {
  705. // Check the quota for the local miniport
  706. if( BrdgBufAssignBasePacketQuota(pPacket, LOCAL_MINIPORT) )
  707. {
  708. // We passed quota.
  709. BrdgFwdIndicatePacket( pPacket, MiniportHandle );
  710. }
  711. else
  712. {
  713. // We didn't pass quota. Fail the transmission.
  714. DBGPRINT(FWD, ("Failed to indicate a compatibility packet because of quota failure\n"));
  715. status = NDIS_STATUS_RESOURCES;
  716. BrdgFwdReleaseBasePacket(pPacket, ppi, BrdgBufGetPacketOwnership(pPacket), NDIS_STATUS_RESOURCES);
  717. }
  718. BrdgMiniReleaseMiniportForIndicate();
  719. }
  720. else
  721. {
  722. // No miniport. Ditch the packet.
  723. BrdgFwdReleaseBasePacket(pPacket, ppi, BrdgBufGetPacketOwnership(pPacket), NDIS_STATUS_SUCCESS);
  724. }
  725. }
  726. VOID BrdgFwdReleaseCompatPacket(
  727. IN PNDIS_PACKET pPacket
  728. )
  729. /*++
  730. Routine Description:
  731. Releases a packet previously allocated with BrdgFwdMakeCompatCopyPacket.
  732. Arguments:
  733. pPacket The packet to release
  734. Return Value:
  735. None
  736. --*/
  737. {
  738. PPACKET_INFO ppi;
  739. // Retrieve the PACKET_INFO pointer
  740. ppi = *((PPACKET_INFO*)pPacket->ProtocolReserved);
  741. SAFEASSERT( ppi->pOwnerPacket == pPacket );
  742. SAFEASSERT( ppi->Flags.bIsBasePacket );
  743. BrdgFwdReleaseBasePacket(pPacket, ppi, BrdgBufGetPacketOwnership(pPacket), NDIS_STATUS_SUCCESS);
  744. }
  745. NDIS_STATUS
  746. BrdgFwdSendBuffer(
  747. IN PADAPT pAdapt,
  748. IN PUCHAR pPacketData,
  749. IN UINT DataSize
  750. )
  751. /*++
  752. Routine Description:
  753. Sends a raw buffer on a particular adapter. Used to send frames in response
  754. to user-mode requests.
  755. Arguments:
  756. pAdapt The adapter to send on
  757. pPacketData The frame
  758. DataSize The size of the supplied frame
  759. Return Value:
  760. Status of the packet transmission
  761. --*/
  762. {
  763. PNDIS_PACKET pPacket;
  764. PPACKET_INFO ppi;
  765. // Build a packet around this buffer
  766. pPacket = BrdgFwdMakeCopyBasePacket( &ppi, pPacketData, NULL, DataSize, 0, DataSize, FALSE, NULL, NULL );
  767. if( pPacket == NULL )
  768. {
  769. return NDIS_STATUS_RESOURCES;
  770. }
  771. SAFEASSERT( ppi != NULL );
  772. // We must do a quota check before sending the packet, as the packet completion
  773. // logic assumes all sent packets have been assigned to their outbound adapters
  774. if( ! BrdgBufAssignBasePacketQuota(pPacket, pAdapt) )
  775. {
  776. // We didn't pass quota. Fail the transmission.
  777. DBGPRINT(FWD, ("Failed to send a raw buffer because of quota failure\n"));
  778. BrdgFwdReleaseBasePacket(pPacket, ppi, BrdgBufGetPacketOwnership(pPacket), NDIS_STATUS_RESOURCES);
  779. return NDIS_STATUS_RESOURCES;
  780. }
  781. // Put a pointer to the ppi where we expect to find it on completion
  782. *((PPACKET_INFO*)pPacket->ProtocolReserved) = ppi;
  783. // Do fixups usually performed by BrdgFwdHandlePacket()
  784. ppi->u.BasePacketInfo.RefCount = 1L;
  785. ppi->u.BasePacketInfo.CompositeStatus = NDIS_STATUS_FAILURE;
  786. // Send the packet
  787. BrdgFwdSendOnLink( pAdapt, pPacket );
  788. return NDIS_STATUS_SUCCESS;
  789. }
  790. NDIS_STATUS
  791. BrdgFwdReceive(
  792. IN NDIS_HANDLE ProtocolBindingContext,
  793. IN NDIS_HANDLE MacReceiveContext,
  794. IN PVOID pHeader,
  795. IN UINT HeaderSize,
  796. IN PVOID pLookAheadBuffer,
  797. IN UINT LookAheadSize,
  798. IN UINT PacketSize
  799. )
  800. /*++
  801. Routine Description:
  802. NDIS copy-path entry point. Receives an inbound packet on the copy path.
  803. Because the indicated data buffers are valid only for the duration of this
  804. function, we must copy the indicated data to our own packet descriptor
  805. before proceeding.
  806. Arguments:
  807. ProtocolBindingContext The receiving adapter
  808. MacReceiveContext Must be passed as a param to certain Ndis APIs
  809. pHeader Packet header buffer
  810. HeaderSize Size of pHeader
  811. pLookAheadBuffer Buffer with packet data
  812. LookAheadSize Size of pLookAheadBuffer
  813. PacketSize Total packet size
  814. Return Value:
  815. Status of the receive (cannot be NDIS_STATUS_PENDING)
  816. --*/
  817. {
  818. PADAPT pAdapt = (PADAPT)ProtocolBindingContext, TargetAdapt = NULL;
  819. PUCHAR SrcAddr = ((PUCHAR)pHeader) + ETH_LENGTH_OF_ADDRESS, DstAddr = pHeader;
  820. PNDIS_PACKET pNewPacket;
  821. PPACKET_INFO ppi;
  822. PPACKET_Q_INFO ppqi;
  823. UINT SizeOfPacket = HeaderSize + PacketSize;
  824. BOOLEAN bIsSTAPacket = FALSE, bIsUnicastToBridge = FALSE, bRequiresCompatWork = FALSE;
  825. UINT result;
  826. #if DBG
  827. // Paranoia check for incorrectly looped-back packets
  828. {
  829. PNDIS_PACKET pPacket = NdisGetReceivedPacket(pAdapt->BindingHandle, MacReceiveContext);
  830. if( pPacket != NULL )
  831. {
  832. SAFEASSERT( BrdgBufGetPacketOwnership(pPacket) == BrdgNotOwned );
  833. }
  834. }
  835. // Break on packets from gBreakMACAddress
  836. if( gBreakOnMACAddress )
  837. {
  838. ETH_COMPARE_NETWORK_ADDRESSES_EQ( SrcAddr, gBreakMACAddress, &result );
  839. if( result == 0 )
  840. {
  841. KdBreakPoint();
  842. }
  843. }
  844. #endif
  845. //
  846. // We don't accept packets that are sent from our MAC address to us.
  847. //
  848. ETH_COMPARE_NETWORK_ADDRESSES_EQ( SrcAddr, gBridgeAddress, &result );
  849. if (0 == result)
  850. {
  851. return NDIS_STATUS_NOT_ACCEPTED;
  852. }
  853. // Don't accept packets if we are shutting down or this adapter is being torn down or reset
  854. if( (gShuttingDown) || (pAdapt->bResetting) || (! BrdgAcquireAdapter(pAdapt)) )
  855. {
  856. return NDIS_STATUS_NOT_ACCEPTED;
  857. }
  858. // Must have at least a complete Ethernet header!
  859. if( HeaderSize < ETHERNET_HEADER_SIZE )
  860. {
  861. THROTTLED_DBGPRINT(FWD, ("Too-small header seen in BrdgFwdReceive!\n"));
  862. BrdgReleaseAdapter( pAdapt );
  863. return NDIS_STATUS_NOT_ACCEPTED;
  864. }
  865. // Packet can't be larger than the maximum size we can handle
  866. if( SizeOfPacket > MAX_PACKET_SIZE )
  867. {
  868. THROTTLED_DBGPRINT(FWD, ("Too-large packet seen in BrdgFwdReceive!\n"));
  869. BrdgReleaseAdapter( pAdapt );
  870. return NDIS_STATUS_NOT_ACCEPTED;
  871. }
  872. //
  873. // If this is an STA packet, we go through all the receive motions regardless of
  874. // our state
  875. //
  876. if( BrdgFwdIsSTAGroupAddress(DstAddr) )
  877. {
  878. if( DstAddr[5] == STA_MAC_ADDR[5] )
  879. {
  880. bIsSTAPacket = TRUE;
  881. TargetAdapt = NULL;
  882. }
  883. else
  884. {
  885. // Packet was sent to a reserved multicast address that we don't use.
  886. // We mustn't forward the frame.
  887. BrdgReleaseAdapter( pAdapt );
  888. return NDIS_STATUS_NOT_ACCEPTED;
  889. }
  890. }
  891. if( ! bIsSTAPacket )
  892. {
  893. // Note the MAC address of the frame if this adapter is learning
  894. if( (pAdapt->State == Learning) || (pAdapt->State == Forwarding) )
  895. {
  896. BrdgTblNoteAddress(SrcAddr, pAdapt);
  897. }
  898. //
  899. // Check if we are accepting packets or not
  900. //
  901. if( pAdapt->State != Forwarding )
  902. {
  903. BrdgReleaseAdapter( pAdapt );
  904. return NDIS_STATUS_NOT_ACCEPTED;
  905. }
  906. //
  907. // Look up the target in our table.
  908. // ** TargetAdapt comes back with its refcount incremented!
  909. //
  910. TargetAdapt = BrdgTblFindTargetAdapter( DstAddr );
  911. // If the target host is known to be on the same segment as the received
  912. // packet, there is no need to forward the packet.
  913. //
  914. // Also bail out here if the target adapter is resetting
  915. if( (TargetAdapt == pAdapt) ||
  916. ((TargetAdapt != NULL) && (TargetAdapt->bResetting)) )
  917. {
  918. BrdgReleaseAdapter( TargetAdapt );
  919. BrdgReleaseAdapter( pAdapt );
  920. return NDIS_STATUS_NOT_ACCEPTED;
  921. }
  922. // Learn if this packet requires compatibility-mode processing later
  923. // (this forces us to copy the packet to our own buffers and queue it)
  924. bRequiresCompatWork = BrdgCompRequiresCompatWork( pAdapt, pHeader, HeaderSize );
  925. // If the packet came in on a compatibility adapter, or is going to
  926. // a compatibility-mode adapter, but the compatibility code is not
  927. // interested in it, there is nothing further to be done with the packet.
  928. if( (pAdapt->bCompatibilityMode || ((TargetAdapt != NULL) && (TargetAdapt->bCompatibilityMode)))
  929. &&
  930. (! bRequiresCompatWork) )
  931. {
  932. if( TargetAdapt != NULL )
  933. {
  934. BrdgReleaseAdapter( TargetAdapt );
  935. }
  936. BrdgReleaseAdapter( pAdapt );
  937. return NDIS_STATUS_NOT_ACCEPTED;
  938. }
  939. bIsUnicastToBridge = BrdgMiniIsUnicastToBridge(DstAddr);
  940. // Sanity
  941. if( bIsUnicastToBridge && (TargetAdapt != NULL) )
  942. {
  943. //
  944. // This indicates that someone else on the network is using our MAC address,
  945. // or that there is an undetected loop such that we are seeing our own traffic!
  946. // Either way, this is very bad.
  947. //
  948. THROTTLED_DBGPRINT(FWD, ("*** Have a table entry for our own MAC address! PROBABLE NET LOOP!\n"));
  949. // Ditch the target adapter since we won't be using it
  950. BrdgReleaseAdapter( TargetAdapt );
  951. TargetAdapt = NULL;
  952. }
  953. }
  954. // else was STA packet; continue processing below
  955. //
  956. // There is no fast-track on the copy-receive path. Copy the packet data into our
  957. // own descriptor and queue the packet for processing later.
  958. //
  959. if (LookAheadSize == PacketSize)
  960. {
  961. // A normal, non-fragmented indicate. Copy the data to a new packet.
  962. pNewPacket = BrdgFwdMakeCopyBasePacket( &ppi, pHeader, pLookAheadBuffer, HeaderSize, LookAheadSize,
  963. SizeOfPacket, TRUE, pAdapt, NULL );
  964. if( pNewPacket == NULL )
  965. {
  966. // We failed to get a copy packet to wrap this data
  967. goto failure;
  968. }
  969. SAFEASSERT( ppi != NULL );
  970. if (bRequiresCompatWork && (TargetAdapt == NULL) && !bIsUnicastToBridge)
  971. {
  972. TargetAdapt = BrdgCompFindTargetAdapterForIPAddress(pNewPacket);
  973. if (TargetAdapt && !BrdgAcquireAdapter(TargetAdapt))
  974. {
  975. return NDIS_STATUS_NOT_ACCEPTED;
  976. }
  977. }
  978. // Queue the new packet for processing
  979. ppqi = (PPACKET_Q_INFO)&pNewPacket->ProtocolReserved;
  980. ppqi->u.pTargetAdapt = TargetAdapt;
  981. ppqi->pInfo = ppi;
  982. ppqi->Flags.bIsSTAPacket = bIsSTAPacket;
  983. ppqi->Flags.bFastTrackReceive = FALSE;
  984. ppqi->Flags.bRequiresCompatWork = bRequiresCompatWork;
  985. if( bIsUnicastToBridge )
  986. {
  987. SAFEASSERT( TargetAdapt == NULL );
  988. ppqi->Flags.bIsUnicastToBridge = TRUE;
  989. ppqi->Flags.bShouldIndicate = TRUE;
  990. }
  991. else
  992. {
  993. ppqi->Flags.bIsUnicastToBridge = FALSE;
  994. ppqi->Flags.bShouldIndicate = BrdgMiniShouldIndicatePacket(DstAddr);
  995. }
  996. BrdgFwdQueuePacket( ppqi, pAdapt );
  997. }
  998. else
  999. {
  1000. NDIS_STATUS Status;
  1001. UINT transferred;
  1002. PNDIS_BUFFER pBufDesc;
  1003. PUCHAR pBuf;
  1004. //
  1005. // This is an unusual code path in this day and age; the underlying driver
  1006. // is an old NDIS driver that still does fragmented receives.
  1007. //
  1008. SAFEASSERT( LookAheadSize < PacketSize );
  1009. // Get copy packet and copy in the header data (but NOT the lookahead)
  1010. pNewPacket = BrdgFwdMakeCopyBasePacket( &ppi, pHeader, NULL, HeaderSize, 0, SizeOfPacket, TRUE, pAdapt, &pBuf );
  1011. if( pNewPacket == NULL )
  1012. {
  1013. // We failed to get a copy packet
  1014. goto failure;
  1015. }
  1016. SAFEASSERT( ppi != NULL );
  1017. SAFEASSERT( pBuf != NULL );
  1018. //
  1019. // NdisTransferData is kind of a crummy API; it won't copy the entire packet
  1020. // (i.e., you have to copy the header separately), and it won't let you specify
  1021. // an offset in the receiving packet to copy to. The NIC wants to copy into the
  1022. // beginning of the first buffer chained to the packet.
  1023. //
  1024. // Because of this silliness, we copy the header into the beginning of our copy
  1025. // packet's data buffer (done in the call to BrdgFwdMakeCopyBasePacket above).
  1026. //
  1027. // Then we grab a NEW buffer descriptor, point it to the area of the data buffer
  1028. // *after* the header, and chain it to the front of the packet. Then we request
  1029. // that all data (other than the header) be copied.
  1030. //
  1031. // In BrdgFwdTransferComplete, we rip off the leading buffer descriptor and
  1032. // dispose of it, leaving a single buffer descriptor that correctly describes
  1033. // the (single) data buffer, now containing all data.
  1034. //
  1035. pBufDesc = BrdgBufAllocateBuffer( pBuf + HeaderSize, PacketSize );
  1036. if( pBufDesc == NULL )
  1037. {
  1038. BrdgFwdReleaseBasePacket( pNewPacket, ppi, BrdgBufGetPacketOwnership(pNewPacket),
  1039. NDIS_STATUS_FAILURE );
  1040. goto failure;
  1041. }
  1042. // Chain this to the front of the packet where it will be used during the copy
  1043. NdisChainBufferAtFront( pNewPacket, pBufDesc );
  1044. // Set up the queuing structure in the packet's ProtocolReserved area
  1045. ppqi = (PPACKET_Q_INFO)&pNewPacket->ProtocolReserved;
  1046. ppqi->u.pTargetAdapt = TargetAdapt;
  1047. ppqi->pInfo = ppi;
  1048. ppqi->Flags.bIsSTAPacket = bIsSTAPacket;
  1049. ppqi->Flags.bFastTrackReceive = FALSE;
  1050. ppqi->Flags.bRequiresCompatWork = bRequiresCompatWork;
  1051. if( bIsUnicastToBridge )
  1052. {
  1053. SAFEASSERT( TargetAdapt == NULL );
  1054. ppqi->Flags.bIsUnicastToBridge = TRUE;
  1055. ppqi->Flags.bShouldIndicate = TRUE;
  1056. }
  1057. else
  1058. {
  1059. ppqi->Flags.bIsUnicastToBridge = FALSE;
  1060. ppqi->Flags.bShouldIndicate = BrdgMiniShouldIndicatePacket(DstAddr);
  1061. }
  1062. // Ask the NIC to copy the packet's data into the new packet
  1063. NdisTransferData( &Status, pAdapt->BindingHandle, MacReceiveContext, 0, PacketSize,
  1064. pNewPacket, &transferred );
  1065. if( Status == NDIS_STATUS_SUCCESS )
  1066. {
  1067. // Call BrdgFwdTransferComplete by hand to postprocess the packet.
  1068. BrdgFwdTransferComplete( (NDIS_HANDLE)pAdapt, pNewPacket, Status, transferred );
  1069. }
  1070. else if( Status != NDIS_STATUS_PENDING )
  1071. {
  1072. // The transfer failed for some reason.
  1073. NdisUnchainBufferAtFront( pNewPacket, &pBufDesc );
  1074. if( pBufDesc != NULL )
  1075. {
  1076. NdisFreeBuffer( pBufDesc );
  1077. }
  1078. else
  1079. {
  1080. SAFEASSERT( FALSE );
  1081. }
  1082. BrdgFwdReleaseBasePacket( pNewPacket, ppi, BrdgBufGetPacketOwnership(pNewPacket),
  1083. NDIS_STATUS_FAILURE );
  1084. goto failure;
  1085. }
  1086. // else BrdgFwdTransferComplete will be called to postprocess the packet.
  1087. }
  1088. BrdgReleaseAdapter( pAdapt );
  1089. return NDIS_STATUS_SUCCESS;
  1090. failure:
  1091. if( TargetAdapt != NULL )
  1092. {
  1093. BrdgReleaseAdapter( TargetAdapt );
  1094. }
  1095. if( BrdgMiniShouldIndicatePacket(DstAddr) )
  1096. {
  1097. ExInterlockedAddLargeStatistic( &gStatIndicatedDroppedFrames, 1L );
  1098. }
  1099. BrdgReleaseAdapter( pAdapt );
  1100. return NDIS_STATUS_NOT_ACCEPTED;
  1101. }
  1102. VOID
  1103. BrdgFwdTransferComplete(
  1104. IN NDIS_HANDLE ProtocolBindingContext,
  1105. IN PNDIS_PACKET pPacket,
  1106. IN NDIS_STATUS Status,
  1107. IN UINT BytesTransferred
  1108. )
  1109. /*++
  1110. Routine Description:
  1111. NDIS entry point, registered in BrdgProtRegisterProtocol. Called when a
  1112. call to NdisTransferData() that returned NDIS_STATUS_PENDING completes
  1113. (we also call this by hand to postprocess a call that completes immediately).
  1114. If the data copy from the underlying NIC was successful, the packet is
  1115. queued for processing on the owner adapter's queue. Otherwise the packet
  1116. is released.
  1117. Arguments:
  1118. ProtocolBindingContext The receiving adapter
  1119. pPacket The base packet into which data was being copied
  1120. Status Status of the copy
  1121. BytesTransferred Number of transferred bytes (unused)
  1122. Return Value:
  1123. None
  1124. --*/
  1125. {
  1126. PADAPT pAdapt = (PADAPT)ProtocolBindingContext;
  1127. PPACKET_Q_INFO ppqi = (PPACKET_Q_INFO)&pPacket->ProtocolReserved;
  1128. PNDIS_BUFFER pBuf;
  1129. SAFEASSERT( pAdapt != NULL );
  1130. SAFEASSERT( pPacket != NULL );
  1131. SAFEASSERT( ppqi->pInfo != NULL );
  1132. SAFEASSERT( ppqi->pInfo->pOwnerPacket == pPacket );
  1133. SAFEASSERT( ppqi->Flags.bFastTrackReceive == FALSE );
  1134. // Remove the extra buffer descriptor on the front of the packet and dispose of it
  1135. // (see comments in BrdgFwdReceive() for details)
  1136. NdisUnchainBufferAtFront( pPacket, &pBuf );
  1137. if( pBuf != NULL )
  1138. {
  1139. NdisFreeBuffer( pBuf );
  1140. }
  1141. else
  1142. {
  1143. // Should never happen
  1144. SAFEASSERT( FALSE );
  1145. }
  1146. // We should still have the original buffer descriptor describing the entire data buffer
  1147. // chained to the packet
  1148. SAFEASSERT( BrdgBufPacketHeadBuffer(pPacket) != NULL );
  1149. if( Status != NDIS_STATUS_SUCCESS )
  1150. {
  1151. // The copy failed. Undo everything.
  1152. if( ppqi->u.pTargetAdapt != NULL )
  1153. {
  1154. BrdgReleaseAdapter( ppqi->u.pTargetAdapt );
  1155. }
  1156. if( ppqi->Flags.bShouldIndicate )
  1157. {
  1158. ExInterlockedAddLargeStatistic( &gStatIndicatedDroppedFrames, 1L );
  1159. }
  1160. BrdgFwdReleaseBasePacket( pPacket, ppqi->pInfo, BrdgBufGetPacketOwnership(pPacket), Status );
  1161. }
  1162. else
  1163. {
  1164. // Success! Queue the packet for processing
  1165. BrdgFwdQueuePacket( ppqi, pAdapt );
  1166. }
  1167. }
  1168. INT
  1169. BrdgFwdReceivePacket(
  1170. IN NDIS_HANDLE ProtocolBindingContext,
  1171. IN PNDIS_PACKET pPacket
  1172. )
  1173. /*++
  1174. Routine Description:
  1175. NDIS no-copy entry point
  1176. Receives a packet on the no-copy path
  1177. Arguments:
  1178. ProtocolBindingContext The adapter on which the packet is received
  1179. pPacket The received packet
  1180. Return Value:
  1181. The number of times we will call NdisReturnPackets() to free this packet.
  1182. We return 0 to complete immediately or 1 to pend.
  1183. --*/
  1184. {
  1185. PADAPT pAdapt = (PADAPT)ProtocolBindingContext, TargetAdapt;
  1186. UINT PacketSize;
  1187. PNDIS_BUFFER Buffer;
  1188. PUCHAR DstAddr, SrcAddr;
  1189. UINT Size;
  1190. PPACKET_Q_INFO ppqi;
  1191. INT rc;
  1192. BOOLEAN bForceCopy = FALSE, bFastTrack = FALSE, bIsUnicastToBridge = FALSE,
  1193. bRequiresCompatWork = FALSE;
  1194. // Paranoia check for incorrectly looped-back packets
  1195. SAFEASSERT( BrdgBufGetPacketOwnership(pPacket) == BrdgNotOwned );
  1196. // Don't receive packets if we are shutting down or this adapter is being torn down or reset
  1197. if ( gShuttingDown || (pAdapt->bResetting) || (! BrdgAcquireAdapter(pAdapt)) )
  1198. {
  1199. return 0;
  1200. }
  1201. NdisQueryPacket(pPacket, NULL, NULL, &Buffer, &PacketSize);
  1202. if (!Buffer)
  1203. {
  1204. BrdgReleaseAdapter( pAdapt );
  1205. return 0;
  1206. }
  1207. NdisQueryBufferSafe(Buffer, &DstAddr, &Size, NormalPagePriority);
  1208. if( DstAddr == NULL )
  1209. {
  1210. BrdgReleaseAdapter( pAdapt );
  1211. return 0;
  1212. }
  1213. // Must have at least a complete Ethernet header!
  1214. if( Size < ETHERNET_HEADER_SIZE )
  1215. {
  1216. THROTTLED_DBGPRINT(FWD, ("Packet smaller than Ethernet header seen!\n"));
  1217. BrdgReleaseAdapter( pAdapt );
  1218. return 0;
  1219. }
  1220. // Packet can't be larger than the maximum we can handle
  1221. if( Size > MAX_PACKET_SIZE )
  1222. {
  1223. THROTTLED_DBGPRINT(FWD, ("Over-large packet seen!\n"));
  1224. BrdgReleaseAdapter( pAdapt );
  1225. return 0;
  1226. }
  1227. SrcAddr = DstAddr + ETH_LENGTH_OF_ADDRESS;
  1228. #if DBG
  1229. // Break on packets from gBreakMACAddress
  1230. if( gBreakOnMACAddress )
  1231. {
  1232. UINT result;
  1233. ETH_COMPARE_NETWORK_ADDRESSES_EQ( SrcAddr, gBreakMACAddress, &result );
  1234. if( result == 0 )
  1235. {
  1236. KdBreakPoint();
  1237. }
  1238. }
  1239. #endif
  1240. //
  1241. // If this is an STA packet, don't process it, but hand it off
  1242. //
  1243. if( BrdgFwdIsSTAGroupAddress(DstAddr) )
  1244. {
  1245. if( (! gDisableSTA) && (DstAddr[5] == STA_MAC_ADDR[5]))
  1246. {
  1247. if (BrdgFwdBridgingNetworks())
  1248. {
  1249. // Hand off this packet for processing
  1250. BrdgSTAReceivePacket( pAdapt, pPacket );
  1251. }
  1252. }
  1253. BrdgReleaseAdapter( pAdapt );
  1254. return 0;
  1255. }
  1256. // Note the MAC address of the frame if this adapter is learning
  1257. if( (pAdapt->State == Learning) || (pAdapt->State == Forwarding) )
  1258. {
  1259. BrdgTblNoteAddress(SrcAddr, pAdapt);
  1260. }
  1261. //
  1262. // Check if we are accepting packets or not
  1263. //
  1264. if( pAdapt->State != Forwarding )
  1265. {
  1266. BrdgReleaseAdapter( pAdapt );
  1267. return 0;
  1268. }
  1269. // Look up the target in our table
  1270. TargetAdapt = BrdgTblFindTargetAdapter( DstAddr );
  1271. // If the target host is known to be on the same segment as the received
  1272. // packet, there is no need to forward the packet.
  1273. //
  1274. // Also bail out if the target adapter is resetting
  1275. if( (TargetAdapt == pAdapt) ||
  1276. ((TargetAdapt != NULL) && (TargetAdapt->bResetting)) )
  1277. {
  1278. BrdgReleaseAdapter( TargetAdapt );
  1279. BrdgReleaseAdapter( pAdapt );
  1280. return 0;
  1281. }
  1282. // Check if the packet will require compatibility-mode processing
  1283. bRequiresCompatWork = BrdgCompRequiresCompatWork( pAdapt, DstAddr, Size );
  1284. // If a packet requires compatibility work, we MUST copy it so the
  1285. // compatibility code has a flat, editable buffer to work with.
  1286. if( bRequiresCompatWork )
  1287. {
  1288. bForceCopy = TRUE;
  1289. }
  1290. // If the packet came in on a compatibility adapter, or is going to
  1291. // a compatibility-mode adapter, but the compatibility code is not
  1292. // interested in it, there is nothing further to be done with the packet.
  1293. if( (pAdapt->bCompatibilityMode || ((TargetAdapt != NULL) && (TargetAdapt->bCompatibilityMode)))
  1294. &&
  1295. (! bRequiresCompatWork) )
  1296. {
  1297. if( TargetAdapt != NULL )
  1298. {
  1299. BrdgReleaseAdapter( TargetAdapt );
  1300. }
  1301. BrdgReleaseAdapter( pAdapt );
  1302. return 0;
  1303. }
  1304. //
  1305. // If this packet is a unicast packet ONLY for the local machine,
  1306. // we can fast-track it by just passing through the indication to
  1307. // upper-layer protocols.
  1308. //
  1309. // We can't pull this stunt if the packet requires compatibility-mode
  1310. // processing.
  1311. //
  1312. bIsUnicastToBridge = BrdgMiniIsUnicastToBridge(DstAddr);
  1313. if( bIsUnicastToBridge && (!bRequiresCompatWork) )
  1314. {
  1315. NDIS_HANDLE MiniportHandle;
  1316. BOOLEAN bRemaining, bRetain;
  1317. if( TargetAdapt != NULL )
  1318. {
  1319. //
  1320. // This indicates that someone else on the network is using our MAC address,
  1321. // or that there is an undetected loop such that we are seeing our own traffic!
  1322. // Either way, this is very bad.
  1323. //
  1324. THROTTLED_DBGPRINT(FWD, ("** Have a table entry for our own MAC address! PROBABLE NET LOOP!\n"));
  1325. // We won't be needing the target adapter
  1326. BrdgReleaseAdapter( TargetAdapt );
  1327. TargetAdapt = NULL;
  1328. }
  1329. MiniportHandle = BrdgMiniAcquireMiniportForIndicate();
  1330. if( MiniportHandle == NULL )
  1331. {
  1332. // Nothing to do with this packet since we don't have a miniport to
  1333. // indicate it with!
  1334. BrdgReleaseAdapter( pAdapt );
  1335. return 0;
  1336. }
  1337. //
  1338. // Figure out if it's possible to fast-track this packet
  1339. //
  1340. NdisIMGetCurrentPacketStack(pPacket, &bRemaining);
  1341. if( bRemaining )
  1342. {
  1343. //
  1344. // We can fast-track right away if the packet queue for this adapter
  1345. // is empty. Otherwise, we would be cutting ahead of other packets from this
  1346. // adapter.
  1347. //
  1348. if( ! pAdapt->bServiceInProgress )
  1349. {
  1350. // We can fast-track this packet right now.
  1351. if( BrdgFwdNoCopyFastTrackReceive(pPacket, pAdapt, MiniportHandle, DstAddr, &bRetain) )
  1352. {
  1353. // bRetain tells us whether to retain ownership of this packet or not
  1354. BrdgReleaseAdapter( pAdapt );
  1355. BrdgMiniReleaseMiniportForIndicate();
  1356. return bRetain ? 1 : 0;
  1357. }
  1358. else
  1359. {
  1360. // This should never happen since we checked to see if there was stack room
  1361. SAFEASSERT( FALSE );
  1362. bForceCopy = TRUE;
  1363. bFastTrack = FALSE;
  1364. }
  1365. }
  1366. else
  1367. {
  1368. // We want to fast-track this packet but the processing queue is not
  1369. // empty. Flag it for fast-tracking in the queue draining thread.
  1370. bFastTrack = TRUE;
  1371. bForceCopy = FALSE;
  1372. }
  1373. }
  1374. else
  1375. {
  1376. // Force this packet to be copied into a base packet since
  1377. // we know it can't be fast-tracked.
  1378. bForceCopy = TRUE;
  1379. bFastTrack = FALSE;
  1380. }
  1381. // Allow the miniport to shut down
  1382. BrdgMiniReleaseMiniportForIndicate();
  1383. }
  1384. //
  1385. // We couldn't fast-track the packet. We will have to queue it for processing.
  1386. //
  1387. if ( bForceCopy || !bFastTrack || (NDIS_GET_PACKET_STATUS(pPacket) == NDIS_STATUS_RESOURCES) )
  1388. {
  1389. // We must copy this packet's data.
  1390. PNDIS_PACKET pNewPacket;
  1391. PPACKET_INFO ppi;
  1392. UINT copied;
  1393. // Get a new copy packet with nothing copied in yet.
  1394. pNewPacket = BrdgFwdMakeCopyBasePacket( &ppi, NULL, NULL, 0, 0, PacketSize, TRUE, pAdapt, NULL );
  1395. if( pNewPacket == NULL )
  1396. {
  1397. // Failed to get a copy packet to hold the data.
  1398. goto failure;
  1399. }
  1400. SAFEASSERT( ppi != NULL );
  1401. // Copy data out of the old packet into the new one
  1402. NdisCopyFromPacketToPacket( pNewPacket, 0, PacketSize, pPacket, 0, &copied );
  1403. if( copied != PacketSize )
  1404. {
  1405. BrdgFwdReleaseBasePacket( pNewPacket, ppi, BrdgBufGetPacketOwnership(pNewPacket),
  1406. NDIS_STATUS_FAILURE );
  1407. goto failure;
  1408. }
  1409. if (bRequiresCompatWork && (TargetAdapt == NULL) && !bIsUnicastToBridge)
  1410. {
  1411. TargetAdapt = BrdgCompFindTargetAdapterForIPAddress(pNewPacket);
  1412. if (TargetAdapt && !BrdgAcquireAdapter(TargetAdapt))
  1413. {
  1414. TargetAdapt = NULL;
  1415. }
  1416. }
  1417. // Queue the new base packet for processing
  1418. ppqi = (PPACKET_Q_INFO)&pNewPacket->ProtocolReserved;
  1419. ppqi->pInfo = ppi;
  1420. ppqi->u.pTargetAdapt = TargetAdapt;
  1421. ppqi->Flags.bIsSTAPacket = FALSE;
  1422. ppqi->Flags.bFastTrackReceive = FALSE;
  1423. ppqi->Flags.bRequiresCompatWork = bRequiresCompatWork;
  1424. if( bIsUnicastToBridge )
  1425. {
  1426. SAFEASSERT( TargetAdapt == NULL );
  1427. ppqi->Flags.bIsUnicastToBridge = TRUE;
  1428. ppqi->Flags.bShouldIndicate = TRUE;
  1429. }
  1430. else
  1431. {
  1432. ppqi->Flags.bIsUnicastToBridge = FALSE;
  1433. ppqi->Flags.bShouldIndicate = BrdgMiniShouldIndicatePacket(DstAddr);
  1434. }
  1435. // The NIC gets its packet back immediately since we copied its data
  1436. rc = 0;
  1437. }
  1438. else
  1439. {
  1440. // Queue the original packet for processing
  1441. ppqi = (PPACKET_Q_INFO)&pPacket->ProtocolReserved;
  1442. ppqi->pInfo = NULL;
  1443. ppqi->Flags.bIsSTAPacket = FALSE;
  1444. ppqi->Flags.bIsUnicastToBridge = bIsUnicastToBridge;
  1445. ppqi->Flags.bRequiresCompatWork = bRequiresCompatWork;
  1446. if( bFastTrack )
  1447. {
  1448. SAFEASSERT( bIsUnicastToBridge );
  1449. SAFEASSERT( TargetAdapt == NULL );
  1450. ppqi->Flags.bFastTrackReceive = TRUE;
  1451. ppqi->Flags.bShouldIndicate = TRUE;
  1452. ppqi->u.pOriginalAdapt = pAdapt;
  1453. }
  1454. else
  1455. {
  1456. ppqi->Flags.bFastTrackReceive = FALSE;
  1457. ppqi->u.pTargetAdapt = TargetAdapt;
  1458. if( bIsUnicastToBridge )
  1459. {
  1460. SAFEASSERT( TargetAdapt == NULL );
  1461. ppqi->Flags.bShouldIndicate = TRUE;
  1462. }
  1463. else
  1464. {
  1465. ppqi->Flags.bShouldIndicate = BrdgMiniShouldIndicatePacket(DstAddr);
  1466. }
  1467. }
  1468. // We require the use of the packet until our processing is complete
  1469. rc = 1;
  1470. }
  1471. // Queue the packet for processing
  1472. BrdgFwdQueuePacket( ppqi, pAdapt );
  1473. BrdgReleaseAdapter( pAdapt );
  1474. return rc;
  1475. failure:
  1476. if( TargetAdapt != NULL )
  1477. {
  1478. BrdgReleaseAdapter( TargetAdapt );
  1479. }
  1480. if( BrdgMiniShouldIndicatePacket(DstAddr) )
  1481. {
  1482. ExInterlockedAddLargeStatistic( &gStatIndicatedDroppedFrames, 1L );
  1483. }
  1484. BrdgReleaseAdapter( pAdapt );
  1485. // We are done with this packet
  1486. return 0;
  1487. }
  1488. NDIS_STATUS
  1489. BrdgFwdSendPacket(
  1490. IN PNDIS_PACKET pPacket
  1491. )
  1492. /*++
  1493. Routine Description:
  1494. Called to handle the transmission of a packet from an overlying protocol
  1495. Arguments:
  1496. pPacket The packet to send
  1497. Return Value:
  1498. Status of the send (NDIS_STATUS_PENDING means the send will be completed later)
  1499. --*/
  1500. {
  1501. PNDIS_BUFFER Buffer;
  1502. PUCHAR DstAddr;
  1503. UINT Size;
  1504. PADAPT TargetAdapt;
  1505. BOOLEAN bRemaining;
  1506. NDIS_STATUS Status;
  1507. PNDIS_PACKET_STACK pStack;
  1508. NdisQueryPacket(pPacket, NULL, NULL, &Buffer, NULL);
  1509. NdisQueryBufferSafe(Buffer, &DstAddr, &Size, NormalPagePriority);
  1510. if( DstAddr == NULL )
  1511. {
  1512. return NDIS_STATUS_RESOURCES;
  1513. }
  1514. //
  1515. // See if we know the adapter to reach the target through
  1516. //
  1517. TargetAdapt = BrdgTblFindTargetAdapter( DstAddr );
  1518. // Fail silently if the target adapter is resetting
  1519. if( (TargetAdapt != NULL) && (TargetAdapt->bResetting) )
  1520. {
  1521. BrdgReleaseAdapter( TargetAdapt );
  1522. return NDIS_STATUS_SUCCESS;
  1523. }
  1524. // Do compatibility processing, unless the packet is going to
  1525. // a known target that isn't on a compatibility adapter (in
  1526. // which case no compatibility processing is required).
  1527. if( (TargetAdapt == NULL) || (TargetAdapt->bCompatibilityMode) )
  1528. {
  1529. BrdgCompProcessOutboundPacket( pPacket, TargetAdapt );
  1530. }
  1531. // If the target adapter is in compatibility-mode, no processing
  1532. // other than the compatibility processing is required.
  1533. if( (TargetAdapt != NULL) && (TargetAdapt->bCompatibilityMode) )
  1534. {
  1535. // We're done with this packet!
  1536. BrdgReleaseAdapter( TargetAdapt );
  1537. return NDIS_STATUS_SUCCESS;
  1538. }
  1539. //
  1540. // We can fast-track the packet if there is an NDIS stack slot available
  1541. // for use and there is a single target adapter to send on.
  1542. //
  1543. pStack = NdisIMGetCurrentPacketStack(pPacket, &bRemaining);
  1544. if( (TargetAdapt != NULL) && bRemaining && (pStack != NULL) )
  1545. {
  1546. // We fiddle with some of the packet flags when sending a packet. Remember the
  1547. // state of the flags we change so we can restore them before handing back the
  1548. // packet when the send completes.
  1549. *((PUINT)(pStack->IMReserved)) = NdisGetPacketFlags(pPacket) & CHANGED_PACKET_FLAGS;
  1550. // Just fast-track it out the target adapter
  1551. BrdgFwdSendOnLink( TargetAdapt, pPacket );
  1552. // Done with the adapter pointer
  1553. BrdgReleaseAdapter( TargetAdapt );
  1554. // We retain the buffers until we're done
  1555. return NDIS_STATUS_PENDING;
  1556. }
  1557. //
  1558. // Can't fast-track for whatever reason. We need to take the slow path through BrdgFwdHandlePacket
  1559. //
  1560. Status = BrdgFwdHandlePacket( BrdgPacketOutbound, TargetAdapt, NULL /* No source adapter */, FALSE /* Do not indicate */,
  1561. NULL /*No miniport handle because no indication*/, NULL, NULL, /*No base packet yet*/
  1562. BrdgFwdMakeSendBasePacket, pPacket, NULL, 0, 0 );
  1563. if( TargetAdapt != NULL )
  1564. {
  1565. // We're done with this adapter pointer
  1566. BrdgReleaseAdapter( TargetAdapt );
  1567. }
  1568. return Status;
  1569. }
  1570. VOID
  1571. BrdgFwdCleanupPacket(
  1572. IN PADAPT pAdapt,
  1573. IN PNDIS_PACKET pPacket,
  1574. IN NDIS_STATUS Status
  1575. )
  1576. /*++
  1577. Routine Description:
  1578. NDIS entry point called when a packet transmission has completed
  1579. Arguments:
  1580. ProtocolBindingContext The adapter on which the packet was send
  1581. pPacket The transmitted packet
  1582. Status The status of the send
  1583. Return Value:
  1584. None
  1585. --*/
  1586. {
  1587. PACKET_OWNERSHIP Own;
  1588. // Find out whether we own this packet
  1589. Own = BrdgBufGetPacketOwnership(pPacket);
  1590. if( Own == BrdgNotOwned )
  1591. {
  1592. NDIS_HANDLE MiniportHandle;
  1593. PNDIS_PACKET_STACK pStack;
  1594. BOOLEAN bRemaining;
  1595. // This packet must have been a fast-track send. Return it to
  1596. // its upper-layer owner.
  1597. // Restore the flags that we change on a packet send by retrieving the
  1598. // stored state of these flags that we stashed in IMReserved in
  1599. // BrdgFwdSendPacket.
  1600. pStack = NdisIMGetCurrentPacketStack(pPacket, &bRemaining);
  1601. if( (pStack != NULL) && bRemaining )
  1602. {
  1603. NdisClearPacketFlags( pPacket, CHANGED_PACKET_FLAGS );
  1604. NdisSetPacketFlags( pPacket, *((PUINT)(pStack->IMReserved)) );
  1605. }
  1606. else
  1607. {
  1608. // There was stack room on the way down so this shouldn't happen.
  1609. SAFEASSERT( FALSE );
  1610. }
  1611. if( Status == NDIS_STATUS_SUCCESS )
  1612. {
  1613. PVOID pHeader = BrdgBufGetPacketHeader(pPacket);
  1614. if( pHeader != NULL )
  1615. {
  1616. BrdgFwdCountTransmittedPacket( pAdapt, pHeader, BrdgBufTotalPacketSize(pPacket) );
  1617. }
  1618. // pHeader can only be NULL under heavy system stress
  1619. }
  1620. else
  1621. {
  1622. ExInterlockedAddLargeStatistic( &gStatTransmittedErrorFrames, 1L );
  1623. }
  1624. // NDIS should prevent the miniport from shutting down while
  1625. // there is still a send pending.
  1626. MiniportHandle = BrdgMiniAcquireMiniport();
  1627. SAFEASSERT( MiniportHandle != NULL );
  1628. NdisMSendComplete( MiniportHandle, pPacket, Status );
  1629. BrdgMiniReleaseMiniport();
  1630. }
  1631. else
  1632. {
  1633. //
  1634. // We allocated this packet ourselves.
  1635. //
  1636. // Recover the info pointer from our reserved area in the packet header
  1637. PPACKET_INFO ppi = *((PPACKET_INFO*)pPacket->ProtocolReserved),
  1638. baseppi;
  1639. PNDIS_PACKET pBasePacket;
  1640. if( ppi->Flags.bIsBasePacket == FALSE )
  1641. {
  1642. // This packet is using buffers from another packet.
  1643. baseppi = ppi->u.pBasePacketInfo;
  1644. SAFEASSERT( baseppi != NULL );
  1645. pBasePacket = baseppi->pOwnerPacket;
  1646. SAFEASSERT( pBasePacket != NULL );
  1647. }
  1648. else
  1649. {
  1650. // This packet tracks its own buffers.
  1651. pBasePacket = pPacket;
  1652. baseppi = ppi;
  1653. }
  1654. // Contribute to the composite status of this packet
  1655. if( Status == NDIS_STATUS_SUCCESS )
  1656. {
  1657. baseppi->u.BasePacketInfo.CompositeStatus = NDIS_STATUS_SUCCESS;
  1658. }
  1659. {
  1660. UCHAR DstAddr[ETH_LENGTH_OF_ADDRESS];
  1661. UINT PacketSize;
  1662. PVOID pHeader = BrdgBufGetPacketHeader(pBasePacket);
  1663. NDIS_STATUS PacketStatus;
  1664. PACKET_DIRECTION PacketDirection;
  1665. // Pull out some information before we try to free the packet
  1666. if( pHeader != NULL )
  1667. {
  1668. ETH_COPY_NETWORK_ADDRESS( DstAddr, pHeader );
  1669. }
  1670. // pHeader can only == NULL under heavy system stress
  1671. PacketStatus = baseppi->u.BasePacketInfo.CompositeStatus;
  1672. PacketDirection = baseppi->Flags.OriginalDirection;
  1673. BrdgFwdValidatePacketDirection( PacketDirection );
  1674. PacketSize = BrdgBufTotalPacketSize(pBasePacket);
  1675. // Now deref the packet
  1676. if( BrdgFwdDerefBasePacket( pAdapt, pBasePacket, baseppi, PacketStatus ) )
  1677. {
  1678. // The base packet was freed. Now ILLEGAL to reference pHeader, baseppi or pBasepacket
  1679. if( PacketDirection == BrdgPacketOutbound )
  1680. {
  1681. // This was a local-source packet.
  1682. if( PacketStatus == NDIS_STATUS_SUCCESS )
  1683. {
  1684. if( pHeader != NULL )
  1685. {
  1686. BrdgFwdCountTransmittedPacket( pAdapt, DstAddr, PacketSize );
  1687. }
  1688. }
  1689. else
  1690. {
  1691. ExInterlockedAddLargeStatistic( &gStatTransmittedErrorFrames, 1L );
  1692. }
  1693. }
  1694. else
  1695. {
  1696. // This was a relayed packet.
  1697. ExInterlockedAddLargeStatistic( &pAdapt->SentFrames, 1L );
  1698. ExInterlockedAddLargeStatistic( &pAdapt->SentBytes, PacketSize );
  1699. }
  1700. }
  1701. }
  1702. if( pBasePacket != pPacket )
  1703. {
  1704. // Owned copy packets are always base packets, so this should be a no-copy packet.
  1705. SAFEASSERT( Own == BrdgOwnWrapperPacket );
  1706. BrdgFwdFreeWrapperPacket( pPacket, ppi, pAdapt );
  1707. }
  1708. }
  1709. }
  1710. VOID
  1711. BrdgFwdSendComplete(
  1712. IN NDIS_HANDLE ProtocolBindingContext,
  1713. IN PNDIS_PACKET pPacket,
  1714. IN NDIS_STATUS Status
  1715. )
  1716. /*++
  1717. Routine Description:
  1718. NDIS entry point called when a packet transmission has completed
  1719. Arguments:
  1720. ProtocolBindingContext The adapter on which the packet was send
  1721. pPacket The transmitted packet
  1722. Status The status of the send
  1723. Return Value:
  1724. None
  1725. --*/
  1726. {
  1727. PADAPT pAdapt = (PADAPT)ProtocolBindingContext;
  1728. SAFEASSERT( pAdapt != NULL );
  1729. if (pAdapt)
  1730. {
  1731. if( Status != NDIS_STATUS_SUCCESS )
  1732. {
  1733. THROTTLED_DBGPRINT(FWD, ("Packet send failed with %08x\n", Status));
  1734. }
  1735. BrdgFwdCleanupPacket(pAdapt, pPacket, Status);
  1736. BrdgDecrementWaitRef(&pAdapt->Refcount);
  1737. }
  1738. }
  1739. VOID
  1740. BrdgFwdReturnIndicatedPacket(
  1741. IN NDIS_HANDLE MiniportAdapterContext,
  1742. IN PNDIS_PACKET pPacket
  1743. )
  1744. /*++
  1745. Routine Description:
  1746. NDIS entry point called when a packet indication has completed
  1747. Arguments:
  1748. MiniportAdapterContext Ignored
  1749. pPacket The transmitted packet
  1750. Return Value:
  1751. None
  1752. --*/
  1753. {
  1754. PACKET_OWNERSHIP Own;
  1755. // Find out whether we own this packet
  1756. Own = BrdgBufGetPacketOwnership(pPacket);
  1757. if( Own == BrdgNotOwned )
  1758. {
  1759. // This packet must have been a fast-track receive. Return it to
  1760. // its lower-layer owner.
  1761. BOOLEAN bRemaining;
  1762. PNDIS_PACKET_STACK pStack = NdisIMGetCurrentPacketStack(pPacket, &bRemaining);
  1763. PADAPT pOwnerAdapt;
  1764. // If we fast-tracked this packet, it MUST have had room for us to stash our
  1765. // pointer to the owning adapter
  1766. SAFEASSERT( pStack != NULL );
  1767. SAFEASSERT( bRemaining );
  1768. if (pStack)
  1769. {
  1770. // We incremented the owning adapter's refcount when we first received the packet
  1771. pOwnerAdapt = (PADAPT)pStack->IMReserved[0];
  1772. SAFEASSERT( pOwnerAdapt != NULL );
  1773. // Here you go
  1774. NdisReturnPackets( &pPacket, 1 );
  1775. // Release the owning NIC after the packet release
  1776. BrdgReleaseAdapter( pOwnerAdapt );
  1777. }
  1778. else
  1779. {
  1780. // if pStack is NULL, then we just return the packet as we can't determine the owning adapter.
  1781. // Here you go
  1782. NdisReturnPackets( &pPacket, 1 );
  1783. }
  1784. // Illegal to refer to pPacket now
  1785. pPacket = NULL;
  1786. }
  1787. else
  1788. {
  1789. // Recover our packet info block from our reserved area in the packet header
  1790. PPACKET_INFO ppi = *((PPACKET_INFO*)pPacket->MiniportReserved);
  1791. // Indications are always made with the base packet
  1792. SAFEASSERT( ppi->Flags.bIsBasePacket );
  1793. // Let go of the base packet
  1794. BrdgFwdDerefBasePacket( LOCAL_MINIPORT, pPacket, ppi, ppi->u.BasePacketInfo.CompositeStatus );
  1795. }
  1796. }
  1797. // ===========================================================================
  1798. //
  1799. // PRIVATE FUNCTIONS
  1800. //
  1801. // ===========================================================================
  1802. BOOLEAN
  1803. BrdgFwdServiceQueue(
  1804. IN PADAPT pAdapt
  1805. )
  1806. /*++
  1807. Routine Description:
  1808. Services the inbound packet queue of a particular adapter
  1809. This routine raises IRQL to DISPATCH to service the queue. It will
  1810. service up to MAX_PACKETS_AT_DPC packets at DISPATCH and then
  1811. return, even if the adapter's queue has not been drained.
  1812. The bServiceInProgress flag is cleared if this routine manages to
  1813. drain the adapter's queue. If the queue is non-empty when the
  1814. routine exits, the bServiceInProgress flag is left set.
  1815. Arguments:
  1816. pAdapt The adapter to service
  1817. Return Value:
  1818. TRUE == the adapter's queue was drained FALSE == there are still queued
  1819. packets to be serviced in the adapter's queue.
  1820. --*/
  1821. {
  1822. PPACKET_Q_INFO pqi;
  1823. NDIS_HANDLE MiniportHandle = NULL;
  1824. KIRQL oldIrql;
  1825. ULONG HandledPackets = 0L;
  1826. BOOLEAN bQueueWasEmptied;
  1827. SAFEASSERT( pAdapt != NULL );
  1828. KeRaiseIrql( DISPATCH_LEVEL, &oldIrql );
  1829. // We should only be scheduled when there's something to deal with
  1830. SAFEASSERT( BrdgQuerySingleListLength(&pAdapt->Queue) > 0 );
  1831. SAFEASSERT( pAdapt->bServiceInProgress );
  1832. // Get a handle on the miniport for the entire function duration
  1833. MiniportHandle = BrdgMiniAcquireMiniportForIndicate();
  1834. //
  1835. // The queue lock protects bServiceInProgress as well. Use it to dequeue
  1836. // packets and update the flag atomically.
  1837. //
  1838. NdisDprAcquireSpinLock( &pAdapt->QueueLock);
  1839. pqi = (PPACKET_Q_INFO)BrdgRemoveHeadSingleList(&pAdapt->Queue);
  1840. while( pqi != NULL )
  1841. {
  1842. PNDIS_PACKET pPacket;
  1843. PADAPT TargetAdapt = NULL, OriginalAdapt = NULL;
  1844. //
  1845. // QueueRefcount reflects the number of elements in the processing queue
  1846. // so people can block on it becoming empty
  1847. //
  1848. BrdgDecrementWaitRef( &pAdapt->QueueRefcount );
  1849. SAFEASSERT( (ULONG)pAdapt->QueueRefcount.Refcount == pAdapt->Queue.Length );
  1850. NdisDprReleaseSpinLock( &pAdapt->QueueLock );
  1851. // Demultiplex the union
  1852. if( pqi->Flags.bFastTrackReceive )
  1853. {
  1854. OriginalAdapt = pqi->u.pOriginalAdapt;
  1855. }
  1856. else
  1857. {
  1858. TargetAdapt = pqi->u.pTargetAdapt;
  1859. }
  1860. // Recover the packet pointer from the ProtocolReserved offset
  1861. pPacket = CONTAINING_RECORD(pqi, NDIS_PACKET, ProtocolReserved);
  1862. // Deal with this packet
  1863. if( pqi->pInfo != NULL )
  1864. {
  1865. if( pqi->Flags.bIsSTAPacket )
  1866. {
  1867. if( ! gDisableSTA && BrdgFwdBridgingNetworks() )
  1868. {
  1869. // Hand this packet off to the STA code
  1870. BrdgSTAReceivePacket( pAdapt, pPacket );
  1871. }
  1872. // We're done with this packet
  1873. BrdgFwdReleaseBasePacket( pPacket, pqi->pInfo, BrdgBufGetPacketOwnership(pPacket),
  1874. NDIS_STATUS_SUCCESS );
  1875. // It is an error to use any of these variables now
  1876. pPacket = NULL;
  1877. pqi = NULL;
  1878. }
  1879. else
  1880. {
  1881. BOOLEAN bShouldIndicate = pqi->Flags.bShouldIndicate,
  1882. bIsUnicastToBridge = pqi->Flags.bIsUnicastToBridge,
  1883. bRequiresCompatWork = pqi->Flags.bRequiresCompatWork,
  1884. bCompatOnly;
  1885. NDIS_STATUS Status;
  1886. PPACKET_INFO ppi = pqi->pInfo;
  1887. BOOLEAN bRetained = FALSE;
  1888. //
  1889. // This is an already-wrapped packet from the copy path.
  1890. //
  1891. SAFEASSERT( ! pqi->Flags.bFastTrackReceive );
  1892. // Before passing this packet along for processing, we must put a pointer to the packet's
  1893. // info block back into its MiniportReserved and ProtocolReserved areas so completion
  1894. // routines can recover the info block.
  1895. //
  1896. SAFEASSERT( ppi->pOwnerPacket == pPacket );
  1897. *((PPACKET_INFO*)pPacket->ProtocolReserved) = ppi;
  1898. *((PPACKET_INFO*)pPacket->MiniportReserved) = ppi;
  1899. // It is an error to use pqi anymore since it points into the ProtocolReserved area
  1900. pqi = NULL;
  1901. // If this packet arrived on a compatibility adapter or is bound for a
  1902. // compatibility adapter, only compatibility-mode work is required.
  1903. bCompatOnly = (BOOLEAN)((pAdapt->bCompatibilityMode) ||
  1904. ((TargetAdapt != NULL) && (TargetAdapt->bCompatibilityMode)));
  1905. // Do compatibility work first if required
  1906. if( bRequiresCompatWork )
  1907. {
  1908. bRetained = BrdgCompProcessInboundPacket( pPacket, pAdapt, bCompatOnly );
  1909. Status = NDIS_STATUS_SUCCESS;
  1910. }
  1911. else
  1912. {
  1913. // Packet shouldn't have gotten here if there's nothing to do with it
  1914. SAFEASSERT( ! bCompatOnly );
  1915. bRetained = FALSE;
  1916. Status = NDIS_STATUS_SUCCESS;
  1917. }
  1918. if( ! bCompatOnly )
  1919. {
  1920. // We told the compatibility module not to retain the packet
  1921. SAFEASSERT( ! bRetained );
  1922. if( bIsUnicastToBridge )
  1923. {
  1924. SAFEASSERT( TargetAdapt == NULL );
  1925. bRetained = FALSE;
  1926. Status = NDIS_STATUS_FAILURE;
  1927. if( MiniportHandle != NULL )
  1928. {
  1929. if( BrdgBufAssignBasePacketQuota(pPacket, LOCAL_MINIPORT) )
  1930. {
  1931. // Do fixups usually done in BrdgFwdHandlePacket
  1932. ppi->u.BasePacketInfo.RefCount = 1L;
  1933. ppi->u.BasePacketInfo.CompositeStatus = NDIS_STATUS_FAILURE;
  1934. // Indicate the packet up
  1935. BrdgFwdIndicatePacket( pPacket, MiniportHandle );
  1936. bRetained = TRUE;
  1937. }
  1938. else
  1939. {
  1940. THROTTLED_DBGPRINT(FWD, ("Local miniport over quota on queued receive!\n"));
  1941. }
  1942. }
  1943. }
  1944. else
  1945. {
  1946. if ((NULL == TargetAdapt) && pAdapt->bCompatibilityMode)
  1947. {
  1948. TargetAdapt = BrdgCompFindTargetAdapterForIPAddress(pPacket);
  1949. if (TargetAdapt && !BrdgAcquireAdapter(TargetAdapt))
  1950. {
  1951. TargetAdapt = NULL;
  1952. }
  1953. }
  1954. // Hand off this packet for general processing
  1955. Status = BrdgFwdHandlePacket( BrdgPacketInbound, TargetAdapt, pAdapt, bShouldIndicate,
  1956. MiniportHandle, pPacket, ppi, NULL, NULL, NULL, 0, 0 );
  1957. if( Status == NDIS_STATUS_PENDING )
  1958. {
  1959. bRetained = TRUE;
  1960. }
  1961. else
  1962. {
  1963. // The base packet we previously created was not actually used by BrdgFwdHandlePacket.
  1964. bRetained = FALSE;
  1965. }
  1966. }
  1967. }
  1968. // If our processing did not retain the packet for later release, release it now.
  1969. if( ! bRetained )
  1970. {
  1971. BrdgFwdReleaseBasePacket( pPacket, ppi, BrdgBufGetPacketOwnership(pPacket), Status );
  1972. }
  1973. }
  1974. }
  1975. else
  1976. {
  1977. // Can't have unwrapped STA packets
  1978. SAFEASSERT( ! pqi->Flags.bIsSTAPacket );
  1979. // Can't have unwrapped packets for compatibility processing
  1980. SAFEASSERT( ! pqi->Flags.bRequiresCompatWork );
  1981. // Packet should not be here (unwrapped) if it arrived from a compatibility-mode
  1982. // adapter.
  1983. SAFEASSERT( ! pAdapt->bCompatibilityMode );
  1984. // BrdgFwdReceivePacket should copy unicast packets that can't be fast-tracked
  1985. // into base packets before queuing them; we shouldn't end up with unwrapped
  1986. // packets that are unicast to the bridge but aren't tagged for fast-tracking.
  1987. if( pqi->Flags.bIsUnicastToBridge )
  1988. {
  1989. SAFEASSERT( pqi->Flags.bFastTrackReceive );
  1990. }
  1991. if( pqi->Flags.bFastTrackReceive )
  1992. {
  1993. BOOLEAN bRetained = FALSE;
  1994. SAFEASSERT( pqi->Flags.bIsUnicastToBridge );
  1995. if( MiniportHandle != NULL )
  1996. {
  1997. PUCHAR DstAddr = BrdgBufGetPacketHeader(pPacket);
  1998. if( DstAddr != NULL )
  1999. {
  2000. // This is unicast to the bridge only; we are asked to try to fast-track it straight up to
  2001. // overlying protocols.
  2002. if( BrdgFwdNoCopyFastTrackReceive(pPacket, OriginalAdapt, MiniportHandle, DstAddr, &bRetained ) )
  2003. {
  2004. // We had better be able to retain ownership of the original packet because we've already
  2005. // hung on to it past the return of FwdReceivePacket!
  2006. SAFEASSERT( bRetained );
  2007. }
  2008. else
  2009. {
  2010. // BrdgFwdReceivePacket is supposed to make sure packets can be fast-tracked
  2011. // before queuing them up
  2012. SAFEASSERT( FALSE );
  2013. }
  2014. }
  2015. // DstAddr can only == NULL under heavy system stress
  2016. }
  2017. if( !bRetained )
  2018. {
  2019. // Error of some sort or the miniport isn't available for indications. Ditch the packet.
  2020. NdisReturnPackets( &pPacket, 1 );
  2021. // Illegal to refer to the packet now
  2022. pPacket = NULL;
  2023. }
  2024. }
  2025. else
  2026. {
  2027. NDIS_STATUS Status;
  2028. // Packet should not be here (unwrapped) if it is bound for a compatibility-mode adapter.
  2029. SAFEASSERT( ! TargetAdapt->bCompatibilityMode );
  2030. // This is not a packet unicast to the bridge. Do the more general processing.
  2031. Status = BrdgFwdHandlePacket( BrdgPacketInbound, TargetAdapt, pAdapt, pqi->Flags.bShouldIndicate,
  2032. MiniportHandle, NULL, NULL, BrdgFwdMakeNoCopyBasePacket, pPacket, pAdapt, 0, 0 );
  2033. if( Status != NDIS_STATUS_PENDING )
  2034. {
  2035. // The unwrapped packet from the underlying NIC was not used. Release it now.
  2036. NdisReturnPackets( &pPacket, 1 );
  2037. // Illegal to refer to the packet now
  2038. pPacket = NULL;
  2039. }
  2040. }
  2041. }
  2042. // Release the target adapter if there was one
  2043. if( TargetAdapt )
  2044. {
  2045. BrdgReleaseAdapter( TargetAdapt );
  2046. }
  2047. // Acquire the spin lock before either exiting or grabbing the next packet
  2048. NdisDprAcquireSpinLock( &pAdapt->QueueLock );
  2049. // If we've processed too many packets, bail out even if the queue is not empty
  2050. HandledPackets++;
  2051. if( HandledPackets >= MAX_PACKETS_AT_DPC )
  2052. {
  2053. break;
  2054. }
  2055. // Get the next packet off the queue
  2056. pqi = (PPACKET_Q_INFO)BrdgRemoveHeadSingleList(&pAdapt->Queue);
  2057. }
  2058. //
  2059. // Clear bServiceInProgress only if we emptied the queue. Otherwise, leave it set to
  2060. // prevent spurious signalling of the QueueEvent, which would cause more than one
  2061. // draining thread to service the same queue!
  2062. //
  2063. if( BrdgQuerySingleListLength(&pAdapt->Queue) == 0L )
  2064. {
  2065. bQueueWasEmptied = TRUE;
  2066. pAdapt->bServiceInProgress = FALSE;
  2067. }
  2068. else
  2069. {
  2070. bQueueWasEmptied = FALSE;
  2071. }
  2072. NdisDprReleaseSpinLock( &pAdapt->QueueLock );
  2073. // Let go of the miniport until next time
  2074. if( MiniportHandle != NULL )
  2075. {
  2076. BrdgMiniReleaseMiniportForIndicate();
  2077. }
  2078. KeLowerIrql(oldIrql);
  2079. return bQueueWasEmptied;
  2080. }
  2081. VOID
  2082. BrdgFwdProcessQueuedPackets(
  2083. IN PVOID Param1
  2084. )
  2085. /*++
  2086. Routine Description:
  2087. Per-adapter inbound packet queue draining function
  2088. There is one instance of this function running per processor.
  2089. This routine sleeps until there is work to be done, and then calls
  2090. BrdgFwdServiceQueue to service whichever adapter needs attention.
  2091. It does this by blocking against the QueueEvent object for each
  2092. adapter's queue, as well as the global gKillThreads and the
  2093. gThreadsCheckAdapters event for this processor.
  2094. When the block returns, there is an event needing attention; it
  2095. may be the fact that the thread has been signaled to exit, that
  2096. this thread is supposed to re-enumerate adapters, or that an
  2097. adapter needs its inbound queue serviced.
  2098. This routine increments the refcount of every adapter that it
  2099. sleeps against; the gThreadsCheckAdapters event causes the thread
  2100. to re-examine the adapter list and release its refcount on any
  2101. adapters that were removed (or notice new additions).
  2102. Must be called at < DISPATCH_LEVEL since we wait on an event
  2103. Arguments:
  2104. Param1 The processor on which we should execute
  2105. (is not necessarily the processor on which
  2106. we are first scheduled)
  2107. Return Value:
  2108. None
  2109. --*/
  2110. {
  2111. // Double cast to tell the IA64 compiler we really mean to truncate
  2112. UINT Processor = (UINT)(ULONG_PTR)Param1;
  2113. PVOID WaitObjects[MAXIMUM_WAIT_OBJECTS];
  2114. KWAIT_BLOCK WaitBlocks[MAXIMUM_WAIT_OBJECTS];
  2115. ULONG numWaitObjects;
  2116. BOOLEAN bDie = FALSE;
  2117. PVOID pThread = KeGetCurrentThread();
  2118. // Constants
  2119. const ULONG KILL_EVENT = 0L, CHECK_EVENT = 1L;
  2120. DBGPRINT(FWD, ("Spinning up a thread on processor %i\n", Processor));
  2121. // Elevate our priority
  2122. KeSetPriorityThread(pThread, LOW_REALTIME_PRIORITY);
  2123. // Attach ourselves to our designated processor
  2124. KeSetAffinityThread(pThread, (KAFFINITY)(1<<Processor));
  2125. // Start off waiting against just the kill event and the re-enumerate event.
  2126. WaitObjects[KILL_EVENT] = &gKillThreads;
  2127. WaitObjects[CHECK_EVENT] = &gThreadsCheckAdapters[Processor];
  2128. numWaitObjects = 2L;
  2129. while( ! bDie )
  2130. {
  2131. NTSTATUS Status;
  2132. ULONG firedObject;
  2133. //
  2134. // Block until we are told to exit, re-enumerate, or until a processor's
  2135. // queue signals that it needs servicing.
  2136. //
  2137. SAFEASSERT(CURRENT_IRQL < DISPATCH_LEVEL);
  2138. Status = KeWaitForMultipleObjects( numWaitObjects, WaitObjects, WaitAny, Executive,
  2139. KernelMode, FALSE, NULL, WaitBlocks );
  2140. if( ! NT_SUCCESS(Status) )
  2141. {
  2142. // This really shouldn't happen
  2143. DBGPRINT(FWD, ("KeWaitForMultipleObjects failed! %08x\n", Status));
  2144. SAFEASSERT(FALSE);
  2145. // Pretend this was a signal to exit
  2146. firedObject = KILL_EVENT;
  2147. }
  2148. else
  2149. {
  2150. firedObject = (ULONG)Status - (ULONG)STATUS_WAIT_0;
  2151. }
  2152. if( firedObject == KILL_EVENT )
  2153. {
  2154. // We are asked to exit.
  2155. DBGPRINT(FWD, ("Exiting queue servicing thread on processor %i\n", Processor));
  2156. bDie = TRUE;
  2157. }
  2158. else if( firedObject == CHECK_EVENT )
  2159. {
  2160. LOCK_STATE LockState;
  2161. UINT i;
  2162. PADAPT pAdapt;
  2163. DBGPRINT(FWD, ("Re-enumerating adapters on processor %i\n", Processor));
  2164. // We must re-enumerate the list of adapters. First decrement the refcount on any
  2165. // adapters we're already holding
  2166. for( i = 2; i < numWaitObjects; i++ )
  2167. {
  2168. pAdapt = CONTAINING_RECORD( WaitObjects[i], ADAPT, QueueEvent );
  2169. BrdgReleaseAdapter( pAdapt );
  2170. }
  2171. numWaitObjects = 2;
  2172. // Now walk the adapter list and retrieve a pointer to each one's queue event.
  2173. NdisAcquireReadWriteLock( &gAdapterListLock, FALSE/*Read only*/, &LockState );
  2174. for( pAdapt = gAdapterList; pAdapt != NULL; pAdapt = pAdapt->Next )
  2175. {
  2176. // We will be using this adapter outside the list lock
  2177. BrdgAcquireAdapterInLock(pAdapt);
  2178. WaitObjects[numWaitObjects] = &pAdapt->QueueEvent;
  2179. numWaitObjects++;
  2180. }
  2181. NdisReleaseReadWriteLock( &gAdapterListLock, &LockState );
  2182. }
  2183. else
  2184. {
  2185. // An adapter needs queue servicing.
  2186. PADAPT pAdapt = CONTAINING_RECORD( WaitObjects[firedObject], ADAPT, QueueEvent );
  2187. if( ! BrdgFwdServiceQueue( pAdapt ) )
  2188. {
  2189. // The adapter's queue was serviced but not emptied. Signal the queue event so
  2190. // someone (maybe us!) will be scheduled to service the queue
  2191. KeSetEvent( &pAdapt->QueueEvent, EVENT_INCREMENT, FALSE );
  2192. }
  2193. }
  2194. }
  2195. // Shoot ourselves in the head
  2196. PsTerminateSystemThread( STATUS_SUCCESS );
  2197. }
  2198. PNDIS_PACKET
  2199. BrdgFwdMakeSendBasePacket(
  2200. OUT PPACKET_INFO *pppi,
  2201. IN PADAPT Target,
  2202. IN PVOID Param1,
  2203. IN PVOID Param2,
  2204. IN UINT Param3,
  2205. IN UINT Param4
  2206. )
  2207. /*++
  2208. Routine Description:
  2209. Passed as a parameter to BrdgFwdHandlePacket and called back as necessary
  2210. Builds a base packet from a packet outbound from overlying protocols
  2211. Arguments:
  2212. pppi The info block of the new base packet or NULL if the
  2213. allocation failed
  2214. Target The adapter to "charge" the new base packet to
  2215. Param1 The outbound packet
  2216. Param2 - Param4 Unused
  2217. Return Value:
  2218. The new base packet or NULL if the allocation failed (usually because the
  2219. target adapter didn't pass quota)
  2220. --*/
  2221. {
  2222. PNDIS_PACKET pPacket = (PNDIS_PACKET)Param1;
  2223. PNDIS_PACKET pNewPacket;
  2224. SAFEASSERT( pPacket != NULL );
  2225. // Get a wrapper packet to be the base packet
  2226. pNewPacket = BrdgFwdAllocAndWrapPacketForSend( pPacket, pppi, Target );
  2227. if( pNewPacket == NULL )
  2228. {
  2229. // We didn't pass quota for this target
  2230. return NULL;
  2231. }
  2232. // Stuff a pointer to the packet's info block into both the ProtocolReserved
  2233. // and the MiniportReserved areas so we can recover the info block no matter
  2234. // how we plan to use this packet
  2235. *((PPACKET_INFO*)pNewPacket->ProtocolReserved) = *pppi;
  2236. *((PPACKET_INFO*)pNewPacket->MiniportReserved) = *pppi;
  2237. SAFEASSERT( *pppi != NULL );
  2238. (*pppi)->u.BasePacketInfo.pOriginalPacket = pPacket;
  2239. (*pppi)->u.BasePacketInfo.pOwnerAdapter = NULL;
  2240. (*pppi)->Flags.OriginalDirection = BrdgPacketOutbound;
  2241. (*pppi)->Flags.bIsBasePacket = TRUE;
  2242. // Signal that the underlying NIC can hang on to the buffers
  2243. NDIS_SET_PACKET_STATUS( pNewPacket, NDIS_STATUS_SUCCESS );
  2244. return pNewPacket;
  2245. }
  2246. PNDIS_PACKET
  2247. BrdgFwdMakeNoCopyBasePacket(
  2248. OUT PPACKET_INFO *pppi,
  2249. IN PADAPT Target,
  2250. IN PVOID Param1,
  2251. IN PVOID Param2,
  2252. IN UINT Param3,
  2253. IN UINT Param4
  2254. )
  2255. /*++
  2256. Routine Description:
  2257. Passed as a parameter to BrdgFwdHandlePacket and called back as necessary
  2258. Builds a new base packet from a packet received on the no-copy path
  2259. Arguments:
  2260. pppi The info block for the new packet or NULL if the alloc
  2261. failed
  2262. Target The adapter to "charge" the new packet to
  2263. Param1 The originally indicated packet descriptor
  2264. Param2 The adapter on which the packet was received
  2265. Param3, Param4 Unused
  2266. Return Value:
  2267. A new base packet or NULL if the allocation failed (usually because the
  2268. target adapter did not pass quota)
  2269. --*/
  2270. {
  2271. PNDIS_PACKET pPacket = (PNDIS_PACKET)Param1;
  2272. PADAPT pOwnerAdapt = (PADAPT)Param2;
  2273. PNDIS_PACKET NewPacket;
  2274. SAFEASSERT( pPacket != NULL );
  2275. SAFEASSERT( pOwnerAdapt != NULL );
  2276. // Get a new wrapper packet
  2277. NewPacket = BrdgFwdAllocAndWrapPacketForReceive( pPacket, pppi, Target );
  2278. if (NewPacket == NULL)
  2279. {
  2280. // We didn't pass quota for this target
  2281. return NULL;
  2282. }
  2283. SAFEASSERT( *pppi != NULL );
  2284. // Stuff a pointer to the packet's info block into both the ProtocolReserved
  2285. // and the MiniportReserved areas so we can recover the info block no matter
  2286. // how we plan to use this packet
  2287. *((PPACKET_INFO*)NewPacket->ProtocolReserved) = *pppi;
  2288. *((PPACKET_INFO*)NewPacket->MiniportReserved) = *pppi;
  2289. //
  2290. // We must ensure that the adapter we just got this packet from is not unbound until we are
  2291. // done with its packet. Bump the adapter's refcount here. The adapter's refcount will be
  2292. // decremented again when this base packet is freed.
  2293. //
  2294. BrdgReacquireAdapter( pOwnerAdapt );
  2295. (*pppi)->u.BasePacketInfo.pOwnerAdapter = pOwnerAdapt;
  2296. (*pppi)->u.BasePacketInfo.pOriginalPacket = pPacket;
  2297. (*pppi)->Flags.OriginalDirection = BrdgPacketInbound;
  2298. (*pppi)->Flags.bIsBasePacket = TRUE;
  2299. // Make sure the packet indicates that it's OK to hang on to buffers
  2300. NDIS_SET_PACKET_STATUS( NewPacket, NDIS_STATUS_SUCCESS );
  2301. // Count this packet as received
  2302. ExInterlockedAddLargeStatistic( &gStatReceivedFrames, 1L );
  2303. ExInterlockedAddLargeStatistic( &gStatReceivedBytes, BrdgBufTotalPacketSize(pPacket) );
  2304. ExInterlockedAddLargeStatistic( &gStatReceivedNoCopyFrames, 1L );
  2305. ExInterlockedAddLargeStatistic( &gStatReceivedNoCopyBytes, BrdgBufTotalPacketSize(pPacket) );
  2306. ExInterlockedAddLargeStatistic( &pOwnerAdapt->ReceivedFrames, 1L );
  2307. ExInterlockedAddLargeStatistic( &pOwnerAdapt->ReceivedBytes, BrdgBufTotalPacketSize(pPacket) );
  2308. return NewPacket;
  2309. }
  2310. PNDIS_PACKET
  2311. BrdgFwdMakeCopyBasePacket(
  2312. OUT PPACKET_INFO *pppi,
  2313. IN PVOID pHeader,
  2314. IN PVOID pData,
  2315. IN UINT HeaderSize,
  2316. IN UINT DataSize,
  2317. IN UINT SizeOfPacket,
  2318. IN BOOLEAN bCountAsReceived,
  2319. IN PADAPT pOwnerAdapt,
  2320. PVOID *ppBuf
  2321. )
  2322. /*++
  2323. Routine Description:
  2324. Builds a new copy packet to hold inbound data on the copy path or on the
  2325. no-copy path if a packet arrives with STATUS_RESOURCES.
  2326. The new packet has NO ATTRIBUTED QUOTA to any adapter. This is because
  2327. at the time of the initial receive, a target adapter is not yet known
  2328. and the inbound data must be wrapped in a copy packet to be queued for
  2329. processing.
  2330. The cost of the base packet is assigned to target adapters as it is
  2331. processed in the queue-draining thread.
  2332. Arguments:
  2333. pppi Output of the new info block associated with the
  2334. new packet (NULL if alloc failed)
  2335. pHeader Pointer to the header buffer originally indicated
  2336. Can be NULL to not copy the header
  2337. pData Pointer to the data buffer originally indicated
  2338. Can be NULL to not copy the data buffer
  2339. HeaderSize Size of the header buffer
  2340. DataSize Size of the data buffer
  2341. SizeOfPacket Size to set the packet's buffer to. Can be different
  2342. from HeaderSize+DataSize if the caller plans to
  2343. copy more data in later
  2344. bCountAsReceived Whether to count this packet as received
  2345. pOwnerAdapt Adapter this packet was received on (purely for
  2346. statistics purposes). Can be NULL if bCountAsReceived == FALSE
  2347. ppBuf (optionally) receives a pointer to the data buffer
  2348. of the freshly allocated packet
  2349. Return Value:
  2350. A new base packet or NULL if the allocation failed
  2351. --*/
  2352. {
  2353. PNDIS_PACKET NewPacket;
  2354. PNDIS_BUFFER pBuffer;
  2355. PVOID pvBuf;
  2356. UINT bufLength;
  2357. // Get a copy packet to carry the data
  2358. NewPacket = BrdgBufGetBaseCopyPacket( pppi );
  2359. if (NewPacket == NULL)
  2360. {
  2361. // Our copy packet pool is full!
  2362. return NULL;
  2363. }
  2364. SAFEASSERT( *pppi != NULL );
  2365. // Get a pointer to the preallocated buffer in this packet
  2366. pBuffer = BrdgBufPacketHeadBuffer(NewPacket);
  2367. SAFEASSERT( pBuffer != NULL );
  2368. NdisQueryBufferSafe( pBuffer, &pvBuf, &bufLength, NormalPagePriority );
  2369. if( pvBuf == NULL )
  2370. {
  2371. // This shouldn't be possible because the data buffer should have been
  2372. // alloced from kernel space
  2373. SAFEASSERT(FALSE);
  2374. BrdgBufFreeBaseCopyPacket( NewPacket, *pppi );
  2375. *pppi = NULL;
  2376. return NULL;
  2377. }
  2378. SAFEASSERT( bufLength == MAX_PACKET_SIZE );
  2379. if( ppBuf != NULL )
  2380. {
  2381. *ppBuf = pvBuf;
  2382. }
  2383. // Copy the packet data into our own preallocated buffers
  2384. if( pHeader != NULL )
  2385. {
  2386. NdisMoveMemory(pvBuf, pHeader, HeaderSize);
  2387. }
  2388. else
  2389. {
  2390. SAFEASSERT( HeaderSize == 0 );
  2391. }
  2392. if( pData != NULL )
  2393. {
  2394. NdisMoveMemory((PUCHAR)pvBuf + HeaderSize, pData, DataSize);
  2395. }
  2396. else
  2397. {
  2398. SAFEASSERT( DataSize == 0 );
  2399. }
  2400. // Tweak the size of the buffer so it looks like the right length
  2401. NdisAdjustBufferLength(pBuffer, SizeOfPacket);
  2402. (*pppi)->u.BasePacketInfo.pOriginalPacket = NULL;
  2403. (*pppi)->u.BasePacketInfo.pOwnerAdapter = NULL;
  2404. (*pppi)->Flags.OriginalDirection = BrdgPacketInbound;
  2405. (*pppi)->Flags.bIsBasePacket = TRUE;
  2406. // Make the header size correct
  2407. NDIS_SET_PACKET_HEADER_SIZE(NewPacket, ETHERNET_HEADER_SIZE);
  2408. // Indicate that upper-layer protocols can hang on to these buffers
  2409. NDIS_SET_PACKET_STATUS( NewPacket, NDIS_STATUS_SUCCESS );
  2410. // Count this packet as received
  2411. if( bCountAsReceived )
  2412. {
  2413. ExInterlockedAddLargeStatistic( &gStatReceivedFrames, 1L );
  2414. ExInterlockedAddLargeStatistic( &gStatReceivedBytes, SizeOfPacket );
  2415. ExInterlockedAddLargeStatistic( &gStatReceivedCopyFrames, 1L );
  2416. ExInterlockedAddLargeStatistic( &gStatReceivedCopyBytes, SizeOfPacket );
  2417. SAFEASSERT( pOwnerAdapt != NULL );
  2418. ExInterlockedAddLargeStatistic( &pOwnerAdapt->ReceivedFrames, 1L );
  2419. ExInterlockedAddLargeStatistic( &pOwnerAdapt->ReceivedBytes, SizeOfPacket );
  2420. }
  2421. return NewPacket;
  2422. }
  2423. VOID
  2424. BrdgFwdSendOnLink(
  2425. IN PADAPT pAdapt,
  2426. IN PNDIS_PACKET pPacket
  2427. )
  2428. /*++
  2429. Routine Description:
  2430. Sends a packet to a particular adapter
  2431. Arguments:
  2432. pAdapt The adapter to send to
  2433. pPacket The packet to send
  2434. Return Value:
  2435. None
  2436. --*/
  2437. {
  2438. PPACKET_INFO ppi;
  2439. PACKET_DIRECTION PacketDirection = BrdgPacketImpossible;
  2440. BOOLEAN Bridging = BrdgFwdBridgingNetworks();
  2441. BOOLEAN Incremented = FALSE;
  2442. // Make sure this doesn't loop back
  2443. NdisClearPacketFlags( pPacket, NDIS_FLAGS_LOOPBACK_ONLY );
  2444. NdisSetPacketFlags( pPacket, NDIS_FLAGS_DONT_LOOPBACK );
  2445. //
  2446. // Logic is like this:
  2447. // If the packet is an Outbound packet then we send it.
  2448. // If the packet has been created in the bridge, then we check
  2449. // the base packet to see if it is outbound, if it is then we send the packet.
  2450. //
  2451. if (!Bridging)
  2452. {
  2453. if (BrdgBufGetPacketOwnership(pPacket) != BrdgNotOwned)
  2454. {
  2455. ppi = *((PPACKET_INFO*)pPacket->MiniportReserved);
  2456. if (!ppi)
  2457. {
  2458. ppi = *((PPACKET_INFO*)pPacket->ProtocolReserved);
  2459. }
  2460. if (ppi)
  2461. {
  2462. if (((ppi->Flags.OriginalDirection == BrdgPacketOutbound) ||
  2463. ((ppi->Flags.OriginalDirection == BrdgPacketCreatedInBridge) &&
  2464. (ppi->u.pBasePacketInfo != NULL &&
  2465. ppi->u.pBasePacketInfo->Flags.OriginalDirection == BrdgPacketOutbound)
  2466. )
  2467. )
  2468. )
  2469. {
  2470. PacketDirection = BrdgPacketOutbound;
  2471. }
  2472. }
  2473. else
  2474. {
  2475. // If it doesn't contain a ppi then it never came through the bridge, so it's being transmitted locally.
  2476. PacketDirection = BrdgPacketOutbound;
  2477. #if DBG
  2478. if (gBreakIfNullPPI)
  2479. {
  2480. KdBreakPoint();
  2481. }
  2482. #endif // DBG
  2483. }
  2484. }
  2485. else
  2486. {
  2487. PacketDirection = BrdgPacketOutbound;
  2488. }
  2489. }
  2490. Incremented = BrdgIncrementWaitRef(&pAdapt->Refcount);
  2491. if (Incremented &&
  2492. (PacketDirection == BrdgPacketOutbound || Bridging))
  2493. {
  2494. #if DBG
  2495. if (gPrintPacketTypes)
  2496. {
  2497. if (PacketDirection == BrdgPacketOutbound)
  2498. {
  2499. THROTTLED_DBGPRINT(FWD, ("Sending Outbound packet\r\n"));
  2500. }
  2501. else
  2502. {
  2503. THROTTLED_DBGPRINT(FWD, ("Forwarding packet\r\n"));
  2504. }
  2505. }
  2506. #endif // DBG
  2507. // Send!
  2508. NdisSendPackets( pAdapt->BindingHandle, &pPacket, 1 );
  2509. }
  2510. else
  2511. {
  2512. #if DBG
  2513. if (Bridging && gPrintPacketTypes)
  2514. {
  2515. THROTTLED_DBGPRINT(FWD, ("Not allowed to send packet\r\n"));
  2516. }
  2517. #endif // DBG
  2518. //
  2519. // We incremented this, but we're not going to be going through any path that
  2520. // decrements this, so we need to do this here.
  2521. //
  2522. if (Incremented)
  2523. {
  2524. BrdgDecrementWaitRef(&pAdapt->Refcount);
  2525. }
  2526. BrdgFwdCleanupPacket(pAdapt, pPacket, NDIS_STATUS_CLOSING);
  2527. }
  2528. }
  2529. VOID
  2530. BrdgFwdReleaseBasePacket(
  2531. IN PNDIS_PACKET pPacket,
  2532. PPACKET_INFO ppi,
  2533. IN PACKET_OWNERSHIP Own,
  2534. IN NDIS_STATUS Status
  2535. )
  2536. /*++
  2537. Routine Description:
  2538. Frees a base packet. Called when a base packet's refcount reaches zero.
  2539. Arguments:
  2540. pPacket The base packet to free
  2541. ppi The packet's info block
  2542. Own The result of a call to BrdgBufGetPacketOwnership(pPacket)
  2543. Status The status to be returned to the entity owning the
  2544. original packet wrapped by the base packet (if any)
  2545. Return Value:
  2546. None
  2547. --*/
  2548. {
  2549. SAFEASSERT( ppi->Flags.bIsBasePacket );
  2550. if( Own == BrdgOwnCopyPacket )
  2551. {
  2552. // This packet was allocated to wrap copied buffers. Free it back to our pool.
  2553. BrdgFwdValidatePacketDirection( ppi->Flags.OriginalDirection );
  2554. BrdgBufFreeBaseCopyPacket( pPacket, ppi );
  2555. }
  2556. else
  2557. {
  2558. // This packet was allocated to wrap a protocol or miniport's buffers.
  2559. // Return the packet to its original owner.
  2560. SAFEASSERT( Own == BrdgOwnWrapperPacket );
  2561. SAFEASSERT( ppi->u.BasePacketInfo.pOriginalPacket != NULL );
  2562. if( ppi->Flags.OriginalDirection == BrdgPacketInbound )
  2563. {
  2564. // Wraps a lower-layer miniport packet.
  2565. NdisReturnPackets( &ppi->u.BasePacketInfo.pOriginalPacket, 1 );
  2566. // We incremented the adapter's refcount when we first received the packet
  2567. // to prevent the adapter from shutting down while we still held some of
  2568. // its packets
  2569. SAFEASSERT( ppi->u.BasePacketInfo.pOwnerAdapter != NULL );
  2570. BrdgReleaseAdapter( ppi->u.BasePacketInfo.pOwnerAdapter );
  2571. }
  2572. else
  2573. {
  2574. NDIS_HANDLE MiniportHandle;
  2575. // Wraps a higher-layer protocol packet
  2576. SAFEASSERT( ppi->Flags.OriginalDirection == BrdgPacketOutbound );
  2577. // Shuttle back per-packet information before returning the original descriptor
  2578. NdisIMCopySendCompletePerPacketInfo (ppi->u.BasePacketInfo.pOriginalPacket, pPacket);
  2579. // Give back the original descriptor.
  2580. // NDIS should prevent the miniport from shutting down while there is still an
  2581. // indicate pending.
  2582. MiniportHandle = BrdgMiniAcquireMiniport();
  2583. SAFEASSERT( MiniportHandle != NULL );
  2584. if (MiniportHandle)
  2585. {
  2586. NdisMSendComplete( MiniportHandle, ppi->u.BasePacketInfo.pOriginalPacket, Status );
  2587. BrdgMiniReleaseMiniport();
  2588. }
  2589. }
  2590. // Don't forget to free the wrapper packet as well
  2591. BrdgFwdFreeBaseWrapperPacket( pPacket, ppi );
  2592. }
  2593. }
  2594. VOID
  2595. BrdgFwdWrapPacketForReceive(
  2596. IN PNDIS_PACKET pOriginalPacket,
  2597. IN PNDIS_PACKET pNewPacket
  2598. )
  2599. /*++
  2600. Routine Description:
  2601. Copies state information into a wrapper packet for the purposes of indicating
  2602. the new packet up to overlying protocols
  2603. Arguments:
  2604. pOriginalPacket The packet to copy state out of
  2605. pNewPacket The wrapper packet to copy state into
  2606. Return Value:
  2607. None
  2608. --*/
  2609. {
  2610. NDIS_STATUS Status;
  2611. // Copy other header and OOB data
  2612. NDIS_SET_ORIGINAL_PACKET(pNewPacket, NDIS_GET_ORIGINAL_PACKET(pOriginalPacket));
  2613. NdisSetPacketFlags( pNewPacket, NdisGetPacketFlags(pOriginalPacket) );
  2614. Status = NDIS_GET_PACKET_STATUS(pOriginalPacket);
  2615. NDIS_SET_PACKET_STATUS(pNewPacket, Status);
  2616. NDIS_SET_PACKET_HEADER_SIZE(pNewPacket, NDIS_GET_PACKET_HEADER_SIZE(pOriginalPacket));
  2617. }
  2618. VOID
  2619. BrdgFwdWrapPacketForSend(
  2620. IN PNDIS_PACKET pOriginalPacket,
  2621. IN PNDIS_PACKET pNewPacket
  2622. )
  2623. /*++
  2624. Routine Description:
  2625. Copies state information into a wrapper packet for the purposes of transmitting the
  2626. new packet to underlying NICs
  2627. Arguments:
  2628. pOriginalPacket The packet to copy state out of
  2629. pNewPacket The wrapper packet to copy state into
  2630. Return Value:
  2631. None
  2632. --*/
  2633. {
  2634. PVOID MediaSpecificInfo = NULL;
  2635. ULONG MediaSpecificInfoSize = 0;
  2636. NdisSetPacketFlags( pNewPacket, NdisGetPacketFlags(pOriginalPacket) );
  2637. //
  2638. // Copy the OOB Offset from the original packet to the new
  2639. // packet.
  2640. //
  2641. NdisMoveMemory(NDIS_OOB_DATA_FROM_PACKET(pNewPacket),
  2642. NDIS_OOB_DATA_FROM_PACKET(pOriginalPacket),
  2643. sizeof(NDIS_PACKET_OOB_DATA));
  2644. //
  2645. // Copy the per packet info into the new packet
  2646. // This includes ClassificationHandle, etc.
  2647. // Make sure other stuff is not copied !!!
  2648. //
  2649. NdisIMCopySendPerPacketInfo(pNewPacket, pOriginalPacket);
  2650. //
  2651. // Copy the Media specific information
  2652. //
  2653. NDIS_GET_PACKET_MEDIA_SPECIFIC_INFO(pOriginalPacket,
  2654. &MediaSpecificInfo,
  2655. &MediaSpecificInfoSize);
  2656. if (MediaSpecificInfo || MediaSpecificInfoSize)
  2657. {
  2658. NDIS_SET_PACKET_MEDIA_SPECIFIC_INFO(pNewPacket,
  2659. MediaSpecificInfo,
  2660. MediaSpecificInfoSize);
  2661. }
  2662. }
  2663. PNDIS_PACKET
  2664. BrdgFwdCommonAllocAndWrapPacket(
  2665. IN PNDIS_PACKET pBasePacket,
  2666. OUT PPACKET_INFO *pppi,
  2667. IN PADAPT pTargetAdapt,
  2668. IN PWRAPPER_FUNC pFunc
  2669. )
  2670. /*++
  2671. Routine Description:
  2672. Common logic for creating a wrapper packet
  2673. Creates a new wrapper packet and calls the supplied function to copy
  2674. state information from the original packet into the wrapper
  2675. Arguments:
  2676. pBasePacket The packet to wrap
  2677. pppi Returns the new wrapper packet's info block or
  2678. NULL if the allocation fails
  2679. pTargetAdapt The adapter to charge the new wrapper packet (and
  2680. the cost of hanging onto the base packet) to
  2681. pFunc The function to call to copy state from the original
  2682. packet to the new wrapper
  2683. Return Value:
  2684. The newly allocated wrapper packet or NULL if the allocation failed (usually
  2685. because the target adapter did not pass quota)
  2686. --*/
  2687. {
  2688. PNDIS_PACKET pNewPacket;
  2689. NDIS_STATUS Status;
  2690. SAFEASSERT( pTargetAdapt != NULL );
  2691. // Must first determine if the target can handle the quota of
  2692. // holding onto the base packet.
  2693. //
  2694. // If we do not own the base packet, this has no effect.
  2695. if( ! BrdgBufAssignBasePacketQuota(pBasePacket, pTargetAdapt) )
  2696. {
  2697. *pppi = NULL;
  2698. return NULL;
  2699. }
  2700. // Try to get a wrapper packet
  2701. pNewPacket = BrdgBufGetWrapperPacket( pppi, pTargetAdapt );
  2702. if( pNewPacket == NULL )
  2703. {
  2704. SAFEASSERT( *pppi == NULL );
  2705. // Reverse the previous accounting for holding onto the base packet
  2706. BrdgBufReleaseBasePacketQuota( pBasePacket, pTargetAdapt );
  2707. return NULL;
  2708. }
  2709. SAFEASSERT( *pppi != NULL );
  2710. // Point the new packet to the old buffers
  2711. Status = BrdgBufChainCopyBuffers( pNewPacket, pBasePacket );
  2712. if( Status != NDIS_STATUS_SUCCESS )
  2713. {
  2714. BrdgBufReleaseBasePacketQuota( pBasePacket, pTargetAdapt );
  2715. BrdgBufFreeWrapperPacket( pNewPacket, *pppi, pTargetAdapt );
  2716. *pppi = NULL;
  2717. return NULL;
  2718. }
  2719. // Stuff a pointer to the packet's info block into both the ProtocolReserved
  2720. // and the MiniportReserved areas so we can recover the info block no matter
  2721. // how we plan to use this packet
  2722. *((PPACKET_INFO*)pNewPacket->ProtocolReserved) = *pppi;
  2723. *((PPACKET_INFO*)pNewPacket->MiniportReserved) = *pppi;
  2724. // Copy whatever state needs to be copied for the direction this packet is heading
  2725. (*pFunc)(pBasePacket, pNewPacket);
  2726. return pNewPacket;
  2727. }
  2728. //
  2729. // Paranoid checking of base packets
  2730. //
  2731. #if DBG
  2732. _inline VOID
  2733. BrdgFwdCheckBasePacket(
  2734. IN PNDIS_PACKET pPacket,
  2735. IN PPACKET_INFO ppi
  2736. )
  2737. {
  2738. SAFEASSERT( ppi != NULL );
  2739. // Packets should come prepared so the PACKET_INFO structure is recoverable from
  2740. // both the MiniportReserved and ProtocolReserved areas, so it won't matter whether
  2741. // we use the packet for a send or an indicate.
  2742. SAFEASSERT( *((PPACKET_INFO*)pPacket->ProtocolReserved) == ppi );
  2743. SAFEASSERT( *((PPACKET_INFO*)pPacket->MiniportReserved) == ppi );
  2744. // The base packet refcounts its own buffers
  2745. SAFEASSERT( ppi->Flags.bIsBasePacket );
  2746. // The base packet must allow the upper-layer protocol to hang onto its buffers
  2747. SAFEASSERT( NDIS_GET_PACKET_STATUS( pPacket ) == NDIS_STATUS_SUCCESS );
  2748. }
  2749. #else
  2750. #define BrdgFwdCheckBasePacket(A,B) {}
  2751. #endif
  2752. NDIS_STATUS
  2753. BrdgFwdHandlePacket(
  2754. IN PACKET_DIRECTION PacketDirection,
  2755. IN PADAPT pTargetAdapt,
  2756. IN PADAPT pOriginalAdapt,
  2757. IN BOOLEAN bShouldIndicate,
  2758. IN NDIS_HANDLE MiniportHandle,
  2759. IN PNDIS_PACKET pBasePacket,
  2760. IN PPACKET_INFO baseppi,
  2761. IN PPACKET_BUILD_FUNC pFunc,
  2762. IN PVOID Param1,
  2763. IN PVOID Param2,
  2764. IN UINT Param3,
  2765. IN UINT Param4
  2766. )
  2767. /*++
  2768. Routine Description:
  2769. Common logic for handling packets that cannot be fast-tracked
  2770. A base packet can optionally be passed in. This is only done when handling
  2771. packets from the copy path or the no-copy path when packets arrived with
  2772. STATUS_RESOURCES set, since those types of packets must be wrapped just to
  2773. be queued for processing.
  2774. If a base packet is passed in, it is assumed that NO QUOTA has been assigned
  2775. to any adapter for that base packet. The cost of the base packet is assigned
  2776. to any prospective target via BrdgBufAssignBasePacketQuota().
  2777. If a base packet is not passed in, a function pointer must be supplied that
  2778. can build a base packet on demand from the supplied parameters. When base
  2779. packets are built on the fly, they DO require immediate quota assignments.
  2780. Note that if a base packet is passed in, it is possible for this function to
  2781. release the base packet itself (via BrdgFwdReleaseBasePacket) and return
  2782. NDIS_STATUS_PENDING.
  2783. Arguments:
  2784. PacketDirection The original direction of the packet being handled
  2785. pTargetAdapt The adapter corresponding to the packet's target
  2786. MAC address, or NULL if not known. A non-NULL value
  2787. implies that bShouldIndicate == FALSE, since it doesn't
  2788. make sense for a unicast packet bound for another
  2789. adapter to require indication to the local machine.
  2790. pOriginalAdapt The adapter on which the original packet was received
  2791. bShouldIndicate Whether the packet should be indicated to overlying protocols
  2792. MiniportHandle The handle to our local miniport (CALLER IS RESPONSIBLE
  2793. FOR ENSURING THE MINIPORT'S EXISTENCE DURING THIS CALL!)
  2794. pBasePacket The base packet to use if one has already been built (this
  2795. occurs on the copy-receive path)
  2796. baseppi The base packet's PACKET_INFO if one exists.
  2797. pFunc A function that, when passed Param1 - Param4, can build
  2798. a base packet from the originally received packet for
  2799. a particular target adapter.
  2800. Param1 - Param4 Parameters to pass to pFunc
  2801. If a base packet is not supplied, pFunc must be non-NULL. Conversely, if a base
  2802. packet is supplied, pFunc should be NULL because it will never be called.
  2803. Return Value:
  2804. NDIS_STATUS_PENDING Indicates that the base packet passed in was used successfully
  2805. or that a base packet was successfully built and used with
  2806. the help of pFunc. The base packet and any wrapper packets
  2807. build by BrdgFwdHandlePacket will be automatically deallocated
  2808. in the future; the caller need not take any additional action.
  2809. OTHER RETURN CODE No targets were found or none passed quota check. If a base
  2810. packet was passed in, the caller should free it. If there is
  2811. an underlying packet that was to be used to build a base packet,
  2812. the caller should free it.
  2813. --*/
  2814. {
  2815. BOOLEAN dataRetained = FALSE;
  2816. PACKET_DIRECTION tmpPacketDirection;
  2817. tmpPacketDirection = PacketDirection;
  2818. SAFEASSERT( (PacketDirection == BrdgPacketInbound) ||
  2819. (PacketDirection == BrdgPacketOutbound) );
  2820. SAFEASSERT( (pBasePacket != NULL) || (pFunc != NULL) );
  2821. SAFEASSERT( (pTargetAdapt == NULL) || (bShouldIndicate == FALSE) );
  2822. if( pBasePacket != NULL )
  2823. {
  2824. SAFEASSERT( baseppi != NULL );
  2825. BrdgFwdCheckBasePacket( pBasePacket, baseppi );
  2826. }
  2827. if( bShouldIndicate )
  2828. {
  2829. // Don't try to indicate if the miniport doesn't exist
  2830. if( MiniportHandle == NULL )
  2831. {
  2832. // Count this as a failed indicate
  2833. ExInterlockedAddLargeStatistic( &gStatIndicatedDroppedFrames, 1L );
  2834. bShouldIndicate = FALSE;
  2835. }
  2836. }
  2837. // Not allowed to pass in a target adapter in compatibility-mode, since
  2838. // only the compatibility-mode code is supposed to deal with those.
  2839. if( pTargetAdapt != NULL )
  2840. {
  2841. SAFEASSERT( !pTargetAdapt->bCompatibilityMode );
  2842. }
  2843. if( (pTargetAdapt != NULL) && (! bShouldIndicate) )
  2844. {
  2845. // This packet is going to a single destination.
  2846. if( pBasePacket != NULL )
  2847. {
  2848. // We were passed in a base packet. See if the target adapter can accept
  2849. // the quota of the base packet.
  2850. if( ! BrdgBufAssignBasePacketQuota(pBasePacket, pTargetAdapt) )
  2851. {
  2852. // The target is over quota and can't accept this packet. We will
  2853. // return an error code to indicate that we never used the caller's base
  2854. // packet.
  2855. pBasePacket = NULL;
  2856. baseppi = NULL;
  2857. }
  2858. // else we continue processing below
  2859. }
  2860. else
  2861. {
  2862. // Alloc a base packet with the supplied function
  2863. SAFEASSERT( pFunc != NULL );
  2864. pBasePacket = (*pFunc)(&baseppi, pTargetAdapt, Param1, Param2, Param3, Param4);
  2865. }
  2866. if( pBasePacket != NULL )
  2867. {
  2868. // Paranoia
  2869. BrdgFwdCheckBasePacket( pBasePacket, baseppi );
  2870. baseppi->u.BasePacketInfo.RefCount = 1L;
  2871. baseppi->u.BasePacketInfo.CompositeStatus = NDIS_STATUS_FAILURE;
  2872. BrdgFwdSendOnLink( pTargetAdapt, pBasePacket );
  2873. // We're using the base packet or the underlying packet used to build the
  2874. // base packet
  2875. dataRetained = TRUE;
  2876. }
  2877. else
  2878. {
  2879. THROTTLED_DBGPRINT(FWD, ("Over quota for single target adapter\n"));
  2880. if( PacketDirection == BrdgPacketOutbound )
  2881. {
  2882. // This was a failed local-source transmit
  2883. ExInterlockedAddLargeStatistic( &gStatTransmittedErrorFrames, 1L );
  2884. }
  2885. }
  2886. }
  2887. else
  2888. {
  2889. //
  2890. // Our packet isn't bound for a single destination. Do the slow processing.
  2891. //
  2892. UINT numTargets = 0L, actualTargets, i;
  2893. PADAPT pAdapt;
  2894. PADAPT SendList[MAX_ADAPTERS];
  2895. LOCK_STATE LockState;
  2896. BOOLEAN sentBase = FALSE; // Whether we have sent the base packet yet
  2897. //
  2898. // First we need a list of the adapters we intend to send this packet to
  2899. //
  2900. NdisAcquireReadWriteLock( &gAdapterListLock, FALSE /*Read only*/, &LockState );
  2901. // Always indicate with the base packet
  2902. if( bShouldIndicate )
  2903. {
  2904. SendList[0] = LOCAL_MINIPORT;
  2905. numTargets = 1L;
  2906. }
  2907. if( pTargetAdapt != NULL )
  2908. {
  2909. BrdgReacquireAdapter( pTargetAdapt );
  2910. SendList[numTargets] = pTargetAdapt;
  2911. numTargets++;
  2912. }
  2913. else
  2914. {
  2915. // Note each adapter to send to
  2916. for( pAdapt = gAdapterList; pAdapt != NULL; pAdapt = pAdapt->Next )
  2917. {
  2918. // Don't need to acquire the global adapter characteristics lock to read the
  2919. // media state because we don't care about the global consistency of the
  2920. // adapters' characteristics here
  2921. if( (pAdapt != pOriginalAdapt) &&
  2922. (pAdapt->MediaState == NdisMediaStateConnected) && // Don't send to disconnected adapters
  2923. (pAdapt->State == Forwarding) && // Adapter must be in relaying state
  2924. (! pAdapt->bResetting) && // Adapter must not be resetting
  2925. (! pAdapt->bCompatibilityMode) ) // Adapter can't be in compat-mode
  2926. {
  2927. if( numTargets < MAX_ADAPTERS )
  2928. {
  2929. // We will use this adapter outside the list lock; bump its refcount
  2930. BrdgAcquireAdapterInLock(pAdapt);
  2931. SendList[numTargets] = pAdapt;
  2932. numTargets++;
  2933. }
  2934. else
  2935. {
  2936. // Too many copies to send!
  2937. SAFEASSERT( FALSE );
  2938. }
  2939. }
  2940. }
  2941. }
  2942. // Can let go of the adapter list now; we have copied out all the target adapters
  2943. // and incremented the refcount for the adapters we will be using.
  2944. NdisReleaseReadWriteLock( &gAdapterListLock, &LockState );
  2945. if( numTargets == 0 )
  2946. {
  2947. //
  2948. // Nowhere to send the packet! Nothing to do.
  2949. //
  2950. // This should not happen often. If the packet is a local send, our media status
  2951. // should be DISCONNECTED, so there should be no transmits from above.
  2952. //
  2953. if( PacketDirection == BrdgPacketOutbound )
  2954. {
  2955. // This was a failed local-source transmit (although the caller probably
  2956. // shouldn't have sent the packet in the first place since our media status
  2957. // should be DISCONNECTED
  2958. ExInterlockedAddLargeStatistic( &gStatTransmittedErrorFrames, 1L );
  2959. }
  2960. //
  2961. // Indicate to the caller that no send occurred
  2962. //
  2963. return NDIS_STATUS_NO_CABLE;
  2964. }
  2965. actualTargets = numTargets;
  2966. // If we had a base packet passed in, set its refcount now that we know how many
  2967. // adapters we will be targeting
  2968. if( pBasePacket != NULL )
  2969. {
  2970. baseppi->u.BasePacketInfo.RefCount = actualTargets;
  2971. baseppi->u.BasePacketInfo.CompositeStatus = NDIS_STATUS_FAILURE;
  2972. // We now need ownership of the base packet passed in; even if all our send
  2973. // attempts fail, we will release the base packet ourselves below, so the
  2974. // caller should not dispose of the base packet himself.
  2975. dataRetained = TRUE;
  2976. }
  2977. //
  2978. // Walk the list of targets and try to send to each
  2979. //
  2980. for( i = 0L; i < numTargets; i++ )
  2981. {
  2982. PADAPT OutAdapt = SendList[i];
  2983. PNDIS_PACKET pPacketToSend = NULL;
  2984. PPACKET_INFO ppiToSend = NULL;
  2985. SAFEASSERT(tmpPacketDirection == PacketDirection);
  2986. if( pBasePacket == NULL )
  2987. {
  2988. //
  2989. // We weren't passed in a base packet and we haven't built one yet. Build one now
  2990. // that we have a specific target adapter.
  2991. //
  2992. pBasePacket = (*pFunc)(&baseppi, OutAdapt, Param1, Param2, Param3, Param4);
  2993. if( pBasePacket != NULL )
  2994. {
  2995. // Paranoia
  2996. BrdgFwdCheckBasePacket( pBasePacket, baseppi );
  2997. SAFEASSERT( actualTargets > 0L );
  2998. baseppi->u.BasePacketInfo.RefCount = actualTargets;
  2999. baseppi->u.BasePacketInfo.CompositeStatus = NDIS_STATUS_FAILURE;
  3000. pPacketToSend = pBasePacket;
  3001. ppiToSend = baseppi;
  3002. sentBase = TRUE;
  3003. }
  3004. else
  3005. {
  3006. // We failed to build a base packet. Just pretend there was one less target
  3007. // for the next time through
  3008. actualTargets--;
  3009. }
  3010. }
  3011. else
  3012. {
  3013. if( ! sentBase )
  3014. {
  3015. //
  3016. // We have a base packet but we haven't sent it yet. Send to this target if quota allows.
  3017. //
  3018. if( BrdgBufAssignBasePacketQuota(pBasePacket, OutAdapt) )
  3019. {
  3020. // This target can accept the base packet.
  3021. pPacketToSend = pBasePacket;
  3022. ppiToSend = baseppi;
  3023. sentBase = TRUE;
  3024. }
  3025. else
  3026. {
  3027. // The target is over quota and can't accept this packet.
  3028. pPacketToSend = NULL;
  3029. ppiToSend = NULL;
  3030. // bookkeeping on the base packet done below
  3031. }
  3032. }
  3033. else
  3034. {
  3035. //
  3036. // We have a base packet and we have already sent it. Use wrapper packets for each additional
  3037. // send.
  3038. //
  3039. if( baseppi->Flags.OriginalDirection == BrdgPacketInbound )
  3040. {
  3041. pPacketToSend = BrdgFwdAllocAndWrapPacketForReceive( pBasePacket, &ppiToSend, OutAdapt );
  3042. }
  3043. else
  3044. {
  3045. SAFEASSERT( baseppi->Flags.OriginalDirection == BrdgPacketOutbound );
  3046. pPacketToSend = BrdgFwdAllocAndWrapPacketForSend( pBasePacket, &ppiToSend, OutAdapt );
  3047. }
  3048. if( pPacketToSend != NULL )
  3049. {
  3050. // Signal that the upper-layer protocol can hang on to these buffers
  3051. NDIS_SET_PACKET_STATUS(pPacketToSend, NDIS_STATUS_SUCCESS);
  3052. // Set up the wrapper's info block
  3053. SAFEASSERT( ppiToSend != NULL );
  3054. ppiToSend->Flags.OriginalDirection = BrdgPacketCreatedInBridge;
  3055. ppiToSend->Flags.bIsBasePacket = FALSE;
  3056. ppiToSend->u.pBasePacketInfo = baseppi;
  3057. }
  3058. // else bookkeeping done below
  3059. }
  3060. }
  3061. if( pPacketToSend == NULL )
  3062. {
  3063. // Record the failed attempt as appropriate
  3064. SAFEASSERT( ppiToSend == NULL );
  3065. if( OutAdapt == LOCAL_MINIPORT )
  3066. {
  3067. THROTTLED_DBGPRINT(FWD, ("Over quota for local miniport during processing\n"));
  3068. ExInterlockedAddLargeStatistic( &gStatIndicatedDroppedFrames, 1L );
  3069. }
  3070. else
  3071. {
  3072. THROTTLED_DBGPRINT(FWD, ("Over quota for adapter during processing\n"));
  3073. }
  3074. if( pBasePacket != NULL )
  3075. {
  3076. // We failed to send or wrap the base packet to this target. Do bookkeeping.
  3077. SAFEASSERT( baseppi != NULL );
  3078. if( BrdgFwdDerefBasePacket( NULL/*The cost of the base packet never got assigned to OutAdapt*/,
  3079. pBasePacket, baseppi, NDIS_STATUS_FAILURE ) )
  3080. {
  3081. // We should have been the last target in the list to cause the base packet
  3082. // to actually be freed.
  3083. SAFEASSERT( i == numTargets - 1 );
  3084. pBasePacket = NULL;
  3085. baseppi = NULL;
  3086. // We just disposed of the caller's base packet, so we should not cause him to
  3087. // try to do that again on return
  3088. SAFEASSERT( dataRetained );
  3089. }
  3090. }
  3091. }
  3092. else
  3093. {
  3094. // We have a packet to send.
  3095. SAFEASSERT( ppiToSend != NULL );
  3096. if( OutAdapt == LOCAL_MINIPORT )
  3097. {
  3098. // We are indicating this packet
  3099. SAFEASSERT( MiniportHandle != NULL );
  3100. BrdgFwdIndicatePacket( pPacketToSend, MiniportHandle );
  3101. }
  3102. else
  3103. {
  3104. // We are sending to an adapter, not the local miniport
  3105. BrdgFwdSendOnLink( OutAdapt, pPacketToSend );
  3106. }
  3107. // We definitely need ownership of the underlying data since we just handed it off
  3108. // to a target
  3109. dataRetained = TRUE;
  3110. }
  3111. if( OutAdapt != LOCAL_MINIPORT )
  3112. {
  3113. // We're done with this adapter now
  3114. BrdgReleaseAdapter( OutAdapt );
  3115. }
  3116. }
  3117. if( ! dataRetained )
  3118. {
  3119. // If we're not claiming ownership of the underlying data, we had better not have
  3120. // actually used it
  3121. SAFEASSERT( ! sentBase );
  3122. if( PacketDirection == BrdgPacketOutbound )
  3123. {
  3124. // This was a failed local-source transmit
  3125. ExInterlockedAddLargeStatistic( &gStatTransmittedErrorFrames, 1L );
  3126. }
  3127. }
  3128. else
  3129. {
  3130. // If we are claiming owernship of the underlying data, we must have used it or
  3131. // disposed of the base packet ourselves.
  3132. SAFEASSERT( sentBase || (pBasePacket == NULL) );
  3133. }
  3134. }
  3135. // Tell the caller whether we are hanging into his data or not
  3136. return dataRetained ? NDIS_STATUS_PENDING : NDIS_STATUS_FAILURE;
  3137. }
  3138. BOOLEAN
  3139. BrdgFwdNoCopyFastTrackReceive(
  3140. IN PNDIS_PACKET pPacket,
  3141. IN PADAPT pAdapt,
  3142. IN NDIS_HANDLE MiniportHandle,
  3143. IN PUCHAR DstAddr,
  3144. OUT BOOLEAN *bRetainPacket
  3145. )
  3146. /*++
  3147. Routine Description:
  3148. Called to indicate a packet descriptor from an underlying NIC straight up to
  3149. overlying protocols without wrapping.
  3150. Arguments:
  3151. pPacket The packet to indicate
  3152. pAdapt The adapter that owns this packet descriptor
  3153. MiniportHandle The miniport handle (must be != NULL)
  3154. DstAddr The target MAC address of the packet
  3155. bRetainPacket Whether the caller should retain ownership of the
  3156. given packet descriptor or not. TRUE if the original
  3157. packet's status was not STATUS_RESOURCES, FALSE otherwise.
  3158. Undefined if return value != TRUE
  3159. Return Value:
  3160. TRUE if the indication succeeded, FALSE otherwise.
  3161. --*/
  3162. {
  3163. BOOLEAN bRemaining;
  3164. NDIS_STATUS Status;
  3165. PNDIS_PACKET_STACK pStack;
  3166. SAFEASSERT( pPacket != NULL );
  3167. SAFEASSERT( pAdapt != NULL );
  3168. SAFEASSERT( MiniportHandle != NULL );
  3169. SAFEASSERT( bRetainPacket != NULL );
  3170. *bRetainPacket = FALSE;
  3171. // The fast-track is possible only if NDIS has room left in its packet stack
  3172. pStack = NdisIMGetCurrentPacketStack(pPacket, &bRemaining);
  3173. if ( bRemaining )
  3174. {
  3175. Status = NDIS_GET_PACKET_STATUS(pPacket);
  3176. if( Status != NDIS_STATUS_RESOURCES )
  3177. {
  3178. SAFEASSERT( (Status == NDIS_STATUS_SUCCESS) || (Status == NDIS_STATUS_PENDING) );
  3179. //
  3180. // The upper-layer protocol gets to hang on to this packet until it's done.
  3181. // We must ensure that this adapter is not allowed to shut down while we are
  3182. // still holding its packet. As a special case for fast-track receives, we
  3183. // stash a pointer to the adapter's PADAPT struct in the magic NDIS stack
  3184. // area reserved for intermediate drivers. This allows us to decrement the
  3185. // adapter's refcount when the indication completes.
  3186. //
  3187. BrdgReacquireAdapter( pAdapt );
  3188. pStack->IMReserved[0] = (ULONG_PTR)pAdapt;
  3189. // Tell the caller to retain ownership of the packet
  3190. *bRetainPacket = TRUE;
  3191. }
  3192. else
  3193. {
  3194. // Paranoia: zero out the area we use to stash the PADAPT pointer in case
  3195. // we get confused about the path this packet took
  3196. pStack->IMReserved[0] = 0L;
  3197. // Tell the owner not to retain ownership of the packet
  3198. *bRetainPacket = FALSE;
  3199. }
  3200. // Count the packet as received
  3201. ExInterlockedAddLargeStatistic( &gStatReceivedFrames, 1L );
  3202. ExInterlockedAddLargeStatistic( &gStatReceivedBytes, BrdgBufTotalPacketSize(pPacket) );
  3203. ExInterlockedAddLargeStatistic( &gStatReceivedNoCopyFrames, 1L );
  3204. ExInterlockedAddLargeStatistic( &gStatReceivedNoCopyBytes, BrdgBufTotalPacketSize(pPacket) );
  3205. ExInterlockedAddLargeStatistic( &pAdapt->ReceivedFrames, 1L );
  3206. ExInterlockedAddLargeStatistic( &pAdapt->ReceivedBytes, BrdgBufTotalPacketSize(pPacket) );
  3207. // Hand up to overlying protocols
  3208. BrdgFwdIndicatePacket( pPacket, MiniportHandle );
  3209. // Fast-track succeeded.
  3210. return TRUE;
  3211. }
  3212. // Can't fast-track.
  3213. return FALSE;
  3214. }
  3215. //
  3216. // Changes Bridging Status due to a GPO change
  3217. //
  3218. VOID
  3219. BrdgFwdChangeBridging(
  3220. IN BOOLEAN Bridging
  3221. )
  3222. {
  3223. //
  3224. // Since we don't want to empty our tables if the settings are the same, we check
  3225. // this before updating anything. If nothing has changed, we just return
  3226. //
  3227. if (gBridging != Bridging)
  3228. {
  3229. gBridging = Bridging;
  3230. // Remove all MAC addresses from tables
  3231. BrdgTblScrubAllAdapters();
  3232. // Remove all IP addresses from tables
  3233. BrdgCompScrubAllAdapters();
  3234. if (!Bridging)
  3235. {
  3236. DBGPRINT(FWD, ("Bridging is now OFF.\r\n"));
  3237. if (gHaveID)
  3238. {
  3239. BrdgSTACancelTimersGPO();
  3240. }
  3241. }
  3242. else
  3243. {
  3244. DBGPRINT(FWD, ("Bridging is now ON.\r\n"));
  3245. if (gHaveID)
  3246. {
  3247. BrdgSTARestartTimersGPO();
  3248. BrdgSTAResetSTAInfoGPO();
  3249. }
  3250. }
  3251. }
  3252. }