int rtllib_rx_DELBA(struct rtllib_device *ieee, struct sk_buff *skb) { struct rtllib_hdr_3addr *delba = NULL; union delba_param_set *pDelBaParamSet = NULL; u16 *pReasonCode = NULL; u8 *dst = NULL; if (skb->len < sizeof(struct rtllib_hdr_3addr) + 6) { RTLLIB_DEBUG(RTLLIB_DL_ERR, " Invalid skb len in DELBA(%d /" " %d)\n", (int)skb->len, (int)(sizeof(struct rtllib_hdr_3addr) + 6)); return -1; } if (ieee->current_network.qos_data.active == 0 || ieee->pHTInfo->bCurrentHTSupport == false) { RTLLIB_DEBUG(RTLLIB_DL_ERR, "received DELBA while QOS or HT " "is not supported(%d, %d)\n", ieee->current_network. qos_data.active, ieee->pHTInfo->bCurrentHTSupport); return -1; } RTLLIB_DEBUG_DATA(RTLLIB_DL_DATA|RTLLIB_DL_BA, skb->data, skb->len); delba = (struct rtllib_hdr_3addr *)skb->data; dst = (u8 *)(&delba->addr2[0]); delba += sizeof(struct rtllib_hdr_3addr); pDelBaParamSet = (union delba_param_set *)(delba+2); pReasonCode = (u16 *)(delba+4); if (pDelBaParamSet->field.Initiator == 1) { struct rx_ts_record *pRxTs; if (!GetTs(ieee, (struct ts_common_info **)&pRxTs, dst, (u8)pDelBaParamSet->field.TID, RX_DIR, false)) { RTLLIB_DEBUG(RTLLIB_DL_ERR, "can't get TS for RXTS in " "%s().dst: %pM TID:%d\n", __func__, dst, (u8)pDelBaParamSet->field.TID); return -1; } RxTsDeleteBA(ieee, pRxTs); } else { struct tx_ts_record *pTxTs; if (!GetTs(ieee, (struct ts_common_info **)&pTxTs, dst, (u8)pDelBaParamSet->field.TID, TX_DIR, false)) { RTLLIB_DEBUG(RTLLIB_DL_ERR, "can't get TS for TXTS in " "%s()\n", __func__); return -1; } pTxTs->bUsingBa = false; pTxTs->bAddBaReqInProgress = false; pTxTs->bAddBaReqDelayed = false; del_timer_sync(&pTxTs->TsAddBaTimer); TxTsDeleteBA(ieee, pTxTs); } return 0; }
void rtl8723e_dm_bt_reject_ap_aggregated_packet(struct ieee80211_hw *hw, bool b_reject) { #if 0 struct rtl_priv rtlpriv = rtl_priv(hw); PRX_TS_RECORD pRxTs = NULL; if(b_reject){ // Do not allow receiving A-MPDU aggregation. if (rtlpriv->mac80211.vendor == PEER_CISCO) { if (pHTInfo->bAcceptAddbaReq) { RTPRINT(FBT, BT_TRACE, ("BT_Disallow AMPDU \n")); pHTInfo->bAcceptAddbaReq = FALSE; if(GetTs(Adapter, (PTS_COMMON_INFO*)(&pRxTs), pMgntInfo->Bssid, 0, RX_DIR, FALSE)) TsInitDelBA(Adapter, (PTS_COMMON_INFO)pRxTs, RX_DIR); } } else { if (!pHTInfo->bAcceptAddbaReq) { RTPRINT(FBT, BT_TRACE, ("BT_Allow AMPDU BT Idle\n")); pHTInfo->bAcceptAddbaReq = TRUE; } } } else { if(rtlpriv->mac80211.vendor == PEER_CISCO) { if (!pHTInfo->bAcceptAddbaReq) { RTPRINT(FBT, BT_TRACE, ("BT_Allow AMPDU \n")); pHTInfo->bAcceptAddbaReq = TRUE; } } } #endif }
void ieee80211_query_seqnum(struct ieee80211_device*ieee, struct sk_buff* skb, u8* dst) { if (is_multicast_ether_addr(dst) || is_broadcast_ether_addr(dst)) return; if (IsQoSDataFrame(skb->data)) //we deal qos data only { PTX_TS_RECORD pTS = NULL; if (!GetTs(ieee, (PTS_COMMON_INFO*)(&pTS), dst, skb->priority, TX_DIR, true)) { return; } pTS->TxCurSeq = (pTS->TxCurSeq+1)%4096; } }
u16 rtllib_query_seqnum(struct rtllib_device *ieee, struct sk_buff *skb, u8 *dst) { u16 seqnum = 0; if (is_multicast_ether_addr(dst)) return 0; if (IsQoSDataFrame(skb->data)) { struct tx_ts_record *pTS = NULL; if (!GetTs(ieee, (struct ts_common_info **)(&pTS), dst, skb->priority, TX_DIR, true)) return 0; seqnum = pTS->TxCurSeq; pTS->TxCurSeq = (pTS->TxCurSeq+1)%4096; return seqnum; } return 0; }
u16 rtllib_query_seqnum(struct rtllib_device*ieee, struct sk_buff* skb, u8* dst) { u16 seqnum = 0; if (is_multicast_ether_addr(dst) || is_broadcast_ether_addr(dst)) return 0; if (IsQoSDataFrame(skb->data)) { PTX_TS_RECORD pTS = NULL; if (!GetTs(ieee, (PTS_COMMON_INFO*)(&pTS), dst, skb->priority, TX_DIR, true)) { return 0; } seqnum = pTS->TxCurSeq; pTS->TxCurSeq = (pTS->TxCurSeq+1)%4096; return seqnum; } return 0; }
/******************************************************************************************************************** *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; } }
/******************************************************************************************************************** *function: RX ADDBAReq * 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_ADDBAReq(struct ieee80211_device *ieee, struct sk_buff *skb) { struct rtl_80211_hdr_3addr *req = NULL; u16 rc = 0; u8 *dst = NULL, *pDialogToken = NULL, *tag = NULL; PBA_RECORD pBA = NULL; PBA_PARAM_SET pBaParamSet = NULL; u16 *pBaTimeoutVal = NULL; PSEQUENCE_CONTROL pBaStartSeqCtrl = NULL; PRX_TS_RECORD pTS = NULL; if (skb->len < sizeof(struct rtl_80211_hdr_3addr) + 9) { IEEE80211_DEBUG(IEEE80211_DL_ERR, " Invalid skb len in BAREQ(%d / %zu)\n", skb->len, (sizeof(struct rtl_80211_hdr_3addr) + 9)); return -1; } IEEE80211_DEBUG_DATA(IEEE80211_DL_DATA|IEEE80211_DL_BA, skb->data, skb->len); req = (struct rtl_80211_hdr_3addr *) skb->data; tag = (u8 *)req; dst = &req->addr2[0]; tag += sizeof(struct rtl_80211_hdr_3addr); pDialogToken = tag + 2; //category+action pBaParamSet = (PBA_PARAM_SET)(tag + 3); //+DialogToken pBaTimeoutVal = (u16 *)(tag + 5); pBaStartSeqCtrl = (PSEQUENCE_CONTROL)(req + 7); printk(KERN_INFO "====================>rx ADDBAREQ from :%pM\n", dst); //some other capability is not ready now. if ((ieee->current_network.qos_data.active == 0) || (!ieee->pHTInfo->bCurrentHTSupport)) //|| // (!ieee->pStaQos->bEnableRxImmBA) ) { rc = ADDBA_STATUS_REFUSED; IEEE80211_DEBUG(IEEE80211_DL_ERR, "Failed to reply on ADDBA_REQ as some capability is not ready(%d, %d)\n", ieee->current_network.qos_data.active, ieee->pHTInfo->bCurrentHTSupport); goto OnADDBAReq_Fail; } // Search for related traffic stream. // If there is no matched TS, reject the ADDBA request. if (!GetTs( ieee, (PTS_COMMON_INFO *)(&pTS), dst, (u8)(pBaParamSet->field.TID), RX_DIR, true) ) { rc = ADDBA_STATUS_REFUSED; IEEE80211_DEBUG(IEEE80211_DL_ERR, "can't get TS in %s()\n", __func__); goto OnADDBAReq_Fail; } pBA = &pTS->RxAdmittedBARecord; // To Determine the ADDBA Req content // We can do much more check here, including BufferSize, AMSDU_Support, Policy, StartSeqCtrl... // I want to check StartSeqCtrl to make sure when we start aggregation!!! // if (pBaParamSet->field.BAPolicy == BA_POLICY_DELAYED) { rc = ADDBA_STATUS_INVALID_PARAM; IEEE80211_DEBUG(IEEE80211_DL_ERR, "BA Policy is not correct in %s()\n", __func__); goto OnADDBAReq_Fail; } // Admit the ADDBA Request // DeActivateBAEntry(ieee, pBA); pBA->DialogToken = *pDialogToken; pBA->BaParamSet = *pBaParamSet; pBA->BaTimeoutValue = *pBaTimeoutVal; pBA->BaStartSeqCtrl = *pBaStartSeqCtrl; //for half N mode we only aggregate 1 frame if (ieee->GetHalfNmodeSupportByAPsHandler(ieee->dev)) pBA->BaParamSet.field.BufferSize = 1; else pBA->BaParamSet.field.BufferSize = 32; ActivateBAEntry(ieee, pBA, pBA->BaTimeoutValue); ieee80211_send_ADDBARsp(ieee, dst, pBA, ADDBA_STATUS_SUCCESS); // End of procedure. return 0; OnADDBAReq_Fail: { BA_RECORD BA; BA.BaParamSet = *pBaParamSet; BA.BaTimeoutValue = *pBaTimeoutVal; BA.DialogToken = *pDialogToken; BA.BaParamSet.field.BAPolicy = BA_POLICY_IMMEDIATE; ieee80211_send_ADDBARsp(ieee, dst, &BA, rc); return 0; //we send RSP out. } }
void ieee80211_tx_query_agg_cap(struct ieee80211_device* ieee, struct sk_buff* skb, cb_desc* tcb_desc) { PRT_HIGH_THROUGHPUT pHTInfo = ieee->pHTInfo; PTX_TS_RECORD pTxTs = NULL; struct ieee80211_hdr_1addr* hdr = (struct ieee80211_hdr_1addr*)skb->data; if (!pHTInfo->bCurrentHTSupport||!pHTInfo->bEnableHT) return; if (!IsQoSDataFrame(skb->data)) return; if (is_multicast_ether_addr(hdr->addr1) || is_broadcast_ether_addr(hdr->addr1)) return; //check packet and mode later #ifdef TO_DO_LIST if(pTcb->PacketLength >= 4096) return; // For RTL819X, if pairwisekey = wep/tkip, we don't aggrregation. if(!Adapter->HalFunc.GetNmodeSupportBySecCfgHandler(Adapter)) return; #endif if(!ieee->GetNmodeSupportBySecCfg(ieee->dev)) { return; } if(pHTInfo->bCurrentAMPDUEnable) { if (!GetTs(ieee, (PTS_COMMON_INFO*)(&pTxTs), hdr->addr1, skb->priority, TX_DIR, true)) { ; return; } if (pTxTs->TxAdmittedBARecord.bValid == false) { TsStartAddBaProcess(ieee, pTxTs); goto FORCED_AGG_SETTING; } else if (pTxTs->bUsingBa == false) { if (SN_LESS(pTxTs->TxAdmittedBARecord.BaStartSeqCtrl.field.SeqNum, (pTxTs->TxCurSeq+1)%4096)) pTxTs->bUsingBa = true; else goto FORCED_AGG_SETTING; } if (ieee->iw_mode == IW_MODE_INFRA) { tcb_desc->bAMPDUEnable = true; tcb_desc->ampdu_factor = pHTInfo->CurrentAMPDUFactor; tcb_desc->ampdu_density = pHTInfo->CurrentMPDUDensity; } } FORCED_AGG_SETTING: switch(pHTInfo->ForcedAMPDUMode ) { case HT_AGG_AUTO: break; case HT_AGG_FORCE_ENABLE: tcb_desc->bAMPDUEnable = true; tcb_desc->ampdu_density = pHTInfo->ForcedMPDUDensity; tcb_desc->ampdu_factor = pHTInfo->ForcedAMPDUFactor; break; case HT_AGG_FORCE_DISABLE: tcb_desc->bAMPDUEnable = false; tcb_desc->ampdu_density = 0; tcb_desc->ampdu_factor = 0; break; } return; }
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; } }
int ieee80211_rx_ADDBAReq( struct ieee80211_device* ieee, struct sk_buff *skb) { struct ieee80211_hdr_3addr* req = NULL; u16 rc = 0; u8 * dst = NULL, *pDialogToken = NULL, *tag = NULL; PBA_RECORD pBA = NULL; PBA_PARAM_SET pBaParamSet = NULL; u16* pBaTimeoutVal = NULL; PSEQUENCE_CONTROL pBaStartSeqCtrl = NULL; PRX_TS_RECORD pTS = NULL; if (skb->len < sizeof( struct ieee80211_hdr_3addr) + 9) { IEEE80211_DEBUG(IEEE80211_DL_ERR, " Invalid skb len in BAREQ(%d / %zu)\n", skb->len, (sizeof( struct ieee80211_hdr_3addr) + 9)); return -1; } IEEE80211_DEBUG_DATA(IEEE80211_DL_DATA|IEEE80211_DL_BA, skb->data, skb->len); req = ( struct ieee80211_hdr_3addr*) skb->data; tag = (u8*)req; dst = (u8*)(&req->addr2[0]); tag += sizeof( struct ieee80211_hdr_3addr); pDialogToken = tag + 2; // pBaParamSet = (PBA_PARAM_SET)(tag + 3); // pBaTimeoutVal = (u16*)(tag + 5); pBaStartSeqCtrl = (PSEQUENCE_CONTROL)(req + 7); printk("====================>rx ADDBAREQ from :%pM\n", dst); // if( (ieee->current_network.qos_data.active == 0) || (ieee->pHTInfo->bCurrentHTSupport == false)) // // { rc = ADDBA_STATUS_REFUSED; IEEE80211_DEBUG(IEEE80211_DL_ERR, "Failed to reply on ADDBA_REQ as some capability is not ready(%d, %d)\n", ieee->current_network.qos_data.active, ieee->pHTInfo->bCurrentHTSupport); goto OnADDBAReq_Fail; } // // if( !GetTs( ieee, (PTS_COMMON_INFO*)(&pTS), dst, (u8)(pBaParamSet->field.TID), RX_DIR, true) ) { rc = ADDBA_STATUS_REFUSED; IEEE80211_DEBUG(IEEE80211_DL_ERR, "can't get TS in %s()\n", __FUNCTION__); goto OnADDBAReq_Fail; } pBA = &pTS->RxAdmittedBARecord; // // // // if(pBaParamSet->field.BAPolicy == BA_POLICY_DELAYED) { rc = ADDBA_STATUS_INVALID_PARAM; IEEE80211_DEBUG(IEEE80211_DL_ERR, "BA Policy is not correct in %s()\n", __FUNCTION__); goto OnADDBAReq_Fail; } // // DeActivateBAEntry(ieee, pBA); pBA->DialogToken = *pDialogToken; pBA->BaParamSet = *pBaParamSet; pBA->BaTimeoutValue = *pBaTimeoutVal; pBA->BaStartSeqCtrl = *pBaStartSeqCtrl; // if (ieee->GetHalfNmodeSupportByAPsHandler(ieee->dev)) pBA->BaParamSet.field.BufferSize = 1; else pBA->BaParamSet.field.BufferSize = 32; ActivateBAEntry(ieee, pBA, pBA->BaTimeoutValue); ieee80211_send_ADDBARsp(ieee, dst, pBA, ADDBA_STATUS_SUCCESS); // return 0; OnADDBAReq_Fail: { BA_RECORD BA; BA.BaParamSet = *pBaParamSet; BA.BaTimeoutValue = *pBaTimeoutVal; BA.DialogToken = *pDialogToken; BA.BaParamSet.field.BAPolicy = BA_POLICY_IMMEDIATE; ieee80211_send_ADDBARsp(ieee, dst, &BA, rc); return 0; // } }
int rtllib_rx_ADDBAReq(struct rtllib_device *ieee, struct sk_buff *skb) { struct rtllib_hdr_3addr *req = NULL; u16 rc = 0; u8 *dst = NULL, *pDialogToken = NULL, *tag = NULL; struct ba_record *pBA = NULL; union ba_param_set *pBaParamSet = NULL; u16 *pBaTimeoutVal = NULL; union sequence_control *pBaStartSeqCtrl = NULL; struct rx_ts_record *pTS = NULL; if (skb->len < sizeof(struct rtllib_hdr_3addr) + 9) { netdev_warn(ieee->dev, "Invalid skb len in BAREQ(%d / %d)\n", (int)skb->len, (int)(sizeof(struct rtllib_hdr_3addr) + 9)); return -1; } #ifdef VERBOSE_DEBUG print_hex_dump_bytes("rtllib_rx_ADDBAReq(): ", DUMP_PREFIX_NONE, skb->data, skb->len); #endif req = (struct rtllib_hdr_3addr *) skb->data; tag = (u8 *)req; dst = (u8 *)(&req->addr2[0]); tag += sizeof(struct rtllib_hdr_3addr); pDialogToken = tag + 2; pBaParamSet = (union ba_param_set *)(tag + 3); pBaTimeoutVal = (u16 *)(tag + 5); pBaStartSeqCtrl = (union sequence_control *)(req + 7); RT_TRACE(COMP_DBG, "====>rx ADDBAREQ from : %pM\n", dst); if (ieee->current_network.qos_data.active == 0 || (ieee->pHTInfo->bCurrentHTSupport == false) || (ieee->pHTInfo->IOTAction & HT_IOT_ACT_REJECT_ADDBA_REQ)) { rc = ADDBA_STATUS_REFUSED; netdev_warn(ieee->dev, "Failed to reply on ADDBA_REQ as some capability is not ready(%d, %d)\n", ieee->current_network.qos_data.active, ieee->pHTInfo->bCurrentHTSupport); goto OnADDBAReq_Fail; } if (!GetTs(ieee, (struct ts_common_info **)(&pTS), dst, (u8)(pBaParamSet->field.TID), RX_DIR, true)) { rc = ADDBA_STATUS_REFUSED; netdev_warn(ieee->dev, "%s(): can't get TS\n", __func__); goto OnADDBAReq_Fail; } pBA = &pTS->RxAdmittedBARecord; if (pBaParamSet->field.BAPolicy == BA_POLICY_DELAYED) { rc = ADDBA_STATUS_INVALID_PARAM; netdev_warn(ieee->dev, "%s(): BA Policy is not correct\n", __func__); goto OnADDBAReq_Fail; } rtllib_FlushRxTsPendingPkts(ieee, pTS); DeActivateBAEntry(ieee, pBA); pBA->DialogToken = *pDialogToken; pBA->BaParamSet = *pBaParamSet; pBA->BaTimeoutValue = *pBaTimeoutVal; pBA->BaStartSeqCtrl = *pBaStartSeqCtrl; if (ieee->GetHalfNmodeSupportByAPsHandler(ieee->dev) || (ieee->pHTInfo->IOTAction & HT_IOT_ACT_ALLOW_PEER_AGG_ONE_PKT)) pBA->BaParamSet.field.BufferSize = 1; else pBA->BaParamSet.field.BufferSize = 32; ActivateBAEntry(ieee, pBA, 0); rtllib_send_ADDBARsp(ieee, dst, pBA, ADDBA_STATUS_SUCCESS); return 0; OnADDBAReq_Fail: { struct ba_record BA; BA.BaParamSet = *pBaParamSet; BA.BaTimeoutValue = *pBaTimeoutVal; BA.DialogToken = *pDialogToken; BA.BaParamSet.field.BAPolicy = BA_POLICY_IMMEDIATE; rtllib_send_ADDBARsp(ieee, dst, &BA, rc); return 0; } }
static void rtllib_tx_query_agg_cap(struct rtllib_device *ieee, struct sk_buff *skb, struct cb_desc *tcb_desc) { struct rt_hi_throughput *pHTInfo = ieee->pHTInfo; struct tx_ts_record *pTxTs = NULL; struct rtllib_hdr_1addr *hdr = (struct rtllib_hdr_1addr *)skb->data; if (rtllib_act_scanning(ieee, false)) return; if (!pHTInfo->bCurrentHTSupport || !pHTInfo->bEnableHT) return; if (!IsQoSDataFrame(skb->data)) return; if (is_multicast_ether_addr(hdr->addr1)) return; if (tcb_desc->bdhcp || ieee->CntAfterLink < 2) return; if (pHTInfo->IOTAction & HT_IOT_ACT_TX_NO_AGGREGATION) return; if (!ieee->GetNmodeSupportBySecCfg(ieee->dev)) return; if (pHTInfo->bCurrentAMPDUEnable) { if (!GetTs(ieee, (struct ts_common_info **)(&pTxTs), hdr->addr1, skb->priority, TX_DIR, true)) { printk(KERN_INFO "%s: can't get TS\n", __func__); return; } if (pTxTs->TxAdmittedBARecord.bValid == false) { if (ieee->wpa_ie_len && (ieee->pairwise_key_type == KEY_TYPE_NA)) { ; } else if (tcb_desc->bdhcp == 1) { ; } else if (!pTxTs->bDisable_AddBa) { TsStartAddBaProcess(ieee, pTxTs); } goto FORCED_AGG_SETTING; } else if (pTxTs->bUsingBa == false) { if (SN_LESS(pTxTs->TxAdmittedBARecord.BaStartSeqCtrl.field.SeqNum, (pTxTs->TxCurSeq+1)%4096)) pTxTs->bUsingBa = true; else goto FORCED_AGG_SETTING; } if (ieee->iw_mode == IW_MODE_INFRA) { tcb_desc->bAMPDUEnable = true; tcb_desc->ampdu_factor = pHTInfo->CurrentAMPDUFactor; tcb_desc->ampdu_density = pHTInfo->CurrentMPDUDensity; } } FORCED_AGG_SETTING: switch (pHTInfo->ForcedAMPDUMode) { case HT_AGG_AUTO: break; case HT_AGG_FORCE_ENABLE: tcb_desc->bAMPDUEnable = true; tcb_desc->ampdu_density = pHTInfo->ForcedMPDUDensity; tcb_desc->ampdu_factor = pHTInfo->ForcedAMPDUFactor; break; case HT_AGG_FORCE_DISABLE: tcb_desc->bAMPDUEnable = false; tcb_desc->ampdu_density = 0; tcb_desc->ampdu_factor = 0; break; } return; }
void rtllib_tx_query_agg_cap(struct rtllib_device* ieee, struct sk_buff* skb, cb_desc* tcb_desc) { PRT_HIGH_THROUGHPUT pHTInfo = ieee->pHTInfo; PTX_TS_RECORD pTxTs = NULL; struct rtllib_hdr_1addr* hdr = (struct rtllib_hdr_1addr*)skb->data; if(tcb_desc->bBTTxPacket) return; if(rtllib_act_scanning(ieee,false)) return; if (!pHTInfo->bCurrentHTSupport||!pHTInfo->bEnableHT){ return; } if (!IsQoSDataFrame(skb->data)){ return; } if (is_multicast_ether_addr(hdr->addr1) || is_broadcast_ether_addr(hdr->addr1)){ return; } #ifdef TO_DO_LIST if(pTcb->PacketLength >= 4096) return; if(!Adapter->HalFunc.GetNmodeSupportBySecCfgHandler(Adapter)) return; #endif if(tcb_desc->bdhcp || ieee->CntAfterLink<2){ return; } if(pHTInfo->IOTAction & HT_IOT_ACT_TX_NO_AGGREGATION){ return; } if(!ieee->GetNmodeSupportBySecCfg(ieee->dev)){ return; } if(pHTInfo->bCurrentAMPDUEnable){ if (!GetTs(ieee, (PTS_COMMON_INFO*)(&pTxTs), hdr->addr1, skb->priority, TX_DIR, true)){ printk("%s: can't get TS\n", __func__); return; } if (pTxTs->TxAdmittedBARecord.bValid == false){ if (ieee->wpa_ie_len && (ieee->pairwise_key_type == KEY_TYPE_NA)) { ; } else if (tcb_desc->bdhcp == 1){ ; } else if (!pTxTs->bDisable_AddBa){ TsStartAddBaProcess(ieee, pTxTs); } goto FORCED_AGG_SETTING; } else if (pTxTs->bUsingBa == false) { if (SN_LESS(pTxTs->TxAdmittedBARecord.BaStartSeqCtrl.field.SeqNum, (pTxTs->TxCurSeq+1)%4096)) pTxTs->bUsingBa = true; else goto FORCED_AGG_SETTING; } #ifndef _RTL8192_EXT_PATCH_ #ifndef RTL8192S_WAPI_SUPPORT if (ieee->iw_mode == IW_MODE_INFRA #ifdef ASL || (ieee->iw_mode == IW_MODE_APSTA && ieee->state == RTLLIB_LINKED) #endif ) #endif #endif { tcb_desc->bAMPDUEnable = true; tcb_desc->ampdu_factor = pHTInfo->CurrentAMPDUFactor; tcb_desc->ampdu_density = pHTInfo->CurrentMPDUDensity; } } FORCED_AGG_SETTING: switch(pHTInfo->ForcedAMPDUMode ) { case HT_AGG_AUTO: break; case HT_AGG_FORCE_ENABLE: tcb_desc->bAMPDUEnable = true; tcb_desc->ampdu_density = pHTInfo->ForcedMPDUDensity; tcb_desc->ampdu_factor = pHTInfo->ForcedAMPDUFactor; break; case HT_AGG_FORCE_DISABLE: tcb_desc->bAMPDUEnable = false; tcb_desc->ampdu_density = 0; tcb_desc->ampdu_factor = 0; break; } return; }
char * CQ931Pdu::ComposeJoyitApi(UINT16& len) { char * pPdu = NULL; char pdu[MAX_MSGLEN] = { 0 }; UINT8 pos = 0; UINT16 l; int i; UINT16 msgType = GetMessageType( ); UINT8 noIe = 2; // = NoIe( ); // Make up API header. memcpy(pdu, Header, sizeof(SInterApiHead)); pos += sizeof(SInterApiHead); // #### Add 2005-10-30, by Wujianjin. ### // Construct the FIX information element first. // UINT8 pt = GetProtocolType( ); // if ((MOD_TUPAPI == pt) // || (MOD_ISUPAPI == pt) // || (MOD_Q931API == pt)) // { // Construct the fix ie first. // Message index. CIeBase * pIe; pIe = GetIE(PSG_IE_MSGTYPE); if ((pIe != NULL) && (pIe->id != IE_NOT_EXIST)) { pdu[pos++] = pIe->id; pdu[pos++] = pIe->len; memcpy(pdu+pos, pIe->GetIeData(l), pIe->len); pos += pIe->len; } else { // Not exist, I will get it from mType. pdu[pos++] = PSG_IE_MSGTYPE; pdu[pos++] = 2; // memcpy(pdu+pos, &mType, 2); memcpy(pdu+pos, &msgType, 2); pos += 2; } if (pIe != NULL) { DelIE(PSG_IE_MSGTYPE); } // Circuit structure. pIe = GetIE(PSG_IE_CIR_STRUCT); if ((pIe != NULL) && (pIe->id != IE_NOT_EXIST)) { pdu[pos++] = pIe->id; pdu[pos++] = pIe->len; memcpy(pdu+pos, pIe->GetIeData(l), pIe->len); pos += pIe->len; } else { // Exception handle. // return pPdu; pdu[pos ++] = PSG_IE_CIR_STRUCT; pdu[pos ++] = sizeof(SCircuitStructIE); SCircuitStructIE chn; chn.pcmId = GetPri( ); chn.tsId = GetTs( ); memcpy(pdu+pos, &chn, sizeof(SCircuitStructIE)); pos += sizeof(SCircuitStructIE); } if (pIe != NULL) { DelIE(PSG_IE_CIR_STRUCT); } // Circuit group indicator. pIe = GetIE(PSG_IE_CG_IND); if ((pIe != NULL) && (pIe->id != IE_NOT_EXIST)) { pdu[pos++] = pIe->id; pdu[pos++] = pIe->len; memcpy(pdu+pos, pIe->GetIeData(l), pIe->len); pos += pIe->len; ++ noIe; } if (pIe != NULL) { DelIE(PSG_IE_CG_IND); } // } // ### End 2005-10-30 ### // Make up all other IEs. for (i=0; i<NoIe( ); ++i) { if ((PSG_IE_L3_SGM == IE[i].id) // || (PSG_IE_L3_SNDCMP == IE[i].id) // Delete 2005-11-21, by Wujianjin. || (PSG_IE_L3_MOREDATA == IE[i].id) || (PSG_IE_L3_CR == IE[i].id) || (PSG_IE_L3_PTLDCM == IE[i].id) || (PSG_IE_L3_CHNID == IE[i].id)) { // noIe --; continue; } pdu[pos++] = IE[i].id; pdu[pos++] = IE[i].len; noIe ++; if ((pos + IE[i].len) >= MAX_MSGLEN) { // Message too long. printf("Joyit API too long. mType:0x%04X\n", msgType); break; } memcpy(pdu+pos, IE[i].GetIeData(l), IE[i].len); pos += IE[i].len; } // Allocate memory for this PDU. // if (i == IeCounter) // { pPdu = new char[pos]; if (pPdu != NULL) { ((SInterApiHead *)pdu)->primType = GetPrimitiveType( ); // Modify 2005-10-27, by Wujianjin. ((SInterApiHead *)pdu)->noie = noIe;; // ((SJoyitApiHead *)pdu)->PktLength = pos; memcpy(pPdu, pdu, pos); len = pos; } else { // Out of memory. printf("Make up Joyit API out of memory. mType:0x%04X\n", msgType); } // } return pPdu; }
/******************************************************************************************************************** *function: RX DELBA * 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_DELBA(struct ieee80211_device *ieee, struct sk_buff *skb) { struct rtl_80211_hdr_3addr *delba = NULL; PDELBA_PARAM_SET pDelBaParamSet = NULL; u8 *dst = NULL; if (skb->len < sizeof(struct rtl_80211_hdr_3addr) + 6) { IEEE80211_DEBUG(IEEE80211_DL_ERR, " Invalid skb len in DELBA(%d / %zu)\n", skb->len, (sizeof(struct rtl_80211_hdr_3addr) + 6)); return -1; } if (ieee->current_network.qos_data.active == 0 || !ieee->pHTInfo->bCurrentHTSupport) { IEEE80211_DEBUG(IEEE80211_DL_ERR, "received DELBA while QOS or HT is not supported(%d, %d)\n",ieee->current_network.qos_data.active, ieee->pHTInfo->bCurrentHTSupport); return -1; } IEEE80211_DEBUG_DATA(IEEE80211_DL_DATA|IEEE80211_DL_BA, skb->data, skb->len); delba = (struct rtl_80211_hdr_3addr *)skb->data; dst = &delba->addr2[0]; pDelBaParamSet = (PDELBA_PARAM_SET)&delba->payload[2]; if(pDelBaParamSet->field.Initiator == 1) { PRX_TS_RECORD pRxTs; if (!GetTs( ieee, (PTS_COMMON_INFO *)&pRxTs, dst, (u8)pDelBaParamSet->field.TID, RX_DIR, false) ) { IEEE80211_DEBUG(IEEE80211_DL_ERR, "can't get TS for RXTS in %s()\n", __func__); return -1; } RxTsDeleteBA(ieee, pRxTs); } else { PTX_TS_RECORD pTxTs; if (!GetTs( ieee, (PTS_COMMON_INFO *)&pTxTs, dst, (u8)pDelBaParamSet->field.TID, TX_DIR, false) ) { IEEE80211_DEBUG(IEEE80211_DL_ERR, "can't get TS for TXTS in %s()\n", __func__); return -1; } pTxTs->bUsingBa = false; pTxTs->bAddBaReqInProgress = false; pTxTs->bAddBaReqDelayed = false; del_timer_sync(&pTxTs->TsAddBaTimer); //PlatformCancelTimer(Adapter, &pTxTs->TsAddBaTimer); TxTsDeleteBA(ieee, pTxTs); } return 0; }
int rtllib_rx_ADDBARsp(struct rtllib_device *ieee, struct sk_buff *skb) { struct rtllib_hdr_3addr *rsp = NULL; struct ba_record *pPendingBA, *pAdmittedBA; struct tx_ts_record *pTS = NULL; u8 *dst = NULL, *pDialogToken = NULL, *tag = NULL; u16 *pStatusCode = NULL, *pBaTimeoutVal = NULL; union ba_param_set *pBaParamSet = NULL; u16 ReasonCode; if (skb->len < sizeof(struct rtllib_hdr_3addr) + 9) { netdev_warn(ieee->dev, "Invalid skb len in BARSP(%d / %d)\n", (int)skb->len, (int)(sizeof(struct rtllib_hdr_3addr) + 9)); return -1; } rsp = (struct rtllib_hdr_3addr *)skb->data; tag = (u8 *)rsp; dst = (u8 *)(&rsp->addr2[0]); tag += sizeof(struct rtllib_hdr_3addr); pDialogToken = tag + 2; pStatusCode = (u16 *)(tag + 3); pBaParamSet = (union ba_param_set *)(tag + 5); pBaTimeoutVal = (u16 *)(tag + 7); RT_TRACE(COMP_DBG, "====>rx ADDBARSP from : %pM\n", dst); if (ieee->current_network.qos_data.active == 0 || ieee->pHTInfo->bCurrentHTSupport == false || ieee->pHTInfo->bCurrentAMPDUEnable == false) { netdev_warn(ieee->dev, "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, (struct ts_common_info **)(&pTS), dst, (u8)(pBaParamSet->field.TID), TX_DIR, false)) { netdev_warn(ieee->dev, "%s(): can't get TS\n", __func__); ReasonCode = DELBA_REASON_UNKNOWN_BA; goto OnADDBARsp_Reject; } pTS->bAddBaReqInProgress = false; pPendingBA = &pTS->TxPendingBARecord; pAdmittedBA = &pTS->TxAdmittedBARecord; if (pAdmittedBA->bValid == true) { netdev_dbg(ieee->dev, "%s(): ADDBA response already admitted\n", __func__); return -1; } else if ((pPendingBA->bValid == false) || (*pDialogToken != pPendingBA->DialogToken)) { netdev_warn(ieee->dev, "%s(): ADDBA Rsp. BA invalid, DELBA!\n", __func__); ReasonCode = DELBA_REASON_UNKNOWN_BA; goto OnADDBARsp_Reject; } else { netdev_dbg(ieee->dev, "%s(): Recv ADDBA Rsp. BA is admitted! Status code:%X\n", __func__, *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; pTS->bDisable_AddBa = true; ReasonCode = DELBA_REASON_END_BA; goto OnADDBARsp_Reject; } return 0; OnADDBARsp_Reject: { struct ba_record BA; BA.BaParamSet = *pBaParamSet; rtllib_send_DELBA(ieee, dst, &BA, TX_DIR, ReasonCode); return 0; } }
void rtllib_tx_query_agg_cap(struct rtllib_device* ieee, struct sk_buff* skb, cb_desc* tcb_desc) { PRT_HIGH_THROUGHPUT pHTInfo = ieee->pHTInfo; PTX_TS_RECORD pTxTs = NULL; struct rtllib_hdr_1addr* hdr = (struct rtllib_hdr_1addr*)skb->data; if (!pHTInfo->bCurrentHTSupport||!pHTInfo->bEnableHT) return; if (!IsQoSDataFrame(skb->data)) return; if (is_multicast_ether_addr(hdr->addr1) || is_broadcast_ether_addr(hdr->addr1)) return; //check packet and mode later #ifdef TO_DO_LIST if(pTcb->PacketLength >= 4096) return; // For RTL819X, if pairwisekey = wep/tkip, we don't aggrregation. if(!Adapter->HalFunc.GetNmodeSupportBySecCfgHandler(Adapter)) return; #endif if(pHTInfo->IOTAction & HT_IOT_ACT_TX_NO_AGGREGATION) return; if(!ieee->GetNmodeSupportBySecCfg(ieee->dev)) { return; } if(pHTInfo->bCurrentAMPDUEnable) { if (!GetTs(ieee, (PTS_COMMON_INFO*)(&pTxTs), hdr->addr1, skb->priority, TX_DIR, true)) { printk("===>can't get TS\n"); return; } if (pTxTs->TxAdmittedBARecord.bValid == false) { //as some AP will refuse our action frame until key handshake has been finished. WB if (ieee->wpa_ie_len && (ieee->pairwise_key_type == KEY_TYPE_NA)) { ;//printk("############### ieee->wpa_ie_len=%d ieee->pairwise_key_type=%d\n", ieee->wpa_ie_len,ieee->pairwise_key_type); } else if (tcb_desc->bdhcp == 1){ ;//dhcp my be very slow for some ap like linksys610N/350N } else if (!pTxTs->bDisable_AddBa){ TsStartAddBaProcess(ieee, pTxTs); } goto FORCED_AGG_SETTING; } else if (pTxTs->bUsingBa == false) { if (SN_LESS(pTxTs->TxAdmittedBARecord.BaStartSeqCtrl.field.SeqNum, (pTxTs->TxCurSeq+1)%4096)) pTxTs->bUsingBa = true; else goto FORCED_AGG_SETTING; } #ifndef _RTL8192_EXT_PATCH_ if (ieee->iw_mode == IW_MODE_INFRA) #endif { tcb_desc->bAMPDUEnable = true; tcb_desc->ampdu_factor = pHTInfo->CurrentAMPDUFactor; tcb_desc->ampdu_density = pHTInfo->CurrentMPDUDensity; } } FORCED_AGG_SETTING: switch(pHTInfo->ForcedAMPDUMode ) { case HT_AGG_AUTO: break; case HT_AGG_FORCE_ENABLE: tcb_desc->bAMPDUEnable = true; tcb_desc->ampdu_density = pHTInfo->ForcedMPDUDensity; tcb_desc->ampdu_factor = pHTInfo->ForcedAMPDUFactor; break; case HT_AGG_FORCE_DISABLE: tcb_desc->bAMPDUEnable = false; tcb_desc->ampdu_density = 0; tcb_desc->ampdu_factor = 0; break; } return; }
int rtllib_rx_DELBA(struct rtllib_device *ieee, struct sk_buff *skb) { struct rtllib_hdr_3addr *delba = NULL; union delba_param_set *pDelBaParamSet = NULL; u8 *dst = NULL; if (skb->len < sizeof(struct rtllib_hdr_3addr) + 6) { netdev_warn(ieee->dev, "Invalid skb len in DELBA(%d / %d)\n", (int)skb->len, (int)(sizeof(struct rtllib_hdr_3addr) + 6)); return -1; } if (ieee->current_network.qos_data.active == 0 || ieee->pHTInfo->bCurrentHTSupport == false) { netdev_warn(ieee->dev, "received DELBA while QOS or HT is not supported(%d, %d)\n", ieee->current_network. qos_data.active, ieee->pHTInfo->bCurrentHTSupport); return -1; } #ifdef VERBOSE_DEBUG print_hex_dump_bytes("rtllib_rx_DELBA(): ", DUMP_PREFIX_NONE, skb->data, skb->len); #endif delba = (struct rtllib_hdr_3addr *)skb->data; dst = (u8 *)(&delba->addr2[0]); pDelBaParamSet = (union delba_param_set *)&delba->payload[2]; if (pDelBaParamSet->field.Initiator == 1) { struct rx_ts_record *pRxTs; if (!GetTs(ieee, (struct ts_common_info **)&pRxTs, dst, (u8)pDelBaParamSet->field.TID, RX_DIR, false)) { netdev_warn(ieee->dev, "%s(): can't get TS for RXTS. dst:%pM TID:%d\n", __func__, dst, (u8)pDelBaParamSet->field.TID); return -1; } RxTsDeleteBA(ieee, pRxTs); } else { struct tx_ts_record *pTxTs; if (!GetTs(ieee, (struct ts_common_info **)&pTxTs, dst, (u8)pDelBaParamSet->field.TID, TX_DIR, false)) { netdev_warn(ieee->dev, "%s(): can't get TS for TXTS\n", __func__); return -1; } pTxTs->bUsingBa = false; pTxTs->bAddBaReqInProgress = false; pTxTs->bAddBaReqDelayed = false; del_timer_sync(&pTxTs->TsAddBaTimer); TxTsDeleteBA(ieee, pTxTs); } return 0; }