void TsInitDelBA( struct ieee80211_device *ieee, PTS_COMMON_INFO pTsCommonInfo, TR_SELECT TxRxSelect) { if(TxRxSelect == TX_DIR) { PTX_TS_RECORD pTxTs = (PTX_TS_RECORD)pTsCommonInfo; if(TxTsDeleteBA(ieee, pTxTs)) ieee80211_send_DELBA( ieee, pTsCommonInfo->Addr, (pTxTs->TxAdmittedBARecord.bValid)?(&pTxTs->TxAdmittedBARecord):(&pTxTs->TxPendingBARecord), TxRxSelect, DELBA_REASON_END_BA); } else if(TxRxSelect == RX_DIR) { PRX_TS_RECORD pRxTs = (PRX_TS_RECORD)pTsCommonInfo; if(RxTsDeleteBA(ieee, pRxTs)) ieee80211_send_DELBA( ieee, pTsCommonInfo->Addr, &pRxTs->RxAdmittedBARecord, TxRxSelect, DELBA_REASON_END_BA ); } }
void TxBaInactTimeout(unsigned long data) { PTX_TS_RECORD pTxTs = (PTX_TS_RECORD)data; struct ieee80211_device *ieee = container_of(pTxTs, struct ieee80211_device, TxTsRecord[pTxTs->num]); TxTsDeleteBA(ieee, pTxTs); ieee80211_send_DELBA( ieee, pTxTs->TsCommonInfo.Addr, &pTxTs->TxAdmittedBARecord, TX_DIR, DELBA_REASON_TIMEOUT); }
void RxBaInactTimeout(unsigned long data) { PRX_TS_RECORD pRxTs = (PRX_TS_RECORD)data; struct ieee80211_device *ieee = container_of(pRxTs, struct ieee80211_device, RxTsRecord[pRxTs->num]); RxTsDeleteBA(ieee, pRxTs); ieee80211_send_DELBA( ieee, pRxTs->TsCommonInfo.Addr, &pRxTs->RxAdmittedBARecord, RX_DIR, DELBA_REASON_TIMEOUT); return ; }
/******************************************************************************************************************** *function: RX ADDBARSP * input: struct sk_buff * skb //incoming ADDBAReq skb. * return: 0(pass), other(fail) * notice: As this function need support of QOS, I comment some code out. And when qos is ready, this code need to be support. ********************************************************************************************************************/ int ieee80211_rx_ADDBARsp(struct ieee80211_device *ieee, struct sk_buff *skb) { struct rtl_80211_hdr_3addr *rsp = NULL; PBA_RECORD pPendingBA, pAdmittedBA; PTX_TS_RECORD pTS = NULL; u8 *dst = NULL, *pDialogToken = NULL, *tag = NULL; u16 *pStatusCode = NULL, *pBaTimeoutVal = NULL; PBA_PARAM_SET pBaParamSet = NULL; u16 ReasonCode; if (skb->len < sizeof(struct rtl_80211_hdr_3addr) + 9) { IEEE80211_DEBUG(IEEE80211_DL_ERR, " Invalid skb len in BARSP(%d / %zu)\n", skb->len, (sizeof(struct rtl_80211_hdr_3addr) + 9)); return -1; } rsp = (struct rtl_80211_hdr_3addr *)skb->data; tag = (u8 *)rsp; dst = &rsp->addr2[0]; tag += sizeof(struct rtl_80211_hdr_3addr); pDialogToken = tag + 2; pStatusCode = (u16 *)(tag + 3); pBaParamSet = (PBA_PARAM_SET)(tag + 5); pBaTimeoutVal = (u16 *)(tag + 7); // Check the capability // Since we can always receive A-MPDU, we just check if it is under HT mode. if (ieee->current_network.qos_data.active == 0 || !ieee->pHTInfo->bCurrentHTSupport || !ieee->pHTInfo->bCurrentAMPDUEnable) { IEEE80211_DEBUG(IEEE80211_DL_ERR, "reject to ADDBA_RSP as some capability is not ready(%d, %d, %d)\n",ieee->current_network.qos_data.active, ieee->pHTInfo->bCurrentHTSupport, ieee->pHTInfo->bCurrentAMPDUEnable); ReasonCode = DELBA_REASON_UNKNOWN_BA; goto OnADDBARsp_Reject; } // // Search for related TS. // If there is no TS found, we wil reject ADDBA Rsp by sending DELBA frame. // if (!GetTs( ieee, (PTS_COMMON_INFO *)(&pTS), dst, (u8)(pBaParamSet->field.TID), TX_DIR, false) ) { IEEE80211_DEBUG(IEEE80211_DL_ERR, "can't get TS in %s()\n", __func__); ReasonCode = DELBA_REASON_UNKNOWN_BA; goto OnADDBARsp_Reject; } pTS->bAddBaReqInProgress = false; pPendingBA = &pTS->TxPendingBARecord; pAdmittedBA = &pTS->TxAdmittedBARecord; // // Check if related BA is waiting for setup. // If not, reject by sending DELBA frame. // if (pAdmittedBA->bValid) { // Since BA is already setup, we ignore all other ADDBA Response. IEEE80211_DEBUG(IEEE80211_DL_BA, "OnADDBARsp(): Recv ADDBA Rsp. Drop because already admit it! \n"); return -1; } else if((!pPendingBA->bValid) ||(*pDialogToken != pPendingBA->DialogToken)) { IEEE80211_DEBUG(IEEE80211_DL_ERR, "OnADDBARsp(): Recv ADDBA Rsp. BA invalid, DELBA! \n"); ReasonCode = DELBA_REASON_UNKNOWN_BA; goto OnADDBARsp_Reject; } else { IEEE80211_DEBUG(IEEE80211_DL_BA, "OnADDBARsp(): Recv ADDBA Rsp. BA is admitted! Status code:%X\n", *pStatusCode); DeActivateBAEntry(ieee, pPendingBA); } if(*pStatusCode == ADDBA_STATUS_SUCCESS) { // // Determine ADDBA Rsp content here. // We can compare the value of BA parameter set that Peer returned and Self sent. // If it is OK, then admitted. Or we can send DELBA to cancel BA mechanism. // if (pBaParamSet->field.BAPolicy == BA_POLICY_DELAYED) { // Since this is a kind of ADDBA failed, we delay next ADDBA process. pTS->bAddBaReqDelayed = true; DeActivateBAEntry(ieee, pAdmittedBA); ReasonCode = DELBA_REASON_END_BA; goto OnADDBARsp_Reject; } // // Admitted condition // pAdmittedBA->DialogToken = *pDialogToken; pAdmittedBA->BaTimeoutValue = *pBaTimeoutVal; pAdmittedBA->BaStartSeqCtrl = pPendingBA->BaStartSeqCtrl; pAdmittedBA->BaParamSet = *pBaParamSet; DeActivateBAEntry(ieee, pAdmittedBA); ActivateBAEntry(ieee, pAdmittedBA, *pBaTimeoutVal); } else { // Delay next ADDBA process. pTS->bAddBaReqDelayed = true; } // End of procedure return 0; OnADDBARsp_Reject: { BA_RECORD BA; BA.BaParamSet = *pBaParamSet; ieee80211_send_DELBA(ieee, dst, &BA, TX_DIR, ReasonCode); return 0; } }
int ieee80211_rx_ADDBARsp( struct ieee80211_device* ieee, struct sk_buff *skb) { struct ieee80211_hdr_3addr* rsp = NULL; PBA_RECORD pPendingBA, pAdmittedBA; PTX_TS_RECORD pTS = NULL; u8* dst = NULL, *pDialogToken = NULL, *tag = NULL; u16* pStatusCode = NULL, *pBaTimeoutVal = NULL; PBA_PARAM_SET pBaParamSet = NULL; u16 ReasonCode; if (skb->len < sizeof( struct ieee80211_hdr_3addr) + 9) { IEEE80211_DEBUG(IEEE80211_DL_ERR, " Invalid skb len in BARSP(%d / %zu)\n", skb->len, (sizeof( struct ieee80211_hdr_3addr) + 9)); return -1; } rsp = ( struct ieee80211_hdr_3addr*)skb->data; tag = (u8*)rsp; dst = (u8*)(&rsp->addr2[0]); tag += sizeof( struct ieee80211_hdr_3addr); pDialogToken = tag + 2; pStatusCode = (u16*)(tag + 3); pBaParamSet = (PBA_PARAM_SET)(tag + 5); pBaTimeoutVal = (u16*)(tag + 7); // // if( ieee->current_network.qos_data.active == 0 || ieee->pHTInfo->bCurrentHTSupport == false || ieee->pHTInfo->bCurrentAMPDUEnable == false ) { IEEE80211_DEBUG(IEEE80211_DL_ERR, "reject to ADDBA_RSP as some capability is not ready(%d, %d, %d)\n",ieee->current_network.qos_data.active, ieee->pHTInfo->bCurrentHTSupport, ieee->pHTInfo->bCurrentAMPDUEnable); ReasonCode = DELBA_REASON_UNKNOWN_BA; goto OnADDBARsp_Reject; } // // // // if (!GetTs( ieee, (PTS_COMMON_INFO*)(&pTS), dst, (u8)(pBaParamSet->field.TID), TX_DIR, false) ) { IEEE80211_DEBUG(IEEE80211_DL_ERR, "can't get TS in %s()\n", __FUNCTION__); ReasonCode = DELBA_REASON_UNKNOWN_BA; goto OnADDBARsp_Reject; } pTS->bAddBaReqInProgress = false; pPendingBA = &pTS->TxPendingBARecord; pAdmittedBA = &pTS->TxAdmittedBARecord; // // // // if((pAdmittedBA->bValid==true)) { // IEEE80211_DEBUG(IEEE80211_DL_BA, "OnADDBARsp(): Recv ADDBA Rsp. Drop because already admit it! \n"); return -1; } else if((pPendingBA->bValid == false) ||(*pDialogToken != pPendingBA->DialogToken)) { IEEE80211_DEBUG(IEEE80211_DL_ERR, "OnADDBARsp(): Recv ADDBA Rsp. BA invalid, DELBA! \n"); ReasonCode = DELBA_REASON_UNKNOWN_BA; goto OnADDBARsp_Reject; } else { IEEE80211_DEBUG(IEEE80211_DL_BA, "OnADDBARsp(): Recv ADDBA Rsp. BA is admitted! Status code:%X\n", *pStatusCode); DeActivateBAEntry(ieee, pPendingBA); } if(*pStatusCode == ADDBA_STATUS_SUCCESS) { // // // // // if(pBaParamSet->field.BAPolicy == BA_POLICY_DELAYED) { // pTS->bAddBaReqDelayed = true; DeActivateBAEntry(ieee, pAdmittedBA); ReasonCode = DELBA_REASON_END_BA; goto OnADDBARsp_Reject; } // // // pAdmittedBA->DialogToken = *pDialogToken; pAdmittedBA->BaTimeoutValue = *pBaTimeoutVal; pAdmittedBA->BaStartSeqCtrl = pPendingBA->BaStartSeqCtrl; pAdmittedBA->BaParamSet = *pBaParamSet; DeActivateBAEntry(ieee, pAdmittedBA); ActivateBAEntry(ieee, pAdmittedBA, *pBaTimeoutVal); } else { // pTS->bAddBaReqDelayed = true; } // return 0; OnADDBARsp_Reject: { BA_RECORD BA; BA.BaParamSet = *pBaParamSet; ieee80211_send_DELBA(ieee, dst, &BA, TX_DIR, ReasonCode); return 0; } }