static bool ieee80211_assoc_state_run_event(void *ctx, u_int16_t event, u_int16_t event_data_len, void *event_data) { wlan_assoc_sm_t sm = (wlan_assoc_sm_t) ctx; wlan_if_t vap = sm->vap_handle; u_int32_t time_elapsed; switch(event) { case IEEE80211_ASSOC_EVENT_BEACON_MISS: sm->last_failure = WLAN_ASSOC_SM_REASON_BEACON_MISS; /* beacon miss */ ieee80211_sm_transition_to(sm->hsm_handle,IEEE80211_ASSOC_STATE_INIT); return true; break; case IEEE80211_ASSOC_EVENT_DISASSOC: time_elapsed = CONVERT_SYSTEM_TIME_TO_MS(OS_GET_TIMESTAMP() - sm->last_connected_time); if ((sm->last_reason == IEEE80211_REASON_AUTH_EXPIRE || sm->last_reason == IEEE80211_REASON_ASSOC_EXPIRE) && (vap->auto_assoc)) { ieee80211_send_event(sm, WLAN_ASSOC_SM_EVENT_REJOINING, WLAN_ASSOC_SM_REASON_DISASSOC); ieee80211_sm_transition_to(sm->hsm_handle,IEEE80211_ASSOC_STATE_JOIN); #if ATH_SUPPORT_WPA_SUPPLICANT_CHECK_TIME } else if(sm->cur_rejoin_attempts < vap->iv_rejoint_attemp_time ) { sm->cur_rejoin_attempts++; ieee80211_send_event(sm, WLAN_ASSOC_SM_EVENT_REJOINING, WLAN_ASSOC_SM_REASON_DISASSOC); ieee80211_sm_transition_to(sm->hsm_handle, IEEE80211_ASSOC_STATE_JOIN); } else { #else } else if(sm->cur_rejoin_attempts < REJOIN_ATTEMP_TIME && time_elapsed < REJOIN_CHECKING_TIME) { sm->cur_rejoin_attempts++; ieee80211_send_event(sm, WLAN_ASSOC_SM_EVENT_REJOINING, WLAN_ASSOC_SM_REASON_DISASSOC); ieee80211_sm_transition_to(sm->hsm_handle, IEEE80211_ASSOC_STATE_JOIN); } else { #endif ieee80211_sm_transition_to(sm->hsm_handle,IEEE80211_ASSOC_STATE_INIT); } return true; break; case IEEE80211_ASSOC_EVENT_DEAUTH: time_elapsed = CONVERT_SYSTEM_TIME_TO_MS(OS_GET_TIMESTAMP() - sm->last_connected_time); if ((sm->last_reason == IEEE80211_REASON_AUTH_EXPIRE || sm->last_reason == IEEE80211_REASON_ASSOC_EXPIRE) && (vap->auto_assoc)) { ieee80211_send_event(sm, WLAN_ASSOC_SM_EVENT_REJOINING, WLAN_ASSOC_SM_REASON_DEAUTH); ieee80211_sm_transition_to(sm->hsm_handle,IEEE80211_ASSOC_STATE_JOIN); #if ATH_SUPPORT_WPA_SUPPLICANT_CHECK_TIME } else if(sm->cur_rejoin_attempts < vap->iv_rejoint_attemp_time ) { sm->cur_rejoin_attempts++; ieee80211_send_event(sm, WLAN_ASSOC_SM_EVENT_REJOINING, WLAN_ASSOC_SM_REASON_DEAUTH); ieee80211_sm_transition_to(sm->hsm_handle, IEEE80211_ASSOC_STATE_JOIN); } else { #else } else if(sm->cur_rejoin_attempts < REJOIN_ATTEMP_TIME && time_elapsed < REJOIN_CHECKING_TIME) {
/** * @brief noise histogrm response * * @param rrm * @param ie * * @return */ u_int8_t *ieee80211_rrm_send_nhist_resp(ieee80211_rrm_t rrm,u_int8_t *ie) { struct ieee80211_nhistrsp *rsp=NULL; struct ieee80211_measrsp_ie *measrsp=NULL; struct ieee80211_rrmreq_info *params=NULL; unsigned long tsf; #if UMAC_SUPPORT_RRM_DEBUG wlan_if_t vap = rrm->rrm_vap; #endif RRM_FUNCTION_ENTER; params = (struct ieee80211_rrmreq_info *)(rrm->rrmcb); measrsp = (struct ieee80211_measrsp_ie *)ie; measrsp->id = IEEE80211_ELEMID_MEASREP; measrsp->token=params->rep_dialogtoken; measrsp->rspmode = 0x00; /* Need to validate */ measrsp->rsptype = IEEE80211_MEASRSP_NOISE_HISTOGRAM_REPORT; rsp = (struct ieee80211_nhistrsp *)(&measrsp->rsp[0]); rsp->mduration = params->duration; rsp->regclass = params->regclass; rsp->chnum = params->chnum; rsp->anpi = (u_int8_t)rrm->rrm_noisefloor[rsp->chnum]; OS_GET_RANDOM_BYTES(&rsp->antid,sizeof(rsp->antid)); OS_GET_RANDOM_BYTES(rsp->ipi,sizeof(rsp->ipi)); tsf = OS_GET_TIMESTAMP(); OS_MEMCPY(rsp->tsf,&tsf,4); ie = &rsp->rsp[0]; measrsp->len = (ie - &measrsp->token); RRM_FUNCTION_EXIT; return ie; }
void ieee80211_inact_timeout_sta(struct ieee80211vap *vap) { struct ieee80211_mlme_priv *mlme_priv = vap->iv_mlme_priv; if (!mlme_priv->im_connection_up) { return; } /* * if there was an activity in the last IEEE80211_INACT_WAIT period. * then reset the counter. */ if (CONVERT_SYSTEM_TIME_TO_MS(OS_GET_TIMESTAMP() - vap->iv_last_directed_frame) < (IEEE80211_INACT_WAIT * 1000)) { vap->iv_inact_count = (vap->iv_keep_alive_timeout + IEEE80211_INACT_WAIT -1)/IEEE80211_INACT_WAIT; } if (vap->iv_inact_count) { --vap->iv_inact_count; if (vap->iv_inact_count == 0) { if (ieee80211_sta_power_send_keepalive(vap->iv_pwrsave_sta) == ENXIO) { ieee80211_send_nulldata(vap->iv_bss,false); } if (vap->iv_keep_alive_timeout) { vap->iv_inact_count = (vap->iv_keep_alive_timeout + IEEE80211_INACT_WAIT -1)/IEEE80211_INACT_WAIT; } } } }
void ieee80211_prdperfstat_thrput_update_hist(struct ieee80211com *ic) { struct ieee80211_prdperfstat_thrput *thrput = &ic->ic_thrput; if (thrput->is_histogram_full) { thrput->histogram_bytecount -= thrput->histogram[thrput->histogram_tail]; /* We do not use modulo since it is expensive */ if (thrput->histogram_tail == (thrput->histogram_size - 1)) { thrput->histogram_tail = 0; } else { thrput->histogram_tail++; } } thrput->histogram_bytecount += thrput->curr_bytecount; thrput->histogram[thrput->histogram_head] = thrput->curr_bytecount; thrput->curr_bytecount = 0; thrput->last_save_ms = OS_GET_TIMESTAMP(); /* Slide ahead */ if (thrput->histogram_head == (thrput->histogram_size - 1)) { thrput->is_histogram_full = 1; thrput->histogram_head = 0; } else { thrput->histogram_head++; } }
/* Return throughput in kbps */ u_int32_t ieee80211_prdperfstat_thrput_get(struct ieee80211com *ic) { struct ieee80211_prdperfstat_thrput *thrput = &ic->ic_thrput; u_int32_t total_bytes = 0; u_int32_t elapsed_time_ms = 0; u_int32_t thrput_kbps = 0; int num_histogram_entries = 0; if (!thrput->is_started) { return 0; } if (unlikely(!thrput->is_histogram_full)) { num_histogram_entries = thrput->histogram_head - thrput->histogram_tail; } else { num_histogram_entries = thrput->histogram_size; } total_bytes = (thrput->histogram_bytecount + thrput->curr_bytecount); elapsed_time_ms = (num_histogram_entries * PRDPERFSTAT_THRPUT_INTERVAL_MS) + (OS_GET_TIMESTAMP() - thrput->last_save_ms); thrput_kbps = (total_bytes * 8)/ elapsed_time_ms; return thrput_kbps; }
/** * @brief * * @param vap * @param mode * * @return * @return on success return 0. * on failure returns -ve value. */ int ieee80211_rrm_scan(wlan_if_t vap, u_int8_t mode) { int retval = 0; RRM_FUNCTION_ENTER; if ((mode == 0) || (mode == 1)) { /* Active mode */ wlan_scan_table_flush(vap); retval = ieee80211_rrm_scan_start(vap, (mode == 1)?true:false); if ((retval != 0) && vap->rrm->pending_report) { ieee80211_rrm_free_report(vap->rrm); return -EBUSY; } else { vap->rrm->rrm_last_scan = OS_GET_TIMESTAMP(); } } else { /* Send last Beacon Table as report */ if(vap->rrm->pending_report) { ieee80211_send_report(vap->rrm); return EOK; } } RRM_FUNCTION_EXIT; return EOK; }
static void pktlog_getbuf_intsafe(struct ath_pktlog_arg *plarg) { struct ath_pktlog_buf *log_buf; int32_t buf_size; struct ath_pktlog_hdr *log_hdr; int32_t cur_wr_offset; char *log_ptr; struct ath_pktlog_info *pl_info = plarg->pl_info; u_int16_t log_type = plarg->log_type; size_t log_size = plarg->log_size; u_int32_t flags = plarg->flags; log_buf = pl_info->buf; buf_size = pl_info->buf_size; cur_wr_offset = log_buf->wr_offset; /* Move read offset to the next entry if there is a buffer overlap */ if (log_buf->rd_offset >= 0) { if ((cur_wr_offset <= log_buf->rd_offset) && (cur_wr_offset + sizeof(struct ath_pktlog_hdr)) > log_buf->rd_offset) PKTLOG_MOV_RD_IDX(log_buf->rd_offset, log_buf, buf_size); } else { log_buf->rd_offset = cur_wr_offset; } log_hdr = (struct ath_pktlog_hdr *) (log_buf->log_data + cur_wr_offset); log_hdr->log_type = log_type; log_hdr->flags = flags; log_hdr->timestamp = (u_int32_t) CONVERT_SYSTEM_TIME_TO_MS(OS_GET_TIMESTAMP()); log_hdr->size = (u_int16_t)log_size; cur_wr_offset += sizeof(*log_hdr); if ((buf_size - cur_wr_offset) < log_size) { while ((cur_wr_offset <= log_buf->rd_offset) && (log_buf->rd_offset < buf_size)) PKTLOG_MOV_RD_IDX(log_buf->rd_offset, log_buf, buf_size); cur_wr_offset = 0; } while ((cur_wr_offset <= log_buf->rd_offset) && (cur_wr_offset + log_size) > log_buf->rd_offset) PKTLOG_MOV_RD_IDX(log_buf->rd_offset, log_buf, buf_size); log_ptr = &(log_buf->log_data[cur_wr_offset]); cur_wr_offset += log_hdr->size; log_buf->wr_offset = ((buf_size - cur_wr_offset) >= sizeof(struct ath_pktlog_hdr)) ? cur_wr_offset : 0; plarg->buf = log_ptr; }
/* * set vap pause in progress flag . */ static inline void ath_vap_pause_set_in_progress(struct ath_softc *sc) { int iter_count=0; systime_t start_timestamp = OS_GET_TIMESTAMP(); systime_t cur_timestamp ; while(atomic_read(&sc->sc_txq_use_cnt)) { OS_DELAY(10); ++ iter_count; if ((iter_count % 1000) == 0) { cur_timestamp = OS_GET_TIMESTAMP(); if (CONVERT_SYSTEM_TIME_TO_MS(cur_timestamp - start_timestamp) >= VAP_PAUSE_SYNCHRONIZATION_TIMEOUT) { ASSERT(0); } } } atomic_set(&sc->sc_vap_pause_in_progress, 1); }
/** * @brief * * @param vap * @param ni * @param req * @param rm_token * * @return * @return on success return 0. * on failure returns -ve value. */ int ieee80211_rrm_recv_beacon_req(wlan_if_t vap, wlan_node_t ni, struct ieee80211_measreq_ie *req,u_int8_t rm_token) { struct ieee80211_rrmreq_info *params=NULL; struct ieee80211_beaconreq *bcnreq=NULL; RRM_FUNCTION_ENTER; bcnreq = (struct ieee80211_beaconreq *)(&(req->req[0])); params = (struct ieee80211_rrmreq_info *) OS_MALLOC(vap->rrm->rrm_osdev, sizeof(struct ieee80211_rrmreq_info), 0); if(NULL == params) return -EBUSY; params->rm_dialogtoken = rm_token; params->rep_dialogtoken= req->token; params->duration=bcnreq->duration; params->chnum = bcnreq->channum; RRM_DEBUG(vap, RRM_DEBUG_INFO, "%s : duration %d chnum %d regclass %d\n", __func__, params->duration, params->chnum, params->regclass); IEEE80211_ADDR_COPY(params->bssid,bcnreq->bssid); ieee80211_rrm_set_report_pending(vap,IEEE80211_MEASREQ_BR_TYPE,(void *)params); if(vap->rrm->rrm_last_scan == 0) { ieee80211_rrm_scan(vap, bcnreq->mode); return EOK; } else { u_int32_t last_scan_time=0,msec_current_time = 0; last_scan_time = (u_int32_t) CONVERT_SYSTEM_TIME_TO_MS(vap->rrm->rrm_last_scan); msec_current_time = (u_int32_t) CONVERT_SYSTEM_TIME_TO_MS(OS_GET_TIMESTAMP()); msec_current_time -= last_scan_time; if(msec_current_time < 60*1000) { if(vap->rrm->pending_report) ieee80211_send_report(vap->rrm); } else { ieee80211_rrm_scan(vap, bcnreq->mode); } } RRM_FUNCTION_EXIT; return EOK; }
/* * set vap pause in progress flag . */ static inline void ath_vap_pause_set_in_progress(struct ath_softc *sc) { int iter_count=0; systime_t start_timestamp = OS_GET_TIMESTAMP(); systime_t cur_timestamp ; spin_lock(&(sc)->sc_vap_pause_lock); while(sc->sc_txq_use_cnt) { spin_unlock(&(sc)->sc_vap_pause_lock); OS_DELAY(10); ++ iter_count; if ((iter_count % 1000) == 0) { cur_timestamp = OS_GET_TIMESTAMP(); if (CONVERT_SYSTEM_TIME_TO_MS(cur_timestamp - start_timestamp) >= VAP_PAUSE_SYNCHRONIZATION_TIMEOUT) { ASSERT(0); } } spin_lock(&(sc)->sc_vap_pause_lock); } sc->sc_vap_pause_in_progress=1; spin_unlock(&(sc)->sc_vap_pause_lock); }
static void ol_ath_node_collect_stats(struct ieee80211_node *ni) { u_int32_t old_phyerr, new_phyerr; u_int32_t old_ostime, new_ostime; u_int32_t phyerr_rate; u_int32_t msdu_size, max_msdu_size; old_phyerr = ni->ni_vap->iv_ald->ald_phyerr; old_ostime = ni->ni_vap->iv_ald->ald_ostime; new_phyerr = (OL_ATH_NODE_NET80211(ni))->an_phy_err_cnt; new_ostime = CONVERT_SYSTEM_TIME_TO_SEC(OS_GET_TIMESTAMP()); if((new_ostime > old_ostime) && (old_ostime > 0)) phyerr_rate = (new_phyerr - old_phyerr)/(new_ostime - old_ostime); else phyerr_rate = 0; ni->ni_vap->iv_ald->ald_phyerr = new_phyerr; ni->ni_vap->iv_ald->ald_ostime = new_ostime; ni->ni_ald.ald_capacity = (OL_ATH_NODE_NET80211(ni))->an_tx_cnt ? ((OL_ATH_NODE_NET80211(ni))->an_tx_rates_used/ (OL_ATH_NODE_NET80211(ni))->an_tx_cnt) : 0; if(ni->ni_ald.ald_capacity == 0) ni->ni_ald.ald_capacity = (OL_ATH_NODE_NET80211(ni))->an_ni_tx_rate/1000; if((OL_ATH_NODE_NET80211(ni))->an_tx_bytes == 0) msdu_size = ALD_MSDU_SIZE; else msdu_size = (OL_ATH_NODE_NET80211(ni))->an_tx_bytes/ni->ni_ald.ald_txcount; if (msdu_size < DEFAULT_MSDU_SIZE) ni->ni_ald.ald_msdusize = ALD_MSDU_SIZE; else ni->ni_ald.ald_msdusize = msdu_size; max_msdu_size = (msdu_size > ALD_MSDU_SIZE) ? msdu_size : ALD_MSDU_SIZE; if ((OL_ATH_NODE_NET80211(ni))->an_tx_ratecount > 0) ni->ni_ald.ald_avgmax4msaggr = ni->ni_ald.ald_max4msframelen / ((OL_ATH_NODE_NET80211(ni))->an_tx_ratecount * max_msdu_size); if(ni->ni_ald.ald_avgmax4msaggr > 192) ni->ni_ald.ald_avgmax4msaggr = 192; if(ni->ni_ald.ald_avgmax4msaggr > 0) ni->ni_ald.ald_aggr = ni->ni_ald.ald_avgmax4msaggr/2; else ni->ni_ald.ald_aggr = 96; //Max aggr 192/2 /* Avg Aggr should be atleast 1 */ ni->ni_ald.ald_aggr = ni->ni_ald.ald_aggr > 1 ? ni->ni_ald.ald_aggr : 1; }
void ieee80211_prdperfstat_thrput_start(struct ieee80211com *ic) { struct ieee80211_prdperfstat_thrput *thrput = &ic->ic_thrput; OS_MEMSET(thrput->histogram, 0, thrput->histogram_size * sizeof(u_int32_t)); thrput->histogram_head = 0; thrput->histogram_tail = 0; thrput->is_histogram_full = 0; thrput->histogram_bytecount = 0; thrput->curr_bytecount = 0; thrput->last_save_ms = OS_GET_TIMESTAMP(); thrput->timer_count = 0; thrput->is_started = 1; }
static bool ieee80211_assoc_state_assoc_event(void *ctx, u_int16_t event, u_int16_t event_data_len, void *event_data) { wlan_assoc_sm_t sm = (wlan_assoc_sm_t) ctx; switch(event) { case IEEE80211_ASSOC_EVENT_ASSOC_SUCCESS: sm->last_connected_time = OS_GET_TIMESTAMP(); ieee80211_sm_transition_to(sm->hsm_handle,IEEE80211_ASSOC_STATE_RUN); return true; break; case IEEE80211_ASSOC_EVENT_ASSOC_FAIL: case IEEE80211_ASSOC_EVENT_TIMEOUT: if (sm->cur_assoc_attempts >= sm->max_assoc_attempts) { IEEE80211_DPRINTF(sm->vap_handle,IEEE80211_MSG_STATE,"%s: max assoc attempts reached \n",__func__); if (sm->scan_entry) wlan_scan_entry_set_assoc_state(sm->scan_entry, AP_ASSOC_STATE_NONE); ieee80211_sm_transition_to(sm->hsm_handle,IEEE80211_ASSOC_STATE_INIT); return true; } sm->last_failure = WLAN_ASSOC_SM_REASON_ASSOC_FAILED; ieee80211_sm_transition_to(sm->hsm_handle,IEEE80211_ASSOC_STATE_ASSOC); return true; break; case IEEE80211_ASSOC_EVENT_DISCONNECT_REQUEST: case IEEE80211_ASSOC_EVENT_DISASSOC_REQUEST: if (sm->scan_entry) wlan_scan_entry_set_assoc_state(sm->scan_entry, AP_ASSOC_STATE_NONE); /* cancel pending mlme operation */ wlan_mlme_cancel(sm->vap_handle); if (wlan_mlme_operation_in_progress(sm->vap_handle)) { ieee80211_sm_transition_to(sm->hsm_handle,IEEE80211_ASSOC_STATE_MLME_WAIT); } else { ieee80211_sm_transition_to(sm->hsm_handle,IEEE80211_ASSOC_STATE_INIT); } break; case IEEE80211_ASSOC_EVENT_DEAUTH: ieee80211_send_event(sm, WLAN_ASSOC_SM_EVENT_REJOINING, WLAN_ASSOC_SM_REASON_DEAUTH); ieee80211_sm_transition_to(sm->hsm_handle,IEEE80211_ASSOC_STATE_AUTH); return true; break; default: return false; } return false; }
int pktlog_enable(ath_generic_softc_handle scn, int32_t log_state) { struct pktlog_handle_t *pl_dev = get_pl_handle(scn); struct ath_pktlog_info *pl_info = (pl_dev) ? pl_dev->pl_info : g_pktlog_info; int error; if (!pl_info) { return 0; } pl_info->log_state = 0; if (log_state != 0) { if (!pl_dev) { if (g_pktlog_mode == PKTLOG_MODE_ADAPTER) { pktlog_disable_adapter_logging(); g_pktlog_mode = PKTLOG_MODE_SYSTEM; } } else { if (g_pktlog_mode == PKTLOG_MODE_SYSTEM) { /* Currently the system wide logging is disabled */ g_pktlog_info->log_state = 0; g_pktlog_mode = PKTLOG_MODE_ADAPTER; } } if (pl_info->buf == NULL) { error = pktlog_alloc_buf(scn ,pl_info); if (error != 0) return error; pl_info->buf->bufhdr.version = CUR_PKTLOG_VER; pl_info->buf->bufhdr.magic_num = PKTLOG_MAGIC_NUM; pl_info->buf->wr_offset = 0; pl_info->buf->rd_offset = -1; } pl_info->start_time_thruput = OS_GET_TIMESTAMP(); pl_info->start_time_per = pl_info->start_time_thruput; } pl_info->log_state = log_state; return 0; }
/* * count PER and stop pktlog if it's over a threshold. Clear the count per an interval. */ static void pktlog_trigger_thruput(HAL_BOOL pkt_good, u_int32_t pktlen, struct ath_pktlog_info *pl_info) { static u_int32_t total = 0; // in bytes u_int32_t now; if (pkt_good) total += pktlen; now = OS_GET_TIMESTAMP(); if (CONVERT_SYSTEM_TIME_TO_MS(now - pl_info->start_time_thruput) > pl_info->trigger_interval) { if (total < pl_info->thruput_thresh) { //trigger stop DPRINTF(pl_info->pl_sc, ATH_DEBUG_ANY, "pktlog stopped: only %d bytes thruput in past %dms\n", total, pl_info->trigger_interval); if (pl_info->log_state) { pl_info->saved_state = pl_info->log_state; pl_info->log_state = 0; } } total = 0; pl_info->start_time_thruput = now; } }
/* * count PER and stop pktlog if it's over a threshold. Clear the count per an interval. */ static void pktlog_trigger_per(HAL_BOOL pkt_good, struct ath_pktlog_info *pl_info, int failcount, int nframes, int nbad) { static u_int32_t pkt_err = 0, pkt_cnt = 0; u_int32_t now; if(nframes > 1) { /* * this is a tx aggregate packet * failcount: number of tx retries due to not seeing Block ACK * nframes: number of subframes in an aggregate */ pkt_cnt += failcount * nframes; pkt_err += failcount * nframes; if (pkt_good) { pkt_cnt += nframes; pkt_err += nbad; } } else { pkt_cnt += failcount; pkt_err += failcount; if (pkt_good) pkt_cnt++; } now = OS_GET_TIMESTAMP(); if (CONVERT_SYSTEM_TIME_TO_MS(now - pl_info->start_time_per) > pl_info->trigger_interval) { if (pkt_err * 100 > pkt_cnt * pl_info->per_thresh) { //trigger stop DPRINTF(pl_info->pl_sc, ATH_DEBUG_ANY, "pktlog stopped: seen %d bad packets out of %d in past %dms\n", pkt_err, pkt_cnt, pl_info->trigger_interval); if (pl_info->log_state) { pl_info->saved_state = pl_info->log_state; pl_info->log_state = 0; } } pkt_err = 0; pkt_cnt = 0; pl_info->start_time_per = now; } }
/* * Calculate maximum allowed scan_entry age, in ms. * Reference_time specifies the timestamp of the oldest accepted entry. */ u_int32_t ieee80211_mlme_maximum_scan_entry_age(wlan_if_t vaphandle, systime_t reference_time) { #define IEEE80211_SCAN_LATENCY_TIME 1000 u_int32_t maximum_age = 0; systime_t current_time = OS_GET_TIMESTAMP(); if (reference_time == 0) { /* Make all entries old if there's no record of the last scan */ maximum_age = 0; } else { maximum_age = CONVERT_SYSTEM_TIME_TO_MS(current_time - reference_time); /* * Make all entries in the table "old" by setting the maximum age * to 0 if last scan occurred too long ago. This can happen when * system is resuming from S3/S4. */ if (maximum_age > IEEE80211_SCAN_ENTRY_EXPIRE_TIME) { maximum_age = IEEE80211_SCAN_ENTRY_EXPIRE_TIME; } } /* * Add a latency time to account for the delay from the time the * maximum age is calculated to the time it's actually used. * Failing to account for this latency time can cause the oldest * entries in the scan list to be skipped. */ if (maximum_age > 0) { maximum_age += IEEE80211_SCAN_LATENCY_TIME; } return maximum_age; #undef IEEE80211_SCAN_LATENCY_TIME }
void ieee80211_recv_beacon_ibss(struct ieee80211_node *ni, wbuf_t wbuf, int subtype, struct ieee80211_rx_status *rs, ieee80211_scan_entry_t scan_entry) { struct ieee80211vap *vap = ni->ni_vap; struct ieee80211com *ic = ni->ni_ic; u_int16_t capinfo; int ibssmerge = 0; struct ieee80211_channelswitch_ie *chanie = NULL; struct ieee80211_extendedchannelswitch_ie *echanie = NULL; struct ieee80211_frame *wh; u_int64_t tsf; u_int8_t *quiet_elm = NULL; bool free_node = FALSE; #if ATH_SUPPORT_IBSS_DFS struct ieee80211_ibssdfs_ie *ibssdfsie = NULL; #endif /* ATH_SUPPORT_IBSS_DFS */ wh = (struct ieee80211_frame *)wbuf_header(wbuf); capinfo = ieee80211_scan_entry_capinfo(scan_entry); if (!(capinfo & IEEE80211_CAPINFO_IBSS)) return; OS_MEMCPY((u_int8_t *)&tsf, ieee80211_scan_entry_tsf(scan_entry), sizeof(tsf)); if (ni != ni->ni_bss_node) { OS_MEMCPY(ni->ni_tstamp.data, &tsf, sizeof(ni->ni_tstamp)); /* update activity indication */ ni->ni_beacon_rstamp = OS_GET_TIMESTAMP(); ni->ni_probe_ticks = 0; } /* * Check BBSID before updating our beacon configuration to make * sure the received beacon really belongs to our Adhoc network. */ if ((subtype == IEEE80211_FC0_SUBTYPE_BEACON) && ieee80211_vap_ready_is_set(vap) && (IEEE80211_ADDR_EQ(wh->i_addr3, ieee80211_node_get_bssid(vap->iv_bss)))) { /* * if the neighbor is not in the list, add it to the list. */ if (ni == ni->ni_bss_node) { ni = ieee80211_add_neighbor(ni, scan_entry); if (ni == NULL) { return; } OS_MEMCPY(ni->ni_tstamp.data, &tsf, sizeof(ni->ni_tstamp)); free_node = TRUE; } ni->ni_rssi = rs->rs_rssi; /* * record tsf of last beacon into bss node */ OS_MEMCPY(ni->ni_bss_node->ni_tstamp.data, &tsf, sizeof(ni->ni_tstamp)); /* * record absolute time of last beacon */ vap->iv_last_beacon_time = OS_GET_TIMESTAMP(); ic->ic_beacon_update(ni, rs->rs_rssi); #if ATH_SUPPORT_IBSS_WMM /* * check for WMM parameters */ if ((ieee80211_scan_entry_wmeparam_ie(scan_entry) != NULL) || (ieee80211_scan_entry_wmeinfo_ie(scan_entry) != NULL)) { /* Node is WMM-capable if WME IE (either subtype) is present */ ni->ni_ext_caps |= IEEE80211_NODE_C_QOS; /* QOS-enable */ ieee80211node_set_flag(ni, IEEE80211_NODE_QOS); } else { /* If WME IE not present node is not WMM capable */ ni->ni_ext_caps &= ~IEEE80211_NODE_C_QOS; ieee80211node_clear_flag(ni, IEEE80211_NODE_QOS); } #endif #if ATH_SUPPORT_IBSS_DFS if (ic->ic_curchan->ic_flagext & IEEE80211_CHAN_DFS) { //check and see if we need to update other info for ibss_dfsie ibssdfsie = (struct ieee80211_ibssdfs_ie *)ieee80211_scan_entry_ibssdfs_ie(scan_entry); if(ibssdfsie) { if (ieee80211_check_and_update_ibss_dfs(vap, ibssdfsie)) { ieee80211_ibss_beacon_update_start(ic); } } /* update info from DFS owner */ if(ibssdfsie){ if(IEEE80211_ADDR_EQ(wh->i_addr2, ibssdfsie->owner)) { if(OS_MEMCMP(ibssdfsie, &vap->iv_ibssdfs_ie_data, MIN_IBSS_DFS_IE_CONTENT_SIZE)) { if(le64_to_cpu(tsf) >= rs->rs_tstamp.tsf){ IEEE80211_ADDR_COPY(vap->iv_ibssdfs_ie_data.owner, ibssdfsie->owner); vap->iv_ibssdfs_ie_data.rec_interval = ibssdfsie->rec_interval; ieee80211_ibss_beacon_update_start(ic); } } } } /* check if owner and it is not transmitting ibssIE */ else if(IEEE80211_ADDR_EQ(wh->i_addr2, vap->iv_ibssdfs_ie_data.owner)){ IEEE80211_ADDR_COPY(vap->iv_ibssdfs_ie_data.owner, vap->iv_myaddr); vap->iv_ibssdfs_state = IEEE80211_IBSSDFS_OWNER; ieee80211_ibss_beacon_update_start(ic); } } #endif /* ATH_SUPPORT_IBSS_DFS */ /* * check for spectrum management */ if (capinfo & IEEE80211_CAPINFO_SPECTRUM_MGMT) { chanie = (struct ieee80211_channelswitch_ie *) ieee80211_scan_entry_csa(scan_entry); #if ATH_SUPPORT_IBSS_DFS if(chanie) { OS_MEMCPY(&vap->iv_channelswitch_ie_data, chanie, sizeof(struct ieee80211_channelswitch_ie)); ieee80211_ibss_beacon_update_start(ic); } #endif /* ATH_SUPPORT_IBSS_DFS */ echanie = (struct ieee80211_extendedchannelswitch_ie *) ieee80211_scan_entry_xcsa(scan_entry); if ((!chanie) && (!echanie)) { quiet_elm = ieee80211_scan_entry_quiet(scan_entry); } } } /* * Handle ibss merge as needed; check the tsf on the * frame before attempting the merge. The 802.11 spec * says the station should change its bssid to match * the oldest station with the same ssid, where oldest * is determined by the tsf. Note that hardware * reconfiguration happens through callback to * ath as the state machine will go from * RUN -> RUN when this happens. */ if (ieee80211_vap_ready_is_set(vap) && (le64_to_cpu(tsf) >= rs->rs_tstamp.tsf)) { ibssmerge = ieee80211_ibss_merge(ni,scan_entry); } if (ibssmerge) { ieee80211_mlme_adhoc_merge_start(ni); } /* * RNWF-specific: indicate to NDIS about the potential association. * It should be done after IBSS merge, which is called from ath_beacon_update(). */ if (IEEE80211_ADDR_EQ(wh->i_addr3, ieee80211_node_get_bssid(ni))) { /* Indicate node joined IBSS */ if ((capinfo & IEEE80211_CAPINFO_RADIOMEAS) && ieee80211_vap_rrm_is_set(vap)) { if(ni->ni_assoc_state != IEEE80211_NODE_ADHOC_STATE_AUTH_ASSOC) ieee80211_set_node_rrm(ni,TRUE); } else { ieee80211_set_node_rrm(ni,FALSE); } ieee80211_mlme_adhoc_join_indication(ni, wbuf); /* notify mlme of beacon reception */ ieee80211_mlme_join_complete_adhoc(ni); } if (ibssmerge) { ieee80211_mlme_adhoc_merge_completion(ni); } if (quiet_elm) { ic->ic_set_quiet(ni, quiet_elm); } if (free_node == TRUE) { ieee80211_free_node(ni); } }
void ieee80211_vap_iter_beacon_miss(void *arg, wlan_if_t vap) { systime_t tstamp; systime_t last_link_time; systime_t last_traffic_time; struct ieee80211com *ic = vap->iv_ic; struct ieee80211_mlme_priv *mlme_priv = vap->iv_mlme_priv; ieee80211_mlme_event event; IEEE80211_DPRINTF(vap, IEEE80211_MSG_SCAN, "%s: %s iv_bmiss_count=%d reset=%d max=%d arg=%08p swbmiss=%d\n", __func__, (arg != NULL) ? "SW" : "HW", vap->iv_bmiss_count, vap->iv_bmiss_count_for_reset, vap->iv_bmiss_count_max, arg, mlme_sta_swbmiss_active(vap)); /* * Our handling is only meaningful for stations that are * associated; any other conditions else will be handled * through different means (e.g. the tx timeout on mgt frames). */ if ((vap->iv_opmode != IEEE80211_M_STA) || !ieee80211_vap_ready_is_set(vap)) { mlme_sta_swbmiss_timer_print_status(vap); /* print the status of sw bmiss */ return; } /* * ignore HW beacon miss if SW beacon miss is enabled. * and completely rely on SW beacon miss. */ if ((arg == NULL) && mlme_sta_swbmiss_active(vap)) { return; } /* * WAR for excessive beacon miss problem on SoC. * Consider a beacon miss only when we have two consecutive * beacon misses and there are no rx activities in between. * * Count beacon misses only if we gave the AP a chance by sending a * directed Probe Request. * * Don't do anything if we are scanning a foreign channel. * Trying to transmit a frame (Probe Request) during a channel change * (which includes a channel reset) can cause a NMI due to invalid HW * addresses. * Trying to transmit a Probe Request while in a foreign channel * wouldn't do us any good either. * * Query current time only after retrieving LastLinkTime. This avoids * possible negative values if this routine is preempted by reception of * a beacon or directed frame which would update the fields used to * calculate LastLinkTime. */ last_traffic_time = ieee80211_get_directed_frame_timestamp(vap); last_link_time = (vap->iv_last_beacon_time > last_traffic_time) ? vap->iv_last_beacon_time : last_traffic_time; tstamp = OS_GET_TIMESTAMP(); { IEEE80211_DPRINTF(vap, IEEE80211_MSG_SCAN, "%d.%03d | %s: count=%d probe=%d beacon:%lums directed:%lums data:%lums ap_frame:%lums traffic_ind:%lums\n", ((u_int32_t) CONVERT_SYSTEM_TIME_TO_MS(tstamp)) / 1000, ((u_int32_t) CONVERT_SYSTEM_TIME_TO_MS(tstamp)) % 1000, __func__, vap->iv_bmiss_count, ieee80211_scan_can_transmit(ic->ic_scanner), (u_int32_t) CONVERT_SYSTEM_TIME_TO_MS(tstamp - vap->iv_last_beacon_time), (u_int32_t) CONVERT_SYSTEM_TIME_TO_MS(tstamp - last_traffic_time), (u_int32_t) CONVERT_SYSTEM_TIME_TO_MS(tstamp - vap->iv_lastdata), (u_int32_t) CONVERT_SYSTEM_TIME_TO_MS(tstamp - vap->iv_last_ap_frame), (u_int32_t) CONVERT_SYSTEM_TIME_TO_MS(tstamp - vap->iv_last_traffic_indication)); } /* * Do not count beacon misses received when we're off-channel, or * within IEEE80211_MINIMUM_BMISS_TIME ms of the last valid beacon. */ if ((! ieee80211_scan_in_home_channel(ic->ic_scanner)) || (CONVERT_SYSTEM_TIME_TO_MS(tstamp - last_link_time) < IEEE80211_MINIMUM_BMISS_TIME)) { mlme_sta_swbmiss_timer_start(vap); /* restart beacon miss timer */ return; } vap->iv_bmiss_count++; event.u.event_bmiss.cur_bmiss_count = vap->iv_bmiss_count; event.u.event_bmiss.max_bmiss_count = vap->iv_bmiss_count_for_reset; event.type = IEEE80211_MLME_EVENT_BEACON_MISS; ieee80211_mlme_deliver_event(mlme_priv,&event); if (vap->iv_bmiss_count < vap->iv_bmiss_count_for_reset) { #ifdef ATH_SWRETRY /* Turn off the sw retry mechanism until we receive * any data frame or probe response for the BSS we are * associated to. */ ic->ic_set_swretrystate(vap->iv_bss, FALSE); #endif /* * It is possible that the hardware gets into * deaf mode. Reset the hardware to see if it can recover * from the condition. */ /* indicate device error */ IEEE80211_DPRINTF(vap, IEEE80211_MSG_SCAN, "%s: Beacon miss, do internal reset!!\n", __func__); IEEE80211_DELIVER_EVENT_DEVICE_ERROR(vap); mlme_sta_swbmiss_timer_start(vap); /* restart beacon miss timer */ return; } /* max bmiss count reached */ vap->iv_bmiss_count = 0; /* reset bmiss counter */ IEEE80211_DPRINTF(vap, IEEE80211_MSG_ANY, "%s: Beacon miss, will indicate to OS!!\n", __func__); /* indicate beacon miss */ IEEE80211_DELIVER_EVENT_BEACON_MISS(vap); }
static int ol_vdev_wmi_event_handler(ol_scn_t scn, u_int8_t *data, u_int16_t datalen, void *context) { ieee80211_resmgr_t resmgr = (ieee80211_resmgr_t )context; wmi_vdev_start_response_event *wmi_vdev_start_resp_ev = (wmi_vdev_start_response_event *)data; wlan_if_t vaphandle; struct ieee80211com *ic = resmgr->ic; struct ieee80211_channel *chan = NULL; struct ieee80211_node *ni; u_int8_t numvaps, actidx = 0; struct ol_ath_vap_net80211 *avn; bool do_notify = true; vaphandle = ol_ath_vap_get(scn, wmi_vdev_start_resp_ev->vdev_id); if (NULL == vaphandle) { printk("Event received for Invalid/Deleted vap handle\n"); return 0; } avn = OL_ATH_VAP_NET80211(vaphandle); printk("ol_vdev_start_resp_ev for vap %d (%p)\n", wmi_vdev_start_resp_ev->vdev_id, scn->wmi_handle); spin_lock(&vaphandle->init_lock); switch (vaphandle->iv_opmode) { case IEEE80211_M_MONITOR: /* Handle same as HOSTAP */ case IEEE80211_M_HOSTAP: /* If vap is not waiting for the WMI event from target return here */ if(avn->av_ol_resmgr_wait == FALSE) { spin_unlock(&vaphandle->init_lock); return 0; } /* Resetting the ol_resmgr_wait flag*/ avn->av_ol_resmgr_wait = FALSE; numvaps = ieee80211_vaps_active(ic); chan = vaphandle->iv_des_chan[vaphandle->iv_des_mode]; /* * if there is a vap already running. * ignore the desired channel and use the * operating channel of the other vap. */ /* so that cwm can do its own crap. need to untie from state */ /* vap join is called here to wake up the chip if it is in sleep state */ ieee80211_vap_join(vaphandle); if (numvaps == 0) { //AP_DFS: ieee80211_set_channel(ic, chan); if (wmi_vdev_start_resp_ev->resp_type != WMI_VDEV_RESTART_RESP_EVENT) { /* 20/40 Mhz coexistence handler */ if ((avn->av_ol_resmgr_chan != NULL) && (chan != avn->av_ol_resmgr_chan)) { chan = avn->av_ol_resmgr_chan; } ic->ic_prevchan = ic->ic_curchan; ic->ic_curchan = chan; /*update channel history*/ actidx = ic->ic_chanidx; ic->ic_chanhist[actidx].chanid = (ic->ic_curchan)->ic_ieee; ic->ic_chanhist[actidx].chanjiffies = OS_GET_TIMESTAMP(); ic->ic_chanidx == (IEEE80211_CHAN_MAXHIST - 1) ? ic->ic_chanidx = 0 : ++(ic->ic_chanidx); /* update max channel power to max regpower of current channel */ ieee80211com_set_curchanmaxpwr(ic, chan->ic_maxregpower); ieee80211_wme_initparams(vaphandle); } /* ieee80211 Layer - Default Configuration */ vaphandle->iv_bsschan = ic->ic_curchan; /* XXX reset erp state */ ieee80211_reset_erp(ic, ic->ic_curmode, vaphandle->iv_opmode); } else { /* ieee80211 Layer - Default Configuration */ vaphandle->iv_bsschan = ic->ic_curchan; } /* use the vap bsschan for dfs configure */ if ( IEEE80211_IS_CHAN_DFS(vaphandle->iv_bsschan)) { extern void ol_if_dfs_configure(struct ieee80211com *ic); ol_if_dfs_configure(ic); } break; case IEEE80211_M_STA: ni = vaphandle->iv_bss; chan = ni->ni_chan; vaphandle->iv_bsschan = chan; ic->ic_prevchan = ic->ic_curchan; ic->ic_curchan = chan; /* update max channel power to max regpower of current channel */ ieee80211com_set_curchanmaxpwr(ic, chan->ic_maxregpower); /* ieee80211 Layer - Default Configuration */ vaphandle->iv_bsschan = ic->ic_curchan; /* XXX reset erp state */ ieee80211_reset_erp(ic, ic->ic_curmode, vaphandle->iv_opmode); ieee80211_wme_initparams(vaphandle); if (wmi_vdev_start_resp_ev->resp_type == WMI_VDEV_RESTART_RESP_EVENT) { do_notify = false; } break; default: break; } vaphandle->init_in_progress = false; spin_unlock(&vaphandle->init_lock); /* Intimate start completion to VAP module */ /* if STA, bypass notification for RESTERT EVENT */ if (do_notify) ieee80211_notify_vap_start_complete(resmgr, vaphandle, IEEE80211_RESMGR_STATUS_SUCCESS); return 0; }
int ath_ald_collect_data(ath_dev_t dev, ath_ald_t ald_data) { u_int32_t cu = 0; /* cu: channel utilization; cc: channel capacity */ u_int32_t msdu_size=0, load=0; u_int32_t rxclear=0, rxframe=0, txframe=0; u_int32_t new_phyerr=0, new_ostime=0; u_int32_t old_phyerr=0, old_ostime=0; u_int32_t phyerr_rate=0; u_int32_t tmp = 0; u_int8_t good; struct ath_softc *sc = ATH_DEV_TO_SC(dev); spin_lock(ald_data->ald_lock); good = ath_hal_getMibCycleCountsPct(sc->sc_ah, &rxclear, &rxframe, &txframe); if(good) { cu = rxclear; } old_phyerr = ald_data->ald_phyerr; old_ostime = ald_data->ald_ostime; new_phyerr = sc->sc_phy_stats[sc->sc_curmode].ast_rx_phyerr; new_ostime = OS_GET_TIMESTAMP()/1000; if((new_ostime > old_ostime) && (old_ostime > 0)) phyerr_rate = (new_phyerr - old_phyerr)/(new_ostime - old_ostime); else phyerr_rate = 0; ald_data->ald_phyerr = new_phyerr; ald_data->ald_ostime = new_ostime; if(ald_data->ald_unicast_tx_packets != 0 ){ msdu_size = ald_data->ald_unicast_tx_bytes/ald_data->ald_unicast_tx_packets; }else{ msdu_size = ALD_MSDU_SIZE; } ald_data->phyerr_rate = phyerr_rate; ald_data->msdu_size = msdu_size; /* currently not in use, the value is not accurate somehow */ if((sc->sc_ald.sc_ald_tbuf != 0) && (sc->sc_ald.sc_ald_tnum != 0)){ tmp = sc->sc_ald.sc_ald_tbuf/sc->sc_ald.sc_ald_tnum; if (tmp > 0) { load = sc->sc_txbuf_free*msdu_size/(tmp*1000); } }else load = ALD_MAX_DEV_LOAD; if (sc->sc_ald.sc_ald_cunum > 0) { cu = sc->sc_ald.sc_ald_cu / sc->sc_ald.sc_ald_cunum; } sc->sc_ald.sc_ald_cu = 0; sc->sc_ald.sc_ald_cunum = 0; ald_data->ald_unicast_tx_bytes = 0; ald_data->ald_unicast_tx_packets = 0; ald_data->ald_chan_util = cu; ald_data->ald_dev_load = load; spin_unlock(ald_data->ald_lock); sc->sc_ald.sc_ald_tbuf = 0; sc->sc_ald.sc_ald_tnum = 0; return 0; }