WLAN 帧详解
帧格式
如上是一个80211的帧格式,传输顺序是从左向右发送,也就是是说最高bit将会最后出现
FrameControl
FrameControl如下图所示
FrameControl的第一个字段是Protocal目前为0,其次是Type【bit3,bit2】与Subtype位【bit7,bit6,bit5,bit4】,在射频发送的时候的先发送bit0后发送bit7,发送时最高bit最后出现,在下面的描述中为了方便阅读,我们将最高位放在左边。
Subtype
管理帧类型type为00
子类型
- 0000 Association request(连接要求)
- 0001 Association response(连接应答)
- 0010 Reassociation request(重新连接要求)
- 0011 Reassociation response(重新连接应答)
- 0100 Probe request(探查要求)
- 0101 Probe response(探查应答)
- 1000 Beacon(导引信号)
- 1001 ATIM(数据代传指示通知信号)
- 1010 Disassociation(解除连接)
- 1011 Authentication(身份验证)
- 1100 Deauthentication(解除认证)
FrameControl一共包含两个字节,在Linux中一般表示为 __le16 fc,__le表示小端模式,也就是说低字节保存在低地址,这样做的原因是在硬件发送时一般只给寄存器写一个开始地址由硬件自动发送,接收也是一样总是先接收到低地址的数据然后将数据保存在一段内存当中,程序在处理的时候直接将这段内存在进行拷贝和强制转换,如在Linux中的如下定义
struct ieee80211_hdr {
__le16 frame_control;
__le16 duration_id;
u8 addr1[ETH_ALEN];
u8 addr2[ETH_ALEN];
u8 addr3[ETH_ALEN];
__le16 seq_ctrl;
u8 addr4[ETH_ALEN];
}
处理无线数据时直接进行强制转换如下,假设接收数据内存为buffer
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)buffer
这样就可以通过hdr操作接收的数据,hdr->frame_control表示帧控制字段,在不同的架构上处理时需要将数据使用cpu_to_le16进行转化,如果获取FrameType
hdr->frame_countrol & cpu_to_le16(IEEE80211_FCTL_FTYPE) 、
将IEEE80211_FCTL_FTYPE转换为小端,之所以这样做,是因为IEEE80211_FCTL_FTYPE这个值0x000c在不同的架构内存分布是不一样的
- 小端下0x000c = 低地址0x0c 高地址0x00
- 大端下0x000c = 低地址0x00 高地址0x00
这样的话程序处理起来就会很方便,而且在使用硬件DMA发送时传递地址即可
同样的我们可以知道控制帧type为01,并有如下类型
- 1010 Power Save-Poll(省电模式-轮询)
- 1011 RTS(请求发送)
- 1100 CTS(允许发送)
- 1101 ACK(应答)
- 1110 CF-End(免竞争期间结束)
- 1111 CF-End(免竞争期间结束)+CF-Ack(免竞争期间回应)
数据帧的type为10
并有如下子类型
- 0000 Data(数据)
- 0001 Data+CF-Ack
- 0010 Data+CF-Poll
- 0011 Data+CF-Ack+CF-Poll
- 0100 Null data (无数据:未发送数据)
- 0101 CF-Ack (未发送数据)
- 0110 CF-Poll (未发送数据)
- 0111 Data+CF-Ack+CF-Poll
- 1000 QoS Data
- 1001 QoS Data + CF-Ack
- 1010 QoS Data + CF-Poll
- 1011 QoS Data + CF-Ack + CF-Poll
- 1100 QoS Null (未发送数据)
- 1101 QoS CF-Ack (未发送数据)
- 1110 QoS CF-Poll (未发送数据)
- 1111 QoS CF-Ack+CF-Poll (未发送数据)
我们可以看到QoS数据的高位为1,因此也把第一个bit称为QoSbit