All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/3] Export TXQ parameters and statistics via nl80211
@ 2018-02-19 17:02 Toke Høiland-Jørgensen
  2018-02-19 17:02 ` [PATCH 1/3] cfg80211: Expose TXQ stats and parameters to userspace Toke Høiland-Jørgensen
                   ` (5 more replies)
  0 siblings, 6 replies; 22+ messages in thread
From: Toke Høiland-Jørgensen @ 2018-02-19 17:02 UTC (permalink / raw)
  To: make-wifi-fast, linux-wireless; +Cc: Toke Høiland-Jørgensen

This series adds TXQ parameters and statistics that were previously only
available through debugfs to the nl80211 userspace interface and the
cfg80211 kernel interface. Patches for iw to print the statistics and
change the settings are included.

Wasn't sure whether to include the updates to nl80211.h in the iw
patchset, so I didn't :)

-Toke


Kernel patch:

Toke Høiland-Jørgensen (1):
  cfg80211: Expose TXQ stats and parameters to userspace

 include/net/cfg80211.h       |  52 +++++++++++++++++++
 include/uapi/linux/nl80211.h |  57 +++++++++++++++++++++
 net/mac80211/cfg.c           |  95 +++++++++++++++++++++++++++++++++++
 net/mac80211/ieee80211_i.h   |   3 ++
 net/mac80211/main.c          |   3 ++
 net/mac80211/sta_info.c      |  12 +++++
 net/mac80211/tx.c            |  20 ++++++++
 net/wireless/nl80211.c       | 115 +++++++++++++++++++++++++++++++++++++++++++
 net/wireless/rdev-ops.h      |  12 +++++
 net/wireless/trace.h         |  14 ++++++
 10 files changed, 383 insertions(+)


iw patches (updated nl80211.h not included):

Toke Høiland-Jørgensen (2):
  iw: Print TXQ statistics for stations and interfaces
  iw: Add getting and setting of TXQ params for phy

 info.c      |   3 ++
 interface.c |   6 ++++
 iw.h        |   2 ++
 phy.c       | 116 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 station.c   |  91 ++++++++++++++++++++++++++++++++++++++++++++++-
 5 files changed, 217 insertions(+), 1 deletion(-)

^ permalink raw reply	[flat|nested] 22+ messages in thread

* [PATCH 1/3] cfg80211: Expose TXQ stats and parameters to userspace
  2018-02-19 17:02 [PATCH 0/3] Export TXQ parameters and statistics via nl80211 Toke Høiland-Jørgensen
@ 2018-02-19 17:02 ` Toke Høiland-Jørgensen
  2018-05-07 19:13   ` Johannes Berg
  2018-05-08 10:21   ` Johannes Berg
  2018-02-19 17:02 ` [PATCH 2/3] iw: Print TXQ statistics for stations and interfaces Toke Høiland-Jørgensen
                   ` (4 subsequent siblings)
  5 siblings, 2 replies; 22+ messages in thread
From: Toke Høiland-Jørgensen @ 2018-02-19 17:02 UTC (permalink / raw)
  To: make-wifi-fast, linux-wireless; +Cc: Toke Høiland-Jørgensen

This adds support for exporting the mac80211 TXQ stats via nl80211 by
way of a nested TXQ stats attribute, as well as for configuring the
quantum and limits that were previously only changeable through debugfs.

Signed-off-by: Toke Høiland-Jørgensen <toke@toke.dk>
---
 include/net/cfg80211.h       |  50 +++++++++++++++++++
 include/uapi/linux/nl80211.h |  57 +++++++++++++++++++++
 net/mac80211/cfg.c           |  95 +++++++++++++++++++++++++++++++++++
 net/mac80211/ieee80211_i.h   |   3 ++
 net/mac80211/main.c          |   3 ++
 net/mac80211/sta_info.c      |  12 +++++
 net/mac80211/tx.c            |  20 ++++++++
 net/wireless/nl80211.c       | 115 +++++++++++++++++++++++++++++++++++++++++++
 net/wireless/rdev-ops.h      |  12 +++++
 net/wireless/trace.h         |  14 ++++++
 10 files changed, 381 insertions(+)

diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index 56e905cd4b07..9e8041f7cb37 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -1075,6 +1075,37 @@ struct sta_bss_parameters {
 	u16 beacon_interval;
 };
 
+/**
+ * struct cfg80211_txq_stats - TXQ statistics for this TID
+ * @filled: bitmap of flags using the bits of &enum nl80211_txq_stats to
+ *	indicate the relevant values in this struct are filled
+ * @backlog_bytes: total number of bytes currently backlogged
+ * @backlog_packets: total number of packets currently backlogged
+ * @flows: number of new flows seen
+ * @drops: total number of packets dropped
+ * @ecn_marks: total number of packets marked with ECN CE
+ * @overlimit: number of drops due to queue space overflow
+ * @overmemory: number of drops due to memory limit overflow
+ * @collisions: number of hash collisions
+ * @tx_bytes: total number of bytes dequeued
+ * @tx_packets: total number of packets dequeued
+ * @max_flows: maximum number of flows supported
+ */
+struct cfg80211_txq_stats {
+	u32 filled;
+	u32 backlog_bytes;
+	u32 backlog_packets;
+	u32 flows;
+	u32 drops;
+	u32 ecn_marks;
+	u32 overlimit;
+	u32 overmemory;
+	u32 collisions;
+	u32 tx_bytes;
+	u32 tx_packets;
+	u32 max_flows;
+};
+
 /**
  * struct cfg80211_tid_stats - per-TID statistics
  * @filled: bitmap of flags using the bits of &enum nl80211_tid_stats to
@@ -1084,6 +1115,7 @@ struct sta_bss_parameters {
  * @tx_msdu_retries: number of retries (not counting the first) for
  *	transmitted MSDUs
  * @tx_msdu_failed: number of failed transmitted MSDUs
+ * @txq_stats: TXQ statistics
  */
 struct cfg80211_tid_stats {
 	u32 filled;
@@ -1091,6 +1123,7 @@ struct cfg80211_tid_stats {
 	u64 tx_msdu;
 	u64 tx_msdu_retries;
 	u64 tx_msdu_failed;
+	struct cfg80211_txq_stats txq_stats;
 };
 
 #define IEEE80211_MAX_CHAINS	4
@@ -2191,6 +2224,9 @@ enum cfg80211_connect_params_changed {
  * @WIPHY_PARAM_RTS_THRESHOLD: wiphy->rts_threshold has changed
  * @WIPHY_PARAM_COVERAGE_CLASS: coverage class changed
  * @WIPHY_PARAM_DYN_ACK: dynack has been enabled
+ * @WIPHY_PARAM_TXQ_LIMIT: TXQ packet limit has been changed
+ * @WIPHY_PARAM_TXQ_MEMORY_LIMIT: TXQ memory limit has been changed
+ * @WIPHY_PARAM_TXQ_QUANTUM: TXQ scheduler quantum
  */
 enum wiphy_params_flags {
 	WIPHY_PARAM_RETRY_SHORT		= 1 << 0,
@@ -2199,6 +2235,9 @@ enum wiphy_params_flags {
 	WIPHY_PARAM_RTS_THRESHOLD	= 1 << 3,
 	WIPHY_PARAM_COVERAGE_CLASS	= 1 << 4,
 	WIPHY_PARAM_DYN_ACK		= 1 << 5,
+	WIPHY_PARAM_TXQ_LIMIT		= 1 << 6,
+	WIPHY_PARAM_TXQ_MEMORY_LIMIT	= 1 << 7,
+	WIPHY_PARAM_TXQ_QUANTUM		= 1 << 8,
 };
 
 /**
@@ -2951,6 +2990,9 @@ struct cfg80211_external_auth_params {
  *
  * @set_multicast_to_unicast: configure multicast to unicast conversion for BSS
  *
+ * @get_txq_stats: Get TXQ stats for interface or phy. If wdev is %NULL, this
+ *      function should return phy stats, and interface stats otherwise.
+ *
  * @set_pmk: configure the PMK to be used for offloaded 802.1X 4-Way handshake.
  *	If not deleted through @del_pmk the PMK remains valid until disconnect
  *	upon which the driver should clear it.
@@ -3249,6 +3291,10 @@ struct cfg80211_ops {
 					    struct net_device *dev,
 					    const bool enabled);
 
+	int	(*get_txq_stats)(struct wiphy *wiphy,
+			         struct wireless_dev *wdev,
+			         struct cfg80211_txq_stats *txqstats);
+
 	int	(*set_pmk)(struct wiphy *wiphy, struct net_device *dev,
 			   const struct cfg80211_pmk_conf *conf);
 	int	(*del_pmk)(struct wiphy *wiphy, struct net_device *dev,
@@ -3921,6 +3967,10 @@ struct wiphy {
 
 	u8 nan_supported_bands;
 
+	u32 txq_limit;
+	u32 txq_memory_limit;
+	u32 txq_quantum;
+
 	char priv[0] __aligned(NETDEV_ALIGN);
 };
 
diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h
index c13c84304be3..fc814037bb39 100644
--- a/include/uapi/linux/nl80211.h
+++ b/include/uapi/linux/nl80211.h
@@ -2196,6 +2196,16 @@ enum nl80211_commands {
  * @NL80211_ATTR_NSS: Station's New/updated  RX_NSS value notified using this
  *	u8 attribute. This is used with %NL80211_CMD_STA_OPMODE_CHANGED.
  *
+ * @NL80211_ATTR_TXQ_STATS: TXQ statistics (nested attribute, see enum
+ *      nl80211_txq_stats)
+ * @NL80211_ATTR_TXQ_LIMIT: Total packet limit for the TXQ queues for this phy.
+ *      The smaller of this and the memory limit is enforced.
+ * @NL80211_ATTR_TXQ_MEMORY_LIMIT: Total memory memory limit (in bytes) for the
+ *      TXQ queues for this phy. The smaller of this and the packet limit is
+ *      enforced.
+ * @NL80211_ATTR_TXQ_QUANTUM: TXQ scheduler quantum (bytes). Number of bytes
+ *      a flow is assigned on each round of the DRR scheduler.
+ *
  * @NUM_NL80211_ATTR: total number of nl80211_attrs available
  * @NL80211_ATTR_MAX: highest attribute number currently defined
  * @__NL80211_ATTR_AFTER_LAST: internal use
@@ -2628,6 +2638,11 @@ enum nl80211_attrs {
 	NL80211_ATTR_NSS,
 	NL80211_ATTR_ACK_SIGNAL,
 
+	NL80211_ATTR_TXQ_STATS,
+	NL80211_ATTR_TXQ_LIMIT,
+	NL80211_ATTR_TXQ_MEMORY_LIMIT,
+	NL80211_ATTR_TXQ_QUANTUM,
+
 	/* add attributes here, update the policy in nl80211.c */
 
 	__NL80211_ATTR_AFTER_LAST,
@@ -3005,6 +3020,7 @@ enum nl80211_sta_info {
  * @NL80211_TID_STATS_TX_MSDU_FAILED: number of failed transmitted
  *	MSDUs (u64)
  * @NL80211_TID_STATS_PAD: attribute used for padding for 64-bit alignment
+ * @NL80211_TID_STATS_TXQ_STATS: TXQ stats (nested attribute)
  * @NUM_NL80211_TID_STATS: number of attributes here
  * @NL80211_TID_STATS_MAX: highest numbered attribute here
  */
@@ -3015,12 +3031,51 @@ enum nl80211_tid_stats {
 	NL80211_TID_STATS_TX_MSDU_RETRIES,
 	NL80211_TID_STATS_TX_MSDU_FAILED,
 	NL80211_TID_STATS_PAD,
+	NL80211_TID_STATS_TXQ_STATS,
 
 	/* keep last */
 	NUM_NL80211_TID_STATS,
 	NL80211_TID_STATS_MAX = NUM_NL80211_TID_STATS - 1
 };
 
+/**
+ * enum nl80211_txq_stats - per TXQ statistics attributes
+ * @__NL80211_TXQ_STATS_INVALID: attribute number 0 is reserved
+ * @NUM_NL80211_TXQ_STATS: number of attributes here
+ * @NL80211_TXQ_STATS_BACKLOG_BYTES: number of bytes currently backlogged
+ * @NL80211_TXQ_STATS_BACKLOG_PACKETS: number of packets currently
+ *      backlogged
+ * @NL80211_TXQ_STATS_FLOWS: total number of new flows seen
+ * @NL80211_TXQ_STATS_DROPS: total number of packet drops
+ * @NL80211_TXQ_STATS_ECN_MARKS: total number of packet ECN marks
+ * @NL80211_TXQ_STATS_OVERLIMIT: number of drops due to queue space overflow
+ * @NL80211_TXQ_STATS_OVERMEMORY: number of drops due to memory limit overflow
+ *      (only for per-phy stats)
+ * @NL80211_TXQ_STATS_COLLISIONS: number of hash collisions
+ * @NL80211_TXQ_STATS_TX_BYTES: total number of bytes dequeued from TXQ
+ * @NL80211_TXQ_STATS_TX_PACKETS: total number of packets dequeued from TXQ
+ * @NL80211_TXQ_STATS_MAX_FLOWS: number of flow buckets for PHY
+ * @NL80211_TXQ_STATS_MAX: highest numbered attribute here
+ */
+enum nl80211_txq_stats {
+	__NL80211_TXQ_STATS_INVALID,
+	NL80211_TXQ_STATS_BACKLOG_BYTES,
+	NL80211_TXQ_STATS_BACKLOG_PACKETS,
+	NL80211_TXQ_STATS_FLOWS,
+	NL80211_TXQ_STATS_DROPS,
+	NL80211_TXQ_STATS_ECN_MARKS,
+	NL80211_TXQ_STATS_OVERLIMIT,
+	NL80211_TXQ_STATS_OVERMEMORY,
+	NL80211_TXQ_STATS_COLLISIONS,
+	NL80211_TXQ_STATS_TX_BYTES,
+	NL80211_TXQ_STATS_TX_PACKETS,
+	NL80211_TXQ_STATS_MAX_FLOWS,
+
+	/* keep last */
+	NUM_NL80211_TXQ_STATS,
+	NL80211_TXQ_STATS_MAX = NUM_NL80211_TXQ_STATS - 1
+};
+
 /**
  * enum nl80211_mpath_flags - nl80211 mesh path flags
  *
@@ -4999,6 +5054,7 @@ enum nl80211_feature_flags {
  * @NL80211_EXT_FEATURE_LOW_SPAN_SCAN: Driver supports low span scan.
  * @NL80211_EXT_FEATURE_LOW_POWER_SCAN: Driver supports low power scan.
  * @NL80211_EXT_FEATURE_HIGH_ACCURACY_SCAN: Driver supports high accuracy scan.
+ * @NL80211_EXT_FEATURE_TXQS: Driver supports FQ-CoDel-enabled intermediate TXQs.
  *
  * @NUM_NL80211_EXT_FEATURES: number of extended features.
  * @MAX_NL80211_EXT_FEATURES: highest extended feature index.
@@ -5029,6 +5085,7 @@ enum nl80211_ext_feature_index {
 	NL80211_EXT_FEATURE_LOW_SPAN_SCAN,
 	NL80211_EXT_FEATURE_LOW_POWER_SCAN,
 	NL80211_EXT_FEATURE_HIGH_ACCURACY_SCAN,
+	NL80211_EXT_FEATURE_TXQS,
 
 	/* add new features before the definition below */
 	NUM_NL80211_EXT_FEATURES,
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index 46028e12e216..18418f88e383 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -2365,6 +2365,11 @@ static int ieee80211_set_wiphy_params(struct wiphy *wiphy, u32 changed)
 	    (WIPHY_PARAM_RETRY_SHORT | WIPHY_PARAM_RETRY_LONG))
 		ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_RETRY_LIMITS);
 
+	if (changed & (WIPHY_PARAM_TXQ_LIMIT |
+		       WIPHY_PARAM_TXQ_MEMORY_LIMIT |
+			WIPHY_PARAM_TXQ_QUANTUM))
+		ieee80211_txq_set_params(local);
+
 	return 0;
 }
 
@@ -3693,6 +3698,95 @@ static int ieee80211_set_multicast_to_unicast(struct wiphy *wiphy,
 	return 0;
 }
 
+void ieee80211_fill_txq_stats(struct cfg80211_txq_stats *txqstats,
+			     struct txq_info *txqi)
+{
+	if (!(txqstats->filled & BIT(NL80211_TXQ_STATS_BACKLOG_BYTES))) {
+		txqstats->filled |= BIT(NL80211_TXQ_STATS_BACKLOG_BYTES);
+		txqstats->backlog_bytes = txqi->tin.backlog_bytes;
+	}
+
+	if (!(txqstats->filled & BIT(NL80211_TXQ_STATS_BACKLOG_PACKETS))) {
+		txqstats->filled |= BIT(NL80211_TXQ_STATS_BACKLOG_PACKETS);
+		txqstats->backlog_packets = txqi->tin.backlog_packets;
+	}
+
+	if (!(txqstats->filled & BIT(NL80211_TXQ_STATS_FLOWS))) {
+		txqstats->filled |= BIT(NL80211_TXQ_STATS_FLOWS);
+		txqstats->flows = txqi->tin.flows;
+	}
+
+	if (!(txqstats->filled & BIT(NL80211_TXQ_STATS_DROPS))) {
+		txqstats->filled |= BIT(NL80211_TXQ_STATS_DROPS);
+		txqstats->drops = txqi->cstats.drop_count;
+	}
+
+	if (!(txqstats->filled & BIT(NL80211_TXQ_STATS_ECN_MARKS))) {
+		txqstats->filled |= BIT(NL80211_TXQ_STATS_ECN_MARKS);
+		txqstats->ecn_marks = txqi->cstats.ecn_mark;
+	}
+
+	if (!(txqstats->filled & BIT(NL80211_TXQ_STATS_OVERLIMIT))) {
+		txqstats->filled |= BIT(NL80211_TXQ_STATS_OVERLIMIT);
+		txqstats->overlimit = txqi->tin.overlimit;
+	}
+
+	if (!(txqstats->filled & BIT(NL80211_TXQ_STATS_COLLISIONS))) {
+		txqstats->filled |= BIT(NL80211_TXQ_STATS_COLLISIONS);
+		txqstats->collisions = txqi->tin.collisions;
+	}
+
+	if (!(txqstats->filled & BIT(NL80211_TXQ_STATS_TX_BYTES))) {
+		txqstats->filled |= BIT(NL80211_TXQ_STATS_TX_BYTES);
+		txqstats->tx_bytes = txqi->tin.tx_bytes;
+	}
+
+	if (!(txqstats->filled & BIT(NL80211_TXQ_STATS_TX_PACKETS))) {
+		txqstats->filled |= BIT(NL80211_TXQ_STATS_TX_PACKETS);
+		txqstats->tx_packets = txqi->tin.tx_packets;
+	}
+}
+
+static int ieee80211_get_txq_stats(struct wiphy *wiphy,
+				   struct wireless_dev *wdev,
+				   struct cfg80211_txq_stats *txqstats)
+{
+	struct ieee80211_local *local = wiphy_priv(wiphy);
+	struct ieee80211_sub_if_data *sdata;
+
+	if (!local->ops->wake_tx_queue)
+		return 1;
+
+	spin_lock_bh(&local->fq.lock);
+	rcu_read_lock();
+
+	if (wdev) {
+		sdata = IEEE80211_WDEV_TO_SUB_IF(wdev);
+		if (!sdata->vif.txq)
+			return 1;
+		ieee80211_fill_txq_stats(txqstats, to_txq_info(sdata->vif.txq));
+	} else {
+		/* phy stats */
+		txqstats->filled |= (BIT(NL80211_TXQ_STATS_BACKLOG_PACKETS) |
+				     BIT(NL80211_TXQ_STATS_BACKLOG_BYTES) |
+				     BIT(NL80211_TXQ_STATS_OVERLIMIT) |
+				     BIT(NL80211_TXQ_STATS_OVERMEMORY) |
+				     BIT(NL80211_TXQ_STATS_COLLISIONS) |
+				     BIT(NL80211_TXQ_STATS_MAX_FLOWS));
+		txqstats->backlog_packets = local->fq.backlog;
+		txqstats->backlog_bytes = local->fq.memory_usage;
+		txqstats->overlimit = local->fq.overlimit;
+		txqstats->overmemory = local->fq.overmemory;
+		txqstats->collisions = local->fq.collisions;
+		txqstats->max_flows = local->fq.flows_cnt;
+	}
+
+	rcu_read_unlock();
+	spin_unlock_bh(&local->fq.lock);
+
+	return 0;
+}
+
 const struct cfg80211_ops mac80211_config_ops = {
 	.add_virtual_intf = ieee80211_add_iface,
 	.del_virtual_intf = ieee80211_del_iface,
@@ -3785,4 +3879,5 @@ const struct cfg80211_ops mac80211_config_ops = {
 	.add_nan_func = ieee80211_add_nan_func,
 	.del_nan_func = ieee80211_del_nan_func,
 	.set_multicast_to_unicast = ieee80211_set_multicast_to_unicast,
+	.get_txq_stats = ieee80211_get_txq_stats,
 };
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index 26900025de2f..c2f3310c41e8 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -2000,6 +2000,7 @@ static inline bool ieee80211_can_run_worker(struct ieee80211_local *local)
 }
 
 int ieee80211_txq_setup_flows(struct ieee80211_local *local);
+int ieee80211_txq_set_params(struct ieee80211_local *local);
 void ieee80211_txq_teardown_flows(struct ieee80211_local *local);
 void ieee80211_txq_init(struct ieee80211_sub_if_data *sdata,
 			struct sta_info *sta,
@@ -2008,6 +2009,8 @@ void ieee80211_txq_purge(struct ieee80211_local *local,
 			 struct txq_info *txqi);
 void ieee80211_txq_remove_vlan(struct ieee80211_local *local,
 			       struct ieee80211_sub_if_data *sdata);
+void ieee80211_fill_txq_stats(struct cfg80211_txq_stats *txqstats,
+			      struct txq_info *txqi);
 void ieee80211_send_auth(struct ieee80211_sub_if_data *sdata,
 			 u16 transaction, u16 auth_alg, u16 status,
 			 const u8 *extra, size_t extra_len, const u8 *bssid,
diff --git a/net/mac80211/main.c b/net/mac80211/main.c
index 0785d04a80bc..e884f3b5064f 100644
--- a/net/mac80211/main.c
+++ b/net/mac80211/main.c
@@ -563,6 +563,9 @@ struct ieee80211_hw *ieee80211_alloc_hw_nm(size_t priv_data_len,
 	if (!ops->set_key)
 		wiphy->flags |= WIPHY_FLAG_IBSS_RSN;
 
+	if (ops->wake_tx_queue)
+		wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_TXQS);
+
 	wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_RRM);
 
 	wiphy->bss_priv_size = sizeof(struct ieee80211_bss);
diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c
index 0bc40c719a55..7f535452fcc4 100644
--- a/net/mac80211/sta_info.c
+++ b/net/mac80211/sta_info.c
@@ -2050,6 +2050,18 @@ static void sta_set_tidstats(struct sta_info *sta,
 		tidstats->filled |= BIT(NL80211_TID_STATS_TX_MSDU_FAILED);
 		tidstats->tx_msdu_failed = sta->status_stats.msdu_failed[tid];
 	}
+
+	if (local->ops->wake_tx_queue && tid < IEEE80211_NUM_TIDS) {
+		spin_lock_bh(&local->fq.lock);
+		rcu_read_lock();
+
+		tidstats->filled |= BIT(NL80211_TID_STATS_TXQ_STATS);
+		ieee80211_fill_txq_stats(&tidstats->txq_stats,
+					 to_txq_info(sta->sta.txq[tid]));
+
+		rcu_read_unlock();
+		spin_unlock_bh(&local->fq.lock);
+	}
 }
 
 static inline u64 sta_get_stats_bytes(struct ieee80211_sta_rx_stats *rxstats)
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c
index 933c67b5f845..6826d8d73eb3 100644
--- a/net/mac80211/tx.c
+++ b/net/mac80211/tx.c
@@ -1459,6 +1459,24 @@ void ieee80211_txq_purge(struct ieee80211_local *local,
 	ieee80211_purge_tx_queue(&local->hw, &txqi->frags);
 }
 
+int ieee80211_txq_set_params(struct ieee80211_local *local)
+{
+	if (local->hw.wiphy->txq_limit)
+		local->fq.limit = local->hw.wiphy->txq_limit;
+	else
+		local->hw.wiphy->txq_limit = local->fq.limit;
+
+	if (local->hw.wiphy->txq_memory_limit)
+		local->fq.memory_limit = local->hw.wiphy->txq_memory_limit;
+	else
+		local->hw.wiphy->txq_memory_limit = local->fq.memory_limit;
+
+	if (local->hw.wiphy->txq_quantum)
+		local->fq.quantum = local->hw.wiphy->txq_quantum;
+	else
+		local->hw.wiphy->txq_quantum = local->fq.quantum;
+}
+
 int ieee80211_txq_setup_flows(struct ieee80211_local *local)
 {
 	struct fq *fq = &local->fq;
@@ -1508,6 +1526,8 @@ int ieee80211_txq_setup_flows(struct ieee80211_local *local)
 	for (i = 0; i < fq->flows_cnt; i++)
 		codel_vars_init(&local->cvars[i]);
 
+	ieee80211_txq_set_params(local);
+
 	return 0;
 }
 
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 050ff61b06a3..9d2cc8e3afba 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -421,6 +421,10 @@ static const struct nla_policy nl80211_policy[NUM_NL80211_ATTR] = {
 	[NL80211_ATTR_PMK] = { .type = NLA_BINARY, .len = PMK_MAX_LEN },
 	[NL80211_ATTR_SCHED_SCAN_MULTI] = { .type = NLA_FLAG },
 	[NL80211_ATTR_EXTERNAL_AUTH_SUPPORT] = { .type = NLA_FLAG },
+
+	[NL80211_ATTR_TXQ_LIMIT] = { .type = NLA_U32 },
+	[NL80211_ATTR_TXQ_MEMORY_LIMIT] = { .type = NLA_U32 },
+	[NL80211_ATTR_TXQ_QUANTUM] = { .type = NLA_U32 },
 };
 
 /* policy for the key attributes */
@@ -725,6 +729,39 @@ static int nl80211_msg_put_channel(struct sk_buff *msg,
 	return -ENOBUFS;
 }
 
+static bool nl80211_put_txq_stats(struct sk_buff *msg,
+				  struct cfg80211_txq_stats *txqstats,
+				  int attrtype)
+{
+	struct nlattr *txqattr;
+
+#define PUT_TXQVAL_U32(attr, memb) do {					  \
+	if (txqstats->filled & BIT(NL80211_TXQ_STATS_ ## attr) &&	  \
+	    nla_put_u32(msg, NL80211_TXQ_STATS_ ## attr, txqstats->memb)) \
+		return false;						  \
+	} while (0)
+
+	txqattr = nla_nest_start(msg, attrtype);
+	if (!txqattr)
+		return false;
+
+	PUT_TXQVAL_U32(BACKLOG_BYTES, backlog_bytes);
+	PUT_TXQVAL_U32(BACKLOG_PACKETS, backlog_packets);
+	PUT_TXQVAL_U32(FLOWS, flows);
+	PUT_TXQVAL_U32(DROPS, drops);
+	PUT_TXQVAL_U32(ECN_MARKS, ecn_marks);
+	PUT_TXQVAL_U32(OVERLIMIT, overlimit);
+	PUT_TXQVAL_U32(OVERMEMORY, overmemory);
+	PUT_TXQVAL_U32(COLLISIONS, collisions);
+	PUT_TXQVAL_U32(TX_BYTES, tx_bytes);
+	PUT_TXQVAL_U32(TX_PACKETS, tx_packets);
+	PUT_TXQVAL_U32(MAX_FLOWS, max_flows);
+	nla_nest_end(msg, txqattr);
+
+#undef PUT_TXQVAL_U32
+	return true;
+}
+
 /* netlink command implementations */
 
 struct key_parse {
@@ -1924,6 +1961,28 @@ static int nl80211_send_wiphy(struct cfg80211_registered_device *rdev,
 				rdev->wiphy.nan_supported_bands))
 			goto nla_put_failure;
 
+		if (wiphy_ext_feature_isset(&rdev->wiphy,
+					    NL80211_EXT_FEATURE_TXQS)) {
+
+			struct cfg80211_txq_stats txqstats = {};
+			int res;
+
+			res = rdev_get_txq_stats(rdev, NULL, &txqstats);
+			if (!res && !nl80211_put_txq_stats(msg, &txqstats,
+							   NL80211_ATTR_TXQ_STATS))
+				goto nla_put_failure;
+
+			if (nla_put_u32(msg, NL80211_ATTR_TXQ_LIMIT,
+						rdev->wiphy.txq_limit))
+				goto nla_put_failure;
+			if (nla_put_u32(msg, NL80211_ATTR_TXQ_MEMORY_LIMIT,
+						rdev->wiphy.txq_memory_limit))
+				goto nla_put_failure;
+			if (nla_put_u32(msg, NL80211_ATTR_TXQ_QUANTUM,
+						rdev->wiphy.txq_quantum))
+				goto nla_put_failure;
+		}
+
 		/* done */
 		state->split_start = 0;
 		break;
@@ -2299,6 +2358,7 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info)
 	u8 retry_short = 0, retry_long = 0;
 	u32 frag_threshold = 0, rts_threshold = 0;
 	u8 coverage_class = 0;
+	u32 txq_limit = 0, txq_memory_limit = 0, txq_quantum = 0;
 
 	ASSERT_RTNL();
 
@@ -2505,10 +2565,38 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info)
 		changed |= WIPHY_PARAM_DYN_ACK;
 	}
 
+	if (info->attrs[NL80211_ATTR_TXQ_LIMIT]) {
+		if (!wiphy_ext_feature_isset(&rdev->wiphy,
+					     NL80211_EXT_FEATURE_TXQS))
+			return -EOPNOTSUPP;
+		txq_limit = nla_get_u32(
+			info->attrs[NL80211_ATTR_TXQ_LIMIT]);
+		changed |= WIPHY_PARAM_TXQ_LIMIT;
+	}
+
+	if (info->attrs[NL80211_ATTR_TXQ_MEMORY_LIMIT]) {
+		if (!wiphy_ext_feature_isset(&rdev->wiphy,
+					     NL80211_EXT_FEATURE_TXQS))
+			return -EOPNOTSUPP;
+		txq_memory_limit = nla_get_u32(
+			info->attrs[NL80211_ATTR_TXQ_MEMORY_LIMIT]);
+		changed |= WIPHY_PARAM_TXQ_MEMORY_LIMIT;
+	}
+
+	if (info->attrs[NL80211_ATTR_TXQ_QUANTUM]) {
+		if (!wiphy_ext_feature_isset(&rdev->wiphy,
+					     NL80211_EXT_FEATURE_TXQS))
+			return -EOPNOTSUPP;
+		txq_quantum = nla_get_u32(
+			info->attrs[NL80211_ATTR_TXQ_QUANTUM]);
+		changed |= WIPHY_PARAM_TXQ_QUANTUM;
+	}
+
 	if (changed) {
 		u8 old_retry_short, old_retry_long;
 		u32 old_frag_threshold, old_rts_threshold;
 		u8 old_coverage_class;
+		u32 old_txq_limit, old_txq_memory_limit, old_txq_quantum;
 
 		if (!rdev->ops->set_wiphy_params)
 			return -EOPNOTSUPP;
@@ -2518,6 +2606,9 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info)
 		old_frag_threshold = rdev->wiphy.frag_threshold;
 		old_rts_threshold = rdev->wiphy.rts_threshold;
 		old_coverage_class = rdev->wiphy.coverage_class;
+		old_txq_limit = rdev->wiphy.txq_limit;
+		old_txq_memory_limit = rdev->wiphy.txq_memory_limit;
+		old_txq_quantum = rdev->wiphy.txq_quantum;
 
 		if (changed & WIPHY_PARAM_RETRY_SHORT)
 			rdev->wiphy.retry_short = retry_short;
@@ -2529,6 +2620,12 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info)
 			rdev->wiphy.rts_threshold = rts_threshold;
 		if (changed & WIPHY_PARAM_COVERAGE_CLASS)
 			rdev->wiphy.coverage_class = coverage_class;
+		if (changed & WIPHY_PARAM_TXQ_LIMIT)
+			rdev->wiphy.txq_limit = txq_limit;
+		if (changed & WIPHY_PARAM_TXQ_MEMORY_LIMIT)
+			rdev->wiphy.txq_memory_limit = txq_memory_limit;
+		if (changed & WIPHY_PARAM_TXQ_QUANTUM)
+			rdev->wiphy.txq_quantum = txq_quantum;
 
 		result = rdev_set_wiphy_params(rdev, changed);
 		if (result) {
@@ -2537,6 +2634,9 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info)
 			rdev->wiphy.frag_threshold = old_frag_threshold;
 			rdev->wiphy.rts_threshold = old_rts_threshold;
 			rdev->wiphy.coverage_class = old_coverage_class;
+			rdev->wiphy.txq_limit = old_txq_limit;
+			rdev->wiphy.txq_memory_limit = old_txq_memory_limit;
+			rdev->wiphy.txq_quantum = old_txq_quantum;
 			return result;
 		}
 	}
@@ -2658,6 +2758,16 @@ static int nl80211_send_iface(struct sk_buff *msg, u32 portid, u32 seq, int flag
 	}
 	wdev_unlock(wdev);
 
+	if (rdev->ops->get_txq_stats) {
+		struct cfg80211_txq_stats txqstats = {};
+		int ret = rdev_get_txq_stats(rdev, wdev, &txqstats);
+
+		if (ret == 0 &&
+			!nl80211_put_txq_stats(msg, &txqstats,
+					NL80211_ATTR_TXQ_STATS))
+			goto nla_put_failure;
+	}
+
 	genlmsg_end(msg, hdr);
 	return 0;
 
@@ -4525,6 +4635,11 @@ static int nl80211_send_station(struct sk_buff *msg, u32 cmd, u32 portid,
 			PUT_TIDVAL_U64(TX_MSDU_FAILED, tx_msdu_failed);
 
 #undef PUT_TIDVAL_U64
+			if ((tidstats->filled & BIT(NL80211_TID_STATS_TXQ_STATS)) &&
+				!nl80211_put_txq_stats(msg, &tidstats->txq_stats,
+						NL80211_TID_STATS_TXQ_STATS))
+				goto nla_put_failure;
+
 			nla_nest_end(msg, tidattr);
 		}
 
diff --git a/net/wireless/rdev-ops.h b/net/wireless/rdev-ops.h
index 84f23ae015fc..37b6858437bd 100644
--- a/net/wireless/rdev-ops.h
+++ b/net/wireless/rdev-ops.h
@@ -586,6 +586,18 @@ rdev_set_multicast_to_unicast(struct cfg80211_registered_device *rdev,
 	return ret;
 }
 
+static inline int
+rdev_get_txq_stats(struct cfg80211_registered_device *rdev,
+		   struct wireless_dev *wdev,
+		   struct cfg80211_txq_stats *txqstats)
+{
+	int ret;
+	trace_rdev_get_txq_stats(&rdev->wiphy, wdev);
+	ret = rdev->ops->get_txq_stats(&rdev->wiphy, wdev, txqstats);
+	trace_rdev_return_int(&rdev->wiphy, ret);
+	return ret;
+}
+
 static inline void rdev_rfkill_poll(struct cfg80211_registered_device *rdev)
 {
 	trace_rdev_rfkill_poll(&rdev->wiphy);
diff --git a/net/wireless/trace.h b/net/wireless/trace.h
index 5152938b358d..89140feb3f1b 100644
--- a/net/wireless/trace.h
+++ b/net/wireless/trace.h
@@ -3196,6 +3196,20 @@ TRACE_EVENT(rdev_set_multicast_to_unicast,
 		  WIPHY_PR_ARG, NETDEV_PR_ARG,
 		  BOOL_TO_STR(__entry->enabled))
 );
+
+TRACE_EVENT(rdev_get_txq_stats,
+	TP_PROTO(struct wiphy *wiphy, struct wireless_dev *wdev),
+	TP_ARGS(wiphy, wdev),
+	TP_STRUCT__entry(
+		WIPHY_ENTRY
+		WDEV_ENTRY
+	),
+	TP_fast_assign(
+		WIPHY_ASSIGN;
+		WDEV_ASSIGN;
+	),
+	TP_printk(WIPHY_PR_FMT ", " WDEV_PR_FMT, WIPHY_PR_ARG, WDEV_PR_ARG)
+);
 #endif /* !__RDEV_OPS_TRACE || TRACE_HEADER_MULTI_READ */
 
 #undef TRACE_INCLUDE_PATH
-- 
2.16.1

^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [PATCH 2/3] iw: Print TXQ statistics for stations and interfaces
  2018-02-19 17:02 [PATCH 0/3] Export TXQ parameters and statistics via nl80211 Toke Høiland-Jørgensen
  2018-02-19 17:02 ` [PATCH 1/3] cfg80211: Expose TXQ stats and parameters to userspace Toke Høiland-Jørgensen
@ 2018-02-19 17:02 ` Toke Høiland-Jørgensen
  2018-05-07 21:21   ` Johannes Berg
  2018-02-19 17:02 ` [PATCH 3/3] iw: Add getting and setting of TXQ params for phy Toke Høiland-Jørgensen
                   ` (3 subsequent siblings)
  5 siblings, 1 reply; 22+ messages in thread
From: Toke Høiland-Jørgensen @ 2018-02-19 17:02 UTC (permalink / raw)
  To: make-wifi-fast, linux-wireless; +Cc: Toke Høiland-Jørgensen

This adds printing of TXQ statistics for stations and interfaces when
supplied by the kernel. For stations, another section is added when verbose
mode is enabled; for interfaces, the multicast queue information is always
printed when available.

This is the information also available through debugfs in
/sys/kernel/debug/ieee80211/phyX/netdev:Y/aqm and
/sys/kernel/debug/ieee80211/phyX/netdev:Y/stations/*/aqm.

Sample output:

$ iw dev wlp2s0 station dump -v
Station xx:xx:xx:xx:xx:xx (on wlp2s0)
[...]
	TXQs:
		TID	qsz-byt	qsz-pkt	flows	drops	marks	overlmt	hashcol	tx-bytes	tx-packets
		0	0	0	0	0	0	0	0	0		0
		1	0	0	0	0	0	0	0	0		0
		2	0	0	0	0	0	0	0	0		0
		3	0	0	0	0	0	0	0	0		0
		4	0	0	0	0	0	0	0	0		0
		5	0	0	0	0	0	0	0	0		0
		6	0	0	0	0	0	0	0	0		0
		7	0	0	0	0	0	0	0	0		0
		8	0	0	0	0	0	0	0	0		0
		9	0	0	0	0	0	0	0	0		0
		10	0	0	0	0	0	0	0	0		0
		11	0	0	0	0	0	0	0	0		0
		12	0	0	0	0	0	0	0	0		0
		13	0	0	0	0	0	0	0	0		0
		14	0	0	0	0	0	0	0	0		0
		15	0	0	0	0	0	0	0	0		0
[...]


$ iw dev wlp2s0 info
Interface wlp2s0
	ifindex 9
	wdev 0x1
	addr xx:xx:xx:xx:xx:xx
	type AP
	wiphy 0
	channel 165 (5825 MHz), width: 20 MHz, center1: 5825 MHz
	txpower 24.00 dBm
	Multicast TXQ:
		qsz-byt	qsz-pkt	flows	drops	marks	overlmt	hashcol	tx-bytes	tx-packets
		0	0	72	0	0	0	0	7380		72


Signed-off-by: Toke Høiland-Jørgensen <toke@toke.dk>
---
 interface.c |  6 ++++
 iw.h        |  2 ++
 station.c   | 91 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
 3 files changed, 98 insertions(+), 1 deletion(-)

diff --git a/interface.c b/interface.c
index a19c83f..8a35dd6 100644
--- a/interface.c
+++ b/interface.c
@@ -441,6 +441,12 @@ static int print_iface_handler(struct nl_msg *msg, void *arg)
 		       indent, txp / 100, txp % 100);
 	}
 
+	if (tb_msg[NL80211_ATTR_TXQ_STATS]) {
+		char buf[150];
+		parse_txq_stats(buf, sizeof(buf), tb_msg[NL80211_ATTR_TXQ_STATS], 1, -1);
+		printf("\tMulticast TXQ:%s\n", buf);
+	}
+
 	return NL_SKIP;
 }
 
diff --git a/iw.h b/iw.h
index ee7ca20..1fd227f 100644
--- a/iw.h
+++ b/iw.h
@@ -183,6 +183,8 @@ unsigned char *parse_hex(char *hex, size_t *outlen);
 int parse_keys(struct nl_msg *msg, char **argv, int argc);
 int parse_freqchan(struct chandef *chandef, bool chan, int argc, char **argv, int *parsed);
 enum nl80211_chan_width str_to_bw(const char *str);
+int parse_txq_stats(char *buf, int buflen, struct nlattr *tid_stats_attr, int header,
+		    int tid);
 int put_chandef(struct nl_msg *msg, struct chandef *chandef);
 
 void print_ht_mcs(const __u8 *mcs);
diff --git a/station.c b/station.c
index f836d0a..ba8c83f 100644
--- a/station.c
+++ b/station.c
@@ -43,6 +43,82 @@ static void print_power_mode(struct nlattr *a)
 	}
 }
 
+int parse_txq_stats(char *buf, int buflen, struct nlattr *tid_stats_attr, int header,
+		    int tid)
+{
+	struct nlattr *txqstats_info[NL80211_TXQ_STATS_MAX + 1], *txqinfo;
+	static struct nla_policy txqstats_policy[NL80211_TXQ_STATS_MAX + 1] = {
+		[NL80211_TXQ_STATS_BACKLOG_BYTES] = { .type = NLA_U32 },
+		[NL80211_TXQ_STATS_BACKLOG_PACKETS] = { .type = NLA_U32 },
+		[NL80211_TXQ_STATS_FLOWS] = { .type = NLA_U32 },
+		[NL80211_TXQ_STATS_DROPS] = { .type = NLA_U32 },
+		[NL80211_TXQ_STATS_ECN_MARKS] = { .type = NLA_U32 },
+		[NL80211_TXQ_STATS_OVERLIMIT] = { .type = NLA_U32 },
+		[NL80211_TXQ_STATS_COLLISIONS] = { .type = NLA_U32 },
+		[NL80211_TXQ_STATS_TX_BYTES] = { .type = NLA_U32 },
+		[NL80211_TXQ_STATS_TX_PACKETS] = { .type = NLA_U32 },
+	};
+	char *pos = buf;
+	if (nla_parse_nested(txqstats_info, NL80211_TXQ_STATS_MAX, tid_stats_attr,
+			     txqstats_policy)) {
+		printf("failed to parse nested TXQ stats attributes!");
+		return 0;
+	}
+
+	if (header && tid >= 0)
+		pos += snprintf(buf, buflen, "\n\t\tTID\tqsz-byt\t"
+				"qsz-pkt\tflows\tdrops\tmarks\toverlmt\t"
+				"hashcol\ttx-bytes\ttx-packets");
+	else if (header)
+		pos += snprintf(buf, buflen, "\n\t\tqsz-byt\t"
+				"qsz-pkt\tflows\tdrops\tmarks\toverlmt\t"
+				"hashcol\ttx-bytes\ttx-packets");
+
+	if (tid >= 0)
+		pos += snprintf(pos, buflen - (pos - buf), "\n\t\t%d", tid);
+	else
+		pos += snprintf(pos, buflen - (pos - buf), "\n\t");
+
+	txqinfo = txqstats_info[NL80211_TXQ_STATS_BACKLOG_BYTES];
+	if (txqinfo)
+		pos += snprintf(pos, buflen - (pos - buf), "\t%u",
+				nla_get_u32(txqinfo));
+	txqinfo = txqstats_info[NL80211_TXQ_STATS_BACKLOG_PACKETS];
+	if (txqinfo)
+		pos += snprintf(pos, buflen - (pos - buf), "\t%u",
+				nla_get_u32(txqinfo));
+	txqinfo = txqstats_info[NL80211_TXQ_STATS_FLOWS];
+	if (txqinfo)
+		pos += snprintf(pos, buflen - (pos - buf), "\t%u",
+				nla_get_u32(txqinfo));
+	txqinfo = txqstats_info[NL80211_TXQ_STATS_DROPS];
+	if (txqinfo)
+		pos += snprintf(pos, buflen - (pos - buf), "\t%u",
+				nla_get_u32(txqinfo));
+	txqinfo = txqstats_info[NL80211_TXQ_STATS_ECN_MARKS];
+	if (txqinfo)
+		pos += snprintf(pos, buflen - (pos - buf), "\t%u",
+				nla_get_u32(txqinfo));
+	txqinfo = txqstats_info[NL80211_TXQ_STATS_OVERLIMIT];
+	if (txqinfo)
+		pos += snprintf(pos, buflen - (pos - buf), "\t%u",
+				nla_get_u32(txqinfo));
+	txqinfo = txqstats_info[NL80211_TXQ_STATS_COLLISIONS];
+	if (txqinfo)
+		pos += snprintf(pos, buflen - (pos - buf), "\t%u",
+				nla_get_u32(txqinfo));
+	txqinfo = txqstats_info[NL80211_TXQ_STATS_TX_BYTES];
+	if (txqinfo)
+		pos += snprintf(pos, buflen - (pos - buf), "\t%u",
+				nla_get_u32(txqinfo));
+	txqinfo = txqstats_info[NL80211_TXQ_STATS_TX_PACKETS];
+	if (txqinfo)
+		pos += snprintf(pos, buflen - (pos - buf), "\t\t%u",
+				nla_get_u32(txqinfo));
+
+	return pos - buf;
+
+}
 void parse_tid_stats(struct nlattr *tid_stats_attr)
 {
 	struct nlattr *stats_info[NL80211_TID_STATS_MAX + 1], *tidattr, *info;
@@ -51,8 +127,11 @@ void parse_tid_stats(struct nlattr *tid_stats_attr)
 		[NL80211_TID_STATS_TX_MSDU] = { .type = NLA_U64 },
 		[NL80211_TID_STATS_TX_MSDU_RETRIES] = { .type = NLA_U64 },
 		[NL80211_TID_STATS_TX_MSDU_FAILED] = { .type = NLA_U64 },
+		[NL80211_TID_STATS_TXQ_STATS] = { .type = NLA_NESTED },
 	};
 	int rem, i = 0;
+	char txqbuf[2000] = {}, *pos = txqbuf;
+	int buflen = sizeof(txqbuf), foundtxq = 0;
 
 	printf("\n\tMSDU:\n\t\tTID\trx\ttx\ttx retries\ttx failed");
 	nla_for_each_nested(tidattr, tid_stats_attr, rem) {
@@ -61,7 +140,7 @@ void parse_tid_stats(struct nlattr *tid_stats_attr)
 			printf("failed to parse nested stats attributes!");
 			return;
 		}
-		printf("\n\t\t%d", i++);
+		printf("\n\t\t%d", i);
 		info = stats_info[NL80211_TID_STATS_RX_MSDU];
 		if (info)
 			printf("\t%llu", (unsigned long long)nla_get_u64(info));
@@ -74,7 +153,17 @@ void parse_tid_stats(struct nlattr *tid_stats_attr)
 		info = stats_info[NL80211_TID_STATS_TX_MSDU_FAILED];
 		if (info)
 			printf("\t\t%llu", (unsigned long long)nla_get_u64(info));
+		info = stats_info[NL80211_TID_STATS_TXQ_STATS];
+		if (info) {
+			pos += parse_txq_stats(pos, buflen - (pos - txqbuf), info, !foundtxq, i);
+			foundtxq = 1;
+		}
+
+		i++;
 	}
+
+	if (foundtxq)
+		printf("\n\tTXQs:%s", txqbuf);
 }
 
 void parse_bss_param(struct nlattr *bss_param_attr)
-- 
2.16.1

^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [PATCH 3/3] iw: Add getting and setting of TXQ params for phy
  2018-02-19 17:02 [PATCH 0/3] Export TXQ parameters and statistics via nl80211 Toke Høiland-Jørgensen
  2018-02-19 17:02 ` [PATCH 1/3] cfg80211: Expose TXQ stats and parameters to userspace Toke Høiland-Jørgensen
  2018-02-19 17:02 ` [PATCH 2/3] iw: Print TXQ statistics for stations and interfaces Toke Høiland-Jørgensen
@ 2018-02-19 17:02 ` Toke Høiland-Jørgensen
  2018-02-21  8:56 ` [PATCH 0/3] Export TXQ parameters and statistics via nl80211 Arend van Spriel
                   ` (2 subsequent siblings)
  5 siblings, 0 replies; 22+ messages in thread
From: Toke Høiland-Jørgensen @ 2018-02-19 17:02 UTC (permalink / raw)
  To: make-wifi-fast, linux-wireless; +Cc: Toke Høiland-Jørgensen

This adds commands to get and set the per-phy TXQ parameters for drivers
that use the intermediate TXQs. These are the settings and statistics that
are also available through /sys/kernel/debug/ieee80211/phyX/aqm.

Sample output:

$ iw phy phy0 get txq
Packet limit:		8192 pkts
Memory limit:		4194304 bytes
Quantum:		300 bytes
Number of queues:	4096
Backlog:		12 pkts
Memory usage:		52224 bytes
Packet limit overflows:	0
Memory limit overflows:	0
Hash collisions:	1

# iw phy phy0 set txq limit 1024
# iw phy phy0 set txq memory_limit 1024000
# iw phy phy0 set txq quantum 1000

Signed-off-by: Toke Høiland-Jørgensen <toke@toke.dk>
---
 info.c |   3 ++
 phy.c  | 116 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 119 insertions(+)

diff --git a/info.c b/info.c
index 1eba5c9..291cf24 100644
--- a/info.c
+++ b/info.c
@@ -609,6 +609,9 @@ broken_combination:
 		if (ext_feature_isset(nla_data(tb), nla_len(tb),
 				      NL80211_EXT_FEATURE_VHT_IBSS))
 			printf("\tDevice supports VHT-IBSS.\n");
+		if (ext_feature_isset(nla_data(tb), nla_len(tb),
+				      NL80211_EXT_FEATURE_TXQS))
+			printf("\tDriver supports FQ-CoDel-enabled intermediate TXQs.\n");
 	}
 
 	if (tb_msg[NL80211_ATTR_TDLS_SUPPORT])
diff --git a/phy.c b/phy.c
index be31820..77df7a7 100644
--- a/phy.c
+++ b/phy.c
@@ -727,3 +727,119 @@ COMMAND(set, antenna, "<bitmap> | all | <tx bitmap> <rx bitmap>",
 	NL80211_CMD_SET_WIPHY, 0, CIB_PHY, handle_antenna,
 	"Set a bitmap of allowed antennas to use for TX and RX.\n"
 	"The driver may reject antenna configurations it cannot support.");
+
+static int handle_set_txq(struct nl80211_state *state,
+			  struct nl_msg *msg,
+			  int argc, char **argv,
+			  enum id_input id)
+{
+	unsigned int argval;
+	char *end;
+
+	if (argc != 2)
+		return 1;
+
+	if (!*argv[0] || !*argv[1])
+		return 1;
+
+	argval = strtoul(argv[1], &end, 10);
+
+	if (*end)
+		return 1;
+
+	if (!argval)
+		return 1;
+
+	if (strcmp("limit", argv[0]) == 0)
+		NLA_PUT_U32(msg, NL80211_ATTR_TXQ_LIMIT, argval);
+	else if (strcmp("memory_limit", argv[0]) == 0)
+		NLA_PUT_U32(msg, NL80211_ATTR_TXQ_MEMORY_LIMIT, argval);
+	else if (strcmp("quantum", argv[0]) == 0)
+		NLA_PUT_U32(msg, NL80211_ATTR_TXQ_QUANTUM, argval);
+	else
+		return -1;
+
+	return 0;
+ nla_put_failure:
+	return -ENOBUFS;
+}
+COMMAND(set, txq, "limit <packets> | memory_limit <bytes> | quantum <bytes>",
+	NL80211_CMD_SET_WIPHY, 0, CIB_PHY, handle_set_txq,
+	"Set TXQ parameters. The limit and memory_limit are global queue limits\n"
+	"for the whole phy. The quantum is the DRR scheduler quantum setting.\n"
+	"Valid values: 1 - 2**32");
+
+static int print_txq_handler(struct nl_msg *msg, void *arg)
+{
+	struct nlattr *attrs[NL80211_ATTR_MAX + 1];
+	struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
+	struct nlattr *txqstats_info[NL80211_TXQ_STATS_MAX + 1], *txqinfo;
+	static struct nla_policy txqstats_policy[NL80211_TXQ_STATS_MAX + 1] = {
+		[NL80211_TXQ_STATS_BACKLOG_PACKETS] = { .type = NLA_U32 },
+		[NL80211_TXQ_STATS_BACKLOG_BYTES] = { .type = NLA_U32 },
+		[NL80211_TXQ_STATS_OVERLIMIT] = { .type = NLA_U32 },
+		[NL80211_TXQ_STATS_OVERMEMORY] = { .type = NLA_U32 },
+		[NL80211_TXQ_STATS_COLLISIONS] = { .type = NLA_U32 },
+		[NL80211_TXQ_STATS_MAX_FLOWS] = { .type = NLA_U32 },
+	};
+
+	nla_parse(attrs, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
+		  genlmsg_attrlen(gnlh, 0), NULL);
+
+
+	if (attrs[NL80211_ATTR_TXQ_LIMIT])
+		printf("Packet limit:\t\t%u pkts\n",
+			nla_get_u32(attrs[NL80211_ATTR_TXQ_LIMIT]));
+	if (attrs[NL80211_ATTR_TXQ_MEMORY_LIMIT])
+		printf("Memory limit:\t\t%u bytes\n",
+			nla_get_u32(attrs[NL80211_ATTR_TXQ_MEMORY_LIMIT]));
+	if (attrs[NL80211_ATTR_TXQ_QUANTUM])
+		printf("Quantum:\t\t%u bytes\n",
+			nla_get_u32(attrs[NL80211_ATTR_TXQ_QUANTUM]));
+
+	if (attrs[NL80211_ATTR_TXQ_STATS]) {
+		if (nla_parse_nested(txqstats_info, NL80211_TXQ_STATS_MAX,
+				     attrs[NL80211_ATTR_TXQ_STATS],
+				     txqstats_policy)) {
+			printf("failed to parse nested TXQ stats attributes!");
+			return 0;
+		}
+		txqinfo = txqstats_info[NL80211_TXQ_STATS_MAX_FLOWS];
+		if (txqinfo)
+			printf("Number of queues:\t%u\n", nla_get_u32(txqinfo));
+
+		txqinfo = txqstats_info[NL80211_TXQ_STATS_BACKLOG_PACKETS];
+		if (txqinfo)
+			printf("Backlog:\t\t%u pkts\n", nla_get_u32(txqinfo));
+
+		txqinfo = txqstats_info[NL80211_TXQ_STATS_BACKLOG_BYTES];
+		if (txqinfo)
+			printf("Memory usage:\t\t%u bytes\n", nla_get_u32(txqinfo));
+
+		txqinfo = txqstats_info[NL80211_TXQ_STATS_OVERLIMIT];
+		if (txqinfo)
+			printf("Packet limit overflows:\t%u\n", nla_get_u32(txqinfo));
+
+		txqinfo = txqstats_info[NL80211_TXQ_STATS_OVERMEMORY];
+		if (txqinfo)
+			printf("Memory limit overflows:\t%u\n", nla_get_u32(txqinfo));
+		txqinfo = txqstats_info[NL80211_TXQ_STATS_COLLISIONS];
+		if (txqinfo)
+			printf("Hash collisions:\t%u\n", nla_get_u32(txqinfo));
+	}
+	return NL_SKIP;
+}
+
+static int handle_get_txq(struct nl80211_state *state,
+			  struct nl_msg *msg,
+			  int argc, char **argv,
+			  enum id_input id)
+{
+	nla_put_flag(msg, NL80211_ATTR_SPLIT_WIPHY_DUMP);
+	nlmsg_hdr(msg)->nlmsg_flags |= NLM_F_DUMP;
+	register_handler(print_txq_handler, NULL);
+	return 0;
+}
+COMMAND(get, txq, "",
+	NL80211_CMD_GET_WIPHY, 0, CIB_PHY, handle_get_txq,
+	"Get TXQ parameters.");
-- 
2.16.1

^ permalink raw reply related	[flat|nested] 22+ messages in thread

* Re: [PATCH 0/3] Export TXQ parameters and statistics via nl80211
  2018-02-19 17:02 [PATCH 0/3] Export TXQ parameters and statistics via nl80211 Toke Høiland-Jørgensen
                   ` (2 preceding siblings ...)
  2018-02-19 17:02 ` [PATCH 3/3] iw: Add getting and setting of TXQ params for phy Toke Høiland-Jørgensen
@ 2018-02-21  8:56 ` Arend van Spriel
  2018-02-21 11:00   ` Toke Høiland-Jørgensen
  2018-02-22 10:18 ` [PATCH v2] iw: Print TXQ statistics for stations and interfaces Toke Høiland-Jørgensen
  2018-04-19  9:20 ` [PATCH 0/3] Export TXQ parameters and statistics via nl80211 Toke Høiland-Jørgensen
  5 siblings, 1 reply; 22+ messages in thread
From: Arend van Spriel @ 2018-02-21  8:56 UTC (permalink / raw)
  To: Toke Høiland-Jørgensen, make-wifi-fast, linux-wireless

On 2/19/2018 6:02 PM, Toke Høiland-Jørgensen wrote:
> This series adds TXQ parameters and statistics that were previously only
> available through debugfs to the nl80211 userspace interface and the
> cfg80211 kernel interface. Patches for iw to print the statistics and
> change the settings are included.

So what is your motivation for having this exposed through nl80211. For 
the average end-user the stats and parameters are fairly fuzzy. So can 
we expect some manual in which is described what parameter should be 
tweaked based on the retrieved statistics.

Also do you intend to remove the debugfs method? Seems a bit redundant 
to have two mostly identical interfaces in place.

> Wasn't sure whether to include the updates to nl80211.h in the iw
> patchset, so I didn't :)

Updating the nl80211.h in iw should be done with a copy from the kernel 
so it has to wait for the kernel patch to be applied (which tree I am 
unsure).

Regards,
Arend

> -Toke
>
>
> Kernel patch:
>
> Toke Høiland-Jørgensen (1):
>    cfg80211: Expose TXQ stats and parameters to userspace
>
>   include/net/cfg80211.h       |  52 +++++++++++++++++++
>   include/uapi/linux/nl80211.h |  57 +++++++++++++++++++++
>   net/mac80211/cfg.c           |  95 +++++++++++++++++++++++++++++++++++
>   net/mac80211/ieee80211_i.h   |   3 ++
>   net/mac80211/main.c          |   3 ++
>   net/mac80211/sta_info.c      |  12 +++++
>   net/mac80211/tx.c            |  20 ++++++++
>   net/wireless/nl80211.c       | 115 +++++++++++++++++++++++++++++++++++++++++++
>   net/wireless/rdev-ops.h      |  12 +++++
>   net/wireless/trace.h         |  14 ++++++
>   10 files changed, 383 insertions(+)
>
>
> iw patches (updated nl80211.h not included):
>
> Toke Høiland-Jørgensen (2):
>    iw: Print TXQ statistics for stations and interfaces
>    iw: Add getting and setting of TXQ params for phy
>
>   info.c      |   3 ++
>   interface.c |   6 ++++
>   iw.h        |   2 ++
>   phy.c       | 116 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
>   station.c   |  91 ++++++++++++++++++++++++++++++++++++++++++++++-
>   5 files changed, 217 insertions(+), 1 deletion(-)
>

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH 0/3] Export TXQ parameters and statistics via nl80211
  2018-02-21  8:56 ` [PATCH 0/3] Export TXQ parameters and statistics via nl80211 Arend van Spriel
@ 2018-02-21 11:00   ` Toke Høiland-Jørgensen
  2018-02-21 19:53     ` Arend van Spriel
  0 siblings, 1 reply; 22+ messages in thread
From: Toke Høiland-Jørgensen @ 2018-02-21 11:00 UTC (permalink / raw)
  To: Arend van Spriel, make-wifi-fast, linux-wireless

Arend van Spriel <arend.vanspriel@broadcom.com> writes:

> On 2/19/2018 6:02 PM, Toke H=C3=B8iland-J=C3=B8rgensen wrote:
>> This series adds TXQ parameters and statistics that were previously only
>> available through debugfs to the nl80211 userspace interface and the
>> cfg80211 kernel interface. Patches for iw to print the statistics and
>> change the settings are included.
>
> So what is your motivation for having this exposed through nl80211.
> For the average end-user the stats and parameters are fairly fuzzy.

Two reasons, basically:

1. Visibility and statistics; this is basically the same information
   that is available at the qdisc layer (with `tc -s qdisc`), but which
   has been missing on WiFi interfaces ever sine we switched to the TXQ
   structure. Having this available has been quite valuable for
   debugging qdisc setups on wired links, and it's not always feasible
   to ask users to recompile their kernels with debugfs enabled.

2. Having visibility into the queues from userspace makes it possible to
   make decisions based upon (e.g.) which stations are currently
   backlogged. I'm working on a "policy mode" for the airtime fairness
   scheduler which will use this capability.

> So can we expect some manual in which is described what parameter
> should be tweaked based on the retrieved statistics.

Heh, not sure I'll promise a whole manual, but I am happy to write a
blog post (or wiki page if that's better) explaining what these values
mean and what insight one might gain from them.

> Also do you intend to remove the debugfs method? Seems a bit redundant
> to have two mostly identical interfaces in place.

Yes, I am planning to do that in a separate patch; I also have some
patches pending that changes the airtime scheduler and adds airtime
statistics to nl80211. So I am planning to send a cleanup patch once all
that is in place (and I've had time to change my tools that are
currently parsing debugfs :)).

>> Wasn't sure whether to include the updates to nl80211.h in the iw
>> patchset, so I didn't :)
>
> Updating the nl80211.h in iw should be done with a copy from the
> kernel so it has to wait for the kernel patch to be applied (which
> tree I am unsure).

Gotcha. Sort of guessed that from the commit history, but wasn't sure.
Thanks for confirming my suspicions :)

-Toke

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH 0/3] Export TXQ parameters and statistics via nl80211
  2018-02-21 11:00   ` Toke Høiland-Jørgensen
@ 2018-02-21 19:53     ` Arend van Spriel
  2018-02-22 10:11       ` Toke Høiland-Jørgensen
  0 siblings, 1 reply; 22+ messages in thread
From: Arend van Spriel @ 2018-02-21 19:53 UTC (permalink / raw)
  To: Toke Høiland-Jørgensen, make-wifi-fast, linux-wireless

On 2/21/2018 12:00 PM, Toke Høiland-Jørgensen wrote:
> Arend van Spriel <arend.vanspriel@broadcom.com> writes:
>
>> On 2/19/2018 6:02 PM, Toke Høiland-Jørgensen wrote:
>>> This series adds TXQ parameters and statistics that were previously only
>>> available through debugfs to the nl80211 userspace interface and the
>>> cfg80211 kernel interface. Patches for iw to print the statistics and
>>> change the settings are included.
>>
>> So what is your motivation for having this exposed through nl80211.
>> For the average end-user the stats and parameters are fairly fuzzy.
>
> Two reasons, basically:
>
> 1. Visibility and statistics; this is basically the same information
>     that is available at the qdisc layer (with `tc -s qdisc`), but which
>     has been missing on WiFi interfaces ever sine we switched to the TXQ
>     structure. Having this available has been quite valuable for
>     debugging qdisc setups on wired links, and it's not always feasible
>     to ask users to recompile their kernels with debugfs enabled.
>
> 2. Having visibility into the queues from userspace makes it possible to
>     make decisions based upon (e.g.) which stations are currently
>     backlogged. I'm working on a "policy mode" for the airtime fairness
>     scheduler which will use this capability.

I see. Was just wondering whether there were concrete user-space 
applications planned to use the information. Cool.

>> So can we expect some manual in which is described what parameter
>> should be tweaked based on the retrieved statistics.
>
> Heh, not sure I'll promise a whole manual, but I am happy to write a
> blog post (or wiki page if that's better) explaining what these values
> mean and what insight one might gain from them.

My preference would be to have something on wireless.wiki.kernel.org. 
Another option might be to add kerneldoc section for this.

Regards,
Arend

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH 0/3] Export TXQ parameters and statistics via nl80211
  2018-02-21 19:53     ` Arend van Spriel
@ 2018-02-22 10:11       ` Toke Høiland-Jørgensen
  0 siblings, 0 replies; 22+ messages in thread
From: Toke Høiland-Jørgensen @ 2018-02-22 10:11 UTC (permalink / raw)
  To: Arend van Spriel, make-wifi-fast, linux-wireless

Arend van Spriel <arend.vanspriel@broadcom.com> writes:

>>> So can we expect some manual in which is described what parameter
>>> should be tweaked based on the retrieved statistics.
>>
>> Heh, not sure I'll promise a whole manual, but I am happy to write a
>> blog post (or wiki page if that's better) explaining what these values
>> mean and what insight one might gain from them.
>
> My preference would be to have something on wireless.wiki.kernel.org. 
> Another option might be to add kerneldoc section for this.

Sure, I can add a page on the wiki about TXQs :)

-Toke

^ permalink raw reply	[flat|nested] 22+ messages in thread

* [PATCH v2] iw: Print TXQ statistics for stations and interfaces
  2018-02-19 17:02 [PATCH 0/3] Export TXQ parameters and statistics via nl80211 Toke Høiland-Jørgensen
                   ` (3 preceding siblings ...)
  2018-02-21  8:56 ` [PATCH 0/3] Export TXQ parameters and statistics via nl80211 Arend van Spriel
@ 2018-02-22 10:18 ` Toke Høiland-Jørgensen
  2018-04-19  9:20 ` [PATCH 0/3] Export TXQ parameters and statistics via nl80211 Toke Høiland-Jørgensen
  5 siblings, 0 replies; 22+ messages in thread
From: Toke Høiland-Jørgensen @ 2018-02-22 10:18 UTC (permalink / raw)
  To: linux-wireless, make-wifi-fast; +Cc: Toke Høiland-Jørgensen

This adds printing of TXQ statistics for stations and interfaces when
supplied by the kernel. For stations, another section is added when verbose
mode is enabled; for interfaces, the multicast queue information is always
printed when available.

This is the information also available through debugfs in
/sys/kernel/debug/ieee80211/phyX/netdev:Y/aqm and
/sys/kernel/debug/ieee80211/phyX/netdev:Y/stations/*/aqm.

Sample output:

$ iw dev wlp2s0 station dump -v
Station xx:xx:xx:xx:xx:xx (on wlp2s0)
[...]
	TXQs:
		TID	qsz-byt	qsz-pkt	flows	drops	marks	overlmt	hashcol	tx-bytes	tx-packets
		0	0	0	0	0	0	0	0	0		0
		1	0	0	0	0	0	0	0	0		0
		2	0	0	0	0	0	0	0	0		0
		3	0	0	0	0	0	0	0	0		0
		4	0	0	0	0	0	0	0	0		0
		5	0	0	0	0	0	0	0	0		0
		6	0	0	0	0	0	0	0	0		0
		7	0	0	0	0	0	0	0	0		0
		8	0	0	0	0	0	0	0	0		0
		9	0	0	0	0	0	0	0	0		0
		10	0	0	0	0	0	0	0	0		0
		11	0	0	0	0	0	0	0	0		0
		12	0	0	0	0	0	0	0	0		0
		13	0	0	0	0	0	0	0	0		0
		14	0	0	0	0	0	0	0	0		0
		15	0	0	0	0	0	0	0	0		0
[...]

$ iw dev wlp2s0 info
Interface wlp2s0
	ifindex 9
	wdev 0x1
	addr xx:xx:xx:xx:xx:xx
	type AP
	wiphy 0
	channel 165 (5825 MHz), width: 20 MHz, center1: 5825 MHz
	txpower 24.00 dBm
	multicast TXQ:
		qsz-byt	qsz-pkt	flows	drops	marks	overlmt	hashcol	tx-bytes	tx-packets
		0	0	72	0	0	0	0	7380		72

Signed-off-by: Toke Høiland-Jørgensen <toke@toke.dk>
---
v2:
  - Correctly handle variable indent of 'iw dev' output

 interface.c |  6 +++++
 iw.h        |  2 ++
 station.c   | 88 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
 3 files changed, 95 insertions(+), 1 deletion(-)

diff --git a/interface.c b/interface.c
index a19c83f..712bbdc 100644
--- a/interface.c
+++ b/interface.c
@@ -441,6 +441,12 @@ static int print_iface_handler(struct nl_msg *msg, void *arg)
 		       indent, txp / 100, txp % 100);
 	}
 
+	if (tb_msg[NL80211_ATTR_TXQ_STATS]) {
+		char buf[150];
+		parse_txq_stats(buf, sizeof(buf), tb_msg[NL80211_ATTR_TXQ_STATS], 1, -1, indent);
+		printf("%s\tmulticast TXQ:%s\n", indent, buf);
+	}
+
 	return NL_SKIP;
 }
 
diff --git a/iw.h b/iw.h
index ee7ca20..47aa27d 100644
--- a/iw.h
+++ b/iw.h
@@ -183,6 +183,8 @@ unsigned char *parse_hex(char *hex, size_t *outlen);
 int parse_keys(struct nl_msg *msg, char **argv, int argc);
 int parse_freqchan(struct chandef *chandef, bool chan, int argc, char **argv, int *parsed);
 enum nl80211_chan_width str_to_bw(const char *str);
+int parse_txq_stats(char *buf, int buflen, struct nlattr *tid_stats_attr, int header,
+		    int tid, const char *indent);
 int put_chandef(struct nl_msg *msg, struct chandef *chandef);
 
 void print_ht_mcs(const __u8 *mcs);
diff --git a/station.c b/station.c
index f836d0a..0d2c1ba 100644
--- a/station.c
+++ b/station.c
@@ -43,6 +43,79 @@ static void print_power_mode(struct nlattr *a)
 	}
 }
 
+int parse_txq_stats(char *buf, int buflen, struct nlattr *tid_stats_attr, int header,
+		    int tid, const char *indent)
+{
+	struct nlattr *txqstats_info[NL80211_TXQ_STATS_MAX + 1], *txqinfo;
+	static struct nla_policy txqstats_policy[NL80211_TXQ_STATS_MAX + 1] = {
+		[NL80211_TXQ_STATS_BACKLOG_BYTES] = { .type = NLA_U32 },
+		[NL80211_TXQ_STATS_BACKLOG_PACKETS] = { .type = NLA_U32 },
+		[NL80211_TXQ_STATS_FLOWS] = { .type = NLA_U32 },
+		[NL80211_TXQ_STATS_DROPS] = { .type = NLA_U32 },
+		[NL80211_TXQ_STATS_ECN_MARKS] = { .type = NLA_U32 },
+		[NL80211_TXQ_STATS_OVERLIMIT] = { .type = NLA_U32 },
+		[NL80211_TXQ_STATS_COLLISIONS] = { .type = NLA_U32 },
+		[NL80211_TXQ_STATS_TX_BYTES] = { .type = NLA_U32 },
+		[NL80211_TXQ_STATS_TX_PACKETS] = { .type = NLA_U32 },
+	};
+	char *pos = buf;
+	if (nla_parse_nested(txqstats_info, NL80211_TXQ_STATS_MAX, tid_stats_attr,
+			     txqstats_policy)) {
+		printf("failed to parse nested TXQ stats attributes!");
+		return 0;
+	}
+
+	if (header)
+		pos += snprintf(buf, buflen, "\n%s\t%s\tqsz-byt\t"
+				"qsz-pkt\tflows\tdrops\tmarks\toverlmt\t"
+				"hashcol\ttx-bytes\ttx-packets", indent,
+				tid >= 0 ? "TID" : "");
+
+	pos += snprintf(pos, buflen - (pos - buf), "\n%s\t", indent);
+	if (tid >= 0)
+		pos += snprintf(pos, buflen - (pos - buf), "%d", tid);
+
+
+	txqinfo = txqstats_info[NL80211_TXQ_STATS_BACKLOG_BYTES];
+	if (txqinfo)
+		pos += snprintf(pos, buflen - (pos - buf), "\t%u",
+				nla_get_u32(txqinfo));
+	txqinfo = txqstats_info[NL80211_TXQ_STATS_BACKLOG_PACKETS];
+	if (txqinfo)
+		pos += snprintf(pos, buflen - (pos - buf), "\t%u",
+				nla_get_u32(txqinfo));
+	txqinfo = txqstats_info[NL80211_TXQ_STATS_FLOWS];
+	if (txqinfo)
+		pos += snprintf(pos, buflen - (pos - buf), "\t%u",
+				nla_get_u32(txqinfo));
+	txqinfo = txqstats_info[NL80211_TXQ_STATS_DROPS];
+	if (txqinfo)
+		pos += snprintf(pos, buflen - (pos - buf), "\t%u",
+				nla_get_u32(txqinfo));
+	txqinfo = txqstats_info[NL80211_TXQ_STATS_ECN_MARKS];
+	if (txqinfo)
+		pos += snprintf(pos, buflen - (pos - buf), "\t%u",
+				nla_get_u32(txqinfo));
+	txqinfo = txqstats_info[NL80211_TXQ_STATS_OVERLIMIT];
+	if (txqinfo)
+		pos += snprintf(pos, buflen - (pos - buf), "\t%u",
+				nla_get_u32(txqinfo));
+	txqinfo = txqstats_info[NL80211_TXQ_STATS_COLLISIONS];
+	if (txqinfo)
+		pos += snprintf(pos, buflen - (pos - buf), "\t%u",
+				nla_get_u32(txqinfo));
+	txqinfo = txqstats_info[NL80211_TXQ_STATS_TX_BYTES];
+	if (txqinfo)
+		pos += snprintf(pos, buflen - (pos - buf), "\t%u",
+				nla_get_u32(txqinfo));
+	txqinfo = txqstats_info[NL80211_TXQ_STATS_TX_PACKETS];
+	if (txqinfo)
+		pos += snprintf(pos, buflen - (pos - buf), "\t\t%u",
+				nla_get_u32(txqinfo));
+
+	return pos - buf;
+
+}
 void parse_tid_stats(struct nlattr *tid_stats_attr)
 {
 	struct nlattr *stats_info[NL80211_TID_STATS_MAX + 1], *tidattr, *info;
@@ -51,8 +124,11 @@ void parse_tid_stats(struct nlattr *tid_stats_attr)
 		[NL80211_TID_STATS_TX_MSDU] = { .type = NLA_U64 },
 		[NL80211_TID_STATS_TX_MSDU_RETRIES] = { .type = NLA_U64 },
 		[NL80211_TID_STATS_TX_MSDU_FAILED] = { .type = NLA_U64 },
+		[NL80211_TID_STATS_TXQ_STATS] = { .type = NLA_NESTED },
 	};
 	int rem, i = 0;
+	char txqbuf[2000] = {}, *pos = txqbuf;
+	int buflen = sizeof(txqbuf), foundtxq = 0;
 
 	printf("\n\tMSDU:\n\t\tTID\trx\ttx\ttx retries\ttx failed");
 	nla_for_each_nested(tidattr, tid_stats_attr, rem) {
@@ -61,7 +137,7 @@ void parse_tid_stats(struct nlattr *tid_stats_attr)
 			printf("failed to parse nested stats attributes!");
 			return;
 		}
-		printf("\n\t\t%d", i++);
+		printf("\n\t\t%d", i);
 		info = stats_info[NL80211_TID_STATS_RX_MSDU];
 		if (info)
 			printf("\t%llu", (unsigned long long)nla_get_u64(info));
@@ -74,7 +150,17 @@ void parse_tid_stats(struct nlattr *tid_stats_attr)
 		info = stats_info[NL80211_TID_STATS_TX_MSDU_FAILED];
 		if (info)
 			printf("\t\t%llu", (unsigned long long)nla_get_u64(info));
+		info = stats_info[NL80211_TID_STATS_TXQ_STATS];
+		if (info) {
+			pos += parse_txq_stats(pos, buflen - (pos - txqbuf), info, !foundtxq, i, "\t");
+			foundtxq = 1;
+		}
+
+		i++;
 	}
+
+	if (foundtxq)
+		printf("\n\tTXQs:%s", txqbuf);
 }
 
 void parse_bss_param(struct nlattr *bss_param_attr)
-- 
2.16.2

^ permalink raw reply related	[flat|nested] 22+ messages in thread

* Re: [PATCH 0/3] Export TXQ parameters and statistics via nl80211
  2018-02-19 17:02 [PATCH 0/3] Export TXQ parameters and statistics via nl80211 Toke Høiland-Jørgensen
                   ` (4 preceding siblings ...)
  2018-02-22 10:18 ` [PATCH v2] iw: Print TXQ statistics for stations and interfaces Toke Høiland-Jørgensen
@ 2018-04-19  9:20 ` Toke Høiland-Jørgensen
  2018-04-19  9:52   ` Johannes Berg
  5 siblings, 1 reply; 22+ messages in thread
From: Toke Høiland-Jørgensen @ 2018-04-19  9:20 UTC (permalink / raw)
  To: make-wifi-fast, linux-wireless

Toke H=C3=B8iland-J=C3=B8rgensen <toke@toke.dk> writes:

> This series adds TXQ parameters and statistics that were previously only
> available through debugfs to the nl80211 userspace interface and the
> cfg80211 kernel interface. Patches for iw to print the statistics and
> change the settings are included.

So this patch set is now three months old. Any chance of actually
getting it, you know, merged? Or is there something more I need to do? :)

-Toke

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH 0/3] Export TXQ parameters and statistics via nl80211
  2018-04-19  9:20 ` [PATCH 0/3] Export TXQ parameters and statistics via nl80211 Toke Høiland-Jørgensen
@ 2018-04-19  9:52   ` Johannes Berg
  2018-04-19 10:30     ` Toke Høiland-Jørgensen
  0 siblings, 1 reply; 22+ messages in thread
From: Johannes Berg @ 2018-04-19  9:52 UTC (permalink / raw)
  To: Toke Høiland-Jørgensen, make-wifi-fast, linux-wireless

On Thu, 2018-04-19 at 11:20 +0200, Toke Høiland-Jørgensen wrote:
> Toke Høiland-Jørgensen <toke@toke.dk> writes:
> 
> > This series adds TXQ parameters and statistics that were previously only
> > available through debugfs to the nl80211 userspace interface and the
> > cfg80211 kernel interface. Patches for iw to print the statistics and
> > change the settings are included.
> 
> So this patch set is now three months old. Any chance of actually
> getting it, you know, merged? Or is there something more I need to do? :)

I was just thinking about it yesterday, "sighing" that I'll need to make
a decision even though I don't really know it well and can't even say if
another API would be better :-)

I think I'll take it, but I guess I'll need to review it again.

johannes

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH 0/3] Export TXQ parameters and statistics via nl80211
  2018-04-19  9:52   ` Johannes Berg
@ 2018-04-19 10:30     ` Toke Høiland-Jørgensen
  0 siblings, 0 replies; 22+ messages in thread
From: Toke Høiland-Jørgensen @ 2018-04-19 10:30 UTC (permalink / raw)
  To: Johannes Berg, make-wifi-fast, linux-wireless

Johannes Berg <johannes@sipsolutions.net> writes:

> On Thu, 2018-04-19 at 11:20 +0200, Toke H=C3=B8iland-J=C3=B8rgensen wrote:
>> Toke H=C3=B8iland-J=C3=B8rgensen <toke@toke.dk> writes:
>>=20
>> > This series adds TXQ parameters and statistics that were previously on=
ly
>> > available through debugfs to the nl80211 userspace interface and the
>> > cfg80211 kernel interface. Patches for iw to print the statistics and
>> > change the settings are included.
>>=20
>> So this patch set is now three months old. Any chance of actually
>> getting it, you know, merged? Or is there something more I need to do? :)
>
> I was just thinking about it yesterday, "sighing" that I'll need to make
> a decision even though I don't really know it well and can't even say if
> another API would be better :-)

Right. Well, feel free to bikeshed the API if you want. I just went with
the straight-forward approach :)

> I think I'll take it, but I guess I'll need to review it again.

Cool.

-Toke

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH 1/3] cfg80211: Expose TXQ stats and parameters to userspace
  2018-02-19 17:02 ` [PATCH 1/3] cfg80211: Expose TXQ stats and parameters to userspace Toke Høiland-Jørgensen
@ 2018-05-07 19:13   ` Johannes Berg
  2018-05-07 21:19     ` Toke Høiland-Jørgensen
  2018-05-08 10:18     ` Toke Høiland-Jørgensen
  2018-05-08 10:21   ` Johannes Berg
  1 sibling, 2 replies; 22+ messages in thread
From: Johannes Berg @ 2018-05-07 19:13 UTC (permalink / raw)
  To: Toke Høiland-Jørgensen, make-wifi-fast, linux-wireless

On Mon, 2018-02-19 at 18:02 +0100, Toke Høiland-Jørgensen wrote:
> This adds support for exporting the mac80211 TXQ stats via nl80211 by
> way of a nested TXQ stats attribute, as well as for configuring the
> quantum and limits that were previously only changeable through debugfs.

So I finally (sorry) decided to apply this, but I get a few issues with
it (aside from trivial rebase issues). If you're not able to fix them
now let me know and I can:

1) Lots of places put the sinfo on the stack, but it's now way bigger,
so we get warnings like

net/mac80211/ethtool.c: In function ‘ieee80211_get_stats’:
net/mac80211/ethtool.c:204:1: warning: the frame size of 1752 bytes is larger than 1024 bytes [-Wframe-larger-than=]
net/mac80211/ethtool.c:74 ieee80211_get_stats() warn: 'sinfo' puts 1672 bytes on stack

I guess we need to pull those out to dynamic allocations.

net/mac80211/cfg.c:3762:12: warning: context imbalance in 'ieee80211_get_txq_stats' - different lock contexts for basic block
net/mac80211/tx.c: In function ‘ieee80211_txq_set_params’:
net/mac80211/tx.c:1478:1: warning: control reaches end of non-void function [-Wreturn-type]

also show up.

johannes

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH 1/3] cfg80211: Expose TXQ stats and parameters to userspace
  2018-05-07 19:13   ` Johannes Berg
@ 2018-05-07 21:19     ` Toke Høiland-Jørgensen
  2018-05-07 21:20       ` Johannes Berg
  2018-05-08 10:18     ` Toke Høiland-Jørgensen
  1 sibling, 1 reply; 22+ messages in thread
From: Toke Høiland-Jørgensen @ 2018-05-07 21:19 UTC (permalink / raw)
  To: Johannes Berg, make-wifi-fast, linux-wireless



On 7 May 2018 21:13:04 CEST, Johannes Berg <johannes@sipsolutions=2Enet> w=
rote:
>On Mon, 2018-02-19 at 18:02 +0100, Toke H=C3=B8iland-J=C3=B8rgensen wrote=
:
>> This adds support for exporting the mac80211 TXQ stats via nl80211 by
>> way of a nested TXQ stats attribute, as well as for configuring the
>> quantum and limits that were previously only changeable through
>debugfs=2E
>
>So I finally (sorry) decided to apply this, but I get a few issues with
>it (aside from trivial rebase issues)=2E If you're not able to fix them
>now let me know and I can:

Great! I'll rebase and fix those and resend :)

Is the iw patch fine as-is?

-Toke

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH 1/3] cfg80211: Expose TXQ stats and parameters to userspace
  2018-05-07 21:19     ` Toke Høiland-Jørgensen
@ 2018-05-07 21:20       ` Johannes Berg
  0 siblings, 0 replies; 22+ messages in thread
From: Johannes Berg @ 2018-05-07 21:20 UTC (permalink / raw)
  To: Toke Høiland-Jørgensen, make-wifi-fast, linux-wireless

On Mon, 2018-05-07 at 23:19 +0200, Toke Høiland-Jørgensen wrote:
> 
> On 7 May 2018 21:13:04 CEST, Johannes Berg <johannes@sipsolutions.net> wrote:
> > On Mon, 2018-02-19 at 18:02 +0100, Toke Høiland-Jørgensen wrote:
> > > This adds support for exporting the mac80211 TXQ stats via nl80211 by
> > > way of a nested TXQ stats attribute, as well as for configuring the
> > > quantum and limits that were previously only changeable through
> > 
> > debugfs.
> > 
> > So I finally (sorry) decided to apply this, but I get a few issues with
> > it (aside from trivial rebase issues). If you're not able to fix them
> > now let me know and I can:
> 
> Great! I'll rebase and fix those and resend :)
> 
> Is the iw patch fine as-is?

Good question, let me review it :-)

johannes

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH 2/3] iw: Print TXQ statistics for stations and interfaces
  2018-02-19 17:02 ` [PATCH 2/3] iw: Print TXQ statistics for stations and interfaces Toke Høiland-Jørgensen
@ 2018-05-07 21:21   ` Johannes Berg
  2018-05-07 21:30     ` Toke Høiland-Jørgensen
  0 siblings, 1 reply; 22+ messages in thread
From: Johannes Berg @ 2018-05-07 21:21 UTC (permalink / raw)
  To: Toke Høiland-Jørgensen, make-wifi-fast, linux-wireless

On Mon, 2018-02-19 at 18:02 +0100, Toke Høiland-Jørgensen wrote:
> 
> +	if (header && tid >= 0)
> +		pos += snprintf(buf, buflen, "\n\t\tTID\tqsz-byt\t"
> +				"qsz-pkt\tflows\tdrops\tmarks\toverlmt\t"
> +				"hashcol\ttx-bytes\ttx-packets");
> +	else if (header)
> +		pos += snprintf(buf, buflen, "\n\t\tqsz-byt\t"
> +				"qsz-pkt\tflows\tdrops\tmarks\toverlmt\t"
> +				"hashcol\ttx-bytes\ttx-packets");
> +
> +	if (tid >= 0)
> +		pos += snprintf(pos, buflen - (pos - buf), "\n\t\t%d", tid);
> +	else
> +		pos += snprintf(pos, buflen - (pos - buf), "\n\t");
> +
> +	txqinfo = txqstats_info[NL80211_TXQ_STATS_BACKLOG_BYTES];
> +	if (txqinfo)
> +		pos += snprintf(pos, buflen - (pos - buf), "\t%u",
> +				nla_get_u32(txqinfo));

since the header is fixed, shouldn't all of these get an else branch
that just prints a tab or so?

johannes

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH 2/3] iw: Print TXQ statistics for stations and interfaces
  2018-05-07 21:21   ` Johannes Berg
@ 2018-05-07 21:30     ` Toke Høiland-Jørgensen
  0 siblings, 0 replies; 22+ messages in thread
From: Toke Høiland-Jørgensen @ 2018-05-07 21:30 UTC (permalink / raw)
  To: Johannes Berg, make-wifi-fast, linux-wireless



On 7 May 2018 23:21:30 CEST, Johannes Berg <johannes@sipsolutions=2Enet> w=
rote:
>On Mon, 2018-02-19 at 18:02 +0100, Toke H=C3=B8iland-J=C3=B8rgensen wrote=
:
>>=20
>> +	if (header && tid >=3D 0)
>> +		pos +=3D snprintf(buf, buflen, "\n\t\tTID\tqsz-byt\t"
>> +				"qsz-pkt\tflows\tdrops\tmarks\toverlmt\t"
>> +				"hashcol\ttx-bytes\ttx-packets");
>> +	else if (header)
>> +		pos +=3D snprintf(buf, buflen, "\n\t\tqsz-byt\t"
>> +				"qsz-pkt\tflows\tdrops\tmarks\toverlmt\t"
>> +				"hashcol\ttx-bytes\ttx-packets");
>> +
>> +	if (tid >=3D 0)
>> +		pos +=3D snprintf(pos, buflen - (pos - buf), "\n\t\t%d", tid);
>> +	else
>> +		pos +=3D snprintf(pos, buflen - (pos - buf), "\n\t");
>> +
>> +	txqinfo =3D txqstats_info[NL80211_TXQ_STATS_BACKLOG_BYTES];
>> +	if (txqinfo)
>> +		pos +=3D snprintf(pos, buflen - (pos - buf), "\t%u",
>> +				nla_get_u32(txqinfo));
>
>since the header is fixed, shouldn't all of these get an else branch
>that just prints a tab or so?

Ah, right, good point=2E Didn't think about what would happen if any of th=
e fields were actually omitted=2E Will fix that as well :)

-Toke

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH 1/3] cfg80211: Expose TXQ stats and parameters to userspace
  2018-05-07 19:13   ` Johannes Berg
  2018-05-07 21:19     ` Toke Høiland-Jørgensen
@ 2018-05-08 10:18     ` Toke Høiland-Jørgensen
  2018-05-08 10:18       ` Johannes Berg
  2018-05-08 10:19       ` Johannes Berg
  1 sibling, 2 replies; 22+ messages in thread
From: Toke Høiland-Jørgensen @ 2018-05-08 10:18 UTC (permalink / raw)
  To: Johannes Berg, make-wifi-fast, linux-wireless

Johannes Berg <johannes@sipsolutions.net> writes:

> net/mac80211/cfg.c:3762:12: warning: context imbalance in
> 'ieee80211_get_txq_stats' - different lock contexts for basic block

Found and fixed all the other warnings, but I'm not seeing this one. And
I don't really see what is wrong with the locking in that function? What
am I missing?

-Toke

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH 1/3] cfg80211: Expose TXQ stats and parameters to userspace
  2018-05-08 10:18     ` Toke Høiland-Jørgensen
@ 2018-05-08 10:18       ` Johannes Berg
  2018-05-08 10:19       ` Johannes Berg
  1 sibling, 0 replies; 22+ messages in thread
From: Johannes Berg @ 2018-05-08 10:18 UTC (permalink / raw)
  To: Toke Høiland-Jørgensen, make-wifi-fast, linux-wireless

On Tue, 2018-05-08 at 12:18 +0200, Toke Høiland-Jørgensen wrote:
> Johannes Berg <johannes@sipsolutions.net> writes:
> 
> > net/mac80211/cfg.c:3762:12: warning: context imbalance in
> > 'ieee80211_get_txq_stats' - different lock contexts for basic block
> 
> Found and fixed all the other warnings, but I'm not seeing this one. And
> I don't really see what is wrong with the locking in that function? What
> am I missing?

This probably came up with sparse/smatch only, I run both sparse and
smatch from "make C=1"

johannes

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH 1/3] cfg80211: Expose TXQ stats and parameters to userspace
  2018-05-08 10:18     ` Toke Høiland-Jørgensen
  2018-05-08 10:18       ` Johannes Berg
@ 2018-05-08 10:19       ` Johannes Berg
  2018-05-08 10:23         ` Toke Høiland-Jørgensen
  1 sibling, 1 reply; 22+ messages in thread
From: Johannes Berg @ 2018-05-08 10:19 UTC (permalink / raw)
  To: Toke Høiland-Jørgensen, make-wifi-fast, linux-wireless

On Tue, 2018-05-08 at 12:18 +0200, Toke Høiland-Jørgensen wrote:
> Johannes Berg <johannes@sipsolutions.net> writes:
> 
> > net/mac80211/cfg.c:3762:12: warning: context imbalance in
> > 'ieee80211_get_txq_stats' - different lock contexts for basic block
> 
> Found and fixed all the other warnings, but I'm not seeing this one. And
> I don't really see what is wrong with the locking in that function? What
> am I missing?

Oh and what's wrong is that you "return 1" from the function with a lock
held in one place, IIRC.

johannes

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH 1/3] cfg80211: Expose TXQ stats and parameters to userspace
  2018-02-19 17:02 ` [PATCH 1/3] cfg80211: Expose TXQ stats and parameters to userspace Toke Høiland-Jørgensen
  2018-05-07 19:13   ` Johannes Berg
@ 2018-05-08 10:21   ` Johannes Berg
  1 sibling, 0 replies; 22+ messages in thread
From: Johannes Berg @ 2018-05-08 10:21 UTC (permalink / raw)
  To: Toke Høiland-Jørgensen, make-wifi-fast, linux-wireless

On Mon, 2018-02-19 at 18:02 +0100, Toke Høiland-Jørgensen wrote:
> +static int ieee80211_get_txq_stats(struct wiphy *wiphy,
> +                                  struct wireless_dev *wdev,
> +                                  struct cfg80211_txq_stats *txqstats)
> +{
> +       struct ieee80211_local *local = wiphy_priv(wiphy);
> +       struct ieee80211_sub_if_data *sdata;
> +
> +       if (!local->ops->wake_tx_queue)
> +               return 1;
> +
> +       spin_lock_bh(&local->fq.lock);
> +       rcu_read_lock();
> +
> +       if (wdev) {
> +               sdata = IEEE80211_WDEV_TO_SUB_IF(wdev);
> +               if (!sdata->vif.txq)
> +                       return 1;

here.

btw, it'd be nice to split it into cfg80211 and mac80211 separate
patches.

johannes

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH 1/3] cfg80211: Expose TXQ stats and parameters to userspace
  2018-05-08 10:19       ` Johannes Berg
@ 2018-05-08 10:23         ` Toke Høiland-Jørgensen
  0 siblings, 0 replies; 22+ messages in thread
From: Toke Høiland-Jørgensen @ 2018-05-08 10:23 UTC (permalink / raw)
  To: Johannes Berg, make-wifi-fast, linux-wireless

Johannes Berg <johannes@sipsolutions.net> writes:

> On Tue, 2018-05-08 at 12:18 +0200, Toke H=C3=B8iland-J=C3=B8rgensen wrote:
>> Johannes Berg <johannes@sipsolutions.net> writes:
>>=20
>> > net/mac80211/cfg.c:3762:12: warning: context imbalance in
>> > 'ieee80211_get_txq_stats' - different lock contexts for basic block
>>=20
>> Found and fixed all the other warnings, but I'm not seeing this one. And
>> I don't really see what is wrong with the locking in that function? What
>> am I missing?
>
> Oh and what's wrong is that you "return 1" from the function with a lock
> held in one place, IIRC.

Ohhh, right... I already fixed that in my local branch, which is why I
can't find it I guess :D

-Toke

^ permalink raw reply	[flat|nested] 22+ messages in thread

end of thread, other threads:[~2018-05-08 10:23 UTC | newest]

Thread overview: 22+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-02-19 17:02 [PATCH 0/3] Export TXQ parameters and statistics via nl80211 Toke Høiland-Jørgensen
2018-02-19 17:02 ` [PATCH 1/3] cfg80211: Expose TXQ stats and parameters to userspace Toke Høiland-Jørgensen
2018-05-07 19:13   ` Johannes Berg
2018-05-07 21:19     ` Toke Høiland-Jørgensen
2018-05-07 21:20       ` Johannes Berg
2018-05-08 10:18     ` Toke Høiland-Jørgensen
2018-05-08 10:18       ` Johannes Berg
2018-05-08 10:19       ` Johannes Berg
2018-05-08 10:23         ` Toke Høiland-Jørgensen
2018-05-08 10:21   ` Johannes Berg
2018-02-19 17:02 ` [PATCH 2/3] iw: Print TXQ statistics for stations and interfaces Toke Høiland-Jørgensen
2018-05-07 21:21   ` Johannes Berg
2018-05-07 21:30     ` Toke Høiland-Jørgensen
2018-02-19 17:02 ` [PATCH 3/3] iw: Add getting and setting of TXQ params for phy Toke Høiland-Jørgensen
2018-02-21  8:56 ` [PATCH 0/3] Export TXQ parameters and statistics via nl80211 Arend van Spriel
2018-02-21 11:00   ` Toke Høiland-Jørgensen
2018-02-21 19:53     ` Arend van Spriel
2018-02-22 10:11       ` Toke Høiland-Jørgensen
2018-02-22 10:18 ` [PATCH v2] iw: Print TXQ statistics for stations and interfaces Toke Høiland-Jørgensen
2018-04-19  9:20 ` [PATCH 0/3] Export TXQ parameters and statistics via nl80211 Toke Høiland-Jørgensen
2018-04-19  9:52   ` Johannes Berg
2018-04-19 10:30     ` Toke Høiland-Jørgensen

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.