diff options
Diffstat (limited to 'net/mac80211/rx.c')
-rw-r--r-- | net/mac80211/rx.c | 116 |
1 files changed, 67 insertions, 49 deletions
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index 6d9ae67c27ca..6db854505193 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c | |||
@@ -1109,20 +1109,9 @@ ieee80211_data_to_8023(struct ieee80211_rx_data *rx) | |||
1109 | 1109 | ||
1110 | hdrlen = ieee80211_get_hdrlen(fc); | 1110 | hdrlen = ieee80211_get_hdrlen(fc); |
1111 | 1111 | ||
1112 | if (ieee80211_vif_is_mesh(&sdata->vif)) { | 1112 | if (ieee80211_vif_is_mesh(&sdata->vif)) |
1113 | int meshhdrlen = ieee80211_get_mesh_hdrlen( | 1113 | hdrlen += ieee80211_get_mesh_hdrlen( |
1114 | (struct ieee80211s_hdr *) (skb->data + hdrlen)); | 1114 | (struct ieee80211s_hdr *) (skb->data + hdrlen)); |
1115 | /* Copy on cb: | ||
1116 | * - mesh header: to be used for mesh forwarding | ||
1117 | * decision. It will also be used as mesh header template at | ||
1118 | * tx.c:ieee80211_subif_start_xmit() if interface | ||
1119 | * type is mesh and skb->pkt_type == PACKET_OTHERHOST | ||
1120 | * - ta: to be used if a RERR needs to be sent. | ||
1121 | */ | ||
1122 | memcpy(skb->cb, skb->data + hdrlen, meshhdrlen); | ||
1123 | memcpy(MESH_PREQ(skb), hdr->addr2, ETH_ALEN); | ||
1124 | hdrlen += meshhdrlen; | ||
1125 | } | ||
1126 | 1115 | ||
1127 | /* convert IEEE 802.11 header + possible LLC headers into Ethernet | 1116 | /* convert IEEE 802.11 header + possible LLC headers into Ethernet |
1128 | * header | 1117 | * header |
@@ -1269,38 +1258,6 @@ ieee80211_deliver_skb(struct ieee80211_rx_data *rx) | |||
1269 | } | 1258 | } |
1270 | } | 1259 | } |
1271 | 1260 | ||
1272 | /* Mesh forwarding */ | ||
1273 | if (ieee80211_vif_is_mesh(&sdata->vif)) { | ||
1274 | u8 *mesh_ttl = &((struct ieee80211s_hdr *)skb->cb)->ttl; | ||
1275 | (*mesh_ttl)--; | ||
1276 | |||
1277 | if (is_multicast_ether_addr(skb->data)) { | ||
1278 | if (*mesh_ttl > 0) { | ||
1279 | xmit_skb = skb_copy(skb, GFP_ATOMIC); | ||
1280 | if (xmit_skb) | ||
1281 | xmit_skb->pkt_type = PACKET_OTHERHOST; | ||
1282 | else if (net_ratelimit()) | ||
1283 | printk(KERN_DEBUG "%s: failed to clone " | ||
1284 | "multicast frame\n", dev->name); | ||
1285 | } else | ||
1286 | IEEE80211_IFSTA_MESH_CTR_INC(&sdata->u.sta, | ||
1287 | dropped_frames_ttl); | ||
1288 | } else if (skb->pkt_type != PACKET_OTHERHOST && | ||
1289 | compare_ether_addr(dev->dev_addr, skb->data) != 0) { | ||
1290 | if (*mesh_ttl == 0) { | ||
1291 | IEEE80211_IFSTA_MESH_CTR_INC(&sdata->u.sta, | ||
1292 | dropped_frames_ttl); | ||
1293 | dev_kfree_skb(skb); | ||
1294 | skb = NULL; | ||
1295 | } else { | ||
1296 | xmit_skb = skb; | ||
1297 | xmit_skb->pkt_type = PACKET_OTHERHOST; | ||
1298 | if (!(dev->flags & IFF_PROMISC)) | ||
1299 | skb = NULL; | ||
1300 | } | ||
1301 | } | ||
1302 | } | ||
1303 | |||
1304 | if (skb) { | 1261 | if (skb) { |
1305 | /* deliver to local stack */ | 1262 | /* deliver to local stack */ |
1306 | skb->protocol = eth_type_trans(skb, dev); | 1263 | skb->protocol = eth_type_trans(skb, dev); |
@@ -1431,6 +1388,63 @@ ieee80211_rx_h_amsdu(struct ieee80211_rx_data *rx) | |||
1431 | } | 1388 | } |
1432 | 1389 | ||
1433 | static ieee80211_rx_result debug_noinline | 1390 | static ieee80211_rx_result debug_noinline |
1391 | ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx) | ||
1392 | { | ||
1393 | struct ieee80211_hdr *hdr; | ||
1394 | struct ieee80211s_hdr *mesh_hdr; | ||
1395 | unsigned int hdrlen; | ||
1396 | struct sk_buff *skb = rx->skb, *fwd_skb; | ||
1397 | |||
1398 | hdr = (struct ieee80211_hdr *) skb->data; | ||
1399 | hdrlen = ieee80211_hdrlen(hdr->frame_control); | ||
1400 | mesh_hdr = (struct ieee80211s_hdr *) (skb->data + hdrlen); | ||
1401 | |||
1402 | if (!ieee80211_is_data(hdr->frame_control)) | ||
1403 | return RX_CONTINUE; | ||
1404 | |||
1405 | if (!mesh_hdr->ttl) | ||
1406 | /* illegal frame */ | ||
1407 | return RX_DROP_MONITOR; | ||
1408 | |||
1409 | if (compare_ether_addr(rx->dev->dev_addr, hdr->addr3) == 0) | ||
1410 | return RX_CONTINUE; | ||
1411 | |||
1412 | mesh_hdr->ttl--; | ||
1413 | |||
1414 | if (rx->flags & IEEE80211_RX_RA_MATCH) { | ||
1415 | if (!mesh_hdr->ttl) | ||
1416 | IEEE80211_IFSTA_MESH_CTR_INC(&rx->sdata->u.sta, | ||
1417 | dropped_frames_ttl); | ||
1418 | else { | ||
1419 | struct ieee80211_hdr *fwd_hdr; | ||
1420 | fwd_skb = skb_copy(skb, GFP_ATOMIC); | ||
1421 | |||
1422 | if (!fwd_skb && net_ratelimit()) | ||
1423 | printk(KERN_DEBUG "%s: failed to clone mesh frame\n", | ||
1424 | rx->dev->name); | ||
1425 | |||
1426 | fwd_hdr = (struct ieee80211_hdr *) fwd_skb->data; | ||
1427 | /* | ||
1428 | * Save TA to addr1 to send TA a path error if a | ||
1429 | * suitable next hop is not found | ||
1430 | */ | ||
1431 | memcpy(fwd_hdr->addr1, fwd_hdr->addr2, ETH_ALEN); | ||
1432 | memcpy(fwd_hdr->addr2, rx->dev->dev_addr, ETH_ALEN); | ||
1433 | fwd_skb->dev = rx->local->mdev; | ||
1434 | fwd_skb->iif = rx->dev->ifindex; | ||
1435 | dev_queue_xmit(fwd_skb); | ||
1436 | } | ||
1437 | } | ||
1438 | |||
1439 | if (is_multicast_ether_addr(hdr->addr3) || | ||
1440 | rx->dev->flags & IFF_PROMISC) | ||
1441 | return RX_CONTINUE; | ||
1442 | else | ||
1443 | return RX_DROP_MONITOR; | ||
1444 | } | ||
1445 | |||
1446 | |||
1447 | static ieee80211_rx_result debug_noinline | ||
1434 | ieee80211_rx_h_data(struct ieee80211_rx_data *rx) | 1448 | ieee80211_rx_h_data(struct ieee80211_rx_data *rx) |
1435 | { | 1449 | { |
1436 | struct net_device *dev = rx->dev; | 1450 | struct net_device *dev = rx->dev; |
@@ -1663,10 +1677,12 @@ static void ieee80211_invoke_rx_handlers(struct ieee80211_sub_if_data *sdata, | |||
1663 | rx->sdata = sdata; | 1677 | rx->sdata = sdata; |
1664 | rx->dev = sdata->dev; | 1678 | rx->dev = sdata->dev; |
1665 | 1679 | ||
1666 | #define CALL_RXH(rxh) \ | 1680 | #define CALL_RXH(rxh) \ |
1667 | res = rxh(rx); \ | 1681 | do { \ |
1668 | if (res != RX_CONTINUE) \ | 1682 | res = rxh(rx); \ |
1669 | goto rxh_done; | 1683 | if (res != RX_CONTINUE) \ |
1684 | goto rxh_done; \ | ||
1685 | } while (0); | ||
1670 | 1686 | ||
1671 | CALL_RXH(ieee80211_rx_h_passive_scan) | 1687 | CALL_RXH(ieee80211_rx_h_passive_scan) |
1672 | CALL_RXH(ieee80211_rx_h_check) | 1688 | CALL_RXH(ieee80211_rx_h_check) |
@@ -1678,6 +1694,8 @@ static void ieee80211_invoke_rx_handlers(struct ieee80211_sub_if_data *sdata, | |||
1678 | /* must be after MMIC verify so header is counted in MPDU mic */ | 1694 | /* must be after MMIC verify so header is counted in MPDU mic */ |
1679 | CALL_RXH(ieee80211_rx_h_remove_qos_control) | 1695 | CALL_RXH(ieee80211_rx_h_remove_qos_control) |
1680 | CALL_RXH(ieee80211_rx_h_amsdu) | 1696 | CALL_RXH(ieee80211_rx_h_amsdu) |
1697 | if (ieee80211_vif_is_mesh(&sdata->vif)) | ||
1698 | CALL_RXH(ieee80211_rx_h_mesh_fwding); | ||
1681 | CALL_RXH(ieee80211_rx_h_data) | 1699 | CALL_RXH(ieee80211_rx_h_data) |
1682 | CALL_RXH(ieee80211_rx_h_ctrl) | 1700 | CALL_RXH(ieee80211_rx_h_ctrl) |
1683 | CALL_RXH(ieee80211_rx_h_mgmt) | 1701 | CALL_RXH(ieee80211_rx_h_mgmt) |