First cut at half/quarter-rate 11a channel support (e.g. for use
in the Public Safety Band): o add channel flags to identify half/quarter-rate operation o add rate sets (need to check spec on 4Mb/s in 1/4 rate) o add if_media definitions for new rates o split net80211 channel setup out into ieee80211_chan_init o fixup ieee80211_mhz2ieee and ieee80211_ieee2mhz to understand half/quarter rate channels: note we temporarily use a nonstandard/hack numbering that avoids overlap with 2.4G channels because we don't (yet) have enough state to identify and/or map overlapping channel sets o fixup ieee80211_ifmedia_init so it can be called post attach and will recalculate the channel list and associated state; this enables changing channel-related state like the regulatory domain after attach (will be needed for 802.11d support too) o add ieee80211_get_suprates to return a reference to the supported rate set for a given channel o add 3, 4.5, and 27 MB/s tx rates to rate <-> media conversion routines o const-poison channel arg to ieee80211_chan2mode
This commit is contained in:
parent
bf42b54c6c
commit
41b3c790eb
@ -198,6 +198,9 @@ uint64_t ifmedia_baudrate(int);
|
||||
#define IFM_IEEE80211_OFDM72 18 /* OFDM 72Mbps */
|
||||
#define IFM_IEEE80211_DS354k 19 /* Direct Sequence 354Kbps */
|
||||
#define IFM_IEEE80211_DS512k 20 /* Direct Sequence 512Kbps */
|
||||
#define IFM_IEEE80211_OFDM3 21 /* OFDM 3Mbps */
|
||||
#define IFM_IEEE80211_OFDM4 22 /* OFDM 4.5Mbps */
|
||||
#define IFM_IEEE80211_OFDM27 23 /* OFDM 27Mbps */
|
||||
|
||||
#define IFM_IEEE80211_ADHOC 0x00000100 /* Operate in Adhoc mode */
|
||||
#define IFM_IEEE80211_HOSTAP 0x00000200 /* Operate in Host AP mode */
|
||||
@ -437,6 +440,9 @@ struct ifmedia_description {
|
||||
{ IFM_IEEE80211_OFDM72, "OFDM/72Mbps" }, \
|
||||
{ IFM_IEEE80211_DS354k, "DS/354Kbps" }, \
|
||||
{ IFM_IEEE80211_DS512k, "DS/512Kbps" }, \
|
||||
{ IFM_IEEE80211_OFDM3, "OFDM/3Mbps" }, \
|
||||
{ IFM_IEEE80211_OFDM4, "OFDM/4.5Mbps" }, \
|
||||
{ IFM_IEEE80211_OFDM27, "OFDM/27Mbps" }, \
|
||||
{ 0, NULL }, \
|
||||
}
|
||||
|
||||
@ -472,6 +478,9 @@ struct ifmedia_description {
|
||||
{ IFM_IEEE80211_DS354k, "DirectSequence/354Kbps" }, \
|
||||
{ IFM_IEEE80211_DS512k, "DS512K" }, \
|
||||
{ IFM_IEEE80211_DS512k, "DirectSequence/512Kbps" }, \
|
||||
{ IFM_IEEE80211_OFDM3, "OFDM3" }, \
|
||||
{ IFM_IEEE80211_OFDM4, "OFDM4.5" }, \
|
||||
{ IFM_IEEE80211_OFDM27, "OFDM27" }, \
|
||||
{ 0, NULL }, \
|
||||
}
|
||||
|
||||
|
@ -123,6 +123,8 @@ struct ieee80211_channel {
|
||||
#define IEEE80211_CHAN_PASSIVE 0x0200 /* Only passive scan allowed */
|
||||
#define IEEE80211_CHAN_DYN 0x0400 /* Dynamic CCK-OFDM channel */
|
||||
#define IEEE80211_CHAN_GFSK 0x0800 /* GFSK channel (FHSS PHY) */
|
||||
#define IEEE80211_CHAN_HALF 0x4000 /* Half rate channel */
|
||||
#define IEEE80211_CHAN_QUARTER 0x8000 /* Quarter rate channel */
|
||||
|
||||
/*
|
||||
* Useful combinations of channel characteristics.
|
||||
@ -175,6 +177,10 @@ struct ieee80211_channel {
|
||||
(((_c)->ic_flags & IEEE80211_CHAN_CCK) != 0)
|
||||
#define IEEE80211_IS_CHAN_GFSK(_c) \
|
||||
(((_c)->ic_flags & IEEE80211_CHAN_GFSK) != 0)
|
||||
#define IEEE80211_IS_CHAN_HALF(_c) \
|
||||
(((_c)->ic_flags & IEEE80211_CHAN_HALF) != 0)
|
||||
#define IEEE80211_IS_CHAN_QUARTER(_c) \
|
||||
(((_c)->ic_flags & IEEE80211_CHAN_QUARTER) != 0)
|
||||
|
||||
/* ni_chan encoding for FH phy */
|
||||
#define IEEE80211_FH_CHANMOD 80
|
||||
|
@ -67,6 +67,10 @@ const char *ieee80211_phymode_name[] = {
|
||||
#define B(r) ((r) | IEEE80211_RATE_BASIC)
|
||||
static const struct ieee80211_rateset ieee80211_rateset_11a =
|
||||
{ 8, { B(12), 18, B(24), 36, B(48), 72, 96, 108 } };
|
||||
static const struct ieee80211_rateset ieee80211_rateset_half =
|
||||
{ 8, { B(6), 9, B(12), 18, B(24), 36, 48, 54 } };
|
||||
static const struct ieee80211_rateset ieee80211_rateset_quarter =
|
||||
{ 8, { B(3), 4, B(6), 9, B(12), 18, 24, 27 } };
|
||||
static const struct ieee80211_rateset ieee80211_rateset_11b =
|
||||
{ 4, { B(2), B(4), B(11), B(22) } };
|
||||
/* NB: OFDM rates are handled specially based on mode */
|
||||
@ -131,30 +135,25 @@ ieee80211_default_reset(struct ifnet *ifp)
|
||||
return ENETRESET;
|
||||
}
|
||||
|
||||
void
|
||||
ieee80211_ifattach(struct ieee80211com *ic)
|
||||
/*
|
||||
* Fill in 802.11 available channel set, mark
|
||||
* all available channels as active, and pick
|
||||
* a default channel if not already specified.
|
||||
*/
|
||||
static void
|
||||
ieee80211_chan_init(struct ieee80211com *ic)
|
||||
{
|
||||
#define RATESDEFINED(m) \
|
||||
((ic->ic_modecaps & (1<<m)) && ic->ic_sup_rates[m].rs_nrates != 0)
|
||||
#define DEFAULTRATES(m, def) do { \
|
||||
if (!RATESDEFINED(m)) ic->ic_sup_rates[m] = def; \
|
||||
} while (0)
|
||||
struct ifnet *ifp = ic->ic_ifp;
|
||||
struct ieee80211_channel *c;
|
||||
int i;
|
||||
|
||||
ether_ifattach(ifp, ic->ic_myaddr);
|
||||
ifp->if_output = ieee80211_output;
|
||||
|
||||
bpfattach2(ifp, DLT_IEEE802_11,
|
||||
sizeof(struct ieee80211_frame_addr4), &ic->ic_rawbpf);
|
||||
|
||||
ieee80211_crypto_attach(ic);
|
||||
|
||||
/*
|
||||
* Fill in 802.11 available channel set, mark
|
||||
* all available channels as active, and pick
|
||||
* a default channel if not already specified.
|
||||
*/
|
||||
memset(ic->ic_chan_avail, 0, sizeof(ic->ic_chan_avail));
|
||||
ic->ic_modecaps |= 1<<IEEE80211_MODE_AUTO;
|
||||
ic->ic_modecaps = 1<<IEEE80211_MODE_AUTO;
|
||||
for (i = 0; i <= IEEE80211_CHAN_MAX; i++) {
|
||||
c = &ic->ic_channels[i];
|
||||
if (c->ic_flags) {
|
||||
@ -190,22 +189,42 @@ ieee80211_ifattach(struct ieee80211com *ic)
|
||||
}
|
||||
}
|
||||
}
|
||||
/* validate ic->ic_curmode */
|
||||
if ((ic->ic_modecaps & (1<<ic->ic_curmode)) == 0)
|
||||
ic->ic_curmode = IEEE80211_MODE_AUTO;
|
||||
ic->ic_des_chan = IEEE80211_CHAN_ANYC; /* any channel is ok */
|
||||
|
||||
/* fillin well-known rate sets if driver has not specified */
|
||||
if (!RATESDEFINED(IEEE80211_MODE_11B))
|
||||
ic->ic_sup_rates[IEEE80211_MODE_11B] = ieee80211_rateset_11b;
|
||||
if (!RATESDEFINED(IEEE80211_MODE_11G))
|
||||
ic->ic_sup_rates[IEEE80211_MODE_11G] = ieee80211_rateset_11g;
|
||||
if (!RATESDEFINED(IEEE80211_MODE_11A))
|
||||
ic->ic_sup_rates[IEEE80211_MODE_11A] = ieee80211_rateset_11a;
|
||||
if (!RATESDEFINED(IEEE80211_MODE_TURBO_A))
|
||||
ic->ic_sup_rates[IEEE80211_MODE_TURBO_A] = ieee80211_rateset_11a;
|
||||
if (!RATESDEFINED(IEEE80211_MODE_TURBO_G))
|
||||
ic->ic_sup_rates[IEEE80211_MODE_TURBO_G] = ieee80211_rateset_11g;
|
||||
DEFAULTRATES(IEEE80211_MODE_11B, ieee80211_rateset_11b);
|
||||
DEFAULTRATES(IEEE80211_MODE_11G, ieee80211_rateset_11g);
|
||||
DEFAULTRATES(IEEE80211_MODE_11A, ieee80211_rateset_11a);
|
||||
DEFAULTRATES(IEEE80211_MODE_TURBO_A, ieee80211_rateset_11a);
|
||||
DEFAULTRATES(IEEE80211_MODE_TURBO_G, ieee80211_rateset_11g);
|
||||
|
||||
/*
|
||||
* Set auto mode to reset active channel state and any desired channel.
|
||||
*/
|
||||
(void) ieee80211_setmode(ic, IEEE80211_MODE_AUTO);
|
||||
#undef DEFAULTRATES
|
||||
#undef RATESDEFINED
|
||||
}
|
||||
|
||||
void
|
||||
ieee80211_ifattach(struct ieee80211com *ic)
|
||||
{
|
||||
struct ifnet *ifp = ic->ic_ifp;
|
||||
|
||||
ether_ifattach(ifp, ic->ic_myaddr);
|
||||
ifp->if_output = ieee80211_output;
|
||||
|
||||
bpfattach2(ifp, DLT_IEEE802_11,
|
||||
sizeof(struct ieee80211_frame_addr4), &ic->ic_rawbpf);
|
||||
|
||||
ieee80211_crypto_attach(ic);
|
||||
|
||||
ic->ic_des_chan = IEEE80211_CHAN_ANYC;
|
||||
/*
|
||||
* Fill in 802.11 available channel set, mark all
|
||||
* available channels as active, and pick a default
|
||||
* channel if not already specified.
|
||||
*/
|
||||
ieee80211_chan_init(ic);
|
||||
#if 0
|
||||
/*
|
||||
* Enable WME by default if we're capable.
|
||||
@ -215,7 +234,6 @@ ieee80211_ifattach(struct ieee80211com *ic)
|
||||
#endif
|
||||
if (ic->ic_caps & IEEE80211_C_BURST)
|
||||
ic->ic_flags |= IEEE80211_F_BURST;
|
||||
(void) ieee80211_setmode(ic, ic->ic_curmode);
|
||||
|
||||
ic->ic_bintval = IEEE80211_BINTVAL_DEFAULT;
|
||||
ic->ic_bmissthreshold = IEEE80211_HWBMISS_DEFAULT;
|
||||
@ -241,7 +259,6 @@ ieee80211_ifattach(struct ieee80211com *ic)
|
||||
|
||||
KASSERT(ifp->if_spare2 == NULL, ("oops, hosed"));
|
||||
ifp->if_spare2 = ic; /* XXX temp backpointer */
|
||||
#undef RATESDEFINED
|
||||
}
|
||||
|
||||
void
|
||||
@ -277,9 +294,12 @@ ieee80211_mhz2ieee(u_int freq, u_int flags)
|
||||
else
|
||||
return 15 + ((freq - 2512) / 20);
|
||||
} else if (flags & IEEE80211_CHAN_5GHZ) { /* 5Ghz band */
|
||||
if (freq <= 5000)
|
||||
if (freq <= 5000) {
|
||||
if (flags &(IEEE80211_CHAN_HALF|IEEE80211_CHAN_QUARTER))
|
||||
return 37 + ((freq * 10) +
|
||||
((freq % 5) == 2 ? 5 : 0) - 49400) / 5;
|
||||
return (freq - 4000) / 5;
|
||||
else
|
||||
} else
|
||||
return (freq - 5000) / 5;
|
||||
} else { /* either, guess */
|
||||
if (freq == 2484)
|
||||
@ -287,7 +307,10 @@ ieee80211_mhz2ieee(u_int freq, u_int flags)
|
||||
if (freq < 2484)
|
||||
return ((int) freq - 2407) / 5;
|
||||
if (freq < 5000) {
|
||||
if (freq > 4900)
|
||||
if (flags &(IEEE80211_CHAN_HALF|IEEE80211_CHAN_QUARTER))
|
||||
return 37 + ((freq * 10) +
|
||||
((freq % 5) == 2 ? 5 : 0) - 49400) / 5;
|
||||
else if (freq > 4900)
|
||||
return (freq - 4000) / 5;
|
||||
else
|
||||
return 15 + ((freq - 2512) / 20);
|
||||
@ -330,6 +353,10 @@ ieee80211_ieee2mhz(u_int chan, u_int flags)
|
||||
else
|
||||
return 2512 + ((chan-15)*20);
|
||||
} else if (flags & IEEE80211_CHAN_5GHZ) {/* 5Ghz band */
|
||||
if (flags & (IEEE80211_CHAN_HALF|IEEE80211_CHAN_QUARTER)) {
|
||||
chan -= 37;
|
||||
return 4940 + chan*5 + (chan % 5 ? 2 : 0);
|
||||
}
|
||||
return 5000 + (chan*5);
|
||||
} else { /* either, guess */
|
||||
if (chan == 14)
|
||||
@ -338,6 +365,7 @@ ieee80211_ieee2mhz(u_int chan, u_int flags)
|
||||
return 2407 + chan*5;
|
||||
if (chan < 27) /* 15-26 */
|
||||
return 2512 + ((chan-15)*20);
|
||||
/* XXX can't distinguish PSB channels */
|
||||
return 5000 + (chan*5);
|
||||
}
|
||||
}
|
||||
@ -360,11 +388,22 @@ ieee80211_media_init(struct ieee80211com *ic,
|
||||
struct ieee80211_rateset *rs;
|
||||
struct ieee80211_rateset allrates;
|
||||
|
||||
/*
|
||||
* Do late attach work that must wait for any subclass
|
||||
* (i.e. driver) work such as overriding methods.
|
||||
*/
|
||||
ieee80211_node_lateattach(ic);
|
||||
/* NB: this works because the structure is initialized to zero */
|
||||
if (LIST_EMPTY(&ic->ic_media.ifm_list)) {
|
||||
/*
|
||||
* Do late attach work that must wait for any subclass
|
||||
* (i.e. driver) work such as overriding methods.
|
||||
*/
|
||||
ieee80211_node_lateattach(ic);
|
||||
} else {
|
||||
/*
|
||||
* We are re-initializing the channel list; clear
|
||||
* the existing media state as the media routines
|
||||
* don't suppress duplicates.
|
||||
*/
|
||||
ifmedia_removeall(&ic->ic_media);
|
||||
ieee80211_chan_init(ic);
|
||||
}
|
||||
|
||||
/*
|
||||
* Fill in media characteristics.
|
||||
@ -452,6 +491,20 @@ ieee80211_media_init(struct ieee80211com *ic,
|
||||
#undef ADD
|
||||
}
|
||||
|
||||
const struct ieee80211_rateset *
|
||||
ieee80211_get_suprates(struct ieee80211com *ic, const struct ieee80211_channel *c)
|
||||
{
|
||||
enum ieee80211_phymode mode = ieee80211_chan2mode(ic, c);
|
||||
|
||||
if (mode == IEEE80211_MODE_11A) {
|
||||
if (IEEE80211_IS_CHAN_HALF(c))
|
||||
return &ieee80211_rateset_half;
|
||||
if (IEEE80211_IS_CHAN_QUARTER(c))
|
||||
return &ieee80211_rateset_quarter;
|
||||
}
|
||||
return &ic->ic_sup_rates[mode];
|
||||
}
|
||||
|
||||
void
|
||||
ieee80211_announce(struct ieee80211com *ic)
|
||||
{
|
||||
@ -697,7 +750,7 @@ void
|
||||
ieee80211_media_status(struct ifnet *ifp, struct ifmediareq *imr)
|
||||
{
|
||||
struct ieee80211com *ic;
|
||||
struct ieee80211_rateset *rs;
|
||||
const struct ieee80211_rateset *rs;
|
||||
|
||||
ic = ieee80211_find_instance(ifp);
|
||||
if (!ic) {
|
||||
@ -932,7 +985,7 @@ ieee80211_setmode(struct ieee80211com *ic, enum ieee80211_phymode mode)
|
||||
* In those cases we defer to the current operating mode when set.
|
||||
*/
|
||||
enum ieee80211_phymode
|
||||
ieee80211_chan2mode(struct ieee80211com *ic, struct ieee80211_channel *chan)
|
||||
ieee80211_chan2mode(struct ieee80211com *ic, const struct ieee80211_channel *chan)
|
||||
{
|
||||
if (IEEE80211_IS_CHAN_T(chan)) {
|
||||
return IEEE80211_MODE_TURBO_A;
|
||||
@ -993,6 +1046,9 @@ ieee80211_rate2media(struct ieee80211com *ic, int rate, enum ieee80211_phymode m
|
||||
{ 72 | IFM_IEEE80211_11G, IFM_IEEE80211_OFDM36 },
|
||||
{ 96 | IFM_IEEE80211_11G, IFM_IEEE80211_OFDM48 },
|
||||
{ 108 | IFM_IEEE80211_11G, IFM_IEEE80211_OFDM54 },
|
||||
{ 6 | IFM_IEEE80211_11A, IFM_IEEE80211_OFDM3 },
|
||||
{ 9 | IFM_IEEE80211_11A, IFM_IEEE80211_OFDM4 },
|
||||
{ 54 | IFM_IEEE80211_11A, IFM_IEEE80211_OFDM27 },
|
||||
/* NB: OFDM72 doesn't realy exist so we don't handle it */
|
||||
};
|
||||
u_int mask, i;
|
||||
@ -1053,6 +1109,11 @@ ieee80211_media2rate(int mword)
|
||||
96, /* IFM_IEEE80211_OFDM48 */
|
||||
108, /* IFM_IEEE80211_OFDM54 */
|
||||
144, /* IFM_IEEE80211_OFDM72 */
|
||||
0, /* IFM_IEEE80211_DS354k */
|
||||
0, /* IFM_IEEE80211_DS512k */
|
||||
6, /* IFM_IEEE80211_OFDM3 */
|
||||
9, /* IFM_IEEE80211_OFDM4 */
|
||||
54, /* IFM_IEEE80211_OFDM27 */
|
||||
};
|
||||
return IFM_SUBTYPE(mword) < N(ieeerates) ?
|
||||
ieeerates[IFM_SUBTYPE(mword)] : 0;
|
||||
|
@ -230,7 +230,7 @@ ieee80211_set_chan(struct ieee80211com *ic,
|
||||
if (chan == IEEE80211_CHAN_ANYC) /* XXX while scanning */
|
||||
chan = ic->ic_curchan;
|
||||
ni->ni_chan = chan;
|
||||
ni->ni_rates = ic->ic_sup_rates[ieee80211_chan2mode(ic, chan)];
|
||||
ni->ni_rates = *ieee80211_get_suprates(ic, chan);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -344,8 +344,7 @@ ieee80211_next_scan(struct ieee80211com *ic)
|
||||
* XXX drivers should do this as needed,
|
||||
* XXX for now maintain compatibility
|
||||
*/
|
||||
ic->ic_bss->ni_rates =
|
||||
ic->ic_sup_rates[ieee80211_chan2mode(ic, chan)];
|
||||
ic->ic_bss->ni_rates = *ieee80211_get_suprates(ic, chan);
|
||||
ieee80211_new_state(ic, IEEE80211_S_SCAN, -1);
|
||||
return 1;
|
||||
}
|
||||
|
@ -1110,8 +1110,8 @@ ieee80211_send_probereq(struct ieee80211_node *ni,
|
||||
const void *optie, size_t optielen)
|
||||
{
|
||||
struct ieee80211com *ic = ni->ni_ic;
|
||||
enum ieee80211_phymode mode;
|
||||
struct ieee80211_frame *wh;
|
||||
const struct ieee80211_rateset *rs;
|
||||
struct mbuf *m;
|
||||
u_int8_t *frm;
|
||||
|
||||
@ -1147,9 +1147,9 @@ ieee80211_send_probereq(struct ieee80211_node *ni,
|
||||
}
|
||||
|
||||
frm = ieee80211_add_ssid(frm, ssid, ssidlen);
|
||||
mode = ieee80211_chan2mode(ic, ic->ic_curchan);
|
||||
frm = ieee80211_add_rates(frm, &ic->ic_sup_rates[mode]);
|
||||
frm = ieee80211_add_xrates(frm, &ic->ic_sup_rates[mode]);
|
||||
rs = ieee80211_get_suprates(ic, ic->ic_curchan);
|
||||
frm = ieee80211_add_rates(frm, rs);
|
||||
frm = ieee80211_add_xrates(frm, rs);
|
||||
|
||||
if (optie != NULL) {
|
||||
memcpy(frm, optie, optielen);
|
||||
|
@ -329,7 +329,8 @@ ieee80211_fix_rate(struct ieee80211_node *ni, int flags)
|
||||
struct ieee80211com *ic = ni->ni_ic;
|
||||
int i, j, ignore, error;
|
||||
int okrate, badrate, fixedrate;
|
||||
struct ieee80211_rateset *srs, *nrs;
|
||||
const struct ieee80211_rateset *srs;
|
||||
struct ieee80211_rateset *nrs;
|
||||
u_int8_t r;
|
||||
|
||||
/*
|
||||
@ -341,7 +342,7 @@ ieee80211_fix_rate(struct ieee80211_node *ni, int flags)
|
||||
flags &= ~IEEE80211_F_DOFRATE;
|
||||
error = 0;
|
||||
okrate = badrate = fixedrate = 0;
|
||||
srs = &ic->ic_sup_rates[ieee80211_chan2mode(ic, ni->ni_chan)];
|
||||
srs = ieee80211_get_suprates(ic, ni->ni_chan);
|
||||
nrs = &ni->ni_rates;
|
||||
for (i = 0; i < nrs->rs_nrates; ) {
|
||||
ignore = 0;
|
||||
|
@ -285,6 +285,8 @@ struct ieee80211com {
|
||||
|
||||
void ieee80211_ifattach(struct ieee80211com *);
|
||||
void ieee80211_ifdetach(struct ieee80211com *);
|
||||
const struct ieee80211_rateset *ieee80211_get_suprates(struct ieee80211com *,
|
||||
const struct ieee80211_channel *);
|
||||
void ieee80211_announce(struct ieee80211com *);
|
||||
void ieee80211_media_init(struct ieee80211com *,
|
||||
ifm_change_cb_t, ifm_stat_cb_t);
|
||||
@ -303,7 +305,7 @@ int ieee80211_chan2ieee(struct ieee80211com *, struct ieee80211_channel *);
|
||||
u_int ieee80211_ieee2mhz(u_int, u_int);
|
||||
int ieee80211_setmode(struct ieee80211com *, enum ieee80211_phymode);
|
||||
enum ieee80211_phymode ieee80211_chan2mode(struct ieee80211com *,
|
||||
struct ieee80211_channel *);
|
||||
const struct ieee80211_channel *);
|
||||
|
||||
/*
|
||||
* Key update synchronization methods. XXX should not be visible.
|
||||
|
Loading…
Reference in New Issue
Block a user