static void rate_control_pid_get_rate(void *priv, struct net_device *dev, struct ieee80211_hw_mode *mode, struct sk_buff *skb, struct rate_selection *sel) { struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; struct ieee80211_sub_if_data *sdata; struct sta_info *sta; int rateidx; u16 fc; sta = sta_info_get(local, hdr->addr1); /* Send management frames and broadcast/multicast data using lowest * rate. */ fc = le16_to_cpu(hdr->frame_control); if ((fc & IEEE80211_FCTL_FTYPE) != IEEE80211_FTYPE_DATA || is_multicast_ether_addr(hdr->addr1) || !sta) { sel->rate = rate_lowest(local, mode, sta); if (sta) sta_info_put(sta); return; } /* If a forced rate is in effect, select it. */ sdata = IEEE80211_DEV_TO_SUB_IF(dev); if (sdata->bss && sdata->bss->force_unicast_rateidx > -1) sta->txrate = sdata->bss->force_unicast_rateidx; rateidx = sta->txrate; if (rateidx >= mode->num_rates) rateidx = mode->num_rates - 1; sta->last_txrate = rateidx; sta_info_put(sta); sel->rate = &mode->rates[rateidx]; #ifdef CONFIG_MAC80211_DEBUGFS rate_control_pid_event_tx_rate( &((struct rc_pid_sta_info *) sta->rate_ctrl_priv)->events, rateidx, mode->rates[rateidx].rate); #endif }
static struct ieee80211_rate * rate_control_simple_get_rate(void *priv, struct net_device *dev, struct sk_buff *skb, struct rate_control_extra *extra) { struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); struct ieee80211_sub_if_data *sdata; struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; struct ieee80211_hw_mode *mode = extra->mode; struct sta_info *sta; int rateidx, nonerp_idx; u16 fc; memset(extra, 0, sizeof(*extra)); fc = le16_to_cpu(hdr->frame_control); if ((fc & IEEE80211_FCTL_FTYPE) != IEEE80211_FTYPE_DATA || (hdr->addr1[0] & 0x01)) { /* Send management frames and broadcast/multicast data using * lowest rate. */ /* TODO: this could probably be improved.. */ return rate_control_lowest_rate(local, mode); } sta = sta_info_get(local, hdr->addr1); if (!sta) return rate_control_lowest_rate(local, mode); sdata = IEEE80211_DEV_TO_SUB_IF(dev); if (sdata->bss && sdata->bss->force_unicast_rateidx > -1) sta->txrate = sdata->bss->force_unicast_rateidx; rateidx = sta->txrate; if (rateidx >= mode->num_rates) rateidx = mode->num_rates - 1; sta->last_txrate = rateidx; nonerp_idx = rateidx; while (nonerp_idx > 0 && ((mode->rates[nonerp_idx].flags & IEEE80211_RATE_ERP) || !(mode->rates[nonerp_idx].flags & IEEE80211_RATE_SUPPORTED) || !(sta->supp_rates & BIT(nonerp_idx)))) nonerp_idx--; extra->nonerp = &mode->rates[nonerp_idx]; sta_info_put(sta); return &mode->rates[rateidx]; }
static void rate_control_simple_tx_status(void *priv, struct net_device *dev, struct sk_buff *skb, struct ieee80211_tx_status *status) { struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; struct sta_info *sta; struct sta_rate_control *srctrl; sta = sta_info_get(local, hdr->addr1); if (!sta) return; srctrl = sta->rate_ctrl_priv; srctrl->tx_num_xmit++; if (status->excessive_retries) { srctrl->tx_num_failures++; sta->tx_retry_failed++; sta->tx_num_consecutive_failures++; sta->tx_num_mpdu_fail++; } else { sta->last_ack_rssi[0] = sta->last_ack_rssi[1]; sta->last_ack_rssi[1] = sta->last_ack_rssi[2]; sta->last_ack_rssi[2] = status->ack_signal; sta->tx_num_consecutive_failures = 0; sta->tx_num_mpdu_ok++; } sta->tx_retry_count += status->retry_count; sta->tx_num_mpdu_fail += status->retry_count; if (time_after(jiffies, srctrl->last_rate_change + RATE_CONTROL_INTERVAL) && srctrl->tx_num_xmit > RATE_CONTROL_MIN_TX) { u32 per_failed; srctrl->last_rate_change = jiffies; per_failed = (100 * sta->tx_num_mpdu_fail) / (sta->tx_num_mpdu_fail + sta->tx_num_mpdu_ok); /* TODO: calculate average per_failed to make adjusting * parameters easier */ #if 0 if (net_ratelimit()) { printk(KERN_DEBUG "MPDU fail=%d ok=%d per_failed=%d\n", sta->tx_num_mpdu_fail, sta->tx_num_mpdu_ok, per_failed); } #endif /* * XXX: Make these configurable once we have an * interface to the rate control algorithms */ if (per_failed > RATE_CONTROL_NUM_DOWN) { rate_control_rate_dec(local, sta); } else if (per_failed < RATE_CONTROL_NUM_UP) { rate_control_rate_inc(local, sta); } srctrl->tx_avg_rate_sum += status->control.rate->rate; srctrl->tx_avg_rate_num++; srctrl->tx_num_failures = 0; srctrl->tx_num_xmit = 0; } else if (sta->tx_num_consecutive_failures >= RATE_CONTROL_EMERG_DEC) { rate_control_rate_dec(local, sta); } if (srctrl->avg_rate_update + 60 * HZ < jiffies) { srctrl->avg_rate_update = jiffies; if (srctrl->tx_avg_rate_num > 0) { #ifdef CONFIG_MAC80211_VERBOSE_DEBUG DECLARE_MAC_BUF(mac); printk(KERN_DEBUG "%s: STA %s Average rate: " "%d (%d/%d)\n", dev->name, print_mac(mac, sta->addr), srctrl->tx_avg_rate_sum / srctrl->tx_avg_rate_num, srctrl->tx_avg_rate_sum, srctrl->tx_avg_rate_num); #endif /* CONFIG_MAC80211_VERBOSE_DEBUG */ srctrl->tx_avg_rate_sum = 0; srctrl->tx_avg_rate_num = 0; } } sta_info_put(sta); }
struct ieee80211_key *ieee80211_key_alloc(struct ieee80211_sub_if_data *sdata, struct sta_info *sta, enum ieee80211_key_alg alg, int idx, size_t key_len, const u8 *key_data) { struct ieee80211_key *key; BUG_ON(idx < 0 || idx >= NUM_DEFAULT_KEYS); key = kzalloc(sizeof(struct ieee80211_key) + key_len, GFP_KERNEL); if (!key) return NULL; /* * Default to software encryption; we'll later upload the * key to the hardware if possible. */ key->conf.flags = 0; key->flags = 0; key->conf.alg = alg; key->conf.keyidx = idx; key->conf.keylen = key_len; memcpy(key->conf.key, key_data, key_len); key->local = sdata->local; key->sdata = sdata; key->sta = sta; if (alg == ALG_CCMP) { /* * Initialize AES key state here as an optimization so that * it does not need to be initialized for every packet. */ key->u.ccmp.tfm = ieee80211_aes_key_setup_encrypt(key_data); if (!key->u.ccmp.tfm) { ieee80211_key_free(key); return NULL; } } ieee80211_debugfs_key_add(key->local, key); /* remove key first */ if (sta) ieee80211_key_free(sta->key); else ieee80211_key_free(sdata->keys[idx]); if (sta) { ieee80211_debugfs_key_sta_link(key, sta); /* * some hardware cannot handle TKIP with QoS, so * we indicate whether QoS could be in use. */ if (sta->flags & WLAN_STA_WME) key->conf.flags |= IEEE80211_KEY_FLAG_WMM_STA; } else { if (sdata->type == IEEE80211_IF_TYPE_STA) { struct sta_info *ap; /* same here, the AP could be using QoS */ ap = sta_info_get(key->local, key->sdata->u.sta.bssid); if (ap) { if (ap->flags & WLAN_STA_WME) key->conf.flags |= IEEE80211_KEY_FLAG_WMM_STA; sta_info_put(ap); } } } /* enable hwaccel if appropriate */ if (netif_running(key->sdata->dev)) ieee80211_key_enable_hw_accel(key); if (sta) rcu_assign_pointer(sta->key, key); else rcu_assign_pointer(sdata->keys[idx], key); list_add(&key->list, &sdata->key_list); return key; }
static void rate_control_pid_tx_status(void *priv, struct net_device *dev, struct sk_buff *skb, struct ieee80211_tx_status *status) { struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; struct ieee80211_sub_if_data *sdata; struct rc_pid_info *pinfo = priv; struct sta_info *sta; struct rc_pid_sta_info *spinfo; unsigned long period; sta = sta_info_get(local, hdr->addr1); if (!sta) return; /* Don't update the state if we're not controlling the rate. */ sdata = IEEE80211_DEV_TO_SUB_IF(sta->dev); if (sdata->bss && sdata->bss->force_unicast_rateidx > -1) { sta->txrate = sdata->bss->max_ratectrl_rateidx; return; } /* Ignore all frames that were sent with a different rate than the rate * we currently advise mac80211 to use. */ if (status->control.rate != &local->oper_hw_mode->rates[sta->txrate]) goto ignore; spinfo = sta->rate_ctrl_priv; spinfo->tx_num_xmit++; #ifdef CONFIG_MAC80211_DEBUGFS rate_control_pid_event_tx_status(&spinfo->events, status); #endif /* We count frames that totally failed to be transmitted as two bad * frames, those that made it out but had some retries as one good and * one bad frame. */ if (status->excessive_retries) { spinfo->tx_num_failed += 2; spinfo->tx_num_xmit++; } else if (status->retry_count) { spinfo->tx_num_failed++; spinfo->tx_num_xmit++; } if (status->excessive_retries) { sta->tx_retry_failed++; sta->tx_num_consecutive_failures++; sta->tx_num_mpdu_fail++; } else { sta->last_ack_rssi[0] = sta->last_ack_rssi[1]; sta->last_ack_rssi[1] = sta->last_ack_rssi[2]; sta->last_ack_rssi[2] = status->ack_signal; sta->tx_num_consecutive_failures = 0; sta->tx_num_mpdu_ok++; } sta->tx_retry_count += status->retry_count; sta->tx_num_mpdu_fail += status->retry_count; /* Update PID controller state. */ period = (HZ * pinfo->sampling_period + 500) / 1000; if (!period) period = 1; if (time_after(jiffies, spinfo->last_sample + period)) rate_control_pid_sample(pinfo, local, sta); ignore: sta_info_put(sta); }
static void rate_control_simple_tx_status(void *priv, struct net_device *dev, struct sk_buff *skb, struct ieee80211_tx_status *status) { struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; struct sta_info *sta; struct sta_rate_control *srctrl; sta = sta_info_get(local, hdr->addr1); if (!sta) return; srctrl = sta->rate_ctrl_priv; srctrl->tx_num_xmit++; if (status->excessive_retries) { sta->antenna_sel_tx = sta->antenna_sel_tx == 1 ? 2 : 1; sta->antenna_sel_rx = sta->antenna_sel_rx == 1 ? 2 : 1; if (local->sta_antenna_sel == STA_ANTENNA_SEL_SW_CTRL_DEBUG) { printk(KERN_DEBUG "%s: " MAC_FMT " TX antenna --> %d " "RX antenna --> %d (@%lu)\n", dev->name, MAC_ARG(hdr->addr1), sta->antenna_sel_tx, sta->antenna_sel_rx, jiffies); } srctrl->tx_num_failures++; sta->tx_retry_failed++; sta->tx_num_consecutive_failures++; sta->tx_num_mpdu_fail++; } else { sta->last_ack_rssi[0] = sta->last_ack_rssi[1]; sta->last_ack_rssi[1] = sta->last_ack_rssi[2]; sta->last_ack_rssi[2] = status->ack_signal; sta->tx_num_consecutive_failures = 0; sta->tx_num_mpdu_ok++; } sta->tx_retry_count += status->retry_count; sta->tx_num_mpdu_fail += status->retry_count; if (time_after(jiffies, srctrl->last_rate_change + RATE_CONTROL_INTERVAL) && srctrl->tx_num_xmit > RATE_CONTROL_MIN_TX) { u32 per_failed; srctrl->last_rate_change = jiffies; per_failed = (100 * sta->tx_num_mpdu_fail) / (sta->tx_num_mpdu_fail + sta->tx_num_mpdu_ok); /* TODO: calculate average per_failed to make adjusting * parameters easier */ #if 0 if (net_ratelimit()) { printk(KERN_DEBUG "MPDU fail=%d ok=%d per_failed=%d\n", sta->tx_num_mpdu_fail, sta->tx_num_mpdu_ok, per_failed); } #endif if (per_failed > local->rate_ctrl_num_down) { rate_control_rate_dec(local, sta); } else if (per_failed < local->rate_ctrl_num_up) { rate_control_rate_inc(local, sta); } srctrl->tx_avg_rate_sum += status->control.rate->rate; srctrl->tx_avg_rate_num++; srctrl->tx_num_failures = 0; srctrl->tx_num_xmit = 0; } else if (sta->tx_num_consecutive_failures >= RATE_CONTROL_EMERG_DEC) { rate_control_rate_dec(local, sta); } if (srctrl->avg_rate_update + 60 * HZ < jiffies) { srctrl->avg_rate_update = jiffies; if (srctrl->tx_avg_rate_num > 0) { #ifdef CONFIG_MAC80211_VERBOSE_DEBUG printk(KERN_DEBUG "%s: STA " MAC_FMT " Average rate: " "%d (%d/%d)\n", dev->name, MAC_ARG(sta->addr), srctrl->tx_avg_rate_sum / srctrl->tx_avg_rate_num, srctrl->tx_avg_rate_sum, srctrl->tx_avg_rate_num); #endif /* CONFIG_MAC80211_VERBOSE_DEBUG */ srctrl->tx_avg_rate_sum = 0; srctrl->tx_avg_rate_num = 0; } } sta_info_put(sta); }