aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac80211/rx.c
diff options
context:
space:
mode:
authorLuis Carlos Cobo <luisca@cozybit.com>2008-02-23 09:17:10 -0500
committerJohn W. Linville <linville@tuxdriver.com>2008-03-06 15:30:41 -0500
commit33b64eb2b1b1759cbdafbe5c59df652f1e7c746e (patch)
tree10b314d244e4a44229a6b0da85c3ac76cce2c895 /net/mac80211/rx.c
parent2e3c8736820bf72a8ad10721c7e31d36d4fa7790 (diff)
mac80211: support for mesh interfaces in mac80211 data path
This changes the TX/RX paths in mac80211 to support mesh interfaces. This code will be cleaned up later again before being enabled. Signed-off-by: Luis Carlos Cobo <luisca@cozybit.com> Signed-off-by: Johannes Berg <johannes@sipsolutions.net> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'net/mac80211/rx.c')
-rw-r--r--net/mac80211/rx.c121
1 files changed, 117 insertions, 4 deletions
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c
index b7eeae0d3956..cc4a896c617f 100644
--- a/net/mac80211/rx.c
+++ b/net/mac80211/rx.c
@@ -20,6 +20,9 @@
20 20
21#include "ieee80211_i.h" 21#include "ieee80211_i.h"
22#include "ieee80211_led.h" 22#include "ieee80211_led.h"
23#ifdef CONFIG_MAC80211_MESH
24#include "mesh.h"
25#endif
23#include "wep.h" 26#include "wep.h"
24#include "wpa.h" 27#include "wpa.h"
25#include "tkip.h" 28#include "tkip.h"
@@ -390,10 +393,60 @@ ieee80211_rx_h_passive_scan(struct ieee80211_txrx_data *rx)
390 return RX_CONTINUE; 393 return RX_CONTINUE;
391} 394}
392 395
396#ifdef CONFIG_MAC80211_MESH
397#define msh_h_get(h, l) ((struct ieee80211s_hdr *) ((u8 *)h + l))
398static ieee80211_rx_result
399ieee80211_rx_mesh_check(struct ieee80211_txrx_data *rx)
400{
401 int hdrlen = ieee80211_get_hdrlen(rx->fc);
402 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) rx->skb->data;
403 if ((rx->fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_DATA) {
404 if (!((rx->fc & IEEE80211_FCTL_FROMDS) &&
405 (rx->fc & IEEE80211_FCTL_TODS)))
406 return RX_DROP_MONITOR;
407 if (memcmp(hdr->addr4, rx->dev->dev_addr, ETH_ALEN) == 0)
408 return RX_DROP_MONITOR;
409 }
410
411 /* If there is not an established peer link and this is not a peer link
412 * establisment frame, beacon or probe, drop the frame.
413 */
414
415 if (!rx->sta || rx->sta->plink_state != ESTAB) {
416 struct ieee80211_mgmt *mgmt;
417 if ((rx->fc & IEEE80211_FCTL_FTYPE) != IEEE80211_FTYPE_MGMT)
418 return RX_DROP_MONITOR;
419
420 switch (rx->fc & IEEE80211_FCTL_STYPE) {
421 case IEEE80211_STYPE_ACTION:
422 mgmt = (struct ieee80211_mgmt *)hdr;
423 if (mgmt->u.action.category != PLINK_CATEGORY)
424 return RX_DROP_MONITOR;
425 /* fall through on else */
426 case IEEE80211_STYPE_PROBE_REQ:
427 case IEEE80211_STYPE_PROBE_RESP:
428 case IEEE80211_STYPE_BEACON:
429 return RX_CONTINUE;
430 break;
431 default:
432 return RX_DROP_MONITOR;
433 }
434
435 } else if ((rx->fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_DATA &&
436 is_broadcast_ether_addr(hdr->addr1) &&
437 mesh_rmc_check(hdr->addr4, msh_h_get(hdr, hdrlen), rx->dev))
438 return RX_DROP_MONITOR;
439 else
440 return RX_CONTINUE;
441}
442#endif
443
444
393static ieee80211_rx_result 445static ieee80211_rx_result
394ieee80211_rx_h_check(struct ieee80211_txrx_data *rx) 446ieee80211_rx_h_check(struct ieee80211_txrx_data *rx)
395{ 447{
396 struct ieee80211_hdr *hdr; 448 struct ieee80211_hdr *hdr;
449
397 hdr = (struct ieee80211_hdr *) rx->skb->data; 450 hdr = (struct ieee80211_hdr *) rx->skb->data;
398 451
399 /* Drop duplicate 802.11 retransmissions (IEEE 802.11 Chap. 9.2.9) */ 452 /* Drop duplicate 802.11 retransmissions (IEEE 802.11 Chap. 9.2.9) */
@@ -423,6 +476,12 @@ ieee80211_rx_h_check(struct ieee80211_txrx_data *rx)
423 * deauth/disassoc frames when needed. In addition, hostapd is 476 * deauth/disassoc frames when needed. In addition, hostapd is
424 * responsible for filtering on both auth and assoc states. 477 * responsible for filtering on both auth and assoc states.
425 */ 478 */
479
480#ifdef CONFIG_MAC80211_MESH
481 if (rx->sdata->vif.type == IEEE80211_IF_TYPE_MESH_POINT)
482 return ieee80211_rx_mesh_check(rx);
483#endif
484
426 if (unlikely(((rx->fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_DATA || 485 if (unlikely(((rx->fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_DATA ||
427 ((rx->fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_CTL && 486 ((rx->fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_CTL &&
428 (rx->fc & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_PSPOLL)) && 487 (rx->fc & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_PSPOLL)) &&
@@ -657,6 +716,8 @@ ieee80211_rx_h_sta_process(struct ieee80211_txrx_data *rx)
657 /* Update last_rx only for unicast frames in order to prevent 716 /* Update last_rx only for unicast frames in order to prevent
658 * the Probe Request frames (the only broadcast frames from a 717 * the Probe Request frames (the only broadcast frames from a
659 * STA in infrastructure mode) from keeping a connection alive. 718 * STA in infrastructure mode) from keeping a connection alive.
719 * Mesh beacons will update last_rx when if they are found to
720 * match the current local configuration when processed.
660 */ 721 */
661 sta->last_rx = jiffies; 722 sta->last_rx = jiffies;
662 } 723 }
@@ -1050,6 +1111,23 @@ ieee80211_data_to_8023(struct ieee80211_txrx_data *rx)
1050 1111
1051 hdrlen = ieee80211_get_hdrlen(fc); 1112 hdrlen = ieee80211_get_hdrlen(fc);
1052 1113
1114#ifdef CONFIG_MAC80211_MESH
1115 if (sdata->vif.type == IEEE80211_IF_TYPE_MESH_POINT) {
1116 int meshhdrlen = ieee80211_get_mesh_hdrlen(
1117 (struct ieee80211s_hdr *) (skb->data + hdrlen));
1118 /* Copy on cb:
1119 * - mesh header: to be used for mesh forwarding
1120 * decision. It will also be used as mesh header template at
1121 * tx.c:ieee80211_subif_start_xmit() if interface
1122 * type is mesh and skb->pkt_type == PACKET_OTHERHOST
1123 * - ta: to be used if a RERR needs to be sent.
1124 */
1125 memcpy(skb->cb, skb->data + hdrlen, meshhdrlen);
1126 memcpy(MESH_PREQ(skb), hdr->addr2, ETH_ALEN);
1127 hdrlen += meshhdrlen;
1128 }
1129#endif
1130
1053 /* convert IEEE 802.11 header + possible LLC headers into Ethernet 1131 /* convert IEEE 802.11 header + possible LLC headers into Ethernet
1054 * header 1132 * header
1055 * IEEE 802.11 address fields: 1133 * IEEE 802.11 address fields:
@@ -1083,9 +1161,10 @@ ieee80211_data_to_8023(struct ieee80211_txrx_data *rx)
1083 memcpy(dst, hdr->addr3, ETH_ALEN); 1161 memcpy(dst, hdr->addr3, ETH_ALEN);
1084 memcpy(src, hdr->addr4, ETH_ALEN); 1162 memcpy(src, hdr->addr4, ETH_ALEN);
1085 1163
1086 if (unlikely(sdata->vif.type != IEEE80211_IF_TYPE_WDS)) { 1164 if (unlikely(sdata->vif.type != IEEE80211_IF_TYPE_WDS &&
1087 if (net_ratelimit()) 1165 sdata->vif.type != IEEE80211_IF_TYPE_MESH_POINT)) {
1088 printk(KERN_DEBUG "%s: dropped FromDS&ToDS " 1166 if (net_ratelimit())
1167 printk(KERN_DEBUG "%s: dropped FromDS&ToDS "
1089 "frame (RA=%s TA=%s DA=%s SA=%s)\n", 1168 "frame (RA=%s TA=%s DA=%s SA=%s)\n",
1090 rx->dev->name, 1169 rx->dev->name,
1091 print_mac(mac, hdr->addr1), 1170 print_mac(mac, hdr->addr1),
@@ -1227,6 +1306,39 @@ ieee80211_deliver_skb(struct ieee80211_txrx_data *rx)
1227 } 1306 }
1228 } 1307 }
1229 1308
1309#ifdef CONFIG_MAC80211_MESH
1310 /* Mesh forwarding */
1311 if (sdata->vif.type == IEEE80211_IF_TYPE_MESH_POINT) {
1312 u8 *mesh_ttl = &((struct ieee80211s_hdr *)skb->cb)->ttl;
1313 (*mesh_ttl)--;
1314
1315 if (is_multicast_ether_addr(skb->data)) {
1316 if (*mesh_ttl > 0) {
1317 xmit_skb = skb_copy(skb, GFP_ATOMIC);
1318 if (!xmit_skb && net_ratelimit())
1319 printk(KERN_DEBUG "%s: failed to clone "
1320 "multicast frame\n", dev->name);
1321 else
1322 xmit_skb->pkt_type = PACKET_OTHERHOST;
1323 } else
1324 sdata->u.sta.mshstats.dropped_frames_ttl++;
1325
1326 } else if (skb->pkt_type != PACKET_OTHERHOST &&
1327 compare_ether_addr(dev->dev_addr, skb->data) != 0) {
1328 if (*mesh_ttl == 0) {
1329 sdata->u.sta.mshstats.dropped_frames_ttl++;
1330 dev_kfree_skb(skb);
1331 skb = NULL;
1332 } else {
1333 xmit_skb = skb;
1334 xmit_skb->pkt_type = PACKET_OTHERHOST;
1335 if (!(dev->flags & IFF_PROMISC))
1336 skb = NULL;
1337 }
1338 }
1339 }
1340#endif
1341
1230 if (skb) { 1342 if (skb) {
1231 /* deliver to local stack */ 1343 /* deliver to local stack */
1232 skb->protocol = eth_type_trans(skb, dev); 1344 skb->protocol = eth_type_trans(skb, dev);
@@ -1444,7 +1556,8 @@ ieee80211_rx_h_mgmt(struct ieee80211_txrx_data *rx)
1444 1556
1445 sdata = IEEE80211_DEV_TO_SUB_IF(rx->dev); 1557 sdata = IEEE80211_DEV_TO_SUB_IF(rx->dev);
1446 if ((sdata->vif.type == IEEE80211_IF_TYPE_STA || 1558 if ((sdata->vif.type == IEEE80211_IF_TYPE_STA ||
1447 sdata->vif.type == IEEE80211_IF_TYPE_IBSS) && 1559 sdata->vif.type == IEEE80211_IF_TYPE_IBSS ||
1560 sdata->vif.type == IEEE80211_IF_TYPE_MESH_POINT) &&
1448 !(sdata->flags & IEEE80211_SDATA_USERSPACE_MLME)) 1561 !(sdata->flags & IEEE80211_SDATA_USERSPACE_MLME))
1449 ieee80211_sta_rx_mgmt(rx->dev, rx->skb, rx->u.rx.status); 1562 ieee80211_sta_rx_mgmt(rx->dev, rx->skb, rx->u.rx.status);
1450 else 1563 else