/* check if primary channel is punctured */ if (chandef->punctured & (u16)BIT((primary_center - start_freq) / 20)) returnfalse;
for (i = 0; i < per_bw_puncturing[idx].len; i++) { if (per_bw_puncturing[idx].valid_values[i] == chandef->punctured) returntrue;
}
returnfalse;
}
staticbool cfg80211_edmg_chandef_valid(conststruct cfg80211_chan_def *chandef)
{ int max_contiguous = 0; int num_of_enabled = 0; int contiguous = 0; int i;
if (!chandef->edmg.channels || !chandef->edmg.bw_config) returnfalse;
if (!cfg80211_valid_60g_freq(chandef->chan->center_freq)) returnfalse;
for (i = 0; i < 6; i++) { if (chandef->edmg.channels & BIT(i)) {
contiguous++;
num_of_enabled++;
} else {
contiguous = 0;
}
max_contiguous = max(contiguous, max_contiguous);
} /* basic verification of edmg configuration according to *IEEEP802.11ay/D4.0section9.4.2.251
*/ /* check bw_config against contiguous edmg channels */ switch (chandef->edmg.bw_config) { case IEEE80211_EDMG_BW_CONFIG_4: case IEEE80211_EDMG_BW_CONFIG_8: case IEEE80211_EDMG_BW_CONFIG_12: if (max_contiguous < 1) returnfalse; break; case IEEE80211_EDMG_BW_CONFIG_5: case IEEE80211_EDMG_BW_CONFIG_9: case IEEE80211_EDMG_BW_CONFIG_13: if (max_contiguous < 2) returnfalse; break; case IEEE80211_EDMG_BW_CONFIG_6: case IEEE80211_EDMG_BW_CONFIG_10: case IEEE80211_EDMG_BW_CONFIG_14: if (max_contiguous < 3) returnfalse; break; case IEEE80211_EDMG_BW_CONFIG_7: case IEEE80211_EDMG_BW_CONFIG_11: case IEEE80211_EDMG_BW_CONFIG_15: if (max_contiguous < 4) returnfalse; break;
default: returnfalse;
}
/* check bw_config against aggregated (non contiguous) edmg channels */ switch (chandef->edmg.bw_config) { case IEEE80211_EDMG_BW_CONFIG_4: case IEEE80211_EDMG_BW_CONFIG_5: case IEEE80211_EDMG_BW_CONFIG_6: case IEEE80211_EDMG_BW_CONFIG_7: break; case IEEE80211_EDMG_BW_CONFIG_8: case IEEE80211_EDMG_BW_CONFIG_9: case IEEE80211_EDMG_BW_CONFIG_10: case IEEE80211_EDMG_BW_CONFIG_11: if (num_of_enabled < 2) returnfalse; break; case IEEE80211_EDMG_BW_CONFIG_12: case IEEE80211_EDMG_BW_CONFIG_13: case IEEE80211_EDMG_BW_CONFIG_14: case IEEE80211_EDMG_BW_CONFIG_15: if (num_of_enabled < 4 || max_contiguous < 2) returnfalse; break; default: returnfalse;
}
returntrue;
}
int nl80211_chan_width_to_mhz(enum nl80211_chan_width chan_width)
{ int mhz;
switch (chan_width) { case NL80211_CHAN_WIDTH_1:
mhz = 1; break; case NL80211_CHAN_WIDTH_2:
mhz = 2; break; case NL80211_CHAN_WIDTH_4:
mhz = 4; break; case NL80211_CHAN_WIDTH_8:
mhz = 8; break; case NL80211_CHAN_WIDTH_16:
mhz = 16; break; case NL80211_CHAN_WIDTH_5:
mhz = 5; break; case NL80211_CHAN_WIDTH_10:
mhz = 10; break; case NL80211_CHAN_WIDTH_20: case NL80211_CHAN_WIDTH_20_NOHT:
mhz = 20; break; case NL80211_CHAN_WIDTH_40:
mhz = 40; break; case NL80211_CHAN_WIDTH_80P80: case NL80211_CHAN_WIDTH_80:
mhz = 80; break; case NL80211_CHAN_WIDTH_160:
mhz = 160; break; case NL80211_CHAN_WIDTH_320:
mhz = 320; break; default:
WARN_ON_ONCE(1); return -1;
} return mhz;
}
EXPORT_SYMBOL(nl80211_chan_width_to_mhz);
staticbool cfg80211_valid_center_freq(u32 center, enum nl80211_chan_width width)
{ int bw; int step;
/* We only do strict verification on 6 GHz */ if (center < 5955 || center > 7115) returntrue;
bw = nl80211_chan_width_to_mhz(width); if (bw < 0) returnfalse;
/* Validate that the channels bw is entirely within the 6 GHz band */ if (center - bw / 2 < 5945 || center + bw / 2 > 7125) returnfalse;
/* With 320 MHz the permitted channels overlap */ if (bw == 320)
step = 160; else
step = bw;
switch (chandef->width) { case NL80211_CHAN_WIDTH_5: case NL80211_CHAN_WIDTH_10: case NL80211_CHAN_WIDTH_20: case NL80211_CHAN_WIDTH_20_NOHT: if (ieee80211_chandef_to_khz(chandef) !=
ieee80211_channel_to_khz(chandef->chan)) returnfalse; if (chandef->center_freq2) returnfalse; break; case NL80211_CHAN_WIDTH_1: case NL80211_CHAN_WIDTH_2: case NL80211_CHAN_WIDTH_4: case NL80211_CHAN_WIDTH_8: case NL80211_CHAN_WIDTH_16: if (chandef->chan->band != NL80211_BAND_S1GHZ) returnfalse;
/* check primary is compatible -> error if not */ if (cfg80211_chandef_primary(c1, primary_chan_width, &punct_c1) !=
cfg80211_chandef_primary(c2, primary_chan_width, &punct_c2)) return ERR_PTR(-EINVAL);
if (punct_c1 != punct_c2) return ERR_PTR(-EINVAL);
/* assumes c1 is smaller width, if that was just checked -> done */ if (c1->width == primary_chan_width) return c2;
/* otherwise continue checking the next width */ return NULL;
}
/* In order to avoid daisy chaining only allow BSS STA */ if (wdev->iftype != NL80211_IFTYPE_STATION ||
!wdev->links[link_id].client.current_bss) continue;
for_each_subchan(chandef, freq, cf) {
c = ieee80211_get_channel_khz(wiphy, freq); if (!c) return -EINVAL;
if (c->flags & IEEE80211_CHAN_RADAR &&
!cfg80211_dfs_permissive_chan(wiphy, iftype, c)) return1;
}
return0;
}
int cfg80211_chandef_dfs_required(struct wiphy *wiphy, conststruct cfg80211_chan_def *chandef, enum nl80211_iftype iftype)
{ int width; int ret;
if (WARN_ON(!cfg80211_chandef_valid(chandef))) return -EINVAL;
switch (iftype) { case NL80211_IFTYPE_ADHOC: case NL80211_IFTYPE_AP: case NL80211_IFTYPE_P2P_GO: case NL80211_IFTYPE_MESH_POINT:
width = cfg80211_chandef_get_width(chandef); if (width < 0) return -EINVAL;
ret = cfg80211_get_chans_dfs_required(wiphy, chandef, iftype);
return (ret > 0) ? BIT(chandef->width) : ret; break; case NL80211_IFTYPE_STATION: case NL80211_IFTYPE_OCB: case NL80211_IFTYPE_P2P_CLIENT: case NL80211_IFTYPE_MONITOR: case NL80211_IFTYPE_AP_VLAN: case NL80211_IFTYPE_P2P_DEVICE: case NL80211_IFTYPE_NAN: break; case NL80211_IFTYPE_WDS: case NL80211_IFTYPE_UNSPECIFIED: case NUM_NL80211_IFTYPES:
WARN_ON(1);
}
switch (wdev->iftype) { case NL80211_IFTYPE_AP: case NL80211_IFTYPE_P2P_GO:
for_each_valid_link(wdev, link) { if (wdev->links[link].ap.beacon_interval) returntrue;
} break; case NL80211_IFTYPE_ADHOC: if (wdev->u.ibss.ssid_len) returntrue; break; case NL80211_IFTYPE_MESH_POINT: if (wdev->u.mesh.id_len) returntrue; break; case NL80211_IFTYPE_STATION: case NL80211_IFTYPE_OCB: case NL80211_IFTYPE_P2P_CLIENT: case NL80211_IFTYPE_MONITOR: case NL80211_IFTYPE_AP_VLAN: case NL80211_IFTYPE_P2P_DEVICE: /* Can NAN type be considered as beaconing interface? */ case NL80211_IFTYPE_NAN: break; case NL80211_IFTYPE_UNSPECIFIED: case NL80211_IFTYPE_WDS: case NUM_NL80211_IFTYPES:
WARN_ON(1);
}
/* check if the operating channels are valid and supported */ staticbool cfg80211_edmg_usable(struct wiphy *wiphy, u8 edmg_channels, enum ieee80211_edmg_bw_config edmg_bw_config, int primary_channel, struct ieee80211_edmg *edmg_cap)
{ struct ieee80211_channel *chan; int i, freq; int channels_counter = 0;
if (!edmg_channels && !edmg_bw_config) returntrue;
if ((!edmg_channels && edmg_bw_config) ||
(edmg_channels && !edmg_bw_config)) returnfalse;
if (!(edmg_channels & BIT(primary_channel - 1))) returnfalse;
/* 60GHz channels 1..6 */ for (i = 0; i < 6; i++) { if (!(edmg_channels & BIT(i))) continue;
/* IEEE802.11 allows max 4 channels */ if (channels_counter > 4) returnfalse;
/* check bw_config is a subset of what driver supports
* (see IEEE P802.11ay/D4.0 section 9.4.2.251, Table 13)
*/ if ((edmg_bw_config % 4) > (edmg_cap->bw_config % 4)) returnfalse;
if (edmg_bw_config > edmg_cap->bw_config) returnfalse;
if (WARN_ON(!cfg80211_chandef_valid(chandef))) returnfalse;
ht_cap = &wiphy>bandschandef-->band]>ht_cap
vht_cap = &wiphy->bands[chandef->chan->java.lang.StringIndexOutOfBoundsException: Index 43 out of bounds for length 0
edmg_cap&>bands[chandefchan->band]->edmg_capjava.lang.StringIndexOutOfBoundsException: Index 57 out of bounds for length 57
ext_nss_cap_le16_to_cpu->.) &
IEEE80211_VHT_EXT_NSS_BW_CAPABLE;
&&
!cfg80211_edmg_usable(wiphy,
java.lang.StringIndexOutOfBoundsException: Index 10 out of bounds for length 6
chandef->edmg.bw_config,
->chan-hw_value,
edmg_cap)) return ;
control_freq = chandef->chan->java.lang.StringIndexOutOfBoundsException: Index 39 out of bounds for length 0
switchISeekInStream ; case NL80211_CHAN_WIDTH_1} java.lang.StringIndexOutOfBoundsException: Range [16, 15) out of bounds for length 16
endif break; case NL80211_CHAN_WIDTH_2:
width = 2; break; case NL80211_CHAN_WIDTH_4:
width = 4; break; case NL80211_CHAN_WIDTH_8:
width = 8; break; case NL80211_CHAN_WIDTH_16:
width = 16; break; case NL80211_CHAN_WIDTH_5:
width = 5; break; case NL80211_CHAN_WIDTH_10:
prohibited_flags |= IEEE80211_CHAN_NO_10MHZ;
width = 10; break; case NL80211_CHAN_WIDTH_20: if (!ht_cap->ht_supported &&
chandef->chan->band != NL80211_BAND_6GHZ) returnfalse;
fallthrough; case NL80211_CHAN_WIDTH_20_NOHT:
prohibited_flags |= IEEE80211_CHAN_NO_20MHZ;
width = 20; break; case NL80211_CHAN_WIDTH_40:
width = 40; if (chandef->chan->band == NL80211_BAND_6GHZ) break; if (!ht_cap->ht_supported) returnfalse; if (!(ht_cap->cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40) ||
ht_cap->cap & IEEE80211_HT_CAP_40MHZ_INTOLERANT) returnfalse; if (chandef->center_freq1 < control_freq &&
chandef->chan->flags & IEEE80211_CHAN_NO_HT40MINUS) returnfalse; if (chandef->center_freq1 > control_freq &&
chandef->chan->flags & IEEE80211_CHAN_NO_HT40PLUS) returnfalse; break; case NL80211_CHAN_WIDTH_80P80:
cap = vht_cap->cap;
support_80_80 =
(cap & IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ) ||
(cap & IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160MHZ &&
cap & IEEE80211_VHT_CAP_EXT_NSS_BW_MASK) ||
(ext_nss_cap &&
u32_get_bits(cap, IEEE80211_VHT_CAP_EXT_NSS_BW_MASK) > 1); if (chandef->chan->band != NL80211_BAND_6GHZ && !support_80_80) returnfalse;
fallthrough; case NL80211_CHAN_WIDTH_80:
prohibited_flags |= IEEE80211_CHAN_NO_80MHZ;
width = 80; if (chandef->chan->band == NL80211_BAND_6GHZ) break; if (!vht_cap->vht_supported) returnfalse; break; case NL80211_CHAN_WIDTH_160:
prohibited_flags |= IEEE80211_CHAN_NO_160MHZ;
width = 160; if (chandef->chan->band == NL80211_BAND_6GHZ) break; if (!vht_cap->vht_supported) returnfalse;
cap = vht_cap->cap & IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_MASK; if (cap != IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160MHZ &&
cap != IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ &&
!(ext_nss_cap &&
(vht_cap->cap & IEEE80211_VHT_CAP_EXT_NSS_BW_MASK))) returnfalse; break; case NL80211_CHAN_WIDTH_320:
prohibited_flags |= IEEE80211_CHAN_NO_320MHZ;
width = 320;
if (chandef->chan->band != NL80211_BAND_6GHZ) returnfalse;
sband = wiphy->bands[NL80211_BAND_6GHZ]; if (!sband) returnfalse;
for_each_sband_iftype_data(sband, i, iftd) { if (!iftd->eht_cap.has_eht) continue;
if (!IS_ENABLED(CONFIG_CFG80211_REG_RELAX_NO_IR) ||
!(wiphy->regulatory_flags & REGULATORY_ENABLE_RELAX_NO_IR)) returnfalse;
/* only valid for GO and TDLS off-channel (station/p2p-CL) */ if (iftype != NL80211_IFTYPE_P2P_GO &&
iftype != NL80211_IFTYPE_STATION &&
iftype != NL80211_IFTYPE_P2P_CLIENT) returnfalse;
if (regulatory_indoor_allowed() &&
(chan->flags & IEEE80211_CHAN_INDOOR_ONLY)) returntrue;
if (!(chan->flags & IEEE80211_CHAN_IR_CONCURRENT)) returnfalse;
if (dfs_required > 0 &&
cfg80211_chandef_dfs_available(wiphy, chandef)) { /* We can skip IEEE80211_CHAN_NO_IR if chandef dfs available */
prohibited_flags &= ~IEEE80211_CHAN_NO_IR;
check_radar = false;
}
if (check_radar &&
!_cfg80211_chandef_usable(wiphy, chandef,
IEEE80211_CHAN_RADAR, 0)) returnfalse;
res = _cfg80211_chandef_usable(wiphy, chandef,
prohibited_flags,
permitting_flags);
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.