📄 rtmp_data.c
字号:
{ // can't aggregate. put next packe back to TxSwQueue InsertHeadQueue(&pAd->TxSwQueue[QueIdx], pNextEntry); pNextPacket = NULL; } } // Decide if Packet Cloning is required - // 1. when fragmentation && TKIP is inused, we have to clone it into a single buffer // NDIS_PACKET so that driver can pre-cluculate and append TKIP MIC at tail of the // source packet before hardware fragmentation can be performed // 2. when CKIP MIC format is inused, we have to walk through the source NDIS packet to // pre-calculate CMIC and insert at front of 1st output MPDU if ((RTMP_GET_PACKET_SOURCE(pPacket) == PKTSRC_NDIS) && (bClonePacket == FALSE)) { pScatterGatherList = (PRTMP_SCATTER_GATHER_LIST) GET_SG_LIST_FROM_PACKET(pPacket, &LocalScatterGatherList); ASSERT(pScatterGatherList); } // Clone then release the original NDIS packet if (bClonePacket) { PNDIS_PACKET pOutPacket; NDIS_STATUS Status; printk("### Buggy: clone a fragmented packet as a linear packet ###\n"); Status = RTMPCloneNdisPacket(pAd, bAMSDU, pPacket, &pOutPacket); RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_SUCCESS); if (Status != NDIS_STATUS_SUCCESS) { if (pNextPacket) RELEASE_NDIS_PACKET(pAd, pNextPacket, NDIS_STATUS_SUCCESS); return Status; } // Use the new cloned packet from now on pPacket = pOutPacket; RTMP_SET_PACKET_UP(pPacket, UserPriority); RTMP_QueryPacketInfo(pPacket, &PacketInfo, &pSrcBufVA, &SrcBufLen); } // if orginal Ethernet frame contains no LLC/SNAP, then an extra LLC/SNAP encap is required EXTRA_LLCSNAP_ENCAP(pSrcBufVA, pExtraLlcSnapEncap); // link next MSDU into scatter list, if any if (pNextPacket) { // // A-MSDU or A-Ralink // if (CLIENT_STATUS_TEST_FLAG(&pAd->MacTab.Content[BSSID_WCID], fCLIENT_STATUS_AMSDU_INUSED)) { USHORT subMSDULen; if (pExtraLlcSnapEncap) subMSDULen = SrcBufLen - LENGTH_802_3 + LENGTH_802_1_H; else subMSDULen = SrcBufLen - LENGTH_802_3; // 2.1. Make sub-AMSDU header, RTMPMoveMemory(&AMSDUsubheader[0], pSrcBufVA, 12); AMSDUsubheader[12] = (subMSDULen & 0xFF00) >> 8; AMSDUsubheader[13]= subMSDULen & 0xFF; // This is a A-MSDU frame bAMSDU = TRUE; } else { bARALINK = TRUE;// Ralink Aggregation pAd->RalinkCounters.OneSecTxAggregationCount++; } bAllowFrag = FALSE; // // set local scatter gather list // LocalScatterGatherList.NumberOfElements = 2; LocalScatterGatherList.Elements[1].Length = NextPacketBufLen; LocalScatterGatherList.Elements[1].Address = pNextPacketBufVA; PacketInfo.TotalPacketLength += NextPacketBufLen; } pScatterGatherList = &LocalScatterGatherList; // ------------------------------------------ // STEP 0.1 Add 802.1x protocol check. // ------------------------------------------ if (NdisEqualMemory(EAPOL, pSrcBufVA + 12, 2)) { bEAPOLFrame = TRUE; } else bEAPOLFrame = FALSE; // we using lowest basic rate when DHCP and EAPOL packet if ((bDHCPFrame == TRUE) || (bEAPOLFrame == TRUE)) bHTRate = FALSE; // // WPA 802.1x secured port control - drop all non-802.1x frame before port secured // if (((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA) || (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPAPSK) || (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2) || (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2PSK)#ifdef WPA_SUPPLICANT_SUPPORT || (pAd->StaCfg.IEEE8021X == TRUE) #endif // WPA_SUPPLICANT_SUPPORT // ) && ((pAd->StaCfg.PortSecured == WPA_802_1X_PORT_NOT_SECURED) || (pAd->StaCfg.MicErrCnt >= 2)) && (bEAPOLFrame == FALSE)) { DBGPRINT(RT_DEBUG_TRACE,("RTMPHardTransmit --> Drop packet before port secured !!!\n")); RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE); if (pNextPacket) { RELEASE_NDIS_PACKET(pAd, pNextPacket, NDIS_STATUS_FAILURE); } return (NDIS_STATUS_FAILURE); } // allow to use A-MPDU and A-MSDU altogether. if (((pAd->MacTab.Content[RAWcid].TXBAbitmap&(1<<UserPriority)) != 0) && (((INFRA_ON(pAd))) || ((*pSrcBufVA & 0x01) == 0)) && (bDHCPFrame == FALSE)) // only unicast RA use Block Ack. { bTXBA = TRUE; bAllowFrag = FALSE; } if (pAd->CommonCfg.AckPolicy[QueIdx] != NORMAL_ACK) { bAckRequired = FALSE; PID = 0; Cipher = pAd->StaCfg.PairCipher; // Cipher for Unicast } else if (bTXBA) { bAckRequired = TRUE; Cipher = pAd->StaCfg.PairCipher; // Cipher for Unicast } else if ((*pSrcBufVA & 0x01) && (ADHOC_ON(pAd))) // Multicast or Broadcast { bAckRequired = FALSE; INC_COUNTER64(pAd->WlanCounters.MulticastTransmittedFrameCount); Cipher = pAd->StaCfg.GroupCipher; // Cipher for Multicast or Broadcast } else { bAckRequired = TRUE; PID = 0; Cipher = pAd->StaCfg.PairCipher; // Cipher for Unicast if (letusprint == TRUE) DBGPRINT_RAW(RT_DEBUG_TRACE, ("Use PairCipher = %d ", Cipher)); } // When HT rate, always use IFS_HTTXOP if (bHTRate == TRUE) FrameGap = IFS_HTTXOP; // When RTS enable, always use IFS_HTTXOP, or ASIC will not help send RTS frame else if (PacketInfo.TotalPacketLength > pAd->CommonCfg.RtsThreshold) FrameGap = IFS_HTTXOP; // When B/G protection enable, always use IFS_HTTXOP, or ASIC will not help send CTS frame else if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_BG_PROTECTION_INUSED)) FrameGap = IFS_HTTXOP; else if(OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_WMM_INUSED)) { if (!pAd->CommonCfg.APEdcaParm.Txop[QueIdx]) FrameGap = IFS_HTTXOP; else FrameGap = IFS_BACKOFF; } // Tx burst mode else if (pAd->CommonCfg.bEnableTxBurst) FrameGap = IFS_HTTXOP; // otherwise, always BACKOFF before transmission else FrameGap = IFS_BACKOFF; // Default frame gap mode // ------------------------------------------------------------------ // STEP 1. WAKE UP PHY // outgoing frame always wakeup PHY to prevent frame lost and // turn off PSM bit to improve performance // ------------------------------------------------------------------ // not to change PSM bit, just send this frame out? if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE)) AsicForceWakeup(pAd); // It should not change PSM bit, when APSD turn on. if ((!(pAd->CommonCfg.bAPSDCapable && pAd->CommonCfg.APEdcaParm.bAPSDCapable) && (pAd->CommonCfg.bAPSDForcePowerSave == FALSE)) || bEAPOLFrame) { if (pAd->StaCfg.Psm == PWR_SAVE) MlmeSetPsmBit(pAd, PWR_ACTIVE); } // ----------------------------------------------------------------- // STEP 2. MAKE A COMMON 802.11 HEADER SHARED BY ENTIRE FRAGMENT BURST. Fill sequence later. // ----------------------------------------------------------------- MAKE_802_11_HEADER(pAd, Header_802_11, pSrcBufVA); if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_WMM_INUSED)) { Header_802_11.FC.SubType = SUBTYPE_QDATA; bWMM = TRUE; if ((pAd->MacTab.Content[BSSID_WCID].HTCapability.ExtHtCapInfo.PlusHTC == TRUE) && (pAd->MacTab.Content[BSSID_WCID].HTPhyMode.field.MODE >= MODE_HTMIX) && (bDHCPFrame == FALSE)) { Header_802_11.FC.Order = 1; // HTC bit share with order bit bHTC = TRUE; } } // -------------------------------------------------------- // 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[BSS0][0].CipherAlg <= CIPHER_CKIP128); // 4-way handshaking frame must be clear if (!(bWPA4WAYFrame) && (pAd->SharedKey[BSS0][0].CipherAlg) && (pAd->SharedKey[BSS0][0].KeyLen)) { CipherAlg = pAd->SharedKey[BSS0][0].CipherAlg; KeyIdx = 0; } } else if (Cipher == Ndis802_11Encryption1Enabled) {#ifdef LEAP_SUPPORT if (pAd->StaCfg.CkipFlag & 0x10) // Cisco CKIP KP is on { if (LEAP_CCKM_ON(pAd)) { if (Header_802_11.Addr1[0] & 0x01) KeyIdx = 1; else KeyIdx = 0; } else KeyIdx = pAd->StaCfg.DefaultKeyId; } else if (pAd->StaCfg.CkipFlag & 0x08) // only CKIP CMIC KeyIdx = pAd->StaCfg.DefaultKeyId; else if (LEAP_CCKM_ON(pAd)) { if (Header_802_11.Addr1[0] & 0x01) KeyIdx = 1; else KeyIdx = 0; } else // standard WEP64 or WEP128#endif // LEAP_SUPPORT // KeyIdx = pAd->StaCfg.DefaultKeyId; } else if ((Cipher == Ndis802_11Encryption2Enabled) || (Cipher == Ndis802_11Encryption3Enabled)) { if (Header_802_11.Addr1[0] & 0x01) // multicast KeyIdx = pAd->StaCfg.DefaultKeyId; else if (pAd->SharedKey[BSS0][0].KeyLen) KeyIdx = 0; else KeyIdx = pAd->StaCfg.DefaultKeyId; } if (KeyIdx == 0xff) CipherAlg = CIPHER_NONE; else if ((Cipher == Ndis802_11EncryptionDisabled) || (pAd->SharedKey[BSS0][KeyIdx].KeyLen == 0)) CipherAlg = CIPHER_NONE;#ifdef WPA_SUPPLICANT_SUPPORT else if ( pAd->StaCfg.WpaSupplicantUP && (Cipher == Ndis802_11Encryption1Enabled) && (pAd->StaCfg.IEEE8021X == TRUE) && (pAd->StaCfg.PortSecured == WPA_802_1X_PORT_NOT_SECURED)) CipherAlg = CIPHER_NONE;#endif // WPA_SUPPLICANT_SUPPORT // else { Header_802_11.FC.Wep = 1; CipherAlg = pAd->SharedKey[BSS0][KeyIdx].CipherAlg; pKey = &pAd->SharedKey[BSS0][KeyIdx]; } // 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 NDIS PACKET). // MAC ASIC will only perform IV/EIV/ICV insertion but no TKIP MIC if ((MpduRequired > 1) && (CipherAlg == CIPHER_TKIP)) { ASSERT(pScatterGatherList->NumberOfElements == 1); RTMPCalculateMICValue(pAd, pPacket, pExtraLlcSnapEncap, pKey, 0); NdisMoveMemory(pSrcBufVA + SrcBufLen, pAd->PrivateInfo.Tx.MIC, 8); SrcBufLen += 8; PacketInfo.TotalPacketLength += 8; CipherAlg = CIPHER_TKIP_NO_MIC; } else { // // Snice the ScatterGather may allocate on the contiguous range of the base physical address // In that case, the pScatterGatherList->Elements[0].Length will equal to PacketInfo.TotalPacketLength // And the pScatterGatherList->NumberOfElements will be reduce one snice the contiguous range of the data. // So we need to reset the SrcBufLen as pScatterGatherList->Elements[0].Length as our first Packet length. // Otherwise will not get the next pScatterGatherList Elements's length and cause TxRing Full. // This is ok on PKTSRC_NDIS case or not the PKTSRC_NDIS case. // ASSERT(pScatterGatherList); SrcBufLen = pScatterGatherList->Elements[0].Length; } // ---------------------------------------------------------------- // 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->CommonCfg.ExpectedACKRate[TxRate], 14); if (RtsRequired) { // Leave this because maybe need driver send RTS/CTS future. } // -------------------------------------------------------- // STEP 5. SEARCH BA PEER(s). As Sta, always use MacTab.Content[BSSID_WCID] // --------------------------------------------------------{ if (RAWcid != MCAST_WCID) { MAC_TABLE_ENTRY *pMacEntry; pMacEntry = &pAd->MacTab.Content[RAWcid]; if (bTXBA) { RABAOriIdx = pMacEntry->BAOriWcidArray[UserPriority]; TXWIBAWinSize = pAd->BATable.BAOriEntry[RABAOriIdx].BAWinSize; TXWIAMPDU = TRUE; Header_802_11.Frag = 0; } Header_802_11.Sequence = pMacEntry->TxSeq[UserPriority]; pMacEntry->TxSeq[UserPriority] = (pMacEntry->TxSeq[UserPriority]+1) & 0x0FFF; } else { Header_802_11.Sequence = pAd->Sequence; pAd->Sequence = (pAd->Sequence+1) & 0x0FFFF; // next sequence }} // -------------------------------------------------------- // STEP 6. 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 // -------------------------------------------------------- SrcBufIdx = 0; SrcRemainingBytes = PacketInfo.TotalPacketLength; { ULONG OffsetSrcVA = (ULONG)pScatterGatherList->Elements[0].Address; OffsetSrcVA += LENGTH_802_3; // skip 802.3 header SrcBufLen -= LENGTH_802_3; // skip 802.3 header SrcBufPA = (ULONG)PCI_MAP_SINGLE(pAd, (char *)OffsetSrcVA, SrcBufLen, PCI_DMA_TODEVICE); OrgSrcBufPA = SrcBufPA - LENGTH_802_3; // update accurate payload size SrcRemainingBytes = PacketInfo.TotalPacketLength - LENGTH_802_3; } //NdisAcquireSpinLock(&pAd->TxRingLock); //TxIdx =pAd->TxRing[QueIdx].TxCpuIdx; // Update SW_TX_IDX[QueIdx] and *pFreeTXDLeft after finish the copy while-loop // FreeTXDLeft is used to record current Free TXD. If return middle way, real *pFreeTXDLeft don't change. FreeTXDLeft = *pFreeTXDLeft; // Outer while loop loops for fragment packet. At beginning of outer loop, it's a complete wireless MPDU. do { ULONG BufBasePaLow; if (FreeTXDLeft == 0) { DBGPRINT(RT_DEBUG_ERROR,("RTMPHardTransmit: No Free TXD Left\n")); pAd->RalinkCounters.TxRingErrCount++; //NdisReleaseSpinLock(&pAd->TxRingLock); RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE); if (pNextPacket) { RELEASE_NDIS_PACKET(pAd, pNextPacket, NDIS_STATUS_FAILURE); } return (NDIS_STATUS_RESOURCES); } //
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -