]> git.karo-electronics.de Git - karo-tx-linux.git/blobdiff - drivers/net/wireless/mac80211_hwsim.c
b43: add hardware tkip
[karo-tx-linux.git] / drivers / net / wireless / mac80211_hwsim.c
index e789c6e9938cb60e62a918b2f5e2083af7251591..6f6cd43592c84d7db96242e88359f295badeafc5 100644 (file)
@@ -15,6 +15,8 @@
 
 #include <linux/list.h>
 #include <linux/spinlock.h>
+#include <net/dst.h>
+#include <net/xfrm.h>
 #include <net/mac80211.h>
 #include <net/ieee80211_radiotap.h>
 #include <linux/if_arp.h>
@@ -314,7 +316,7 @@ static int hwsim_mon_xmit(struct sk_buff *skb, struct net_device *dev)
 {
        /* TODO: allow packet injection */
        dev_kfree_skb(skb);
-       return 0;
+       return NETDEV_TX_OK;
 }
 
 
@@ -404,11 +406,19 @@ static bool mac80211_hwsim_tx_frame(struct ieee80211_hw *hw,
        rx_status.freq = data->channel->center_freq;
        rx_status.band = data->channel->band;
        rx_status.rate_idx = info->control.rates[0].idx;
-       /* TODO: simulate signal strength (and optional packet drop) */
+       /* TODO: simulate real signal strength (and optional packet loss) */
+       rx_status.signal = -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);
+       skb->mark = 0;
+       secpath_reset(skb);
+       nf_reset(skb);
+
        /* Copy skb to all enabled radios that are on the current frequency */
        spin_lock(&hwsim_radio_lock);
        list_for_each_entry(data2, &hwsim_radios, list) {
@@ -418,6 +428,7 @@ static bool mac80211_hwsim_tx_frame(struct ieee80211_hw *hw,
                        continue;
 
                if (!data2->started || !hwsim_ps_rx_ok(data2, skb) ||
+                   !data->channel || !data2->channel ||
                    data->channel->center_freq != data2->channel->center_freq ||
                    !(data->group & data2->group))
                        continue;
@@ -429,7 +440,8 @@ static bool mac80211_hwsim_tx_frame(struct ieee80211_hw *hw,
                if (memcmp(hdr->addr1, data2->hw->wiphy->perm_addr,
                           ETH_ALEN) == 0)
                        ack = true;
-               ieee80211_rx_irqsafe(data2->hw, nskb, &rx_status);
+               memcpy(IEEE80211_SKB_RXCB(nskb), &rx_status, sizeof(rx_status));
+               ieee80211_rx_irqsafe(data2->hw, nskb);
        }
        spin_unlock(&hwsim_radio_lock);
 
@@ -570,9 +582,7 @@ static int mac80211_hwsim_config(struct ieee80211_hw *hw, u32 changed)
 
 static void mac80211_hwsim_configure_filter(struct ieee80211_hw *hw,
                                            unsigned int changed_flags,
-                                           unsigned int *total_flags,
-                                           int mc_count,
-                                           struct dev_addr_list *mc_list)
+                                           unsigned int *total_flags,u64 multicast)
 {
        struct mac80211_hwsim_data *data = hw->priv;
 
@@ -689,6 +699,74 @@ static int mac80211_hwsim_conf_tx(
        return 0;
 }
 
+#ifdef CONFIG_NL80211_TESTMODE
+/*
+ * This section contains example code for using netlink
+ * attributes with the testmode command in nl80211.
+ */
+
+/* These enums need to be kept in sync with userspace */
+enum hwsim_testmode_attr {
+       __HWSIM_TM_ATTR_INVALID = 0,
+       HWSIM_TM_ATTR_CMD       = 1,
+       HWSIM_TM_ATTR_PS        = 2,
+
+       /* keep last */
+       __HWSIM_TM_ATTR_AFTER_LAST,
+       HWSIM_TM_ATTR_MAX       = __HWSIM_TM_ATTR_AFTER_LAST - 1
+};
+
+enum hwsim_testmode_cmd {
+       HWSIM_TM_CMD_SET_PS             = 0,
+       HWSIM_TM_CMD_GET_PS             = 1,
+};
+
+static const struct nla_policy hwsim_testmode_policy[HWSIM_TM_ATTR_MAX + 1] = {
+       [HWSIM_TM_ATTR_CMD] = { .type = NLA_U32 },
+       [HWSIM_TM_ATTR_PS] = { .type = NLA_U32 },
+};
+
+static int hwsim_fops_ps_write(void *dat, u64 val);
+
+static int mac80211_hwsim_testmode_cmd(struct ieee80211_hw *hw,
+                                      void *data, int len)
+{
+       struct mac80211_hwsim_data *hwsim = hw->priv;
+       struct nlattr *tb[HWSIM_TM_ATTR_MAX + 1];
+       struct sk_buff *skb;
+       int err, ps;
+
+       err = nla_parse(tb, HWSIM_TM_ATTR_MAX, data, len,
+                       hwsim_testmode_policy);
+       if (err)
+               return err;
+
+       if (!tb[HWSIM_TM_ATTR_CMD])
+               return -EINVAL;
+
+       switch (nla_get_u32(tb[HWSIM_TM_ATTR_CMD])) {
+       case HWSIM_TM_CMD_SET_PS:
+               if (!tb[HWSIM_TM_ATTR_PS])
+                       return -EINVAL;
+               ps = nla_get_u32(tb[HWSIM_TM_ATTR_PS]);
+               return hwsim_fops_ps_write(hwsim, ps);
+       case HWSIM_TM_CMD_GET_PS:
+               skb = cfg80211_testmode_alloc_reply_skb(hw->wiphy,
+                                               nla_total_size(sizeof(u32)));
+               if (!skb)
+                       return -ENOMEM;
+               NLA_PUT_U32(skb, HWSIM_TM_ATTR_PS, hwsim->ps);
+               return cfg80211_testmode_reply(skb);
+       default:
+               return -EOPNOTSUPP;
+       }
+
+ nla_put_failure:
+       kfree_skb(skb);
+       return -ENOBUFS;
+}
+#endif
+
 static const struct ieee80211_ops mac80211_hwsim_ops =
 {
        .tx = mac80211_hwsim_tx,
@@ -702,13 +780,14 @@ static const struct ieee80211_ops mac80211_hwsim_ops =
        .sta_notify = mac80211_hwsim_sta_notify,
        .set_tim = mac80211_hwsim_set_tim,
        .conf_tx = mac80211_hwsim_conf_tx,
+       CFG80211_TESTMODE_CMD(mac80211_hwsim_testmode_cmd)
 };
 
 
 static void mac80211_hwsim_free(void)
 {
        struct list_head tmplist, *i, *tmp;
-       struct mac80211_hwsim_data *data;
+       struct mac80211_hwsim_data *data, *tmpdata;
 
        INIT_LIST_HEAD(&tmplist);
 
@@ -717,7 +796,7 @@ static void mac80211_hwsim_free(void)
                list_move(i, &tmplist);
        spin_unlock_bh(&hwsim_radio_lock);
 
-       list_for_each_entry(data, &tmplist, list) {
+       list_for_each_entry_safe(data, tmpdata, &tmplist, list) {
                debugfs_remove(data->debugfs_group);
                debugfs_remove(data->debugfs_ps);
                debugfs_remove(data->debugfs);
@@ -756,7 +835,6 @@ static void hwsim_send_ps_poll(void *dat, u8 *mac, struct ieee80211_vif *vif)
 {
        struct mac80211_hwsim_data *data = dat;
        struct hwsim_vif_priv *vp = (void *)vif->drv_priv;
-       DECLARE_MAC_BUF(buf);
        struct sk_buff *skb;
        struct ieee80211_pspoll *pspoll;
 
@@ -786,7 +864,6 @@ static void hwsim_send_nullfunc(struct mac80211_hwsim_data *data, u8 *mac,
                                struct ieee80211_vif *vif, int ps)
 {
        struct hwsim_vif_priv *vp = (void *)vif->drv_priv;
-       DECLARE_MAC_BUF(buf);
        struct sk_buff *skb;
        struct ieee80211_hdr *hdr;
 
@@ -944,7 +1021,8 @@ static int __init init_mac80211_hwsim(void)
                        BIT(NL80211_IFTYPE_AP) |
                        BIT(NL80211_IFTYPE_MESH_POINT);
 
-               hw->flags = IEEE80211_HW_MFP_CAPABLE;
+               hw->flags = IEEE80211_HW_MFP_CAPABLE |
+                           IEEE80211_HW_SIGNAL_DBM;
 
                /* ask mac80211 to reserve space for magic */
                hw->vif_data_size = sizeof(struct hwsim_vif_priv);
@@ -1166,8 +1244,8 @@ static void __exit exit_mac80211_hwsim(void)
 {
        printk(KERN_DEBUG "mac80211_hwsim: unregister radios\n");
 
-       unregister_netdev(hwsim_mon);
        mac80211_hwsim_free();
+       unregister_netdev(hwsim_mon);
 }