802.11协议在Linux内核中的实现
合集下载
相关主题
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
3 /42
1.2驱动概念
驱动程序是指一组子程序它们屏蔽了底层硬件处理细 节,同时向上层软件提供硬件无关接口。可形象比喻 为软硬皆吃。 由于无线媒体的特殊性,其网络设备的驱动相对(以 太网)来说要复杂得多。
4 /42
2. 驱动框架
以2002-5-19版 prism2驱动为蓝本,主要分析Ad-hoc 网络设备驱动程序编写方法有两种:通过模块驱动和 通过内核启动时自动检测的方法。 通过模块驱动的优点: 1、减小内核体积; 2、有助于调试。 2 用shell命令的insmod将该模块插入到内核运行空间; 用rmmod命令将该模块卸载。insmod触发的是程序里 面的init_module()函数;而rmmod命令触发的是 cleanup_module()函数。注意:需要root权限。 #insmod ./hostap_cs.o #rmmod hostap_cs
10 /42
2.4中断
11 /42
2.5 统计数据
12 /42
2.6 用户的ioctl命令系统调用
13 /42
3. 寄存器
软硬件之间的交互基本都是通过寄存器进行的,比如 硬件的初始化,激活、关闭、设置或读取硬件的属性 等等。 Prism2硬件里的寄存器均是16位
14 /42
3. 1 指令寄存器
26 /42
3.9.3 数据寄存器
数据寄存器(Data0-1 Registers) 用于读写buffer的数据,读写时内部的指针会自动增 加(有点和文件的读写操作类似)。
27 /42
3.10 RxFID Register
当网络设备接收到数据包,且EvStat register的Rx位被 置1后,即可从中读取用于接收数据缓冲结构体的FID。 在EvAck register的RxAck位被置1后,表示FID无效。
7 /42
2. 1模块的加载和卸载(Cont.)
8 /42
2.2 设备的打开与关闭
在允许发送接收数据之前,需要打开(即激活)网络 设备。对应于打开操作,还有关闭操作。 它们在驱动中对应的函数分别为: static int prism2_open(struct net_device *dev); static int prism2_close(struct net_device *dev); 可以通过ifconfig命令手动激活或关闭。 #ifconfig wlan0 up #ifconfig wlan0 down
IEEE 802.11协议在Linux内核中的实现
Outline
预备知识 驱动框架 寄存器(代码示例) 传送及接收帧结构体 传送及接收数据流程 调试 总结(到目前为止,我们能做什么)
2 /42
1.1 涉及到的内核中的数据结构
套接字缓冲区(sk_buff)---- sockfd = socket(AF_INET,SOCK_STREAM,0) -是以双向链表结构进行管理, 在INET Socket层和硬件层之 间存放数据包,并完成数据 包在不同层次之间的传递的 载体。特点:跨层、指针移 位操作减少内存里的数据 copy,提高效率。 net_device结构------供网 络接口设备使用。特点:每 个网络设备都有且仅有一个 对应的此结构。所有的网络 设备都会添加到一个以 dev_base为表头的链表中。
21 /42
3.8 实例
22 /42
3.8 实例(Cont.)
23 /42
3.9 缓冲访问通道
缓冲访问路径--Buffer Access Paths (BAPs) 在硬件中有两个BAP0和BAP1(不是指寄存器,我认 为是一种机制),每个又对应有三个寄存器Select0-1 Registers、Offset0-1 Registers及Data0-1 Registers。 主要用于把需要发送的数据包写入缓冲(FID),读取接 收的数据包(FID)及读取或设置硬件相关参数(RID) , 如使用频率、传输速率等。 在使用BAP之前,需要调用hfa384x_setup_bap()进行 初始化,把获得的fid和offest写入相应的寄存器中。
指令寄存器(Command Register) 这个寄存器是用来执行指令的,比如硬件初始化(Initialize)、 激活(enable)、关闭(disable)、分配fid(Allocate)、传输数据 包(Transmit)等,每一个指令操作都需要通过此寄存器。
当一个指令写入寄存器中时,busy位会自动设为1,表示 不能再接收其它指令;当指令被接受是又会自动设为0。
25 /42
3.9.2 偏移寄存器
偏移寄存器(Offset0-1 Registers) 用于写数据的偏移值。 当某个值写入到寄存器中时,busy位会自动置为1,在 100微秒内会自动置为0。如果busy位重置,表示写入 完成,并且Err位生效。 Err=0&&busy=0:表示能通过data register指定的地址 访问数据。 Err=1&&busy=0:表示buffer溢出或FID/RID有误。
5 /42
2. 1模块的加载和卸载(初始化)
6 /42
2. 1模块的加载和卸载(Cont.)
由于此网络设备是PCMCIA规范,所以先向PCMCIA卡 管理器注册该设备 (调用register_pccard_driver),使 driver_info_t结构attach函数指针指向prism2_attach(), detach函数指针指向prism2_detach()。 prism2_attach()调用prism2_init_local_data() 初始化网络 设备的local_info_t结构;调用prism2_setup_dev(),初始 local_info_t prism2_setup_dev() 化网络设备结构struct net_device *dev的多个函数指针 ; 调用prism2_hw_init()建立FID(Frame IDentifiers)与缓冲 区之间的映射,通过RID(Resource IDentifiers)初始化网 络设备的一些属性,如传输速率;注册中断服务类程。 调用prism2_init_dev()把网络设备添加到dev_base为链表 头的链表中,在proc文件系统中建立相应的目录,初始 化数据加密过程等。
读取传送用于数据的缓冲结构体FID(一般用于TxOK 及TxExc中断事件中)。 其它注意事项与前同(略)。
31 /42
4.传送及接收帧结构体
32 /42
4.传送及接收帧结构体(Cont.)
33 /42
4.1传送帧结构体
Struct hfa384x_tx_frame用于提供构造实际硬件头的必 要信息,它即包括802.11格式又包括802.3格式,当需 要802.11时就用802.11格式,反之亦然。 成员TxControl
17 /42
3.4 指令反馈寄存器
指令反馈寄存器(Resp0-2 Registers) Prism中总共有三个(0, 1, 2)。 这个寄存器用于读取指令执行完后的response resulting。 在状态寄存器中数据有效的情况下,此response resulting 才算有效。
18 /42
36 /42
5.1发送数据流程
ip层调用dev->hard_start_xmit即 对应prism2_tx() 调用prism2_transmit(dev, idx),停止上层继续往下发数据, 并调用hfa384x_cmd_no_wait(),延时等待command寄存器清 忙位。如果设备仍忙,则返回并打印错误信息,同时清位允 许上层继续往下发送数据。否则把fid所对应的数据发送出去, 不等待发送完成返回。等待硬中断事件发生。 调用prism2_get_txfid_idx()获得 一个空闲fid
28 /42
3.11 AllocFID Register
在command register中执行Alloc指令后,可从中获得缓 冲结构体的地址。 其它注意事项与前同(略)。
29 /42
3.11AllocFID Register(Cont.)
30 /42
3.12 TxComplFID Register
9 /42
2.3 数据包的发送和接收
在驱动层次上的发送和接收都是通过底层对硬件的读 写来完成的。 发送数据的时候,在prism2网卡上,通过对网卡的发 送缓冲区写需要发送的数据,然后向command寄存器 写发送命令,将数据包发送到物理网络上。 当网络上有数据包来的时候,会触发硬件中断,根据 注册的中断向量表确定处理函数,进入中断处理程序, 将数据发送到上层协议进行处理。 发送和接收数据函数分别为: static int prism2_tx(struct sk_buff *skb, struct net_device *dev); static int prism2_rx(struct net_device *dev);
调 用 hfa384x_setup_bap() 把 申 请到的fid 所代表的地址写入 select0寄存器中,并把偏移写 入offest0寄存器中
MACPort---用于传送数据的MAC端口。 位StrucType=0,表示用802.3格式;…=1,则反之。 位T百度文库Ex---当传送失败是否需要触发TxExc中断,为0表 示不触发。 位TxOK----当传送成功是否需要触发Tx中断,为0表示 不触发。(驱动中未实现)
34 /42
4.1传送帧结构体(Cont.)
15 /42
3.2 参数寄存器
参数寄存器(Param0-2 Registers) 用来存放指令的参数。 Prism中总共有三个(0, 1, 2)。 必须在指令写入指令寄存器之前,且指令寄存器的 busy为0的情况下,才能向参数寄存器写入参数
16 /42
3.3 状态寄存器
状态寄存器(Status Register) 这个寄存器用于读取指令执行后的状态,如Successful、 Card failure、No buffer space、Command error。 CmdCode存放上次执行的指令。 只有在EvStat register的cmd位置1,读取出来的状态才算 有效,另外,一旦EvAck register的CmdAck位被置1,则 表示状态过期无效。
20 /42
3.7 事件确认寄存器
事件确认寄存器(EvAck Register) 一个事件发生之后,总是必须确认,一旦确认后随此 事件发生的一切状态及产生的结果就都不再具有任何 意义。 方法是把与事件状态寄存器(EvStat Register)中的相同 位置1,当确认事件完成,硬件会自动把相应位置为0。
3.5 事件状态寄存器
事件状态寄存器(EvStat Register) 某位置1,则表示相应的事件发生。 当EvAck register寄存器相应的位被置1时,则表示此 事件被确认,硬件会自动重置EvStat Register。
19 /42
3.6 中断寄存器
中断寄存器(IntEn Register) 当事件状态寄存器(EvStat Register)和此寄存器有相同 的位被置1时,则会产生相应的中断。
当数据传送完成(不论是否成功),可通过成员status可 以获得数据传送的结果。
35 /42
4.2接收帧结构体
成员status
MessageType---数据域中数据的类型 PCF置1,表示此包在CF(自由竞争)期间接收的 MACPort接收数据所用的mac端口 后面两个分别与解密及CRC相关
成员frame_control---可判断接收到的数据包是哪一类 型(管理帧、数据帧、控制帧)。
24 /42
3.9.1 选择寄存器
选择寄存器(Select0-1 Registers) 用于写入FID/RID的值,它必须在Offset Registers的 busy位为0且在偏移值(data offset)写入Offset Registers 之前进行。 FID用于描述一个特殊的帧缓冲结构。 RID是一个16进制0xFC00–0xFFFF范围内的值,用于 设置或读取硬件的相关参数。
1.2驱动概念
驱动程序是指一组子程序它们屏蔽了底层硬件处理细 节,同时向上层软件提供硬件无关接口。可形象比喻 为软硬皆吃。 由于无线媒体的特殊性,其网络设备的驱动相对(以 太网)来说要复杂得多。
4 /42
2. 驱动框架
以2002-5-19版 prism2驱动为蓝本,主要分析Ad-hoc 网络设备驱动程序编写方法有两种:通过模块驱动和 通过内核启动时自动检测的方法。 通过模块驱动的优点: 1、减小内核体积; 2、有助于调试。 2 用shell命令的insmod将该模块插入到内核运行空间; 用rmmod命令将该模块卸载。insmod触发的是程序里 面的init_module()函数;而rmmod命令触发的是 cleanup_module()函数。注意:需要root权限。 #insmod ./hostap_cs.o #rmmod hostap_cs
10 /42
2.4中断
11 /42
2.5 统计数据
12 /42
2.6 用户的ioctl命令系统调用
13 /42
3. 寄存器
软硬件之间的交互基本都是通过寄存器进行的,比如 硬件的初始化,激活、关闭、设置或读取硬件的属性 等等。 Prism2硬件里的寄存器均是16位
14 /42
3. 1 指令寄存器
26 /42
3.9.3 数据寄存器
数据寄存器(Data0-1 Registers) 用于读写buffer的数据,读写时内部的指针会自动增 加(有点和文件的读写操作类似)。
27 /42
3.10 RxFID Register
当网络设备接收到数据包,且EvStat register的Rx位被 置1后,即可从中读取用于接收数据缓冲结构体的FID。 在EvAck register的RxAck位被置1后,表示FID无效。
7 /42
2. 1模块的加载和卸载(Cont.)
8 /42
2.2 设备的打开与关闭
在允许发送接收数据之前,需要打开(即激活)网络 设备。对应于打开操作,还有关闭操作。 它们在驱动中对应的函数分别为: static int prism2_open(struct net_device *dev); static int prism2_close(struct net_device *dev); 可以通过ifconfig命令手动激活或关闭。 #ifconfig wlan0 up #ifconfig wlan0 down
IEEE 802.11协议在Linux内核中的实现
Outline
预备知识 驱动框架 寄存器(代码示例) 传送及接收帧结构体 传送及接收数据流程 调试 总结(到目前为止,我们能做什么)
2 /42
1.1 涉及到的内核中的数据结构
套接字缓冲区(sk_buff)---- sockfd = socket(AF_INET,SOCK_STREAM,0) -是以双向链表结构进行管理, 在INET Socket层和硬件层之 间存放数据包,并完成数据 包在不同层次之间的传递的 载体。特点:跨层、指针移 位操作减少内存里的数据 copy,提高效率。 net_device结构------供网 络接口设备使用。特点:每 个网络设备都有且仅有一个 对应的此结构。所有的网络 设备都会添加到一个以 dev_base为表头的链表中。
21 /42
3.8 实例
22 /42
3.8 实例(Cont.)
23 /42
3.9 缓冲访问通道
缓冲访问路径--Buffer Access Paths (BAPs) 在硬件中有两个BAP0和BAP1(不是指寄存器,我认 为是一种机制),每个又对应有三个寄存器Select0-1 Registers、Offset0-1 Registers及Data0-1 Registers。 主要用于把需要发送的数据包写入缓冲(FID),读取接 收的数据包(FID)及读取或设置硬件相关参数(RID) , 如使用频率、传输速率等。 在使用BAP之前,需要调用hfa384x_setup_bap()进行 初始化,把获得的fid和offest写入相应的寄存器中。
指令寄存器(Command Register) 这个寄存器是用来执行指令的,比如硬件初始化(Initialize)、 激活(enable)、关闭(disable)、分配fid(Allocate)、传输数据 包(Transmit)等,每一个指令操作都需要通过此寄存器。
当一个指令写入寄存器中时,busy位会自动设为1,表示 不能再接收其它指令;当指令被接受是又会自动设为0。
25 /42
3.9.2 偏移寄存器
偏移寄存器(Offset0-1 Registers) 用于写数据的偏移值。 当某个值写入到寄存器中时,busy位会自动置为1,在 100微秒内会自动置为0。如果busy位重置,表示写入 完成,并且Err位生效。 Err=0&&busy=0:表示能通过data register指定的地址 访问数据。 Err=1&&busy=0:表示buffer溢出或FID/RID有误。
5 /42
2. 1模块的加载和卸载(初始化)
6 /42
2. 1模块的加载和卸载(Cont.)
由于此网络设备是PCMCIA规范,所以先向PCMCIA卡 管理器注册该设备 (调用register_pccard_driver),使 driver_info_t结构attach函数指针指向prism2_attach(), detach函数指针指向prism2_detach()。 prism2_attach()调用prism2_init_local_data() 初始化网络 设备的local_info_t结构;调用prism2_setup_dev(),初始 local_info_t prism2_setup_dev() 化网络设备结构struct net_device *dev的多个函数指针 ; 调用prism2_hw_init()建立FID(Frame IDentifiers)与缓冲 区之间的映射,通过RID(Resource IDentifiers)初始化网 络设备的一些属性,如传输速率;注册中断服务类程。 调用prism2_init_dev()把网络设备添加到dev_base为链表 头的链表中,在proc文件系统中建立相应的目录,初始 化数据加密过程等。
读取传送用于数据的缓冲结构体FID(一般用于TxOK 及TxExc中断事件中)。 其它注意事项与前同(略)。
31 /42
4.传送及接收帧结构体
32 /42
4.传送及接收帧结构体(Cont.)
33 /42
4.1传送帧结构体
Struct hfa384x_tx_frame用于提供构造实际硬件头的必 要信息,它即包括802.11格式又包括802.3格式,当需 要802.11时就用802.11格式,反之亦然。 成员TxControl
17 /42
3.4 指令反馈寄存器
指令反馈寄存器(Resp0-2 Registers) Prism中总共有三个(0, 1, 2)。 这个寄存器用于读取指令执行完后的response resulting。 在状态寄存器中数据有效的情况下,此response resulting 才算有效。
18 /42
36 /42
5.1发送数据流程
ip层调用dev->hard_start_xmit即 对应prism2_tx() 调用prism2_transmit(dev, idx),停止上层继续往下发数据, 并调用hfa384x_cmd_no_wait(),延时等待command寄存器清 忙位。如果设备仍忙,则返回并打印错误信息,同时清位允 许上层继续往下发送数据。否则把fid所对应的数据发送出去, 不等待发送完成返回。等待硬中断事件发生。 调用prism2_get_txfid_idx()获得 一个空闲fid
28 /42
3.11 AllocFID Register
在command register中执行Alloc指令后,可从中获得缓 冲结构体的地址。 其它注意事项与前同(略)。
29 /42
3.11AllocFID Register(Cont.)
30 /42
3.12 TxComplFID Register
9 /42
2.3 数据包的发送和接收
在驱动层次上的发送和接收都是通过底层对硬件的读 写来完成的。 发送数据的时候,在prism2网卡上,通过对网卡的发 送缓冲区写需要发送的数据,然后向command寄存器 写发送命令,将数据包发送到物理网络上。 当网络上有数据包来的时候,会触发硬件中断,根据 注册的中断向量表确定处理函数,进入中断处理程序, 将数据发送到上层协议进行处理。 发送和接收数据函数分别为: static int prism2_tx(struct sk_buff *skb, struct net_device *dev); static int prism2_rx(struct net_device *dev);
调 用 hfa384x_setup_bap() 把 申 请到的fid 所代表的地址写入 select0寄存器中,并把偏移写 入offest0寄存器中
MACPort---用于传送数据的MAC端口。 位StrucType=0,表示用802.3格式;…=1,则反之。 位T百度文库Ex---当传送失败是否需要触发TxExc中断,为0表 示不触发。 位TxOK----当传送成功是否需要触发Tx中断,为0表示 不触发。(驱动中未实现)
34 /42
4.1传送帧结构体(Cont.)
15 /42
3.2 参数寄存器
参数寄存器(Param0-2 Registers) 用来存放指令的参数。 Prism中总共有三个(0, 1, 2)。 必须在指令写入指令寄存器之前,且指令寄存器的 busy为0的情况下,才能向参数寄存器写入参数
16 /42
3.3 状态寄存器
状态寄存器(Status Register) 这个寄存器用于读取指令执行后的状态,如Successful、 Card failure、No buffer space、Command error。 CmdCode存放上次执行的指令。 只有在EvStat register的cmd位置1,读取出来的状态才算 有效,另外,一旦EvAck register的CmdAck位被置1,则 表示状态过期无效。
20 /42
3.7 事件确认寄存器
事件确认寄存器(EvAck Register) 一个事件发生之后,总是必须确认,一旦确认后随此 事件发生的一切状态及产生的结果就都不再具有任何 意义。 方法是把与事件状态寄存器(EvStat Register)中的相同 位置1,当确认事件完成,硬件会自动把相应位置为0。
3.5 事件状态寄存器
事件状态寄存器(EvStat Register) 某位置1,则表示相应的事件发生。 当EvAck register寄存器相应的位被置1时,则表示此 事件被确认,硬件会自动重置EvStat Register。
19 /42
3.6 中断寄存器
中断寄存器(IntEn Register) 当事件状态寄存器(EvStat Register)和此寄存器有相同 的位被置1时,则会产生相应的中断。
当数据传送完成(不论是否成功),可通过成员status可 以获得数据传送的结果。
35 /42
4.2接收帧结构体
成员status
MessageType---数据域中数据的类型 PCF置1,表示此包在CF(自由竞争)期间接收的 MACPort接收数据所用的mac端口 后面两个分别与解密及CRC相关
成员frame_control---可判断接收到的数据包是哪一类 型(管理帧、数据帧、控制帧)。
24 /42
3.9.1 选择寄存器
选择寄存器(Select0-1 Registers) 用于写入FID/RID的值,它必须在Offset Registers的 busy位为0且在偏移值(data offset)写入Offset Registers 之前进行。 FID用于描述一个特殊的帧缓冲结构。 RID是一个16进制0xFC00–0xFFFF范围内的值,用于 设置或读取硬件的相关参数。