diff options
author | sam <sam@FreeBSD.org> | 2007-01-08 17:24:51 +0000 |
---|---|---|
committer | sam <sam@FreeBSD.org> | 2007-01-08 17:24:51 +0000 |
commit | fae048c8598d2452ea294b97092f230431c7d37c (patch) | |
tree | db2e192b629326cfac5f0245ca3a5e0ed3326978 /sys/net80211/ieee80211_proto.c | |
parent | 6d67972dc50a1f716abce17b6a0a3c60b8df2449 (diff) | |
download | FreeBSD-src-fae048c8598d2452ea294b97092f230431c7d37c.zip FreeBSD-src-fae048c8598d2452ea294b97092f230431c7d37c.tar.gz |
Correct several issues with rate set negotiation:
o add IEEE80211_F_JOIN flag to ieee80211_fix_rate to indicate a station
is joining a BSS; this is used to control whether or not we over-write
the basic rate bit in the calculated rate set
o fix ieee80211_fix_rate to honor IEEE80211_F_DODEL when IEEE80211_F_DONEGO
is not specified (e.g. when joining an ibss network)
o on sta join always delete unusable rates from the negotiated rate set,
this was being done only ibss networks but is also needed for 11g bss
with mixed stations
o on sta join delete unusable rates from the bss node's rate set, not the
scan table entry's rate set
o when calculating a rate set for new neighbors in an ibss caculate a
negotiated rate set so drivers are not presented with rates they should
not use
Submitted by: Sepherosa Ziehau (w/ modifications)
Obtained from: DragonFly
MFC after: 1 month
Diffstat (limited to 'sys/net80211/ieee80211_proto.c')
-rw-r--r-- | sys/net80211/ieee80211_proto.c | 65 |
1 files changed, 32 insertions, 33 deletions
diff --git a/sys/net80211/ieee80211_proto.c b/sys/net80211/ieee80211_proto.c index e11fb70..590522f 100644 --- a/sys/net80211/ieee80211_proto.c +++ b/sys/net80211/ieee80211_proto.c @@ -322,12 +322,23 @@ ieee80211_dump_pkt(const u_int8_t *buf, int len, int rate, int rssi) } } +static __inline int +findrix(const struct ieee80211_rateset *rs, int r) +{ + int i; + + for (i = 0; i < rs->rs_nrates; i++) + if ((rs->rs_rates[i] & IEEE80211_RATE_VAL) == r) + return i; + return -1; +} + int ieee80211_fix_rate(struct ieee80211_node *ni, int flags) { #define RV(v) ((v) & IEEE80211_RATE_VAL) struct ieee80211com *ic = ni->ni_ic; - int i, j, ignore, error; + int i, j, rix, error; int okrate, badrate, fixedrate; const struct ieee80211_rateset *srs; struct ieee80211_rateset *nrs; @@ -345,7 +356,6 @@ ieee80211_fix_rate(struct ieee80211_node *ni, int flags) srs = ieee80211_get_suprates(ic, ni->ni_chan); nrs = &ni->ni_rates; for (i = 0; i < nrs->rs_nrates; ) { - ignore = 0; if (flags & IEEE80211_F_DOSORT) { /* * Sort rates. @@ -367,51 +377,40 @@ ieee80211_fix_rate(struct ieee80211_node *ni, int flags) if (r == RV(srs->rs_rates[ic->ic_fixed_rate])) fixedrate = r; } + /* + * Check against supported rates. + */ + rix = findrix(srs, r); if (flags & IEEE80211_F_DONEGO) { - /* - * Check against supported rates. - */ - for (j = 0; j < srs->rs_nrates; j++) { - if (r == RV(srs->rs_rates[j])) { - /* - * Overwrite with the supported rate - * value so any basic rate bit is set. - * This insures that response we send - * to stations have the necessary basic - * rate bit set. - */ - nrs->rs_rates[i] = srs->rs_rates[j]; - break; - } - } - if (j == srs->rs_nrates) { + if (rix < 0) { /* * A rate in the node's rate set is not * supported. If this is a basic rate and we - * are operating as an AP then this is an error. + * are operating as a STA then this is an error. * Otherwise we just discard/ignore the rate. - * Note that this is important for 11b stations - * when they want to associate with an 11g AP. */ - if (ic->ic_opmode == IEEE80211_M_HOSTAP && + if ((flags & IEEE80211_F_JOIN) && (nrs->rs_rates[i] & IEEE80211_RATE_BASIC)) error++; - ignore++; + } else if ((flags & IEEE80211_F_JOIN) == 0) { + /* + * Overwrite with the supported rate + * value so any basic rate bit is set. + */ + nrs->rs_rates[i] = srs->rs_rates[rix]; } } - if (flags & IEEE80211_F_DODEL) { + if ((flags & IEEE80211_F_DODEL) && rix < 0) { /* * Delete unacceptable rates. */ - if (ignore) { - nrs->rs_nrates--; - for (j = i; j < nrs->rs_nrates; j++) - nrs->rs_rates[j] = nrs->rs_rates[j + 1]; - nrs->rs_rates[j] = 0; - continue; - } + nrs->rs_nrates--; + for (j = i; j < nrs->rs_nrates; j++) + nrs->rs_rates[j] = nrs->rs_rates[j + 1]; + nrs->rs_rates[j] = 0; + continue; } - if (!ignore) + if (rix >= 0) okrate = nrs->rs_rates[i]; i++; } |