aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac80211/tx.c
diff options
context:
space:
mode:
authorJavier Cardona <javier@cozybit.com>2009-08-10 15:15:48 -0400
committerJohn W. Linville <linville@tuxdriver.com>2009-08-14 09:14:00 -0400
commit3c5772a5279de9eadfff7adb5ddea08106495fff (patch)
tree297772521c18283ccfa19aacb090f396fa2b399e /net/mac80211/tx.c
parenta9e3091bf08ddea35f172549a8a21d5bd6ee6129 (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.c64
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: