Monday, October 10, 2011

madwifi 设备获取过程

madwifi驱动里面有两套net_device设备,一套是if_ath­_xx.c程序使用的,名字为“wifi0”,另一套是ieee802.11_xx程序使用的,为ath0

ath_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
\if_ath_pci.c(179):   dev = alloc_netdev(sizeof(struct ath_pci_softc), “wifi%d”, ether_setup);

int ath_attach(u_int16_t devid, struct net_device *dev)
\if_ath.c(897): error = ieee80211_create_vap(ic, “ath%d”, dev, autocreatemode, IEEE80211_CLONE_BSSID);

相应的,两个设备都定义了自己的发送函数

这是ath0的发送函数,
int ieee80211_vap_setup(struct ieee80211com *ic, struct net_device *dev,
const char *name, int unit, int opmode, int flags)
\ieee80211.c(395):    dev->hard_start_xmit = ieee80211_hardstart;

这是wifi的发送函数,
  int ath_attach(u_int16_t devid, struct net_device *dev)
  if_ath.c(670):   dev->hard_start_xmit = ath_hardstart;

ieee80211_hardstart函数调用ieee80211_parent_queue_xmitieee80211_parent_queue_xmit 继续调用(void) dev_queue_xmit(skb)dev_queue_xmit函数是在linux内核中定义的

\net\core\dev.c(994):int dev_queue_xmit(struct sk_buff *skb),该函数会调用 dev->hard_start_xmit,这个函数估计就是ath_hardstart。

ath_hardstart调用ath_tx_start函数,ath_tx_start继续调用ath_hal_filltxdesc等与硬件相关的函数,完成最终的发送任务。

这样就出来一个问题了,由谁来调用ieee80211_hardstart?  经过查找,两个hard_start_xmit函数都没有在madfiwi程序中调用,看来都是在linux内核中调用的。也就说,madwifi同时注册了两个网络设备,一个是ath0,一个是wifi0,应用程序发送数据的流程是这样的:应用程序->内核->ath0设备->内核->wifi0设备。

要搞清楚为什么会这样,就必须了解madwifi中的VAP(虚拟AP的概念),可以在一个实际的无线设备上创建多个逻辑设备,要使用设备,必须使用下面的命令创建ath设备
    wlanconfig athX create wlandev wifiX wlanmode
例如:
    wlanconfig ath0 create wlandev wifi0 wlanmode ap
    wlanconfig ath1 create wlandev wifi0 wlanmode ap
    wlanconfig ath2 create wlandev wifi0 wlanmode ap
    iwconfig ath0 essid “lmn”
    iwconfig ath1 essid “XYZ”
    iwconfig ath2 essid “abc”

因此,可以认为ath是逻辑设备,wifi是物理设备。
(上面部分参考了madwifi.pdf文档,一个ppt,上面对madwifi进行了粗略的介绍,包括存在的问题)

The OpenHAL ported to MADWiFi at http://pdos.csail.mit.edu/~jbicket/openhal/  因此,我们在发送数据的时候,已经指明了使用ath0虚拟网卡,自然就会调用ieee80211_hardstart,问题就变成了两次调用内核操作是如何实现的?  还是先看看几个结构体是如何关联的,
ath_attach(u_int16_t devid, struct net_device *dev)
{
    struct ath_softc *sc = dev->priv;  由wifi设备获得sc
    struct ieee80211com *ic = &sc->sc_ic; 由wifi设备获得com设备ic,
    ……….
    ic->ic_dev = dev;          ic的设备指向wifi
    ic->ic_mgtstart = ath_mgtstart;
    ic->ic_init = ath_init;
    ic->ic_reset = ath_reset;
    ic->ic_newassoc = ath_newassoc;
    ic->ic_updateslot = ath_updateslot;
    ………
    dev->open = ath_init;
    dev->stop = ath_stop;
    dev->hard_start_xmit = ath_hardstart;
    dev->tx_timeout = ath_tx_timeout;
    ieee80211_ifattach(ic); 加载ieee802设备

    创建VAP,得到ath0设备。
    error = ieee80211_create_vap(ic, “ath%d”, dev, autocreatemode, IEEE80211_CLONE_BSSID);


No comments:

Post a Comment