mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/netfilter/nf.git
synced 2026-04-03 23:38:12 -04:00
This is based on Draft P802.11bn_D1.2, but that's still very incomplete, so don't handle a number of things and make some local decisions such as using 40 bits for MAC capabilities and 8 bits for PHY capabilities. Link: https://patch.msgid.link/20260130164259.b28c9456ff94.I5b11fb0345a933bf497fd802aecc72932d58dd68@changeid Signed-off-by: Johannes Berg <johannes.berg@intel.com>
221 lines
6.2 KiB
C
221 lines
6.2 KiB
C
/* SPDX-License-Identifier: GPL-2.0-only */
|
|
/*
|
|
* IEEE 802.11 UHR definitions
|
|
*
|
|
* Copyright (c) 2025-2026 Intel Corporation
|
|
*/
|
|
#ifndef LINUX_IEEE80211_UHR_H
|
|
#define LINUX_IEEE80211_UHR_H
|
|
|
|
#include <linux/types.h>
|
|
#include <linux/if_ether.h>
|
|
|
|
#define IEEE80211_UHR_OPER_PARAMS_DPS_ENA 0x0001
|
|
#define IEEE80211_UHR_OPER_PARAMS_NPCA_ENA 0x0002
|
|
#define IEEE80211_UHR_OPER_PARAMS_DBE_ENA 0x0004
|
|
#define IEEE80211_UHR_OPER_PARAMS_PEDCA_ENA 0x0008
|
|
|
|
struct ieee80211_uhr_operation {
|
|
__le16 params;
|
|
u8 basic_mcs_nss_set[4];
|
|
u8 variable[];
|
|
} __packed;
|
|
|
|
#define IEEE80211_UHR_NPCA_PARAMS_PRIMARY_CHAN_OFFS 0x0000000F
|
|
#define IEEE80211_UHR_NPCA_PARAMS_MIN_DUR_THRESH 0x000000F0
|
|
#define IEEE80211_UHR_NPCA_PARAMS_SWITCH_DELAY 0x00003F00
|
|
#define IEEE80211_UHR_NPCA_PARAMS_SWITCH_BACK_DELAY 0x000FC000
|
|
#define IEEE80211_UHR_NPCA_PARAMS_INIT_QSRC 0x00300000
|
|
#define IEEE80211_UHR_NPCA_PARAMS_MOPLEN 0x00400000
|
|
#define IEEE80211_UHR_NPCA_PARAMS_DIS_SUBCH_BMAP_PRES 0x00800000
|
|
|
|
struct ieee80211_uhr_npca_info {
|
|
__le32 params;
|
|
__le16 dis_subch_bmap[];
|
|
} __packed;
|
|
|
|
static inline bool ieee80211_uhr_oper_size_ok(const u8 *data, u8 len,
|
|
bool beacon)
|
|
{
|
|
const struct ieee80211_uhr_operation *oper = (const void *)data;
|
|
u8 needed = sizeof(*oper);
|
|
|
|
if (len < needed)
|
|
return false;
|
|
|
|
/* nothing else present in beacons */
|
|
if (beacon)
|
|
return true;
|
|
|
|
/* FIXME: DPS, DBE, P-EDCA (consider order, also relative to NPCA) */
|
|
|
|
if (oper->params & cpu_to_le16(IEEE80211_UHR_OPER_PARAMS_NPCA_ENA)) {
|
|
const struct ieee80211_uhr_npca_info *npca =
|
|
(const void *)oper->variable;
|
|
|
|
needed += sizeof(*npca);
|
|
|
|
if (len < needed)
|
|
return false;
|
|
|
|
if (npca->params & cpu_to_le32(IEEE80211_UHR_NPCA_PARAMS_DIS_SUBCH_BMAP_PRES))
|
|
needed += sizeof(npca->dis_subch_bmap[0]);
|
|
}
|
|
|
|
return len >= needed;
|
|
}
|
|
|
|
/*
|
|
* Note: cannot call this on the element coming from a beacon,
|
|
* must ensure ieee80211_uhr_oper_size_ok(..., false) first
|
|
*/
|
|
static inline const struct ieee80211_uhr_npca_info *
|
|
ieee80211_uhr_npca_info(const struct ieee80211_uhr_operation *oper)
|
|
{
|
|
if (!(oper->params & cpu_to_le16(IEEE80211_UHR_OPER_PARAMS_NPCA_ENA)))
|
|
return NULL;
|
|
|
|
/* FIXME: DPS */
|
|
|
|
return (const void *)oper->variable;
|
|
}
|
|
|
|
static inline const __le16 *
|
|
ieee80211_uhr_npca_dis_subch_bitmap(const struct ieee80211_uhr_operation *oper)
|
|
{
|
|
const struct ieee80211_uhr_npca_info *npca;
|
|
|
|
npca = ieee80211_uhr_npca_info(oper);
|
|
if (!npca)
|
|
return NULL;
|
|
if (!(npca->params & cpu_to_le32(IEEE80211_UHR_NPCA_PARAMS_DIS_SUBCH_BMAP_PRES)))
|
|
return NULL;
|
|
return npca->dis_subch_bmap;
|
|
}
|
|
|
|
#define IEEE80211_UHR_MAC_CAP0_DPS_SUPP 0x01
|
|
#define IEEE80211_UHR_MAC_CAP0_DPS_ASSIST_SUPP 0x02
|
|
#define IEEE80211_UHR_MAC_CAP0_DPS_AP_STATIC_HCM_SUPP 0x04
|
|
#define IEEE80211_UHR_MAC_CAP0_NPCA_SUPP 0x10
|
|
#define IEEE80211_UHR_MAC_CAP0_ENH_BSR_SUPP 0x20
|
|
#define IEEE80211_UHR_MAC_CAP0_ADD_MAP_TID_SUPP 0x40
|
|
#define IEEE80211_UHR_MAC_CAP0_EOTSP_SUPP 0x80
|
|
|
|
#define IEEE80211_UHR_MAC_CAP1_DSO_SUPP 0x01
|
|
#define IEEE80211_UHR_MAC_CAP1_PEDCA_SUPP 0x02
|
|
#define IEEE80211_UHR_MAC_CAP1_DBE_SUPP 0x04
|
|
#define IEEE80211_UHR_MAC_CAP1_UL_LLI_SUPP 0x08
|
|
#define IEEE80211_UHR_MAC_CAP1_P2P_LLI_SUPP 0x10
|
|
#define IEEE80211_UHR_MAC_CAP1_PUO_SUPP 0x20
|
|
#define IEEE80211_UHR_MAC_CAP1_AP_PUO_SUPP 0x40
|
|
#define IEEE80211_UHR_MAC_CAP1_DUO_SUPP 0x80
|
|
|
|
#define IEEE80211_UHR_MAC_CAP2_OMC_UL_MU_DIS_RX_SUPP 0x01
|
|
#define IEEE80211_UHR_MAC_CAP2_AOM_SUPP 0x02
|
|
#define IEEE80211_UHR_MAC_CAP2_IFCS_LOC_SUPP 0x04
|
|
#define IEEE80211_UHR_MAC_CAP2_UHR_TRS_SUPP 0x08
|
|
#define IEEE80211_UHR_MAC_CAP2_TXSPG_SUPP 0x10
|
|
#define IEEE80211_UHR_MAC_CAP2_TXOP_RET_IN_TXSPG 0x20
|
|
#define IEEE80211_UHR_MAC_CAP2_UHR_OM_PU_TO_LOW 0xC0
|
|
|
|
#define IEEE80211_UHR_MAC_CAP3_UHR_OM_PU_TO_HIGH 0x03
|
|
#define IEEE80211_UHR_MAC_CAP3_PARAM_UPD_ADV_NOTIF_INTV 0x1C
|
|
#define IEEE80211_UHR_MAC_CAP3_UPD_IND_TIM_INTV_LOW 0xE0
|
|
|
|
#define IEEE80211_UHR_MAC_CAP4_UPD_IND_TIM_INTV_HIGH 0x03
|
|
#define IEEE80211_UHR_MAC_CAP4_BOUNDED_ESS 0x04
|
|
#define IEEE80211_UHR_MAC_CAP4_BTM_ASSURANCE 0x08
|
|
#define IEEE80211_UHR_MAC_CAP4_CO_BF_SUPP 0x10
|
|
|
|
#define IEEE80211_UHR_MAC_CAP_DBE_MAX_BW 0x07
|
|
#define IEEE80211_UHR_MAC_CAP_DBE_EHT_MCS_MAP_160_PRES 0x08
|
|
#define IEEE80211_UHR_MAC_CAP_DBE_EHT_MCS_MAP_320_PRES 0x10
|
|
|
|
struct ieee80211_uhr_cap_mac {
|
|
u8 mac_cap[5];
|
|
} __packed;
|
|
|
|
struct ieee80211_uhr_cap {
|
|
struct ieee80211_uhr_cap_mac mac;
|
|
/* DBE, PHY capabilities */
|
|
u8 variable[];
|
|
} __packed;
|
|
|
|
#define IEEE80211_UHR_PHY_CAP_MAX_NSS_RX_SND_NDP_LE80 0x01
|
|
#define IEEE80211_UHR_PHY_CAP_MAX_NSS_RX_DL_MU_LE80 0x02
|
|
#define IEEE80211_UHR_PHY_CAP_MAX_NSS_RX_SND_NDP_160 0x04
|
|
#define IEEE80211_UHR_PHY_CAP_MAX_NSS_RX_DL_MU_160 0x08
|
|
#define IEEE80211_UHR_PHY_CAP_MAX_NSS_RX_SND_NDP_320 0x10
|
|
#define IEEE80211_UHR_PHY_CAP_MAX_NSS_RX_DL_MU_320 0x20
|
|
#define IEEE80211_UHR_PHY_CAP_ELR_RX 0x40
|
|
#define IEEE80211_UHR_PHY_CAP_ELR_TX 0x80
|
|
|
|
struct ieee80211_uhr_cap_phy {
|
|
u8 cap;
|
|
} __packed;
|
|
|
|
static inline bool ieee80211_uhr_capa_size_ok(const u8 *data, u8 len,
|
|
bool from_ap)
|
|
{
|
|
const struct ieee80211_uhr_cap *cap = (const void *)data;
|
|
size_t needed = sizeof(*cap) + sizeof(struct ieee80211_uhr_cap_phy);
|
|
|
|
if (len < needed)
|
|
return false;
|
|
|
|
/*
|
|
* A non-AP STA does not include the DBE Capability Parameters field
|
|
* in the UHR MAC Capabilities Information field.
|
|
*/
|
|
if (from_ap && cap->mac.mac_cap[1] & IEEE80211_UHR_MAC_CAP1_DBE_SUPP) {
|
|
u8 dbe;
|
|
|
|
needed += 1;
|
|
if (len < needed)
|
|
return false;
|
|
|
|
dbe = cap->variable[0];
|
|
|
|
if (dbe & IEEE80211_UHR_MAC_CAP_DBE_EHT_MCS_MAP_160_PRES)
|
|
needed += 3;
|
|
|
|
if (dbe & IEEE80211_UHR_MAC_CAP_DBE_EHT_MCS_MAP_320_PRES)
|
|
needed += 3;
|
|
}
|
|
|
|
return len >= needed;
|
|
}
|
|
|
|
static inline const struct ieee80211_uhr_cap_phy *
|
|
ieee80211_uhr_phy_cap(const struct ieee80211_uhr_cap *cap, bool from_ap)
|
|
{
|
|
u8 offs = 0;
|
|
|
|
if (from_ap && cap->mac.mac_cap[1] & IEEE80211_UHR_MAC_CAP1_DBE_SUPP) {
|
|
u8 dbe = cap->variable[0];
|
|
|
|
offs += 1;
|
|
|
|
if (dbe & IEEE80211_UHR_MAC_CAP_DBE_EHT_MCS_MAP_160_PRES)
|
|
offs += 3;
|
|
|
|
if (dbe & IEEE80211_UHR_MAC_CAP_DBE_EHT_MCS_MAP_320_PRES)
|
|
offs += 3;
|
|
}
|
|
|
|
return (const void *)&cap->variable[offs];
|
|
}
|
|
|
|
#define IEEE80211_SMD_INFO_CAPA_DL_DATA_FWD 0x01
|
|
#define IEEE80211_SMD_INFO_CAPA_MAX_NUM_PREP 0x0E
|
|
#define IEEE80211_SMD_INFO_CAPA_TYPE 0x10
|
|
#define IEEE80211_SMD_INFO_CAPA_PTK_PER_AP_MLD 0x20
|
|
|
|
struct ieee80211_smd_info {
|
|
u8 id[ETH_ALEN];
|
|
u8 capa;
|
|
__le16 timeout;
|
|
} __packed;
|
|
|
|
#endif /* LINUX_IEEE80211_UHR_H */
|