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);
|
IEEE80211_VERIFY_ELEMENT(rates, IEEE80211_RATE_MAXSIZE);
|
||||||
rate = ieee80211_setup_rates(ni, rates, xrates,
|
rate = ieee80211_setup_rates(ni, rates, xrates,
|
||||||
|
IEEE80211_F_JOIN |
|
||||||
IEEE80211_F_DOSORT | IEEE80211_F_DOFRATE |
|
IEEE80211_F_DOSORT | IEEE80211_F_DOFRATE |
|
||||||
IEEE80211_F_DONEGO | IEEE80211_F_DODEL);
|
IEEE80211_F_DONEGO | IEEE80211_F_DODEL);
|
||||||
if (rate & IEEE80211_RATE_BASIC) {
|
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)
|
if (ni->ni_capinfo & IEEE80211_CAPINFO_PRIVACY)
|
||||||
fail |= 0x04;
|
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)
|
if (rate & IEEE80211_RATE_BASIC)
|
||||||
fail |= 0x08;
|
fail |= 0x08;
|
||||||
if (ic->ic_des_esslen != 0 &&
|
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) {
|
if (ic->ic_opmode == IEEE80211_M_IBSS) {
|
||||||
struct ieee80211_node_table *nt;
|
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
|
* Fillin the neighbor table; it will already
|
||||||
* exist if we are simply switching mastership.
|
* 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);
|
copy_bss(selbs, obss);
|
||||||
ieee80211_free_node(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
|
* Set the erp state (mostly the slot time) to deal with
|
||||||
* the auto-select case; this should be redundant if the
|
* 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);
|
ieee80211_saveie(&ni->ni_wpa_ie, sp->wpa);
|
||||||
|
|
||||||
/* NB: must be after ni_chan is setup */
|
/* 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
|
int
|
||||||
ieee80211_fix_rate(struct ieee80211_node *ni, int flags)
|
ieee80211_fix_rate(struct ieee80211_node *ni, int flags)
|
||||||
{
|
{
|
||||||
#define RV(v) ((v) & IEEE80211_RATE_VAL)
|
#define RV(v) ((v) & IEEE80211_RATE_VAL)
|
||||||
struct ieee80211com *ic = ni->ni_ic;
|
struct ieee80211com *ic = ni->ni_ic;
|
||||||
int i, j, ignore, error;
|
int i, j, rix, error;
|
||||||
int okrate, badrate, fixedrate;
|
int okrate, badrate, fixedrate;
|
||||||
const struct ieee80211_rateset *srs;
|
const struct ieee80211_rateset *srs;
|
||||||
struct ieee80211_rateset *nrs;
|
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);
|
srs = ieee80211_get_suprates(ic, ni->ni_chan);
|
||||||
nrs = &ni->ni_rates;
|
nrs = &ni->ni_rates;
|
||||||
for (i = 0; i < nrs->rs_nrates; ) {
|
for (i = 0; i < nrs->rs_nrates; ) {
|
||||||
ignore = 0;
|
|
||||||
if (flags & IEEE80211_F_DOSORT) {
|
if (flags & IEEE80211_F_DOSORT) {
|
||||||
/*
|
/*
|
||||||
* Sort rates.
|
* 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]))
|
if (r == RV(srs->rs_rates[ic->ic_fixed_rate]))
|
||||||
fixedrate = r;
|
fixedrate = r;
|
||||||
}
|
}
|
||||||
|
/*
|
||||||
|
* Check against supported rates.
|
||||||
|
*/
|
||||||
|
rix = findrix(srs, r);
|
||||||
if (flags & IEEE80211_F_DONEGO) {
|
if (flags & IEEE80211_F_DONEGO) {
|
||||||
/*
|
if (rix < 0) {
|
||||||
* 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) {
|
|
||||||
/*
|
/*
|
||||||
* A rate in the node's rate set is not
|
* A rate in the node's rate set is not
|
||||||
* supported. If this is a basic rate and we
|
* 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.
|
* 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))
|
(nrs->rs_rates[i] & IEEE80211_RATE_BASIC))
|
||||||
error++;
|
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.
|
* Delete unacceptable rates.
|
||||||
*/
|
*/
|
||||||
if (ignore) {
|
nrs->rs_nrates--;
|
||||||
nrs->rs_nrates--;
|
for (j = i; j < nrs->rs_nrates; j++)
|
||||||
for (j = i; j < nrs->rs_nrates; j++)
|
nrs->rs_rates[j] = nrs->rs_rates[j + 1];
|
||||||
nrs->rs_rates[j] = nrs->rs_rates[j + 1];
|
nrs->rs_rates[j] = 0;
|
||||||
nrs->rs_rates[j] = 0;
|
continue;
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if (!ignore)
|
if (rix >= 0)
|
||||||
okrate = nrs->rs_rates[i];
|
okrate = nrs->rs_rates[i];
|
||||||
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_DOFRATE 0x00000002 /* use fixed rate */
|
||||||
#define IEEE80211_F_DONEGO 0x00000004 /* calc negotiated rate */
|
#define IEEE80211_F_DONEGO 0x00000004 /* calc negotiated rate */
|
||||||
#define IEEE80211_F_DODEL 0x00000008 /* delete ignore 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);
|
int ieee80211_fix_rate(struct ieee80211_node *, int);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
Loading…
x
Reference in New Issue
Block a user