/* * Age frames on the age queue. Ages are stored as time * deltas (in seconds) relative to the head so we can check * and/or adjust only the head of the list. If a frame's age * exceeds the time quanta then remove it. The list of removed * frames is is returned to the caller joined by m_nextpkt. */ struct mbuf * ieee80211_ageq_age(struct ieee80211_ageq *aq, int quanta) { struct mbuf *head, **phead; struct mbuf *m; phead = &head; if (aq->aq_len != 0) { IEEE80211_AGEQ_LOCK(aq); while ((m = aq->aq_head) != NULL && M_AGE_GET(m) < quanta) { if ((aq->aq_head = m->m_nextpkt) == NULL) aq->aq_tail = NULL; KASSERT(aq->aq_len > 0, ("aq len %d", aq->aq_len)); aq->aq_len--; /* add to private list for return */ *phead = m; phead = &m->m_nextpkt; } if (m != NULL) M_AGE_SUB(m, quanta); IEEE80211_AGEQ_UNLOCK(aq); } *phead = NULL; return head; }
/* * 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; }