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; } }
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); }
/*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>*/ } } } } }
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); }
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]; } }
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; } }
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 {
/* * 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; }
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; }
/* * 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; }
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); } }
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 {
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; }
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); } }
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; }
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); }
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; } }