Source code of Windows XP (NT5)
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.

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