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这个接口实现发送操作。