Another set of changes:
* HE ranging (fine timing measurement) API support * hwsim gets virtio support, for use with wmediumd, to be able to simulate with multiple machines * eapol-over-nl80211 improvements to exclude preauth * IBSS reset support, to recover connections from userspace * and various others. -----BEGIN PGP SIGNATURE----- iQIzBAABCgAdFiEEH1e1rEeCd0AIMq6MB8qZga/fl8QFAl50yM8ACgkQB8qZga/f l8Qe0w//Rt5vsqlkiuZtg1SHQcMHq5Y6jJ92Xfg6Yw8H3H1g40r6UWDeSsF7Dl9H YuC4VvfNH/FhnNz01FDVxjgjnUyjpAolxM6sYj3hW3ZIBahSBeovAdjTP59y1Fhi zLMP/zYLsqtlKO5qr0fK7tUmENiF/IxyALRcxqsmQ1ul5003pIpFRVPoQVDTjHZn JCzDTboQLmtyYiDYjejaeauo4Awjj4lDiyk3Fu+kXSv8weY4dl+w8/AM5zsiVNDs 4HRDpJUBIwfwWuygMNwl0EQVhnpYaNQFQ+IEe9B29qiAEb95MPHhSudU1qaT+4d7 CykikhH39/n4Wv1PBg4PrCfWInxAUiPz6K027lDOY5VtJFFbLg8GqQkn3Vy/WnHm CJuVaLdJ73k7AypvWdZUgSe9SaloymVd987IIMixmz0t0cqIE3kPYot//kXFjy6m rqvWJ3a7SIopPdkD4xXDwzASUmctCUedQ0QVnWYRQCUW5rnkZ96SHjblUA9IykYS Ia44BwB8ggZsax1KrqyGV9hgj8mh9srLmEjtRPhxVD3ncE1ewiQaBRwv56J0EKNu yRnV10dNMCtUyT3j9dRpHa8zuNpS/A6ShXe4aGgoXAz+ShjNOBj2GxXtolsDJzrd zIqZH8gcWaeV+8yWhaGx8d82gvY8PhRvJl+AMax7Ds2avOZ/pa0= =t3QF -----END PGP SIGNATURE----- Merge tag 'mac80211-next-for-net-next-2020-03-20' of git://git.kernel.org/pub/scm/linux/kernel/git/jberg/mac80211-next Johannes Berg says: ==================== Another set of changes: * HE ranging (fine timing measurement) API support * hwsim gets virtio support, for use with wmediumd, to be able to simulate with multiple machines * eapol-over-nl80211 improvements to exclude preauth * IBSS reset support, to recover connections from userspace * and various others. ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
commit
0d7043f355
@ -4,7 +4,7 @@
|
||||
* Copyright (c) 2008, Jouni Malinen <j@w1.fi>
|
||||
* Copyright (c) 2011, Javier Lopez <jlopex@gmail.com>
|
||||
* Copyright (c) 2016 - 2017 Intel Deutschland GmbH
|
||||
* Copyright (C) 2018 Intel Corporation
|
||||
* Copyright (C) 2018 - 2020 Intel Corporation
|
||||
*/
|
||||
|
||||
/*
|
||||
@ -33,6 +33,9 @@
|
||||
#include <net/netns/generic.h>
|
||||
#include <linux/rhashtable.h>
|
||||
#include <linux/nospec.h>
|
||||
#include <linux/virtio.h>
|
||||
#include <linux/virtio_ids.h>
|
||||
#include <linux/virtio_config.h>
|
||||
#include "mac80211_hwsim.h"
|
||||
|
||||
#define WARN_QUEUE 100
|
||||
@ -613,14 +616,14 @@ static const struct genl_multicast_group hwsim_mcgrps[] = {
|
||||
/* MAC80211_HWSIM netlink policy */
|
||||
|
||||
static const struct nla_policy hwsim_genl_policy[HWSIM_ATTR_MAX + 1] = {
|
||||
[HWSIM_ATTR_ADDR_RECEIVER] = { .type = NLA_UNSPEC, .len = ETH_ALEN },
|
||||
[HWSIM_ATTR_ADDR_TRANSMITTER] = { .type = NLA_UNSPEC, .len = ETH_ALEN },
|
||||
[HWSIM_ATTR_ADDR_RECEIVER] = NLA_POLICY_ETH_ADDR_COMPAT,
|
||||
[HWSIM_ATTR_ADDR_TRANSMITTER] = NLA_POLICY_ETH_ADDR_COMPAT,
|
||||
[HWSIM_ATTR_FRAME] = { .type = NLA_BINARY,
|
||||
.len = IEEE80211_MAX_DATA_LEN },
|
||||
[HWSIM_ATTR_FLAGS] = { .type = NLA_U32 },
|
||||
[HWSIM_ATTR_RX_RATE] = { .type = NLA_U32 },
|
||||
[HWSIM_ATTR_SIGNAL] = { .type = NLA_U32 },
|
||||
[HWSIM_ATTR_TX_INFO] = { .type = NLA_UNSPEC,
|
||||
[HWSIM_ATTR_TX_INFO] = { .type = NLA_BINARY,
|
||||
.len = IEEE80211_TX_MAX_RATES *
|
||||
sizeof(struct hwsim_tx_rate)},
|
||||
[HWSIM_ATTR_COOKIE] = { .type = NLA_U64 },
|
||||
@ -630,15 +633,61 @@ static const struct nla_policy hwsim_genl_policy[HWSIM_ATTR_MAX + 1] = {
|
||||
[HWSIM_ATTR_REG_CUSTOM_REG] = { .type = NLA_U32 },
|
||||
[HWSIM_ATTR_REG_STRICT_REG] = { .type = NLA_FLAG },
|
||||
[HWSIM_ATTR_SUPPORT_P2P_DEVICE] = { .type = NLA_FLAG },
|
||||
[HWSIM_ATTR_USE_CHANCTX] = { .type = NLA_FLAG },
|
||||
[HWSIM_ATTR_DESTROY_RADIO_ON_CLOSE] = { .type = NLA_FLAG },
|
||||
[HWSIM_ATTR_RADIO_NAME] = { .type = NLA_STRING },
|
||||
[HWSIM_ATTR_NO_VIF] = { .type = NLA_FLAG },
|
||||
[HWSIM_ATTR_FREQ] = { .type = NLA_U32 },
|
||||
[HWSIM_ATTR_PERM_ADDR] = { .type = NLA_UNSPEC, .len = ETH_ALEN },
|
||||
[HWSIM_ATTR_TX_INFO_FLAGS] = { .type = NLA_BINARY },
|
||||
[HWSIM_ATTR_PERM_ADDR] = NLA_POLICY_ETH_ADDR_COMPAT,
|
||||
[HWSIM_ATTR_IFTYPE_SUPPORT] = { .type = NLA_U32 },
|
||||
[HWSIM_ATTR_CIPHER_SUPPORT] = { .type = NLA_BINARY },
|
||||
};
|
||||
|
||||
#if IS_REACHABLE(CONFIG_VIRTIO)
|
||||
|
||||
/* MAC80211_HWSIM virtio queues */
|
||||
static struct virtqueue *hwsim_vqs[HWSIM_NUM_VQS];
|
||||
static bool hwsim_virtio_enabled;
|
||||
static spinlock_t hwsim_virtio_lock;
|
||||
|
||||
static void hwsim_virtio_rx_work(struct work_struct *work);
|
||||
static DECLARE_WORK(hwsim_virtio_rx, hwsim_virtio_rx_work);
|
||||
|
||||
static int hwsim_tx_virtio(struct mac80211_hwsim_data *data,
|
||||
struct sk_buff *skb)
|
||||
{
|
||||
struct scatterlist sg[1];
|
||||
unsigned long flags;
|
||||
int err;
|
||||
|
||||
spin_lock_irqsave(&hwsim_virtio_lock, flags);
|
||||
if (!hwsim_virtio_enabled) {
|
||||
err = -ENODEV;
|
||||
goto out_free;
|
||||
}
|
||||
|
||||
sg_init_one(sg, skb->head, skb_end_offset(skb));
|
||||
err = virtqueue_add_outbuf(hwsim_vqs[HWSIM_VQ_TX], sg, 1, skb,
|
||||
GFP_ATOMIC);
|
||||
if (err)
|
||||
goto out_free;
|
||||
virtqueue_kick(hwsim_vqs[HWSIM_VQ_TX]);
|
||||
spin_unlock_irqrestore(&hwsim_virtio_lock, flags);
|
||||
return 0;
|
||||
|
||||
out_free:
|
||||
spin_unlock_irqrestore(&hwsim_virtio_lock, flags);
|
||||
nlmsg_free(skb);
|
||||
return err;
|
||||
}
|
||||
#else
|
||||
/* cause a linker error if this ends up being needed */
|
||||
extern int hwsim_tx_virtio(struct mac80211_hwsim_data *data,
|
||||
struct sk_buff *skb);
|
||||
#define hwsim_virtio_enabled false
|
||||
#endif
|
||||
|
||||
static void mac80211_hwsim_tx_frame(struct ieee80211_hw *hw,
|
||||
struct sk_buff *skb,
|
||||
struct ieee80211_channel *chan);
|
||||
@ -1138,8 +1187,14 @@ static void mac80211_hwsim_tx_frame_nl(struct ieee80211_hw *hw,
|
||||
goto nla_put_failure;
|
||||
|
||||
genlmsg_end(skb, msg_head);
|
||||
if (hwsim_unicast_netgroup(data, skb, dst_portid))
|
||||
goto err_free_txskb;
|
||||
|
||||
if (hwsim_virtio_enabled) {
|
||||
if (hwsim_tx_virtio(data, skb))
|
||||
goto err_free_txskb;
|
||||
} else {
|
||||
if (hwsim_unicast_netgroup(data, skb, dst_portid))
|
||||
goto err_free_txskb;
|
||||
}
|
||||
|
||||
/* Enqueue the packet */
|
||||
skb_queue_tail(&data->pending, my_skb);
|
||||
@ -1441,7 +1496,7 @@ static void mac80211_hwsim_tx(struct ieee80211_hw *hw,
|
||||
/* wmediumd mode check */
|
||||
_portid = READ_ONCE(data->wmediumd);
|
||||
|
||||
if (_portid)
|
||||
if (_portid || hwsim_virtio_enabled)
|
||||
return mac80211_hwsim_tx_frame_nl(hw, skb, _portid);
|
||||
|
||||
/* NO wmediumd detected, perfect medium simulation */
|
||||
@ -1547,7 +1602,7 @@ static void mac80211_hwsim_tx_frame(struct ieee80211_hw *hw,
|
||||
|
||||
mac80211_hwsim_monitor_rx(hw, skb, chan);
|
||||
|
||||
if (_pid)
|
||||
if (_pid || hwsim_virtio_enabled)
|
||||
return mac80211_hwsim_tx_frame_nl(hw, skb, _pid);
|
||||
|
||||
mac80211_hwsim_tx_frame_no_nl(hw, skb, chan);
|
||||
@ -3293,11 +3348,14 @@ static int hwsim_tx_info_frame_received_nl(struct sk_buff *skb_2,
|
||||
if (!data2)
|
||||
goto out;
|
||||
|
||||
if (hwsim_net_get_netgroup(genl_info_net(info)) != data2->netgroup)
|
||||
goto out;
|
||||
if (!hwsim_virtio_enabled) {
|
||||
if (hwsim_net_get_netgroup(genl_info_net(info)) !=
|
||||
data2->netgroup)
|
||||
goto out;
|
||||
|
||||
if (info->snd_portid != data2->wmediumd)
|
||||
goto out;
|
||||
if (info->snd_portid != data2->wmediumd)
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* look for the skb matching the cookie passed back from user */
|
||||
skb_queue_walk_safe(&data2->pending, skb, tmp) {
|
||||
@ -3387,11 +3445,14 @@ static int hwsim_cloned_frame_received_nl(struct sk_buff *skb_2,
|
||||
if (!data2)
|
||||
goto out;
|
||||
|
||||
if (hwsim_net_get_netgroup(genl_info_net(info)) != data2->netgroup)
|
||||
goto out;
|
||||
if (!hwsim_virtio_enabled) {
|
||||
if (hwsim_net_get_netgroup(genl_info_net(info)) !=
|
||||
data2->netgroup)
|
||||
goto out;
|
||||
|
||||
if (info->snd_portid != data2->wmediumd)
|
||||
goto out;
|
||||
if (info->snd_portid != data2->wmediumd)
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* check if radio is configured properly */
|
||||
|
||||
@ -3932,6 +3993,229 @@ static void hwsim_exit_netlink(void)
|
||||
genl_unregister_family(&hwsim_genl_family);
|
||||
}
|
||||
|
||||
#if IS_REACHABLE(CONFIG_VIRTIO)
|
||||
static void hwsim_virtio_tx_done(struct virtqueue *vq)
|
||||
{
|
||||
unsigned int len;
|
||||
struct sk_buff *skb;
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&hwsim_virtio_lock, flags);
|
||||
while ((skb = virtqueue_get_buf(vq, &len)))
|
||||
nlmsg_free(skb);
|
||||
spin_unlock_irqrestore(&hwsim_virtio_lock, flags);
|
||||
}
|
||||
|
||||
static int hwsim_virtio_handle_cmd(struct sk_buff *skb)
|
||||
{
|
||||
struct nlmsghdr *nlh;
|
||||
struct genlmsghdr *gnlh;
|
||||
struct nlattr *tb[HWSIM_ATTR_MAX + 1];
|
||||
struct genl_info info = {};
|
||||
int err;
|
||||
|
||||
nlh = nlmsg_hdr(skb);
|
||||
gnlh = nlmsg_data(nlh);
|
||||
err = genlmsg_parse(nlh, &hwsim_genl_family, tb, HWSIM_ATTR_MAX,
|
||||
hwsim_genl_policy, NULL);
|
||||
if (err) {
|
||||
pr_err_ratelimited("hwsim: genlmsg_parse returned %d\n", err);
|
||||
return err;
|
||||
}
|
||||
|
||||
info.attrs = tb;
|
||||
|
||||
switch (gnlh->cmd) {
|
||||
case HWSIM_CMD_FRAME:
|
||||
hwsim_cloned_frame_received_nl(skb, &info);
|
||||
break;
|
||||
case HWSIM_CMD_TX_INFO_FRAME:
|
||||
hwsim_tx_info_frame_received_nl(skb, &info);
|
||||
break;
|
||||
default:
|
||||
pr_err_ratelimited("hwsim: invalid cmd: %d\n", gnlh->cmd);
|
||||
return -EPROTO;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void hwsim_virtio_rx_work(struct work_struct *work)
|
||||
{
|
||||
struct virtqueue *vq;
|
||||
unsigned int len;
|
||||
struct sk_buff *skb;
|
||||
struct scatterlist sg[1];
|
||||
int err;
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&hwsim_virtio_lock, flags);
|
||||
if (!hwsim_virtio_enabled)
|
||||
goto out_unlock;
|
||||
|
||||
skb = virtqueue_get_buf(hwsim_vqs[HWSIM_VQ_RX], &len);
|
||||
if (!skb)
|
||||
goto out_unlock;
|
||||
spin_unlock_irqrestore(&hwsim_virtio_lock, flags);
|
||||
|
||||
skb->data = skb->head;
|
||||
skb_set_tail_pointer(skb, len);
|
||||
hwsim_virtio_handle_cmd(skb);
|
||||
|
||||
spin_lock_irqsave(&hwsim_virtio_lock, flags);
|
||||
if (!hwsim_virtio_enabled) {
|
||||
nlmsg_free(skb);
|
||||
goto out_unlock;
|
||||
}
|
||||
vq = hwsim_vqs[HWSIM_VQ_RX];
|
||||
sg_init_one(sg, skb->head, skb_end_offset(skb));
|
||||
err = virtqueue_add_inbuf(vq, sg, 1, skb, GFP_KERNEL);
|
||||
if (WARN(err, "virtqueue_add_inbuf returned %d\n", err))
|
||||
nlmsg_free(skb);
|
||||
else
|
||||
virtqueue_kick(vq);
|
||||
schedule_work(&hwsim_virtio_rx);
|
||||
|
||||
out_unlock:
|
||||
spin_unlock_irqrestore(&hwsim_virtio_lock, flags);
|
||||
}
|
||||
|
||||
static void hwsim_virtio_rx_done(struct virtqueue *vq)
|
||||
{
|
||||
schedule_work(&hwsim_virtio_rx);
|
||||
}
|
||||
|
||||
static int init_vqs(struct virtio_device *vdev)
|
||||
{
|
||||
vq_callback_t *callbacks[HWSIM_NUM_VQS] = {
|
||||
[HWSIM_VQ_TX] = hwsim_virtio_tx_done,
|
||||
[HWSIM_VQ_RX] = hwsim_virtio_rx_done,
|
||||
};
|
||||
const char *names[HWSIM_NUM_VQS] = {
|
||||
[HWSIM_VQ_TX] = "tx",
|
||||
[HWSIM_VQ_RX] = "rx",
|
||||
};
|
||||
|
||||
return virtio_find_vqs(vdev, HWSIM_NUM_VQS,
|
||||
hwsim_vqs, callbacks, names, NULL);
|
||||
}
|
||||
|
||||
static int fill_vq(struct virtqueue *vq)
|
||||
{
|
||||
int i, err;
|
||||
struct sk_buff *skb;
|
||||
struct scatterlist sg[1];
|
||||
|
||||
for (i = 0; i < virtqueue_get_vring_size(vq); i++) {
|
||||
skb = genlmsg_new(GENLMSG_DEFAULT_SIZE, GFP_KERNEL);
|
||||
if (!skb)
|
||||
return -ENOMEM;
|
||||
|
||||
sg_init_one(sg, skb->head, skb_end_offset(skb));
|
||||
err = virtqueue_add_inbuf(vq, sg, 1, skb, GFP_KERNEL);
|
||||
if (err) {
|
||||
nlmsg_free(skb);
|
||||
return err;
|
||||
}
|
||||
}
|
||||
virtqueue_kick(vq);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void remove_vqs(struct virtio_device *vdev)
|
||||
{
|
||||
int i;
|
||||
|
||||
vdev->config->reset(vdev);
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(hwsim_vqs); i++) {
|
||||
struct virtqueue *vq = hwsim_vqs[i];
|
||||
struct sk_buff *skb;
|
||||
|
||||
while ((skb = virtqueue_detach_unused_buf(vq)))
|
||||
nlmsg_free(skb);
|
||||
}
|
||||
|
||||
vdev->config->del_vqs(vdev);
|
||||
}
|
||||
|
||||
static int hwsim_virtio_probe(struct virtio_device *vdev)
|
||||
{
|
||||
int err;
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&hwsim_virtio_lock, flags);
|
||||
if (hwsim_virtio_enabled) {
|
||||
spin_unlock_irqrestore(&hwsim_virtio_lock, flags);
|
||||
return -EEXIST;
|
||||
}
|
||||
spin_unlock_irqrestore(&hwsim_virtio_lock, flags);
|
||||
|
||||
err = init_vqs(vdev);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
err = fill_vq(hwsim_vqs[HWSIM_VQ_RX]);
|
||||
if (err)
|
||||
goto out_remove;
|
||||
|
||||
spin_lock_irqsave(&hwsim_virtio_lock, flags);
|
||||
hwsim_virtio_enabled = true;
|
||||
spin_unlock_irqrestore(&hwsim_virtio_lock, flags);
|
||||
|
||||
schedule_work(&hwsim_virtio_rx);
|
||||
return 0;
|
||||
|
||||
out_remove:
|
||||
remove_vqs(vdev);
|
||||
return err;
|
||||
}
|
||||
|
||||
static void hwsim_virtio_remove(struct virtio_device *vdev)
|
||||
{
|
||||
hwsim_virtio_enabled = false;
|
||||
|
||||
cancel_work_sync(&hwsim_virtio_rx);
|
||||
|
||||
remove_vqs(vdev);
|
||||
}
|
||||
|
||||
/* MAC80211_HWSIM virtio device id table */
|
||||
static const struct virtio_device_id id_table[] = {
|
||||
{ VIRTIO_ID_MAC80211_HWSIM, VIRTIO_DEV_ANY_ID },
|
||||
{ 0 }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(virtio, id_table);
|
||||
|
||||
static struct virtio_driver virtio_hwsim = {
|
||||
.driver.name = KBUILD_MODNAME,
|
||||
.driver.owner = THIS_MODULE,
|
||||
.id_table = id_table,
|
||||
.probe = hwsim_virtio_probe,
|
||||
.remove = hwsim_virtio_remove,
|
||||
};
|
||||
|
||||
static int hwsim_register_virtio_driver(void)
|
||||
{
|
||||
spin_lock_init(&hwsim_virtio_lock);
|
||||
|
||||
return register_virtio_driver(&virtio_hwsim);
|
||||
}
|
||||
|
||||
static void hwsim_unregister_virtio_driver(void)
|
||||
{
|
||||
unregister_virtio_driver(&virtio_hwsim);
|
||||
}
|
||||
#else
|
||||
static inline int hwsim_register_virtio_driver(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline void hwsim_unregister_virtio_driver(void)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
static int __init init_mac80211_hwsim(void)
|
||||
{
|
||||
int i, err;
|
||||
@ -3960,10 +4244,14 @@ static int __init init_mac80211_hwsim(void)
|
||||
if (err)
|
||||
goto out_unregister_driver;
|
||||
|
||||
err = hwsim_register_virtio_driver();
|
||||
if (err)
|
||||
goto out_exit_netlink;
|
||||
|
||||
hwsim_class = class_create(THIS_MODULE, "mac80211_hwsim");
|
||||
if (IS_ERR(hwsim_class)) {
|
||||
err = PTR_ERR(hwsim_class);
|
||||
goto out_exit_netlink;
|
||||
goto out_exit_virtio;
|
||||
}
|
||||
|
||||
for (i = 0; i < radios; i++) {
|
||||
@ -4075,6 +4363,8 @@ out_free_mon:
|
||||
free_netdev(hwsim_mon);
|
||||
out_free_radios:
|
||||
mac80211_hwsim_free();
|
||||
out_exit_virtio:
|
||||
hwsim_unregister_virtio_driver();
|
||||
out_exit_netlink:
|
||||
hwsim_exit_netlink();
|
||||
out_unregister_driver:
|
||||
@ -4091,6 +4381,7 @@ static void __exit exit_mac80211_hwsim(void)
|
||||
{
|
||||
pr_debug("mac80211_hwsim: unregister radios\n");
|
||||
|
||||
hwsim_unregister_virtio_driver();
|
||||
hwsim_exit_netlink();
|
||||
|
||||
mac80211_hwsim_free();
|
||||
|
@ -3,6 +3,7 @@
|
||||
* mac80211_hwsim - software simulator of 802.11 radio(s) for mac80211
|
||||
* Copyright (c) 2008, Jouni Malinen <j@w1.fi>
|
||||
* Copyright (c) 2011, Javier Lopez <jlopex@gmail.com>
|
||||
* Copyright (C) 2020 Intel Corporation
|
||||
*/
|
||||
|
||||
#ifndef __MAC80211_HWSIM_H
|
||||
@ -245,4 +246,24 @@ struct hwsim_tx_rate_flag {
|
||||
s8 idx;
|
||||
u16 flags;
|
||||
} __packed;
|
||||
|
||||
/**
|
||||
* DOC: Frame transmission support over virtio
|
||||
*
|
||||
* Frame transmission is also supported over virtio to allow communication
|
||||
* with external entities.
|
||||
*/
|
||||
|
||||
/**
|
||||
* enum hwsim_vqs - queues for virtio frame transmission
|
||||
*
|
||||
* @HWSIM_VQ_TX: send frames to external entity
|
||||
* @HWSIM_VQ_RX: receive frames and transmission info reports
|
||||
* @HWSIM_NUM_VQS: enum limit
|
||||
*/
|
||||
enum {
|
||||
HWSIM_VQ_TX,
|
||||
HWSIM_VQ_RX,
|
||||
HWSIM_NUM_VQS,
|
||||
};
|
||||
#endif /* __MAC80211_HWSIM_H */
|
||||
|
@ -436,10 +436,18 @@ static int virt_wifi_net_device_stop(struct net_device *dev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int virt_wifi_net_device_get_iflink(const struct net_device *dev)
|
||||
{
|
||||
struct virt_wifi_netdev_priv *priv = netdev_priv(dev);
|
||||
|
||||
return priv->lowerdev->ifindex;
|
||||
}
|
||||
|
||||
static const struct net_device_ops virt_wifi_ops = {
|
||||
.ndo_start_xmit = virt_wifi_start_xmit,
|
||||
.ndo_open = virt_wifi_net_device_open,
|
||||
.ndo_stop = virt_wifi_net_device_stop,
|
||||
.ndo_open = virt_wifi_net_device_open,
|
||||
.ndo_stop = virt_wifi_net_device_stop,
|
||||
.ndo_get_iflink = virt_wifi_net_device_get_iflink,
|
||||
};
|
||||
|
||||
/* Invoked as part of rtnl lock release. */
|
||||
|
@ -7,7 +7,7 @@
|
||||
* Copyright 2006-2010 Johannes Berg <johannes@sipsolutions.net>
|
||||
* Copyright 2013-2014 Intel Mobile Communications GmbH
|
||||
* Copyright 2015-2017 Intel Deutschland GmbH
|
||||
* Copyright (C) 2018-2019 Intel Corporation
|
||||
* Copyright (C) 2018-2020 Intel Corporation
|
||||
*/
|
||||
|
||||
#include <linux/netdevice.h>
|
||||
@ -924,6 +924,7 @@ struct cfg80211_crypto_settings {
|
||||
__be16 control_port_ethertype;
|
||||
bool control_port_no_encrypt;
|
||||
bool control_port_over_nl80211;
|
||||
bool control_port_no_preauth;
|
||||
struct key_params *wep_keys;
|
||||
int wep_tx_key;
|
||||
const u8 *psk;
|
||||
@ -1054,6 +1055,7 @@ enum cfg80211_ap_settings_flags {
|
||||
* @flags: flags, as defined in enum cfg80211_ap_settings_flags
|
||||
* @he_obss_pd: OBSS Packet Detection settings
|
||||
* @he_bss_color: BSS Color settings
|
||||
* @he_oper: HE operation IE (or %NULL if HE isn't enabled)
|
||||
*/
|
||||
struct cfg80211_ap_settings {
|
||||
struct cfg80211_chan_def chandef;
|
||||
@ -1078,6 +1080,7 @@ struct cfg80211_ap_settings {
|
||||
const struct ieee80211_ht_cap *ht_cap;
|
||||
const struct ieee80211_vht_cap *vht_cap;
|
||||
const struct ieee80211_he_cap_elem *he_cap;
|
||||
const struct ieee80211_he_operation *he_oper;
|
||||
bool ht_required, vht_required;
|
||||
bool twt_responder;
|
||||
u32 flags;
|
||||
@ -2696,6 +2699,17 @@ enum wiphy_params_flags {
|
||||
* @cache_id: 2-octet cache identifier advertized by a FILS AP identifying the
|
||||
* scope of PMKSA. This is valid only if @ssid_len is non-zero (may be
|
||||
* %NULL).
|
||||
* @pmk_lifetime: Maximum lifetime for PMKSA in seconds
|
||||
* (dot11RSNAConfigPMKLifetime) or 0 if not specified.
|
||||
* The configured PMKSA must not be used for PMKSA caching after
|
||||
* expiration and any keys derived from this PMK become invalid on
|
||||
* expiration, i.e., the current association must be dropped if the PMK
|
||||
* used for it expires.
|
||||
* @pmk_reauth_threshold: Threshold time for reauthentication (percentage of
|
||||
* PMK lifetime, dot11RSNAConfigPMKReauthThreshold) or 0 if not specified.
|
||||
* Drivers are expected to trigger a full authentication instead of using
|
||||
* this PMKSA for caching when reassociating to a new BSS after this
|
||||
* threshold to generate a new PMK before the current one expires.
|
||||
*/
|
||||
struct cfg80211_pmksa {
|
||||
const u8 *bssid;
|
||||
@ -2705,6 +2719,8 @@ struct cfg80211_pmksa {
|
||||
const u8 *ssid;
|
||||
size_t ssid_len;
|
||||
const u8 *cache_id;
|
||||
u32 pmk_lifetime;
|
||||
u8 pmk_reauth_threshold;
|
||||
};
|
||||
|
||||
/**
|
||||
@ -3269,6 +3285,12 @@ struct cfg80211_pmsr_result {
|
||||
* @ftmr_retries: number of retries for FTM request
|
||||
* @request_lci: request LCI information
|
||||
* @request_civicloc: request civic location information
|
||||
* @trigger_based: use trigger based ranging for the measurement
|
||||
* If neither @trigger_based nor @non_trigger_based is set,
|
||||
* EDCA based ranging will be used.
|
||||
* @non_trigger_based: use non trigger based ranging for the measurement
|
||||
* If neither @trigger_based nor @non_trigger_based is set,
|
||||
* EDCA based ranging will be used.
|
||||
*
|
||||
* See also nl80211 for the respective attribute documentation.
|
||||
*/
|
||||
@ -3278,7 +3300,9 @@ struct cfg80211_pmsr_ftm_request_peer {
|
||||
u8 requested:1,
|
||||
asap:1,
|
||||
request_lci:1,
|
||||
request_civicloc:1;
|
||||
request_civicloc:1,
|
||||
trigger_based:1,
|
||||
non_trigger_based:1;
|
||||
u8 num_bursts_exp;
|
||||
u8 burst_duration;
|
||||
u8 ftms_per_burst;
|
||||
@ -3404,7 +3428,7 @@ struct cfg80211_update_owe_info {
|
||||
* @set_default_key: set the default key on an interface
|
||||
*
|
||||
* @set_default_mgmt_key: set the default management frame key on an interface
|
||||
|
||||
*
|
||||
* @set_default_beacon_key: set the default Beacon frame key on an interface
|
||||
*
|
||||
* @set_rekey_data: give the data necessary for GTK rekeying to the driver
|
||||
@ -4434,6 +4458,8 @@ struct wiphy_iftype_ext_capab {
|
||||
* forbid using the value 15 to let the responder pick)
|
||||
* @ftm.max_ftms_per_burst: maximum FTMs per burst supported (set to 0 if
|
||||
* not limited)
|
||||
* @ftm.trigger_based: trigger based ranging measurement is supported
|
||||
* @ftm.non_trigger_based: non trigger based ranging measurement is supported
|
||||
*/
|
||||
struct cfg80211_pmsr_capabilities {
|
||||
unsigned int max_peers;
|
||||
@ -4449,7 +4475,9 @@ struct cfg80211_pmsr_capabilities {
|
||||
asap:1,
|
||||
non_asap:1,
|
||||
request_lci:1,
|
||||
request_civicloc:1;
|
||||
request_civicloc:1,
|
||||
trigger_based:1,
|
||||
non_trigger_based:1;
|
||||
} ftm;
|
||||
};
|
||||
|
||||
|
@ -1987,6 +1987,7 @@ struct ieee80211_sta_txpwr {
|
||||
* @support_p2p_ps: indicates whether the STA supports P2P PS mechanism or not.
|
||||
* @max_rc_amsdu_len: Maximum A-MSDU size in bytes recommended by rate control.
|
||||
* @max_tid_amsdu_len: Maximum A-MSDU size in bytes for this TID
|
||||
* @txpwr: the station tx power configuration
|
||||
* @txq: per-TID data TX queues (if driver uses the TXQ abstraction); note that
|
||||
* the last entry (%IEEE80211_NUM_TIDS) is used for non-data frames
|
||||
*/
|
||||
@ -3451,6 +3452,10 @@ enum ieee80211_reconfig_type {
|
||||
* in AP mode, this callback will not be called when the flag
|
||||
* %IEEE80211_HW_AP_LINK_PS is set. Must be atomic.
|
||||
*
|
||||
* @sta_set_txpwr: Configure the station tx power. This callback set the tx
|
||||
* power for the station.
|
||||
* This callback can sleep.
|
||||
*
|
||||
* @sta_state: Notifies low level driver about state transition of a
|
||||
* station (which can be the AP, a client, IBSS/WDS/mesh peer etc.)
|
||||
* This callback is mutually exclusive with @sta_add/@sta_remove.
|
||||
|
@ -11,7 +11,7 @@
|
||||
* Copyright 2008 Jouni Malinen <jouni.malinen@atheros.com>
|
||||
* Copyright 2008 Colin McCabe <colin@cozybit.com>
|
||||
* Copyright 2015-2017 Intel Deutschland GmbH
|
||||
* Copyright (C) 2018-2019 Intel Corporation
|
||||
* Copyright (C) 2018-2020 Intel Corporation
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
@ -1632,7 +1632,8 @@ enum nl80211_commands {
|
||||
* flag is included, then control port frames are sent over NL80211 instead
|
||||
* using %CMD_CONTROL_PORT_FRAME. If control port routing over NL80211 is
|
||||
* to be used then userspace must also use the %NL80211_ATTR_SOCKET_OWNER
|
||||
* flag.
|
||||
* flag. When used with %NL80211_ATTR_CONTROL_PORT_NO_PREAUTH, pre-auth
|
||||
* frames are not forwared over the control port.
|
||||
*
|
||||
* @NL80211_ATTR_TESTDATA: Testmode data blob, passed through to the driver.
|
||||
* We recommend using nested, driver-specific attributes within this.
|
||||
@ -2442,6 +2443,33 @@ enum nl80211_commands {
|
||||
* on output (in wiphy attributes) it contains only the feature sub-
|
||||
* attributes.
|
||||
*
|
||||
* @NL80211_ATTR_CONTROL_PORT_NO_PREAUTH: disable preauth frame rx on control
|
||||
* port in order to forward/receive them as ordinary data frames.
|
||||
*
|
||||
* @NL80211_ATTR_PMK_LIFETIME: Maximum lifetime for PMKSA in seconds (u32,
|
||||
* dot11RSNAConfigPMKReauthThreshold; 0 is not a valid value).
|
||||
* An optional parameter configured through %NL80211_CMD_SET_PMKSA.
|
||||
* Drivers that trigger roaming need to know the lifetime of the
|
||||
* configured PMKSA for triggering the full vs. PMKSA caching based
|
||||
* authentication. This timeout helps authentication methods like SAE,
|
||||
* where PMK gets updated only by going through a full (new SAE)
|
||||
* authentication instead of getting updated during an association for EAP
|
||||
* authentication. No new full authentication within the PMK expiry shall
|
||||
* result in a disassociation at the end of the lifetime.
|
||||
*
|
||||
* @NL80211_ATTR_PMK_REAUTH_THRESHOLD: Reauthentication threshold time, in
|
||||
* terms of percentage of %NL80211_ATTR_PMK_LIFETIME
|
||||
* (u8, dot11RSNAConfigPMKReauthThreshold, 1..100). This is an optional
|
||||
* parameter configured through %NL80211_CMD_SET_PMKSA. Requests the
|
||||
* driver to trigger a full authentication roam (without PMKSA caching)
|
||||
* after the reauthentication threshold time, but before the PMK lifetime
|
||||
* has expired.
|
||||
*
|
||||
* Authentication methods like SAE need to be able to generate a new PMKSA
|
||||
* entry without having to force a disconnection after the PMK timeout. If
|
||||
* no roaming occurs between the reauth threshold and PMK expiration,
|
||||
* disassociation is still forced.
|
||||
*
|
||||
* @NUM_NL80211_ATTR: total number of nl80211_attrs available
|
||||
* @NL80211_ATTR_MAX: highest attribute number currently defined
|
||||
* @__NL80211_ATTR_AFTER_LAST: internal use
|
||||
@ -2912,6 +2940,11 @@ enum nl80211_attrs {
|
||||
|
||||
NL80211_ATTR_TID_CONFIG,
|
||||
|
||||
NL80211_ATTR_CONTROL_PORT_NO_PREAUTH,
|
||||
|
||||
NL80211_ATTR_PMK_LIFETIME,
|
||||
NL80211_ATTR_PMK_REAUTH_THRESHOLD,
|
||||
|
||||
/* add attributes here, update the policy in nl80211.c */
|
||||
|
||||
__NL80211_ATTR_AFTER_LAST,
|
||||
@ -5642,6 +5675,15 @@ enum nl80211_feature_flags {
|
||||
* @NL80211_EXT_FEATURE_BEACON_PROTECTION: The driver supports Beacon protection
|
||||
* and can receive key configuration for BIGTK using key indexes 6 and 7.
|
||||
*
|
||||
* @NL80211_EXT_FEATURE_CONTROL_PORT_NO_PREAUTH: The driver can disable the
|
||||
* forwarding of preauth frames over the control port. They are then
|
||||
* handled as ordinary data frames.
|
||||
*
|
||||
* @NL80211_EXT_FEATURE_PROTECTED_TWT: Driver supports protected TWT frames
|
||||
*
|
||||
* @NL80211_EXT_FEATURE_DEL_IBSS_STA: The driver supports removing stations
|
||||
* in IBSS mode, essentially by dropping their state.
|
||||
*
|
||||
* @NUM_NL80211_EXT_FEATURES: number of extended features.
|
||||
* @MAX_NL80211_EXT_FEATURES: highest extended feature index.
|
||||
*/
|
||||
@ -5690,6 +5732,9 @@ enum nl80211_ext_feature_index {
|
||||
NL80211_EXT_FEATURE_VLAN_OFFLOAD,
|
||||
NL80211_EXT_FEATURE_AQL,
|
||||
NL80211_EXT_FEATURE_BEACON_PROTECTION,
|
||||
NL80211_EXT_FEATURE_CONTROL_PORT_NO_PREAUTH,
|
||||
NL80211_EXT_FEATURE_PROTECTED_TWT,
|
||||
NL80211_EXT_FEATURE_DEL_IBSS_STA,
|
||||
|
||||
/* add new features before the definition below */
|
||||
NUM_NL80211_EXT_FEATURES,
|
||||
@ -6312,12 +6357,14 @@ enum nl80211_ftm_responder_stats {
|
||||
* @NL80211_PREAMBLE_HT: HT preamble
|
||||
* @NL80211_PREAMBLE_VHT: VHT preamble
|
||||
* @NL80211_PREAMBLE_DMG: DMG preamble
|
||||
* @NL80211_PREAMBLE_HE: HE preamble
|
||||
*/
|
||||
enum nl80211_preamble {
|
||||
NL80211_PREAMBLE_LEGACY,
|
||||
NL80211_PREAMBLE_HT,
|
||||
NL80211_PREAMBLE_VHT,
|
||||
NL80211_PREAMBLE_DMG,
|
||||
NL80211_PREAMBLE_HE,
|
||||
};
|
||||
|
||||
/**
|
||||
@ -6510,6 +6557,10 @@ enum nl80211_peer_measurement_attrs {
|
||||
* is valid)
|
||||
* @NL80211_PMSR_FTM_CAPA_ATTR_MAX_FTMS_PER_BURST: u32 attribute indicating
|
||||
* the maximum FTMs per burst (if not present anything is valid)
|
||||
* @NL80211_PMSR_FTM_CAPA_ATTR_TRIGGER_BASED: flag attribute indicating if
|
||||
* trigger based ranging measurement is supported
|
||||
* @NL80211_PMSR_FTM_CAPA_ATTR_NON_TRIGGER_BASED: flag attribute indicating
|
||||
* if non trigger based ranging measurement is supported
|
||||
*
|
||||
* @NUM_NL80211_PMSR_FTM_CAPA_ATTR: internal
|
||||
* @NL80211_PMSR_FTM_CAPA_ATTR_MAX: highest attribute number
|
||||
@ -6525,6 +6576,8 @@ enum nl80211_peer_measurement_ftm_capa {
|
||||
NL80211_PMSR_FTM_CAPA_ATTR_BANDWIDTHS,
|
||||
NL80211_PMSR_FTM_CAPA_ATTR_MAX_BURSTS_EXPONENT,
|
||||
NL80211_PMSR_FTM_CAPA_ATTR_MAX_FTMS_PER_BURST,
|
||||
NL80211_PMSR_FTM_CAPA_ATTR_TRIGGER_BASED,
|
||||
NL80211_PMSR_FTM_CAPA_ATTR_NON_TRIGGER_BASED,
|
||||
|
||||
/* keep last */
|
||||
NUM_NL80211_PMSR_FTM_CAPA_ATTR,
|
||||
@ -6554,6 +6607,20 @@ enum nl80211_peer_measurement_ftm_capa {
|
||||
* @NL80211_PMSR_FTM_REQ_ATTR_REQUEST_LCI: request LCI data (flag)
|
||||
* @NL80211_PMSR_FTM_REQ_ATTR_REQUEST_CIVICLOC: request civic location data
|
||||
* (flag)
|
||||
* @NL80211_PMSR_FTM_REQ_ATTR_TRIGGER_BASED: request trigger based ranging
|
||||
* measurement (flag).
|
||||
* This attribute and %NL80211_PMSR_FTM_REQ_ATTR_NON_TRIGGER_BASED are
|
||||
* mutually exclusive.
|
||||
* if neither %NL80211_PMSR_FTM_REQ_ATTR_TRIGGER_BASED nor
|
||||
* %NL80211_PMSR_FTM_REQ_ATTR_NON_TRIGGER_BASED is set, EDCA based
|
||||
* ranging will be used.
|
||||
* @NL80211_PMSR_FTM_REQ_ATTR_NON_TRIGGER_BASED: request non trigger based
|
||||
* ranging measurement (flag)
|
||||
* This attribute and %NL80211_PMSR_FTM_REQ_ATTR_TRIGGER_BASED are
|
||||
* mutually exclusive.
|
||||
* if neither %NL80211_PMSR_FTM_REQ_ATTR_TRIGGER_BASED nor
|
||||
* %NL80211_PMSR_FTM_REQ_ATTR_NON_TRIGGER_BASED is set, EDCA based
|
||||
* ranging will be used.
|
||||
*
|
||||
* @NUM_NL80211_PMSR_FTM_REQ_ATTR: internal
|
||||
* @NL80211_PMSR_FTM_REQ_ATTR_MAX: highest attribute number
|
||||
@ -6570,6 +6637,8 @@ enum nl80211_peer_measurement_ftm_req {
|
||||
NL80211_PMSR_FTM_REQ_ATTR_NUM_FTMR_RETRIES,
|
||||
NL80211_PMSR_FTM_REQ_ATTR_REQUEST_LCI,
|
||||
NL80211_PMSR_FTM_REQ_ATTR_REQUEST_CIVICLOC,
|
||||
NL80211_PMSR_FTM_REQ_ATTR_TRIGGER_BASED,
|
||||
NL80211_PMSR_FTM_REQ_ATTR_NON_TRIGGER_BASED,
|
||||
|
||||
/* keep last */
|
||||
NUM_NL80211_PMSR_FTM_REQ_ATTR,
|
||||
|
@ -46,5 +46,6 @@
|
||||
#define VIRTIO_ID_IOMMU 23 /* virtio IOMMU */
|
||||
#define VIRTIO_ID_FS 26 /* virtio filesystem */
|
||||
#define VIRTIO_ID_PMEM 27 /* virtio pmem */
|
||||
#define VIRTIO_ID_MAC80211_HWSIM 29 /* virtio mac80211-hwsim */
|
||||
|
||||
#endif /* _LINUX_VIRTIO_IDS_H */
|
||||
|
@ -5,8 +5,7 @@
|
||||
* Copyright 2006-2010 Johannes Berg <johannes@sipsolutions.net>
|
||||
* Copyright 2013-2015 Intel Mobile Communications GmbH
|
||||
* Copyright (C) 2015-2017 Intel Deutschland GmbH
|
||||
* Copyright (C) 2018-2019 Intel Corporation
|
||||
* Copyright (C) 2018 Intel Corporation
|
||||
* Copyright (C) 2018-2020 Intel Corporation
|
||||
*/
|
||||
|
||||
#include <linux/ieee80211.h>
|
||||
@ -1012,8 +1011,15 @@ static int ieee80211_start_ap(struct wiphy *wiphy, struct net_device *dev,
|
||||
prev_beacon_int = sdata->vif.bss_conf.beacon_int;
|
||||
sdata->vif.bss_conf.beacon_int = params->beacon_interval;
|
||||
|
||||
if (params->he_cap)
|
||||
if (params->he_cap && params->he_oper) {
|
||||
sdata->vif.bss_conf.he_support = true;
|
||||
sdata->vif.bss_conf.htc_trig_based_pkt_ext =
|
||||
le32_get_bits(params->he_oper->he_oper_params,
|
||||
IEEE80211_HE_OPERATION_DFLT_PE_DURATION_MASK);
|
||||
sdata->vif.bss_conf.frame_time_rts_th =
|
||||
le32_get_bits(params->he_oper->he_oper_params,
|
||||
IEEE80211_HE_OPERATION_RTS_THRESHOLD_MASK);
|
||||
}
|
||||
|
||||
mutex_lock(&local->mtx);
|
||||
err = ieee80211_vif_use_channel(sdata, ¶ms->chandef,
|
||||
@ -1034,6 +1040,8 @@ static int ieee80211_start_ap(struct wiphy *wiphy, struct net_device *dev,
|
||||
sdata->control_port_no_encrypt = params->crypto.control_port_no_encrypt;
|
||||
sdata->control_port_over_nl80211 =
|
||||
params->crypto.control_port_over_nl80211;
|
||||
sdata->control_port_no_preauth =
|
||||
params->crypto.control_port_no_preauth;
|
||||
sdata->encrypt_headroom = ieee80211_cs_headroom(sdata->local,
|
||||
¶ms->crypto,
|
||||
sdata->vif.type);
|
||||
@ -1045,6 +1053,8 @@ static int ieee80211_start_ap(struct wiphy *wiphy, struct net_device *dev,
|
||||
params->crypto.control_port_no_encrypt;
|
||||
vlan->control_port_over_nl80211 =
|
||||
params->crypto.control_port_over_nl80211;
|
||||
vlan->control_port_no_preauth =
|
||||
params->crypto.control_port_no_preauth;
|
||||
vlan->encrypt_headroom =
|
||||
ieee80211_cs_headroom(sdata->local,
|
||||
¶ms->crypto,
|
||||
|
@ -912,6 +912,7 @@ struct ieee80211_sub_if_data {
|
||||
u16 sequence_number;
|
||||
__be16 control_port_protocol;
|
||||
bool control_port_no_encrypt;
|
||||
bool control_port_no_preauth;
|
||||
bool control_port_over_nl80211;
|
||||
int encrypt_headroom;
|
||||
|
||||
|
@ -519,6 +519,8 @@ int ieee80211_do_open(struct wireless_dev *wdev, bool coming_up)
|
||||
master->control_port_no_encrypt;
|
||||
sdata->control_port_over_nl80211 =
|
||||
master->control_port_over_nl80211;
|
||||
sdata->control_port_no_preauth =
|
||||
master->control_port_no_preauth;
|
||||
sdata->vif.cab_queue = master->vif.cab_queue;
|
||||
memcpy(sdata->vif.hw_queue, master->vif.hw_queue,
|
||||
sizeof(sdata->vif.hw_queue));
|
||||
@ -1463,6 +1465,8 @@ static void ieee80211_setup_sdata(struct ieee80211_sub_if_data *sdata,
|
||||
|
||||
sdata->control_port_protocol = cpu_to_be16(ETH_P_PAE);
|
||||
sdata->control_port_no_encrypt = false;
|
||||
sdata->control_port_over_nl80211 = false;
|
||||
sdata->control_port_no_preauth = false;
|
||||
sdata->encrypt_headroom = IEEE80211_ENCRYPT_HEADROOM;
|
||||
sdata->vif.bss_conf.idle = true;
|
||||
sdata->vif.bss_conf.txpower = INT_MIN; /* unset */
|
||||
|
@ -576,7 +576,7 @@ struct ieee80211_hw *ieee80211_alloc_hw_nm(size_t priv_data_len,
|
||||
WIPHY_FLAG_REPORTS_OBSS |
|
||||
WIPHY_FLAG_OFFCHAN_TX;
|
||||
|
||||
if (ops->remain_on_channel)
|
||||
if (!use_chanctx || ops->remain_on_channel)
|
||||
wiphy->flags |= WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL;
|
||||
|
||||
wiphy->features |= NL80211_FEATURE_SK_TX_STATUS |
|
||||
@ -589,6 +589,8 @@ struct ieee80211_hw *ieee80211_alloc_hw_nm(size_t priv_data_len,
|
||||
wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_FILS_STA);
|
||||
wiphy_ext_feature_set(wiphy,
|
||||
NL80211_EXT_FEATURE_CONTROL_PORT_OVER_NL80211);
|
||||
wiphy_ext_feature_set(wiphy,
|
||||
NL80211_EXT_FEATURE_CONTROL_PORT_NO_PREAUTH);
|
||||
|
||||
if (!ops->hw_scan) {
|
||||
wiphy->features |= NL80211_FEATURE_LOW_PRIORITY_SCAN |
|
||||
@ -1081,6 +1083,10 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
|
||||
NL80211_EXT_FEATURE_EXT_KEY_ID);
|
||||
}
|
||||
|
||||
if (local->hw.wiphy->interface_modes & BIT(NL80211_IFTYPE_ADHOC))
|
||||
wiphy_ext_feature_set(local->hw.wiphy,
|
||||
NL80211_EXT_FEATURE_DEL_IBSS_STA);
|
||||
|
||||
/*
|
||||
* Calculate scan IE length -- we need this to alloc
|
||||
* memory and to subtract from the driver limit. It
|
||||
|
@ -5458,6 +5458,7 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata,
|
||||
sdata->control_port_no_encrypt = req->crypto.control_port_no_encrypt;
|
||||
sdata->control_port_over_nl80211 =
|
||||
req->crypto.control_port_over_nl80211;
|
||||
sdata->control_port_no_preauth = req->crypto.control_port_no_preauth;
|
||||
sdata->encrypt_headroom = ieee80211_cs_headroom(local, &req->crypto,
|
||||
sdata->vif.type);
|
||||
|
||||
|
@ -2497,7 +2497,8 @@ static void ieee80211_deliver_skb_to_local_stack(struct sk_buff *skb,
|
||||
struct net_device *dev = sdata->dev;
|
||||
|
||||
if (unlikely((skb->protocol == sdata->control_port_protocol ||
|
||||
skb->protocol == cpu_to_be16(ETH_P_PREAUTH)) &&
|
||||
(skb->protocol == cpu_to_be16(ETH_P_PREAUTH) &&
|
||||
!sdata->control_port_no_preauth)) &&
|
||||
sdata->control_port_over_nl80211)) {
|
||||
struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb);
|
||||
bool noencrypt = !(status->flag & RX_FLAG_DECRYPTED);
|
||||
|
@ -2150,19 +2150,41 @@ static int sta_set_rate_info_rx(struct sta_info *sta, struct rate_info *rinfo)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline u64 sta_get_tidstats_msdu(struct ieee80211_sta_rx_stats *rxstats,
|
||||
int tid)
|
||||
{
|
||||
unsigned int start;
|
||||
u64 value;
|
||||
|
||||
do {
|
||||
start = u64_stats_fetch_begin(&rxstats->syncp);
|
||||
value = rxstats->msdu[tid];
|
||||
} while (u64_stats_fetch_retry(&rxstats->syncp, start));
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
static void sta_set_tidstats(struct sta_info *sta,
|
||||
struct cfg80211_tid_stats *tidstats,
|
||||
int tid)
|
||||
{
|
||||
struct ieee80211_local *local = sta->local;
|
||||
int cpu;
|
||||
|
||||
if (!(tidstats->filled & BIT(NL80211_TID_STATS_RX_MSDU))) {
|
||||
unsigned int start;
|
||||
if (!ieee80211_hw_check(&local->hw, USES_RSS))
|
||||
tidstats->rx_msdu +=
|
||||
sta_get_tidstats_msdu(&sta->rx_stats, tid);
|
||||
|
||||
do {
|
||||
start = u64_stats_fetch_begin(&sta->rx_stats.syncp);
|
||||
tidstats->rx_msdu = sta->rx_stats.msdu[tid];
|
||||
} while (u64_stats_fetch_retry(&sta->rx_stats.syncp, start));
|
||||
if (sta->pcpu_rx_stats) {
|
||||
for_each_possible_cpu(cpu) {
|
||||
struct ieee80211_sta_rx_stats *cpurxs;
|
||||
|
||||
cpurxs = per_cpu_ptr(sta->pcpu_rx_stats, cpu);
|
||||
tidstats->rx_msdu +=
|
||||
sta_get_tidstats_msdu(cpurxs, tid);
|
||||
}
|
||||
}
|
||||
|
||||
tidstats->filled |= BIT(NL80211_TID_STATS_RX_MSDU);
|
||||
}
|
||||
@ -2266,7 +2288,8 @@ void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo,
|
||||
|
||||
if (!(sinfo->filled & (BIT_ULL(NL80211_STA_INFO_RX_BYTES64) |
|
||||
BIT_ULL(NL80211_STA_INFO_RX_BYTES)))) {
|
||||
sinfo->rx_bytes += sta_get_stats_bytes(&sta->rx_stats);
|
||||
if (!ieee80211_hw_check(&local->hw, USES_RSS))
|
||||
sinfo->rx_bytes += sta_get_stats_bytes(&sta->rx_stats);
|
||||
|
||||
if (sta->pcpu_rx_stats) {
|
||||
for_each_possible_cpu(cpu) {
|
||||
|
@ -4670,6 +4670,7 @@ static int ieee80211_beacon_protect(struct sk_buff *skb,
|
||||
{
|
||||
ieee80211_tx_result res;
|
||||
struct ieee80211_tx_data tx;
|
||||
struct sk_buff *check_skb;
|
||||
|
||||
memset(&tx, 0, sizeof(tx));
|
||||
tx.key = rcu_dereference(sdata->default_beacon_key);
|
||||
@ -4680,8 +4681,11 @@ static int ieee80211_beacon_protect(struct sk_buff *skb,
|
||||
__skb_queue_head_init(&tx.skbs);
|
||||
__skb_queue_tail(&tx.skbs, skb);
|
||||
res = ieee80211_tx_h_encrypt(&tx);
|
||||
check_skb = __skb_dequeue(&tx.skbs);
|
||||
/* we may crash after this, but it'd be a bug in crypto */
|
||||
WARN_ON(check_skb != skb);
|
||||
if (WARN_ON_ONCE(res != TX_CONTINUE))
|
||||
return -1;
|
||||
return -EINVAL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -912,8 +912,12 @@ static void ieee80211_parse_extension_element(u32 *crc,
|
||||
break;
|
||||
case WLAN_EID_EXT_HE_OPERATION:
|
||||
if (len >= sizeof(*elems->he_operation) &&
|
||||
len == ieee80211_he_oper_size(data) - 1)
|
||||
len == ieee80211_he_oper_size(data) - 1) {
|
||||
if (crc)
|
||||
*crc = crc32_be(*crc, (void *)elem,
|
||||
elem->datalen + 2);
|
||||
elems->he_operation = data;
|
||||
}
|
||||
break;
|
||||
case WLAN_EID_EXT_UORA:
|
||||
if (len == 1)
|
||||
|
@ -693,8 +693,14 @@ int wiphy_register(struct wiphy *wiphy)
|
||||
~(BIT(NL80211_PREAMBLE_LEGACY) |
|
||||
BIT(NL80211_PREAMBLE_HT) |
|
||||
BIT(NL80211_PREAMBLE_VHT) |
|
||||
BIT(NL80211_PREAMBLE_HE) |
|
||||
BIT(NL80211_PREAMBLE_DMG))))
|
||||
return -EINVAL;
|
||||
if (WARN_ON((wiphy->pmsr_capa->ftm.trigger_based ||
|
||||
wiphy->pmsr_capa->ftm.non_trigger_based) &&
|
||||
!(wiphy->pmsr_capa->ftm.preambles &
|
||||
BIT(NL80211_PREAMBLE_HE))))
|
||||
return -EINVAL;
|
||||
if (WARN_ON(wiphy->pmsr_capa->ftm.bandwidths &
|
||||
~(BIT(NL80211_CHAN_WIDTH_20_NOHT) |
|
||||
BIT(NL80211_CHAN_WIDTH_20) |
|
||||
|
@ -5,7 +5,7 @@
|
||||
* Copyright 2006-2010 Johannes Berg <johannes@sipsolutions.net>
|
||||
* Copyright 2013-2014 Intel Mobile Communications GmbH
|
||||
* Copyright 2015-2017 Intel Deutschland GmbH
|
||||
* Copyright (C) 2018-2019 Intel Corporation
|
||||
* Copyright (C) 2018-2020 Intel Corporation
|
||||
*/
|
||||
|
||||
#include <linux/if.h>
|
||||
@ -276,6 +276,8 @@ nl80211_pmsr_ftm_req_attr_policy[NL80211_PMSR_FTM_REQ_ATTR_MAX + 1] = {
|
||||
[NL80211_PMSR_FTM_REQ_ATTR_NUM_FTMR_RETRIES] = { .type = NLA_U8 },
|
||||
[NL80211_PMSR_FTM_REQ_ATTR_REQUEST_LCI] = { .type = NLA_FLAG },
|
||||
[NL80211_PMSR_FTM_REQ_ATTR_REQUEST_CIVICLOC] = { .type = NLA_FLAG },
|
||||
[NL80211_PMSR_FTM_REQ_ATTR_TRIGGER_BASED] = { .type = NLA_FLAG },
|
||||
[NL80211_PMSR_FTM_REQ_ATTR_NON_TRIGGER_BASED] = { .type = NLA_FLAG },
|
||||
};
|
||||
|
||||
static const struct nla_policy
|
||||
@ -658,6 +660,9 @@ const struct nla_policy nl80211_policy[NUM_NL80211_ATTR] = {
|
||||
[NL80211_ATTR_HE_BSS_COLOR] = NLA_POLICY_NESTED(he_bss_color_policy),
|
||||
[NL80211_ATTR_TID_CONFIG] =
|
||||
NLA_POLICY_NESTED_ARRAY(nl80211_tid_config_attr_policy),
|
||||
[NL80211_ATTR_CONTROL_PORT_NO_PREAUTH] = { .type = NLA_FLAG },
|
||||
[NL80211_ATTR_PMK_LIFETIME] = NLA_POLICY_MIN(NLA_U32, 1),
|
||||
[NL80211_ATTR_PMK_REAUTH_THRESHOLD] = NLA_POLICY_RANGE(NLA_U8, 1, 100),
|
||||
};
|
||||
|
||||
/* policy for the key attributes */
|
||||
@ -1884,6 +1889,12 @@ nl80211_send_pmsr_ftm_capa(const struct cfg80211_pmsr_capabilities *cap,
|
||||
nla_put_u32(msg, NL80211_PMSR_FTM_CAPA_ATTR_MAX_FTMS_PER_BURST,
|
||||
cap->ftm.max_ftms_per_burst))
|
||||
return -ENOBUFS;
|
||||
if (cap->ftm.trigger_based &&
|
||||
nla_put_flag(msg, NL80211_PMSR_FTM_CAPA_ATTR_TRIGGER_BASED))
|
||||
return -ENOBUFS;
|
||||
if (cap->ftm.non_trigger_based &&
|
||||
nla_put_flag(msg, NL80211_PMSR_FTM_CAPA_ATTR_NON_TRIGGER_BASED))
|
||||
return -ENOBUFS;
|
||||
|
||||
nla_nest_end(msg, ftm);
|
||||
return 0;
|
||||
@ -4748,6 +4759,9 @@ static void nl80211_calculate_ap_params(struct cfg80211_ap_settings *params)
|
||||
cap = cfg80211_find_ext_ie(WLAN_EID_EXT_HE_CAPABILITY, ies, ies_len);
|
||||
if (cap && cap[1] >= sizeof(*params->he_cap) + 1)
|
||||
params->he_cap = (void *)(cap + 3);
|
||||
cap = cfg80211_find_ext_ie(WLAN_EID_EXT_HE_OPERATION, ies, ies_len);
|
||||
if (cap && cap[1] >= sizeof(*params->he_oper) + 1)
|
||||
params->he_oper = (void *)(cap + 3);
|
||||
}
|
||||
|
||||
static bool nl80211_get_ap_channel(struct cfg80211_registered_device *rdev,
|
||||
@ -6271,11 +6285,22 @@ static int nl80211_del_station(struct sk_buff *skb, struct genl_info *info)
|
||||
if (info->attrs[NL80211_ATTR_MAC])
|
||||
params.mac = nla_data(info->attrs[NL80211_ATTR_MAC]);
|
||||
|
||||
if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP &&
|
||||
dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP_VLAN &&
|
||||
dev->ieee80211_ptr->iftype != NL80211_IFTYPE_MESH_POINT &&
|
||||
dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO)
|
||||
switch (dev->ieee80211_ptr->iftype) {
|
||||
case NL80211_IFTYPE_AP:
|
||||
case NL80211_IFTYPE_AP_VLAN:
|
||||
case NL80211_IFTYPE_MESH_POINT:
|
||||
case NL80211_IFTYPE_P2P_GO:
|
||||
/* always accept these */
|
||||
break;
|
||||
case NL80211_IFTYPE_ADHOC:
|
||||
/* conditionally accept */
|
||||
if (wiphy_ext_feature_isset(&rdev->wiphy,
|
||||
NL80211_EXT_FEATURE_DEL_IBSS_STA))
|
||||
break;
|
||||
return -EINVAL;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (!rdev->ops->del_station)
|
||||
return -EOPNOTSUPP;
|
||||
@ -9306,6 +9331,9 @@ static int nl80211_crypto_settings(struct cfg80211_registered_device *rdev,
|
||||
return r;
|
||||
|
||||
settings->control_port_over_nl80211 = true;
|
||||
|
||||
if (info->attrs[NL80211_ATTR_CONTROL_PORT_NO_PREAUTH])
|
||||
settings->control_port_no_preauth = true;
|
||||
}
|
||||
|
||||
if (info->attrs[NL80211_ATTR_CIPHER_SUITES_PAIRWISE]) {
|
||||
@ -10494,6 +10522,15 @@ static int nl80211_setdel_pmksa(struct sk_buff *skb, struct genl_info *info)
|
||||
pmksa.pmk_len = nla_len(info->attrs[NL80211_ATTR_PMK]);
|
||||
}
|
||||
|
||||
if (info->attrs[NL80211_ATTR_PMK_LIFETIME])
|
||||
pmksa.pmk_lifetime =
|
||||
nla_get_u32(info->attrs[NL80211_ATTR_PMK_LIFETIME]);
|
||||
|
||||
if (info->attrs[NL80211_ATTR_PMK_REAUTH_THRESHOLD])
|
||||
pmksa.pmk_reauth_threshold =
|
||||
nla_get_u8(
|
||||
info->attrs[NL80211_ATTR_PMK_REAUTH_THRESHOLD]);
|
||||
|
||||
if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_STATION &&
|
||||
dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_CLIENT &&
|
||||
!(dev->ieee80211_ptr->iftype == NL80211_IFTYPE_AP &&
|
||||
|
@ -126,6 +126,38 @@ static int pmsr_parse_ftm(struct cfg80211_registered_device *rdev,
|
||||
"FTM: civic location request not supported");
|
||||
}
|
||||
|
||||
out->ftm.trigger_based =
|
||||
!!tb[NL80211_PMSR_FTM_REQ_ATTR_TRIGGER_BASED];
|
||||
if (out->ftm.trigger_based && !capa->ftm.trigger_based) {
|
||||
NL_SET_ERR_MSG_ATTR(info->extack,
|
||||
tb[NL80211_PMSR_FTM_REQ_ATTR_TRIGGER_BASED],
|
||||
"FTM: trigger based ranging is not supported");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
out->ftm.non_trigger_based =
|
||||
!!tb[NL80211_PMSR_FTM_REQ_ATTR_NON_TRIGGER_BASED];
|
||||
if (out->ftm.non_trigger_based && !capa->ftm.non_trigger_based) {
|
||||
NL_SET_ERR_MSG_ATTR(info->extack,
|
||||
tb[NL80211_PMSR_FTM_REQ_ATTR_NON_TRIGGER_BASED],
|
||||
"FTM: trigger based ranging is not supported");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (out->ftm.trigger_based && out->ftm.non_trigger_based) {
|
||||
NL_SET_ERR_MSG(info->extack,
|
||||
"FTM: can't set both trigger based and non trigger based");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if ((out->ftm.trigger_based || out->ftm.non_trigger_based) &&
|
||||
out->ftm.preamble != NL80211_PREAMBLE_HE) {
|
||||
NL_SET_ERR_MSG_ATTR(info->extack,
|
||||
tb[NL80211_PMSR_FTM_REQ_ATTR_PREAMBLE],
|
||||
"FTM: non EDCA based ranging must use HE preamble");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user