From 93d01030c99e049ea89fa4c785fb08c5d3bf3696 Mon Sep 17 00:00:00 2001 From: damien Date: Mon, 1 Sep 2008 19:41:10 +0000 Subject: [PATCH] rework previously unused ieee80211_pwrsave() function, call it from 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 | 10 ++--- sys/net80211/ieee80211_output.c | 75 ++++++++++++++++++++++++--------- sys/net80211/ieee80211_proto.h | 6 +-- sys/net80211/ieee80211_var.h | 4 +- 4 files changed, 66 insertions(+), 29 deletions(-) diff --git a/sys/net80211/ieee80211_input.c b/sys/net80211/ieee80211_input.c index dc5808885a9..a98174527c0 100644 --- a/sys/net80211/ieee80211_input.c +++ b/sys/net80211/ieee80211_input.c @@ -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; diff --git a/sys/net80211/ieee80211_output.c b/sys/net80211/ieee80211_output.c index cb4181759c5..da7d2f1a953 100644 --- a/sys/net80211/ieee80211_output.c +++ b/sys/net80211/ieee80211_output.c @@ -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 */ diff --git a/sys/net80211/ieee80211_proto.h b/sys/net80211/ieee80211_proto.h index 93982eec369..15b316c4efa 100644 --- a/sys/net80211/ieee80211_proto.h +++ b/sys/net80211/ieee80211_proto.h @@ -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))) diff --git a/sys/net80211/ieee80211_var.h b/sys/net80211/ieee80211_var.h index 568a76350b2..f327032d5e9 100644 --- a/sys/net80211/ieee80211_var.h +++ b/sys/net80211/ieee80211_var.h @@ -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; }; -- 2.20.1