📄 rtusb_data.c
字号:
Return Value:
None
Note:
========================================================================
*/
#ifdef BIG_ENDIAN
static inline
#endif
NDIS_STATUS RTUSBHardTransmit(
IN PRTMP_ADAPTER pAd,
IN struct sk_buff *pSkb,
IN UCHAR NumberRequired,
IN UCHAR QueIdx)
{
UINT LengthQosPAD =0;
UINT BytesCopied;
UINT TxSize;
UINT FreeMpduSize;
UINT SrcRemainingBytes;
USHORT Protocol;
UCHAR FrameGap;
HEADER_802_11 Header_802_11;
PHEADER_802_11 pHeader80211;
PUCHAR pDest;
// PUCHAR pSrc;
PTX_CONTEXT pTxContext;
PTXD_STRUC pTxD;
#ifdef BIG_ENDIAN
PTXD_STRUC pDestTxD;
TXD_STRUC TxD;
#endif
// PURB pUrb;
BOOLEAN StartOfFrame;
BOOLEAN bEAPOLFrame;
ULONG Iv16;
ULONG Iv32;
BOOLEAN MICFrag;
// PCIPHER_KEY pWpaKey = NULL;
BOOLEAN Cipher;
ULONG TransferBufferLength;
USHORT AckDuration = 0;
USHORT EncryptionOverhead = 0;
UCHAR CipherAlg;
BOOLEAN bAckRequired;
UCHAR RetryMode = SHORT_RETRY;
UCHAR UserPriority;
UCHAR MpduRequired, RtsRequired;
UCHAR TxRate;
PCIPHER_KEY pKey = NULL ;
PUCHAR pSrcBufVA = NULL;
ULONG SrcBufLen;
PUCHAR pExtraLlcSnapEncap = NULL; // NULL: no extra LLC/SNAP is required
UCHAR KeyIdx;
PUCHAR pWirelessPacket;
ULONG NextMpduSize;
BOOLEAN bRTS_CTSFrame = FALSE;
if ((pAd->PortCfg.bIEEE80211H == 1) && (pAd->PortCfg.RadarDetect.RDMode != RD_NORMAL_MODE))
{
DBGPRINT(RT_DEBUG_INFO,"RTUSBHardTransmit --> radar detect not in normal mode !!!\n");
return (NDIS_STATUS_FAILURE);
}
TxRate = RTMP_GET_PACKET_TXRATE(pSkb);
MpduRequired = RTMP_GET_PACKET_FRAGMENTS(pSkb);
RtsRequired = RTMP_GET_PACKET_RTS(pSkb);
UserPriority = RTMP_GET_PACKET_UP(pSkb);
//
// Prepare packet information structure which will be query for buffer descriptor
//
pSrcBufVA = (PVOID)pSkb->data;
SrcBufLen = pSkb->len;
// Check for virtual address allocation, it might fail !!!
if (pSrcBufVA == NULL)
{
DBGPRINT_RAW(RT_DEBUG_TRACE, "pSrcBufVA == NULL\n");
return(NDIS_STATUS_RESOURCES);
}
if (SrcBufLen < 14)
{
DBGPRINT_RAW(RT_DEBUG_ERROR, "RTUSBHardTransmit --> Skb buffer error !!!\n");
return (NDIS_STATUS_FAILURE);
}
//
// If DHCP datagram or ARP datagram , we need to send it as Low rates.
//
if (pAd->PortCfg.Channel <= 14)
{
//
// Case 802.11 b/g
// basic channel means that we can use CCKM's low rate as RATE_1.
//
if ((TxRate != RATE_1) && RTMPCheckDHCPFrame(pAd, pSkb))
TxRate = RATE_1;
}
else
{
//
// Case 802.11a
// We must used OFDM's low rate as RATE_6, note RATE_1 is not allow
// Only OFDM support on Channel > 14
//
if ((TxRate != RATE_6) && RTMPCheckDHCPFrame(pAd, pSkb))
TxRate = RATE_6;
}
// ------------------------------------------
// STEP 0.1 Add 802.1x protocol check.
// ------------------------------------------
// For non-WPA network, 802.1x message should not encrypt even privacy is on.
if (NdisEqualMemory(EAPOL, pSrcBufVA + 12, 2))
{
bEAPOLFrame = TRUE;
if (pAd->PortCfg.MicErrCnt >= 2)
pAd->PortCfg.MicErrCnt++;
}
else
bEAPOLFrame = FALSE;
//
// WPA 802.1x secured port control - drop all non-802.1x frame before port secured
//
if (((pAd->PortCfg.AuthMode == Ndis802_11AuthModeWPA) ||
(pAd->PortCfg.AuthMode == Ndis802_11AuthModeWPAPSK) ||
(pAd->PortCfg.AuthMode == Ndis802_11AuthModeWPA2) ||
(pAd->PortCfg.AuthMode == Ndis802_11AuthModeWPA2PSK)
#if WPA_SUPPLICANT_SUPPORT
|| (pAd->PortCfg.IEEE8021X == TRUE)
#endif
) &&
((pAd->PortCfg.PortSecured == WPA_802_1X_PORT_NOT_SECURED) || (pAd->PortCfg.MicErrCnt >= 2)) &&
(bEAPOLFrame == FALSE))
{
DBGPRINT_RAW(RT_DEBUG_INFO, "RTUSBHardTransmit --> Drop packet before port secured !!!\n");
return (NDIS_STATUS_FAILURE);
}
if (*pSrcBufVA & 0x01) // Multicast or Broadcast
{
bAckRequired = FALSE;
INC_COUNTER64(pAd->WlanCounters.MulticastTransmittedFrameCount);
Cipher = pAd->PortCfg.GroupCipher; // Cipher for Multicast or Broadcast
}
else
{
bAckRequired = TRUE;
Cipher = pAd->PortCfg.PairCipher; // Cipher for Unicast
}
// 1. traditional TX burst
if (pAd->PortCfg.bEnableTxBurst && (pAd->Sequence & 0x7))
FrameGap = IFS_SIFS;
// 2. frame belonging to AC that has non-zero TXOP
else if (pAd->PortCfg.APEdcaParm.bValid && pAd->PortCfg.APEdcaParm.Txop[QueIdx])
FrameGap = IFS_SIFS;
// 3. otherwise, always BACKOFF before transmission
else
FrameGap = IFS_BACKOFF; // Default frame gap mode
Protocol = *(pSrcBufVA + 12) * 256 + *(pSrcBufVA + 13);
// if orginal Ethernet frame contains no LLC/SNAP, then an extra LLC/SNAP encap is required
if (Protocol > 1500)
{
pExtraLlcSnapEncap = SNAP_802_1H;
if (NdisEqualMemory(IPX, pSrcBufVA + 12, 2) ||
NdisEqualMemory(APPLE_TALK, pSrcBufVA + 12, 2))
{
pExtraLlcSnapEncap = SNAP_BRIDGE_TUNNEL;
}
}
else
pExtraLlcSnapEncap = NULL;
// Update software power save state
OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_DOZE);
pAd->PortCfg.Psm = PWR_ACTIVE;
// -----------------------------------------------------------------
// STEP 2. MAKE A COMMON 802.11 HEADER SHARED BY ENTIRE FRAGMENT BURST.
// -----------------------------------------------------------------
pAd->Sequence = ((pAd->Sequence) + 1) & (MAX_SEQ_NUMBER);
MAKE_802_11_HEADER(pAd, Header_802_11, pSrcBufVA, pAd->Sequence);
#if 0
if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_WMM_INUSED))
Header_802_11.FC.SubType = SUBTYPE_QDATA;
#endif
// --------------------------------------------------------
// STEP 3. FIND ENCRYPT KEY AND DECIDE CIPHER ALGORITHM
// Find the WPA key, either Group or Pairwise Key
// LEAP + TKIP also use WPA key.
// --------------------------------------------------------
// Decide WEP bit and cipher suite to be used. Same cipher suite should be used for whole fragment burst
// In Cisco CCX 2.0 Leap Authentication
// WepStatus is Ndis802_11Encryption1Enabled but the key will use PairwiseKey
// Instead of the SharedKey, SharedKey Length may be Zero.
KeyIdx = 0xff;
if (bEAPOLFrame)
{
ASSERT(pAd->SharedKey[0].CipherAlg <= CIPHER_CKIP128);
if ((pAd->SharedKey[0].CipherAlg) &&
(pAd->SharedKey[0].KeyLen) )
{
CipherAlg = pAd->SharedKey[0].CipherAlg;
KeyIdx = 0;
}
}
else if (Cipher == Ndis802_11Encryption1Enabled)
{
// standard WEP64 or WEP128
KeyIdx = pAd->PortCfg.DefaultKeyId;
}
else if ((Cipher == Ndis802_11Encryption2Enabled) ||
(Cipher == Ndis802_11Encryption3Enabled))
{
if (Header_802_11.Addr1[0] & 0x01) // multicast
KeyIdx = pAd->PortCfg.DefaultKeyId;
else if (pAd->SharedKey[0].KeyLen)
KeyIdx = 0;
else
KeyIdx = pAd->PortCfg.DefaultKeyId;
}
if (KeyIdx == 0xff)
CipherAlg = CIPHER_NONE;
else if (pAd->SharedKey[KeyIdx].KeyLen == 0)
CipherAlg = CIPHER_NONE;
else
{
Header_802_11.FC.Wep = 1;
CipherAlg = pAd->SharedKey[KeyIdx].CipherAlg;
pKey = &pAd->SharedKey[KeyIdx];
}
DBGPRINT(RT_DEBUG_INFO,"RTUSBHardTransmit(bEAP=%d) - %s key#%d, KeyLen=%d\n",
bEAPOLFrame, CipherName[CipherAlg], KeyIdx, pAd->SharedKey[KeyIdx].KeyLen);
// STEP 3.1 if TKIP is used and fragmentation is required. Driver has to
// append TKIP MIC at tail of the scatter buffer (This must be the
// ONLY scatter buffer in the skb buffer).
// MAC ASIC will only perform IV/EIV/ICV insertion but no TKIP MIC
if ((MpduRequired > 1) && (CipherAlg == CIPHER_TKIP))
{
pSkb->len += 8;
CipherAlg = CIPHER_TKIP_NO_MIC;
}
// ----------------------------------------------------------------
// STEP 4. Make RTS frame or CTS-to-self frame if required
// ----------------------------------------------------------------
//
// calcuate the overhead bytes that encryption algorithm may add. This
// affects the calculate of "duration" field
//
if ((CipherAlg == CIPHER_WEP64) || (CipherAlg == CIPHER_WEP128))
EncryptionOverhead = 8; //WEP: IV[4] + ICV[4];
else if (CipherAlg == CIPHER_TKIP_NO_MIC)
EncryptionOverhead = 12;//TKIP: IV[4] + EIV[4] + ICV[4], MIC will be added to TotalPacketLength
else if (CipherAlg == CIPHER_TKIP)
EncryptionOverhead = 20;//TKIP: IV[4] + EIV[4] + ICV[4] + MIC[8]
else if (CipherAlg == CIPHER_AES)
EncryptionOverhead = 16; // AES: IV[4] + EIV[4] + MIC[8]
else
EncryptionOverhead = 0;
// decide how much time an ACK/CTS frame will consume in the air
AckDuration = RTMPCalcDuration(pAd, pAd->PortCfg.ExpectedACKRate[TxRate], 14);
// If fragment required, MPDU size is maximum fragment size
// Else, MPDU size should be frame with 802.11 header & CRC
if (MpduRequired > 1)
NextMpduSize = pAd->PortCfg.FragmentThreshold;
else
{
NextMpduSize = pSkb->len + LENGTH_802_11 + LENGTH_CRC - LENGTH_802_3;
if (pExtraLlcSnapEncap)
NextMpduSize += LENGTH_802_1_H;
}
if (RtsRequired || OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_RTS_PROTECTION_ENABLE))
{
RTMPSendRTSCTSFrame(pAd,
Header_802_11.Addr1,
NextMpduSize + EncryptionOverhead,
TxRate,
pAd->PortCfg.RtsRate,
AckDuration,
QueIdx,
FrameGap,
SUBTYPE_RTS);
// RTS/CTS-protected frame should use LONG_RETRY (=4) and SIFS
RetryMode = LONG_RETRY;
FrameGap = IFS_SIFS;
bRTS_CTSFrame = TRUE;
if (RtsRequired)
NumberRequired--;
}
else if ((pAd->PortCfg.TxRate >= RATE_FIRST_OFDM_RATE) && OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_BG_PROTECTION_INUSED))
{
RTMPSendRTSCTSFrame(pAd,
Header_802_11.Addr1,
NextMpduSize + EncryptionOverhead,
TxRate,
pAd->PortCfg.RtsRate,
AckDuration,
QueIdx,
FrameGap,
SUBTYPE_CTS);
// RTS/CTS-protected frame should use LONG_RETRY (=4) and SIFS
RetryMode = LONG_RETRY;
FrameGap = IFS_SIFS;
bRTS_CTSFrame = TRUE;
}
// --------------------------------------------------------
// STEP 5. START MAKING MPDU(s)
// Start Copy Ndis Packet into Ring buffer.
// For frame required more than one ring buffer (fragment), all ring buffers
// have to be filled before kicking start tx bit.
// Make sure TX ring resource won't be used by other threads
// --------------------------------------------------------
SrcRemainingBytes = pSkb->len - LENGTH_802_3;
SrcBufLen -= LENGTH_802_3; // skip 802.3 header
StartOfFrame = TRUE;
MICFrag = FALSE; // Flag to indicate MIC shall spread into two MPDUs
// Start Copy Ndis Packet into Ring buffer.
// For frame required more than one ring buffer (fragment), all ring buffers
// have to be filled before kicking start tx bit.
do
{
//
// STEP 5.1 Get the Tx Ring descriptor & Dma Buffer address
//
pTxContext = &pAd->TxContext[QueIdx][pAd->NextTxIndex[QueIdx]];
if ((pTxContext->bWaitingBulkOut == TRUE) || (pTxContext->InUse == TRUE) ||
(pAd->TxRingTotalNumber[QueIdx] >= TX_RING_SIZE))
{
DBGPRINT_ERR("RTUSBHardTransmit: TX RING full\n");
pAd->RalinkCounters.TxRingErrCount++;
return (NDIS_STATUS_RESOURCES);
}
pTxContext->InUse = TRUE;
// Increase & maintain Tx Ring Index
pAd->NextTxIndex[QueIdx]++;
if (pAd->NextTxIndex[QueIdx] >= TX_RING_SIZE)
{
pAd->NextTxIndex[QueIdx] = 0;
}
#ifndef BIG_ENDIAN
pTxD = (PTXD_STRUC) &pTxContext->TransferBuffer->TxDesc;
#else
pDestTxD = (PTXD_STRUC) &pTxContext->TransferBuffer->TxDesc;
TxD = *pDestTxD;
pTxD = &TxD;
RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD);
#endif
NdisZeroMemory(pTxD, sizeof(TXD_STRUC));
pWirelessPacket = pTxContext->TransferBuffer->WirelessPacket;
//
// STEP 5.2 PUT IVOFFSET, IV, EIV INTO TXD
//
pTxD->IvOffset = LENGTH_802_11;
#if 0
if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_WMM_INUSED))
pTxD->IvOffset += 2; // add QOS CONTROL bytes
#endif
if ((CipherAlg == CIPHER_WEP64) || (CipherAlg == CIPHER_WEP128))
{
PUCHAR pTmp;
pTmp = (PUCHAR) &pTxD->Iv;
*pTmp = RandomByte(pAd);
*(pTmp + 1) = RandomByte(pAd);
*(pTmp + 2) = RandomByte(pAd);
*(pTmp + 3) = (KeyIdx << 6);
}
else if ((CipherAlg == CIPHER_TKIP) || (CipherAlg == CIPHER_TKIP_NO_MIC))
{
RTMPInitTkipEngine(
pAd,
pKey->Key,
KeyIdx, // This might cause problem when using peer key
Header_802_11.Addr2,
pKey->TxMic,
pKey->TxTsc,
&Iv16,
&Iv32);
NdisMoveMemory(&pTxD->Iv, &Iv16, 4); // Copy IV
NdisMoveMemory(&pTxD->Eiv, &Iv32, 4); // Copy EIV
INC_TX_TSC(pKey->TxTsc); // Increase TxTsc for next transmission
}
else if (CipherAlg == CIPHER_AES)
{
PUCHAR pTmp;
pTmp = (PUCHAR) &Iv16;
*pTmp = pKey->TxTsc[0];
*(pTmp + 1) = pKey->TxTsc[1];
*(pTmp + 2) = 0;
*(pTmp + 3) = (pAd->PortCfg.DefaultKeyId << 6) | 0x20;
Iv32 = *(PULONG)(&pKey->TxTsc[2]);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -