@文章中的内容不必定正确,只表明了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函数完成了上述状态机的创建。可是创建起这一套状态机之后,是谁在什么地方出发了该这些状态机的运转呢??