RU puncturing bitmap consists of 16 bits, each bit corresponding to
a 20 MHz channel in the operating bandwidth. Lowest bit corresponds to
the lowest frequency. Bit set to 1 indicates that the channel is
punctured otherwise it is active.
Validate the bitmap against following rules:
- Primary 20 MHz channel cannot be punctured
- As per IEEE P802.11be/D1.3, December 2021, 36.3.12.11.3 Preamble
puncturing for PPDUs in a non-OFDMA transmission
- As per IEEE P802.11be/D1.3, December 2021, 36.3.12.11.2 Preamble
puncturing for PPDUs in an OFDMA transmission.
Signed-off-by: Aloka Dixit <[email protected]>
---
v2: Exported the function cfg80211_ru_punct_bitmap_valid() as
suggested in v1.
include/net/cfg80211.h | 12 ++++-
net/wireless/chan.c | 100 +++++++++++++++++++++++++++++++++++++++++
2 files changed, 111 insertions(+), 1 deletion(-)
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index 46630a125e8e..b0f7993778aa 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -742,6 +742,11 @@ struct key_params {
* chan will define the primary channel and all other
* parameters are ignored.
* @freq1_offset: offset from @center_freq1, in KHz
+ * @ru_punct_bitmap: RU puncturing bitmap. Each bit represents a 20 MHz channel
+ * with lowest bit corresponding to the smallest frequency. Bit set to 1
+ * indicates that the channel is punctured, otherwise the channel is active
+ * @ru_punct_bitmap_supp_he: Indicates whether RU puncturing bitmap validation
+ * should include OFDMA bitmaps.
*/
struct cfg80211_chan_def {
struct ieee80211_channel *chan;
@@ -750,6 +755,8 @@ struct cfg80211_chan_def {
u32 center_freq2;
struct ieee80211_edmg edmg;
u16 freq1_offset;
+ u16 ru_punct_bitmap;
+ bool ru_punct_bitmap_supp_he;
};
/*
@@ -878,7 +885,10 @@ cfg80211_chandef_identical(const struct cfg80211_chan_def *chandef1,
chandef1->width == chandef2->width &&
chandef1->center_freq1 == chandef2->center_freq1 &&
chandef1->freq1_offset == chandef2->freq1_offset &&
- chandef1->center_freq2 == chandef2->center_freq2);
+ chandef1->center_freq2 == chandef2->center_freq2 &&
+ chandef1->ru_punct_bitmap == chandef2->ru_punct_bitmap &&
+ chandef1->ru_punct_bitmap_supp_he ==
+ chandef2->ru_punct_bitmap_supp_he);
}
/**
diff --git a/net/wireless/chan.c b/net/wireless/chan.c
index 8b7fb4a9e07b..aa17631da087 100644
--- a/net/wireless/chan.c
+++ b/net/wireless/chan.c
@@ -32,6 +32,7 @@ void cfg80211_chandef_create(struct cfg80211_chan_def *chandef,
chandef->center_freq2 = 0;
chandef->edmg.bw_config = 0;
chandef->edmg.channels = 0;
+ chandef->ru_punct_bitmap = 0;
switch (chan_type) {
case NL80211_CHAN_NO_HT:
@@ -196,6 +197,102 @@ static int cfg80211_chandef_get_width(const struct cfg80211_chan_def *c)
return nl80211_chan_width_to_mhz(c->width);
}
+/* IEEE P802.11be/D1.31, December 2021, Table 36-30 5-bit punctured channel
+ * indication for the non-OFDMA case in an EHT MU PPDU
+ */
+static const u16 ru_punct_bitmap_80[] = {0xF, 0xE, 0xD, 0xB, 0x7};
+static const u16 ru_punct_bitmap_160[] = {0xFF, 0xFE, 0xFD, 0xFB, 0xF7, 0xEF,
+ 0xDF, 0xBF, 0x7F, 0xFC, 0xF3, 0xCF,
+ 0x3F};
+static const u16 ru_punct_bitmap_320[] = {0xFFFF, 0xFFFC, 0xFFF3, 0xFFCF,
+ 0xFF3F, 0xFCFF, 0xF3FF, 0xCFFF,
+ 0x3FFF, 0xFFF0, 0xFF0F, 0xF0FF,
+ 0x0FFF, 0xFFC0, 0xFF30, 0xFCF0,
+ 0xF3F0, 0xCFF0, 0x3FF0, 0x0FFC,
+ 0x0FF3, 0x0FCF, 0x0F3F, 0x0CFF,
+ 0x03FF};
+
+bool cfg80211_ru_punct_bitmap_valid(const struct cfg80211_chan_def *chandef)
+{
+ u8 i, non_ofdma_bitmap_count, ofdma_block_count = 1;
+ u16 bitmap, pri_ch_bit_pos;
+ const u16 *non_ofdma_bitmap;
+ u32 start_freq;
+
+ if (!chandef->ru_punct_bitmap) /* All channels active */
+ return true;
+
+ bitmap = ~chandef->ru_punct_bitmap;
+ WARN_ON_ONCE(sizeof(bitmap) != sizeof(chandef->ru_punct_bitmap));
+
+ switch (chandef->width) {
+ case NL80211_CHAN_WIDTH_80:
+ bitmap &= 0xF;
+ non_ofdma_bitmap = &ru_punct_bitmap_80[0];
+ non_ofdma_bitmap_count = ARRAY_SIZE(ru_punct_bitmap_80);
+ start_freq = chandef->center_freq1 - 40;
+ break;
+
+ case NL80211_CHAN_WIDTH_160:
+ bitmap &= 0xFF;
+ non_ofdma_bitmap = &ru_punct_bitmap_160[0];
+ non_ofdma_bitmap_count = ARRAY_SIZE(ru_punct_bitmap_160);
+ ofdma_block_count = 2;
+ start_freq = chandef->center_freq1 - 80;
+ break;
+
+ case NL80211_CHAN_WIDTH_320:
+ bitmap &= 0xFFFF;
+ non_ofdma_bitmap = &ru_punct_bitmap_320[0];
+ non_ofdma_bitmap_count = ARRAY_SIZE(ru_punct_bitmap_320);
+ ofdma_block_count = 4;
+ start_freq = chandef->center_freq1 - 160;
+ break;
+
+ default:
+ return false;
+ }
+
+ if (!bitmap) /* No channel active */
+ return false;
+
+ pri_ch_bit_pos = ((chandef->chan->center_freq - start_freq) / 20);
+ if (!(bitmap & BIT(pri_ch_bit_pos)))
+ return false;
+
+ /* Check for non-OFDMA puncturing patterns */
+ for (i = 0; i < non_ofdma_bitmap_count; i++)
+ if (non_ofdma_bitmap[i] == bitmap)
+ return true;
+
+ if (!chandef->ru_punct_bitmap_supp_he)
+ return false;
+
+ /* Check for OFDMA puncturing patterns */
+ for (i = 0; i < ofdma_block_count; i++) {
+ switch ((bitmap >> (i * 4)) & 0xF) {
+ /* IEEE P802.11be/D1.31, December 2021, 36.3.12.11.2 Preamble
+ * puncturing for PPDUs in an OFDMA transmission
+ */
+ case 0xF:
+ case 0x7:
+ case 0xB:
+ case 0xD:
+ case 0xE:
+ case 0x3:
+ case 0xC:
+ case 0x9:
+ case 0x0:
+ break;
+ default:
+ return false;
+ }
+ }
+
+ return true;
+}
+EXPORT_SYMBOL(cfg80211_ru_punct_bitmap_valid);
+
bool cfg80211_chandef_valid(const struct cfg80211_chan_def *chandef)
{
u32 control_freq, oper_freq;
@@ -316,6 +413,9 @@ bool cfg80211_chandef_valid(const struct cfg80211_chan_def *chandef)
!cfg80211_edmg_chandef_valid(chandef))
return false;
+ if (!cfg80211_ru_punct_bitmap_valid(chandef))
+ return false;
+
return true;
}
EXPORT_SYMBOL(cfg80211_chandef_valid);
--
2.31.1
> + * @ru_punct_bitmap: RU puncturing bitmap. Each bit represents a 20 MHz channel
> + * with lowest bit corresponding to the smallest frequency. Bit set to 1
> + * indicates that the channel is punctured, otherwise the channel is active
> + * @ru_punct_bitmap_supp_he: Indicates whether RU puncturing bitmap validation
> + * should include OFDMA bitmaps.
> */
> struct cfg80211_chan_def {
> struct ieee80211_channel *chan;
> @@ -750,6 +755,8 @@ struct cfg80211_chan_def {
> u32 center_freq2;
> struct ieee80211_edmg edmg;
> u16 freq1_offset;
> + u16 ru_punct_bitmap;
> + bool ru_punct_bitmap_supp_he;
I don't feel we finished the discussion on why it should be in the
chandef.
On the one hand, I can see how you argue that it's a part of how the
channel is defined, after all, this is now in a sense different from the
non- or differently-punctured channel since some parts of it are "gone".
This makes saying that two chandefs are only identical if also their
puncturing matches completely sensible, as seen in the changed
implementation of cfg80211_chandef_identical().
On the other hand, however, I don't think this makes a lot of sense with
mac80211's channel contexts, and especially not in a client-side
implementation. If you were to e.g. have two simultaneous connections to
two different APs on the "same" channel but different puncturing
configuration, I'm not convinced it makes sense to treat that as
requiring two entirely separate channel contexts and have to go to
powersave on one AP to receive on the other etc.? At least from my
(Intel HW) POV that doesn't make much sense.
As a result, we treat the puncturing more of a bss_conf type thing, and
we indeed have a patch to do that for the client side, which I should
get sent out so we can have a better discussion about both sides.
But honestly part of that probably is that I don't really entirely
understand the need for puncturing in the first place.
(and also, you included all kinds of random other things in these
patches, specifically in nl80211.h, so there's no way I can apply them
as is anyway)
johannes
On 3/24/2022 3:37 AM, Johannes Berg wrote:
>
> (and also, you included all kinds of random other things in these
> patches, specifically in nl80211.h, so there's no way I can apply them
> as is anyway)
>
I had added the other nl80211 parts to match local user-space
nl80211 order during testing, forgot to take it out.
Let's discuss once your client side version is sent out.
Thanks.
>
>
>
> -------- Forwarded Message --------
> Subject: Re: [PATCH v2 2/4] cfg80211: validate RU puncturing bitmap
> Date: Thu, 24 Mar 2022 09:35:27 -0700
> From: Aloka Dixit <[email protected]>
> To: Johannes Berg <[email protected]>,
> [email protected]
>
> On 3/24/2022 3:37 AM, Johannes Berg wrote:
>>
>> (and also, you included all kinds of random other things in these
>> patches, specifically in nl80211.h, so there's no way I can apply them
>> as is anyway)
>>
>
> I had added the other nl80211 parts to match local user-space
> nl80211 order during testing, forgot to take it out.
>
> Let's discuss once your client side version is sent out.
>
> Thanks.
9.4.2.45 Multiple BSSID element (excerpts from Draft 2.0 version)
The Timestamp and Beacon Interval fields, TIM, DSSS Parameter Set, IBSS
Parameter Set, Coun
try, Channel Switch Announcement, Extended Channel Switch Announcement,
Wide Bandwidth Channel Switch, Transmit Power Envelope, Supported
Operating Classes, IBSS DFS, ERP Informa
tion, HT Capabilities, HT Operation, VHT Capabilities, and VHT
Operation, S1G Beacon Compati
bility, Short Beacon Interval, S1G Capabilities, and S1G Operation, HE
Capabilities, HE 6 GHz Band Capabilities, HE Operation, BSS Color Change
Announcement,
and Spatial Reuse Parameter Set , EHT Capabilities, and EHT Operation
elements are not included in the Nontransmitted BSSID Profile
subelement; the values of these elements for each nontransmitted BSSID
are always the same as the corresponding transmitted BSSID element values.
Hi Johannes,
I am looking at the change in design and i see the below concerns.
While a BSS level RU puncturing gives the flexibility of configuring
different puncturing bitmaps in MBSSID scenario, the same cannot be
advertised on a per BSS basis over the beacon to the stations trying to
associate with the AP. (with reference to text above from Spec)
1. There is a only one EHT operation element (which holds the disabled
subchannel bitmap) that can be announced in a MBSSID beacon.
The spec doesn't allow to announce EHT operation on a per BSS basis.
2. Having a ru_puncturing_bitmap at the chandef level for the AP mode
could also help us decide easily whether DFS is needed or not (Skip DFS
if the dfs channels are punctured) . Having RU puncturing at BSS level
could again lead to confusion if certain BSSes of a single phy are
configured with different RU puncturing bitmaps some including the DFS
channel and some puncturing out all the DFS channels.
Shall we retain the RU puncturing bitmap at chandef level for the AP
mode and keep the RU puncturing bitmap at BSS level for the STA scenarios?
From: Johannes
that's probably a discussion better had on the mailing list, rather than
long-form chat here? :)
not sure it's easy to do with AP/client modes different since we also
have AP + client concurrency scenarios
Hi Johannes,
I have captured the offline discussions above to set the context for others.
Even in the AP & STA concurrent scenario, i believe this approach should
work.
1. In the STA case, The STA shall use the puncture pattern from its
BSS conf for all transmission to its connected AP.
2. In the AP case ( MBSSID case as well), the AP shall use the
puncture pattern from the chandef while it transmits frame to its
connected stations.
The chandef ru_punct_bitmap ultimately gets assigned to the
virtual interfaces at the driver when virtual interfaces are created.
The AP vif shall use the value to control the transmissions to
all its connected stations.
Since the ru_punct_bitmap is announced over EHT Operation IE,
the connected stations would limit its transmission only to the
non-punctured channels.
Could you please share your comments on the above approach?
Thanks
Maha