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

📄 tx.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 4 页
字号:
	if (!(tx->flags & IEEE80211_TXRXD_FRAGMENTED))		return TXRX_CONTINUE;	first = tx->skb;	hdrlen = ieee80211_get_hdrlen(tx->fc);	payload_len = first->len - hdrlen;	per_fragm = frag_threshold - hdrlen - FCS_LEN;	num_fragm = DIV_ROUND_UP(payload_len, per_fragm);	frags = kzalloc(num_fragm * sizeof(struct sk_buff *), GFP_ATOMIC);	if (!frags)		goto fail;	hdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_MOREFRAGS);	seq = le16_to_cpu(hdr->seq_ctrl) & IEEE80211_SCTL_SEQ;	pos = first->data + hdrlen + per_fragm;	left = payload_len - per_fragm;	for (i = 0; i < num_fragm - 1; i++) {		struct ieee80211_hdr *fhdr;		size_t copylen;		if (left <= 0)			goto fail;		/* reserve enough extra head and tail room for possible		 * encryption */		frag = frags[i] =			dev_alloc_skb(tx->local->tx_headroom +				      frag_threshold +				      IEEE80211_ENCRYPT_HEADROOM +				      IEEE80211_ENCRYPT_TAILROOM);		if (!frag)			goto fail;		/* Make sure that all fragments use the same priority so		 * that they end up using the same TX queue */		frag->priority = first->priority;		skb_reserve(frag, tx->local->tx_headroom +				  IEEE80211_ENCRYPT_HEADROOM);		fhdr = (struct ieee80211_hdr *) skb_put(frag, hdrlen);		memcpy(fhdr, first->data, hdrlen);		if (i == num_fragm - 2)			fhdr->frame_control &= cpu_to_le16(~IEEE80211_FCTL_MOREFRAGS);		fhdr->seq_ctrl = cpu_to_le16(seq | ((i + 1) & IEEE80211_SCTL_FRAG));		copylen = left > per_fragm ? per_fragm : left;		memcpy(skb_put(frag, copylen), pos, copylen);		pos += copylen;		left -= copylen;	}	skb_trim(first, hdrlen + per_fragm);	tx->u.tx.num_extra_frag = num_fragm - 1;	tx->u.tx.extra_frag = frags;	return TXRX_CONTINUE; fail:	printk(KERN_DEBUG "%s: failed to fragment frame\n", tx->dev->name);	if (frags) {		for (i = 0; i < num_fragm - 1; i++)			if (frags[i])				dev_kfree_skb(frags[i]);		kfree(frags);	}	I802_DEBUG_INC(tx->local->tx_handlers_drop_fragment);	return TXRX_DROP;}static ieee80211_txrx_resultieee80211_tx_h_encrypt(struct ieee80211_txrx_data *tx){	if (!tx->key)		return TXRX_CONTINUE;	switch (tx->key->conf.alg) {	case ALG_WEP:		return ieee80211_crypto_wep_encrypt(tx);	case ALG_TKIP:		return ieee80211_crypto_tkip_encrypt(tx);	case ALG_CCMP:		return ieee80211_crypto_ccmp_encrypt(tx);	}	/* not reached */	WARN_ON(1);	return TXRX_DROP;}static ieee80211_txrx_resultieee80211_tx_h_rate_ctrl(struct ieee80211_txrx_data *tx){	struct rate_control_extra extra;	if (likely(!tx->u.tx.rate)) {		memset(&extra, 0, sizeof(extra));		extra.mode = tx->u.tx.mode;		extra.ethertype = tx->ethertype;		tx->u.tx.rate = rate_control_get_rate(tx->local, tx->dev,						      tx->skb, &extra);		if (unlikely(extra.probe != NULL)) {			tx->u.tx.control->flags |=				IEEE80211_TXCTL_RATE_CTRL_PROBE;			tx->flags |= IEEE80211_TXRXD_TXPROBE_LAST_FRAG;			tx->u.tx.control->alt_retry_rate = tx->u.tx.rate->val;			tx->u.tx.rate = extra.probe;		} else			tx->u.tx.control->alt_retry_rate = -1;		if (!tx->u.tx.rate)			return TXRX_DROP;	} else		tx->u.tx.control->alt_retry_rate = -1;	if (tx->u.tx.mode->mode == MODE_IEEE80211G &&	    (tx->sdata->flags & IEEE80211_SDATA_USE_PROTECTION) &&	    (tx->flags & IEEE80211_TXRXD_FRAGMENTED) && extra.nonerp) {		tx->u.tx.last_frag_rate = tx->u.tx.rate;		if (extra.probe)			tx->flags &= ~IEEE80211_TXRXD_TXPROBE_LAST_FRAG;		else			tx->flags |= IEEE80211_TXRXD_TXPROBE_LAST_FRAG;		tx->u.tx.rate = extra.nonerp;		tx->u.tx.control->rate = extra.nonerp;		tx->u.tx.control->flags &= ~IEEE80211_TXCTL_RATE_CTRL_PROBE;	} else {		tx->u.tx.last_frag_rate = tx->u.tx.rate;		tx->u.tx.control->rate = tx->u.tx.rate;	}	tx->u.tx.control->tx_rate = tx->u.tx.rate->val;	return TXRX_CONTINUE;}static ieee80211_txrx_resultieee80211_tx_h_misc(struct ieee80211_txrx_data *tx){	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) tx->skb->data;	u16 fc = le16_to_cpu(hdr->frame_control);	u16 dur;	struct ieee80211_tx_control *control = tx->u.tx.control;	struct ieee80211_hw_mode *mode = tx->u.tx.mode;	if (!control->retry_limit) {		if (!is_multicast_ether_addr(hdr->addr1)) {			if (tx->skb->len + FCS_LEN > tx->local->rts_threshold			    && tx->local->rts_threshold <					IEEE80211_MAX_RTS_THRESHOLD) {				control->flags |=					IEEE80211_TXCTL_USE_RTS_CTS;				control->flags |=					IEEE80211_TXCTL_LONG_RETRY_LIMIT;				control->retry_limit =					tx->local->long_retry_limit;			} else {				control->retry_limit =					tx->local->short_retry_limit;			}		} else {			control->retry_limit = 1;		}	}	if (tx->flags & IEEE80211_TXRXD_FRAGMENTED) {		/* Do not use multiple retry rates when sending fragmented		 * frames.		 * TODO: The last fragment could still use multiple retry		 * rates. */		control->alt_retry_rate = -1;	}	/* Use CTS protection for unicast frames sent using extended rates if	 * there are associated non-ERP stations and RTS/CTS is not configured	 * for the frame. */	if (mode->mode == MODE_IEEE80211G &&	    (tx->u.tx.rate->flags & IEEE80211_RATE_ERP) &&	    (tx->flags & IEEE80211_TXRXD_TXUNICAST) &&	    (tx->sdata->flags & IEEE80211_SDATA_USE_PROTECTION) &&	    !(control->flags & IEEE80211_TXCTL_USE_RTS_CTS))		control->flags |= IEEE80211_TXCTL_USE_CTS_PROTECT;	/* Transmit data frames using short preambles if the driver supports	 * short preambles at the selected rate and short preambles are	 * available on the network at the current point in time. */	if (((fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_DATA) &&	    (tx->u.tx.rate->flags & IEEE80211_RATE_PREAMBLE2) &&	    (tx->sdata->flags & IEEE80211_SDATA_SHORT_PREAMBLE) &&	    (!tx->sta || (tx->sta->flags & WLAN_STA_SHORT_PREAMBLE))) {		tx->u.tx.control->tx_rate = tx->u.tx.rate->val2;	}	/* Setup duration field for the first fragment of the frame. Duration	 * for remaining fragments will be updated when they are being sent	 * to low-level driver in ieee80211_tx(). */	dur = ieee80211_duration(tx, is_multicast_ether_addr(hdr->addr1),				 (tx->flags & IEEE80211_TXRXD_FRAGMENTED) ?				 tx->u.tx.extra_frag[0]->len : 0);	hdr->duration_id = cpu_to_le16(dur);	if ((control->flags & IEEE80211_TXCTL_USE_RTS_CTS) ||	    (control->flags & IEEE80211_TXCTL_USE_CTS_PROTECT)) {		struct ieee80211_rate *rate;		/* Do not use multiple retry rates when using RTS/CTS */		control->alt_retry_rate = -1;		/* Use min(data rate, max base rate) as CTS/RTS rate */		rate = tx->u.tx.rate;		while (rate > mode->rates &&		       !(rate->flags & IEEE80211_RATE_BASIC))			rate--;		control->rts_cts_rate = rate->val;		control->rts_rate = rate;	}	if (tx->sta) {		tx->sta->tx_packets++;		tx->sta->tx_fragments++;		tx->sta->tx_bytes += tx->skb->len;		if (tx->u.tx.extra_frag) {			int i;			tx->sta->tx_fragments += tx->u.tx.num_extra_frag;			for (i = 0; i < tx->u.tx.num_extra_frag; i++) {				tx->sta->tx_bytes +=					tx->u.tx.extra_frag[i]->len;			}		}	}	/*	 * Tell hardware to not encrypt when we had sw crypto.	 * Because we use the same flag to internally indicate that	 * no (software) encryption should be done, we have to set it	 * after all crypto handlers.	 */	if (tx->key && !(tx->key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE))		tx->u.tx.control->flags |= IEEE80211_TXCTL_DO_NOT_ENCRYPT;	return TXRX_CONTINUE;}static ieee80211_txrx_resultieee80211_tx_h_load_stats(struct ieee80211_txrx_data *tx){	struct ieee80211_local *local = tx->local;	struct ieee80211_hw_mode *mode = tx->u.tx.mode;	struct sk_buff *skb = tx->skb;	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;	u32 load = 0, hdrtime;	/* TODO: this could be part of tx_status handling, so that the number	 * of retries would be known; TX rate should in that case be stored	 * somewhere with the packet */	/* Estimate total channel use caused by this frame */	/* 1 bit at 1 Mbit/s takes 1 usec; in channel_use values,	 * 1 usec = 1/8 * (1080 / 10) = 13.5 */	if (mode->mode == MODE_IEEE80211A ||	    (mode->mode == MODE_IEEE80211G &&	     tx->u.tx.rate->flags & IEEE80211_RATE_ERP))		hdrtime = CHAN_UTIL_HDR_SHORT;	else		hdrtime = CHAN_UTIL_HDR_LONG;	load = hdrtime;	if (!is_multicast_ether_addr(hdr->addr1))		load += hdrtime;	if (tx->u.tx.control->flags & IEEE80211_TXCTL_USE_RTS_CTS)		load += 2 * hdrtime;	else if (tx->u.tx.control->flags & IEEE80211_TXCTL_USE_CTS_PROTECT)		load += hdrtime;	load += skb->len * tx->u.tx.rate->rate_inv;	if (tx->u.tx.extra_frag) {		int i;		for (i = 0; i < tx->u.tx.num_extra_frag; i++) {			load += 2 * hdrtime;			load += tx->u.tx.extra_frag[i]->len *				tx->u.tx.rate->rate;		}	}	/* Divide channel_use by 8 to avoid wrapping around the counter */	load >>= CHAN_UTIL_SHIFT;	local->channel_use_raw += load;	if (tx->sta)		tx->sta->channel_use_raw += load;	tx->sdata->channel_use_raw += load;	return TXRX_CONTINUE;}/* TODO: implement register/unregister functions for adding TX/RX handlers * into ordered list */ieee80211_tx_handler ieee80211_tx_handlers[] ={	ieee80211_tx_h_check_assoc,	ieee80211_tx_h_sequence,	ieee80211_tx_h_ps_buf,	ieee80211_tx_h_select_key,	ieee80211_tx_h_michael_mic_add,	ieee80211_tx_h_fragment,	ieee80211_tx_h_encrypt,	ieee80211_tx_h_rate_ctrl,	ieee80211_tx_h_misc,	ieee80211_tx_h_load_stats,	NULL};/* actual transmit path *//* * deal with packet injection down monitor interface * with Radiotap Header -- only called for monitor mode interface */static ieee80211_txrx_result__ieee80211_parse_tx_radiotap(struct ieee80211_txrx_data *tx,			      struct sk_buff *skb){	/*	 * this is the moment to interpret and discard the radiotap header that	 * must be at the start of the packet injected in Monitor mode	 *	 * Need to take some care with endian-ness since radiotap	 * args are little-endian	 */	struct ieee80211_radiotap_iterator iterator;	struct ieee80211_radiotap_header *rthdr =		(struct ieee80211_radiotap_header *) skb->data;	struct ieee80211_hw_mode *mode = tx->local->hw.conf.mode;	int ret = ieee80211_radiotap_iterator_init(&iterator, rthdr, skb->len);	struct ieee80211_tx_control *control = tx->u.tx.control;	control->flags |= IEEE80211_TXCTL_DO_NOT_ENCRYPT;	tx->flags |= IEEE80211_TXRXD_TX_INJECTED;	tx->flags &= ~IEEE80211_TXRXD_FRAGMENTED;	/*	 * for every radiotap entry that is present	 * (ieee80211_radiotap_iterator_next returns -ENOENT when no more	 * entries present, or -EINVAL on error)	 */	while (!ret) {		int i, target_rate;		ret = ieee80211_radiotap_iterator_next(&iterator);		if (ret)			continue;		/* see if this argument is something we can use */		switch (iterator.this_arg_index) {		/*		 * You must take care when dereferencing iterator.this_arg		 * for multibyte types... the pointer is not aligned.  Use		 * get_unaligned((type *)iterator.this_arg) to dereference		 * iterator.this_arg for type "type" safely on all arches.		*/		case IEEE80211_RADIOTAP_RATE:			/*			 * radiotap rate u8 is in 500kbps units eg, 0x02=1Mbps			 * ieee80211 rate int is in 100kbps units eg, 0x0a=1Mbps			 */			target_rate = (*iterator.this_arg) * 5;			for (i = 0; i < mode->num_rates; i++) {				struct ieee80211_rate *r = &mode->rates[i];				if (r->rate == target_rate) {					tx->u.tx.rate = r;					break;				}			}			break;		case IEEE80211_RADIOTAP_ANTENNA:			/*			 * radiotap uses 0 for 1st ant, mac80211 is 1 for			 * 1st ant			 */			control->antenna_sel_tx = (*iterator.this_arg) + 1;			break;		case IEEE80211_RADIOTAP_DBM_TX_POWER:			control->power_level = *iterator.this_arg;			break;		case IEEE80211_RADIOTAP_FLAGS:			if (*iterator.this_arg & IEEE80211_RADIOTAP_F_FCS) {				/*				 * this indicates that the skb we have been				 * handed has the 32-bit FCS CRC at the end...				 * we should react to that by snipping it off				 * because it will be recomputed and added				 * on transmission				 */				if (skb->len < (iterator.max_length + FCS_LEN))					return TXRX_DROP;				skb_trim(skb, skb->len - FCS_LEN);			}			if (*iterator.this_arg & IEEE80211_RADIOTAP_F_WEP)				control->flags &=					~IEEE80211_TXCTL_DO_NOT_ENCRYPT;			if (*iterator.this_arg & IEEE80211_RADIOTAP_F_FRAG)				tx->flags |= IEEE80211_TXRXD_FRAGMENTED;			break;		/*		 * Please update the file		 * Documentation/networking/mac80211-injection.txt		 * when parsing new fields here.		 */		default:			break;		}	}	if (ret != -ENOENT) /* ie, if we didn't simply run out of fields */		return TXRX_DROP;	/*	 * remove the radiotap header	 * iterator->max_length was sanity-checked against	 * skb->len by iterator init	 */	skb_pull(skb, iterator.max_length);	return TXRX_CONTINUE;}/* * initialises @tx */static ieee80211_txrx_result__ieee80211_tx_prepare(struct ieee80211_txrx_data *tx,		       struct sk_buff *skb,		       struct net_device *dev,		       struct ieee80211_tx_control *control){	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);	struct ieee80211_hdr *hdr;	struct ieee80211_sub_if_data *sdata;	ieee80211_txrx_result res = TXRX_CONTINUE;	int hdrlen;	memset(tx, 0, sizeof(*tx));	tx->skb = skb;	tx->dev = dev; /* use original interface */	tx->local = local;	tx->sdata = IEEE80211_DEV_TO_SUB_IF(dev);	tx->u.tx.control = control;	/*	 * Set this flag (used below to indicate "automatic fragmentation"),	 * it will be cleared/left by radiotap as desired.	 */	tx->flags |= IEEE80211_TXRXD_FRAGMENTED;	/* process and remove the injection radiotap header */	sdata = IEEE80211_DEV_TO_SUB_IF(dev);	if (unlikely(sdata->type == IEEE80211_IF_TYPE_MNTR)) {		if (__ieee80211_parse_tx_radiotap(tx, skb) == TXRX_DROP)			return TXRX_DROP;		/*

⌨️ 快捷键说明

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