All of lore.kernel.org
 help / color / mirror / Atom feed
From: Marco Porsch <marco.porsch@etit.tu-chemnitz.de>
To: johannes@sipsolutions.net, javier@cozybit.com
Cc: linux-wireless@vger.kernel.org,
	Marco Porsch <marco.porsch@etit.tu-chemnitz.de>,
	Ivan Bezyazychnyy <ivan.bezyazychnyy@gmail.com>,
	Mike Krinkin <krinkin.m.u@gmail.com>,
	Max Filippov <jcmvbkbc@gmail.com>
Subject: [RFC 06/14] mac80211: track neighbor STA power modes
Date: Fri, 16 Nov 2012 22:47:58 -0800	[thread overview]
Message-ID: <1353134886-13256-7-git-send-email-marco.porsch@etit.tu-chemnitz.de> (raw)
In-Reply-To: <1353134886-13256-1-git-send-email-marco.porsch@etit.tu-chemnitz.de>

According to IEEE802.11-2012 a mesh peering is always associated between
two mesh STAs. Both mesh STAs have their own mesh power mode for the
mesh peering. This power mode is called the link-specific power mode.
The peer_ps_mode field has been added to the sta_info structure to
represent the peer's link-specific power mode towards the local station.
The nonpeer_ps_mode field has been added to represent the peer's power
mode towards all non-peer stations.

The peer's link-specific power modes are tracked from the Power Management
field in the Frame Control field and the Mesh Power Save Level field
in the QoS Control field. Peer and non-peer modes are tracked independently
from respective frames. This allows fast reconfiguration after a peering
change.

Signed-off-by: Marco Porsch <marco.porsch@etit.tu-chemnitz.de>
Signed-off-by: Ivan Bezyazychnyy <ivan.bezyazychnyy@gmail.com>
Signed-off-by: Mike Krinkin <krinkin.m.u@gmail.com>
Signed-off-by: Max Filippov <jcmvbkbc@gmail.com>
---
 include/linux/ieee80211.h |    9 ++++++
 net/mac80211/mesh.h       |    4 +++
 net/mac80211/mesh_ps.c    |   79 +++++++++++++++++++++++++++++++++++++++++++++
 net/mac80211/rx.c         |   18 +++++++++++
 net/mac80211/sta_info.h   |    4 +++
 5 files changed, 114 insertions(+)

diff --git a/include/linux/ieee80211.h b/include/linux/ieee80211.h
index 537edf3..1d8e69a 100644
--- a/include/linux/ieee80211.h
+++ b/include/linux/ieee80211.h
@@ -571,6 +571,15 @@ static inline int ieee80211_is_first_frag(__le16 seq_ctrl)
 	return (seq_ctrl & cpu_to_le16(IEEE80211_SCTL_FRAG)) == 0;
 }
 
+/**
+ * ieee80211_has_qos_pm - check Power Save Level in QoS control
+ * @qc - QoS control bytes in little-endian byteorder
+ */
+static inline int ieee80211_has_qos_pm(__le16 qc)
+{
+	return (qc & cpu_to_le16(IEEE80211_QOS_CTL_MESH_PS_LEVEL)) != 0;
+}
+
 struct ieee80211s_hdr {
 	u8 flags;
 	u8 ttl;
diff --git a/net/mac80211/mesh.h b/net/mac80211/mesh.h
index a13549e..0e80ea7 100644
--- a/net/mac80211/mesh.h
+++ b/net/mac80211/mesh.h
@@ -264,6 +264,10 @@ void ieee80211_set_local_ps_mode(struct sta_info *sta,
 void ieee80211_set_mesh_ps_flags(struct ieee80211_sub_if_data *sdata,
 				 struct sta_info *sta,
 				 struct ieee80211_hdr *hdr);
+void ieee80211_set_peer_ps_mode(struct sta_info *sta,
+				struct ieee80211_hdr *hdr);
+void ieee80211_set_nonpeer_ps_mode(struct sta_info *sta,
+				   struct ieee80211_hdr *hdr);
 
 /* Mesh paths */
 int mesh_nexthop_lookup(struct sk_buff *skb,
diff --git a/net/mac80211/mesh_ps.c b/net/mac80211/mesh_ps.c
index 4b7d2ef..2d147d2 100644
--- a/net/mac80211/mesh_ps.c
+++ b/net/mac80211/mesh_ps.c
@@ -232,3 +232,82 @@ void ieee80211_set_mesh_ps_flags(struct ieee80211_sub_if_data *sdata,
 	else
 		*qc &= cpu_to_le16(~IEEE80211_QOS_CTL_MESH_PS_LEVEL);
 }
+
+/**
+ * ieee80211_set_peer_ps_mode - track the neighbor mesh STA's peer-specific
+ * power mode towards the local STA
+ *
+ * @sta: STA info to update
+ * @hdr: IEEE 802.11 QoS Header
+ */
+void ieee80211_set_peer_ps_mode(struct sta_info *sta,
+				struct ieee80211_hdr *hdr)
+{
+	enum nl80211_mesh_power_mode pm;
+	__le16 *qc = (__le16 *) ieee80211_get_qos_ctl(hdr);
+	static const char *modes[] = {
+		[NL80211_MESH_POWER_ACTIVE] = "active",
+		[NL80211_MESH_POWER_LIGHT_SLEEP] = "light sleep",
+		[NL80211_MESH_POWER_DEEP_SLEEP] = "deep sleep",
+	};
+
+	WARN_ON(!ieee80211_is_data_qos(hdr->frame_control) ||
+		is_multicast_ether_addr(hdr->addr1));
+
+	/*
+	 * Test Power Managment field of frame control (PW) and
+	 * mesh power save level subfield of QoS control field (PSL)
+	 *
+	 * | PM | PSL| Mesh Power Mode |
+	 * +----+----+-----------------+
+	 * | 0  |Rsrv|    Active       |
+	 * | 1  | 0  |    Light        |
+	 * | 1  | 1  |    Deep         |
+	 */
+	if (ieee80211_has_pm(hdr->frame_control)) {
+		if (ieee80211_has_qos_pm(*qc))
+			pm = NL80211_MESH_POWER_DEEP_SLEEP;
+		else
+			pm = NL80211_MESH_POWER_LIGHT_SLEEP;
+	} else {
+		pm = NL80211_MESH_POWER_ACTIVE;
+	}
+
+	if (sta->peer_ps_mode == pm)
+		return;
+
+	mps_dbg(sta->sdata, "STA %pM enters %s mode\n",
+		sta->sta.addr, modes[pm]);
+
+	sta->peer_ps_mode = pm;
+}
+
+/**
+ * ieee80211_set_nonpeer_ps_mode - track the neighbor mesh STA's
+ * power mode towards non-peer STA
+ *
+ * @sta: STA info to update
+ * @hdr: IEEE 802.11 (QoS) Header
+ */
+void ieee80211_set_nonpeer_ps_mode(struct sta_info *sta,
+				   struct ieee80211_hdr *hdr)
+{
+	enum nl80211_mesh_power_mode pm;
+	static const char *modes[] = {
+		[NL80211_MESH_POWER_ACTIVE] = "active",
+		[NL80211_MESH_POWER_DEEP_SLEEP] = "deep sleep",
+	};
+
+	if (ieee80211_has_pm(hdr->frame_control))
+		pm = NL80211_MESH_POWER_DEEP_SLEEP;
+	else
+		pm = NL80211_MESH_POWER_ACTIVE;
+
+	if (sta->nonpeer_ps_mode == pm)
+		return;
+
+	mps_dbg(sta->sdata, "STA %pM sets non-peer mode to %s\n",
+		sta->sta.addr, modes[pm]);
+
+	sta->nonpeer_ps_mode = pm;
+}
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c
index 67aa26c..90f2ce5 100644
--- a/net/mac80211/rx.c
+++ b/net/mac80211/rx.c
@@ -1356,6 +1356,24 @@ ieee80211_rx_h_sta_process(struct ieee80211_rx_data *rx)
 		}
 	}
 
+	/* mesh power save support */
+	if (ieee80211_vif_is_mesh(&rx->sdata->vif)) {
+		if (is_unicast_ether_addr(hdr->addr1) &&
+		    ieee80211_is_data_qos(hdr->frame_control)) {
+			/*
+			 * individually addressed QoS Data/Null frames contain
+			 * peer's link-specific PS mode towards the local STA
+			 */
+			ieee80211_set_peer_ps_mode(sta, hdr);
+		} else {
+			/*
+			 * can only determine non-peer PS mode
+			 * (see IEEE802.11-2012 8.2.4.1.7)
+			 */
+			ieee80211_set_nonpeer_ps_mode(sta, hdr);
+		}
+	}
+
 	/*
 	 * Drop (qos-)data::nullfunc frames silently, since they
 	 * are used only to control station power saving mode.
diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h
index 046ca70..dbb3a10 100644
--- a/net/mac80211/sta_info.h
+++ b/net/mac80211/sta_info.h
@@ -277,6 +277,8 @@ struct sta_ampdu_mlme {
  * @local_ps_mode: local link-specific power save mode
  * @local_ps_mode_delayed: temp. storage for delayed setting of local_ps_mode
  * @local_ps_mode_timer: timer for delayed setting of local_ps_mode
+ * @peer_ps_mode: peer's link-specific power save mode
+ * @nonpeer_ps_mode: STA's power save mode towards non-peer neighbors
  * @debugfs: debug filesystem info
  * @dead: set to true when sta is unlinked
  * @uploaded: set to true when sta is uploaded to the driver
@@ -376,6 +378,8 @@ struct sta_info {
 	enum nl80211_mesh_power_mode local_ps_mode;
 	enum nl80211_mesh_power_mode local_ps_mode_delayed;
 	struct timer_list local_ps_mode_timer;
+	enum nl80211_mesh_power_mode peer_ps_mode;
+	enum nl80211_mesh_power_mode nonpeer_ps_mode;
 #endif
 
 #ifdef CONFIG_MAC80211_DEBUGFS
-- 
1.7.9.5


  parent reply	other threads:[~2012-11-17  6:48 UTC|newest]

Thread overview: 38+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2012-11-17  6:47 [RFC 00/14] mesh powersave - basics Marco Porsch
2012-11-17  6:47 ` [RFC 01/14] {nl,cfg,mac}80211: add beacon interval and DTIM period to mesh config Marco Porsch
2012-11-17  8:54   ` Johannes Berg
2012-11-17  6:47 ` [RFC 02/14] {cfg,nl}80211: mesh power mode config parameters Marco Porsch
2012-11-17  8:57   ` Johannes Berg
2012-11-17  6:47 ` [RFC 03/14] {cfg,nl}80211: set and get default mesh power mode Marco Porsch
2012-11-17  8:59   ` Johannes Berg
2012-11-17 23:38     ` Thomas Pedersen
2012-11-17  6:47 ` [RFC 04/14] mac80211: local link-specific mesh power mode logic Marco Porsch
2012-11-17  9:05   ` Johannes Berg
2012-11-17  6:47 ` [RFC 05/14] mac80211: mesh power mode indication in transmitted frames Marco Porsch
2012-11-17  9:10   ` Johannes Berg
2012-11-19 20:07     ` Marco Porsch
2012-11-19 20:32       ` Johannes Berg
2012-11-17  6:47 ` Marco Porsch [this message]
2012-11-17  9:14   ` [RFC 06/14] mac80211: track neighbor STA power modes Johannes Berg
2012-11-17  6:47 ` [RFC 07/14] {cfg,nl}80211: set local link-specific power mode Marco Porsch
2012-11-17  9:16   ` Johannes Berg
2012-11-17  6:48 ` [RFC 08/14] {cfg,nl}80211: get local and peer mesh power modes Marco Porsch
2012-11-17  6:48 ` [RFC 09/14] mac80211: add power save support structure to mesh interface Marco Porsch
2012-11-17  9:26   ` Johannes Berg
2012-11-20 23:53     ` Marco Porsch
2012-11-26 10:39       ` Johannes Berg
2012-11-17  6:48 ` [RFC 10/14] mac80211: enable frame buffering for PS STA Marco Porsch
2012-11-17  9:28   ` Johannes Berg
2012-11-17  6:48 ` [RFC 11/14] {cfg,nl}80211: add awake window to mesh config Marco Porsch
2012-11-17  9:29   ` Johannes Berg
2012-11-17  6:48 ` [RFC 12/14] mac80211: add awake window IE to mesh beacons Marco Porsch
2012-11-17  9:30   ` Johannes Berg
2012-11-17  6:48 ` [RFC 13/14] mac80211: add TIM " Marco Porsch
2012-11-17  9:33   ` Johannes Berg
2012-11-17  6:48 ` [RFC 14/14] mac80211: mesh PS individually-addressed frame release Marco Porsch
2012-11-17  9:40   ` Johannes Berg
2012-11-20 18:11     ` Marco Porsch
2012-11-26 10:45       ` Johannes Berg
2012-11-26 18:27         ` Marco Porsch
2012-11-28 13:07           ` Johannes Berg
2012-11-17  9:41 ` [RFC 00/14] mesh powersave - basics Johannes Berg

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1353134886-13256-7-git-send-email-marco.porsch@etit.tu-chemnitz.de \
    --to=marco.porsch@etit.tu-chemnitz.de \
    --cc=ivan.bezyazychnyy@gmail.com \
    --cc=javier@cozybit.com \
    --cc=jcmvbkbc@gmail.com \
    --cc=johannes@sipsolutions.net \
    --cc=krinkin.m.u@gmail.com \
    --cc=linux-wireless@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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.