linux下wlan驅動代碼學習-join過程

@文章中的內容不必定正確,只表明了idiotshi目前的認識水平,歡迎指正!node

首先,提出一個問題:ni是什麼?vap是什麼?ni與vap之間是什麼關係?數據結構

ni是一個數據結構,對於STA來講,ni存儲了STA與某一個AP交互時用到的信息(這些信息對於不一樣的AP是不同的,須要單獨維護),表示的是對方的信息。函數

而vap存儲的是STA本身的信息。ui

就從ieee80211_assoc_state_join_entry函數開始提及吧。spa

 1 /*
 2  *JOIN 
 3  */
 4 static void ieee80211_assoc_state_join_entry(void *ctx) 
 5 {
 6     wlan_assoc_sm_t sm = (wlan_assoc_sm_t) ctx;
 7     sm->is_join=1;
 8     //sm->vap_handle,指向vap的指針
 9     //sm->scan_entry,當前鏈接AP的scan_scentry?
10     //sm->max_tsfsync_time,join定時器超時時間,在發送probe_req的時候設置該定時器,當定時器超時以前沒有收到probe_resp則出錯
11     if (wlan_mlme_join_infra(sm->vap_handle, sm->scan_entry, sm->max_tsfsync_time) != 0 ) {
12         IEEE80211_DPRINTF(sm->vap_handle,IEEE80211_MSG_STATE,"%s: join_infra failed \n",__func__);
13         ieee80211_sm_dispatch(sm->hsm_handle,IEEE80211_ASSOC_EVENT_JOIN_FAIL,0,NULL);
14         return;
15     }
16 }

wlan_mlme_join_infra函數中調用ieee80211_sta_join函數,該函數主要做用是對ni進行操做:釋放舊node,創建新的node並對新的node賦值。並藉着調用ieee80211_sta_join_bss(ni);函數中將vap->iv_bss替換成新創建的ni,而且若是原來的vap->iv_bss != NULL ,須要作一次釋放。線程

1     ...
2     error = ieee80211_sta_join(vap, scan_entry);
3     if (error) {
4         IEEE80211_DPRINTF(vap, IEEE80211_MSG_MLME, "%s: Error %d (0x%08X) in ieee80211_sta_join\n", 
5             __func__, error, error);
6         goto err;
7     }
8     ...

當ieee80211_sta_join函數返回之後,wlan_mlme_join_infra就得到了ni信息,下面繼續調用ieee80211_mlme_join_infra_continue函數,在該函數中調用ieee80211_send_probereq發送probe request,而且啓動一個定時器等待probe resp。函數執行完畢後,一步步返回退出,直到ieee80211_assoc_state_join_entry返回。debug

那ieee80211_assoc_state_join_entry是如何被調用的?指針

對於join過程而言,該函數經過assoc狀態機來維護,assoc狀態機在INIT狀態下收到IEEE80211_ASSOC_EVENT_REASSOC_REQUEST事件或者IEEE80211_ASSOC_EVENT_CONNECT_REQUEST事件時會調用ieee80211_sm_transition_to(sm->hsm_handle,IEEE80211_ASSOC_STATE_JOIN);rest

 

2.狀態機是神馬?code

我的理解,狀態機是一個由定時器維護的數據結構的」組合「。猜想應該能夠用線程來替代。

驅動程序在建立VAP的時候(osif_vap_setup)建立了兩個狀態機:connection狀態機和assoc狀態機。connection狀態機的數據結構以下:

 1 struct _wlan_connection_sm {
 2 
 3     osdev_t                     os_handle;
 4     wlan_if_t                   vap_handle;
 5     ieee80211_hsm_t             hsm_handle; 
 6     wlan_assoc_sm_t             assoc_sm_handle; 
 7     wlan_scan_entry_t           cur_scan_entry; /* current bss scan entry */
 8     u_int8_t                    cur_bssid[IEEE80211_ADDR_LEN];
 9     wlan_connection_sm_event_handler sm_evhandler;
10     u_int8_t                    bgscan_rssi_thresh;
11     u_int8_t                    bgscan_rssi_change;
12     u_int8_t                    bgscan_rssi_thresh_forced_scan;  /* rssi below which it scan is a forces scan */
13     u_int8_t                    roam_threshold;
14     u_int32_t                   bgscan_period; /* in seconds */
15     u_int32_t                   scan_cache_valid_time; /* in msec */
16     u_int32_t                   roam_check_period; /* in msec */
17     u_int32_t                   connect_timeout;   /* connection attempt timeout in msec */
18     u_int32_t                   reconnect_timeout; /* after losing connection max re connection attempt timeout */
19     u_int32_t                   connection_lost_timeout; /* after losing connection time to wait before sending notification up */
20     u_int32_t                   bad_ap_timeout; /* time out before trying out the AP after connection failure */
21     u_int32_t                   bgscan_min_dwell_time; /* minimum dwell time for bg scan */
22     u_int32_t                   bgscan_max_dwell_time; /* maximum dwell time for bg scan */
23     u_int32_t                   bgscan_min_rest_time;  /* minimum rest time for bg scan */
24     u_int32_t                   bgscan_max_rest_time;  /* maximum rest time for bg scan */
25     wlan_connection_sm_bgscan_policy bgscan_policy;
26     os_if_t                     osif;
27     os_timer_t                  sm_timer;      /* generic event timer */
28     os_timer_t                  sm_roam_check_timer; /* roam check timer */
29     u_int8_t                    timeout_event;      /* event to dispacth when timer expires */
30     u_int32_t                   is_running:1,       /* SM is running */
31                                 is_stop_requested:1,      /* SM is being stopped */
32                                 sync_stop_requested:1,    /* SM is being stopped synchronously */
33                                 is_aplist_built:1,  /* ap list has been built */
34                                 is_reconnecting:1, /* connection lost(bmiss, deauth), reconnecting. also called hard roam */
35                                 lost_notification_sent:1,
36                                 is_connected:1;  /* lost connection with an ap reconnecting */
37     IEEE80211_SCAN_REQUESTOR    scan_requestor;  /* requestor id assigned by scan module */
38     IEEE80211_SCAN_ID           scan_id;         /* id assigned by scan scheduler */
39     u_int32_t                   candidate_aplist_count;
40     u_int32_t                   candidate_aplist_index;
41     u_int32_t                   connection_req_time;  /* os time stamp at which connection request is made  */
42     u_int32_t                   connection_lost_time; /* os time stamp at which connection is lost  */
43     u_int32_t                   last_scan_time;       /* os time stamp when last scan was complete*/
44     u_int32_t                   scan_channels[IEEE80211_CHAN_MAX];
45     u_int16_t                   num_channels;
46     u_int8_t                    last_scan_rssi;       /* last bss rssi at which scan is done  */
47     u_int8_t          scan_fail_count;      /* how mainy times scan start has failed  */
48     wlan_assoc_sm_event         assoc_event; /* last assoc event */
49     wlan_connection_sm_event_disconnect_reason disconnect_reason; /* reason for connection down */
50 }

assoc狀態機的數據結構以下:

 1 typedef struct _ieee80211_hsm {
 2     u_int8_t                      name[IEEE80211_HSM_MAX_NAME];  /* name of the state machine */
 3     u_int8_t                      cur_state;
 4     u_int8_t                      next_state; /* is different from cur_state in the middle of ieee80211_transition_to */
 5     u_int8_t                      event_state; /* holds the current state to which  the event is delivered to */
 6     u_int8_t                      num_states;
 7     u_int8_t                      last_event;  /* last event */
 8     osdev_t                       oshandle;
 9     const ieee80211_state_info    *state_info;
10     void                          *ctx;                    /* context specific to the caller */
11     u_int32_t                     in_state_transition : 1; /* in state transition */
12     os_mesg_queue_t               mesg_q;
13     const char                    **event_names;   /* for debug printing */
14     u_int32_t                     num_event_names; /* for debug printing */
15 #if ENABLE_HSM_HISTORY
16     hsm_history_t                 history;
17 #endif    /* ENABLE_HISTORY */
18 
19     void (*ieee80211_hsm_debug_print) (void *ctx, const char *fmt,...);     
20 } ieee80211_hsm; 

而真正維護狀態機狀態信息的數據結構以下:

 1 typedef struct _ieee80211_hsm {
 2     u_int8_t                      name[IEEE80211_HSM_MAX_NAME];  /* name of the state machine */
 3     u_int8_t                      cur_state;
 4     u_int8_t                      next_state; /* is different from cur_state in the middle of ieee80211_transition_to */
 5     u_int8_t                      event_state; /* holds the current state to which  the event is delivered to */
 6     u_int8_t                      num_states;
 7     u_int8_t                      last_event;  /* last event */
 8     osdev_t                       oshandle;
 9     const ieee80211_state_info    *state_info;
10     void                          *ctx;                    /* context specific to the caller */
11     u_int32_t                     in_state_transition : 1; /* in state transition */
12     os_mesg_queue_t               mesg_q;
13     const char                    **event_names;   /* for debug printing */
14     u_int32_t                     num_event_names; /* for debug printing */
15 #if ENABLE_HSM_HISTORY
16     hsm_history_t                 history;
17 #endif    /* ENABLE_HISTORY */
18 
19     void (*ieee80211_hsm_debug_print) (void *ctx, const char *fmt,...);     
20 } ieee80211_hsm; 

上述數據結構中各字段的意義後面再分析,首先繼續來看流程。 sm是wlan_connection_sm_create函數的局部變量(指針),在該函數中得到了分配的內核空間空間後調用    

1 OS_INIT_TIMER(oshandle, &(sm->sm_timer),connection_sm_timer_handler, (void *)sm);
2 
3 OS_INIT_TIMER(oshandle, &(sm->sm_roam_check_timer),connection_sm_roam_check_timer_handler, (void *)sm); 

註冊了兩個定時器。sm->sm_timer是assoc的各狀態超時時間,sm->sm_roam_check_timer是爲了切換設置的,定時器超時後驅動程序回去從新計算當前掃描到的AP排名, 以決定是否須要掃描(可是此時定時器並無開啓)。

調用  

1 rc = wlan_scan_register_event_handler(sm->vap_handle,ieee80211_connection_sm_scan_evhandler, sm); 

將ieee80211_connection_sm_scan_evhandler函數賦給ss->ss_event_handlers//(ss = vaphandle->iv_ic->ic_scanner)。 函數ieee80211_connection_sm_scan_evhandler的功能是開始/結束SCAN。

目前只猜想osif_ioctl_create_vap函數接收應用層ioctl命令後調用osif_vap_setup函數完成了上述狀態機的創建。可是創建起這一套狀態機之後,是誰在什麼地方出發了該這些狀態機的運轉呢??

相關文章
相關標籤/搜索