diff options
Diffstat (limited to 'net/mac80211/tx.c')
-rw-r--r-- | net/mac80211/tx.c | 44 |
1 files changed, 38 insertions, 6 deletions
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index 00d798cc9e04..00d96e63dce9 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c | |||
@@ -1498,18 +1498,50 @@ int ieee80211_subif_start_xmit(struct sk_buff *skb, | |||
1498 | #ifdef CONFIG_MAC80211_MESH | 1498 | #ifdef CONFIG_MAC80211_MESH |
1499 | case NL80211_IFTYPE_MESH_POINT: | 1499 | case NL80211_IFTYPE_MESH_POINT: |
1500 | fc |= cpu_to_le16(IEEE80211_FCTL_FROMDS | IEEE80211_FCTL_TODS); | 1500 | fc |= cpu_to_le16(IEEE80211_FCTL_FROMDS | IEEE80211_FCTL_TODS); |
1501 | /* RA TA DA SA */ | ||
1502 | memset(hdr.addr1, 0, ETH_ALEN); | ||
1503 | memcpy(hdr.addr2, dev->dev_addr, ETH_ALEN); | ||
1504 | memcpy(hdr.addr3, skb->data, ETH_ALEN); | ||
1505 | memcpy(hdr.addr4, skb->data + ETH_ALEN, ETH_ALEN); | ||
1506 | if (!sdata->u.mesh.mshcfg.dot11MeshTTL) { | 1501 | if (!sdata->u.mesh.mshcfg.dot11MeshTTL) { |
1507 | /* Do not send frames with mesh_ttl == 0 */ | 1502 | /* Do not send frames with mesh_ttl == 0 */ |
1508 | sdata->u.mesh.mshstats.dropped_frames_ttl++; | 1503 | sdata->u.mesh.mshstats.dropped_frames_ttl++; |
1509 | ret = 0; | 1504 | ret = 0; |
1510 | goto fail; | 1505 | goto fail; |
1511 | } | 1506 | } |
1512 | meshhdrlen = ieee80211_new_mesh_header(&mesh_hdr, sdata); | 1507 | memset(&mesh_hdr, 0, sizeof(mesh_hdr)); |
1508 | |||
1509 | if (compare_ether_addr(dev->dev_addr, | ||
1510 | skb->data + ETH_ALEN) == 0) { | ||
1511 | /* RA TA DA SA */ | ||
1512 | memset(hdr.addr1, 0, ETH_ALEN); | ||
1513 | memcpy(hdr.addr2, dev->dev_addr, ETH_ALEN); | ||
1514 | memcpy(hdr.addr3, skb->data, ETH_ALEN); | ||
1515 | memcpy(hdr.addr4, skb->data + ETH_ALEN, ETH_ALEN); | ||
1516 | meshhdrlen = ieee80211_new_mesh_header(&mesh_hdr, sdata); | ||
1517 | } else { | ||
1518 | /* packet from other interface */ | ||
1519 | struct mesh_path *mppath; | ||
1520 | |||
1521 | memset(hdr.addr1, 0, ETH_ALEN); | ||
1522 | memcpy(hdr.addr2, dev->dev_addr, ETH_ALEN); | ||
1523 | memcpy(hdr.addr4, dev->dev_addr, ETH_ALEN); | ||
1524 | |||
1525 | if (is_multicast_ether_addr(skb->data)) | ||
1526 | memcpy(hdr.addr3, skb->data, ETH_ALEN); | ||
1527 | else { | ||
1528 | rcu_read_lock(); | ||
1529 | mppath = mpp_path_lookup(skb->data, sdata); | ||
1530 | if (mppath) | ||
1531 | memcpy(hdr.addr3, mppath->mpp, ETH_ALEN); | ||
1532 | else | ||
1533 | memset(hdr.addr3, 0xff, ETH_ALEN); | ||
1534 | rcu_read_unlock(); | ||
1535 | } | ||
1536 | |||
1537 | mesh_hdr.flags |= MESH_FLAGS_AE_A5_A6; | ||
1538 | mesh_hdr.ttl = sdata->u.mesh.mshcfg.dot11MeshTTL; | ||
1539 | put_unaligned(cpu_to_le32(sdata->u.mesh.mesh_seqnum), &mesh_hdr.seqnum); | ||
1540 | memcpy(mesh_hdr.eaddr1, skb->data, ETH_ALEN); | ||
1541 | memcpy(mesh_hdr.eaddr2, skb->data + ETH_ALEN, ETH_ALEN); | ||
1542 | sdata->u.mesh.mesh_seqnum++; | ||
1543 | meshhdrlen = 18; | ||
1544 | } | ||
1513 | hdrlen = 30; | 1545 | hdrlen = 30; |
1514 | break; | 1546 | break; |
1515 | #endif | 1547 | #endif |