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
This commit is contained in:
parent
d05b58ad32
commit
79edaebfe4
@ -2471,6 +2471,7 @@ ieee80211_recv_mgmt(struct ieee80211com *ic, struct mbuf *m0,
|
||||
|
||||
IEEE80211_VERIFY_ELEMENT(rates, IEEE80211_RATE_MAXSIZE);
|
||||
rate = ieee80211_setup_rates(ni, rates, xrates,
|
||||
IEEE80211_F_JOIN |
|
||||
IEEE80211_F_DOSORT | IEEE80211_F_DOFRATE |
|
||||
IEEE80211_F_DONEGO | IEEE80211_F_DODEL);
|
||||
if (rate & IEEE80211_RATE_BASIC) {
|
||||
|
@ -517,7 +517,8 @@ ieee80211_match_bss(struct ieee80211com *ic, struct ieee80211_node *ni)
|
||||
if (ni->ni_capinfo & IEEE80211_CAPINFO_PRIVACY)
|
||||
fail |= 0x04;
|
||||
}
|
||||
rate = ieee80211_fix_rate(ni, IEEE80211_F_DONEGO | IEEE80211_F_DOFRATE);
|
||||
rate = ieee80211_fix_rate(ni,
|
||||
IEEE80211_F_JOIN | IEEE80211_F_DONEGO | IEEE80211_F_DOFRATE);
|
||||
if (rate & IEEE80211_RATE_BASIC)
|
||||
fail |= 0x08;
|
||||
if (ic->ic_des_esslen != 0 &&
|
||||
@ -802,11 +803,6 @@ ieee80211_sta_join(struct ieee80211com *ic, struct ieee80211_node *selbs)
|
||||
|
||||
if (ic->ic_opmode == IEEE80211_M_IBSS) {
|
||||
struct ieee80211_node_table *nt;
|
||||
/*
|
||||
* Delete unusable rates; we've already checked
|
||||
* that the negotiated rate set is acceptable.
|
||||
*/
|
||||
ieee80211_fix_rate(selbs, IEEE80211_F_DODEL);
|
||||
/*
|
||||
* Fillin the neighbor table; it will already
|
||||
* exist if we are simply switching mastership.
|
||||
@ -828,6 +824,13 @@ ieee80211_sta_join(struct ieee80211com *ic, struct ieee80211_node *selbs)
|
||||
copy_bss(selbs, obss);
|
||||
ieee80211_free_node(obss);
|
||||
}
|
||||
|
||||
/*
|
||||
* Delete unusable rates; we've already checked
|
||||
* that the negotiated rate set is acceptable.
|
||||
*/
|
||||
ieee80211_fix_rate(ic->ic_bss, IEEE80211_F_DODEL | IEEE80211_F_JOIN);
|
||||
|
||||
/*
|
||||
* Set the erp state (mostly the slot time) to deal with
|
||||
* the auto-select case; this should be redundant if the
|
||||
@ -1295,7 +1298,9 @@ ieee80211_init_neighbor(struct ieee80211_node *ni,
|
||||
ieee80211_saveie(&ni->ni_wpa_ie, sp->wpa);
|
||||
|
||||
/* NB: must be after ni_chan is setup */
|
||||
ieee80211_setup_rates(ni, sp->rates, sp->xrates, IEEE80211_F_DOSORT);
|
||||
ieee80211_setup_rates(ni, sp->rates, sp->xrates,
|
||||
IEEE80211_F_DOSORT | IEEE80211_F_DOFRATE |
|
||||
IEEE80211_F_DONEGO | IEEE80211_F_DODEL);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -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++;
|
||||
}
|
||||
|
@ -180,6 +180,7 @@ const struct ieee80211_aclator *ieee80211_aclator_get(const char *name);
|
||||
#define IEEE80211_F_DOFRATE 0x00000002 /* use fixed rate */
|
||||
#define IEEE80211_F_DONEGO 0x00000004 /* calc negotiated rate */
|
||||
#define IEEE80211_F_DODEL 0x00000008 /* delete ignore rate */
|
||||
#define IEEE80211_F_JOIN 0x00000010 /* sta joining our bss */
|
||||
int ieee80211_fix_rate(struct ieee80211_node *, int);
|
||||
|
||||
/*
|
||||
|
Loading…
Reference in New Issue
Block a user