📄 rtmp_data.c
字号:
{ // get Ethernet protocol field Protocol = (USHORT)((pSrcBufVA[12] << 8) + pSrcBufVA[13]); if (Protocol <= 1500) { // get Ethernet protocol field from LLC/SNAP if (Sniff2BytesFromNdisBuffer(PacketInfo.pFirstBuffer, LENGTH_802_3 + 6, &Byte0, &Byte1) != NDIS_STATUS_SUCCESS) break; Protocol = (USHORT)((Byte0 << 8) + Byte1); LlcSnapLen = 8; } // always AC_BE for non-IP packet if (Protocol != 0x0800) break; // get IP header if (Sniff2BytesFromNdisBuffer(PacketInfo.pFirstBuffer, LENGTH_802_3 + LlcSnapLen, &Byte0, &Byte1) != NDIS_STATUS_SUCCESS) break; // return AC_BE if packet is not IPv4 if ((Byte0 & 0xf0) != 0x40) break; UserPriority = (Byte1 & 0xe0) >> 5; QueIdx = MapUserPriorityToAccessCategory[UserPriority]; // TODO: have to check ACM bit. apply TSPEC if ACM is ON // TODO: downgrade UP & QueIdx before passing ACM if (pAd->CommonCfg.APEdcaParm.bACM[QueIdx]) { UserPriority = 0; QueIdx = QID_AC_BE; } } while (FALSE); } RTMP_SET_PACKET_UP(pPacket, UserPriority); NdisAcquireSpinLock(&pAd->TxSwQueueLock); if (pAd->TxSwQueue[QueIdx].Number >= MAX_PACKETS_IN_QUEUE) {#ifdef BLOCK_NET_IF StopNetIfQueue(pAd, QueIdx, pPacket);#endif // BLOCK_NET_IF // RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE); NdisReleaseSpinLock(&pAd->TxSwQueueLock); return NDIS_STATUS_FAILURE; } else { InsertTailQueue(&pAd->TxSwQueue[QueIdx], PACKET_TO_QUEUE_ENTRY(pPacket)); } NdisReleaseSpinLock(&pAd->TxSwQueueLock); pAd->RalinkCounters.OneSecOsTxCount[QueIdx]++; // TODO: for debug only. to be removed return NDIS_STATUS_SUCCESS;}/* ======================================================================== Routine Description: This subroutine will scan through releative ring descriptor to find out avaliable free ring descriptor and compare with request size. Arguments: pAd Pointer to our adapter QueIdx Selected TX Ring Return Value: NDIS_STATUS_FAILURE Not enough free descriptor NDIS_STATUS_SUCCESS Enough free descriptor IRQL = PASSIVE_LEVEL IRQL = DISPATCH_LEVEL Note: ========================================================================*/NDIS_STATUS RTMPFreeTXDRequest( IN PRTMP_ADAPTER pAd, IN UCHAR QueIdx, IN UCHAR NumberRequired, IN PUCHAR FreeNumberIs){ ULONG FreeNumber = 0; NDIS_STATUS Status = NDIS_STATUS_FAILURE; switch (QueIdx) { case QID_AC_BK: case QID_AC_BE: case QID_AC_VI: case QID_AC_VO: case QID_HCCA: if (pAd->TxRing[QueIdx].TxSwFreeIdx > pAd->TxRing[QueIdx].TxCpuIdx) FreeNumber = pAd->TxRing[QueIdx].TxSwFreeIdx - pAd->TxRing[QueIdx].TxCpuIdx - 1; else FreeNumber = pAd->TxRing[QueIdx].TxSwFreeIdx + TX_RING_SIZE - pAd->TxRing[QueIdx].TxCpuIdx - 1; if (FreeNumber >= NumberRequired) Status = NDIS_STATUS_SUCCESS; break; case QID_MGMT: if (pAd->MgmtRing.TxSwFreeIdx > pAd->MgmtRing.TxCpuIdx) FreeNumber = pAd->MgmtRing.TxSwFreeIdx - pAd->MgmtRing.TxCpuIdx - 1; else FreeNumber = pAd->MgmtRing.TxSwFreeIdx + MGMT_RING_SIZE - pAd->MgmtRing.TxCpuIdx - 1; if (FreeNumber >= NumberRequired) Status = NDIS_STATUS_SUCCESS; break; default: DBGPRINT(RT_DEBUG_ERROR,("RTMPFreeTXDRequest::Invalid QueIdx(=%d)\n", QueIdx)); break; } *FreeNumberIs = (UCHAR)FreeNumber; return (Status);}VOID RTMPSendDisassociationFrame( IN PRTMP_ADAPTER pAd){} // IRQL = DISPATCH_LEVELVOID RTMPSendNullFrame( IN PRTMP_ADAPTER pAd, IN UCHAR TxRate, IN BOOLEAN bQosNull){ UCHAR NullFrame[48]; ULONG Length; PHEADER_802_11 pHeader_802_11; // WPA 802.1x secured port control 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 ) && (pAd->StaCfg.PortSecured == WPA_802_1X_PORT_NOT_SECURED)) { return; } NdisZeroMemory(NullFrame, 48); Length = sizeof(HEADER_802_11); pHeader_802_11 = (PHEADER_802_11) NullFrame; pHeader_802_11->FC.Type = BTYPE_DATA; pHeader_802_11->FC.SubType = SUBTYPE_NULL_FUNC; pHeader_802_11->FC.ToDs = 1; COPY_MAC_ADDR(pHeader_802_11->Addr1, pAd->CommonCfg.Bssid); COPY_MAC_ADDR(pHeader_802_11->Addr2, pAd->CurrentAddress); COPY_MAC_ADDR(pHeader_802_11->Addr3, pAd->CommonCfg.Bssid); if (pAd->CommonCfg.bAPSDForcePowerSave) { pHeader_802_11->FC.PwrMgmt = PWR_SAVE; } else { pHeader_802_11->FC.PwrMgmt = (pAd->StaCfg.Psm == PWR_SAVE) ? 1: 0; } pHeader_802_11->Duration = pAd->CommonCfg.Dsifs + RTMPCalcDuration(pAd, TxRate, 14); pAd->Sequence++; pHeader_802_11->Sequence = pAd->Sequence; // Prepare QosNull function frame if (bQosNull) { pHeader_802_11->FC.SubType = SUBTYPE_QOS_NULL; // copy QOS control bytes NullFrame[Length] = 0; NullFrame[Length+1] = 0; Length += 2;// if pad with 2 bytes for alignment, APSD will fail } MiniportMMRequest(pAd, 0, NullFrame, Length);}// IRQL = DISPATCH_LEVELVOID RTMPSendRTSFrame( IN PRTMP_ADAPTER pAd, IN PUCHAR pDA, IN unsigned int NextMpduSize, IN UCHAR TxRate, IN UCHAR RTSRate, IN USHORT AckDuration, IN UCHAR QueIdx, IN UCHAR FrameGap){}/* ======================================================================== Routine Description: Copy frame from waiting queue into relative ring buffer and set appropriate ASIC register to kick hardware encryption before really sent out to air. Arguments: pAd Pointer to our adapter PNDIS_PACKET Pointer to outgoing Ndis frame NumberOfFrag Number of fragment required Return Value: None IRQL = DISPATCH_LEVEL Note: ========================================================================*/NDIS_STATUS RTMPHardTransmit( IN PRTMP_ADAPTER pAd, IN PNDIS_PACKET pPacket, IN UCHAR QueIdx, OUT PULONG pFreeTXDLeft){ PACKET_INFO PacketInfo, NextPacketInfo; PUCHAR pSrcBufVA, pNextPacketBufVA = 0; PUCHAR pDMAHeaderBufVA, pDMAHeaderBufPtr; UINT SrcBytesCopied; UINT FreeMpduSize, MpduSize = 0; UINT SrcBufLen, NextPacketBufLen = 0; UCHAR SrcBufIdx; ULONG SrcBufPA; INT SrcRemainingBytes; UCHAR FrameGap = IFS_HTTXOP; HEADER_802_11 Header_802_11; PHEADER_802_11 pHeader80211 = NULL; PUCHAR pExtraLlcSnapEncap; // NULL: no extra LLC/SNAP is required UCHAR CipherAlg; PTXD_STRUC pTxD;#ifdef BIG_ENDIAN TXD_STRUC TxD; PTXD_STRUC pDestTxD;#endif PTXWI_STRUC pFirstTxWI; BOOLEAN bEAPOLFrame; BOOLEAN bAckRequired;// UCHAR RetryMode = SHORT_RETRY; USHORT AckDuration = 0; USHORT EncryptionOverhead = 0; UCHAR KeyIdx; PCIPHER_KEY pKey = NULL; UCHAR PID = 0; PRTMP_TX_RING pTxRing = &pAd->TxRing[QueIdx]; PRTMP_SCATTER_GATHER_LIST pScatterGatherList; RTMP_SCATTER_GATHER_LIST LocalScatterGatherList; PNDIS_PACKET pNextPacket = NULL; BOOLEAN bClonePacket = FALSE; UCHAR MpduRequired, RtsRequired, UserPriority, MimoPs = MMPS_ENABLE; UCHAR TxRate; //USHORT Protocol; // To indicate cipher used for this packet NDIS_802_11_ENCRYPTION_STATUS Cipher; //BOOLEAN bRTS_CTSFrame = FALSE; BOOLEAN bHTC = FALSE; // TRUE if HT AMSDU used for this MPDU. BOOLEAN bTXBA = FALSE; // TRUE if use block ack. ULONG FreeTXDLeft = *pFreeTXDLeft; BOOLEAN TXWIAMPDU = FALSE; //AMPDU bit in TXWI UCHAR TXWIBAWinSize = 0; //BAWinSize field in TXWI ULONG TxIdx =pAd->TxRing[QueIdx].TxCpuIdx; UCHAR SDPNowUsed = 1; //UCHAR ScatterNowUsed = 0; BOOLEAN IsSD0 = TRUE; PULONG ptemp; BOOLEAN letusprint = FALSE; UCHAR RAWcid = BSSID_WCID; // default in infra mode or adhoc mode using legacy rate, RA is BSSID. UCHAR RABAOriIdx = 0; //The RA's BA Originator table index. BOOLEAN bPiggyBack = FALSE; BOOLEAN bARALINK = FALSE; BOOLEAN bAMSDU = FALSE; // use HT AMSDU BOOLEAN bAllowFrag = TRUE; // A-MPDU, A-MSDU, A-Ralink is not allowed to fragment BOOLEAN bWMM = FALSE; BOOLEAN bDHCPFrame = FALSE; UCHAR AMSDUsubheader[14]; UCHAR padding = 0; BOOLEAN bHTRate = FALSE; // use HT AMSDU ULONG OrgSrcBufPA; BOOLEAN bWPA4WAYFrame = FALSE; if ((pAd->CommonCfg.bIEEE80211H == 1) && (pAd->CommonCfg.RadarDetect.RDMode != RD_NORMAL_MODE)) { DBGPRINT(RT_DEBUG_INFO,("RTMPHardTransmit --> radar detect not in normal mode !!!\n")); RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE); return (NDIS_STATUS_FAILURE); } MpduRequired = RTMP_GET_PACKET_FRAGMENTS(pPacket); RtsRequired = RTMP_GET_PACKET_RTS(pPacket); UserPriority = RTMP_GET_PACKET_UP(pPacket); TxRate = RTMP_GET_PACKET_TXRATE(pPacket); bWPA4WAYFrame = RTMP_GET_PACKET_WPA_4WAY_MSG(pPacket); RABAOriIdx = UserPriority; // default in using UP as originator index in Infra mode. // --------------------------------------------- // STEP 0. PARSING THE NDIS PACKET // --------------------------------------------- // // Prepare packet information structure which will be query for buffer descriptor // RTMP_QueryPacketInfo(pPacket, &PacketInfo, &pSrcBufVA, &SrcBufLen); if (SrcBufLen < 14) { DBGPRINT(RT_DEBUG_ERROR,("RTMPHardTransmit --> Ndis Packet buffer error !!!\n")); RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE); return (NDIS_STATUS_FAILURE); } if (pAd->bForcePrintTX == TRUE) letusprint = TRUE; // In HT rate adhoc mode, A-MPDU is often used. So need to lookup BA Table and MAC Entry. // Note multicast packets in adhoc also use BSSID_WCID index. if (ADHOC_ON(pAd) &&((*pSrcBufVA & 0x01) == 1)) { RAWcid = MCAST_WCID; } else if (ADHOC_ON(pAd)) // only unicast data use Block Ack { MAC_TABLE_ENTRY *pEntry; pEntry = MacTableLookup(pAd, pSrcBufVA); if (pEntry) { RAWcid = (UCHAR)pEntry->Aid; } } if (pAd->MacTab.Content[RAWcid].HTPhyMode.field.MODE & 0x2) { bHTRate = TRUE; MimoPs = pAd->MacTab.Content[RAWcid].MmpsMode; } // Update Originator index as the RA's BA Originator index. RABAOriIdx = pAd->MacTab.Content[RAWcid].BAOriWcidArray[UserPriority]; // // Only Broadcast packet could be DHCP or ARP. // If DHCP datagram or ARP datagram , we need to send it as Low rates. // if ((*pSrcBufVA & 0x01) && RTMPCheckDHCPFrame(pAd, pPacket)) { bDHCPFrame = TRUE; } if (TxRate < pAd->CommonCfg.MinTxRate) TxRate = pAd->CommonCfg.MinTxRate; #ifdef UNDER_CE bClonePacket = TRUE; #else#ifdef ME_98 // // It's not support ScatterGatherDma in Win9x and WinME // So, ClonePacket functionality is always TRUE. // bClonePacket = TRUE; #else if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_SCATTER_GATHER)) bClonePacket = FALSE; // cloning is not necessary if used scatter-gather DMA else bClonePacket = TRUE; // cloning is necessary when scatter-gather DMA failed.#endif // #if ME_98#endif // #ifdef UNDER_CE pNextPacket = NULL; // no aggregation is required#if 1 /* clone is not necessary in Linux or uCOS-II */ bClonePacket = OS_Need_Clone_Packet();#endif // check if aggregation applicable on this MSDU and the next one. If applicable // make sure both MSDUs use internally created NDIS PACKET structure so that both has // only one scatter-gather buffer // NOTE: 1.) aggregation not applicable when CKIP inused. because it's difficult for driver // to calculate CMIC on the aggregated MSDU // 2.) used Aggregation if packet didn't be fragment, that means MpduRequired must be 1. // 3.) backward compatible SW Aggregation with RT2661, which is not MIMO txrate. // 4.) DHCP frame should not aggregate to increase success rate if ( ( //(OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_AGGREGATION_INUSED) && (pAd->CommonCfg.HTPhyMode.field.MODE == MODE_OFDM)) || //(OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_TX_AMSDU_INUSED)) (RAWcid != 0) && PeerIsAggreOn(pAd, TxRate, &pAd->MacTab.Content[RAWcid]) ) && (pAd->TxSwQueue[QueIdx].Head != NULL) && (FreeTXDLeft > 1) && //scattered-gather use many descriptor for a-msdu (pAd->StaCfg.bCkipOn == FALSE) && (MpduRequired == 1) && (bDHCPFrame == FALSE) && TxFrameIsAggregatible(pAd, NULL, pSrcBufVA)) { PQUEUE_ENTRY pNextEntry;// UINT TotalPacketLength; // RT2860B . erase after verified. pNextEntry = RemoveHeadQueue(&pAd->TxSwQueue[QueIdx]); pNextPacket = QUEUE_ENTRY_TO_PACKET(pNextEntry); RTMP_QueryPacketInfo(pNextPacket, &NextPacketInfo, &pNextPacketBufVA, &NextPacketBufLen); DBGPRINT(RT_DEBUG_INFO,("AGGRE: 1st MSDU aggregatible(len=%d)\n", PacketInfo.TotalPacketLength)); if (NextPacketBufLen < 14) { DBGPRINT(RT_DEBUG_ERROR,("RTMPHardTransmit --> Ndis NextPacket buffer error !!!\n")); RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE); RELEASE_NDIS_PACKET(pAd, pNextPacket, NDIS_STATUS_FAILURE); return (NDIS_STATUS_FAILURE); } if (TxFrameIsAggregatible(pAd, pSrcBufVA, pNextPacketBufVA)) { } else
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -