All of lore.kernel.org
 help / color / mirror / Atom feed
From: Javier Cardona <javier@cozybit.com>
To: Javier Lopez <jlopex@gmail.com>
Cc: linux-wireless@vger.kernel.org
Subject: Re: [PATCH] mac80211_hwsim driver support userspace frame tx/rx
Date: Mon, 18 Apr 2011 19:19:05 -0700	[thread overview]
Message-ID: <BANLkTi=_snQBSFH-d344bjk8-aSeC9Jh5w@mail.gmail.com> (raw)
In-Reply-To: <1303159510-2548-1-git-send-email-jlopex@gmail.com>

On Mon, Apr 18, 2011 at 1:45 PM, Javier Lopez <jlopex@gmail.com> wrote:
> This patch adds the capability to hwsim to send traffic via userspace.
>
> Frame exchange between kernel and userspace is done through a generic
> netlink communication protocol, a new family called HWSIM is proposed
> in order to communicate with userspace applications. This family
> contains three basic commands; HWSIM_CMD_REGISTER which is used to
> register a userspace application with this driver, HWSIM_CMD_FRAME to
> exchange frames from kernel to user and vice-versa, and  finally
> HWSIM_CMD_TX_INFO_FRAME which returns to the kernel all the information
> about a frame transmission over the medium, number of tries, rates,
> ack signal and so on.
>
> How it works:
>
> Once the driver is loaded, it registers the HWSIM generic netlink
> family. In the absence of a daemon the driver implements a perfect
> wireless medium in the kernel as it did in the past. Once a daemon a
> registers itself via HWSIM_CMD_REGISTER, the kernel module stores the
> daemon PID and from this moment all frames will be sent to the daemon.
>
> The userspace application will be in charge of process/forward all
> frames broadcast by any radio using the mac80211_hwsim driver. If the
> user application is stopped the module will switch back to in-kernel
> perfect channel simulation. This transmission of kernel to user space
> is done through the HWSIM_CMD_FRAME command.
>
> The userspace application once sends the HWSIM_CMD_REGISTER, waits
> for incoming messages from kernel, for each HWSIM_CMD_FRAME command
> received, the application will try to broadcast it, cloning the frame
> to all known mac80211_hwsim radios. The daemon may decide to send or
> drop this frame. In the case of sending a frame back to kernel, the
> daemon will create a new HWSIM_CMD_FRAME command, fill the necessary
> attributes and send it back. In the case of a frame drop, the example
> userspace daemon retransmits frames according to the ieee80211_tx_info
> values received from the kernel.
>
> After each frame complete transmission a HWSIM_CMD_TX_INFO command
> may be sent to the kernel to inform about the tx status, this command
> contains information such as number of tries, rates, ack'ed or not
> ack'ed, ack_signal, etc.
>
> If you want to test the actual implementation of the wireless medium
> daemon (wmediumd) and test this patch, just get it from GitHub:
>
> - Last version tarball: https://github.com/jlopex/cozybit/tarball/master
> - Or visiting my github tree: https://github.com/jlopex/cozybit/tree
>
> Best regards,
>
> Signed-off-by: Javier Lopez <jlopex@gmail.com>
> Signed-off-by: Javier Cardona <javier@cozybit.com>

My apologies Javier, but after my first review of your patch I noticed
other issues.  See below.

> ---
>  drivers/net/wireless/mac80211_hwsim.c |  378 ++++++++++++++++++++++++++++++++-
>  drivers/net/wireless/mac80211_hwsim.h |  123 +++++++++++
>  2 files changed, 495 insertions(+), 6 deletions(-)
>  create mode 100644 drivers/net/wireless/mac80211_hwsim.h
>
> diff --git a/drivers/net/wireless/mac80211_hwsim.c b/drivers/net/wireless/mac80211_hwsim.c
> index f4f4257..0be0ad7 100644
> --- a/drivers/net/wireless/mac80211_hwsim.c
> +++ b/drivers/net/wireless/mac80211_hwsim.c
> @@ -1,6 +1,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>
>  *
>  * This program is free software; you can redistribute it and/or modify
>  * it under the terms of the GNU General Public License version 2 as
> @@ -25,11 +26,15 @@
>  #include <linux/rtnetlink.h>
>  #include <linux/etherdevice.h>
>  #include <linux/debugfs.h>
> +#include <net/genetlink.h>
> +#include "mac80211_hwsim.h"
>
>  MODULE_AUTHOR("Jouni Malinen");
>  MODULE_DESCRIPTION("Software simulator of 802.11 radio(s) for mac80211");
>  MODULE_LICENSE("GPL");
>
> +static atomic_t wmediumd_pid;
> +
>  static int radios = 2;
>  module_param(radios, int, 0444);
>  MODULE_PARM_DESC(radios, "Number of simulated radios");
> @@ -479,20 +484,92 @@ static bool mac80211_hwsim_addr_match(struct mac80211_hwsim_data *data,
>  }
>
>
> +static int hwsim_frame_send_nl(struct mac_address *src,
> +                              struct sk_buff *my_skb, int _pid)
> +{
> +
> +       struct ieee80211_tx_info *txi;
> +       struct sk_buff *skb;
> +       void *msg_head;
> +       int rc;
> +
> +       skb = genlmsg_new(NLMSG_GOODSIZE, GFP_ATOMIC);
> +       msg_head = genlmsg_put(skb, 0, 0, &hwsim_genl_family, 0,
> +                              HWSIM_CMD_FRAME);
> +       if (msg_head == NULL) {
> +               printk(KERN_DEBUG "mac80211_hwsim: problem with msg_head\n");
> +               goto out;
> +       }
> +
> +       rc = nla_put(skb, HWSIM_ATTR_ADDR_TRANSMITTER,
> +                    sizeof(struct mac_address), src);
> +
> +       rc = nla_put_u32(skb, HWSIM_ATTR_MSG_LEN, my_skb->len);

Use nla_len instead

> +
> +       rc = nla_put(skb, HWSIM_ATTR_MSG, my_skb->len, my_skb->data);
> +       if (rc != 0) {
> +               printk(KERN_DEBUG "mac80211_hwsim: "
> +                      "error filling msg payload\n");
> +               goto out;
> +       }
> +
> +       /* We get a copy of the control buffer for this tx*/
> +       rc = nla_put(skb, HWSIM_ATTR_CB_SKB, sizeof(my_skb->cb),
> +                    my_skb->cb);
> +
> +       txi = IEEE80211_SKB_CB(my_skb);
> +
> +       /* We get the flags for this transmission, wmediumd maybe
> +          changes its behaviour depending on the flags */
> +       rc = nla_put_u32(skb, HWSIM_ATTR_FLAGS, txi->flags);
> +       /* We get the tx control (rate and retries) info*/
> +       rc = nla_put(skb, HWSIM_ATTR_TX_INFO,
> +                    sizeof(struct ieee80211_tx_rate)*IEEE80211_TX_MAX_RATES,
> +                    txi->control.rates);

Aren't you sending these already inside the control buffer?  If so, why send
them twice?

> +
> +       genlmsg_end(skb, msg_head);
> +       rc = genlmsg_unicast(&init_net, skb, _pid);
> +       if (rc != 0) {
> +               printk(KERN_DEBUG "mac80211_hwsim: wmediumd not responding "
> +                      "at PID:%d, switching to no wmediumd mode.\n", _pid);
> +               atomic_set(&wmediumd_pid, 0);
> +       }
> +
> +       return 0;
> +
> +out:
> +       printk(KERN_DEBUG "mac80211_hwsim: error occured in %s\n", __func__);
> +       return -1;
> +}
> +
>  static bool mac80211_hwsim_tx_frame(struct ieee80211_hw *hw,
>                                    struct sk_buff *skb)
>  {
>        struct mac80211_hwsim_data *data = hw->priv, *data2;
> -       bool ack = false;
>        struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
>        struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
>        struct ieee80211_rx_status rx_status;
>
> +       bool ack = false;
> +
>        if (data->idle) {
>                wiphy_debug(hw->wiphy, "Trying to TX when idle - reject\n");
>                return false;
>        }
>
> +       if (data->ps != PS_DISABLED)
> +               hdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_PM);
> +
> +       /* wmediumd mode */
> +       if (atomic_read(&wmediumd_pid)) {
> +               hwsim_frame_send_nl((struct mac_address *)
> +                       &data->addresses[1].addr, skb,
> +                       atomic_read(&wmediumd_pid));
> +               return true;
> +       }
> +
> +       /* NO wmediumd, normal mac80211_hwsim behaviour*/
> +
>        memset(&rx_status, 0, sizeof(rx_status));
>        /* TODO: set mactime */
>        rx_status.freq = data->channel->center_freq;
> @@ -501,9 +578,6 @@ static bool mac80211_hwsim_tx_frame(struct ieee80211_hw *hw,
>        /* TODO: simulate real signal strength (and optional packet loss) */
>        rx_status.signal = data->power_level - 50;
>
> -       if (data->ps != PS_DISABLED)
> -               hdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_PM);
> -
>        /* release the skb's source info */
>        skb_orphan(skb);
>        skb_dst_drop(skb);
> @@ -530,9 +604,10 @@ static bool mac80211_hwsim_tx_frame(struct ieee80211_hw *hw,
>                if (nskb == NULL)
>                        continue;
>
> +               memcpy(IEEE80211_SKB_RXCB(nskb), &rx_status, sizeof(rx_status));
> +
>                if (mac80211_hwsim_addr_match(data2, hdr->addr1))
>                        ack = true;
> -               memcpy(IEEE80211_SKB_RXCB(nskb), &rx_status, sizeof(rx_status));
>                ieee80211_rx_irqsafe(data2->hw, nskb);
>        }
>        spin_unlock(&hwsim_radio_lock);
> @@ -540,12 +615,12 @@ static bool mac80211_hwsim_tx_frame(struct ieee80211_hw *hw,
>        return ack;
>  }
>
> -
>  static void mac80211_hwsim_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
>  {
>        bool ack;
>        struct ieee80211_tx_info *txi;
>
> +
>        mac80211_hwsim_monitor_rx(hw, skb);
>
>        if (skb->len < 10) {
> @@ -554,6 +629,13 @@ static void mac80211_hwsim_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
>                return;
>        }
>
> +       /* wmediumd mode*/
> +       if (atomic_read(&wmediumd_pid)) {
> +               mac80211_hwsim_tx_frame(hw, skb);
> +               return;
> +       }
> +
> +       /* NO wmediumd, normal mac80211_hwsim behaviour*/
>        ack = mac80211_hwsim_tx_frame(hw, skb);
>        if (ack && skb->len >= 16) {
>                struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
> @@ -1244,6 +1326,276 @@ static int hwsim_fops_group_write(void *dat, u64 val)
>        return 0;
>  }
>
> +
> +struct mac80211_hwsim_data *get_hwsim_data_ref_from_addr(
> +                            struct mac_address *addr)
> +{
> +       struct mac80211_hwsim_data *data;
> +       bool _found = false;
> +
> +       spin_lock(&hwsim_radio_lock);
> +       list_for_each_entry(data, &hwsim_radios, list) {
> +               if (memcmp(data->addresses[1].addr, addr,
> +                         sizeof(struct mac_address)) == 0) {
> +                       _found = true;
> +                       break;
> +               }
> +       }
> +       spin_unlock(&hwsim_radio_lock);
> +
> +       if (!_found) {
> +               printk(KERN_DEBUG "mac80211_hwsim: invalid radio ID\n");
> +               return NULL;
> +       }
> +
> +       return data;
> +
> +
> +}
> +
> +static int hwsim_tx_info_frame_received_nl(struct sk_buff *skb_2,
> +                                          struct genl_info *info)
> +{
> +
> +       struct ieee80211_hdr *hdr;
> +       struct mac80211_hwsim_data *data2;
> +       struct ieee80211_tx_info *txi;
> +       struct ieee80211_tx_rate *tx_attempts;
> +       char *cb;
> +
> +       int i;
> +
> +       struct mac_address *dst = (struct mac_address *)nla_data(
> +                                  info->attrs[HWSIM_ATTR_ADDR_TRANSMITTER]);
> +       int frame_data_len = nla_get_u32(info->attrs[HWSIM_ATTR_MSG_LEN]);
> +       char *frame_data = (char *)nla_data(info->attrs[HWSIM_ATTR_MSG]);
> +       int flags = nla_get_u32(info->attrs[HWSIM_ATTR_FLAGS]);
> +
> +       /* Allocate new skb here */
> +       struct sk_buff *skb = alloc_skb(IEEE80211_MAX_DATA_LEN, GFP_KERNEL);

Again, skb may be null here.

> +
> +       if (frame_data_len <= IEEE80211_MAX_DATA_LEN) {
> +               /* Copy the data */
> +               memcpy(skb_put(skb, frame_data_len), frame_data,
> +                      frame_data_len);
> +       } else
> +               goto out;
> +
> +       data2 = get_hwsim_data_ref_from_addr(dst);
> +
> +       if (data2 == NULL)
> +               goto out;
> +
> +       printk(KERN_DEBUG "mac80211_hwsim: TX_INFO received\n");
> +
> +       /*Tx info received because the frame was acked on user space,
> +        so we get all the necessary info: tx attempts and skb control buffer*/
> +
> +       tx_attempts = (struct ieee80211_tx_rate *)nla_data(
> +                      info->attrs[HWSIM_ATTR_TX_INFO]);
> +
> +       /* ieee80211_tx_status() does not dereference anything from the
> +        ieee80211_tx_info structure included in this cb, so it is safe
> +        to get whatever we get from userspace and copy it here. */
> +
> +       cb = (char *)nla_data(info->attrs[HWSIM_ATTR_CB_SKB]);

You should probably check that nla_len of CB == sizeof(skb->cb)

> +       memcpy(skb->cb, cb, sizeof(skb->cb));
> +
> +       /* now send back TX status */
> +       txi = IEEE80211_SKB_CB(skb);
> +
> +       if (txi->control.vif)
> +               hwsim_check_magic(txi->control.vif);
> +       if (txi->control.sta)
> +               hwsim_check_sta_magic(txi->control.sta);
> +
> +       ieee80211_tx_info_clear_status(txi);
> +       txi->flags = flags;
> +
> +       for (i = 0; i < IEEE80211_TX_MAX_RATES; i++) {
> +               txi->status.rates[i].idx = tx_attempts[i].idx;
> +               txi->status.rates[i].count = tx_attempts[i].count;
> +               txi->status.rates[i].flags = tx_attempts[i].flags;
> +       }
> +
> +       /* unknown values that must be filled in:
> +               txi->status.ampdu_ack_len = 驴?驴驴?驴?驴;
> +               txi->status.ampdu_ack_map = 驴?驴?;
> +       */

These show as the Chinese character for 'donkey' on my display, probably not
what you intended.  Anyway, why adding that commented out code?

> +
> +       txi->status.ack_signal = nla_get_u32(info->attrs[HWSIM_ATTR_SIGNAL]);
> +
> +       if (!(txi->flags & IEEE80211_TX_CTL_NO_ACK) &&
> +          (txi->flags & IEEE80211_TX_STAT_ACK)) {
> +               if (skb->len >= 16) {
> +                       hdr = (struct ieee80211_hdr *) skb->data;
> +                       mac80211_hwsim_monitor_ack(data2->hw, hdr->addr2);
> +               }
> +       }
> +       ieee80211_tx_status_irqsafe(data2->hw, skb);
> +       return 0;
> +
> +out:
> +       kfree_skb(skb);
> +       printk(KERN_DEBUG "mac80211_hwsim: error occured in %s\n", __func__);
> +       return -1;
> +
> +}
> +
> +static int hwsim_cloned_frame_received_nl(struct sk_buff *skb_2,
> +                                         struct genl_info *info)
> +{
> +
> +       struct mac80211_hwsim_data *data2;
> +       struct ieee80211_rx_status rx_status;
> +
> +       struct mac_address *dst = (struct mac_address *)nla_data(
> +                                  info->attrs[HWSIM_ATTR_ADDR_RECEIVER]);
> +
> +       int frame_data_len = nla_get_u32(info->attrs[HWSIM_ATTR_MSG_LEN]);

> +       char* frame_data = (char *)nla_data(info->attrs[HWSIM_ATTR_MSG]);
> +
> +       /* Allocate new skb here */
> +       struct sk_buff *skb = alloc_skb(IEEE80211_MAX_DATA_LEN, GFP_KERNEL);

Should handle no-memory situations here.

> +
> +       if (frame_data_len <= IEEE80211_MAX_DATA_LEN) {
> +               /* Copy the data */
> +               memcpy(skb_put(skb, frame_data_len), frame_data,
> +                      frame_data_len);
> +       } else
> +               goto out;
> +
> +       data2 = get_hwsim_data_ref_from_addr(dst);
> +
> +       if (data2 == NULL)
> +               goto out;
> +
> +       /*A frame is received from user space*/
> +       printk(KERN_DEBUG "mac80211_hwsim: CLONED FRAME received\n");

This and all other printks in the normal execution path should
probably be removed.

> +       memset(&rx_status, 0, sizeof(rx_status));
> +       /* TODO: set mactime */
> +       rx_status.freq = data2->channel->center_freq;
> +       rx_status.band = data2->channel->band;
> +       rx_status.rate_idx = nla_get_u32(info->attrs[HWSIM_ATTR_RX_RATE]);
> +       rx_status.signal = nla_get_u32(info->attrs[HWSIM_ATTR_SIGNAL]);
> +
> +       memcpy(IEEE80211_SKB_RXCB(skb), &rx_status, sizeof(rx_status));
> +       ieee80211_rx_irqsafe(data2->hw, skb);
> +
> +       return 0;
> +out:
> +       kfree_skb(skb);
> +       printk(KERN_DEBUG "mac80211_hwsim: error occured in %s\n", __func__);
> +       return -1;
> +}
> +
> +static int hwsim_register_received_nl(struct sk_buff *skb_2,
> +                                     struct genl_info *info)
> +{
> +       if (info == NULL)
> +               goto out;
> +
> +       atomic_set(&wmediumd_pid, info->snd_pid);
> +
> +       printk(KERN_DEBUG "mac80211_hwsim: received a REGISTER, "
> +              "switching to wmediumd mode with pid %d\n", info->snd_pid);
> +
> +       return 0;
> +
> +out:
> +       printk(KERN_DEBUG "mac80211_hwsim: error occured in %s\n", __func__);
> +       return -1;
> +}
> +
> +/* Generic Netlink operations array */
> +static struct genl_ops hwsim_ops[] = {
> +       {
> +               .cmd = HWSIM_CMD_REGISTER,
> +               .flags = 0,
> +               .policy = hwsim_genl_policy,
> +               .doit = hwsim_register_received_nl,
> +               .dumpit = NULL,
> +       },
> +       {
> +               .cmd = HWSIM_CMD_FRAME,
> +               .flags = 0,
> +               .policy = hwsim_genl_policy,
> +               .doit = hwsim_cloned_frame_received_nl,
> +               .dumpit = NULL,
> +       },
> +       {
> +               .cmd = HWSIM_CMD_TX_INFO_FRAME,
> +               .flags = 0,
> +               .policy = hwsim_genl_policy,
> +               .doit = hwsim_tx_info_frame_received_nl,
> +               .dumpit = NULL,
> +       },
> +};
> +
> +static int hwsim_init_netlink(void)
> +{
> +       int rc;
> +       printk(KERN_INFO "mac80211_hwsim: initializing netlink\n");
> +
> +       atomic_set(&wmediumd_pid, 0);
> +
> +       rc = genl_register_family(&hwsim_genl_family);
> +       if (rc != 0)
> +               goto failure;
> +       rc = genl_register_ops(&hwsim_genl_family, &hwsim_ops[0]);
> +       if (rc != 0) {
> +               printk(KERN_DEBUG "mac80211_hwsim: register ops: %i\n", rc);
> +               genl_unregister_family(&hwsim_genl_family);
> +               goto failure;
> +       }
> +       rc = genl_register_ops(&hwsim_genl_family, &hwsim_ops[1]);
> +       if (rc != 0) {
> +               printk(KERN_DEBUG "mac80211_hwsim: register ops: %i\n", rc);
> +               genl_unregister_family(&hwsim_genl_family);
> +               goto failure;
> +       }
> +       rc = genl_register_ops(&hwsim_genl_family, &hwsim_ops[2]);
> +       if (rc != 0) {
> +               printk(KERN_DEBUG "mac80211_hwsim: register ops: %i\n", rc);
> +               genl_unregister_family(&hwsim_genl_family);
> +               goto failure;
> +       }
> +       return 0;
> +
> +failure:
> +       printk(KERN_DEBUG "mac80211_hwsim: error occured in %s\n", __func__);
> +       return -1;
> +}
> +
> +static void hwsim_exit_netlink(void)
> +{
> +       int ret;
> +
> +       printk(KERN_INFO "mac80211_hwsim: closing netlink\n");
> +       /*unregister the functions*/
> +
> +       ret = genl_unregister_ops(&hwsim_genl_family, &hwsim_ops[0]);
> +       if (ret != 0) {
> +               printk(KERN_DEBUG "mac80211_hwsim: unregister ops: %i\n", ret);
> +               return;
> +       }
> +       ret = genl_unregister_ops(&hwsim_genl_family, &hwsim_ops[1]);
> +       if (ret != 0) {
> +               printk(KERN_DEBUG "mac80211_hwsim: unregister ops: %i\n", ret);
> +               return;
> +       }
> +       ret = genl_unregister_ops(&hwsim_genl_family, &hwsim_ops[2]);
> +       if (ret != 0) {
> +               printk(KERN_DEBUG "mac80211_hwsim: unregister ops: %i\n", ret);
> +               return;
> +       }
> +       ret = genl_unregister_family(&hwsim_genl_family);
> +       if (ret != 0)
> +               printk(KERN_DEBUG "mac80211_hwsim: "
> +                      "unregister family %i\n", ret);
> +}
> +
> +
>  DEFINE_SIMPLE_ATTRIBUTE(hwsim_fops_group,
>                        hwsim_fops_group_read, hwsim_fops_group_write,
>                        "%llx\n");
> @@ -1379,6 +1731,10 @@ static int __init init_mac80211_hwsim(void)
>                data->group = 1;
>                mutex_init(&data->mutex);
>
> +               /* Enable frame retransmission mechanism for a lossy channel */
> +               hw->max_rates = 4;
> +               hw->max_rate_tries = 11;
> +
>                /* Work to be done prior to ieee80211_register_hw() */
>                switch (regtest) {
>                case HWSIM_REGTEST_DISABLED:
> @@ -1528,8 +1884,16 @@ static int __init init_mac80211_hwsim(void)
>
>        rtnl_unlock();
>
> +       err = hwsim_init_netlink();
> +       if (err < 0)
> +               goto failed_nl;
> +
>        return 0;
>
> +failed_nl:
> +       printk(KERN_DEBUG "mac80211_hwsim: failed initializing netlink\n");
> +       return err;
> +
>  failed_mon:
>        rtnl_unlock();
>        free_netdev(hwsim_mon);
> @@ -1550,6 +1914,8 @@ static void __exit exit_mac80211_hwsim(void)
>  {
>        printk(KERN_DEBUG "mac80211_hwsim: unregister radios\n");
>
> +       hwsim_exit_netlink();
> +
>        mac80211_hwsim_free();
>        unregister_netdev(hwsim_mon);
>  }
> diff --git a/drivers/net/wireless/mac80211_hwsim.h b/drivers/net/wireless/mac80211_hwsim.h
> new file mode 100644
> index 0000000..be37f44
> --- /dev/null
> +++ b/drivers/net/wireless/mac80211_hwsim.h
> @@ -0,0 +1,123 @@
> +/*
> + * 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>
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> + */
> +
> +#include <net/mac80211.h>
> +
> +/**
> + * DOC: Frame transmission/registration support
> + *
> + * Frame transmission and registration support exists to allow userspace
> + * entities such as wmediumd to receive and process all broadcasted
> + * frames from a mac80211_hwsim radio device.
> + *
> + * This allow user space applications to decide if the frame should be
> + * dropped or not and implement a wireless medium simulator at user space.
> + *
> + * Registration is done by sending a register message to the driver and
> + * will be automatically unregistered if the user application doesn't
> + * responds to sent frames.
> + * Once registered the user application has to take responsibility of
> + * broadcasting the frames to all listening mac80211_hwsim radio
> + * interfaces.
> + *
> + * For more technical details, see the corresponding command descriptions
> + * below.
> + */
> +
> +/**
> + * enum hwsim_commands - supported hwsim commands
> + *
> + * @HWSIM_CMD_UNSPEC: unspecified command to catch errors
> + *
> + * @HWSIM_CMD_REGISTER: request to register and received all broadcasted
> + *     frames by any mac80211_hwsim radio device.
> + * @HWSIM_CMD_FRAME: send/receive a broadcasted frame from/to kernel/user
> + * space, uses:
> + *     %HWSIM_ATTR_ADDR_TRANSMITTER, %HWSIM_ATTR_ADDR_RECEIVER,
> + *     %HWSIM_ATTR_MSG, %HWSIM_ATTR_MSG_LEN, %HWSIM_ATTR_FLAGS,
> + *     %HWSIM_ATTR_RX_RATE, %HWSIM_ATTR_SIGNAL, %HWSIM_ATTR_CB_SKB
> + * @HWSIM_CMD_TX_INFO_FRAME: Transmission info report from user space to
> + * kernel, uses:
> + *     %HWSIM_ATTR_ADDR_TRANSMITTER, %HWSIM_ATTR_MSG, %HWSIM_ATTR_MSG_LEN,
> + *     %HWSIM_ATTR_FLAGS, %HWSIM_ATTR_TX_INFO, %HWSIM_ATTR_SIGNAL
> + * @__HWSIM_CMD_MAX: enum limit
> + */
> +enum {
> +       HWSIM_CMD_UNSPEC,
> +       HWSIM_CMD_REGISTER,
> +       HWSIM_CMD_FRAME,
> +       HWSIM_CMD_TX_INFO_FRAME,
> +       __HWSIM_CMD_MAX,
> +};
> +#define HWSIM_CMD_MAX (_HWSIM_CMD_MAX - 1)
> +
> +/**
> + * enum hwsim_attrs - hwsim netlink attributes
> + *
> + * @HWSIM_ATTR_UNSPEC: unspecified attribute to catch errors
> + *
> + * @HWSIM_ATTR_ADDR_RECEIVER: MAC address of the radio device that
> + *     the frame is broadcasted to
> + * @HWSIM_ATTR_ADDR_TRANSMITTER: MAC address of the radio device that
> + *     the frame was broadcasted from
> + * @HWSIM_ATTR_MSG_LEN: Length of the broadcasted frame
> + * @HWSIM_ATTR_MSG: Data array
> + * @HWSIM_ATTR_FLAGS: mac80211 transmission flags, used to process
> +       properly the frame at user space
> + * @HWSIM_ATTR_RX_RATE: estimated rx rate index for this frame at user
> +       space
> + * @HWSIM_ATTR_SIGNAL: estimated RX signal for this frame at user
> +       space
> + * @HWSIM_ATTR_TX_INFO: ieee80211_tx_rate array
> + * @HWSIM_ATTR_CB_SKB: sk_buff custom buffer of the broadcasted frame
> + * @__HWSIM_ATTR_MAX: enum limit
> + */
> +
> +
> +enum {
> +       HWSIM_ATTR_UNSPEC,
> +       HWSIM_ATTR_ADDR_RECEIVER,
> +       HWSIM_ATTR_ADDR_TRANSMITTER,
> +       HWSIM_ATTR_MSG_LEN,
> +       HWSIM_ATTR_MSG,
> +       HWSIM_ATTR_FLAGS,
> +       HWSIM_ATTR_RX_RATE,
> +       HWSIM_ATTR_SIGNAL,
> +       HWSIM_ATTR_TX_INFO,
> +       HWSIM_ATTR_CB_SKB,
> +       __HWSIM_ATTR_MAX,
> +};
> +#define HWSIM_ATTR_MAX (__HWSIM_ATTR_MAX - 1)
> +
> +static struct nla_policy hwsim_genl_policy[HWSIM_ATTR_MAX + 1] = {
> +       [HWSIM_ATTR_ADDR_RECEIVER] = { .type = NLA_UNSPEC,
> +                                      .len = 6*sizeof(u8) },
> +       [HWSIM_ATTR_ADDR_TRANSMITTER] = { .type = NLA_UNSPEC,
> +                                         .len = 6*sizeof(u8) },
> +       [HWSIM_ATTR_MSG_LEN] = { .type = NLA_U32 },

You don't need this, use nla_len instead.  See nl80211.c for examples.

> +       [HWSIM_ATTR_MSG] = { .type = NLA_STRING },

To me, FRAME would be more intuitive than MSG.

> +       [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,
> +                                .len = IEEE80211_TX_MAX_RATES*sizeof(
> +                                       struct ieee80211_tx_rate)},
> +       [HWSIM_ATTR_CB_SKB] = { .type = NLA_UNSPEC, .len = 48*sizeof(char) },
> +};
> +
> +#define VERSION_NR 1
> +
> +static struct genl_family hwsim_genl_family = {
> +       .id = GENL_ID_GENERATE,
> +       .hdrsize = 0,
> +       .name = "HWSIM",
> +       .version = VERSION_NR,
> +       .maxattr = HWSIM_ATTR_MAX,
> +};
> --
> 1.7.0.4
>
>



-- 
Javier Cardona
cozybit Inc.
http://www.cozybit.com

  reply	other threads:[~2011-04-19  2:19 UTC|newest]

Thread overview: 18+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2011-04-18 20:45 [PATCH] mac80211_hwsim driver support userspace frame tx/rx Javier Lopez
2011-04-19  2:19 ` Javier Cardona [this message]
2011-04-22 19:31   ` [PATCH v2] " Javier Lopez
2011-04-28 18:34     ` John W. Linville
2011-05-01 19:29   ` [PATCH v3] " Javier Lopez
2011-05-01 21:35     ` Johannes Berg
2011-05-11 21:32   ` [PATCH v4] " Javier Lopez
2011-05-18  0:09     ` Javier Cardona
2011-05-18 20:58       ` Johannes Berg
2011-05-19 16:00     ` Johannes Berg
2011-05-25 10:41   ` [PATCH v5] " Javier Lopez
2011-05-25 19:03   ` [PATCH v6] " Javier Lopez
2011-05-26  3:54     ` Johannes Berg
2011-05-31 21:29   ` [PATCH v7] " Javier Lopez
2011-05-31 22:06   ` Javier Lopez
2011-06-01  4:16     ` Johannes Berg
     [not found]       ` <BANLkTinE0axwc_X9Gt=qdrjufopvPNADng@mail.gmail.com>
2011-06-01  8:48         ` Johannes Berg
2011-06-01  9:26   ` [PATCH v8] " Javier Lopez

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to='BANLkTi=_snQBSFH-d344bjk8-aSeC9Jh5w@mail.gmail.com' \
    --to=javier@cozybit.com \
    --cc=jlopex@gmail.com \
    --cc=linux-wireless@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.