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

📄 ieee80211_node.c.svn-base

📁 最新之atheros芯片driver source code, 基于linux操作系统,內含atheros芯片HAL全部代码
💻 SVN-BASE
📖 第 1 页 / 共 5 页
字号:
/* * Return the node for the sender of a frame; if the sender is unknown return  * NULL. The caller is expected to deal with this. (The frame is sent to all  * VAPs in this case). * * NB: A node reference is acquired here; the caller MUST release it. */struct ieee80211_node *ieee80211_find_rxnode(struct ieee80211com *ic,	const struct ieee80211_frame_min *wh){#define	IS_CTL(wh) \	((wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) == IEEE80211_FC0_TYPE_CTL)#define	IS_PSPOLL(wh) \	((wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK) == IEEE80211_FC0_SUBTYPE_PS_POLL)#define	IS_RTS(wh) \	((wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK) == IEEE80211_FC0_SUBTYPE_RTS)	struct ieee80211_node_table *nt;	struct ieee80211_node *ni;	/* XXX: check ic_bss first in station mode */	/* XXX: 4-address frames? */	nt = &ic->ic_sta;	IEEE80211_NODE_TABLE_LOCK_IRQ(nt);	/* NB: Control frames typically have one address, except	 * for RTS and PSPOLL */	if (IS_CTL(wh) && !IS_PSPOLL(wh) && !IS_RTS(wh)) 		ni = ieee80211_find_node_locked(nt, wh->i_addr1);	else		ni = ieee80211_find_node_locked(nt, wh->i_addr2);	IEEE80211_NODE_TABLE_UNLOCK_IRQ(nt);	return ni;#undef IS_PSPOLL#undef IS_CTL#undef IS_RTS}EXPORT_SYMBOL(ieee80211_find_rxnode);/* * Return the appropriate node for sending a data frame.  This handles node  * discovery in adhoc networks. * * NB: A node reference is acquired here; the caller MUST release it. */struct ieee80211_node *ieee80211_find_txnode(struct ieee80211vap *vap, const u_int8_t *mac){	struct ieee80211_node_table *nt;	struct ieee80211_node *ni = NULL;	/* The destination address should be in the node table	 * unless we are operating in station mode or this is a	 * multicast/broadcast frame. */	if (vap->iv_opmode == IEEE80211_M_STA || IEEE80211_IS_MULTICAST(mac))		return ieee80211_ref_node(vap->iv_bss);	/* XXX: Can't hold lock across dup_bss due to recursive locking. */	nt = &vap->iv_ic->ic_sta;	IEEE80211_NODE_TABLE_LOCK_IRQ(nt);	ni = ieee80211_find_node_locked(nt, mac);	IEEE80211_NODE_TABLE_UNLOCK_IRQ(nt);	if (ni == NULL) {		if (vap->iv_opmode == IEEE80211_M_IBSS ||		    vap->iv_opmode == IEEE80211_M_AHDEMO) {			/* In adhoc mode cons up a node for the destination.			 * Note that we need an additional reference for the			 * caller to be consistent with ieee80211_find_node. */			ni = ieee80211_fakeup_adhoc_node(vap, mac);			if (ni != NULL)				ieee80211_ref_node(ni);		} else {			IEEE80211_NOTE_MAC(vap, IEEE80211_MSG_OUTPUT, mac,				"no node, discard frame (%s)", __func__);			vap->iv_stats.is_tx_nonode++;		}	}	return ni;}EXPORT_SYMBOL(ieee80211_find_txnode);/* Context: hwIRQ, softIRQ and process context. */voidieee80211_free_node(struct ieee80211_node *ni){	struct ieee80211vap *vap = ni->ni_vap;	atomic_dec(&ni->ni_ic->ic_node_counter);	node_print_message(IEEE80211_MSG_NODE | IEEE80211_MSG_NODE_REF,			   1 /* show counter */, 			   0 /* adjust refcount */, 			   ni, 			   "free" /* message */);	if (vap->iv_aid_bitmap != NULL)		IEEE80211_AID_CLR(vap, ni->ni_associd);	vap->iv_ic->ic_node_free(ni);}EXPORT_SYMBOL(ieee80211_free_node);static void _reset_node(void *arg, struct ieee80211_node *ni){	if (ni->ni_associd != 0) {		struct ieee80211vap *vap = ni->ni_vap;		if (vap->iv_auth->ia_node_leave != NULL)			vap->iv_auth->ia_node_leave(ni);		if (vap->iv_aid_bitmap != NULL)			IEEE80211_AID_CLR(vap, ni->ni_associd);	}	ieee80211_node_leave(ni);}static voidieee80211_node_table_reset(struct ieee80211_node_table *nt,	struct ieee80211vap *vap){	ieee80211_iterate_dev_nodes(vap->iv_dev, nt, _reset_node, NULL);}static voidieee80211_node_table_cleanup(struct ieee80211_node_table *nt){	struct ieee80211com *ic = nt->nt_ic;	struct ieee80211_node *ni, *next;	TAILQ_FOREACH_SAFE(ni, &nt->nt_node, ni_list, next) {		if (ni->ni_associd != 0) {			struct ieee80211vap *vap = ni->ni_vap;			if (vap->iv_auth->ia_node_leave != NULL)				vap->iv_auth->ia_node_leave(ni);			if (vap->iv_aid_bitmap != NULL)				IEEE80211_AID_CLR(vap, ni->ni_associd);		}		ic->ic_node_cleanup(ni);	}	del_timer(&nt->nt_wds_aging_timer);	IEEE80211_SCAN_LOCK_DESTROY(nt);	IEEE80211_NODE_TABLE_LOCK_DESTROY(nt);}/* * Timeout inactive stations and do related housekeeping. * Note that we cannot hold the node lock while sending a * frame as this would lead to a LOR.  Instead we use a * generation number to mark nodes that we've scanned and * drop the lock and restart a scan if we have to time out * a node.  Since we are single-threaded by virtue of * controlling the inactivity timer we can be sure this will * process each node only once. * * Context: softIRQ (tasklet) */static voidieee80211_timeout_stations(struct ieee80211_node_table *nt){	struct ieee80211com *ic = nt->nt_ic;	struct ieee80211_node *ni;	u_int gen;	int isadhoc;	isadhoc = (ic->ic_opmode == IEEE80211_M_IBSS ||		   ic->ic_opmode == IEEE80211_M_AHDEMO);	IEEE80211_SCAN_LOCK_IRQ(nt);	gen = ++nt->nt_scangen;restart:	IEEE80211_NODE_TABLE_LOCK_IRQ(nt);	TAILQ_FOREACH(ni, &nt->nt_node, ni_list) {		if (ni->ni_scangen == gen)	/* previously handled */			continue;		ni->ni_scangen = gen;		/*		 * Free fragment if not needed anymore		 * (last fragment older than 1s).		 * XXX doesn't belong here		 */		if (ni->ni_rxfrag != NULL &&		    time_after(jiffies, ni->ni_rxfragstamp + HZ)) {			ieee80211_dev_kfree_skb(&ni->ni_rxfrag);		}		/*		 * Special case ourself; we may be idle for extended periods		 * of time and regardless reclaiming our state is wrong.		 * Special case a WDS link: it may be dead or idle, but it is 		 * never ok to reclaim it, as this will block transmissions		 * and nobody will recreate the node when the WDS peer is		 * available again. */		if ((ni == ni->ni_vap->iv_bss) ||		    (ni->ni_vap->iv_opmode == IEEE80211_M_WDS && 		     !memcmp(ni->ni_macaddr, ni->ni_vap->wds_mac, ETH_ALEN)))		{			/* NB: don't permit it to go negative */			if (ni->ni_inact > 0)				ni->ni_inact--;			continue;		}		ni->ni_inact--;		if (ni->ni_associd != 0 || isadhoc) {			struct ieee80211vap *vap = ni->ni_vap;			/*			 * Age frames on the power save queue.			 */			if (ieee80211_node_saveq_age(ni) != 0 &&			    IEEE80211_NODE_SAVEQ_QLEN(ni) == 0 &&			    vap->iv_set_tim != NULL)				vap->iv_set_tim(ni, 0);			/*			 * Probe the station before time it out.  We			 * send a null data frame which may not be			 * universally supported by drivers (need it			 * for ps-poll support so it should be...).			 */			if (0 < ni->ni_inact &&			    ni->ni_inact <= vap->iv_inact_probe) {				IEEE80211_NOTE(vap,					IEEE80211_MSG_INACT | IEEE80211_MSG_NODE,					ni, "%s",					"probe station due to inactivity");				/*				 * Grab a reference before unlocking the table				 * so the node cannot be reclaimed before we				 * send the frame. ieee80211_send_nulldata				 * understands we've done this and reclaims the				 * ref for us as needed.				 */				ieee80211_ref_node(ni);				IEEE80211_NODE_TABLE_UNLOCK_IRQ_EARLY(nt);				ieee80211_send_nulldata(ni);				/* XXX stat? */				goto restart;			}		}		if (ni->ni_inact <= 0) {			IEEE80211_NOTE(ni->ni_vap,				IEEE80211_MSG_INACT | IEEE80211_MSG_NODE, ni,				"station timed out due to inactivity (refcnt %u)",				atomic_read(&ni->ni_refcnt));			/*			 * Send a deauthenticate frame and drop the station.			 * We grab a reference before unlocking the table so			 * the node cannot be reclaimed before we complete our			 * work.			 *			 * Separately we must drop the node lock before sending			 * in case the driver takes a lock, as this may result			 * in a LOR between the node lock and the driver lock.			 */			ni->ni_vap->iv_stats.is_node_timeout++;			ieee80211_ref_node(ni);			IEEE80211_NODE_TABLE_UNLOCK_IRQ_EARLY(nt);			if (ni->ni_associd != 0) {				IEEE80211_SEND_MGMT(ni,					IEEE80211_FC0_SUBTYPE_DEAUTH,					IEEE80211_REASON_AUTH_EXPIRE);			}			ieee80211_node_leave(ni);			ieee80211_unref_node(&ni);			goto restart;		}	}	IEEE80211_NODE_TABLE_UNLOCK_IRQ(nt);	IEEE80211_SCAN_UNLOCK_IRQ(nt);}/* * Per-ieee80211com inactivity timer callback. */static voidieee80211_node_timeout(unsigned long arg){	struct ieee80211com *ic = (struct ieee80211com *)arg;	ieee80211_scan_timeout(ic);	ieee80211_timeout_stations(&ic->ic_sta);	mod_timer(&ic->ic_inact, jiffies + IEEE80211_INACT_WAIT * HZ);}voidieee80211_iterate_nodes(struct ieee80211_node_table *nt,		ieee80211_iter_func *f, void *arg){	ieee80211_iterate_dev_nodes(NULL, nt, f, arg);}EXPORT_SYMBOL(ieee80211_iterate_nodes);voidieee80211_iterate_dev_nodes(struct net_device *dev,		struct ieee80211_node_table *nt,		ieee80211_iter_func *f, void *arg){	struct ieee80211_node *ni;	u_int gen;	IEEE80211_SCAN_LOCK_IRQ(nt);	gen = ++nt->nt_scangen;restart:	IEEE80211_NODE_TABLE_LOCK_IRQ(nt);	TAILQ_FOREACH(ni, &nt->nt_node, ni_list) {		if (dev != NULL && ni->ni_vap->iv_dev != dev)			continue;  /* skip node not for this vap */		if (ni->ni_scangen != gen) {			ni->ni_scangen = gen;			(void)ieee80211_ref_node(ni);			IEEE80211_NODE_TABLE_UNLOCK_IRQ_EARLY(nt);			(*f)(arg, ni);			ieee80211_unref_node(&ni);			goto restart;		}	}	IEEE80211_NODE_TABLE_UNLOCK_IRQ(nt);	IEEE80211_SCAN_UNLOCK_IRQ(nt);}EXPORT_SYMBOL(ieee80211_iterate_dev_nodes);voidieee80211_dump_node(struct ieee80211_node_table *nt, struct ieee80211_node *ni){	int i;	printk("0x%p: mac " MAC_FMT " (refcnt %d)\n", ni,		MAC_ADDR(ni->ni_macaddr), atomic_read(&ni->ni_refcnt));	printk("\tscangen %u authmode %u flags 0x%x\n",		ni->ni_scangen, ni->ni_authmode, ni->ni_flags);	printk("\tassocid 0x%x txpower %u vlan %u\n",		ni->ni_associd, ni->ni_txpower, ni->ni_vlan);	printk ("rxfragstamp %lu\n", ni->ni_rxfragstamp);	for (i = 0; i < 17; i++) {		printk("\t%d: txseq %u rxseq %u fragno %u\n", i,		       ni->ni_txseqs[i],		       ni->ni_rxseqs[i] >> IEEE80211_SEQ_SEQ_SHIFT,		       ni->ni_rxseqs[i] & IEEE80211_SEQ_FRAG_MASK);	}	printk("\trtsf %10llu rssi %u intval %u capinfo 0x%x\n",		ni->ni_rtsf, ni->ni_rssi, ni->ni_intval, ni->ni_capinfo);	printk("\tbssid " MAC_FMT " essid \"%.*s\" channel %u:0x%x\n",		MAC_ADDR(ni->ni_bssid),		ni->ni_esslen, ni->ni_essid,		ni->ni_chan != IEEE80211_CHAN_ANYC ?			ni->ni_chan->ic_freq : IEEE80211_CHAN_ANY,		ni->ni_chan != IEEE80211_CHAN_ANYC ? ni->ni_chan->ic_flags : 0);	printk("\tinact %u txrate %u\n",		ni->ni_inact, ni->ni_txrate);}voidieee80211_dump_nodes(struct ieee80211_node_table *nt){	ieee80211_iterate_nodes(nt,		(ieee80211_iter_func *)ieee80211_dump_node, nt);}/* * Handle a station joining an 11g network. */static voidieee80211_node_join_11g(struct ieee80211_node *ni){	struct ieee80211com *ic = ni->ni_ic;#ifdef IEEE80211_DEBUG	struct ieee80211vap *vap = ni->ni_vap;#endif	IEEE80211_LOCK_ASSERT(ic);	KASSERT(IEEE80211_IS_CHAN_ANYG(ic->ic_bsschan),	    ("not in 11g, bss %u:0x%x, curmode %u", ic->ic_bsschan->ic_freq,	    ic->ic_bsschan->ic_flags, ic->ic_curmode));	/*	 * Station isn't capable of short slot time.  Bump	 * the count of long slot time stations and disable	 * use of short slot time.  Note that the actual switch	 * over to long slot time use may not occur until the	 * next beacon transmission (per sec. 7.3.1.4 of 11g).	 */	if ((ni->ni_capinfo & IEEE80211_CAPINFO_SHORT_SLOTTIME) == 0) {		ic->ic_longslotsta++;		IEEE80211_NOTE(vap, IEEE80211_MSG_ASSOC, ni,			"station needs long slot time, count %d",			ic->ic_longslotsta);		/* XXX VAPs w/ conflicting needs won't work */		if (!IEEE80211_IS_CHAN_108G(ic->ic_bsschan)) {			/*			 * Don't force slot time when switched to turbo			 * mode as non-ERP stations won't be present; this			 * need only be done when on the normal G channel.			 */			ieee80211_set_shortslottime(ic, 0);		}	}	/*	 * If the new station is not an ERP station	 * then bump the counter and enable protection	 * if configured.	 */	if (!ieee80211_iserp_rateset(ic, &ni->ni_rates)) {		ic->ic_nonerpsta++;		IEEE80211_NOTE(vap, IEEE80211_MSG_ASSOC, ni,			"station is !ERP, %d non-ERP stations associated",			ic->ic_nonerpsta);		/*		 * If protection is configured, enable it.		 */		if (ic->ic_protmode != IEEE80211_PROT_NONE) {			IEEE80211_DPRINTF(vap, IEEE80211_MSG_ASSOC,				"%s: enable use of protection\n", __func__);			ic->ic_flags |= IEEE80211_F_USEPROT;		}		/*		 * If station does not support short preamble		 * then we must enable use of Barker preamble.		 */		if ((ni->ni_capinfo & IEEE80211_CAPINFO_SHORT_PREAMBLE) == 0) {			IEEE80211_NOTE(vap, IEEE80211_MSG_ASSOC, ni,				"%s", "station needs long preamble");			ic->ic_flags |= IEEE80211_F_USEBARKER;			ic->ic_flags &= ~IEEE80211_F_SHPREAMBLE;		}		/* Update ERP element if this is first non ERP station */		if (ic->ic_nonerpsta == 1)			ic->ic_flags_ext |= IEEE80211_FEXT_ERPUPDATE;	} else

⌨️ 快捷键说明

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