ieee80211_rx_h_mgmt的处理

上一篇说道,ieee80211_invoke_rx_handlers中CALL_RXH(ieee80211_rx_h_mgmt)用于管理帧的处理,这篇文章将对ieee80211_rx_h_mgmt函数进行简单分析。

ieee80211_queue_work(&rx->local->hw, &sdata->work);sdata->work放入处理队里,而sdata->work被初始化为ieee80211_iface_work函数。继续跟踪ieee80211_iface_work下面一切操作的前提是接口类型是station,如果是AP,会在前面的用户空间处理函数中上交给上层,如hostapd。

①sta = sta_info_get_bss(sdata, mgmt->sa)这个函数根据mgmt->sa,也就是mgmt frame的源地址,进行哈希查表找到对应的station信息,然后判断sta对应的sdata(sdata是一个ieee80211_sub_if_data结构体)是否是这个的sdata,sta对应的bss是不是该sdata对应的bss。

②ieee80211_sta_rx_queued_mgmt(sdata, skb)。粘一段代码。

	switch (fc & IEEE80211_FCTL_STYPE) {
	case IEEE80211_STYPE_BEACON:
		ieee80211_rx_mgmt_beacon(sdata, mgmt, skb->len, rx_status);
		break;
	case IEEE80211_STYPE_PROBE_RESP:
		ieee80211_rx_mgmt_probe_resp(sdata, skb);
		break;
	case IEEE80211_STYPE_AUTH:
		ieee80211_rx_mgmt_auth(sdata, mgmt, skb->len);
		break;
	case IEEE80211_STYPE_DEAUTH:
		ieee80211_rx_mgmt_deauth(sdata, mgmt, skb->len);
		break;
	case IEEE80211_STYPE_DISASSOC:
		ieee80211_rx_mgmt_disassoc(sdata, mgmt, skb->len);
		break;
首先说ieee80211_rx_mgmt_beacon.

①ieee80211_rx_bss_info,更新功率及一些统计信息;

②更新当前AP的RSSI统计值;RSSI超过或低于某一门限时通过回调函数通知底层驱动;

③有一些ieee80211_send_nullfunc操作,好像和powersave模式有关,但是没有读懂;

④如果HT模式,带宽改变会引起disassociate;

⑤ieee80211_bss_info_change_notify(sdata, changed)通知底层驱动改变相关参数。


接着说ieee80211_rx_mgmt_auth。

①如果认证失败,就会通过cfg80211_rx_mlme_mgmt——>cfg80211_process_auth——>nl80211_send_rx_auth交给上层处理;

②cfg80211_process_auth——>如果status为加密算法选择错误,cfg80211_sme_rx_auth自动选择加密方式,此时的状态为关联后\正在认证,然后schedule_work(&rdev->conn_work)进行cfg80211_conn_work工作。else (status_code != WLAN_STATUS_SUCCESS) __cfg80211_connect_result,应该是结果上传给上层,但是不能确定;否则status转为正在关联状态。cfg80211_conn_do_work简单叙述如下:

cfg80211_conn_do_work(wdev)

	switch (wdev->conn->state) {
	case CFG80211_CONN_SCANNING:
		/* didn't find it during scan ... */
		return -ENOENT;
	case CFG80211_CONN_SCAN_AGAIN:
		return cfg80211_conn_scan(wdev);
	case CFG80211_CONN_AUTHENTICATE_NEXT:
		BUG_ON(!rdev->ops->auth);
		wdev->conn->state = CFG80211_CONN_AUTHENTICATING;
		return cfg80211_mlme_auth(rdev, wdev->netdev,
					  params->channel, params->auth_type,
					  params->bssid,
					  params->ssid, params->ssid_len,
					  NULL, 0,
					  params->key, params->key_len,
					  params->key_idx, NULL, 0);
	case CFG80211_CONN_AUTH_FAILED:
		return -ENOTCONN;
	case CFG80211_CONN_ASSOCIATE_NEXT:
		BUG_ON(!rdev->ops->assoc);
		wdev->conn->state = CFG80211_CONN_ASSOCIATING;
		if (wdev->conn->prev_bssid_valid)
			req.prev_bssid = wdev->conn->prev_bssid;
		req.ie = params->ie;
		req.ie_len = params->ie_len;
		req.use_mfp = params->mfp != NL80211_MFP_NO;
		req.crypto = params->crypto;
		req.flags = params->flags;
		req.ht_capa = params->ht_capa;
		req.ht_capa_mask = params->ht_capa_mask;
		req.vht_capa = params->vht_capa;
		req.vht_capa_mask = params->vht_capa_mask;

		err = cfg80211_mlme_assoc(rdev, wdev->netdev, params->channel,
					  params->bssid, params->ssid,
					  params->ssid_len, &req);
		if (err)
			cfg80211_mlme_deauth(rdev, wdev->netdev, params->bssid,
					     NULL, 0,
					     WLAN_REASON_DEAUTH_LEAVING,
					     false);
		return err;
	case CFG80211_CONN_ASSOC_FAILED:
		cfg80211_mlme_deauth(rdev, wdev->netdev, params->bssid,
				     NULL, 0,
				     WLAN_REASON_DEAUTH_LEAVING, false);
		return -ENOTCONN;
	case CFG80211_CONN_DEAUTH:
		cfg80211_mlme_deauth(rdev, wdev->netdev, params->bssid,
				     NULL, 0,
				     WLAN_REASON_DEAUTH_LEAVING, false);
		/* free directly, disconnected event already sent */
		cfg80211_sme_free(wdev);
		return 0;
	default:
		return 0;
	}
}
cfg80211_mlme_xx会调用到ieee80211_mgd_xx都是用于配置相应结构体的成员变量。



你可能感兴趣的:(wireless)