608 lines
14 KiB
C
608 lines
14 KiB
C
/*
|
|
***************************************************************************
|
|
* Ralink Tech Inc.
|
|
* 4F, No. 2 Technology 5th Rd.
|
|
* Science-based Industrial Park
|
|
* Hsin-chu, Taiwan, R.O.C.
|
|
*
|
|
* (c) Copyright 2002-2006, Ralink Technology, Inc.
|
|
*
|
|
* All rights reserved. Ralink's source code is an unpublished work and the
|
|
* use of a copyright notice does not imply otherwise. This source code
|
|
* contains confidential trade secret material of Ralink Tech. Any attemp
|
|
* or participation in deciphering, decoding, reverse engineering or in any
|
|
* way altering the source code is stricitly prohibited, unless the prior
|
|
* written consent of Ralink Technology, Inc. is obtained.
|
|
***************************************************************************
|
|
|
|
Module Name:
|
|
mesh.c
|
|
|
|
Abstract:
|
|
|
|
Revision History:
|
|
Who When What
|
|
-------- ---------- ----------------------------------------------
|
|
Fonchi 2007-08-06 For mesh (802.11s) support.
|
|
*/
|
|
|
|
#ifdef MESH_SUPPORT
|
|
|
|
|
|
#include "rt_config.h"
|
|
|
|
VOID BMPktSigTabInit(
|
|
IN PRTMP_ADAPTER pAd)
|
|
{
|
|
NdisAllocateSpinLock(pAd, &pAd->MeshTab.MeshBMPktTabLock);
|
|
|
|
os_alloc_mem(pAd, (UCHAR **)&(pAd->MeshTab.pBMPktSigTab), sizeof(MESH_BMPKTSIG_TAB));
|
|
if (pAd->MeshTab.pBMPktSigTab)
|
|
NdisZeroMemory(pAd->MeshTab.pBMPktSigTab, sizeof(MESH_BMPKTSIG_TAB));
|
|
else
|
|
DBGPRINT(RT_DEBUG_ERROR, ("%s Fail to alloc memory for pAd->MeshTab.pBMPktSigTab", __FUNCTION__));
|
|
|
|
return;
|
|
}
|
|
|
|
VOID BMPktSigTabExit(
|
|
IN PRTMP_ADAPTER pAd)
|
|
{
|
|
NdisFreeSpinLock(&pAd->MeshTab.MeshBMPktTabLock);
|
|
|
|
if (pAd->MeshTab.pBMPktSigTab)
|
|
os_free_mem(NULL, pAd->MeshTab.pBMPktSigTab);
|
|
pAd->MeshTab.pBMPktSigTab = NULL;
|
|
|
|
return;
|
|
}
|
|
|
|
PMESH_BMPKTSIG_ENTRY BMPktSigTabLookUp(
|
|
IN PRTMP_ADAPTER pAd,
|
|
IN PUCHAR MeshSA)
|
|
{
|
|
UINT HashIdx;
|
|
ULONG Now;
|
|
PMESH_BMPKTSIG_TAB pTab = pAd->MeshTab.pBMPktSigTab;
|
|
PMESH_BMPKTSIG_ENTRY pEntry = NULL;
|
|
PMESH_BMPKTSIG_ENTRY pPrevEntry = NULL;
|
|
|
|
if (pTab == NULL)
|
|
{
|
|
DBGPRINT(RT_DEBUG_ERROR, ("%s: pBMPktSigTab doesn't exist.\n", __FUNCTION__));
|
|
return NULL;
|
|
}
|
|
|
|
RTMP_SEM_LOCK(&pAd->MeshTab.MeshBMPktTabLock);
|
|
|
|
HashIdx = BMPKT_MAC_ADDR_HASH_INDEX(MeshSA);
|
|
pEntry = pTab->Hash[HashIdx];
|
|
|
|
while (pEntry)
|
|
{
|
|
if (MAC_ADDR_EQUAL(pEntry->MeshSA, MeshSA))
|
|
break;
|
|
else
|
|
{
|
|
pPrevEntry = pEntry;
|
|
pEntry = pEntry->pNext;
|
|
}
|
|
}
|
|
|
|
if (pEntry)
|
|
{
|
|
NdisGetSystemUpTime(&Now);
|
|
if (RTMP_TIME_AFTER((unsigned long)Now, (unsigned long)(pEntry->LastRefTime + MESH_BMPKT_RECORD_TIME)))
|
|
{ /* remove ageout entry. */
|
|
if (pPrevEntry == NULL)
|
|
pTab->Hash[HashIdx] = pEntry->pNext;
|
|
else
|
|
pPrevEntry->pNext = pEntry->pNext;
|
|
|
|
NdisZeroMemory(pEntry, sizeof(MESH_BMPKTSIG_ENTRY));
|
|
pEntry = NULL;
|
|
pTab->Size--;
|
|
}
|
|
else
|
|
pEntry->LastRefTime = Now;
|
|
}
|
|
|
|
RTMP_SEM_UNLOCK(&pAd->MeshTab.MeshBMPktTabLock);
|
|
|
|
return pEntry;
|
|
}
|
|
|
|
PMESH_BMPKTSIG_ENTRY BMPktSigTabInsert(
|
|
IN PRTMP_ADAPTER pAd,
|
|
IN PUCHAR MeshSA)
|
|
{
|
|
INT i;
|
|
ULONG HashIdx;
|
|
PMESH_BMPKTSIG_TAB pTab = pAd->MeshTab.pBMPktSigTab;
|
|
PMESH_BMPKTSIG_ENTRY pEntry = NULL, pCurrEntry;
|
|
ULONG Now;
|
|
|
|
if(pTab == NULL)
|
|
{
|
|
DBGPRINT(RT_DEBUG_ERROR, ("%s: pBMPktSigTab doesn't exist.\n", __FUNCTION__));
|
|
return NULL;
|
|
}
|
|
|
|
pEntry = BMPktSigTabLookUp(pAd, MeshSA);
|
|
if (pEntry == NULL)
|
|
{
|
|
/* if FULL, return */
|
|
if (pTab->Size >= MAX_BMPKTSIG_TAB_SIZE)
|
|
{
|
|
DBGPRINT(RT_DEBUG_ERROR, ("%s: pBMPktSigTab FULL.\n", __FUNCTION__));
|
|
return NULL;
|
|
}
|
|
|
|
RTMP_SEM_LOCK(&pAd->MeshTab.MeshBMPktTabLock);
|
|
for (i = 0; i < MAX_BMPKTSIG_TAB_SIZE; i++)
|
|
{
|
|
NdisGetSystemUpTime(&Now);
|
|
pEntry = &pTab->Content[i];
|
|
|
|
if ((pEntry->Valid == TRUE)
|
|
&& RTMP_TIME_AFTER((unsigned long)Now, (unsigned long)(pEntry->LastRefTime + MESH_BMPKT_RECORD_TIME)))
|
|
{
|
|
PMESH_BMPKTSIG_ENTRY pPrevEntry = NULL;
|
|
ULONG HashIdx = BMPKT_MAC_ADDR_HASH_INDEX(pEntry->MeshSA);
|
|
PMESH_BMPKTSIG_ENTRY pProbeEntry = pTab->Hash[HashIdx];
|
|
|
|
/* update Hash list */
|
|
do
|
|
{
|
|
if (pProbeEntry == pEntry)
|
|
{
|
|
if (pPrevEntry == NULL)
|
|
{
|
|
pTab->Hash[HashIdx] = pEntry->pNext;
|
|
}
|
|
else
|
|
{
|
|
pPrevEntry->pNext = pEntry->pNext;
|
|
}
|
|
break;
|
|
}
|
|
|
|
pPrevEntry = pProbeEntry;
|
|
pProbeEntry = pProbeEntry->pNext;
|
|
} while (pProbeEntry);
|
|
|
|
NdisZeroMemory(pEntry, sizeof(MESH_BMPKTSIG_ENTRY));
|
|
pTab->Size--;
|
|
|
|
continue;
|
|
}
|
|
|
|
if (pEntry->Valid == FALSE)
|
|
break;
|
|
}
|
|
|
|
if (i < MAX_BMPKTSIG_TAB_SIZE)
|
|
{
|
|
NdisGetSystemUpTime(&Now);
|
|
pEntry->LastRefTime = Now;
|
|
pEntry->Valid = TRUE;
|
|
COPY_MAC_ADDR(pEntry->MeshSA, MeshSA);
|
|
pTab->Size++;
|
|
}
|
|
else
|
|
{
|
|
pEntry = NULL;
|
|
DBGPRINT(RT_DEBUG_ERROR, ("%s: pBMPktSigTab tab full.\n", __FUNCTION__));
|
|
}
|
|
|
|
/* add this Neighbor entry into HASH table */
|
|
if (pEntry)
|
|
{
|
|
HashIdx = BMPKT_MAC_ADDR_HASH_INDEX(MeshSA);
|
|
if (pTab->Hash[HashIdx] == NULL)
|
|
{
|
|
pTab->Hash[HashIdx] = pEntry;
|
|
}
|
|
else
|
|
{
|
|
pCurrEntry = pTab->Hash[HashIdx];
|
|
while (pCurrEntry->pNext != NULL)
|
|
pCurrEntry = pCurrEntry->pNext;
|
|
pCurrEntry->pNext = pEntry;
|
|
}
|
|
}
|
|
|
|
RTMP_SEM_UNLOCK(&pAd->MeshTab.MeshBMPktTabLock);
|
|
}
|
|
|
|
return pEntry;
|
|
}
|
|
|
|
VOID BMPktSigTabDelete(
|
|
IN PRTMP_ADAPTER pAd,
|
|
IN PUCHAR MeshSA)
|
|
{
|
|
PMESH_BMPKTSIG_TAB pTab = pAd->MeshTab.pBMPktSigTab;
|
|
PMESH_BMPKTSIG_ENTRY pEntry = NULL;
|
|
|
|
if(pTab == NULL)
|
|
{
|
|
DBGPRINT(RT_DEBUG_ERROR, ("%s: pBMPktSigTab doesn't exist.\n", __FUNCTION__));
|
|
return;
|
|
}
|
|
|
|
/* if empty, return */
|
|
if (pTab->Size == 0)
|
|
{
|
|
DBGPRINT(RT_DEBUG_ERROR, ("pBMPktSigTab empty.\n"));
|
|
return;
|
|
}
|
|
|
|
pEntry = BMPktSigTabLookUp(pAd, MeshSA);
|
|
if (pEntry != NULL)
|
|
{
|
|
PMESH_BMPKTSIG_ENTRY pPrevEntry = NULL;
|
|
ULONG HashIdx = BMPKT_MAC_ADDR_HASH_INDEX(pEntry->MeshSA);
|
|
PMESH_BMPKTSIG_ENTRY pProbeEntry = pTab->Hash[HashIdx];
|
|
|
|
RTMP_SEM_LOCK(&pAd->MeshTab.MeshBMPktTabLock);
|
|
/* update Hash list */
|
|
do
|
|
{
|
|
if (pProbeEntry == pEntry)
|
|
{
|
|
if (pPrevEntry == NULL)
|
|
{
|
|
pTab->Hash[HashIdx] = pEntry->pNext;
|
|
}
|
|
else
|
|
{
|
|
pPrevEntry->pNext = pEntry->pNext;
|
|
}
|
|
break;
|
|
}
|
|
|
|
pPrevEntry = pProbeEntry;
|
|
pProbeEntry = pProbeEntry->pNext;
|
|
} while (pProbeEntry);
|
|
|
|
NdisZeroMemory(pEntry, sizeof(MESH_BMPKTSIG_ENTRY));
|
|
pTab->Size--;
|
|
|
|
RTMP_SEM_UNLOCK(&pAd->MeshTab.MeshBMPktTabLock);
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
BOOLEAN PktSigCheck(
|
|
IN PRTMP_ADAPTER pAd,
|
|
IN PUCHAR pTA,
|
|
IN PUCHAR pDA,
|
|
IN PUCHAR pSA,
|
|
IN UINT32 MeshSeq,
|
|
IN ULONG FrameType)
|
|
{
|
|
BOOLEAN result = FALSE;
|
|
PMESH_BMPKTSIG_ENTRY pBMPktSigEntry = NULL;
|
|
|
|
do
|
|
{
|
|
if ((FrameType == FC_TYPE_MGMT) || (*pDA & 0x01))
|
|
{
|
|
if ((pBMPktSigEntry = BMPktSigTabLookUp(pAd, pSA)) == NULL)
|
|
{
|
|
if ((pBMPktSigEntry = BMPktSigTabInsert(pAd, pSA)) == NULL)
|
|
break;
|
|
|
|
pBMPktSigEntry->MeshSeqBased = MeshSeq;
|
|
COPY_MAC_ADDR(pBMPktSigEntry->Precursor, pTA);
|
|
NdisZeroMemory(pBMPktSigEntry->Offset, sizeof(UINT32) * 4);
|
|
}
|
|
else
|
|
{
|
|
UINT32 DevNum;
|
|
UINT32 RemainNum;
|
|
UINT32 SeqDiff;
|
|
|
|
if (MESH_SEQ_AFTER(pBMPktSigEntry->MeshSeqBased, MeshSeq))
|
|
break;
|
|
|
|
SeqDiff = MESH_SEQ_SUB(MeshSeq, pBMPktSigEntry->MeshSeqBased);
|
|
if (SeqDiff == 0)
|
|
break;
|
|
|
|
if (SeqDiff > 128)
|
|
{
|
|
pBMPktSigEntry->MeshSeqBased = MeshSeq;
|
|
NdisZeroMemory(pBMPktSigEntry->Offset, sizeof(UINT32) * 4);
|
|
}
|
|
else
|
|
{
|
|
DevNum = (SeqDiff - 1) / 32;
|
|
RemainNum = (SeqDiff - 1) % 32;
|
|
if (pBMPktSigEntry->Offset[DevNum] & (1 << RemainNum))
|
|
break;
|
|
else
|
|
pBMPktSigEntry->Offset[DevNum] |= (1 << RemainNum);
|
|
}
|
|
}
|
|
}
|
|
|
|
#if 0
|
|
/* mesh unicast packet doesn't need to check packet signature. */
|
|
else
|
|
{
|
|
if((pBMPktSigEntry = BMPktSigTabLookUp(pAd, pSA)) == NULL)
|
|
{
|
|
if((pBMPktSigEntry = BMPktSigTabInsert(pAd, pSA)) == NULL)
|
|
break;
|
|
pBMPktSigEntry->UcaseMeshSeq = MeshSeq;
|
|
COPY_MAC_ADDR(pBMPktSigEntry->Precursor, pTA);
|
|
}
|
|
else
|
|
{
|
|
if (MESH_SEQ_AFTER(pBMPktSigEntry->UcaseMeshSeq, MeshSeq))
|
|
break;
|
|
pBMPktSigEntry->UcaseMeshSeq = MeshSeq;
|
|
}
|
|
}
|
|
#endif
|
|
result = TRUE;
|
|
} while (FALSE);
|
|
|
|
if ((result == FALSE)
|
|
&& (FrameType == FC_TYPE_DATA)
|
|
&& IS_MULTICAST_MAC_ADDR(pDA)
|
|
&& (pBMPktSigEntry != NULL)
|
|
&& !MAC_ADDR_EQUAL(pBMPktSigEntry->Precursor, pTA))
|
|
{
|
|
MeshMultipathNotice(pAd, pTA, pSA, 1);
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
VOID MeshClonePacket(
|
|
IN PRTMP_ADAPTER pAd,
|
|
IN PNDIS_PACKET pPacket,
|
|
IN UINT8 MeshSrc,
|
|
IN UINT8 MeshLinkIdx)
|
|
{
|
|
INT idx;
|
|
PUCHAR pSA = NULL;
|
|
PUCHAR pDA = NULL;
|
|
|
|
for (idx = 0; idx < MAX_MESH_LINKS; idx++)
|
|
{
|
|
if ((MeshSrc == MESH_FORWARD)
|
|
&& (MeshLinkIdx == idx))
|
|
continue;
|
|
|
|
pSA = GET_OS_PKT_DATAPTR(pPacket) + MAC_ADDR_LEN;
|
|
if (MAC_ADDR_EQUAL(pAd->MeshTab.MeshLink[idx].Entry.PeerMacAddr, pSA))
|
|
continue;
|
|
|
|
pDA = GET_OS_PKT_DATAPTR(pPacket);
|
|
if (IS_MULTICAST_MAC_ADDR(pDA)
|
|
&& (MultipathEntryLookUp(pAd, idx, pSA) != NULL))
|
|
continue;
|
|
|
|
if (PeerLinkValidCheck(pAd, idx) == TRUE)
|
|
{
|
|
PNDIS_PACKET pPacketClone;
|
|
|
|
/* pPacketClone = skb_clone(RTPKT_TO_OSPKT(pPacket), GFP_ATOMIC); */
|
|
OS_PKT_CLONE(pAd, pPacket, pPacketClone, GFP_ATOMIC);
|
|
if (pPacketClone == NULL)
|
|
continue;
|
|
|
|
RTMP_SET_PACKET_MOREDATA(pPacketClone, FALSE);
|
|
RTMP_SET_PACKET_WCID(pPacketClone, pAd->MeshTab.MeshLink[idx].Entry.MacTabMatchWCID);
|
|
RTMP_SET_PACKET_WDEV(pPacket, pAd->MeshTab.wdev.wdev_idx);
|
|
RTMP_SET_MESH_ROUTE_ID(pPacketClone, BMCAST_ROUTE_ID);
|
|
RTMP_SET_MESH_SOURCE(pPacketClone, MeshSrc);
|
|
#ifdef CONFIG_AP_SUPPORT
|
|
APSendPacket(pAd, pPacketClone);
|
|
#endif /* CONFIG_AP_SUPPORT */
|
|
#ifdef CONFIG_STA_SUPPORT
|
|
STASendPacket(pAd, pPacketClone);
|
|
#endif /* CONFIG_STA_SUPPORT */
|
|
}
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
VOID MultipathPoolInit(
|
|
IN PRTMP_ADAPTER pAd)
|
|
{
|
|
ULONG i;
|
|
|
|
NdisAllocateSpinLock(pAd, &pAd->MeshTab.MultipathTabLock);
|
|
|
|
os_alloc_mem(pAd, (UCHAR **)&(pAd->MeshTab.pMultipathEntryPool), sizeof(MESH_MULTIPATH_ENTRY) * MULTIPATH_POOL_SIZE);
|
|
if (pAd->MeshTab.pMultipathEntryPool)
|
|
{
|
|
NdisZeroMemory(pAd->MeshTab.pMultipathEntryPool, sizeof(MESH_BMPKTSIG_TAB));
|
|
initList(&pAd->MeshTab.MultipathEntryFreeList);
|
|
for (i = 0; i < MULTIPATH_POOL_SIZE; i++)
|
|
insertTailList(&pAd->MeshTab.MultipathEntryFreeList, (RT_LIST_ENTRY *)(pAd->MeshTab.pMultipathEntryPool + (ULONG)i));
|
|
}
|
|
else
|
|
DBGPRINT(RT_DEBUG_ERROR, ("%s Fail to alloc memory for pAd->MeshTab.pMultipathEntryPool", __FUNCTION__));
|
|
|
|
return;
|
|
}
|
|
|
|
VOID MultipathPoolExit(
|
|
IN PRTMP_ADAPTER pAd)
|
|
{
|
|
NdisFreeSpinLock(&pAd->MeshTab.MultipathTabLock);
|
|
|
|
if (pAd->MeshTab.pMultipathEntryPool)
|
|
os_free_mem(NULL, pAd->MeshTab.pMultipathEntryPool);
|
|
pAd->MeshTab.pMultipathEntryPool = NULL;
|
|
|
|
return;
|
|
}
|
|
|
|
PMESH_MULTIPATH_ENTRY MultipathEntyAlloc(
|
|
IN PRTMP_ADAPTER pAd)
|
|
{
|
|
PMESH_MULTIPATH_ENTRY pEntry;
|
|
|
|
RTMP_SEM_LOCK(&pAd->MeshTab.MultipathTabLock);
|
|
|
|
pEntry = (PMESH_MULTIPATH_ENTRY)removeHeadList(&pAd->MeshTab.MultipathEntryFreeList);
|
|
|
|
RTMP_SEM_UNLOCK(&pAd->MeshTab.MultipathTabLock);
|
|
|
|
return pEntry;
|
|
}
|
|
|
|
VOID MultipathEntyFree(
|
|
IN PRTMP_ADAPTER pAd,
|
|
IN PMESH_MULTIPATH_ENTRY pEntry)
|
|
{
|
|
RTMP_SEM_LOCK(&pAd->MeshTab.MultipathTabLock);
|
|
|
|
insertTailList(&pAd->MeshTab.MultipathEntryFreeList, (RT_LIST_ENTRY *)pEntry);
|
|
|
|
RTMP_SEM_UNLOCK(&pAd->MeshTab.MultipathTabLock);
|
|
|
|
return;
|
|
}
|
|
|
|
VOID MultipathEntryInsert(
|
|
IN PRTMP_ADAPTER pAd,
|
|
IN UCHAR LinkIdx,
|
|
IN PUCHAR pMac)
|
|
{
|
|
PMESH_MULTIPATH_ENTRY pEntry;
|
|
UINT8 HashId = *(pMac + 5);
|
|
ULONG Now;
|
|
|
|
if (!VALID_MESH_LINK_ID(LinkIdx))
|
|
return;
|
|
|
|
pEntry = MultipathEntryLookUp(pAd, LinkIdx, pMac);
|
|
if(pEntry == NULL)
|
|
{
|
|
if ((pEntry = MultipathEntyAlloc(pAd)) == NULL)
|
|
return;
|
|
insertTailList(&pAd->MeshTab.MeshLink[LinkIdx].Entry.MultiPathHash[HashId], (RT_LIST_ENTRY *)pEntry);
|
|
}
|
|
|
|
DBGPRINT(RT_DEBUG_TRACE, ("Block multipath pkt to link(%d) from SA=%02x:%02x:%02x:%02x:%02x:%02x\n",
|
|
LinkIdx, pMac[0], pMac[1], pMac[2], pMac[3], pMac[4], pMac[5]));
|
|
|
|
NdisGetSystemUpTime(&Now);
|
|
COPY_MAC_ADDR(pEntry->MeshSA, pMac);
|
|
pEntry->ReferTime = Now;
|
|
|
|
return;
|
|
}
|
|
|
|
VOID MultipathEntryDelete(
|
|
IN PRTMP_ADAPTER pAd,
|
|
IN UCHAR LinkIdx,
|
|
IN PUCHAR pMac)
|
|
{
|
|
UINT8 HashId = *(pMac + 5);
|
|
PMESH_MULTIPATH_ENTRY pEntry;
|
|
|
|
if (!VALID_MESH_LINK_ID(LinkIdx))
|
|
return;
|
|
|
|
pEntry = MultipathEntryLookUp(pAd, LinkIdx, pMac);
|
|
|
|
if (pEntry != NULL)
|
|
{
|
|
DBGPRINT(RT_DEBUG_TRACE, ("release multipath pkt to link(%d) from SA=%02x:%02x:%02x:%02x:%02x:%02x\n",
|
|
LinkIdx, pMac[0], pMac[1], pMac[2], pMac[3], pMac[4], pMac[5]));
|
|
|
|
delEntryList(&pAd->MeshTab.MeshLink[LinkIdx].Entry.MultiPathHash[HashId], (RT_LIST_ENTRY *)pEntry);
|
|
MultipathEntyFree(pAd, pEntry);
|
|
}
|
|
}
|
|
|
|
VOID MultipathListDelete(
|
|
IN PRTMP_ADAPTER pAd,
|
|
IN UCHAR LinkIdx)
|
|
{
|
|
ULONG i;
|
|
PMESH_MULTIPATH_ENTRY pEntry;
|
|
|
|
if (!VALID_MESH_LINK_ID(LinkIdx))
|
|
return;
|
|
|
|
DBGPRINT(RT_DEBUG_TRACE, ("release all multipath pkt of link(%d)\n", LinkIdx));
|
|
|
|
for (i = 0; i < MULTIPATH_HASH_TAB_SIZE; i++)
|
|
{
|
|
pEntry = (PMESH_MULTIPATH_ENTRY)removeHeadList(&pAd->MeshTab.MeshLink[LinkIdx].Entry.MultiPathHash[i]);
|
|
while (pEntry != NULL)
|
|
{
|
|
MultipathEntyFree(pAd, pEntry);
|
|
pEntry = (PMESH_MULTIPATH_ENTRY)removeHeadList(&pAd->MeshTab.MeshLink[LinkIdx].Entry.MultiPathHash[i]);
|
|
}
|
|
}
|
|
return;
|
|
}
|
|
|
|
PMESH_MULTIPATH_ENTRY MultipathEntryLookUp(
|
|
IN PRTMP_ADAPTER pAd,
|
|
IN UCHAR LinkIdx,
|
|
IN PUCHAR pMac)
|
|
{
|
|
UINT8 HashId = *(pMac + 5);
|
|
PMESH_MULTIPATH_ENTRY pEntry;
|
|
|
|
if (!VALID_MESH_LINK_ID(LinkIdx))
|
|
return NULL;
|
|
|
|
pEntry = (PMESH_MULTIPATH_ENTRY)(pAd->MeshTab.MeshLink[LinkIdx].Entry.MultiPathHash[HashId].pHead);
|
|
while (pEntry != NULL)
|
|
{
|
|
if(MAC_ADDR_EQUAL(pEntry->MeshSA, pMac))
|
|
break;
|
|
pEntry = pEntry->pNext;
|
|
}
|
|
|
|
return pEntry;
|
|
}
|
|
|
|
VOID MultipathEntryMaintain(
|
|
IN PRTMP_ADAPTER pAd,
|
|
IN UCHAR LinkIdx)
|
|
{
|
|
ULONG i;
|
|
PMESH_MULTIPATH_ENTRY pEntry;
|
|
ULONG Now;
|
|
|
|
if (!VALID_MESH_LINK_ID(LinkIdx))
|
|
return;
|
|
|
|
NdisGetSystemUpTime(&Now);
|
|
for (i = 0; i < MULTIPATH_HASH_TAB_SIZE; i++)
|
|
{
|
|
pEntry = (PMESH_MULTIPATH_ENTRY)(pAd->MeshTab.MeshLink[LinkIdx].Entry.MultiPathHash[i].pHead);
|
|
while (pEntry)
|
|
{
|
|
PMESH_MULTIPATH_ENTRY pEntryNext = pEntry->pNext;
|
|
if (RTMP_TIME_AFTER(Now, pEntry->ReferTime + (pAd->MeshTab.MeshMultiCastAgeOut * OS_HZ / 1000)))
|
|
{
|
|
delEntryList(&pAd->MeshTab.MeshLink[LinkIdx].Entry.MultiPathHash[i], (RT_LIST_ENTRY *)pEntry);
|
|
MultipathEntyFree(pAd, pEntry);
|
|
}
|
|
pEntry = pEntryNext;
|
|
}
|
|
}
|
|
return;
|
|
}
|
|
|
|
#endif /* MESH_SUPPORT */
|
|
|