ieee80211rx.c(E:\code\linux\net\ieee80211)
所有接收到的帧都送到这个函数中去
int ieee80211_rx(struct ieee80211_device *ieee, struct sk_buff *skb,struct ieee80211_rx_stats *rx_stats) 进行处理。
函数的实现过程如下:
(1)判断接收的帧的长度是否符合数据帧或管理帧的长度。若不符合,则丢弃。
fc = le16_to_cpu(hdr->frame_ctl);
hdrlen = ieee80211_get_hdrlen(fc);
if (skb->len < hdrlen) {
printk(KERN_INFO "%s: invalid SKB length %d\n",
dev->name, skb->len);
goto rx_dropped;
}
(2)如果ap处于监听模式IW_MODE_MONITOR
ieee80211_monitor_rx(ieee, skb, rx_stats);
(3)
=================================================
补充:
1、ieee80211_get_hdrlen
作用:根据传入的帧的类型进行长度的判断。 对于802.11的帧,只有数据帧和管理帧这两类。
2、在双向列表末尾插入
static inline void __skb_queue_tail(struct sk_buff_head *list, struct sk_buff *newsk)
{
struct sk_buff *prev, *next;
list->qlen++;
next = (struct sk_buff *)list;
prev = next->prev;
newsk->next = next;
newsk->prev = prev;
next->prev = prev->next = newsk;
}
3、static void ieee80211_monitor_rx(struct ieee80211_device *ieee, struct sk_buff *skb, struct ieee80211_rx_stats *rx_stats) { netif_rx(skb); } 4、传统方法处理报文的网络层代码
将接收到的报文放到特定CPU的等待队列中,并退出中断上下文
int netif_rx(struct sk_buff *skb) {
/* if netpoll wants it, pretend we never saw it */
if (netpoll_rx(skb))/* netpoll功能需要处理该报文,退出。该功能用于内核调试 */
return NET_RX_DROP; }
5、处理ieee80211管理帧
static int ieee80211_rx_frame_mgmt(struct ieee80211_device *ieee, struct sk_buff *skb, struct ieee80211_rx_stats *rx_stats, u16 type, u16 stype) {
}
6、帧类型的定义
#define IEEE80211_FTYPE_MGMT 0x0000 // 管理帧
#define IEEE80211_FTYPE_CTL 0x0004 // 控制帧
#define IEEE80211_FTYPE_DATA 0x0008 // 数据帧
7、从跟ap连接的sta中查找相关
sta static struct sta_info* ap_get_sta(struct ap_data *ap, u8 *sta)
{
struct sta_info *s;
s = ap->sta_hash[STA_HASH(sta)];
while (s != NULL && memcmp(s->addr, sta, ETH_ALEN) != 0)
s = s->hnext;
return s;
}