📄 ieee80211_tx.c
字号:
/****************************************************************************** Copyright(c) 2003 - 2004 Intel Corporation. All rights reserved. ieee802.11 header construcion, some TX logic and misc modifications for rtl8180-sa2400 driver added by Andrea Merello <andreamrl@tiscali.it> This program is free software; you can redistribute it and/or modify it under the terms of version 2 of the GNU General Public License as published by the Free Software Foundation. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. The full GNU General Public License is included in this distribution in the file called LICENSE. Contact Information: James P. Ketrenos <ipw2100-admin@linux.intel.com> Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 Please note that the file has been heavily modified for the rtl8180-sa2400 driver, so please don't contact the above person for bugs or other issues if you are not sure they are related to the original code******************************************************************************/#include <linux/compiler.h>#include <linux/config.h>#include <linux/errno.h>#include <linux/if_arp.h>#include <linux/in6.h>#include <linux/in.h>#include <linux/ip.h>#include <linux/kernel.h>#include <linux/module.h>#include <linux/netdevice.h>#include <linux/pci.h>#include <linux/proc_fs.h>#include <linux/skbuff.h>#include <linux/slab.h>#include <linux/tcp.h>#include <linux/types.h>#include <linux/version.h>#include <linux/wireless.h>#include <linux/etherdevice.h>#include <asm/uaccess.h>#include "ieee80211.h"/*#define DEBUG_SKB2TXB#define DEBUG_HARD_XMIT*//*802.11 frame_contorl for data frames - 2 bytes ,-----------------------------------------------------------------------------------------.bits | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | a | b | c | d | e | |----|-----|-----|-----|-----|-----|-----|-----|-----|-----|-----|-----|-----|-----|------|val | 0 | 0 | 0 | 1 | x | 0 | 0 | 0 | 1 | 0 | x | x | x | x | x | |----|-----|-----|-----|-----|-----|-----|-----|-----|-----|-----|-----|-----|-----|------|desc | ^-ver-^ | ^type-^ | ^-----subtype-----^ | to |from |more |retry| pwr |more |wep | | | | x=0 data,x=1 data+ack | DS | DS |frag | | mgm |data | | '-----------------------------------------------------------------------------------------' /\ |802.11 Data Frame | ,--------- 'ctrl' expands to >-----------' | ,---'--, | |------------------------------------------------------------.Bytes | 2 | 2 | 6 | 6 | 6 | 2 | 0..2312 | 4 | |------|------|---------|---------|---------|------|---------|------|Desc. | ctrl | dura | DA/RA | TA | SA | Sequ | Frame | fcs | | | tion | (BSSID) | | | ence | data | | `--------------------------------------------------| |------'Total: 28 non-data bytes `----.----' | .- 'Frame data' expands to <---------------------------' | V ,---------------------------------------------------.Bytes | 1 | 1 | 1 | 3 | 2 | 0-2304 | |------|------|---------|----------|------|---------|Desc. | SNAP | SNAP | Control |Eth Tunnel| Type | IP | | DSAP | SSAP | | | | Packet | | 0xAA | 0xAA |0x03 (UI)|0x00-00-F8| | | `-----------------------------------------| |Total: 8 non-data bytes `----.----' | .- 'IP Packet' expands, if WEP enabled, to <--' | V ,-----------------------.Bytes | 4 | 0-2296 | 4 | |-----|-----------|-----|Desc. | IV | Encrypted | ICV | | | IP Packet | | `-----------------------'Total: 8 non-data bytes802.3 Ethernet Data Frame ,-----------------------------------------.Bytes | 6 | 6 | 2 | Variable | 4 | |-------|-------|------|-----------|------|Desc. | Dest. | Source| Type | IP Packet | fcs | | MAC | MAC | | | | `-----------------------------------------'Total: 18 non-data bytesIn the event that fragmentation is required, the incoming payload is split intoN parts of size ieee->fts. The first fragment contains the SNAP header and theremaining packets are just data.If encryption is enabled, each fragment payload size is reduced by enough spaceto add the prefix and postfix (IV and ICV totalling 8 bytes in the case of WEP)So if you have 1500 bytes of payload with ieee->fts set to 500 without encryption it will take 3 frames. With WEP it will take 4 frames as the payload of each frame is reduced to 492 bytes.* SKB visualization* * ,- skb->data * |* | ETHERNET HEADER ,-<-- PAYLOAD* | | 14 bytes from skb->data * | 2 bytes for Type --> ,T. | (sizeof ethhdr)* | | | | * |,-Dest.--. ,--Src.---. | | | * | 6 bytes| | 6 bytes | | | |* v | | | | | |* 0 | v 1 | v | v 2 * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5* ^ | ^ | ^ | * | | | | | | * | | | | `T' <---- 2 bytes for Type* | | | |* | | '---SNAP--' <-------- 6 bytes for SNAP* | | * `-IV--' <-------------------- 4 bytes for IV (WEP)** SNAP HEADER**/static u8 P802_1H_OUI[P80211_OUI_LEN] = { 0x00, 0x00, 0xf8 };static u8 RFC1042_OUI[P80211_OUI_LEN] = { 0x00, 0x00, 0x00 };static inline int ieee80211_put_snap(u8 *data, u16 h_proto){ struct ieee_802_11_snap_header *snap; u8 *oui; snap = (struct ieee_802_11_snap_header *)data; snap->dsap = 0xaa; snap->ssap = 0xaa; snap->ctrl = 0x03; if (h_proto == 0x8137 || h_proto == 0x80f3) oui = P802_1H_OUI; else oui = RFC1042_OUI; snap->oui[0] = oui[0]; snap->oui[1] = oui[1]; snap->oui[2] = oui[2]; *(u16 *)(data + SNAP_SIZE) = htons(h_proto); return SNAP_SIZE + sizeof(u16);}#ifndef CONFIG_IEEE80211_NOWEPstatic inline int ieee80211_encrypt_fragment( struct ieee80211_device *ieee, struct sk_buff *frag, int hdr_len){ struct ieee80211_crypt_data* crypt = ieee->crypt[ieee->tx_keyidx]; int res; #ifdef NOT_YET if (ieee->tkip_countermeasures && crypt && crypt->ops && strcmp(crypt->ops->name, "TKIP") == 0) { hdr = (struct ieee80211_hdr *) skb->data; if (net_ratelimit()) { printk(KERN_DEBUG "%s: TKIP countermeasures: dropped " "TX packet to " MACSTR "\n", ieee->dev->name, MAC2STR(hdr->addr1)); } return NULL; }#endif /* To encrypt, frame format is: * IV (4 bytes), clear payload (including SNAP), ICV (4 bytes) */ // PR: FIXME: Copied from hostap. Check fragmentation/MSDU/MPDU encryption. /* Host-based IEEE 802.11 fragmentation for TX is not yet supported, so * call both MSDU and MPDU encryption functions from here. */ atomic_inc(&crypt->refcnt); res = 0; if (crypt->ops->encrypt_msdu) res = crypt->ops->encrypt_msdu(frag, hdr_len, crypt->priv); if (res == 0 && crypt->ops->encrypt_mpdu) res = crypt->ops->encrypt_mpdu(frag, hdr_len, crypt->priv); atomic_dec(&crypt->refcnt); if (res < 0) { printk(KERN_INFO "%s: Encryption failed: len=%d.\n", ieee->dev->name, frag->len); ieee->ieee_stats.tx_discards++; return -1; } return 0;}#endifvoid ieee80211_r8180_txb_free(struct ieee80211_txb *txb) { int i; //static int alloc=0; if (unlikely(!txb)) return; for (i = 0; i < txb->nr_frags; i++) if (txb->fragments[i]) dev_kfree_skb_any(txb->fragments[i]); kfree(txb); }struct ieee80211_txb *ieee80211_r8180_alloc_txb(int nr_frags, int txb_size, int gfp_mask) { struct ieee80211_txb *txb; int i; //static int dealloc=0; txb = (struct ieee80211_txb *)kmalloc( sizeof(struct ieee80211_txb) + (sizeof(u8*) * nr_frags), gfp_mask); if (!txb) return NULL; memset(txb, 0, sizeof(struct ieee80211_txb)); txb->nr_frags = nr_frags; txb->frag_size = txb_size; for (i = 0; i < nr_frags; i++) { txb->fragments[i] = dev_alloc_skb(txb_size); if (unlikely(!txb->fragments[i])) { i--; break; } } if (unlikely(i != nr_frags)) { while (i >= 0) dev_kfree_skb_any(txb->fragments[i--]); kfree(txb); IEEE80211DMESG("fail"); return NULL; } return txb;}u16 ieee80211_calc_duration(u32 len, short rate)//,short* ext){ //*ext=0; u16 duration; u16 drift; switch(rate){ case 0://1mbps // *ext=0; duration = ((len+4)<<4) /0x2; drift = ((len+4)<<4) % 0x2; if(drift ==0 ) break; duration++; break; case 1://2mbps // *ext=0; duration = ((len+4)<<4) /0x4; drift = ((len+4)<<4) % 0x4; if(drift ==0 ) break; duration++; break; case 2: //5.5mbps // *ext=0; duration = ((len+4)<<4) /0xb; drift = ((len+4)<<4) % 0xb; if(drift ==0 ) break; duration++; break; default: case 3://11mbps // *ext=0; duration = ((len+4)<<4) /0x16; drift = ((len+4)<<4) % 0x16; if(drift ==0 ) break; duration++; /* if(drift > 6) break; *ext=1;*/ break; } return duration;}struct ieee80211_txb *ieee80211_r8180_skb_to_txb(struct ieee80211_device *ieee, struct sk_buff *skb){ struct ieee80211_txb *txb; int i, payload_size, nr_frags, last_payload_size; //unsigned long flags; struct net_device_stats *stats = &ieee->stats; int ether_type, encrypt; int size, fc, hdr_len; struct sk_buff *skb_frag; struct ieee80211_header_data *header; u8 src_addr[ETH_ALEN]; u8 dst_addr[ETH_ALEN]; u16 acktime; u8 icv[]={0,0,0,0}; #ifndef CONFIG_IEEE80211_NOWEP struct ieee80211_crypt_data* crypt;#endif /* we don't aquire lock since this is called only from * already-locked context */ //spin_lock_irqsave(&ieee->lock, flags); /* We do not return fail even if not associated, * during reassociation data frame are accepted until * the TX buffer is full. The nic should avoid to TX * them due to HW disable of the dma from data ring
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -