diff options
| -rw-r--r-- | net/mac80211/mesh.h | 5 | ||||
| -rw-r--r-- | net/mac80211/mesh_hwmp.c | 19 | ||||
| -rw-r--r-- | net/mac80211/mesh_pathtbl.c | 11 | ||||
| -rw-r--r-- | net/mac80211/rx.c | 116 | ||||
| -rw-r--r-- | net/mac80211/tx.c | 45 |
5 files changed, 106 insertions, 90 deletions
diff --git a/net/mac80211/mesh.h b/net/mac80211/mesh.h index 669eafafe497..7495fbb0d211 100644 --- a/net/mac80211/mesh.h +++ b/net/mac80211/mesh.h | |||
| @@ -214,8 +214,7 @@ void ieee80211s_stop(void); | |||
| 214 | void ieee80211_mesh_init_sdata(struct ieee80211_sub_if_data *sdata); | 214 | void ieee80211_mesh_init_sdata(struct ieee80211_sub_if_data *sdata); |
| 215 | 215 | ||
| 216 | /* Mesh paths */ | 216 | /* Mesh paths */ |
| 217 | int mesh_nexthop_lookup(u8 *next_hop, struct sk_buff *skb, | 217 | int mesh_nexthop_lookup(struct sk_buff *skb, struct net_device *dev); |
| 218 | struct net_device *dev); | ||
| 219 | void mesh_path_start_discovery(struct net_device *dev); | 218 | void mesh_path_start_discovery(struct net_device *dev); |
| 220 | struct mesh_path *mesh_path_lookup(u8 *dst, struct net_device *dev); | 219 | struct mesh_path *mesh_path_lookup(u8 *dst, struct net_device *dev); |
| 221 | struct mesh_path *mesh_path_lookup_by_idx(int idx, struct net_device *dev); | 220 | struct mesh_path *mesh_path_lookup_by_idx(int idx, struct net_device *dev); |
| @@ -286,6 +285,4 @@ static inline void mesh_path_activate(struct mesh_path *mpath) | |||
| 286 | #define mesh_allocated 0 | 285 | #define mesh_allocated 0 |
| 287 | #endif | 286 | #endif |
| 288 | 287 | ||
| 289 | #define MESH_PREQ(skb) (skb->cb + 30) | ||
| 290 | |||
| 291 | #endif /* IEEE80211S_H */ | 288 | #endif /* IEEE80211S_H */ |
diff --git a/net/mac80211/mesh_hwmp.c b/net/mac80211/mesh_hwmp.c index 7fa149e230e6..08aca446ca01 100644 --- a/net/mac80211/mesh_hwmp.c +++ b/net/mac80211/mesh_hwmp.c | |||
| @@ -758,29 +758,30 @@ enddiscovery: | |||
| 758 | /** | 758 | /** |
| 759 | * ieee80211s_lookup_nexthop - put the appropriate next hop on a mesh frame | 759 | * ieee80211s_lookup_nexthop - put the appropriate next hop on a mesh frame |
| 760 | * | 760 | * |
| 761 | * @next_hop: output argument for next hop address | 761 | * @skb: 802.11 frame to be sent |
| 762 | * @skb: frame to be sent | ||
| 763 | * @dev: network device the frame will be sent through | 762 | * @dev: network device the frame will be sent through |
| 763 | * @fwd_frame: true if this frame was originally from a different host | ||
| 764 | * | 764 | * |
| 765 | * Returns: 0 if the next hop was found. Nonzero otherwise. If no next hop is | 765 | * Returns: 0 if the next hop was found. Nonzero otherwise. If no next hop is |
| 766 | * found, the function will start a path discovery and queue the frame so it is | 766 | * found, the function will start a path discovery and queue the frame so it is |
| 767 | * sent when the path is resolved. This means the caller must not free the skb | 767 | * sent when the path is resolved. This means the caller must not free the skb |
| 768 | * in this case. | 768 | * in this case. |
| 769 | */ | 769 | */ |
| 770 | int mesh_nexthop_lookup(u8 *next_hop, struct sk_buff *skb, | 770 | int mesh_nexthop_lookup(struct sk_buff *skb, struct net_device *dev) |
| 771 | struct net_device *dev) | ||
| 772 | { | 771 | { |
| 773 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 772 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
| 774 | struct sk_buff *skb_to_free = NULL; | 773 | struct sk_buff *skb_to_free = NULL; |
| 775 | struct mesh_path *mpath; | 774 | struct mesh_path *mpath; |
| 775 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; | ||
| 776 | u8 *dst_addr = hdr->addr3; | ||
| 776 | int err = 0; | 777 | int err = 0; |
| 777 | 778 | ||
| 778 | rcu_read_lock(); | 779 | rcu_read_lock(); |
| 779 | mpath = mesh_path_lookup(skb->data, dev); | 780 | mpath = mesh_path_lookup(dst_addr, dev); |
| 780 | 781 | ||
| 781 | if (!mpath) { | 782 | if (!mpath) { |
| 782 | mesh_path_add(skb->data, dev); | 783 | mesh_path_add(dst_addr, dev); |
| 783 | mpath = mesh_path_lookup(skb->data, dev); | 784 | mpath = mesh_path_lookup(dst_addr, dev); |
| 784 | if (!mpath) { | 785 | if (!mpath) { |
| 785 | dev_kfree_skb(skb); | 786 | dev_kfree_skb(skb); |
| 786 | sdata->u.sta.mshstats.dropped_frames_no_route++; | 787 | sdata->u.sta.mshstats.dropped_frames_no_route++; |
| @@ -792,13 +793,13 @@ int mesh_nexthop_lookup(u8 *next_hop, struct sk_buff *skb, | |||
| 792 | if (mpath->flags & MESH_PATH_ACTIVE) { | 793 | if (mpath->flags & MESH_PATH_ACTIVE) { |
| 793 | if (time_after(jiffies, mpath->exp_time - | 794 | if (time_after(jiffies, mpath->exp_time - |
| 794 | msecs_to_jiffies(sdata->u.sta.mshcfg.path_refresh_time)) | 795 | msecs_to_jiffies(sdata->u.sta.mshcfg.path_refresh_time)) |
| 795 | && skb->pkt_type != PACKET_OTHERHOST | 796 | && !memcmp(dev->dev_addr, hdr->addr4, ETH_ALEN) |
| 796 | && !(mpath->flags & MESH_PATH_RESOLVING) | 797 | && !(mpath->flags & MESH_PATH_RESOLVING) |
| 797 | && !(mpath->flags & MESH_PATH_FIXED)) { | 798 | && !(mpath->flags & MESH_PATH_FIXED)) { |
| 798 | mesh_queue_preq(mpath, | 799 | mesh_queue_preq(mpath, |
| 799 | PREQ_Q_F_START | PREQ_Q_F_REFRESH); | 800 | PREQ_Q_F_START | PREQ_Q_F_REFRESH); |
| 800 | } | 801 | } |
| 801 | memcpy(next_hop, mpath->next_hop->addr, | 802 | memcpy(hdr->addr1, mpath->next_hop->addr, |
| 802 | ETH_ALEN); | 803 | ETH_ALEN); |
| 803 | } else { | 804 | } else { |
| 804 | if (!(mpath->flags & MESH_PATH_RESOLVING)) { | 805 | if (!(mpath->flags & MESH_PATH_RESOLVING)) { |
diff --git a/net/mac80211/mesh_pathtbl.c b/net/mac80211/mesh_pathtbl.c index 5f88a2e6ee50..838ee60492ad 100644 --- a/net/mac80211/mesh_pathtbl.c +++ b/net/mac80211/mesh_pathtbl.c | |||
| @@ -388,18 +388,15 @@ void mesh_path_tx_pending(struct mesh_path *mpath) | |||
| 388 | void mesh_path_discard_frame(struct sk_buff *skb, struct net_device *dev) | 388 | void mesh_path_discard_frame(struct sk_buff *skb, struct net_device *dev) |
| 389 | { | 389 | { |
| 390 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 390 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
| 391 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; | ||
| 391 | struct mesh_path *mpath; | 392 | struct mesh_path *mpath; |
| 392 | u32 dsn = 0; | 393 | u32 dsn = 0; |
| 393 | 394 | ||
| 394 | if (skb->pkt_type == PACKET_OTHERHOST) { | 395 | if (memcmp(hdr->addr4, dev->dev_addr, ETH_ALEN) != 0) { |
| 395 | struct ieee80211s_hdr *prev_meshhdr; | ||
| 396 | int mshhdrlen; | ||
| 397 | u8 *ra, *da; | 396 | u8 *ra, *da; |
| 398 | 397 | ||
| 399 | prev_meshhdr = ((struct ieee80211s_hdr *)skb->cb); | 398 | da = hdr->addr3; |
| 400 | mshhdrlen = ieee80211_get_mesh_hdrlen(prev_meshhdr); | 399 | ra = hdr->addr2; |
| 401 | da = skb->data; | ||
| 402 | ra = MESH_PREQ(skb); | ||
| 403 | mpath = mesh_path_lookup(da, dev); | 400 | mpath = mesh_path_lookup(da, dev); |
| 404 | if (mpath) | 401 | if (mpath) |
| 405 | dsn = ++mpath->dsn; | 402 | dsn = ++mpath->dsn; |
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) |
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index 771ec68b848d..4788f7b91f49 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c | |||
| @@ -1301,6 +1301,7 @@ int ieee80211_master_start_xmit(struct sk_buff *skb, | |||
| 1301 | struct net_device *dev) | 1301 | struct net_device *dev) |
| 1302 | { | 1302 | { |
| 1303 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | 1303 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); |
| 1304 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; | ||
| 1304 | struct net_device *odev = NULL; | 1305 | struct net_device *odev = NULL; |
| 1305 | struct ieee80211_sub_if_data *osdata; | 1306 | struct ieee80211_sub_if_data *osdata; |
| 1306 | int headroom; | 1307 | int headroom; |
| @@ -1328,6 +1329,20 @@ int ieee80211_master_start_xmit(struct sk_buff *skb, | |||
| 1328 | 1329 | ||
| 1329 | osdata = IEEE80211_DEV_TO_SUB_IF(odev); | 1330 | osdata = IEEE80211_DEV_TO_SUB_IF(odev); |
| 1330 | 1331 | ||
| 1332 | if (ieee80211_vif_is_mesh(&osdata->vif) && | ||
| 1333 | ieee80211_is_data(hdr->frame_control)) { | ||
| 1334 | if (ieee80211_is_data(hdr->frame_control)) { | ||
| 1335 | if (is_multicast_ether_addr(hdr->addr3)) | ||
| 1336 | memcpy(hdr->addr1, hdr->addr3, ETH_ALEN); | ||
| 1337 | else | ||
| 1338 | if (mesh_nexthop_lookup(skb, odev)) | ||
| 1339 | return 0; | ||
| 1340 | if (memcmp(odev->dev_addr, hdr->addr4, ETH_ALEN) != 0) | ||
| 1341 | IEEE80211_IFSTA_MESH_CTR_INC(&osdata->u.sta, | ||
| 1342 | fwded_frames); | ||
| 1343 | } | ||
| 1344 | } | ||
| 1345 | |||
| 1331 | may_encrypt = !skb->do_not_encrypt; | 1346 | may_encrypt = !skb->do_not_encrypt; |
| 1332 | 1347 | ||
| 1333 | headroom = osdata->local->tx_headroom; | 1348 | headroom = osdata->local->tx_headroom; |
| @@ -1472,30 +1487,17 @@ int ieee80211_subif_start_xmit(struct sk_buff *skb, | |||
| 1472 | case IEEE80211_IF_TYPE_MESH_POINT: | 1487 | case IEEE80211_IF_TYPE_MESH_POINT: |
| 1473 | fc |= cpu_to_le16(IEEE80211_FCTL_FROMDS | IEEE80211_FCTL_TODS); | 1488 | fc |= cpu_to_le16(IEEE80211_FCTL_FROMDS | IEEE80211_FCTL_TODS); |
| 1474 | /* RA TA DA SA */ | 1489 | /* RA TA DA SA */ |
| 1475 | if (is_multicast_ether_addr(skb->data)) | 1490 | memset(hdr.addr1, 0, ETH_ALEN); |
| 1476 | memcpy(hdr.addr1, skb->data, ETH_ALEN); | ||
| 1477 | else if (mesh_nexthop_lookup(hdr.addr1, skb, dev)) | ||
| 1478 | return 0; | ||
| 1479 | memcpy(hdr.addr2, dev->dev_addr, ETH_ALEN); | 1491 | memcpy(hdr.addr2, dev->dev_addr, ETH_ALEN); |
| 1480 | memcpy(hdr.addr3, skb->data, ETH_ALEN); | 1492 | memcpy(hdr.addr3, skb->data, ETH_ALEN); |
| 1481 | memcpy(hdr.addr4, skb->data + ETH_ALEN, ETH_ALEN); | 1493 | memcpy(hdr.addr4, skb->data + ETH_ALEN, ETH_ALEN); |
| 1482 | if (skb->pkt_type == PACKET_OTHERHOST) { | 1494 | if (!sdata->u.sta.mshcfg.dot11MeshTTL) { |
| 1483 | /* Forwarded frame, keep mesh ttl and seqnum */ | 1495 | /* Do not send frames with mesh_ttl == 0 */ |
| 1484 | struct ieee80211s_hdr *prev_meshhdr; | 1496 | sdata->u.sta.mshstats.dropped_frames_ttl++; |
| 1485 | prev_meshhdr = ((struct ieee80211s_hdr *)skb->cb); | 1497 | ret = 0; |
| 1486 | meshhdrlen = ieee80211_get_mesh_hdrlen(prev_meshhdr); | 1498 | goto fail; |
| 1487 | memcpy(&mesh_hdr, prev_meshhdr, meshhdrlen); | ||
| 1488 | sdata->u.sta.mshstats.fwded_frames++; | ||
| 1489 | } else { | ||
| 1490 | if (!sdata->u.sta.mshcfg.dot11MeshTTL) { | ||
| 1491 | /* Do not send frames with mesh_ttl == 0 */ | ||
| 1492 | sdata->u.sta.mshstats.dropped_frames_ttl++; | ||
| 1493 | ret = 0; | ||
| 1494 | goto fail; | ||
| 1495 | } | ||
| 1496 | meshhdrlen = ieee80211_new_mesh_header(&mesh_hdr, | ||
| 1497 | sdata); | ||
| 1498 | } | 1499 | } |
| 1500 | meshhdrlen = ieee80211_new_mesh_header(&mesh_hdr, sdata); | ||
| 1499 | hdrlen = 30; | 1501 | hdrlen = 30; |
| 1500 | break; | 1502 | break; |
| 1501 | #endif | 1503 | #endif |
| @@ -1543,7 +1545,8 @@ int ieee80211_subif_start_xmit(struct sk_buff *skb, | |||
| 1543 | * Drop unicast frames to unauthorised stations unless they are | 1545 | * Drop unicast frames to unauthorised stations unless they are |
| 1544 | * EAPOL frames from the local station. | 1546 | * EAPOL frames from the local station. |
| 1545 | */ | 1547 | */ |
| 1546 | if (unlikely(!is_multicast_ether_addr(hdr.addr1) && | 1548 | if (!ieee80211_vif_is_mesh(&sdata->vif) && |
| 1549 | unlikely(!is_multicast_ether_addr(hdr.addr1) && | ||
| 1547 | !(sta_flags & WLAN_STA_AUTHORIZED) && | 1550 | !(sta_flags & WLAN_STA_AUTHORIZED) && |
| 1548 | !(ethertype == ETH_P_PAE && | 1551 | !(ethertype == ETH_P_PAE && |
| 1549 | compare_ether_addr(dev->dev_addr, | 1552 | compare_ether_addr(dev->dev_addr, |
