Commit 40f7cac9 authored by Johannes Berg's avatar Johannes Berg Committed by John W. Linville

[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: default avatarJohannes Berg <johannes@sipsolutions.net>
Signed-off-by: default avatarJiri Benc <jbenc@suse.cz>
Signed-off-by: default avatarJohn W. Linville <linville@tuxdriver.com>
parent 333af2f0
...@@ -1673,6 +1673,56 @@ static int ieee80211_master_start_xmit(struct sk_buff *skb, ...@@ -1673,6 +1673,56 @@ static int ieee80211_master_start_xmit(struct sk_buff *skb,
} }
int ieee80211_monitor_start_xmit(struct sk_buff *skb,
struct net_device *dev)
{
struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
struct ieee80211_tx_packet_data *pkt_data;
struct ieee80211_radiotap_header *prthdr =
(struct ieee80211_radiotap_header *)skb->data;
u16 len;
/*
* there must be a radiotap header at the
* start in this case
*/
if (unlikely(prthdr->it_version)) {
/* only version 0 is supported */
dev_kfree_skb(skb);
return NETDEV_TX_OK;
}
skb->dev = local->mdev;
pkt_data = (struct ieee80211_tx_packet_data *)skb->cb;
memset(pkt_data, 0, sizeof(*pkt_data));
pkt_data->ifindex = dev->ifindex;
pkt_data->mgmt_iface = 0;
pkt_data->do_not_encrypt = 1;
/* above needed because we set skb device to master */
/*
* fix up the pointers accounting for the radiotap
* header still being in there. We are being given
* a precooked IEEE80211 header so no need for
* normal processing
*/
len = le16_to_cpu(get_unaligned(&prthdr->it_len));
skb_set_mac_header(skb, len);
skb_set_network_header(skb, len + sizeof(struct ieee80211_hdr));
skb_set_transport_header(skb, len + sizeof(struct ieee80211_hdr));
/*
* pass the radiotap header up to
* the next stage intact
*/
dev_queue_xmit(skb);
return NETDEV_TX_OK;
}
/** /**
* ieee80211_subif_start_xmit - netif start_xmit function for Ethernet-type * ieee80211_subif_start_xmit - netif start_xmit function for Ethernet-type
* subinterfaces (wlan#, WDS, and VLAN interfaces) * subinterfaces (wlan#, WDS, and VLAN interfaces)
...@@ -1688,8 +1738,8 @@ static int ieee80211_master_start_xmit(struct sk_buff *skb, ...@@ -1688,8 +1738,8 @@ static int ieee80211_master_start_xmit(struct sk_buff *skb,
* encapsulated packet will then be passed to master interface, wlan#.11, for * encapsulated packet will then be passed to master interface, wlan#.11, for
* transmission (through low-level driver). * transmission (through low-level driver).
*/ */
static int ieee80211_subif_start_xmit(struct sk_buff *skb, int ieee80211_subif_start_xmit(struct sk_buff *skb,
struct net_device *dev) struct net_device *dev)
{ {
struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
struct ieee80211_tx_packet_data *pkt_data; struct ieee80211_tx_packet_data *pkt_data;
...@@ -1710,51 +1760,6 @@ static int ieee80211_subif_start_xmit(struct sk_buff *skb, ...@@ -1710,51 +1760,6 @@ static int ieee80211_subif_start_xmit(struct sk_buff *skb,
goto fail; goto fail;
} }
if (unlikely(sdata->type == IEEE80211_IF_TYPE_MNTR)) {
struct ieee80211_radiotap_header *prthdr =
(struct ieee80211_radiotap_header *)skb->data;
u16 len;
/*
* there must be a radiotap header at the
* start in this case
*/
if (unlikely(prthdr->it_version)) {
/* only version 0 is supported */
ret = 0;
goto fail;
}
skb->dev = local->mdev;
pkt_data = (struct ieee80211_tx_packet_data *)skb->cb;
memset(pkt_data, 0, sizeof(*pkt_data));
pkt_data->ifindex = sdata->dev->ifindex;
pkt_data->mgmt_iface = 0;
pkt_data->do_not_encrypt = 1;
/* above needed because we set skb device to master */
/*
* fix up the pointers accounting for the radiotap
* header still being in there. We are being given
* a precooked IEEE80211 header so no need for
* normal processing
*/
len = le16_to_cpu(get_unaligned(&prthdr->it_len));
skb_set_mac_header(skb, len);
skb_set_network_header(skb, len + sizeof(hdr));
skb_set_transport_header(skb, len + sizeof(hdr));
/*
* pass the radiotap header up to
* the next stage intact
*/
dev_queue_xmit(skb);
return 0;
}
nh_pos = skb_network_header(skb) - skb->data; nh_pos = skb_network_header(skb) - skb->data;
h_pos = skb_transport_header(skb) - skb->data; h_pos = skb_transport_header(skb) - skb->data;
...@@ -1882,7 +1887,7 @@ static int ieee80211_subif_start_xmit(struct sk_buff *skb, ...@@ -1882,7 +1887,7 @@ static int ieee80211_subif_start_xmit(struct sk_buff *skb,
pkt_data = (struct ieee80211_tx_packet_data *)skb->cb; pkt_data = (struct ieee80211_tx_packet_data *)skb->cb;
memset(pkt_data, 0, sizeof(struct ieee80211_tx_packet_data)); memset(pkt_data, 0, sizeof(struct ieee80211_tx_packet_data));
pkt_data->ifindex = sdata->dev->ifindex; pkt_data->ifindex = dev->ifindex;
pkt_data->mgmt_iface = (sdata->type == IEEE80211_IF_TYPE_MGMT); pkt_data->mgmt_iface = (sdata->type == IEEE80211_IF_TYPE_MGMT);
pkt_data->do_not_encrypt = no_encrypt; pkt_data->do_not_encrypt = no_encrypt;
......
...@@ -720,6 +720,8 @@ void ieee80211_prepare_rates(struct ieee80211_local *local, ...@@ -720,6 +720,8 @@ void ieee80211_prepare_rates(struct ieee80211_local *local,
struct ieee80211_hw_mode *mode); struct ieee80211_hw_mode *mode);
void ieee80211_tx_set_iswep(struct ieee80211_txrx_data *tx); void ieee80211_tx_set_iswep(struct ieee80211_txrx_data *tx);
int ieee80211_if_update_wds(struct net_device *dev, u8 *remote_addr); int ieee80211_if_update_wds(struct net_device *dev, u8 *remote_addr);
int ieee80211_monitor_start_xmit(struct sk_buff *skb, struct net_device *dev);
int ieee80211_subif_start_xmit(struct sk_buff *skb, struct net_device *dev);
void ieee80211_if_setup(struct net_device *dev); void ieee80211_if_setup(struct net_device *dev);
void ieee80211_if_mgmt_setup(struct net_device *dev); void ieee80211_if_mgmt_setup(struct net_device *dev);
int ieee80211_init_rate_ctrl_alg(struct ieee80211_local *local, int ieee80211_init_rate_ctrl_alg(struct ieee80211_local *local,
......
...@@ -157,6 +157,8 @@ void ieee80211_if_set_type(struct net_device *dev, int type) ...@@ -157,6 +157,8 @@ void ieee80211_if_set_type(struct net_device *dev, int type)
struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
int oldtype = sdata->type; int oldtype = sdata->type;
dev->hard_start_xmit = ieee80211_subif_start_xmit;
sdata->type = type; sdata->type = type;
switch (type) { switch (type) {
case IEEE80211_IF_TYPE_WDS: case IEEE80211_IF_TYPE_WDS:
...@@ -196,6 +198,7 @@ void ieee80211_if_set_type(struct net_device *dev, int type) ...@@ -196,6 +198,7 @@ void ieee80211_if_set_type(struct net_device *dev, int type)
} }
case IEEE80211_IF_TYPE_MNTR: case IEEE80211_IF_TYPE_MNTR:
dev->type = ARPHRD_IEEE80211_RADIOTAP; dev->type = ARPHRD_IEEE80211_RADIOTAP;
dev->hard_start_xmit = ieee80211_monitor_start_xmit;
break; break;
default: default:
printk(KERN_WARNING "%s: %s: Unknown interface type 0x%x", printk(KERN_WARNING "%s: %s: Unknown interface type 0x%x",
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment