PERFORCE change 77273 for review

Sam Leffler sam at FreeBSD.org
Sun May 22 03:49:07 GMT 2005


http://perforce.freebsd.org/chv.cgi?CH=77273

Change 77273 by sam at sam_ebb on 2005/05/22 03:48:56

	Fillin simple sta-side ps operation:
	o process tim ie and drop out of ps when we see frame(s) pending
	  (need to optimize, e.g. just stay awake for mcast traffic)
	o do sta beacon processing when scanning too
	o flush ps queue when leaving sta ps state; we don't need to wait
	  for an ack of the null data frame since we're guaranteed frame
	  ordering (though bad things will happen if the ap doesn't hear
	  the null data frame)

Affected files ...

.. //depot/projects/vap/sys/net80211/ieee80211_input.c#14 edit

Differences ...

==== //depot/projects/vap/sys/net80211/ieee80211_input.c#14 (text+ko) ====

@@ -2109,6 +2109,7 @@
 	u_int8_t *frm, *efrm;
 	u_int8_t *ssid, *rates, *xrates, *wpa, *wme, *ath;
 	int reassoc, resp, allocbs;
+	struct ieee80211_tim_ie *tim;
 
 	wh = mtod(m0, struct ieee80211_frame *);
 	frm = (u_int8_t *)&wh[1];
@@ -2154,6 +2155,7 @@
 		scan.capinfo = le16toh(*(u_int16_t *)frm);	frm += 2;
 		scan.bchan = ieee80211_chan2ieee(ic, ic->ic_curchan);
 		scan.chan = scan.bchan;
+		tim = NULL;
 
 		while (frm < efrm) {
 			switch (*frm) {
@@ -2184,6 +2186,7 @@
 			case IEEE80211_ELEMID_TIM:
 				/* XXX ATIM? */
 				scan.timoff = frm - mtod(m0, u_int8_t *);
+				tim = (struct ieee80211_tim_ie *) frm;
 				break;
 			case IEEE80211_ELEMID_IBSSPARMS:
 				break;
@@ -2247,6 +2250,7 @@
 			 *     But we should take it for FH phy because
 			 *     the rssi value should be correct even for
 			 *     different hop pattern in FH.
+			 * XXX detect associated ap changing channels
 			 */
 			IEEE80211_DISCARD(vap, IEEE80211_MSG_ELEMID,
 			    wh, ieee80211_mgt_subtype_name[subtype >>
@@ -2271,8 +2275,7 @@
 		 */
 		if (vap->iv_opmode == IEEE80211_M_STA &&
 		    ni->ni_associd != 0 &&
-		    ((ic->ic_flags & IEEE80211_F_SCAN) == 0 ||
-		     IEEE80211_ADDR_EQ(wh->i_addr2, ni->ni_bssid))) {
+		    IEEE80211_ADDR_EQ(wh->i_addr2, ni->ni_bssid)) {
 			if (ni->ni_erp != scan.erp) {
 				IEEE80211_NOTE(vap, IEEE80211_MSG_ASSOC, ni,
 				    "erp change: was 0x%x, now 0x%x",
@@ -2322,28 +2325,45 @@
 			}
 			if (scan.doth != NULL)
 				ieee80211_parse_dothparams(vap, scan.doth, wh);
-			if ((ic->ic_flags & IEEE80211_F_SCAN) == 0) {
+			if (tim != NULL) {
 				/*
-				 * Check if it's the right time to do a
-				 * background scan.  Background scanning must
-				 * be enabled and we must not be operating in
-				 * turbo phase of dynamic turbo mode.  Then,
-				 * it's been a while since the last background
-				 * scan and if no data frames have come through
-				 * recently, kick off a scan.  Note that this
-				 * is the mechanism by which a background scan
-				 * is started _and_ continued each time we
-				 * return on-channel to receive a beacon from
-				 * our ap.
+				 * Check the TIM. For now we drop out of
+				 * power save mode for any reason.
 				 */
-				if ((vap->iv_flags & IEEE80211_F_BGSCAN) &&
-				    !IEEE80211_IS_CHAN_DTURBO(ic->ic_curchan) &&
-				    ticks - ic->ic_lastscan >= vap->iv_bgscanintvl &&
-				    ticks - ic->ic_lastdata >= vap->iv_bgscanidle)
-					ieee80211_bg_scan(vap);
-				/* NB: don't need the rest of this */
-				return;
+				int aid = IEEE80211_AID(ni->ni_associd);
+				int ix = aid / NBBY;
+				int min = tim->tim_bitctl &~ 1;
+				int max = tim->tim_len + min - 4;
+				if ((tim->tim_bitctl&1) ||
+				    (min <= ix && ix <= max &&
+				     isset(tim->tim_bitmap - min, aid)))
+					ieee80211_sta_pwrsave(vap, 0);
 			}
+			/*
+			 * If scanning, pass the info to the scan module.
+			 * Otherwise, check if it's the right time to do
+			 * a background scan.  Background scanning must
+			 * be enabled and we must not be operating in the
+			 * turbo phase of dynamic turbo mode.  Then,
+			 * it's been a while since the last background
+			 * scan and if no data frames have come through
+			 * recently, kick off a scan.  Note that this
+			 * is the mechanism by which a background scan
+			 * is started _and_ continued each time we
+			 * return on-channel to receive a beacon from
+			 * our ap.
+			 */
+			if (ic->ic_flags & IEEE80211_F_SCAN)
+				ieee80211_add_scan(vap, &scan, wh,
+					subtype, rssi, rstamp);
+			else if ((vap->iv_flags & IEEE80211_F_BGSCAN) &&
+			    !IEEE80211_IS_CHAN_DTURBO(ic->ic_curchan) &&
+			    time_after(ticks,
+			       ic->ic_lastscan + vap->iv_bgscanintvl) &&
+			    time_after(ticks,
+			       ic->ic_lastdata + vap->iv_bgscanidle))
+				ieee80211_bg_scan(vap);
+			return;
 		}
 		/*
 		 * If scanning, just pass information to the scan module.
@@ -2985,20 +3005,54 @@
 ieee80211_sta_pwrsave(struct ieee80211vap *vap, int enable)
 {
 	struct ieee80211_node *ni = vap->iv_bss;
+	int qlen;
 
 	IEEE80211_NOTE(vap, IEEE80211_MSG_POWER, ni,
 	    "sta power save mode %s", enable ? "on" : "off");
-	if (enable) {
-		if ((ni->ni_flags & IEEE80211_NODE_PWR_MGT) == 0) {
-			ni->ni_flags |= IEEE80211_NODE_PWR_MGT;
+	if (!enable) {
+		if (ni->ni_flags & IEEE80211_NODE_PWR_MGT) {
+			ni->ni_flags &= ~IEEE80211_NODE_PWR_MGT;
 			ieee80211_send_nulldata(ieee80211_ref_node(ni));
+			/*
+			 * Flush any queued frames; we can do this immediately
+			 * because we know they'll be queued behind the null
+			 * data frame we send the ap.
+			 * XXX can we use a data frame to take us out of ps?
+			 */
+			qlen = IEEE80211_NODE_SAVEQ_QLEN(ni);
+			if (qlen != 0) {
+				struct ifnet *ifp = &vap->iv_arp.ac_if;
+				struct ifaltq *ifq = &ifp->if_snd;
+				struct ifqueue *psq = &ni->ni_savedq;
+				int active;
+
+				IEEE80211_NOTE(vap, IEEE80211_MSG_POWER, ni,
+				    "flush ps queue, %u packets queued", qlen);
+				active = 1;
+				IF_LOCK(ifq);
+				IF_LOCK(psq);
+				for (;;) {
+					struct mbuf *m;
+
+					if (_IF_QLEN(psq) == 0)
+						break;
+					if (_IF_QFULL(ifq))
+						break;
+					_IF_DEQUEUE(psq, m);
+					/* NB: no accounting, already done */
+					_IF_ENQUEUE(ifq, m);
+					active = ifp->if_flags & IFF_OACTIVE;
+				}
+				IF_UNLOCK(psq);
+				IF_UNLOCK(ifq);
+				if (!active)
+					if_start(ifp);
+			}
 		}
 	} else {
-		if (ni->ni_flags & IEEE80211_NODE_PWR_MGT) {
-			ni->ni_flags &= ~IEEE80211_NODE_PWR_MGT;
+		if ((ni->ni_flags & IEEE80211_NODE_PWR_MGT) == 0) {
+			ni->ni_flags |= IEEE80211_NODE_PWR_MGT;
 			ieee80211_send_nulldata(ieee80211_ref_node(ni));
-			/* NB: cannot flush ps queue until ack received */
-			/* XXX no mechanism for this... */
 		}
 	}
 }


More information about the p4-projects mailing list