void ol_rx_fwd_check( struct ol_txrx_vdev_t *vdev, struct ol_txrx_peer_t *peer, unsigned tid, adf_nbuf_t msdu_list) { struct ol_txrx_pdev_t *pdev = vdev->pdev; adf_nbuf_t deliver_list_head = NULL; adf_nbuf_t deliver_list_tail = NULL; adf_nbuf_t msdu; if (OL_CFG_RAW_RX_LIKELINESS(pdev->rx_decap_mode == htt_pkt_type_raw)) { /* Forwarding is not handled since keys would reside on Access * Controller. * * Full fledged Mixed VAP functionality can add requisite exceptions in * this function. */ ol_rx_deliver(vdev, peer, tid, msdu_list); return; } msdu = msdu_list; while (msdu) { struct ol_txrx_vdev_t *tx_vdev; void *rx_desc; /* * Remember the next list elem, because our processing * may cause the MSDU to get linked into a different list. */ msdu_list = adf_nbuf_next(msdu); rx_desc = htt_rx_msdu_desc_retrieve(pdev->htt_pdev, msdu); if (htt_rx_msdu_forward(pdev->htt_pdev, rx_desc)) { /* * Use the same vdev that received the frame to * transmit the frame. * This is exactly what we want for intra-BSS forwarding, * like STA-to-STA forwarding and multicast echo. * If this is a intra-BSS forwarding case (which is not * currently supported), then the tx vdev is different * from the rx vdev. * On the LL host the vdevs are not actually used for tx, * so it would still work to use the rx vdev rather than * the tx vdev. * For HL, the tx classification searches for the DA within * the given vdev, so we would want to get the DA peer ID * from the target, so we can locate the tx vdev. */ tx_vdev = vdev; /* * This MSDU needs to be forwarded to the tx path. * Check whether it also needs to be sent to the OS shim, * in which case we need to make a copy (or clone?). */ if (htt_rx_msdu_discard(pdev->htt_pdev, rx_desc)) { htt_rx_msdu_desc_free(pdev->htt_pdev, msdu); ol_rx_fwd_to_tx(tx_vdev, msdu); msdu = NULL; /* already handled this MSDU */ } else { adf_nbuf_t copy; copy = adf_nbuf_copy(msdu); if (copy) { ol_rx_fwd_to_tx(tx_vdev, copy); } } } if (msdu) { /* send this frame to the OS */ OL_TXRX_LIST_APPEND(deliver_list_head, deliver_list_tail, msdu); } msdu = msdu_list; } if (deliver_list_head) { adf_nbuf_set_next(deliver_list_tail, NULL); /* add NULL terminator */ ol_rx_deliver(vdev, peer, tid, deliver_list_head); } }
void ol_rx_fwd_check( struct ol_txrx_vdev_t *vdev, struct ol_txrx_peer_t *peer, unsigned tid, adf_nbuf_t msdu_list) { struct ol_txrx_pdev_t *pdev = vdev->pdev; adf_nbuf_t deliver_list_head = NULL; adf_nbuf_t deliver_list_tail = NULL; adf_nbuf_t msdu; msdu = msdu_list; while (msdu) { struct ol_txrx_vdev_t *tx_vdev; void *rx_desc; /* * Remember the next list elem, because our processing * may cause the MSDU to get linked into a different list. */ msdu_list = adf_nbuf_next(msdu); rx_desc = htt_rx_msdu_desc_retrieve(pdev->htt_pdev, msdu); if (!vdev->disable_intrabss_fwd && htt_rx_msdu_forward(pdev->htt_pdev, rx_desc)) { #ifdef QCA_ARP_SPOOFING_WAR void *filter_cb; #endif int do_not_fwd = 0; /* * Use the same vdev that received the frame to * transmit the frame. * This is exactly what we want for intra-BSS forwarding, * like STA-to-STA forwarding and multicast echo. * If this is a intra-BSS forwarding case (which is not * currently supported), then the tx vdev is different * from the rx vdev. * On the LL host the vdevs are not actually used for tx, * so it would still work to use the rx vdev rather than * the tx vdev. * For HL, the tx classification searches for the DA within * the given vdev, so we would want to get the DA peer ID * from the target, so we can locate the tx vdev. */ tx_vdev = vdev; /* * Copying TID value of RX packet to forwarded * packet if the tid is other than non qos tid. * But for non qos tid fill invalid tid so that * Fw will take care of filling proper tid. */ if (tid != HTT_NON_QOS_TID) { adf_nbuf_set_tid(msdu, tid); } else { adf_nbuf_set_tid(msdu, ADF_NBUF_TX_EXT_TID_INVALID); } #ifdef QCA_ARP_SPOOFING_WAR filter_cb = (void *)NBUF_CB_PTR(msdu); if (filter_cb) { do_not_fwd = (*(hdd_filter_cb_t)filter_cb)(vdev->vdev_id, msdu, RX_INTRA_BSS_FWD); } #endif /* * This MSDU needs to be forwarded to the tx path. * Check whether it also needs to be sent to the OS shim, * in which case we need to make a copy (or clone?). */ if (!do_not_fwd) { if (htt_rx_msdu_discard(pdev->htt_pdev, rx_desc)) { htt_rx_msdu_desc_free(pdev->htt_pdev, msdu); adf_net_buf_debug_release_skb(msdu); ol_rx_fwd_to_tx(tx_vdev, msdu); msdu = NULL; /* already handled this MSDU */ tx_vdev->fwd_tx_packets++; vdev->fwd_rx_packets++; TXRX_STATS_ADD(pdev, pub.rx.intra_bss_fwd.packets_fwd, 1); } else { adf_nbuf_t copy; copy = adf_nbuf_copy(msdu); if (copy) { ol_rx_fwd_to_tx(tx_vdev, copy); tx_vdev->fwd_tx_packets++; } TXRX_STATS_ADD(pdev, pub.rx.intra_bss_fwd.packets_stack_n_fwd, 1); } } } else { TXRX_STATS_ADD(pdev, pub.rx.intra_bss_fwd.packets_stack, 1); } if (msdu) { /* send this frame to the OS */ OL_TXRX_LIST_APPEND(deliver_list_head, deliver_list_tail, msdu); } msdu = msdu_list; } if (deliver_list_head) { adf_nbuf_set_next(deliver_list_tail, NULL); /* add NULL terminator */ if (ol_cfg_is_full_reorder_offload(pdev->ctrl_pdev)) { ol_rx_in_order_deliver(vdev, peer, tid, deliver_list_head); } else { ol_rx_deliver(vdev, peer, tid, deliver_list_head); } } }