void epping_tx_copier_schedule(epping_context_t *pEpping_ctx, HTC_ENDPOINT_ID eid, adf_nbuf_t skb)
{
   epping_poll_t *epping_poll = &pEpping_ctx->epping_poll[eid];

   if (!epping_poll->skb && skb) {
      epping_poll->skb = adf_nbuf_copy(skb);
   }
   if (adf_os_atomic_read(&epping_poll->atm) < EPPING_MAX_WATER_MARK) {
      adf_os_atomic_inc(&epping_poll->atm);
      up(&epping_poll->sem);
   }
}
void epping_tx_dup_pkt(epping_adapter_t *pAdapter,
                       HTC_ENDPOINT_ID eid, adf_nbuf_t skb)
{
   struct epping_cookie * cookie = NULL;
   int skb_len, ret;
   adf_nbuf_t new_skb;

   cookie = epping_alloc_cookie(pAdapter->pEpping_ctx);
   if (cookie == NULL) {
      EPPING_LOG(VOS_TRACE_LEVEL_FATAL,
         "%s: epping_alloc_cookie returns no resource\n", __func__);
      return;
   }
   new_skb = adf_nbuf_copy(skb);
   if (!new_skb) {
      EPPING_LOG(VOS_TRACE_LEVEL_FATAL,
         "%s: adf_nbuf_copy returns no resource\n", __func__);
      epping_free_cookie(pAdapter->pEpping_ctx, cookie);
      return;
   }
   SET_HTC_PACKET_INFO_TX(&cookie->HtcPkt,
      cookie, adf_nbuf_data(skb), adf_nbuf_len(new_skb), eid, 0);
   SET_HTC_PACKET_NET_BUF_CONTEXT(&cookie->HtcPkt, new_skb);
   skb_len = (int)adf_nbuf_len(new_skb);
   /* send the packet */
   ret = HTCSendPkt(pAdapter->pEpping_ctx->HTCHandle, &cookie->HtcPkt);
   if (ret != A_OK) {
      EPPING_LOG(VOS_TRACE_LEVEL_FATAL,
         "%s: HTCSendPkt failed, ret = %d\n", __func__, ret);
      epping_free_cookie(pAdapter->pEpping_ctx, cookie);
      adf_nbuf_free(new_skb);
      return;
   }
   pAdapter->stats.tx_bytes += skb_len;
   ++pAdapter->stats.tx_packets;
   if (((pAdapter->stats.tx_packets +
         pAdapter->stats.tx_dropped) % EPPING_STATS_LOG_COUNT) == 0 &&
       (pAdapter->stats.tx_packets || pAdapter->stats.tx_dropped)) {
       epping_log_stats(pAdapter, __func__);
   }
}
Example #3
0
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);
        }
    }
}