rework previously unused ieee80211_pwrsave() function, call it from
authordamien <damien@openbsd.org>
Mon, 1 Sep 2008 19:41:10 +0000 (19:41 +0000)
committerdamien <damien@openbsd.org>
Mon, 1 Sep 2008 19:41:10 +0000 (19:41 +0000)
ieee80211_mgmt_output() and ieee80211_encap().
use new IEEE80211_C_APPMGT capability flag where appropriate.
rename ic_tim_mcast to ic_tim_mcast_pending.

sys/net80211/ieee80211_input.c
sys/net80211/ieee80211_output.c
sys/net80211/ieee80211_proto.h
sys/net80211/ieee80211_var.h

index dc58088..a981745 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: ieee80211_input.c,v 1.103 2008/08/29 12:14:53 damien Exp $    */
+/*     $OpenBSD: ieee80211_input.c,v 1.104 2008/09/01 19:41:10 damien Exp $    */
 
 /*-
  * Copyright (c) 2001 Atsushi Onoe
@@ -215,8 +215,8 @@ ieee80211_input(struct ifnet *ifp, struct mbuf *m, struct ieee80211_node *ni,
        }
 
 #ifndef IEEE80211_STA_ONLY
-       if ((ic->ic_caps & IEEE80211_C_PMGT) &&
-           ic->ic_opmode == IEEE80211_M_HOSTAP &&
+       if (ic->ic_opmode == IEEE80211_M_HOSTAP &&
+           (ic->ic_caps & IEEE80211_C_APPMGT) &&
            ni->ni_state == IEEE80211_STA_ASSOC) {
                if (wh->i_fc[1] & IEEE80211_FC1_PWR_MGT) {
                        if (ni->ni_pwrsave == IEEE80211_PS_AWAKE) {
@@ -1998,8 +1998,8 @@ ieee80211_recv_pspoll(struct ieee80211com *ic, struct mbuf *m,
        struct ieee80211_frame *wh;
        u_int16_t aid;
 
-       if (!(ic->ic_caps & IEEE80211_C_PMGT) ||
-           ic->ic_opmode != IEEE80211_M_HOSTAP ||
+       if (ic->ic_opmode != IEEE80211_M_HOSTAP ||
+           !(ic->ic_caps & IEEE80211_C_APPMGT) ||
            ni->ni_state != IEEE80211_STA_ASSOC)
                return;
 
index cb41817..da7d2f1 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: ieee80211_output.c,v 1.73 2008/08/29 12:14:53 damien Exp $    */
+/*     $OpenBSD: ieee80211_output.c,v 1.74 2008/09/01 19:41:10 damien Exp $    */
 /*     $NetBSD: ieee80211_output.c,v 1.13 2004/05/31 11:02:55 dyoung Exp $     */
 
 /*-
@@ -238,6 +238,11 @@ ieee80211_mgmt_output(struct ifnet *ifp, struct ieee80211_node *ni,
                            ieee80211_chan2mode(ic, ni->ni_chan)]);
        }
 
+#ifndef IEEE80211_STA_ONLY
+       if (ic->ic_opmode == IEEE80211_M_HOSTAP &&
+           ieee80211_pwrsave(ic, m, ni) != 0)
+               return 0;
+#endif
        IF_ENQUEUE(&ic->ic_mgtq, m);
        ifp->if_timer = 1;
        (*ifp->if_start)(ifp);
@@ -606,6 +611,13 @@ ieee80211_encap(struct ifnet *ifp, struct mbuf *m, struct ieee80211_node **pni)
             (ni->ni_flags & IEEE80211_NODE_TXPROT)))
                wh->i_fc[1] |= IEEE80211_FC1_PROTECTED;
 
+#ifndef IEEE80211_STA_ONLY
+       if (ic->ic_opmode == IEEE80211_M_HOSTAP &&
+           ieee80211_pwrsave(ic, m, ni) != 0) {
+               *pni = NULL;
+               return NULL;
+       }
+#endif
        *pni = ni;
        return m;
 bad:
@@ -718,7 +730,7 @@ ieee80211_add_tim(u_int8_t *frm, struct ieee80211com *ic)
        /* Bitmap Control */
        *frm = offset;
        /* set broadcast/multicast indication bit if necessary */
-       if (ic->ic_dtim_count == 0 && ic->ic_tim_mcast)
+       if (ic->ic_dtim_count == 0 && ic->ic_tim_mcast_pending)
                *frm |= 0x01;
        frm++;
 
@@ -1527,31 +1539,56 @@ ieee80211_beacon_alloc(struct ieee80211com *ic, struct ieee80211_node *ni)
        return m;
 }
 
-void
-ieee80211_pwrsave(struct ieee80211com *ic, struct ieee80211_node *ni,
-    struct mbuf *m)
+/*
+ * Check if an outgoing MSDU or management frame should be buffered into
+ * the AP for power management.  Return 1 if the frame was buffered into
+ * the AP, or 0 if the frame shall be transmitted immediately.
+ */
+int
+ieee80211_pwrsave(struct ieee80211com *ic, struct mbuf *m,
+    struct ieee80211_node *ni)
 {
-       /* store the new packet on our queue, changing the TIM if necessary */
-       if (IF_IS_EMPTY(&ni->ni_savedq))
-               (*ic->ic_set_tim)(ic, ni->ni_associd, 1);
+       const struct ieee80211_frame *wh;
 
-       if (ni->ni_savedq.ifq_len >= IEEE80211_PS_MAX_QUEUE) {
+       KASSERT(ic->ic_opmode == IEEE80211_M_HOSTAP);
+       if (!(ic->ic_caps & IEEE80211_C_APPMGT))
+               return 0;
+
+       wh = mtod(m, struct ieee80211_frame *);
+       if (IEEE80211_IS_MULTICAST(wh->i_addr1)) {
+               /*
+                * Buffer group addressed MSDUs with the Order bit clear
+                * if any associated STAs are in PS mode.
+                */
+               if ((wh->i_fc[1] & IEEE80211_FC1_ORDER) ||
+                   ic->ic_pssta == 0)
+                       return 0;
+               ic->ic_tim_mcast_pending = 1;
+       } else {
+               /*
+                * Buffer MSDUs, A-MSDUs or management frames destined for
+                * PS STAs.
+                */
+               if (ni->ni_pwrsave == IEEE80211_PS_AWAKE ||
+                   (wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) ==
+                   IEEE80211_FC0_TYPE_CTL)
+                       return 0;
+               if (IF_IS_EMPTY(&ni->ni_savedq))
+                       (*ic->ic_set_tim)(ic, ni->ni_associd, 1);
+       }
+       /* NB: ni == ic->ic_bss for broadcast/multicast */
+       if (IF_QFULL(&ni->ni_savedq)) {
+               /* XXX should we drop the oldest instead? */
                IF_DROP(&ni->ni_savedq);
                m_freem(m);
-               if (ic->ic_if.if_flags & IFF_DEBUG)
-                       printf("%s: station %s power save queue overflow"
-                           " of size %d drops %d\n",
-                           ic->ic_if.if_xname,
-                           ether_sprintf(ni->ni_macaddr),
-                           IEEE80211_PS_MAX_QUEUE,
-                           ni->ni_savedq.ifq_drops);
        } else {
+               IF_ENQUEUE(&ni->ni_savedq, m);
                /*
-                * Similar to ieee80211_mgmt_output, store the node in
-                * the rcvif field.
+                * Similar to ieee80211_mgmt_output, store the node in the
+                * rcvif field.
                 */
-               IF_ENQUEUE(&ni->ni_savedq, m);
                m->m_pkthdr.rcvif = (void *)ni;
        }
+       return 1;
 }
 #endif /* IEEE80211_STA_ONLY */
index 93982ee..15b316c 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: ieee80211_proto.h,v 1.33 2008/08/14 15:51:43 damien Exp $     */
+/*     $OpenBSD: ieee80211_proto.h,v 1.34 2008/09/01 19:41:10 damien Exp $     */
 /*     $NetBSD: ieee80211_proto.h,v 1.3 2003/10/13 04:23:56 dyoung Exp $       */
 
 /*-
@@ -95,8 +95,8 @@ extern        int ieee80211_send_group_msg2(struct ieee80211com *,
                struct ieee80211_node *, const struct ieee80211_key *);
 extern int ieee80211_send_eapol_key_req(struct ieee80211com *,
                struct ieee80211_node *, u_int16_t, u_int64_t);
-extern void ieee80211_pwrsave(struct ieee80211com *, struct ieee80211_node *,
-               struct mbuf *);
+extern int ieee80211_pwrsave(struct ieee80211com *, struct mbuf *,
+               struct ieee80211_node *);
 extern struct mbuf *ieee80211_decap(struct ifnet *, struct mbuf *, int);
 #define        ieee80211_new_state(_ic, _nstate, _arg) \
        (((_ic)->ic_newstate)((_ic), (_nstate), (_arg)))
index 568a763..f327032 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: ieee80211_var.h,v 1.50 2008/08/29 12:14:53 damien Exp $       */
+/*     $OpenBSD: ieee80211_var.h,v 1.51 2008/09/01 19:41:11 damien Exp $       */
 /*     $NetBSD: ieee80211_var.h,v 1.7 2004/05/06 03:07:10 dyoung Exp $ */
 
 /*-
@@ -291,7 +291,7 @@ struct ieee80211com {
 
        u_int8_t                *ic_tim_bitmap;
        u_int                   ic_tim_len;
-       u_int                   ic_tim_mcast;
+       u_int                   ic_tim_mcast_pending;
        u_int                   ic_dtim_period;
        u_int                   ic_dtim_count;
 };