kern/124753: [ieee80211] net80211 discards power-save queue packets early

Adrian Chadd adrian at freebsd.org
Sun Dec 5 06:32:48 UTC 2010


Right, the problem here is:

* the listen interval advertised by the device is "1". The math here is:

        age = IEEE80211_TU_TO_MS((ni->ni_intval * ic->ic_bintval) << 2) / 1000;

* the default beacon interval is 100 TU's.
* (1 * 100) << 2 == 400 TU's
* It then is converted up to milliseconds - * 1024 / 1000, so just for
arguments sake say "400"
* then that's divided by 1000 to get age in seconds - which results in 0
* thus the packets are immediately discarded in the next call to
ieee80211_node_psq_age()

Does this always happen? From what I can tell, the code path to
actually calling ieee80211_node_psq_age() goes via the callout
ieee80211_node_timeout(), which is called every IEEE80211_INACT_WAIT
seconds (15). Unless something else is calling
ieee80211_node_timeout() more frequently.

Can you add some debugging into ieee80211_node_timeout() and find out
how often it's actually being called? If the above is actually
happening, it should only be being called every 15 seconds and thus
the chances of it occuring just as you have some age=0 frames on the
ps queue should be pretty low.

I think it's worthwhile fixing what "age" is, but I guess that'll have
to come later.

Thanks,


Adrian

2010/12/5 Adrian Chadd <adrian at freebsd.org>:
> I've done a bit of digging with this in private, would you (and others
> having this problem) please re-test with this patch:
>
> [adrian at pcbsd-3114]/data/freebsd/git/adrianchadd-freebsd/sys/net80211(48)%
> git diff .
> diff --git a/sys/net80211/ieee80211_power.c b/sys/net80211/ieee80211_power.c
> index aad82ba..a9d8eff 100644
> --- a/sys/net80211/ieee80211_power.c
> +++ b/sys/net80211/ieee80211_power.c
> @@ -393,7 +393,7 @@ ieee80211_pwrsave(struct ieee80211_node *ni, struct mbuf *m)
>        IEEE80211_PSQ_UNLOCK(psq);
>
>        IEEE80211_NOTE(vap, IEEE80211_MSG_POWER, ni,
> -           "save frame with age %d, %u now queued", age, qlen);
> +           "save frame with age %d, %u now queued (intval=%d,
> bintval=%d)", age, qlen, ni->ni_intval, ic->ic_bintval);
>
>        if (qlen == 1 && vap->iv_set_tim != NULL)
>                vap->iv_set_tim(ni, 1);
>
> I'd like to see exactly what's going on there; age=0 looks very wrong.
>
>
>
> Adrian
>


More information about the freebsd-net mailing list