📄 ieee80211_tx.c
字号:
* 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 + -