/** * test main entrance for library sched */ static int test_sched(void) { struct rte_mempool *mp = NULL; struct rte_sched_port *port = NULL; uint32_t pipe; struct rte_mbuf *in_mbufs[10]; struct rte_mbuf *out_mbufs[10]; int i; int err; mp = create_mempool(); port_param.socket = 0; port_param.rate = (uint64_t) 10000 * 1000 * 1000 / 8; port = rte_sched_port_config(&port_param); VERIFY(port != NULL, "Error config sched port\n"); err = rte_sched_subport_config(port, SUBPORT, subport_param); VERIFY(err == 0, "Error config sched, err=%d\n", err); for (pipe = 0; pipe < port_param.n_pipes_per_subport; pipe ++) { err = rte_sched_pipe_config(port, SUBPORT, pipe, 0); VERIFY(err == 0, "Error config sched pipe %u, err=%d\n", pipe, err); } for (i = 0; i < 10; i++) { in_mbufs[i] = rte_pktmbuf_alloc(mp); prepare_pkt(in_mbufs[i]); } err = rte_sched_port_enqueue(port, in_mbufs, 10); VERIFY(err == 10, "Wrong enqueue, err=%d\n", err); err = rte_sched_port_dequeue(port, out_mbufs, 10); VERIFY(err == 10, "Wrong dequeue, err=%d\n", err); for (i = 0; i < 10; i++) { enum rte_meter_color color; uint32_t subport, traffic_class, queue; color = rte_sched_port_pkt_read_color(out_mbufs[i]); VERIFY(color == e_RTE_METER_YELLOW, "Wrong color\n"); rte_sched_port_pkt_read_tree_path(out_mbufs[i], &subport, &pipe, &traffic_class, &queue); VERIFY(subport == SUBPORT, "Wrong subport\n"); VERIFY(pipe == PIPE, "Wrong pipe\n"); VERIFY(traffic_class == TC, "Wrong traffic_class\n"); VERIFY(queue == QUEUE, "Wrong queue\n"); } struct rte_sched_subport_stats subport_stats; uint32_t tc_ov; rte_sched_subport_read_stats(port, SUBPORT, &subport_stats, &tc_ov); //VERIFY(subport_stats.n_pkts_tc[TC-1] == 10, "Wrong subport stats\n"); struct rte_sched_queue_stats queue_stats; uint16_t qlen; rte_sched_queue_read_stats(port, QUEUE, &queue_stats, &qlen); //VERIFY(queue_stats.n_pkts == 10, "Wrong queue stats\n"); rte_sched_port_free(port); return 0; }
/** * Dequeue mbufs from output queue and send to ethernet port. * This function is called from I/O (Output) thread. */ static inline void app_lcore_io_tx(struct app_lcore_params_io *lp, uint32_t n_workers, uint32_t bsz_rd, uint32_t bsz_wr) { uint32_t worker; for (worker = 0; worker < n_workers; worker ++) { uint32_t i; for (i = 0; i < lp->tx.n_nic_ports; i ++) { uint8_t port = lp->tx.nic_ports[i]; struct rte_ring *ring = lp->tx.rings[port][worker]; struct interface *ifp; uint32_t n_mbufs, n_pkts; int ret; n_mbufs = lp->tx.mbuf_out[port].n_mbufs; ret = rte_ring_sc_dequeue_burst(ring, (void **) &lp->tx.mbuf_out[port].array[n_mbufs], bsz_rd - n_mbufs); if (unlikely(ret == 0)) { continue; } n_mbufs += (uint32_t)ret; #if APP_IO_TX_DROP_ALL_PACKETS { uint32_t j; APP_IO_TX_PREFETCH0(lp->tx.mbuf_out[port].array[0]); APP_IO_TX_PREFETCH0(lp->tx.mbuf_out[port].array[1]); for (j = 0; j < n_mbufs; j ++) { if (likely(j < n_mbufs - 2)) { APP_IO_TX_PREFETCH0(lp->tx.mbuf_out[port].array[j + 2]); } rte_pktmbuf_free(lp->tx.mbuf_out[port].array[j]); } lp->tx.mbuf_out[port].n_mbufs = 0; continue; } #endif if (unlikely(n_mbufs < bsz_wr)) { lp->tx.mbuf_out[port].n_mbufs = n_mbufs; lp->tx.mbuf_out_flush[port] = 1; continue; } ifp = dpdk_interface_lookup(port); if (ifp != NULL && ifp->sched_port != NULL) { struct lagopus_packet *pkt; struct rte_mbuf *m; int qidx, color; for (i = 0; i < n_mbufs; i++) { m = lp->tx.mbuf_out[port].array[i]; pkt = (struct lagopus_packet *) (m->buf_addr + APP_DEFAULT_MBUF_LOCALDATA_OFFSET); if (unlikely(pkt->queue_id != 0)) { qidx = dpdk_interface_queue_id_to_index(ifp, pkt->queue_id); color = rte_meter_trtcm_color_blind_check(&ifp->ifqueue.meters[qidx], rte_rdtsc(), OS_M_PKTLEN(m)); rte_sched_port_pkt_write(m, 0, 0, 0, qidx, color); } } n_mbufs = rte_sched_port_enqueue(ifp->sched_port, lp->tx.mbuf_out[port].array, n_mbufs); n_mbufs = rte_sched_port_dequeue(ifp->sched_port, lp->tx.mbuf_out[port].array, n_mbufs); } DPRINTF("send %d pkts\n", n_mbufs); n_pkts = rte_eth_tx_burst(port, 0, lp->tx.mbuf_out[port].array, (uint16_t) n_mbufs); DPRINTF("sent %d pkts\n", n_pkts); #if APP_STATS lp->tx.nic_ports_iters[port] ++; lp->tx.nic_ports_count[port] += n_pkts; if (unlikely(lp->tx.nic_ports_iters[port] == APP_STATS)) { unsigned lcore = rte_lcore_id(); printf("\t\t\tI/O TX %u out (port %u): avg burst size = %.2f\n", lcore, (unsigned) port, ((double) lp->tx.nic_ports_count[port]) / ((double) lp->tx.nic_ports_iters[port])); lp->tx.nic_ports_iters[port] = 0; lp->tx.nic_ports_count[port] = 0; } #endif if (unlikely(n_pkts < n_mbufs)) { uint32_t k; for (k = n_pkts; k < n_mbufs; k ++) { struct rte_mbuf *pkt_to_free = lp->tx.mbuf_out[port].array[k]; rte_pktmbuf_free(pkt_to_free); } } lp->tx.mbuf_out[port].n_mbufs = 0; lp->tx.mbuf_out_flush[port] = 0; } } }