]> err.no Git - linux-2.6/blobdiff - net/mac80211/rx.c
mac80211: remove useless tid assignment for management and control frames
[linux-2.6] / net / mac80211 / rx.c
index 9400a9766a7727ccf1cedcc65277e0da37e37b1d..6a88e8f9bff0dbc7576b22df65bef52db44b8ac8 100644 (file)
@@ -61,18 +61,15 @@ static inline int should_drop_frame(struct ieee80211_rx_status *status,
                                    int present_fcs_len,
                                    int radiotap_len)
 {
-       struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
+       struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
 
        if (status->flag & (RX_FLAG_FAILED_FCS_CRC | RX_FLAG_FAILED_PLCP_CRC))
                return 1;
        if (unlikely(skb->len < 16 + present_fcs_len + radiotap_len))
                return 1;
-       if (((hdr->frame_control & cpu_to_le16(IEEE80211_FCTL_FTYPE)) ==
-                       cpu_to_le16(IEEE80211_FTYPE_CTL)) &&
-           ((hdr->frame_control & cpu_to_le16(IEEE80211_FCTL_STYPE)) !=
-                       cpu_to_le16(IEEE80211_STYPE_PSPOLL)) &&
-           ((hdr->frame_control & cpu_to_le16(IEEE80211_FCTL_STYPE)) !=
-                       cpu_to_le16(IEEE80211_STYPE_BACK_REQ)))
+       if (ieee80211_is_ctl(hdr->frame_control) &&
+           !ieee80211_is_pspoll(hdr->frame_control) &&
+           !ieee80211_is_back_req(hdr->frame_control))
                return 1;
        return 0;
 }
@@ -389,7 +386,7 @@ static void ieee80211_verify_ip_alignment(struct ieee80211_rx_data *rx)
 
 /* rx handlers */
 
-static ieee80211_rx_result
+static ieee80211_rx_result debug_noinline
 ieee80211_rx_h_passive_scan(struct ieee80211_rx_data *rx)
 {
        struct ieee80211_local *local = rx->local;
@@ -466,7 +463,7 @@ ieee80211_rx_mesh_check(struct ieee80211_rx_data *rx)
 }
 
 
-static ieee80211_rx_result
+static ieee80211_rx_result debug_noinline
 ieee80211_rx_h_check(struct ieee80211_rx_data *rx)
 {
        struct ieee80211_hdr *hdr;
@@ -525,7 +522,7 @@ ieee80211_rx_h_check(struct ieee80211_rx_data *rx)
 }
 
 
-static ieee80211_rx_result
+static ieee80211_rx_result debug_noinline
 ieee80211_rx_h_decrypt(struct ieee80211_rx_data *rx)
 {
        struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) rx->skb->data;
@@ -616,11 +613,6 @@ ieee80211_rx_h_decrypt(struct ieee80211_rx_data *rx)
                rx->key->tx_rx_count++;
                /* TODO: add threshold stuff again */
        } else {
-#ifdef CONFIG_MAC80211_DEBUG
-               if (net_ratelimit())
-                       printk(KERN_DEBUG "%s: RX protected frame,"
-                              " but have no key\n", rx->dev->name);
-#endif /* CONFIG_MAC80211_DEBUG */
                return RX_DROP_MONITOR;
        }
 
@@ -713,7 +705,7 @@ static int ap_sta_ps_end(struct net_device *dev, struct sta_info *sta)
        return sent;
 }
 
-static ieee80211_rx_result
+static ieee80211_rx_result debug_noinline
 ieee80211_rx_h_sta_process(struct ieee80211_rx_data *rx)
 {
        struct sta_info *sta = rx->sta;
@@ -792,7 +784,7 @@ ieee80211_reassemble_add(struct ieee80211_sub_if_data *sdata,
                sdata->fragment_next = 0;
 
        if (!skb_queue_empty(&entry->skb_list)) {
-#ifdef CONFIG_MAC80211_DEBUG
+#ifdef CONFIG_MAC80211_VERBOSE_DEBUG
                struct ieee80211_hdr *hdr =
                        (struct ieee80211_hdr *) entry->skb_list.next->data;
                DECLARE_MAC_BUF(mac);
@@ -804,7 +796,7 @@ ieee80211_reassemble_add(struct ieee80211_sub_if_data *sdata,
                       jiffies - entry->first_frag_time, entry->seq,
                       entry->last_frag, print_mac(mac, hdr->addr1),
                       print_mac(mac2, hdr->addr2));
-#endif /* CONFIG_MAC80211_DEBUG */
+#endif
                __skb_queue_purge(&entry->skb_list);
        }
 
@@ -861,7 +853,7 @@ ieee80211_reassemble_find(struct ieee80211_sub_if_data *sdata,
        return NULL;
 }
 
-static ieee80211_rx_result
+static ieee80211_rx_result debug_noinline
 ieee80211_rx_h_defragment(struct ieee80211_rx_data *rx)
 {
        struct ieee80211_hdr *hdr;
@@ -925,18 +917,8 @@ ieee80211_rx_h_defragment(struct ieee80211_rx_data *rx)
                                break;
                }
                rpn = rx->key->u.ccmp.rx_pn[rx->queue];
-               if (memcmp(pn, rpn, CCMP_PN_LEN) != 0) {
-                       if (net_ratelimit())
-                               printk(KERN_DEBUG "%s: defrag: CCMP PN not "
-                                      "sequential A2=%s"
-                                      " PN=%02x%02x%02x%02x%02x%02x "
-                                      "(expected %02x%02x%02x%02x%02x%02x)\n",
-                                      rx->dev->name, print_mac(mac, hdr->addr2),
-                                      rpn[0], rpn[1], rpn[2], rpn[3], rpn[4],
-                                      rpn[5], pn[0], pn[1], pn[2], pn[3],
-                                      pn[4], pn[5]);
+               if (memcmp(pn, rpn, CCMP_PN_LEN))
                        return RX_DROP_UNUSABLE;
-               }
                memcpy(entry->last_pn, pn, CCMP_PN_LEN);
        }
 
@@ -977,7 +959,7 @@ ieee80211_rx_h_defragment(struct ieee80211_rx_data *rx)
        return RX_CONTINUE;
 }
 
-static ieee80211_rx_result
+static ieee80211_rx_result debug_noinline
 ieee80211_rx_h_ps_poll(struct ieee80211_rx_data *rx)
 {
        struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(rx->dev);
@@ -1040,7 +1022,7 @@ ieee80211_rx_h_ps_poll(struct ieee80211_rx_data *rx)
                 *        have nothing buffered for it?
                 */
                printk(KERN_DEBUG "%s: STA %s sent PS Poll even "
-                      "though there is no buffered frames for it\n",
+                      "though there are no buffered frames for it\n",
                       rx->dev->name, print_mac(mac, rx->sta->addr));
 #endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */
        }
@@ -1052,7 +1034,7 @@ ieee80211_rx_h_ps_poll(struct ieee80211_rx_data *rx)
        return RX_QUEUED;
 }
 
-static ieee80211_rx_result
+static ieee80211_rx_result debug_noinline
 ieee80211_rx_h_remove_qos_control(struct ieee80211_rx_data *rx)
 {
        u16 fc = rx->fc;
@@ -1076,14 +1058,8 @@ static int
 ieee80211_802_1x_port_control(struct ieee80211_rx_data *rx)
 {
        if (unlikely(!rx->sta ||
-           !test_sta_flags(rx->sta, WLAN_STA_AUTHORIZED))) {
-#ifdef CONFIG_MAC80211_DEBUG
-               if (net_ratelimit())
-                       printk(KERN_DEBUG "%s: dropped frame "
-                              "(unauthorized port)\n", rx->dev->name);
-#endif /* CONFIG_MAC80211_DEBUG */
+           !test_sta_flags(rx->sta, WLAN_STA_AUTHORIZED)))
                return -EACCES;
-       }
 
        return 0;
 }
@@ -1116,7 +1092,7 @@ ieee80211_data_to_8023(struct ieee80211_rx_data *rx)
        u16 fc, hdrlen, ethertype;
        u8 *payload;
        u8 dst[ETH_ALEN];
-       u8 src[ETH_ALEN];
+       u8 src[ETH_ALEN] __aligned(2);
        struct sk_buff *skb = rx->skb;
        struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
        DECLARE_MAC_BUF(mac);
@@ -1163,16 +1139,8 @@ ieee80211_data_to_8023(struct ieee80211_rx_data *rx)
                memcpy(src, hdr->addr2, ETH_ALEN);
 
                if (unlikely(sdata->vif.type != IEEE80211_IF_TYPE_AP &&
-                            sdata->vif.type != IEEE80211_IF_TYPE_VLAN)) {
-                       if (net_ratelimit())
-                               printk(KERN_DEBUG "%s: dropped ToDS frame "
-                                      "(BSSID=%s SA=%s DA=%s)\n",
-                                      dev->name,
-                                      print_mac(mac, hdr->addr1),
-                                      print_mac(mac2, hdr->addr2),
-                                      print_mac(mac3, hdr->addr3));
+                            sdata->vif.type != IEEE80211_IF_TYPE_VLAN))
                        return -1;
-               }
                break;
        case (IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS):
                /* RA TA DA SA */
@@ -1180,17 +1148,8 @@ ieee80211_data_to_8023(struct ieee80211_rx_data *rx)
                memcpy(src, hdr->addr4, ETH_ALEN);
 
                 if (unlikely(sdata->vif.type != IEEE80211_IF_TYPE_WDS &&
-                            sdata->vif.type != IEEE80211_IF_TYPE_MESH_POINT)) {
-                        if (net_ratelimit())
-                                printk(KERN_DEBUG "%s: dropped FromDS&ToDS "
-                                      "frame (RA=%s TA=%s DA=%s SA=%s)\n",
-                                      rx->dev->name,
-                                      print_mac(mac, hdr->addr1),
-                                      print_mac(mac2, hdr->addr2),
-                                      print_mac(mac3, hdr->addr3),
-                                      print_mac(mac4, hdr->addr4));
+                            sdata->vif.type != IEEE80211_IF_TYPE_MESH_POINT))
                        return -1;
-               }
                break;
        case IEEE80211_FCTL_FROMDS:
                /* DA BSSID SA */
@@ -1207,27 +1166,13 @@ ieee80211_data_to_8023(struct ieee80211_rx_data *rx)
                memcpy(dst, hdr->addr1, ETH_ALEN);
                memcpy(src, hdr->addr2, ETH_ALEN);
 
-               if (sdata->vif.type != IEEE80211_IF_TYPE_IBSS) {
-                       if (net_ratelimit()) {
-                               printk(KERN_DEBUG "%s: dropped IBSS frame "
-                                      "(DA=%s SA=%s BSSID=%s)\n",
-                                      dev->name,
-                                      print_mac(mac, hdr->addr1),
-                                      print_mac(mac2, hdr->addr2),
-                                      print_mac(mac3, hdr->addr3));
-                       }
+               if (sdata->vif.type != IEEE80211_IF_TYPE_IBSS)
                        return -1;
-               }
                break;
        }
 
-       if (unlikely(skb->len - hdrlen < 8)) {
-               if (net_ratelimit()) {
-                       printk(KERN_DEBUG "%s: RX too short data frame "
-                              "payload\n", dev->name);
-               }
+       if (unlikely(skb->len - hdrlen < 8))
                return -1;
-       }
 
        payload = skb->data + hdrlen;
        ethertype = (payload[6] << 8) | payload[7];
@@ -1259,7 +1204,7 @@ ieee80211_data_to_8023(struct ieee80211_rx_data *rx)
  */
 static bool ieee80211_frame_allowed(struct ieee80211_rx_data *rx)
 {
-       static const u8 pae_group_addr[ETH_ALEN]
+       static const u8 pae_group_addr[ETH_ALEN] __aligned(2)
                = { 0x01, 0x80, 0xC2, 0x00, 0x00, 0x03 };
        struct ethhdr *ehdr = (struct ethhdr *) rx->skb->data;
 
@@ -1370,7 +1315,7 @@ ieee80211_deliver_skb(struct ieee80211_rx_data *rx)
        }
 }
 
-static ieee80211_rx_result
+static ieee80211_rx_result debug_noinline
 ieee80211_rx_h_amsdu(struct ieee80211_rx_data *rx)
 {
        struct net_device *dev = rx->dev;
@@ -1419,10 +1364,8 @@ ieee80211_rx_h_amsdu(struct ieee80211_rx_data *rx)
 
                padding = ((4 - subframe_len) & 0x3);
                /* the last MSDU has no padding */
-               if (subframe_len > remaining) {
-                       printk(KERN_DEBUG "%s: wrong buffer size\n", dev->name);
+               if (subframe_len > remaining)
                        return RX_DROP_UNUSABLE;
-               }
 
                skb_pull(skb, sizeof(struct ethhdr));
                /* if last subframe reuse skb */
@@ -1443,8 +1386,6 @@ ieee80211_rx_h_amsdu(struct ieee80211_rx_data *rx)
                        eth = (struct ethhdr *) skb_pull(skb, ntohs(len) +
                                                        padding);
                        if (!eth) {
-                               printk(KERN_DEBUG "%s: wrong buffer size\n",
-                                      dev->name);
                                dev_kfree_skb(frame);
                                return RX_DROP_UNUSABLE;
                        }
@@ -1487,7 +1428,7 @@ ieee80211_rx_h_amsdu(struct ieee80211_rx_data *rx)
        return RX_QUEUED;
 }
 
-static ieee80211_rx_result
+static ieee80211_rx_result debug_noinline
 ieee80211_rx_h_data(struct ieee80211_rx_data *rx)
 {
        struct net_device *dev = rx->dev;
@@ -1518,7 +1459,7 @@ ieee80211_rx_h_data(struct ieee80211_rx_data *rx)
        return RX_QUEUED;
 }
 
-static ieee80211_rx_result
+static ieee80211_rx_result debug_noinline
 ieee80211_rx_h_ctrl(struct ieee80211_rx_data *rx)
 {
        struct ieee80211_local *local = rx->local;
@@ -1562,7 +1503,7 @@ ieee80211_rx_h_ctrl(struct ieee80211_rx_data *rx)
        return RX_CONTINUE;
 }
 
-static ieee80211_rx_result
+static ieee80211_rx_result debug_noinline
 ieee80211_rx_h_mgmt(struct ieee80211_rx_data *rx)
 {
        struct ieee80211_sub_if_data *sdata;
@@ -1596,31 +1537,16 @@ static void ieee80211_rx_michael_mic_report(struct net_device *dev,
        else
                keyidx = -1;
 
-       if (net_ratelimit())
-               printk(KERN_DEBUG "%s: TKIP hwaccel reported Michael MIC "
-                      "failure from %s to %s keyidx=%d\n",
-                      dev->name, print_mac(mac, hdr->addr2),
-                      print_mac(mac2, hdr->addr1), keyidx);
-
        if (!rx->sta) {
                /*
                 * Some hardware seem to generate incorrect Michael MIC
                 * reports; ignore them to avoid triggering countermeasures.
                 */
-               if (net_ratelimit())
-                       printk(KERN_DEBUG "%s: ignored spurious Michael MIC "
-                              "error for unknown address %s\n",
-                              dev->name, print_mac(mac, hdr->addr2));
                goto ignore;
        }
 
-       if (!(rx->fc & IEEE80211_FCTL_PROTECTED)) {
-               if (net_ratelimit())
-                       printk(KERN_DEBUG "%s: ignored spurious Michael MIC "
-                              "error for a frame with no PROTECTED flag (src "
-                              "%s)\n", dev->name, print_mac(mac, hdr->addr2));
+       if (!(rx->fc & IEEE80211_FCTL_PROTECTED))
                goto ignore;
-       }
 
        if (rx->sdata->vif.type == IEEE80211_IF_TYPE_AP && keyidx) {
                /*
@@ -1629,24 +1555,13 @@ static void ieee80211_rx_michael_mic_report(struct net_device *dev,
                 * group keys and only the AP is sending real multicast
                 * frames in the BSS.
                 */
-               if (net_ratelimit())
-                       printk(KERN_DEBUG "%s: ignored Michael MIC error for "
-                              "a frame with non-zero keyidx (%d)"
-                              " (src %s)\n", dev->name, keyidx,
-                              print_mac(mac, hdr->addr2));
                goto ignore;
        }
 
        if ((rx->fc & IEEE80211_FCTL_FTYPE) != IEEE80211_FTYPE_DATA &&
            ((rx->fc & IEEE80211_FCTL_FTYPE) != IEEE80211_FTYPE_MGMT ||
-            (rx->fc & IEEE80211_FCTL_STYPE) != IEEE80211_STYPE_AUTH)) {
-               if (net_ratelimit())
-                       printk(KERN_DEBUG "%s: ignored spurious Michael MIC "
-                              "error for a frame that cannot be encrypted "
-                              "(fc=0x%04x) (src %s)\n",
-                              dev->name, rx->fc, print_mac(mac, hdr->addr2));
+            (rx->fc & IEEE80211_FCTL_STYPE) != IEEE80211_STYPE_AUTH))
                goto ignore;
-       }
 
        mac80211_ev_michael_mic_failure(rx->dev, keyidx, hdr);
  ignore:
@@ -1735,66 +1650,57 @@ static void ieee80211_rx_cooked_monitor(struct ieee80211_rx_data *rx)
        dev_kfree_skb(skb);
 }
 
-typedef ieee80211_rx_result (*ieee80211_rx_handler)(struct ieee80211_rx_data *);
-static ieee80211_rx_handler ieee80211_rx_handlers[] =
-{
-       ieee80211_rx_h_passive_scan,
-       ieee80211_rx_h_check,
-       ieee80211_rx_h_decrypt,
-       ieee80211_rx_h_sta_process,
-       ieee80211_rx_h_defragment,
-       ieee80211_rx_h_ps_poll,
-       ieee80211_rx_h_michael_mic_verify,
-       /* this must be after decryption - so header is counted in MPDU mic
-        * must be before pae and data, so QOS_DATA format frames
-        * are not passed to user space by these functions
-        */
-       ieee80211_rx_h_remove_qos_control,
-       ieee80211_rx_h_amsdu,
-       ieee80211_rx_h_data,
-       ieee80211_rx_h_ctrl,
-       ieee80211_rx_h_mgmt,
-       NULL
-};
 
 static void ieee80211_invoke_rx_handlers(struct ieee80211_sub_if_data *sdata,
                                         struct ieee80211_rx_data *rx,
                                         struct sk_buff *skb)
 {
-       ieee80211_rx_handler *handler;
        ieee80211_rx_result res = RX_DROP_MONITOR;
 
        rx->skb = skb;
        rx->sdata = sdata;
        rx->dev = sdata->dev;
 
-       for (handler = ieee80211_rx_handlers; *handler != NULL; handler++) {
-               res = (*handler)(rx);
-
-               switch (res) {
-               case RX_CONTINUE:
-                       continue;
-               case RX_DROP_UNUSABLE:
-               case RX_DROP_MONITOR:
-                       I802_DEBUG_INC(sdata->local->rx_handlers_drop);
-                       if (rx->sta)
-                               rx->sta->rx_dropped++;
-                       break;
-               case RX_QUEUED:
-                       I802_DEBUG_INC(sdata->local->rx_handlers_queued);
-                       break;
-               }
-               break;
-       }
-
+#define CALL_RXH(rxh)          \
+       res = rxh(rx);          \
+       if (res != RX_CONTINUE) \
+               goto rxh_done;
+
+       CALL_RXH(ieee80211_rx_h_passive_scan)
+       CALL_RXH(ieee80211_rx_h_check)
+       CALL_RXH(ieee80211_rx_h_decrypt)
+       CALL_RXH(ieee80211_rx_h_sta_process)
+       CALL_RXH(ieee80211_rx_h_defragment)
+       CALL_RXH(ieee80211_rx_h_ps_poll)
+       CALL_RXH(ieee80211_rx_h_michael_mic_verify)
+       /* must be after MMIC verify so header is counted in MPDU mic */
+       CALL_RXH(ieee80211_rx_h_remove_qos_control)
+       CALL_RXH(ieee80211_rx_h_amsdu)
+       CALL_RXH(ieee80211_rx_h_data)
+       CALL_RXH(ieee80211_rx_h_ctrl)
+       CALL_RXH(ieee80211_rx_h_mgmt)
+
+#undef CALL_RXH
+
+ rxh_done:
        switch (res) {
-       case RX_CONTINUE:
        case RX_DROP_MONITOR:
+               I802_DEBUG_INC(sdata->local->rx_handlers_drop);
+               if (rx->sta)
+                       rx->sta->rx_dropped++;
+               /* fall through */
+       case RX_CONTINUE:
                ieee80211_rx_cooked_monitor(rx);
                break;
        case RX_DROP_UNUSABLE:
+               I802_DEBUG_INC(sdata->local->rx_handlers_drop);
+               if (rx->sta)
+                       rx->sta->rx_dropped++;
                dev_kfree_skb(rx->skb);
                break;
+       case RX_QUEUED:
+               I802_DEBUG_INC(sdata->local->rx_handlers_queued);
+               break;
        }
 }
 
@@ -1826,8 +1732,13 @@ static int prepare_for_handlers(struct ieee80211_sub_if_data *sdata,
                if (!bssid)
                        return 0;
                if ((rx->fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_MGMT &&
-                   (rx->fc & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_BEACON)
+                   (rx->fc & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_BEACON) {
+                       if (!rx->sta)
+                               rx->sta = ieee80211_ibss_add_sta(sdata->dev,
+                                               rx->skb, bssid, hdr->addr2,
+                                               BIT(rx->status->rate_idx));
                        return 1;
+               }
                else if (!ieee80211_bssid_match(bssid, sdata->u.sta.bssid)) {
                        if (!(rx->flags & IEEE80211_RX_IN_SCAN))
                                return 0;
@@ -1840,7 +1751,8 @@ static int prepare_for_handlers(struct ieee80211_sub_if_data *sdata,
                        rx->flags &= ~IEEE80211_RX_RA_MATCH;
                } else if (!rx->sta)
                        rx->sta = ieee80211_ibss_add_sta(sdata->dev, rx->skb,
-                                                        bssid, hdr->addr2);
+                                               bssid, hdr->addr2,
+                                               BIT(rx->status->rate_idx));
                break;
        case IEEE80211_IF_TYPE_MESH_POINT:
                if (!multicast &&
@@ -2118,24 +2030,21 @@ static u8 ieee80211_rx_reorder_ampdu(struct ieee80211_local *local,
        struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
        struct sta_info *sta;
        struct tid_ampdu_rx *tid_agg_rx;
-       u16 fc, sc;
+       u16 sc;
        u16 mpdu_seq_num;
-       u8 ret = 0, *qc;
+       u8 ret = 0;
        int tid;
 
        sta = sta_info_get(local, hdr->addr2);
        if (!sta)
                return ret;
 
-       fc = le16_to_cpu(hdr->frame_control);
-
        /* filter the QoS data rx stream according to
         * STA/TID and check if this STA/TID is on aggregation */
-       if (!WLAN_FC_IS_QOS_DATA(fc))
+       if (!ieee80211_is_data_qos(hdr->frame_control))
                goto end_reorder;
 
-       qc = skb->data + ieee80211_get_hdrlen(fc) - QOS_CONTROL_LEN;
-       tid = qc[0] & QOS_CONTROL_TID_MASK;
+       tid = *ieee80211_get_qos_ctl(hdr) & QOS_CONTROL_TID_MASK;
 
        if (sta->ampdu_mlme.tid_state_rx[tid] != HT_AGG_STATE_OPERATIONAL)
                goto end_reorder;
@@ -2143,7 +2052,7 @@ static u8 ieee80211_rx_reorder_ampdu(struct ieee80211_local *local,
        tid_agg_rx = sta->ampdu_mlme.tid_rx[tid];
 
        /* null data frames are excluded */
-       if (unlikely(fc & IEEE80211_STYPE_NULLFUNC))
+       if (unlikely(ieee80211_is_nullfunc(hdr->frame_control)))
                goto end_reorder;
 
        /* new un-ordered ampdu frame - process it */