/** * enum hwsim_regtest - the type of regulatory tests we offer * * @HWSIM_REGTEST_DISABLED: No regulatory tests are performed, * this is the default value. * @HWSIM_REGTEST_DRIVER_REG_FOLLOW: Used for testing the driver regulatory * hint, only one driver regulatory hint will be sent as such the * secondary radios are expected to follow. * @HWSIM_REGTEST_DRIVER_REG_ALL: Used for testing the driver regulatory * request with all radios reporting the same regulatory domain. * @HWSIM_REGTEST_DIFF_COUNTRY: Used for testing the drivers calling * different regulatory domains requests. Expected behaviour is for * an intersection to occur but each device will still use their * respective regulatory requested domains. Subsequent radios will * use the resulting intersection. * @HWSIM_REGTEST_WORLD_ROAM: Used for testing the world roaming. We accomplish * this by using a custom beacon-capable regulatory domain for the first * radio. All other device world roam. * @HWSIM_REGTEST_CUSTOM_WORLD: Used for testing the custom world regulatory * domain requests. All radios will adhere to this custom world regulatory * domain. * @HWSIM_REGTEST_CUSTOM_WORLD_2: Used for testing 2 custom world regulatory * domain requests. The first radio will adhere to the first custom world * regulatory domain, the second one to the second custom world regulatory * domain. All other devices will world roam. * @HWSIM_REGTEST_STRICT_FOLLOW: Used for testing strict regulatory domain * settings, only the first radio will send a regulatory domain request * and use strict settings. The rest of the radios are expected to follow. * @HWSIM_REGTEST_STRICT_ALL: Used for testing strict regulatory domain * settings. All radios will adhere to this. * @HWSIM_REGTEST_STRICT_AND_DRIVER_REG: Used for testing strict regulatory * domain settings, combined with secondary driver regulatory domain * settings. The first radio will get a strict regulatory domain setting * using the first driver regulatory request and the second radio will use * non-strict settings using the second driver regulatory request. All * other devices should follow the intersection created between the * first two. * @HWSIM_REGTEST_ALL: Used for testing every possible mix. You will need * at least 6 radios for a complete test. We will test in this order: * 1 - driver custom world regulatory domain * 2 - second custom world regulatory domain * 3 - first driver regulatory domain request * 4 - second driver regulatory domain request * 5 - strict regulatory domain settings using the third driver regulatory * domain request * 6 and on - should follow the intersection of the 3rd, 4rth and 5th radio * regulatory requests. * * These are the different values you can use for the regtest * module parameter. This is useful to help test world roaming * and the driver regulatory_hint() call and combinations of these. * If you want to do specific alpha2 regulatory domain tests simply * use the userspace regulatory request as that will be respected as * well without the need of this module parameter. This is designed * only for testing the driver regulatory request, world roaming * and all possible combinations.
*/ enum hwsim_regtest {
HWSIM_REGTEST_DISABLED = 0,
HWSIM_REGTEST_DRIVER_REG_FOLLOW = 1,
HWSIM_REGTEST_DRIVER_REG_ALL = 2,
HWSIM_REGTEST_DIFF_COUNTRY = 3,
HWSIM_REGTEST_WORLD_ROAM = 4,
HWSIM_REGTEST_CUSTOM_WORLD = 5,
HWSIM_REGTEST_CUSTOM_WORLD_2 = 6,
HWSIM_REGTEST_STRICT_FOLLOW = 7,
HWSIM_REGTEST_STRICT_ALL = 8,
HWSIM_REGTEST_STRICT_AND_DRIVER_REG = 9,
HWSIM_REGTEST_ALL = 10,
};
/* Set to one of the HWSIM_REGTEST_* values above */ staticint regtest = HWSIM_REGTEST_DISABLED;
module_param(regtest, int, 0444);
MODULE_PARM_DESC(regtest, "The type of regulatory test we want to run");
err = nla_parse_deprecated(tb, QCA_WLAN_VENDOR_ATTR_MAX, data,
data_len, hwsim_vendor_test_policy, NULL); if (err) return err; if (!tb[QCA_WLAN_VENDOR_ATTR_TEST]) return -EINVAL;
val = nla_get_u32(tb[QCA_WLAN_VENDOR_ATTR_TEST]);
wiphy_dbg(wiphy, "%s: test=%u\n", __func__, val);
/* Send a vendor event as a test. Note that this would not normally be * done within a command handler, but rather, based on some other * trigger. For simplicity, this command is used to trigger the event * here. * * event_idx = 0 (index in mac80211_hwsim_vendor_commands)
*/
skb = cfg80211_vendor_event_alloc(wiphy, wdev, 100, 0, GFP_KERNEL); if (skb) { /* skb_put() or nla_put() will fill up data within * NL80211_ATTR_VENDOR_DATA.
*/
/* Add vendor data */
nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_TEST, val + 1);
/* Send the event - this will call nla_nest_end() */
cfg80211_vendor_event(skb, GFP_KERNEL);
}
/* Send a response to the command */
skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, 10); if (!skb) return -ENOMEM;
/* skb_put() or nla_put() will fill up data within * NL80211_ATTR_VENDOR_DATA
*/
nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_TEST, val + 2);
atomic_t pending_cookie; struct sk_buff_head pending; /* packets pending */ /* * Only radios in the same group can communicate together (the * channel has to match too). Each bit represents a group. A * radio can be in more than one group.
*/
u64 group;
/* group shared by radios created in the same netns */ int netgroup; /* wmediumd portid responsible for netgroup of this radio */
u32 wmediumd;
/* difference between this hw's clock and the real clock, in usecs */
s64 tsf_offset;
s64 bcn_delta; /* absolute beacon transmission time. Used to cover up "tx" delay. */
u64 abs_bcn_ts;
/* RSSI in rx status of the receiver */ int rx_rssi;
/* only used when pmsr capability is supplied */ struct cfg80211_pmsr_capabilities pmsr_capa; struct cfg80211_pmsr_request *pmsr_request; struct wireless_dev *pmsr_request_wdev;
out_free:
spin_unlock_irqrestore(&hwsim_virtio_lock, flags);
nlmsg_free(skb); return err;
} #else /* cause a linker error if this ends up being needed */ externint hwsim_tx_virtio(struct mac80211_hwsim_data *data, struct sk_buff *skb); #define hwsim_virtio_enabled false #endif
staticint hwsim_get_chanwidth(enum nl80211_chan_width bw)
{ switch (bw) { case NL80211_CHAN_WIDTH_20_NOHT: case NL80211_CHAN_WIDTH_20: return 20; case NL80211_CHAN_WIDTH_40: return 40; case NL80211_CHAN_WIDTH_80: return 80; case NL80211_CHAN_WIDTH_80P80: case NL80211_CHAN_WIDTH_160: return 160; case NL80211_CHAN_WIDTH_320: return 320; case NL80211_CHAN_WIDTH_5: return 5; case NL80211_CHAN_WIDTH_10: return 10; case NL80211_CHAN_WIDTH_1: return 1; case NL80211_CHAN_WIDTH_2: return 2; case NL80211_CHAN_WIDTH_4: return 4; case NL80211_CHAN_WIDTH_8: return 8; case NL80211_CHAN_WIDTH_16: return 16;
}
staticbool hwsim_ps_rx_ok(struct mac80211_hwsim_data *data, struct sk_buff *skb)
{ switch (data->ps) { case PS_DISABLED: returntrue; case PS_ENABLED: returnfalse; case PS_AUTO_POLL: /* TODO: accept (some) Beacons by default and other frames only
* if pending PS-Poll has been sent */ returntrue; case PS_MANUAL_POLL: /* Allow unicast frames to own address if there is a pending
* PS-Poll */ if (data->ps_poll_pending &&
mac80211_hwsim_addr_match(data, skb->data + 4)) {
data->ps_poll_pending = false; returntrue;
} returnfalse;
}
returntrue;
}
staticint hwsim_unicast_netgroup(struct mac80211_hwsim_data *data, struct sk_buff *skb, int portid)
{ struct net *net; bool found = false; int res = -ENOENT;
rcu_read_lock();
for_each_net_rcu(net) { if (data->netgroup == hwsim_net_get_netgroup(net)) {
res = genlmsg_unicast(net, skb, portid);
found = true; break;
}
}
rcu_read_unlock();
staticinline u16 trans_tx_rate_flags_ieee2hwsim(struct ieee80211_tx_rate *rate)
{
u16 result = 0;
if (rate->flags & IEEE80211_TX_RC_USE_RTS_CTS)
result |= MAC80211_HWSIM_TX_RC_USE_RTS_CTS; if (rate->flags & IEEE80211_TX_RC_USE_CTS_PROTECT)
result |= MAC80211_HWSIM_TX_RC_USE_CTS_PROTECT; if (rate->flags & IEEE80211_TX_RC_USE_SHORT_PREAMBLE)
result |= MAC80211_HWSIM_TX_RC_USE_SHORT_PREAMBLE; if (rate->flags & IEEE80211_TX_RC_MCS)
result |= MAC80211_HWSIM_TX_RC_MCS; if (rate->flags & IEEE80211_TX_RC_GREEN_FIELD)
result |= MAC80211_HWSIM_TX_RC_GREEN_FIELD; if (rate->flags & IEEE80211_TX_RC_40_MHZ_WIDTH)
result |= MAC80211_HWSIM_TX_RC_40_MHZ_WIDTH; if (rate->flags & IEEE80211_TX_RC_DUP_DATA)
result |= MAC80211_HWSIM_TX_RC_DUP_DATA; if (rate->flags & IEEE80211_TX_RC_SHORT_GI)
result |= MAC80211_HWSIM_TX_RC_SHORT_GI; if (rate->flags & IEEE80211_TX_RC_VHT_MCS)
result |= MAC80211_HWSIM_TX_RC_VHT_MCS; if (rate->flags & IEEE80211_TX_RC_80_MHZ_WIDTH)
result |= MAC80211_HWSIM_TX_RC_80_MHZ_WIDTH; if (rate->flags & IEEE80211_TX_RC_160_MHZ_WIDTH)
result |= MAC80211_HWSIM_TX_RC_160_MHZ_WIDTH;
if (data->ps != PS_DISABLED)
hdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_PM); /* If the queue contains MAX_QUEUE skb's drop some */ if (skb_queue_len(&data->pending) >= MAX_QUEUE) { /* Dropping until WARN_QUEUE level */ while (skb_queue_len(&data->pending) >= WARN_QUEUE) {
ieee80211_free_txskb(hw, skb_dequeue(&data->pending));
data->tx_dropped++;
}
}
skb = genlmsg_new(GENLMSG_DEFAULT_SIZE, GFP_ATOMIC); if (skb == NULL) goto nla_put_failure;
msg_head = genlmsg_put(skb, 0, 0, &hwsim_genl_family, 0,
HWSIM_CMD_FRAME); if (msg_head == NULL) {
pr_debug("mac80211_hwsim: problem with msg_head\n"); goto nla_put_failure;
}
if (nla_put(skb, HWSIM_ATTR_ADDR_TRANSMITTER,
ETH_ALEN, data->addresses[1].addr)) goto nla_put_failure;
/* We get the skb->data */ if (nla_put(skb, HWSIM_ATTR_FRAME, my_skb->len, my_skb->data)) goto nla_put_failure;
/* We get the flags for this transmission, and we translate them to
wmediumd flags */
if (info->flags & IEEE80211_TX_CTL_REQ_TX_STATUS)
hwsim_flags |= HWSIM_TX_CTL_REQ_TX_STATUS;
if (info->flags & IEEE80211_TX_CTL_NO_ACK)
hwsim_flags |= HWSIM_TX_CTL_NO_ACK;
if (nla_put_u32(skb, HWSIM_ATTR_FLAGS, hwsim_flags)) goto nla_put_failure;
if (nla_put_u32(skb, HWSIM_ATTR_FREQ, channel->center_freq)) goto nla_put_failure;
/* We get the tx control (rate and retries) info*/
for (i = 0; i < IEEE80211_TX_MAX_RATES; i++) {
tx_attempts[i].idx = info->status.rates[i].idx;
tx_attempts_flags[i].idx = info->status.rates[i].idx;
tx_attempts[i].count = info->status.rates[i].count;
tx_attempts_flags[i].flags =
trans_tx_rate_flags_ieee2hwsim(
&info->status.rates[i]);
}
if (nla_put(skb, HWSIM_ATTR_TX_INFO, sizeof(struct hwsim_tx_rate)*IEEE80211_TX_MAX_RATES,
tx_attempts)) goto nla_put_failure;
if (nla_put(skb, HWSIM_ATTR_TX_INFO_FLAGS, sizeof(struct hwsim_tx_rate_flag) * IEEE80211_TX_MAX_RATES,
tx_attempts_flags)) goto nla_put_failure;
/* We create a cookie to identify this skb */
cookie = atomic_inc_return(&data->pending_cookie);
info->rate_driver_data[0] = (void *)cookie; if (nla_put_u64_64bit(skb, HWSIM_ATTR_COOKIE, cookie, HWSIM_ATTR_PAD)) goto nla_put_failure;
genlmsg_end(skb, msg_head);
if (hwsim_virtio_enabled) { if (hwsim_tx_virtio(data, skb)) goto err_free_txskb;
} else { if (hwsim_unicast_netgroup(data, skb, dst_portid)) goto err_free_txskb;
}
for (i = 0; i < ARRAY_SIZE(vif->link_conf); i++) { struct ieee80211_bss_conf *conf; struct ieee80211_chanctx_conf *chanctx;
conf = rcu_dereference(vif->link_conf[i]); if (!conf) continue;
chanctx = rcu_dereference(conf->chanctx_conf); if (!chanctx) continue;
if (!hwsim_chans_compat(data->channel, chanctx->def.chan)) continue;
data->receive = true; return;
}
}
staticvoid mac80211_hwsim_add_vendor_rtap(struct sk_buff *skb)
{ /* * To enable this code, #define the HWSIM_RADIOTAP_OUI, * e.g. like this: * #define HWSIM_RADIOTAP_OUI "\x02\x00\x00" * (but you should use a valid OUI, not that) * * If anyone wants to 'donate' a radiotap OUI/subns code * please send a patch removing this #ifdef and changing * the values accordingly.
*/ #ifdef HWSIM_RADIOTAP_OUI struct ieee80211_radiotap_vendor_tlv *rtap; staticconstchar vendor_data[8] = "ABCDEFGH";
// Make sure no padding is needed
BUILD_BUG_ON(sizeof(vendor_data) % 4); /* this is last radiotap info before the mac header, so * skb_reset_mac_header for mac8022 to know the end of * the radiotap TLV/beginning of the 802.11 header
*/
skb_reset_mac_header(skb);
/* * Note that this code requires the headroom in the SKB * that was allocated earlier.
*/
rtap = skb_push(skb, sizeof(*rtap) + sizeof(vendor_data));
if (data->ps != PS_DISABLED)
hdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_PM);
/* release the skb's source info */
skb_orphan(skb);
skb_dst_drop(skb);
skb->mark = 0;
skb_ext_reset(skb);
nf_reset_ct(skb);
/* * Get absolute mactime here so all HWs RX at the "same time", and * absolute TX time for beacon mactime so the timestamp matches. * Giving beacons a different mactime than non-beacons looks messy, but * it helps the Toffset be exact and a ~10us mactime discrepancy * probably doesn't really matter.
*/ if (ieee80211_is_beacon(hdr->frame_control) ||
ieee80211_is_probe_resp(hdr->frame_control)) {
rx_status.boottime_ns = ktime_get_boottime_ns();
now = data->abs_bcn_ts;
} else {
now = mac80211_hwsim_get_tsf_raw();
}
/* Copy skb to all enabled radios that are on the current frequency */
spin_lock(&hwsim_radio_lock);
list_for_each_entry(data2, &hwsim_radios, list) { struct sk_buff *nskb; struct tx_iter_data tx_iter_data = {
.receive = false,
.channel = chan,
};
if (data == data2) continue;
if (!data2->started || (data2->idle && !data2->tmp_chan) ||
!hwsim_ps_rx_ok(data2, skb)) continue;
if (!(data->group & data2->group)) continue;
if (data->netgroup != data2->netgroup) continue;
if (!hwsim_chans_compat(chan, data2->tmp_chan) &&
!hwsim_chans_compat(chan, data2->channel)) {
ieee80211_iterate_active_interfaces_atomic(
data2->hw, IEEE80211_IFACE_ITER_NORMAL,
mac80211_hwsim_tx_iter, &tx_iter_data); if (!tx_iter_data.receive) continue;
}
/* * reserve some space for our vendor and the normal * radiotap header, since we're copying anyway
*/ if (skb->len < PAGE_SIZE && paged_rx) { struct page *page = alloc_page(GFP_ATOMIC);
if (!page) continue;
nskb = dev_alloc_skb(128); if (!nskb) {
__free_page(page); continue;
}
if (unlikely(!bss_conf)) { /* if it's an MLO STA, it might have deactivated all * links temporarily - but we don't handle real PS in * this code yet, so just drop the frame in that case
*/
WARN(link != IEEE80211_LINK_UNSPECIFIED || !sta || !sta->mlo, "link:%d, sta:%pM, sta->mlo:%d\n",
link, sta ? sta->addr : NULL, sta ? sta->mlo : -1);
ieee80211_free_txskb(hw, skb); return;
}
/* Do address translations only between shared links. It is * possible that while an non-AP MLD station and an AP MLD * station have shared links, the frame is intended to be sent * on a link which is not shared (for example when sending a * probe response).
*/ if (sta && sta->mlo && link_sta) { /* address translation to link addresses on TX */
ether_addr_copy(hdr->addr1, link_sta->addr);
ether_addr_copy(hdr->addr2, bss_conf->addr); /* translate A3 only if it's the BSSID */ if (!ieee80211_has_tods(hdr->frame_control) &&
!ieee80211_has_fromds(hdr->frame_control)) { if (ether_addr_equal(hdr->addr3, sta->addr))
ether_addr_copy(hdr->addr3, link_sta->addr); elseif (ether_addr_equal(hdr->addr3, vif->addr))
ether_addr_copy(hdr->addr3, bss_conf->addr);
} /* no need to look at A4, if present it's SA */
}
if (vp->skip_beacons[link_conf->link_id]) {
vp->skip_beacons[link_conf->link_id]--;
dev_kfree_skb(skb); return;
}
info = IEEE80211_SKB_CB(skb); if (ieee80211_hw_check(hw, SUPPORTS_RC_TABLE))
ieee80211_get_tx_rates(vif, NULL, skb,
info->control.rates,
ARRAY_SIZE(info->control.rates));
--> --------------------
--> maximum size reached
--> --------------------
Messung V0.5
¤ 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.0.11Bemerkung:
(vorverarbeitet)
¤
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.