📄 rtmp_data.c
字号:
// Dequeue outgoing frames from TxSwQueue[] and process it RTMPDeQueuePacket(pAd, FALSE, NUM_OF_TX_RING, MAX_TX_PROCESS);}/*========================================================================Routine Description: This routine is used to do packet parsing and classification for Tx packet to STA device, and it will en-queue packets to our TxSwQueue depends on AC class. Arguments: pAd Pointer to our adapter pPacket Pointer to send packetReturn Value: NDIS_STATUS_SUCCESS If succes to queue the packet into TxSwQueue. NDIS_STATUS_FAILURE If failed to do en-queue.Note: You only can put OS-indepened & STA related code in here.========================================================================*/NDIS_STATUS STASendPacket( IN PRTMP_ADAPTER pAd, IN PNDIS_PACKET pPacket){ PACKET_INFO PacketInfo; PUCHAR pSrcBufVA; UINT SrcBufLen; UINT AllowFragSize; UCHAR NumberOfFrag; UCHAR RTSRequired; UCHAR QueIdx, UserPriority; MAC_TABLE_ENTRY *pEntry = NULL; unsigned int IrqFlags; UCHAR FlgIsIP = 0; UCHAR Rate; // Prepare packet information structure for buffer descriptor // chained within a single NDIS packet. RTMP_QueryPacketInfo(pPacket, &PacketInfo, &pSrcBufVA, &SrcBufLen); if (pSrcBufVA == NULL) { DBGPRINT(RT_DEBUG_ERROR,("STASendPacket --> pSrcBufVA == NULL !!!SrcBufLen=%x\n",SrcBufLen)); // Resourece is low, system did not allocate virtual address // return NDIS_STATUS_FAILURE directly to upper layer RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE); return NDIS_STATUS_FAILURE; } if (SrcBufLen < 14) { DBGPRINT(RT_DEBUG_ERROR,("STASendPacket --> Ndis Packet buffer error !!!\n")); RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE); return (NDIS_STATUS_FAILURE); } // 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(INFRA_ON(pAd)) {#ifdef QOS_DLS_SUPPORT USHORT tmpWcid; tmpWcid = RTMP_GET_PACKET_WCID(pPacket); if (VALID_WCID(tmpWcid) && (pAd->MacTab.Content[tmpWcid].ValidAsDls== TRUE)) { pEntry = &pAd->MacTab.Content[tmpWcid]; Rate = pAd->MacTab.Content[tmpWcid].CurrTxRate; } else#endif // QOS_DLS_SUPPORT // { pEntry = &pAd->MacTab.Content[BSSID_WCID]; RTMP_SET_PACKET_WCID(pPacket, BSSID_WCID); Rate = pAd->CommonCfg.TxRate; } } else if (ADHOC_ON(pAd)) { if (*pSrcBufVA & 0x01) { RTMP_SET_PACKET_WCID(pPacket, MCAST_WCID); pEntry = &pAd->MacTab.Content[MCAST_WCID]; } else { pEntry = MacTableLookup(pAd, pSrcBufVA); } Rate = pAd->CommonCfg.TxRate; } } if (!pEntry) { DBGPRINT(RT_DEBUG_ERROR,("STASendPacket->Cannot find pEntry(%2x:%2x:%2x:%2x:%2x:%2x) in MacTab!\n", PRINT_MAC(pSrcBufVA))); // Resourece is low, system did not allocate virtual address // return NDIS_STATUS_FAILURE directly to upper layer RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE); return NDIS_STATUS_FAILURE; } if (ADHOC_ON(pAd) ) { RTMP_SET_PACKET_WCID(pPacket, (UCHAR)pEntry->Aid); } // // Check the Ethernet Frame type of this packet, and set the RTMP_SET_PACKET_SPECIFIC flags. // Here we set the PACKET_SPECIFIC flags(LLC, VLAN, DHCP/ARP, EAPOL). RTMPCheckEtherType(pAd, pPacket); // // 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)) && (RTMP_GET_PACKET_EAPOL(pPacket)== FALSE) ) { DBGPRINT(RT_DEBUG_TRACE,("STASendPacket --> Drop packet before port secured !!!\n")); RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE); return (NDIS_STATUS_FAILURE); } // STEP 1. Decide number of fragments required to deliver this MSDU. // The estimation here is not very accurate because difficult to // take encryption overhead into consideration here. The result // "NumberOfFrag" is then just used to pre-check if enough free // TXD are available to hold this MSDU. if (*pSrcBufVA & 0x01) // fragmentation not allowed on multicast & broadcast NumberOfFrag = 1; else if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_AGGREGATION_INUSED)) NumberOfFrag = 1; // Aggregation overwhelms fragmentation else if (CLIENT_STATUS_TEST_FLAG(pEntry, fCLIENT_STATUS_AMSDU_INUSED)) NumberOfFrag = 1; // Aggregation overwhelms fragmentation#ifdef DOT11_N_SUPPORT else if ((pAd->StaCfg.HTPhyMode.field.MODE == MODE_HTMIX) || (pAd->StaCfg.HTPhyMode.field.MODE == MODE_HTGREENFIELD)) NumberOfFrag = 1; // MIMO RATE overwhelms fragmentation#endif // DOT11_N_SUPPORT // else { // The calculated "NumberOfFrag" is a rough estimation because of various // encryption/encapsulation overhead not taken into consideration. This number is just // used to make sure enough free TXD are available before fragmentation takes place. // In case the actual required number of fragments of an NDIS packet // excceeds "NumberOfFrag"caculated here and not enough free TXD available, the // last fragment (i.e. last MPDU) will be dropped in RTMPHardTransmit() due to out of // resource, and the NDIS packet will be indicated NDIS_STATUS_FAILURE. This should // rarely happen and the penalty is just like a TX RETRY fail. Affordable. AllowFragSize = (pAd->CommonCfg.FragmentThreshold) - LENGTH_802_11 - LENGTH_CRC; NumberOfFrag = ((PacketInfo.TotalPacketLength - LENGTH_802_3 + LENGTH_802_1_H) / AllowFragSize) + 1; // To get accurate number of fragmentation, Minus 1 if the size just match to allowable fragment size if (((PacketInfo.TotalPacketLength - LENGTH_802_3 + LENGTH_802_1_H) % AllowFragSize) == 0) { NumberOfFrag--; } } // Save fragment number to Ndis packet reserved field RTMP_SET_PACKET_FRAGMENTS(pPacket, NumberOfFrag); // STEP 2. Check the requirement of RTS: // If multiple fragment required, RTS is required only for the first fragment // if the fragment size large than RTS threshold // For RT28xx, Let ASIC send RTS/CTS// RTMP_SET_PACKET_RTS(pPacket, 0); if (NumberOfFrag > 1) RTSRequired = (pAd->CommonCfg.FragmentThreshold > pAd->CommonCfg.RtsThreshold) ? 1 : 0; else RTSRequired = (PacketInfo.TotalPacketLength > pAd->CommonCfg.RtsThreshold) ? 1 : 0; // Save RTS requirement to Ndis packet reserved field RTMP_SET_PACKET_RTS(pPacket, RTSRequired); RTMP_SET_PACKET_TXRATE(pPacket, pAd->CommonCfg.TxRate); // // STEP 3. Traffic classification. outcome = <UserPriority, QueIdx> // UserPriority = 0; QueIdx = QID_AC_BE; if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_WMM_INUSED) && CLIENT_STATUS_TEST_FLAG(pEntry, fCLIENT_STATUS_WMM_CAPABLE)) { USHORT Protocol; UCHAR LlcSnapLen = 0, Byte0, Byte1; do { // 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; FlgIsIP = 1; 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 /* Under WMM ACM control, we dont need to check the bit; Or when a TSPEC is built for VO but we will change to issue BA session for BE here, so we will not use BA to send VO packets. */ if (pAd->CommonCfg.APEdcaParm.bACM[QueIdx]) { UserPriority = 0; QueIdx = QID_AC_BE; } } while (FALSE); } RTMP_SET_PACKET_UP(pPacket, UserPriority); // Make sure SendTxWait queue resource won't be used by other threads RTMP_IRQ_LOCK(&pAd->irq_lock, IrqFlags); if (pAd->TxSwQueue[QueIdx].Number >= MAX_PACKETS_IN_QUEUE) { RTMP_IRQ_UNLOCK(&pAd->irq_lock, IrqFlags);#ifdef BLOCK_NET_IF StopNetIfQueue(pAd, QueIdx, pPacket);#endif // BLOCK_NET_IF // RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE); return NDIS_STATUS_FAILURE; } else { InsertTailQueueAc(pAd, pEntry, &pAd->TxSwQueue[QueIdx], PACKET_TO_QUEUE_ENTRY(pPacket)); } RTMP_IRQ_UNLOCK(&pAd->irq_lock, IrqFlags);#ifdef DOT11_N_SUPPORT if ((pAd->CommonCfg.BACapability.field.AutoBA == TRUE)&& IS_HT_STA(pEntry)) { //PMAC_TABLE_ENTRY pMacEntry = &pAd->MacTab.Content[BSSID_WCID]; if (((pEntry->TXBAbitmap & (1<<UserPriority)) == 0) && ((pEntry->BADeclineBitmap & (1<<UserPriority)) == 0) && (pEntry->PortSecured == WPA_802_1X_PORT_SECURED) // For IOT compatibility, if // 1. It is Ralink chip or // 2. It is OPEN or AES mode, // then BA session can be bulit. && ((pEntry->ValidAsCLI && pAd->MlmeAux.APRalinkIe != 0x0) || (pEntry->WepStatus != Ndis802_11WEPEnabled && pEntry->WepStatus != Ndis802_11Encryption2Enabled)) ) { BAOriSessionSetUp(pAd, pEntry, UserPriority, 0, 10, FALSE); } }#endif // DOT11_N_SUPPORT // 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: ========================================================================*/#ifdef RTMP_MAC_USB/* Actually, this function used to check if the TxHardware Queue still has frame need to send. If no frame need to send, go to sleep, else, still wake up.*/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; unsigned long IrqFlags; HT_TX_CONTEXT *pHTTXContext; switch (QueIdx) { case QID_AC_BK: case QID_AC_BE: case QID_AC_VI: case QID_AC_VO: case QID_HCCA: { pHTTXContext = &pAd->TxContext[QueIdx]; RTMP_IRQ_LOCK(&pAd->TxContextQueueLock[QueIdx], IrqFlags); if ((pHTTXContext->CurWritePosition != pHTTXContext->ENextBulkOutPosition) || (pHTTXContext->IRPPending == TRUE)) { Status = NDIS_STATUS_FAILURE; } else { Status = NDIS_STATUS_SUCCESS; } RTMP_IRQ_UNLOCK(&pAd->TxContextQueueLock[QueIdx], IrqFlags); } break; case QID_MGMT: if (pAd->MgmtRing.TxSwFreeIdx != MGMT_RING_SIZE) Status = NDIS_STATUS_FAILURE; else Status = NDIS_STATUS_SUCCESS; break; default: DBGPRINT(RT_DEBUG_ERROR,("RTMPFreeTXDRequest::Invalid QueIdx(=%d)\n", QueIdx)); break; } return (Status); }#endif // RTMP_MAC_USB //VOID RTMPSendDisassociationFrame( IN PRTMP_ADAPTER pAd){} VOID RTMPSendNullFrame( IN PRTMP_ADAPTER pAd, IN UCHAR TxRate, IN BOOLEAN bQosNull){ UCHAR NullFrame[48]; ULONG Length; PHEADER_802_11 pHeader_802_11;#ifdef RALINK_ATE if(ATE_ON(pAd)) { return; }#endif // RALINK_ATE // // 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 } HAL_KickOutNullFrameTx(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){}// --------------------------------------------------------// FIND ENCRYPT KEY AND DECIDE CIPHER ALGORITHM// Find the WPA key, either Group or Pairwise Key// LEAP + TKIP also use WPA key.// --------------------------------------------------------
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -