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/tx.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/tx.c')
-rw-r--r-- | net/mac80211/tx.c | 64 |
1 files changed, 34 insertions, 30 deletions
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index 32442980cc24..ee8aa76f071a 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c | |||
@@ -1414,9 +1414,7 @@ static void ieee80211_xmit(struct ieee80211_sub_if_data *sdata, | |||
1414 | 1414 | ||
1415 | if (ieee80211_vif_is_mesh(&sdata->vif) && | 1415 | if (ieee80211_vif_is_mesh(&sdata->vif) && |
1416 | ieee80211_is_data(hdr->frame_control)) { | 1416 | ieee80211_is_data(hdr->frame_control)) { |
1417 | if (is_multicast_ether_addr(hdr->addr3)) | 1417 | if (!is_multicast_ether_addr(hdr->addr1)) |
1418 | memcpy(hdr->addr1, hdr->addr3, ETH_ALEN); | ||
1419 | else | ||
1420 | if (mesh_nexthop_lookup(skb, sdata)) { | 1418 | if (mesh_nexthop_lookup(skb, sdata)) { |
1421 | dev_put(sdata->dev); | 1419 | dev_put(sdata->dev); |
1422 | return; | 1420 | return; |
@@ -1619,52 +1617,58 @@ int ieee80211_subif_start_xmit(struct sk_buff *skb, | |||
1619 | break; | 1617 | break; |
1620 | #ifdef CONFIG_MAC80211_MESH | 1618 | #ifdef CONFIG_MAC80211_MESH |
1621 | case NL80211_IFTYPE_MESH_POINT: | 1619 | case NL80211_IFTYPE_MESH_POINT: |
1622 | fc |= cpu_to_le16(IEEE80211_FCTL_FROMDS | IEEE80211_FCTL_TODS); | ||
1623 | if (!sdata->u.mesh.mshcfg.dot11MeshTTL) { | 1620 | if (!sdata->u.mesh.mshcfg.dot11MeshTTL) { |
1624 | /* Do not send frames with mesh_ttl == 0 */ | 1621 | /* Do not send frames with mesh_ttl == 0 */ |
1625 | sdata->u.mesh.mshstats.dropped_frames_ttl++; | 1622 | sdata->u.mesh.mshstats.dropped_frames_ttl++; |
1626 | ret = NETDEV_TX_OK; | 1623 | ret = NETDEV_TX_OK; |
1627 | goto fail; | 1624 | goto fail; |
1628 | } | 1625 | } |
1629 | memset(&mesh_hdr, 0, sizeof(mesh_hdr)); | ||
1630 | 1626 | ||
1631 | if (compare_ether_addr(dev->dev_addr, | 1627 | if (compare_ether_addr(dev->dev_addr, |
1632 | skb->data + ETH_ALEN) == 0) { | 1628 | skb->data + ETH_ALEN) == 0) { |
1633 | /* RA TA DA SA */ | 1629 | hdrlen = ieee80211_fill_mesh_addresses(&hdr, &fc, |
1634 | memset(hdr.addr1, 0, ETH_ALEN); | 1630 | skb->data, skb->data + ETH_ALEN); |
1635 | memcpy(hdr.addr2, dev->dev_addr, ETH_ALEN); | 1631 | meshhdrlen = ieee80211_new_mesh_header(&mesh_hdr, |
1636 | memcpy(hdr.addr3, skb->data, ETH_ALEN); | 1632 | sdata, NULL, NULL, NULL); |
1637 | memcpy(hdr.addr4, skb->data + ETH_ALEN, ETH_ALEN); | ||
1638 | meshhdrlen = ieee80211_new_mesh_header(&mesh_hdr, sdata); | ||
1639 | } else { | 1633 | } else { |
1640 | /* packet from other interface */ | 1634 | /* packet from other interface */ |
1641 | struct mesh_path *mppath; | 1635 | struct mesh_path *mppath; |
1636 | int is_mesh_mcast = 1; | ||
1637 | char *mesh_da; | ||
1642 | 1638 | ||
1643 | memset(hdr.addr1, 0, ETH_ALEN); | 1639 | rcu_read_lock(); |
1644 | memcpy(hdr.addr2, dev->dev_addr, ETH_ALEN); | ||
1645 | memcpy(hdr.addr4, dev->dev_addr, ETH_ALEN); | ||
1646 | |||
1647 | if (is_multicast_ether_addr(skb->data)) | 1640 | if (is_multicast_ether_addr(skb->data)) |
1648 | memcpy(hdr.addr3, skb->data, ETH_ALEN); | 1641 | /* DA TA mSA AE:SA */ |
1642 | mesh_da = skb->data; | ||
1649 | else { | 1643 | else { |
1650 | rcu_read_lock(); | ||
1651 | mppath = mpp_path_lookup(skb->data, sdata); | 1644 | mppath = mpp_path_lookup(skb->data, sdata); |
1652 | if (mppath) | 1645 | if (mppath) { |
1653 | memcpy(hdr.addr3, mppath->mpp, ETH_ALEN); | 1646 | /* RA TA mDA mSA AE:DA SA */ |
1654 | else | 1647 | mesh_da = mppath->mpp; |
1655 | memset(hdr.addr3, 0xff, ETH_ALEN); | 1648 | is_mesh_mcast = 0; |
1656 | rcu_read_unlock(); | 1649 | } else |
1650 | /* DA TA mSA AE:SA */ | ||
1651 | mesh_da = dev->broadcast; | ||
1657 | } | 1652 | } |
1653 | hdrlen = ieee80211_fill_mesh_addresses(&hdr, &fc, | ||
1654 | mesh_da, dev->dev_addr); | ||
1655 | rcu_read_unlock(); | ||
1656 | if (is_mesh_mcast) | ||
1657 | meshhdrlen = | ||
1658 | ieee80211_new_mesh_header(&mesh_hdr, | ||
1659 | sdata, | ||
1660 | skb->data + ETH_ALEN, | ||
1661 | NULL, | ||
1662 | NULL); | ||
1663 | else | ||
1664 | meshhdrlen = | ||
1665 | ieee80211_new_mesh_header(&mesh_hdr, | ||
1666 | sdata, | ||
1667 | NULL, | ||
1668 | skb->data, | ||
1669 | skb->data + ETH_ALEN); | ||
1658 | 1670 | ||
1659 | mesh_hdr.flags |= MESH_FLAGS_AE_A5_A6; | ||
1660 | mesh_hdr.ttl = sdata->u.mesh.mshcfg.dot11MeshTTL; | ||
1661 | put_unaligned(cpu_to_le32(sdata->u.mesh.mesh_seqnum), &mesh_hdr.seqnum); | ||
1662 | memcpy(mesh_hdr.eaddr1, skb->data, ETH_ALEN); | ||
1663 | memcpy(mesh_hdr.eaddr2, skb->data + ETH_ALEN, ETH_ALEN); | ||
1664 | sdata->u.mesh.mesh_seqnum++; | ||
1665 | meshhdrlen = 18; | ||
1666 | } | 1671 | } |
1667 | hdrlen = 30; | ||
1668 | break; | 1672 | break; |
1669 | #endif | 1673 | #endif |
1670 | case NL80211_IFTYPE_STATION: | 1674 | case NL80211_IFTYPE_STATION: |