📄 sample.c
字号:
update_stats(sc, an, frame_size, ndx[1], tries[1], ndx[2], tries[2], ndx[3], tries[3], 0, 0, short_tries, ds->ds_txstat.ts_longretry + 1 - tries[0], ds->ds_txstat.ts_status); if (tries[2] && finalTSIdx > 1) update_stats(sc, an, frame_size, ndx[2], tries[2], ndx[3], tries[3], 0, 0, 0, 0, short_tries, ds->ds_txstat.ts_longretry + 1 - tries[0] - tries[1], ds->ds_txstat.ts_status); if (tries[3] && finalTSIdx > 2) update_stats(sc, an, frame_size, ndx[3], tries[3], 0, 0, 0, 0, 0, 0, short_tries, ds->ds_txstat.ts_longretry + 1 - tries[0] - tries[1] - tries[2], ds->ds_txstat.ts_status); }}static voidath_rate_newassoc(struct ath_softc *sc, struct ath_node *an, int isnew){ DPRINTF(sc, "%s: %s %s\n", dev_info, ether_sprintf(an->an_node.ni_macaddr), __func__); if (isnew) ath_rate_ctl_reset(sc, &an->an_node);}/* * Initialize the tables for a node. */static voidath_rate_ctl_reset(struct ath_softc *sc, struct ieee80211_node *ni){ struct ath_node *an = ATH_NODE(ni); struct sample_node *sn = ATH_NODE_SAMPLE(an); struct ieee80211vap *vap = ni->ni_vap; const HAL_RATE_TABLE *rt = sc->sc_currates; unsigned int x, y; unsigned int srate; sn->num_rates = 0; if (rt == NULL) { printk(KERN_WARNING "no rates yet! mode %u\n", sc->sc_curmode); return; } sn->static_rate_ndx = -1; sn->num_rates = ni->ni_rates.rs_nrates; for (x = 0; x < ni->ni_rates.rs_nrates; x++) { sn->rates[x].rate = ni->ni_rates.rs_rates[x] & IEEE80211_RATE_VAL; sn->rates[x].rix = sc->sc_rixmap[sn->rates[x].rate]; if (sn->rates[x].rix == 0xff) { DPRINTF(sc, "%s: %s ignore bogus rix at %u\n", dev_info, __func__, x); continue; } sn->rates[x].rateCode = rt->info[sn->rates[x].rix].rateCode; sn->rates[x].shortPreambleRateCode = rt->info[sn->rates[x].rix].rateCode | rt->info[sn->rates[x].rix].shortPreamble; } ni->ni_txrate = 0; sn->num_rates = ni->ni_rates.rs_nrates; if (sn->num_rates <= 0) { DPRINTF(sc, "%s: %s %s no rates (fixed %u) \n", dev_info, __func__, ether_sprintf(ni->ni_macaddr), vap->iv_fixed_rate); /* there are no rates yet we're done */ return; } if (vap->iv_fixed_rate != -1) { srate = sn->num_rates - 1; /* * A fixed rate is to be used; ic_fixed_rate is an * index into the supported rate set. Convert this * to the index into the negotiated rate set for * the node. We know the rate is there because the * rate set is checked when the station associates. */ /* NB: the rate set is assumed sorted */ for (; srate >= 0 && (ni->ni_rates.rs_rates[srate] & IEEE80211_RATE_VAL) != vap->iv_fixed_rate; srate--); KASSERT(srate >= 0, ("fixed rate %u not in rate set", vap->iv_fixed_rate)); sn->static_rate_ndx = srate; ni->ni_txrate = srate; DPRINTF(sc, "%s: %s %s fixed rate %u%sMbps\n", dev_info, __func__, ether_sprintf(ni->ni_macaddr), sn->rates[srate].rate / 2, (sn->rates[srate].rate % 0x1) ? ".5" : " "); return; } for (y = 0; y < NUM_PACKET_SIZE_BINS; y++) { unsigned int size = bin_to_size(y); int ndx = 0; sn->packets_sent[y] = 0; sn->current_sample_ndx[y] = -1; sn->last_sample_ndx[y] = 0; for (x = 0; x < ni->ni_rates.rs_nrates; x++) { sn->stats[y][x].successive_failures = 0; sn->stats[y][x].tries = 0; sn->stats[y][x].total_packets = 0; sn->stats[y][x].packets_acked = 0; sn->stats[y][x].last_tx = 0; sn->stats[y][x].perfect_tx_time = calc_usecs_unicast_packet(sc, size, sn->rates[x].rix, 0, 0); sn->stats[y][x].average_tx_time = sn->stats[y][x].perfect_tx_time; } /* set the initial rate */ for (ndx = sn->num_rates - 1; ndx > 0; ndx--) if (sn->rates[ndx].rate <= 72) break; sn->current_rate[y] = ndx; } DPRINTF(sc, "%s: %s %s %u rates %u%sMbps (%uus)- %u%sMbps (%uus)\n", dev_info, __func__, ether_sprintf(ni->ni_macaddr), sn->num_rates, sn->rates[0].rate / 2, sn->rates[0].rate % 0x1 ? ".5" : "", sn->stats[1][0].perfect_tx_time, sn->rates[sn->num_rates-1].rate / 2, sn->rates[sn->num_rates-1].rate % 0x1 ? ".5" : "", sn->stats[1][sn->num_rates-1].perfect_tx_time); ni->ni_txrate = sn->current_rate[0];}static voidath_rate_cb(void *arg, struct ieee80211_node *ni){ ath_rate_ctl_reset(ni->ni_ic->ic_dev->priv, ni);}/* * Reset the rate control state for each 802.11 state transition. */static voidath_rate_newstate(struct ieee80211vap *vap, enum ieee80211_state newstate){ struct ieee80211com *ic = vap->iv_ic; if (newstate == IEEE80211_S_RUN) { if (ic->ic_opmode != IEEE80211_M_STA) { /* * Sync rates for associated stations and neighbors. */ ieee80211_iterate_nodes(&ic->ic_sta, ath_rate_cb, NULL); } ath_rate_newassoc(ic->ic_dev->priv, ATH_NODE(vap->iv_bss), 1); }}static struct ath_ratectrl *ath_rate_attach(struct ath_softc *sc){ struct sample_softc *osc; DPRINTF(sc, "%s: %s\n", dev_info, __func__); _MOD_INC_USE(THIS_MODULE, return NULL); osc = kmalloc(sizeof(struct sample_softc), GFP_ATOMIC); if (osc == NULL) { _MOD_DEC_USE(THIS_MODULE); return NULL; } osc->arc.arc_space = sizeof(struct sample_node); osc->arc.arc_vap_space = 0; osc->ath_smoothing_rate = ath_smoothing_rate; osc->ath_sample_rate = ath_sample_rate; return &osc->arc;}static voidath_rate_detach(struct ath_ratectrl *arc){ struct sample_softc *osc = (struct sample_softc *) arc; kfree(osc); _MOD_DEC_USE(THIS_MODULE);}static intproc_read_nodes(struct ieee80211vap *vap, const int size, char *buf, int space){ char *p = buf; struct ieee80211_node *ni; struct ath_node *an; struct sample_node *sn; struct ieee80211_node_table *nt = (struct ieee80211_node_table *) &vap->iv_ic->ic_sta; unsigned int x; unsigned int size_bin; TAILQ_FOREACH(ni, &nt->nt_node, ni_list) { /* Assume each node needs 500 bytes */ if (buf + space < p + 500) break; an = ATH_NODE(ni); sn = ATH_NODE_SAMPLE(an); /* Skip ourself */ if (memcmp(vap->iv_myaddr, ni->ni_macaddr, IEEE80211_ADDR_LEN)==0) { continue; } size_bin = size_to_bin(size); p += sprintf(p, "%s\n", ether_sprintf(ni->ni_macaddr)); p += sprintf(p, "rate\ttt\tperfect\tfailed\tpkts\tavg_tries\tlast_tx\n"); for (x = 0; x < sn->num_rates; x++) { unsigned int a = 1; unsigned int t = 1; p += sprintf(p, "%s", (x == sn->current_rate[size_bin]) ? "*" : " "); p += sprintf(p, "%3u%s", sn->rates[x].rate/2, (sn->rates[x].rate & 0x1) != 0 ? ".5" : " "); p += sprintf(p, "\t%4u\t%4u\t%2u\t%3u", sn->stats[size_bin][x].average_tx_time, sn->stats[size_bin][x].perfect_tx_time, sn->stats[size_bin][x].successive_failures, sn->stats[size_bin][x].total_packets); if (sn->stats[size_bin][x].total_packets) { a = sn->stats[size_bin][x].total_packets; t = sn->stats[size_bin][x].tries; } p += sprintf(p, "\t%u.%02u\t", t/a, (t*100/a) % 100); if (sn->stats[size_bin][x].last_tx) { unsigned d = jiffies - sn->stats[size_bin][x].last_tx; p += sprintf(p, "%u.%02u", d / HZ, d % HZ); } else { p += sprintf(p, "-"); } p += sprintf(p, "\n"); } printk("\n"); } return (p - buf);}static intproc_ratesample_open(struct inode *inode, struct file *file){ struct proc_ieee80211_priv *pv; struct proc_dir_entry *dp = PDE(inode); struct ieee80211vap *vap = dp->data; unsigned long size; if (!(file->private_data = kmalloc(sizeof(struct proc_ieee80211_priv), GFP_KERNEL))) return -ENOMEM; /* initially allocate both read and write buffers */ pv = (struct proc_ieee80211_priv *) file->private_data; memset(pv, 0, sizeof(struct proc_ieee80211_priv)); pv->rbuf = vmalloc(MAX_PROC_IEEE80211_SIZE); if (!pv->rbuf) { kfree(pv); return -ENOMEM; } pv->wbuf = vmalloc(MAX_PROC_IEEE80211_SIZE); if (!pv->wbuf) { vfree(pv->rbuf); kfree(pv); return -ENOMEM; } memset(pv->wbuf, 0, MAX_PROC_IEEE80211_SIZE); memset(pv->rbuf, 0, MAX_PROC_IEEE80211_SIZE); pv->max_wlen = MAX_PROC_IEEE80211_SIZE; pv->max_rlen = MAX_PROC_IEEE80211_SIZE; /* Determine what size packets to get stats for based on proc filename */ size = simple_strtoul(dp->name + 10, NULL, 0); /* now read the data into the buffer */ pv->rlen = proc_read_nodes(vap, size, pv->rbuf, MAX_PROC_IEEE80211_SIZE); return 0;}static struct file_operations proc_ratesample_ops = { .read = NULL, .write = NULL, .open = proc_ratesample_open, .release = NULL,};static voidath_rate_dynamic_proc_register(struct ieee80211vap *vap){ /* Create proc entries for the rate control algorithm */ ieee80211_proc_vcreate(vap, &proc_ratesample_ops, "ratestats_250"); ieee80211_proc_vcreate(vap, &proc_ratesample_ops, "ratestats_1600"); ieee80211_proc_vcreate(vap, &proc_ratesample_ops, "ratestats_3000"); }static struct ieee80211_rate_ops ath_rate_ops = { .ratectl_id = IEEE80211_RATE_SAMPLE, .node_init = ath_rate_node_init, .node_cleanup = ath_rate_node_cleanup, .findrate = ath_rate_findrate, .setupxtxdesc = ath_rate_setupxtxdesc, .tx_complete = ath_rate_tx_complete, .newassoc = ath_rate_newassoc, .newstate = ath_rate_newstate, .attach = ath_rate_attach, .detach = ath_rate_detach, .dynamic_proc_register = ath_rate_dynamic_proc_register,};MODULE_AUTHOR("John Bicket");MODULE_DESCRIPTION("SampleRate bit-rate selection algorithm for Atheros devices");#ifdef MODULE_VERSIONMODULE_VERSION(RELEASE_VERSION);#endif#ifdef MODULE_LICENSEMODULE_LICENSE("Dual BSD/GPL");#endifstatic int __initinit_ath_rate_sample(void){ printk(KERN_INFO "%s: %s\n", dev_info, version); return ieee80211_rate_register(&ath_rate_ops);}module_init(init_ath_rate_sample);static void __exitexit_ath_rate_sample(void){ ieee80211_rate_unregister(&ath_rate_ops); printk(KERN_INFO "%s: unloaded\n", dev_info);}module_exit(exit_ath_rate_sample);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -