Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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

[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
Loading
Loading
Loading
Loading
+53 −48
Original line number Diff line number Diff line
@@ -1673,44 +1673,11 @@ static int ieee80211_master_start_xmit(struct sk_buff *skb,
}


/**
 * ieee80211_subif_start_xmit - netif start_xmit function for Ethernet-type
 * subinterfaces (wlan#, WDS, and VLAN interfaces)
 * @skb: packet to be sent
 * @dev: incoming interface
 *
 * Returns: 0 on success (and frees skb in this case) or 1 on failure (skb will
 * not be freed, and caller is responsible for either retrying later or freeing
 * skb).
 *
 * This function takes in an Ethernet header and encapsulates it with suitable
 * IEEE 802.11 header based on which interface the packet is coming in. The
 * encapsulated packet will then be passed to master interface, wlan#.11, for
 * transmission (through low-level driver).
 */
static int ieee80211_subif_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_sub_if_data *sdata;
	int ret = 1, head_need;
	u16 ethertype, hdrlen, fc;
	struct ieee80211_hdr hdr;
	const u8 *encaps_data;
	int encaps_len, skip_header_bytes;
	int nh_pos, h_pos, no_encrypt = 0;
	struct sta_info *sta;

	sdata = IEEE80211_DEV_TO_SUB_IF(dev);
	if (unlikely(skb->len < ETH_HLEN)) {
		printk(KERN_DEBUG "%s: short skb (len=%d)\n",
		       dev->name, skb->len);
		ret = 0;
		goto fail;
	}

	if (unlikely(sdata->type == IEEE80211_IF_TYPE_MNTR)) {
	struct ieee80211_radiotap_header *prthdr =
		(struct ieee80211_radiotap_header *)skb->data;
	u16 len;
@@ -1721,15 +1688,15 @@ static int ieee80211_subif_start_xmit(struct sk_buff *skb,
	 */
	if (unlikely(prthdr->it_version)) {
		/* only version 0 is supported */
			ret = 0;
			goto fail;
		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 = sdata->dev->ifindex;
	pkt_data->ifindex = dev->ifindex;
	pkt_data->mgmt_iface = 0;
	pkt_data->do_not_encrypt = 1;

@@ -1743,8 +1710,8 @@ static int ieee80211_subif_start_xmit(struct sk_buff *skb,
	 */
	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));
	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
@@ -1752,7 +1719,45 @@ static int ieee80211_subif_start_xmit(struct sk_buff *skb,
	 */
	dev_queue_xmit(skb);

		return 0;
	return NETDEV_TX_OK;
}


/**
 * ieee80211_subif_start_xmit - netif start_xmit function for Ethernet-type
 * subinterfaces (wlan#, WDS, and VLAN interfaces)
 * @skb: packet to be sent
 * @dev: incoming interface
 *
 * Returns: 0 on success (and frees skb in this case) or 1 on failure (skb will
 * not be freed, and caller is responsible for either retrying later or freeing
 * skb).
 *
 * This function takes in an Ethernet header and encapsulates it with suitable
 * IEEE 802.11 header based on which interface the packet is coming in. The
 * encapsulated packet will then be passed to master interface, wlan#.11, for
 * transmission (through low-level driver).
 */
int ieee80211_subif_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_sub_if_data *sdata;
	int ret = 1, head_need;
	u16 ethertype, hdrlen, fc;
	struct ieee80211_hdr hdr;
	const u8 *encaps_data;
	int encaps_len, skip_header_bytes;
	int nh_pos, h_pos, no_encrypt = 0;
	struct sta_info *sta;

	sdata = IEEE80211_DEV_TO_SUB_IF(dev);
	if (unlikely(skb->len < ETH_HLEN)) {
		printk(KERN_DEBUG "%s: short skb (len=%d)\n",
		       dev->name, skb->len);
		ret = 0;
		goto fail;
	}

	nh_pos = skb_network_header(skb) - skb->data;
@@ -1882,7 +1887,7 @@ static int ieee80211_subif_start_xmit(struct sk_buff *skb,

	pkt_data = (struct ieee80211_tx_packet_data *)skb->cb;
	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->do_not_encrypt = no_encrypt;

+2 −0
Original line number Diff line number Diff line
@@ -720,6 +720,8 @@ void ieee80211_prepare_rates(struct ieee80211_local *local,
			     struct ieee80211_hw_mode *mode);
void ieee80211_tx_set_iswep(struct ieee80211_txrx_data *tx);
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_mgmt_setup(struct net_device *dev);
int ieee80211_init_rate_ctrl_alg(struct ieee80211_local *local,
+3 −0
Original line number Diff line number Diff line
@@ -157,6 +157,8 @@ void ieee80211_if_set_type(struct net_device *dev, int type)
	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
	int oldtype = sdata->type;

	dev->hard_start_xmit = ieee80211_subif_start_xmit;

	sdata->type = type;
	switch (type) {
	case IEEE80211_IF_TYPE_WDS:
@@ -196,6 +198,7 @@ void ieee80211_if_set_type(struct net_device *dev, int type)
	}
	case IEEE80211_IF_TYPE_MNTR:
		dev->type = ARPHRD_IEEE80211_RADIOTAP;
		dev->hard_start_xmit = ieee80211_monitor_start_xmit;
		break;
	default:
		printk(KERN_WARNING "%s: %s: Unknown interface type 0x%x",