📄 soft_ap.c
字号:
if (bFindIt == TRUE)
break;
};
}
else
{
for (ch=0; ch<pAd->ChannelListNum; ch++)
{
AsicSwitchChannel(pAd, pAd->ChannelList[ch].Channel);
AsicLockChannel(pAd, pAd->ChannelList[ch].Channel);
pAd->Counters8023.GoodReceives = 0;
pAd->Counters8023.RxErrors = 0;
pAd->PortCfg.AutoChannel_MaxRssi = 0;
pAd->PortCfg.AutoChannel_Channel = pAd->ChannelList[ch].Channel;
max_rssi[ch]=0;
RTMPusecDelay(200000); // 0.2 sec at each channel
max_rssi[ch] = pAd->PortCfg.AutoChannel_MaxRssi;
RTMP_IO_READ32(pAd, STA_CSR1, &FalseCca);
FalseCca = FalseCca >> 16;
RTMP_IO_READ32(pAd, STA_CSR0, &FcsError);
FcsError &= 0x0000ffff;
if (max_rssi[ch])
{
dirtyness[ch] += 10;
}
DBGPRINT(RT_DEBUG_TRACE,"Sleep at ch#%d to collect RX=%d, RSSI=%d, CRC error=%d, False CCA=%d\n",
pAd->ChannelList[ch].Channel, pAd->Counters8023.GoodReceives, max_rssi[ch] - pAd->BbpRssiToDbmDelta, FcsError, FalseCca);
}
pAd->PortCfg.AutoChannel_Channel = 0;
DBGPRINT(RT_DEBUG_TRACE,"Dirtyness = %d.%d.%d.%d - %d.%d.%d.%d - %d.%d.%d.%d - %d.%d\n",
dirtyness[0], dirtyness[1], dirtyness[2], dirtyness[3], dirtyness[4], dirtyness[5], dirtyness[6],
dirtyness[7], dirtyness[8], dirtyness[9], dirtyness[10], dirtyness[11], dirtyness[12], dirtyness[13]);
// RULE 1. pick up a good channel that no one used
for (ch=0; ch<pAd->ChannelListNum; ch++)
{
if (dirtyness[ch] == 0) break;
}
if (ch < pAd->ChannelListNum)
{
DBGPRINT(RT_DEBUG_TRACE,"1.APAutoSelectChannel pick up ch#%d\n",pAd->ChannelList[ch].Channel);
return pAd->ChannelList[ch].Channel;
}
// RULE 2. if not available, pick up the channel with minimum RSSI
{
UCHAR min_rssi = 255, final_channel = 0;
for (ch = 0; ch < pAd->ChannelListNum; ch++)
{
if (max_rssi[ch] < min_rssi)
{
final_channel = ch;
min_rssi = max_rssi[ch];
}
}
if (final_channel < pAd->ChannelListNum)
{
DBGPRINT(RT_DEBUG_TRACE,"2.APAutoSelectChannel pick up ch#%d\n",pAd->ChannelList[final_channel].Channel);
return pAd->ChannelList[final_channel].Channel;
}
}
// RULE 3. still not available, pick up the first channel
ch = FirstChannel(pAd);
DBGPRINT(RT_DEBUG_TRACE,"3.APAutoSelectChannel pick up ch#%d\n",ch);
}
DBGPRINT(RT_DEBUG_TRACE,"APAutoSelectChannel pick up ch#%d\n",ch);
return ch;
}
else
{
for (ch=14; ch>=1; ch--)
{
AsicSwitchChannel(pAd, ch);
AsicLockChannel(pAd, ch);
pAd->Counters8023.GoodReceives = 0;
pAd->Counters8023.RxErrors = 0;
pAd->PortCfg.AutoChannel_MaxRssi = 0;
pAd->PortCfg.AutoChannel_Channel = ch;
max_rssi[ch]=0;
RTMPusecDelay(500000); // 0.5 sec at each channel
max_rssi[ch] = pAd->PortCfg.AutoChannel_MaxRssi;
RTMP_IO_READ32(pAd, STA_CSR1, &FalseCca);
FalseCca = FalseCca >> 16;
RTMP_IO_READ32(pAd, STA_CSR0, &FcsError);
FcsError &= 0x0000ffff;
if (max_rssi[ch])
{
dirtyness[ch] += 10;
if (ch > 1) dirtyness[ch-1] += 1;
if (ch > 2) dirtyness[ch-2] += 1;
if (ch > 3) dirtyness[ch-3] += 1;
if (ch > 4) dirtyness[ch-4] += 1;
if (ch < 14) dirtyness[ch+1] += 1;
if (ch < 13) dirtyness[ch+2] += 1;
if (ch < 12) dirtyness[ch+3] += 1;
if (ch < 11) dirtyness[ch+4] += 1;
}
DBGPRINT(RT_DEBUG_TRACE,"Sleep at ch#%d to collect RX=%d, RSSI=%d, CRC error=%d, False CCA=%d\n",
ch, pAd->Counters8023.GoodReceives, max_rssi[ch] - pAd->BbpRssiToDbmDelta, FcsError, FalseCca);
}
pAd->PortCfg.AutoChannel_Channel = 0;
DBGPRINT(RT_DEBUG_TRACE,"Dirtyness = %d.%d.%d.%d - %d.%d.%d.%d - %d.%d.%d.%d - %d.%d\n",
dirtyness[1], dirtyness[2], dirtyness[3], dirtyness[4], dirtyness[5], dirtyness[6], dirtyness[7],
dirtyness[8], dirtyness[9], dirtyness[10], dirtyness[11], dirtyness[12], dirtyness[13], dirtyness[14]);
// RULE 1. pick up a good channel that no one used
for (ch = FirstChannel(pAd); ch !=0; ch = NextChannel(pAd, ch))
{
if (dirtyness[ch] == 0) break;
}
if (ch != 0)
{
DBGPRINT(RT_DEBUG_TRACE,"2.APAutoSelectChannel pick up ch#%d\n",ch);
return ch;
}
// RULE 2. if not available, then co-use a channel that's no interference (dirtyness=10)
// RULE 3. if not available, then co-use a channel that has minimum interference (dirtyness=11,12)
for (dirty = 10; dirty <= 12; dirty++)
{
UCHAR candidate[MAX_NUM_OF_CHANNELS+1], candidate_num;
UCHAR min_rssi = 255, final_channel = 0;
candidate_num = 0;
NdisZeroMemory(candidate, MAX_NUM_OF_CHANNELS+1);
for (ch = FirstChannel(pAd); ch != 0; ch = NextChannel(pAd, ch))
{
if (dirtyness[ch] == dirty)
{
candidate[ch]=1;
candidate_num++;
}
}
// if there's more than 1 candidate, pick up the channel with minimum RSSI
if (candidate_num)
{
for (ch = 1; ch <= 14; ch ++)
{
if (candidate[ch] && (max_rssi[ch] < min_rssi))
{
final_channel = ch;
min_rssi = max_rssi[ch];
}
}
if (final_channel != 0)
{
DBGPRINT(RT_DEBUG_TRACE,"3.APAutoSelectChannel pick up ch#%d\n",final_channel);
return final_channel;
}
}
}
// RULE 4. still not available, pick up the first channel
ch = FirstChannel(pAd);
DBGPRINT(RT_DEBUG_TRACE,"4.APAutoSelectChannel pick up ch#%d\n",ch);
return ch;
}
}
/*
==========================================================================
Description:
Send out a NULL frame to a specified STA at a higher TX rate. The
purpose is to ensure the designated client is okay to received at this
rate.
==========================================================================
*/
VOID ApEnqueueNullFrame(
IN PRTMP_ADAPTER pAd,
IN PUCHAR pAddr,
IN UCHAR TxRate,
IN UCHAR PID,
IN UCHAR Apidx,
IN BOOLEAN bQosNull,
IN BOOLEAN bEOSP,
IN UCHAR OldUP)
{
UCHAR NullFrame[48];
PHEADER_802_11 pNullFr;
ULONG Length;
NdisZeroMemory(NullFrame, 48);
Length = sizeof(HEADER_802_11);
pNullFr = (PHEADER_802_11)NullFrame;
// since TxRate may change, we have to change Duration each time
if (pNullFr)
{
#ifdef APCLI_SUPPORT
if ((PID & 0x3f) >= APCLI_PAIRWISE_KEY_OFFSET)
{
// Send to Ap Client
UCHAR ToWhichApCli = (PID & 0x3f) - APCLI_PAIRWISE_KEY_OFFSET;
NdisZeroMemory(pNullFr, sizeof(HEADER_802_11));
pNullFr->FC.Type = BTYPE_DATA;
pNullFr->FC.SubType = SUBTYPE_NULL_FUNC;
pNullFr->FC.ToDs = 1;
COPY_MAC_ADDR(pNullFr->Addr1, pAd->ApCliTab.ApCliEntry[ToWhichApCli].ApCliBssid);
COPY_MAC_ADDR(pNullFr->Addr2, pAd->ApCliTab.ApCliEntry[ToWhichApCli].CurrentAddress);
COPY_MAC_ADDR(pNullFr->Addr3, pAd->ApCliTab.ApCliEntry[ToWhichApCli].ApCliBssid);
pNullFr->Duration = RTMPCalcDuration(pAd, TxRate, 14);
ApSendFrame(pAd, pNullFr, Length, TxRate, PID);
}
else
#endif
if ((PID & 0x3f) >= WDS_PAIRWISE_KEY_OFFSET)
{ // Send to WDS
UCHAR ToWhichWds = (PID & 0x3f) - WDS_PAIRWISE_KEY_OFFSET;
NdisZeroMemory(pNullFr, LENGTH_802_11_WITH_ADDR4);
pNullFr->FC.Type = BTYPE_DATA;
pNullFr->FC.SubType = SUBTYPE_NULL_FUNC;
pNullFr->FC.FrDs = 1;
pNullFr->FC.ToDs = 1;
COPY_MAC_ADDR(pNullFr->Addr1, pAd->WdsTab.WdsEntry[ToWhichWds].WdsAddr);
COPY_MAC_ADDR(pNullFr->Addr2, pAd->PortCfg.MBSSID[MAIN_MBSSID].Bssid);
COPY_MAC_ADDR(pNullFr->Addr3, pAd->WdsTab.WdsEntry[ToWhichWds].WdsAddr);
COPY_MAC_ADDR(pNullFr->Addr3 + MAC_ADDR_LEN, pAd->PortCfg.MBSSID[MAIN_MBSSID].Bssid);
pNullFr->Duration = RTMPCalcDuration(pAd, TxRate, 14);
ApSendFrame(pAd, pNullFr, LENGTH_802_11_WITH_ADDR4, TxRate, PID);
}
else
{ // Send to BSS
MgtMacHeaderInit(pAd, pNullFr, SUBTYPE_NULL_FUNC, 0, pAddr, pAd->PortCfg.MBSSID[Apidx].Bssid);
pNullFr->FC.Type = BTYPE_DATA;
pNullFr->FC.FrDs = 1;
pNullFr->Duration = RTMPCalcDuration(pAd, TxRate, 14);
if (bQosNull)
{
pNullFr->FC.SubType = SUBTYPE_QOS_NULL;
// copy QOS control bytes
NullFrame[Length] = ((bEOSP) ? (1 << 4) : 0) | OldUP;
NullFrame[Length+1] = 0;
Length += 2;
}
ApSendFrame(pAd, pNullFr, Length, TxRate, PID);
}
}
}
VOID ApSendFrame(
IN PRTMP_ADAPTER pAd,
IN PVOID pBuffer,
IN ULONG Length,
IN UCHAR TxRate,
IN UCHAR PID)
{
PUCHAR pDest;
PTXD_STRUC pTxD;
PRTMP_TX_RING pTxRing = &pAd->TxRing[QID_AC_BE];
ULONG IrqFlags;
#ifdef BIG_ENDIAN
PTXD_STRUC pDestTxD;
TXD_STRUC TxD;
#endif
if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS) ||
RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF) ||
RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS))
{
return;
}
// Make sure Tx ring resource won't be used by other threads
#ifndef THREAD_ISR
RTMP_SEM_LOCK(&pAd->TxRingLock, IrqFlags);
#else
RTMP_IRQ_LOCK(IrqFlags);
#endif
// Get the Tx Ring descriptor & Dma Buffer address
pDest = (PUCHAR) pTxRing->Cell[pTxRing->CurTxIndex].DmaBuf.AllocVa;
#ifndef BIG_ENDIAN
pTxD = (PTXD_STRUC) pTxRing->Cell[pTxRing->CurTxIndex].AllocVa;
#else
pDestTxD = (PTXD_STRUC) pTxRing->Cell[pTxRing->CurTxIndex].AllocVa;
TxD = *pDestTxD;
pTxD = &TxD;
RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD);
#endif
if ((pTxD->Owner == DESC_OWN_NIC) || (pTxD->bWaitingDmaDoneInt == 1))
{
// Descriptor owned by NIC. No descriptor avaliable
// This should not happen since caller guaranteed.
DBGPRINT_ERR("APSendNullFrame: TX RING full\n");
pAd->RalinkCounters.TxRingErrCount++;
#ifndef THREAD_ISR
RTMP_SEM_UNLOCK(&pAd->TxRingLock, IrqFlags);
#else
RTMP_IRQ_UNLOCK(IrqFlags);
#endif
return;
}
DBGPRINT(RT_DEBUG_TRACE, "send NULL Frame @%d Mbps...\n", RateIdToMbps[TxRate]);
#ifdef BIG_ENDIAN
RTMPFrameEndianChange(pAd, (PUCHAR)pBuffer, DIR_WRITE, FALSE);
#endif
NdisMoveMemory(pDest, pBuffer, Length);
// pTxRing->Cell[pTxRing->CurTxIndex].FrameType = BTYPE_DATA;
pTxD->BufCount = 1;
pTxD->BufLen0 = Length;
#ifdef BIG_ENDIAN
RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD);
*pDestTxD = TxD;
pTxD = pDestTxD;
#endif
RTMPWriteTxDescriptor(pAd,
pTxD,
CIPHER_NONE, 0, 0,
TRUE,
FALSE,
FALSE,
SHORT_RETRY,
IFS_BACKOFF,
TxRate,
Length,
QID_AC_BE,
PID,
NULL,
NULL,
FALSE,
FALSE,
FALSE,
FALSE);
INC_RING_INDEX(pTxRing->CurTxIndex, TX_RING_SIZE);
pAd->RalinkCounters.KickTxCount++;
#ifndef THREAD_ISR
RTMP_SEM_UNLOCK(&pAd->TxRingLock, IrqFlags);
#else
RTMP_IRQ_UNLOCK(IrqFlags);
#endif
RTMP_IO_WRITE32(pAd, TX_CNTL_CSR, BIT8[QID_AC_BE]); // use AC_BE
}
VOID RTMPHandleNotify8021xDiscardSta(
IN PRTMP_ADAPTER pAd,
IN MAC_TABLE_ENTRY *pEntry)
{
INT apidx = MAIN_MBSSID;
UCHAR SrcAddr[MAC_ADDR_LEN];
UCHAR DestAddr[MAC_ADDR_LEN];
apidx = pEntry->ApIdx;
COPY_MAC_ADDR(SrcAddr, pEntry->Addr);
COPY_MAC_ADDR(DestAddr, pAd->PortCfg.MBSSID[apidx].Bssid);
if((pEntry->AuthMode == Ndis802_11AuthModeWPA) || (pEntry->AuthMode == Ndis802_11AuthModeWPA2) || (pAd->PortCfg.MBSSID[apidx].IEEE8021X == TRUE))
{
UCHAR LLC_Len[2];
UCHAR Header802_3[14];
UCHAR RalinkDiscardIe[] = {0x01, 0xFE, 0x00, 0x06, 0x52, 0x61, 0x6c, 0x69, 0x6e, 0x6b};
struct net_device *net_dev = pAd->net_dev;
net_dev = pAd->PortCfg.MBSSID[apidx].MSSIDDev;
DBGPRINT(RT_DEBUG_TRACE, "Notify 8021.x daemon to remove this sta(%x %x %x %x %x %x)\n",SrcAddr[0],SrcAddr[1],SrcAddr[2],SrcAddr[3],SrcAddr[4],SrcAddr[5]);
NdisMoveMemory(LLC_Len, EAPOL, 2);
MAKE_802_3_HEADER(Header802_3, DestAddr, SrcAddr, ((PUCHAR) LLC_Len));
#ifdef RTL865X_SOC
REPORT_ETHERNET_FRAME_TO_LLC_RTL865X(pAd, Header802_3, RalinkDiscardIe, 10, net_dev);
#else
REPORT_ETHERNET_FRAME_TO_LLC(pAd, Header802_3, RalinkDiscardIe, 10, net_dev);
#endif
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -