Esempio n. 1
0
void rtl_get_tcb_desc(struct ieee80211_hw *hw,
		      struct ieee80211_tx_info *info,
		      struct ieee80211_sta *sta,
		      struct sk_buff *skb, struct rtl_tcb_desc *tcb_desc)
{
	struct rtl_priv *rtlpriv = rtl_priv(hw);
	struct rtl_mac *rtlmac = rtl_mac(rtl_priv(hw));
	struct ieee80211_hdr *hdr = rtl_get_hdr(skb);
	struct ieee80211_rate *txrate;
	__le16 fc = hdr->frame_control;

	txrate = ieee80211_get_tx_rate(hw, info);
	if (txrate)
		tcb_desc->hw_rate = txrate->hw_value;
	else
		tcb_desc->hw_rate = 0;

	if (ieee80211_is_data(fc)) {

		if (info->control.rates[0].idx == 0 ||
				ieee80211_is_nullfunc(fc)) {
			tcb_desc->use_driver_rate = true;
			tcb_desc->ratr_index = RATR_INX_WIRELESS_MC;

			tcb_desc->disable_ratefallback = 1;
		} else {
			if (sta && (sta->ht_cap.ht_supported)) {
				tcb_desc->hw_rate = _rtl_get_highest_n_rate(hw);
			} else {
				if (rtlmac->mode == WIRELESS_MODE_B) {
					tcb_desc->hw_rate =
					   rtlpriv->cfg->maps[RTL_RC_CCK_RATE11M];
				} else {
					tcb_desc->hw_rate =
					   rtlpriv->cfg->maps[RTL_RC_OFDM_RATE54M];
				}
			}
		}

		if (is_multicast_ether_addr(ieee80211_get_DA(hdr)))
			tcb_desc->multicast = 1;
		else if (is_broadcast_ether_addr(ieee80211_get_DA(hdr)))
			tcb_desc->broadcast = 1;

		_rtl_txrate_selectmode(hw, sta, tcb_desc);
		_rtl_query_bandwidth_mode(hw, sta, tcb_desc);
		_rtl_qurey_shortpreamble_mode(hw, tcb_desc, info);
		_rtl_query_shortgi(hw, sta, tcb_desc, info);
		_rtl_query_protection_mode(hw, tcb_desc, info);
	} else {
		tcb_desc->use_driver_rate = true;
		tcb_desc->ratr_index = RATR_INX_WIRELESS_MC;
		tcb_desc->disable_ratefallback = 1;
		tcb_desc->mac_id = 0;
		tcb_desc->packet_bw = false;
	}
}
Esempio n. 2
0
File: trx.c Progetto: mkrufky/linux
static void _rtl8822be_translate_rx_signal_stuff(struct ieee80211_hw *hw,
						 struct sk_buff *skb,
						 struct rtl_stats *pstatus,
						 u8 *p_phystrpt)
{
	struct ieee80211_hdr *hdr;
	u8 *tmp_buf;

	tmp_buf = skb->data + pstatus->rx_drvinfo_size + pstatus->rx_bufshift +
		  24;

	hdr = (struct ieee80211_hdr *)tmp_buf;

	/* query phy status */
	_rtl8822be_query_rxphystatus(hw, p_phystrpt, hdr, pstatus);

	/* packet statistics */
	if (pstatus->packet_beacon && pstatus->packet_matchbssid)
		rtl_priv(hw)->dm.dbginfo.num_qry_beacon_pkt++;

	if (pstatus->packet_matchbssid &&
	    ieee80211_is_data_qos(hdr->frame_control) &&
	    !is_multicast_ether_addr(ieee80211_get_DA(hdr))) {
		struct ieee80211_qos_hdr *hdr_qos =
			(struct ieee80211_qos_hdr *)tmp_buf;
		u16 tid = le16_to_cpu(hdr_qos->qos_ctrl) & 0xf;

		if (tid != 0 && tid != 3)
			rtl_priv(hw)->dm.dbginfo.num_non_be_pkt++;
	}

	/* signal statistics */
	if (p_phystrpt)
		rtl_process_phyinfo(hw, tmp_buf, pstatus);
}
Esempio n. 3
0
File: rc.c Progetto: IDM350/linux
/*mac80211 Rate Control callbacks*/
static void rtl_tx_status(void *ppriv,
			  struct ieee80211_supported_band *sband,
			  struct ieee80211_sta *sta, void *priv_sta,
			  struct sk_buff *skb)
{
	struct rtl_priv *rtlpriv = ppriv;
	struct rtl_mac *mac = rtl_mac(rtlpriv);
	struct ieee80211_hdr *hdr = rtl_get_hdr(skb);
	__le16 fc = rtl_get_fc(skb);
	struct rtl_sta_info *sta_entry;

	if (!priv_sta || !ieee80211_is_data(fc))
		return;

	if (rtl_is_special_data(mac->hw, skb, true))
		return;

	if (is_multicast_ether_addr(ieee80211_get_DA(hdr)) ||
	    is_broadcast_ether_addr(ieee80211_get_DA(hdr)))
		return;

	if (sta) {
		/* Check if aggregation has to be enabled for this tid */
		sta_entry = (struct rtl_sta_info *) sta->drv_priv;
		if ((sta->ht_cap.ht_supported == true) &&
				!(skb->protocol == cpu_to_be16(ETH_P_PAE))) {
			if (ieee80211_is_data_qos(fc)) {
				u8 tid = rtl_get_tid(skb);
				if (_rtl_tx_aggr_check(rtlpriv, sta_entry,
						       tid)) {
					sta_entry->tids[tid].agg.agg_state =
						RTL_AGG_PROGRESS;
					/*<delete in kernel start>*/
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
					/*<delete in kernel end>*/
					ieee80211_start_tx_ba_session(sta, tid,
								      5000);
					/*<delete in kernel start>*/
#else
					ieee80211_start_tx_ba_session(sta, tid);
#endif
					/*<delete in kernel end>*/
				}
			}
		}
	}
}
Esempio n. 4
0
static void michael_mic_hdr(struct michael_mic_ctx *mctx, const u8 *key,
			    struct ieee80211_hdr *hdr)
{
	u8 *da, *sa, tid;

	da = ieee80211_get_DA(hdr);
	sa = ieee80211_get_SA(hdr);
	if (ieee80211_is_data_qos(hdr->frame_control))
		tid = *ieee80211_get_qos_ctl(hdr) & IEEE80211_QOS_CTL_TID_MASK;
	else
		tid = 0;

	mctx->l = get_unaligned_le32(key);
	mctx->r = get_unaligned_le32(key + 4);

	
	michael_block(mctx, get_unaligned_le32(da));
	michael_block(mctx, get_unaligned_le16(&da[4]) |
			    (get_unaligned_le16(sa) << 16));
	michael_block(mctx, get_unaligned_le32(&sa[2]));
	michael_block(mctx, tid);
}
Esempio n. 5
0
void rtl_get_tcb_desc(struct ieee80211_hw *hw,
		      struct ieee80211_tx_info *info,
		      struct sk_buff *skb, struct rtl_tcb_desc *tcb_desc)
{
	struct rtl_priv *rtlpriv = rtl_priv(hw);
	struct rtl_mac *rtlmac = rtl_mac(rtl_priv(hw));
	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)(skb->data);
	struct ieee80211_rate *txrate;
	u16 fc = le16_to_cpu(hdr->frame_control);

	memset(tcb_desc, 0, sizeof(struct rtl_tcb_desc));

	if (ieee80211_is_data(fc)) {
		txrate = ieee80211_get_tx_rate(hw, info);
		tcb_desc->hw_rate = txrate->hw_value;

		/*
		 *we set data rate RTL_RC_CCK_RATE1M
		 *in rtl_rc.c   if skb is special data or
		 *mgt which need low data rate.
		 */

		/*
		 *So tcb_desc->hw_rate is just used for
		 *special data and mgt frames
		 */
		if (tcb_desc->hw_rate < rtlpriv->cfg->maps[RTL_RC_CCK_RATE11M]) {
			tcb_desc->use_driver_rate = true;
			tcb_desc->ratr_index = 7;

			tcb_desc->hw_rate =
			    rtlpriv->cfg->maps[RTL_RC_CCK_RATE1M];
			tcb_desc->disable_ratefallback = 1;
		} else {
			/*
			 *because hw will nerver use hw_rate
			 *when tcb_desc->use_driver_rate = false
			 *so we never set highest N rate here,
			 *and N rate will all be controled by FW
			 *when tcb_desc->use_driver_rate = false
			 */
			if (rtlmac->ht_enable) {
				tcb_desc->hw_rate = _rtl_get_highest_n_rate(hw);
			} else {
				if (rtlmac->mode == WIRELESS_MODE_B) {
					tcb_desc->hw_rate =
					   rtlpriv->cfg->maps[RTL_RC_CCK_RATE11M];
				} else {
					tcb_desc->hw_rate =
					   rtlpriv->cfg->maps[RTL_RC_OFDM_RATE54M];
				}
			}
		}

		if (is_multicast_ether_addr(ieee80211_get_DA(hdr)))
			tcb_desc->b_multicast = 1;
		else if (is_broadcast_ether_addr(ieee80211_get_DA(hdr)))
			tcb_desc->b_broadcast = 1;

		_rtl_txrate_selectmode(hw, tcb_desc);
		_rtl_query_bandwidth_mode(hw, tcb_desc);
		_rtl_qurey_shortpreamble_mode(hw, tcb_desc, info);
		_rtl_query_shortgi(hw, tcb_desc, info);
		_rtl_query_protection_mode(hw, tcb_desc, info);
	} else {
		tcb_desc->use_driver_rate = true;
		tcb_desc->ratr_index = 7;
		tcb_desc->disable_ratefallback = 1;
		tcb_desc->mac_id = 0;

		tcb_desc->hw_rate = rtlpriv->cfg->maps[RTL_RC_CCK_RATE1M];
	}
}
Esempio n. 6
0
void rtl_get_tcb_desc(struct ieee80211_hw *hw,
		      struct ieee80211_tx_info *info,
		      struct ieee80211_sta *sta,
		      struct sk_buff *skb, struct rtl_tcb_desc *tcb_desc)
{
	struct rtl_priv *rtlpriv = rtl_priv(hw);
	struct rtl_mac *rtlmac = rtl_mac(rtl_priv(hw));
	struct ieee80211_hdr *hdr = rtl_get_hdr(skb);
	struct ieee80211_rate *txrate;
	__le16 fc = hdr->frame_control;

	txrate = ieee80211_get_tx_rate(hw, info);
	if (txrate)
		tcb_desc->hw_rate = txrate->hw_value;
	else
		tcb_desc->hw_rate = 0;

	if (ieee80211_is_data(fc)) {
		/*
		 *we set data rate INX 0
		 *in rtl_rc.c   if skb is special data or
		 *mgt which need low data rate.
		 */

		/*
		 *So tcb_desc->hw_rate is just used for
		 *special data and mgt frames
		 */
		if (info->control.rates[0].idx == 0 ||
				ieee80211_is_nullfunc(fc)) {
			tcb_desc->use_driver_rate = true;
			tcb_desc->ratr_index = RATR_INX_WIRELESS_MC;

			tcb_desc->disable_ratefallback = 1;
		} else {
			/*
			 *because hw will nerver use hw_rate
			 *when tcb_desc->use_driver_rate = false
			 *so we never set highest N rate here,
			 *and N rate will all be controlled by FW
			 *when tcb_desc->use_driver_rate = false
			 */
			if (sta && (sta->ht_cap.ht_supported)) {
				tcb_desc->hw_rate = _rtl_get_highest_n_rate(hw);
			} else {
				if (rtlmac->mode == WIRELESS_MODE_B) {
					tcb_desc->hw_rate =
					   rtlpriv->cfg->maps[RTL_RC_CCK_RATE11M];
				} else {
					tcb_desc->hw_rate =
					   rtlpriv->cfg->maps[RTL_RC_OFDM_RATE54M];
				}
			}
		}

		if (is_multicast_ether_addr(ieee80211_get_DA(hdr)))
			tcb_desc->multicast = 1;
		else if (is_broadcast_ether_addr(ieee80211_get_DA(hdr)))
			tcb_desc->broadcast = 1;

		_rtl_txrate_selectmode(hw, sta, tcb_desc);
		_rtl_query_bandwidth_mode(hw, sta, tcb_desc);
		_rtl_qurey_shortpreamble_mode(hw, tcb_desc, info);
		_rtl_query_shortgi(hw, sta, tcb_desc, info);
		_rtl_query_protection_mode(hw, tcb_desc, info);
	} else {
		tcb_desc->use_driver_rate = true;
		tcb_desc->ratr_index = RATR_INX_WIRELESS_MC;
		tcb_desc->disable_ratefallback = 1;
		tcb_desc->mac_id = 0;
		tcb_desc->packet_bw = false;
	}
}
Esempio n. 7
0
static inline struct sk_buff *mwl_tx_do_amsdu(struct mwl_priv *priv,
					      int desc_num,
					      struct sk_buff *tx_skb,
					      struct ieee80211_tx_info *tx_info)
{
	struct ieee80211_sta *sta;
	struct mwl_sta *sta_info;
	struct mwl_tx_ctrl *tx_ctrl = (struct mwl_tx_ctrl *)&tx_info->status;
	struct ieee80211_tx_info *amsdu_info;
	struct sk_buff_head *amsdu_pkts;
	struct mwl_amsdu_frag *amsdu;
	int amsdu_allow_size;
	struct ieee80211_hdr *wh;
	int wh_len;
	u16 len;
	u8 *data;

	sta = (struct ieee80211_sta *)tx_ctrl->sta;
	sta_info = mwl_dev_get_sta(sta);

	if (!sta_info->is_amsdu_allowed)
		return tx_skb;

	wh = (struct ieee80211_hdr *)tx_skb->data;
	if (sta_info->is_mesh_node && is_multicast_ether_addr(wh->addr3))
		return tx_skb;

	if (sta_info->amsdu_ctrl.cap == MWL_AMSDU_SIZE_4K)
		amsdu_allow_size = SYSADPT_AMSDU_4K_MAX_SIZE;
	else if (sta_info->amsdu_ctrl.cap == MWL_AMSDU_SIZE_8K)
		amsdu_allow_size = SYSADPT_AMSDU_8K_MAX_SIZE;
	else
		return tx_skb;

	spin_lock_bh(&sta_info->amsdu_lock);
	amsdu = &sta_info->amsdu_ctrl.frag[desc_num];

	if (tx_skb->len > SYSADPT_AMSDU_ALLOW_SIZE) {
		if (amsdu->num) {
			mwl_tx_skb(priv, desc_num, amsdu->skb);
			amsdu->num = 0;
			amsdu->cur_pos = NULL;

			if (!mwl_tx_available(priv, desc_num)) {
				skb_queue_head(&priv->txq[desc_num], tx_skb);
				spin_unlock_bh(&sta_info->amsdu_lock);
				return NULL;
			}
		}
		spin_unlock_bh(&sta_info->amsdu_lock);
		return tx_skb;
	}

	/* potential amsdu size, should add amsdu header 14 bytes +
	 * maximum padding 3.
	 */
	wh_len = ieee80211_hdrlen(wh->frame_control);
	len = tx_skb->len - wh_len + 17;

	if (amsdu->num) {
		if ((amsdu->skb->len + len) > amsdu_allow_size) {
			mwl_tx_skb(priv, desc_num, amsdu->skb);
			amsdu->num = 0;
			amsdu->cur_pos = NULL;
		}
	}

	amsdu->jiffies = jiffies;
	len = tx_skb->len - wh_len;

	if (amsdu->num == 0) {
		struct sk_buff *newskb;

		amsdu_pkts = (struct sk_buff_head *)
			kmalloc(sizeof(*amsdu_pkts), GFP_ATOMIC);
		if (!amsdu_pkts) {
			spin_unlock_bh(&sta_info->amsdu_lock);
			return tx_skb;
		}
		newskb = dev_alloc_skb(amsdu_allow_size +
				       SYSADPT_MIN_BYTES_HEADROOM);
		if (!newskb) {
			spin_unlock_bh(&sta_info->amsdu_lock);
			kfree(amsdu_pkts);
			return tx_skb;
		}

		data = newskb->data;
		memcpy(data, tx_skb->data, wh_len);
		if (sta_info->is_mesh_node) {
			ether_addr_copy(data + wh_len, wh->addr3);
			ether_addr_copy(data + wh_len + ETH_ALEN, wh->addr4);
		} else {
			ether_addr_copy(data + wh_len,
					ieee80211_get_DA(wh));
			ether_addr_copy(data + wh_len + ETH_ALEN,
					ieee80211_get_SA(wh));
		}
		*(u8 *)(data + wh_len + ETH_HLEN - 1) = len & 0xff;
		*(u8 *)(data + wh_len + ETH_HLEN - 2) = (len >> 8) & 0xff;
		memcpy(data + wh_len + ETH_HLEN, tx_skb->data + wh_len, len);

		skb_put(newskb, tx_skb->len + ETH_HLEN);
		tx_ctrl->qos_ctrl |= IEEE80211_QOS_CTL_A_MSDU_PRESENT;
		amsdu_info = IEEE80211_SKB_CB(newskb);
		memcpy(amsdu_info, tx_info, sizeof(*tx_info));
		skb_queue_head_init(amsdu_pkts);
		((struct mwl_tx_ctrl *)&amsdu_info->status)->amsdu_pkts =
			(void *)amsdu_pkts;
		amsdu->skb = newskb;
	} else {
Esempio n. 8
0
/*
 * Sets most of the Tx cmd's fields
 */
static void iwl_mvm_set_tx_cmd(struct iwl_mvm *mvm, struct sk_buff *skb,
			       struct iwl_tx_cmd *tx_cmd,
			       struct ieee80211_tx_info *info, u8 sta_id)
{
	struct ieee80211_hdr *hdr = (void *)skb->data;
	__le16 fc = hdr->frame_control;
	u32 tx_flags = le32_to_cpu(tx_cmd->tx_flags);
	u32 len = skb->len + FCS_LEN;

	if (!(info->flags & IEEE80211_TX_CTL_NO_ACK))
		tx_flags |= TX_CMD_FLG_ACK;
	else
		tx_flags &= ~TX_CMD_FLG_ACK;

	if (ieee80211_is_probe_resp(fc))
		tx_flags |= TX_CMD_FLG_TSF;
	else if (ieee80211_is_back_req(fc))
		tx_flags |= TX_CMD_FLG_ACK | TX_CMD_FLG_BAR;

	/* High prio packet (wrt. BT coex) if it is EAPOL, MCAST or MGMT */
	if (info->band == IEEE80211_BAND_2GHZ &&
	    (info->control.flags & IEEE80211_TX_CTRL_PORT_CTRL_PROTO ||
	     is_multicast_ether_addr(hdr->addr1) ||
	     ieee80211_is_back_req(fc) || ieee80211_is_mgmt(fc)))
		tx_flags |= TX_CMD_FLG_BT_DIS;

	if (ieee80211_has_morefrags(fc))
		tx_flags |= TX_CMD_FLG_MORE_FRAG;

	if (ieee80211_is_data_qos(fc)) {
		u8 *qc = ieee80211_get_qos_ctl(hdr);
		tx_cmd->tid_tspec = qc[0] & 0xf;
		tx_flags &= ~TX_CMD_FLG_SEQ_CTL;
	} else {
		tx_cmd->tid_tspec = IWL_TID_NON_QOS;
		if (info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ)
			tx_flags |= TX_CMD_FLG_SEQ_CTL;
		else
			tx_flags &= ~TX_CMD_FLG_SEQ_CTL;
	}

	if (ieee80211_is_mgmt(fc)) {
		if (ieee80211_is_assoc_req(fc) || ieee80211_is_reassoc_req(fc))
			tx_cmd->pm_frame_timeout = cpu_to_le16(3);
		else
			tx_cmd->pm_frame_timeout = cpu_to_le16(2);

		/* The spec allows Action frames in A-MPDU, we don't support
		 * it
		 */
		WARN_ON_ONCE(info->flags & IEEE80211_TX_CTL_AMPDU);
	} else if (skb->protocol == cpu_to_be16(ETH_P_PAE)) {
		tx_cmd->pm_frame_timeout = cpu_to_le16(2);
	} else {
		tx_cmd->pm_frame_timeout = 0;
	}

	if (info->flags & IEEE80211_TX_CTL_AMPDU)
		tx_flags |= TX_CMD_FLG_PROT_REQUIRE;

	if (ieee80211_is_data(fc) && len > mvm->rts_threshold &&
	    !is_multicast_ether_addr(ieee80211_get_DA(hdr)))
		tx_flags |= TX_CMD_FLG_PROT_REQUIRE;

	tx_cmd->driver_txop = 0;
	tx_cmd->tx_flags = cpu_to_le32(tx_flags);
	/* Total # bytes to be transmitted */
	tx_cmd->len = cpu_to_le16((u16)skb->len);
	tx_cmd->next_frame_len = 0;
	tx_cmd->life_time = cpu_to_le32(TX_CMD_LIFE_TIME_INFINITE);
	tx_cmd->sta_id = sta_id;
}
Esempio n. 9
0
int
parse_80211_header(const u_char* buf, int len, struct packet_info* p)
{
	struct ieee80211_hdr* wh;
	int hdrlen;
	uint8_t *sa = NULL;
	uint8_t *da = NULL;
	u16 fc;

	if (len < 2)
		return -1;

	wh = (struct ieee80211_hdr*)buf;
	fc = le16toh(wh->frame_control);
	hdrlen = ieee80211_get_hdrlen(fc);

	DEBUG("len %d hdrlen %d\n", len, hdrlen);

	if (len < hdrlen)
		return -1;

	p->wlan_len = len;
	p->wlan_type = (fc & (IEEE80211_FCTL_FTYPE | IEEE80211_FCTL_STYPE));



	switch (p->wlan_type & IEEE80211_FCTL_FTYPE) {
	case IEEE80211_FTYPE_DATA:
		p->pkt_types = PKT_TYPE_DATA;

                switch (p->wlan_type & IEEE80211_FCTL_STYPE) {
                case IEEE80211_STYPE_NULLFUNC:
                        p->pkt_types |= PKT_TYPE_NULL;
                        break;
                case IEEE80211_STYPE_QOS_DATA:
                        /* TODO: ouch, should properly define a qos header */
                        p->wlan_qos_class = wh->addr4[0] & 0x7;
                        DEBUG("***QDATA %x\n", p->wlan_qos_class);
                        break;
                }

		sa = ieee80211_get_SA(wh);
		da = ieee80211_get_DA(wh);

		p->wlan_seqno = le16toh(wh->seq_ctrl) / 16;

		if (fc & IEEE80211_FCTL_PROTECTED)
			p->wlan_wep = 1;
		if (fc & IEEE80211_FCTL_RETRY)
			p->wlan_retry = 1;
		break;
	case IEEE80211_FTYPE_CTL:
		p->pkt_types = PKT_TYPE_CTRL;
		DEBUG("CTL\n");
		switch (p->wlan_type & IEEE80211_FCTL_STYPE) {
		case IEEE80211_STYPE_RTS:
			p->pkt_types |= PKT_TYPE_RTS;
			p->wlan_nav = le16toh(wh->duration_id);
			DEBUG("RTS NAV %d\n", p->wlan_nav);
			sa = wh->addr2;
			da = wh->addr1;
			break;

		case IEEE80211_STYPE_CTS:
			p->pkt_types |= PKT_TYPE_CTS;
			p->wlan_nav = le16toh(wh->duration_id);
			DEBUG("CTS NAV %d\n", p->wlan_nav);
			da = wh->addr1;
			break;

		case IEEE80211_STYPE_ACK:
			p->pkt_types |= PKT_TYPE_ACK;
			p->wlan_nav = le16toh(wh->duration_id);
			DEBUG("ACK NAV %d\n", p->wlan_nav);
			da = wh->addr1;
			break;

		case IEEE80211_STYPE_PSPOLL:
			sa = wh->addr2;
			break;

		case IEEE80211_STYPE_CFEND:
			da = wh->addr1;
			sa = wh->addr2;
			break;

		case IEEE80211_STYPE_CFENDACK:
			/* dont know, dont care */
			break;
		}

		break;
	
	case IEEE80211_FTYPE_MGMT:
		p->pkt_types = PKT_TYPE_MGMT;
		DEBUG("MGMT\n");
		break;
	}

	if (sa != NULL) {
		memcpy(p->wlan_src, sa, 6);
		DEBUG("SA    %s\n", ether_sprintf(sa));
	}
	if (da != NULL) {
		memcpy(p->wlan_dst, da, 6);
		DEBUG("DA    %s\n", ether_sprintf(da));
	}

	DEBUG("%s\n", get_packet_type_name(fc));

	return 0;
}
Esempio n. 10
0
/*
 * Sets most of the Tx cmd's fields
 */
static void iwl_mvm_set_tx_cmd(struct iwl_mvm *mvm, struct sk_buff *skb,
			       struct iwl_tx_cmd *tx_cmd,
			       struct ieee80211_tx_info *info, u8 sta_id)
{
	struct ieee80211_hdr *hdr = (void *)skb->data;
	__le16 fc = hdr->frame_control;
	u32 tx_flags = le32_to_cpu(tx_cmd->tx_flags);
	u32 len = skb->len + FCS_LEN;
	u8 ac;

	if (!(info->flags & IEEE80211_TX_CTL_NO_ACK))
		tx_flags |= TX_CMD_FLG_ACK;
	else
		tx_flags &= ~TX_CMD_FLG_ACK;

	if (ieee80211_is_probe_resp(fc))
		tx_flags |= TX_CMD_FLG_TSF;
	else if (ieee80211_is_back_req(fc))
		tx_flags |= TX_CMD_FLG_ACK | TX_CMD_FLG_BAR;

	if (ieee80211_has_morefrags(fc))
		tx_flags |= TX_CMD_FLG_MORE_FRAG;

	if (ieee80211_is_data_qos(fc)) {
		u8 *qc = ieee80211_get_qos_ctl(hdr);
		tx_cmd->tid_tspec = qc[0] & 0xf;
		tx_flags &= ~TX_CMD_FLG_SEQ_CTL;
	} else {
		tx_cmd->tid_tspec = IWL_TID_NON_QOS;
		if (info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ)
			tx_flags |= TX_CMD_FLG_SEQ_CTL;
		else
			tx_flags &= ~TX_CMD_FLG_SEQ_CTL;
	}

	/* tid_tspec will default to 0 = BE when QOS isn't enabled */
	ac = tid_to_mac80211_ac[tx_cmd->tid_tspec];
	tx_flags |= iwl_mvm_bt_coex_tx_prio(mvm, hdr, info, ac) <<
			TX_CMD_FLG_BT_PRIO_POS;

	if (ieee80211_is_mgmt(fc)) {
		if (ieee80211_is_assoc_req(fc) || ieee80211_is_reassoc_req(fc))
			tx_cmd->pm_frame_timeout = cpu_to_le16(3);
		else
			tx_cmd->pm_frame_timeout = cpu_to_le16(2);

		/* The spec allows Action frames in A-MPDU, we don't support
		 * it
		 */
		WARN_ON_ONCE(info->flags & IEEE80211_TX_CTL_AMPDU);
	} else if (info->control.flags & IEEE80211_TX_CTRL_PORT_CTRL_PROTO) {
		tx_cmd->pm_frame_timeout = cpu_to_le16(2);
	} else {
		tx_cmd->pm_frame_timeout = 0;
	}

	if (ieee80211_is_data(fc) && len > mvm->rts_threshold &&
	    !is_multicast_ether_addr(ieee80211_get_DA(hdr)))
		tx_flags |= TX_CMD_FLG_PROT_REQUIRE;

	if ((mvm->fw->ucode_capa.capa[0] &
	     IWL_UCODE_TLV_CAPA_TXPOWER_INSERTION_SUPPORT) &&
	    ieee80211_action_contains_tpc(skb))
		tx_flags |= TX_CMD_FLG_WRITE_TX_POWER;

	tx_cmd->tx_flags = cpu_to_le32(tx_flags);
	/* Total # bytes to be transmitted */
	tx_cmd->len = cpu_to_le16((u16)skb->len);
	tx_cmd->next_frame_len = 0;
	tx_cmd->life_time = cpu_to_le32(TX_CMD_LIFE_TIME_INFINITE);
	tx_cmd->sta_id = sta_id;
}
Esempio n. 11
0
void update_recvframe_phyinfo(struct recv_frame *precvframe,
			      struct phy_stat *pphy_status)
{
	struct rtw_adapter *padapter = precvframe->adapter;
	struct rx_pkt_attrib *pattrib = &precvframe->attrib;
	struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter);
	struct odm_phy_info *pPHYInfo = (struct odm_phy_info *)(&pattrib->phy_info);
	struct odm_packet_info pkt_info;
	u8 *sa = NULL, *da;
	struct sta_priv *pstapriv;
	struct sta_info *psta;
	struct sk_buff *skb = precvframe->pkt;
	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
	u8 *wlanhdr = skb->data;

	pkt_info.bPacketMatchBSSID = false;
	pkt_info.bPacketToSelf = false;
	pkt_info.bPacketBeacon = false;

	pkt_info.bPacketMatchBSSID =
		(!ieee80211_is_ctl(hdr->frame_control) &&
		 !pattrib->icv_err &&
		 !pattrib->crc_err &&
		 !memcmp(get_hdr_bssid(wlanhdr),
			 get_bssid(&padapter->mlmepriv), ETH_ALEN));

	da = ieee80211_get_DA(hdr);
	pkt_info.bPacketToSelf = pkt_info.bPacketMatchBSSID &&
		(!memcmp(da, myid(&padapter->eeprompriv), ETH_ALEN));

	pkt_info.bPacketBeacon = pkt_info.bPacketMatchBSSID &&
		ieee80211_is_beacon(hdr->frame_control);

	pkt_info.StationID = 0xFF;
	if (pkt_info.bPacketBeacon) {
		if (check_fwstate(&padapter->mlmepriv, WIFI_STATION_STATE) == true)
			sa = padapter->mlmepriv.cur_network.network.MacAddress;
		/* to do Ad-hoc */
	} else {
		sa = ieee80211_get_SA(hdr);
	}

	pstapriv = &padapter->stapriv;
	psta = rtw_get_stainfo23a(pstapriv, sa);
	if (psta) {
		pkt_info.StationID = psta->mac_id;
		/* printk("%s ==> StationID(%d)\n", __FUNCTION__, pkt_info.StationID); */
	}
	pkt_info.Rate = pattrib->mcs_rate;

	ODM_PhyStatusQuery23a(&pHalData->odmpriv, pPHYInfo,
			   (u8 *)pphy_status, &pkt_info);
	precvframe->psta = NULL;
	if (pkt_info.bPacketMatchBSSID &&
	    (check_fwstate(&padapter->mlmepriv, WIFI_AP_STATE) == true)) {
		if (psta) {
			precvframe->psta = psta;
			rtl8723a_process_phy_info(padapter, precvframe);
		}
	} else if (pkt_info.bPacketToSelf || pkt_info.bPacketBeacon) {
		if (check_fwstate(&padapter->mlmepriv,
				  WIFI_ADHOC_STATE|WIFI_ADHOC_MASTER_STATE) ==
		    true) {
			if (psta)
				precvframe->psta = psta;
		}
		rtl8723a_process_phy_info(padapter, precvframe);
	}
}
Esempio n. 12
0
void sc_capwap_parsingdatapacket(struct sc_capwap_session* session, struct sk_buff* skb)
{
	uint8_t* pos;
	uint8_t* dstaddress;
	struct net_device* dev;
	struct sc_capwap_header* header = (struct sc_capwap_header*)skb->data;
	int is80211 = (IS_FLAG_T_HEADER(header) ? 1 : 0);
	struct sc_capwap_radio_addr* radioaddr = NULL;
	int radioaddrsize = 0;
	struct sc_capwap_wireless_information* winfo = NULL;
	struct sc_capwap_destination_wlans* destwlan = NULL;
	int winfosize = 0;

	TRACEKMOD("### sc_capwap_parsingdatapacket\n");

	/* Retrieve optional attribute */
	pos = skb->data + sizeof(struct sc_capwap_header);
	if (IS_FLAG_M_HEADER(header)) {
		radioaddr = (struct sc_capwap_radio_addr*)pos;
		radioaddrsize = (sizeof(struct sc_capwap_radio_addr) + radioaddr->length + 3) & ~3;
		pos += radioaddrsize;
	}

	if (IS_FLAG_W_HEADER(header)) {
		winfo = (struct sc_capwap_wireless_information*)pos;
		destwlan = (struct sc_capwap_destination_wlans*)(pos + sizeof(struct sc_capwap_wireless_information));
		winfosize = (sizeof(struct sc_capwap_wireless_information) + winfo->length + 3) & ~3;
		pos += winfosize;
	}

	/* Body packet */
	skb_pull(skb, GET_HLEN_HEADER(header) * 4);

	dstaddress = (is80211 ? ieee80211_get_DA((struct ieee80211_hdr*)skb->data) : (uint8_t*)((struct ethhdr*)skb->data)->h_dest);
	if (is_multicast_ether_addr(dstaddress)) {
		uint8_t wlanid;
		uint16_t bitmask;

		/* Accept only broadcast packet with wireless information */
		if (!winfo) {
			TRACEKMOD("*** Invalid broadcast packet\n");

			/* Free broadcast packet */
			kfree_skb(skb);
			return;
		}

		for (wlanid = 1, bitmask = be16_to_cpu(destwlan->wlanidbitmap);
		     bitmask;
		     wlanid++, bitmask >>=1 )
		{
			struct sk_buff* clone;

			if (!(bitmask & 0x01))
				continue;

			dev = sc_netlink_getdev_from_wlanid(session->net, GET_RID_HEADER(header), wlanid);
			if (!dev) {
				TRACEKMOD("*** Unknown wlanid: %d\n", (int)wlanid);
				continue;
			}

			clone = skb_copy_expand(skb, skb_headroom(skb), skb_tailroom(skb), GFP_KERNEL);
			if (!clone)
				goto error;

			/* */
			if (!is80211) {
				TRACEKMOD("*** Send 802.3 broadcast packet to interface: %d\n",
					  dev->ifindex);

				sc_send_8023(clone, dev);
			} else {
				TRACEKMOD("*** Send broadcast packet to interface: %d\n", dev->ifindex);

				/* Send packet */
				local_bh_disable();
				ieee80211_inject_xmit(clone, dev);
				local_bh_enable();
			}
		}
	} else {
Esempio n. 13
0
static int iwl_pcie_gen2_build_amsdu(struct iwl_trans *trans,
				     struct sk_buff *skb,
				     struct iwl_tfh_tfd *tfd, int start_len,
				     u8 hdr_len, struct iwl_device_cmd *dev_cmd)
{
#ifdef CONFIG_INET
	struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
	struct iwl_tx_cmd_gen2 *tx_cmd = (void *)dev_cmd->payload;
	struct ieee80211_hdr *hdr = (void *)skb->data;
	unsigned int snap_ip_tcp_hdrlen, ip_hdrlen, total_len, hdr_room;
	unsigned int mss = skb_shinfo(skb)->gso_size;
	u16 length, iv_len, amsdu_pad;
	u8 *start_hdr;
	struct iwl_tso_hdr_page *hdr_page;
	struct page **page_ptr;
	struct tso_t tso;

	/* if the packet is protected, then it must be CCMP or GCMP */
	iv_len = ieee80211_has_protected(hdr->frame_control) ?
		IEEE80211_CCMP_HDR_LEN : 0;

	trace_iwlwifi_dev_tx(trans->dev, skb, tfd, sizeof(*tfd),
			     &dev_cmd->hdr, start_len, 0);

	ip_hdrlen = skb_transport_header(skb) - skb_network_header(skb);
	snap_ip_tcp_hdrlen = 8 + ip_hdrlen + tcp_hdrlen(skb);
	total_len = skb->len - snap_ip_tcp_hdrlen - hdr_len - iv_len;
	amsdu_pad = 0;

	/* total amount of header we may need for this A-MSDU */
	hdr_room = DIV_ROUND_UP(total_len, mss) *
		(3 + snap_ip_tcp_hdrlen + sizeof(struct ethhdr)) + iv_len;

	/* Our device supports 9 segments at most, it will fit in 1 page */
	hdr_page = get_page_hdr(trans, hdr_room);
	if (!hdr_page)
		return -ENOMEM;

	get_page(hdr_page->page);
	start_hdr = hdr_page->pos;
	page_ptr = (void *)((u8 *)skb->cb + trans_pcie->page_offs);
	*page_ptr = hdr_page->page;
	memcpy(hdr_page->pos, skb->data + hdr_len, iv_len);
	hdr_page->pos += iv_len;

	/*
	 * Pull the ieee80211 header + IV to be able to use TSO core,
	 * we will restore it for the tx_status flow.
	 */
	skb_pull(skb, hdr_len + iv_len);

	/*
	 * Remove the length of all the headers that we don't actually
	 * have in the MPDU by themselves, but that we duplicate into
	 * all the different MSDUs inside the A-MSDU.
	 */
	le16_add_cpu(&tx_cmd->len, -snap_ip_tcp_hdrlen);

	tso_start(skb, &tso);

	while (total_len) {
		/* this is the data left for this subframe */
		unsigned int data_left = min_t(unsigned int, mss, total_len);
		struct sk_buff *csum_skb = NULL;
		unsigned int tb_len;
		dma_addr_t tb_phys;
		u8 *subf_hdrs_start = hdr_page->pos;

		total_len -= data_left;

		memset(hdr_page->pos, 0, amsdu_pad);
		hdr_page->pos += amsdu_pad;
		amsdu_pad = (4 - (sizeof(struct ethhdr) + snap_ip_tcp_hdrlen +
				  data_left)) & 0x3;
		ether_addr_copy(hdr_page->pos, ieee80211_get_DA(hdr));
		hdr_page->pos += ETH_ALEN;
		ether_addr_copy(hdr_page->pos, ieee80211_get_SA(hdr));
		hdr_page->pos += ETH_ALEN;

		length = snap_ip_tcp_hdrlen + data_left;
		*((__be16 *)hdr_page->pos) = cpu_to_be16(length);
		hdr_page->pos += sizeof(length);

		/*
		 * This will copy the SNAP as well which will be considered
		 * as MAC header.
		 */
		tso_build_hdr(skb, hdr_page->pos, &tso, data_left, !total_len);

		hdr_page->pos += snap_ip_tcp_hdrlen;

		tb_len = hdr_page->pos - start_hdr;
		tb_phys = dma_map_single(trans->dev, start_hdr,
					 tb_len, DMA_TO_DEVICE);
		if (unlikely(dma_mapping_error(trans->dev, tb_phys))) {
			dev_kfree_skb(csum_skb);
			goto out_err;
		}
		iwl_pcie_gen2_set_tb(trans, tfd, tb_phys, tb_len);
		trace_iwlwifi_dev_tx_tb(trans->dev, skb, start_hdr, tb_len);
		/* add this subframe's headers' length to the tx_cmd */
		le16_add_cpu(&tx_cmd->len, hdr_page->pos - subf_hdrs_start);

		/* prepare the start_hdr for the next subframe */
		start_hdr = hdr_page->pos;

		/* put the payload */
		while (data_left) {
			tb_len = min_t(unsigned int, tso.size, data_left);
			tb_phys = dma_map_single(trans->dev, tso.data,
						 tb_len, DMA_TO_DEVICE);
			if (unlikely(dma_mapping_error(trans->dev, tb_phys))) {
				dev_kfree_skb(csum_skb);
				goto out_err;
			}
			iwl_pcie_gen2_set_tb(trans, tfd, tb_phys, tb_len);
			trace_iwlwifi_dev_tx_tb(trans->dev, skb, tso.data,
						tb_len);

			data_left -= tb_len;
			tso_build_data(skb, &tso, tb_len);
		}
	}

	/* re -add the WiFi header and IV */
	skb_push(skb, hdr_len + iv_len);

	return 0;

out_err:
#endif
	return -EINVAL;
}
Esempio n. 14
0
void update_recvframe_phyinfo(struct recv_frame *precvframe,
			      struct phy_stat *pphy_status)
{
	struct rtw_adapter *padapter = precvframe->adapter;
	struct rx_pkt_attrib *pattrib = &precvframe->attrib;
	struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter);
	struct phy_info *pPHYInfo = &pattrib->phy_info;
	struct odm_packet_info pkt_info;
	u8 *sa = NULL, *da;
	struct sta_priv *pstapriv;
	struct sta_info *psta;
	struct sk_buff *skb = precvframe->pkt;
	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
	bool matchbssid = false;
	u8 *bssid;

	matchbssid = (!ieee80211_is_ctl(hdr->frame_control) &&
		      !pattrib->icv_err && !pattrib->crc_err);

	if (matchbssid) {
		switch (hdr->frame_control &
			cpu_to_le16(IEEE80211_FCTL_TODS |
				    IEEE80211_FCTL_FROMDS)) {
		case cpu_to_le16(IEEE80211_FCTL_TODS):
			bssid = hdr->addr1;
			break;
		case cpu_to_le16(IEEE80211_FCTL_FROMDS):
			bssid = hdr->addr2;
			break;
		case cpu_to_le16(0):
			bssid = hdr->addr3;
			break;
		default:
			bssid = NULL;
			matchbssid = false;
		}

		if (bssid)
			matchbssid = ether_addr_equal(
				get_bssid(&padapter->mlmepriv), bssid);
	}

	pkt_info.bPacketMatchBSSID = matchbssid;

	da = ieee80211_get_DA(hdr);
	pkt_info.bPacketToSelf = pkt_info.bPacketMatchBSSID &&
		(!memcmp(da, myid(&padapter->eeprompriv), ETH_ALEN));

	pkt_info.bPacketBeacon = pkt_info.bPacketMatchBSSID &&
		ieee80211_is_beacon(hdr->frame_control);

	pkt_info.StationID = 0xFF;
	if (pkt_info.bPacketBeacon) {
		if (check_fwstate(&padapter->mlmepriv, WIFI_STATION_STATE) == true)
			sa = padapter->mlmepriv.cur_network.network.MacAddress;
		/* to do Ad-hoc */
	} else {
		sa = ieee80211_get_SA(hdr);
	}

	pstapriv = &padapter->stapriv;
	psta = rtw_get_stainfo23a(pstapriv, sa);
	if (psta) {
		pkt_info.StationID = psta->mac_id;
		/* printk("%s ==> StationID(%d)\n", __func__, pkt_info.StationID); */
	}
	pkt_info.Rate = pattrib->mcs_rate;

	ODM_PhyStatusQuery23a(&pHalData->odmpriv, pPHYInfo,
			      (u8 *)pphy_status, &pkt_info);
	precvframe->psta = NULL;
	if (pkt_info.bPacketMatchBSSID &&
	    (check_fwstate(&padapter->mlmepriv, WIFI_AP_STATE) == true)) {
		if (psta) {
			precvframe->psta = psta;
			rtl8723a_process_phy_info(padapter, precvframe);
		}
	} else if (pkt_info.bPacketToSelf || pkt_info.bPacketBeacon) {
		if (check_fwstate(&padapter->mlmepriv,
				  WIFI_ADHOC_STATE|WIFI_ADHOC_MASTER_STATE) ==
		    true) {
			if (psta)
				precvframe->psta = psta;
		}
		rtl8723a_process_phy_info(padapter, precvframe);
	}
}
Esempio n. 15
0
static inline int pcie_tx_skb_ndp(struct mwl_priv *priv,
				  struct sk_buff *tx_skb)
{
	struct pcie_priv *pcie_priv = priv->hif.priv;
	struct pcie_desc_data_ndp *desc = &pcie_priv->desc_data_ndp;
	u32 tx_send_tail;
	u32 tx_send_head_new;
	struct ieee80211_tx_info *tx_info;
	struct pcie_tx_ctrl_ndp *tx_ctrl;
	struct pcie_tx_desc_ndp *pnext_tx_desc;
	struct ieee80211_hdr *wh;
	u32 ctrl = 0;
	dma_addr_t dma;

	spin_lock_bh(&pcie_priv->tx_desc_lock);

	tx_send_tail = desc->tx_sent_tail;
	tx_send_head_new = desc->tx_sent_head;

	if (((tx_send_head_new + 1) & (MAX_NUM_TX_DESC-1)) == tx_send_tail) {
		/* Update the tx_send_tail */
		tx_send_tail = readl(pcie_priv->iobase1 +
				     MACREG_REG_TXSEDNTAIL);
		desc->tx_sent_tail = tx_send_tail;

		if (((tx_send_head_new + 1) & (MAX_NUM_TX_DESC-1)) ==
		    tx_send_tail) {
			spin_unlock_bh(&pcie_priv->tx_desc_lock);
			return -EAGAIN;
		}
	}

	tx_info = IEEE80211_SKB_CB(tx_skb);
	tx_ctrl = (struct pcie_tx_ctrl_ndp *)tx_info->status.status_driver_data;
	pnext_tx_desc = &desc->ptx_ring[tx_send_head_new];

	if (tx_ctrl->flags & TX_CTRL_TYPE_DATA) {
		wh = (struct ieee80211_hdr *)tx_skb->data;

		skb_pull(tx_skb, tx_ctrl->hdrlen);
		ether_addr_copy(pnext_tx_desc->u.sa,
				ieee80211_get_SA(wh));
		ether_addr_copy(pnext_tx_desc->u.da,
				ieee80211_get_DA(wh));

		if (tx_ctrl->flags & TX_CTRL_EAPOL)
			ctrl = TXRING_CTRL_TAG_EAP << TXRING_CTRL_TAG_SHIFT;
		if (tx_ctrl->flags & TX_CTRL_TCP_ACK) {
			pnext_tx_desc->tcp_dst_src =
				cpu_to_le32(tx_ctrl->tcp_dst_src);
			pnext_tx_desc->tcp_sn = cpu_to_le32(tx_ctrl->tcp_sn);
			ctrl = TXRING_CTRL_TAG_TCP_ACK << TXRING_CTRL_TAG_SHIFT;
		}
		ctrl |= (((tx_ctrl->tx_que_priority & TXRING_CTRL_QID_MASK) <<
			TXRING_CTRL_QID_SHIFT) |
			((tx_skb->len & TXRING_CTRL_LEN_MASK) <<
			TXRING_CTRL_LEN_SHIFT));
	} else {
		/* Assigning rate code; use legacy 6mbps rate. */
		pnext_tx_desc->u.rate_code = cpu_to_le16(RATECODE_TYPE_LEGACY +
			(0 << RATECODE_MCS_SHIFT) + RATECODE_BW_20MHZ);
		pnext_tx_desc->u.max_retry = 5;

		ctrl = (((tx_ctrl->tx_que_priority & TXRING_CTRL_QID_MASK) <<
			TXRING_CTRL_QID_SHIFT) |
			(((tx_skb->len - sizeof(struct pcie_dma_data)) &
			TXRING_CTRL_LEN_MASK) << TXRING_CTRL_LEN_SHIFT) |
			(TXRING_CTRL_TAG_MGMT << TXRING_CTRL_TAG_SHIFT));
	}

	dma = pci_map_single(pcie_priv->pdev, tx_skb->data,
			     tx_skb->len, PCI_DMA_TODEVICE);
	if (pci_dma_mapping_error(pcie_priv->pdev, dma)) {
		dev_kfree_skb_any(tx_skb);
		wiphy_err(priv->hw->wiphy,
			  "failed to map pci memory!\n");
		spin_unlock_bh(&pcie_priv->tx_desc_lock);
		return -EIO;
	}

	pnext_tx_desc->data = cpu_to_le32(dma);
	pnext_tx_desc->ctrl = cpu_to_le32(ctrl);
	pnext_tx_desc->user = cpu_to_le32(pcie_tx_set_skb(priv, tx_skb, dma));

	if ((tx_ctrl->flags & TX_CTRL_TYPE_DATA) &&
	    (tx_ctrl->rate != 0)) {
		skb_push(tx_skb, tx_ctrl->hdrlen);
		skb_get(tx_skb);
		pcie_tx_prepare_info(priv, tx_ctrl->rate, tx_info);
		tx_ctrl->flags |= TX_CTRL_TYPE_DATA;
		ieee80211_tx_status(priv->hw, tx_skb);
	}

	if (++tx_send_head_new >= MAX_NUM_TX_DESC)
		tx_send_head_new = 0;
	desc->tx_sent_head = tx_send_head_new;
	wmb(); /*Data Memory Barrier*/
	writel(tx_send_head_new, pcie_priv->iobase1 + MACREG_REG_TXSENDHEAD);
	desc->tx_desc_busy_cnt++;

	spin_unlock_bh(&pcie_priv->tx_desc_lock);

	return 0;
}
Esempio n. 16
0
static void
indra_get_rate(void *priv, struct ieee80211_sta *sta,
		  void *priv_sta, struct ieee80211_tx_rate_control *txrc)
{
	struct indra_priv *ip = priv;
	struct indra_sta_info *ii = priv_sta;
	struct sk_buff *skb = txrc->skb;
	struct ieee80211_hdr *hdr = (void *)skb->data;
	u8 dst[ETH_ALEN];
	int record, i, status = 0, snr;
	unsigned int per, previous_per;
	bool found = false;
	char* p_data;
	
	/* Search for entry in signals memory from the same 
	 * node that this packet is destined to */
	memcpy(dst, ieee80211_get_DA(hdr), ETH_ALEN);
	for (record=0; record<signals_index; record++) {
		found = true;
		for (i=0; i<ETH_ALEN; i++){
			if (signals[record].address[i] != dst[i]) {
				found = false;  
				break;
			}
		}
		if (found) break;
	}
	
	/* Write received signals data on the new packet and retrieve 
	 * SNR index at the destination node */
	p_data = (char*)skb->data;
    p_data = p_data + 42;
	if (found) {
		p_data[0] = signals[record].rx_signal;
		p_data[1] = signals[record].rx_noise;
		status = signals[record].status;
		if (status == 2) {
			snr = signals[record].tx_signal - signals[record].tx_noise;
			ii->last_snr = snr + SNR_MIN;
			if (ii->last_snr < 0)
				ii->last_snr = 0;
			if (ii->last_snr > SNR_RANGE - 1)
				ii->last_snr = SNR_RANGE - 1;
			printk("MICHELE: SNR index = %i\n",ii->last_snr);
		}
	}
	
	/* Update SNR-PER map */
	if (status == 2) {
		for (i = 0; i < ii->n_rates; i++) {
			if (ii->r[i].last_attempts != 0) {
				per = INDRA_TRUNC(INDRA_FRAC(ii->r[i].last_attempts-ii->r[i].last_success,ii->r[i].last_attempts));
				previous_per = ii->r[i].per_snr_map[ii->last_snr];
				ii->r[i].per_snr_map[ii->last_snr] = INDRA_TRUNC(INDRA_FRAC(ALPHA_INDRA,100)*previous_per) + INDRA_TRUNC(INDRA_FRAC(100-ALPHA_INDRA,100)*per);
				printk("MICHELE: per = %u, previous per = %u, new per = %u\n",per,previous_per,ii->r[i].per_snr_map[ii->last_snr]);
				ii->r[i].last_attempts = 0;
				ii->r[i].last_success = 0;
			}
		}
	}
	
	/* management/no-ack frames do not use rate control */
	if (rate_control_send_low(sta, priv_sta, txrc))
		return;
		
	/* Rate selection algorithm */
	indra_update_rates(ip, ii);

}
Esempio n. 17
0
static void
indra_tx_status(void *priv, struct ieee80211_supported_band *sband,
		   struct ieee80211_sta *sta, void *priv_sta,
		   struct sk_buff *skb)
{
	struct indra_sta_info *ii = priv_sta;
	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
	struct ieee80211_tx_rate *ar = info->status.rates;
	struct ieee80211_hdr *hdr = (void *)skb->data;
	u8 dst[ETH_ALEN];
	bool found = false;
	int i, s, count, record, r = 0, ndx = 0, snr_index = SNR_RANGE-1;			
	int success, null;
	unsigned int per_threshold = INDRA_FRAC(PER_TH_INDRA,100);

	/* Check transmission status: successful or not */
	success = !!(info->flags & IEEE80211_TX_STAT_ACK);
	
	/* Check if this is a null transmission: if so, exit */
	null = !!(info->flags & IEEE80211_TX_CTL_USE_MINRATE);
	if (null)
	  return;
	
	/* Reset number of attempts and successes for each rate */
	for (i = 0; i < ii->n_rates; i++) {
		ii->r[i].last_attempts = 0;
		ii->r[i].last_success = 0;
	}
	
	/* Initialize new entry in rclog character device */  
	data_rclog_buf[rclog_in].success = success;
	data_rclog_buf[rclog_in].probe = 0;  
	for (i = 0; i < 4; i++) {
		data_rclog_buf[rclog_in].rate_idx[i] = -1;
		data_rclog_buf[rclog_in].rate_count[i] = -1;
	}
	
	/* Check used rates */
	for (i = 0; i < IEEE80211_TX_MAX_RATES; i++) {			
		/* Retrieve used rate */
		if (ar[i].idx < 0)
			break;
		ndx = rix_to_ndx(ii, ar[i].idx);
		if (ndx < 0)
			continue;
		
		/* Retrieve and update number of attempts
		 * for the retrieved rate */
		count = ar[i].count;
		ii->r[ndx].last_attempts = ar[i].count;
		
		/* Retrieve maximum SNR index with PER over the 
		 * threshold for the retrieved rate */
		for (s = snr_index; s >= 0; s--) {
			if (ii->r[ndx].per_snr_map[s] >= per_threshold) {
				snr_index = s;
				break;
			}
		} 
		
		/* Write in the rclog device */		
		data_rclog_buf[rclog_in].rate_idx[r] = ndx;
		data_rclog_buf[rclog_in].rate_count[r] = count;
		r++;				
		
		/* Update number of successes for the 
		 * retrieved rate */ 
		if ((i != IEEE80211_TX_MAX_RATES - 1) && (ar[i + 1].idx < 0))
			ii->r[ndx].last_success += success;
	}
	
	/* Point to new entry in rclog character device */
	rclog_in = (rclog_in+1)%RCLOG_BUF_DIM;
		
	/* Update estimated SNR */	
	ii->last_snr = snr_index;
	
	/* Retrieve receiver and update status (waiting for packet
	 * or not)*/
	memcpy(dst, ieee80211_get_DA(hdr), ETH_ALEN);
	for (record = 0; record < signals_index; record++) {
		found = true;
		for (i = 0; i < ETH_ALEN; i++){
			if (signals[record].address[i] != dst[i]) {
				found = false;  
				break;
			}
		}
		if (found) break;
	}
	if (found) {
		signals[record].status = success;
	}

}