From patchwork Thu Sep 20 19:05:31 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Rajkumar Manoharan X-Patchwork-Id: 10608629 X-Patchwork-Delegate: johannes@sipsolutions.net Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 4FA6E5A4 for ; Thu, 20 Sep 2018 19:05:38 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 3D3C52E24F for ; Thu, 20 Sep 2018 19:05:38 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 30C7A2E33F; Thu, 20 Sep 2018 19:05:38 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-7.8 required=2.0 tests=BAYES_00,DKIM_SIGNED, MAILING_LIST_MULTI,RCVD_IN_DNSWL_HI,T_DKIM_INVALID autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 5CC6D2E330 for ; Thu, 20 Sep 2018 19:05:37 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S2388195AbeIUAub (ORCPT ); Thu, 20 Sep 2018 20:50:31 -0400 Received: from smtp.codeaurora.org ([198.145.29.96]:45042 "EHLO smtp.codeaurora.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727481AbeIUAub (ORCPT ); Thu, 20 Sep 2018 20:50:31 -0400 Received: by smtp.codeaurora.org (Postfix, from userid 1000) id 0F9696083C; Thu, 20 Sep 2018 19:05:34 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=codeaurora.org; s=default; t=1537470335; bh=SNKr9mKynOwvdKMJvVTXwDU89Il7dqjH0oRmRe02cHQ=; h=From:To:Cc:Subject:Date:From; b=HZFZ3nFTP72/yT0MLsxFZ5Zbf9b1QHeUabL0Gy4zMm+4cgww3tNx98+mD8UduikoX qLzBffJ9f3lQlAiEaEtaD3/mzA+W07bdce80sBIqgNRIuP30f/O8gU3W/3PDXFtg6n 4PfXyYs0qcf5eo0syKzTOa2lvo4RN7J7bMNE116I= Received: from smtp.codeaurora.org (i-global254.qualcomm.com [199.106.103.254]) (using TLSv1 with cipher AES128-SHA (128/128 bits)) (No client certificate requested) (Authenticated sender: rmanohar@smtp.codeaurora.org) by smtp.codeaurora.org (Postfix) with ESMTPSA id AC6F460BF7; Thu, 20 Sep 2018 19:05:32 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=codeaurora.org; s=default; t=1537470334; bh=SNKr9mKynOwvdKMJvVTXwDU89Il7dqjH0oRmRe02cHQ=; h=From:To:Cc:Subject:Date:From; b=a3FCwReFJNwFSwK6drx0giN3kAC0YlM6H6JQAuA5k1Jo8myyNLNf+ynetw1avWBO8 dPp5Px2jIm+/k/BUvthzeiSEe3H5D/dW5dPtG7hlpapKa7V2xY8pV8pq8N0hNkyXts CFTt/Ig9D7pDEYEog9tlNJ/bva89lCIcgiVBNs44= DMARC-Filter: OpenDMARC Filter v1.3.2 smtp.codeaurora.org AC6F460BF7 Authentication-Results: pdx-caf-mail.web.codeaurora.org; dmarc=none (p=none dis=none) header.from=codeaurora.org Authentication-Results: pdx-caf-mail.web.codeaurora.org; spf=none smtp.mailfrom=rmanohar@codeaurora.org Received: by smtp.codeaurora.org (sSMTP sendmail emulation); Thu, 20 Sep 2018 12:05:31 -0700 From: Rajkumar Manoharan To: johannes@sipsolutions.net Cc: linux-wireless@vger.kernel.org, Rajkumar Manoharan , Kan Yan , =?utf-8?q?Toke_H=C3=B8iland-J=C3=B8rgensen?= Subject: [RFC v2] mac80211: budget outstanding airtime for transmission Date: Thu, 20 Sep 2018 12:05:31 -0700 Message-Id: <1537470331-6270-1-git-send-email-rmanohar@codeaurora.org> X-Mailer: git-send-email 1.9.1 MIME-Version: 1.0 Sender: linux-wireless-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-wireless@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP Per frame airtime estimation could be used to track outstanding airtime of each txq and can be used to throttle ieee80211_tx_dequeue(). This mechanism on its own will get us the queue limiting and latency reduction goodness for firmwares with deep queues. And for that it can be completely independent of the airtime fairness scheduler, which can use the after-tx-compl airtime information to presumably get more accurate fairness which includes retransmissions etc. Signed-off-by: Kan Yan Signed-off-by: Toke Høiland-Jørgensen Signed-off-by: Rajkumar Manoharan --- include/net/mac80211.h | 2 +- net/mac80211/sta_info.h | 1 + net/mac80211/status.c | 22 ++++++++++++++---- net/mac80211/tx.c | 61 +++++++++++++++++++++++++++++++++++++++++++++++-- 4 files changed, 79 insertions(+), 7 deletions(-) diff --git a/include/net/mac80211.h b/include/net/mac80211.h index 89b192e93ac9..3a9a61fe30b5 100644 --- a/include/net/mac80211.h +++ b/include/net/mac80211.h @@ -947,7 +947,7 @@ struct ieee80211_tx_info { u8 use_cts_prot:1; u8 short_preamble:1; u8 skip_table:1; - /* 2 bytes free */ + u16 airtime_est; }; /* only needed before rate control */ unsigned long jiffies; diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h index b1b0fd6a2e21..06fdac2ee202 100644 --- a/net/mac80211/sta_info.h +++ b/net/mac80211/sta_info.h @@ -135,6 +135,7 @@ struct airtime_info { u64 rx_airtime; u64 tx_airtime; s64 deficit; + u32 budget; }; struct sta_info; diff --git a/net/mac80211/status.c b/net/mac80211/status.c index 664379797c46..81cc4a2c98b2 100644 --- a/net/mac80211/status.c +++ b/net/mac80211/status.c @@ -718,6 +718,7 @@ static void __ieee80211_tx_status(struct ieee80211_hw *hw, struct ieee80211_bar *bar; int shift = 0; int tid = IEEE80211_NUM_TIDS; + u32 ac = IEEE80211_AC_BE; rates_idx = ieee80211_tx_get_rates(hw, info, &retry_count); @@ -733,6 +734,23 @@ static void __ieee80211_tx_status(struct ieee80211_hw *hw, acked = !!(info->flags & IEEE80211_TX_STAT_ACK); + if (ieee80211_is_data_qos(fc)) { + u8 *qc = ieee80211_get_qos_ctl(hdr); + + tid = qc[0] & 0xf; + ac = ieee80211_ac_from_tid(tid); + } + if (wiphy_ext_feature_isset(local->hw.wiphy, + NL80211_EXT_FEATURE_AIRTIME_FAIRNESS)) { + spin_lock_bh(&local->active_txq_lock[ac]); + if (sta->airtime[ac].budget < info->control.airtime_est) + sta->airtime[ac].budget = 0; + else + sta->airtime[ac].budget -= + info->control.airtime_est; + spin_unlock_bh(&local->active_txq_lock[ac]); + } + /* mesh Peer Service Period support */ if (ieee80211_vif_is_mesh(&sta->sdata->vif) && ieee80211_is_data_qos(fc)) @@ -765,10 +783,6 @@ static void __ieee80211_tx_status(struct ieee80211_hw *hw, & IEEE80211_SCTL_SEQ); ieee80211_send_bar(&sta->sdata->vif, hdr->addr1, tid, ssn); - } else if (ieee80211_is_data_qos(fc)) { - u8 *qc = ieee80211_get_qos_ctl(hdr); - - tid = qc[0] & 0xf; } if (!acked && ieee80211_is_back_req(fc)) { diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index e4bc43904a8e..c9997a63e5cf 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c @@ -3485,6 +3485,54 @@ static bool ieee80211_xmit_fast(struct ieee80211_sub_if_data *sdata, return true; } +/* The estimated airtime (in microseconds), which is calculated using last + * reported TX rate is stored in info context buffer. The budget will be + * adjusted upon tx completion. + */ +#define IEEE80211_AIRTIME_BUDGET_MAX 4000 /* txq airtime limit: 4ms */ +#define IEEE80211_AIRTIME_OVERHEAD 100 /* IFS + some slot time */ +#define IEEE80211_AIRTIME_OVERHEAD_IFS 16 /* IFS only */ +static void ieee80211_calc_airtime_budget(struct ieee80211_local *local, + struct sta_info *sta, + struct sk_buff *skb, u8 ac) +{ + struct ieee80211_tx_info *info; + struct ieee80211_hdr *hdr; + struct rate_info rinfo; + u32 pktlen, bitrate; + u16 airtime = 0; + + if (!wiphy_ext_feature_isset(local->hw.wiphy, + NL80211_EXT_FEATURE_AIRTIME_FAIRNESS)) + return; + + lockdep_assert_held(&local->active_txq_lock[ac]); + + hdr = (struct ieee80211_hdr *)skb->data; + info = IEEE80211_SKB_CB(skb); + + sta_set_rate_info_tx(sta, &sta->tx_stats.last_rate, &rinfo); + bitrate = cfg80211_calculate_bitrate(&rinfo); + + pktlen = skb->len + 38; /* Assume MAC header 30, SNAP 8 for most case */ + if (!is_multicast_ether_addr(hdr->addr1)) { + /* airtime in us, last tx bitrate in 100kbps */ + airtime = (pktlen * 8 * (1000 / 100)) / bitrate; + airtime += IEEE80211_AIRTIME_OVERHEAD_IFS; + } else { + /* This is mostly for throttle excessive BC/MC frames, and the + * airtime/rate doesn't need be exact. Airtime of BC/MC frames + * in 2G get some discount, which helps prevent very low rate + * frames from being blocked for too long. + */ + airtime = (pktlen * 8 * (1000 / 100)) / 60; /* 6M */ + airtime += IEEE80211_AIRTIME_OVERHEAD; + } + + info->control.airtime_est = airtime; + sta->airtime[ac].budget += airtime; +} + struct sk_buff *ieee80211_tx_dequeue(struct ieee80211_hw *hw, struct ieee80211_txq *txq) { @@ -3498,6 +3546,7 @@ struct sk_buff *ieee80211_tx_dequeue(struct ieee80211_hw *hw, struct ieee80211_tx_data tx; ieee80211_tx_result r; struct ieee80211_vif *vif = txq->vif; + struct sta_info *sta = NULL; spin_lock_bh(&fq->lock); @@ -3510,6 +3559,12 @@ struct sk_buff *ieee80211_tx_dequeue(struct ieee80211_hw *hw, goto out; } + if (txq->sta) { + sta = container_of(txq->sta, struct sta_info, sta); + if (sta->airtime[txq->ac].budget > IEEE80211_AIRTIME_BUDGET_MAX) + goto out; + } + /* Make sure fragments stay together. */ skb = __skb_dequeue(&txqi->frags); if (skb) @@ -3529,8 +3584,7 @@ struct sk_buff *ieee80211_tx_dequeue(struct ieee80211_hw *hw, tx.skb = skb; tx.sdata = vif_to_sdata(info->control.vif); - if (txq->sta) - tx.sta = container_of(txq->sta, struct sta_info, sta); + tx.sta = sta; /* * The key can be removed while the packet was queued, so need to call @@ -3542,6 +3596,9 @@ struct sk_buff *ieee80211_tx_dequeue(struct ieee80211_hw *hw, goto begin; } + if (sta) + ieee80211_calc_airtime_budget(local, sta, skb, txq->ac); + if (test_bit(IEEE80211_TXQ_AMPDU, &txqi->flags)) info->flags |= IEEE80211_TX_CTL_AMPDU; else