2022-09-06 04:51:42

by Kieran Frewen

[permalink] [raw]
Subject: [PATCH v3 00/12] Additional Support for 802.11ah (S1G)

This patchset builds on the work down by Thomas Pedersen to add further
support for 802.11ah in cfg80211 and mac80211. The ultimate goal is
to enable the successful starting of an AP on 802.11ah using 802.11ah
terms by implementing the various features that are required by the
AP. The features are split into their own commits, please see those
patches for more details.
The patchset has been tested on both real hardware (Morse Micro MM610x)
and mac80211_hwsim, in AP and STA modes. Basic regression testing was
performed on 802.11n with mac80211_hwsim by starting an AP and having a
STA interface connect to it.
802.11ah features/support missing:

Rate control integration
Regulatory database updates (only US regulatory information exists)
Optional 802.11ah (S1G) features such as RAW, TWT and AID grouping

Changelog

v3:
[PATCH 01/12]
Added prototype definition and description for
ieee80211_channel_to_freq_khz.
Fixed issue introduced in v1 where center_freq_khz
in handle_channel_custom() was uninitialised.
[PATCH 10/12]
Fixed comment block style

v2:
[PATCH 01/12]
Added validation to assignment of s1g_oper_class and class_idx.
Changed align_to_end from u8 to bool.
Added clarification of usage requirements for country code in
s1g_oper_class struct.
Changed cc field in s1g_oper_class struct from char * to cc[3].
Moved initialised structs and arrays and from reg_s1g.h to reg_s1g.c.
Moved reg_s1g_get_oper_class from reg_s1g.h to reg_s1g.c
reg_s1g_get_oper_class now defaults to NULL if no natching
s1g_oper_class is found.
[PATCH 04/12]
NL80211_ATTR_SHORT_BEACON_PERIOD changed to NLA_U16.
[PATCH 07/12]
Implemented ieee80211_ie_build_s1g_cap function to build S1G
capability IE in place. Mimicing behaviour of
ieee80211_ie_build_ht_cap.
[PATCH 08/12]
Capatilisation of MCS in description of RATE_INFO_FLAGS_S1G_MCS.
Re-ordered grouping of fields in rate_info struct to order by size.
[PATCH 09/12]
Capatilisation of MCS in field naming of NL80211_RATE_INFO_S1G_MSS.
Reordering of info->bw cases in switch to numberical order.

Kieran Frewen (12):
cfg80211: regulatory: extend regulatory support for S1G
mac80211: update TIM for S1G specification changes
mac80211: S1G beacon/short beacon support
nl80211: support setting S1G short beacon period
nl80211: support advertising S1G capabilities
mac80211: support ieee80211_ext format
mac80211: S1G capabilities information element in probe request
cfg80211: S1G rate flags
nl80211: support advertising S1G rate information
mac80211: support S1G rate encoding.
cfg80211: support for calculating S1G bitrates
mac80211_hwsim: support for S1G rate information

drivers/net/wireless/mac80211_hwsim.c | 40 +++--
include/net/cfg80211.h | 26 ++-
include/net/mac80211.h | 33 +++-
include/uapi/linux/nl80211.h | 28 ++++
net/mac80211/cfg.c | 43 +++--
net/mac80211/ieee80211_i.h | 2 +
net/mac80211/rx.c | 32 +++-
net/mac80211/sta_info.c | 7 +
net/mac80211/sta_info.h | 7 +
net/mac80211/tx.c | 27 ++-
net/mac80211/util.c | 50 +++++-
net/wireless/Makefile | 2 +-
net/wireless/nl80211.c | 37 +++++
net/wireless/reg.c | 60 +++++--
net/wireless/reg_s1g.c | 231 ++++++++++++++++++++++++++
net/wireless/reg_s1g.h | 53 ++++++
net/wireless/util.c | 148 ++++++++++++++++-
17 files changed, 772 insertions(+), 54 deletions(-)
create mode 100644 net/wireless/reg_s1g.c
create mode 100644 net/wireless/reg_s1g.h


base-commit: 7dad3e39fde1eef97bc1a0b92e5d0f3500c9ed56
--
2.34.1


2022-09-06 04:51:58

by Kieran Frewen

[permalink] [raw]
Subject: [PATCH v3 08/12] cfg80211: S1G rate flags

Increase the size of S1G rate_info flags to support S1G. Add flags for new
S1G bandwidths and S1G MCS.

Signed-off-by: Kieran Frewen <[email protected]>
---
include/net/cfg80211.h | 16 ++++++++++++++--
1 file changed, 14 insertions(+), 2 deletions(-)

diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index b750b2ad246b..281775f6b3e0 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -1660,6 +1660,7 @@ int cfg80211_check_station_change(struct wiphy *wiphy,
* @RATE_INFO_FLAGS_EDMG: 60GHz MCS in EDMG mode
* @RATE_INFO_FLAGS_EXTENDED_SC_DMG: 60GHz extended SC MCS
* @RATE_INFO_FLAGS_EHT_MCS: EHT MCS information
+ * @RATE_INFO_FLAGS_S1G_MCS: MCS field filled with S1G MCS
*/
enum rate_info_flags {
RATE_INFO_FLAGS_MCS = BIT(0),
@@ -1670,6 +1671,7 @@ enum rate_info_flags {
RATE_INFO_FLAGS_EDMG = BIT(5),
RATE_INFO_FLAGS_EXTENDED_SC_DMG = BIT(6),
RATE_INFO_FLAGS_EHT_MCS = BIT(7),
+ RATE_INFO_FLAGS_S1G_MCS = BIT(8),
};

/**
@@ -1686,6 +1688,11 @@ enum rate_info_flags {
* @RATE_INFO_BW_HE_RU: bandwidth determined by HE RU allocation
* @RATE_INFO_BW_320: 320 MHz bandwidth
* @RATE_INFO_BW_EHT_RU: bandwidth determined by EHT RU allocation
+ * @RATE_INFO_BW_1: 1 MHz bandwidth
+ * @RATE_INFO_BW_2: 2 MHz bandwidth
+ * @RATE_INFO_BW_4: 4 MHz bandwidth
+ * @RATE_INFO_BW_8: 8 MHz bandwidth
+ * @RATE_INFO_BW_16: 16 MHz bandwidth
*/
enum rate_info_bw {
RATE_INFO_BW_20 = 0,
@@ -1697,6 +1704,11 @@ enum rate_info_bw {
RATE_INFO_BW_HE_RU,
RATE_INFO_BW_320,
RATE_INFO_BW_EHT_RU,
+ RATE_INFO_BW_1,
+ RATE_INFO_BW_2,
+ RATE_INFO_BW_4,
+ RATE_INFO_BW_8,
+ RATE_INFO_BW_16,
};

/**
@@ -1719,9 +1731,9 @@ enum rate_info_bw {
* only valid if bw is %RATE_INFO_BW_EHT_RU)
*/
struct rate_info {
- u8 flags;
- u8 mcs;
+ u16 flags;
u16 legacy;
+ u8 mcs;
u8 nss;
u8 bw;
u8 he_gi;
--
2.34.1

2022-09-06 04:52:43

by Kieran Frewen

[permalink] [raw]
Subject: [PATCH v3 10/12] mac80211: support S1G rate encoding.

Add support for receiving and transmitting S1G frames.

Signed-off-by: Kieran Frewen <[email protected]>
---
drivers/net/wireless/mac80211_hwsim.c | 2 +-
include/net/mac80211.h | 32 ++++++++++++++++----
net/mac80211/cfg.c | 42 ++++++++++++++++++++-------
net/mac80211/rx.c | 8 +++++
net/mac80211/sta_info.c | 7 +++++
net/mac80211/sta_info.h | 7 +++++
net/mac80211/util.c | 29 +++++++++++++++++-
7 files changed, 109 insertions(+), 18 deletions(-)

diff --git a/drivers/net/wireless/mac80211_hwsim.c b/drivers/net/wireless/mac80211_hwsim.c
index 6e55f153ff26..5ecbc80be338 100644
--- a/drivers/net/wireless/mac80211_hwsim.c
+++ b/drivers/net/wireless/mac80211_hwsim.c
@@ -1575,7 +1575,7 @@ static bool mac80211_hwsim_tx_frame_no_nl(struct ieee80211_hw *hw,
memset(&rx_status, 0, sizeof(rx_status));
rx_status.flag |= RX_FLAG_MACTIME_START;
rx_status.freq = chan->center_freq;
- rx_status.freq_offset = chan->freq_offset ? 1 : 0;
+ rx_status.freq_offset = chan->freq_offset;
rx_status.band = chan->band;
if (info->control.rates[0].flags & IEEE80211_TX_RC_VHT_MCS) {
rx_status.rate_idx =
diff --git a/include/net/mac80211.h b/include/net/mac80211.h
index 359edfa9ec1c..2e4a78301e3d 100644
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
@@ -863,6 +863,10 @@ enum mac80211_tx_info_flags {
#define IEEE80211_TX_CTL_STBC_SHIFT 23

#define IEEE80211_TX_RC_S1G_MCS IEEE80211_TX_RC_VHT_MCS
+#define IEEE80211_TX_RC_2_MHZ_WIDTH IEEE80211_TX_RC_MCS
+#define IEEE80211_TX_RC_4_MHZ_WIDTH IEEE80211_TX_RC_40_MHZ_WIDTH
+#define IEEE80211_TX_RC_8_MHZ_WIDTH IEEE80211_TX_RC_80_MHZ_WIDTH
+#define IEEE80211_TX_RC_16_MHZ_WIDTH IEEE80211_TX_RC_160_MHZ_WIDTH

/**
* enum mac80211_tx_control_flags - flags to describe transmit control
@@ -1051,6 +1055,20 @@ ieee80211_rate_get_vht_nss(const struct ieee80211_tx_rate *rate)
return (rate->idx >> 4) + 1;
}

+static inline u8
+ieee80211_rate_get_s1g_mcs(const struct ieee80211_tx_rate *rate)
+{
+ /* S1G uses the same MCS encoding as VHT */
+ return ieee80211_rate_get_vht_mcs(rate);
+}
+
+static inline u8
+ieee80211_rate_get_s1g_nss(const struct ieee80211_tx_rate *rate)
+{
+ /* S1G uses the same NSS encoding as VHT */
+ return ieee80211_rate_get_vht_nss(rate);
+}
+
/**
* struct ieee80211_tx_info - skb transmit information
*
@@ -1435,6 +1453,7 @@ enum mac80211_rx_encoding {
RX_ENC_HT,
RX_ENC_VHT,
RX_ENC_HE,
+ RX_ENC_S1G,
};

/**
@@ -1491,10 +1510,11 @@ struct ieee80211_rx_status {
u32 device_timestamp;
u32 ampdu_reference;
u32 flag;
- u16 freq: 13, freq_offset: 1;
+ u16 freq;
+ u16 freq_offset;
u8 enc_flags;
- u8 encoding:2, bw:3, he_ru:3;
- u8 he_gi:2, he_dcm:1;
+ u8 encoding:3, bw:5;
+ u8 he_ru:3, he_gi:2, he_dcm:1;
u8 rate_idx;
u8 nss;
u8 rx_flags;
@@ -1510,8 +1530,7 @@ struct ieee80211_rx_status {
static inline u32
ieee80211_rx_status_to_khz(struct ieee80211_rx_status *rx_status)
{
- return MHZ_TO_KHZ(rx_status->freq) +
- (rx_status->freq_offset ? 500 : 0);
+ return MHZ_TO_KHZ(rx_status->freq) + rx_status->freq_offset;
}

/**
@@ -6568,6 +6587,9 @@ bool rate_usable_index_exists(struct ieee80211_supported_band *sband,
{
unsigned int i;

+ if (sband->band == NL80211_BAND_S1GHZ)
+ return true;
+
for (i = 0; i < sband->n_bitrates; i++)
if (rate_supported(sta, sband->band, i))
return true;
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index 03ed90ce9a84..7cbf85338c9e 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -747,8 +747,16 @@ void sta_set_rate_info_tx(struct sta_info *sta,
const struct ieee80211_tx_rate *rate,
struct rate_info *rinfo)
{
+ struct ieee80211_supported_band *sband;
+
+ sband = ieee80211_get_sband(sta->sdata);
rinfo->flags = 0;
- if (rate->flags & IEEE80211_TX_RC_MCS) {
+ if (rate->flags & IEEE80211_TX_RC_S1G_MCS &&
+ sband->band == NL80211_BAND_S1GHZ) {
+ rinfo->flags |= RATE_INFO_FLAGS_S1G_MCS;
+ rinfo->mcs = ieee80211_rate_get_s1g_mcs(rate);
+ rinfo->nss = ieee80211_rate_get_s1g_nss(rate);
+ } else if (rate->flags & IEEE80211_TX_RC_MCS) {
rinfo->flags |= RATE_INFO_FLAGS_MCS;
rinfo->mcs = rate->idx;
} else if (rate->flags & IEEE80211_TX_RC_VHT_MCS) {
@@ -756,25 +764,37 @@ void sta_set_rate_info_tx(struct sta_info *sta,
rinfo->mcs = ieee80211_rate_get_vht_mcs(rate);
rinfo->nss = ieee80211_rate_get_vht_nss(rate);
} else {
- struct ieee80211_supported_band *sband;
int shift = ieee80211_vif_get_shift(&sta->sdata->vif);
u16 brate;

- sband = ieee80211_get_sband(sta->sdata);
WARN_ON_ONCE(sband && !sband->bitrates);
if (sband && sband->bitrates) {
brate = sband->bitrates[rate->idx].bitrate;
rinfo->legacy = DIV_ROUND_UP(brate, 1 << shift);
}
}
- if (rate->flags & IEEE80211_TX_RC_40_MHZ_WIDTH)
- rinfo->bw = RATE_INFO_BW_40;
- else if (rate->flags & IEEE80211_TX_RC_80_MHZ_WIDTH)
- rinfo->bw = RATE_INFO_BW_80;
- else if (rate->flags & IEEE80211_TX_RC_160_MHZ_WIDTH)
- rinfo->bw = RATE_INFO_BW_160;
- else
- rinfo->bw = RATE_INFO_BW_20;
+ if (sband->band == NL80211_BAND_S1GHZ) {
+ if (rate->flags & IEEE80211_TX_RC_2_MHZ_WIDTH)
+ rinfo->bw = RATE_INFO_BW_2;
+ else if (rate->flags & IEEE80211_TX_RC_4_MHZ_WIDTH)
+ rinfo->bw = RATE_INFO_BW_4;
+ else if (rate->flags & IEEE80211_TX_RC_8_MHZ_WIDTH)
+ rinfo->bw = RATE_INFO_BW_8;
+ else if (rate->flags & IEEE80211_TX_RC_16_MHZ_WIDTH)
+ rinfo->bw = RATE_INFO_BW_16;
+ else
+ rinfo->bw = RATE_INFO_BW_1;
+ } else {
+ if (rate->flags & IEEE80211_TX_RC_40_MHZ_WIDTH)
+ rinfo->bw = RATE_INFO_BW_40;
+ else if (rate->flags & IEEE80211_TX_RC_80_MHZ_WIDTH)
+ rinfo->bw = RATE_INFO_BW_80;
+ else if (rate->flags & IEEE80211_TX_RC_160_MHZ_WIDTH)
+ rinfo->bw = RATE_INFO_BW_160;
+ else
+ rinfo->bw = RATE_INFO_BW_20;
+ }
+
if (rate->flags & IEEE80211_TX_RC_SHORT_GI)
rinfo->flags |= RATE_INFO_FLAGS_SHORT_GI;
}
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c
index d46eeebedb4b..9eab2af626d6 100644
--- a/net/mac80211/rx.c
+++ b/net/mac80211/rx.c
@@ -5106,6 +5106,14 @@ void ieee80211_rx_list(struct ieee80211_hw *hw, struct ieee80211_sta *pubsta,
status->rate_idx, status->nss))
goto drop;
break;
+ case RX_ENC_S1G:
+ if (WARN_ONCE(status->rate_idx > 10 ||
+ !status->nss ||
+ status->nss > 8,
+ "Rate marked as a S1G rate but data is invalid: MCS: %d, NSS: %d\n",
+ status->rate_idx, status->nss))
+ goto drop;
+ break;
default:
WARN_ON_ONCE(1);
fallthrough;
diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c
index cb23da9aff1e..331f5551477e 100644
--- a/net/mac80211/sta_info.c
+++ b/net/mac80211/sta_info.c
@@ -2295,6 +2295,13 @@ static void sta_stats_decode_rate(struct ieee80211_local *local, u32 rate,
rinfo->he_ru_alloc = STA_STATS_GET(HE_RU, rate);
rinfo->he_dcm = STA_STATS_GET(HE_DCM, rate);
break;
+ case STA_STATS_RATE_TYPE_S1G:
+ rinfo->flags = RATE_INFO_FLAGS_S1G_MCS;
+ rinfo->mcs = STA_STATS_GET(S1G_MCS, rate);
+ rinfo->nss = STA_STATS_GET(S1G_NSS, rate);
+ if (STA_STATS_GET(SGI, rate))
+ rinfo->flags |= RATE_INFO_FLAGS_SHORT_GI;
+ break;
}
}

diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h
index 2eb3a9452e07..1c0547769803 100644
--- a/net/mac80211/sta_info.h
+++ b/net/mac80211/sta_info.h
@@ -935,6 +935,8 @@ enum sta_stats_type {
#define STA_STATS_FIELD_VHT_NSS GENMASK( 7, 4)
#define STA_STATS_FIELD_HE_MCS GENMASK( 3, 0)
#define STA_STATS_FIELD_HE_NSS GENMASK( 7, 4)
+#define STA_STATS_FIELD_S1G_MCS GENMASK( 3, 0)
+#define STA_STATS_FIELD_S1G_NSS GENMASK( 7, 4)
#define STA_STATS_FIELD_BW GENMASK(11, 8)
#define STA_STATS_FIELD_SGI GENMASK(12, 12)
#define STA_STATS_FIELD_TYPE GENMASK(15, 13)
@@ -979,6 +981,11 @@ static inline u32 sta_stats_encode_rate(struct ieee80211_rx_status *s)
r |= STA_STATS_FIELD(HE_RU, s->he_ru);
r |= STA_STATS_FIELD(HE_DCM, s->he_dcm);
break;
+ case RX_ENC_S1G:
+ r |= STA_STATS_FIELD(TYPE, STA_STATS_RATE_TYPE_S1G);
+ r |= STA_STATS_FIELD(S1G_NSS, s->nss);
+ r |= STA_STATS_FIELD(S1G_MCS, s->rate_idx);
+ break;
default:
WARN_ON(1);
return STA_STATS_RATE_INVALID;
diff --git a/net/mac80211/util.c b/net/mac80211/util.c
index 78e8c286011e..68aa99acfdc4 100644
--- a/net/mac80211/util.c
+++ b/net/mac80211/util.c
@@ -3929,7 +3929,7 @@ u64 ieee80211_calculate_rx_timestamp(struct ieee80211_local *local,
u64 ts = status->mactime;
struct rate_info ri;
u16 rate;
- u8 n_ltf;
+ u8 n_ltf, guard_factor;

if (WARN_ON(!ieee80211_have_rx_timestamp(status)))
return 0;
@@ -4016,6 +4016,33 @@ u64 ieee80211_calculate_rx_timestamp(struct ieee80211_local *local,
ts += 4 * n_ltf;
}

+ break;
+ case RX_ENC_S1G:
+ /* Set to duration of S1G OFDM symbol with normal GI */
+ guard_factor = 40;
+ ri.flags |= RATE_INFO_FLAGS_S1G_MCS;
+ ri.mcs = status->rate_idx;
+ ri.nss = status->nss;
+ if (status->enc_flags & RX_ENC_FLAG_SHORT_GI) {
+ ri.flags |= RATE_INFO_FLAGS_SHORT_GI;
+ guard_factor = 36;
+ }
+
+ /* See 80211-2020, section 23.3.2 for S1G PPDU
+ * format and 23.3.6 for timing-related parameters.
+ * Here using the general structure for S1G_1M as
+ * in figure 23-3.
+ */
+ if (status->flag & RX_FLAG_MACTIME_PLCP_START) {
+ mpdu_offset += 2;
+ ts += (14 * guard_factor);
+
+ /* Add S1G-LTFs per streams */
+ n_ltf = (ri.nss != 1) && (ri.nss % 2) ?
+ ri.nss + 1 : ri.nss;
+ ts += (guard_factor * n_ltf);
+ }
+
break;
default:
WARN_ON(1);
--
2.34.1

2022-09-06 04:53:19

by Kieran Frewen

[permalink] [raw]
Subject: [PATCH v3 06/12] mac80211: support ieee80211_ext format

Ensure S1G beacons use the new ieee80211_ext format when required.

Signed-off-by: Kieran Frewen <[email protected]>
---
net/mac80211/rx.c | 24 ++++++++++++++++++------
1 file changed, 18 insertions(+), 6 deletions(-)

diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c
index 57df21e2170a..d46eeebedb4b 100644
--- a/net/mac80211/rx.c
+++ b/net/mac80211/rx.c
@@ -4895,6 +4895,7 @@ static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw,
struct ieee80211_local *local = hw_to_local(hw);
struct ieee80211_sub_if_data *sdata;
struct ieee80211_hdr *hdr;
+ struct ieee80211_ext *ext_hdr;
__le16 fc;
struct ieee80211_rx_data rx;
struct ieee80211_sub_if_data *prev;
@@ -4911,7 +4912,7 @@ static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw,
if (ieee80211_is_data(fc) || ieee80211_is_mgmt(fc))
I802_DEBUG_INC(local->dot11ReceivedFragmentCount);

- if (ieee80211_is_mgmt(fc)) {
+ if (ieee80211_is_mgmt(fc) || ieee80211_is_s1g_beacon(fc)) {
/* drop frame if too short for header */
if (skb->len < ieee80211_hdrlen(fc))
err = -ENOBUFS;
@@ -4926,13 +4927,17 @@ static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw,
return;
}

- hdr = (struct ieee80211_hdr *)skb->data;
+ if (ieee80211_is_s1g_beacon(fc))
+ ext_hdr = (struct ieee80211_ext *)skb->data;
+ else
+ hdr = (struct ieee80211_hdr *)skb->data;
+
ieee80211_parse_qos(&rx);
ieee80211_verify_alignment(&rx);

- if (unlikely(ieee80211_is_probe_resp(hdr->frame_control) ||
- ieee80211_is_beacon(hdr->frame_control) ||
- ieee80211_is_s1g_beacon(hdr->frame_control)))
+ if (unlikely(ieee80211_is_probe_resp(fc) ||
+ ieee80211_is_beacon(fc) ||
+ ieee80211_is_s1g_beacon(fc)))
ieee80211_scan_rx(local, skb);

if (ieee80211_is_data(fc)) {
@@ -4991,7 +4996,10 @@ static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw,
prev = sdata;
continue;
}
-
+ if (ieee80211_is_s1g_beacon(fc))
+ rx.sta = sta_info_get_bss(prev, ext_hdr->u.s1g_beacon.sa);
+ else
+ rx.sta = sta_info_get_bss(prev, hdr->addr2);
rx.sdata = prev;
ieee80211_rx_for_interface(&rx, skb, false);

@@ -4999,6 +5007,10 @@ static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw,
}

if (prev) {
+ if (ieee80211_is_s1g_beacon(fc))
+ rx.sta = sta_info_get_bss(prev, ext_hdr->u.s1g_beacon.sa);
+ else
+ rx.sta = sta_info_get_bss(prev, hdr->addr2);
rx.sdata = prev;

if (ieee80211_rx_for_interface(&rx, skb, true))
--
2.34.1

2022-09-06 04:53:19

by Kieran Frewen

[permalink] [raw]
Subject: [PATCH v3 05/12] nl80211: support advertising S1G capabilities

Include S1G capabilities in netlink band info messages.

Signed-off-by: Kieran Frewen <[email protected]>
---
include/uapi/linux/nl80211.h | 7 +++++++
net/wireless/nl80211.c | 10 ++++++++++
2 files changed, 17 insertions(+)

diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h
index 7daa2ce1cb57..f20b9aefd420 100644
--- a/include/uapi/linux/nl80211.h
+++ b/include/uapi/linux/nl80211.h
@@ -3994,6 +3994,10 @@ enum nl80211_band_iftype_attr {
* @NL80211_BAND_ATTR_EDMG_BW_CONFIG: Channel BW Configuration subfield encodes
* the allowed channel bandwidth configurations.
* Defined by IEEE P802.11ay/D4.0 section 9.4.2.251, Table 13.
+ * @NL80211_BAND_ATTR_S1G_MCS_NSS_SET: S1G capabilities, supported S1G-MCS and NSS
+ * set subfield, as in the S1G information IE, 5 bytes
+ * @NL80211_BAND_ATTR_S1G_CAPA: S1G capabilities information subfield as in the
+ * S1G information IE, 10 bytes
* @NL80211_BAND_ATTR_MAX: highest band attribute currently defined
* @__NL80211_BAND_ATTR_AFTER_LAST: internal use
*/
@@ -4014,6 +4018,9 @@ enum nl80211_band_attr {
NL80211_BAND_ATTR_EDMG_CHANNELS,
NL80211_BAND_ATTR_EDMG_BW_CONFIG,

+ NL80211_BAND_ATTR_S1G_MCS_NSS_SET,
+ NL80211_BAND_ATTR_S1G_CAPA,
+
/* keep last */
__NL80211_BAND_ATTR_AFTER_LAST,
NL80211_BAND_ATTR_MAX = __NL80211_BAND_ATTR_AFTER_LAST - 1
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 5e9aaa8c0d7d..931e35619cf4 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -1949,6 +1949,16 @@ static int nl80211_send_band_rateinfo(struct sk_buff *msg,

nla_nest_end(msg, nl_rates);

+ /* S1G capabilities */
+ if (sband->band == NL80211_BAND_S1GHZ && sband->s1g_cap.s1g &&
+ (nla_put(msg, NL80211_BAND_ATTR_S1G_CAPA,
+ sizeof(sband->s1g_cap.cap),
+ sband->s1g_cap.cap) ||
+ nla_put(msg, NL80211_BAND_ATTR_S1G_MCS_NSS_SET,
+ sizeof(sband->s1g_cap.nss_mcs),
+ sband->s1g_cap.nss_mcs)))
+ return -ENOBUFS;
+
return 0;
}

--
2.34.1

2022-09-06 04:53:19

by Kieran Frewen

[permalink] [raw]
Subject: [PATCH v3 03/12] mac80211: S1G beacon/short beacon support

If configured, use the S1G short beacon format. The S1G short beacon
format includes a limited set of information elements.

Signed-off-by: Kieran Frewen <[email protected]>
---
include/net/cfg80211.h | 2 +-
include/net/mac80211.h | 1 +
net/mac80211/cfg.c | 1 +
net/mac80211/ieee80211_i.h | 1 +
net/mac80211/tx.c | 14 +++++++++++++-
5 files changed, 17 insertions(+), 2 deletions(-)

diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index 945e7700de66..b750b2ad246b 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -1328,7 +1328,7 @@ struct cfg80211_ap_settings {

struct cfg80211_beacon_data beacon;

- int beacon_interval, dtim_period;
+ int beacon_interval, dtim_period, short_beacon_period;
const u8 *ssid;
size_t ssid_len;
enum nl80211_hidden_ssid hidden_ssid;
diff --git a/include/net/mac80211.h b/include/net/mac80211.h
index f198af600b5e..359edfa9ec1c 100644
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
@@ -672,6 +672,7 @@ struct ieee80211_bss_conf {
bool enable_beacon;
u8 dtim_period;
u16 beacon_int;
+ u8 short_beacon_period;
u16 assoc_capability;
u64 sync_tsf;
u32 sync_device_ts;
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index a4f6971b7a19..03ed90ce9a84 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -1236,6 +1236,7 @@ static int ieee80211_start_ap(struct wiphy *wiphy, struct net_device *dev,
}

link_conf->dtim_period = params->dtim_period;
+ link_conf->short_beacon_period = params->short_beacon_period;
link_conf->enable_beacon = true;
link_conf->allow_p2p_go_ps = sdata->vif.p2p;
link_conf->twt_responder = params->twt_responder;
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index e192e1ec0261..cd8879998739 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -267,6 +267,7 @@ struct beacon_data {
struct ieee80211_meshconf_ie *meshconf;
u16 cntdwn_counter_offsets[IEEE80211_MAX_CNTDWN_COUNTERS_NUM];
u8 cntdwn_current_counter;
+ u8 long_beacon_count;
struct cfg80211_mbssid_elems *mbssid_ies;
struct rcu_head rcu_head;
};
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c
index bf85a01fcf9d..48c737aeb3f7 100644
--- a/net/mac80211/tx.c
+++ b/net/mac80211/tx.c
@@ -5099,6 +5099,18 @@ ieee80211_beacon_get_ap(struct ieee80211_hw *hw,
struct sk_buff *skb = NULL;
u16 csa_off_base = 0;
int mbssid_len;
+ bool is_short = false;
+
+ if (vif->cfg.s1g) {
+ if (beacon->long_beacon_count == 0) {
+ is_short = false;
+ beacon->long_beacon_count =
+ vif->bss_conf.short_beacon_period - 1;
+ } else {
+ is_short = true;
+ beacon->long_beacon_count--;
+ }
+ }

if (beacon->cntdwn_counter_offsets[0]) {
if (!is_template)
@@ -5136,7 +5148,7 @@ ieee80211_beacon_get_ap(struct ieee80211_hw *hw,
csa_off_base = skb->len;
}

- if (beacon->tail)
+ if (beacon->tail && !is_short)
skb_put_data(skb, beacon->tail, beacon->tail_len);

if (ieee80211_beacon_protect(skb, local, sdata, link) < 0)
--
2.34.1

2022-09-06 04:53:20

by Kieran Frewen

[permalink] [raw]
Subject: [PATCH v3 04/12] nl80211: support setting S1G short beacon period

With the kernel able to send both short and long S1G beacons, include
the ability for setting the short beacon period.

Signed-off-by: Kieran Frewen <[email protected]>
---
include/uapi/linux/nl80211.h | 7 +++++++
net/wireless/nl80211.c | 4 ++++
2 files changed, 11 insertions(+)

diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h
index ffb7c573e299..7daa2ce1cb57 100644
--- a/include/uapi/linux/nl80211.h
+++ b/include/uapi/linux/nl80211.h
@@ -2741,6 +2741,9 @@ enum nl80211_commands {
* When used with %NL80211_CMD_FRAME_TX_STATUS, indicates the ack RX
* timestamp. When used with %NL80211_CMD_FRAME RX notification, indicates
* the incoming frame RX timestamp.
+ *
+ * @NL80211_ATTR_SHORT_BEACON_PERIOD: S1G short beacon period in TUs.
+ *
* @NUM_NL80211_ATTR: total number of nl80211_attrs available
* @NL80211_ATTR_MAX: highest attribute number currently defined
* @__NL80211_ATTR_AFTER_LAST: internal use
@@ -3269,6 +3272,8 @@ enum nl80211_attrs {
NL80211_ATTR_TX_HW_TIMESTAMP,
NL80211_ATTR_RX_HW_TIMESTAMP,

+ NL80211_ATTR_SHORT_BEACON_PERIOD,
+
/* add attributes here, update the policy in nl80211.c */

__NL80211_ATTR_AFTER_LAST,
@@ -4951,6 +4956,7 @@ enum nl80211_bss_scan_width {
* using the nesting index as the antenna number.
* @NL80211_BSS_FREQUENCY_OFFSET: frequency offset in KHz
* @NL80211_BSS_MLO_LINK_ID: MLO link ID of the BSS (u8).
+ * @NL80211_BSS_SHORT_BEACON_PERIOD: S1G short beacon period in TUs
* @__NL80211_BSS_AFTER_LAST: internal
* @NL80211_BSS_MAX: highest BSS attribute
*/
@@ -4977,6 +4983,7 @@ enum nl80211_bss {
NL80211_BSS_CHAIN_SIGNAL,
NL80211_BSS_FREQUENCY_OFFSET,
NL80211_BSS_MLO_LINK_ID,
+ NL80211_BSS_SHORT_BEACON_PERIOD,

/* keep last */
__NL80211_BSS_AFTER_LAST,
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 2705e3ee8fc4..5e9aaa8c0d7d 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -805,6 +805,7 @@ static const struct nla_policy nl80211_policy[NUM_NL80211_ATTR] = {
[NL80211_ATTR_MLD_ADDR] = NLA_POLICY_EXACT_LEN(ETH_ALEN),
[NL80211_ATTR_MLO_SUPPORT] = { .type = NLA_FLAG },
[NL80211_ATTR_MAX_NUM_AKM_SUITES] = { .type = NLA_REJECT },
+ [NL80211_ATTR_SHORT_BEACON_PERIOD] = { .type = NLA_U16 },
};

/* policy for the key attributes */
@@ -5711,6 +5712,9 @@ static int nl80211_start_ap(struct sk_buff *skb, struct genl_info *info)
nla_get_u32(info->attrs[NL80211_ATTR_BEACON_INTERVAL]);
params->dtim_period =
nla_get_u32(info->attrs[NL80211_ATTR_DTIM_PERIOD]);
+ if (info->attrs[NL80211_ATTR_SHORT_BEACON_PERIOD])
+ params->short_beacon_period =
+ nla_get_u32(info->attrs[NL80211_ATTR_SHORT_BEACON_PERIOD]);

err = cfg80211_validate_beacon_int(rdev, dev->ieee80211_ptr->iftype,
params->beacon_interval);
--
2.34.1

2022-09-06 04:53:20

by Kieran Frewen

[permalink] [raw]
Subject: [PATCH v3 01/12] cfg80211: regulatory: extend regulatory support for S1G

Extend the S1G regulatory information to support all regulatory
domains. An reg_s1g.h file is included containing structs with key
regulatory class information. These structs were required to ensure
the right combination of information was available to a series of
functions which support the mapping between frequencies, bandwidths,
and channels.

Reported-by: kernel test robot <[email protected]>
Signed-off-by: Kieran Frewen <[email protected]>
---
include/net/cfg80211.h | 8 ++
net/wireless/Makefile | 2 +-
net/wireless/reg.c | 60 +++++++++--
net/wireless/reg_s1g.c | 231 +++++++++++++++++++++++++++++++++++++++++
net/wireless/reg_s1g.h | 53 ++++++++++
net/wireless/util.c | 35 ++++++-
6 files changed, 376 insertions(+), 13 deletions(-)
create mode 100644 net/wireless/reg_s1g.c
create mode 100644 net/wireless/reg_s1g.h

diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index 908d58393484..945e7700de66 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -5909,6 +5909,14 @@ ieee80211_channel_to_khz(const struct ieee80211_channel *chan)
return MHZ_TO_KHZ(chan->center_freq) + chan->freq_offset;
}

+/**
+ * ieee80211_s1g_channel_to_freq_khz - convert S1G channel index to
+ * frequency in khz
+ * @chan: int channel index to convert
+ * Return: The corresponding frequency (in KHz)
+ */
+u32 ieee80211_s1g_channel_to_freq_khz(int chan);
+
/**
* ieee80211_s1g_channel_width - get allowed channel width from @chan
*
diff --git a/net/wireless/Makefile b/net/wireless/Makefile
index 527ae669f6f7..10cc0db5a935 100644
--- a/net/wireless/Makefile
+++ b/net/wireless/Makefile
@@ -10,7 +10,7 @@ obj-$(CONFIG_WEXT_PROC) += wext-proc.o
obj-$(CONFIG_WEXT_SPY) += wext-spy.o
obj-$(CONFIG_WEXT_PRIV) += wext-priv.o

-cfg80211-y += core.o sysfs.o radiotap.o util.o reg.o scan.o nl80211.o
+cfg80211-y += core.o sysfs.o radiotap.o util.o reg.o reg_s1g.o scan.o nl80211.o
cfg80211-y += mlme.o ibss.o sme.o chan.o ethtool.o mesh.o ap.o trace.o ocb.o
cfg80211-y += pmsr.o
cfg80211-$(CONFIG_OF) += of.o
diff --git a/net/wireless/reg.c b/net/wireless/reg.c
index c7383ede794f..3377cea16c2b 100644
--- a/net/wireless/reg.c
+++ b/net/wireless/reg.c
@@ -62,6 +62,7 @@
#include "reg.h"
#include "rdev-ops.h"
#include "nl80211.h"
+#include "reg_s1g.h"

/*
* Grace period we give before making sure all current interfaces reside on
@@ -1737,26 +1738,54 @@ static uint32_t reg_rule_to_chan_bw_flags(const struct ieee80211_regdomain *regd
* the largest bandwidth which cleanly divides the freq_range.
*/
int edge_offset;
- int ch_bw = max_bandwidth_khz;
+ int ch_bw, freq_end, freq_start, class_idx = -1;
+ unsigned int i;
+ const struct s1g_oper_class *oper = reg_s1g_get_oper_class(regd->alpha2);
+
+ if (!oper) {
+ bw_flags |= IEEE80211_CHAN_DISABLED;
+ return bw_flags;
+ }
+
+ for (i = 0; i < oper->class_count; i++) {
+ if (center_freq_khz >= oper->class[i].start_freq &&
+ center_freq_khz <= oper->class[i].end_freq) {
+ class_idx = i;
+ break;
+ }
+ }
+
+ if (class_idx == -1) {
+ bw_flags |= IEEE80211_CHAN_DISABLED;
+ return bw_flags;
+ }
+
+ ch_bw = oper->class[class_idx].max_bw_khz;
+ freq_start = oper->class[class_idx].start_freq;
+ freq_end = oper->class[class_idx].end_freq;

while (ch_bw) {
- edge_offset = (center_freq_khz - ch_bw / 2) -
- freq_range->start_freq_khz;
- if (edge_offset % ch_bw == 0) {
- switch (KHZ_TO_MHZ(ch_bw)) {
- case 1:
+ if (oper->class[class_idx].align_to_end)
+ edge_offset = freq_end -
+ (center_freq_khz - (ch_bw) / 2);
+ else
+ edge_offset = (center_freq_khz - (ch_bw) / 2) -
+ freq_start;
+ if (edge_offset % (ch_bw) == 0) {
+ switch (ch_bw) {
+ case MHZ_TO_KHZ(1):
bw_flags |= IEEE80211_CHAN_1MHZ;
break;
- case 2:
+ case MHZ_TO_KHZ(2):
bw_flags |= IEEE80211_CHAN_2MHZ;
break;
- case 4:
+ case MHZ_TO_KHZ(4):
bw_flags |= IEEE80211_CHAN_4MHZ;
break;
- case 8:
+ case MHZ_TO_KHZ(8):
bw_flags |= IEEE80211_CHAN_8MHZ;
break;
- case 16:
+ case MHZ_TO_KHZ(16):
bw_flags |= IEEE80211_CHAN_16MHZ;
break;
default:
@@ -2555,9 +2584,18 @@ static void handle_channel_custom(struct wiphy *wiphy,
const struct ieee80211_reg_rule *reg_rule = NULL;
const struct ieee80211_power_rule *power_rule = NULL;
u32 bw, center_freq_khz;
+ bool is_s1g = chan->band == NL80211_BAND_S1GHZ;

center_freq_khz = ieee80211_channel_to_khz(chan);
- for (bw = MHZ_TO_KHZ(20); bw >= min_bw; bw = bw / 2) {
+
+ if (is_s1g) {
+ bw = MHZ_TO_KHZ(16);
+ min_bw = MHZ_TO_KHZ(1);
+ } else {
+ bw = MHZ_TO_KHZ(20);
+ }
+
+ for (; bw >= min_bw; bw = bw / 2) {
reg_rule = freq_reg_info_regd(center_freq_khz, regd, bw);
if (!IS_ERR(reg_rule))
break;
diff --git a/net/wireless/reg_s1g.c b/net/wireless/reg_s1g.c
new file mode 100644
index 000000000000..6727d9986419
--- /dev/null
+++ b/net/wireless/reg_s1g.c
@@ -0,0 +1,231 @@
+// SPDX-License-Identifier: GPL-2.0
+#include "reg_s1g.h"
+
+/* The following channel lists have been retrieved from
+ * IEEE Std 802.11-2020 Table E-5
+ */
+static const u8 us_supported_channels[] = {
+ 1, 2, 3, 5, 6, 7, 8, 9, 10, 11, 12, 13,
+ 14, 15, 16, 17, 18, 19, 20, 21, 22, 23,
+ 24, 25, 26, 27, 28, 29, 30, 31, 32, 33,
+ 34, 35, 37, 38, 39, 40, 41, 42, 43, 44,
+ 45, 46, 47, 48, 49, 50, 51
+};
+
+static const u8 eu_supported_channels_863[] = {
+ 1, 3, 5, 7, 9
+};
+
+static const u8 eu_supported_channels_901_4[] = {
+ 33, 35
+};
+
+static const u8 jp_supported_channels[] = {
+ 1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21
+};
+
+static const u8 kr_supported_channels[] = {
+ 1, 2, 3, 5, 6, 7, 8, 9, 10, 11
+};
+
+static const u8 sg_supported_channels_863[] = {
+ 7, 9, 10, 11
+};
+
+static const u8 sg_supported_channels_902[] = {
+ 37, 38, 39, 40, 41, 42, 43, 45
+};
+
+static const u8 au_nz_supported_channels[] = {
+ 27, 29, 30, 31, 32, 33, 34, 35, 37, 38, 39,
+ 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50,
+ 51
+};
+
+/* The following s1g_oper_class structs are taken from
+ * IEEE Std 802.11-2020 Table E-5
+ */
+static const struct s1g_oper_class country_class_au = {
+ .cc = "AU",
+ .class_count = 2,
+ .class = {
+ {
+ .band_start = 902000,
+ .start_freq = 915000,
+ .end_freq = 920000,
+ .max_bw_khz = MHZ_TO_KHZ(4),
+ .align_to_end = false,
+ .supported_chan = au_nz_supported_channels,
+ .n_supported_chan = sizeof(au_nz_supported_channels),
+ },
+ {
+ .band_start = 902000,
+ .start_freq = 920000,
+ .end_freq = 928000,
+ .max_bw_khz = MHZ_TO_KHZ(8),
+ .align_to_end = true,
+ .supported_chan = NULL,
+ .n_supported_chan = 0,
+ }
+ },
+};
+
+static const struct s1g_oper_class country_class_nz = {
+ .cc = "NZ",
+ .class_count = 2,
+ .class = {
+ {
+ .band_start = 902000,
+ .start_freq = 915000,
+ .end_freq = 924000,
+ .max_bw_khz = MHZ_TO_KHZ(8),
+ .align_to_end = false,
+ .supported_chan = au_nz_supported_channels,
+ .n_supported_chan = sizeof(au_nz_supported_channels),
+ },
+ {
+ .band_start = 902000,
+ .start_freq = 924000,
+ .end_freq = 928000,
+ .max_bw_khz = MHZ_TO_KHZ(8),
+ .align_to_end = false,
+ .supported_chan = NULL,
+ .n_supported_chan = 0,
+ }
+ },
+};
+
+static const struct s1g_oper_class country_class_us = {
+ .cc = "US",
+ .class_count = 3,
+ .class = {
+ {
+ .band_start = 902000,
+ .start_freq = 902000,
+ .end_freq = 904000,
+ .max_bw_khz = MHZ_TO_KHZ(16),
+ .align_to_end = false,
+ .supported_chan = us_supported_channels,
+ .n_supported_chan = sizeof(us_supported_channels),
+ },
+ {
+ .band_start = 902000,
+ .start_freq = 920000,
+ .end_freq = 928000,
+ .max_bw_khz = MHZ_TO_KHZ(16),
+ .align_to_end = false,
+ .supported_chan = NULL,
+ .n_supported_chan = 0,
+ },
+ {
+ .band_start = 902000,
+ .start_freq = 904000,
+ .end_freq = 920000,
+ .max_bw_khz = MHZ_TO_KHZ(16),
+ .align_to_end = false,
+ .supported_chan = NULL,
+ .n_supported_chan = 0,
+ }
+ },
+};
+
+static const struct s1g_oper_class country_class_sg = {
+ .cc = "SG",
+ .class_count = 2,
+ .class = {
+ {
+ .band_start = 863000,
+ .start_freq = 866000,
+ .end_freq = 869000,
+ .max_bw_khz = MHZ_TO_KHZ(2),
+ .align_to_end = true,
+ .supported_chan = sg_supported_channels_863,
+ .n_supported_chan = sizeof(sg_supported_channels_863),
+ },
+ {
+ .band_start = 902000,
+ .start_freq = 920000,
+ .end_freq = 925000,
+ .max_bw_khz = MHZ_TO_KHZ(4),
+ .align_to_end = false,
+ .supported_chan = sg_supported_channels_902,
+ .n_supported_chan = sizeof(sg_supported_channels_902),
+ },
+ },
+};
+
+static const struct s1g_oper_class country_class_kr = {
+ .cc = "KR",
+ .class_count = 1,
+ .class = {
+ {
+ .band_start = 917500,
+ .start_freq = 917500,
+ .end_freq = 923500,
+ .max_bw_khz = MHZ_TO_KHZ(4),
+ .align_to_end = true,
+ .supported_chan = kr_supported_channels,
+ .n_supported_chan = sizeof(kr_supported_channels),
+ }
+ },
+};
+
+static const struct s1g_oper_class country_class_eu = {
+ .cc = "EU",
+ .class_count = 1,
+ .class = {
+ {
+ .band_start = 863000,
+ .start_freq = 863000,
+ .end_freq = 868000,
+ .max_bw_khz = MHZ_TO_KHZ(1),
+ .align_to_end = false,
+ .supported_chan = eu_supported_channels_863,
+ .n_supported_chan = sizeof(eu_supported_channels_863),
+ },
+ {
+ .band_start = 901400,
+ .start_freq = 917400,
+ .end_freq = 919400,
+ .max_bw_khz = MHZ_TO_KHZ(1),
+ .align_to_end = false,
+ .supported_chan = eu_supported_channels_901_4,
+ .n_supported_chan = sizeof(eu_supported_channels_901_4),
+ }
+ },
+};
+
+static const struct s1g_oper_class country_class_jp = {
+ .cc = "JP",
+ .class_count = 1,
+ .class = {
+ {
+ .band_start = 916500,
+ .start_freq = 916500,
+ .end_freq = 927500,
+ .max_bw_khz = MHZ_TO_KHZ(1),
+ .align_to_end = false,
+ .supported_chan = jp_supported_channels,
+ .n_supported_chan = sizeof(jp_supported_channels),
+ }
+ },
+};
+
+const struct s1g_oper_class *reg_s1g_get_oper_class(const char *cc)
+{
+ if (!strcmp(cc, "EU"))
+ return &country_class_eu;
+ if (!strcmp(cc, "SG"))
+ return &country_class_sg;
+ if (!strcmp(cc, "US"))
+ return &country_class_us;
+ if (!strcmp(cc, "AU"))
+ return &country_class_au;
+ if (!strcmp(cc, "KR"))
+ return &country_class_kr;
+ if (!strcmp(cc, "JP"))
+ return &country_class_jp;
+ if (!strcmp(cc, "NZ"))
+ return &country_class_nz;
+ return NULL;
+}
diff --git a/net/wireless/reg_s1g.h b/net/wireless/reg_s1g.h
new file mode 100644
index 000000000000..3165166054d2
--- /dev/null
+++ b/net/wireless/reg_s1g.h
@@ -0,0 +1,53 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef __NET_WIRELESS_REG_S1G_H
+#define __NET_WIRELESS_REG_S1G_H
+
+#include "reg.h"
+
+/**
+ * Struct cca_class
+ *
+ * The specifics of a cca level classification used to validate bw/frequency
+ * combinations in a regulatory domain
+ * @band_start: The channel starting frequency (kHz) for that CCA classification
+ * @start_freq: The start of the valid frequency (kHz) range for the CCA
+ * classification
+ * @end_freq: The end of the valid frequency (kHz) range for the CCA
+ * classification
+ * @max_bw_khz: The maximum valid bandwidth for the CCA classification
+ * @align_to_end: True if the maximum valid bandwidth for the range is aligned
+ * to the end_freq
+ * @supported_chan: A list of supported channel indexes
+ * @n_supported_chan: A count of the supported channels for this CCA
+ * classification
+ */
+struct s1g_cca_classification {
+ u32 band_start;
+ u32 start_freq;
+ u32 end_freq;
+ u32 max_bw_khz;
+ bool align_to_end;
+ const u8 *supported_chan;
+ u8 n_supported_chan;
+};
+
+/**
+ * Struct s1g_oper_class
+ *
+ * An aggregated view of the operating classes for a single regulatory
+ * domain
+ * @cc: country code (2-character code)
+ * @class_count: The number of CCA level classifications that exist
+ * within that country
+ * @class: The specifics of a CCA level classification within a regulatory
+ * domain.
+ */
+struct s1g_oper_class {
+ char cc[3];
+ int class_count;
+ struct s1g_cca_classification class[];
+};
+
+const struct s1g_oper_class *reg_s1g_get_oper_class(const char *cc);
+
+#endif /*__NET_WIRELESS_REG_S1G_H */
diff --git a/net/wireless/util.c b/net/wireless/util.c
index 2c127951764a..aeccb6ce595c 100644
--- a/net/wireless/util.c
+++ b/net/wireless/util.c
@@ -22,6 +22,7 @@
#include <linux/nospec.h>
#include "core.h"
#include "rdev-ops.h"
+#include "reg_s1g.h"


const struct ieee80211_rate *
@@ -72,6 +73,27 @@ u32 ieee80211_mandatory_rates(struct ieee80211_supported_band *sband,
}
EXPORT_SYMBOL(ieee80211_mandatory_rates);

+static u32 ieee80211_s1g_base_freq(int chan)
+{
+ const struct ieee80211_regdomain *regd = rtnl_dereference(cfg80211_regdomain);
+ const struct s1g_oper_class *oper = reg_s1g_get_oper_class(regd->alpha2);
+ u8 i, j, index = 0;
+
+ if (!oper)
+ return 0;
+
+ if (oper->class_count > 1)
+ for (i = 0; i < oper->class_count; i++)
+ for (j = 0; j < oper->class[i].n_supported_chan; j++)
+ if (oper->class[i].supported_chan[j] == chan) {
+ index = i;
+ goto out;
+ }
+ return 0; /* not supported */
+out:
+ return oper->class[index].band_start;
+}
+
u32 ieee80211_channel_to_freq_khz(int chan, enum nl80211_band band)
{
/* see 802.11 17.3.8.3.2 and Annex J
@@ -104,7 +126,7 @@ u32 ieee80211_channel_to_freq_khz(int chan, enum nl80211_band band)
return MHZ_TO_KHZ(56160 + chan * 2160);
break;
case NL80211_BAND_S1GHZ:
- return 902000 + chan * 500;
+ return ieee80211_s1g_base_freq(chan) + chan * 500;
default:
;
}
@@ -112,6 +134,17 @@ u32 ieee80211_channel_to_freq_khz(int chan, enum nl80211_band band)
}
EXPORT_SYMBOL(ieee80211_channel_to_freq_khz);

+u32 ieee80211_s1g_channel_to_freq_khz(int chan)
+{
+ u32 base = ieee80211_s1g_base_freq(chan);
+
+ if (!base)
+ return 0;
+
+ return (base + chan * 500);
+}
+EXPORT_SYMBOL(ieee80211_s1g_channel_to_freq_khz);
+
enum nl80211_chan_width
ieee80211_s1g_channel_width(const struct ieee80211_channel *chan)
{
--
2.34.1

2022-09-06 04:53:20

by Kieran Frewen

[permalink] [raw]
Subject: [PATCH v3 07/12] mac80211: S1G capabilities information element in probe request

Add the missing S1G capabilities information element to probe requests.

Signed-off-by: Kieran Frewen <[email protected]>
---
net/mac80211/ieee80211_i.h | 1 +
net/mac80211/util.c | 21 +++++++++++++++++++++
2 files changed, 22 insertions(+)

diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index cd8879998739..e8ff4af9fc03 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -2400,6 +2400,7 @@ void ieee80211_add_s1g_capab_ie(struct ieee80211_sub_if_data *sdata,
struct sk_buff *skb);
void ieee80211_add_aid_request_ie(struct ieee80211_sub_if_data *sdata,
struct sk_buff *skb);
+u8 *ieee80211_ie_build_s1g_cap(u8 *pos, struct ieee80211_sta_s1g_cap *s1g_cap);

/* channel management */
bool ieee80211_chandef_ht_oper(const struct ieee80211_ht_operation *ht_oper,
diff --git a/net/mac80211/util.c b/net/mac80211/util.c
index 53826c663723..78e8c286011e 100644
--- a/net/mac80211/util.c
+++ b/net/mac80211/util.c
@@ -1857,6 +1857,12 @@ static int ieee80211_build_preq_ies_band(struct ieee80211_sub_if_data *sdata,
rate_flags = ieee80211_chandef_rate_flags(chandef);
shift = ieee80211_chandef_get_shift(chandef);

+ /* For direct mac80211 scan (probe request), add S1G IE and consider its override bits */
+ if (band == NL80211_BAND_S1GHZ) {
+ pos = ieee80211_ie_build_s1g_cap(pos, &sband->s1g_cap);
+ goto done;
+ }
+
num_rates = 0;
for (i = 0; i < sband->n_bitrates; i++) {
if ((BIT(i) & rate_mask) == 0)
@@ -2919,6 +2925,21 @@ size_t ieee80211_ie_split_vendor(const u8 *ies, size_t ielen, size_t offset)
return pos;
}

+u8 *ieee80211_ie_build_s1g_cap(u8 *pos, struct ieee80211_sta_s1g_cap *s1g_cap)
+{
+ *pos++ = WLAN_EID_S1G_CAPABILITIES;
+ *pos++ = sizeof(struct ieee80211_s1g_cap);
+ memset(pos, 0, sizeof(struct ieee80211_s1g_cap));
+
+ memcpy(pos, &s1g_cap->cap, sizeof(s1g_cap->cap));
+ pos += sizeof(s1g_cap->cap);
+
+ memcpy(pos, &s1g_cap->nss_mcs, sizeof(s1g_cap->nss_mcs));
+ pos += sizeof(s1g_cap->nss_mcs);
+
+ return pos;
+}
+
u8 *ieee80211_ie_build_ht_cap(u8 *pos, struct ieee80211_sta_ht_cap *ht_cap,
u16 cap)
{
--
2.34.1

2022-09-06 04:53:52

by Kieran Frewen

[permalink] [raw]
Subject: [PATCH v3 09/12] nl80211: support advertising S1G rate information

Add S1G rate information to netlink STA rate message.

Signed-off-by: Kieran Frewen <[email protected]>
---
include/uapi/linux/nl80211.h | 14 ++++++++++++++
net/wireless/nl80211.c | 23 +++++++++++++++++++++++
2 files changed, 37 insertions(+)

diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h
index f20b9aefd420..5ae301905671 100644
--- a/include/uapi/linux/nl80211.h
+++ b/include/uapi/linux/nl80211.h
@@ -3600,6 +3600,13 @@ enum nl80211_eht_ru_alloc {
* (u8, see &enum nl80211_eht_gi)
* @NL80211_RATE_INFO_EHT_RU_ALLOC: EHT RU allocation, if not present then
* non-OFDMA was used (u8, see &enum nl80211_eht_ru_alloc)
+ * @NL80211_RATE_INFO_S1G_MCS: S1G MCS index (u8, 0-10)
+ * @NL80211_RATE_INFO_S1G_NSS: S1G NSS value (u8, 1-4)
+ * @NL80211_RATE_INFO_1_MHZ_WIDTH: 1 MHz S1G rate
+ * @NL80211_RATE_INFO_2_MHZ_WIDTH: 2 MHz S1G rate
+ * @NL80211_RATE_INFO_4_MHZ_WIDTH: 4 MHz S1G rate
+ * @NL80211_RATE_INFO_8_MHZ_WIDTH: 8 MHz S1G rate
+ * @NL80211_RATE_INFO_16_MHZ_WIDTH: 16 MHz S1G rate
* @__NL80211_RATE_INFO_AFTER_LAST: internal use
*/
enum nl80211_rate_info {
@@ -3626,6 +3633,13 @@ enum nl80211_rate_info {
NL80211_RATE_INFO_EHT_NSS,
NL80211_RATE_INFO_EHT_GI,
NL80211_RATE_INFO_EHT_RU_ALLOC,
+ NL80211_RATE_INFO_S1G_MCS,
+ NL80211_RATE_INFO_S1G_NSS,
+ NL80211_RATE_INFO_1_MHZ_WIDTH,
+ NL80211_RATE_INFO_2_MHZ_WIDTH,
+ NL80211_RATE_INFO_4_MHZ_WIDTH,
+ NL80211_RATE_INFO_8_MHZ_WIDTH,
+ NL80211_RATE_INFO_16_MHZ_WIDTH,

/* keep last */
__NL80211_RATE_INFO_AFTER_LAST,
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 931e35619cf4..73eef7e9f4c3 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -6133,12 +6133,27 @@ bool nl80211_put_sta_rate(struct sk_buff *msg, struct rate_info *info, int attr)
return false;

switch (info->bw) {
+ case RATE_INFO_BW_1:
+ rate_flg = NL80211_RATE_INFO_1_MHZ_WIDTH;
+ break;
+ case RATE_INFO_BW_2:
+ rate_flg = NL80211_RATE_INFO_2_MHZ_WIDTH;
+ break;
+ case RATE_INFO_BW_4:
+ rate_flg = NL80211_RATE_INFO_4_MHZ_WIDTH;
+ break;
case RATE_INFO_BW_5:
rate_flg = NL80211_RATE_INFO_5_MHZ_WIDTH;
break;
+ case RATE_INFO_BW_8:
+ rate_flg = NL80211_RATE_INFO_8_MHZ_WIDTH;
+ break;
case RATE_INFO_BW_10:
rate_flg = NL80211_RATE_INFO_10_MHZ_WIDTH;
break;
+ case RATE_INFO_BW_16:
+ rate_flg = NL80211_RATE_INFO_16_MHZ_WIDTH;
+ break;
default:
WARN_ON(1);
fallthrough;
@@ -6197,6 +6212,14 @@ bool nl80211_put_sta_rate(struct sk_buff *msg, struct rate_info *info, int attr)
nla_put_u8(msg, NL80211_RATE_INFO_HE_RU_ALLOC,
info->he_ru_alloc))
return false;
+ } else if (info->flags & RATE_INFO_FLAGS_S1G_MCS) {
+ if (nla_put_u8(msg, NL80211_RATE_INFO_S1G_MCS, info->mcs))
+ return false;
+ if (nla_put_u8(msg, NL80211_RATE_INFO_S1G_NSS, info->nss))
+ return false;
+ if (info->flags & RATE_INFO_FLAGS_SHORT_GI &&
+ nla_put_flag(msg, NL80211_RATE_INFO_SHORT_GI))
+ return false;
} else if (info->flags & RATE_INFO_FLAGS_EHT_MCS) {
if (nla_put_u8(msg, NL80211_RATE_INFO_EHT_MCS, info->mcs))
return false;
--
2.34.1

2022-09-06 04:55:10

by Kieran Frewen

[permalink] [raw]
Subject: [PATCH v3 11/12] cfg80211: support for calculating S1G bitrates

Support for reporting and calculating S1G MCS bitrates.

Signed-off-by: Kieran Frewen <[email protected]>
---
net/wireless/util.c | 113 ++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 113 insertions(+)

diff --git a/net/wireless/util.c b/net/wireless/util.c
index aeccb6ce595c..d9d7dde3d4f2 100644
--- a/net/wireless/util.c
+++ b/net/wireless/util.c
@@ -1384,6 +1384,117 @@ static u32 cfg80211_calculate_bitrate_vht(struct rate_info *rate)
return 0;
}

+static u32 cfg80211_calculate_bitrate_s1g(struct rate_info *rate)
+{
+ /* For 1, 2, 4, 8 and 16 MHz channels */
+ static const u32 base[5][12] = {
+ { 300000,
+ 600000,
+ 900000,
+ 1200000,
+ 1800000,
+ 2400000,
+ 2700000,
+ 3000000,
+ 3600000,
+ 4000000,
+ /* MCS 10 supported in 1 MHz only */
+ 150000,
+ },
+ { 650000,
+ 1300000,
+ 1950000,
+ 2600000,
+ 3900000,
+ 5200000,
+ 5850000,
+ 6500000,
+ 7800000,
+ /* MCS 9 not valid */
+ },
+ { 1350000,
+ 2700000,
+ 4050000,
+ 5400000,
+ 8100000,
+ 10800000,
+ 12150000,
+ 13500000,
+ 16200000,
+ 18000000,
+ },
+ { 2925000,
+ 5850000,
+ 8775000,
+ 11700000,
+ 17550000,
+ 23400000,
+ 26325000,
+ 29250000,
+ 35100000,
+ 39000000,
+ },
+ { 8580000,
+ 11700000,
+ 17550000,
+ 23400000,
+ 35100000,
+ 46800000,
+ 52650000,
+ 58500000,
+ 70200000,
+ 78000000,
+ },
+ };
+ u32 bitrate;
+ /* default is 1 MHz index */
+ int idx = 0;
+
+ if (rate->mcs > 11)
+ goto warn;
+
+ switch (rate->bw) {
+ case RATE_INFO_BW_16:
+ idx = 4;
+ break;
+ case RATE_INFO_BW_8:
+ idx = 3;
+ break;
+ case RATE_INFO_BW_4:
+ idx = 2;
+ break;
+ case RATE_INFO_BW_2:
+ idx = 1;
+ break;
+ case RATE_INFO_BW_1:
+ idx = 0;
+ break;
+ case RATE_INFO_BW_5:
+ case RATE_INFO_BW_10:
+ case RATE_INFO_BW_20:
+ case RATE_INFO_BW_40:
+ case RATE_INFO_BW_80:
+ case RATE_INFO_BW_160:
+ default:
+ goto warn;
+ }
+
+ bitrate = base[idx][rate->mcs];
+ bitrate *= rate->nss;
+
+ if (rate->flags & RATE_INFO_FLAGS_SHORT_GI)
+ bitrate = (bitrate / 9) * 10;
+ /* do NOT round down here */
+ return (bitrate + 50000) / 100000;
+warn:
+ if (!rate->bw && !rate->mcs && !rate->nss)
+ pr_debug("%s: rx status was not received yet!", __func__);
+ else
+ WARN_ONCE(1, "invalid rate bw=%d, mcs=%d, nss=%d\n",
+ rate->bw, rate->mcs, rate->nss);
+ return 0;
+}
+
static u32 cfg80211_calculate_bitrate_he(struct rate_info *rate)
{
#define SCALE 6144
@@ -1612,6 +1723,8 @@ u32 cfg80211_calculate_bitrate(struct rate_info *rate)
return cfg80211_calculate_bitrate_he(rate);
if (rate->flags & RATE_INFO_FLAGS_EHT_MCS)
return cfg80211_calculate_bitrate_eht(rate);
+ if (rate->flags & RATE_INFO_FLAGS_S1G_MCS)
+ return cfg80211_calculate_bitrate_s1g(rate);

return rate->legacy;
}
--
2.34.1

2022-09-06 04:55:10

by Kieran Frewen

[permalink] [raw]
Subject: [PATCH v3 12/12] mac80211_hwsim: support for S1G rate information

Include S1G rate information in S1G frames.

Signed-off-by: Kieran Frewen<[email protected]>
---
drivers/net/wireless/mac80211_hwsim.c | 38 ++++++++++++++++++++-------
1 file changed, 29 insertions(+), 9 deletions(-)

diff --git a/drivers/net/wireless/mac80211_hwsim.c b/drivers/net/wireless/mac80211_hwsim.c
index 5ecbc80be338..6742f308ef7a 100644
--- a/drivers/net/wireless/mac80211_hwsim.c
+++ b/drivers/net/wireless/mac80211_hwsim.c
@@ -1577,7 +1577,14 @@ static bool mac80211_hwsim_tx_frame_no_nl(struct ieee80211_hw *hw,
rx_status.freq = chan->center_freq;
rx_status.freq_offset = chan->freq_offset;
rx_status.band = chan->band;
- if (info->control.rates[0].flags & IEEE80211_TX_RC_VHT_MCS) {
+ if (info->control.rates[0].flags & IEEE80211_TX_RC_S1G_MCS &&
+ rx_status.band == NL80211_BAND_S1GHZ) {
+ rx_status.rate_idx =
+ ieee80211_rate_get_s1g_mcs(&info->control.rates[0]);
+ rx_status.nss =
+ ieee80211_rate_get_s1g_nss(&info->control.rates[0]);
+ rx_status.encoding = RX_ENC_S1G;
+ } else if (info->control.rates[0].flags & IEEE80211_TX_RC_VHT_MCS) {
rx_status.rate_idx =
ieee80211_rate_get_vht_mcs(&info->control.rates[0]);
rx_status.nss =
@@ -1588,14 +1595,27 @@ static bool mac80211_hwsim_tx_frame_no_nl(struct ieee80211_hw *hw,
if (info->control.rates[0].flags & IEEE80211_TX_RC_MCS)
rx_status.encoding = RX_ENC_HT;
}
- if (info->control.rates[0].flags & IEEE80211_TX_RC_40_MHZ_WIDTH)
- rx_status.bw = RATE_INFO_BW_40;
- else if (info->control.rates[0].flags & IEEE80211_TX_RC_80_MHZ_WIDTH)
- rx_status.bw = RATE_INFO_BW_80;
- else if (info->control.rates[0].flags & IEEE80211_TX_RC_160_MHZ_WIDTH)
- rx_status.bw = RATE_INFO_BW_160;
- else
- rx_status.bw = RATE_INFO_BW_20;
+ if (rx_status.band == NL80211_BAND_S1GHZ) {
+ if (info->control.rates[0].flags & IEEE80211_TX_RC_2_MHZ_WIDTH)
+ rx_status.bw = RATE_INFO_BW_2;
+ else if (info->control.rates[0].flags & IEEE80211_TX_RC_4_MHZ_WIDTH)
+ rx_status.bw = RATE_INFO_BW_4;
+ else if (info->control.rates[0].flags & IEEE80211_TX_RC_8_MHZ_WIDTH)
+ rx_status.bw = RATE_INFO_BW_8;
+ else if (info->control.rates[0].flags & IEEE80211_TX_RC_16_MHZ_WIDTH)
+ rx_status.bw = RATE_INFO_BW_16;
+ else
+ rx_status.bw = RATE_INFO_BW_1;
+ } else {
+ if (info->control.rates[0].flags & IEEE80211_TX_RC_40_MHZ_WIDTH)
+ rx_status.bw = RATE_INFO_BW_40;
+ else if (info->control.rates[0].flags & IEEE80211_TX_RC_80_MHZ_WIDTH)
+ rx_status.bw = RATE_INFO_BW_80;
+ else if (info->control.rates[0].flags & IEEE80211_TX_RC_160_MHZ_WIDTH)
+ rx_status.bw = RATE_INFO_BW_160;
+ else
+ rx_status.bw = RATE_INFO_BW_20;
+ }
if (info->control.rates[0].flags & IEEE80211_TX_RC_SHORT_GI)
rx_status.enc_flags |= RX_ENC_FLAG_SHORT_GI;
/* TODO: simulate optional packet loss */
--
2.34.1

2022-09-06 09:44:05

by Johannes Berg

[permalink] [raw]
Subject: Re: [PATCH v3 01/12] cfg80211: regulatory: extend regulatory support for S1G

On Tue, 2022-09-06 at 16:48 +1200, Kieran Frewen wrote:
> Extend the S1G regulatory information to support all regulatory
> domains. An reg_s1g.h file is included containing structs with key
> regulatory class information. These structs were required to ensure
> the right combination of information was available to a series of
> functions which support the mapping between frequencies, bandwidths,
> and channels.
>

Hm. Isn't this type of thing something we'd usually want to keep in the
regulatory database to be able to update it? Who says JP will always
stick to their restrictive scheme, for example.

johannes

2022-09-06 09:44:26

by Johannes Berg

[permalink] [raw]
Subject: Re: [PATCH v3 03/12] mac80211: S1G beacon/short beacon support

On Tue, 2022-09-06 at 16:48 +1200, Kieran Frewen wrote:
> If configured, use the S1G short beacon format. The S1G short beacon
> format includes a limited set of information elements.

Could you be more specific? Is there really no reason to think that this
limited set might need to be set partially by hostapd?

> - if (beacon->tail)
> + if (beacon->tail && !is_short)
> skb_put_data(skb, beacon->tail, beacon->tail_len);

Asking since you do this here.

johannes

2022-09-06 09:45:29

by Johannes Berg

[permalink] [raw]
Subject: Re: [PATCH v3 03/12] mac80211: S1G beacon/short beacon support

On Tue, 2022-09-06 at 16:48 +1200, Kieran Frewen wrote:
> If configured, use the S1G short beacon format. The S1G short beacon
> format includes a limited set of information elements.
>
> Signed-off-by: Kieran Frewen <[email protected]>
> ---
> include/net/cfg80211.h | 2 +-
> include/net/mac80211.h | 1 +
> net/mac80211/cfg.c | 1 +
> net/mac80211/ieee80211_i.h | 1 +
> net/mac80211/tx.c | 14 +++++++++++++-
> 5 files changed, 17 insertions(+), 2 deletions(-)
>
> diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
> index 945e7700de66..b750b2ad246b 100644
> --- a/include/net/cfg80211.h
> +++ b/include/net/cfg80211.h
> @@ -1328,7 +1328,7 @@ struct cfg80211_ap_settings {
>
> struct cfg80211_beacon_data beacon;
>
> - int beacon_interval, dtim_period;
> + int beacon_interval, dtim_period, short_beacon_period;
>

One way or the other, this doesn't belong into this patch - you should
reorder so cfg80211 comes first and then mac80211 can use it, and then
this change goes into the cfg80211 patch.

johannes

2022-09-06 09:45:29

by Johannes Berg

[permalink] [raw]
Subject: Re: [PATCH v3 04/12] nl80211: support setting S1G short beacon period

On Tue, 2022-09-06 at 16:48 +1200, Kieran Frewen wrote:
>
> @@ -805,6 +805,7 @@ static const struct nla_policy nl80211_policy[NUM_NL80211_ATTR] = {
> [NL80211_ATTR_MLD_ADDR] = NLA_POLICY_EXACT_LEN(ETH_ALEN),
> [NL80211_ATTR_MLO_SUPPORT] = { .type = NLA_FLAG },
> [NL80211_ATTR_MAX_NUM_AKM_SUITES] = { .type = NLA_REJECT },
> + [NL80211_ATTR_SHORT_BEACON_PERIOD] = { .type = NLA_U16 },

You probably want _some_ kind of range validation here, like "don't set
it to zero" at least?

> + if (info->attrs[NL80211_ATTR_SHORT_BEACON_PERIOD])
> + params->short_beacon_period =
> + nla_get_u32(info->attrs[NL80211_ATTR_SHORT_BEACON_PERIOD]);
>

And maybe it should be < the long beacon period?

Actually the mac80211 code makes it sound like what you really should
have is a "long beacon period" or something, so that every N beacons you
send a long one?

Or are these really completely independent? It feels like probably the
intention would be to have a (short) beacon period, and then every N
beacons you send a long one?

johannes

2022-09-06 09:47:57

by Johannes Berg

[permalink] [raw]
Subject: Re: [PATCH v3 06/12] mac80211: support ieee80211_ext format

On Tue, 2022-09-06 at 16:48 +1200, Kieran Frewen wrote:
>
> + if (ieee80211_is_s1g_beacon(fc))

maybe use "if (ext_hdr)" here so it's easier to understand? Even for
static checkers :)

> + rx.sta = sta_info_get_bss(prev, ext_hdr->u.s1g_beacon.sa);
> + else
> + rx.sta = sta_info_get_bss(prev, hdr->addr2);
> rx.sdata = prev;
> ieee80211_rx_for_interface(&rx, skb, false);
>
> @@ -4999,6 +5007,10 @@ static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw,
> }
>
> if (prev) {
> + if (ieee80211_is_s1g_beacon(fc))
> + rx.sta = sta_info_get_bss(prev, ext_hdr->u.s1g_beacon.sa);
> + else
> + rx.sta = sta_info_get_bss(prev, hdr->addr2);
>

here too, I guess

johannes

2022-09-06 09:48:14

by Johannes Berg

[permalink] [raw]
Subject: Re: [PATCH v3 07/12] mac80211: S1G capabilities information element in probe request



Feels like somewhere in this patch you should consider the size of the
new element?

> /* channel management */
> bool ieee80211_chandef_ht_oper(const struct ieee80211_ht_operation *ht_oper,
> diff --git a/net/mac80211/util.c b/net/mac80211/util.c
> index 53826c663723..78e8c286011e 100644
> --- a/net/mac80211/util.c
> +++ b/net/mac80211/util.c
> @@ -1857,6 +1857,12 @@ static int ieee80211_build_preq_ies_band(struct ieee80211_sub_if_data *sdata,
> rate_flags = ieee80211_chandef_rate_flags(chandef);
> shift = ieee80211_chandef_get_shift(chandef);
>
> + /* For direct mac80211 scan (probe request), add S1G IE and consider its override bits */
> + if (band == NL80211_BAND_S1GHZ) {
> + pos = ieee80211_ie_build_s1g_cap(pos, &sband->s1g_cap);
> + goto done;
> + }
>

Though off the top of my head I'm not really sure how it works for the
other bits.

johannes

2022-09-06 10:06:41

by Johannes Berg

[permalink] [raw]
Subject: Re: [PATCH v3 11/12] cfg80211: support for calculating S1G bitrates

On Tue, 2022-09-06 at 16:48 +1200, Kieran Frewen wrote:
>
> +warn:
> + if (!rate->bw && !rate->mcs && !rate->nss)
> + pr_debug("%s: rx status was not received yet!", __func__);

That part seems ... odd? Why not just warn?

johannes

2022-09-21 22:16:35

by Kieran Frewen

[permalink] [raw]
Subject: Re: [PATCH v3 01/12] cfg80211: regulatory: extend regulatory support for S1G

On Tue, Sep 6, 2022 at 9:36 PM Johannes Berg <[email protected]> wrote:
>
> On Tue, 2022-09-06 at 16:48 +1200, Kieran Frewen wrote:
> > Extend the S1G regulatory information to support all regulatory
> > domains. An reg_s1g.h file is included containing structs with key
> > regulatory class information. These structs were required to ensure
> > the right combination of information was available to a series of
> > functions which support the mapping between frequencies, bandwidths,
> > and channels.
> >
>
> Hm. Isn't this type of thing something we'd usually want to keep in the
> regulatory database to be able to update it? Who says JP will always
> stick to their restrictive scheme, for example.
>
> johannes

Yes I agree that this information would be best stored in the
regulatory database.
Especially in respect to maintaining a single up-to-date source of knowledge.
I have done a bit of investigation into what information we would
require in order
to maintain the same level of functionality. I think at the very least
we would have to
add the base frequency to what already exists in the regulatory
database. By adding
this we would maintain the ability to map from S1G channels to frequencies. We
would, however, lose the ability to specify exact bandwidths for a
certain frequency
as is the current behaviour in reg_rule_to_chan_bw_flags() and would
likely have to
change the S1G bandwidth flags to not permit certain bandwidths on a
channel, e.g.
IEEE80211_CHAN_NO_2MHZ as opposed to flagging a single allowed bandwidth.

I do wonder that if we do add a base frequency to the regulatory database are we
straying from just maintaining information which permits or prevents operation
in a regulatory domain for a specific frequency and starting to
include information
that the kernel is relying on for mapping from one field to another, e.g.
ieee80211_channel_to_freq_khz().

Kieran

2022-11-07 20:13:57

by Kieran Frewen

[permalink] [raw]
Subject: Re: [PATCH v3 00/12] Additional Support for 802.11ah (S1G)

On Tue, Sep 6, 2022 at 4:48 PM Kieran Frewen
<[email protected]> wrote:
>
> This patchset builds on the work down by Thomas Pedersen to add further
> support for 802.11ah in cfg80211 and mac80211. The ultimate goal is
> to enable the successful starting of an AP on 802.11ah using 802.11ah
> terms by implementing the various features that are required by the
> AP. The features are split into their own commits, please see those
> patches for more details.
> The patchset has been tested on both real hardware (Morse Micro MM610x)
> and mac80211_hwsim, in AP and STA modes. Basic regression testing was
> performed on 802.11n with mac80211_hwsim by starting an AP and having a
> STA interface connect to it.
> 802.11ah features/support missing:
>
> Rate control integration
> Regulatory database updates (only US regulatory information exists)
> Optional 802.11ah (S1G) features such as RAW, TWT and AID grouping
>
> Changelog
>
> v3:
> [PATCH 01/12]
> Added prototype definition and description for
> ieee80211_channel_to_freq_khz.
> Fixed issue introduced in v1 where center_freq_khz
> in handle_channel_custom() was uninitialised.
> [PATCH 10/12]
> Fixed comment block style
>
> v2:
> [PATCH 01/12]
> Added validation to assignment of s1g_oper_class and class_idx.
> Changed align_to_end from u8 to bool.
> Added clarification of usage requirements for country code in
> s1g_oper_class struct.
> Changed cc field in s1g_oper_class struct from char * to cc[3].
> Moved initialised structs and arrays and from reg_s1g.h to reg_s1g.c.
> Moved reg_s1g_get_oper_class from reg_s1g.h to reg_s1g.c
> reg_s1g_get_oper_class now defaults to NULL if no natching
> s1g_oper_class is found.
> [PATCH 04/12]
> NL80211_ATTR_SHORT_BEACON_PERIOD changed to NLA_U16.
> [PATCH 07/12]
> Implemented ieee80211_ie_build_s1g_cap function to build S1G
> capability IE in place. Mimicing behaviour of
> ieee80211_ie_build_ht_cap.
> [PATCH 08/12]
> Capatilisation of MCS in description of RATE_INFO_FLAGS_S1G_MCS.
> Re-ordered grouping of fields in rate_info struct to order by size.
> [PATCH 09/12]
> Capatilisation of MCS in field naming of NL80211_RATE_INFO_S1G_MSS.
> Reordering of info->bw cases in switch to numberical order.
>
> Kieran Frewen (12):
> cfg80211: regulatory: extend regulatory support for S1G
> mac80211: update TIM for S1G specification changes
> mac80211: S1G beacon/short beacon support
> nl80211: support setting S1G short beacon period
> nl80211: support advertising S1G capabilities
> mac80211: support ieee80211_ext format
> mac80211: S1G capabilities information element in probe request
> cfg80211: S1G rate flags
> nl80211: support advertising S1G rate information
> mac80211: support S1G rate encoding.
> cfg80211: support for calculating S1G bitrates
> mac80211_hwsim: support for S1G rate information
>
> drivers/net/wireless/mac80211_hwsim.c | 40 +++--
> include/net/cfg80211.h | 26 ++-
> include/net/mac80211.h | 33 +++-
> include/uapi/linux/nl80211.h | 28 ++++
> net/mac80211/cfg.c | 43 +++--
> net/mac80211/ieee80211_i.h | 2 +
> net/mac80211/rx.c | 32 +++-
> net/mac80211/sta_info.c | 7 +
> net/mac80211/sta_info.h | 7 +
> net/mac80211/tx.c | 27 ++-
> net/mac80211/util.c | 50 +++++-
> net/wireless/Makefile | 2 +-
> net/wireless/nl80211.c | 37 +++++
> net/wireless/reg.c | 60 +++++--
> net/wireless/reg_s1g.c | 231 ++++++++++++++++++++++++++
> net/wireless/reg_s1g.h | 53 ++++++
> net/wireless/util.c | 148 ++++++++++++++++-
> 17 files changed, 772 insertions(+), 54 deletions(-)
> create mode 100644 net/wireless/reg_s1g.c
> create mode 100644 net/wireless/reg_s1g.h
>
>
> base-commit: 7dad3e39fde1eef97bc1a0b92e5d0f3500c9ed56
> --
> 2.34.1
>

Quick update on this changeset, I have handed off some of the
continued development of this patchset. Additionally we decided it was
best to split up the patches in this changeset as much as possible to
individually addressable changes. You may have seen a new patch appear
as a result of this.

Thanks, Kieran