aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJohannes Berg <johannes@sipsolutions.net>2007-09-26 09:19:39 -0400
committerDavid S. Miller <davem@sunset.davemloft.net>2007-10-10 19:53:12 -0400
commitb2e7771e556917cc301a3308561f49b2b2272c07 (patch)
treeb80ba2b75a78c87d7fcc5f444cb0accae00d8670
parent5b2812e925c8e976852867f8d760637c5926d817 (diff)
[PATCH] mac80211: pass frames to monitor interfaces early
This makes mac80211 pass all frames to monitor interfaces early before all receive processing with the benefit that only a single copy needs to be made, all monitors can receive clones of the skb and if the frame will be discarded we don't even need to make a single copy. Signed-off-by: Johannes Berg <johannes@sipsolutions.net> Signed-off-by: John W. Linville <linville@tuxdriver.com>
-rw-r--r--net/mac80211/rx.c350
1 files changed, 226 insertions, 124 deletions
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c
index cb44a9db0e19..a0dfafb4f38b 100644
--- a/net/mac80211/rx.c
+++ b/net/mac80211/rx.c
@@ -25,6 +25,207 @@
25#include "tkip.h" 25#include "tkip.h"
26#include "wme.h" 26#include "wme.h"
27 27
28/*
29 * monitor mode reception
30 *
31 * This function cleans up the SKB, i.e. it removes all the stuff
32 * only useful for monitoring.
33 */
34static struct sk_buff *remove_monitor_info(struct ieee80211_local *local,
35 struct sk_buff *skb,
36 int rtap_len)
37{
38 skb_pull(skb, rtap_len);
39
40 if (local->hw.flags & IEEE80211_HW_RX_INCLUDES_FCS) {
41 if (likely(skb->len > FCS_LEN))
42 skb_trim(skb, skb->len - FCS_LEN);
43 else {
44 /* driver bug */
45 WARN_ON(1);
46 dev_kfree_skb(skb);
47 skb = NULL;
48 }
49 }
50
51 return skb;
52}
53
54static inline int should_drop_frame(struct ieee80211_rx_status *status,
55 struct sk_buff *skb,
56 int present_fcs_len,
57 int radiotap_len)
58{
59 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
60
61 if (status->flag & (RX_FLAG_FAILED_FCS_CRC | RX_FLAG_FAILED_PLCP_CRC))
62 return 1;
63 if (unlikely(skb->len < 16 + present_fcs_len + radiotap_len))
64 return 1;
65 if ((hdr->frame_control & cpu_to_le16(IEEE80211_FCTL_FTYPE)) ==
66 cpu_to_le16(IEEE80211_FTYPE_CTL))
67 return 1;
68 return 0;
69}
70
71/*
72 * This function copies a received frame to all monitor interfaces and
73 * returns a cleaned-up SKB that no longer includes the FCS nor the
74 * radiotap header the driver might have added.
75 */
76static struct sk_buff *
77ieee80211_rx_monitor(struct ieee80211_local *local, struct sk_buff *origskb,
78 struct ieee80211_rx_status *status)
79{
80 struct ieee80211_sub_if_data *sdata;
81 struct ieee80211_rate *rate;
82 int needed_headroom = 0;
83 struct ieee80211_rtap_hdr {
84 struct ieee80211_radiotap_header hdr;
85 u8 flags;
86 u8 rate;
87 __le16 chan_freq;
88 __le16 chan_flags;
89 u8 antsignal;
90 u8 padding_for_rxflags;
91 __le16 rx_flags;
92 } __attribute__ ((packed)) *rthdr;
93 struct sk_buff *skb, *skb2;
94 struct net_device *prev_dev = NULL;
95 int present_fcs_len = 0;
96 int rtap_len = 0;
97
98 /*
99 * First, we may need to make a copy of the skb because
100 * (1) we need to modify it for radiotap (if not present), and
101 * (2) the other RX handlers will modify the skb we got.
102 *
103 * We don't need to, of course, if we aren't going to return
104 * the SKB because it has a bad FCS/PLCP checksum.
105 */
106 if (status->flag & RX_FLAG_RADIOTAP)
107 rtap_len = ieee80211_get_radiotap_len(origskb->data);
108 else
109 needed_headroom = sizeof(*rthdr);
110
111 if (local->hw.flags & IEEE80211_HW_RX_INCLUDES_FCS)
112 present_fcs_len = FCS_LEN;
113
114 if (!local->monitors) {
115 if (should_drop_frame(status, origskb, present_fcs_len,
116 rtap_len)) {
117 dev_kfree_skb(origskb);
118 return NULL;
119 }
120
121 return remove_monitor_info(local, origskb, rtap_len);
122 }
123
124 if (should_drop_frame(status, origskb, present_fcs_len, rtap_len)) {
125 /* only need to expand headroom if necessary */
126 skb = origskb;
127 origskb = NULL;
128
129 /*
130 * This shouldn't trigger often because most devices have an
131 * RX header they pull before we get here, and that should
132 * be big enough for our radiotap information. We should
133 * probably export the length to drivers so that we can have
134 * them allocate enough headroom to start with.
135 */
136 if (skb_headroom(skb) < needed_headroom &&
137 pskb_expand_head(skb, sizeof(*rthdr), 0, GFP_ATOMIC)) {
138 dev_kfree_skb(skb);
139 return NULL;
140 }
141 } else {
142 /*
143 * Need to make a copy and possibly remove radiotap header
144 * and FCS from the original.
145 */
146 skb = skb_copy_expand(origskb, needed_headroom, 0, GFP_ATOMIC);
147
148 origskb = remove_monitor_info(local, origskb, rtap_len);
149
150 if (!skb)
151 return origskb;
152 }
153
154 /* if necessary, prepend radiotap information */
155 if (!(status->flag & RX_FLAG_RADIOTAP)) {
156 rthdr = (void *) skb_push(skb, sizeof(*rthdr));
157 memset(rthdr, 0, sizeof(*rthdr));
158 rthdr->hdr.it_len = cpu_to_le16(sizeof(*rthdr));
159 rthdr->hdr.it_present =
160 cpu_to_le32((1 << IEEE80211_RADIOTAP_FLAGS) |
161 (1 << IEEE80211_RADIOTAP_RATE) |
162 (1 << IEEE80211_RADIOTAP_CHANNEL) |
163 (1 << IEEE80211_RADIOTAP_DB_ANTSIGNAL) |
164 (1 << IEEE80211_RADIOTAP_RX_FLAGS));
165 rthdr->flags = local->hw.flags & IEEE80211_HW_RX_INCLUDES_FCS ?
166 IEEE80211_RADIOTAP_F_FCS : 0;
167
168 /* FIXME: when radiotap gets a 'bad PLCP' flag use it here */
169 rthdr->rx_flags = 0;
170 if (status->flag &
171 (RX_FLAG_FAILED_FCS_CRC | RX_FLAG_FAILED_PLCP_CRC))
172 rthdr->rx_flags |=
173 cpu_to_le16(IEEE80211_RADIOTAP_F_RX_BADFCS);
174
175 rate = ieee80211_get_rate(local, status->phymode,
176 status->rate);
177 if (rate)
178 rthdr->rate = rate->rate / 5;
179
180 rthdr->chan_freq = cpu_to_le16(status->freq);
181
182 if (status->phymode == MODE_IEEE80211A)
183 rthdr->chan_flags =
184 cpu_to_le16(IEEE80211_CHAN_OFDM |
185 IEEE80211_CHAN_5GHZ);
186 else
187 rthdr->chan_flags =
188 cpu_to_le16(IEEE80211_CHAN_DYN |
189 IEEE80211_CHAN_2GHZ);
190
191 rthdr->antsignal = status->ssi;
192 }
193
194 skb_set_mac_header(skb, 0);
195 skb->ip_summed = CHECKSUM_UNNECESSARY;
196 skb->pkt_type = PACKET_OTHERHOST;
197 skb->protocol = htons(ETH_P_802_2);
198
199 list_for_each_entry_rcu(sdata, &local->interfaces, list) {
200 if (!netif_running(sdata->dev))
201 continue;
202
203 if (sdata->type != IEEE80211_IF_TYPE_MNTR)
204 continue;
205
206 if (prev_dev) {
207 skb2 = skb_clone(skb, GFP_ATOMIC);
208 if (skb2) {
209 skb2->dev = prev_dev;
210 netif_rx(skb2);
211 }
212 }
213
214 prev_dev = sdata->dev;
215 sdata->dev->stats.rx_packets++;
216 sdata->dev->stats.rx_bytes += skb->len;
217 }
218
219 if (prev_dev) {
220 skb->dev = prev_dev;
221 netif_rx(skb);
222 } else
223 dev_kfree_skb(skb);
224
225 return origskb;
226}
227
228
28/* pre-rx handlers 229/* pre-rx handlers
29 * 230 *
30 * these don't have dev/sdata fields in the rx data 231 * these don't have dev/sdata fields in the rx data
@@ -132,100 +333,6 @@ ieee80211_rx_h_if_stats(struct ieee80211_txrx_data *rx)
132 return TXRX_CONTINUE; 333 return TXRX_CONTINUE;
133} 334}
134 335
135static void
136ieee80211_rx_monitor(struct net_device *dev, struct sk_buff *skb,
137 struct ieee80211_rx_status *status)
138{
139 struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
140 struct ieee80211_rate *rate;
141 struct ieee80211_rtap_hdr {
142 struct ieee80211_radiotap_header hdr;
143 u8 flags;
144 u8 rate;
145 __le16 chan_freq;
146 __le16 chan_flags;
147 u8 antsignal;
148 u8 padding_for_rxflags;
149 __le16 rx_flags;
150 } __attribute__ ((packed)) *rthdr;
151
152 skb->dev = dev;
153
154 if (status->flag & RX_FLAG_RADIOTAP)
155 goto out;
156
157 if (skb_headroom(skb) < sizeof(*rthdr)) {
158 I802_DEBUG_INC(local->rx_expand_skb_head);
159 if (pskb_expand_head(skb, sizeof(*rthdr), 0, GFP_ATOMIC)) {
160 dev_kfree_skb(skb);
161 return;
162 }
163 }
164
165 rthdr = (struct ieee80211_rtap_hdr *) skb_push(skb, sizeof(*rthdr));
166 memset(rthdr, 0, sizeof(*rthdr));
167 rthdr->hdr.it_len = cpu_to_le16(sizeof(*rthdr));
168 rthdr->hdr.it_present =
169 cpu_to_le32((1 << IEEE80211_RADIOTAP_FLAGS) |
170 (1 << IEEE80211_RADIOTAP_RATE) |
171 (1 << IEEE80211_RADIOTAP_CHANNEL) |
172 (1 << IEEE80211_RADIOTAP_DB_ANTSIGNAL) |
173 (1 << IEEE80211_RADIOTAP_RX_FLAGS));
174 rthdr->flags = local->hw.flags & IEEE80211_HW_RX_INCLUDES_FCS ?
175 IEEE80211_RADIOTAP_F_FCS : 0;
176
177 /* FIXME: when radiotap gets a 'bad PLCP' flag use it here */
178 rthdr->rx_flags = 0;
179 if (status->flag &
180 (RX_FLAG_FAILED_FCS_CRC | RX_FLAG_FAILED_PLCP_CRC))
181 rthdr->rx_flags |= cpu_to_le16(IEEE80211_RADIOTAP_F_RX_BADFCS);
182
183 rate = ieee80211_get_rate(local, status->phymode, status->rate);
184 if (rate)
185 rthdr->rate = rate->rate / 5;
186
187 rthdr->chan_freq = cpu_to_le16(status->freq);
188 rthdr->chan_flags =
189 status->phymode == MODE_IEEE80211A ?
190 cpu_to_le16(IEEE80211_CHAN_OFDM | IEEE80211_CHAN_5GHZ) :
191 cpu_to_le16(IEEE80211_CHAN_DYN | IEEE80211_CHAN_2GHZ);
192 rthdr->antsignal = status->ssi;
193
194 out:
195 dev->stats.rx_packets++;
196 dev->stats.rx_bytes += skb->len;
197
198 skb_set_mac_header(skb, 0);
199 skb->ip_summed = CHECKSUM_UNNECESSARY;
200 skb->pkt_type = PACKET_OTHERHOST;
201 skb->protocol = htons(ETH_P_802_2);
202 memset(skb->cb, 0, sizeof(skb->cb));
203 netif_rx(skb);
204}
205
206static ieee80211_txrx_result
207ieee80211_rx_h_monitor(struct ieee80211_txrx_data *rx)
208{
209 if (rx->sdata->type == IEEE80211_IF_TYPE_MNTR) {
210 ieee80211_rx_monitor(rx->dev, rx->skb, rx->u.rx.status);
211 return TXRX_QUEUED;
212 }
213
214 /*
215 * Drop frames with failed FCS/PLCP checksums here, they are only
216 * relevant for monitor mode, the rest of the stack should never
217 * see them.
218 */
219 if (rx->u.rx.status->flag &
220 (RX_FLAG_FAILED_FCS_CRC | RX_FLAG_FAILED_PLCP_CRC))
221 return TXRX_DROP;
222
223 if (rx->u.rx.status->flag & RX_FLAG_RADIOTAP)
224 skb_pull(rx->skb, ieee80211_get_radiotap_len(rx->skb->data));
225
226 return TXRX_CONTINUE;
227}
228
229static ieee80211_txrx_result 336static ieee80211_txrx_result
230ieee80211_rx_h_passive_scan(struct ieee80211_txrx_data *rx) 337ieee80211_rx_h_passive_scan(struct ieee80211_txrx_data *rx)
231{ 338{
@@ -266,10 +373,6 @@ ieee80211_rx_h_check(struct ieee80211_txrx_data *rx)
266 rx->sta->last_seq_ctrl[rx->u.rx.queue] = hdr->seq_ctrl; 373 rx->sta->last_seq_ctrl[rx->u.rx.queue] = hdr->seq_ctrl;
267 } 374 }
268 375
269 if ((rx->local->hw.flags & IEEE80211_HW_RX_INCLUDES_FCS) &&
270 rx->skb->len > FCS_LEN)
271 skb_trim(rx->skb, rx->skb->len - FCS_LEN);
272
273 if (unlikely(rx->skb->len < 16)) { 376 if (unlikely(rx->skb->len < 16)) {
274 I802_DEBUG_INC(rx->local->rx_handlers_drop_short); 377 I802_DEBUG_INC(rx->local->rx_handlers_drop_short);
275 return TXRX_DROP; 378 return TXRX_DROP;
@@ -1264,7 +1367,6 @@ static void ieee80211_rx_michael_mic_report(struct net_device *dev,
1264ieee80211_rx_handler ieee80211_rx_handlers[] = 1367ieee80211_rx_handler ieee80211_rx_handlers[] =
1265{ 1368{
1266 ieee80211_rx_h_if_stats, 1369 ieee80211_rx_h_if_stats,
1267 ieee80211_rx_h_monitor,
1268 ieee80211_rx_h_passive_scan, 1370 ieee80211_rx_h_passive_scan,
1269 ieee80211_rx_h_check, 1371 ieee80211_rx_h_check,
1270 ieee80211_rx_h_load_key, 1372 ieee80211_rx_h_load_key,
@@ -1371,16 +1473,10 @@ void __ieee80211_rx(struct ieee80211_hw *hw, struct sk_buff *skb,
1371 struct ieee80211_hdr *hdr; 1473 struct ieee80211_hdr *hdr;
1372 struct ieee80211_txrx_data rx; 1474 struct ieee80211_txrx_data rx;
1373 u16 type; 1475 u16 type;
1374 int radiotap_len = 0, prepres; 1476 int prepres;
1375 struct ieee80211_sub_if_data *prev = NULL; 1477 struct ieee80211_sub_if_data *prev = NULL;
1376 struct sk_buff *skb_new; 1478 struct sk_buff *skb_new;
1377 u8 *bssid; 1479 u8 *bssid;
1378 int bogon;
1379
1380 if (status->flag & RX_FLAG_RADIOTAP) {
1381 radiotap_len = ieee80211_get_radiotap_len(skb->data);
1382 skb_pull(skb, radiotap_len);
1383 }
1384 1480
1385 /* 1481 /*
1386 * key references and virtual interfaces are protected using RCU 1482 * key references and virtual interfaces are protected using RCU
@@ -1389,30 +1485,35 @@ void __ieee80211_rx(struct ieee80211_hw *hw, struct sk_buff *skb,
1389 */ 1485 */
1390 rcu_read_lock(); 1486 rcu_read_lock();
1391 1487
1488 /*
1489 * Frames with failed FCS/PLCP checksum are not returned,
1490 * all other frames are returned without radiotap header
1491 * if it was previously present.
1492 * Also, frames with less than 16 bytes are dropped.
1493 */
1494 skb = ieee80211_rx_monitor(local, skb, status);
1495 if (!skb) {
1496 rcu_read_unlock();
1497 return;
1498 }
1499
1392 hdr = (struct ieee80211_hdr *) skb->data; 1500 hdr = (struct ieee80211_hdr *) skb->data;
1393 memset(&rx, 0, sizeof(rx)); 1501 memset(&rx, 0, sizeof(rx));
1394 rx.skb = skb; 1502 rx.skb = skb;
1395 rx.local = local; 1503 rx.local = local;
1396 1504
1397 rx.u.rx.status = status; 1505 rx.u.rx.status = status;
1398 rx.fc = skb->len >= 2 ? le16_to_cpu(hdr->frame_control) : 0; 1506 rx.fc = le16_to_cpu(hdr->frame_control);
1399 type = rx.fc & IEEE80211_FCTL_FTYPE; 1507 type = rx.fc & IEEE80211_FCTL_FTYPE;
1400 1508
1401 bogon = status->flag & (RX_FLAG_FAILED_FCS_CRC | 1509 if (type == IEEE80211_FTYPE_DATA || type == IEEE80211_FTYPE_MGMT)
1402 RX_FLAG_FAILED_PLCP_CRC);
1403
1404 if (!bogon && (type == IEEE80211_FTYPE_DATA ||
1405 type == IEEE80211_FTYPE_MGMT))
1406 local->dot11ReceivedFragmentCount++; 1510 local->dot11ReceivedFragmentCount++;
1407 1511
1408 if (!bogon && skb->len >= 16) { 1512 sta = rx.sta = sta_info_get(local, hdr->addr2);
1409 sta = rx.sta = sta_info_get(local, hdr->addr2); 1513 if (sta) {
1410 if (sta) { 1514 rx.dev = rx.sta->dev;
1411 rx.dev = rx.sta->dev; 1515 rx.sdata = IEEE80211_DEV_TO_SUB_IF(rx.dev);
1412 rx.sdata = IEEE80211_DEV_TO_SUB_IF(rx.dev); 1516 }
1413 }
1414 } else
1415 sta = rx.sta = NULL;
1416 1517
1417 if ((status->flag & RX_FLAG_MMIC_ERROR)) { 1518 if ((status->flag & RX_FLAG_MMIC_ERROR)) {
1418 ieee80211_rx_michael_mic_report(local->mdev, hdr, sta, &rx); 1519 ieee80211_rx_michael_mic_report(local->mdev, hdr, sta, &rx);
@@ -1427,7 +1528,6 @@ void __ieee80211_rx(struct ieee80211_hw *hw, struct sk_buff *skb,
1427 goto end; 1528 goto end;
1428 skb = rx.skb; 1529 skb = rx.skb;
1429 1530
1430 skb_push(skb, radiotap_len);
1431 if (sta && !(sta->flags & (WLAN_STA_WDS | WLAN_STA_ASSOC_AP)) && 1531 if (sta && !(sta->flags & (WLAN_STA_WDS | WLAN_STA_ASSOC_AP)) &&
1432 !local->iff_promiscs && !is_multicast_ether_addr(hdr->addr1)) { 1532 !local->iff_promiscs && !is_multicast_ether_addr(hdr->addr1)) {
1433 rx.flags |= IEEE80211_TXRXD_RXRA_MATCH; 1533 rx.flags |= IEEE80211_TXRXD_RXRA_MATCH;
@@ -1438,14 +1538,16 @@ void __ieee80211_rx(struct ieee80211_hw *hw, struct sk_buff *skb,
1438 return; 1538 return;
1439 } 1539 }
1440 1540
1441 bssid = ieee80211_get_bssid(hdr, skb->len - radiotap_len); 1541 bssid = ieee80211_get_bssid(hdr, skb->len);
1442 1542
1443 list_for_each_entry_rcu(sdata, &local->interfaces, list) { 1543 list_for_each_entry_rcu(sdata, &local->interfaces, list) {
1444 rx.flags |= IEEE80211_TXRXD_RXRA_MATCH;
1445
1446 if (!netif_running(sdata->dev)) 1544 if (!netif_running(sdata->dev))
1447 continue; 1545 continue;
1448 1546
1547 if (sdata->type == IEEE80211_IF_TYPE_MNTR)
1548 continue;
1549
1550 rx.flags |= IEEE80211_TXRXD_RXRA_MATCH;
1449 prepres = prepare_for_handlers(sdata, bssid, &rx, hdr); 1551 prepres = prepare_for_handlers(sdata, bssid, &rx, hdr);
1450 /* prepare_for_handlers can change sta */ 1552 /* prepare_for_handlers can change sta */
1451 sta = rx.sta; 1553 sta = rx.sta;