diff options
author | Javier Cardona <javier@cozybit.com> | 2009-08-10 15:15:48 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2009-08-14 09:14:00 -0400 |
commit | 3c5772a5279de9eadfff7adb5ddea08106495fff (patch) | |
tree | 297772521c18283ccfa19aacb090f396fa2b399e /net/mac80211/rx.c | |
parent | a9e3091bf08ddea35f172549a8a21d5bd6ee6129 (diff) |
mac80211: Use 3-address format for mesh broadcast frames.
The 11s task group recently changed the frame mesh multicast/broadcast frame
format to use 3-address. This was done to avoid interactions with widely
deployed lazy-WDS access points.
This patch changes the format of group addressed frames, both mesh-originated
and proxied, to use the data format defined in draft D2.08 and forward. The
address fields used for group addressed frames is:
In 802.11 header
ToDS:0 FromDS:1
addr1: DA (broadcast/multicast address)
addr2: TA
addr3: Mesh SA
In address extension header:
addr4: SA (only present if frame was proxied)
Note that this change breaks backward compatibility with earlier mesh stack
versions.
Signed-off-by: Andrey Yurovsky <andrey@cozybit.com>
Signed-off-by: Javier Cardona <javier@cozybit.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'net/mac80211/rx.c')
-rw-r--r-- | net/mac80211/rx.c | 45 |
1 files changed, 28 insertions, 17 deletions
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index 25a669c86e14..4cd9e45b1443 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c | |||
@@ -489,12 +489,21 @@ ieee80211_rx_mesh_check(struct ieee80211_rx_data *rx) | |||
489 | { | 489 | { |
490 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)rx->skb->data; | 490 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)rx->skb->data; |
491 | unsigned int hdrlen = ieee80211_hdrlen(hdr->frame_control); | 491 | unsigned int hdrlen = ieee80211_hdrlen(hdr->frame_control); |
492 | char *dev_addr = rx->dev->dev_addr; | ||
492 | 493 | ||
493 | if (ieee80211_is_data(hdr->frame_control)) { | 494 | if (ieee80211_is_data(hdr->frame_control)) { |
494 | if (!ieee80211_has_a4(hdr->frame_control)) | 495 | if (is_multicast_ether_addr(hdr->addr1)) { |
495 | return RX_DROP_MONITOR; | 496 | if (ieee80211_has_tods(hdr->frame_control) || |
496 | if (memcmp(hdr->addr4, rx->dev->dev_addr, ETH_ALEN) == 0) | 497 | !ieee80211_has_fromds(hdr->frame_control)) |
497 | return RX_DROP_MONITOR; | 498 | return RX_DROP_MONITOR; |
499 | if (memcmp(hdr->addr3, dev_addr, ETH_ALEN) == 0) | ||
500 | return RX_DROP_MONITOR; | ||
501 | } else { | ||
502 | if (!ieee80211_has_a4(hdr->frame_control)) | ||
503 | return RX_DROP_MONITOR; | ||
504 | if (memcmp(hdr->addr4, dev_addr, ETH_ALEN) == 0) | ||
505 | return RX_DROP_MONITOR; | ||
506 | } | ||
498 | } | 507 | } |
499 | 508 | ||
500 | /* If there is not an established peer link and this is not a peer link | 509 | /* If there is not an established peer link and this is not a peer link |
@@ -527,7 +536,7 @@ ieee80211_rx_mesh_check(struct ieee80211_rx_data *rx) | |||
527 | 536 | ||
528 | if (ieee80211_is_data(hdr->frame_control) && | 537 | if (ieee80211_is_data(hdr->frame_control) && |
529 | is_multicast_ether_addr(hdr->addr1) && | 538 | is_multicast_ether_addr(hdr->addr1) && |
530 | mesh_rmc_check(hdr->addr4, msh_h_get(hdr, hdrlen), rx->sdata)) | 539 | mesh_rmc_check(hdr->addr3, msh_h_get(hdr, hdrlen), rx->sdata)) |
531 | return RX_DROP_MONITOR; | 540 | return RX_DROP_MONITOR; |
532 | #undef msh_h_get | 541 | #undef msh_h_get |
533 | 542 | ||
@@ -1495,7 +1504,8 @@ ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx) | |||
1495 | /* illegal frame */ | 1504 | /* illegal frame */ |
1496 | return RX_DROP_MONITOR; | 1505 | return RX_DROP_MONITOR; |
1497 | 1506 | ||
1498 | if (mesh_hdr->flags & MESH_FLAGS_AE_A5_A6){ | 1507 | if (!is_multicast_ether_addr(hdr->addr1) && |
1508 | (mesh_hdr->flags & MESH_FLAGS_AE_A5_A6)) { | ||
1499 | struct mesh_path *mppath; | 1509 | struct mesh_path *mppath; |
1500 | 1510 | ||
1501 | rcu_read_lock(); | 1511 | rcu_read_lock(); |
@@ -1512,7 +1522,9 @@ ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx) | |||
1512 | rcu_read_unlock(); | 1522 | rcu_read_unlock(); |
1513 | } | 1523 | } |
1514 | 1524 | ||
1515 | if (compare_ether_addr(rx->dev->dev_addr, hdr->addr3) == 0) | 1525 | /* Frame has reached destination. Don't forward */ |
1526 | if (!is_multicast_ether_addr(hdr->addr1) && | ||
1527 | compare_ether_addr(rx->dev->dev_addr, hdr->addr3) == 0) | ||
1516 | return RX_CONTINUE; | 1528 | return RX_CONTINUE; |
1517 | 1529 | ||
1518 | mesh_hdr->ttl--; | 1530 | mesh_hdr->ttl--; |
@@ -1532,22 +1544,21 @@ ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx) | |||
1532 | rx->dev->name); | 1544 | rx->dev->name); |
1533 | 1545 | ||
1534 | fwd_hdr = (struct ieee80211_hdr *) fwd_skb->data; | 1546 | fwd_hdr = (struct ieee80211_hdr *) fwd_skb->data; |
1535 | /* | ||
1536 | * Save TA to addr1 to send TA a path error if a | ||
1537 | * suitable next hop is not found | ||
1538 | */ | ||
1539 | memcpy(fwd_hdr->addr1, fwd_hdr->addr2, ETH_ALEN); | ||
1540 | memcpy(fwd_hdr->addr2, rx->dev->dev_addr, ETH_ALEN); | 1547 | memcpy(fwd_hdr->addr2, rx->dev->dev_addr, ETH_ALEN); |
1541 | info = IEEE80211_SKB_CB(fwd_skb); | 1548 | info = IEEE80211_SKB_CB(fwd_skb); |
1542 | memset(info, 0, sizeof(*info)); | 1549 | memset(info, 0, sizeof(*info)); |
1543 | info->flags |= IEEE80211_TX_INTFL_NEED_TXPROCESSING; | 1550 | info->flags |= IEEE80211_TX_INTFL_NEED_TXPROCESSING; |
1544 | info->control.vif = &rx->sdata->vif; | 1551 | info->control.vif = &rx->sdata->vif; |
1545 | ieee80211_select_queue(local, fwd_skb); | 1552 | ieee80211_select_queue(local, fwd_skb); |
1546 | if (is_multicast_ether_addr(fwd_hdr->addr3)) | 1553 | if (!is_multicast_ether_addr(fwd_hdr->addr1)) { |
1547 | memcpy(fwd_hdr->addr1, fwd_hdr->addr3, | 1554 | int err; |
1555 | /* | ||
1556 | * Save TA to addr1 to send TA a path error if a | ||
1557 | * suitable next hop is not found | ||
1558 | */ | ||
1559 | memcpy(fwd_hdr->addr1, fwd_hdr->addr2, | ||
1548 | ETH_ALEN); | 1560 | ETH_ALEN); |
1549 | else { | 1561 | err = mesh_nexthop_lookup(fwd_skb, sdata); |
1550 | int err = mesh_nexthop_lookup(fwd_skb, sdata); | ||
1551 | /* Failed to immediately resolve next hop: | 1562 | /* Failed to immediately resolve next hop: |
1552 | * fwded frame was dropped or will be added | 1563 | * fwded frame was dropped or will be added |
1553 | * later to the pending skb queue. */ | 1564 | * later to the pending skb queue. */ |
@@ -1560,7 +1571,7 @@ ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx) | |||
1560 | } | 1571 | } |
1561 | } | 1572 | } |
1562 | 1573 | ||
1563 | if (is_multicast_ether_addr(hdr->addr3) || | 1574 | if (is_multicast_ether_addr(hdr->addr1) || |
1564 | rx->dev->flags & IFF_PROMISC) | 1575 | rx->dev->flags & IFF_PROMISC) |
1565 | return RX_CONTINUE; | 1576 | return RX_CONTINUE; |
1566 | else | 1577 | else |