📄 ba_action.c
字号:
if (BARecSessionAdd(pAd, &pAd->MacTab.Content[Elem->Wcid], pAddreqFrame)) Status = 0; else Status = 38; // more parameters have invalid values } else { Status = 37; // the request has been declined. } } if (pAd->MacTab.Content[Elem->Wcid].ValidAsCLI) ASSERT(pAd->MacTab.Content[Elem->Wcid].Sst == SST_ASSOC); pAddreqFrame = (PFRAME_ADDBA_REQ)(&Elem->Msg[0]); // 2. Always send back ADDBA Response NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); //Get an unused nonpaged memory if (NStatus != NDIS_STATUS_SUCCESS) { DBGPRINT(RT_DEBUG_TRACE,("ACTION - PeerBAAction() allocate memory failed \n")); return; } NdisZeroMemory(&ADDframe, sizeof(FRAME_ADDBA_RSP)); // 2-1. Prepare ADDBA Response frame.#ifdef CONFIG_STA_SUPPORT ActHeaderInit(pAd, &ADDframe.Hdr, pAd->CommonCfg.Bssid, pAd->CurrentAddress, pAddr);#endif // CONFIG_STA_SUPPORT // ADDframe.Category = CATEGORY_BA; ADDframe.Action = ADDBA_RESP; ADDframe.Token = pAddreqFrame->Token; // What is the Status code?? need to check. ADDframe.StatusCode = Status; ADDframe.BaParm.BAPolicy = IMMED_BA; ADDframe.BaParm.AMSDUSupported = 0; ADDframe.BaParm.TID = pAddreqFrame->BaParm.TID; ADDframe.BaParm.BufSize = min(((UCHAR)pAddreqFrame->BaParm.BufSize), (UCHAR)pAd->CommonCfg.BACapability.field.RxBAWinLimit); if (ADDframe.BaParm.BufSize == 0) { ADDframe.BaParm.BufSize = 64; } ADDframe.TimeOutValue = 0; //pAddreqFrame->TimeOutValue;#ifdef BIG_ENDIAN *(USHORT *)(&ADDframe.BaParm) = SWAP16(*(USHORT *)(&ADDframe.BaParm)); ADDframe.StatusCode = SWAP16(ADDframe.StatusCode); ADDframe.TimeOutValue = SWAP16(ADDframe.TimeOutValue);#endif MakeOutgoingFrame(pOutBuffer, &FrameLen, sizeof(FRAME_ADDBA_RSP), &ADDframe, END_OF_ARGS); MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer, FrameLen); MlmeFreeMemory(pAd, pOutBuffer); DBGPRINT(RT_DEBUG_TRACE, ("%s(%d): TID(%d), BufSize(%d) <== \n", __FUNCTION__, Elem->Wcid, ADDframe.BaParm.TID, ADDframe.BaParm.BufSize));}VOID PeerAddBARspAction( IN PRTMP_ADAPTER pAd, IN MLME_QUEUE_ELEM *Elem) { //UCHAR Idx, i; //PUCHAR pOutBuffer = NULL; PFRAME_ADDBA_RSP pFrame = NULL; //PBA_ORI_ENTRY pBAEntry; //ADDBA Response from unknown peer, ignore this. if (Elem->Wcid >= MAX_LEN_OF_MAC_TABLE) return; DBGPRINT(RT_DEBUG_TRACE, ("%s ==> Wcid(%d)\n", __FUNCTION__, Elem->Wcid)); //hex_dump("AddBARsp, Elem->Msg, Elem->MsgLen); if (PeerAddBARspActionSanity(pAd, Elem->Msg, Elem->MsgLen)) { pFrame = (PFRAME_ADDBA_RSP)(&Elem->Msg[0]); DBGPRINT(RT_DEBUG_TRACE, ("\t\t StatusCode = %d\n", pFrame->StatusCode)); switch (pFrame->StatusCode) { case 0: // I want a BAsession with this peer as an originator. BAOriSessionAdd(pAd, &pAd->MacTab.Content[Elem->Wcid], pFrame); break; default: // check status == USED ??? BAOriSessionTearDown(pAd, Elem->Wcid, pFrame->BaParm.TID, TRUE, FALSE); break; } // Rcv Decline StatusCode if (pFrame->StatusCode == 37) { pAd->MacTab.Content[Elem->Wcid].BADeclineBitmap |= 1<<pFrame->BaParm.TID; } }}VOID PeerDelBAAction( IN PRTMP_ADAPTER pAd, IN MLME_QUEUE_ELEM *Elem) { //UCHAR Idx; //PUCHAR pOutBuffer = NULL; PFRAME_DELBA_REQ pDelFrame = NULL; DBGPRINT(RT_DEBUG_TRACE,("%s ==>\n", __FUNCTION__)); //DELBA Request from unknown peer, ignore this. if (PeerDelBAActionSanity(pAd, Elem->Wcid, Elem->Msg, Elem->MsgLen)) { pDelFrame = (PFRAME_DELBA_REQ)(&Elem->Msg[0]); if (pDelFrame->DelbaParm.Initiator == ORIGINATOR) { DBGPRINT(RT_DEBUG_TRACE,("BA - PeerDelBAAction----> ORIGINATOR\n")); BARecSessionTearDown(pAd, Elem->Wcid, pDelFrame->DelbaParm.TID, TRUE); } else { DBGPRINT(RT_DEBUG_TRACE,("BA - PeerDelBAAction----> RECIPIENT, Reason = %d\n", pDelFrame->ReasonCode)); //hex_dump("DelBA Frame", pDelFrame, Elem->MsgLen); BAOriSessionTearDown(pAd, Elem->Wcid, pDelFrame->DelbaParm.TID, TRUE, FALSE); } }}BOOLEAN CntlEnqueueForRecv( IN PRTMP_ADAPTER pAd, IN ULONG Wcid, IN ULONG MsgLen, IN PFRAME_BA_REQ pMsg) { PFRAME_BA_REQ pFrame = pMsg; //PRTMP_REORDERBUF pBuffer; //PRTMP_REORDERBUF pDmaBuf; PBA_REC_ENTRY pBAEntry; //BOOLEAN Result; ULONG Idx; //UCHAR NumRxPkt; UCHAR TID;//, i; TID = (UCHAR)pFrame->BARControl.TID; DBGPRINT(RT_DEBUG_ERROR, ("BAR(%ld) : Tid (%d)\n", Wcid, TID)); //hex_dump("BAR", (PCHAR) pFrame, MsgLen); // Do nothing if the driver is starting halt state. // This might happen when timer already been fired before cancel timer with mlmehalt if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS)) return FALSE; // First check the size, it MUST not exceed the mlme queue size if (MsgLen > MGMT_DMA_BUFFER_SIZE) { DBGPRINT_ERR(("CntlEnqueueForRecv: frame too large, size = %ld \n", MsgLen)); return FALSE; } else if (MsgLen != sizeof(FRAME_BA_REQ)) { DBGPRINT_ERR(("CntlEnqueueForRecv: BlockAck Request frame length size = %ld incorrect\n", MsgLen)); return FALSE; } else if (MsgLen != sizeof(FRAME_BA_REQ)) { DBGPRINT_ERR(("CntlEnqueueForRecv: BlockAck Request frame length size = %ld incorrect\n", MsgLen)); return FALSE; } if ((Wcid < MAX_LEN_OF_MAC_TABLE) && (TID < 8)) { // if this receiving packet is from SA that is in our OriEntry. Since WCID <9 has direct mapping. no need search. Idx = pAd->MacTab.Content[Wcid].BARecWcidArray[TID]; pBAEntry = &pAd->BATable.BARecEntry[Idx]; } else { return FALSE; } //printk("BAR Seq = %x, LastIndSeq = %x\n", pFrame->BAStartingSeq.field.StartSeq, pBAEntry->LastIndSeq); ba_indicate_reordering_mpdus_le_seq(pAd, pBAEntry, pFrame->BAStartingSeq.field.StartSeq); pBAEntry->LastIndSeq = (pFrame->BAStartingSeq.field.StartSeq == 0) ? MAXSEQ :(pFrame->BAStartingSeq.field.StartSeq -1); //ba_refresh_reordering_mpdus(pAd, pBAEntry); return TRUE;}/*Description : Send PSMP Action frame If PSMP mode switches.*/VOID SendPSMPAction( IN PRTMP_ADAPTER pAd, IN UCHAR Wcid, IN UCHAR Psmp) { PUCHAR pOutBuffer = NULL; NDIS_STATUS NStatus; //ULONG Idx; FRAME_PSMP_ACTION Frame; ULONG FrameLen; NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); //Get an unused nonpaged memory if (NStatus != NDIS_STATUS_SUCCESS) { DBGPRINT(RT_DEBUG_ERROR,("BA - MlmeADDBAAction() allocate memory failed \n")); return; } #ifdef CONFIG_STA_SUPPORT ActHeaderInit(pAd, &Frame.Hdr, pAd->CommonCfg.Bssid, pAd->CurrentAddress, pAd->MacTab.Content[Wcid].Addr);#endif // CONFIG_STA_SUPPORT // Frame.Category = CATEGORY_HT; Frame.Action = SMPS_ACTION; switch (Psmp) { case MMPS_ENABLE: Frame.Psmp = 0; break; case MMPS_DYNAMIC: Frame.Psmp = 3; break; case MMPS_STATIC: Frame.Psmp = 1; break; } MakeOutgoingFrame(pOutBuffer, &FrameLen, sizeof(FRAME_PSMP_ACTION), &Frame, END_OF_ARGS); MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer, FrameLen); MlmeFreeMemory(pAd, pOutBuffer); DBGPRINT(RT_DEBUG_ERROR,("HT - SendPSMPAction( %d ) \n", Frame.Psmp));}#define RADIO_MEASUREMENT_REQUEST_ACTION 0typedef struct PACKED{ UCHAR RegulatoryClass; UCHAR ChannelNumber; USHORT RandomInterval; USHORT MeasurementDuration; UCHAR MeasurementMode; UCHAR BSSID[MAC_ADDR_LEN]; UCHAR ReportingCondition; UCHAR Threshold; UCHAR SSIDIE[2]; // 2 byte} BEACON_REQUEST;typedef struct PACKED{ UCHAR ID; UCHAR Length; UCHAR Token; UCHAR RequestMode; UCHAR Type;} MEASUREMENT_REQ;void convert_reordering_packet_to_preAMSDU_or_802_3_packet( IN PRTMP_ADAPTER pAd, IN RX_BLK *pRxBlk, IN UCHAR FromWhichBSSID){ PNDIS_PACKET pRxPkt; UCHAR Header802_3[LENGTH_802_3]; // 1. get 802.3 Header // 2. remove LLC // a. pointer pRxBlk->pData to payload // b. modify pRxBlk->DataSize RTMP_802_11_REMOVE_LLC_AND_CONVERT_TO_802_3(pRxBlk, Header802_3); ASSERT(pRxBlk->pRxPacket); pRxPkt = RTPKT_TO_OSPKT(pRxBlk->pRxPacket); RTPKT_TO_OSPKT(pRxPkt)->dev = get_netdev_from_bssid(pAd, FromWhichBSSID); RTPKT_TO_OSPKT(pRxPkt)->data = pRxBlk->pData; RTPKT_TO_OSPKT(pRxPkt)->len = pRxBlk->DataSize; RTPKT_TO_OSPKT(pRxPkt)->tail = RTPKT_TO_OSPKT(pRxPkt)->data + RTPKT_TO_OSPKT(pRxPkt)->len; // // copy 802.3 header, if necessary // if (!RX_BLK_TEST_FLAG(pRxBlk, fRX_AMSDU)) {#ifdef CONFIG_STA_SUPPORT#ifdef LINUX NdisMoveMemory(skb_push(pRxPkt, LENGTH_802_3), Header802_3, LENGTH_802_3);#endif#ifdef UCOS NdisMoveMemory(net_pkt_push(pRxPkt, LENGTH_802_3), Header802_3, LENGTH_802_3);#endif #endif // CONFIG_STA_SUPPORT // }}#define INDICATE_LEGACY_OR_AMSDU(_pAd, _pRxBlk, _fromWhichBSSID) \ do \ { \ if (RX_BLK_TEST_FLAG(_pRxBlk, fRX_AMSDU)) \ { \ Indicate_AMSDU_Packet(_pAd, _pRxBlk, _fromWhichBSSID); \ } \ else \ { \ Indicate_Legacy_Packet(_pAd, _pRxBlk, _fromWhichBSSID); \ } \ } while (0);static VOID ba_enqueue_reordering_packet( IN PRTMP_ADAPTER pAd, IN PBA_REC_ENTRY pBAEntry, IN RX_BLK *pRxBlk, IN UCHAR FromWhichBSSID){ struct reordering_mpdu *mpdu_blk; UINT16 Sequence = (UINT16) pRxBlk->pHeader->Sequence; mpdu_blk = ba_mpdu_blk_alloc(pAd); if (mpdu_blk != NULL) { // Write RxD buffer address & allocated buffer length NdisAcquireSpinLock(&pBAEntry->RxReRingLock); mpdu_blk->Sequence = Sequence; mpdu_blk->bAMSDU = RX_BLK_TEST_FLAG(pRxBlk, fRX_AMSDU); convert_reordering_packet_to_preAMSDU_or_802_3_packet(pAd, pRxBlk, FromWhichBSSID); STATS_INC_RX_PACKETS(pAd, FromWhichBSSID); // // it is necessary for reordering packet to record // which BSS it come from // RTMP_SET_PACKET_IF(pRxBlk->pRxPacket, FromWhichBSSID); mpdu_blk->pPacket = pRxBlk->pRxPacket; if (ba_reordering_mpdu_insertsorted(&pBAEntry->list, mpdu_blk) == FALSE) { // had been already within reordering list // don't indicate RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_SUCCESS); ba_mpdu_blk_free(pAd, mpdu_blk); } ASSERT((0<= pBAEntry->list.qlen) && (pBAEntry->list.qlen <= pBAEntry->BAWinSize)); NdisReleaseSpinLock(&pBAEntry->RxReRingLock); } else { DBGPRINT(RT_DEBUG_ERROR, ("!!! (%d:%d) Can't allocate reordering mpdu blk\n", blk_count, pBAEntry->list.qlen)); /* * flush all pending reordering mpdus * and receving mpdu to upper layer * make tcp/ip to take care reordering mechanism */ //ba_refresh_reordering_mpdus(pAd, pBAEntry); ba_indicate_reordering_mpdus_le_seq(pAd, pBAEntry, Sequence); pBAEntry->LastIndSeq = Sequence; INDICATE_LEGACY_OR_AMSDU(pAd, pRxBlk, FromWhichBSSID); }}/* ========================================================================== Description: Indicate this packet to upper layer or put it into reordering buffer Parametrs: pRxBlk : carry necessary packet info 802.11 format FromWhichBSSID : the packet received from which BSS Return : none Note : the packet queued into reordering buffer need to cover to 802.3 format or pre_AMSDU format ========================================================================== */VOID Indicate_AMPDU_Packet( IN PRTMP_ADAPTER pAd, IN RX_BLK *pRxBlk, IN UCHAR FromWhichBSSID){ USHORT Idx; PBA_REC_ENTRY pBAEntry = NULL; UINT16 Sequence = pRxBlk->pHeader->Sequence; ULONG Now32; UCHAR Wcid = pRxBlk->pRxWI->WirelessCliID; UCHAR TID = pRxBlk->pRxWI->TID; if (!RX_BLK_TEST_FLAG(pRxBlk, fRX_AMSDU) && (pRxBlk->DataSize > 1520)) { static int err_size; err_size++; if (err_size > 20) { printk("AMPDU DataSize = %d\n", pRxBlk->DataSize); hex_dump("802.11 Header", (UCHAR *)pRxBlk->pHeader, 24); hex_dump("Payload", pRxBlk->pData, 64); err_size = 0; } // release packet RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE); return; } if (Wcid < MAX_LEN_OF_MAC_TABLE) { Idx = pAd->MacTab.Content[Wcid].BARecWcidArray[TID]; if (Idx == 0) { /* Rec BA Session had been torn down */ INDICATE_LEGACY_OR_AMSDU(pAd, pRxBlk, FromWhichBSSID); return; } pBAEntry = &pAd->BATable.BARecEntry[Idx]; } else { // impossible !!! ASSERT(0); // release packet RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE); return; } ASSERT(pBAEntry); // update last rx time NdisGetSystemUpTime(&Now32); pBAEntry->rcvSeq = Sequence; ba_flush_reordering_timeout_mpdus(pAd, pBAEntry, Now32); pBAEntry->LastIndSeqAtTimer = Now32; // // Reset Last Indicate Sequence // if (pBAEntry->LastIndSeq == RESET_RCV_SEQ) { ASSERT((pBAEntry->list.qlen == 0) && (pBAEntry->list.next == NULL)); // reset rcv sequence of BA session pBAEntry->LastIndSeq = Sequence; pBAEntry->LastIndSeqAtTimer = Now32; INDICATE_LEGACY_OR_AMSDU(pAd, pRxBlk, FromWhichBSSID); return; } // // I. Check if in order. // if (SEQ_STEPONE(Sequence, pBAEntry->LastIndSeq, MAXSEQ)) { USHORT LastIndSeq; pBAEntry->LastIndSeq = Sequence; INDICATE_LEGACY_OR_AMSDU(pAd, pRxBlk, FromWhichBSSID); LastIndSeq = ba_indicate_reordering_mpdus_in_order(pAd, pBAEntry, pBAEntry->LastIndSeq); if (LastIndSeq != RESET_RCV_SEQ) { pBAEntry->LastIndSeq = LastIndSeq; } pBAEntry->LastIndSeqAtTimer = Now32; } // // II. Drop Duplicated Packet // else if (Sequence == pBAEntry->LastIndSeq) { DBGPRINT(RT_DEBUG_INFO, ("Duplicated receive pHeader->Sequence = 0x%x ,LastIndSeq = 0x%x. drop \n" , Sequence, pBAEntry->LastIndSeq)); // drop and release packet pBAEntry->nDropPacket++; RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE); } // // III. Drop Old Received Packet // else if (SEQ_SMALLER(Sequence, pBAEntry->LastIndSeq, MAXSEQ)) { DBGPRINT(RT_DEBUG_INFO, ("Rcv old pHeader->Sequence = 0x%x ,LastIndSeq = 0x%x. drop \n" , Sequence, pBAEntry->LastIndSeq)); // drop and release packet pBAEntry->nDropPacket++; RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE); } // // IV. Receive Sequence within Window Size // else if (SEQ_SMALLER(Sequence, (((pBAEntry->LastIndSeq+pBAEntry->BAWinSize+1)) & MAXSEQ), MAXSEQ)) { ba_enqueue_reordering_packet(pAd, pBAEntry, pRxBlk, FromWhichBSSID); } // // V. Receive seq surpasses Win(lastseq + nMSDU). So refresh all reorder buffer // else { LONG WinStartSeq, TmpSeq; DBGPRINT(RT_DEBUG_INFO, ("%lu: Refresh. Sequence=0x%x, #RxPkt = %d. LastIndSeq = 0x%x.\n", Now32, Sequence, pBAEntry->list.qlen, pBAEntry->LastIndSeq)); TmpSeq = Sequence - (pBAEntry->BAWinSize) -1; if (TmpSeq < 0) { TmpSeq = (MAXSEQ+1) + TmpSeq; } WinStartSeq = (TmpSeq+1) & MAXSEQ; ba_indicate_reordering_mpdus_le_seq(pAd, pBAEntry, WinStartSeq); pBAEntry->LastIndSeq = WinStartSeq; //TmpSeq; pBAEntry->LastIndSeqAtTimer = Now32; ba_enqueue_reordering_packet(pAd, pBAEntry, pRxBlk, FromWhichBSSID); TmpSeq = ba_indicate_reordering_mpdus_in_order(pAd, pBAEntry, pBAEntry->LastIndSeq); if (TmpSeq != RESET_RCV_SEQ) { pBAEntry->LastIndSeq = TmpSeq; } }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -