.. | .. |
---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-only |
---|
1 | 2 | /* |
---|
2 | 3 | * mac80211_hwsim - software simulator of 802.11 radio(s) for mac80211 |
---|
3 | 4 | * Copyright (c) 2008, Jouni Malinen <j@w1.fi> |
---|
4 | 5 | * Copyright (c) 2011, Javier Lopez <jlopex@gmail.com> |
---|
5 | 6 | * Copyright (c) 2016 - 2017 Intel Deutschland GmbH |
---|
6 | | - * |
---|
7 | | - * This program is free software; you can redistribute it and/or modify |
---|
8 | | - * it under the terms of the GNU General Public License version 2 as |
---|
9 | | - * published by the Free Software Foundation. |
---|
| 7 | + * Copyright (C) 2018 - 2020 Intel Corporation |
---|
10 | 8 | */ |
---|
11 | 9 | |
---|
12 | 10 | /* |
---|
.. | .. |
---|
35 | 33 | #include <net/netns/generic.h> |
---|
36 | 34 | #include <linux/rhashtable.h> |
---|
37 | 35 | #include <linux/nospec.h> |
---|
| 36 | +#include <linux/virtio.h> |
---|
| 37 | +#include <linux/virtio_ids.h> |
---|
| 38 | +#include <linux/virtio_config.h> |
---|
38 | 39 | #include "mac80211_hwsim.h" |
---|
39 | 40 | |
---|
40 | 41 | #define WARN_QUEUE 100 |
---|
.. | .. |
---|
63 | 64 | static bool support_p2p_device = true; |
---|
64 | 65 | module_param(support_p2p_device, bool, 0444); |
---|
65 | 66 | MODULE_PARM_DESC(support_p2p_device, "Support P2P-Device interface type"); |
---|
| 67 | + |
---|
| 68 | +static ushort mac_prefix; |
---|
| 69 | +module_param(mac_prefix, ushort, 0444); |
---|
| 70 | +MODULE_PARM_DESC(mac_prefix, "Second and third most significant octets in MAC"); |
---|
66 | 71 | |
---|
67 | 72 | /** |
---|
68 | 73 | * enum hwsim_regtest - the type of regulatory tests we offer |
---|
.. | .. |
---|
98 | 103 | * domain requests. The first radio will adhere to the first custom world |
---|
99 | 104 | * regulatory domain, the second one to the second custom world regulatory |
---|
100 | 105 | * domain. All other devices will world roam. |
---|
101 | | - * @HWSIM_REGTEST_STRICT_FOLLOW_: Used for testing strict regulatory domain |
---|
| 106 | + * @HWSIM_REGTEST_STRICT_FOLLOW: Used for testing strict regulatory domain |
---|
102 | 107 | * settings, only the first radio will send a regulatory domain request |
---|
103 | 108 | * and use strict settings. The rest of the radios are expected to follow. |
---|
104 | 109 | * @HWSIM_REGTEST_STRICT_ALL: Used for testing strict regulatory domain |
---|
.. | .. |
---|
150 | 155 | }; |
---|
151 | 156 | |
---|
152 | 157 | static const struct ieee80211_regdomain hwsim_world_regdom_custom_01 = { |
---|
153 | | - .n_reg_rules = 4, |
---|
| 158 | + .n_reg_rules = 5, |
---|
154 | 159 | .alpha2 = "99", |
---|
155 | 160 | .reg_rules = { |
---|
156 | 161 | REG_RULE(2412-10, 2462+10, 40, 0, 20, 0), |
---|
157 | 162 | REG_RULE(2484-10, 2484+10, 40, 0, 20, 0), |
---|
158 | 163 | REG_RULE(5150-10, 5240+10, 40, 0, 30, 0), |
---|
159 | 164 | REG_RULE(5745-10, 5825+10, 40, 0, 30, 0), |
---|
| 165 | + REG_RULE(5855-10, 5925+10, 40, 0, 33, 0), |
---|
160 | 166 | } |
---|
161 | 167 | }; |
---|
162 | 168 | |
---|
163 | 169 | static const struct ieee80211_regdomain hwsim_world_regdom_custom_02 = { |
---|
164 | | - .n_reg_rules = 2, |
---|
| 170 | + .n_reg_rules = 3, |
---|
165 | 171 | .alpha2 = "99", |
---|
166 | 172 | .reg_rules = { |
---|
167 | 173 | REG_RULE(2412-10, 2462+10, 40, 0, 20, 0), |
---|
168 | 174 | REG_RULE(5725-10, 5850+10, 40, 0, 30, |
---|
169 | 175 | NL80211_RRF_NO_IR), |
---|
| 176 | + REG_RULE(5855-10, 5925+10, 40, 0, 33, 0), |
---|
170 | 177 | } |
---|
171 | 178 | }; |
---|
172 | 179 | |
---|
.. | .. |
---|
300 | 307 | .band = NL80211_BAND_2GHZ, \ |
---|
301 | 308 | .center_freq = (_freq), \ |
---|
302 | 309 | .hw_value = (_freq), \ |
---|
303 | | - .max_power = 20, \ |
---|
304 | 310 | } |
---|
305 | 311 | |
---|
306 | 312 | #define CHAN5G(_freq) { \ |
---|
307 | 313 | .band = NL80211_BAND_5GHZ, \ |
---|
308 | 314 | .center_freq = (_freq), \ |
---|
309 | 315 | .hw_value = (_freq), \ |
---|
310 | | - .max_power = 20, \ |
---|
311 | 316 | } |
---|
312 | 317 | |
---|
313 | 318 | static const struct ieee80211_channel hwsim_channels_2ghz[] = { |
---|
.. | .. |
---|
356 | 361 | CHAN5G(5805), /* Channel 161 */ |
---|
357 | 362 | CHAN5G(5825), /* Channel 165 */ |
---|
358 | 363 | CHAN5G(5845), /* Channel 169 */ |
---|
| 364 | + |
---|
| 365 | + CHAN5G(5855), /* Channel 171 */ |
---|
| 366 | + CHAN5G(5860), /* Channel 172 */ |
---|
| 367 | + CHAN5G(5865), /* Channel 173 */ |
---|
| 368 | + CHAN5G(5870), /* Channel 174 */ |
---|
| 369 | + |
---|
| 370 | + CHAN5G(5875), /* Channel 175 */ |
---|
| 371 | + CHAN5G(5880), /* Channel 176 */ |
---|
| 372 | + CHAN5G(5885), /* Channel 177 */ |
---|
| 373 | + CHAN5G(5890), /* Channel 178 */ |
---|
| 374 | + CHAN5G(5895), /* Channel 179 */ |
---|
| 375 | + CHAN5G(5900), /* Channel 180 */ |
---|
| 376 | + CHAN5G(5905), /* Channel 181 */ |
---|
| 377 | + |
---|
| 378 | + CHAN5G(5910), /* Channel 182 */ |
---|
| 379 | + CHAN5G(5915), /* Channel 183 */ |
---|
| 380 | + CHAN5G(5920), /* Channel 184 */ |
---|
| 381 | + CHAN5G(5925), /* Channel 185 */ |
---|
359 | 382 | }; |
---|
| 383 | + |
---|
| 384 | +#define NUM_S1G_CHANS_US 51 |
---|
| 385 | +static struct ieee80211_channel hwsim_channels_s1g[NUM_S1G_CHANS_US]; |
---|
| 386 | + |
---|
| 387 | +static const struct ieee80211_sta_s1g_cap hwsim_s1g_cap = { |
---|
| 388 | + .s1g = true, |
---|
| 389 | + .cap = { S1G_CAP0_SGI_1MHZ | S1G_CAP0_SGI_2MHZ, |
---|
| 390 | + 0, |
---|
| 391 | + 0, |
---|
| 392 | + S1G_CAP3_MAX_MPDU_LEN, |
---|
| 393 | + 0, |
---|
| 394 | + S1G_CAP5_AMPDU, |
---|
| 395 | + 0, |
---|
| 396 | + S1G_CAP7_DUP_1MHZ, |
---|
| 397 | + S1G_CAP8_TWT_RESPOND | S1G_CAP8_TWT_REQUEST, |
---|
| 398 | + 0}, |
---|
| 399 | + .nss_mcs = { 0xfc | 1, /* MCS 7 for 1 SS */ |
---|
| 400 | + /* RX Highest Supported Long GI Data Rate 0:7 */ |
---|
| 401 | + 0, |
---|
| 402 | + /* RX Highest Supported Long GI Data Rate 0:7 */ |
---|
| 403 | + /* TX S1G MCS Map 0:6 */ |
---|
| 404 | + 0xfa, |
---|
| 405 | + /* TX S1G MCS Map :7 */ |
---|
| 406 | + /* TX Highest Supported Long GI Data Rate 0:6 */ |
---|
| 407 | + 0x80, |
---|
| 408 | + /* TX Highest Supported Long GI Data Rate 7:8 */ |
---|
| 409 | + /* Rx Single spatial stream and S1G-MCS Map for 1MHz */ |
---|
| 410 | + /* Tx Single spatial stream and S1G-MCS Map for 1MHz */ |
---|
| 411 | + 0 }, |
---|
| 412 | +}; |
---|
| 413 | + |
---|
| 414 | +static void hwsim_init_s1g_channels(struct ieee80211_channel *channels) |
---|
| 415 | +{ |
---|
| 416 | + int ch, freq; |
---|
| 417 | + |
---|
| 418 | + for (ch = 0; ch < NUM_S1G_CHANS_US; ch++) { |
---|
| 419 | + freq = 902000 + (ch + 1) * 500; |
---|
| 420 | + channels[ch].band = NL80211_BAND_S1GHZ; |
---|
| 421 | + channels[ch].center_freq = KHZ_TO_MHZ(freq); |
---|
| 422 | + channels[ch].freq_offset = freq % 1000; |
---|
| 423 | + channels[ch].hw_value = ch + 1; |
---|
| 424 | + } |
---|
| 425 | +} |
---|
360 | 426 | |
---|
361 | 427 | static const struct ieee80211_rate hwsim_rates[] = { |
---|
362 | 428 | { .bitrate = 10 }, |
---|
.. | .. |
---|
371 | 437 | { .bitrate = 360 }, |
---|
372 | 438 | { .bitrate = 480 }, |
---|
373 | 439 | { .bitrate = 540 } |
---|
| 440 | +}; |
---|
| 441 | + |
---|
| 442 | +static const u32 hwsim_ciphers[] = { |
---|
| 443 | + WLAN_CIPHER_SUITE_WEP40, |
---|
| 444 | + WLAN_CIPHER_SUITE_WEP104, |
---|
| 445 | + WLAN_CIPHER_SUITE_TKIP, |
---|
| 446 | + WLAN_CIPHER_SUITE_CCMP, |
---|
| 447 | + WLAN_CIPHER_SUITE_CCMP_256, |
---|
| 448 | + WLAN_CIPHER_SUITE_GCMP, |
---|
| 449 | + WLAN_CIPHER_SUITE_GCMP_256, |
---|
| 450 | + WLAN_CIPHER_SUITE_AES_CMAC, |
---|
| 451 | + WLAN_CIPHER_SUITE_BIP_CMAC_256, |
---|
| 452 | + WLAN_CIPHER_SUITE_BIP_GMAC_128, |
---|
| 453 | + WLAN_CIPHER_SUITE_BIP_GMAC_256, |
---|
374 | 454 | }; |
---|
375 | 455 | |
---|
376 | 456 | #define OUI_QCA 0x001374 |
---|
.. | .. |
---|
394 | 474 | int err; |
---|
395 | 475 | u32 val; |
---|
396 | 476 | |
---|
397 | | - err = nla_parse(tb, QCA_WLAN_VENDOR_ATTR_MAX, data, data_len, |
---|
398 | | - hwsim_vendor_test_policy, NULL); |
---|
| 477 | + err = nla_parse_deprecated(tb, QCA_WLAN_VENDOR_ATTR_MAX, data, |
---|
| 478 | + data_len, hwsim_vendor_test_policy, NULL); |
---|
399 | 479 | if (err) |
---|
400 | 480 | return err; |
---|
401 | 481 | if (!tb[QCA_WLAN_VENDOR_ATTR_TEST]) |
---|
.. | .. |
---|
442 | 522 | .subcmd = QCA_NL80211_SUBCMD_TEST }, |
---|
443 | 523 | .flags = WIPHY_VENDOR_CMD_NEED_NETDEV, |
---|
444 | 524 | .doit = mac80211_hwsim_vendor_cmd_test, |
---|
| 525 | + .policy = hwsim_vendor_test_policy, |
---|
| 526 | + .maxattr = QCA_WLAN_VENDOR_ATTR_MAX, |
---|
445 | 527 | } |
---|
446 | 528 | }; |
---|
447 | 529 | |
---|
.. | .. |
---|
450 | 532 | { .vendor_id = OUI_QCA, .subcmd = 1 }, |
---|
451 | 533 | }; |
---|
452 | 534 | |
---|
453 | | -static const struct ieee80211_iface_limit hwsim_if_limits[] = { |
---|
454 | | - { .max = 1, .types = BIT(NL80211_IFTYPE_ADHOC) }, |
---|
455 | | - { .max = 2048, .types = BIT(NL80211_IFTYPE_STATION) | |
---|
456 | | - BIT(NL80211_IFTYPE_P2P_CLIENT) | |
---|
457 | | -#ifdef CONFIG_MAC80211_MESH |
---|
458 | | - BIT(NL80211_IFTYPE_MESH_POINT) | |
---|
459 | | -#endif |
---|
460 | | - BIT(NL80211_IFTYPE_AP) | |
---|
461 | | - BIT(NL80211_IFTYPE_P2P_GO) }, |
---|
462 | | - /* must be last, see hwsim_if_comb */ |
---|
463 | | - { .max = 1, .types = BIT(NL80211_IFTYPE_P2P_DEVICE) } |
---|
464 | | -}; |
---|
465 | | - |
---|
466 | | -static const struct ieee80211_iface_combination hwsim_if_comb[] = { |
---|
467 | | - { |
---|
468 | | - .limits = hwsim_if_limits, |
---|
469 | | - /* remove the last entry which is P2P_DEVICE */ |
---|
470 | | - .n_limits = ARRAY_SIZE(hwsim_if_limits) - 1, |
---|
471 | | - .max_interfaces = 2048, |
---|
472 | | - .num_different_channels = 1, |
---|
473 | | - .radar_detect_widths = BIT(NL80211_CHAN_WIDTH_20_NOHT) | |
---|
474 | | - BIT(NL80211_CHAN_WIDTH_20) | |
---|
475 | | - BIT(NL80211_CHAN_WIDTH_40) | |
---|
476 | | - BIT(NL80211_CHAN_WIDTH_80) | |
---|
477 | | - BIT(NL80211_CHAN_WIDTH_160), |
---|
478 | | - }, |
---|
479 | | -}; |
---|
480 | | - |
---|
481 | | -static const struct ieee80211_iface_combination hwsim_if_comb_p2p_dev[] = { |
---|
482 | | - { |
---|
483 | | - .limits = hwsim_if_limits, |
---|
484 | | - .n_limits = ARRAY_SIZE(hwsim_if_limits), |
---|
485 | | - .max_interfaces = 2048, |
---|
486 | | - .num_different_channels = 1, |
---|
487 | | - .radar_detect_widths = BIT(NL80211_CHAN_WIDTH_20_NOHT) | |
---|
488 | | - BIT(NL80211_CHAN_WIDTH_20) | |
---|
489 | | - BIT(NL80211_CHAN_WIDTH_40) | |
---|
490 | | - BIT(NL80211_CHAN_WIDTH_80) | |
---|
491 | | - BIT(NL80211_CHAN_WIDTH_160), |
---|
492 | | - }, |
---|
493 | | -}; |
---|
494 | | - |
---|
495 | 535 | static spinlock_t hwsim_radio_lock; |
---|
496 | 536 | static LIST_HEAD(hwsim_radios); |
---|
497 | | -static struct workqueue_struct *hwsim_wq; |
---|
498 | 537 | static struct rhashtable hwsim_radios_rht; |
---|
499 | 538 | static int hwsim_radio_idx; |
---|
500 | 539 | static int hwsim_radios_generation = 1; |
---|
.. | .. |
---|
513 | 552 | struct ieee80211_supported_band bands[NUM_NL80211_BANDS]; |
---|
514 | 553 | struct ieee80211_channel channels_2ghz[ARRAY_SIZE(hwsim_channels_2ghz)]; |
---|
515 | 554 | struct ieee80211_channel channels_5ghz[ARRAY_SIZE(hwsim_channels_5ghz)]; |
---|
| 555 | + struct ieee80211_channel channels_s1g[ARRAY_SIZE(hwsim_channels_s1g)]; |
---|
516 | 556 | struct ieee80211_rate rates[ARRAY_SIZE(hwsim_rates)]; |
---|
517 | 557 | struct ieee80211_iface_combination if_combination; |
---|
| 558 | + struct ieee80211_iface_limit if_limits[3]; |
---|
| 559 | + int n_if_limits; |
---|
| 560 | + |
---|
| 561 | + u32 ciphers[ARRAY_SIZE(hwsim_ciphers)]; |
---|
518 | 562 | |
---|
519 | 563 | struct mac_address addresses[2]; |
---|
| 564 | + struct ieee80211_chanctx_conf *chanctx; |
---|
520 | 565 | int channels, idx; |
---|
521 | 566 | bool use_chanctx; |
---|
522 | 567 | bool destroy_on_close; |
---|
.. | .. |
---|
545 | 590 | unsigned int rx_filter; |
---|
546 | 591 | bool started, idle, scanning; |
---|
547 | 592 | struct mutex mutex; |
---|
548 | | - struct tasklet_hrtimer beacon_timer; |
---|
| 593 | + struct hrtimer beacon_timer; |
---|
549 | 594 | enum ps_mode { |
---|
550 | 595 | PS_DISABLED, PS_ENABLED, PS_AUTO_POLL, PS_MANUAL_POLL |
---|
551 | 596 | } ps; |
---|
552 | 597 | bool ps_poll_pending; |
---|
553 | 598 | struct dentry *debugfs; |
---|
554 | 599 | |
---|
555 | | - uintptr_t pending_cookie; |
---|
| 600 | + atomic_t pending_cookie; |
---|
556 | 601 | struct sk_buff_head pending; /* packets pending */ |
---|
557 | 602 | /* |
---|
558 | 603 | * Only radios in the same group can communicate together (the |
---|
.. | .. |
---|
620 | 665 | /* MAC80211_HWSIM netlink policy */ |
---|
621 | 666 | |
---|
622 | 667 | static const struct nla_policy hwsim_genl_policy[HWSIM_ATTR_MAX + 1] = { |
---|
623 | | - [HWSIM_ATTR_ADDR_RECEIVER] = { .type = NLA_UNSPEC, .len = ETH_ALEN }, |
---|
624 | | - [HWSIM_ATTR_ADDR_TRANSMITTER] = { .type = NLA_UNSPEC, .len = ETH_ALEN }, |
---|
| 668 | + [HWSIM_ATTR_ADDR_RECEIVER] = NLA_POLICY_ETH_ADDR_COMPAT, |
---|
| 669 | + [HWSIM_ATTR_ADDR_TRANSMITTER] = NLA_POLICY_ETH_ADDR_COMPAT, |
---|
625 | 670 | [HWSIM_ATTR_FRAME] = { .type = NLA_BINARY, |
---|
626 | 671 | .len = IEEE80211_MAX_DATA_LEN }, |
---|
627 | 672 | [HWSIM_ATTR_FLAGS] = { .type = NLA_U32 }, |
---|
628 | 673 | [HWSIM_ATTR_RX_RATE] = { .type = NLA_U32 }, |
---|
629 | 674 | [HWSIM_ATTR_SIGNAL] = { .type = NLA_U32 }, |
---|
630 | | - [HWSIM_ATTR_TX_INFO] = { .type = NLA_UNSPEC, |
---|
| 675 | + [HWSIM_ATTR_TX_INFO] = { .type = NLA_BINARY, |
---|
631 | 676 | .len = IEEE80211_TX_MAX_RATES * |
---|
632 | 677 | sizeof(struct hwsim_tx_rate)}, |
---|
633 | 678 | [HWSIM_ATTR_COOKIE] = { .type = NLA_U64 }, |
---|
.. | .. |
---|
637 | 682 | [HWSIM_ATTR_REG_CUSTOM_REG] = { .type = NLA_U32 }, |
---|
638 | 683 | [HWSIM_ATTR_REG_STRICT_REG] = { .type = NLA_FLAG }, |
---|
639 | 684 | [HWSIM_ATTR_SUPPORT_P2P_DEVICE] = { .type = NLA_FLAG }, |
---|
| 685 | + [HWSIM_ATTR_USE_CHANCTX] = { .type = NLA_FLAG }, |
---|
640 | 686 | [HWSIM_ATTR_DESTROY_RADIO_ON_CLOSE] = { .type = NLA_FLAG }, |
---|
641 | 687 | [HWSIM_ATTR_RADIO_NAME] = { .type = NLA_STRING }, |
---|
642 | 688 | [HWSIM_ATTR_NO_VIF] = { .type = NLA_FLAG }, |
---|
643 | 689 | [HWSIM_ATTR_FREQ] = { .type = NLA_U32 }, |
---|
644 | | - [HWSIM_ATTR_PERM_ADDR] = { .type = NLA_UNSPEC, .len = ETH_ALEN }, |
---|
| 690 | + [HWSIM_ATTR_TX_INFO_FLAGS] = { .type = NLA_BINARY }, |
---|
| 691 | + [HWSIM_ATTR_PERM_ADDR] = NLA_POLICY_ETH_ADDR_COMPAT, |
---|
| 692 | + [HWSIM_ATTR_IFTYPE_SUPPORT] = { .type = NLA_U32 }, |
---|
| 693 | + [HWSIM_ATTR_CIPHER_SUPPORT] = { .type = NLA_BINARY }, |
---|
645 | 694 | }; |
---|
| 695 | + |
---|
| 696 | +#if IS_REACHABLE(CONFIG_VIRTIO) |
---|
| 697 | + |
---|
| 698 | +/* MAC80211_HWSIM virtio queues */ |
---|
| 699 | +static struct virtqueue *hwsim_vqs[HWSIM_NUM_VQS]; |
---|
| 700 | +static bool hwsim_virtio_enabled; |
---|
| 701 | +static spinlock_t hwsim_virtio_lock; |
---|
| 702 | + |
---|
| 703 | +static void hwsim_virtio_rx_work(struct work_struct *work); |
---|
| 704 | +static DECLARE_WORK(hwsim_virtio_rx, hwsim_virtio_rx_work); |
---|
| 705 | + |
---|
| 706 | +static int hwsim_tx_virtio(struct mac80211_hwsim_data *data, |
---|
| 707 | + struct sk_buff *skb) |
---|
| 708 | +{ |
---|
| 709 | + struct scatterlist sg[1]; |
---|
| 710 | + unsigned long flags; |
---|
| 711 | + int err; |
---|
| 712 | + |
---|
| 713 | + spin_lock_irqsave(&hwsim_virtio_lock, flags); |
---|
| 714 | + if (!hwsim_virtio_enabled) { |
---|
| 715 | + err = -ENODEV; |
---|
| 716 | + goto out_free; |
---|
| 717 | + } |
---|
| 718 | + |
---|
| 719 | + sg_init_one(sg, skb->head, skb_end_offset(skb)); |
---|
| 720 | + err = virtqueue_add_outbuf(hwsim_vqs[HWSIM_VQ_TX], sg, 1, skb, |
---|
| 721 | + GFP_ATOMIC); |
---|
| 722 | + if (err) |
---|
| 723 | + goto out_free; |
---|
| 724 | + virtqueue_kick(hwsim_vqs[HWSIM_VQ_TX]); |
---|
| 725 | + spin_unlock_irqrestore(&hwsim_virtio_lock, flags); |
---|
| 726 | + return 0; |
---|
| 727 | + |
---|
| 728 | +out_free: |
---|
| 729 | + spin_unlock_irqrestore(&hwsim_virtio_lock, flags); |
---|
| 730 | + nlmsg_free(skb); |
---|
| 731 | + return err; |
---|
| 732 | +} |
---|
| 733 | +#else |
---|
| 734 | +/* cause a linker error if this ends up being needed */ |
---|
| 735 | +extern int hwsim_tx_virtio(struct mac80211_hwsim_data *data, |
---|
| 736 | + struct sk_buff *skb); |
---|
| 737 | +#define hwsim_virtio_enabled false |
---|
| 738 | +#endif |
---|
646 | 739 | |
---|
647 | 740 | static void mac80211_hwsim_tx_frame(struct ieee80211_hw *hw, |
---|
648 | 741 | struct sk_buff *skb, |
---|
.. | .. |
---|
686 | 779 | struct hwsim_vif_priv *vp = (void *)vif->drv_priv; |
---|
687 | 780 | struct sk_buff *skb; |
---|
688 | 781 | struct ieee80211_hdr *hdr; |
---|
| 782 | + struct ieee80211_tx_info *cb; |
---|
689 | 783 | |
---|
690 | 784 | if (!vp->assoc) |
---|
691 | 785 | return; |
---|
.. | .. |
---|
706 | 800 | memcpy(hdr->addr1, vp->bssid, ETH_ALEN); |
---|
707 | 801 | memcpy(hdr->addr2, mac, ETH_ALEN); |
---|
708 | 802 | memcpy(hdr->addr3, vp->bssid, ETH_ALEN); |
---|
| 803 | + |
---|
| 804 | + cb = IEEE80211_SKB_CB(skb); |
---|
| 805 | + cb->control.rates[0].count = 1; |
---|
| 806 | + cb->control.rates[1].idx = -1; |
---|
709 | 807 | |
---|
710 | 808 | rcu_read_lock(); |
---|
711 | 809 | mac80211_hwsim_tx_frame(data->hw, skb, |
---|
.. | .. |
---|
772 | 870 | return 0; |
---|
773 | 871 | } |
---|
774 | 872 | |
---|
775 | | -DEFINE_SIMPLE_ATTRIBUTE(hwsim_fops_ps, hwsim_fops_ps_read, hwsim_fops_ps_write, |
---|
776 | | - "%llu\n"); |
---|
| 873 | +DEFINE_DEBUGFS_ATTRIBUTE(hwsim_fops_ps, hwsim_fops_ps_read, hwsim_fops_ps_write, |
---|
| 874 | + "%llu\n"); |
---|
777 | 875 | |
---|
778 | 876 | static int hwsim_write_simulate_radar(void *dat, u64 val) |
---|
779 | 877 | { |
---|
.. | .. |
---|
784 | 882 | return 0; |
---|
785 | 883 | } |
---|
786 | 884 | |
---|
787 | | -DEFINE_SIMPLE_ATTRIBUTE(hwsim_simulate_radar, NULL, |
---|
788 | | - hwsim_write_simulate_radar, "%llu\n"); |
---|
| 885 | +DEFINE_DEBUGFS_ATTRIBUTE(hwsim_simulate_radar, NULL, |
---|
| 886 | + hwsim_write_simulate_radar, "%llu\n"); |
---|
789 | 887 | |
---|
790 | 888 | static int hwsim_fops_group_read(void *dat, u64 *val) |
---|
791 | 889 | { |
---|
.. | .. |
---|
801 | 899 | return 0; |
---|
802 | 900 | } |
---|
803 | 901 | |
---|
804 | | -DEFINE_SIMPLE_ATTRIBUTE(hwsim_fops_group, |
---|
805 | | - hwsim_fops_group_read, hwsim_fops_group_write, |
---|
806 | | - "%llx\n"); |
---|
| 902 | +DEFINE_DEBUGFS_ATTRIBUTE(hwsim_fops_group, |
---|
| 903 | + hwsim_fops_group_read, hwsim_fops_group_write, |
---|
| 904 | + "%llx\n"); |
---|
807 | 905 | |
---|
808 | 906 | static netdev_tx_t hwsim_mon_xmit(struct sk_buff *skb, |
---|
809 | 907 | struct net_device *dev) |
---|
.. | .. |
---|
856 | 954 | struct mac80211_hwsim_data *data = hw->priv; |
---|
857 | 955 | struct sk_buff *skb; |
---|
858 | 956 | struct hwsim_radiotap_hdr *hdr; |
---|
859 | | - u16 flags; |
---|
| 957 | + u16 flags, bitrate; |
---|
860 | 958 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx_skb); |
---|
861 | 959 | struct ieee80211_rate *txrate = ieee80211_get_tx_rate(hw, info); |
---|
862 | 960 | |
---|
863 | | - if (WARN_ON(!txrate)) |
---|
864 | | - return; |
---|
| 961 | + if (!txrate) |
---|
| 962 | + bitrate = 0; |
---|
| 963 | + else |
---|
| 964 | + bitrate = txrate->bitrate; |
---|
865 | 965 | |
---|
866 | 966 | if (!netif_running(hwsim_mon)) |
---|
867 | 967 | return; |
---|
.. | .. |
---|
880 | 980 | (1 << IEEE80211_RADIOTAP_CHANNEL)); |
---|
881 | 981 | hdr->rt_tsft = __mac80211_hwsim_get_tsf(data); |
---|
882 | 982 | hdr->rt_flags = 0; |
---|
883 | | - hdr->rt_rate = txrate->bitrate / 5; |
---|
| 983 | + hdr->rt_rate = bitrate / 5; |
---|
884 | 984 | hdr->rt_channel = cpu_to_le16(chan->center_freq); |
---|
885 | 985 | flags = IEEE80211_CHAN_2GHZ; |
---|
886 | | - if (txrate->flags & IEEE80211_RATE_ERP_G) |
---|
| 986 | + if (txrate && txrate->flags & IEEE80211_RATE_ERP_G) |
---|
887 | 987 | flags |= IEEE80211_CHAN_OFDM; |
---|
888 | 988 | else |
---|
889 | 989 | flags |= IEEE80211_CHAN_CCK; |
---|
.. | .. |
---|
1024 | 1124 | return res; |
---|
1025 | 1125 | } |
---|
1026 | 1126 | |
---|
| 1127 | +static void mac80211_hwsim_config_mac_nl(struct ieee80211_hw *hw, |
---|
| 1128 | + const u8 *addr, bool add) |
---|
| 1129 | +{ |
---|
| 1130 | + struct mac80211_hwsim_data *data = hw->priv; |
---|
| 1131 | + u32 _portid = READ_ONCE(data->wmediumd); |
---|
| 1132 | + struct sk_buff *skb; |
---|
| 1133 | + void *msg_head; |
---|
| 1134 | + |
---|
| 1135 | + if (!_portid && !hwsim_virtio_enabled) |
---|
| 1136 | + return; |
---|
| 1137 | + |
---|
| 1138 | + skb = genlmsg_new(GENLMSG_DEFAULT_SIZE, GFP_ATOMIC); |
---|
| 1139 | + if (!skb) |
---|
| 1140 | + return; |
---|
| 1141 | + |
---|
| 1142 | + msg_head = genlmsg_put(skb, 0, 0, &hwsim_genl_family, 0, |
---|
| 1143 | + add ? HWSIM_CMD_ADD_MAC_ADDR : |
---|
| 1144 | + HWSIM_CMD_DEL_MAC_ADDR); |
---|
| 1145 | + if (!msg_head) { |
---|
| 1146 | + pr_debug("mac80211_hwsim: problem with msg_head\n"); |
---|
| 1147 | + goto nla_put_failure; |
---|
| 1148 | + } |
---|
| 1149 | + |
---|
| 1150 | + if (nla_put(skb, HWSIM_ATTR_ADDR_TRANSMITTER, |
---|
| 1151 | + ETH_ALEN, data->addresses[1].addr)) |
---|
| 1152 | + goto nla_put_failure; |
---|
| 1153 | + |
---|
| 1154 | + if (nla_put(skb, HWSIM_ATTR_ADDR_RECEIVER, ETH_ALEN, addr)) |
---|
| 1155 | + goto nla_put_failure; |
---|
| 1156 | + |
---|
| 1157 | + genlmsg_end(skb, msg_head); |
---|
| 1158 | + |
---|
| 1159 | + if (hwsim_virtio_enabled) |
---|
| 1160 | + hwsim_tx_virtio(data, skb); |
---|
| 1161 | + else |
---|
| 1162 | + hwsim_unicast_netgroup(data, skb, _portid); |
---|
| 1163 | + return; |
---|
| 1164 | +nla_put_failure: |
---|
| 1165 | + nlmsg_free(skb); |
---|
| 1166 | +} |
---|
| 1167 | + |
---|
1027 | 1168 | static inline u16 trans_tx_rate_flags_ieee2hwsim(struct ieee80211_tx_rate *rate) |
---|
1028 | 1169 | { |
---|
1029 | 1170 | u16 result = 0; |
---|
.. | .. |
---|
1056 | 1197 | |
---|
1057 | 1198 | static void mac80211_hwsim_tx_frame_nl(struct ieee80211_hw *hw, |
---|
1058 | 1199 | struct sk_buff *my_skb, |
---|
1059 | | - int dst_portid) |
---|
| 1200 | + int dst_portid, |
---|
| 1201 | + struct ieee80211_channel *channel) |
---|
1060 | 1202 | { |
---|
1061 | 1203 | struct sk_buff *skb; |
---|
1062 | 1204 | struct mac80211_hwsim_data *data = hw->priv; |
---|
.. | .. |
---|
1111 | 1253 | if (nla_put_u32(skb, HWSIM_ATTR_FLAGS, hwsim_flags)) |
---|
1112 | 1254 | goto nla_put_failure; |
---|
1113 | 1255 | |
---|
1114 | | - if (nla_put_u32(skb, HWSIM_ATTR_FREQ, data->channel->center_freq)) |
---|
| 1256 | + if (nla_put_u32(skb, HWSIM_ATTR_FREQ, channel->center_freq)) |
---|
1115 | 1257 | goto nla_put_failure; |
---|
1116 | 1258 | |
---|
1117 | 1259 | /* We get the tx control (rate and retries) info*/ |
---|
.. | .. |
---|
1136 | 1278 | goto nla_put_failure; |
---|
1137 | 1279 | |
---|
1138 | 1280 | /* We create a cookie to identify this skb */ |
---|
1139 | | - data->pending_cookie++; |
---|
1140 | | - cookie = data->pending_cookie; |
---|
| 1281 | + cookie = atomic_inc_return(&data->pending_cookie); |
---|
1141 | 1282 | info->rate_driver_data[0] = (void *)cookie; |
---|
1142 | 1283 | if (nla_put_u64_64bit(skb, HWSIM_ATTR_COOKIE, cookie, HWSIM_ATTR_PAD)) |
---|
1143 | 1284 | goto nla_put_failure; |
---|
1144 | 1285 | |
---|
1145 | 1286 | genlmsg_end(skb, msg_head); |
---|
1146 | | - if (hwsim_unicast_netgroup(data, skb, dst_portid)) |
---|
1147 | | - goto err_free_txskb; |
---|
| 1287 | + |
---|
| 1288 | + if (hwsim_virtio_enabled) { |
---|
| 1289 | + if (hwsim_tx_virtio(data, skb)) |
---|
| 1290 | + goto err_free_txskb; |
---|
| 1291 | + } else { |
---|
| 1292 | + if (hwsim_unicast_netgroup(data, skb, dst_portid)) |
---|
| 1293 | + goto err_free_txskb; |
---|
| 1294 | + } |
---|
1148 | 1295 | |
---|
1149 | 1296 | /* Enqueue the packet */ |
---|
1150 | 1297 | skb_queue_tail(&data->pending, my_skb); |
---|
.. | .. |
---|
1250 | 1397 | memset(&rx_status, 0, sizeof(rx_status)); |
---|
1251 | 1398 | rx_status.flag |= RX_FLAG_MACTIME_START; |
---|
1252 | 1399 | rx_status.freq = chan->center_freq; |
---|
| 1400 | + rx_status.freq_offset = chan->freq_offset ? 1 : 0; |
---|
1253 | 1401 | rx_status.band = chan->band; |
---|
1254 | 1402 | if (info->control.rates[0].flags & IEEE80211_TX_RC_VHT_MCS) { |
---|
1255 | 1403 | rx_status.rate_idx = |
---|
.. | .. |
---|
1284 | 1432 | skb_orphan(skb); |
---|
1285 | 1433 | skb_dst_drop(skb); |
---|
1286 | 1434 | skb->mark = 0; |
---|
1287 | | - secpath_reset(skb); |
---|
1288 | | - nf_reset(skb); |
---|
| 1435 | + skb_ext_reset(skb); |
---|
| 1436 | + nf_reset_ct(skb); |
---|
1289 | 1437 | |
---|
1290 | 1438 | /* |
---|
1291 | 1439 | * Get absolute mactime here so all HWs RX at the "same time", and |
---|
.. | .. |
---|
1295 | 1443 | * probably doesn't really matter. |
---|
1296 | 1444 | */ |
---|
1297 | 1445 | if (ieee80211_is_beacon(hdr->frame_control) || |
---|
1298 | | - ieee80211_is_probe_resp(hdr->frame_control)) |
---|
| 1446 | + ieee80211_is_probe_resp(hdr->frame_control)) { |
---|
| 1447 | + rx_status.boottime_ns = ktime_get_boottime_ns(); |
---|
1299 | 1448 | now = data->abs_bcn_ts; |
---|
1300 | | - else |
---|
| 1449 | + } else { |
---|
1301 | 1450 | now = mac80211_hwsim_get_tsf_raw(); |
---|
| 1451 | + } |
---|
1302 | 1452 | |
---|
1303 | 1453 | /* Copy skb to all enabled radios that are on the current frequency */ |
---|
1304 | 1454 | spin_lock(&hwsim_radio_lock); |
---|
.. | .. |
---|
1429 | 1579 | /* fake header transmission time */ |
---|
1430 | 1580 | struct ieee80211_mgmt *mgmt; |
---|
1431 | 1581 | struct ieee80211_rate *txrate; |
---|
| 1582 | + /* TODO: get MCS */ |
---|
| 1583 | + int bitrate = 100; |
---|
1432 | 1584 | u64 ts; |
---|
1433 | 1585 | |
---|
1434 | 1586 | mgmt = (struct ieee80211_mgmt *)skb->data; |
---|
1435 | 1587 | txrate = ieee80211_get_tx_rate(hw, txi); |
---|
| 1588 | + if (txrate) |
---|
| 1589 | + bitrate = txrate->bitrate; |
---|
1436 | 1590 | ts = mac80211_hwsim_get_tsf_raw(); |
---|
1437 | 1591 | mgmt->u.probe_resp.timestamp = |
---|
1438 | 1592 | cpu_to_le64(ts + data->tsf_offset + |
---|
1439 | | - 24 * 8 * 10 / txrate->bitrate); |
---|
| 1593 | + 24 * 8 * 10 / bitrate); |
---|
1440 | 1594 | } |
---|
1441 | 1595 | |
---|
1442 | 1596 | mac80211_hwsim_monitor_rx(hw, skb, channel); |
---|
.. | .. |
---|
1444 | 1598 | /* wmediumd mode check */ |
---|
1445 | 1599 | _portid = READ_ONCE(data->wmediumd); |
---|
1446 | 1600 | |
---|
1447 | | - if (_portid) |
---|
1448 | | - return mac80211_hwsim_tx_frame_nl(hw, skb, _portid); |
---|
| 1601 | + if (_portid || hwsim_virtio_enabled) |
---|
| 1602 | + return mac80211_hwsim_tx_frame_nl(hw, skb, _portid, channel); |
---|
1449 | 1603 | |
---|
1450 | 1604 | /* NO wmediumd detected, perfect medium simulation */ |
---|
1451 | 1605 | data->tx_pkts++; |
---|
.. | .. |
---|
1479 | 1633 | static void mac80211_hwsim_stop(struct ieee80211_hw *hw) |
---|
1480 | 1634 | { |
---|
1481 | 1635 | struct mac80211_hwsim_data *data = hw->priv; |
---|
| 1636 | + |
---|
1482 | 1637 | data->started = false; |
---|
1483 | | - tasklet_hrtimer_cancel(&data->beacon_timer); |
---|
| 1638 | + hrtimer_cancel(&data->beacon_timer); |
---|
| 1639 | + |
---|
| 1640 | + while (!skb_queue_empty(&data->pending)) |
---|
| 1641 | + ieee80211_free_txskb(hw, skb_dequeue(&data->pending)); |
---|
| 1642 | + |
---|
1484 | 1643 | wiphy_dbg(hw->wiphy, "%s\n", __func__); |
---|
1485 | 1644 | } |
---|
1486 | 1645 | |
---|
.. | .. |
---|
1492 | 1651 | __func__, ieee80211_vif_type_p2p(vif), |
---|
1493 | 1652 | vif->addr); |
---|
1494 | 1653 | hwsim_set_magic(vif); |
---|
| 1654 | + |
---|
| 1655 | + if (vif->type != NL80211_IFTYPE_MONITOR) |
---|
| 1656 | + mac80211_hwsim_config_mac_nl(hw, vif->addr, true); |
---|
1495 | 1657 | |
---|
1496 | 1658 | vif->cab_queue = 0; |
---|
1497 | 1659 | vif->hw_queue[IEEE80211_AC_VO] = 0; |
---|
.. | .. |
---|
1532 | 1694 | vif->addr); |
---|
1533 | 1695 | hwsim_check_magic(vif); |
---|
1534 | 1696 | hwsim_clear_magic(vif); |
---|
| 1697 | + if (vif->type != NL80211_IFTYPE_MONITOR) |
---|
| 1698 | + mac80211_hwsim_config_mac_nl(hw, vif->addr, false); |
---|
1535 | 1699 | } |
---|
1536 | 1700 | |
---|
1537 | 1701 | static void mac80211_hwsim_tx_frame(struct ieee80211_hw *hw, |
---|
.. | .. |
---|
1550 | 1714 | |
---|
1551 | 1715 | mac80211_hwsim_monitor_rx(hw, skb, chan); |
---|
1552 | 1716 | |
---|
1553 | | - if (_pid) |
---|
1554 | | - return mac80211_hwsim_tx_frame_nl(hw, skb, _pid); |
---|
| 1717 | + if (_pid || hwsim_virtio_enabled) |
---|
| 1718 | + return mac80211_hwsim_tx_frame_nl(hw, skb, _pid, chan); |
---|
1555 | 1719 | |
---|
1556 | 1720 | mac80211_hwsim_tx_frame_no_nl(hw, skb, chan); |
---|
1557 | 1721 | dev_kfree_skb(skb); |
---|
.. | .. |
---|
1566 | 1730 | struct ieee80211_rate *txrate; |
---|
1567 | 1731 | struct ieee80211_mgmt *mgmt; |
---|
1568 | 1732 | struct sk_buff *skb; |
---|
| 1733 | + /* TODO: get MCS */ |
---|
| 1734 | + int bitrate = 100; |
---|
1569 | 1735 | |
---|
1570 | 1736 | hwsim_check_magic(vif); |
---|
1571 | 1737 | |
---|
1572 | 1738 | if (vif->type != NL80211_IFTYPE_AP && |
---|
1573 | 1739 | vif->type != NL80211_IFTYPE_MESH_POINT && |
---|
1574 | | - vif->type != NL80211_IFTYPE_ADHOC) |
---|
| 1740 | + vif->type != NL80211_IFTYPE_ADHOC && |
---|
| 1741 | + vif->type != NL80211_IFTYPE_OCB) |
---|
1575 | 1742 | return; |
---|
1576 | 1743 | |
---|
1577 | 1744 | skb = ieee80211_beacon_get(hw, vif); |
---|
.. | .. |
---|
1584 | 1751 | ARRAY_SIZE(info->control.rates)); |
---|
1585 | 1752 | |
---|
1586 | 1753 | txrate = ieee80211_get_tx_rate(hw, info); |
---|
| 1754 | + if (txrate) |
---|
| 1755 | + bitrate = txrate->bitrate; |
---|
1587 | 1756 | |
---|
1588 | 1757 | mgmt = (struct ieee80211_mgmt *) skb->data; |
---|
1589 | 1758 | /* fake header transmission time */ |
---|
1590 | 1759 | data->abs_bcn_ts = mac80211_hwsim_get_tsf_raw(); |
---|
1591 | | - mgmt->u.beacon.timestamp = cpu_to_le64(data->abs_bcn_ts + |
---|
1592 | | - data->tsf_offset + |
---|
1593 | | - 24 * 8 * 10 / txrate->bitrate); |
---|
| 1760 | + if (ieee80211_is_s1g_beacon(mgmt->frame_control)) { |
---|
| 1761 | + struct ieee80211_ext *ext = (void *) mgmt; |
---|
| 1762 | + |
---|
| 1763 | + ext->u.s1g_beacon.timestamp = cpu_to_le32(data->abs_bcn_ts + |
---|
| 1764 | + data->tsf_offset + |
---|
| 1765 | + 10 * 8 * 10 / |
---|
| 1766 | + bitrate); |
---|
| 1767 | + } else { |
---|
| 1768 | + mgmt->u.beacon.timestamp = cpu_to_le64(data->abs_bcn_ts + |
---|
| 1769 | + data->tsf_offset + |
---|
| 1770 | + 24 * 8 * 10 / |
---|
| 1771 | + bitrate); |
---|
| 1772 | + } |
---|
1594 | 1773 | |
---|
1595 | 1774 | mac80211_hwsim_tx_frame(hw, skb, |
---|
1596 | 1775 | rcu_dereference(vif->chanctx_conf)->def.chan); |
---|
1597 | 1776 | |
---|
1598 | | - if (vif->csa_active && ieee80211_csa_is_complete(vif)) |
---|
| 1777 | + while ((skb = ieee80211_get_buffered_bc(hw, vif)) != NULL) { |
---|
| 1778 | + mac80211_hwsim_tx_frame(hw, skb, |
---|
| 1779 | + rcu_dereference(vif->chanctx_conf)->def.chan); |
---|
| 1780 | + } |
---|
| 1781 | + |
---|
| 1782 | + if (vif->csa_active && ieee80211_beacon_cntdwn_is_complete(vif)) |
---|
1599 | 1783 | ieee80211_csa_finish(vif); |
---|
1600 | 1784 | } |
---|
1601 | 1785 | |
---|
.. | .. |
---|
1603 | 1787 | mac80211_hwsim_beacon(struct hrtimer *timer) |
---|
1604 | 1788 | { |
---|
1605 | 1789 | struct mac80211_hwsim_data *data = |
---|
1606 | | - container_of(timer, struct mac80211_hwsim_data, |
---|
1607 | | - beacon_timer.timer); |
---|
| 1790 | + container_of(timer, struct mac80211_hwsim_data, beacon_timer); |
---|
1608 | 1791 | struct ieee80211_hw *hw = data->hw; |
---|
1609 | 1792 | u64 bcn_int = data->beacon_int; |
---|
1610 | | - ktime_t next_bcn; |
---|
1611 | 1793 | |
---|
1612 | 1794 | if (!data->started) |
---|
1613 | | - goto out; |
---|
| 1795 | + return HRTIMER_NORESTART; |
---|
1614 | 1796 | |
---|
1615 | 1797 | ieee80211_iterate_active_interfaces_atomic( |
---|
1616 | 1798 | hw, IEEE80211_IFACE_ITER_NORMAL, |
---|
.. | .. |
---|
1621 | 1803 | bcn_int -= data->bcn_delta; |
---|
1622 | 1804 | data->bcn_delta = 0; |
---|
1623 | 1805 | } |
---|
1624 | | - |
---|
1625 | | - next_bcn = ktime_add(hrtimer_get_expires(timer), |
---|
1626 | | - ns_to_ktime(bcn_int * 1000)); |
---|
1627 | | - tasklet_hrtimer_start(&data->beacon_timer, next_bcn, HRTIMER_MODE_ABS); |
---|
1628 | | -out: |
---|
1629 | | - return HRTIMER_NORESTART; |
---|
| 1806 | + hrtimer_forward_now(&data->beacon_timer, |
---|
| 1807 | + ns_to_ktime(bcn_int * NSEC_PER_USEC)); |
---|
| 1808 | + return HRTIMER_RESTART; |
---|
1630 | 1809 | } |
---|
1631 | 1810 | |
---|
1632 | 1811 | static const char * const hwsim_chanwidths[] = { |
---|
| 1812 | + [NL80211_CHAN_WIDTH_5] = "ht5", |
---|
| 1813 | + [NL80211_CHAN_WIDTH_10] = "ht10", |
---|
1633 | 1814 | [NL80211_CHAN_WIDTH_20_NOHT] = "noht", |
---|
1634 | 1815 | [NL80211_CHAN_WIDTH_20] = "ht20", |
---|
1635 | 1816 | [NL80211_CHAN_WIDTH_40] = "ht40", |
---|
1636 | 1817 | [NL80211_CHAN_WIDTH_80] = "vht80", |
---|
1637 | 1818 | [NL80211_CHAN_WIDTH_80P80] = "vht80p80", |
---|
1638 | 1819 | [NL80211_CHAN_WIDTH_160] = "vht160", |
---|
| 1820 | + [NL80211_CHAN_WIDTH_1] = "1MHz", |
---|
| 1821 | + [NL80211_CHAN_WIDTH_2] = "2MHz", |
---|
| 1822 | + [NL80211_CHAN_WIDTH_4] = "4MHz", |
---|
| 1823 | + [NL80211_CHAN_WIDTH_8] = "8MHz", |
---|
| 1824 | + [NL80211_CHAN_WIDTH_16] = "16MHz", |
---|
1639 | 1825 | }; |
---|
1640 | 1826 | |
---|
1641 | 1827 | static int mac80211_hwsim_config(struct ieee80211_hw *hw, u32 changed) |
---|
.. | .. |
---|
1700 | 1886 | mutex_unlock(&data->mutex); |
---|
1701 | 1887 | |
---|
1702 | 1888 | if (!data->started || !data->beacon_int) |
---|
1703 | | - tasklet_hrtimer_cancel(&data->beacon_timer); |
---|
1704 | | - else if (!hrtimer_is_queued(&data->beacon_timer.timer)) { |
---|
| 1889 | + hrtimer_cancel(&data->beacon_timer); |
---|
| 1890 | + else if (!hrtimer_is_queued(&data->beacon_timer)) { |
---|
1705 | 1891 | u64 tsf = mac80211_hwsim_get_tsf(hw, NULL); |
---|
1706 | 1892 | u32 bcn_int = data->beacon_int; |
---|
1707 | 1893 | u64 until_tbtt = bcn_int - do_div(tsf, bcn_int); |
---|
1708 | 1894 | |
---|
1709 | | - tasklet_hrtimer_start(&data->beacon_timer, |
---|
1710 | | - ns_to_ktime(until_tbtt * 1000), |
---|
1711 | | - HRTIMER_MODE_REL); |
---|
| 1895 | + hrtimer_start(&data->beacon_timer, |
---|
| 1896 | + ns_to_ktime(until_tbtt * NSEC_PER_USEC), |
---|
| 1897 | + HRTIMER_MODE_REL_SOFT); |
---|
1712 | 1898 | } |
---|
1713 | 1899 | |
---|
1714 | 1900 | return 0; |
---|
.. | .. |
---|
1726 | 1912 | data->rx_filter = 0; |
---|
1727 | 1913 | if (*total_flags & FIF_ALLMULTI) |
---|
1728 | 1914 | data->rx_filter |= FIF_ALLMULTI; |
---|
| 1915 | + if (*total_flags & FIF_MCAST_ACTION) |
---|
| 1916 | + data->rx_filter |= FIF_MCAST_ACTION; |
---|
1729 | 1917 | |
---|
1730 | 1918 | *total_flags = data->rx_filter; |
---|
1731 | 1919 | } |
---|
.. | .. |
---|
1771 | 1959 | info->enable_beacon, info->beacon_int); |
---|
1772 | 1960 | vp->bcn_en = info->enable_beacon; |
---|
1773 | 1961 | if (data->started && |
---|
1774 | | - !hrtimer_is_queued(&data->beacon_timer.timer) && |
---|
| 1962 | + !hrtimer_is_queued(&data->beacon_timer) && |
---|
1775 | 1963 | info->enable_beacon) { |
---|
1776 | 1964 | u64 tsf, until_tbtt; |
---|
1777 | 1965 | u32 bcn_int; |
---|
.. | .. |
---|
1779 | 1967 | tsf = mac80211_hwsim_get_tsf(hw, vif); |
---|
1780 | 1968 | bcn_int = data->beacon_int; |
---|
1781 | 1969 | until_tbtt = bcn_int - do_div(tsf, bcn_int); |
---|
1782 | | - tasklet_hrtimer_start(&data->beacon_timer, |
---|
1783 | | - ns_to_ktime(until_tbtt * 1000), |
---|
1784 | | - HRTIMER_MODE_REL); |
---|
| 1970 | + |
---|
| 1971 | + hrtimer_start(&data->beacon_timer, |
---|
| 1972 | + ns_to_ktime(until_tbtt * NSEC_PER_USEC), |
---|
| 1973 | + HRTIMER_MODE_REL_SOFT); |
---|
1785 | 1974 | } else if (!info->enable_beacon) { |
---|
1786 | 1975 | unsigned int count = 0; |
---|
1787 | 1976 | ieee80211_iterate_active_interfaces_atomic( |
---|
.. | .. |
---|
1790 | 1979 | wiphy_dbg(hw->wiphy, " beaconing vifs remaining: %u", |
---|
1791 | 1980 | count); |
---|
1792 | 1981 | if (count == 0) { |
---|
1793 | | - tasklet_hrtimer_cancel(&data->beacon_timer); |
---|
| 1982 | + hrtimer_cancel(&data->beacon_timer); |
---|
1794 | 1983 | data->beacon_int = 0; |
---|
1795 | 1984 | } |
---|
1796 | 1985 | } |
---|
.. | .. |
---|
1956 | 2145 | struct sk_buff *skb; |
---|
1957 | 2146 | int err, ps; |
---|
1958 | 2147 | |
---|
1959 | | - err = nla_parse(tb, HWSIM_TM_ATTR_MAX, data, len, |
---|
1960 | | - hwsim_testmode_policy, NULL); |
---|
| 2148 | + err = nla_parse_deprecated(tb, HWSIM_TM_ATTR_MAX, data, len, |
---|
| 2149 | + hwsim_testmode_policy, NULL); |
---|
1961 | 2150 | if (err) |
---|
1962 | 2151 | return err; |
---|
1963 | 2152 | |
---|
.. | .. |
---|
2004 | 2193 | |
---|
2005 | 2194 | switch (action) { |
---|
2006 | 2195 | case IEEE80211_AMPDU_TX_START: |
---|
2007 | | - ieee80211_start_tx_ba_cb_irqsafe(vif, sta->addr, tid); |
---|
2008 | | - break; |
---|
| 2196 | + return IEEE80211_AMPDU_TX_START_IMMEDIATE; |
---|
2009 | 2197 | case IEEE80211_AMPDU_TX_STOP_CONT: |
---|
2010 | 2198 | case IEEE80211_AMPDU_TX_STOP_FLUSH: |
---|
2011 | 2199 | case IEEE80211_AMPDU_TX_STOP_FLUSH_CONT: |
---|
.. | .. |
---|
2049 | 2237 | hwsim->hw_scan_vif = NULL; |
---|
2050 | 2238 | hwsim->tmp_chan = NULL; |
---|
2051 | 2239 | mutex_unlock(&hwsim->mutex); |
---|
| 2240 | + mac80211_hwsim_config_mac_nl(hwsim->hw, hwsim->scan_addr, |
---|
| 2241 | + false); |
---|
2052 | 2242 | return; |
---|
2053 | 2243 | } |
---|
2054 | 2244 | |
---|
.. | .. |
---|
2082 | 2272 | if (req->ie_len) |
---|
2083 | 2273 | skb_put_data(probe, req->ie, req->ie_len); |
---|
2084 | 2274 | |
---|
| 2275 | + rcu_read_lock(); |
---|
| 2276 | + if (!ieee80211_tx_prepare_skb(hwsim->hw, |
---|
| 2277 | + hwsim->hw_scan_vif, |
---|
| 2278 | + probe, |
---|
| 2279 | + hwsim->tmp_chan->band, |
---|
| 2280 | + NULL)) { |
---|
| 2281 | + rcu_read_unlock(); |
---|
| 2282 | + kfree_skb(probe); |
---|
| 2283 | + continue; |
---|
| 2284 | + } |
---|
| 2285 | + |
---|
2085 | 2286 | local_bh_disable(); |
---|
2086 | 2287 | mac80211_hwsim_tx_frame(hwsim->hw, probe, |
---|
2087 | 2288 | hwsim->tmp_chan); |
---|
| 2289 | + rcu_read_unlock(); |
---|
2088 | 2290 | local_bh_enable(); |
---|
2089 | 2291 | } |
---|
2090 | 2292 | } |
---|
.. | .. |
---|
2122 | 2324 | memset(hwsim->survey_data, 0, sizeof(hwsim->survey_data)); |
---|
2123 | 2325 | mutex_unlock(&hwsim->mutex); |
---|
2124 | 2326 | |
---|
| 2327 | + mac80211_hwsim_config_mac_nl(hw, hwsim->scan_addr, true); |
---|
2125 | 2328 | wiphy_dbg(hw->wiphy, "hwsim hw_scan request\n"); |
---|
2126 | 2329 | |
---|
2127 | 2330 | ieee80211_queue_delayed_work(hwsim->hw, &hwsim->hw_scan, 0); |
---|
.. | .. |
---|
2165 | 2368 | pr_debug("hwsim sw_scan request, prepping stuff\n"); |
---|
2166 | 2369 | |
---|
2167 | 2370 | memcpy(hwsim->scan_addr, mac_addr, ETH_ALEN); |
---|
| 2371 | + mac80211_hwsim_config_mac_nl(hw, hwsim->scan_addr, true); |
---|
2168 | 2372 | hwsim->scanning = true; |
---|
2169 | 2373 | memset(hwsim->survey_data, 0, sizeof(hwsim->survey_data)); |
---|
2170 | 2374 | |
---|
.. | .. |
---|
2181 | 2385 | |
---|
2182 | 2386 | pr_debug("hwsim sw_scan_complete\n"); |
---|
2183 | 2387 | hwsim->scanning = false; |
---|
| 2388 | + mac80211_hwsim_config_mac_nl(hw, hwsim->scan_addr, false); |
---|
2184 | 2389 | eth_zero_addr(hwsim->scan_addr); |
---|
2185 | 2390 | |
---|
2186 | 2391 | mutex_unlock(&hwsim->mutex); |
---|
.. | .. |
---|
2241 | 2446 | return 0; |
---|
2242 | 2447 | } |
---|
2243 | 2448 | |
---|
2244 | | -static int mac80211_hwsim_croc(struct ieee80211_hw *hw) |
---|
| 2449 | +static int mac80211_hwsim_croc(struct ieee80211_hw *hw, |
---|
| 2450 | + struct ieee80211_vif *vif) |
---|
2245 | 2451 | { |
---|
2246 | 2452 | struct mac80211_hwsim_data *hwsim = hw->priv; |
---|
2247 | 2453 | |
---|
.. | .. |
---|
2260 | 2466 | static int mac80211_hwsim_add_chanctx(struct ieee80211_hw *hw, |
---|
2261 | 2467 | struct ieee80211_chanctx_conf *ctx) |
---|
2262 | 2468 | { |
---|
| 2469 | + struct mac80211_hwsim_data *hwsim = hw->priv; |
---|
| 2470 | + |
---|
| 2471 | + mutex_lock(&hwsim->mutex); |
---|
| 2472 | + hwsim->chanctx = ctx; |
---|
| 2473 | + mutex_unlock(&hwsim->mutex); |
---|
2263 | 2474 | hwsim_set_chanctx_magic(ctx); |
---|
2264 | 2475 | wiphy_dbg(hw->wiphy, |
---|
2265 | 2476 | "add channel context control: %d MHz/width: %d/cfreqs:%d/%d MHz\n", |
---|
.. | .. |
---|
2271 | 2482 | static void mac80211_hwsim_remove_chanctx(struct ieee80211_hw *hw, |
---|
2272 | 2483 | struct ieee80211_chanctx_conf *ctx) |
---|
2273 | 2484 | { |
---|
| 2485 | + struct mac80211_hwsim_data *hwsim = hw->priv; |
---|
| 2486 | + |
---|
| 2487 | + mutex_lock(&hwsim->mutex); |
---|
| 2488 | + hwsim->chanctx = NULL; |
---|
| 2489 | + mutex_unlock(&hwsim->mutex); |
---|
2274 | 2490 | wiphy_dbg(hw->wiphy, |
---|
2275 | 2491 | "remove channel context control: %d MHz/width: %d/cfreqs:%d/%d MHz\n", |
---|
2276 | 2492 | ctx->def.chan->center_freq, ctx->def.width, |
---|
.. | .. |
---|
2283 | 2499 | struct ieee80211_chanctx_conf *ctx, |
---|
2284 | 2500 | u32 changed) |
---|
2285 | 2501 | { |
---|
| 2502 | + struct mac80211_hwsim_data *hwsim = hw->priv; |
---|
| 2503 | + |
---|
| 2504 | + mutex_lock(&hwsim->mutex); |
---|
| 2505 | + hwsim->chanctx = ctx; |
---|
| 2506 | + mutex_unlock(&hwsim->mutex); |
---|
2286 | 2507 | hwsim_check_chanctx_magic(ctx); |
---|
2287 | 2508 | wiphy_dbg(hw->wiphy, |
---|
2288 | 2509 | "change channel context control: %d MHz/width: %d/cfreqs:%d/%d MHz\n", |
---|
.. | .. |
---|
2357 | 2578 | WARN_ON(i != MAC80211_HWSIM_SSTATS_LEN); |
---|
2358 | 2579 | } |
---|
2359 | 2580 | |
---|
| 2581 | +static int mac80211_hwsim_tx_last_beacon(struct ieee80211_hw *hw) |
---|
| 2582 | +{ |
---|
| 2583 | + return 1; |
---|
| 2584 | +} |
---|
| 2585 | + |
---|
2360 | 2586 | #define HWSIM_COMMON_OPS \ |
---|
2361 | 2587 | .tx = mac80211_hwsim_tx, \ |
---|
2362 | 2588 | .start = mac80211_hwsim_start, \ |
---|
.. | .. |
---|
2367 | 2593 | .config = mac80211_hwsim_config, \ |
---|
2368 | 2594 | .configure_filter = mac80211_hwsim_configure_filter, \ |
---|
2369 | 2595 | .bss_info_changed = mac80211_hwsim_bss_info_changed, \ |
---|
| 2596 | + .tx_last_beacon = mac80211_hwsim_tx_last_beacon, \ |
---|
2370 | 2597 | .sta_add = mac80211_hwsim_sta_add, \ |
---|
2371 | 2598 | .sta_remove = mac80211_hwsim_sta_remove, \ |
---|
2372 | 2599 | .sta_notify = mac80211_hwsim_sta_notify, \ |
---|
.. | .. |
---|
2414 | 2641 | const char *hwname; |
---|
2415 | 2642 | bool no_vif; |
---|
2416 | 2643 | const u8 *perm_addr; |
---|
| 2644 | + u32 iftypes; |
---|
| 2645 | + u32 *ciphers; |
---|
| 2646 | + u8 n_ciphers; |
---|
2417 | 2647 | }; |
---|
2418 | 2648 | |
---|
2419 | 2649 | static void hwsim_mcast_config_msg(struct sk_buff *mcast_skb, |
---|
.. | .. |
---|
2518 | 2748 | nlmsg_free(mcast_skb); |
---|
2519 | 2749 | } |
---|
2520 | 2750 | |
---|
2521 | | -static const struct ieee80211_sband_iftype_data he_capa_2ghz = { |
---|
2522 | | - /* TODO: should we support other types, e.g., P2P?*/ |
---|
2523 | | - .types_mask = BIT(NL80211_IFTYPE_STATION) | BIT(NL80211_IFTYPE_AP), |
---|
2524 | | - .he_cap = { |
---|
2525 | | - .has_he = true, |
---|
2526 | | - .he_cap_elem = { |
---|
2527 | | - .mac_cap_info[0] = |
---|
2528 | | - IEEE80211_HE_MAC_CAP0_HTC_HE, |
---|
2529 | | - .mac_cap_info[1] = |
---|
2530 | | - IEEE80211_HE_MAC_CAP1_TF_MAC_PAD_DUR_16US | |
---|
2531 | | - IEEE80211_HE_MAC_CAP1_MULTI_TID_AGG_QOS_8, |
---|
2532 | | - .mac_cap_info[2] = |
---|
2533 | | - IEEE80211_HE_MAC_CAP2_BSR | |
---|
2534 | | - IEEE80211_HE_MAC_CAP2_MU_CASCADING | |
---|
2535 | | - IEEE80211_HE_MAC_CAP2_ACK_EN, |
---|
2536 | | - .mac_cap_info[3] = |
---|
2537 | | - IEEE80211_HE_MAC_CAP3_GRP_ADDR_MULTI_STA_BA_DL_MU | |
---|
2538 | | - IEEE80211_HE_MAC_CAP3_OMI_CONTROL | |
---|
2539 | | - IEEE80211_HE_MAC_CAP3_MAX_A_AMPDU_LEN_EXP_VHT_2, |
---|
2540 | | - .mac_cap_info[4] = IEEE80211_HE_MAC_CAP4_AMDSU_IN_AMPDU, |
---|
2541 | | - .phy_cap_info[0] = |
---|
2542 | | - IEEE80211_HE_PHY_CAP0_DUAL_BAND, |
---|
2543 | | - .phy_cap_info[1] = |
---|
2544 | | - IEEE80211_HE_PHY_CAP1_PREAMBLE_PUNC_RX_MASK | |
---|
2545 | | - IEEE80211_HE_PHY_CAP1_DEVICE_CLASS_A | |
---|
2546 | | - IEEE80211_HE_PHY_CAP1_LDPC_CODING_IN_PAYLOAD | |
---|
2547 | | - IEEE80211_HE_PHY_CAP1_MIDAMBLE_RX_MAX_NSTS, |
---|
2548 | | - .phy_cap_info[2] = |
---|
2549 | | - IEEE80211_HE_PHY_CAP2_NDP_4x_LTF_AND_3_2US | |
---|
2550 | | - IEEE80211_HE_PHY_CAP2_STBC_TX_UNDER_80MHZ | |
---|
2551 | | - IEEE80211_HE_PHY_CAP2_STBC_RX_UNDER_80MHZ | |
---|
2552 | | - IEEE80211_HE_PHY_CAP2_UL_MU_FULL_MU_MIMO | |
---|
2553 | | - IEEE80211_HE_PHY_CAP2_UL_MU_PARTIAL_MU_MIMO, |
---|
| 2751 | +static const struct ieee80211_sband_iftype_data he_capa_2ghz[] = { |
---|
| 2752 | + { |
---|
| 2753 | + /* TODO: should we support other types, e.g., P2P?*/ |
---|
| 2754 | + .types_mask = BIT(NL80211_IFTYPE_STATION) | |
---|
| 2755 | + BIT(NL80211_IFTYPE_AP), |
---|
| 2756 | + .he_cap = { |
---|
| 2757 | + .has_he = true, |
---|
| 2758 | + .he_cap_elem = { |
---|
| 2759 | + .mac_cap_info[0] = |
---|
| 2760 | + IEEE80211_HE_MAC_CAP0_HTC_HE, |
---|
| 2761 | + .mac_cap_info[1] = |
---|
| 2762 | + IEEE80211_HE_MAC_CAP1_TF_MAC_PAD_DUR_16US | |
---|
| 2763 | + IEEE80211_HE_MAC_CAP1_MULTI_TID_AGG_RX_QOS_8, |
---|
| 2764 | + .mac_cap_info[2] = |
---|
| 2765 | + IEEE80211_HE_MAC_CAP2_BSR | |
---|
| 2766 | + IEEE80211_HE_MAC_CAP2_MU_CASCADING | |
---|
| 2767 | + IEEE80211_HE_MAC_CAP2_ACK_EN, |
---|
| 2768 | + .mac_cap_info[3] = |
---|
| 2769 | + IEEE80211_HE_MAC_CAP3_OMI_CONTROL | |
---|
| 2770 | + IEEE80211_HE_MAC_CAP3_MAX_AMPDU_LEN_EXP_VHT_2, |
---|
| 2771 | + .mac_cap_info[4] = IEEE80211_HE_MAC_CAP4_AMDSU_IN_AMPDU, |
---|
| 2772 | + .phy_cap_info[1] = |
---|
| 2773 | + IEEE80211_HE_PHY_CAP1_PREAMBLE_PUNC_RX_MASK | |
---|
| 2774 | + IEEE80211_HE_PHY_CAP1_DEVICE_CLASS_A | |
---|
| 2775 | + IEEE80211_HE_PHY_CAP1_LDPC_CODING_IN_PAYLOAD | |
---|
| 2776 | + IEEE80211_HE_PHY_CAP1_MIDAMBLE_RX_TX_MAX_NSTS, |
---|
| 2777 | + .phy_cap_info[2] = |
---|
| 2778 | + IEEE80211_HE_PHY_CAP2_NDP_4x_LTF_AND_3_2US | |
---|
| 2779 | + IEEE80211_HE_PHY_CAP2_STBC_TX_UNDER_80MHZ | |
---|
| 2780 | + IEEE80211_HE_PHY_CAP2_STBC_RX_UNDER_80MHZ | |
---|
| 2781 | + IEEE80211_HE_PHY_CAP2_UL_MU_FULL_MU_MIMO | |
---|
| 2782 | + IEEE80211_HE_PHY_CAP2_UL_MU_PARTIAL_MU_MIMO, |
---|
2554 | 2783 | |
---|
2555 | | - /* Leave all the other PHY capability bytes unset, as |
---|
2556 | | - * DCM, beam forming, RU and PPE threshold information |
---|
2557 | | - * are not supported |
---|
2558 | | - */ |
---|
2559 | | - }, |
---|
2560 | | - .he_mcs_nss_supp = { |
---|
2561 | | - .rx_mcs_80 = cpu_to_le16(0xfffa), |
---|
2562 | | - .tx_mcs_80 = cpu_to_le16(0xfffa), |
---|
2563 | | - .rx_mcs_160 = cpu_to_le16(0xffff), |
---|
2564 | | - .tx_mcs_160 = cpu_to_le16(0xffff), |
---|
2565 | | - .rx_mcs_80p80 = cpu_to_le16(0xffff), |
---|
2566 | | - .tx_mcs_80p80 = cpu_to_le16(0xffff), |
---|
| 2784 | + /* Leave all the other PHY capability bytes |
---|
| 2785 | + * unset, as DCM, beam forming, RU and PPE |
---|
| 2786 | + * threshold information are not supported |
---|
| 2787 | + */ |
---|
| 2788 | + }, |
---|
| 2789 | + .he_mcs_nss_supp = { |
---|
| 2790 | + .rx_mcs_80 = cpu_to_le16(0xfffa), |
---|
| 2791 | + .tx_mcs_80 = cpu_to_le16(0xfffa), |
---|
| 2792 | + .rx_mcs_160 = cpu_to_le16(0xffff), |
---|
| 2793 | + .tx_mcs_160 = cpu_to_le16(0xffff), |
---|
| 2794 | + .rx_mcs_80p80 = cpu_to_le16(0xffff), |
---|
| 2795 | + .tx_mcs_80p80 = cpu_to_le16(0xffff), |
---|
| 2796 | + }, |
---|
2567 | 2797 | }, |
---|
2568 | 2798 | }, |
---|
2569 | | -}; |
---|
| 2799 | +#ifdef CONFIG_MAC80211_MESH |
---|
| 2800 | + { |
---|
| 2801 | + /* TODO: should we support other types, e.g., IBSS?*/ |
---|
| 2802 | + .types_mask = BIT(NL80211_IFTYPE_MESH_POINT), |
---|
| 2803 | + .he_cap = { |
---|
| 2804 | + .has_he = true, |
---|
| 2805 | + .he_cap_elem = { |
---|
| 2806 | + .mac_cap_info[0] = |
---|
| 2807 | + IEEE80211_HE_MAC_CAP0_HTC_HE, |
---|
| 2808 | + .mac_cap_info[1] = |
---|
| 2809 | + IEEE80211_HE_MAC_CAP1_MULTI_TID_AGG_RX_QOS_8, |
---|
| 2810 | + .mac_cap_info[2] = |
---|
| 2811 | + IEEE80211_HE_MAC_CAP2_ACK_EN, |
---|
| 2812 | + .mac_cap_info[3] = |
---|
| 2813 | + IEEE80211_HE_MAC_CAP3_OMI_CONTROL | |
---|
| 2814 | + IEEE80211_HE_MAC_CAP3_MAX_AMPDU_LEN_EXP_VHT_2, |
---|
| 2815 | + .mac_cap_info[4] = IEEE80211_HE_MAC_CAP4_AMDSU_IN_AMPDU, |
---|
| 2816 | + .phy_cap_info[1] = |
---|
| 2817 | + IEEE80211_HE_PHY_CAP1_PREAMBLE_PUNC_RX_MASK | |
---|
| 2818 | + IEEE80211_HE_PHY_CAP1_DEVICE_CLASS_A | |
---|
| 2819 | + IEEE80211_HE_PHY_CAP1_LDPC_CODING_IN_PAYLOAD | |
---|
| 2820 | + IEEE80211_HE_PHY_CAP1_MIDAMBLE_RX_TX_MAX_NSTS, |
---|
| 2821 | + .phy_cap_info[2] = 0, |
---|
2570 | 2822 | |
---|
2571 | | -static const struct ieee80211_sband_iftype_data he_capa_5ghz = { |
---|
2572 | | - /* TODO: should we support other types, e.g., P2P?*/ |
---|
2573 | | - .types_mask = BIT(NL80211_IFTYPE_STATION) | BIT(NL80211_IFTYPE_AP), |
---|
2574 | | - .he_cap = { |
---|
2575 | | - .has_he = true, |
---|
2576 | | - .he_cap_elem = { |
---|
2577 | | - .mac_cap_info[0] = |
---|
2578 | | - IEEE80211_HE_MAC_CAP0_HTC_HE, |
---|
2579 | | - .mac_cap_info[1] = |
---|
2580 | | - IEEE80211_HE_MAC_CAP1_TF_MAC_PAD_DUR_16US | |
---|
2581 | | - IEEE80211_HE_MAC_CAP1_MULTI_TID_AGG_QOS_8, |
---|
2582 | | - .mac_cap_info[2] = |
---|
2583 | | - IEEE80211_HE_MAC_CAP2_BSR | |
---|
2584 | | - IEEE80211_HE_MAC_CAP2_MU_CASCADING | |
---|
2585 | | - IEEE80211_HE_MAC_CAP2_ACK_EN, |
---|
2586 | | - .mac_cap_info[3] = |
---|
2587 | | - IEEE80211_HE_MAC_CAP3_GRP_ADDR_MULTI_STA_BA_DL_MU | |
---|
2588 | | - IEEE80211_HE_MAC_CAP3_OMI_CONTROL | |
---|
2589 | | - IEEE80211_HE_MAC_CAP3_MAX_A_AMPDU_LEN_EXP_VHT_2, |
---|
2590 | | - .mac_cap_info[4] = IEEE80211_HE_MAC_CAP4_AMDSU_IN_AMPDU, |
---|
2591 | | - .phy_cap_info[0] = |
---|
2592 | | - IEEE80211_HE_PHY_CAP0_DUAL_BAND | |
---|
2593 | | - IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_40MHZ_80MHZ_IN_5G | |
---|
2594 | | - IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_160MHZ_IN_5G | |
---|
2595 | | - IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_80PLUS80_MHZ_IN_5G, |
---|
2596 | | - .phy_cap_info[1] = |
---|
2597 | | - IEEE80211_HE_PHY_CAP1_PREAMBLE_PUNC_RX_MASK | |
---|
2598 | | - IEEE80211_HE_PHY_CAP1_DEVICE_CLASS_A | |
---|
2599 | | - IEEE80211_HE_PHY_CAP1_LDPC_CODING_IN_PAYLOAD | |
---|
2600 | | - IEEE80211_HE_PHY_CAP1_MIDAMBLE_RX_MAX_NSTS, |
---|
2601 | | - .phy_cap_info[2] = |
---|
2602 | | - IEEE80211_HE_PHY_CAP2_NDP_4x_LTF_AND_3_2US | |
---|
2603 | | - IEEE80211_HE_PHY_CAP2_STBC_TX_UNDER_80MHZ | |
---|
2604 | | - IEEE80211_HE_PHY_CAP2_STBC_RX_UNDER_80MHZ | |
---|
2605 | | - IEEE80211_HE_PHY_CAP2_UL_MU_FULL_MU_MIMO | |
---|
2606 | | - IEEE80211_HE_PHY_CAP2_UL_MU_PARTIAL_MU_MIMO, |
---|
2607 | | - |
---|
2608 | | - /* Leave all the other PHY capability bytes unset, as |
---|
2609 | | - * DCM, beam forming, RU and PPE threshold information |
---|
2610 | | - * are not supported |
---|
2611 | | - */ |
---|
2612 | | - }, |
---|
2613 | | - .he_mcs_nss_supp = { |
---|
2614 | | - .rx_mcs_80 = cpu_to_le16(0xfffa), |
---|
2615 | | - .tx_mcs_80 = cpu_to_le16(0xfffa), |
---|
2616 | | - .rx_mcs_160 = cpu_to_le16(0xfffa), |
---|
2617 | | - .tx_mcs_160 = cpu_to_le16(0xfffa), |
---|
2618 | | - .rx_mcs_80p80 = cpu_to_le16(0xfffa), |
---|
2619 | | - .tx_mcs_80p80 = cpu_to_le16(0xfffa), |
---|
| 2823 | + /* Leave all the other PHY capability bytes |
---|
| 2824 | + * unset, as DCM, beam forming, RU and PPE |
---|
| 2825 | + * threshold information are not supported |
---|
| 2826 | + */ |
---|
| 2827 | + }, |
---|
| 2828 | + .he_mcs_nss_supp = { |
---|
| 2829 | + .rx_mcs_80 = cpu_to_le16(0xfffa), |
---|
| 2830 | + .tx_mcs_80 = cpu_to_le16(0xfffa), |
---|
| 2831 | + .rx_mcs_160 = cpu_to_le16(0xffff), |
---|
| 2832 | + .tx_mcs_160 = cpu_to_le16(0xffff), |
---|
| 2833 | + .rx_mcs_80p80 = cpu_to_le16(0xffff), |
---|
| 2834 | + .tx_mcs_80p80 = cpu_to_le16(0xffff), |
---|
| 2835 | + }, |
---|
2620 | 2836 | }, |
---|
2621 | 2837 | }, |
---|
| 2838 | +#endif |
---|
2622 | 2839 | }; |
---|
2623 | 2840 | |
---|
2624 | | -static void mac80211_hswim_he_capab(struct ieee80211_supported_band *sband) |
---|
| 2841 | +static const struct ieee80211_sband_iftype_data he_capa_5ghz[] = { |
---|
| 2842 | + { |
---|
| 2843 | + /* TODO: should we support other types, e.g., P2P?*/ |
---|
| 2844 | + .types_mask = BIT(NL80211_IFTYPE_STATION) | |
---|
| 2845 | + BIT(NL80211_IFTYPE_AP), |
---|
| 2846 | + .he_cap = { |
---|
| 2847 | + .has_he = true, |
---|
| 2848 | + .he_cap_elem = { |
---|
| 2849 | + .mac_cap_info[0] = |
---|
| 2850 | + IEEE80211_HE_MAC_CAP0_HTC_HE, |
---|
| 2851 | + .mac_cap_info[1] = |
---|
| 2852 | + IEEE80211_HE_MAC_CAP1_TF_MAC_PAD_DUR_16US | |
---|
| 2853 | + IEEE80211_HE_MAC_CAP1_MULTI_TID_AGG_RX_QOS_8, |
---|
| 2854 | + .mac_cap_info[2] = |
---|
| 2855 | + IEEE80211_HE_MAC_CAP2_BSR | |
---|
| 2856 | + IEEE80211_HE_MAC_CAP2_MU_CASCADING | |
---|
| 2857 | + IEEE80211_HE_MAC_CAP2_ACK_EN, |
---|
| 2858 | + .mac_cap_info[3] = |
---|
| 2859 | + IEEE80211_HE_MAC_CAP3_OMI_CONTROL | |
---|
| 2860 | + IEEE80211_HE_MAC_CAP3_MAX_AMPDU_LEN_EXP_VHT_2, |
---|
| 2861 | + .mac_cap_info[4] = IEEE80211_HE_MAC_CAP4_AMDSU_IN_AMPDU, |
---|
| 2862 | + .phy_cap_info[0] = |
---|
| 2863 | + IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_40MHZ_80MHZ_IN_5G | |
---|
| 2864 | + IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_160MHZ_IN_5G | |
---|
| 2865 | + IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_80PLUS80_MHZ_IN_5G, |
---|
| 2866 | + .phy_cap_info[1] = |
---|
| 2867 | + IEEE80211_HE_PHY_CAP1_PREAMBLE_PUNC_RX_MASK | |
---|
| 2868 | + IEEE80211_HE_PHY_CAP1_DEVICE_CLASS_A | |
---|
| 2869 | + IEEE80211_HE_PHY_CAP1_LDPC_CODING_IN_PAYLOAD | |
---|
| 2870 | + IEEE80211_HE_PHY_CAP1_MIDAMBLE_RX_TX_MAX_NSTS, |
---|
| 2871 | + .phy_cap_info[2] = |
---|
| 2872 | + IEEE80211_HE_PHY_CAP2_NDP_4x_LTF_AND_3_2US | |
---|
| 2873 | + IEEE80211_HE_PHY_CAP2_STBC_TX_UNDER_80MHZ | |
---|
| 2874 | + IEEE80211_HE_PHY_CAP2_STBC_RX_UNDER_80MHZ | |
---|
| 2875 | + IEEE80211_HE_PHY_CAP2_UL_MU_FULL_MU_MIMO | |
---|
| 2876 | + IEEE80211_HE_PHY_CAP2_UL_MU_PARTIAL_MU_MIMO, |
---|
| 2877 | + |
---|
| 2878 | + /* Leave all the other PHY capability bytes |
---|
| 2879 | + * unset, as DCM, beam forming, RU and PPE |
---|
| 2880 | + * threshold information are not supported |
---|
| 2881 | + */ |
---|
| 2882 | + }, |
---|
| 2883 | + .he_mcs_nss_supp = { |
---|
| 2884 | + .rx_mcs_80 = cpu_to_le16(0xfffa), |
---|
| 2885 | + .tx_mcs_80 = cpu_to_le16(0xfffa), |
---|
| 2886 | + .rx_mcs_160 = cpu_to_le16(0xfffa), |
---|
| 2887 | + .tx_mcs_160 = cpu_to_le16(0xfffa), |
---|
| 2888 | + .rx_mcs_80p80 = cpu_to_le16(0xfffa), |
---|
| 2889 | + .tx_mcs_80p80 = cpu_to_le16(0xfffa), |
---|
| 2890 | + }, |
---|
| 2891 | + }, |
---|
| 2892 | + }, |
---|
| 2893 | +#ifdef CONFIG_MAC80211_MESH |
---|
| 2894 | + { |
---|
| 2895 | + /* TODO: should we support other types, e.g., IBSS?*/ |
---|
| 2896 | + .types_mask = BIT(NL80211_IFTYPE_MESH_POINT), |
---|
| 2897 | + .he_cap = { |
---|
| 2898 | + .has_he = true, |
---|
| 2899 | + .he_cap_elem = { |
---|
| 2900 | + .mac_cap_info[0] = |
---|
| 2901 | + IEEE80211_HE_MAC_CAP0_HTC_HE, |
---|
| 2902 | + .mac_cap_info[1] = |
---|
| 2903 | + IEEE80211_HE_MAC_CAP1_MULTI_TID_AGG_RX_QOS_8, |
---|
| 2904 | + .mac_cap_info[2] = |
---|
| 2905 | + IEEE80211_HE_MAC_CAP2_ACK_EN, |
---|
| 2906 | + .mac_cap_info[3] = |
---|
| 2907 | + IEEE80211_HE_MAC_CAP3_OMI_CONTROL | |
---|
| 2908 | + IEEE80211_HE_MAC_CAP3_MAX_AMPDU_LEN_EXP_VHT_2, |
---|
| 2909 | + .mac_cap_info[4] = IEEE80211_HE_MAC_CAP4_AMDSU_IN_AMPDU, |
---|
| 2910 | + .phy_cap_info[0] = |
---|
| 2911 | + IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_40MHZ_80MHZ_IN_5G | |
---|
| 2912 | + IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_160MHZ_IN_5G | |
---|
| 2913 | + IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_80PLUS80_MHZ_IN_5G, |
---|
| 2914 | + .phy_cap_info[1] = |
---|
| 2915 | + IEEE80211_HE_PHY_CAP1_PREAMBLE_PUNC_RX_MASK | |
---|
| 2916 | + IEEE80211_HE_PHY_CAP1_DEVICE_CLASS_A | |
---|
| 2917 | + IEEE80211_HE_PHY_CAP1_LDPC_CODING_IN_PAYLOAD | |
---|
| 2918 | + IEEE80211_HE_PHY_CAP1_MIDAMBLE_RX_TX_MAX_NSTS, |
---|
| 2919 | + .phy_cap_info[2] = 0, |
---|
| 2920 | + |
---|
| 2921 | + /* Leave all the other PHY capability bytes |
---|
| 2922 | + * unset, as DCM, beam forming, RU and PPE |
---|
| 2923 | + * threshold information are not supported |
---|
| 2924 | + */ |
---|
| 2925 | + }, |
---|
| 2926 | + .he_mcs_nss_supp = { |
---|
| 2927 | + .rx_mcs_80 = cpu_to_le16(0xfffa), |
---|
| 2928 | + .tx_mcs_80 = cpu_to_le16(0xfffa), |
---|
| 2929 | + .rx_mcs_160 = cpu_to_le16(0xfffa), |
---|
| 2930 | + .tx_mcs_160 = cpu_to_le16(0xfffa), |
---|
| 2931 | + .rx_mcs_80p80 = cpu_to_le16(0xfffa), |
---|
| 2932 | + .tx_mcs_80p80 = cpu_to_le16(0xfffa), |
---|
| 2933 | + }, |
---|
| 2934 | + }, |
---|
| 2935 | + }, |
---|
| 2936 | +#endif |
---|
| 2937 | +}; |
---|
| 2938 | + |
---|
| 2939 | +static void mac80211_hwsim_he_capab(struct ieee80211_supported_band *sband) |
---|
2625 | 2940 | { |
---|
2626 | | - if (sband->band == NL80211_BAND_2GHZ) |
---|
2627 | | - sband->iftype_data = |
---|
2628 | | - (struct ieee80211_sband_iftype_data *)&he_capa_2ghz; |
---|
2629 | | - else if (sband->band == NL80211_BAND_5GHZ) |
---|
2630 | | - sband->iftype_data = |
---|
2631 | | - (struct ieee80211_sband_iftype_data *)&he_capa_5ghz; |
---|
2632 | | - else |
---|
2633 | | - return; |
---|
| 2941 | + u16 n_iftype_data; |
---|
2634 | 2942 | |
---|
2635 | | - sband->n_iftype_data = 1; |
---|
| 2943 | + if (sband->band == NL80211_BAND_2GHZ) { |
---|
| 2944 | + n_iftype_data = ARRAY_SIZE(he_capa_2ghz); |
---|
| 2945 | + sband->iftype_data = |
---|
| 2946 | + (struct ieee80211_sband_iftype_data *)he_capa_2ghz; |
---|
| 2947 | + } else if (sband->band == NL80211_BAND_5GHZ) { |
---|
| 2948 | + n_iftype_data = ARRAY_SIZE(he_capa_5ghz); |
---|
| 2949 | + sband->iftype_data = |
---|
| 2950 | + (struct ieee80211_sband_iftype_data *)he_capa_5ghz; |
---|
| 2951 | + } else { |
---|
| 2952 | + return; |
---|
| 2953 | + } |
---|
| 2954 | + |
---|
| 2955 | + sband->n_iftype_data = n_iftype_data; |
---|
2636 | 2956 | } |
---|
| 2957 | + |
---|
| 2958 | +#ifdef CONFIG_MAC80211_MESH |
---|
| 2959 | +#define HWSIM_MESH_BIT BIT(NL80211_IFTYPE_MESH_POINT) |
---|
| 2960 | +#else |
---|
| 2961 | +#define HWSIM_MESH_BIT 0 |
---|
| 2962 | +#endif |
---|
| 2963 | + |
---|
| 2964 | +#define HWSIM_DEFAULT_IF_LIMIT \ |
---|
| 2965 | + (BIT(NL80211_IFTYPE_STATION) | \ |
---|
| 2966 | + BIT(NL80211_IFTYPE_P2P_CLIENT) | \ |
---|
| 2967 | + BIT(NL80211_IFTYPE_AP) | \ |
---|
| 2968 | + BIT(NL80211_IFTYPE_P2P_GO) | \ |
---|
| 2969 | + HWSIM_MESH_BIT) |
---|
| 2970 | + |
---|
| 2971 | +#define HWSIM_IFTYPE_SUPPORT_MASK \ |
---|
| 2972 | + (BIT(NL80211_IFTYPE_STATION) | \ |
---|
| 2973 | + BIT(NL80211_IFTYPE_AP) | \ |
---|
| 2974 | + BIT(NL80211_IFTYPE_P2P_CLIENT) | \ |
---|
| 2975 | + BIT(NL80211_IFTYPE_P2P_GO) | \ |
---|
| 2976 | + BIT(NL80211_IFTYPE_ADHOC) | \ |
---|
| 2977 | + BIT(NL80211_IFTYPE_MESH_POINT) | \ |
---|
| 2978 | + BIT(NL80211_IFTYPE_OCB)) |
---|
2637 | 2979 | |
---|
2638 | 2980 | static int mac80211_hwsim_new_radio(struct genl_info *info, |
---|
2639 | 2981 | struct hwsim_new_radio_params *param) |
---|
.. | .. |
---|
2645 | 2987 | enum nl80211_band band; |
---|
2646 | 2988 | const struct ieee80211_ops *ops = &mac80211_hwsim_ops; |
---|
2647 | 2989 | struct net *net; |
---|
2648 | | - int idx; |
---|
| 2990 | + int idx, i; |
---|
| 2991 | + int n_limits = 0; |
---|
2649 | 2992 | |
---|
2650 | 2993 | if (WARN_ON(param->channels > 1 && !param->use_chanctx)) |
---|
2651 | 2994 | return -EINVAL; |
---|
.. | .. |
---|
2697 | 3040 | if (!param->perm_addr) { |
---|
2698 | 3041 | eth_zero_addr(addr); |
---|
2699 | 3042 | addr[0] = 0x02; |
---|
| 3043 | + addr[1] = (mac_prefix >> 8) & 0xFF; |
---|
| 3044 | + addr[2] = mac_prefix & 0xFF; |
---|
2700 | 3045 | addr[3] = idx >> 8; |
---|
2701 | 3046 | addr[4] = idx; |
---|
2702 | 3047 | memcpy(data->addresses[0].addr, addr, ETH_ALEN); |
---|
.. | .. |
---|
2721 | 3066 | if (info) |
---|
2722 | 3067 | data->portid = info->snd_portid; |
---|
2723 | 3068 | |
---|
| 3069 | + /* setup interface limits, only on interface types we support */ |
---|
| 3070 | + if (param->iftypes & BIT(NL80211_IFTYPE_ADHOC)) { |
---|
| 3071 | + data->if_limits[n_limits].max = 1; |
---|
| 3072 | + data->if_limits[n_limits].types = BIT(NL80211_IFTYPE_ADHOC); |
---|
| 3073 | + n_limits++; |
---|
| 3074 | + } |
---|
| 3075 | + |
---|
| 3076 | + if (param->iftypes & HWSIM_DEFAULT_IF_LIMIT) { |
---|
| 3077 | + data->if_limits[n_limits].max = 2048; |
---|
| 3078 | + /* |
---|
| 3079 | + * For this case, we may only support a subset of |
---|
| 3080 | + * HWSIM_DEFAULT_IF_LIMIT, therefore we only want to add the |
---|
| 3081 | + * bits that both param->iftype & HWSIM_DEFAULT_IF_LIMIT have. |
---|
| 3082 | + */ |
---|
| 3083 | + data->if_limits[n_limits].types = |
---|
| 3084 | + HWSIM_DEFAULT_IF_LIMIT & param->iftypes; |
---|
| 3085 | + n_limits++; |
---|
| 3086 | + } |
---|
| 3087 | + |
---|
| 3088 | + if (param->iftypes & BIT(NL80211_IFTYPE_P2P_DEVICE)) { |
---|
| 3089 | + data->if_limits[n_limits].max = 1; |
---|
| 3090 | + data->if_limits[n_limits].types = |
---|
| 3091 | + BIT(NL80211_IFTYPE_P2P_DEVICE); |
---|
| 3092 | + n_limits++; |
---|
| 3093 | + } |
---|
| 3094 | + |
---|
2724 | 3095 | if (data->use_chanctx) { |
---|
2725 | 3096 | hw->wiphy->max_scan_ssids = 255; |
---|
2726 | 3097 | hw->wiphy->max_scan_ie_len = IEEE80211_MAX_DATA_LEN; |
---|
2727 | 3098 | hw->wiphy->max_remain_on_channel_duration = 1000; |
---|
2728 | | - hw->wiphy->iface_combinations = &data->if_combination; |
---|
2729 | | - if (param->p2p_device) |
---|
2730 | | - data->if_combination = hwsim_if_comb_p2p_dev[0]; |
---|
2731 | | - else |
---|
2732 | | - data->if_combination = hwsim_if_comb[0]; |
---|
2733 | | - hw->wiphy->n_iface_combinations = 1; |
---|
2734 | | - /* For channels > 1 DFS is not allowed */ |
---|
2735 | 3099 | data->if_combination.radar_detect_widths = 0; |
---|
2736 | 3100 | data->if_combination.num_different_channels = data->channels; |
---|
2737 | | - } else if (param->p2p_device) { |
---|
2738 | | - hw->wiphy->iface_combinations = hwsim_if_comb_p2p_dev; |
---|
2739 | | - hw->wiphy->n_iface_combinations = |
---|
2740 | | - ARRAY_SIZE(hwsim_if_comb_p2p_dev); |
---|
| 3101 | + data->chanctx = NULL; |
---|
2741 | 3102 | } else { |
---|
2742 | | - hw->wiphy->iface_combinations = hwsim_if_comb; |
---|
2743 | | - hw->wiphy->n_iface_combinations = ARRAY_SIZE(hwsim_if_comb); |
---|
| 3103 | + data->if_combination.num_different_channels = 1; |
---|
| 3104 | + data->if_combination.radar_detect_widths = |
---|
| 3105 | + BIT(NL80211_CHAN_WIDTH_5) | |
---|
| 3106 | + BIT(NL80211_CHAN_WIDTH_10) | |
---|
| 3107 | + BIT(NL80211_CHAN_WIDTH_20_NOHT) | |
---|
| 3108 | + BIT(NL80211_CHAN_WIDTH_20) | |
---|
| 3109 | + BIT(NL80211_CHAN_WIDTH_40) | |
---|
| 3110 | + BIT(NL80211_CHAN_WIDTH_80) | |
---|
| 3111 | + BIT(NL80211_CHAN_WIDTH_160); |
---|
| 3112 | + } |
---|
| 3113 | + |
---|
| 3114 | + if (!n_limits) { |
---|
| 3115 | + err = -EINVAL; |
---|
| 3116 | + goto failed_hw; |
---|
| 3117 | + } |
---|
| 3118 | + |
---|
| 3119 | + data->if_combination.max_interfaces = 0; |
---|
| 3120 | + for (i = 0; i < n_limits; i++) |
---|
| 3121 | + data->if_combination.max_interfaces += |
---|
| 3122 | + data->if_limits[i].max; |
---|
| 3123 | + |
---|
| 3124 | + data->if_combination.n_limits = n_limits; |
---|
| 3125 | + data->if_combination.limits = data->if_limits; |
---|
| 3126 | + |
---|
| 3127 | + /* |
---|
| 3128 | + * If we actually were asked to support combinations, |
---|
| 3129 | + * advertise them - if there's only a single thing like |
---|
| 3130 | + * only IBSS then don't advertise it as combinations. |
---|
| 3131 | + */ |
---|
| 3132 | + if (data->if_combination.max_interfaces > 1) { |
---|
| 3133 | + hw->wiphy->iface_combinations = &data->if_combination; |
---|
| 3134 | + hw->wiphy->n_iface_combinations = 1; |
---|
| 3135 | + } |
---|
| 3136 | + |
---|
| 3137 | + if (param->ciphers) { |
---|
| 3138 | + memcpy(data->ciphers, param->ciphers, |
---|
| 3139 | + param->n_ciphers * sizeof(u32)); |
---|
| 3140 | + hw->wiphy->cipher_suites = data->ciphers; |
---|
| 3141 | + hw->wiphy->n_cipher_suites = param->n_ciphers; |
---|
2744 | 3142 | } |
---|
2745 | 3143 | |
---|
2746 | 3144 | INIT_DELAYED_WORK(&data->roc_start, hw_roc_start); |
---|
.. | .. |
---|
2749 | 3147 | |
---|
2750 | 3148 | hw->queues = 5; |
---|
2751 | 3149 | hw->offchannel_tx_hw_queue = 4; |
---|
2752 | | - hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) | |
---|
2753 | | - BIT(NL80211_IFTYPE_AP) | |
---|
2754 | | - BIT(NL80211_IFTYPE_P2P_CLIENT) | |
---|
2755 | | - BIT(NL80211_IFTYPE_P2P_GO) | |
---|
2756 | | - BIT(NL80211_IFTYPE_ADHOC) | |
---|
2757 | | - BIT(NL80211_IFTYPE_MESH_POINT); |
---|
2758 | | - |
---|
2759 | | - if (param->p2p_device) |
---|
2760 | | - hw->wiphy->interface_modes |= BIT(NL80211_IFTYPE_P2P_DEVICE); |
---|
2761 | 3150 | |
---|
2762 | 3151 | ieee80211_hw_set(hw, SUPPORT_FAST_XMIT); |
---|
2763 | 3152 | ieee80211_hw_set(hw, CHANCTX_STA_CSA); |
---|
.. | .. |
---|
2768 | 3157 | ieee80211_hw_set(hw, MFP_CAPABLE); |
---|
2769 | 3158 | ieee80211_hw_set(hw, SIGNAL_DBM); |
---|
2770 | 3159 | ieee80211_hw_set(hw, SUPPORTS_PS); |
---|
| 3160 | + ieee80211_hw_set(hw, REPORTS_TX_ACK_STATUS); |
---|
| 3161 | + ieee80211_hw_set(hw, HOST_BROADCAST_PS_BUFFERING); |
---|
| 3162 | + ieee80211_hw_set(hw, PS_NULLFUNC_STACK); |
---|
2771 | 3163 | ieee80211_hw_set(hw, TDLS_WIDER_BW); |
---|
2772 | 3164 | if (rctbl) |
---|
2773 | 3165 | ieee80211_hw_set(hw, SUPPORTS_RC_TABLE); |
---|
| 3166 | + ieee80211_hw_set(hw, SUPPORTS_MULTI_BSSID); |
---|
2774 | 3167 | |
---|
| 3168 | + hw->wiphy->flags &= ~WIPHY_FLAG_PS_ON_BY_DEFAULT; |
---|
2775 | 3169 | hw->wiphy->flags |= WIPHY_FLAG_SUPPORTS_TDLS | |
---|
2776 | 3170 | WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL | |
---|
2777 | 3171 | WIPHY_FLAG_AP_UAPSD | |
---|
| 3172 | + WIPHY_FLAG_SUPPORTS_5_10_MHZ | |
---|
2778 | 3173 | WIPHY_FLAG_HAS_CHANNEL_SWITCH; |
---|
2779 | 3174 | hw->wiphy->features |= NL80211_FEATURE_ACTIVE_MONITOR | |
---|
2780 | 3175 | NL80211_FEATURE_AP_MODE_CHAN_WIDTH_CHANGE | |
---|
.. | .. |
---|
2782 | 3177 | NL80211_FEATURE_DYNAMIC_SMPS | |
---|
2783 | 3178 | NL80211_FEATURE_SCAN_RANDOM_MAC_ADDR; |
---|
2784 | 3179 | wiphy_ext_feature_set(hw->wiphy, NL80211_EXT_FEATURE_VHT_IBSS); |
---|
| 3180 | + wiphy_ext_feature_set(hw->wiphy, NL80211_EXT_FEATURE_BEACON_PROTECTION); |
---|
| 3181 | + wiphy_ext_feature_set(hw->wiphy, |
---|
| 3182 | + NL80211_EXT_FEATURE_MULTICAST_REGISTRATIONS); |
---|
| 3183 | + wiphy_ext_feature_set(hw->wiphy, |
---|
| 3184 | + NL80211_EXT_FEATURE_BEACON_RATE_LEGACY); |
---|
| 3185 | + |
---|
| 3186 | + hw->wiphy->interface_modes = param->iftypes; |
---|
2785 | 3187 | |
---|
2786 | 3188 | /* ask mac80211 to reserve space for magic */ |
---|
2787 | 3189 | hw->vif_data_size = sizeof(struct hwsim_vif_priv); |
---|
.. | .. |
---|
2792 | 3194 | sizeof(hwsim_channels_2ghz)); |
---|
2793 | 3195 | memcpy(data->channels_5ghz, hwsim_channels_5ghz, |
---|
2794 | 3196 | sizeof(hwsim_channels_5ghz)); |
---|
| 3197 | + memcpy(data->channels_s1g, hwsim_channels_s1g, |
---|
| 3198 | + sizeof(hwsim_channels_s1g)); |
---|
2795 | 3199 | memcpy(data->rates, hwsim_rates, sizeof(hwsim_rates)); |
---|
2796 | 3200 | |
---|
2797 | 3201 | for (band = NL80211_BAND_2GHZ; band < NUM_NL80211_BANDS; band++) { |
---|
.. | .. |
---|
2834 | 3238 | sband->vht_cap.vht_mcs.tx_mcs_map = |
---|
2835 | 3239 | sband->vht_cap.vht_mcs.rx_mcs_map; |
---|
2836 | 3240 | break; |
---|
| 3241 | + case NL80211_BAND_S1GHZ: |
---|
| 3242 | + memcpy(&sband->s1g_cap, &hwsim_s1g_cap, |
---|
| 3243 | + sizeof(sband->s1g_cap)); |
---|
| 3244 | + sband->channels = data->channels_s1g; |
---|
| 3245 | + sband->n_channels = ARRAY_SIZE(hwsim_channels_s1g); |
---|
| 3246 | + break; |
---|
2837 | 3247 | default: |
---|
2838 | 3248 | continue; |
---|
2839 | 3249 | } |
---|
.. | .. |
---|
2852 | 3262 | sband->ht_cap.mcs.rx_mask[1] = 0xff; |
---|
2853 | 3263 | sband->ht_cap.mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED; |
---|
2854 | 3264 | |
---|
2855 | | - mac80211_hswim_he_capab(sband); |
---|
| 3265 | + mac80211_hwsim_he_capab(sband); |
---|
2856 | 3266 | |
---|
2857 | 3267 | hw->wiphy->bands[band] = sband; |
---|
2858 | 3268 | } |
---|
.. | .. |
---|
2889 | 3299 | |
---|
2890 | 3300 | wiphy_ext_feature_set(hw->wiphy, NL80211_EXT_FEATURE_CQM_RSSI_LIST); |
---|
2891 | 3301 | |
---|
2892 | | - tasklet_hrtimer_init(&data->beacon_timer, |
---|
2893 | | - mac80211_hwsim_beacon, |
---|
2894 | | - CLOCK_MONOTONIC, HRTIMER_MODE_ABS); |
---|
| 3302 | + hrtimer_init(&data->beacon_timer, CLOCK_MONOTONIC, |
---|
| 3303 | + HRTIMER_MODE_ABS_SOFT); |
---|
| 3304 | + data->beacon_timer.function = mac80211_hwsim_beacon; |
---|
2895 | 3305 | |
---|
2896 | 3306 | err = ieee80211_register_hw(hw); |
---|
2897 | 3307 | if (err < 0) { |
---|
.. | .. |
---|
3108 | 3518 | const u8 *src; |
---|
3109 | 3519 | unsigned int hwsim_flags; |
---|
3110 | 3520 | int i; |
---|
| 3521 | + unsigned long flags; |
---|
3111 | 3522 | bool found = false; |
---|
3112 | 3523 | |
---|
3113 | 3524 | if (!info->attrs[HWSIM_ATTR_ADDR_TRANSMITTER] || |
---|
.. | .. |
---|
3125 | 3536 | if (!data2) |
---|
3126 | 3537 | goto out; |
---|
3127 | 3538 | |
---|
3128 | | - if (hwsim_net_get_netgroup(genl_info_net(info)) != data2->netgroup) |
---|
3129 | | - goto out; |
---|
| 3539 | + if (!hwsim_virtio_enabled) { |
---|
| 3540 | + if (hwsim_net_get_netgroup(genl_info_net(info)) != |
---|
| 3541 | + data2->netgroup) |
---|
| 3542 | + goto out; |
---|
3130 | 3543 | |
---|
3131 | | - if (info->snd_portid != data2->wmediumd) |
---|
3132 | | - goto out; |
---|
| 3544 | + if (info->snd_portid != data2->wmediumd) |
---|
| 3545 | + goto out; |
---|
| 3546 | + } |
---|
3133 | 3547 | |
---|
3134 | 3548 | /* look for the skb matching the cookie passed back from user */ |
---|
| 3549 | + spin_lock_irqsave(&data2->pending.lock, flags); |
---|
3135 | 3550 | skb_queue_walk_safe(&data2->pending, skb, tmp) { |
---|
3136 | | - u64 skb_cookie; |
---|
| 3551 | + uintptr_t skb_cookie; |
---|
3137 | 3552 | |
---|
3138 | 3553 | txi = IEEE80211_SKB_CB(skb); |
---|
3139 | | - skb_cookie = (u64)(uintptr_t)txi->rate_driver_data[0]; |
---|
| 3554 | + skb_cookie = (uintptr_t)txi->rate_driver_data[0]; |
---|
3140 | 3555 | |
---|
3141 | 3556 | if (skb_cookie == ret_skb_cookie) { |
---|
3142 | | - skb_unlink(skb, &data2->pending); |
---|
| 3557 | + __skb_unlink(skb, &data2->pending); |
---|
3143 | 3558 | found = true; |
---|
3144 | 3559 | break; |
---|
3145 | 3560 | } |
---|
3146 | 3561 | } |
---|
| 3562 | + spin_unlock_irqrestore(&data2->pending.lock, flags); |
---|
3147 | 3563 | |
---|
3148 | 3564 | /* not found */ |
---|
3149 | 3565 | if (!found) |
---|
.. | .. |
---|
3176 | 3592 | } |
---|
3177 | 3593 | txi->flags |= IEEE80211_TX_STAT_ACK; |
---|
3178 | 3594 | } |
---|
| 3595 | + |
---|
| 3596 | + if (hwsim_flags & HWSIM_TX_CTL_NO_ACK) |
---|
| 3597 | + txi->flags |= IEEE80211_TX_STAT_NOACK_TRANSMITTED; |
---|
| 3598 | + |
---|
3179 | 3599 | ieee80211_tx_status_irqsafe(data2->hw, skb); |
---|
3180 | 3600 | return 0; |
---|
3181 | 3601 | out: |
---|
.. | .. |
---|
3188 | 3608 | { |
---|
3189 | 3609 | struct mac80211_hwsim_data *data2; |
---|
3190 | 3610 | struct ieee80211_rx_status rx_status; |
---|
| 3611 | + struct ieee80211_hdr *hdr; |
---|
3191 | 3612 | const u8 *dst; |
---|
3192 | 3613 | int frame_data_len; |
---|
3193 | 3614 | void *frame_data; |
---|
3194 | 3615 | struct sk_buff *skb = NULL; |
---|
| 3616 | + struct ieee80211_channel *channel = NULL; |
---|
3195 | 3617 | |
---|
3196 | 3618 | if (!info->attrs[HWSIM_ATTR_ADDR_RECEIVER] || |
---|
3197 | 3619 | !info->attrs[HWSIM_ATTR_FRAME] || |
---|
.. | .. |
---|
3203 | 3625 | frame_data_len = nla_len(info->attrs[HWSIM_ATTR_FRAME]); |
---|
3204 | 3626 | frame_data = (void *)nla_data(info->attrs[HWSIM_ATTR_FRAME]); |
---|
3205 | 3627 | |
---|
| 3628 | + if (frame_data_len < sizeof(struct ieee80211_hdr_3addr) || |
---|
| 3629 | + frame_data_len > IEEE80211_MAX_DATA_LEN) |
---|
| 3630 | + goto err; |
---|
| 3631 | + |
---|
3206 | 3632 | /* Allocate new skb here */ |
---|
3207 | 3633 | skb = alloc_skb(frame_data_len, GFP_KERNEL); |
---|
3208 | 3634 | if (skb == NULL) |
---|
3209 | | - goto err; |
---|
3210 | | - |
---|
3211 | | - if (frame_data_len > IEEE80211_MAX_DATA_LEN) |
---|
3212 | 3635 | goto err; |
---|
3213 | 3636 | |
---|
3214 | 3637 | /* Copy the data */ |
---|
.. | .. |
---|
3218 | 3641 | if (!data2) |
---|
3219 | 3642 | goto out; |
---|
3220 | 3643 | |
---|
3221 | | - if (hwsim_net_get_netgroup(genl_info_net(info)) != data2->netgroup) |
---|
| 3644 | + if (data2->use_chanctx) { |
---|
| 3645 | + if (data2->tmp_chan) |
---|
| 3646 | + channel = data2->tmp_chan; |
---|
| 3647 | + else if (data2->chanctx) |
---|
| 3648 | + channel = data2->chanctx->def.chan; |
---|
| 3649 | + } else { |
---|
| 3650 | + channel = data2->channel; |
---|
| 3651 | + } |
---|
| 3652 | + if (!channel) |
---|
3222 | 3653 | goto out; |
---|
3223 | 3654 | |
---|
3224 | | - if (info->snd_portid != data2->wmediumd) |
---|
3225 | | - goto out; |
---|
| 3655 | + if (!hwsim_virtio_enabled) { |
---|
| 3656 | + if (hwsim_net_get_netgroup(genl_info_net(info)) != |
---|
| 3657 | + data2->netgroup) |
---|
| 3658 | + goto out; |
---|
| 3659 | + |
---|
| 3660 | + if (info->snd_portid != data2->wmediumd) |
---|
| 3661 | + goto out; |
---|
| 3662 | + } |
---|
3226 | 3663 | |
---|
3227 | 3664 | /* check if radio is configured properly */ |
---|
3228 | 3665 | |
---|
3229 | | - if (data2->idle || !data2->started) |
---|
| 3666 | + if ((data2->idle && !data2->tmp_chan) || !data2->started) |
---|
3230 | 3667 | goto out; |
---|
3231 | 3668 | |
---|
3232 | 3669 | /* A frame is received from user space */ |
---|
.. | .. |
---|
3239 | 3676 | mutex_lock(&data2->mutex); |
---|
3240 | 3677 | rx_status.freq = nla_get_u32(info->attrs[HWSIM_ATTR_FREQ]); |
---|
3241 | 3678 | |
---|
3242 | | - if (rx_status.freq != data2->channel->center_freq && |
---|
3243 | | - (!data2->tmp_chan || |
---|
3244 | | - rx_status.freq != data2->tmp_chan->center_freq)) { |
---|
| 3679 | + if (rx_status.freq != channel->center_freq) { |
---|
3245 | 3680 | mutex_unlock(&data2->mutex); |
---|
3246 | 3681 | goto out; |
---|
3247 | 3682 | } |
---|
3248 | 3683 | mutex_unlock(&data2->mutex); |
---|
3249 | 3684 | } else { |
---|
3250 | | - rx_status.freq = data2->channel->center_freq; |
---|
| 3685 | + rx_status.freq = channel->center_freq; |
---|
3251 | 3686 | } |
---|
3252 | 3687 | |
---|
3253 | | - rx_status.band = data2->channel->band; |
---|
| 3688 | + rx_status.band = channel->band; |
---|
3254 | 3689 | rx_status.rate_idx = nla_get_u32(info->attrs[HWSIM_ATTR_RX_RATE]); |
---|
| 3690 | + if (rx_status.rate_idx >= data2->hw->wiphy->bands[rx_status.band]->n_bitrates) |
---|
| 3691 | + goto out; |
---|
3255 | 3692 | rx_status.signal = nla_get_u32(info->attrs[HWSIM_ATTR_SIGNAL]); |
---|
| 3693 | + |
---|
| 3694 | + hdr = (void *)skb->data; |
---|
| 3695 | + |
---|
| 3696 | + if (ieee80211_is_beacon(hdr->frame_control) || |
---|
| 3697 | + ieee80211_is_probe_resp(hdr->frame_control)) |
---|
| 3698 | + rx_status.boottime_ns = ktime_get_boottime_ns(); |
---|
3256 | 3699 | |
---|
3257 | 3700 | memcpy(IEEE80211_SKB_RXCB(skb), &rx_status, sizeof(rx_status)); |
---|
3258 | 3701 | data2->rx_pkts++; |
---|
.. | .. |
---|
3298 | 3741 | return 0; |
---|
3299 | 3742 | } |
---|
3300 | 3743 | |
---|
| 3744 | +/* ensures ciphers only include ciphers listed in 'hwsim_ciphers' array */ |
---|
| 3745 | +static bool hwsim_known_ciphers(const u32 *ciphers, int n_ciphers) |
---|
| 3746 | +{ |
---|
| 3747 | + int i; |
---|
| 3748 | + |
---|
| 3749 | + for (i = 0; i < n_ciphers; i++) { |
---|
| 3750 | + int j; |
---|
| 3751 | + int found = 0; |
---|
| 3752 | + |
---|
| 3753 | + for (j = 0; j < ARRAY_SIZE(hwsim_ciphers); j++) { |
---|
| 3754 | + if (ciphers[i] == hwsim_ciphers[j]) { |
---|
| 3755 | + found = 1; |
---|
| 3756 | + break; |
---|
| 3757 | + } |
---|
| 3758 | + } |
---|
| 3759 | + |
---|
| 3760 | + if (!found) |
---|
| 3761 | + return false; |
---|
| 3762 | + } |
---|
| 3763 | + |
---|
| 3764 | + return true; |
---|
| 3765 | +} |
---|
| 3766 | + |
---|
3301 | 3767 | static int hwsim_new_radio_nl(struct sk_buff *msg, struct genl_info *info) |
---|
3302 | 3768 | { |
---|
3303 | 3769 | struct hwsim_new_radio_params param = { 0 }; |
---|
.. | .. |
---|
3326 | 3792 | if (info->attrs[HWSIM_ATTR_NO_VIF]) |
---|
3327 | 3793 | param.no_vif = true; |
---|
3328 | 3794 | |
---|
3329 | | - if (info->attrs[HWSIM_ATTR_RADIO_NAME]) { |
---|
3330 | | - hwname = kstrndup((char *)nla_data(info->attrs[HWSIM_ATTR_RADIO_NAME]), |
---|
3331 | | - nla_len(info->attrs[HWSIM_ATTR_RADIO_NAME]), |
---|
3332 | | - GFP_KERNEL); |
---|
3333 | | - if (!hwname) |
---|
3334 | | - return -ENOMEM; |
---|
3335 | | - param.hwname = hwname; |
---|
3336 | | - } |
---|
3337 | | - |
---|
3338 | 3795 | if (info->attrs[HWSIM_ATTR_USE_CHANCTX]) |
---|
3339 | 3796 | param.use_chanctx = true; |
---|
3340 | 3797 | else |
---|
.. | .. |
---|
3347 | 3804 | if (info->attrs[HWSIM_ATTR_REG_CUSTOM_REG]) { |
---|
3348 | 3805 | u32 idx = nla_get_u32(info->attrs[HWSIM_ATTR_REG_CUSTOM_REG]); |
---|
3349 | 3806 | |
---|
3350 | | - if (idx >= ARRAY_SIZE(hwsim_world_regdom_custom)) { |
---|
3351 | | - kfree(hwname); |
---|
| 3807 | + if (idx >= ARRAY_SIZE(hwsim_world_regdom_custom)) |
---|
3352 | 3808 | return -EINVAL; |
---|
3353 | | - } |
---|
3354 | 3809 | |
---|
3355 | 3810 | idx = array_index_nospec(idx, |
---|
3356 | 3811 | ARRAY_SIZE(hwsim_world_regdom_custom)); |
---|
.. | .. |
---|
3363 | 3818 | GENL_SET_ERR_MSG(info,"MAC is no valid source addr"); |
---|
3364 | 3819 | NL_SET_BAD_ATTR(info->extack, |
---|
3365 | 3820 | info->attrs[HWSIM_ATTR_PERM_ADDR]); |
---|
3366 | | - kfree(hwname); |
---|
3367 | 3821 | return -EINVAL; |
---|
3368 | 3822 | } |
---|
3369 | 3823 | |
---|
3370 | | - |
---|
3371 | 3824 | param.perm_addr = nla_data(info->attrs[HWSIM_ATTR_PERM_ADDR]); |
---|
| 3825 | + } |
---|
| 3826 | + |
---|
| 3827 | + if (info->attrs[HWSIM_ATTR_IFTYPE_SUPPORT]) { |
---|
| 3828 | + param.iftypes = |
---|
| 3829 | + nla_get_u32(info->attrs[HWSIM_ATTR_IFTYPE_SUPPORT]); |
---|
| 3830 | + |
---|
| 3831 | + if (param.iftypes & ~HWSIM_IFTYPE_SUPPORT_MASK) { |
---|
| 3832 | + NL_SET_ERR_MSG_ATTR(info->extack, |
---|
| 3833 | + info->attrs[HWSIM_ATTR_IFTYPE_SUPPORT], |
---|
| 3834 | + "cannot support more iftypes than kernel"); |
---|
| 3835 | + return -EINVAL; |
---|
| 3836 | + } |
---|
| 3837 | + } else { |
---|
| 3838 | + param.iftypes = HWSIM_IFTYPE_SUPPORT_MASK; |
---|
| 3839 | + } |
---|
| 3840 | + |
---|
| 3841 | + /* ensure both flag and iftype support is honored */ |
---|
| 3842 | + if (param.p2p_device || |
---|
| 3843 | + param.iftypes & BIT(NL80211_IFTYPE_P2P_DEVICE)) { |
---|
| 3844 | + param.iftypes |= BIT(NL80211_IFTYPE_P2P_DEVICE); |
---|
| 3845 | + param.p2p_device = true; |
---|
| 3846 | + } |
---|
| 3847 | + |
---|
| 3848 | + if (info->attrs[HWSIM_ATTR_CIPHER_SUPPORT]) { |
---|
| 3849 | + u32 len = nla_len(info->attrs[HWSIM_ATTR_CIPHER_SUPPORT]); |
---|
| 3850 | + |
---|
| 3851 | + param.ciphers = |
---|
| 3852 | + nla_data(info->attrs[HWSIM_ATTR_CIPHER_SUPPORT]); |
---|
| 3853 | + |
---|
| 3854 | + if (len % sizeof(u32)) { |
---|
| 3855 | + NL_SET_ERR_MSG_ATTR(info->extack, |
---|
| 3856 | + info->attrs[HWSIM_ATTR_CIPHER_SUPPORT], |
---|
| 3857 | + "bad cipher list length"); |
---|
| 3858 | + return -EINVAL; |
---|
| 3859 | + } |
---|
| 3860 | + |
---|
| 3861 | + param.n_ciphers = len / sizeof(u32); |
---|
| 3862 | + |
---|
| 3863 | + if (param.n_ciphers > ARRAY_SIZE(hwsim_ciphers)) { |
---|
| 3864 | + NL_SET_ERR_MSG_ATTR(info->extack, |
---|
| 3865 | + info->attrs[HWSIM_ATTR_CIPHER_SUPPORT], |
---|
| 3866 | + "too many ciphers specified"); |
---|
| 3867 | + return -EINVAL; |
---|
| 3868 | + } |
---|
| 3869 | + |
---|
| 3870 | + if (!hwsim_known_ciphers(param.ciphers, param.n_ciphers)) { |
---|
| 3871 | + NL_SET_ERR_MSG_ATTR(info->extack, |
---|
| 3872 | + info->attrs[HWSIM_ATTR_CIPHER_SUPPORT], |
---|
| 3873 | + "unsupported ciphers specified"); |
---|
| 3874 | + return -EINVAL; |
---|
| 3875 | + } |
---|
| 3876 | + } |
---|
| 3877 | + |
---|
| 3878 | + if (info->attrs[HWSIM_ATTR_RADIO_NAME]) { |
---|
| 3879 | + hwname = kstrndup((char *)nla_data(info->attrs[HWSIM_ATTR_RADIO_NAME]), |
---|
| 3880 | + nla_len(info->attrs[HWSIM_ATTR_RADIO_NAME]), |
---|
| 3881 | + GFP_KERNEL); |
---|
| 3882 | + if (!hwname) |
---|
| 3883 | + return -ENOMEM; |
---|
| 3884 | + param.hwname = hwname; |
---|
3372 | 3885 | } |
---|
3373 | 3886 | |
---|
3374 | 3887 | ret = mac80211_hwsim_new_radio(info, ¶m); |
---|
.. | .. |
---|
3516 | 4029 | } |
---|
3517 | 4030 | |
---|
3518 | 4031 | /* Generic Netlink operations array */ |
---|
3519 | | -static const struct genl_ops hwsim_ops[] = { |
---|
| 4032 | +static const struct genl_small_ops hwsim_ops[] = { |
---|
3520 | 4033 | { |
---|
3521 | 4034 | .cmd = HWSIM_CMD_REGISTER, |
---|
3522 | | - .policy = hwsim_genl_policy, |
---|
| 4035 | + .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, |
---|
3523 | 4036 | .doit = hwsim_register_received_nl, |
---|
3524 | 4037 | .flags = GENL_UNS_ADMIN_PERM, |
---|
3525 | 4038 | }, |
---|
3526 | 4039 | { |
---|
3527 | 4040 | .cmd = HWSIM_CMD_FRAME, |
---|
3528 | | - .policy = hwsim_genl_policy, |
---|
| 4041 | + .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, |
---|
3529 | 4042 | .doit = hwsim_cloned_frame_received_nl, |
---|
3530 | 4043 | }, |
---|
3531 | 4044 | { |
---|
3532 | 4045 | .cmd = HWSIM_CMD_TX_INFO_FRAME, |
---|
3533 | | - .policy = hwsim_genl_policy, |
---|
| 4046 | + .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, |
---|
3534 | 4047 | .doit = hwsim_tx_info_frame_received_nl, |
---|
3535 | 4048 | }, |
---|
3536 | 4049 | { |
---|
3537 | 4050 | .cmd = HWSIM_CMD_NEW_RADIO, |
---|
3538 | | - .policy = hwsim_genl_policy, |
---|
| 4051 | + .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, |
---|
3539 | 4052 | .doit = hwsim_new_radio_nl, |
---|
3540 | 4053 | .flags = GENL_UNS_ADMIN_PERM, |
---|
3541 | 4054 | }, |
---|
3542 | 4055 | { |
---|
3543 | 4056 | .cmd = HWSIM_CMD_DEL_RADIO, |
---|
3544 | | - .policy = hwsim_genl_policy, |
---|
| 4057 | + .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, |
---|
3545 | 4058 | .doit = hwsim_del_radio_nl, |
---|
3546 | 4059 | .flags = GENL_UNS_ADMIN_PERM, |
---|
3547 | 4060 | }, |
---|
3548 | 4061 | { |
---|
3549 | 4062 | .cmd = HWSIM_CMD_GET_RADIO, |
---|
3550 | | - .policy = hwsim_genl_policy, |
---|
| 4063 | + .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, |
---|
3551 | 4064 | .doit = hwsim_get_radio_nl, |
---|
3552 | 4065 | .dumpit = hwsim_dump_radio_nl, |
---|
3553 | 4066 | }, |
---|
.. | .. |
---|
3557 | 4070 | .name = "MAC80211_HWSIM", |
---|
3558 | 4071 | .version = 1, |
---|
3559 | 4072 | .maxattr = HWSIM_ATTR_MAX, |
---|
| 4073 | + .policy = hwsim_genl_policy, |
---|
3560 | 4074 | .netnsok = true, |
---|
3561 | 4075 | .module = THIS_MODULE, |
---|
3562 | | - .ops = hwsim_ops, |
---|
3563 | | - .n_ops = ARRAY_SIZE(hwsim_ops), |
---|
| 4076 | + .small_ops = hwsim_ops, |
---|
| 4077 | + .n_small_ops = ARRAY_SIZE(hwsim_ops), |
---|
3564 | 4078 | .mcgrps = hwsim_mcgrps, |
---|
3565 | 4079 | .n_mcgrps = ARRAY_SIZE(hwsim_mcgrps), |
---|
3566 | 4080 | }; |
---|
.. | .. |
---|
3686 | 4200 | genl_unregister_family(&hwsim_genl_family); |
---|
3687 | 4201 | } |
---|
3688 | 4202 | |
---|
| 4203 | +#if IS_REACHABLE(CONFIG_VIRTIO) |
---|
| 4204 | +static void hwsim_virtio_tx_done(struct virtqueue *vq) |
---|
| 4205 | +{ |
---|
| 4206 | + unsigned int len; |
---|
| 4207 | + struct sk_buff *skb; |
---|
| 4208 | + unsigned long flags; |
---|
| 4209 | + |
---|
| 4210 | + spin_lock_irqsave(&hwsim_virtio_lock, flags); |
---|
| 4211 | + while ((skb = virtqueue_get_buf(vq, &len))) |
---|
| 4212 | + nlmsg_free(skb); |
---|
| 4213 | + spin_unlock_irqrestore(&hwsim_virtio_lock, flags); |
---|
| 4214 | +} |
---|
| 4215 | + |
---|
| 4216 | +static int hwsim_virtio_handle_cmd(struct sk_buff *skb) |
---|
| 4217 | +{ |
---|
| 4218 | + struct nlmsghdr *nlh; |
---|
| 4219 | + struct genlmsghdr *gnlh; |
---|
| 4220 | + struct nlattr *tb[HWSIM_ATTR_MAX + 1]; |
---|
| 4221 | + struct genl_info info = {}; |
---|
| 4222 | + int err; |
---|
| 4223 | + |
---|
| 4224 | + nlh = nlmsg_hdr(skb); |
---|
| 4225 | + gnlh = nlmsg_data(nlh); |
---|
| 4226 | + |
---|
| 4227 | + if (skb->len < nlh->nlmsg_len) |
---|
| 4228 | + return -EINVAL; |
---|
| 4229 | + |
---|
| 4230 | + err = genlmsg_parse(nlh, &hwsim_genl_family, tb, HWSIM_ATTR_MAX, |
---|
| 4231 | + hwsim_genl_policy, NULL); |
---|
| 4232 | + if (err) { |
---|
| 4233 | + pr_err_ratelimited("hwsim: genlmsg_parse returned %d\n", err); |
---|
| 4234 | + return err; |
---|
| 4235 | + } |
---|
| 4236 | + |
---|
| 4237 | + info.attrs = tb; |
---|
| 4238 | + |
---|
| 4239 | + switch (gnlh->cmd) { |
---|
| 4240 | + case HWSIM_CMD_FRAME: |
---|
| 4241 | + hwsim_cloned_frame_received_nl(skb, &info); |
---|
| 4242 | + break; |
---|
| 4243 | + case HWSIM_CMD_TX_INFO_FRAME: |
---|
| 4244 | + hwsim_tx_info_frame_received_nl(skb, &info); |
---|
| 4245 | + break; |
---|
| 4246 | + default: |
---|
| 4247 | + pr_err_ratelimited("hwsim: invalid cmd: %d\n", gnlh->cmd); |
---|
| 4248 | + return -EPROTO; |
---|
| 4249 | + } |
---|
| 4250 | + return 0; |
---|
| 4251 | +} |
---|
| 4252 | + |
---|
| 4253 | +static void hwsim_virtio_rx_work(struct work_struct *work) |
---|
| 4254 | +{ |
---|
| 4255 | + struct virtqueue *vq; |
---|
| 4256 | + unsigned int len; |
---|
| 4257 | + struct sk_buff *skb; |
---|
| 4258 | + struct scatterlist sg[1]; |
---|
| 4259 | + int err; |
---|
| 4260 | + unsigned long flags; |
---|
| 4261 | + |
---|
| 4262 | + spin_lock_irqsave(&hwsim_virtio_lock, flags); |
---|
| 4263 | + if (!hwsim_virtio_enabled) |
---|
| 4264 | + goto out_unlock; |
---|
| 4265 | + |
---|
| 4266 | + skb = virtqueue_get_buf(hwsim_vqs[HWSIM_VQ_RX], &len); |
---|
| 4267 | + if (!skb) |
---|
| 4268 | + goto out_unlock; |
---|
| 4269 | + spin_unlock_irqrestore(&hwsim_virtio_lock, flags); |
---|
| 4270 | + |
---|
| 4271 | + skb->data = skb->head; |
---|
| 4272 | + skb_reset_tail_pointer(skb); |
---|
| 4273 | + skb_put(skb, len); |
---|
| 4274 | + hwsim_virtio_handle_cmd(skb); |
---|
| 4275 | + |
---|
| 4276 | + spin_lock_irqsave(&hwsim_virtio_lock, flags); |
---|
| 4277 | + if (!hwsim_virtio_enabled) { |
---|
| 4278 | + nlmsg_free(skb); |
---|
| 4279 | + goto out_unlock; |
---|
| 4280 | + } |
---|
| 4281 | + vq = hwsim_vqs[HWSIM_VQ_RX]; |
---|
| 4282 | + sg_init_one(sg, skb->head, skb_end_offset(skb)); |
---|
| 4283 | + err = virtqueue_add_inbuf(vq, sg, 1, skb, GFP_ATOMIC); |
---|
| 4284 | + if (WARN(err, "virtqueue_add_inbuf returned %d\n", err)) |
---|
| 4285 | + nlmsg_free(skb); |
---|
| 4286 | + else |
---|
| 4287 | + virtqueue_kick(vq); |
---|
| 4288 | + schedule_work(&hwsim_virtio_rx); |
---|
| 4289 | + |
---|
| 4290 | +out_unlock: |
---|
| 4291 | + spin_unlock_irqrestore(&hwsim_virtio_lock, flags); |
---|
| 4292 | +} |
---|
| 4293 | + |
---|
| 4294 | +static void hwsim_virtio_rx_done(struct virtqueue *vq) |
---|
| 4295 | +{ |
---|
| 4296 | + schedule_work(&hwsim_virtio_rx); |
---|
| 4297 | +} |
---|
| 4298 | + |
---|
| 4299 | +static int init_vqs(struct virtio_device *vdev) |
---|
| 4300 | +{ |
---|
| 4301 | + vq_callback_t *callbacks[HWSIM_NUM_VQS] = { |
---|
| 4302 | + [HWSIM_VQ_TX] = hwsim_virtio_tx_done, |
---|
| 4303 | + [HWSIM_VQ_RX] = hwsim_virtio_rx_done, |
---|
| 4304 | + }; |
---|
| 4305 | + const char *names[HWSIM_NUM_VQS] = { |
---|
| 4306 | + [HWSIM_VQ_TX] = "tx", |
---|
| 4307 | + [HWSIM_VQ_RX] = "rx", |
---|
| 4308 | + }; |
---|
| 4309 | + |
---|
| 4310 | + return virtio_find_vqs(vdev, HWSIM_NUM_VQS, |
---|
| 4311 | + hwsim_vqs, callbacks, names, NULL); |
---|
| 4312 | +} |
---|
| 4313 | + |
---|
| 4314 | +static int fill_vq(struct virtqueue *vq) |
---|
| 4315 | +{ |
---|
| 4316 | + int i, err; |
---|
| 4317 | + struct sk_buff *skb; |
---|
| 4318 | + struct scatterlist sg[1]; |
---|
| 4319 | + |
---|
| 4320 | + for (i = 0; i < virtqueue_get_vring_size(vq); i++) { |
---|
| 4321 | + skb = genlmsg_new(GENLMSG_DEFAULT_SIZE, GFP_KERNEL); |
---|
| 4322 | + if (!skb) |
---|
| 4323 | + return -ENOMEM; |
---|
| 4324 | + |
---|
| 4325 | + sg_init_one(sg, skb->head, skb_end_offset(skb)); |
---|
| 4326 | + err = virtqueue_add_inbuf(vq, sg, 1, skb, GFP_KERNEL); |
---|
| 4327 | + if (err) { |
---|
| 4328 | + nlmsg_free(skb); |
---|
| 4329 | + return err; |
---|
| 4330 | + } |
---|
| 4331 | + } |
---|
| 4332 | + virtqueue_kick(vq); |
---|
| 4333 | + return 0; |
---|
| 4334 | +} |
---|
| 4335 | + |
---|
| 4336 | +static void remove_vqs(struct virtio_device *vdev) |
---|
| 4337 | +{ |
---|
| 4338 | + int i; |
---|
| 4339 | + |
---|
| 4340 | + vdev->config->reset(vdev); |
---|
| 4341 | + |
---|
| 4342 | + for (i = 0; i < ARRAY_SIZE(hwsim_vqs); i++) { |
---|
| 4343 | + struct virtqueue *vq = hwsim_vqs[i]; |
---|
| 4344 | + struct sk_buff *skb; |
---|
| 4345 | + |
---|
| 4346 | + while ((skb = virtqueue_detach_unused_buf(vq))) |
---|
| 4347 | + nlmsg_free(skb); |
---|
| 4348 | + } |
---|
| 4349 | + |
---|
| 4350 | + vdev->config->del_vqs(vdev); |
---|
| 4351 | +} |
---|
| 4352 | + |
---|
| 4353 | +static int hwsim_virtio_probe(struct virtio_device *vdev) |
---|
| 4354 | +{ |
---|
| 4355 | + int err; |
---|
| 4356 | + unsigned long flags; |
---|
| 4357 | + |
---|
| 4358 | + spin_lock_irqsave(&hwsim_virtio_lock, flags); |
---|
| 4359 | + if (hwsim_virtio_enabled) { |
---|
| 4360 | + spin_unlock_irqrestore(&hwsim_virtio_lock, flags); |
---|
| 4361 | + return -EEXIST; |
---|
| 4362 | + } |
---|
| 4363 | + spin_unlock_irqrestore(&hwsim_virtio_lock, flags); |
---|
| 4364 | + |
---|
| 4365 | + err = init_vqs(vdev); |
---|
| 4366 | + if (err) |
---|
| 4367 | + return err; |
---|
| 4368 | + |
---|
| 4369 | + err = fill_vq(hwsim_vqs[HWSIM_VQ_RX]); |
---|
| 4370 | + if (err) |
---|
| 4371 | + goto out_remove; |
---|
| 4372 | + |
---|
| 4373 | + spin_lock_irqsave(&hwsim_virtio_lock, flags); |
---|
| 4374 | + hwsim_virtio_enabled = true; |
---|
| 4375 | + spin_unlock_irqrestore(&hwsim_virtio_lock, flags); |
---|
| 4376 | + |
---|
| 4377 | + schedule_work(&hwsim_virtio_rx); |
---|
| 4378 | + return 0; |
---|
| 4379 | + |
---|
| 4380 | +out_remove: |
---|
| 4381 | + remove_vqs(vdev); |
---|
| 4382 | + return err; |
---|
| 4383 | +} |
---|
| 4384 | + |
---|
| 4385 | +static void hwsim_virtio_remove(struct virtio_device *vdev) |
---|
| 4386 | +{ |
---|
| 4387 | + hwsim_virtio_enabled = false; |
---|
| 4388 | + |
---|
| 4389 | + cancel_work_sync(&hwsim_virtio_rx); |
---|
| 4390 | + |
---|
| 4391 | + remove_vqs(vdev); |
---|
| 4392 | +} |
---|
| 4393 | + |
---|
| 4394 | +/* MAC80211_HWSIM virtio device id table */ |
---|
| 4395 | +static const struct virtio_device_id id_table[] = { |
---|
| 4396 | + { VIRTIO_ID_MAC80211_HWSIM, VIRTIO_DEV_ANY_ID }, |
---|
| 4397 | + { 0 } |
---|
| 4398 | +}; |
---|
| 4399 | +MODULE_DEVICE_TABLE(virtio, id_table); |
---|
| 4400 | + |
---|
| 4401 | +static struct virtio_driver virtio_hwsim = { |
---|
| 4402 | + .driver.name = KBUILD_MODNAME, |
---|
| 4403 | + .driver.owner = THIS_MODULE, |
---|
| 4404 | + .id_table = id_table, |
---|
| 4405 | + .probe = hwsim_virtio_probe, |
---|
| 4406 | + .remove = hwsim_virtio_remove, |
---|
| 4407 | +}; |
---|
| 4408 | + |
---|
| 4409 | +static int hwsim_register_virtio_driver(void) |
---|
| 4410 | +{ |
---|
| 4411 | + spin_lock_init(&hwsim_virtio_lock); |
---|
| 4412 | + |
---|
| 4413 | + return register_virtio_driver(&virtio_hwsim); |
---|
| 4414 | +} |
---|
| 4415 | + |
---|
| 4416 | +static void hwsim_unregister_virtio_driver(void) |
---|
| 4417 | +{ |
---|
| 4418 | + unregister_virtio_driver(&virtio_hwsim); |
---|
| 4419 | +} |
---|
| 4420 | +#else |
---|
| 4421 | +static inline int hwsim_register_virtio_driver(void) |
---|
| 4422 | +{ |
---|
| 4423 | + return 0; |
---|
| 4424 | +} |
---|
| 4425 | + |
---|
| 4426 | +static inline void hwsim_unregister_virtio_driver(void) |
---|
| 4427 | +{ |
---|
| 4428 | +} |
---|
| 4429 | +#endif |
---|
| 4430 | + |
---|
3689 | 4431 | static int __init init_mac80211_hwsim(void) |
---|
3690 | 4432 | { |
---|
3691 | 4433 | int i, err; |
---|
.. | .. |
---|
3698 | 4440 | |
---|
3699 | 4441 | spin_lock_init(&hwsim_radio_lock); |
---|
3700 | 4442 | |
---|
3701 | | - hwsim_wq = alloc_workqueue("hwsim_wq", 0, 0); |
---|
3702 | | - if (!hwsim_wq) |
---|
3703 | | - return -ENOMEM; |
---|
3704 | | - |
---|
3705 | 4443 | err = rhashtable_init(&hwsim_radios_rht, &hwsim_rht_params); |
---|
3706 | 4444 | if (err) |
---|
3707 | | - goto out_free_wq; |
---|
| 4445 | + return err; |
---|
3708 | 4446 | |
---|
3709 | 4447 | err = register_pernet_device(&hwsim_net_ops); |
---|
3710 | 4448 | if (err) |
---|
.. | .. |
---|
3718 | 4456 | if (err) |
---|
3719 | 4457 | goto out_unregister_driver; |
---|
3720 | 4458 | |
---|
| 4459 | + err = hwsim_register_virtio_driver(); |
---|
| 4460 | + if (err) |
---|
| 4461 | + goto out_exit_netlink; |
---|
| 4462 | + |
---|
3721 | 4463 | hwsim_class = class_create(THIS_MODULE, "mac80211_hwsim"); |
---|
3722 | 4464 | if (IS_ERR(hwsim_class)) { |
---|
3723 | 4465 | err = PTR_ERR(hwsim_class); |
---|
3724 | | - goto out_exit_netlink; |
---|
| 4466 | + goto out_exit_virtio; |
---|
3725 | 4467 | } |
---|
| 4468 | + |
---|
| 4469 | + hwsim_init_s1g_channels(hwsim_channels_s1g); |
---|
3726 | 4470 | |
---|
3727 | 4471 | for (i = 0; i < radios; i++) { |
---|
3728 | 4472 | struct hwsim_new_radio_params param = { 0 }; |
---|
.. | .. |
---|
3740 | 4484 | break; |
---|
3741 | 4485 | case HWSIM_REGTEST_STRICT_ALL: |
---|
3742 | 4486 | param.reg_strict = true; |
---|
| 4487 | + fallthrough; |
---|
3743 | 4488 | case HWSIM_REGTEST_DRIVER_REG_ALL: |
---|
3744 | 4489 | param.reg_alpha2 = hwsim_alpha2s[0]; |
---|
3745 | 4490 | break; |
---|
.. | .. |
---|
3796 | 4541 | |
---|
3797 | 4542 | param.p2p_device = support_p2p_device; |
---|
3798 | 4543 | param.use_chanctx = channels > 1; |
---|
| 4544 | + param.iftypes = HWSIM_IFTYPE_SUPPORT_MASK; |
---|
| 4545 | + if (param.p2p_device) |
---|
| 4546 | + param.iftypes |= BIT(NL80211_IFTYPE_P2P_DEVICE); |
---|
3799 | 4547 | |
---|
3800 | 4548 | err = mac80211_hwsim_new_radio(NULL, ¶m); |
---|
3801 | 4549 | if (err < 0) |
---|
.. | .. |
---|
3813 | 4561 | err = dev_alloc_name(hwsim_mon, hwsim_mon->name); |
---|
3814 | 4562 | if (err < 0) { |
---|
3815 | 4563 | rtnl_unlock(); |
---|
3816 | | - goto out_free_radios; |
---|
| 4564 | + goto out_free_mon; |
---|
3817 | 4565 | } |
---|
3818 | 4566 | |
---|
3819 | 4567 | err = register_netdevice(hwsim_mon); |
---|
.. | .. |
---|
3829 | 4577 | free_netdev(hwsim_mon); |
---|
3830 | 4578 | out_free_radios: |
---|
3831 | 4579 | mac80211_hwsim_free(); |
---|
| 4580 | +out_exit_virtio: |
---|
| 4581 | + hwsim_unregister_virtio_driver(); |
---|
3832 | 4582 | out_exit_netlink: |
---|
3833 | 4583 | hwsim_exit_netlink(); |
---|
3834 | 4584 | out_unregister_driver: |
---|
.. | .. |
---|
3837 | 4587 | unregister_pernet_device(&hwsim_net_ops); |
---|
3838 | 4588 | out_free_rht: |
---|
3839 | 4589 | rhashtable_destroy(&hwsim_radios_rht); |
---|
3840 | | -out_free_wq: |
---|
3841 | | - destroy_workqueue(hwsim_wq); |
---|
3842 | 4590 | return err; |
---|
3843 | 4591 | } |
---|
3844 | 4592 | module_init(init_mac80211_hwsim); |
---|
.. | .. |
---|
3847 | 4595 | { |
---|
3848 | 4596 | pr_debug("mac80211_hwsim: unregister radios\n"); |
---|
3849 | 4597 | |
---|
| 4598 | + hwsim_unregister_virtio_driver(); |
---|
3850 | 4599 | hwsim_exit_netlink(); |
---|
3851 | 4600 | |
---|
3852 | 4601 | mac80211_hwsim_free(); |
---|
3853 | | - flush_workqueue(hwsim_wq); |
---|
3854 | 4602 | |
---|
3855 | 4603 | rhashtable_destroy(&hwsim_radios_rht); |
---|
3856 | 4604 | unregister_netdev(hwsim_mon); |
---|
3857 | 4605 | platform_driver_unregister(&mac80211_hwsim_driver); |
---|
3858 | 4606 | unregister_pernet_device(&hwsim_net_ops); |
---|
3859 | | - destroy_workqueue(hwsim_wq); |
---|
3860 | 4607 | } |
---|
3861 | 4608 | module_exit(exit_mac80211_hwsim); |
---|