[net80211] create a helper function to calculate the station facing VHT capabilities.
This is needed for two reasons: * Drivers will need to know what the negotiated set of VHT capabilities and rates are in order to configure (and reconfigure for opmode/chanwidth changes) how to speak to a given peer; and * Because some vendors are "special", we should be careful in what we announce to them during peer association. This isn't the complete solution, as I still need to make sure that when sending out probe requests before we know what we want, we don't limit the capabilities being announced. This is important for IBSS/mesh work later on as probe request/response exchanges are the first hint at what a peer supports. I'll look at adding that to the API soon.
This commit is contained in:
parent
d37cece2b0
commit
791be271f1
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=311855
@ -70,6 +70,15 @@ __FBSDID("$FreeBSD$");
|
||||
frm += 4; \
|
||||
} while (0)
|
||||
|
||||
/*
|
||||
* Immediate TODO:
|
||||
*
|
||||
* + handle WLAN_ACTION_VHT_OPMODE_NOTIF and other VHT action frames
|
||||
* + ensure vhtinfo/vhtcap parameters correctly use the negotiated
|
||||
* capabilities and ratesets
|
||||
* + group ID management operation
|
||||
*/
|
||||
|
||||
/*
|
||||
* XXX TODO: handle WLAN_ACTION_VHT_OPMODE_NOTIF
|
||||
*
|
||||
@ -153,9 +162,9 @@ ieee80211_vht_announce(struct ieee80211com *ic)
|
||||
|
||||
/* Channel width */
|
||||
ic_printf(ic, "[VHT] Channel Widths: 20MHz, 40MHz, 80MHz");
|
||||
if (ic->ic_vhtcaps & IEEE80211_VHTCAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ)
|
||||
if (MS(ic->ic_vhtcaps, IEEE80211_VHTCAP_SUPP_CHAN_WIDTH_MASK) == 2)
|
||||
printf(" 80+80MHz");
|
||||
if (ic->ic_vhtcaps & IEEE80211_VHTCAP_SUPP_CHAN_WIDTH_160MHZ)
|
||||
if (MS(ic->ic_vhtcaps, IEEE80211_VHTCAP_SUPP_CHAN_WIDTH_MASK) >= 1)
|
||||
printf(" 160MHz");
|
||||
printf("\n");
|
||||
|
||||
@ -280,10 +289,342 @@ ieee80211_vht_node_leave(struct ieee80211_node *ni)
|
||||
"%s: called", __func__);
|
||||
}
|
||||
|
||||
/*
|
||||
* Calculate the VHTCAP IE for a given node.
|
||||
*
|
||||
* This includes calculating the capability intersection based on the
|
||||
* current operating mode and intersection of the TX/RX MCS maps.
|
||||
*
|
||||
* The standard only makes it clear about MCS rate negotiation
|
||||
* and MCS basic rates (which must be a subset of the general
|
||||
* negotiated rates). It doesn't make it clear that the AP should
|
||||
* figure out the minimum functional overlap with the STA and
|
||||
* support that.
|
||||
*
|
||||
* Note: this is in host order, not in 802.11 endian order.
|
||||
*
|
||||
* TODO: ensure I re-read 9.7.11 Rate Selection for VHT STAs.
|
||||
*
|
||||
* TODO: investigate what we should negotiate for MU-MIMO beamforming
|
||||
* options.
|
||||
*
|
||||
* opmode is '1' for "vhtcap as if I'm a STA", 0 otherwise.
|
||||
*/
|
||||
void
|
||||
ieee80211_vht_get_vhtcap_ie(struct ieee80211_node *ni,
|
||||
struct ieee80211_ie_vhtcap *vhtcap, int opmode)
|
||||
{
|
||||
struct ieee80211vap *vap = ni->ni_vap;
|
||||
// struct ieee80211com *ic = vap->iv_ic;
|
||||
uint32_t val, val1, val2;
|
||||
uint32_t new_vhtcap;
|
||||
int i;
|
||||
|
||||
vhtcap->ie = IEEE80211_ELEMID_VHT_CAP;
|
||||
vhtcap->len = sizeof(struct ieee80211_ie_vhtcap) - 2;
|
||||
|
||||
/*
|
||||
* Capabilities - it depends on whether we are a station
|
||||
* or not.
|
||||
*/
|
||||
new_vhtcap = 0;
|
||||
|
||||
/*
|
||||
* Station - use our desired configuration based on
|
||||
* local config, local device bits and the already-learnt
|
||||
* vhtcap/vhtinfo IE in the node.
|
||||
*/
|
||||
|
||||
/* Limit MPDU size to the smaller of the two */
|
||||
val2 = val1 = MS(vap->iv_vhtcaps, IEEE80211_VHTCAP_MAX_MPDU_MASK);
|
||||
if (opmode == 1) {
|
||||
val2 = MS(ni->ni_vhtcap, IEEE80211_VHTCAP_MAX_MPDU_MASK);
|
||||
}
|
||||
val = MIN(val1, val2);
|
||||
new_vhtcap |= SM(val, IEEE80211_VHTCAP_MAX_MPDU_MASK);
|
||||
|
||||
/* Limit supp channel config */
|
||||
val2 = val1 = MS(vap->iv_vhtcaps,
|
||||
IEEE80211_VHTCAP_SUPP_CHAN_WIDTH_MASK);
|
||||
if (opmode == 1) {
|
||||
val2 = MS(ni->ni_vhtcap,
|
||||
IEEE80211_VHTCAP_SUPP_CHAN_WIDTH_MASK);
|
||||
}
|
||||
if ((val2 == 2) &&
|
||||
((vap->iv_flags_vht & IEEE80211_FVHT_USEVHT80P80) == 0))
|
||||
val2 = 1;
|
||||
if ((val2 == 1) &&
|
||||
((vap->iv_flags_vht & IEEE80211_FVHT_USEVHT160) == 0))
|
||||
val2 = 0;
|
||||
val = MIN(val1, val2);
|
||||
new_vhtcap |= SM(val, IEEE80211_VHTCAP_SUPP_CHAN_WIDTH_MASK);
|
||||
|
||||
/* RX LDPC */
|
||||
val2 = val1 = MS(vap->iv_vhtcaps, IEEE80211_VHTCAP_RXLDPC);
|
||||
if (opmode == 1) {
|
||||
val2 = MS(ni->ni_vhtcap, IEEE80211_VHTCAP_RXLDPC);
|
||||
}
|
||||
val = MIN(val1, val2);
|
||||
new_vhtcap |= SM(val, IEEE80211_VHTCAP_RXLDPC);
|
||||
|
||||
/* Short-GI 80 */
|
||||
val2 = val1 = MS(vap->iv_vhtcaps, IEEE80211_VHTCAP_SHORT_GI_80);
|
||||
if (opmode == 1) {
|
||||
val2 = MS(ni->ni_vhtcap, IEEE80211_VHTCAP_SHORT_GI_80);
|
||||
}
|
||||
val = MIN(val1, val2);
|
||||
new_vhtcap |= SM(val, IEEE80211_VHTCAP_SHORT_GI_80);
|
||||
|
||||
/* Short-GI 160 */
|
||||
val2 = val1 = MS(vap->iv_vhtcaps, IEEE80211_VHTCAP_SHORT_GI_160);
|
||||
if (opmode == 1) {
|
||||
val2 = MS(ni->ni_vhtcap, IEEE80211_VHTCAP_SHORT_GI_160);
|
||||
}
|
||||
val = MIN(val1, val2);
|
||||
new_vhtcap |= SM(val, IEEE80211_VHTCAP_SHORT_GI_160);
|
||||
|
||||
/*
|
||||
* STBC is slightly more complicated.
|
||||
*
|
||||
* In non-STA mode, we just announce our capabilities and that
|
||||
* is that.
|
||||
*
|
||||
* In STA mode, we should calculate our capabilities based on
|
||||
* local capabilities /and/ what the remote says. So:
|
||||
*
|
||||
* + Only TX STBC if we support it and the remote supports RX STBC;
|
||||
* + Only announce RX STBC if we support it and the remote supports
|
||||
* TX STBC;
|
||||
* + RX STBC should be the minimum of local and remote RX STBC;
|
||||
*/
|
||||
|
||||
/* TX STBC */
|
||||
val2 = val1 = MS(vap->iv_vhtcaps, IEEE80211_VHTCAP_TXSTBC);
|
||||
if (opmode == 1) {
|
||||
/* STA mode - enable it only if node RXSTBC is non-zero */
|
||||
val2 = !! MS(ni->ni_vhtcap, IEEE80211_VHTCAP_RXSTBC_MASK);
|
||||
}
|
||||
val = MIN(val1, val2);
|
||||
/* XXX For now, use the 11n config flag */
|
||||
if ((vap->iv_flags_ht & IEEE80211_FHT_STBC_TX) == 0)
|
||||
val = 0;
|
||||
new_vhtcap |= SM(val, IEEE80211_VHTCAP_TXSTBC);
|
||||
|
||||
/* RX STBC1..4 */
|
||||
val2 = val1 = MS(vap->iv_vhtcaps, IEEE80211_VHTCAP_RXSTBC_MASK);
|
||||
if (opmode == 1) {
|
||||
/* STA mode - enable it only if node TXSTBC is non-zero */
|
||||
val2 = MS(ni->ni_vhtcap, IEEE80211_VHTCAP_TXSTBC);
|
||||
}
|
||||
val = MIN(val1, val2);
|
||||
/* XXX For now, use the 11n config flag */
|
||||
if ((vap->iv_flags_ht & IEEE80211_FHT_STBC_RX) == 0)
|
||||
val = 0;
|
||||
new_vhtcap |= SM(val, IEEE80211_VHTCAP_RXSTBC_MASK);
|
||||
|
||||
/*
|
||||
* Finally - if RXSTBC is 0, then don't enable TXSTBC.
|
||||
* Strictly speaking a device can TXSTBC and not RXSTBC, but
|
||||
* it would be silly.
|
||||
*/
|
||||
if (val == 0)
|
||||
new_vhtcap &= ~IEEE80211_VHTCAP_TXSTBC;
|
||||
|
||||
/*
|
||||
* Some of these fields require other fields to exist.
|
||||
* So before using it, the parent field needs to be checked
|
||||
* otherwise the overridden value may be wrong.
|
||||
*
|
||||
* For example, if SU beamformee is set to 0, then BF STS
|
||||
* needs to be 0.
|
||||
*/
|
||||
|
||||
/* SU Beamformer capable */
|
||||
val2 = val1 = MS(vap->iv_vhtcaps,
|
||||
IEEE80211_VHTCAP_SU_BEAMFORMER_CAPABLE);
|
||||
if (opmode == 1) {
|
||||
val2 = MS(ni->ni_vhtcap,
|
||||
IEEE80211_VHTCAP_SU_BEAMFORMER_CAPABLE);
|
||||
}
|
||||
val = MIN(val1, val2);
|
||||
new_vhtcap |= SM(val, IEEE80211_VHTCAP_SU_BEAMFORMER_CAPABLE);
|
||||
|
||||
/* SU Beamformee capable */
|
||||
val2 = val1 = MS(vap->iv_vhtcaps,
|
||||
IEEE80211_VHTCAP_SU_BEAMFORMEE_CAPABLE);
|
||||
if (opmode == 1) {
|
||||
val2 = MS(ni->ni_vhtcap,
|
||||
IEEE80211_VHTCAP_SU_BEAMFORMEE_CAPABLE);
|
||||
}
|
||||
val = MIN(val1, val2);
|
||||
new_vhtcap |= SM(val, IEEE80211_VHTCAP_SU_BEAMFORMEE_CAPABLE);
|
||||
|
||||
/* Beamformee STS capability - only if SU beamformee capable */
|
||||
val2 = val1 = MS(vap->iv_vhtcaps, IEEE80211_VHTCAP_BEAMFORMEE_STS_MASK);
|
||||
if (opmode == 1) {
|
||||
val2 = MS(ni->ni_vhtcap, IEEE80211_VHTCAP_BEAMFORMEE_STS_MASK);
|
||||
}
|
||||
val = MIN(val1, val2);
|
||||
if ((new_vhtcap & IEEE80211_VHTCAP_SU_BEAMFORMEE_CAPABLE) == 0)
|
||||
val = 0;
|
||||
new_vhtcap |= SM(val, IEEE80211_VHTCAP_BEAMFORMEE_STS_MASK);
|
||||
|
||||
/* Sounding dimensions - only if SU beamformer capable */
|
||||
val2 = val1 = MS(vap->iv_vhtcaps,
|
||||
IEEE80211_VHTCAP_SOUNDING_DIMENSIONS_MASK);
|
||||
if (opmode == 1)
|
||||
val2 = MS(ni->ni_vhtcap,
|
||||
IEEE80211_VHTCAP_SOUNDING_DIMENSIONS_MASK);
|
||||
val = MIN(val1, val2);
|
||||
if ((new_vhtcap & IEEE80211_VHTCAP_SU_BEAMFORMER_CAPABLE) == 0)
|
||||
val = 0;
|
||||
new_vhtcap |= SM(val, IEEE80211_VHTCAP_SOUNDING_DIMENSIONS_MASK);
|
||||
|
||||
/*
|
||||
* MU Beamformer capable - only if SU BFF capable, MU BFF capable
|
||||
* and STA (not AP)
|
||||
*/
|
||||
val2 = val1 = MS(vap->iv_vhtcaps,
|
||||
IEEE80211_VHTCAP_MU_BEAMFORMER_CAPABLE);
|
||||
if (opmode == 1)
|
||||
val2 = MS(ni->ni_vhtcap,
|
||||
IEEE80211_VHTCAP_MU_BEAMFORMER_CAPABLE);
|
||||
val = MIN(val1, val2);
|
||||
if ((new_vhtcap & IEEE80211_VHTCAP_SU_BEAMFORMER_CAPABLE) == 0)
|
||||
val = 0;
|
||||
if (opmode != 1) /* Only enable for STA mode */
|
||||
val = 0;
|
||||
new_vhtcap |= SM(val, IEEE80211_VHTCAP_SU_BEAMFORMER_CAPABLE);
|
||||
|
||||
/*
|
||||
* MU Beamformee capable - only if SU BFE capable, MU BFE capable
|
||||
* and AP (not STA)
|
||||
*/
|
||||
val2 = val1 = MS(vap->iv_vhtcaps,
|
||||
IEEE80211_VHTCAP_MU_BEAMFORMEE_CAPABLE);
|
||||
if (opmode == 1)
|
||||
val2 = MS(ni->ni_vhtcap,
|
||||
IEEE80211_VHTCAP_MU_BEAMFORMEE_CAPABLE);
|
||||
val = MIN(val1, val2);
|
||||
if ((new_vhtcap & IEEE80211_VHTCAP_SU_BEAMFORMEE_CAPABLE) == 0)
|
||||
val = 0;
|
||||
if (opmode != 0) /* Only enable for AP mode */
|
||||
val = 0;
|
||||
new_vhtcap |= SM(val, IEEE80211_VHTCAP_SU_BEAMFORMEE_CAPABLE);
|
||||
|
||||
/* VHT TXOP PS */
|
||||
val2 = val1 = MS(vap->iv_vhtcaps, IEEE80211_VHTCAP_VHT_TXOP_PS);
|
||||
if (opmode == 1)
|
||||
val2 = MS(ni->ni_vhtcap, IEEE80211_VHTCAP_VHT_TXOP_PS);
|
||||
val = MIN(val1, val2);
|
||||
new_vhtcap |= SM(val, IEEE80211_VHTCAP_VHT_TXOP_PS);
|
||||
|
||||
/* HTC_VHT */
|
||||
val2 = val1 = MS(vap->iv_vhtcaps, IEEE80211_VHTCAP_HTC_VHT);
|
||||
if (opmode == 1)
|
||||
val2 = MS(ni->ni_vhtcap, IEEE80211_VHTCAP_HTC_VHT);
|
||||
val = MIN(val1, val2);
|
||||
new_vhtcap |= SM(val, IEEE80211_VHTCAP_HTC_VHT);
|
||||
|
||||
/* A-MPDU length max */
|
||||
/* XXX TODO: we need a userland config knob for this */
|
||||
val2 = val1 = MS(vap->iv_vhtcaps,
|
||||
IEEE80211_VHTCAP_MAX_A_MPDU_LENGTH_EXPONENT_MASK);
|
||||
if (opmode == 1)
|
||||
val2 = MS(ni->ni_vhtcap,
|
||||
IEEE80211_VHTCAP_MAX_A_MPDU_LENGTH_EXPONENT_MASK);
|
||||
val = MIN(val1, val2);
|
||||
new_vhtcap |= SM(val, IEEE80211_VHTCAP_MAX_A_MPDU_LENGTH_EXPONENT_MASK);
|
||||
|
||||
/*
|
||||
* Link adaptation is only valid if HTC-VHT capable is 1.
|
||||
* Otherwise, always set it to 0.
|
||||
*/
|
||||
val2 = val1 = MS(vap->iv_vhtcaps,
|
||||
IEEE80211_VHTCAP_VHT_LINK_ADAPTATION_VHT_MASK);
|
||||
if (opmode == 1)
|
||||
val2 = MS(ni->ni_vhtcap,
|
||||
IEEE80211_VHTCAP_VHT_LINK_ADAPTATION_VHT_MASK);
|
||||
val = MIN(val1, val2);
|
||||
if ((new_vhtcap & IEEE80211_VHTCAP_HTC_VHT) == 0)
|
||||
val = 0;
|
||||
new_vhtcap |= SM(val, IEEE80211_VHTCAP_VHT_LINK_ADAPTATION_VHT_MASK);
|
||||
|
||||
/*
|
||||
* The following two options are 0 if the pattern may change, 1 if it
|
||||
* does not change. So, downgrade to the higher value.
|
||||
*/
|
||||
|
||||
/* RX antenna pattern */
|
||||
val2 = val1 = MS(vap->iv_vhtcaps, IEEE80211_VHTCAP_RX_ANTENNA_PATTERN);
|
||||
if (opmode == 1)
|
||||
val2 = MS(ni->ni_vhtcap, IEEE80211_VHTCAP_RX_ANTENNA_PATTERN);
|
||||
val = MAX(val1, val2);
|
||||
new_vhtcap |= SM(val, IEEE80211_VHTCAP_RX_ANTENNA_PATTERN);
|
||||
|
||||
/* TX antenna pattern */
|
||||
val2 = val1 = MS(vap->iv_vhtcaps, IEEE80211_VHTCAP_TX_ANTENNA_PATTERN);
|
||||
if (opmode == 1)
|
||||
val2 = MS(ni->ni_vhtcap, IEEE80211_VHTCAP_TX_ANTENNA_PATTERN);
|
||||
val = MAX(val1, val2);
|
||||
new_vhtcap |= SM(val, IEEE80211_VHTCAP_TX_ANTENNA_PATTERN);
|
||||
|
||||
/*
|
||||
* MCS set - again, we announce what we want to use
|
||||
* based on configuration, device capabilities and
|
||||
* already-learnt vhtcap/vhtinfo IE information.
|
||||
*/
|
||||
|
||||
/* MCS set - start with whatever the device supports */
|
||||
vhtcap->supp_mcs.rx_mcs_map = vap->iv_vht_mcsinfo.rx_mcs_map;
|
||||
vhtcap->supp_mcs.rx_highest = 0;
|
||||
vhtcap->supp_mcs.tx_mcs_map = vap->iv_vht_mcsinfo.tx_mcs_map;
|
||||
vhtcap->supp_mcs.tx_highest = 0;
|
||||
|
||||
vhtcap->vht_cap_info = new_vhtcap;
|
||||
|
||||
/*
|
||||
* Now, if we're a STA, mask off whatever the AP doesn't support.
|
||||
* Ie, we continue to state we can receive whatever we can do,
|
||||
* but we only announce that we will transmit rates that meet
|
||||
* the AP requirement.
|
||||
*
|
||||
* Note: 0 - MCS0..7; 1 - MCS0..8; 2 - MCS0..9; 3 = not supported.
|
||||
* We can't just use MIN() because '3' means "no", so special case it.
|
||||
*/
|
||||
if (opmode) {
|
||||
for (i = 0; i < 8; i++) {
|
||||
val1 = (vhtcap->supp_mcs.tx_mcs_map >> (i*2)) & 0x3;
|
||||
val2 = (ni->ni_vht_mcsinfo.tx_mcs_map >> (i*2)) & 0x3;
|
||||
val = MIN(val1, val2);
|
||||
if (val1 == 3 || val2 == 3)
|
||||
val = 3;
|
||||
vhtcap->supp_mcs.tx_mcs_map &= ~(0x3 << (i*2));
|
||||
vhtcap->supp_mcs.tx_mcs_map |= (val << (i*2));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Add a VHTCAP field.
|
||||
*
|
||||
* If in station mode, we announce what we would like our
|
||||
* desired configuration to be.
|
||||
*
|
||||
* Else, we announce our capabilities based on our current
|
||||
* configuration.
|
||||
*/
|
||||
uint8_t *
|
||||
ieee80211_add_vhtcap(uint8_t *frm, struct ieee80211_node *ni)
|
||||
{
|
||||
uint32_t cap;
|
||||
struct ieee80211_ie_vhtcap vhtcap;
|
||||
int opmode;
|
||||
|
||||
opmode = 0;
|
||||
if (ni->ni_vap->iv_opmode == IEEE80211_M_STA)
|
||||
opmode = 1;
|
||||
|
||||
ieee80211_vht_get_vhtcap_ie(ni, &vhtcap, opmode);
|
||||
|
||||
memset(frm, '\0', sizeof(struct ieee80211_ie_vhtcap));
|
||||
|
||||
@ -291,27 +632,14 @@ ieee80211_add_vhtcap(uint8_t *frm, struct ieee80211_node *ni)
|
||||
frm[1] = sizeof(struct ieee80211_ie_vhtcap) - 2;
|
||||
frm += 2;
|
||||
|
||||
/*
|
||||
* For now, don't do any configuration.
|
||||
* Just populate the node configuration.
|
||||
* We can worry about making it configurable later.
|
||||
*/
|
||||
|
||||
cap = ni->ni_vhtcap;
|
||||
|
||||
/*
|
||||
* XXX TODO: any capability changes required by
|
||||
* configuration.
|
||||
*/
|
||||
|
||||
/* 32-bit VHT capability */
|
||||
ADDWORD(frm, cap);
|
||||
ADDWORD(frm, vhtcap.vht_cap_info);
|
||||
|
||||
/* suppmcs */
|
||||
ADDSHORT(frm, ni->ni_vht_mcsinfo.rx_mcs_map);
|
||||
ADDSHORT(frm, ni->ni_vht_mcsinfo.rx_highest);
|
||||
ADDSHORT(frm, ni->ni_vht_mcsinfo.tx_mcs_map);
|
||||
ADDSHORT(frm, ni->ni_vht_mcsinfo.tx_highest);
|
||||
ADDSHORT(frm, vhtcap.supp_mcs.rx_mcs_map);
|
||||
ADDSHORT(frm, vhtcap.supp_mcs.rx_highest);
|
||||
ADDSHORT(frm, vhtcap.supp_mcs.tx_mcs_map);
|
||||
ADDSHORT(frm, vhtcap.supp_mcs.tx_highest);
|
||||
|
||||
return (frm);
|
||||
}
|
||||
@ -370,17 +698,6 @@ ieee80211_add_vhtinfo(uint8_t *frm, struct ieee80211_node *ni)
|
||||
frm[1] = sizeof(struct ieee80211_ie_vht_operation) - 2;
|
||||
frm += 2;
|
||||
|
||||
/*
|
||||
* XXX if it's a station, then see if we have a node
|
||||
* channel or ANYC. If it's ANYC then assume we're
|
||||
* scanning, and announce our capabilities.
|
||||
*
|
||||
* This should set the "20/40/80/160MHz wide config";
|
||||
* the 80/80 or 160MHz wide config is done in VHTCAP.
|
||||
*
|
||||
* Other modes - just limit it to the channel.
|
||||
*/
|
||||
|
||||
/* 8-bit chanwidth */
|
||||
*frm++ = ieee80211_vht_get_chwidth_ie(ni->ni_chan);
|
||||
|
||||
@ -475,3 +792,19 @@ ieee80211_vht_adjust_channel(struct ieee80211com *ic,
|
||||
#endif
|
||||
return (chan);
|
||||
}
|
||||
|
||||
/*
|
||||
* Calculate the VHT operation IE for a given node.
|
||||
*
|
||||
* This includes calculating the suitable channel width/parameters
|
||||
* and basic MCS set.
|
||||
*
|
||||
* TODO: ensure I read 9.7.11 Rate Selection for VHT STAs.
|
||||
* TODO: ensure I read 10.39.7 - BSS Basic VHT-MCS and NSS set operation.
|
||||
*/
|
||||
void
|
||||
ieee80211_vht_get_vhtinfo_ie(struct ieee80211_node *ni,
|
||||
struct ieee80211_ie_vht_operation *vhtop, int opmode)
|
||||
{
|
||||
printf("%s: called; TODO!\n", __func__);
|
||||
}
|
||||
|
@ -60,4 +60,9 @@ struct ieee80211_channel *
|
||||
ieee80211_vht_adjust_channel(struct ieee80211com *,
|
||||
struct ieee80211_channel *, int);
|
||||
|
||||
void ieee80211_vht_get_vhtcap_ie(struct ieee80211_node *ni,
|
||||
struct ieee80211_ie_vhtcap *, int);
|
||||
void ieee80211_vht_get_vhtinfo_ie(struct ieee80211_node *ni,
|
||||
struct ieee80211_ie_vht_operation *, int);
|
||||
|
||||
#endif /* _NET80211_IEEE80211_VHT_H_ */
|
||||
|
Loading…
Reference in New Issue
Block a user