aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac80211/tx.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/mac80211/tx.c')
-rw-r--r--net/mac80211/tx.c45
1 files changed, 37 insertions, 8 deletions
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c
index bfaa43e096d2..2f3345c5f7cf 100644
--- a/net/mac80211/tx.c
+++ b/net/mac80211/tx.c
@@ -1051,7 +1051,10 @@ ieee80211_tx_prepare(struct ieee80211_sub_if_data *sdata,
1051 1051
1052 hdr = (struct ieee80211_hdr *) skb->data; 1052 hdr = (struct ieee80211_hdr *) skb->data;
1053 1053
1054 tx->sta = sta_info_get(local, hdr->addr1); 1054 if ((sdata->vif.type == NL80211_IFTYPE_AP_VLAN) && sdata->use_4addr)
1055 tx->sta = rcu_dereference(sdata->u.vlan.sta);
1056 if (!tx->sta)
1057 tx->sta = sta_info_get(local, hdr->addr1);
1055 1058
1056 if (tx->sta && ieee80211_is_data_qos(hdr->frame_control) && 1059 if (tx->sta && ieee80211_is_data_qos(hdr->frame_control) &&
1057 (local->hw.flags & IEEE80211_HW_AMPDU_AGGREGATION)) { 1060 (local->hw.flags & IEEE80211_HW_AMPDU_AGGREGATION)) {
@@ -1613,7 +1616,7 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb,
1613 const u8 *encaps_data; 1616 const u8 *encaps_data;
1614 int encaps_len, skip_header_bytes; 1617 int encaps_len, skip_header_bytes;
1615 int nh_pos, h_pos; 1618 int nh_pos, h_pos;
1616 struct sta_info *sta; 1619 struct sta_info *sta = NULL;
1617 u32 sta_flags = 0; 1620 u32 sta_flags = 0;
1618 1621
1619 if (unlikely(skb->len < ETH_HLEN)) { 1622 if (unlikely(skb->len < ETH_HLEN)) {
@@ -1630,8 +1633,25 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb,
1630 fc = cpu_to_le16(IEEE80211_FTYPE_DATA | IEEE80211_STYPE_DATA); 1633 fc = cpu_to_le16(IEEE80211_FTYPE_DATA | IEEE80211_STYPE_DATA);
1631 1634
1632 switch (sdata->vif.type) { 1635 switch (sdata->vif.type) {
1633 case NL80211_IFTYPE_AP:
1634 case NL80211_IFTYPE_AP_VLAN: 1636 case NL80211_IFTYPE_AP_VLAN:
1637 rcu_read_lock();
1638 if (sdata->use_4addr)
1639 sta = rcu_dereference(sdata->u.vlan.sta);
1640 if (sta) {
1641 fc |= cpu_to_le16(IEEE80211_FCTL_FROMDS | IEEE80211_FCTL_TODS);
1642 /* RA TA DA SA */
1643 memcpy(hdr.addr1, sta->sta.addr, ETH_ALEN);
1644 memcpy(hdr.addr2, dev->dev_addr, ETH_ALEN);
1645 memcpy(hdr.addr3, skb->data, ETH_ALEN);
1646 memcpy(hdr.addr4, skb->data + ETH_ALEN, ETH_ALEN);
1647 hdrlen = 30;
1648 sta_flags = get_sta_flags(sta);
1649 }
1650 rcu_read_unlock();
1651 if (sta)
1652 break;
1653 /* fall through */
1654 case NL80211_IFTYPE_AP:
1635 fc |= cpu_to_le16(IEEE80211_FCTL_FROMDS); 1655 fc |= cpu_to_le16(IEEE80211_FCTL_FROMDS);
1636 /* DA BSSID SA */ 1656 /* DA BSSID SA */
1637 memcpy(hdr.addr1, skb->data, ETH_ALEN); 1657 memcpy(hdr.addr1, skb->data, ETH_ALEN);
@@ -1705,12 +1725,21 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb,
1705 break; 1725 break;
1706#endif 1726#endif
1707 case NL80211_IFTYPE_STATION: 1727 case NL80211_IFTYPE_STATION:
1708 fc |= cpu_to_le16(IEEE80211_FCTL_TODS);
1709 /* BSSID SA DA */
1710 memcpy(hdr.addr1, sdata->u.mgd.bssid, ETH_ALEN); 1728 memcpy(hdr.addr1, sdata->u.mgd.bssid, ETH_ALEN);
1711 memcpy(hdr.addr2, skb->data + ETH_ALEN, ETH_ALEN); 1729 if (sdata->use_4addr && ethertype != ETH_P_PAE) {
1712 memcpy(hdr.addr3, skb->data, ETH_ALEN); 1730 fc |= cpu_to_le16(IEEE80211_FCTL_FROMDS | IEEE80211_FCTL_TODS);
1713 hdrlen = 24; 1731 /* RA TA DA SA */
1732 memcpy(hdr.addr2, dev->dev_addr, ETH_ALEN);
1733 memcpy(hdr.addr3, skb->data, ETH_ALEN);
1734 memcpy(hdr.addr4, skb->data + ETH_ALEN, ETH_ALEN);
1735 hdrlen = 30;
1736 } else {
1737 fc |= cpu_to_le16(IEEE80211_FCTL_TODS);
1738 /* BSSID SA DA */
1739 memcpy(hdr.addr2, skb->data + ETH_ALEN, ETH_ALEN);
1740 memcpy(hdr.addr3, skb->data, ETH_ALEN);
1741 hdrlen = 24;
1742 }
1714 break; 1743 break;
1715 case NL80211_IFTYPE_ADHOC: 1744 case NL80211_IFTYPE_ADHOC:
1716 /* DA SA BSSID */ 1745 /* DA SA BSSID */