Changeset View
Changeset View
Standalone View
Standalone View
sys/net80211/ieee80211_phy.h
/*- | /*- | ||||
* SPDX-License-Identifier: BSD-2-Clause-FreeBSD | * SPDX-License-Identifier: BSD-2-Clause-FreeBSD | ||||
* | * | ||||
* Copyright (c) 2007-2008 Sam Leffler, Errno Consulting | * Copyright (c) 2007-2008 Sam Leffler, Errno Consulting | ||||
* Copyright (c) 2018 Andriy Voskoboinyk <avos@FreeBSD.org> | |||||
* All rights reserved. | * All rights reserved. | ||||
* | * | ||||
* Redistribution and use in source and binary forms, with or without | * Redistribution and use in source and binary forms, with or without | ||||
* modification, are permitted provided that the following conditions | * modification, are permitted provided that the following conditions | ||||
* are met: | * are met: | ||||
* 1. Redistributions of source code must retain the above copyright | * 1. Redistributions of source code must retain the above copyright | ||||
* notice, this list of conditions and the following disclaimer. | * notice, this list of conditions and the following disclaimer. | ||||
* 2. Redistributions in binary form must reproduce the above copyright | * 2. Redistributions in binary form must reproduce the above copyright | ||||
▲ Show 20 Lines • Show All 46 Lines • ▼ Show 20 Lines | #define IEEE80211_GET_SLOTTIME(ic) \ | ||||
((ic->ic_flags & IEEE80211_F_SHSLOT) ? \ | ((ic->ic_flags & IEEE80211_F_SHSLOT) ? \ | ||||
IEEE80211_DUR_SHSLOT : IEEE80211_DUR_SLOT) | IEEE80211_DUR_SHSLOT : IEEE80211_DUR_SLOT) | ||||
/* | /* | ||||
* DIFS (microseconds). | * DIFS (microseconds). | ||||
*/ | */ | ||||
#define IEEE80211_DUR_DIFS(sifs, slot) ((sifs) + 2 * (slot)) | #define IEEE80211_DUR_DIFS(sifs, slot) ((sifs) + 2 * (slot)) | ||||
struct ieee80211_channel; | #define IEEE80211_CTL_RATE_TABLES 6 | ||||
#define IEEE80211_CTL_RATE_VALUES_MAX 256 | |||||
#define IEEE80211_CTL_RATE_TABLE_SIZE 256 | |||||
#define IEEE80211_RATE_TABLE_SIZE 128 | /* | ||||
* Some commonly used rate indices. | |||||
* All but NONEXISTENT must be checked in ieee80211_recheck_rate_indices(). | |||||
*/ | |||||
#define IEEE80211_RATE_INDEX_CCK1 2 | |||||
#define IEEE80211_RATE_INDEX_CCK2 3 | |||||
#define IEEE80211_RATE_INDEX_CCK5 4 | |||||
#define IEEE80211_RATE_INDEX_CCK11 5 | |||||
#define IEEE80211_RATE_INDEX_PBCC22 6 | |||||
#define IEEE80211_RATE_INDEX_OFDM6 8 | |||||
#define IEEE80211_RATE_INDEX_OFDM9 9 | |||||
#define IEEE80211_RATE_INDEX_OFDM12 10 | |||||
#define IEEE80211_RATE_INDEX_OFDM18 11 | |||||
#define IEEE80211_RATE_INDEX_OFDM24 12 | |||||
#define IEEE80211_RATE_INDEX_OFDM36 13 | |||||
#define IEEE80211_RATE_INDEX_OFDM48 14 | |||||
#define IEEE80211_RATE_INDEX_OFDM54 15 | |||||
#define IEEE80211_RATE_INDEX_HALF6 18 | |||||
#define IEEE80211_RATE_INDEX_QUART3 26 | |||||
#define IEEE80211_RATE_INDEX_HT(i) (40 + (i)) | |||||
#define IEEE80211_RATE_INDEX_VHT(i, c) \ | |||||
(117 + (i) + IEEE80211_VHT_MCS_CHAIN * ((c) - 1)) | |||||
#define IEEE80211_RATE_NONEXISTENT (uint16_t)-1 | |||||
struct ieee80211_rate_table { | #define IEEE80211_RATES_COUNT 197 | ||||
int rateCount; /* NB: for proper padding */ | #define IEEE80211_RATES_BYTES howmany(IEEE80211_RATES_COUNT, NBBY) | ||||
uint8_t rateCodeToIndex[256]; /* back mapping */ | |||||
extern const struct ieee80211_rate_t *ieee80211_rates; | |||||
extern uint16_t | |||||
ieee80211_rate_lookup_table[IEEE80211_T_MAX][IEEE80211_RATE_VALUE_MAX]; | |||||
struct ieee80211_ctl_rate_params { | |||||
/* list of global rate indexes available here */ | |||||
uint8_t localRates[IEEE80211_CTL_RATE_VALUES_MAX]; | |||||
/* global index -> local (precedence) index */ | |||||
uint16_t rateIndices[IEEE80211_CTL_RATE_VALUES_MAX]; | |||||
struct { | struct { | ||||
uint8_t phy; /* CCK/OFDM/TURBO */ | struct ieee80211_rate_t ctlRate; /* next lower basic rate; | ||||
uint32_t rateKbps; /* transfer rate in kbs */ | * used for dur. calcs */ | ||||
uint8_t shortPreamble; /* mask for enabling short | uint16_t ackDuration[2]; /* long / short preamble | ||||
* preamble in CCK rate code */ | * ACK dur. */ | ||||
uint8_t dot11Rate; /* value for supported rates | } info[IEEE80211_CTL_RATE_TABLE_SIZE]; | ||||
* info element of MLME */ | |||||
uint8_t ctlRateIndex; /* index of next lower basic | |||||
* rate; used for dur. calcs */ | |||||
uint16_t lpAckDuration; /* long preamble ACK dur. */ | |||||
uint16_t spAckDuration; /* short preamble ACK dur. */ | |||||
} info[IEEE80211_RATE_TABLE_SIZE]; | |||||
}; | }; | ||||
struct ieee80211_rate_table { | |||||
uint8_t types[IEEE80211_T_MAX]; /* included rate types */ | |||||
const struct ieee80211_ctl_rate_params *ctl_rates; | |||||
}; | |||||
struct ieee80211_channel; | |||||
#define IEEE80211_GET_CHAN_FLAGS(_c) \ | |||||
(((_c) != NULL && (_c) != IEEE80211_CHAN_ANYC) ? (_c)->ic_flags : 0) | |||||
uint32_t ieee80211_get_rateKbps(const struct ieee80211_rate_t *, | |||||
uint32_t, int); | |||||
char * ieee80211_rate_to_string(uint16_t, uint32_t, int, char *, int); | |||||
const struct ieee80211_rateset *ieee80211_get_def_rateset( | |||||
const enum ieee80211_phymode); | |||||
const struct ieee80211_rateset *ieee80211_get_basic_rateset( | |||||
const enum ieee80211_phymode); | |||||
const struct ieee80211_rate_table *ieee80211_get_ratetable( | const struct ieee80211_rate_table *ieee80211_get_ratetable( | ||||
struct ieee80211_channel *); | const enum ieee80211_phymode); | ||||
static __inline__ uint8_t | uint16_t ieee80211_convert_from_legacy_rate(uint8_t, | ||||
ieee80211_ack_rate(const struct ieee80211_rate_table *rt, uint8_t rate) | enum ieee80211_phymode); | ||||
uint8_t ieee80211_convert_to_legacy_rate(uint16_t); | |||||
static __inline__ const struct ieee80211_rate_t * | |||||
ieee80211_get_rate(uint16_t index) | |||||
{ | { | ||||
KASSERT(index < IEEE80211_RATES_COUNT, | |||||
("out-of-bounds access to the ieee80211_rates[] array (index %u)", | |||||
index)); | |||||
return (&ieee80211_rates[index]); | |||||
} | |||||
static __inline__ const struct ieee80211_rate_t * | |||||
ieee80211_get_rate_safe(uint16_t index) | |||||
{ | |||||
if (index >= IEEE80211_RATES_COUNT) | |||||
return (NULL); | |||||
return (ieee80211_get_rate(index)); | |||||
} | |||||
static __inline__ int | |||||
ieee80211_lookup_rate_index(uint8_t type, uint8_t value) | |||||
{ | |||||
KASSERT(type < IEEE80211_T_MAX && value < IEEE80211_RATE_VALUE_MAX, | |||||
("out-of-bounds access: type %u, value %u\n", type, value)); | |||||
return (ieee80211_rate_lookup_table[type][value]); | |||||
} | |||||
static __inline__ int | |||||
ieee80211_get_rate_index_no_check(const struct ieee80211_rate_t *rate) | |||||
{ | |||||
KASSERT(rate->type != IEEE80211_T_VHT, | |||||
("use ieee80211_get_anyrate_index_no_check() instead")); | |||||
return (ieee80211_lookup_rate_index(rate->type, rate->value)); | |||||
} | |||||
static __inline__ int | |||||
ieee80211_get_rate_index(const struct ieee80211_rate_t *rate) | |||||
{ | |||||
int index = ieee80211_get_rate_index_no_check(rate); | |||||
KASSERT(index != IEEE80211_RATE_NONEXISTENT, | |||||
("no valid index for rate %u/%u", rate->type, rate->value)); | |||||
return (index); | |||||
} | |||||
/* | /* | ||||
* XXX Assert this is for a legacy rate; not for an MCS rate. | * The same as above, but with VHT rates handling. | ||||
* If the caller wishes to use it for a basic rate, they should | |||||
* clear the high bit first. | |||||
*/ | */ | ||||
KASSERT(! (rate & 0x80), ("rate %d is basic/mcs?", rate)); | static __inline__ int | ||||
ieee80211_get_anyrate_index_no_check(const struct ieee80211_rate_t *rate) | |||||
{ | |||||
uint8_t idx2; | |||||
uint8_t cix = rt->info[rt->rateCodeToIndex[rate & IEEE80211_RATE_VAL]].ctlRateIndex; | if (rate->type == IEEE80211_T_VHT) | ||||
KASSERT(cix != (uint8_t)-1, ("rate %d has no info", rate)); | idx2 = rate->value * rate->props.ht.streams; | ||||
return rt->info[cix].dot11Rate; | else | ||||
idx2 = rate->value; | |||||
return (ieee80211_lookup_rate_index(rate->type, idx2)); | |||||
} | } | ||||
static __inline__ int | |||||
ieee80211_get_anyrate_index(const struct ieee80211_rate_t *rate) | |||||
{ | |||||
int index = ieee80211_get_anyrate_index_no_check(rate); | |||||
KASSERT(index != IEEE80211_RATE_NONEXISTENT, | |||||
("no valid index for rate %u/%u", rate->type, rate->value)); | |||||
return (index); | |||||
} | |||||
static __inline__ uint32_t | |||||
ieee80211_get_rateKbps_by_idx(uint16_t index, uint32_t chan_flags, int shortgi) | |||||
{ | |||||
const struct ieee80211_rate_t *rate = ieee80211_get_rate(index); | |||||
return ieee80211_get_rateKbps(rate, chan_flags, shortgi); | |||||
} | |||||
static __inline__ uint8_t | static __inline__ uint8_t | ||||
ieee80211_ctl_rate(const struct ieee80211_rate_table *rt, uint8_t rate) | ieee80211_legacy_rate_lookup(const struct ieee80211_ctl_rate_params *rp, | ||||
uint16_t index) | |||||
{ | { | ||||
/* | |||||
* XXX Assert this is for a legacy rate; not for an MCS rate. | |||||
* If the caller wishes to use it for a basic rate, they should | |||||
* clear the high bit first. | |||||
*/ | |||||
KASSERT(! (rate & 0x80), ("rate %d is basic/mcs?", rate)); | |||||
uint8_t cix = rt->info[rt->rateCodeToIndex[rate & IEEE80211_RATE_VAL]].ctlRateIndex; | return (rp->rateIndices[index]); | ||||
KASSERT(cix != (uint8_t)-1, ("rate %d has no info", rate)); | |||||
return rt->info[cix].dot11Rate; | |||||
} | } | ||||
static __inline__ enum ieee80211_phytype | static __inline__ const struct ieee80211_rate_t * | ||||
ieee80211_rate2phytype(const struct ieee80211_rate_table *rt, uint8_t rate) | ieee80211_ack_rate(const struct ieee80211_ctl_rate_params *rp, uint16_t index) | ||||
{ | { | ||||
/* | |||||
* XXX Assert this is for a legacy rate; not for an MCS rate. | |||||
* If the caller wishes to use it for a basic rate, they should | |||||
* clear the high bit first. | |||||
*/ | |||||
KASSERT(! (rate & 0x80), ("rate %d is basic/mcs?", rate)); | |||||
uint8_t rix = rt->rateCodeToIndex[rate & IEEE80211_RATE_VAL]; | return &rp->info[index].ctlRate; | ||||
KASSERT(rix != (uint8_t)-1, ("rate %d has no info", rate)); | |||||
return rt->info[rix].phy; | |||||
} | } | ||||
static __inline__ const struct ieee80211_rate_t * | |||||
ieee80211_ctl_rate(const struct ieee80211_ctl_rate_params *rp, uint16_t index) | |||||
{ | |||||
return &rp->info[index].ctlRate; | |||||
} | |||||
static __inline__ int | static __inline__ int | ||||
ieee80211_isratevalid(const struct ieee80211_rate_table *rt, uint8_t rate) | ieee80211_isratevalid(const struct ieee80211_rate_table *rt, | ||||
const struct ieee80211_rate_t *rate) | |||||
{ | { | ||||
/* | |||||
* XXX Assert this is for a legacy rate; not for an MCS rate. | |||||
* If the caller wishes to use it for a basic rate, they should | |||||
* clear the high bit first. | |||||
*/ | |||||
KASSERT(! (rate & 0x80), ("rate %d is basic/mcs?", rate)); | |||||
return rt->rateCodeToIndex[rate] != (uint8_t)-1; | return (rt->types[rate->type]); | ||||
} | } | ||||
/* | /* | ||||
* Calculate ACK field for | * Calculate ACK field for | ||||
* o non-fragment data frames | * o non-fragment data frames | ||||
* o management frames | * o management frames | ||||
* sent using rate, phy and short preamble setting. | * sent using rate, phy and short preamble setting. | ||||
*/ | */ | ||||
static __inline__ uint16_t | static __inline__ uint16_t | ||||
ieee80211_ack_duration(const struct ieee80211_rate_table *rt, | ieee80211_ack_duration(const struct ieee80211_ctl_rate_params *rp, | ||||
uint8_t rate, int isShortPreamble) | uint16_t index, int isShortPreamble) | ||||
{ | { | ||||
uint8_t rix = rt->rateCodeToIndex[rate]; | uint16_t ack_duration; | ||||
KASSERT(rix != (uint8_t)-1, ("rate %d has no info", rate)); | KASSERT(index < nitems(rp->info), ("out of range index value %u", | ||||
if (isShortPreamble) { | index)); | ||||
KASSERT(rt->info[rix].spAckDuration != 0, | |||||
("shpreamble ack dur is not computed!\n")); | |||||
return rt->info[rix].spAckDuration; | |||||
} else { | |||||
KASSERT(rt->info[rix].lpAckDuration != 0, | |||||
("lgpreamble ack dur is not computed!\n")); | |||||
return rt->info[rix].lpAckDuration; | |||||
} | |||||
} | |||||
static __inline__ uint8_t | isShortPreamble = (isShortPreamble != 0); | ||||
ieee80211_legacy_rate_lookup(const struct ieee80211_rate_table *rt, | ack_duration = rp->info[index].ackDuration[isShortPreamble]; | ||||
uint8_t rate) | KASSERT(ack_duration != 0, ("%spreamble ack dur is not computed!\n", | ||||
{ | isShortPreamble ? "sh" : "lg")); | ||||
return (rt->rateCodeToIndex[rate & IEEE80211_RATE_VAL]); | return ack_duration; | ||||
} | } | ||||
/* | /* | ||||
* Compute the time to transmit a frame of length frameLen bytes | * Compute the time to transmit a frame of length frameLen bytes | ||||
* using the specified 802.11 rate code, phy, and short preamble | * using the specified 802.11 rate code, phy, channel width, | ||||
* setting. | * guard interval and short preamble setting. | ||||
* | * | ||||
* NB: SIFS is included. | * NB: SIFS is included. | ||||
*/ | */ | ||||
uint16_t ieee80211_compute_duration(const struct ieee80211_rate_table *, | uint16_t ieee80211_compute_duration(uint16_t, uint32_t, uint32_t, int); | ||||
uint32_t frameLen, uint16_t rate, int isShortPreamble); | |||||
/* | /* | ||||
* Convert PLCP signal/rate field to 802.11 rate code (.5Mbits/s) | * Convert PLCP signal/rate field to 802.11 rate code (.5Mbits/s) | ||||
*/ | */ | ||||
uint8_t ieee80211_plcp2rate(uint8_t, enum ieee80211_phytype); | uint8_t ieee80211_plcp2rate(uint8_t, enum ieee80211_phytype); | ||||
/* | /* | ||||
* Convert 802.11 rate code to PLCP signal. | * Convert 802.11 rate code to PLCP signal. | ||||
*/ | */ | ||||
uint8_t ieee80211_rate2plcp(int, enum ieee80211_phytype); | uint8_t ieee80211_rate2plcp(int, enum ieee80211_phytype); | ||||
/* | /* | ||||
* 802.11n rate manipulation. | * 802.11n legacy rate manipulation. | ||||
*/ | */ | ||||
#define IEEE80211_HT_RC_2_MCS(_rc) ((_rc) & 0x1f) | #define IEEE80211_HT_RC_2_MCS(_rc) ((_rc) & 0x1f) | ||||
#define IEEE80211_HT_RC_2_STREAMS(_rc) ((((_rc) & 0x78) >> 3) + 1) | #define IEEE80211_HT_RC_2_STREAMS(_rc) ((((_rc) & 0x78) >> 3) + 1) | ||||
#define IEEE80211_IS_HT_RATE(_rc) ( (_rc) & IEEE80211_RATE_MCS) | |||||
uint32_t ieee80211_compute_duration_ht(uint32_t frameLen, | |||||
uint16_t rate, int streams, int isht40, | |||||
int isShortGI); | |||||
#endif /* _KERNEL */ | #endif /* _KERNEL */ | ||||
#endif /* !_NET80211_IEEE80211_PHY_H_ */ | #endif /* !_NET80211_IEEE80211_PHY_H_ */ |