ifobj->umem = &ifobj->umem_arr[0];
                ifobj->xsk = &ifobj->xsk_arr[0];
                ifobj->use_poll = false;
+               ifobj->pacing_on = true;
                ifobj->pkt_stream = test->pkt_stream_default;
 
                if (i == 0) {
 {
        struct pkt *pkt = pkt_stream_get_next_rx_pkt(pkt_stream);
        u32 idx_rx = 0, idx_fq = 0, rcvd, i;
+       u32 total = 0;
        int ret;
 
        while (pkt) {
 
                xsk_ring_prod__submit(&xsk->umem->fq, rcvd);
                xsk_ring_cons__release(&xsk->rx, rcvd);
+
+               pthread_mutex_lock(&pacing_mutex);
+               pkts_in_flight -= rcvd;
+               total += rcvd;
+               if (pkts_in_flight < umem->num_frames)
+                       pthread_cond_signal(&pacing_cond);
+               pthread_mutex_unlock(&pacing_mutex);
        }
 }
 
                        valid_pkts++;
        }
 
+       pthread_mutex_lock(&pacing_mutex);
+       pkts_in_flight += valid_pkts;
+       if (ifobject->pacing_on && pkts_in_flight >= ifobject->umem->num_frames - BATCH_SIZE) {
+               kick_tx(xsk);
+               pthread_cond_wait(&pacing_cond, &pacing_mutex);
+       }
+       pthread_mutex_unlock(&pacing_mutex);
+
        xsk_ring_prod__submit(&xsk->tx, i);
        xsk->outstanding_tx += valid_pkts;
-       complete_pkts(xsk, BATCH_SIZE);
+       complete_pkts(xsk, i);
 
+       usleep(10);
        return i;
 }
 
        fds.events = POLLOUT;
 
        while (pkt_cnt < ifobject->pkt_stream->nb_pkts) {
-               u32 sent;
-
                if (ifobject->use_poll) {
                        int ret;
 
                                continue;
                }
 
-               sent = __send_pkts(ifobject, pkt_cnt);
-               pkt_cnt += sent;
-               usleep(10);
+               pkt_cnt += __send_pkts(ifobject, pkt_cnt);
        }
 
        wait_for_tx_completion(ifobject->xsk);
 
        test->current_step++;
        pkt_stream_reset(ifobj_rx->pkt_stream);
+       pkts_in_flight = 0;
 
        /*Spawn RX thread */
        pthread_create(&t0, NULL, ifobj_rx->func_ptr, test);
        for (i = 0; i < STAT_TEST_TYPE_MAX; i++) {
                test_spec_reset(test);
                stat_test_type = i;
+               /* No or few packets will be received so cannot pace packets */
+               test->ifobj_tx->pacing_on = false;
 
                switch (stat_test_type) {
                case STAT_TEST_RX_DROPPED:
 
 #define UDP_PKT_DATA_SIZE (UDP_PKT_SIZE - sizeof(struct udphdr))
 #define USLEEP_MAX 10000
 #define SOCK_RECONF_CTR 10
-#define BATCH_SIZE 8
+#define BATCH_SIZE 64
 #define POLL_TMOUT 1000
 #define DEFAULT_PKT_CNT (4 * 1024)
 #define DEFAULT_UMEM_BUFFERS (DEFAULT_PKT_CNT / 4)
        bool tx_on;
        bool rx_on;
        bool use_poll;
+       bool pacing_on;
        u8 dst_mac[ETH_ALEN];
        u8 src_mac[ETH_ALEN];
 };
 };
 
 pthread_barrier_t barr;
+pthread_mutex_t pacing_mutex = PTHREAD_MUTEX_INITIALIZER;
+pthread_cond_t pacing_cond = PTHREAD_COND_INITIALIZER;
+
+u32 pkts_in_flight;
 
 #endif                         /* XDPXCEIVER_H */