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

📄 ieee80211_scan_ap.c.svn-base

📁 最新之atheros芯片driver source code, 基于linux操作系统,內含atheros芯片HAL全部代码
💻 SVN-BASE
📖 第 1 页 / 共 3 页
字号:
	struct ieee80211_channel *a = ((struct channel *)_a)->chan;	struct ieee80211_channel *b = ((struct channel *)_b)->chan;	struct pc_params *params = ((struct channel *)_a)->params;	struct ieee80211com *ic = params->vap->iv_ic;	int res;#define EVALUATE_CRITERION(name, ...) do {			\	if ((res = pc_cmp_##name(__VA_ARGS__)) != 0) 		\		return res;					\} while (0)	EVALUATE_CRITERION(radar, a, b);	EVALUATE_CRITERION(keepmode, params, a, b);	EVALUATE_CRITERION(sc, ic, a, b);	/* XXX: rssi useless? pick_channel evaluates it anyway */	EVALUATE_CRITERION(rssi, params->ss->ss_priv, a, b);	EVALUATE_CRITERION(samechan, ic, a, b);	EVALUATE_CRITERION(orig, (struct channel *)_a, (struct channel *)_b);#undef EVALUATE_CRITERION	return res;}/* This function must be invoked with locks acquired */static voidpc_swap(void *a, void *b, int n){	struct ieee80211_channel *t = ((struct channel *)a)->chan;	int i;	((struct channel *)a)->chan = ((struct channel *)b)->chan;	((struct channel *)b)->chan = t;	i = ((struct channel *)a)->orig;	((struct channel *)a)->orig = ((struct channel *)b)->orig;	((struct channel *)b)->orig = i;	/* (struct channel *)x->params doesn't have to be swapped, because it 	 * is the same across all channels */}/* Pick a quiet channel to use for ap operation. * Must be invoked while we hold the locks. */static struct ieee80211_channel *pick_channel(struct ieee80211_scan_state *ss, struct ieee80211vap *vap, 		u_int32_t flags){	struct ieee80211com *ic = vap->iv_ic;	unsigned int i, best_rssi;	int ss_last = ss->ss_last;	struct ieee80211_channel *best;	struct ap_state *as = ss->ss_priv;	struct channel chans[ss_last]; /* actually ss_last-1 is required */	struct channel *c = NULL;	struct pc_params params = { vap, ss, flags };	int benefit = 0;	int sta_assoc = 0;	for (i = 0; i < ss_last; i++) {		chans[i].chan = ss->ss_chans[i];		chans[i].orig = i;		chans[i].params = &params;	}	sort(chans, ss_last, sizeof(*chans), pc_cmp, pc_swap);#ifdef IEEE80211_DEBUG	for (i = 0; i < ss_last; i++) {		int chan = ieee80211_chan2ieee(ic, chans[i].chan);		IEEE80211_DPRINTF(vap, IEEE80211_MSG_SCAN, "%s: channel %u, "				"rssi %d, radar %d, cn %d, km %d\n",				__func__, chan, as->as_maxrssi[chan], 				IEEE80211_IS_CHAN_RADAR(chans[i].chan),				ic->ic_chan_nodes[chans[i].chan->ic_ieee],				!!IEEE80211_ARE_CHANS_SAME_MODE(chans[i].chan, 					ic->ic_bsschan));	}#endif /* IEEE80211_DEBUG */	best = NULL;	best_rssi = 0xff; /* If signal is bigger than 0xff, we'd be melting. */	for (i = 0; i < ss_last; i++) {		c = &chans[i];		benefit = best_rssi - as->as_maxrssi[c->chan->ic_ieee];		sta_assoc = ic->ic_sta_assoc;		/* Don't switch... */		if (benefit <= 0)			continue;		/* Verify channel is not marked for non-occupancy */		if (IEEE80211_IS_CHAN_RADAR(c->chan))			continue;		/* Do not select 802.11a ST if mode is specified and is not 		 * 802.11a ST */		if (as->as_required_mode &&		    IEEE80211_IS_CHAN_STURBO(c->chan) &&		    (as->as_vap_desired_mode != IEEE80211_MODE_TURBO_STATIC_A))			continue;		/* Verify mode matches any fixed mode specified */		if ((c->chan->ic_flags & as->as_required_mode) != 				as->as_required_mode)			continue;		if ((ic->ic_bsschan != NULL) &&			(ic->ic_bsschan != IEEE80211_CHAN_ANYC)) {			/* Make sure the channels are the same mode */			if ((flags & IEEE80211_SCAN_KEEPMODE) &&				!IEEE80211_ARE_CHANS_SAME_MODE(c->chan,					ic->ic_bsschan))				/* break the loop as the subsequent chans won't be 				 * better */				break;		}		if (sta_assoc != 0) {			int sl = ic->ic_cn_total - 				ic->ic_chan_nodes[c->chan->ic_ieee]; /* count */			if (ic->ic_sc_algorithm == IEEE80211_SC_LOOSE) {				int sl_max = ic->ic_sc_sldg * benefit;				sl = 1000 * sl / sta_assoc; /* permil */				IEEE80211_DPRINTF(vap, IEEE80211_MSG_SCAN,						"%s: chan %d, dB gained: %d, "						"STAs lost: %d permil (max %d)\n",						__func__, c->chan->ic_ieee, 						benefit, sl, sl_max);				if (sl > sl_max)					continue;			} else if (((ic->ic_sc_algorithm == 						 IEEE80211_SC_TIGHT) ||					(ic->ic_sc_algorithm == 						 IEEE80211_SC_STRICT)) && 					(sl > 0)) {				/* Break the loop as the subsequent chans 				 * won't be better. */				break;			}		}		best = c->chan;		best_rssi = as->as_maxrssi[best->ic_ieee];	}	if (best != NULL) {		i = best->ic_ieee;		IEEE80211_DPRINTF(vap, IEEE80211_MSG_SCAN,				"%s: best: channel %u rssi %d\n",				__func__, i, as->as_maxrssi[i]);	}	return best;}static intap_end(struct ieee80211_scan_state *ss, struct ieee80211vap *vap,		int (*action)(struct ieee80211vap *, 			const struct ieee80211_scan_entry *), 		u_int32_t flags){	struct ap_state *as = ss->ss_priv;	struct ieee80211_channel *bestchan = NULL;	struct ieee80211com *ic = NULL;	int res = 1;	SCAN_AP_LOCK_IRQ(as);	KASSERT(vap->iv_opmode == IEEE80211_M_HOSTAP,		("wrong opmode %u", vap->iv_opmode));	ic = vap->iv_ic;	bestchan = pick_channel(ss, vap, flags);	if (bestchan == NULL) {		if (ss->ss_last > 0) {			/* no suitable channel, should not happen */			printk(KERN_ERR "%s: %s: no suitable channel! "				"(should not happen)\n", 				DEV_NAME(vap->iv_dev), __func__);		}		res = 1; /* Do NOT restart scan */	} else {		struct ieee80211_scan_entry se;		/* XXX: notify all VAPs? */		/* if this is a dynamic turbo frequency , start with normal 		 * mode first */		if (IEEE80211_IS_CHAN_TURBO(bestchan) && 				!IEEE80211_IS_CHAN_STURBO(bestchan)) {			if ((bestchan = ieee80211_find_channel(ic, 					bestchan->ic_freq, bestchan->ic_flags &					~IEEE80211_CHAN_TURBO)) == NULL) {				/* should never happen ?? */				SCAN_AP_UNLOCK_IRQ_EARLY(as);				return 0;			}		}		memset(&se, 0, sizeof(se));		se.se_chan = bestchan;		as->as_action = ss->ss_ops->scan_default;		if (action)			as->as_action = action;		as->as_selbss = se;		/* Must defer action to avoid possible recursive call through 		 * 80211 state machine, which would result in recursive 		 * locking. */		IEEE80211_SCHEDULE_TQUEUE(&as->as_actiontq);		res = 1;	}	SCAN_AP_UNLOCK_IRQ(as);	return res;}static voidap_age(struct ieee80211_scan_state *ss){	struct ap_state *as = ss->ss_priv;	struct scan_entry *se, *next;	SCAN_AP_LOCK_IRQ(as);	TAILQ_FOREACH_SAFE(se, &as->as_entry, se_list, next) {		if (se->se_notseen > AP_PURGE_SCANS) {			TAILQ_REMOVE(&as->as_entry, se, se_list);			LIST_REMOVE(se, se_hash);			FREE(se, M_80211_SCAN);		}	}	SCAN_AP_UNLOCK_IRQ(as);}static intap_iterate(struct ieee80211_scan_state *ss,	ieee80211_scan_iter_func *f, void *arg){	struct ap_state *as = ss->ss_priv;	struct scan_entry *se;	u_int gen;	int res = 0;	SCAN_AP_GEN_LOCK(as);	gen = as->as_scangen++;restart:	SCAN_AP_LOCK_IRQ(as);	TAILQ_FOREACH(se, &as->as_entry, se_list) {		if (se->se_scangen != gen) {			se->se_scangen = gen;			/* update public state */			se->base.se_age = jiffies - se->se_lastupdate;			SCAN_AP_UNLOCK_IRQ_EARLY(as);			res = (*f)(arg, &se->base);			/* We probably ran out of buffer space. */			if (res != 0)				goto done;			goto restart;		}	}	SCAN_AP_UNLOCK_IRQ(as);done:	SCAN_AP_GEN_UNLOCK(as);	return res;}static voidap_assoc_success(struct ieee80211_scan_state *ss,	const u_int8_t macaddr[IEEE80211_ADDR_LEN]){	/* should not be called */}static voidap_assoc_fail(struct ieee80211_scan_state *ss,	const u_int8_t macaddr[IEEE80211_ADDR_LEN], int reason){	/* should not be called */}/* * Default action to execute when a scan entry is found for ap * mode.  Return 1 on success, 0 on failure */static intap_default_action(struct ieee80211vap *vap,	const struct ieee80211_scan_entry *se){	ieee80211_create_ibss(vap, se->se_chan);	return 1;}static voidaction_tasklet(IEEE80211_TQUEUE_ARG data){	struct ieee80211_scan_state *ss = (struct ieee80211_scan_state *)data;	struct ap_state *as = (struct ap_state *)ss->ss_priv;	struct ieee80211vap *vap = ss->ss_vap;	SCAN_AP_LOCK_IRQ(as);	if (as->as_newscan) {		struct scan_entry *se;		TAILQ_FOREACH(se, &as->as_entry, se_list) {			/*			 * If seen then reset and don't bump the count;			 * otherwise bump the ``not seen'' count.  Note			 * that this ensures that stations for which we			 * see frames while not scanning but not during			 * this scan will not be penalized.			 */			if (se->se_seen)				se->se_seen = 0;			else				se->se_notseen++;		}		as->as_newscan = 0;	}	SCAN_AP_UNLOCK_IRQ(as);	(*ss->ss_ops->scan_default)(vap, &as->as_selbss);}/* * Module glue. */MODULE_AUTHOR("Errno Consulting, Sam Leffler");MODULE_DESCRIPTION("802.11 wireless support: default ap scanner");#ifdef MODULE_LICENSEMODULE_LICENSE("Dual BSD/GPL");#endifstatic const struct ieee80211_scanner ap_default = {	.scan_name		= "default",	.scan_attach		= ap_attach,	.scan_detach		= ap_detach,	.scan_start		= ap_start,	.scan_restart		= ap_restart,	.scan_cancel		= ap_cancel,	.scan_end		= ap_end,	.scan_flush		= ap_flush,	.scan_add		= ap_add,	.scan_age		= ap_age,	.scan_iterate		= ap_iterate,	.scan_assoc_success	= ap_assoc_success,	.scan_assoc_fail	= ap_assoc_fail,	.scan_default		= ap_default_action,};static int __initinit_scanner_ap(void){	ieee80211_scanner_register(IEEE80211_M_HOSTAP, &ap_default);	return 0;}module_init(init_scanner_ap);static void __exitexit_scanner_ap(void){	ieee80211_scanner_unregister_all(&ap_default);}module_exit(exit_scanner_ap);

⌨️ 快捷键说明

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