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

📄 ieee80211_output.c.svn-base

📁 最新之atheros芯片driver source code, 基于linux操作系统,內含atheros芯片HAL全部代码
💻 SVN-BASE
📖 第 1 页 / 共 5 页
字号:
	struct sk_buff *skb;	struct ieee80211_frame *wh;	u_int8_t *frm;	skb = ieee80211_getmgtframe(&frm, 0);	if (skb == NULL) {		/* XXX debug msg */		vap->iv_stats.is_tx_nobuf++;		ieee80211_unref_node(&ni);		return -ENOMEM;	}	wh = (struct ieee80211_frame *)		skb_push(skb, sizeof(struct ieee80211_frame));	ieee80211_send_setup(vap, ni, wh,		IEEE80211_FC0_TYPE_DATA | IEEE80211_FC0_SUBTYPE_NULL,		vap->iv_myaddr, ni->ni_macaddr, vap->iv_bssid);	/* NB: power management bit is never sent by an AP */	if ((IEEE80211_VAP_IS_SLEEPING(ni->ni_vap)) &&	    vap->iv_opmode != IEEE80211_M_HOSTAP &&	    vap->iv_opmode != IEEE80211_M_WDS)		wh->i_fc[1] |= IEEE80211_FC1_PWR_MGT;	IEEE80211_NODE_STAT(ni, tx_data);	IEEE80211_DPRINTF(vap, IEEE80211_MSG_DEBUG | IEEE80211_MSG_DUMPPKTS,		"[" MAC_FMT "] send null data frame on channel %u, pwr mgt %s\n",		MAC_ADDR(ni->ni_macaddr),		ieee80211_chan2ieee(ic, ic->ic_curchan),		wh->i_fc[1] & IEEE80211_FC1_PWR_MGT ? "ena" : "dis");	/* XXX assign some priority; this probably is wrong */	skb->priority = WME_AC_BE;	SKB_NI(skb) = PASS_NODE(ni);	(void) ic->ic_mgtstart(ic, skb);	/* cheat */	return 0;}/* * NB: unlike ieee80211_send_nulldata(), the node refcnt is *     bumped within this function. */intieee80211_send_qosnulldata(struct ieee80211_node *ni, int ac){	struct ieee80211vap *vap = ni->ni_vap;	struct ieee80211com *ic = ni->ni_ic;	struct sk_buff *skb;	struct ieee80211_qosframe *qwh;	u_int8_t *frm;	int tid;	skb = ieee80211_getmgtframe(&frm, 2);	if (skb == NULL) {		/* XXX debug msg */		vap->iv_stats.is_tx_nobuf++;		return -ENOMEM;	}	SKB_NI(skb) = ieee80211_ref_node(ni);	skb->priority = ac;	qwh = (struct ieee80211_qosframe *)skb_push(skb, sizeof(struct ieee80211_qosframe));	qwh = (struct ieee80211_qosframe *)skb->data;	ieee80211_send_setup(vap, ni, (struct ieee80211_frame *)qwh,		IEEE80211_FC0_TYPE_DATA,		vap->iv_myaddr, /* SA */		ni->ni_macaddr, /* DA */		vap->iv_bssid);	qwh->i_fc[0] = IEEE80211_FC0_VERSION_0 | IEEE80211_FC0_TYPE_DATA |		IEEE80211_FC0_SUBTYPE_QOS_NULL;	if (IEEE80211_VAP_IS_SLEEPING(ni->ni_vap))		qwh->i_fc[1] |= IEEE80211_FC1_PWR_MGT;	/* map from access class/queue to 11e header priority value */	tid = WME_AC_TO_TID(ac);	qwh->i_qos[0] = tid & IEEE80211_QOS_TID;	if (ic->ic_wme.wme_wmeChanParams.cap_wmeParams[ac].wmep_noackPolicy)		qwh->i_qos[0] |= (1 << IEEE80211_QOS_ACKPOLICY_S) & IEEE80211_QOS_ACKPOLICY;	qwh->i_qos[1] = 0;	IEEE80211_NODE_STAT(ni, tx_data);	if (WME_UAPSD_AC_CAN_TRIGGER(skb->priority, ni)) {		/* U-APSD power save queue */		/* XXXAPSD: assuming triggerable means deliverable */		M_FLAG_SET(skb, M_UAPSD);	}	(void) ic->ic_mgtstart(ic, skb);	/* cheat */	return 0;}EXPORT_SYMBOL(ieee80211_send_qosnulldata);/* * Ensure there is sufficient headroom and tailroom to * encapsulate the 802.11 data frame.  If room isn't * already there, reallocate so there is enough space. * Drivers and cipher modules assume we have done the * necessary work and fail rudely if they don't find * the space they need. */static struct sk_buff *ieee80211_skbhdr_adjust(struct ieee80211vap *vap, int hdrsize,	struct ieee80211_key *key, struct sk_buff *skb, int ismulticast){	/* XXX pre-calculate per node? */	int need_headroom = LLC_SNAPFRAMELEN + hdrsize + IEEE80211_ADDR_LEN;	int need_tailroom = 0;#ifdef ATH_SUPERG_FF	int isff = ATH_FF_MAGIC_PRESENT(skb);	int inter_headroom = sizeof(struct ether_header) + LLC_SNAPFRAMELEN + ATH_FF_MAX_HDR_PAD;	struct sk_buff *skb2 = NULL;	if (isff) {		need_headroom += sizeof(struct athl2p_tunnel_hdr) + ATH_FF_MAX_HDR_PAD +			inter_headroom;		skb2 = skb->next;	}#endif	if (key != NULL) {		const struct ieee80211_cipher *cip = key->wk_cipher;		/*		 * Adjust for crypto needs.  When hardware crypto is		 * being used we assume the hardware/driver will deal		 * with any padding (on the fly, without needing to		 * expand the frame contents).	When software crypto		 * is used we need to ensure room is available at the		 * front and back and also for any per-MSDU additions.		 */		/* XXX belongs in crypto code? */		need_headroom += cip->ic_header;		/* XXX pre-calculate per key */		if (key->wk_flags & IEEE80211_KEY_SWCRYPT)			need_tailroom += cip->ic_trailer;		/* 		** If tx frag is needed and cipher is TKIP,		** then allocate the additional tailroom for SW MIC computation.		*/		if (skb->len > vap->iv_fragthreshold &&		    !ismulticast &&		    cip->ic_cipher == IEEE80211_CIPHER_TKIP)			need_tailroom += cip->ic_miclen;		else			if (key->wk_flags & IEEE80211_KEY_SWMIC)				need_tailroom += cip->ic_miclen;	}	if (skb_shared(skb)) {		/* Take our own reference to the node in the clone */		ieee80211_ref_node(SKB_NI(skb));		/* Unshare the node, decrementing users in the old skb */		skb = skb_unshare(skb, GFP_ATOMIC);	}#ifdef ATH_SUPERG_FF	if (isff) {		if (skb == NULL) {			IEEE80211_DPRINTF(vap, IEEE80211_MSG_OUTPUT,				"%s: cannot unshare for encapsulation\n",				__func__);			vap->iv_stats.is_tx_nobuf++;			ieee80211_dev_kfree_skb(&skb2);			return NULL;		}		/* first skb header */		if (skb_headroom(skb) < need_headroom) {			struct sk_buff *tmp = skb;			skb = skb_realloc_headroom(skb, need_headroom);			if (skb == NULL) {				IEEE80211_DPRINTF(vap, IEEE80211_MSG_OUTPUT,					"%s: cannot expand storage (head1)\n",					__func__);				vap->iv_stats.is_tx_nobuf++;				ieee80211_dev_kfree_skb(&skb2);				return NULL;			} else				ieee80211_skb_copy_noderef(tmp, skb);			ieee80211_dev_kfree_skb(&tmp);			/* NB: cb[] area was copied, but not next ptr. must do that			 *     prior to return on success. */		}		/* second skb with header and tail adjustments possible */		if (skb_tailroom(skb2) < need_tailroom) {			int n = 0;			if (inter_headroom > skb_headroom(skb2))				n = inter_headroom - skb_headroom(skb2);			if (pskb_expand_head(skb2, n,			    need_tailroom - skb_tailroom(skb2), GFP_ATOMIC)) {				ieee80211_dev_kfree_skb(&skb2);				IEEE80211_DPRINTF(vap, IEEE80211_MSG_OUTPUT,					"%s: cannot expand storage (tail2)\n",					__func__);				vap->iv_stats.is_tx_nobuf++;				/* this shouldn't happen, but don't send first ff either */				ieee80211_dev_kfree_skb(&skb);			}		} else if (skb_headroom(skb2) < inter_headroom) {			struct sk_buff *tmp = skb2;			skb2 = skb_realloc_headroom(skb2, inter_headroom);			if (skb2 == NULL) {				IEEE80211_DPRINTF(vap, IEEE80211_MSG_OUTPUT,					"%s: cannot expand storage (head2)\n",					__func__);				vap->iv_stats.is_tx_nobuf++;				/* this shouldn't happen, but don't send first ff either */				ieee80211_dev_kfree_skb(&skb);				skb = NULL;			} else				ieee80211_skb_copy_noderef(tmp, skb);			ieee80211_dev_kfree_skb(&tmp);		}		if (skb) {			skb->next = skb2;		}		return skb;	}#endif /* ATH_SUPERG_FF */	if (skb == NULL) {		IEEE80211_DPRINTF(vap, IEEE80211_MSG_OUTPUT,			"%s: cannot unshare for encapsulation\n", __func__);		vap->iv_stats.is_tx_nobuf++;	} else if (skb_tailroom(skb) < need_tailroom) {		int n = 0;		if (need_headroom > skb_headroom(skb))			n = need_headroom - skb_headroom(skb);		if (pskb_expand_head(skb, n, need_tailroom -					skb_tailroom(skb), GFP_ATOMIC)) {			IEEE80211_DPRINTF(vap, IEEE80211_MSG_OUTPUT,				"%s: cannot expand storage (tail)\n", __func__);			vap->iv_stats.is_tx_nobuf++;			ieee80211_dev_kfree_skb(&skb);		}	} else if (skb_headroom(skb) < need_headroom) {		struct sk_buff *tmp = skb;		skb = skb_realloc_headroom(skb, need_headroom);		/* Increment reference count after copy */		if (skb == NULL) {			IEEE80211_DPRINTF(vap, IEEE80211_MSG_OUTPUT,				"%s: cannot expand storage (head)\n", __func__);			vap->iv_stats.is_tx_nobuf++;		} else			ieee80211_skb_copy_noderef(tmp, skb);		ieee80211_dev_kfree_skb(&tmp);	}	return skb;}#define	KEY_UNDEFINED(k)	((k).wk_cipher == &ieee80211_cipher_none)/* * Return the transmit key to use in sending a unicast frame. * If a unicast key is set we use that.  When no unicast key is set * we fall back to the default transmit key. */static __inline struct ieee80211_key *ieee80211_crypto_getucastkey(struct ieee80211vap *vap, struct ieee80211_node *ni){	if (KEY_UNDEFINED(ni->ni_ucastkey)) {		if (vap->iv_def_txkey == IEEE80211_KEYIX_NONE ||		    KEY_UNDEFINED(vap->iv_nw_keys[vap->iv_def_txkey]))			return NULL;		return &vap->iv_nw_keys[vap->iv_def_txkey];	} else		return &ni->ni_ucastkey;}/* * Return the transmit key to use in sending a multicast frame. * Multicast traffic always uses the group key which is installed as * the default tx key. */static __inline struct ieee80211_key *ieee80211_crypto_getmcastkey(struct ieee80211vap *vap, struct ieee80211_node *ni){	if (vap->iv_def_txkey == IEEE80211_KEYIX_NONE ||	    KEY_UNDEFINED(vap->iv_nw_keys[vap->iv_def_txkey]))		return NULL;	return &vap->iv_nw_keys[vap->iv_def_txkey];}/* * Encapsulate an outbound data frame.	The mbuf chain is updated and * a reference to the destination node is returned.  If an error is * encountered NULL is returned and the node reference will also be NULL. * * NB: The caller is responsible for freeing a returned node reference. *     The convention is ic_bss is not reference counted; the caller must *     maintain that. */struct sk_buff *ieee80211_encap(struct ieee80211_node *ni, struct sk_buff *skb, int *framecnt){#define	WH4(wh)	((struct ieee80211_frame_addr4 *)wh)	struct ieee80211vap *vap = ni->ni_vap;	struct ieee80211com *ic = ni->ni_ic;	struct ether_header eh;	struct ieee80211_frame *wh, *twh;	struct ieee80211_key *key;	struct llc *llc;	int hdrsize, datalen, addqos;	int hdrsize_nopad;	struct sk_buff *framelist = NULL;	struct sk_buff *tskb;	int fragcnt = 1;	int pdusize = 0;	int ismulticast = 0;	int use4addr = 0;#ifdef ATH_SUPERG_FF	struct sk_buff *skb2 = NULL;	struct ether_header eh2;	int isff = ATH_FF_MAGIC_PRESENT(skb);	if (isff) {#if 0		IEEE80211_DPRINTF(vap, IEEE80211_MSG_SUPG,			"%s: handling fast-frame skb (%p)\n", __func__, skb);#endif		skb2 = skb->next;		if (skb2 == NULL) {			IEEE80211_DPRINTF(vap, IEEE80211_MSG_SUPG,				"%s: fast-frame error, only 1 skb\n", __func__);			goto bad;		}		memcpy(&eh2, skb2->data, sizeof(struct ether_header));		skb_pull(skb2, sizeof(struct ether_header));	}#endif	memcpy(&eh, skb->data, sizeof(struct ether_header));	skb_pull(skb, sizeof(struct ether_header));	/*	 * Ensure space for additional headers.	 First identify	 * transmit key to use in calculating any buffer adjustments	 * required.  This is also used below to do privacy	 * encapsulation work.	Then calculate the 802.11 header	 * size and any padding required by the driver.	 *	 * Note key may be NULL if we fall back to the default	 * transmit key and that is not set.  In that case the	 * buffer may not be expanded as needed by the cipher	 * routines, but they will/should discard it.	 */	if (vap->iv_flags & IEEE80211_F_PRIVACY) {		if (vap->iv_opmode == IEEE80211_M_STA ||		    !IEEE80211_IS_MULTICAST(eh.ether_dhost))			key = ieee80211_crypto_getucastkey(vap, ni);		else			key = ieee80211_crypto_getmcastkey(vap, ni);		if ((key == NULL) && (eh.ether_type != htons(ETHERTYPE_PAE))) {			IEEE80211_NOTE_MAC(vap, IEEE80211_MSG_CRYPTO,				eh.ether_dhost,				"no default transmit key (%s) deftxkey %u",				__func__, vap->iv_def_txkey);			vap->iv_stats.is_tx_nodefkey++;			goto bad;		}	} else		key = NULL;	addqos = (ni->ni_flags & IEEE80211_NODE_QOS) &&		 (eh.ether_type != htons(ETHERTYPE_PAE));	if (addqos)		hdrsize = sizeof(struct ieee80211_qosframe);	else		hdrsize = sizeof(struct ieee80211_frame);	switch (vap->iv_opmode) {	case IEEE80211_M_IBSS:	case IEEE80211_M_AHDEMO:		ismulticast = IEEE80211_IS_MULTICAST(eh.ether_dhost);		break;	case IEEE80211_M_WDS:		use4addr = 1;		ismulticast = IEEE80211_IS_MULTICAST(ni->ni_macaddr);		break;	case IEEE80211_M_HOSTAP:		if (!IEEE80211_IS_MULTICAST(eh.ether_dhost) &&		    !IEEE80211_ADDR_EQ(eh.ether_dhost, ni->ni_macaddr)) {			use4addr = 1;			ismulticast = IEEE80211_IS_MULTICAST(ni->ni_macaddr);		} else			ismulticast = IEEE80211_IS_MULTICAST(eh.ether_dhost);		break;	case IEEE80211_M_STA:		if ((vap->iv_flags_ext & IEEE80211_FEXT_WDS) &&		    !IEEE80211_ADDR_EQ(eh.ether_shost, vap->iv_myaddr)) {			use4addr = 1;			ismulticast = IEEE80211_IS_MULTICAST(ni->ni_macaddr);			/* Add a WDS entry to the station VAP */			if (IEEE80211_IS_MULTICAST(eh.ether_dhost)) {				struct ieee80211_node_table *nt = &ic->ic_sta;				struct ieee80211_node *ni_wds 					= ieee80211_find_wds_node(nt, eh.ether_shost);				if (ni_wds)					ieee80211_unref_node(&ni_wds);				else					ieee80211_add_wds_addr(nt, ni, eh.ether_shost, 0);			}		} else			ismulticast = IEEE80211_IS_MULTICAST(vap->iv_bssid);		break;	default:		break;	}	if (use4addr)		hdrsize += IEEE80211_ADDR_LEN;	hdrsize_nopad = hdrsize;	if (ic->ic_flags & IEEE80211_F_DATAPAD)		hdrsize = roundup(hdrsize, sizeof(u_int32_t));	skb = ieee80211_skbhdr_adjust(vap, hdrsize, key, skb, ismulticast);	if (skb == NULL) {		/* NB: ieee80211_skbhdr_adjust handles msgs+statistics */		goto bad;	}#ifdef ATH_SUPERG_FF	if (isff) {		struct ether_header *eh_inter;		struct athl2p_tunnel_hdr *ffhdr;		u_int16_t payload = skb->len + LLC_SNAPFRAMELEN;		int padded_len = payload + LLC_SNAPFRAMELEN + sizeof(struct ether_header);		/* in case header adjustments altered skb2 */		skb2 = skb->next;		if (skb2 == NULL) {			IEEE80211_DPRINTF(vap, IEEE80211_MSG_SUPG,				"%s: skb (%p) hdr adjust dropped 2nd skb\n",				__func__, skb);			goto bad;		}		/*		 * add first skb tunnel hdrs		 */

⌨️ 快捷键说明

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