📄 wlc.c
字号:
/* if there are more channels to scan ... */ if (next_channel != -1) { /* ... continue scanning */ wlc->scan.channel_idx++; channel = (uint)next_channel; wlc->scan.pass = WLC_SCAN_CHANNEL_PREP; } /* ... otherwise the scan is done, * scan.pass > passes and we fall through to the end of this function */ } /* wlc->scan.pass > passes */ if (wlc->scan.pass == WLC_SCAN_CHANNEL_PREP) { /* do off-home-channel setup if we are associated and on the home channel */ if (wlc->pub.associated && wlc->band->pi->radio_channel == wlc->scan.channel_return) { /* announce PS mode to the AP if we are not already in PS mode */ if (wlc->pub.BSS && WLC_BSS_CONNECTED(wlc) && !wlc->PMenabled) { /* set our PS callback flag so that wlc_scantimer is called * when the PM State Null Data packet completes */ wlc->scan.state |= SCAN_STATE_PSPEND; wlc_set_pmstate(wlc, TRUE); /* clear our callback flag if PMpending is false, indicating * that no PM State Null Data packet was sent by * wlc_set_pmstate() */ if (!wlc->PMpending) wlc->scan.state &= ~SCAN_STATE_PSPEND; } /* block any PSPoll operations since we are just holding off AP * traffic */ if (wlc->pub.BSS && wlc->PMenabled) { wlc->PMblocked = TRUE; } /* Must leave IBSS first before starting a scan */ if (!wlc->pub.BSS) { wlc_ibss_suspend(wlc); } /* block any tx traffic */ if (!wlc_tx_suspended(wlc)) { if ((wlc->scan.state & SCAN_STATE_PSPEND) == 0) { /* suspend the data fifos to avoid sending data packets * during scan */ wlc_tx_suspend(wlc); wlc->scan.state |= SCAN_STATE_WSUSPEND; } else { /* wlc_scantimer() will do the wlc_tx_suspend() call * when the PS announce completes */ wlc->scan.state |= SCAN_STATE_SUSPEND_REQ; } } /* if there is any prep work, return here and let wlc_scantimer be called * back */ if (wlc->scan.state & (SCAN_STATE_PSPEND | SCAN_STATE_WSUSPEND)) return; } wlc->scan.pass = 1; } /* scan the channel */ if (wlc->scan.pass >= 1 && wlc->scan.pass <= passes) { /* skip CFP update if not in home channel */ if (channel != wlc->scan.channel_return) wlc_mhf(wlc, MHF_SKIP_CFP_UPDATE, MHF_SKIP_CFP_UPDATE, TRUE); if (channel != wlc->band->pi->radio_channel) { wlc_suspend_mac_and_wait(wlc); wlc_set_channel(wlc, channel); wlc_enable_mac(wlc); } /* * disable txq processing to avoid using wrong rateset and * posting packets to wrong ring during scan on "other" band */ if (wlc->pub.associated && !VALID_CHANNEL(wlc, wlc->scan.channel_return)) wlc->block_datafifo |= DATA_BLOCK_SCAN; else wlc->block_datafifo &= ~DATA_BLOCK_SCAN; if ((wlc->scan.state & SCAN_STATE_PASSIVE) == 0 && !QUIET_CHANNEL(wlc, channel)) { /* Only send probes if in active scan mode, and this is not a quiet * channel. */ wlc_sendprobe(wlc, wlc->scan.ssid, wlc->scan.ssid_len); } else { /* Otherwise, make sure we are promisc for beacons and probes for a passive * scan */ wlc->bcnmisc_scan = TRUE; wlc_mac_bcn_promisc(wlc); } /* Wait for responses to come back */ if ((wlc->scan.state & SCAN_STATE_PASSIVE) || QUIET_CHANNEL(wlc, channel)) { uint32 dummy_tsf_h; /* use passive time for a passive scan or for a quiet channel in a active * scan */ wl_add_timer(wlc->wl, wlc->scan.timer, wlc->scan.passive_time, 0); /* record the start time in case we switch to an active scan in * wlc_scan_radar_clear() */ wlc_read_tsf(wlc, &wlc->scan.start_tsf, &dummy_tsf_h); } else { /* for an active scan on a non-quiet channel, use channel active dwell time * divided by the number of probes we need to send */ wl_add_timer(wlc->wl, wlc->scan.timer, wlc->scan.active_time/wlc->scan.nprobes, 0); } /* wlc_scantimer called back when wlc->scan.timer fires */ /* record phy noise for the scan channel */ wlc->phy_noise_list[channel] = wlc_compute_phy_noise(wlc->band->pi); return; } /* * wraps up scan process. */ WL_INFORM(("wl%d: %s: %s scan done, %d total responses for SSID \"%s\"\n", wlc->pub.unit, __FUNCTION__, ((wlc->scan.state & SCAN_STATE_PASSIVE) ? "Passive" : "Active"), wlc->scan_results.count, ssidbuf)); wlc->scan.channel_idx = -1; /* Return to the original core and change the radio channel to the return channel */ wlc_suspend_mac_and_wait(wlc); wlc_set_channel(wlc, wlc->scan.channel_return); if (!wlc->pub.BSS && wlc->pub.associated) wlc_ibss_resume(wlc); /* Restore promisc behavior for beacons and probes */ wlc->bcnmisc_scan = FALSE; wlc_mac_bcn_promisc(wlc); wlc_enable_mac(wlc); /* Clear the tssi values */ wlc_clear_tssi(wlc->band->pi); /* un-block PSPoll operations and restore PS state */ if (wlc->PMblocked) { wlc->PMblocked = FALSE; /* come out of PS mode if appropriate */ if (wlc->PM != PM_MAX || wlc->WME_PM_blocked) wlc_set_pmstate(wlc, FALSE); } /* un-suspend the DATA fifo now that we are done with the scan */ wlc_tx_resume(wlc); /* re-enable txq processing now that we are done with the scan */ wlc->block_datafifo &= ~DATA_BLOCK_SCAN; /* enable CFP update */ wlc_mhf(wlc, MHF_SKIP_CFP_UPDATE, 0, TRUE); /* allow core to sleep again (no more solicited probe responses) */ wlc_set_ps_ctrl(wlc); if (wlc->scan.cb) { cb_fn_t cb = wlc->scan.cb; void *cb_arg = wlc->scan.cb_arg; wlc->scan.cb = NULL; wlc->scan.cb_arg = NULL; (cb)(cb_arg); if (wlc->assoc_state == AS_IDLE) wlc_mac_event(wlc, WLC_E_SCAN_COMPLETE, NULL, WLC_E_STATUS_SUCCESS, 0, 0, 0, 0); } wlc_bss_list_free(wlc, &wlc->scan_results); WL_ASSOC(("SCAN: wlc_scantimer done\n"));}static voidwlc_scan_radar_clear(wlc_info_t *wlc){ uint32 cur_l, cur_h; uint32 elapsed_time, remaining_time, active_time; /* if we are not on a radar quiet channel, * or a passive scan was requested, * or we already processed the radar clear signal, * then do nothing */ if (!QUIET_CHANNEL(wlc, wlc->band->pi->radio_channel) || (wlc->scan.state & (SCAN_STATE_PASSIVE | SCAN_STATE_RADAR_CLEAR))) return; /* if we are not in the channel scan portion of the scan, do nothing */ if (wlc->scan.pass != 1) return; /* if there is not enough time remaining for a probe, do nothing */ wlc_read_tsf(wlc, &cur_l, &cur_h); elapsed_time = (cur_l - wlc->scan.start_tsf) / 1000; if (elapsed_time > wlc->scan.passive_time) remaining_time = 0; else remaining_time = wlc->scan.passive_time - elapsed_time; if (remaining_time < WLC_SCAN_MIN_PROBE_TIME) return; /* everything is ok to switch to an active scan */ wlc->scan.state |= SCAN_STATE_RADAR_CLEAR; active_time = MIN(remaining_time, wlc->scan.active_time); wl_del_timer(wlc->wl, wlc->scan.timer); wl_add_timer(wlc->wl, wlc->scan.timer, active_time, 0); wlc_mute(wlc, OFF); wlc_sendprobe(wlc, wlc->scan.ssid, wlc->scan.ssid_len); WL_REGULATORY(("wl%d: wlc_scan_radar_clear: rcvd beacon on radar channel %d, converting to" " active scan, %d ms left\n", wlc->pub.unit, wlc->band->pi->radio_channel, active_time));}voidwlc_scan_default_channels(wlc_info_t *wlc, uint8 *channel_list, int *pchannel_num){ uint channel_start; int num; if (wlc->pub.associated) { /* start the scan on the current BSS channel */ channel_start = wlc->pub.current_bss.channel; } else if (SCAN_IN_PROGRESS(wlc)) { /* interrupting a scan, so use the original return channel */ channel_start = wlc->scan.channel_return; } else { /* not associated, so just start on the current channel */ channel_start = wlc->band->pi->radio_channel; } ASSERT(channel_start < MAXCHANNEL); /* enumerate all the active (non-quiet) channels first */ wlc_scan_channels(wlc, channel_list, &num, MAXCHANNEL, channel_start, CHAN_TYPE_CHATTY); *pchannel_num = num; /* enumerate all the passive (quiet) channels second */ wlc_scan_channels(wlc, (channel_list + num), &num, (MAXCHANNEL - num), channel_start, CHAN_TYPE_QUIET); *pchannel_num += num;}static voidwlc_scan_channels(wlc_info_t *wlc, uint8 *channel_list, int *pchannel_num, int channel_max, uint channel_start, int channel_type){ uint bandunit; uint channel; int num = 0; uint i; ASSERT(channel_start < MAXCHANNEL); bandunit = CHANNEL_BANDUNIT(wlc, channel_start); for (i = 0; i < NBANDS(wlc); i++) { /* find all valid channels for this locale in bandunit's band */ channel = channel_start; while (num < channel_max) { if (VALID_CHANNEL_IN_BAND(wlc, bandunit, channel) && ((channel_type == CHAN_TYPE_CHATTY && !QUIET_CHANNEL(wlc, channel)) || (channel_type == CHAN_TYPE_QUIET && QUIET_CHANNEL(wlc, channel)))) channel_list[num++] = (uint8)channel; channel = (channel + 1) % MAXCHANNEL; if (channel == channel_start) break; } /* only find channels for one band */ if (!IS_MBAND_UNLOCKED(wlc)) break; /* prepare to find the other band's channels */ bandunit = ((bandunit == 1) ? 0 : 1); channel_start = 0; } *pchannel_num = num;}voidwlc_set_ssid(wlc_info_t *wlc, uchar SSID[], int len){ wlc_bsscfg_t *cfg; ASSERT(wlc->pub.up); cfg = &wlc->cfg; ASSERT(BSSCFG_STA(cfg)); if (len == 0) WL_ASSOC(("SCAN: wlc_set_ssid, Setting SSID to NULL...\n")); else WL_ASSOC(("SCAN: wlc_set_ssid, Setting SSID to \"%s\"...\n", (wlc_format_ssid(ssidbuf, SSID, len), ssidbuf))); /* abort any association state machine in process */ if ((wlc->assoc_state != AS_IDLE) && (wlc->assoc_state != AS_WAIT_DISASSOC)) wlc_assoc_abort(wlc); /* adopt the default BSS params as the target */ wlc->target_bss = wlc->default_bss; /* update the target_bss and default config with the ssid */ wlc->target_bss.SSID_len = (uint8) len; wlc->cfg.SSID_len = (uint8)len; if (len > 0) { bcopy(SSID, (char*)wlc->target_bss.SSID, len); bcopy(SSID, (char*)wlc->cfg.SSID, len); } /* this is STA only, no aps_associated issues */ wlc->cfg.enable = TRUE; wlc->cfg.up = TRUE;#ifdef BCMWPA2 /* clear PMKID cache */ if (cfg->WPA_auth == WPA2_AUTH_UNSPECIFIED) { WL_WSEC(("wl%d: clearing PMKID cache and candidate list\n", wlc->pub.unit)); wlc->pub.npmkid = 0; wlc->pub.npmkid_cand = 0; }#endif /* BCMWPA2 */ /* initialize ucode default key flag MHF_DEFKEYVALID */ wlc_mhf(wlc, MHF_DEFKEYVALID, wlc_key_defkeyflag(wlc), TRUE); if (wlc->assoc_state == AS_WAIT_DISASSOC) { /* we are interrupting an earlier wlc_set_ssid call and wlc_ssid_scan_start is * scheduled to run as the wlc_disassociate_client callback. The target_bss has * been updated above so just allow the wlc_ssid_scan_start callback to pick up * the set_ssid work with the new target. */ } else { wlc->assoc_type = AS_ASSOCIATION; if (wlc->pub.associated && (len != wlc->pub.current_bss.SSID_len || bcmp(SSID, (char*)wlc->pub.current_bss.SSID, len))) { /* abort any current scan, and return to home channel */ wlc_scan_abort(wlc); WL_ASSOC(("SCAN: wlc_set_ssid, Disassociating from %s first\n", bcm_ether_ntoa(&wlc->prev_BSSID, eabuf))); wlc_assoc_change_state(wlc, AS_WAIT_DISASSOC); wlc_disassociate_client(wlc, TRUE, wlc_setssid_disassoc_complete, NULL); } else { /* make sure the association retry timer is not pending */ wl_del_timer(wlc->wl, wlc->assoc_timer); /* continue the association process by starting the association scan */ wlc_assoc_scan_start(wlc, NULL); } }}static voidwlc_setssid_disassoc_complete(wlc_info_t *wlc, uint txstatus, void *ignore){ WL_ASSOC(("SCAN: disassociation complete, start assoc scan\n")); /* continue with the association process by starting the association scan */ wlc_assoc_scan_start(wlc, NULL); return;}static boolwlc_rsn_ucast_lookup(struct rsn_parms *rsn, uint8 auth){ uint i; for (i = 0; i < rsn->ucount; i++) if (rsn->unicast[i] == auth) return TRUE; return FALSE;}static voidwlc_cook_join_targets(wlc_info_t *wlc, bool roam, int cur_rssi){ int i, j, k; wlc_bss_info_t **bip, *tmp_bi; uint orig_roam_delta, roam_delta = 0; bool done; uint32 *join_pref_score; uint32 join_pref_score_size = wlc->join_targets.count *
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -