aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac80211/tx.c
diff options
context:
space:
mode:
authorJohannes Berg <johannes.berg@intel.com>2011-10-07 08:01:23 -0400
committerJohn W. Linville <linville@tuxdriver.com>2011-10-11 16:41:17 -0400
commit5d9cf4a5d7d46e412bc43b20c79743d81a0328cb (patch)
tree5481f798c9407c16ee7958b24559f23d8808a888 /net/mac80211/tx.c
parentd9cd48f95c5ba9e5f1d5287ed74630607471031c (diff)
mac80211: optimise monitor xmit
Since the only way the interface can be a monitor interface in ieee80211_xmit() is because the frame came from ieee80211_monitor_start_xmit() we can move all the code there. Signed-off-by: Johannes Berg <johannes.berg@intel.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'net/mac80211/tx.c')
-rw-r--r--net/mac80211/tx.c108
1 files changed, 49 insertions, 59 deletions
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c
index ad2ee4a90ec4..84ebc3f89123 100644
--- a/net/mac80211/tx.c
+++ b/net/mac80211/tx.c
@@ -1539,55 +1539,11 @@ void ieee80211_xmit(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb)
1539 struct ieee80211_local *local = sdata->local; 1539 struct ieee80211_local *local = sdata->local;
1540 struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); 1540 struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
1541 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; 1541 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
1542 struct ieee80211_sub_if_data *tmp_sdata;
1543 int headroom; 1542 int headroom;
1544 bool may_encrypt; 1543 bool may_encrypt;
1545 1544
1546 rcu_read_lock(); 1545 rcu_read_lock();
1547 1546
1548 if (unlikely(sdata->vif.type == NL80211_IFTYPE_MONITOR)) {
1549 int hdrlen;
1550 u16 len_rthdr;
1551
1552 info->flags |= IEEE80211_TX_CTL_INJECTED |
1553 IEEE80211_TX_INTFL_HAS_RADIOTAP;
1554
1555 len_rthdr = ieee80211_get_radiotap_len(skb->data);
1556 hdr = (struct ieee80211_hdr *)(skb->data + len_rthdr);
1557 hdrlen = ieee80211_hdrlen(hdr->frame_control);
1558
1559 /* check the header is complete in the frame */
1560 if (likely(skb->len >= len_rthdr + hdrlen)) {
1561 /*
1562 * We process outgoing injected frames that have a
1563 * local address we handle as though they are our
1564 * own frames.
1565 * This code here isn't entirely correct, the local
1566 * MAC address is not necessarily enough to find
1567 * the interface to use; for that proper VLAN/WDS
1568 * support we will need a different mechanism.
1569 */
1570
1571 list_for_each_entry_rcu(tmp_sdata, &local->interfaces,
1572 list) {
1573 if (!ieee80211_sdata_running(tmp_sdata))
1574 continue;
1575 if (tmp_sdata->vif.type ==
1576 NL80211_IFTYPE_MONITOR ||
1577 tmp_sdata->vif.type ==
1578 NL80211_IFTYPE_AP_VLAN ||
1579 tmp_sdata->vif.type ==
1580 NL80211_IFTYPE_WDS)
1581 continue;
1582 if (compare_ether_addr(tmp_sdata->vif.addr,
1583 hdr->addr2) == 0) {
1584 sdata = tmp_sdata;
1585 break;
1586 }
1587 }
1588 }
1589 }
1590
1591 may_encrypt = !(info->flags & IEEE80211_TX_INTFL_DONT_ENCRYPT); 1547 may_encrypt = !(info->flags & IEEE80211_TX_INTFL_DONT_ENCRYPT);
1592 1548
1593 headroom = local->tx_headroom; 1549 headroom = local->tx_headroom;
@@ -1628,8 +1584,9 @@ netdev_tx_t ieee80211_monitor_start_xmit(struct sk_buff *skb,
1628 (struct ieee80211_radiotap_header *)skb->data; 1584 (struct ieee80211_radiotap_header *)skb->data;
1629 struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); 1585 struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
1630 struct ieee80211_hdr *hdr; 1586 struct ieee80211_hdr *hdr;
1587 struct ieee80211_sub_if_data *tmp_sdata, *sdata;
1631 u16 len_rthdr; 1588 u16 len_rthdr;
1632 u8 *payload; 1589 int hdrlen;
1633 1590
1634 /* 1591 /*
1635 * Frame injection is not allowed if beaconing is not allowed 1592 * Frame injection is not allowed if beaconing is not allowed
@@ -1680,30 +1637,63 @@ netdev_tx_t ieee80211_monitor_start_xmit(struct sk_buff *skb,
1680 skb_set_network_header(skb, len_rthdr); 1637 skb_set_network_header(skb, len_rthdr);
1681 skb_set_transport_header(skb, len_rthdr); 1638 skb_set_transport_header(skb, len_rthdr);
1682 1639
1640 if (skb->len < len_rthdr + 2)
1641 goto fail;
1642
1643 hdr = (struct ieee80211_hdr *)(skb->data + len_rthdr);
1644 hdrlen = ieee80211_hdrlen(hdr->frame_control);
1645
1646 if (skb->len < len_rthdr + hdrlen)
1647 goto fail;
1648
1683 /* 1649 /*
1684 * Initialize skb->protocol if the injected frame is a data frame 1650 * Initialize skb->protocol if the injected frame is a data frame
1685 * carrying a rfc1042 header 1651 * carrying a rfc1042 header
1686 */ 1652 */
1687 if (skb->len > len_rthdr + 2) { 1653 if (ieee80211_is_data(hdr->frame_control) &&
1688 hdr = (struct ieee80211_hdr *)(skb->data + len_rthdr); 1654 skb->len >= len_rthdr + hdrlen + sizeof(rfc1042_header) + 2) {
1689 if (ieee80211_is_data(hdr->frame_control) && 1655 u8 *payload = (u8 *)hdr + hdrlen;
1690 skb->len >= len_rthdr + 1656
1691 ieee80211_hdrlen(hdr->frame_control) + 1657 if (compare_ether_addr(payload, rfc1042_header) == 0)
1692 sizeof(rfc1042_header) + 2) { 1658 skb->protocol = cpu_to_be16((payload[6] << 8) |
1693 payload = (u8 *)hdr + 1659 payload[7]);
1694 ieee80211_hdrlen(hdr->frame_control);
1695 if (compare_ether_addr(payload, rfc1042_header) == 0)
1696 skb->protocol = cpu_to_be16((payload[6] << 8) |
1697 payload[7]);
1698 }
1699 } 1660 }
1700 1661
1701 memset(info, 0, sizeof(*info)); 1662 memset(info, 0, sizeof(*info));
1702 1663
1703 info->flags |= IEEE80211_TX_CTL_REQ_TX_STATUS; 1664 info->flags = IEEE80211_TX_CTL_REQ_TX_STATUS |
1665 IEEE80211_TX_CTL_INJECTED |
1666 IEEE80211_TX_INTFL_HAS_RADIOTAP;
1667
1668 rcu_read_lock();
1669
1670 /*
1671 * We process outgoing injected frames that have a local address
1672 * we handle as though they are non-injected frames.
1673 * This code here isn't entirely correct, the local MAC address
1674 * isn't always enough to find the interface to use; for proper
1675 * VLAN/WDS support we will need a different mechanism (which
1676 * likely isn't going to be monitor interfaces).
1677 */
1678 sdata = IEEE80211_DEV_TO_SUB_IF(dev);
1679
1680 list_for_each_entry_rcu(tmp_sdata, &local->interfaces, list) {
1681 if (!ieee80211_sdata_running(tmp_sdata))
1682 continue;
1683 if (tmp_sdata->vif.type == NL80211_IFTYPE_MONITOR ||
1684 tmp_sdata->vif.type == NL80211_IFTYPE_AP_VLAN ||
1685 tmp_sdata->vif.type == NL80211_IFTYPE_WDS)
1686 continue;
1687 if (compare_ether_addr(tmp_sdata->vif.addr, hdr->addr2) == 0) {
1688 sdata = tmp_sdata;
1689 break;
1690 }
1691 }
1704 1692
1705 /* pass the radiotap header up to xmit */ 1693 /* pass the radiotap header up to xmit */
1706 ieee80211_xmit(IEEE80211_DEV_TO_SUB_IF(dev), skb); 1694 ieee80211_xmit(sdata, skb);
1695 rcu_read_unlock();
1696
1707 return NETDEV_TX_OK; 1697 return NETDEV_TX_OK;
1708 1698
1709fail: 1699fail: