/*
 * Age frames on the power save queue. The aging interval is
 * 4 times the listen interval specified by the station.  This
 * number is factored into the age calculations when the frame
 * is placed on the queue.  We store ages as time differences
 * so we can check and/or adjust only the head of the list.
 * If a frame's age exceeds the threshold then discard it.
 * The number of frames discarded is returned so the caller
 * can check if it needs to adjust the tim.
 */
int
ieee80211_node_saveq_age(struct ieee80211_node *ni)
{
    int discard = 0;
    struct node_powersave_queue *dataq,*mgtq;
    struct ieee80211vap *vap=ni->ni_vap;

    dataq = IEEE80211_NODE_SAVEQ_DATAQ(ni); 
    mgtq  = IEEE80211_NODE_SAVEQ_MGMTQ(ni); 

    /* XXX racey but good 'nuf? */
	if ((IEEE80211_NODE_SAVEQ_QLEN(dataq) != 0) ||
	    (IEEE80211_NODE_SAVEQ_QLEN(mgtq) != 0)) {
        wbuf_t wbuf;

        IEEE80211_NODE_SAVEQ_LOCK(dataq);
        while (IEEE80211_NODE_SAVEQ_POLL(dataq, wbuf) != NULL &&
             wbuf_get_age(wbuf) < IEEE80211_INACT_WAIT) {
            struct ieee80211_tx_status ts;
            ts.ts_flags = IEEE80211_TX_ERROR;
            IEEE80211_NOTE(vap, IEEE80211_MSG_POWER, ni,
                "discard frame, age %u \n", wbuf_get_age(wbuf));

            IEEE80211_NODE_SAVEQ_DEQUEUE(dataq, wbuf);
            ieee80211_release_wbuf(ni,wbuf, &ts);
            discard++;
        }
        if (wbuf != NULL)
            wbuf_set_age(wbuf, wbuf_get_age(wbuf) - IEEE80211_INACT_WAIT);
        IEEE80211_NODE_SAVEQ_UNLOCK(dataq);

        IEEE80211_NODE_SAVEQ_LOCK(mgtq);
        while (IEEE80211_NODE_SAVEQ_POLL(mgtq, wbuf) != NULL &&
             wbuf_get_age(wbuf) < IEEE80211_INACT_WAIT) {
            struct ieee80211_tx_status ts;
            ts.ts_flags = IEEE80211_TX_ERROR;
            IEEE80211_NOTE(vap, IEEE80211_MSG_POWER, ni,
                           "discard mgt frame, age %u \n", wbuf_get_age(wbuf));

            IEEE80211_NODE_SAVEQ_DEQUEUE(mgtq, wbuf);
            ieee80211_release_wbuf(ni,wbuf, &ts);
			discard++;
		}
        if (wbuf != NULL)
            wbuf_set_age(wbuf, wbuf_get_age(wbuf) - IEEE80211_INACT_WAIT);
        IEEE80211_NODE_SAVEQ_UNLOCK(mgtq);

        IEEE80211_NOTE(vap, IEEE80211_MSG_POWER, ni,
            "discard %u frames for age \n", discard);
        IEEE80211_NODE_STAT_ADD(ni, ps_discard, discard);
    }
    if ((IEEE80211_NODE_SAVEQ_QLEN(dataq) == 0) && 
        (IEEE80211_NODE_SAVEQ_QLEN(mgtq) == 0)) {
        if (vap->iv_set_tim != NULL)
            vap->iv_set_tim(ni, 0);
    }
    return discard;
}
Beispiel #2
0
/*
 * Age frames on the power save queue. The aging interval is
 * 4 times the listen interval specified by the station.  This
 * number is factored into the age calculations when the frame
 * is placed on the queue.  We store ages as time differences
 * so we can check and/or adjust only the head of the list.
 * If a frame's age exceeds the threshold then discard it.
 * The number of frames discarded is returned so the caller
 * can check if it needs to adjust the tim.
 */
int
ieee80211_node_psq_age(struct ieee80211_node *ni)
{
	struct ieee80211_psq *psq = &ni->ni_psq;
	int discard = 0;

	if (psq->psq_len != 0) {
#ifdef IEEE80211_DEBUG
		struct ieee80211vap *vap = ni->ni_vap;
#endif
		struct ieee80211_psq_head *qhead;
		struct mbuf *m;

		IEEE80211_PSQ_LOCK(psq);
		qhead = &psq->psq_head[0];
	again:
		while ((m = qhead->head) != NULL &&
		    M_AGE_GET(m) < IEEE80211_INACT_WAIT) {
			IEEE80211_NOTE(vap, IEEE80211_MSG_POWER, ni,
			     "discard frame, age %u", M_AGE_GET(m));
			if ((qhead->head = m->m_nextpkt) == NULL)
				qhead->tail = NULL;
			KASSERT(qhead->len > 0, ("qhead len %d", qhead->len));
			qhead->len--;
			KASSERT(psq->psq_len > 0, ("psq len %d", psq->psq_len));
			psq->psq_len--;
			psq_mfree(m);
			discard++;
		}
		if (qhead == &psq->psq_head[0]) { /* Algol-68 style for loop */
			qhead = &psq->psq_head[1];
			goto again;
		}
		if (m != NULL)
			M_AGE_SUB(m, IEEE80211_INACT_WAIT);
		IEEE80211_PSQ_UNLOCK(psq);

		IEEE80211_NOTE(vap, IEEE80211_MSG_POWER, ni,
		    "discard %u frames for age", discard);
		IEEE80211_NODE_STAT_ADD(ni, ps_discard, discard);
	}
	return discard;
}
Beispiel #3
0
/*
 * Age frames on the power save queue. The aging interval is
 * 4 times the listen interval specified by the station.  This
 * number is factored into the age calculations when the frame
 * is placed on the queue.  We store ages as time differences
 * so we can check and/or adjust only the head of the list.
 * If a frame's age exceeds the threshold then discard it.
 * The number of frames discarded is returned so the caller
 * can check if it needs to adjust the tim.
 */
int
ieee80211_node_saveq_age(struct ieee80211_node *ni)
{
    int discard = 0;
    struct node_powersave_queue *dataq,*mgtq;
    struct ieee80211vap *vap=ni->ni_vap;

#if LMAC_SUPPORT_POWERSAVE_QUEUE
    struct ieee80211com *ic = ni->ni_ic;

    ic->ic_node_pwrsaveq_age(ic, ni);
    if (ic->ic_get_lmac_pwrsaveq_len(ic, ni, 0) == 0 && vap->iv_set_tim != NULL) {
        vap->iv_set_tim(ni, 0, false);
    }

    return 0;
#endif

    dataq = IEEE80211_NODE_SAVEQ_DATAQ(ni);
    mgtq  = IEEE80211_NODE_SAVEQ_MGMTQ(ni);

    /* XXX racey but good 'nuf? */
    if ((IEEE80211_NODE_SAVEQ_QLEN(dataq) != 0) ||
            (IEEE80211_NODE_SAVEQ_QLEN(mgtq) != 0)) {
        wbuf_t wbuf;

        IEEE80211_NODE_SAVEQ_LOCK(dataq);
        while (IEEE80211_NODE_SAVEQ_POLL(dataq, wbuf) != NULL &&
                wbuf_get_age(wbuf) < IEEE80211_INACT_WAIT) {
            struct ieee80211_tx_status ts;
            ts.ts_flags = IEEE80211_TX_ERROR;
            IEEE80211_NOTE(vap, IEEE80211_MSG_POWER, ni,
                           "discard frame, age %u \n", wbuf_get_age(wbuf));

            IEEE80211_NODE_SAVEQ_DEQUEUE(dataq, wbuf);
            ieee80211_release_wbuf(ni,wbuf, &ts);
            discard++;
        }
        if (wbuf != NULL)
            wbuf_set_age(wbuf, wbuf_get_age(wbuf) - IEEE80211_INACT_WAIT);
        IEEE80211_NODE_SAVEQ_UNLOCK(dataq);

        IEEE80211_NODE_SAVEQ_LOCK(mgtq);
        while (IEEE80211_NODE_SAVEQ_POLL(mgtq, wbuf) != NULL &&
                wbuf_get_age(wbuf) < IEEE80211_INACT_WAIT) {
            struct ieee80211_tx_status ts;
            ts.ts_flags = IEEE80211_TX_ERROR;
            IEEE80211_NOTE(vap, IEEE80211_MSG_POWER, ni,
                           "discard mgt frame, age %u \n", wbuf_get_age(wbuf));

            IEEE80211_NODE_SAVEQ_DEQUEUE(mgtq, wbuf);
            ieee80211_release_wbuf(ni,wbuf, &ts);
            discard++;
        }
        if (wbuf != NULL)
            wbuf_set_age(wbuf, wbuf_get_age(wbuf) - IEEE80211_INACT_WAIT);
        IEEE80211_NODE_SAVEQ_UNLOCK(mgtq);

        IEEE80211_NOTE(vap, IEEE80211_MSG_POWER, ni,
                       "discard %u frames for age \n", discard);
        IEEE80211_NODE_STAT_ADD(ni, ps_discard, discard);
    }
    if ((IEEE80211_NODE_SAVEQ_QLEN(dataq) == 0) &&
            (IEEE80211_NODE_SAVEQ_QLEN(mgtq) == 0)) {
#ifdef ATH_SWRETRY
        /* also check whether there is frame in tid q */
        if (vap->iv_set_tim != NULL && (ni->ni_ic)->ic_exist_pendingfrm_tidq(ni->ni_ic, ni) !=0)
#else
        if (vap->iv_set_tim != NULL)
#endif
            vap->iv_set_tim(ni, 0, false);
    }
    return discard;
}