/* Try to clear stats for all vport counters, which should succeed */ static void test_stats_vport_xxx_clear(int argc, char *argv[]) { int vportid = 0; stats_init(); stats_vport_clear_all(); /* increment stats so there's something to clear */ for (vportid = 0; vportid < MAX_VPORTS; vportid++) { stats_vport_rx_increment(vportid, 23); stats_vport_rx_drop_increment(vportid, 23); stats_vport_tx_increment(vportid, 23); stats_vport_tx_drop_increment(vportid, 23); stats_vport_overrun_increment(vportid, 23); stats_vport_rx_increment(vportid, 19); stats_vport_rx_drop_increment(vportid, 19); stats_vport_tx_increment(vportid, 19); stats_vport_tx_drop_increment(vportid, 19); stats_vport_overrun_increment(vportid, 19); } for (vportid = 0; vportid < MAX_VPORTS; vportid++) { stats_vport_clear(vportid); assert(stats_vport_rx_get(vportid) == 0); assert(stats_vport_rx_drop_get(vportid) == 0); assert(stats_vport_tx_get(vportid) == 0); assert(stats_vport_tx_drop_get(vportid) == 0); assert(stats_vport_overrun_get(vportid) == 0); } }
/* * Function sends unmatched packets to vswitchd. */ void send_packet_to_vswitchd(struct rte_mbuf *mbuf, struct dpdk_upcall *info) { int rslt = 0; void *mbuf_ptr = NULL; const uint64_t dpif_send_tsc = (rte_get_tsc_hz() + US_PER_S - 1) / US_PER_S * DPIF_SEND_US; uint64_t cur_tsc = 0; uint64_t diff_tsc = 0; static uint64_t prev_tsc = 0; /* send one packet, delete information about segments */ rte_pktmbuf_pkt_len(mbuf) = rte_pktmbuf_data_len(mbuf); /* allocate space before the packet for the upcall info */ mbuf_ptr = rte_pktmbuf_prepend(mbuf, sizeof(*info)); if (mbuf_ptr == NULL) { printf("Cannot prepend upcall info\n"); rte_pktmbuf_free(mbuf); stats_vswitch_tx_drop_increment(INC_BY_1); stats_vport_tx_drop_increment(VSWITCHD, INC_BY_1); return; } rte_memcpy(mbuf_ptr, info, sizeof(*info)); /* send the packet and the upcall info to the daemon */ rslt = rte_ring_mp_enqueue(vswitchd_packet_ring, mbuf); if (rslt < 0) { if (rslt == -ENOBUFS) { rte_pktmbuf_free(mbuf); stats_vswitch_tx_drop_increment(INC_BY_1); stats_vport_tx_drop_increment(VSWITCHD, INC_BY_1); return; } else { stats_vport_overrun_increment(VSWITCHD, INC_BY_1); } } stats_vport_tx_increment(VSWITCHD, INC_BY_1); cur_tsc = rte_rdtsc(); diff_tsc = cur_tsc - prev_tsc; prev_tsc = cur_tsc; /* Only signal the daemon after 100 milliseconds */ if (unlikely(diff_tsc > dpif_send_tsc)) send_signal_to_dpif(); }
/* Try to increment stats for all vport counters, which should * succeed */ static void test_stats_vport_xxx_increment(int argc, char *argv[]) { int vportid = 0; stats_init(); stats_vport_clear_all(); for (vportid = 0; vportid < MAX_VPORTS; vportid++) { stats_vport_rx_increment(vportid, 23); stats_vport_rx_drop_increment(vportid, 23); stats_vport_tx_increment(vportid, 23); stats_vport_tx_drop_increment(vportid, 23); stats_vport_overrun_increment(vportid, 23); stats_vport_rx_increment(vportid, 19); stats_vport_rx_drop_increment(vportid, 19); stats_vport_tx_increment(vportid, 19); stats_vport_tx_drop_increment(vportid, 19); stats_vport_overrun_increment(vportid, 19); } }
/* * Flush packets scheduled for transmit on ports */ static void flush_pkts(unsigned action) { unsigned i = 0; uint16_t deq_count = PKT_BURST_SIZE; struct rte_mbuf *pkts[PKT_BURST_SIZE] = {0}; struct port_queue *pq = &port_queues[action & PORT_MASK]; const uint64_t drain_tsc = (rte_get_tsc_hz() + US_PER_S - 1) / US_PER_S * BURST_TX_DRAIN_US; uint64_t diff_tsc = 0; static uint64_t prev_tsc[MAX_PHYPORTS] = {0}; uint64_t cur_tsc = rte_rdtsc(); unsigned num_pkts; diff_tsc = cur_tsc - prev_tsc[action & PORT_MASK]; if (unlikely(rte_ring_count(pq->tx_q) >= PKT_BURST_SIZE)) { num_pkts = PKT_BURST_SIZE; } else { /* If queue idles with less than PKT_BURST packets, drain it*/ if(unlikely(diff_tsc > drain_tsc)) { num_pkts = rte_ring_count(pq->tx_q); } else { return; } } if (unlikely(rte_ring_dequeue_bulk( pq->tx_q, (void **)pkts, num_pkts) != 0)) return; const uint16_t sent = rte_eth_tx_burst( ports->id[action & PORT_MASK], 0, pkts, num_pkts); prev_tsc[action & PORT_MASK] = cur_tsc; if (unlikely(sent < num_pkts)) { for (i = sent; i < num_pkts; i++) rte_pktmbuf_free(pkts[i]); stats_vport_tx_drop_increment(action, num_pkts - sent); } stats_vport_tx_increment(action, sent); }