⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 minstrel.c

📁 madwifi driver, linux system
💻 C
📖 第 1 页 / 共 3 页
字号:
ath_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 voidath_timer_function(unsigned long data){	struct minstrel_softc *ssc = (struct minstrel_softc *) data;	struct ath_softc *sc = ssc->sc;	struct ieee80211com *ic;	struct net_device *dev = ssc->sc_dev;	struct timer_list *timer;	unsigned int interval = ath_timer_interval;	if (dev == NULL) 		DPRINTF(sc, "%s: 'dev' is null in this timer \n", __func__);	if (sc == NULL) 		DPRINTF(sc, "%s: 'sc' is null in this timer\n", __func__);	ic = &sc->sc_ic;	if (ssc->close_timer_now)		return;		if (dev->flags & IFF_RUNNING) {		sc->sc_stats.ast_rate_calls++;		if (ic->ic_opmode == IEEE80211_M_STA) {			struct ieee80211vap *tmpvap;			TAILQ_FOREACH(tmpvap, &ic->ic_vaps, iv_next) {				ath_rate_statistics(sc, tmpvap->iv_bss);/* NB: no reference */			}		} else                        ieee80211_iterate_nodes(&ic->ic_sta, ath_rate_statistics, sc);	}	if (ic->ic_opmode == IEEE80211_M_STA)		interval = ath_timer_interval >> 1;	timer  = &(ssc->timer);	if (timer == NULL) 		DPRINTF(sc, "%s: timer is null - leave it\n", __func__);        timer->expires = jiffies + ((HZ * interval) / 1000);        add_timer(timer);}static voidath_rate_statistics(void *arg, struct ieee80211_node *ni){        struct ath_node *an = (struct ath_node *) ni;        struct ieee80211_rateset *rs = &ni->ni_rates;        struct minstrel_node *rn = ATH_NODE_MINSTREL(an);        unsigned int i;        u_int32_t p;	u_int32_t micro_secs;	u_int32_t max_prob,    index_max_prob;	u_int32_t max_tp,      index_max_tp,      index_max_tp2;        	/* Calculate statistics for each date rate in the table */	/* micro_secs is the time to transmit 1200 bytes, or 9600 bits.*/        for (i = 0; i < rs->rs_nrates; i++) {		micro_secs = rn->perfect_tx_time[i];		if (micro_secs == 0) 			micro_secs = ONE_SECOND;		                if (rn->rs_rateattempts[i] != 0) {                        p = (rn->rs_ratesuccess[i] * 18000) / rn->rs_rateattempts[i];                        rn->rs_succ_hist[i] += rn->rs_ratesuccess[i];                        rn->rs_att_hist[i]  += rn->rs_rateattempts[i];			rn->rs_thisprob[i] = p;			p = ((p * (100 - ath_ewma_level)) + (rn->rs_probability[i] * ath_ewma_level))/100;			rn->rs_probability[i] = p;			rn->rs_this_tp[i] = p * (ONE_SECOND/micro_secs);			rn->rs_lastratesuccess[i] = rn->rs_ratesuccess[i];			rn->rs_lastrateattempts[i] = rn->rs_rateattempts[i];                        rn->rs_ratesuccess[i] = 0;                        rn->rs_rateattempts[i] = 0;		} else {			rn->rs_lastratesuccess[i] = 0;			rn->rs_lastrateattempts[i] = 0;		}		/* Sample less often below the 10% chance of success.		 * Sample less often above the 95% chance of success.		 * rn->rs_probability is in units of 0..18000(100%), which avoids rounding issues.*/		if ((rn->rs_probability[i] > 17100) || ( rn->rs_probability[i] < 1800)) {			rn->retry_adjusted_count[i] = rn->retry_count[i]>> 1;			if (rn->retry_adjusted_count[i] > 2)				rn->retry_adjusted_count[i] = 2;		} else 			rn->retry_adjusted_count[i] = rn->retry_count[i];		if (rn->retry_adjusted_count[i] == 0)			rn->retry_adjusted_count[i] = 1;	}         	/* The High speed rates (e.g 54mbps) is checked last. If	 * throughput is the same for two rates, we prefer the	 * lower rate, as this has a better chance of success. */	max_prob = 0; 	index_max_prob = 0;	max_tp = 0; 	index_max_tp  = 0;	index_max_tp2 = 0;		/* This code could have been moved up into the previous	 * loop. More readable to have it here */	for (i = 0; i < rs->rs_nrates; i++) {		if (max_tp < rn->rs_this_tp[i]) {			index_max_tp = i;			max_tp = rn->rs_this_tp[i];		}		if (max_prob < rn->rs_probability[i]) {			index_max_prob = i;			max_prob = rn->rs_probability[i];		}	}         	max_tp = 0;	for (i = 0; i < rs->rs_nrates; i++) {		if ((i != index_max_tp) && (max_tp < rn->rs_this_tp[i])) {			index_max_tp2 = i;			max_tp = rn->rs_this_tp[i];		}	}	rn->max_tp_rate   = index_max_tp;	rn->max_tp_rate2  = index_max_tp2;	rn->max_prob_rate = index_max_prob;	rn->current_rate  = index_max_tp;}static struct ath_ratectrl *ath_rate_attach(struct ath_softc *sc){	struct minstrel_softc *osc;	DPRINTF(sc, "%s: %s\n", dev_info, __func__);	        _MOD_INC_USE(THIS_MODULE, return NULL);	osc = kmalloc(sizeof(struct minstrel_softc), GFP_ATOMIC);	if (osc == NULL) {                _MOD_DEC_USE(THIS_MODULE);		return NULL;	}	osc->arc.arc_space = sizeof(struct minstrel_node);	osc->arc.arc_vap_space = 0;	osc->close_timer_now = 0;	init_timer(&osc->timer); 	osc->sc          = sc;	osc->sc_dev      = sc->sc_dev;	osc->timer.function = ath_timer_function;	osc->timer.data = (unsigned long)osc;	        osc->timer.expires = jiffies + HZ;	add_timer(&osc->timer);		return &osc->arc;}static void ath_rate_detach(struct ath_ratectrl *arc){ 	struct minstrel_softc *osc = (struct minstrel_softc *) arc;	osc->close_timer_now = 1;	del_timer(&osc->timer);        kfree(osc);        _MOD_DEC_USE(THIS_MODULE);}#ifdef CONFIG_SYSCTLstatic intath_proc_read_nodes(struct ieee80211vap *vap, char *buf, int space){        char *p = buf;        struct ieee80211_node *ni;        struct ath_node *an;        struct minstrel_node *odst;        struct ieee80211_node_table *nt =                (struct ieee80211_node_table *) &vap->iv_ic->ic_sta;        unsigned int x = 0;	unsigned int this_tp, this_prob, this_eprob;		struct ath_softc *sc = vap->iv_ic->ic_dev->priv;;        TAILQ_FOREACH(ni, &nt->nt_node, ni_list) {                /* Assume each node needs 1500 bytes */                if ((buf + space) < (p + 1500)) {			if ((buf + space) > (p + 100)) {				p += sprintf(p, "out of room for node %s\n\n", ether_sprintf(ni->ni_macaddr));				break;			}			DPRINTF(sc, "%s: out of memeory to write tall of the nodes\n", __func__);                        break;		}                an = ATH_NODE(ni);                odst = ATH_NODE_MINSTREL(an);                /* Skip ourself */                if (memcmp(vap->iv_myaddr, ni->ni_macaddr, IEEE80211_ADDR_LEN) == 0)                        continue;                p += sprintf(p, "rate data for node:: %s\n", ether_sprintf(ni->ni_macaddr));                p += sprintf(p, "rate     throughput  ewma prob   this prob  this succ/attempt   success    attempts\n");                for (x = 0; x < odst->num_rates; x++) {                        p += sprintf(p, "%s",                                        (x == odst->current_rate) ? "T" : " ");						p += sprintf(p, "%s",				     (x == odst->max_tp_rate2) ? "t" : " ");			p += sprintf(p, "%s",				     (x == odst->max_prob_rate) ? "P" : " ");                        p += sprintf(p, "%3d%s",                                        odst->rates[x].rate/2,                                        (odst->rates[x].rate & 0x1) != 0 ? ".5" : "  ");			this_tp = ((odst->rs_this_tp[x] / 18000) * 96) >> 10;			this_prob = odst->rs_thisprob[x] / 18;			this_eprob = odst->rs_probability[x] / 18;                        p += sprintf(p, "  %6u.%1u   %6u.%1u   %6u.%1u        %3u(%3u)   %8llu    %8llu\n",				     this_tp / 10, this_tp % 10,				     this_eprob / 10, this_eprob % 10,				     this_prob / 10, this_prob % 10,				     odst->rs_lastratesuccess[x],				     odst->rs_lastrateattempts[x],				     odst->rs_succ_hist[x],				     odst->rs_att_hist[x]);		}		p += sprintf(p, "\n");		p += sprintf(p, "Total packet count::    ideal %d      lookaround %d\n\n", odst->packet_count, odst->sample_count);        }        return (p - buf);}static intath_proc_ratesample_open(struct inode *inode, struct file *file){        struct proc_ieee80211_priv *pv = NULL;        struct proc_dir_entry *dp = PDE(inode);        struct ieee80211vap *vap = dp->data;        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;        /* now read the data into the buffer */        pv->rlen = ath_proc_read_nodes(vap, pv->rbuf, MAX_PROC_IEEE80211_SIZE);        return 0;}static struct file_operations ath_proc_ratesample_ops = {        .read = NULL,        .write = NULL,        .open = ath_proc_ratesample_open,        .release = NULL,};static void ath_rate_dynamic_proc_register(struct ieee80211vap *vap){        /* Create proc entries for the rate control algorithm */        ieee80211_proc_vcreate(vap, &ath_proc_ratesample_ops, "rate_info");}#endif /* CONFIG_SYSCTL */static struct ieee80211_rate_ops ath_rate_ops = {        .ratectl_id = IEEE80211_RATE_MINSTREL,        .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/Derek Smithies");MODULE_DESCRIPTION("Minstrel Rate bit-rate selection algorithm for Atheros devices");#ifdef MODULE_VERSIONMODULE_VERSION(RELEASE_VERSION);#endif#ifdef MODULE_LICENSEMODULE_LICENSE("Dual BSD/GPL");#endifstatic int __init ath_rate_minstrel_init(void){	printk(KERN_INFO "%s: Minstrel automatic rate control "			"algorithm %s\n", dev_info, version);	printk(KERN_INFO "%s: Look around rate set to %d%%\n", 			dev_info, ath_lookaround_rate);	printk(KERN_INFO "%s: EWMA rolloff level set to %d%%\n", 			dev_info, ath_ewma_level);	printk(KERN_INFO "%s: Max Segment size in the mrr set "			"to %d us\n", dev_info, ath_segment_size);        return ieee80211_rate_register(&ath_rate_ops);}module_init(ath_rate_minstrel_init);static void __exit ath_rate_minstrel_exit(void){        ieee80211_rate_unregister(&ath_rate_ops);	printk(KERN_INFO "%s: unloaded\n", dev_info);}module_exit(ath_rate_minstrel_exit);/* The comment below is magic for those who use emacs to edit this file. *//* With the comment below, the tab key does auto indent to 8 spaces.     */ /* * Local Variables: * mode:c * c-file-style:linux * c-basic-offset:8 * End: */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -