Message ID | 20240826123341.5405-1-quic_kkavita@quicinc.com (mailing list archive) |
---|---|
State | Changes Requested |
Delegated to: | Johannes Berg |
Headers | show |
Series | wifi: cfg80211: skip regulatory checks when the channel is punctured | expand |
Kavita Kavita <quic_kkavita@quicinc.com> writes: > The kernel performs several regulatory checks for AP mode in > nl80211/cfg80211. These checks include radar detection, > verification of whether the sub-channel is disabled, and > an examination to determine if the channel is a DFS channel > (both DFS usable and DFS available). These checks are > performed across a frequency range, examining each sub-channel. > > However, these checks are also performed on frequencies that > have been punctured, which should not be examined as they are > not in use. > > This leads to the issue where the AP stops because one of > the 20 MHz sub-channels is disabled or radar detected on > the channel, even when the sub-channel is punctured. > > To address this issue, add a condition check wherever > regulatory checks exist for AP mode in nl80211/cfg80211. > This check identifies punctured channels and, upon finding > them, skips the regulatory checks for those channels. > > Co-developed-by: Manaswini Paluri <quic_mpaluri@quicinc.com> > Signed-off-by: Manaswini Paluri <quic_mpaluri@quicinc.com> > Signed-off-by: Kavita Kavita <quic_kkavita@quicinc.com> Kavita, is your first and last name really the same? Just trying to verify that s-o-b is correct.
On 8/27/2024 12:35 AM, Kalle Valo wrote: > Kavita Kavita <quic_kkavita@quicinc.com> writes: > >> >> Co-developed-by: Manaswini Paluri <quic_mpaluri@quicinc.com> >> Signed-off-by: Manaswini Paluri <quic_mpaluri@quicinc.com> >> Signed-off-by: Kavita Kavita <quic_kkavita@quicinc.com> > > Kavita, is your first and last name really the same? Just trying to > verify that s-o-b is correct. > Yes, My first name is same as last name.
Kavita Kavita <quic_kkavita@quicinc.com> writes: > On 8/27/2024 12:35 AM, Kalle Valo wrote: >> Kavita Kavita <quic_kkavita@quicinc.com> writes: >> >>> >>> Co-developed-by: Manaswini Paluri <quic_mpaluri@quicinc.com> >>> Signed-off-by: Manaswini Paluri <quic_mpaluri@quicinc.com> >>> Signed-off-by: Kavita Kavita <quic_kkavita@quicinc.com> >> >> Kavita, is your first and last name really the same? Just trying to >> verify that s-o-b is correct. > > Yes, My first name is same as last name. Thanks for confirming, you have a cool name :)
On Mon, 2024-08-26 at 18:03 +0530, Kavita Kavita wrote: > The kernel performs several regulatory checks for AP mode in > nl80211/cfg80211. These checks include radar detection, > verification of whether the sub-channel is disabled, and > an examination to determine if the channel is a DFS channel > (both DFS usable and DFS available). These checks are > performed across a frequency range, examining each sub-channel. > > However, these checks are also performed on frequencies that > have been punctured, which should not be examined as they are > not in use. Makes sense. > This leads to the issue where the AP stops because one of > the 20 MHz sub-channels is disabled or radar detected on > the channel, even when the sub-channel is punctured. I'm curious, how did that even happen? How did it detect radar on a punctured channel in the first place? Or are you saying it was detected before, but you say "the AP stops" rather than "the AP fails to start"? However, this possibly also points to something that's missing in this patch and/or Aditya's patchset: if we do radar detection with a chandef that's already punctured, we don't know that all the subchannels were actually radar-free, and shouldn't mark them accordingly. I think it'd make sense to incorporate that here as well, could you do that? > @@ -781,7 +784,7 @@ int cfg80211_chandef_dfs_required(struct wiphy *wiphy, > > ret = cfg80211_get_chans_dfs_required(wiphy, > MHZ_TO_KHZ(chandef->center_freq2), > - width, iftype); > + width, chandef->punctured, iftype); This isn't really right: center_freq2 is for 80+80 which cannot use puncturing, certainly cannot use puncturing in the secondary 80. It's probably not strictly wrong either since 80+80 cannot be legal with puncturing in the first place, but this really should just pass 0 I'd think. > @@ -868,7 +877,7 @@ bool cfg80211_chandef_dfs_usable(struct wiphy *wiphy, > WARN_ON(!chandef->center_freq2); > r2 = cfg80211_get_chans_dfs_usable(wiphy, > MHZ_TO_KHZ(chandef->center_freq2), > - width); > + width, chandef->punctured); same here > @@ -1113,7 +1128,7 @@ static bool cfg80211_chandef_dfs_available(struct wiphy *wiphy, > WARN_ON(!chandef->center_freq2); > r = cfg80211_get_chans_dfs_available(wiphy, > MHZ_TO_KHZ(chandef->center_freq2), > - width); > + width, chandef->punctured); and here, obviously > @@ -1139,6 +1155,12 @@ static unsigned int cfg80211_get_chans_dfs_cac_time(struct wiphy *wiphy, > if (!c) > return 0; > > + if (punctured & 1) { > + punctured >>= 1; > + continue; > + } > + punctured >>= 1; > + > if (c->flags & IEEE80211_CHAN_DISABLED) > return 0; We have this pattern a lot! I think perhaps we should add a kind of for_each_subchannel() macro? Perhaps even iterate subchannels of a chandef including center_freq2, though I'm not sure how we'd arrange that... Something like cfg80211_wdev_on_sub_chan() also seems to need to take puncturing into account and could be rewritten with such a helper. #define for_each_subchannel(chandef, subchan) for (subchan = ieee80211_next_subchan(chandef, NULL); subchan; subchan = ieee80211_next_subchan(chandef, subchan)) or so, with ieee80211_next_subchan() containing some necessary iteration logic? johannes
On 8/28/2024 3:51 PM, Johannes Berg wrote: > On Mon, 2024-08-26 at 18:03 +0530, Kavita Kavita wrote: >> The kernel performs several regulatory checks for AP mode in >> nl80211/cfg80211. These checks include radar detection, >> verification of whether the sub-channel is disabled, and >> an examination to determine if the channel is a DFS channel >> (both DFS usable and DFS available). These checks are >> performed across a frequency range, examining each sub-channel. >> >> However, these checks are also performed on frequencies that >> have been punctured, which should not be examined as they are >> not in use. > > Makes sense. > >> This leads to the issue where the AP stops because one of >> the 20 MHz sub-channels is disabled or radar detected on >> the channel, even when the sub-channel is punctured. > > I'm curious, how did that even happen? How did it detect radar on a > punctured channel in the first place? > > Or are you saying it was detected before, but you say "the AP stops" > rather than "the AP fails to start"? > One of the use cases we are targeting here is after AP start, if radar is detected, SME offload drivers can indicate a channel switch with the radar-detected channel as punctured instead of switching to a new channel. But when the driver does this, currently the kernel stops the AP even after the driver punctures that channel. Also, for the AP start case mentioned, the AP shouldn't stop or fail to start if the radar-detected channel is punctured in the START_AP command. > However, this possibly also points to something that's missing in this > patch and/or Aditya's patchset: if we do radar detection with a chandef > that's already punctured, we don't know that all the subchannels were > actually radar-free, and shouldn't mark them accordingly. > > I think it'd make sense to incorporate that here as well, could you do > that? > Thanks, I added some additional changes in the v2 patch to handle this. >> @@ -781,7 +784,7 @@ int cfg80211_chandef_dfs_required(struct wiphy *wiphy, >> >> ret = cfg80211_get_chans_dfs_required(wiphy, >> MHZ_TO_KHZ(chandef->center_freq2), >> - width, iftype); >> + width, chandef->punctured, iftype); > > This isn't really right: center_freq2 is for 80+80 which cannot use > puncturing, certainly cannot use puncturing in the secondary 80. It's > probably not strictly wrong either since 80+80 cannot be legal with > puncturing in the first place, but this really should just pass 0 I'd > think. > Thanks, I fixed this in the v2 patch. >> @@ -868,7 +877,7 @@ bool cfg80211_chandef_dfs_usable(struct wiphy *wiphy, >> WARN_ON(!chandef->center_freq2); >> r2 = cfg80211_get_chans_dfs_usable(wiphy, >> MHZ_TO_KHZ(chandef->center_freq2), >> - width); >> + width, chandef->punctured); > > same here > >> @@ -1113,7 +1128,7 @@ static bool cfg80211_chandef_dfs_available(struct wiphy *wiphy, >> WARN_ON(!chandef->center_freq2); >> r = cfg80211_get_chans_dfs_available(wiphy, >> MHZ_TO_KHZ(chandef->center_freq2), >> - width); >> + width, chandef->punctured); > > and here, obviously > >> @@ -1139,6 +1155,12 @@ static unsigned int cfg80211_get_chans_dfs_cac_time(struct wiphy *wiphy, >> if (!c) >> return 0; >> >> + if (punctured & 1) { >> + punctured >>= 1; >> + continue; >> + } >> + punctured >>= 1; >> + >> if (c->flags & IEEE80211_CHAN_DISABLED) >> return 0; > > We have this pattern a lot! I think perhaps we should add a kind of > for_each_subchannel() macro? > > Perhaps even iterate subchannels of a chandef including center_freq2, > though I'm not sure how we'd arrange that... > > Something like cfg80211_wdev_on_sub_chan() also seems to need to take > puncturing into account and could be rewritten with such a helper. > > #define for_each_subchannel(chandef, subchan) > for (subchan = ieee80211_next_subchan(chandef, NULL); > subchan; > subchan = ieee80211_next_subchan(chandef, subchan)) > > or so, with ieee80211_next_subchan() containing some necessary iteration > logic? > Added macro for_each_subchan() in v2 patch. I tried to handle traversing both center_freq1 and center_freq2 with for_each_subchannel(chandef, subchan) as suggested by you, but it's complicated to handle both center_freq1 and center_freq2 cases together due to their different handling requirements. > johannes
diff --git a/net/wireless/chan.c b/net/wireless/chan.c index e579d7e1425f..b363649acd03 100644 --- a/net/wireless/chan.c +++ b/net/wireless/chan.c @@ -727,6 +727,7 @@ static bool cfg80211_dfs_permissive_chan(struct wiphy *wiphy, static int cfg80211_get_chans_dfs_required(struct wiphy *wiphy, u32 center_freq, u32 bandwidth, + u16 punctured, enum nl80211_iftype iftype) { struct ieee80211_channel *c; @@ -740,9 +741,11 @@ static int cfg80211_get_chans_dfs_required(struct wiphy *wiphy, if (!c) return -EINVAL; - if (c->flags & IEEE80211_CHAN_RADAR && + if (!(punctured & 1) && (c->flags & IEEE80211_CHAN_RADAR) && !cfg80211_dfs_permissive_chan(wiphy, iftype, c)) return 1; + + punctured >>= 1; } return 0; @@ -770,7 +773,7 @@ int cfg80211_chandef_dfs_required(struct wiphy *wiphy, ret = cfg80211_get_chans_dfs_required(wiphy, ieee80211_chandef_to_khz(chandef), - width, iftype); + width, chandef->punctured, iftype); if (ret < 0) return ret; else if (ret > 0) @@ -781,7 +784,7 @@ int cfg80211_chandef_dfs_required(struct wiphy *wiphy, ret = cfg80211_get_chans_dfs_required(wiphy, MHZ_TO_KHZ(chandef->center_freq2), - width, iftype); + width, chandef->punctured, iftype); if (ret < 0) return ret; else if (ret > 0) @@ -808,7 +811,7 @@ EXPORT_SYMBOL(cfg80211_chandef_dfs_required); static int cfg80211_get_chans_dfs_usable(struct wiphy *wiphy, u32 center_freq, - u32 bandwidth) + u32 bandwidth, u16 punctured) { struct ieee80211_channel *c; u32 freq, start_freq, end_freq; @@ -828,6 +831,12 @@ static int cfg80211_get_chans_dfs_usable(struct wiphy *wiphy, if (!c) return -EINVAL; + if (punctured & 1) { + punctured >>= 1; + continue; + } + punctured >>= 1; + if (c->flags & IEEE80211_CHAN_DISABLED) return -EINVAL; @@ -858,7 +867,7 @@ bool cfg80211_chandef_dfs_usable(struct wiphy *wiphy, r1 = cfg80211_get_chans_dfs_usable(wiphy, MHZ_TO_KHZ(chandef->center_freq1), - width); + width, chandef->punctured); if (r1 < 0) return false; @@ -868,7 +877,7 @@ bool cfg80211_chandef_dfs_usable(struct wiphy *wiphy, WARN_ON(!chandef->center_freq2); r2 = cfg80211_get_chans_dfs_usable(wiphy, MHZ_TO_KHZ(chandef->center_freq2), - width); + width, chandef->punctured); if (r2 < 0) return false; break; @@ -1053,7 +1062,7 @@ bool cfg80211_any_wiphy_oper_chan(struct wiphy *wiphy, static bool cfg80211_get_chans_dfs_available(struct wiphy *wiphy, u32 center_freq, - u32 bandwidth) + u32 bandwidth, u16 punctured) { struct ieee80211_channel *c; u32 freq, start_freq, end_freq; @@ -1075,6 +1084,12 @@ static bool cfg80211_get_chans_dfs_available(struct wiphy *wiphy, if (!c) return false; + if (punctured & 1) { + punctured >>= 1; + continue; + } + punctured >>= 1; + if (c->flags & IEEE80211_CHAN_DISABLED) return false; @@ -1102,7 +1117,7 @@ static bool cfg80211_chandef_dfs_available(struct wiphy *wiphy, r = cfg80211_get_chans_dfs_available(wiphy, MHZ_TO_KHZ(chandef->center_freq1), - width); + width, chandef->punctured); /* If any of channels unavailable for cf1 just return */ if (!r) @@ -1113,7 +1128,7 @@ static bool cfg80211_chandef_dfs_available(struct wiphy *wiphy, WARN_ON(!chandef->center_freq2); r = cfg80211_get_chans_dfs_available(wiphy, MHZ_TO_KHZ(chandef->center_freq2), - width); + width, chandef->punctured); break; default: WARN_ON(chandef->center_freq2); @@ -1125,7 +1140,8 @@ static bool cfg80211_chandef_dfs_available(struct wiphy *wiphy, static unsigned int cfg80211_get_chans_dfs_cac_time(struct wiphy *wiphy, u32 center_freq, - u32 bandwidth) + u32 bandwidth, + u16 punctured) { struct ieee80211_channel *c; u32 start_freq, end_freq, freq; @@ -1139,6 +1155,12 @@ static unsigned int cfg80211_get_chans_dfs_cac_time(struct wiphy *wiphy, if (!c) return 0; + if (punctured & 1) { + punctured >>= 1; + continue; + } + punctured >>= 1; + if (c->flags & IEEE80211_CHAN_DISABLED) return 0; @@ -1168,14 +1190,14 @@ cfg80211_chandef_dfs_cac_time(struct wiphy *wiphy, t1 = cfg80211_get_chans_dfs_cac_time(wiphy, MHZ_TO_KHZ(chandef->center_freq1), - width); + width, chandef->punctured); if (!chandef->center_freq2) return t1; t2 = cfg80211_get_chans_dfs_cac_time(wiphy, MHZ_TO_KHZ(chandef->center_freq2), - width); + width, chandef->punctured); return max(t1, t2); } @@ -1183,6 +1205,7 @@ EXPORT_SYMBOL(cfg80211_chandef_dfs_cac_time); static bool cfg80211_secondary_chans_ok(struct wiphy *wiphy, u32 center_freq, u32 bandwidth, + u16 punctured, u32 prohibited_flags, u32 permitting_flags) { @@ -1198,8 +1221,10 @@ static bool cfg80211_secondary_chans_ok(struct wiphy *wiphy, return false; if (c->flags & permitting_flags) continue; - if (c->flags & prohibited_flags) + if ((c->flags & prohibited_flags) && !(punctured & 1)) return false; + + punctured >>= 1; } return true; @@ -1423,16 +1448,16 @@ bool _cfg80211_chandef_usable(struct wiphy *wiphy, if (!cfg80211_secondary_chans_ok(wiphy, ieee80211_chandef_to_khz(chandef), - width, prohibited_flags, - permitting_flags)) + width, chandef->punctured, + prohibited_flags, permitting_flags)) return false; if (!chandef->center_freq2) return true; return cfg80211_secondary_chans_ok(wiphy, MHZ_TO_KHZ(chandef->center_freq2), - width, prohibited_flags, - permitting_flags); + width, chandef->punctured, + prohibited_flags, permitting_flags); } bool cfg80211_chandef_usable(struct wiphy *wiphy,