wifi底層學習之路:四,iw指令剖析

目錄

一,iw應用層

二,cfg80211層

三,mac80211層

四,無線驅動層


本章以指令:iw dev wlan0 scan爲例,帶你走進iw層,cfg80211層,mac80211cfg,驅動層細節流程。

一,iw應用層

1,其實是兩條命令
分析scan.c文件,跟蹤TOPLEVEL(scan, "[-u] xx", 0, 0, CIB_NETDEV, handle_scan_combined, "xxx");
從handle_scan_combined()函數可知,最終運行下面兩條指令。

iw dev wlan0 scan trigger 
對應的netlink消息:NL80211_CMD_TRIGGER_SCAN

iw dev wlan0 scan dump 
對應的netlink消息:NL80211_CMD_GET_SCAN

二,cfg80211層

1,netlink接收到 NL80211_CMD_TRIGGER_SCAN,執行下面函數

static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info)
{
	//調用mac80211註冊的cfg80211_ops對應的函數.scan
	rdev_scan(rdev, request);
	-->ret = rdev->ops->scan(&rdev->wiphy, request);  //mac80211實現
	//構造netlink消息,回覆給iw
	nl80211_send_scan_start(rdev, wdev);
	-->nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
	-->nl80211_prep_scan_msg(msg, rdev, wdev, 0, 0, 0,NL80211_CMD_TRIGGER_SCAN) < 0)
	-->nl80211hdr_put(msg, portid, seq, flags, cmd);
	-->nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx);
	-->nl80211_add_scan_req(msg, rdev);
	-->genlmsg_end(msg, hdr);
	--genlmsg_multicast_netns()
}

2,netlink接收到 NL80211_CMD_GET_SCAN,執行下面函數

static int nl80211_dump_scan(struct sk_buff *skb, struct netlink_callback *cb)
{
	nl80211_prepare_wdev_dump(skb, cb, &rdev, &wdev);
	cfg80211_bss_expire(rdev);
	list_for_each_entry(scan, &rdev->bss_list, list) {
		nl80211_send_bss(skb, cb,cb->nlh->nlmsg_seq, NLM_F_MULTI,rdev, wdev, scan); //從bss段中取出數據
	}
}

三,mac80211層

1,從cfg80211層中,可知調用的是.scan函數

const struct cfg80211_ops mac80211_config_ops = {
    .add_virtual_intf = ieee80211_add_iface,
    .del_virtual_intf = ieee80211_del_iface,
    ....
    .scan = ieee80211_scan,
    .abort_scan = ieee80211_abort_scan,
    ....
};

static int ieee80211_scan(struct wiphy *wiphy,struct cfg80211_scan_request *req)
{
    ieee80211_request_scan(sdata, req);
	-->__ieee80211_start_scan(sdata, req);
	
	//軟件掃描方式
	--->ieee80211_start_sw_scan(local, sdata);  
		---->drv_sw_scan_start(local, sdata, local->scan_addr);
		------->local->ops->sw_scan_start(&local->hw, &sdata->vif, mac_addr); //ath9k實現
	
    //延時調用ieee80211_scan_work,調用前需要初始化
    ---->ieee80211_queue_delayed_work(&local->hw,&local->scan_work, 0);	

    //local->scan_work()的實現如下
    local->scan_work
    -->ieee80211_scan_work()
    --->__ieee80211_scan_completed()
    ---->drv_sw_scan_complete()
    ----->.sw_scan_complete//ath9k實現
}

2,延時調用ieee80211_scan_work()的初始化過程在ieee80211_alloc_hw_nm()函數

struct ieee80211_hw *ieee80211_alloc_hw_nm(size_t priv_data_len,
					   const struct ieee80211_ops *ops,
					   const char *requested_name)
{
    INIT_DELAYED_WORK(&local->scan_work, ieee80211_scan_work);	
    // 這裏使用的是INIT_DELAYED_WORK()那麼之後
    // 我們就會調用schedule_delayed_work(),這兩是一對
    // 表示經過一段延時然後在執行某個函數。
}
EXPORT_SYMBOL(ieee80211_alloc_hw_nm);

//以下是ieee80211_scan_work()的實現細節
void ieee80211_scan_work(struct work_struct *work)
{
	__ieee80211_scan_completed(&local->hw, aborted);
}

static void __ieee80211_scan_completed(struct ieee80211_hw *hw, bool aborted)
{
	drv_sw_scan_complete(local, scan_sdata);
}

static inline void drv_sw_scan_complete(struct ieee80211_local *local,
					struct ieee80211_sub_if_data *sdata)
{
	local->ops->sw_scan_complete(&local->hw, &sdata->vif);
}

void ieee80211_scan_work(struct work_struct *work)
{
	__ieee80211_scan_completed(&local->hw, aborted);
}

static void __ieee80211_scan_completed(struct ieee80211_hw *hw, bool aborted)
{
	drv_sw_scan_complete(local, scan_sdata);
}

static inline void drv_sw_scan_complete(struct ieee80211_local *local,
					struct ieee80211_sub_if_data *sdata)
{
	local->ops->sw_scan_complete(&local->hw, &sdata->vif);
}

四,無線驅動層

1,從mac80211層可知,調用的是.sw_scan_start()和.sw_scan_complete()函數

struct ieee80211_ops ath9k_htc_ops = {
	.tx                 = ath9k_htc_tx,
	.start              = ath9k_htc_start,
	.stop               = ath9k_htc_stop,
	.add_interface      = ath9k_htc_add_interface,
	....
	.sw_scan_start      = ath9k_htc_sw_scan_start,
	.sw_scan_complete   = ath9k_htc_sw_scan_complete,
	....
};

歡迎訂閱公衆號【從零開始學無線】,一起學習交流!

                                                                

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章