mac80211: partially fix skb->cb use
authorJohannes Berg <johannes@sipsolutions.net>
Tue, 29 Jul 2008 09:32:07 +0000 (11:32 +0200)
committerJohn W. Linville <linville@tuxdriver.com>
Tue, 29 Jul 2008 20:55:08 +0000 (16:55 -0400)
This patch fixes mac80211 to not use the skb->cb over the queue step
from virtual interfaces to the master. The patch also, for now,
disables aggregation because that would still require requeuing,
will fix that in a separate patch. There are two other places (software
requeue and powersaving stations) where requeue can happen, but that is
not currently used by any drivers/not possible to use respectively.

Signed-off-by: Johannes Berg <johannes@sipsolutions.net>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
13 files changed:
drivers/net/wireless/ath5k/base.c
drivers/net/wireless/b43/xmit.c
drivers/net/wireless/b43legacy/xmit.c
drivers/net/wireless/iwlwifi/iwl-tx.c
drivers/net/wireless/iwlwifi/iwl3945-base.c
drivers/net/wireless/rt2x00/rt2x00mac.c
include/linux/skbuff.h
include/net/mac80211.h
net/core/skbuff.c
net/mac80211/main.c
net/mac80211/mlme.c
net/mac80211/tx.c
net/mac80211/wme.c

index 1106d1c062989ccd55aeb7b0a70383e26fb3d968..ff3fad794b610c465c52295005caf6a4e5fbee57 100644 (file)
@@ -1237,7 +1237,7 @@ ath5k_txbuf_setup(struct ath5k_softc *sc, struct ath5k_buf *bf)
 
        pktlen = skb->len;
 
-       if (!(info->flags & IEEE80211_TX_CTL_DO_NOT_ENCRYPT)) {
+       if (info->control.hw_key) {
                keyidx = info->control.hw_key->hw_key_idx;
                pktlen += info->control.icv_len;
        }
index 8d54502222a6ed78534b8681f5f7fcbe1f12064b..9dda8169f7cc428fb754f03bbcb224a9227a66d4 100644 (file)
@@ -192,7 +192,7 @@ int b43_generate_txhdr(struct b43_wldev *dev,
        const struct b43_phy *phy = &dev->phy;
        const struct ieee80211_hdr *wlhdr =
            (const struct ieee80211_hdr *)fragment_data;
-       int use_encryption = (!(info->flags & IEEE80211_TX_CTL_DO_NOT_ENCRYPT));
+       int use_encryption = !!info->control.hw_key;
        __le16 fctl = wlhdr->frame_control;
        struct ieee80211_rate *fbrate;
        u8 rate, rate_fb;
index e969ed8d412dd6d42638e12521dac9a7a57b5600..68e1f8c78727dd1d4c2504f12b41a75d5080d06e 100644 (file)
@@ -192,7 +192,7 @@ static int generate_txhdr_fw3(struct b43legacy_wldev *dev,
                               u16 cookie)
 {
        const struct ieee80211_hdr *wlhdr;
-       int use_encryption = (!(info->flags & IEEE80211_TX_CTL_DO_NOT_ENCRYPT));
+       int use_encryption = !!info->control.hw_key;
        u16 fctl;
        u8 rate;
        struct ieee80211_rate *rate_fb;
index 9b50b1052b09fe6f750c1693b12dfafca4b3f2f6..f72cd0bf6aa333f9e2f64f1a8f9a3105c5efc37a 100644 (file)
@@ -906,7 +906,7 @@ int iwl_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
         * first entry */
        iwl_hw_txq_attach_buf_to_tfd(priv, tfd, txcmd_phys, len);
 
-       if (!(info->flags & IEEE80211_TX_CTL_DO_NOT_ENCRYPT))
+       if (info->control.hw_key)
                iwl_tx_cmd_build_hwcrypto(priv, info, tx_cmd, skb, sta_id);
 
        /* Set up TFD's 2nd entry to point directly to remainder of skb,
index 05121f395c4ecffb96911b726d8d1dada0161f86..7c82ecfa30a4bf189613fcc6327d88f0ef8fef29 100644 (file)
@@ -2667,7 +2667,7 @@ static int iwl3945_tx_skb(struct iwl3945_priv *priv, struct sk_buff *skb)
         * first entry */
        iwl3945_hw_txq_attach_buf_to_tfd(priv, tfd, txcmd_phys, len);
 
-       if (!(info->flags & IEEE80211_TX_CTL_DO_NOT_ENCRYPT))
+       if (info->control.hw_key)
                iwl3945_build_tx_cmd_hwcrypto(priv, info, out_cmd, skb, 0);
 
        /* Set up TFD's 2nd entry to point directly to remainder of skb,
index 042ab00d8bd213beaa803a36dcac49ddc21dc335..c3ee4ecba792dcb95a8224a21391a2f9dde54860 100644 (file)
@@ -63,7 +63,7 @@ static int rt2x00mac_tx_rts_cts(struct rt2x00_dev *rt2x00dev,
         */
        memcpy(skb->cb, frag_skb->cb, sizeof(skb->cb));
        rts_info = IEEE80211_SKB_CB(skb);
-       rts_info->flags |= IEEE80211_TX_CTL_DO_NOT_ENCRYPT;
+       rts_info->control.hw_key = NULL;
        rts_info->flags &= ~IEEE80211_TX_CTL_USE_RTS_CTS;
        rts_info->flags &= ~IEEE80211_TX_CTL_USE_CTS_PROTECT;
        rts_info->flags &= ~IEEE80211_TX_CTL_REQ_TX_STATUS;
index 7ea44f6621f265a003ad6eb28c9f3934d1dc94e2..a640385e0598b7f127cb21e7688618643152064e 100644 (file)
@@ -316,7 +316,10 @@ struct sk_buff {
 #ifdef CONFIG_IPV6_NDISC_NODETYPE
        __u8                    ndisc_nodetype:2;
 #endif
-       /* 14 bit hole */
+#if defined(CONFIG_MAC80211) || defined(CONFIG_MAC80211_MODULE)
+       __u8                    do_not_encrypt:1;
+#endif
+       /* 0/13/14 bit hole */
 
 #ifdef CONFIG_NET_DMA
        dma_cookie_t            dma_cookie;
index 74487f268237918377a0948b4d18022c4ccffafd..b52721008be81dd34e3b6379e8729c5abf439b0a 100644 (file)
@@ -206,8 +206,6 @@ struct ieee80211_bss_conf {
  * These flags are used with the @flags member of &ieee80211_tx_info.
  *
  * @IEEE80211_TX_CTL_REQ_TX_STATUS: request TX status callback for this frame.
- * @IEEE80211_TX_CTL_DO_NOT_ENCRYPT: send this frame without encryption;
- *     e.g., for EAPOL frame
  * @IEEE80211_TX_CTL_USE_RTS_CTS: use RTS-CTS before sending frame
  * @IEEE80211_TX_CTL_USE_CTS_PROTECT: use CTS protection for the frame (e.g.,
  *     for combined 802.11g / 802.11b networks)
@@ -220,7 +218,6 @@ struct ieee80211_bss_conf {
  * @IEEE80211_TX_CTL_SHORT_PREAMBLE: TBD
  * @IEEE80211_TX_CTL_LONG_RETRY_LIMIT: this frame should be send using the
  *     through set_retry_limit configured long retry value
- * @IEEE80211_TX_CTL_EAPOL_FRAME: internal to mac80211
  * @IEEE80211_TX_CTL_SEND_AFTER_DTIM: send this frame after DTIM beacon
  * @IEEE80211_TX_CTL_AMPDU: this frame should be sent as part of an A-MPDU
  * @IEEE80211_TX_CTL_OFDM_HT: this frame can be sent in HT OFDM rates. number
@@ -253,7 +250,6 @@ struct ieee80211_bss_conf {
  */
 enum mac80211_tx_control_flags {
        IEEE80211_TX_CTL_REQ_TX_STATUS          = BIT(0),
-       IEEE80211_TX_CTL_DO_NOT_ENCRYPT         = BIT(1),
        IEEE80211_TX_CTL_USE_RTS_CTS            = BIT(2),
        IEEE80211_TX_CTL_USE_CTS_PROTECT        = BIT(3),
        IEEE80211_TX_CTL_NO_ACK                 = BIT(4),
@@ -263,7 +259,6 @@ enum mac80211_tx_control_flags {
        IEEE80211_TX_CTL_FIRST_FRAGMENT         = BIT(8),
        IEEE80211_TX_CTL_SHORT_PREAMBLE         = BIT(9),
        IEEE80211_TX_CTL_LONG_RETRY_LIMIT       = BIT(10),
-       IEEE80211_TX_CTL_EAPOL_FRAME            = BIT(11),
        IEEE80211_TX_CTL_SEND_AFTER_DTIM        = BIT(12),
        IEEE80211_TX_CTL_AMPDU                  = BIT(13),
        IEEE80211_TX_CTL_OFDM_HT                = BIT(14),
@@ -323,7 +318,6 @@ struct ieee80211_tx_info {
                        struct ieee80211_vif *vif;
                        struct ieee80211_key_conf *hw_key;
                        unsigned long jiffies;
-                       int ifindex;
                        u16 aid;
                        s8 rts_cts_rate_idx, alt_retry_rate_idx;
                        u8 retry_limit;
index 4e0c922741897eb1ad158880ea9cb96f692894fe..84640172d65d7901387925d49654de4b0ddb41e7 100644 (file)
@@ -485,6 +485,9 @@ static struct sk_buff *__skb_clone(struct sk_buff *n, struct sk_buff *skb)
        C(head);
        C(data);
        C(truesize);
+#if defined(CONFIG_MAC80211) || defined(CONFIG_MAC80211_MODULE)
+       C(do_not_encrypt);
+#endif
        atomic_set(&n->users, 1);
 
        atomic_inc(&(skb_shinfo(skb)->dataref));
index b5830f7055cf3ed822a512db6df0f9bbb2ffeb7c..a4c5b90de76987afb4523cf7ed37efbdab7788ef 100644 (file)
@@ -1233,18 +1233,12 @@ static void ieee80211_tasklet_handler(unsigned long data)
 /* Remove added headers (e.g., QoS control), encryption header/MIC, etc. to
  * make a prepared TX frame (one that has been given to hw) to look like brand
  * new IEEE 802.11 frame that is ready to go through TX processing again.
- * Also, tx_packet_data in cb is restored from tx_control. */
+ */
 static void ieee80211_remove_tx_extra(struct ieee80211_local *local,
                                      struct ieee80211_key *key,
                                      struct sk_buff *skb)
 {
        int hdrlen, iv_len, mic_len;
-       struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
-
-       info->flags &=  IEEE80211_TX_CTL_REQ_TX_STATUS |
-                       IEEE80211_TX_CTL_DO_NOT_ENCRYPT |
-                       IEEE80211_TX_CTL_REQUEUE |
-                       IEEE80211_TX_CTL_EAPOL_FRAME;
 
        hdrlen = ieee80211_get_hdrlen_from_skb(skb);
 
index d7c371e36bf0d5cb3d9d4d35898ec32eda2c31d8..35eb767cbcbec7f9911f1c76a2558acf7c8330ae 100644 (file)
@@ -606,7 +606,6 @@ void ieee80211_sta_tx(struct net_device *dev, struct sk_buff *skb,
                      int encrypt)
 {
        struct ieee80211_sub_if_data *sdata;
-       struct ieee80211_tx_info *info;
 
        sdata = IEEE80211_DEV_TO_SUB_IF(dev);
        skb->dev = sdata->local->mdev;
@@ -614,11 +613,8 @@ void ieee80211_sta_tx(struct net_device *dev, struct sk_buff *skb,
        skb_set_network_header(skb, 0);
        skb_set_transport_header(skb, 0);
 
-       info = IEEE80211_SKB_CB(skb);
-       memset(info, 0, sizeof(struct ieee80211_tx_info));
-       info->control.ifindex = sdata->dev->ifindex;
-       if (!encrypt)
-               info->flags |= IEEE80211_TX_CTL_DO_NOT_ENCRYPT;
+       skb->iif = sdata->dev->ifindex;
+       skb->do_not_encrypt = !encrypt;
 
        dev_queue_xmit(skb);
 }
index c5f78059c6ca174b53a8a4f3b57eee69b48c6dc0..69019e943873b697a4d383b0933318928512b4e5 100644 (file)
@@ -439,14 +439,14 @@ ieee80211_tx_h_select_key(struct ieee80211_tx_data *tx)
        struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx->skb);
        u16 fc = tx->fc;
 
-       if (unlikely(info->flags & IEEE80211_TX_CTL_DO_NOT_ENCRYPT))
+       if (unlikely(tx->skb->do_not_encrypt))
                tx->key = NULL;
        else if (tx->sta && (key = rcu_dereference(tx->sta->key)))
                tx->key = key;
        else if ((key = rcu_dereference(tx->sdata->default_key)))
                tx->key = key;
        else if (tx->sdata->drop_unencrypted &&
-                !(info->flags & IEEE80211_TX_CTL_EAPOL_FRAME) &&
+                (tx->skb->protocol != cpu_to_be16(ETH_P_PAE)) &&
                 !(info->flags & IEEE80211_TX_CTL_INJECTED)) {
                I802_DEBUG_INC(tx->local->tx_handlers_drop_unencrypted);
                return TX_DROP;
@@ -476,7 +476,7 @@ ieee80211_tx_h_select_key(struct ieee80211_tx_data *tx)
        }
 
        if (!tx->key || !(tx->key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE))
-               info->flags |= IEEE80211_TX_CTL_DO_NOT_ENCRYPT;
+               tx->skb->do_not_encrypt = 1;
 
        return TX_CONTINUE;
 }
@@ -732,6 +732,7 @@ ieee80211_tx_h_fragment(struct ieee80211_tx_data *tx)
                memcpy(skb_put(frag, copylen), pos, copylen);
                memcpy(frag->cb, first->cb, sizeof(frag->cb));
                skb_copy_queue_mapping(frag, first);
+               frag->do_not_encrypt = first->do_not_encrypt;
 
                pos += copylen;
                left -= copylen;
@@ -852,7 +853,7 @@ __ieee80211_parse_tx_radiotap(struct ieee80211_tx_data *tx,
 
        sband = tx->local->hw.wiphy->bands[tx->channel->band];
 
-       info->flags |= IEEE80211_TX_CTL_DO_NOT_ENCRYPT;
+       skb->do_not_encrypt = 1;
        info->flags |= IEEE80211_TX_CTL_INJECTED;
        tx->flags &= ~IEEE80211_TX_FRAGMENTED;
 
@@ -925,8 +926,7 @@ __ieee80211_parse_tx_radiotap(struct ieee80211_tx_data *tx,
                                skb_trim(skb, skb->len - FCS_LEN);
                        }
                        if (*iterator.this_arg & IEEE80211_RADIOTAP_F_WEP)
-                               info->flags &=
-                                       ~IEEE80211_TX_CTL_DO_NOT_ENCRYPT;
+                               tx->skb->do_not_encrypt = 0;
                        if (*iterator.this_arg & IEEE80211_RADIOTAP_F_FRAG)
                                tx->flags |= IEEE80211_TX_FRAGMENTED;
                        break;
@@ -1042,10 +1042,9 @@ static int ieee80211_tx_prepare(struct ieee80211_tx_data *tx,
                                struct sk_buff *skb,
                                struct net_device *mdev)
 {
-       struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
        struct net_device *dev;
 
-       dev = dev_get_by_index(&init_net, info->control.ifindex);
+       dev = dev_get_by_index(&init_net, skb->iif);
        if (unlikely(dev && !is_ieee80211_device(dev, mdev))) {
                dev_put(dev);
                dev = NULL;
@@ -1306,8 +1305,8 @@ int ieee80211_master_start_xmit(struct sk_buff *skb,
        bool may_encrypt;
        int ret;
 
-       if (info->control.ifindex)
-               odev = dev_get_by_index(&init_net, info->control.ifindex);
+       if (skb->iif)
+               odev = dev_get_by_index(&init_net, skb->iif);
        if (unlikely(odev && !is_ieee80211_device(odev, dev))) {
                dev_put(odev);
                odev = NULL;
@@ -1321,9 +1320,13 @@ int ieee80211_master_start_xmit(struct sk_buff *skb,
                return 0;
        }
 
+       memset(info, 0, sizeof(*info));
+
+       info->flags |= IEEE80211_TX_CTL_REQ_TX_STATUS;
+
        osdata = IEEE80211_DEV_TO_SUB_IF(odev);
 
-       may_encrypt = !(info->flags & IEEE80211_TX_CTL_DO_NOT_ENCRYPT);
+       may_encrypt = !skb->do_not_encrypt;
 
        headroom = osdata->local->tx_headroom;
        if (may_encrypt)
@@ -1348,7 +1351,6 @@ int ieee80211_monitor_start_xmit(struct sk_buff *skb,
                                 struct net_device *dev)
 {
        struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
-       struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
        struct ieee80211_radiotap_header *prthdr =
                (struct ieee80211_radiotap_header *)skb->data;
        u16 len_rthdr;
@@ -1371,11 +1373,11 @@ int ieee80211_monitor_start_xmit(struct sk_buff *skb,
        skb->dev = local->mdev;
 
        /* needed because we set skb device to master */
-       info->control.ifindex = dev->ifindex;
+       skb->iif = dev->ifindex;
 
-       info->flags |= IEEE80211_TX_CTL_DO_NOT_ENCRYPT;
-       /* Interfaces should always request a status report */
-       info->flags |= IEEE80211_TX_CTL_REQ_TX_STATUS;
+       /* sometimes we do encrypt injected frames, will be fixed
+        * up in radiotap parser if not wanted */
+       skb->do_not_encrypt = 0;
 
        /*
         * fix up the pointers accounting for the radiotap
@@ -1419,7 +1421,6 @@ int ieee80211_subif_start_xmit(struct sk_buff *skb,
                               struct net_device *dev)
 {
        struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
-       struct ieee80211_tx_info *info;
        struct ieee80211_sub_if_data *sdata;
        int ret = 1, head_need;
        u16 ethertype, hdrlen,  meshhdrlen = 0;
@@ -1645,14 +1646,7 @@ int ieee80211_subif_start_xmit(struct sk_buff *skb,
        nh_pos += hdrlen;
        h_pos += hdrlen;
 
-       info = IEEE80211_SKB_CB(skb);
-       memset(info, 0, sizeof(*info));
-       info->control.ifindex = dev->ifindex;
-       if (ethertype == ETH_P_PAE)
-               info->flags |= IEEE80211_TX_CTL_EAPOL_FRAME;
-
-       /* Interfaces should always request a status report */
-       info->flags |= IEEE80211_TX_CTL_REQ_TX_STATUS;
+       skb->iif = dev->ifindex;
 
        skb->dev = local->mdev;
        dev->stats.tx_packets++;
@@ -1922,6 +1916,8 @@ struct sk_buff *ieee80211_beacon_get(struct ieee80211_hw *hw,
 
        info = IEEE80211_SKB_CB(skb);
 
+       skb->do_not_encrypt = 1;
+
        info->band = band;
        rate_control_get_rate(local->mdev, sband, skb, &rsel);
 
@@ -1940,7 +1936,6 @@ struct sk_buff *ieee80211_beacon_get(struct ieee80211_hw *hw,
        info->tx_rate_idx = rsel.rate_idx;
 
        info->flags |= IEEE80211_TX_CTL_NO_ACK;
-       info->flags |= IEEE80211_TX_CTL_DO_NOT_ENCRYPT;
        info->flags |= IEEE80211_TX_CTL_CLEAR_PS_FILT;
        info->flags |= IEEE80211_TX_CTL_ASSIGN_SEQ;
        if (sdata->bss_conf.use_short_preamble &&
index 07edda0b8a5c1c78fef73e9bdca5cf1dbf23abd5..28437f0001db04946b49c330c172b423e92d0913 100644 (file)
@@ -188,6 +188,9 @@ int ieee80211_ht_agg_queue_add(struct ieee80211_local *local,
 {
        int i;
 
+       /* XXX: currently broken due to cb/requeue use */
+       return -EPERM;
+
        /* prepare the filter and save it for the SW queue
         * matching the received HW queue */