⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 tx.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 4 页
字号:
		 * __ieee80211_parse_tx_radiotap has now removed		 * the radiotap header that was present and pre-filled		 * 'tx' with tx control information.		 */	}	hdr = (struct ieee80211_hdr *) skb->data;	tx->sta = sta_info_get(local, hdr->addr1);	tx->fc = le16_to_cpu(hdr->frame_control);	if (is_multicast_ether_addr(hdr->addr1)) {		tx->flags &= ~IEEE80211_TXRXD_TXUNICAST;		control->flags |= IEEE80211_TXCTL_NO_ACK;	} else {		tx->flags |= IEEE80211_TXRXD_TXUNICAST;		control->flags &= ~IEEE80211_TXCTL_NO_ACK;	}	if (tx->flags & IEEE80211_TXRXD_FRAGMENTED) {		if ((tx->flags & IEEE80211_TXRXD_TXUNICAST) &&		    skb->len + FCS_LEN > local->fragmentation_threshold &&		    !local->ops->set_frag_threshold)			tx->flags |= IEEE80211_TXRXD_FRAGMENTED;		else			tx->flags &= ~IEEE80211_TXRXD_FRAGMENTED;	}	if (!tx->sta)		control->flags |= IEEE80211_TXCTL_CLEAR_DST_MASK;	else if (tx->sta->clear_dst_mask) {		control->flags |= IEEE80211_TXCTL_CLEAR_DST_MASK;		tx->sta->clear_dst_mask = 0;	}	hdrlen = ieee80211_get_hdrlen(tx->fc);	if (skb->len > hdrlen + sizeof(rfc1042_header) + 2) {		u8 *pos = &skb->data[hdrlen + sizeof(rfc1042_header)];		tx->ethertype = (pos[0] << 8) | pos[1];	}	control->flags |= IEEE80211_TXCTL_FIRST_FRAGMENT;	return res;}/* Device in tx->dev has a reference added; use dev_put(tx->dev) when * finished with it. * * NB: @tx is uninitialised when passed in here */static int ieee80211_tx_prepare(struct ieee80211_txrx_data *tx,				struct sk_buff *skb,				struct net_device *mdev,				struct ieee80211_tx_control *control){	struct ieee80211_tx_packet_data *pkt_data;	struct net_device *dev;	pkt_data = (struct ieee80211_tx_packet_data *)skb->cb;	dev = dev_get_by_index(&init_net, pkt_data->ifindex);	if (unlikely(dev && !is_ieee80211_device(dev, mdev))) {		dev_put(dev);		dev = NULL;	}	if (unlikely(!dev))		return -ENODEV;	/* initialises tx with control */	__ieee80211_tx_prepare(tx, skb, dev, control);	return 0;}static int __ieee80211_tx(struct ieee80211_local *local, struct sk_buff *skb,			  struct ieee80211_txrx_data *tx){	struct ieee80211_tx_control *control = tx->u.tx.control;	int ret, i;	if (!ieee80211_qdisc_installed(local->mdev) &&	    __ieee80211_queue_stopped(local, 0)) {		netif_stop_queue(local->mdev);		return IEEE80211_TX_AGAIN;	}	if (skb) {		ieee80211_dump_frame(wiphy_name(local->hw.wiphy),				     "TX to low-level driver", skb);		ret = local->ops->tx(local_to_hw(local), skb, control);		if (ret)			return IEEE80211_TX_AGAIN;		local->mdev->trans_start = jiffies;		ieee80211_led_tx(local, 1);	}	if (tx->u.tx.extra_frag) {		control->flags &= ~(IEEE80211_TXCTL_USE_RTS_CTS |				    IEEE80211_TXCTL_USE_CTS_PROTECT |				    IEEE80211_TXCTL_CLEAR_DST_MASK |				    IEEE80211_TXCTL_FIRST_FRAGMENT);		for (i = 0; i < tx->u.tx.num_extra_frag; i++) {			if (!tx->u.tx.extra_frag[i])				continue;			if (__ieee80211_queue_stopped(local, control->queue))				return IEEE80211_TX_FRAG_AGAIN;			if (i == tx->u.tx.num_extra_frag) {				control->tx_rate = tx->u.tx.last_frag_hwrate;				control->rate = tx->u.tx.last_frag_rate;				if (tx->flags & IEEE80211_TXRXD_TXPROBE_LAST_FRAG)					control->flags |=						IEEE80211_TXCTL_RATE_CTRL_PROBE;				else					control->flags &=						~IEEE80211_TXCTL_RATE_CTRL_PROBE;			}			ieee80211_dump_frame(wiphy_name(local->hw.wiphy),					     "TX to low-level driver",					     tx->u.tx.extra_frag[i]);			ret = local->ops->tx(local_to_hw(local),					    tx->u.tx.extra_frag[i],					    control);			if (ret)				return IEEE80211_TX_FRAG_AGAIN;			local->mdev->trans_start = jiffies;			ieee80211_led_tx(local, 1);			tx->u.tx.extra_frag[i] = NULL;		}		kfree(tx->u.tx.extra_frag);		tx->u.tx.extra_frag = NULL;	}	return IEEE80211_TX_OK;}static int ieee80211_tx(struct net_device *dev, struct sk_buff *skb,			struct ieee80211_tx_control *control){	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);	struct sta_info *sta;	ieee80211_tx_handler *handler;	struct ieee80211_txrx_data tx;	ieee80211_txrx_result res = TXRX_DROP, res_prepare;	int ret, i;	WARN_ON(__ieee80211_queue_pending(local, control->queue));	if (unlikely(skb->len < 10)) {		dev_kfree_skb(skb);		return 0;	}	/* initialises tx */	res_prepare = __ieee80211_tx_prepare(&tx, skb, dev, control);	if (res_prepare == TXRX_DROP) {		dev_kfree_skb(skb);		return 0;	}	/*	 * key references are protected using RCU and this requires that	 * we are in a read-site RCU section during receive processing	 */	rcu_read_lock();	sta = tx.sta;	tx.u.tx.mode = local->hw.conf.mode;	for (handler = local->tx_handlers; *handler != NULL;	     handler++) {		res = (*handler)(&tx);		if (res != TXRX_CONTINUE)			break;	}	skb = tx.skb; /* handlers are allowed to change skb */	if (sta)		sta_info_put(sta);	if (unlikely(res == TXRX_DROP)) {		I802_DEBUG_INC(local->tx_handlers_drop);		goto drop;	}	if (unlikely(res == TXRX_QUEUED)) {		I802_DEBUG_INC(local->tx_handlers_queued);		rcu_read_unlock();		return 0;	}	if (tx.u.tx.extra_frag) {		for (i = 0; i < tx.u.tx.num_extra_frag; i++) {			int next_len, dur;			struct ieee80211_hdr *hdr =				(struct ieee80211_hdr *)				tx.u.tx.extra_frag[i]->data;			if (i + 1 < tx.u.tx.num_extra_frag) {				next_len = tx.u.tx.extra_frag[i + 1]->len;			} else {				next_len = 0;				tx.u.tx.rate = tx.u.tx.last_frag_rate;				tx.u.tx.last_frag_hwrate = tx.u.tx.rate->val;			}			dur = ieee80211_duration(&tx, 0, next_len);			hdr->duration_id = cpu_to_le16(dur);		}	}retry:	ret = __ieee80211_tx(local, skb, &tx);	if (ret) {		struct ieee80211_tx_stored_packet *store =			&local->pending_packet[control->queue];		if (ret == IEEE80211_TX_FRAG_AGAIN)			skb = NULL;		set_bit(IEEE80211_LINK_STATE_PENDING,			&local->state[control->queue]);		smp_mb();		/* When the driver gets out of buffers during sending of		 * fragments and calls ieee80211_stop_queue, there is		 * a small window between IEEE80211_LINK_STATE_XOFF and		 * IEEE80211_LINK_STATE_PENDING flags are set. If a buffer		 * gets available in that window (i.e. driver calls		 * ieee80211_wake_queue), we would end up with ieee80211_tx		 * called with IEEE80211_LINK_STATE_PENDING. Prevent this by		 * continuing transmitting here when that situation is		 * possible to have happened. */		if (!__ieee80211_queue_stopped(local, control->queue)) {			clear_bit(IEEE80211_LINK_STATE_PENDING,				  &local->state[control->queue]);			goto retry;		}		memcpy(&store->control, control,		       sizeof(struct ieee80211_tx_control));		store->skb = skb;		store->extra_frag = tx.u.tx.extra_frag;		store->num_extra_frag = tx.u.tx.num_extra_frag;		store->last_frag_hwrate = tx.u.tx.last_frag_hwrate;		store->last_frag_rate = tx.u.tx.last_frag_rate;		store->last_frag_rate_ctrl_probe =			!!(tx.flags & IEEE80211_TXRXD_TXPROBE_LAST_FRAG);	}	rcu_read_unlock();	return 0; drop:	if (skb)		dev_kfree_skb(skb);	for (i = 0; i < tx.u.tx.num_extra_frag; i++)		if (tx.u.tx.extra_frag[i])			dev_kfree_skb(tx.u.tx.extra_frag[i]);	kfree(tx.u.tx.extra_frag);	rcu_read_unlock();	return 0;}/* device xmit handlers */int ieee80211_master_start_xmit(struct sk_buff *skb,				struct net_device *dev){	struct ieee80211_tx_control control;	struct ieee80211_tx_packet_data *pkt_data;	struct net_device *odev = NULL;	struct ieee80211_sub_if_data *osdata;	int headroom;	int ret;	/*	 * copy control out of the skb so other people can use skb->cb	 */	pkt_data = (struct ieee80211_tx_packet_data *)skb->cb;	memset(&control, 0, sizeof(struct ieee80211_tx_control));	if (pkt_data->ifindex)		odev = dev_get_by_index(&init_net, pkt_data->ifindex);	if (unlikely(odev && !is_ieee80211_device(odev, dev))) {		dev_put(odev);		odev = NULL;	}	if (unlikely(!odev)) {#ifdef CONFIG_MAC80211_VERBOSE_DEBUG		printk(KERN_DEBUG "%s: Discarded packet with nonexistent "		       "originating device\n", dev->name);#endif		dev_kfree_skb(skb);		return 0;	}	osdata = IEEE80211_DEV_TO_SUB_IF(odev);	headroom = osdata->local->tx_headroom + IEEE80211_ENCRYPT_HEADROOM;	if (skb_headroom(skb) < headroom) {		if (pskb_expand_head(skb, headroom, 0, GFP_ATOMIC)) {			dev_kfree_skb(skb);			dev_put(odev);			return 0;		}	}	control.ifindex = odev->ifindex;	control.type = osdata->type;	if (pkt_data->flags & IEEE80211_TXPD_REQ_TX_STATUS)		control.flags |= IEEE80211_TXCTL_REQ_TX_STATUS;	if (pkt_data->flags & IEEE80211_TXPD_DO_NOT_ENCRYPT)		control.flags |= IEEE80211_TXCTL_DO_NOT_ENCRYPT;	if (pkt_data->flags & IEEE80211_TXPD_REQUEUE)		control.flags |= IEEE80211_TXCTL_REQUEUE;	control.queue = pkt_data->queue;	ret = ieee80211_tx(odev, skb, &control);	dev_put(odev);	return ret;}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_rthdr;	/* check for not even having the fixed radiotap header part */	if (unlikely(skb->len < sizeof(struct ieee80211_radiotap_header)))		goto fail; /* too short to be possibly valid */	/* is it a header version we can trust to find length from? */	if (unlikely(prthdr->it_version))		goto fail; /* only version 0 is supported */	/* then there must be a radiotap header with a length we can use */	len_rthdr = ieee80211_get_radiotap_len(skb->data);	/* does the skb contain enough to deliver on the alleged length? */	if (unlikely(skb->len < len_rthdr))		goto fail; /* skb too short for claimed rt header extent */	skb->dev = local->mdev;	pkt_data = (struct ieee80211_tx_packet_data *)skb->cb;	memset(pkt_data, 0, sizeof(*pkt_data));	/* needed because we set skb device to master */	pkt_data->ifindex = dev->ifindex;	pkt_data->flags |= IEEE80211_TXPD_DO_NOT_ENCRYPT;	/*	 * 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	 */	skb_set_mac_header(skb, len_rthdr);	/*	 * these are just fixed to the end of the rt area since we	 * don't have any better information and at this point, nobody cares	 */	skb_set_network_header(skb, len_rthdr);	skb_set_transport_header(skb, len_rthdr);	/* pass the radiotap header up to the next stage intact */	dev_queue_xmit(skb);	return NETDEV_TX_OK;fail:	dev_kfree_skb(skb);	return NETDEV_TX_OK; /* meaning, we dealt with the 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). */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;	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;	h_pos = skb_transport_header(skb) - skb->data;	/* convert Ethernet header to proper 802.11 header (based on	 * operation mode) */	ethertype = (skb->data[12] << 8) | skb->data[13];	/* TODO: handling for 802.1x authorized/unauthorized port */	fc = IEEE80211_FTYPE_DATA | IEEE80211_STYPE_DATA;	switch (sdata->type) {	case IEEE80211_IF_TYPE_AP:	case IEEE80211_IF_TYPE_VLAN:		fc |= IEEE80211_FCTL_FROMDS;		/* DA BSSID SA */		memcpy(hdr.addr1, skb->data, ETH_ALEN);		memcpy(hdr.addr2, dev->dev_addr, ETH_ALEN);		memcpy(hdr.addr3, skb->data + ETH_ALEN, ETH_ALEN);		hdrlen = 24;		break;	case IEEE80211_IF_TYPE_WDS:		fc |= IEEE80211_FCTL_FROMDS | IEEE80211_FCTL_TODS;		/* RA TA DA SA */		memcpy(hdr.addr1, sdata->u.wds.remote_addr, ETH_ALEN);		memcpy(hdr.addr2, dev->dev_addr, ETH_ALEN);		memcpy(hdr.addr3, skb->data, ETH_ALEN);		memcpy(hdr.addr4, skb->data + ETH_ALEN, ETH_ALEN);		hdrlen = 30;		break;	case IEEE80211_IF_TYPE_STA:		fc |= IEEE80211_FCTL_TODS;		/* BSSID SA DA */		memcpy(hdr.addr1, sdata->u.sta.bssid, ETH_ALEN);		memcpy(hdr.addr2, skb->data + ETH_ALEN, ETH_ALEN);		memcpy(hdr.addr3, skb->data, ETH_ALEN);		hdrlen = 24;		break;	case IEEE80211_IF_TYPE_IBSS:		/* DA SA BSSID */		memcpy(hdr.addr1, skb->data, ETH_ALEN);		memcpy(hdr.addr2, skb->data + ETH_ALEN, ETH_ALEN);		memcpy(hdr.addr3, sdata->u.sta.bssid, ETH_ALEN);		hdrlen = 24;		break;	default:		ret = 0;		goto fail;	}	/* receiver is QoS enabled, use a QoS type frame */	sta = sta_info_get(local, hdr.addr1);	if (sta) {		if (sta->flags & WLAN_STA_WME) {			fc |= IEEE80211_STYPE_QOS_DATA;			hdrlen += 2;		}		sta_info_put(sta);	}	hdr.frame_control = cpu_to_le16(fc);	hdr.duration_id = 0;	hdr.seq_ctrl = 0;	skip_header_bytes = ETH_HLEN;	if (ethertype == ETH_P_AARP || ethertype == ETH_P_IPX) {		encaps_data = bridge_tunnel_header;		encaps_len = sizeof(bridge_tunnel_header);		skip_header_bytes -= 2;	} else if (ethertype >= 0x600) {		encaps_data = rfc1042_header;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -