struct ol_tx_frms_queue_t * ol_tx_classify( struct ol_txrx_vdev_t *vdev, struct ol_tx_desc_t *tx_desc, adf_nbuf_t tx_nbuf, struct ol_txrx_msdu_info_t *tx_msdu_info) { struct ol_txrx_pdev_t *pdev = vdev->pdev; struct ol_txrx_peer_t *peer = NULL; struct ol_tx_frms_queue_t *txq = NULL; A_UINT8 *dest_addr; A_UINT8 tid; #if defined(CONFIG_HL_SUPPORT) && defined(FEATURE_WLAN_TDLS) u_int8_t peer_id; #endif TX_SCHED_DEBUG_PRINT("Enter %s\n", __func__); dest_addr = ol_tx_dest_addr_find(pdev, tx_nbuf); if ((IEEE80211_IS_MULTICAST(dest_addr)) || (vdev->opmode == wlan_op_mode_ocb)) { txq = &vdev->txqs[OL_TX_VDEV_MCAST_BCAST]; tx_msdu_info->htt.info.ext_tid = HTT_TX_EXT_TID_NON_QOS_MCAST_BCAST; if (vdev->opmode == wlan_op_mode_sta) { /* * The STA sends a frame with a broadcast dest addr (DA) as a * unicast frame to the AP's receive addr (RA). * Find the peer object that represents the AP that the STA * is associated with. */ peer = ol_txrx_assoc_peer_find(vdev); if (!peer) { VOS_TRACE(VOS_MODULE_ID_TXRX, VOS_TRACE_LEVEL_ERROR, "Error: STA %p (%02x:%02x:%02x:%02x:%02x:%02x) " "trying to send bcast DA tx data frame " "w/o association\n", vdev, vdev->mac_addr.raw[0], vdev->mac_addr.raw[1], vdev->mac_addr.raw[2], vdev->mac_addr.raw[3], vdev->mac_addr.raw[4], vdev->mac_addr.raw[5]); return NULL; /* error */ } else if ((peer->security[OL_TXRX_PEER_SECURITY_MULTICAST].sec_type != htt_sec_type_wapi) && (A_STATUS_OK == adf_nbuf_is_dhcp_pkt(tx_nbuf))) { /* DHCP frame to go with voice priority */ txq = &peer->txqs[TX_DHCP_TID]; tx_msdu_info->htt.info.ext_tid = TX_DHCP_TID; } /* * The following line assumes each peer object has a single ID. * This is currently true, and is expected to remain true. */ tx_msdu_info->htt.info.peer_id = peer->peer_ids[0]; } else if (vdev->opmode == wlan_op_mode_ocb) { tx_msdu_info->htt.info.peer_id = HTT_INVALID_PEER_ID; /* In OCB mode, don't worry about the peer. We don't need it. */ peer = NULL; } else { tx_msdu_info->htt.info.peer_id = HTT_INVALID_PEER_ID; /* * Look up the vdev's BSS peer, so that the classify_extension * function can check whether to encrypt multicast / broadcast * frames. */ peer = ol_txrx_peer_find_hash_find(pdev, vdev->mac_addr.raw, 0, 1); if (!peer) { VOS_TRACE(VOS_MODULE_ID_TXRX, VOS_TRACE_LEVEL_ERROR, "Error: vdev %p (%02x:%02x:%02x:%02x:%02x:%02x) " "trying to send bcast/mcast, but no self-peer found\n", vdev, vdev->mac_addr.raw[0], vdev->mac_addr.raw[1], vdev->mac_addr.raw[2], vdev->mac_addr.raw[3], vdev->mac_addr.raw[4], vdev->mac_addr.raw[5]); return NULL; /* error */ } } tx_msdu_info->htt.info.is_unicast = FALSE; } else { /* tid would be overwritten for non QoS case*/ tid = ol_tx_tid(pdev, tx_nbuf, tx_msdu_info); if ((HTT_TX_EXT_TID_INVALID == tid) || (tid >= OL_TX_NUM_TIDS)) { VOS_TRACE(VOS_MODULE_ID_TXRX, VOS_TRACE_LEVEL_ERROR, "%s Error: could not classify packet into valid TID(%d).\n", __func__, tid); return NULL; } #ifdef ATH_SUPPORT_WAPI /* Check to see if a frame is a WAI frame */ if (tx_msdu_info->htt.info.ethertype == ETHERTYPE_WAI) { /* WAI frames should not be encrypted */ tx_msdu_info->htt.action.do_encrypt = 0; VOS_TRACE(VOS_MODULE_ID_TXRX, VOS_TRACE_LEVEL_INFO, "Tx Frame is a WAI frame\n"); } #endif /* ATH_SUPPORT_WAPI */ /* * Find the peer and increment its reference count. * If this vdev is an AP, use the dest addr (DA) to determine * which peer STA this unicast data frame is for. * If this vdev is a STA, the unicast data frame is for the * AP the STA is associated with. */ if (vdev->opmode == wlan_op_mode_sta) { /* * TO DO: * To support TDLS, first check if there is a TDLS peer STA, * and if so, check if the DA matches the TDLS peer STA's * MAC address. * If there is no peer TDLS STA, or if the DA is not the * TDLS STA's address, then the frame is either for the AP * itself, or is supposed to be sent to the AP for forwarding. */ #if 0 if (vdev->num_tdls_peers > 0) { peer = NULL; for (i = 0; i < vdev->num_tdls_peers); i++) { int differs = adf_os_mem_cmp( vdev->tdls_peers[i]->mac_addr.raw, dest_addr, OL_TXRX_MAC_ADDR_LEN); if (!differs) { peer = vdev->tdls_peers[i]; break; } } } else { /* send to AP */ peer = ol_txrx_assoc_peer_find(vdev); } #endif #if defined(CONFIG_HL_SUPPORT) && defined(FEATURE_WLAN_TDLS) if (vdev->hlTdlsFlag) { peer = ol_txrx_find_peer_by_addr(pdev, vdev->hl_tdls_ap_mac_addr.raw, &peer_id); if (peer && (peer->peer_ids[0] == HTT_INVALID_PEER_ID)) peer = NULL; else { if (peer) adf_os_atomic_inc(&peer->ref_cnt); } } if (!peer) peer = ol_txrx_assoc_peer_find(vdev); #else peer = ol_txrx_assoc_peer_find(vdev); #endif } else {
/* * Porting from Ap11PrepareForwardedPacket. * This routine is called when a RX data frame from an associated station is * to be forwarded to another associated station. We will prepare the * received packet so that it is suitable for transmission again. * Check that this Packet is suitable for forwarding. If yes, then * prepare the new 802.11 header. */ static inline void ol_ap_fwd_check(struct ol_txrx_vdev_t *vdev, adf_nbuf_t msdu) { struct ieee80211_frame *mac_header; unsigned char tmp_addr[6]; unsigned char type; unsigned char subtype; unsigned char fromds; unsigned char tods; mac_header = (struct ieee80211_frame *) (adf_nbuf_data(msdu)); TXRX_ASSERT1(mac_header); type = mac_header->i_fc[0] & IEEE80211_FC0_TYPE_MASK; subtype = mac_header->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK; tods = mac_header->i_fc[1] & IEEE80211_FC1_DIR_TODS; fromds = mac_header->i_fc[1] & IEEE80211_FC1_DIR_FROMDS; /* * Make sure no QOS or any other non-data subtype * Should be a ToDs data frame. * Make sure that this frame is unicast and not for us. * These packets should come up through the normal rx path and not forwarded. */ if (type != IEEE80211_FC0_TYPE_DATA || subtype != 0x0 || ((tods != 1) || (fromds != 0)) || (adf_os_mem_cmp( mac_header->i_addr3, vdev->mac_addr.raw, IEEE80211_ADDR_LEN) == 0)) { #ifdef DEBUG_HOST_RC TXRX_PRINT(TXRX_PRINT_LEVEL_INFO1, "Exit: %s | Unnecessary to adjust mac header\n", __func__); #endif } else { // Flip the ToDs bit to FromDs mac_header->i_fc[1] &= 0xfe; mac_header->i_fc[1] |= 0x2; /* * Flip the addresses * (ToDs, addr1, RA=BSSID) move to (FrDs, addr2, TA=BSSID) * (ToDs, addr2, SA) move to (FrDs, addr3, SA) * (ToDs, addr3, DA) move to (FrDs, addr1, DA) */ memcpy(tmp_addr, mac_header->i_addr2, sizeof (tmp_addr)); memcpy(mac_header->i_addr2, mac_header->i_addr1, sizeof (tmp_addr)); memcpy(mac_header->i_addr1, mac_header->i_addr3, sizeof (tmp_addr)); memcpy(mac_header->i_addr3, tmp_addr, sizeof (tmp_addr)); } }