diff options
author | Luis Carlos Cobo <luisca@cozybit.com> | 2008-02-23 09:17:10 -0500 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2008-03-06 15:30:41 -0500 |
commit | 33b64eb2b1b1759cbdafbe5c59df652f1e7c746e (patch) | |
tree | 10b314d244e4a44229a6b0da85c3ac76cce2c895 /net/mac80211/rx.c | |
parent | 2e3c8736820bf72a8ad10721c7e31d36d4fa7790 (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.c | 121 |
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)) | ||
398 | static ieee80211_rx_result | ||
399 | ieee80211_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 | |||
393 | static ieee80211_rx_result | 445 | static ieee80211_rx_result |
394 | ieee80211_rx_h_check(struct ieee80211_txrx_data *rx) | 446 | ieee80211_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 |