1570 lines
43 KiB
C
1570 lines
43 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_ctrl.c
|
|
|
|
Abstract:
|
|
|
|
Revision History:
|
|
Who When What
|
|
-------- ---------- ----------------------------------------------
|
|
Fonchi 2007-06-25 For mesh (802.11s) support.
|
|
*/
|
|
#ifdef MESH_SUPPORT
|
|
|
|
|
|
#include "rt_config.h"
|
|
#include "mesh_sanity.h"
|
|
|
|
static VOID MeshPldTimeout(
|
|
IN PVOID SystemSpecific1,
|
|
IN PVOID FunctionContext,
|
|
IN PVOID SystemSpecific2,
|
|
IN PVOID SystemSpecific3);
|
|
|
|
static VOID MeshMcsTimeout(
|
|
IN PVOID SystemSpecific1,
|
|
IN PVOID FunctionContext,
|
|
IN PVOID SystemSpecific2,
|
|
IN PVOID SystemSpecific3);
|
|
|
|
static VOID
|
|
MeshCtrlJoinAction(
|
|
IN PRTMP_ADAPTER pAd,
|
|
IN MLME_QUEUE_ELEM *Elem);
|
|
|
|
static VOID
|
|
MeshCtrlDisconnectAtDicoveryAction(
|
|
IN PRTMP_ADAPTER pAd,
|
|
IN MLME_QUEUE_ELEM *Elem);
|
|
|
|
static VOID
|
|
MeshCtrlFinishDiscoveryAction(
|
|
IN PRTMP_ADAPTER pAd,
|
|
IN MLME_QUEUE_ELEM *Elem);
|
|
|
|
static VOID
|
|
MeshCtrlDiscoveryAbortAction(
|
|
IN PRTMP_ADAPTER pAd,
|
|
IN MLME_QUEUE_ELEM *Elem);
|
|
|
|
static VOID
|
|
MeshCtrlPeriodPLDAction(
|
|
IN PRTMP_ADAPTER pAd,
|
|
IN MLME_QUEUE_ELEM *Elem);
|
|
|
|
static VOID
|
|
MeshCtrlDisconnectAtActivatedAction(
|
|
IN PRTMP_ADAPTER pAd,
|
|
IN MLME_QUEUE_ELEM *Elem);
|
|
|
|
static VOID
|
|
MeshCtrlUcgWhenActivated(
|
|
IN PRTMP_ADAPTER pAd,
|
|
IN MLME_QUEUE_ELEM *Elem);
|
|
|
|
static VOID
|
|
MeshPeerUcgWhenActivated(
|
|
IN PRTMP_ADAPTER pAd,
|
|
IN MLME_QUEUE_ELEM *Elem);
|
|
|
|
static VOID
|
|
MeshPeerUcgWhenUcg(
|
|
IN PRTMP_ADAPTER pAd,
|
|
IN MLME_QUEUE_ELEM *Elem);
|
|
|
|
static VOID
|
|
MeshCtrlDisconnectAtUCGAction(
|
|
IN PRTMP_ADAPTER pAd,
|
|
IN MLME_QUEUE_ELEM *Elem);
|
|
|
|
static VOID
|
|
MeshCtrlMcsTimeoutAction(
|
|
IN PRTMP_ADAPTER pAd,
|
|
IN MLME_QUEUE_ELEM *Elem);
|
|
|
|
DECLARE_TIMER_FUNCTION(MeshPldTimeout);
|
|
DECLARE_TIMER_FUNCTION(MeshMcsTimeout);
|
|
|
|
BUILD_TIMER_FUNCTION(MeshPldTimeout);
|
|
BUILD_TIMER_FUNCTION(MeshMcsTimeout);
|
|
|
|
static VOID
|
|
NeighborEntrySet(
|
|
OUT PMESH_NEIGHBOR_ENTRY pNeighbor,
|
|
IN CHAR RealRssi,
|
|
IN PUCHAR pPeerMacAddr,
|
|
IN RTMP_STRING *pHostName,
|
|
IN PCHAR pMeshId,
|
|
IN UCHAR MeshIdLen,
|
|
IN UCHAR Channel,
|
|
IN UINT8 ChBW,
|
|
IN UINT8 ExtChOffset,
|
|
IN USHORT CapabilityInfo,
|
|
IN PUCHAR pVIE,
|
|
IN USHORT LenVIE,
|
|
IN PMESH_CONFIGURAION_IE pMeshConfig);
|
|
|
|
static PMESH_NEIGHBOR_ENTRY
|
|
NeighMPWithMaxCPI(
|
|
IN PRTMP_ADAPTER pAd,
|
|
IN PMESH_NEIGHBOR_TAB pNeighborTab);
|
|
|
|
static VOID
|
|
EnqueChSwAnnouncement(
|
|
IN PRTMP_ADAPTER pAd,
|
|
IN PUCHAR PeerMac,
|
|
IN UINT8 MeshTTL,
|
|
IN UINT32 MeshSeq,
|
|
IN UINT8 ChSwMode,
|
|
IN UCHAR NewCh,
|
|
IN UINT32 NewCPI,
|
|
IN UINT8 ChSwCnt,
|
|
IN PUCHAR pMeshSa);
|
|
|
|
BOOLEAN MeshValid(PMESH_STRUCT pMesh)
|
|
{
|
|
return (pMesh->CtrlCurrentState == MESH_CTRL_ACTIVATED) ? TRUE : FALSE;
|
|
}
|
|
|
|
/*
|
|
==========================================================================
|
|
Description:
|
|
The mesh control state machine,
|
|
Parameters:
|
|
Sm - pointer to the state machine
|
|
Note:
|
|
the state machine looks like the following
|
|
==========================================================================
|
|
*/
|
|
VOID MeshCtrlStateMachineInit(
|
|
IN PRTMP_ADAPTER pAd,
|
|
IN STATE_MACHINE *Sm,
|
|
OUT STATE_MACHINE_FUNC Trans[])
|
|
{
|
|
StateMachineInit(Sm, (STATE_MACHINE_FUNC*)Trans, (ULONG)MESH_CTRL_MAX_STATES,
|
|
(ULONG)MESH_CTRL_MAX_EVENTS, (STATE_MACHINE_FUNC)Drop, MESH_CTRL_IDLE, MESH_CTRL_IDLE);
|
|
|
|
/* MESH_CTRL_IDLE state */
|
|
StateMachineSetAction(Sm, MESH_CTRL_IDLE, MESH_CTRL_JOIN, (STATE_MACHINE_FUNC)MeshCtrlJoinAction);
|
|
|
|
/* MESH_CTRL_DISCOVERY state */
|
|
StateMachineSetAction(Sm, MESH_CTRL_DISCOVERY, MESH_CTRL_DISCONNECT, (STATE_MACHINE_FUNC)MeshCtrlDisconnectAtDicoveryAction);
|
|
StateMachineSetAction(Sm, MESH_CTRL_DISCOVERY, APMT2_MLME_SCAN_FINISH, (STATE_MACHINE_FUNC)MeshCtrlFinishDiscoveryAction);
|
|
StateMachineSetAction(Sm, MESH_CTRL_DISCOVERY, APMT2_MLME_SCAN_ABORT, (STATE_MACHINE_FUNC)MeshCtrlDiscoveryAbortAction);
|
|
|
|
/* MESH_CTRL_ACTIVATED state */
|
|
StateMachineSetAction(Sm, MESH_CTRL_ACTIVATED, MESH_CTRL_PLD, (STATE_MACHINE_FUNC)MeshCtrlPeriodPLDAction);
|
|
StateMachineSetAction(Sm, MESH_CTRL_ACTIVATED, MESH_CTRL_DISCONNECT, (STATE_MACHINE_FUNC)MeshCtrlDisconnectAtActivatedAction);
|
|
StateMachineSetAction(Sm, MESH_CTRL_ACTIVATED, MESH_CTRL_UCG_EVT, (STATE_MACHINE_FUNC)MeshCtrlUcgWhenActivated);
|
|
StateMachineSetAction(Sm, MESH_CTRL_ACTIVATED, MESH_PEER_UCG_EVT, (STATE_MACHINE_FUNC)MeshPeerUcgWhenActivated);
|
|
|
|
/* MESH_CTRL_UCG state */
|
|
StateMachineSetAction(Sm, MESH_CTRL_UCG, MESH_CTRL_DISCONNECT, (STATE_MACHINE_FUNC)MeshCtrlDisconnectAtUCGAction);
|
|
StateMachineSetAction(Sm, MESH_CTRL_UCG, MESH_PEER_UCG_EVT, (STATE_MACHINE_FUNC)MeshPeerUcgWhenUcg);
|
|
StateMachineSetAction(Sm, MESH_CTRL_UCG, MESH_CTRL_MCS_TIMEOUT, (STATE_MACHINE_FUNC)MeshCtrlMcsTimeoutAction);
|
|
|
|
/* init all Mesh ctrl state. */
|
|
pAd->MeshTab.CtrlCurrentState = MESH_CTRL_IDLE;
|
|
|
|
/* init all timer relative to mesh ctrl sm. */
|
|
RTMPInitTimer(pAd, &pAd->MeshTab.PldTimer, GET_TIMER_FUNCTION(MeshPldTimeout), pAd, FALSE);
|
|
RTMPInitTimer(pAd, &pAd->MeshTab.McsTimer, GET_TIMER_FUNCTION(MeshMcsTimeout), pAd, FALSE);
|
|
|
|
return;
|
|
}
|
|
|
|
/*
|
|
==========================================================================
|
|
Description:
|
|
Peer-Link-Discovery timeout procedure.
|
|
Parameters:
|
|
Standard timer parameters
|
|
==========================================================================
|
|
*/
|
|
static VOID MeshPldTimeout(
|
|
IN PVOID SystemSpecific1,
|
|
IN PVOID FunctionContext,
|
|
IN PVOID SystemSpecific2,
|
|
IN PVOID SystemSpecific3)
|
|
{
|
|
RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)FunctionContext;
|
|
|
|
DBGPRINT(RT_DEBUG_TRACE, ("%s - enqueue MESH_CTRL_PLD to MESH_CTRL State-Machine.\n", __FUNCTION__));
|
|
|
|
MlmeEnqueue(pAd, MESH_CTRL_STATE_MACHINE, MESH_CTRL_PLD, 0, NULL, 0);
|
|
RTMP_MLME_HANDLER(pAd);
|
|
|
|
return;
|
|
}
|
|
|
|
/*
|
|
==========================================================================
|
|
Description:
|
|
Mesh-Channel-Switch timeout procedure.
|
|
Parameters:
|
|
Standard timer parameters
|
|
==========================================================================
|
|
*/
|
|
static VOID MeshMcsTimeout(
|
|
IN PVOID SystemSpecific1,
|
|
IN PVOID FunctionContext,
|
|
IN PVOID SystemSpecific2,
|
|
IN PVOID SystemSpecific3)
|
|
{
|
|
RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)FunctionContext;
|
|
|
|
DBGPRINT(RT_DEBUG_TRACE, ("%s - enqueue MESH_CTRL_MCS_TIMEOUT to MESH_CTRL State-Machine.\n", __FUNCTION__));
|
|
|
|
MlmeEnqueue(pAd, MESH_CTRL_STATE_MACHINE, MESH_CTRL_MCS_TIMEOUT, 0, NULL, 0);
|
|
RTMP_MLME_HANDLER(pAd);
|
|
|
|
return;
|
|
}
|
|
|
|
static VOID
|
|
MeshCtrlJoinAction(
|
|
IN PRTMP_ADAPTER pAd,
|
|
IN MLME_QUEUE_ELEM *Elem)
|
|
{
|
|
MESH_CTRL_STATE *pCurrState = &(pAd->MeshTab.CtrlCurrentState);
|
|
|
|
#ifdef CONFIG_STA_SUPPORT
|
|
/* Initialize RF register to default value */
|
|
IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
|
|
{
|
|
MeshChannelInit(pAd);
|
|
}
|
|
#endif /* CONFIG_STA_SUPPORT */
|
|
|
|
#ifdef INTEL_CMPC
|
|
/* Set PLD timer. */
|
|
/* transit state to MESH_CTRL_ACTIVATED. */
|
|
|
|
RTMPSetTimer(&pAd->MeshTab.PldTimer, PLD_TIME);
|
|
*pCurrState = MESH_CTRL_ACTIVATED;
|
|
#else
|
|
#ifdef RELEASE_EXCLUDE
|
|
/* send APMT2_MLME_SCAN_REQ to AP-SYNC FSM. */
|
|
/* transit state to MESH_CTRL_DISCOVERY state. */
|
|
#endif /* RELEASE_EXCLUDE */
|
|
|
|
MLME_SCAN_REQ_STRUCT ScanReq;
|
|
UCHAR BroadSsid[MAX_LEN_OF_SSID];
|
|
|
|
DBGPRINT(RT_DEBUG_TRACE, ("%s: Get Join evt when Idle.\n", __FUNCTION__));
|
|
|
|
AsicDisableSync(pAd);
|
|
|
|
BssTableInit(&pAd->ScanTab);
|
|
BroadSsid[0] = '\0';
|
|
|
|
ScanReq.SsidLen = 0;
|
|
NdisMoveMemory(ScanReq.Ssid, BroadSsid, ScanReq.SsidLen);
|
|
ScanReq.BssType = BSS_ANY;
|
|
ScanReq.ScanType = SCAN_PASSIVE;
|
|
|
|
#ifdef CONFIG_AP_SUPPORT
|
|
pAd->Mlme.ApSyncMachine.CurrState = AP_SYNC_IDLE;
|
|
MlmeEnqueue(pAd, AP_SYNC_STATE_MACHINE, APMT2_MLME_SCAN_REQ, sizeof(MLME_SCAN_REQ_STRUCT), &ScanReq, 0);
|
|
RTMP_MLME_HANDLER(pAd);
|
|
#endif /* CONFIG_AP_SUPPORT */
|
|
#ifdef CONFIG_STA_SUPPORT
|
|
ScanParmFill(pAd, &ScanReq, "", 0, BSS_ANY, SCAN_ACTIVE);
|
|
MlmeEnqueue(pAd, SYNC_STATE_MACHINE, MT2_MLME_SCAN_REQ,
|
|
sizeof(MLME_SCAN_REQ_STRUCT), &ScanReq, 0);
|
|
#endif /* CONFIG_STA_SUPPORT */
|
|
|
|
*pCurrState = MESH_CTRL_DISCOVERY;
|
|
#endif
|
|
}
|
|
|
|
static VOID
|
|
MeshCtrlDisconnectAtDicoveryAction(
|
|
IN PRTMP_ADAPTER pAd,
|
|
IN MLME_QUEUE_ELEM *Elem)
|
|
{
|
|
#ifdef RELEASE_EXCLUDE
|
|
/* send MESH_LINK_MNG_CNCL to MESH_LINK_MNG FSM. */
|
|
/* send APMT2_MLME_SCAN_CNCL to AP_SYNC FSM. */
|
|
/* transit state to MESH_CTRL_IDLE. */
|
|
#endif /* RELEASE_EXCLUDE */
|
|
|
|
MESH_CTRL_STATE *pCurrState = &(pAd->MeshTab.CtrlCurrentState);
|
|
INT i;
|
|
|
|
DBGPRINT(RT_DEBUG_TRACE, ("%s: Get Disconnect evt when Discovery.\n", __FUNCTION__));
|
|
|
|
for (i = 0; i < MAX_MESH_LINKS; i++)
|
|
{
|
|
MlmeEnqueue(pAd, MESH_LINK_MNG_STATE_MACHINE, MESH_LINK_MNG_CNCL, 0, NULL, i);
|
|
}
|
|
|
|
#ifdef AP_SCAN_SUPPORT
|
|
MlmeEnqueue(pAd, AP_SYNC_STATE_MACHINE, APMT2_MLME_SCAN_CNCL, 0, NULL, 0);
|
|
#endif
|
|
*pCurrState = MESH_CTRL_IDLE;
|
|
}
|
|
|
|
static VOID
|
|
MeshCtrlFinishDiscoveryAction(
|
|
IN PRTMP_ADAPTER pAd,
|
|
IN MLME_QUEUE_ELEM *Elem)
|
|
{
|
|
#ifdef RELEASE_EXCLUDE
|
|
/* send MESH_LINK_MNG_PASOPN or MESH_LINK_MNG_ACTOPN to MESH_LINK_MNG FSM. */
|
|
/* Set PLD timer. */
|
|
/* transite state to MESH_CTRL_ACTIVATED. */
|
|
#endif /* RELEASE_EXCLUDE */
|
|
|
|
MESH_CTRL_STATE *pCurrState = &(pAd->MeshTab.CtrlCurrentState);
|
|
INT i;
|
|
|
|
DBGPRINT(RT_DEBUG_TRACE, ("%s: Get Scan-Finish evt when Discovery.\n", __FUNCTION__));
|
|
|
|
NeighborTableUpdate(pAd);
|
|
CandidateMPSelect(pAd);
|
|
|
|
for (i = 0; i < MAX_MESH_LINKS; i++)
|
|
{
|
|
if(pAd->MeshTab.MeshLink[i].Entry.Valid)
|
|
MlmeEnqueue(pAd, MESH_LINK_MNG_STATE_MACHINE, MESH_LINK_MNG_ACTOPN, 0, NULL, i);
|
|
}
|
|
|
|
RTMPSetTimer(&pAd->MeshTab.PldTimer, PLD_TIME + RANDOM_TIME(pAd));
|
|
*pCurrState = MESH_CTRL_ACTIVATED;
|
|
}
|
|
|
|
static VOID
|
|
MeshCtrlDiscoveryAbortAction(
|
|
IN PRTMP_ADAPTER pAd,
|
|
IN MLME_QUEUE_ELEM *Elem)
|
|
{
|
|
MESH_CTRL_STATE *pCurrState = &(pAd->MeshTab.CtrlCurrentState);
|
|
|
|
#ifdef RELEASE_EXCLUDE
|
|
/* skip the scan result since scan abort. */
|
|
/* Set PLD timer. */
|
|
/* transite state to MESH_CTRL_ACTIVATED. */
|
|
#endif /* RELEASE_EXCLUDE */
|
|
|
|
DBGPRINT(RT_DEBUG_TRACE, ("%s: Get Scan-Abort evt when Discovery.\n", __FUNCTION__));
|
|
|
|
RTMPSetTimer(&pAd->MeshTab.PldTimer, PLD_TIME + RANDOM_TIME(pAd));
|
|
*pCurrState = MESH_CTRL_ACTIVATED;
|
|
}
|
|
|
|
static VOID
|
|
MeshCtrlPeriodPLDAction(
|
|
IN PRTMP_ADAPTER pAd,
|
|
IN MLME_QUEUE_ELEM *Elem)
|
|
{
|
|
#ifdef INTEL_CMPC
|
|
/* select candidate MPs from neighbor list. */
|
|
/* set PLD timer. */
|
|
|
|
INT i;
|
|
|
|
CandidateMPSelect(pAd);
|
|
for (i = 0; i < MAX_MESH_LINKS; i++)
|
|
{
|
|
BOOLEAN CnetFlag = FALSE;
|
|
|
|
if (pAd->MeshTab.MeshAutoLink == TRUE)
|
|
CnetFlag = pAd->MeshTab.MeshLink[i].Entry.Valid && !PeerLinkValidCheck(pAd, i);
|
|
else
|
|
CnetFlag = pAd->MeshTab.MeshLink[i].Entry.Valid
|
|
&& (pAd->MeshTab.MeshLink[i].Entry.LinkType == MESH_LINK_STATIC)
|
|
&& !PeerLinkValidCheck(pAd, i);
|
|
|
|
if (CnetFlag)
|
|
MlmeEnqueue(pAd, MESH_LINK_MNG_STATE_MACHINE, MESH_LINK_MNG_ACTOPN, 0, NULL, i);
|
|
}
|
|
|
|
RTMPSetTimer(&pAd->MeshTab.PldTimer, PLD_TIME);
|
|
#else
|
|
#ifdef RELEASE_EXCLUDE
|
|
/* send APMT2_MLME_SCAN_REQ to AP-SYNC FSM. */
|
|
/* transit state to MESH_CTRL_DISCOVERY state. */
|
|
#endif /* RELEASE_EXCLUDE */
|
|
|
|
PULONG pCurrState = &(pAd->MeshTab.CtrlCurrentState);
|
|
INT i;
|
|
BOOLEAN Valid = TRUE;
|
|
MLME_SCAN_REQ_STRUCT ScanReq;
|
|
UCHAR BroadSsid[MAX_LEN_OF_SSID];
|
|
|
|
DBGPRINT(RT_DEBUG_TRACE, ("%s: Get PLD evt when Activated.\n", __FUNCTION__));
|
|
|
|
AsicDisableSync(pAd);
|
|
|
|
BssTableInit(&pAd->ScanTab);
|
|
BroadSsid[0] = '\0';
|
|
|
|
ScanReq.SsidLen = 0;
|
|
NdisMoveMemory(ScanReq.Ssid, BroadSsid, ScanReq.SsidLen);
|
|
ScanReq.BssType = BSS_ANY;
|
|
ScanReq.ScanType = SCAN_PASSIVE;
|
|
|
|
#ifdef RELEASE_EXCLUDE
|
|
/* should check that all valid peer links finish establish. */
|
|
/* shall not scan air during Peer link action. */
|
|
#endif /* RELEASE_EXCLUDE */
|
|
for (i = 0; i < MAX_MESH_LINKS; i++)
|
|
{
|
|
if (PeerLinkMngRuning(pAd, i))
|
|
{
|
|
Valid = FALSE;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (Valid)
|
|
{
|
|
#ifdef CONFIG_AP_SUPPORT
|
|
pAd->Mlme.ApSyncMachine.CurrState = AP_SYNC_IDLE;
|
|
MlmeEnqueue(pAd, AP_SYNC_STATE_MACHINE, APMT2_MLME_SCAN_REQ, sizeof(MLME_SCAN_REQ_STRUCT), &ScanReq, 0);
|
|
RTMP_MLME_HANDLER(pAd);
|
|
#endif /* CONFIG_AP_SUPPORT */
|
|
#ifdef CONFIG_STA_SUPPORT
|
|
ScanParmFill(pAd, &ScanReq, "", 0, BSS_ANY, SCAN_ACTIVE);
|
|
MlmeEnqueue(pAd, SYNC_STATE_MACHINE, MT2_MLME_SCAN_REQ,
|
|
sizeof(MLME_SCAN_REQ_STRUCT), &ScanReq, 0);
|
|
#endif /* CONFIG_STA_SUPPORT */
|
|
*pCurrState = MESH_CTRL_DISCOVERY;
|
|
}
|
|
else
|
|
{
|
|
RTMPSetTimer(&pAd->MeshTab.PldTimer, PLD_TIME + RANDOM_TIME(pAd));
|
|
}
|
|
#endif /* INTEL_CMPC */
|
|
}
|
|
|
|
static VOID
|
|
MeshCtrlDisconnectAtActivatedAction(
|
|
IN PRTMP_ADAPTER pAd,
|
|
IN MLME_QUEUE_ELEM *Elem)
|
|
{
|
|
#ifdef RELEASE_EXCLUDE
|
|
/* send MESH_LINK_MNG_CNCL to MESH_LINK_MNG FSM. */
|
|
/* Cancel PLD timer. */
|
|
/* transit state to MESH_CTRL_IDLE. */
|
|
#endif /* RELEASE_EXCLUDE */
|
|
|
|
MESH_CTRL_STATE *pCurrState = &(pAd->MeshTab.CtrlCurrentState);
|
|
INT i;
|
|
BOOLEAN Cancelled;
|
|
|
|
DBGPRINT(RT_DEBUG_TRACE, ("%s: Get Disconnect evt when Activated.\n", __FUNCTION__));
|
|
|
|
for (i = 0; i < MAX_MESH_LINKS; i++)
|
|
{
|
|
MlmeEnqueue(pAd, MESH_LINK_MNG_STATE_MACHINE, MESH_LINK_MNG_CNCL, 0, NULL, i);
|
|
}
|
|
RTMPCancelTimer(&pAd->MeshTab.PldTimer, &Cancelled);
|
|
|
|
*pCurrState = MESH_CTRL_IDLE;
|
|
}
|
|
|
|
static VOID
|
|
MeshCtrlUcgWhenActivated(
|
|
IN PRTMP_ADAPTER pAd,
|
|
IN MLME_QUEUE_ELEM *Elem)
|
|
{
|
|
#ifdef RELEASE_EXCLUDE
|
|
/* Cancel PLD timer. */
|
|
/* chooses a meshchannel switch time. And set MCS timer with the waiting time value. */
|
|
/* increase CPI with a random value. */
|
|
/* send MeshChSwAnnouncement frame to each peer MP. */
|
|
/* transit state to MESH_CTRL_UCG. */
|
|
#endif /* RELEASE_EXCLUDE */
|
|
|
|
MESH_CTRL_STATE *pCurrState = &(pAd->MeshTab.CtrlCurrentState);
|
|
INT i;
|
|
BOOLEAN Cancelled;
|
|
UINT8 ChSwCnt = RandomChSwWaitTime(pAd);
|
|
UINT32 NewCPI = pAd->MeshTab.CPI += RandomByte(pAd);
|
|
UINT32 ChSwMode = 1;
|
|
|
|
RTMPCancelTimer(&pAd->MeshTab.PldTimer, &Cancelled);
|
|
RTMPSetTimer(&pAd->MeshTab.McsTimer, ChSwCnt * MESH_TU);
|
|
|
|
/* propagate channel switch announcement to each peer link. */
|
|
INC_MESH_SEQ(pAd->MeshTab.MeshSeq);
|
|
for (i = 0; i < MAX_MESH_LINKS; i++)
|
|
{
|
|
if (PeerLinkValidCheck(pAd, i) == TRUE)
|
|
EnqueChSwAnnouncement(
|
|
pAd,
|
|
pAd->MeshTab.MeshLink[i].Entry.PeerMacAddr,
|
|
pAd->MeshTab.TTL,
|
|
pAd->MeshTab.MeshSeq,
|
|
ChSwMode,
|
|
pAd->MeshTab.MeshChannel,
|
|
NewCPI,
|
|
ChSwCnt,
|
|
pAd->MeshTab.wdev.if_addr);
|
|
}
|
|
|
|
pAd->MeshTab.NewCPI = NewCPI;
|
|
*pCurrState = MESH_CTRL_UCG;
|
|
|
|
DBGPRINT(RT_DEBUG_TRACE, ("%s: Get UCG evt when Activated.\n", __FUNCTION__));
|
|
}
|
|
|
|
static VOID
|
|
MeshPeerUcgWhenActivated(
|
|
IN PRTMP_ADAPTER pAd,
|
|
IN MLME_QUEUE_ELEM *Elem)
|
|
{
|
|
#ifdef RELEASE_EXCLUDE
|
|
/* check the CPI value from ChSwAnnouncement frame larger than current CPI value. */
|
|
/* if yes copy CPI from frame and start Ucg. if not then ignore the frame. */
|
|
|
|
/* Cancel PLD timer. */
|
|
/* Cancel MCS timer. */
|
|
/* set CPI with the CPI value with the frame. */
|
|
/* set MCS timer with the ChSwWaitTime value with the frame. */
|
|
/* send MeshChSwAnnouncement frame to each peer MP. */
|
|
/* transit state to MESH_CTRL_UCG. */
|
|
#endif /* RELEASE_EXCLUDE */
|
|
|
|
MESH_CTRL_STATE *pCurrState = &(pAd->MeshTab.CtrlCurrentState);
|
|
BOOLEAN Cancelled;
|
|
PMESH_CH_SW_ANN_MSG_STRUCT pInfo = (PMESH_CH_SW_ANN_MSG_STRUCT)(Elem->Msg);
|
|
UINT32 NewCPI = pInfo->NewCPI;
|
|
PUCHAR pMeshSA = pInfo->MeshSA;
|
|
|
|
DBGPRINT(RT_DEBUG_TRACE, ("%s: Get UCG evt when Activated.\n", __FUNCTION__));
|
|
|
|
if ((NewCPI < pAd->MeshTab.CPI)
|
|
|| ((NewCPI == pAd->MeshTab.CPI) && (memcmp(pAd->MeshTab.wdev.if_addr, pMeshSA, MAC_ADDR_LEN) >= 0))
|
|
)
|
|
{
|
|
return;
|
|
}
|
|
|
|
RTMPCancelTimer(&pAd->MeshTab.PldTimer, &Cancelled);
|
|
MeshPeerUcgWhenUcg(pAd, Elem);
|
|
*pCurrState = MESH_CTRL_UCG;
|
|
|
|
return;
|
|
}
|
|
|
|
static VOID
|
|
MeshPeerUcgWhenUcg(
|
|
IN PRTMP_ADAPTER pAd,
|
|
IN MLME_QUEUE_ELEM *Elem)
|
|
{
|
|
#ifdef RELEASE_EXCLUDE
|
|
/* check the CPI value from ChSwAnnouncement frame larger than current CPI value. */
|
|
/* if yes copy CPI from frame and start Ucg. if not then ignore the frame. */
|
|
|
|
/* Cancel PLD timer. */
|
|
/* Cancel MCS timer. */
|
|
/* set CPI with the CPI value with the frame. */
|
|
/* set MCS timer with the ChSwWaitTime value with the frame. */
|
|
/* send MeshChSwAnnouncement frame to each peer MP. */
|
|
/* transit state to MESH_CTRL_UCG. */
|
|
#endif /* RELEASE_EXCLUDE */
|
|
|
|
MESH_CTRL_STATE *pCurrState = &(pAd->MeshTab.CtrlCurrentState);
|
|
INT i;
|
|
BOOLEAN Cancelled;
|
|
PMESH_CH_SW_ANN_MSG_STRUCT pInfo = (PMESH_CH_SW_ANN_MSG_STRUCT)(Elem->Msg);
|
|
UINT32 NewCPI = pInfo->NewCPI;
|
|
UINT32 MeshSeq = pInfo->MeshSeq;
|
|
UINT8 MeshTTL = pInfo->MeshTTL;
|
|
UINT8 ChSwCnt = pInfo->ChSwCnt;
|
|
UINT8 NewCh = pInfo->NewCh;
|
|
UINT8 ChSwMode = pInfo->ChSwMode;
|
|
UINT8 LinkId = pInfo->LinkId;
|
|
PUCHAR pMeshSA = pInfo->MeshSA;
|
|
|
|
if ((NewCPI < pAd->MeshTab.CPI)
|
|
|| ((NewCPI == pAd->MeshTab.CPI) && (memcmp(pAd->MeshTab.wdev.if_addr, pMeshSA, MAC_ADDR_LEN) >= 0))
|
|
)
|
|
{
|
|
return;
|
|
}
|
|
|
|
if (*pCurrState == MESH_CTRL_UCG)
|
|
DBGPRINT(RT_DEBUG_TRACE, ("%s: Get UCG evt when Activated.\n", __FUNCTION__));
|
|
|
|
pAd->MeshTab.MeshChannel = NewCh;
|
|
RTMPCancelTimer(&pAd->MeshTab.McsTimer, &Cancelled);
|
|
RTMPSetTimer(&pAd->MeshTab.McsTimer, ChSwCnt * MESH_TU);
|
|
|
|
/* foward ChSwAnnouncement to each peer link. */
|
|
MeshTTL--;
|
|
do
|
|
{
|
|
if (MeshTTL == 0)
|
|
break;
|
|
|
|
for (i = 0; i < MAX_MESH_LINKS; i++)
|
|
{
|
|
if (PeerLinkValidCheck(pAd, i) == FALSE)
|
|
continue;
|
|
|
|
if (LinkId == i)
|
|
continue;
|
|
|
|
if (MAC_ADDR_EQUAL(pAd->MeshTab.MeshLink[i].Entry.PeerMacAddr, pMeshSA) == TRUE)
|
|
continue;
|
|
|
|
EnqueChSwAnnouncement(
|
|
pAd,
|
|
pAd->MeshTab.MeshLink[i].Entry.PeerMacAddr,
|
|
MeshTTL,
|
|
MeshSeq,
|
|
ChSwMode,
|
|
NewCh,
|
|
NewCPI,
|
|
ChSwCnt,
|
|
pMeshSA);
|
|
}
|
|
} while(FALSE);
|
|
|
|
pAd->MeshTab.NewCPI = NewCPI;
|
|
|
|
return;
|
|
}
|
|
|
|
static VOID
|
|
MeshCtrlDisconnectAtUCGAction(
|
|
IN PRTMP_ADAPTER pAd,
|
|
IN MLME_QUEUE_ELEM *Elem)
|
|
{
|
|
#ifdef RELEASE_EXCLUDE
|
|
/* send MESH_LINK_MNG_CNCL to MESH_LINK_MNG */
|
|
/* cancel MCS timer. */
|
|
/* transit state to MESH_CTRL_IDLE. */
|
|
#endif /* RELEASE_EXCLUDE */
|
|
|
|
MESH_CTRL_STATE *pCurrState = &(pAd->MeshTab.CtrlCurrentState);
|
|
INT i;
|
|
BOOLEAN Cancelled;
|
|
|
|
DBGPRINT(RT_DEBUG_TRACE, ("%s: Get Disconnect evt when UCG.\n", __FUNCTION__));
|
|
|
|
for (i = 0; i < MAX_MESH_LINKS; i++)
|
|
{
|
|
MlmeEnqueue(pAd, MESH_LINK_MNG_STATE_MACHINE, MESH_LINK_MNG_CNCL, 0, NULL, i);
|
|
}
|
|
RTMPCancelTimer(&pAd->MeshTab.McsTimer, &Cancelled);
|
|
|
|
*pCurrState = MESH_CTRL_IDLE;
|
|
}
|
|
|
|
static VOID
|
|
MeshCtrlMcsTimeoutAction(
|
|
IN PRTMP_ADAPTER pAd,
|
|
IN MLME_QUEUE_ELEM *Elem)
|
|
{
|
|
#ifdef RELEASE_EXCLUDE
|
|
/* switch to a new channel. */
|
|
/* set PLD timer. */
|
|
/* transit state to MESH_CTRL_ACTIVATED. */
|
|
#endif /* RELEASE_EXCLUDE */
|
|
|
|
MESH_CTRL_STATE *pCurrState = &(pAd->MeshTab.CtrlCurrentState);
|
|
|
|
DBGPRINT(RT_DEBUG_TRACE, ("%s: Get Mcs evt when UCG.\n", __FUNCTION__));
|
|
|
|
if (!INFRA_ON(pAd) && !ADHOC_ON(pAd))
|
|
{
|
|
/*SET_MESH_CHANNEL(pAd); */
|
|
pAd->CommonCfg.Channel = pAd->MeshTab.MeshChannel;
|
|
#ifdef DOT11_N_SUPPORT
|
|
N_ChannelCheck(pAd);
|
|
#endif /* DOT11_N_SUPPORT */
|
|
AsicSwitchChannel(pAd, pAd->CommonCfg.CentralChannel, FALSE);
|
|
AsicLockChannel(pAd, pAd->CommonCfg.CentralChannel);
|
|
|
|
pAd->MeshTab.CPI = pAd->MeshTab.NewCPI;
|
|
}
|
|
else
|
|
pAd->MeshTab.MeshChannel = pAd->CommonCfg.Channel;
|
|
|
|
RTMPSetTimer(&pAd->MeshTab.PldTimer, PLD_TIME);
|
|
|
|
*pCurrState = MESH_CTRL_ACTIVATED;
|
|
}
|
|
|
|
BOOLEAN NeighborMPCheck(
|
|
IN PRTMP_ADAPTER pAd,
|
|
IN PUCHAR pMeshId,
|
|
IN UINT8 PathSelProtocolId,
|
|
IN UINT8 PathSelMetricId)
|
|
{
|
|
BOOLEAN result = FALSE;
|
|
|
|
if ((NdisEqualMemory(pMeshId, pAd->MeshTab.MeshId, pAd->MeshTab.MeshIdLen))
|
|
&& (PathSelProtocolId == pAd->MeshTab.PathProtocolId)
|
|
&& (PathSelMetricId == pAd->MeshTab.PathMetricId))
|
|
result = TRUE;
|
|
|
|
return result;
|
|
}
|
|
|
|
PMESH_NEIGHBOR_ENTRY InsertNeighborMP(
|
|
IN PRTMP_ADAPTER pAd,
|
|
IN CHAR RealRssi,
|
|
IN PUCHAR pPeerMacAddr,
|
|
IN UCHAR Channel,
|
|
IN UINT8 ChBW,
|
|
IN UINT8 ExtChOffset,
|
|
IN PUCHAR pHostName,
|
|
IN PUCHAR pMeshId,
|
|
IN UCHAR MeshIdLen,
|
|
IN USHORT CapabilityInfo,
|
|
IN PUCHAR pVIE,
|
|
IN USHORT LenVIE,
|
|
IN PMESH_CONFIGURAION_IE pMeshConfig)
|
|
{
|
|
INT i;
|
|
ULONG HashIdx;
|
|
PMESH_NEIGHBOR_TAB pNeighborTab = pAd->MeshTab.pMeshNeighborTab;
|
|
PMESH_NEIGHBOR_ENTRY pNeighborEntry = NULL, pNeighborCurrEntry;
|
|
|
|
if(pNeighborTab == NULL)
|
|
{
|
|
DBGPRINT(RT_DEBUG_ERROR, ("pAd->MeshTab.pMeshNeighborTab equal NULL.\n"));
|
|
return NULL;
|
|
}
|
|
|
|
pNeighborEntry = NeighborSearch(pAd, pPeerMacAddr);
|
|
if (pNeighborEntry == NULL)
|
|
{
|
|
/* if FULL, return */
|
|
if (pNeighborTab->NeighborNr >= MAX_NEIGHBOR_MP)
|
|
{
|
|
DBGPRINT(RT_DEBUG_ERROR, ("pAd->MeshTab.pMeshNeighborTab FULL.\n"));
|
|
return NULL;
|
|
}
|
|
|
|
for (i = 0; i < MAX_NEIGHBOR_MP; i++)
|
|
{
|
|
pNeighborEntry = &pAd->MeshTab.pMeshNeighborTab->NeighborMP[i];
|
|
if (pNeighborEntry->Valid == FALSE)
|
|
break;
|
|
}
|
|
|
|
if (i < MAX_NEIGHBOR_MP)
|
|
{
|
|
ULONG Idx;
|
|
|
|
NeighborEntrySet(pNeighborEntry, RealRssi, pPeerMacAddr, (RTMP_STRING *)pHostName, (PCHAR)pMeshId, MeshIdLen,
|
|
Channel, ChBW, ExtChOffset, CapabilityInfo, pVIE, LenVIE, pMeshConfig);
|
|
Idx = GetMeshLinkId(pAd, (PCHAR)pPeerMacAddr);
|
|
if (Idx != BSS_NOT_FOUND)
|
|
{
|
|
pNeighborEntry->State = CANDIDATE_MP;
|
|
pNeighborEntry->MeshLinkIdx = Idx;
|
|
}
|
|
else
|
|
pNeighborEntry->State = NEIGHBOR_MP;
|
|
|
|
pNeighborTab->NeighborNr++;
|
|
}
|
|
else
|
|
{
|
|
pNeighborEntry = NULL;
|
|
DBGPRINT(RT_DEBUG_ERROR, ("%s: Neighbor tab full.\n", __FUNCTION__));
|
|
}
|
|
|
|
/* add this Neighbor entry into HASH table */
|
|
if (pNeighborEntry)
|
|
{
|
|
HashIdx = MESH_MAC_ADDR_HASH_INDEX(pPeerMacAddr);
|
|
if (pNeighborTab->Hash[HashIdx] == NULL)
|
|
{
|
|
pNeighborTab->Hash[HashIdx] = pNeighborEntry;
|
|
}
|
|
else
|
|
{
|
|
pNeighborCurrEntry = pNeighborTab->Hash[HashIdx];
|
|
while (pNeighborCurrEntry->pNext != NULL)
|
|
pNeighborCurrEntry = pNeighborCurrEntry->pNext;
|
|
pNeighborCurrEntry->pNext = pNeighborEntry;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
NeighborEntrySet(pNeighborEntry, RealRssi, pPeerMacAddr, (RTMP_STRING *)pHostName, (PCHAR)pMeshId, MeshIdLen,
|
|
Channel, ChBW, ExtChOffset, CapabilityInfo, pVIE, LenVIE, pMeshConfig);
|
|
}
|
|
|
|
return pNeighborEntry;
|
|
}
|
|
|
|
VOID DeleteNeighborMP(
|
|
IN PRTMP_ADAPTER pAd,
|
|
IN PUCHAR pPeerMacAddr)
|
|
{
|
|
PMESH_NEIGHBOR_TAB pNeighborTab = pAd->MeshTab.pMeshNeighborTab;
|
|
PMESH_NEIGHBOR_ENTRY pNeighborEntry = NULL;
|
|
|
|
if(pNeighborTab == NULL)
|
|
{
|
|
DBGPRINT(RT_DEBUG_ERROR, ("pAd->MeshTab.pMeshNeighborTab equal NULL.\n"));
|
|
return;
|
|
}
|
|
|
|
/* if empty, return */
|
|
if (pNeighborTab->NeighborNr == 0)
|
|
{
|
|
DBGPRINT(RT_DEBUG_ERROR, ("pMeshNeighborTab empty.\n"));
|
|
return;
|
|
}
|
|
|
|
pNeighborEntry = NeighborSearch(pAd, pPeerMacAddr);
|
|
if (pNeighborEntry != NULL)
|
|
{
|
|
PMESH_NEIGHBOR_ENTRY pPrevEntry = NULL;
|
|
ULONG HashIdx = MESH_MAC_ADDR_HASH_INDEX(pNeighborEntry->PeerMac);
|
|
PMESH_NEIGHBOR_ENTRY pProbeEntry = pNeighborTab->Hash[HashIdx];
|
|
|
|
/* update Hash list */
|
|
do
|
|
{
|
|
if (pProbeEntry == pNeighborEntry)
|
|
{
|
|
if (pPrevEntry == NULL)
|
|
{
|
|
pNeighborTab->Hash[HashIdx] = pNeighborEntry->pNext;
|
|
}
|
|
else
|
|
{
|
|
pPrevEntry->pNext = pNeighborEntry->pNext;
|
|
}
|
|
break;
|
|
}
|
|
|
|
pPrevEntry = pProbeEntry;
|
|
pProbeEntry = pProbeEntry->pNext;
|
|
} while (pProbeEntry);
|
|
|
|
NdisZeroMemory(pNeighborEntry, sizeof(MESH_NEIGHBOR_ENTRY));
|
|
pNeighborTab->NeighborNr--;
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
PMESH_NEIGHBOR_ENTRY NeighborSearch(
|
|
IN PRTMP_ADAPTER pAd,
|
|
IN PUCHAR pPeerMacAddr)
|
|
{
|
|
ULONG HashIdx;
|
|
PMESH_NEIGHBOR_ENTRY pNighborEntry = NULL;
|
|
|
|
HashIdx = MESH_MAC_ADDR_HASH_INDEX(pPeerMacAddr);
|
|
pNighborEntry = pAd->MeshTab.pMeshNeighborTab->Hash[HashIdx];
|
|
|
|
while (pNighborEntry)
|
|
{
|
|
if (MAC_ADDR_EQUAL(pNighborEntry->PeerMac, pPeerMacAddr))
|
|
{
|
|
break;
|
|
}
|
|
else
|
|
pNighborEntry = pNighborEntry->pNext;
|
|
}
|
|
|
|
return pNighborEntry;
|
|
}
|
|
|
|
static VOID NeighborEntrySet(
|
|
OUT PMESH_NEIGHBOR_ENTRY pNeighbor,
|
|
IN CHAR RealRssi,
|
|
IN PUCHAR pPeerMacAddr,
|
|
IN RTMP_STRING *pHostName,
|
|
IN PCHAR pMeshId,
|
|
IN UCHAR MeshIdLen,
|
|
IN UCHAR Channel,
|
|
IN UINT8 ChBW,
|
|
IN UINT8 ExtChOffset,
|
|
IN USHORT CapabilityInfo,
|
|
IN PUCHAR pVIE,
|
|
IN USHORT LenVIE,
|
|
IN PMESH_CONFIGURAION_IE pMeshConfig)
|
|
{
|
|
ULONG Now;
|
|
|
|
NdisGetSystemUpTime(&Now);
|
|
|
|
pNeighbor->Valid = TRUE;
|
|
COPY_MAC_ADDR(pNeighbor->PeerMac, pPeerMacAddr);
|
|
|
|
/* record host name. */
|
|
if(strlen(pHostName) > 0 && strlen(pHostName) < MAX_HOST_NAME_LEN)
|
|
strcpy((RTMP_STRING *) pNeighbor->HostName, pHostName);
|
|
else
|
|
strcpy((RTMP_STRING *) pNeighbor->HostName, DEFAULT_MESH_HOST_NAME);
|
|
|
|
/* record mesh id. */
|
|
if (MeshIdLen > 0)
|
|
{
|
|
NdisMoveMemory(pNeighbor->MeshId, pMeshId, MAX_MESH_ID_LEN);
|
|
pNeighbor->MeshIdLen = MeshIdLen;
|
|
}
|
|
|
|
pNeighbor->RealRssi = RealRssi;
|
|
pNeighbor->Channel = Channel;
|
|
pNeighbor->ChBW = ChBW;
|
|
pNeighbor->ExtChOffset = ExtChOffset;
|
|
pNeighbor->CPI = pMeshConfig->CPI;
|
|
pNeighbor->PathProtocolId = pMeshConfig->PathSelProtocolId;
|
|
pNeighbor->PathMetricId = pMeshConfig->PathSelMetricId;
|
|
pNeighbor->MeshCapability = pMeshConfig->MeshCapability;
|
|
pNeighbor->Version = pMeshConfig->Version;
|
|
|
|
pNeighbor->IdleCnt = 0;
|
|
pNeighbor->LastBeaconTime = Now;
|
|
|
|
/*pNeighbor->MeshEncrypType = MeshCipher; */
|
|
pNeighbor->CapabilityInfo = CapabilityInfo;
|
|
|
|
if (LenVIE > 0)
|
|
{
|
|
NdisMoveMemory(pNeighbor->RSNIE, pVIE, LenVIE);
|
|
pNeighbor->RSNIE_Len = LenVIE;
|
|
}
|
|
else
|
|
{
|
|
pNeighbor->RSNIE_Len = 0;
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
static PMESH_NEIGHBOR_ENTRY NeighMPWithMaxCPI(
|
|
IN PRTMP_ADAPTER pAd,
|
|
IN PMESH_NEIGHBOR_TAB pNeighborTab)
|
|
{
|
|
INT i;
|
|
UINT32 MaxCPI = 0;
|
|
PMESH_NEIGHBOR_ENTRY pMaxCpiEntry = NULL;
|
|
PMESH_NEIGHBOR_ENTRY pNeighborEntry = NULL;
|
|
|
|
for (i = 0; i < MAX_NEIGHBOR_MP; i++)
|
|
{
|
|
pNeighborEntry = &pAd->MeshTab.pMeshNeighborTab->NeighborMP[i];
|
|
if (pNeighborEntry->Valid == FALSE)
|
|
continue;
|
|
|
|
if (!NeighborMPCheck(pAd, pNeighborEntry->MeshId,
|
|
(UINT8)pNeighborEntry->PathProtocolId,
|
|
(UINT8)pNeighborEntry->PathMetricId))
|
|
continue;
|
|
|
|
if (MaxCPI < pNeighborEntry->CPI)
|
|
{
|
|
MaxCPI = pNeighborEntry->CPI;
|
|
pMaxCpiEntry = pNeighborEntry;
|
|
}
|
|
}
|
|
|
|
return pMaxCpiEntry;
|
|
}
|
|
|
|
VOID NeighborTableUpdate(
|
|
IN PRTMP_ADAPTER pAd)
|
|
{
|
|
#ifdef RELEASE_EXCLUDE
|
|
/* 1. Update IdleCnt. */
|
|
/* 2. Maintain Tab. remove dead Neighbor MPs. */
|
|
#endif /* RELEASE_EXCLUDE */
|
|
|
|
INT i;
|
|
PMESH_NEIGHBOR_TAB pNeighborTab = pAd->MeshTab.pMeshNeighborTab;
|
|
PMESH_NEIGHBOR_ENTRY pNeighborEntry = NULL;
|
|
ULONG Now;
|
|
|
|
if(pNeighborTab == NULL)
|
|
{
|
|
DBGPRINT(RT_DEBUG_ERROR, ("pAd->MeshTab.pMeshNeighborTab equal NULL.\n"));
|
|
return;
|
|
}
|
|
|
|
for (i = 0; i < MAX_NEIGHBOR_MP; i++)
|
|
{
|
|
pNeighborEntry = &pAd->MeshTab.pMeshNeighborTab->NeighborMP[i];
|
|
if (pNeighborEntry->Valid == FALSE)
|
|
continue;
|
|
|
|
NdisGetSystemUpTime(&Now);
|
|
/*if ((++pNeighborEntry->IdleCnt > NEIGHBOR_MP_IDLE_CNT)) */
|
|
if(RTMP_TIME_AFTER(Now, pNeighborEntry->LastBeaconTime + (MESH_NEIGHBOR_BEACON_IDLE_TIME * OS_HZ / 1000) ))
|
|
{
|
|
if (MeshValid(&pAd->MeshTab)
|
|
&& (pNeighborEntry->State == CANDIDATE_MP)
|
|
&& (PeerLinkValidCheck(pAd, pNeighborEntry->MeshLinkIdx) == TRUE))
|
|
{
|
|
MlmeEnqueue(pAd, MESH_LINK_MNG_STATE_MACHINE, MESH_LINK_MNG_CNCL, 0, NULL, pNeighborEntry->MeshLinkIdx);
|
|
}
|
|
#ifdef RELEASE_EXCLUDE
|
|
/* some neighbor may not the channel as current Mesh network's. */
|
|
/* so don't update such neighbors. */
|
|
#endif /* RELEASE_EXCLUDE */
|
|
if ( (pAd->MeshTab.UCGEnable && pNeighborEntry->Channel == pAd->MeshTab.MeshChannel)
|
|
|| !pAd->MeshTab.UCGEnable)
|
|
DeleteNeighborMP(pAd, pNeighborEntry->PeerMac);
|
|
}
|
|
else
|
|
{
|
|
if (VALID_MESH_LINK_ID(pNeighborEntry->MeshLinkIdx))
|
|
{
|
|
if ((pNeighborEntry->State == LINK_AVAILABLE)
|
|
&& (pNeighborEntry->ExtChOffset != pAd->MeshTab.MeshLink[pNeighborEntry->MeshLinkIdx].Entry.ExtChOffset))
|
|
{
|
|
DBGPRINT(RT_DEBUG_TRACE, ("Link%d:Neighbor ExtChOffset change from %d to %d , kill the link!\n"
|
|
,pNeighborEntry->MeshLinkIdx
|
|
,pNeighborEntry->ExtChOffset,pAd->MeshTab.MeshLink[pNeighborEntry->MeshLinkIdx].Entry.ExtChOffset));
|
|
MlmeEnqueue(pAd, MESH_LINK_MNG_STATE_MACHINE, MESH_LINK_MNG_CNCL, 0, NULL, pNeighborEntry->MeshLinkIdx);
|
|
RTMP_MLME_HANDLER(pAd);
|
|
}
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
VOID CandidateMPSelect(
|
|
IN PRTMP_ADAPTER pAd)
|
|
{
|
|
#ifdef RELEASE_EXCLUDE
|
|
/* 1. find max CPI. */
|
|
/* 2. select candidate MP. */
|
|
#endif /* RELEASE_EXCLUDE */
|
|
|
|
INT i;
|
|
PMESH_NEIGHBOR_TAB pNeighborTab = pAd->MeshTab.pMeshNeighborTab;
|
|
PMESH_NEIGHBOR_ENTRY pNeighborEntry = NULL;
|
|
|
|
if(pNeighborTab == NULL)
|
|
{
|
|
DBGPRINT(RT_DEBUG_ERROR, ("pAd->MeshTab.pMeshNeighborTab equal NULL.\n"));
|
|
return;
|
|
}
|
|
|
|
if ((pAd->MeshTab.CPI == 0)
|
|
&& (pNeighborTab->NeighborNr == 0))
|
|
{
|
|
#ifdef RELEASE_EXCLUDE
|
|
/* have no avaiable Neighbor MP. */
|
|
/* 1. Random Generate a CPI value. */
|
|
/* 2. Add those IEs in Beacon. */
|
|
#endif /* RELEASE_EXCLUDE */
|
|
pAd->MeshTab.CPI = RandomMeshCPI(pAd);
|
|
}
|
|
else
|
|
{
|
|
#ifdef RELEASE_EXCLUDE
|
|
/* 1. find the channel of Neighbor MP which had Max CPI value. */
|
|
/* 2. switch to the channel. */
|
|
/* 3. insert Mesh-IEs into Beacon. */
|
|
/* 4. select candidate MPs. */
|
|
#endif /* RELEASE_EXCLUDE */
|
|
|
|
pNeighborEntry = NeighMPWithMaxCPI(pAd, pNeighborTab);
|
|
if ((pNeighborEntry != NULL)
|
|
&& (pAd->MeshTab.CPI < pNeighborEntry->CPI))
|
|
{
|
|
if (pAd->CommonCfg.Channel != pNeighborEntry->Channel)
|
|
{
|
|
pAd->MeshTab.CPI = pNeighborEntry->CPI;
|
|
/* start UCG Procedural. */
|
|
}
|
|
}
|
|
|
|
if (pAd->MeshTab.MeshAutoLink == FALSE)
|
|
return;
|
|
|
|
for (i = 0; i < pNeighborTab->NeighborNr; i++)
|
|
{
|
|
pNeighborEntry = &pNeighborTab->NeighborMP[i];
|
|
|
|
if (!NeighborMPCheck(pAd, pNeighborEntry->MeshId,
|
|
(UINT8)pNeighborEntry->PathProtocolId,
|
|
(UINT8)pNeighborEntry->PathMetricId))
|
|
continue;
|
|
|
|
DBGPRINT(RT_DEBUG_TRACE, ("(%d) CPI=%d Apl=%d channel=%d state=%d\n", i, pNeighborEntry->CPI,
|
|
pNeighborEntry->MeshCapability.field.AcceptPeerLinks, pNeighborEntry->Channel, pNeighborEntry->State));
|
|
|
|
DBGPRINT(RT_DEBUG_TRACE, ("%d %d %d %d %d\n",
|
|
(GetMeshSecurity(pAd)==MeshCheckPeerMpCipher(pNeighborEntry->CapabilityInfo, pNeighborEntry->RSNIE, pNeighborEntry->RSNIE_Len)),
|
|
(pNeighborEntry->MeshCapability.field.AcceptPeerLinks),
|
|
(pNeighborEntry->State == NEIGHBOR_MP), MeshChCheck(pAd, pNeighborEntry),
|
|
((pAd->MeshTab.CPI <= pNeighborEntry->CPI)
|
|
||((pAd->MeshTab.CPI == pNeighborEntry->CPI)
|
|
&& (memcmp(pNeighborEntry->PeerMac, pAd->MeshTab.wdev.if_addr, MAC_ADDR_LEN) < 0)))));
|
|
|
|
if ((GetMeshSecurity(pAd)==MeshCheckPeerMpCipher(pNeighborEntry->CapabilityInfo, pNeighborEntry->RSNIE, pNeighborEntry->RSNIE_Len))
|
|
&& (pNeighborEntry->MeshCapability.field.AcceptPeerLinks)
|
|
&& (pNeighborEntry->State == NEIGHBOR_MP)
|
|
&& MeshChCheck(pAd, pNeighborEntry)
|
|
&& ((pAd->MeshTab.CPI <= pNeighborEntry->CPI)
|
|
||((pAd->MeshTab.CPI == pNeighborEntry->CPI)
|
|
&& (memcmp(pNeighborEntry->PeerMac, pAd->MeshTab.wdev.if_addr, MAC_ADDR_LEN) < 0)))
|
|
)
|
|
{
|
|
ULONG LinkIdx = MeshLinkAlloc(pAd, pNeighborEntry->PeerMac, MESH_LINK_DYNAMIC);
|
|
|
|
DBGPRINT(RT_DEBUG_TRACE, ("(%d) pick LinkId=%ld\n", i, LinkIdx));
|
|
|
|
if (VALID_MESH_LINK_ID(LinkIdx))
|
|
{
|
|
pAd->MeshTab.CPI = pNeighborEntry->CPI;
|
|
pNeighborEntry->State = CANDIDATE_MP;
|
|
pNeighborEntry->MeshLinkIdx = LinkIdx;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
void NeighborTableReset(
|
|
IN PRTMP_ADAPTER pAd)
|
|
{
|
|
if (pAd->MeshTab.pMeshNeighborTab)
|
|
NdisZeroMemory(pAd->MeshTab.pMeshNeighborTab, sizeof(MESH_NEIGHBOR_TAB));
|
|
else
|
|
DBGPRINT(RT_DEBUG_ERROR, ("pAd->MeshTab.pMeshNeighborTab equal NULL.\n"));
|
|
|
|
return;
|
|
}
|
|
|
|
void NeighborTableInit(
|
|
IN PRTMP_ADAPTER pAd)
|
|
{
|
|
os_alloc_mem(pAd, (UCHAR **)&(pAd->MeshTab.pMeshNeighborTab), sizeof(MESH_NEIGHBOR_TAB));
|
|
if (pAd->MeshTab.pMeshNeighborTab)
|
|
NdisZeroMemory(pAd->MeshTab.pMeshNeighborTab, sizeof(MESH_NEIGHBOR_TAB));
|
|
else
|
|
DBGPRINT(RT_DEBUG_ERROR, ("%s Fail to alloc memory for pAd->MeshTab.pMeshNeighborTab", __FUNCTION__));
|
|
|
|
return;
|
|
}
|
|
|
|
void NeighborTableDestroy(
|
|
IN PRTMP_ADAPTER pAd)
|
|
{
|
|
if (pAd->MeshTab.pMeshNeighborTab)
|
|
os_free_mem(NULL, pAd->MeshTab.pMeshNeighborTab);
|
|
pAd->MeshTab.pMeshNeighborTab = NULL;
|
|
|
|
return;
|
|
}
|
|
|
|
VOID MeshChSwAnnounceProcess(
|
|
IN PRTMP_ADAPTER pAd,
|
|
IN RX_BLK *pRxBlk)
|
|
{
|
|
PHEADER_802_11 pHeader = (PHEADER_802_11)pRxBlk->pHeader;
|
|
MESH_CH_SW_ANN_MSG_STRUCT PeerChSwAnn;
|
|
PUCHAR pDA;
|
|
PUCHAR pSA;
|
|
UINT32 MeshSeq;
|
|
UINT8 MeshTTL;
|
|
PUCHAR pFrame;
|
|
ULONG FrameLen;
|
|
UINT MeshHdrLen;
|
|
ULONG LinkIdx;
|
|
UINT8 ChSwMode;
|
|
UINT8 NewCh;
|
|
UINT32 NewCPI;
|
|
UINT8 ChSwCnt;
|
|
UCHAR MeshSA[MAC_ADDR_LEN];
|
|
|
|
DBGPRINT(RT_DEBUG_TRACE, ("-----> %s\n", __FUNCTION__));
|
|
|
|
if ((LinkIdx = GetMeshLinkId(pAd, (PCHAR)pHeader->Addr2)) == BSS_NOT_FOUND)
|
|
return;
|
|
|
|
if (!PeerLinkValidCheck(pAd, LinkIdx))
|
|
return;
|
|
|
|
MeshSeq = GetMeshSeq(pRxBlk->pData);
|
|
MeshTTL = GetMeshTTL(pRxBlk->pData);
|
|
pDA = pHeader->Addr1;
|
|
pSA = GetMeshAddr4(pRxBlk->pData);
|
|
if (pSA == NULL)
|
|
pSA = pHeader->Addr2;
|
|
MeshHdrLen = GetMeshHederLen(pRxBlk->pData);
|
|
|
|
/* skip Mesh Header */
|
|
pRxBlk->pData += MeshHdrLen;
|
|
pRxBlk->DataSize -= MeshHdrLen;
|
|
|
|
/* skip Category and ActionCode */
|
|
pFrame = (PUCHAR)(pRxBlk->pData + 2);
|
|
FrameLen = pRxBlk->DataSize - 2;
|
|
|
|
if (PktSigCheck(pAd, pHeader->Addr2, pHeader->Addr1, pSA, MeshSeq, FC_TYPE_MGMT) == FALSE)
|
|
return;
|
|
|
|
MeshChannelSwitchAnnouncementSanity( pAd,
|
|
pFrame,
|
|
FrameLen,
|
|
&ChSwMode,
|
|
&NewCh,
|
|
&NewCPI,
|
|
&ChSwCnt,
|
|
MeshSA);
|
|
|
|
PeerChSwAnn.ChSwMode = ChSwMode;
|
|
PeerChSwAnn.NewCh = NewCh;
|
|
PeerChSwAnn.NewCPI = NewCPI;
|
|
PeerChSwAnn.ChSwCnt = ChSwCnt;
|
|
PeerChSwAnn.LinkId = LinkIdx;
|
|
PeerChSwAnn.MeshSeq = MeshSeq;
|
|
PeerChSwAnn.MeshTTL = MeshTTL;
|
|
COPY_MAC_ADDR(PeerChSwAnn.MeshSA, MeshSA);
|
|
|
|
MlmeEnqueue(pAd, MESH_CTRL_STATE_MACHINE, MESH_PEER_UCG_EVT, sizeof(MESH_CH_SW_ANN_MSG_STRUCT), &PeerChSwAnn, 0);
|
|
DBGPRINT(RT_DEBUG_TRACE, ("<----- %s\n", __FUNCTION__));
|
|
}
|
|
|
|
static VOID EnqueChSwAnnouncement(
|
|
IN PRTMP_ADAPTER pAd,
|
|
IN PUCHAR PeerMac,
|
|
IN UINT8 MeshTTL,
|
|
IN UINT32 MeshSeq,
|
|
IN UINT8 ChSwMode,
|
|
IN UCHAR NewCh,
|
|
IN UINT32 NewCPI,
|
|
IN UINT8 ChSwCnt,
|
|
IN PUCHAR pMeshSa)
|
|
{
|
|
HEADER_802_11 MeshHdr;
|
|
PUCHAR pOutBuffer = NULL;
|
|
NDIS_STATUS NStatus;
|
|
ULONG FrameLen;
|
|
MESH_FLAG MeshFlag;
|
|
|
|
NStatus = MlmeAllocateMemory(pAd, (PVOID)&pOutBuffer); /*Get an unused nonpaged memory */
|
|
if(NStatus != NDIS_STATUS_SUCCESS)
|
|
{
|
|
DBGPRINT(RT_DEBUG_TRACE, ("%s() allocate memory failed \n", __FUNCTION__));
|
|
return;
|
|
}
|
|
|
|
MeshHeaderInit(pAd, &MeshHdr,
|
|
PeerMac, /* addr1 */
|
|
pAd->MeshTab.wdev.if_addr, /* addr2 */
|
|
ZERO_MAC_ADDR); /* addr3 */
|
|
NdisMoveMemory(pOutBuffer, (PCHAR)&MeshHdr, sizeof(HEADER_802_11));
|
|
FrameLen = sizeof(HEADER_802_11);
|
|
|
|
/* Mesh Header */
|
|
MeshFlag.word = 0;
|
|
MeshFlag.field.AE = 0; /* Peer-Link manager frame never carry 6 addresses. */
|
|
InsertMeshHeader(pAd, (pOutBuffer + FrameLen), &FrameLen, MeshFlag.word,
|
|
MeshTTL, MeshSeq, NULL, NULL, NULL);
|
|
|
|
/* Action field */
|
|
InsertMeshActField(pAd, (pOutBuffer + FrameLen), &FrameLen, CATEGORY_MESH_RES_COORDINATION, RESOURCE_CHANNEL_SWITCH_ANNOUNCEMENT);
|
|
|
|
/* Channel Switch Announcement IE. */
|
|
InsertMeshChSwAnnIE(pAd, (pOutBuffer + FrameLen), &FrameLen, ChSwMode, NewCh, NewCPI, ChSwCnt, pMeshSa);
|
|
|
|
MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer, FrameLen);
|
|
MlmeFreeMemory(pAd, pOutBuffer);
|
|
|
|
return;
|
|
}
|
|
|
|
/*
|
|
========================================================================
|
|
|
|
Routine Description:
|
|
Prior to beginning the MSA authentication mechanism, the MP
|
|
determines if it is the Selector MP for the duration of the protocol.
|
|
The MP is the Selector MP if its MAC address is numerically larger
|
|
than that of the candidate peer MP.
|
|
|
|
This routine shall determine if the local MP is Selector MP
|
|
|
|
Arguments:
|
|
|
|
Return Value:
|
|
|
|
Note:
|
|
refer to 802.11s-D1.06 11A.4.2.2
|
|
|
|
========================================================================
|
|
*/
|
|
void ValidateLocalMPAsSelector(
|
|
IN PRTMP_ADAPTER pAd,
|
|
IN INT idx)
|
|
{
|
|
UCHAR i = 0;
|
|
|
|
/* clear this flag */
|
|
pAd->MeshTab.MeshLink[idx].Entry.bValidLocalMpAsSelector = FALSE;
|
|
|
|
#ifdef RELEASE_EXCLUDE
|
|
/* Prior to beginning the MSA authentication mechanism, the MP determines if it is the Selector MP for the */
|
|
/* duration of the protocol. The MP is the Selector MP if its MAC address is numerically larger than that of the */
|
|
/* candidate peer MP. */
|
|
#endif /* RELEASE_EXCLUDE */
|
|
while(i < MAC_ADDR_LEN)
|
|
{
|
|
if (pAd->MeshTab.wdev.if_addr[i] != pAd->MeshTab.MeshLink[idx].Entry.PeerMacAddr[i])
|
|
{
|
|
if (pAd->MeshTab.wdev.if_addr[i] > pAd->MeshTab.MeshLink[idx].Entry.PeerMacAddr[i])
|
|
{
|
|
pAd->MeshTab.MeshLink[idx].Entry.bValidLocalMpAsSelector = TRUE;
|
|
DBGPRINT(RT_DEBUG_TRACE, ("The local MP is the Selector MP"));
|
|
}
|
|
else
|
|
{
|
|
pAd->MeshTab.MeshLink[idx].Entry.bValidLocalMpAsSelector = FALSE;
|
|
DBGPRINT(RT_DEBUG_TRACE, ("The local MP is NOT the Selector MP"));
|
|
}
|
|
|
|
/* Initial MSAIE */
|
|
LocalMsaIeInit(pAd, idx);
|
|
|
|
return;
|
|
}
|
|
i++;
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
/*
|
|
========================================================================
|
|
|
|
Routine Description:
|
|
The MP shall perform the 802.1X role selection procedure based on
|
|
the contents of the received peer link open frame and its own
|
|
configuration.
|
|
|
|
This routine shall determine if the local MP is Authenticator MP
|
|
|
|
Arguments:
|
|
|
|
Return Value:
|
|
|
|
Note:
|
|
refer to 802.11s-D1.06 11A.4.2.2.2
|
|
|
|
========================================================================
|
|
*/
|
|
void ValidateLocalMPAsAuthenticator(
|
|
IN PRTMP_ADAPTER pAd,
|
|
IN UCHAR idx,
|
|
IN PUCHAR pMscIe,
|
|
IN PUCHAR pMsaIe)
|
|
{
|
|
UCHAR offset = 0;
|
|
PMESH_LINK_ENTRY pMeshLinkEntry;
|
|
PMESH_SECURITY_CAPABILITY_IE pPeerMSCIE;
|
|
PMSA_HANDSHAKE_IE pPeerMSAIE;
|
|
|
|
pMeshLinkEntry = &pAd->MeshTab.MeshLink[idx].Entry;
|
|
pPeerMSCIE = (PMESH_SECURITY_CAPABILITY_IE)pMscIe;
|
|
pPeerMSAIE = (PMSA_HANDSHAKE_IE)pMsaIe;
|
|
|
|
/* clear this flag */
|
|
pMeshLinkEntry->bValidLocalMpAsAuthenticator = FALSE;
|
|
|
|
#ifdef RELEASE_EXCLUDE
|
|
/* If neither MP has the "Connected to MKD" bit set to 1, */
|
|
/* then the 802.1X Authenticator is the Selector MP. */
|
|
#endif /* RELEASE_EXCLUDE */
|
|
if (pPeerMSCIE->MeshSecurityConfig.field.ConnectedToMKD == 0 &&
|
|
pAd->MeshTab.LocalMSCIE.MeshSecurityConfig.field.ConnectedToMKD == 0)
|
|
{
|
|
if (pMeshLinkEntry->bValidLocalMpAsSelector)
|
|
pMeshLinkEntry->bValidLocalMpAsAuthenticator = TRUE;
|
|
}
|
|
/*If both MPs have "Connected to MKD" bit set to 1, then: */
|
|
else if (pPeerMSCIE->MeshSecurityConfig.field.ConnectedToMKD == 1 &&
|
|
pAd->MeshTab.LocalMSCIE.MeshSecurityConfig.field.ConnectedToMKD == 1)
|
|
{
|
|
#ifdef RELEASE_EXCLUDE
|
|
/* If both MPs request authentication during this handshake or */
|
|
/* If neither MP requests authentication during this handshake, */
|
|
/* then the 802.1X Authenticator is the Selector MP. */
|
|
#endif /* RELEASE_EXCLUDE */
|
|
if ((pPeerMSAIE->MeshHSControl.field.RequestAuth == 1 && pAd->MeshTab.bInitialMsaDone) ||
|
|
(pPeerMSAIE->MeshHSControl.field.RequestAuth == 0 && !pAd->MeshTab.bInitialMsaDone))
|
|
{
|
|
if (pMeshLinkEntry->bValidLocalMpAsSelector)
|
|
pMeshLinkEntry->bValidLocalMpAsAuthenticator = TRUE;
|
|
}
|
|
#ifdef RELEASE_EXCLUDE
|
|
/* Otherwise, the MP that requests authentication is the 802.1X Supplicant, */
|
|
/* and the other MP is the 802.1X Authenticator */
|
|
#endif /* RELEASE_EXCLUDE */
|
|
else
|
|
{
|
|
if (!pAd->MeshTab.bInitialMsaDone)
|
|
pMeshLinkEntry->bValidLocalMpAsAuthenticator = TRUE;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
#ifdef RELEASE_EXCLUDE
|
|
/* If only one MP has the "Connected to MKD" bit set to 1, */
|
|
/* then that MP is the 802.1X Authenticator. */
|
|
#endif /* RELEASE_EXCLUDE */
|
|
if (pAd->MeshTab.LocalMSCIE.MeshSecurityConfig.field.ConnectedToMKD == 1)
|
|
pMeshLinkEntry->bValidLocalMpAsAuthenticator = TRUE;
|
|
}
|
|
|
|
offset += sizeof(MESH_HANDSHAKE_CONTROL);
|
|
|
|
/* Once the Authenticator MP is decided, fill in MA-ID of MSAIE for local MP */
|
|
if (pMeshLinkEntry->bValidLocalMpAsAuthenticator)
|
|
NdisMoveMemory(&pMeshLinkEntry->LocalMsaIe[offset], pAd->MeshTab.wdev.if_addr, MAC_ADDR_LEN);
|
|
else
|
|
NdisMoveMemory(&pMeshLinkEntry->LocalMsaIe[offset], pMeshLinkEntry->PeerMacAddr, MAC_ADDR_LEN);
|
|
|
|
return;
|
|
}
|
|
|
|
#ifdef RELEASE_EXCLUDE
|
|
/*
|
|
The local MP shall perform the key selection procedure based on the contents of the peer link open frame.
|
|
The result of the procedure determines if a PMK-MA is available to be used to secure the link, or if Initial
|
|
MSA Authentication must occur.
|
|
|
|
*/
|
|
#endif /* RELEASE_EXCLUDE */
|
|
|
|
BOOLEAN MeshKeySelectionAction(
|
|
IN PRTMP_ADAPTER pAd,
|
|
IN PMESH_LINK_ENTRY pMeshLinkEntry,
|
|
IN PUCHAR pMscIe,
|
|
IN PUCHAR pPmkId,
|
|
IN UCHAR PmkIdLen)
|
|
{
|
|
PMESH_SECURITY_CAPABILITY_IE pPeerMSCIE;
|
|
BOOLEAN bValidLocalKey = FALSE;
|
|
BOOLEAN bCachedPeerKey = FALSE;
|
|
|
|
if (pAd->MeshTab.EasyMeshSecurity)
|
|
{
|
|
pMeshLinkEntry->MeshKeySelection = MESH_KEY_NONE;
|
|
return TRUE;
|
|
}
|
|
|
|
pPeerMSCIE = (PMESH_SECURITY_CAPABILITY_IE)pMscIe;
|
|
|
|
/* The key selection procedure first determines */
|
|
/* if Initial MSA Authentication shall occur. */
|
|
if (PmkIdLen == 0 ||
|
|
pAd->MeshTab.bInitialMsaDone == FALSE ||
|
|
pAd->MeshTab.PMKID_Len == 0 ||
|
|
!NdisEqualMemory(pPeerMSCIE->MKDDID, pAd->MeshTab.LocalMSCIE.MKDDID, MAC_ADDR_LEN))
|
|
{
|
|
pMeshLinkEntry->MeshKeySelection = MESH_KEY_NONE;
|
|
return TRUE;
|
|
}
|
|
|
|
#ifdef RELEASE_EXCLUDE
|
|
/* Check Valid-local-key */
|
|
/* The table input Valid-local-key is set to true if PMK-MAName(receiver), contained in the PMKID list field */
|
|
/* in the RSNIE of the received peer link open frame, identifies the PMK-MA belonging to the local MP's key */
|
|
/* hierarchy that is currently valid for securing the link with the peer MP; otherwise, and when there is only */
|
|
/* one PMK-MAName entry, it is false. */
|
|
#endif /* RELEASE_EXCLUDE */
|
|
if (PmkIdLen == MESH_MAX_PMKID_LEN)
|
|
{
|
|
if (NdisEqualMemory(pMeshLinkEntry->PMK_MA_NAME, pPmkId + LEN_PMKID, MESH_PMK_NAME_LEN))
|
|
bValidLocalKey = TRUE;
|
|
}
|
|
|
|
#ifdef RELEASE_EXCLUDE
|
|
/* Check Cached-peer-key */
|
|
/* The table input Cached-peer-key is set to true if the key named by PMK-MAName(sender), contained in the */
|
|
/* PMKID list field in the RSNIE of the received peer link open frame, is cached by the MA function of the */
|
|
/* local MP and is currently valid for securing the link. Otherwise, it is false. */
|
|
#endif /* RELEASE_EXCLUDE */
|
|
if (PmkIdLen >= LEN_PMKID && pAd->MeshTab.bKeyholderDone)
|
|
{
|
|
if (NdisEqualMemory(pMeshLinkEntry->PMK_MA_NAME, pPmkId, MESH_PMK_NAME_LEN))
|
|
bCachedPeerKey = TRUE;
|
|
}
|
|
|
|
/* The key selection procedure, it refers to IEEE 802.11s/D1.06 Table-s46 */
|
|
if (bValidLocalKey == FALSE && bCachedPeerKey == FALSE)
|
|
{
|
|
/* No PMK-MA available and no connection to MKD available, it shall close this link */
|
|
if (pPeerMSCIE->MeshSecurityConfig.field.ConnectedToMKD == 0 &&
|
|
pAd->MeshTab.LocalMSCIE.MeshSecurityConfig.field.ConnectedToMKD == 0)
|
|
{
|
|
return FALSE;
|
|
}
|
|
/* Local MP connected to MKD, but peer MP not */
|
|
else if (pPeerMSCIE->MeshSecurityConfig.field.ConnectedToMKD == 0 &&
|
|
pAd->MeshTab.LocalMSCIE.MeshSecurityConfig.field.ConnectedToMKD == 1)
|
|
{
|
|
pMeshLinkEntry->MeshKeySelection = MESH_KEY_PMKMA_PEER;
|
|
}
|
|
/* Peer MP connected to MKD, but local MP not */
|
|
else if (pPeerMSCIE->MeshSecurityConfig.field.ConnectedToMKD == 1 &&
|
|
pAd->MeshTab.LocalMSCIE.MeshSecurityConfig.field.ConnectedToMKD == 0)
|
|
{
|
|
pMeshLinkEntry->MeshKeySelection = MESH_KEY_PMKMA_LOCAL;
|
|
}
|
|
/* Peer and local MP both connected to MKD */
|
|
else
|
|
{
|
|
if (pMeshLinkEntry->bValidLocalMpAsSelector)
|
|
pMeshLinkEntry->MeshKeySelection = MESH_KEY_PMKMA_PEER;
|
|
else
|
|
pMeshLinkEntry->MeshKeySelection = MESH_KEY_PMKMA_LOCAL;
|
|
}
|
|
|
|
}
|
|
else if (bValidLocalKey == FALSE && bCachedPeerKey == TRUE)
|
|
{
|
|
pMeshLinkEntry->MeshKeySelection = MESH_KEY_PMKMA_PEER;
|
|
}
|
|
else if (bValidLocalKey == TRUE && bCachedPeerKey == FALSE)
|
|
{
|
|
pMeshLinkEntry->MeshKeySelection = MESH_KEY_PMKMA_LOCAL;
|
|
}
|
|
else
|
|
{
|
|
if (pMeshLinkEntry->bValidLocalMpAsSelector)
|
|
pMeshLinkEntry->MeshKeySelection = MESH_KEY_PMKMA_PEER;
|
|
else
|
|
pMeshLinkEntry->MeshKeySelection = MESH_KEY_PMKMA_LOCAL;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
#endif /* MESH_SUPPORT */
|
|
|