/*++ Copyright(c) 1999-2000 Microsoft Corporation Module Name: brdghash.h Abstract: Ethernet MAC level bridge. Hash table implementation header Author: Mark Aiken Environment: Kernel mode driver Revision History: October 2000 - Original version --*/ // =========================================================================== // // DECLARATIONS // // =========================================================================== #define MAX_SUPPORTED_KEYSIZE 8 // Key can be up to 8 bytes // // Structure of a table entry // typedef struct _HASH_TABLE_ENTRY { struct _HASH_TABLE_ENTRY *Next; ULONG LastSeen; // Result of NdisGetSystemUpTime() UCHAR key[MAX_SUPPORTED_KEYSIZE]; // User's data follows } HASH_TABLE_ENTRY, *PHASH_TABLE_ENTRY; // The prototype of a hash function typedef ULONG (*PHASH_FUNCTION)(PUCHAR pKey); // The prototype of a matching function typedef BOOLEAN (*PHASH_MATCH_FUNCTION)(PHASH_TABLE_ENTRY, PVOID); // The prototype of a data-copy function typedef VOID (*PHASH_COPY_FUNCTION)(PHASH_TABLE_ENTRY, PUCHAR); // The prototype of a function used in calls to BrdgHashPrefixMultiMatch typedef VOID (*PMULTIMATCH_FUNC)(PHASH_TABLE_ENTRY, PVOID); // // Structure of the table itself // typedef struct _HASH_TABLE { NPAGED_LOOKASIDE_LIST entryPool; // // The consistency of the buckets is protected by the tableLock. // // The LastSeen field in each entry is volatile and is updated // with interlocked instructions. // NDIS_RW_LOCK tableLock; // These fields never change after creation PHASH_FUNCTION pHashFunction; PHASH_TABLE_ENTRY *pBuckets; ULONG numBuckets, entrySize; UINT keySize; BRIDGE_TIMER timer; ULONG_PTR maxEntries; ULONG maxTimeoutAge; // Maximum possible timeoutAge // These fields change but are protected by the tableLock. ULONG_PTR numEntries; ULONG nextTimerBucket; // This field is manipulated with InterlockExchange() instructions // to avoid having to take the table lock to change it. ULONG timeoutAge; // In debug builds, this tracks how many entries are in each bucket // so we can tell whether the table is well balanced #if DBG PUINT bucketSizes; #endif } HASH_TABLE, *PHASH_TABLE; // =========================================================================== // // PROTOTYPES // // =========================================================================== PHASH_TABLE BrdgHashCreateTable( IN PHASH_FUNCTION pHashFunction, IN ULONG numBuckets, IN ULONG entrySize, IN ULONG maxEntries, IN ULONG startTimeoutAge, IN ULONG maxTimeoutAge, IN UINT keySize ); VOID BrdgHashFreeHashTable( IN PHASH_TABLE pTable ); PHASH_TABLE_ENTRY BrdgHashFindEntry( IN PHASH_TABLE pTable, IN PUCHAR pKey, IN LOCK_STATE *pLockState ); PHASH_TABLE_ENTRY BrdgHashRefreshOrInsert( IN PHASH_TABLE pTable, IN PUCHAR pKey, OUT BOOLEAN *pIsNewEntry, OUT PLOCK_STATE pLockState ); VOID BrdgHashRemoveMatching( IN PHASH_TABLE pTable, IN PHASH_MATCH_FUNCTION pMatchFunc, PVOID pData ); ULONG BrdgHashCopyMatching( IN PHASH_TABLE pTable, IN PHASH_MATCH_FUNCTION pMatchFunc, IN PHASH_COPY_FUNCTION pCopyFunction, IN ULONG copyUnitSize, IN PVOID pData, IN PUCHAR pBuffer, IN ULONG BufferLength ); VOID BrdgHashPrefixMultiMatch( IN PHASH_TABLE pTable, IN PUCHAR pPrefixKey, IN UINT prefixLen, IN PMULTIMATCH_FUNC pFunc, IN PVOID pData ); // =========================================================================== // // INLINES // // =========================================================================== // // Changes the timeout value for a hash table // __forceinline VOID BrdgHashChangeTableTimeout( IN PHASH_TABLE pTable, IN ULONG timeout ) { InterlockedExchange( (PLONG)&pTable->timeoutAge, (LONG)timeout ); } // // Refreshes a table entry held by the caller. // ASSUMES the caller holds a read or write lock on the table // enclosing this entry! // __forceinline VOID BrdgHashRefreshEntry( IN PHASH_TABLE_ENTRY pEntry ) { ULONG CurrentTime; NdisGetSystemUpTime( &CurrentTime ); InterlockedExchange( (PLONG)&pEntry->LastSeen, (LONG)CurrentTime ); }