diff options
author | Johannes Berg <johannes@sipsolutions.net> | 2007-07-10 13:32:08 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2007-07-12 16:07:25 -0400 |
commit | 40f7cac9f8dd662c1dd02334afdceef0be03e34f (patch) | |
tree | 6c8cedbfa99b67305d1b845d7a140a0a185981a6 /net | |
parent | 333af2f0715c8d4d38cb657d8f4fb7c4e3ceba9f (diff) |
[PATCH] mac80211: separate monitor/subif_start_xmit
This patch separates the monitor interface start_xmit from the
subif start xmit (those other devices have 802.3 framing, monitor
interfaces have radiotap framing)
Signed-off-by: Johannes Berg <johannes@sipsolutions.net>
Signed-off-by: Jiri Benc <jbenc@suse.cz>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'net')
-rw-r--r-- | net/mac80211/ieee80211.c | 101 | ||||
-rw-r--r-- | net/mac80211/ieee80211_i.h | 2 | ||||
-rw-r--r-- | net/mac80211/ieee80211_iface.c | 3 |
3 files changed, 58 insertions, 48 deletions
diff --git a/net/mac80211/ieee80211.c b/net/mac80211/ieee80211.c index 4bcf18097e53..e91698308f31 100644 --- a/net/mac80211/ieee80211.c +++ b/net/mac80211/ieee80211.c | |||
@@ -1673,6 +1673,56 @@ static int ieee80211_master_start_xmit(struct sk_buff *skb, | |||
1673 | } | 1673 | } |
1674 | 1674 | ||
1675 | 1675 | ||
1676 | int ieee80211_monitor_start_xmit(struct sk_buff *skb, | ||
1677 | struct net_device *dev) | ||
1678 | { | ||
1679 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | ||
1680 | struct ieee80211_tx_packet_data *pkt_data; | ||
1681 | struct ieee80211_radiotap_header *prthdr = | ||
1682 | (struct ieee80211_radiotap_header *)skb->data; | ||
1683 | u16 len; | ||
1684 | |||
1685 | /* | ||
1686 | * there must be a radiotap header at the | ||
1687 | * start in this case | ||
1688 | */ | ||
1689 | if (unlikely(prthdr->it_version)) { | ||
1690 | /* only version 0 is supported */ | ||
1691 | dev_kfree_skb(skb); | ||
1692 | return NETDEV_TX_OK; | ||
1693 | } | ||
1694 | |||
1695 | skb->dev = local->mdev; | ||
1696 | |||
1697 | pkt_data = (struct ieee80211_tx_packet_data *)skb->cb; | ||
1698 | memset(pkt_data, 0, sizeof(*pkt_data)); | ||
1699 | pkt_data->ifindex = dev->ifindex; | ||
1700 | pkt_data->mgmt_iface = 0; | ||
1701 | pkt_data->do_not_encrypt = 1; | ||
1702 | |||
1703 | /* above needed because we set skb device to master */ | ||
1704 | |||
1705 | /* | ||
1706 | * fix up the pointers accounting for the radiotap | ||
1707 | * header still being in there. We are being given | ||
1708 | * a precooked IEEE80211 header so no need for | ||
1709 | * normal processing | ||
1710 | */ | ||
1711 | len = le16_to_cpu(get_unaligned(&prthdr->it_len)); | ||
1712 | skb_set_mac_header(skb, len); | ||
1713 | skb_set_network_header(skb, len + sizeof(struct ieee80211_hdr)); | ||
1714 | skb_set_transport_header(skb, len + sizeof(struct ieee80211_hdr)); | ||
1715 | |||
1716 | /* | ||
1717 | * pass the radiotap header up to | ||
1718 | * the next stage intact | ||
1719 | */ | ||
1720 | dev_queue_xmit(skb); | ||
1721 | |||
1722 | return NETDEV_TX_OK; | ||
1723 | } | ||
1724 | |||
1725 | |||
1676 | /** | 1726 | /** |
1677 | * ieee80211_subif_start_xmit - netif start_xmit function for Ethernet-type | 1727 | * ieee80211_subif_start_xmit - netif start_xmit function for Ethernet-type |
1678 | * subinterfaces (wlan#, WDS, and VLAN interfaces) | 1728 | * subinterfaces (wlan#, WDS, and VLAN interfaces) |
@@ -1688,8 +1738,8 @@ static int ieee80211_master_start_xmit(struct sk_buff *skb, | |||
1688 | * encapsulated packet will then be passed to master interface, wlan#.11, for | 1738 | * encapsulated packet will then be passed to master interface, wlan#.11, for |
1689 | * transmission (through low-level driver). | 1739 | * transmission (through low-level driver). |
1690 | */ | 1740 | */ |
1691 | static int ieee80211_subif_start_xmit(struct sk_buff *skb, | 1741 | int ieee80211_subif_start_xmit(struct sk_buff *skb, |
1692 | struct net_device *dev) | 1742 | struct net_device *dev) |
1693 | { | 1743 | { |
1694 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | 1744 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); |
1695 | struct ieee80211_tx_packet_data *pkt_data; | 1745 | struct ieee80211_tx_packet_data *pkt_data; |
@@ -1710,51 +1760,6 @@ static int ieee80211_subif_start_xmit(struct sk_buff *skb, | |||
1710 | goto fail; | 1760 | goto fail; |
1711 | } | 1761 | } |
1712 | 1762 | ||
1713 | if (unlikely(sdata->type == IEEE80211_IF_TYPE_MNTR)) { | ||
1714 | struct ieee80211_radiotap_header *prthdr = | ||
1715 | (struct ieee80211_radiotap_header *)skb->data; | ||
1716 | u16 len; | ||
1717 | |||
1718 | /* | ||
1719 | * there must be a radiotap header at the | ||
1720 | * start in this case | ||
1721 | */ | ||
1722 | if (unlikely(prthdr->it_version)) { | ||
1723 | /* only version 0 is supported */ | ||
1724 | ret = 0; | ||
1725 | goto fail; | ||
1726 | } | ||
1727 | |||
1728 | skb->dev = local->mdev; | ||
1729 | |||
1730 | pkt_data = (struct ieee80211_tx_packet_data *)skb->cb; | ||
1731 | memset(pkt_data, 0, sizeof(*pkt_data)); | ||
1732 | pkt_data->ifindex = sdata->dev->ifindex; | ||
1733 | pkt_data->mgmt_iface = 0; | ||
1734 | pkt_data->do_not_encrypt = 1; | ||
1735 | |||
1736 | /* above needed because we set skb device to master */ | ||
1737 | |||
1738 | /* | ||
1739 | * fix up the pointers accounting for the radiotap | ||
1740 | * header still being in there. We are being given | ||
1741 | * a precooked IEEE80211 header so no need for | ||
1742 | * normal processing | ||
1743 | */ | ||
1744 | len = le16_to_cpu(get_unaligned(&prthdr->it_len)); | ||
1745 | skb_set_mac_header(skb, len); | ||
1746 | skb_set_network_header(skb, len + sizeof(hdr)); | ||
1747 | skb_set_transport_header(skb, len + sizeof(hdr)); | ||
1748 | |||
1749 | /* | ||
1750 | * pass the radiotap header up to | ||
1751 | * the next stage intact | ||
1752 | */ | ||
1753 | dev_queue_xmit(skb); | ||
1754 | |||
1755 | return 0; | ||
1756 | } | ||
1757 | |||
1758 | nh_pos = skb_network_header(skb) - skb->data; | 1763 | nh_pos = skb_network_header(skb) - skb->data; |
1759 | h_pos = skb_transport_header(skb) - skb->data; | 1764 | h_pos = skb_transport_header(skb) - skb->data; |
1760 | 1765 | ||
@@ -1882,7 +1887,7 @@ static int ieee80211_subif_start_xmit(struct sk_buff *skb, | |||
1882 | 1887 | ||
1883 | pkt_data = (struct ieee80211_tx_packet_data *)skb->cb; | 1888 | pkt_data = (struct ieee80211_tx_packet_data *)skb->cb; |
1884 | memset(pkt_data, 0, sizeof(struct ieee80211_tx_packet_data)); | 1889 | memset(pkt_data, 0, sizeof(struct ieee80211_tx_packet_data)); |
1885 | pkt_data->ifindex = sdata->dev->ifindex; | 1890 | pkt_data->ifindex = dev->ifindex; |
1886 | pkt_data->mgmt_iface = (sdata->type == IEEE80211_IF_TYPE_MGMT); | 1891 | pkt_data->mgmt_iface = (sdata->type == IEEE80211_IF_TYPE_MGMT); |
1887 | pkt_data->do_not_encrypt = no_encrypt; | 1892 | pkt_data->do_not_encrypt = no_encrypt; |
1888 | 1893 | ||
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index 5a91e179efa0..fadcbccc0da2 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h | |||
@@ -720,6 +720,8 @@ void ieee80211_prepare_rates(struct ieee80211_local *local, | |||
720 | struct ieee80211_hw_mode *mode); | 720 | struct ieee80211_hw_mode *mode); |
721 | void ieee80211_tx_set_iswep(struct ieee80211_txrx_data *tx); | 721 | void ieee80211_tx_set_iswep(struct ieee80211_txrx_data *tx); |
722 | int ieee80211_if_update_wds(struct net_device *dev, u8 *remote_addr); | 722 | int ieee80211_if_update_wds(struct net_device *dev, u8 *remote_addr); |
723 | int ieee80211_monitor_start_xmit(struct sk_buff *skb, struct net_device *dev); | ||
724 | int ieee80211_subif_start_xmit(struct sk_buff *skb, struct net_device *dev); | ||
723 | void ieee80211_if_setup(struct net_device *dev); | 725 | void ieee80211_if_setup(struct net_device *dev); |
724 | void ieee80211_if_mgmt_setup(struct net_device *dev); | 726 | void ieee80211_if_mgmt_setup(struct net_device *dev); |
725 | int ieee80211_init_rate_ctrl_alg(struct ieee80211_local *local, | 727 | int ieee80211_init_rate_ctrl_alg(struct ieee80211_local *local, |
diff --git a/net/mac80211/ieee80211_iface.c b/net/mac80211/ieee80211_iface.c index cf0f32e8c2a2..8532a5ccdd1e 100644 --- a/net/mac80211/ieee80211_iface.c +++ b/net/mac80211/ieee80211_iface.c | |||
@@ -157,6 +157,8 @@ void ieee80211_if_set_type(struct net_device *dev, int type) | |||
157 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | 157 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); |
158 | int oldtype = sdata->type; | 158 | int oldtype = sdata->type; |
159 | 159 | ||
160 | dev->hard_start_xmit = ieee80211_subif_start_xmit; | ||
161 | |||
160 | sdata->type = type; | 162 | sdata->type = type; |
161 | switch (type) { | 163 | switch (type) { |
162 | case IEEE80211_IF_TYPE_WDS: | 164 | case IEEE80211_IF_TYPE_WDS: |
@@ -196,6 +198,7 @@ void ieee80211_if_set_type(struct net_device *dev, int type) | |||
196 | } | 198 | } |
197 | case IEEE80211_IF_TYPE_MNTR: | 199 | case IEEE80211_IF_TYPE_MNTR: |
198 | dev->type = ARPHRD_IEEE80211_RADIOTAP; | 200 | dev->type = ARPHRD_IEEE80211_RADIOTAP; |
201 | dev->hard_start_xmit = ieee80211_monitor_start_xmit; | ||
199 | break; | 202 | break; |
200 | default: | 203 | default: |
201 | printk(KERN_WARNING "%s: %s: Unknown interface type 0x%x", | 204 | printk(KERN_WARNING "%s: %s: Unknown interface type 0x%x", |