/*
 * Handle station leaving bss.
 */
void
ieee80211_node_saveq_cleanup(struct ieee80211_node *ni)
{
    struct ieee80211vap *vap = ni->ni_vap;

    /* vap is already deleted */
    if (vap == NULL) return;

    if (vap->iv_opmode == IEEE80211_M_HOSTAP) {
        ieee80211_mlme_node_leave(ni);
    }
    else {
        ieee80211node_clear_flag(ni, IEEE80211_NODE_PWR_MGT);
#if NOT_YET
        if (ieee80211node_has_flag(ni, IEEE80211_NODE_UAPSD_TRIG)) {
            ieee80211node_clear_flag(ni, IEEE80211_NODE_UAPSD_TRIG);
            IEEE80211_UAPSD_LOCK(ni->ni_ic);
            ni->ni_ic->ic_uapsdmaxtriggers--;
            IEEE80211_UAPSD_UNLOCK(ni->ni_ic);
        }
#endif
    }

    if ((ieee80211_node_saveq_drain(ni) != 0) && (vap->iv_set_tim != NULL))
        vap->iv_set_tim(ni, 0);
    IEEE80211_NOTE(vap, IEEE80211_MSG_POWER, ni,
                       "%s %u sta's in ps mode \n", __func__,vap->iv_ps_sta);
}
示例#2
0
static bool
ieee80211_pwrsave_smps_check(ieee80211_pwrsave_smps_t smps)
{
    u_int16_t i, throughput = 0, rssi;
    struct ieee80211vap *vap = smps->ips_vap;
    struct ieee80211com *ic = vap->iv_ic;

    if (!smps->ips_connected ||
            !ieee80211_vap_ready_is_set(vap) ||
            (vap->iv_opmode != IEEE80211_M_STA) ||
            (!ieee80211node_has_flag(vap->iv_bss, IEEE80211_NODE_HT))) {
        return FALSE;
    }

    /* SM power save check.
     * SM Power save is enabled if,
     * - There is no data traffic or
     * - Throughput is less than threshold and RSSI is greater than threshold.
     */
    throughput = vap->iv_txrxbytes / (IEEE80211_PWRSAVE_TIMER_INTERVAL * 125);  // in Mbps
    rssi = ic->ic_node_getrssi(vap->iv_bss, -1, IEEE80211_RSSI_BEACON);
    vap->iv_txrxbytes = 0;   // Clear byte counter

    smps->ips_smpsDataHistory[smps->ips_smpsCurrDataIndex++] = throughput;
    smps->ips_smpsCurrDataIndex = smps->ips_smpsCurrDataIndex % IEEE80211_SMPS_DATAHIST_NUM;


    /* We calculate average throughput over the past samples */
    throughput = 0;
    for (i = 0; i < IEEE80211_SMPS_DATAHIST_NUM; i++) {
        throughput += smps->ips_smpsDataHistory[i];
    }
    throughput /= IEEE80211_SMPS_DATAHIST_NUM;

    /*
     * We make the thresholds slightly different for SM power save enable & disable to get
     * over the ping-pong effect when calculated throughput is close to the threshold value.
     * SMPS Enable Threshold = Registry Value
     * SMPS Disable Threshold = Registry Value + IEEE80211_SMPS_THRESH_DIFF
     */
    if (!throughput || ((throughput < vap->iv_smps_datathresh) &&
                        (rssi > vap->iv_smps_rssithresh))) {
        /* Receive criteria met, do SM power save. */
        ieee80211_pwrsave_smps_event(smps, IEEE80211_SMPS_ENABLE);
    } else if ((throughput > (vap->iv_smps_datathresh + IEEE80211_SMPS_THRESH_DIFF)) ||
               (rssi < vap->iv_smps_rssithresh)) {
        ieee80211_pwrsave_smps_event(smps, IEEE80211_SMPS_DISABLE);
    }
    return TRUE;
}