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

📄 ieee80211_tx.c

📁 RTL8187 for linux驱动 提供内核支持802.11g的模块
💻 C
📖 第 1 页 / 共 2 页
字号:
	 * buffer. As far as I know frames in the NIC fifo 	 * are TXed without possibility of prevent it.	 * On the other hand when the nic is totally unassociated	 * the kernel queue should be stopped.	 */		//if(ieee->link_state != WLAN_LINK_ASSOCIATED) goto failed;		if (unlikely(skb->len < SNAP_SIZE + sizeof(u16))) {		printk(KERN_WARNING "%s: skb too small (%d).\n",		       ieee->dev->name, skb->len);		goto failed;	}#ifdef DEBUG_SKB2TXB	IEEE80211DMESG("going to copy adr from 8023");#endif	memcpy(dst_addr, skb->data, ETH_ALEN);	memcpy(src_addr, skb->data + ETH_ALEN, ETH_ALEN);	ether_type = ntohs(((struct ethhdr *)skb->data)->h_proto);#ifdef DEBUG_SKB2TXB	IEEE80211DMESG("copy adr from 8023 done");#endif	if(ieee->iw_mode == IW_MODE_MASTER)		add_bridged(ieee,src_addr);#ifndef CONFIG_IEEE80211_NOWEP	crypt = ieee->crypt[ieee->tx_keyidx];	encrypt = (ieee->host_encrypt && ether_type != ETH_P_PAE && 		   crypt && crypt->ops);#else	encrypt = 0;#endif /* CONFIG_IEEE80211_NOWEP */	/* Advance the SKB to the start of the payload */	skb_pull(skb, sizeof(struct ethhdr));	/* Determine total amount of storage required for TXB packets excluded headers*/	size = skb->len + SNAP_SIZE + sizeof(u16);#ifdef DEBUG_SKB2TXB	IEEE80211DMESG("calc payload per frag");#endif	/* Determine amount of data per fragment */	if(ieee->hw_wep)		payload_size = ieee->fts-8;	else		payload_size = ieee->fts;	if (!ieee->tx_payload_only) 		payload_size -= sizeof(struct ieee80211_header_data);#ifndef CONFIG_IEEE80211_NOWEP		if (encrypt)		payload_size -= crypt->ops->extra_prefix_len +			crypt->ops->extra_postfix_len;#endif /* CONFIG_IEEE80211_NOWEP */	nr_frags = size / payload_size;	last_payload_size = size % payload_size;		if (last_payload_size)		nr_frags++;	else		last_payload_size = payload_size;	/* When we allocate the TXB we allocate enough space for the reserve	 * and full fragment size (payload_size doesn't include prefix and 	 * postfix) */#ifdef DEBUG_SKB2TXB	IEEE80211DMESG("going to alloc txb");#endif	txb = ieee80211_r8180_alloc_txb(nr_frags, ieee->fts, GFP_ATOMIC);	if (unlikely(!txb)) {		printk(KERN_WARNING "%s: Could not allocate TXB\n",		       ieee->dev->name);		goto failed;	}	txb->encrypted = encrypt;	txb->payload_size = size;#ifdef DEBUG_SKB2TXB	IEEE80211DMESG("entering frag loop");#endif	for (i = 0; i < nr_frags; i++) {		skb_frag = txb->fragments[i];#ifdef DEBUG_SKB2TXB		IEEE80211DMESG("frag");#endif#ifndef CONFIG_IEEE80211_NOWEP			if (encrypt) 			skb_reserve(skb_frag, crypt->ops->extra_prefix_len);#endif /* CONFIG_IEEE80211_NOWEP */				size = (i == nr_frags - 1) ? last_payload_size : payload_size;				if (!ieee->tx_payload_only) {			header = (struct ieee80211_header_data *)				skb_put(skb_frag, sizeof(struct ieee80211_header_data));			switch(ieee->iw_mode){				case IW_MODE_INFRA:				memcpy(header->addr3 ,dst_addr,ETH_ALEN);				memcpy(header->addr1 ,ieee->ass_beacon->bssid,ETH_ALEN);				memcpy(header->addr2 ,src_addr,ETH_ALEN);				break;							case IW_MODE_MASTER:				memcpy(header->addr1 ,dst_addr,ETH_ALEN);				memcpy(header->addr2 ,ieee->beacon_cell_ssid,ETH_ALEN);				memcpy(header->addr3 ,src_addr,ETH_ALEN);								break;				case IW_MODE_ADHOC: 				memcpy(header->addr1 ,dst_addr,ETH_ALEN);				memcpy(header->addr3 ,ieee->beacon_cell_ssid,ETH_ALEN);				memcpy(header->addr2 ,src_addr,ETH_ALEN);				break;											}			/* 			 LOWORD(fc) = 0x08 for data, =0x18 for data+ack 			 if NO pwr-mngmt HIWORD(fc) =0x1 for last frag, =0x5 for more frag 			*/#ifdef DEBUG_SKB2TXB			IEEE80211DMESG("80211 addr copied");#endif			header->frame_control = 8; 			if(i+1<nr_frags) header->frame_control |= 0x0400;			//else header->frame_control =0x0108;			if(ieee->iw_mode == IW_MODE_INFRA) header->frame_control |= (1<<8);			else if(ieee->iw_mode == IW_MODE_MASTER) 				header->frame_control |= (1<<9);						if(ieee->hw_wep || encrypt) header->frame_control |= 0x4000;			header->seq_ctrl= i;			header->seq_ctrl|= ieee->seq_ctrl<<4;						header->seq_ctrl= cpu_to_le16(header->seq_ctrl);									/*printk(KERN_DEBUG "%s: TODO -- implement 802.11 "			       "header construction...\n", ieee->dev->name);			*/			fc = le16_to_cpu(header->frame_control);			hdr_len = ieee80211_get_hdrlen(fc);#ifdef DEBUG_SKB2TXB			IEEE80211DMESG("going to calc ACKtime");#endif				acktime = ieee80211_calc_duration(ACK_LEN,ieee->rate);			header->duration_id= is_broadcast(header->addr1) ? 0 : (				( i == nr_frags - 1) ? 					acktime + ieee->sifs_time : 										2*acktime + 3*ieee->sifs_time + 					hdr_len +					( i == nr_frags - 2) ? last_payload_size : payload_size				); 			header->duration_id= cpu_to_le16(header->duration_id);			header->duration_id =0;					} else 			hdr_len = 0;						//size-=hdr_len;		if(ieee->hw_wep) skb_put(skb_frag,4); //advance skb to provide IV+key room		/* Put a SNAP header on the first fragment */		if (i == 0) {						ieee80211_put_snap(				skb_put(skb_frag, SNAP_SIZE + sizeof(u16)), 				ether_type);			size -= SNAP_SIZE + sizeof(u16);		}						memcpy(skb_put(skb_frag, size), skb->data, size);		if(ieee->hw_wep) memcpy(skb_put(skb_frag,4),icv,4); //advance skb to provide ICV room		/* Advance the SKB... */		skb_pull(skb, size);#ifndef CONFIG_IEEE80211_NOWEP		/* Encryption routine will move the header forward in order		 * to insert the IV between the header and the payload */		if (encrypt)			ieee80211_encrypt_fragment(ieee, skb_frag, hdr_len);#endif	}#ifdef DEBUG_SKB2TXB	IEEE80211DMESG("Exiting from frag loop");#endif	if(!ieee->hw_seq)	{		if(ieee->seq_ctrl == 0xFFF) ieee->seq_ctrl=0;		else {			ieee->seq_ctrl++;			//IEEE80211DMESG("SW number wrapped back");		}	}	/* We are now done with the SKB provided to us */	dev_kfree_skb_any(skb);		//spin_unlock_irqrestore(&ieee->lock, flags);#ifdef DEBUG_SKB2TXB	IEEE80211DMESG("Exiting from skb2txb");#endif	return txb; failed:	stats->tx_errors++;	//spin_unlock_irqrestore(&ieee->lock, flags);	return NULL;}int ieee80211_r8180_8023_hardstartxmit(struct sk_buff *skb, struct ieee80211_device *ieee){	struct ieee80211_txb *txb;		unsigned long flags;	int  i;	int err=0;		spin_lock_irqsave(&ieee->lock,flags);		if(ieee->queue_stop){		IEEE80211DMESG("EE: IEEE hard_start_xmit invoked when kernel queue should be stopped");		netif_stop_queue(ieee->dev);		ieee->ieee_stats.swtxstop++;		//dev_kfree_skb_any(skb);		err = 1;		goto exit;	}		ieee->stats.tx_bytes+=skb->len;	txb=ieee80211_r8180_skb_to_txb(ieee,skb);	if(txb==NULL){		IEEE80211DMESG("WW: IEEE stack failed to provide txb");		//dev_kfree_skb_any(skb);		err = 1;		goto exit;	}	 	for(i=0; i<txb->nr_frags; i++) {			if(ieee->queue_stop){			ieee->tx_pending.txb = txb;			ieee->tx_pending.frag = i;			goto exit;		}else{#ifdef DEBUG_HARD_XMIT		IEEE80211DMESG("going to call the TX callback");#endif			ieee->func->hard_data_xmit(ieee->dev,				txb->fragments[i],(i+1)<txb->nr_frags);			ieee->stats.tx_packets++;			ieee->dev->trans_start = jiffies; 		}	}		#ifdef DEBUG_HARD_XMIT	IEEE80211DMESG("Going to free txb");#endif	ieee80211_r8180_txb_free(txb);		exit:	spin_unlock_irqrestore(&ieee->lock,flags);		return err;}void ieee80211_r8180_resume_tx(struct ieee80211_device *ieee){	int i;	for(i=ieee->tx_pending.frag; i<ieee->tx_pending.txb->nr_frags; i++) {				if(ieee->queue_stop){			ieee->tx_pending.frag = i;			return;		}else{					ieee->func->hard_data_xmit(ieee->dev, 				ieee->tx_pending.txb->fragments[i],				(i+1)<ieee->tx_pending.txb->nr_frags);			ieee->stats.tx_packets++;			ieee->dev->trans_start = jiffies;		}	}			ieee80211_r8180_txb_free(ieee->tx_pending.txb);	ieee->tx_pending.txb=NULL;}void ieee80211_r8180_reset_queue(struct ieee80211_device *ieee){	if(ieee->tx_pending.txb){		ieee80211_r8180_txb_free(ieee->tx_pending.txb);		ieee->tx_pending.txb=NULL;	}	ieee->queue_stop = 0;	}void ieee80211_r8180_wake_queue(struct ieee80211_device *ieee){	unsigned long flags;		spin_lock_irqsave(&ieee->lock,flags);	if(! ieee->queue_stop) goto exit;		ieee->queue_stop = 0;		if(ieee->tx_pending.txb)		ieee80211_r8180_resume_tx(ieee);		if(!ieee->queue_stop && netif_queue_stopped(ieee->dev)){		ieee->ieee_stats.swtxawake++;		netif_wake_queue(ieee->dev);	}		exit :	spin_unlock_irqrestore(&ieee->lock,flags);}void ieee80211_r8180_stop_queue(struct ieee80211_device *ieee){	if(! netif_queue_stopped(ieee->dev)){		netif_stop_queue(ieee->dev);		ieee->ieee_stats.swtxstop++;	}	ieee->queue_stop = 1;	}EXPORT_SYMBOL(ieee80211_r8180_8023_hardstartxmit);//EXPORT_SYMBOL(ieee80211_r8180_skb_to_txb);EXPORT_SYMBOL(ieee80211_r8180_wake_queue);EXPORT_SYMBOL(ieee80211_r8180_stop_queue);//EXPORT_SYMBOL(ieee80211_r8180_txb_free);//EXPORT_SYMBOL(ieee80211_r8180_alloc_txb);EXPORT_SYMBOL(ieee80211_r8180_reset_queue);

⌨️ 快捷键说明

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