wmaster0接口的简单介绍

        wmaster0是linux无线网络设备的主接口,根据官方说明,从linux2.6.32开始删除了这个接口,所以从linux2.6.32版本开始不会再看到这个接口,我们比较熟悉的是类似于waln0这种接口,因为简单来说,一个wlanx(0,1,2,…)接口就代表一张无线网卡。但是,在linux2.6.31以前,所有的发送操作(还有其他一些操作)都要通过wmaster0来实现,下面以ath5k驱动程序为例简单分析一些发送操作这个过程。

       首先,从ieee80211_register_hw()函数看看wmaster0的注册过程:

1 …
2     mdev = alloc_netdev_mq(sizeof(struct ieee80211_master_priv),
3                    "wmaster%d", ieee80211_master_setup,
4                    hw->queues);
5 …

通过alloc_netdev_mq()函数来注册wmaster0接口,其中ieee80211_master_setup是函数名,其原型如下所示:

 1 …
 2 static const struct net_device_ops ieee80211_master_ops = {
 3     .ndo_start_xmit = ieee80211_master_start_xmit,
 4     .ndo_open = ieee80211_master_open,
 5     .ndo_stop = ieee80211_master_stop,
 6     .ndo_set_multicast_list = ieee80211_master_set_multicast_list,
 7     .ndo_select_queue = ieee80211_select_queue,
 8 };
 9 
10 static void ieee80211_master_setup(struct net_device *mdev)
11 {
12     mdev->type = ARPHRD_IEEE80211;
13     mdev->netdev_ops = &ieee80211_master_ops;
14     mdev->header_ops = &ieee80211_header_ops;
15     mdev->tx_queue_len = 1000;
16     mdev->addr_len = ETH_ALEN;
17 }
18 …

其中ieee80211_master_start_xmit就是实现真正发送操作的函数,从ieee80211_register_hw()函数继续往下看:

1 …
2     if (local->hw.wiphy->interface_modes & BIT(NL80211_IFTYPE_STATION)) {
3         result = ieee80211_if_add(local, "wlan%d", NULL,
4                       NL80211_IFTYPE_STATION, NULL);
5 …

在这里终于注册了wlan0这个接口,下面简单看一下ieee80211_if_add()函数:

1 …
2     ndev = alloc_netdev(sizeof(*sdata) + local->hw.vif_data_size,
3                 name, ieee80211_if_setup);
4 …

再看ieee_if_setup()函数:

 1 …
 2 static const struct net_device_ops ieee80211_dataif_ops = {
 3     .ndo_open        = ieee80211_open,
 4     .ndo_stop        = ieee80211_stop,
 5     .ndo_uninit        = ieee80211_teardown_sdata,
 6     .ndo_start_xmit        = ieee80211_subif_start_xmit,
 7     .ndo_set_multicast_list = ieee80211_set_multicast_list,
 8     .ndo_change_mtu     = ieee80211_change_mtu,
 9     .ndo_set_mac_address     = eth_mac_addr,
10 };
11 …
12 static void ieee80211_if_setup(struct net_device *dev)
13 {
14     ether_setup(dev);
15     dev->netdev_ops = &ieee80211_dataif_ops;
16     dev->wireless_handlers = &ieee80211_iw_handler_def;
17     dev->destructor = free_netdev;
18 }
19 …

其中,dev->netdev_ops = &ieee80211_dataif_ops这是关键,下面看它里面的.ndo_start_xmit = ieee80211_subif_start_xmit成员:

 1 int ieee80211_subif_start_xmit(struct sk_buff *skb,
 2                    struct net_device *dev)
 3 {
 4 …
 5     skb->iif = dev->ifindex;
 6     skb->dev = local->mdev;
 7     dev->stats.tx_packets++;
 8     dev->stats.tx_bytes += skb->len;
 9 …
10     dev_queue_xmit(skb);
11 …
12 }

第6行,medv就是wmaster0接口,第10行,调用了dev_queue_xmit()函数,这个函数是网络层进入数据链路层的关键函数:

1 int dev_queue_xmit(struct sk_buff *skb)
2 {
3 struct net_device *dev = skb->dev;
4 …
5 txq = dev_pick_tx(dev, skb);
6 …
7 }

第3行,skb->dev就是wmaster0接口,以后有关网络设备的操作都是用它了,第5行,通过dev_pick_tx()函数选出当前socket所需要的TOS(Type Of Service)队列,想了解TOS和MAC层中关于QoS的可以看看这个函数,这里不分析。

       到这里可以看出,发送数据时,上层使用wlan0接口,到了数据链路层以下开始使用wmaster0这个接口实现发送操作。

原文地址:https://www.cnblogs.com/lknlfy/p/2844194.html