153a3b7e8SJerin Jacob /* SPDX-License-Identifier: BSD-3-Clause 253a3b7e8SJerin Jacob * Copyright(c) 2017 Cavium, Inc 3d1f59fb7SJerin Jacob */ 4d1f59fb7SJerin Jacob 5d1f59fb7SJerin Jacob #include "test_order_common.h" 6d1f59fb7SJerin Jacob 7d1f59fb7SJerin Jacob int 8ba11ebf1SJerin Jacob order_test_result(struct evt_test *test, struct evt_options *opt) 9ba11ebf1SJerin Jacob { 10ba11ebf1SJerin Jacob RTE_SET_USED(opt); 11ba11ebf1SJerin Jacob struct test_order *t = evt_test_priv(test); 12ba11ebf1SJerin Jacob 13ba11ebf1SJerin Jacob return t->result; 14ba11ebf1SJerin Jacob } 15ba11ebf1SJerin Jacob 1633b7483dSJerin Jacob static inline int 1733b7483dSJerin Jacob order_producer(void *arg) 1833b7483dSJerin Jacob { 1933b7483dSJerin Jacob struct prod_data *p = arg; 2033b7483dSJerin Jacob struct test_order *t = p->t; 2133b7483dSJerin Jacob struct evt_options *opt = t->opt; 2233b7483dSJerin Jacob const uint8_t dev_id = p->dev_id; 2333b7483dSJerin Jacob const uint8_t port = p->port_id; 2433b7483dSJerin Jacob struct rte_mempool *pool = t->pool; 2533b7483dSJerin Jacob const uint64_t nb_pkts = t->nb_pkts; 2633b7483dSJerin Jacob uint32_t *producer_flow_seq = t->producer_flow_seq; 2733b7483dSJerin Jacob const uint32_t nb_flows = t->nb_flows; 2833b7483dSJerin Jacob uint64_t count = 0; 2933b7483dSJerin Jacob struct rte_mbuf *m; 3033b7483dSJerin Jacob struct rte_event ev; 3133b7483dSJerin Jacob 3233b7483dSJerin Jacob if (opt->verbose_level > 1) 3333b7483dSJerin Jacob printf("%s(): lcore %d dev_id %d port=%d queue=%d\n", 3433b7483dSJerin Jacob __func__, rte_lcore_id(), dev_id, port, p->queue_id); 3533b7483dSJerin Jacob 3633b7483dSJerin Jacob ev.event = 0; 3733b7483dSJerin Jacob ev.op = RTE_EVENT_OP_NEW; 3833b7483dSJerin Jacob ev.queue_id = p->queue_id; 3933b7483dSJerin Jacob ev.sched_type = RTE_SCHED_TYPE_ORDERED; 4033b7483dSJerin Jacob ev.priority = RTE_EVENT_DEV_PRIORITY_NORMAL; 4133b7483dSJerin Jacob ev.event_type = RTE_EVENT_TYPE_CPU; 4233b7483dSJerin Jacob ev.sub_event_type = 0; /* stage 0 */ 4333b7483dSJerin Jacob 4433b7483dSJerin Jacob while (count < nb_pkts && t->err == false) { 4533b7483dSJerin Jacob m = rte_pktmbuf_alloc(pool); 4633b7483dSJerin Jacob if (m == NULL) 4733b7483dSJerin Jacob continue; 4833b7483dSJerin Jacob 4933b7483dSJerin Jacob const uint32_t flow = (uintptr_t)m % nb_flows; 5033b7483dSJerin Jacob /* Maintain seq number per flow */ 5133b7483dSJerin Jacob m->seqn = producer_flow_seq[flow]++; 5233b7483dSJerin Jacob 5333b7483dSJerin Jacob ev.flow_id = flow; 5433b7483dSJerin Jacob ev.mbuf = m; 5533b7483dSJerin Jacob 5633b7483dSJerin Jacob while (rte_event_enqueue_burst(dev_id, port, &ev, 1) != 1) { 5733b7483dSJerin Jacob if (t->err) 5833b7483dSJerin Jacob break; 5933b7483dSJerin Jacob rte_pause(); 6033b7483dSJerin Jacob } 6133b7483dSJerin Jacob 6233b7483dSJerin Jacob count++; 6333b7483dSJerin Jacob } 6433b7483dSJerin Jacob return 0; 6533b7483dSJerin Jacob } 6633b7483dSJerin Jacob 67ba11ebf1SJerin Jacob int 68ba11ebf1SJerin Jacob order_opt_check(struct evt_options *opt) 69ba11ebf1SJerin Jacob { 70*f77f8c9fSPavan Nikhilesh if (opt->prod_type != EVT_PROD_TYPE_SYNT) { 71*f77f8c9fSPavan Nikhilesh evt_err("Invalid producer type"); 72*f77f8c9fSPavan Nikhilesh return -EINVAL; 73*f77f8c9fSPavan Nikhilesh } 74*f77f8c9fSPavan Nikhilesh 75ba11ebf1SJerin Jacob /* 1 producer + N workers + 1 master */ 76ba11ebf1SJerin Jacob if (rte_lcore_count() < 3) { 77ba11ebf1SJerin Jacob evt_err("test need minimum 3 lcores"); 78ba11ebf1SJerin Jacob return -1; 79ba11ebf1SJerin Jacob } 80ba11ebf1SJerin Jacob 81ba11ebf1SJerin Jacob /* Validate worker lcores */ 82ba11ebf1SJerin Jacob if (evt_lcores_has_overlap(opt->wlcores, rte_get_master_lcore())) { 83ba11ebf1SJerin Jacob evt_err("worker lcores overlaps with master lcore"); 84ba11ebf1SJerin Jacob return -1; 85ba11ebf1SJerin Jacob } 86ba11ebf1SJerin Jacob 87ba11ebf1SJerin Jacob if (evt_nr_active_lcores(opt->plcores) == 0) { 88ba11ebf1SJerin Jacob evt_err("missing the producer lcore"); 89ba11ebf1SJerin Jacob return -1; 90ba11ebf1SJerin Jacob } 91ba11ebf1SJerin Jacob 92ba11ebf1SJerin Jacob if (evt_nr_active_lcores(opt->plcores) != 1) { 93ba11ebf1SJerin Jacob evt_err("only one producer lcore must be selected"); 94ba11ebf1SJerin Jacob return -1; 95ba11ebf1SJerin Jacob } 96ba11ebf1SJerin Jacob 97ba11ebf1SJerin Jacob int plcore = evt_get_first_active_lcore(opt->plcores); 98ba11ebf1SJerin Jacob 99ba11ebf1SJerin Jacob if (plcore < 0) { 100ba11ebf1SJerin Jacob evt_err("failed to find active producer"); 101ba11ebf1SJerin Jacob return plcore; 102ba11ebf1SJerin Jacob } 103ba11ebf1SJerin Jacob 104ba11ebf1SJerin Jacob if (evt_lcores_has_overlap(opt->wlcores, plcore)) { 105ba11ebf1SJerin Jacob evt_err("worker lcores overlaps producer lcore"); 106ba11ebf1SJerin Jacob return -1; 107ba11ebf1SJerin Jacob } 108ba11ebf1SJerin Jacob if (evt_has_disabled_lcore(opt->wlcores)) { 109ba11ebf1SJerin Jacob evt_err("one or more workers lcores are not enabled"); 110ba11ebf1SJerin Jacob return -1; 111ba11ebf1SJerin Jacob } 112ba11ebf1SJerin Jacob if (!evt_has_active_lcore(opt->wlcores)) { 113ba11ebf1SJerin Jacob evt_err("minimum one worker is required"); 114ba11ebf1SJerin Jacob return -1; 115ba11ebf1SJerin Jacob } 116ba11ebf1SJerin Jacob 117ba11ebf1SJerin Jacob /* Validate producer lcore */ 118ba11ebf1SJerin Jacob if (plcore == (int)rte_get_master_lcore()) { 119ba11ebf1SJerin Jacob evt_err("producer lcore and master lcore should be different"); 120ba11ebf1SJerin Jacob return -1; 121ba11ebf1SJerin Jacob } 122ba11ebf1SJerin Jacob if (!rte_lcore_is_enabled(plcore)) { 123ba11ebf1SJerin Jacob evt_err("producer lcore is not enabled"); 124ba11ebf1SJerin Jacob return -1; 125ba11ebf1SJerin Jacob } 126ba11ebf1SJerin Jacob 127ba11ebf1SJerin Jacob /* Fixups */ 128ba11ebf1SJerin Jacob if (opt->nb_pkts == 0) 129ba11ebf1SJerin Jacob opt->nb_pkts = INT64_MAX; 130ba11ebf1SJerin Jacob 131ba11ebf1SJerin Jacob return 0; 132ba11ebf1SJerin Jacob } 133ba11ebf1SJerin Jacob 134ba11ebf1SJerin Jacob int 135d1f59fb7SJerin Jacob order_test_setup(struct evt_test *test, struct evt_options *opt) 136d1f59fb7SJerin Jacob { 137d1f59fb7SJerin Jacob void *test_order; 138d1f59fb7SJerin Jacob 139d1f59fb7SJerin Jacob test_order = rte_zmalloc_socket(test->name, sizeof(struct test_order), 140d1f59fb7SJerin Jacob RTE_CACHE_LINE_SIZE, opt->socket_id); 141d1f59fb7SJerin Jacob if (test_order == NULL) { 142d1f59fb7SJerin Jacob evt_err("failed to allocate test_order memory"); 143d1f59fb7SJerin Jacob goto nomem; 144d1f59fb7SJerin Jacob } 145d1f59fb7SJerin Jacob test->test_priv = test_order; 146d1f59fb7SJerin Jacob 147d1f59fb7SJerin Jacob struct test_order *t = evt_test_priv(test); 148d1f59fb7SJerin Jacob 149d1f59fb7SJerin Jacob t->producer_flow_seq = rte_zmalloc_socket("test_producer_flow_seq", 150d1f59fb7SJerin Jacob sizeof(*t->producer_flow_seq) * opt->nb_flows, 151d1f59fb7SJerin Jacob RTE_CACHE_LINE_SIZE, opt->socket_id); 152d1f59fb7SJerin Jacob 153d1f59fb7SJerin Jacob if (t->producer_flow_seq == NULL) { 154d1f59fb7SJerin Jacob evt_err("failed to allocate t->producer_flow_seq memory"); 155d1f59fb7SJerin Jacob goto prod_nomem; 156d1f59fb7SJerin Jacob } 157d1f59fb7SJerin Jacob 158d1f59fb7SJerin Jacob t->expected_flow_seq = rte_zmalloc_socket("test_expected_flow_seq", 159d1f59fb7SJerin Jacob sizeof(*t->expected_flow_seq) * opt->nb_flows, 160d1f59fb7SJerin Jacob RTE_CACHE_LINE_SIZE, opt->socket_id); 161d1f59fb7SJerin Jacob 162d1f59fb7SJerin Jacob if (t->expected_flow_seq == NULL) { 163d1f59fb7SJerin Jacob evt_err("failed to allocate t->expected_flow_seq memory"); 164d1f59fb7SJerin Jacob goto exp_nomem; 165d1f59fb7SJerin Jacob } 166d1f59fb7SJerin Jacob rte_atomic64_set(&t->outstand_pkts, opt->nb_pkts); 167d1f59fb7SJerin Jacob t->err = false; 168d1f59fb7SJerin Jacob t->nb_pkts = opt->nb_pkts; 169d1f59fb7SJerin Jacob t->nb_flows = opt->nb_flows; 170d1f59fb7SJerin Jacob t->result = EVT_TEST_FAILED; 171d1f59fb7SJerin Jacob t->opt = opt; 172d1f59fb7SJerin Jacob return 0; 173d1f59fb7SJerin Jacob 174d1f59fb7SJerin Jacob exp_nomem: 175d1f59fb7SJerin Jacob rte_free(t->producer_flow_seq); 176d1f59fb7SJerin Jacob prod_nomem: 177d1f59fb7SJerin Jacob rte_free(test->test_priv); 178d1f59fb7SJerin Jacob nomem: 179d1f59fb7SJerin Jacob return -ENOMEM; 180d1f59fb7SJerin Jacob } 181d1f59fb7SJerin Jacob 182d1f59fb7SJerin Jacob void 183d1f59fb7SJerin Jacob order_test_destroy(struct evt_test *test, struct evt_options *opt) 184d1f59fb7SJerin Jacob { 185d1f59fb7SJerin Jacob RTE_SET_USED(opt); 186d1f59fb7SJerin Jacob struct test_order *t = evt_test_priv(test); 187d1f59fb7SJerin Jacob 188d1f59fb7SJerin Jacob rte_free(t->expected_flow_seq); 189d1f59fb7SJerin Jacob rte_free(t->producer_flow_seq); 190d1f59fb7SJerin Jacob rte_free(test->test_priv); 191d1f59fb7SJerin Jacob } 192ba11ebf1SJerin Jacob 193ba11ebf1SJerin Jacob int 194ba11ebf1SJerin Jacob order_mempool_setup(struct evt_test *test, struct evt_options *opt) 195ba11ebf1SJerin Jacob { 196ba11ebf1SJerin Jacob struct test_order *t = evt_test_priv(test); 197ba11ebf1SJerin Jacob 198ba11ebf1SJerin Jacob t->pool = rte_pktmbuf_pool_create(test->name, opt->pool_sz, 199ba11ebf1SJerin Jacob 256 /* Cache */, 0, 200ba11ebf1SJerin Jacob 512, /* Use very small mbufs */ 201ba11ebf1SJerin Jacob opt->socket_id); 202ba11ebf1SJerin Jacob if (t->pool == NULL) { 203ba11ebf1SJerin Jacob evt_err("failed to create mempool"); 204ba11ebf1SJerin Jacob return -ENOMEM; 205ba11ebf1SJerin Jacob } 206ba11ebf1SJerin Jacob 207ba11ebf1SJerin Jacob return 0; 208ba11ebf1SJerin Jacob } 209ba11ebf1SJerin Jacob 210ba11ebf1SJerin Jacob void 211ba11ebf1SJerin Jacob order_mempool_destroy(struct evt_test *test, struct evt_options *opt) 212ba11ebf1SJerin Jacob { 213ba11ebf1SJerin Jacob RTE_SET_USED(opt); 214ba11ebf1SJerin Jacob struct test_order *t = evt_test_priv(test); 215ba11ebf1SJerin Jacob 216ba11ebf1SJerin Jacob rte_mempool_free(t->pool); 217ba11ebf1SJerin Jacob } 218ba11ebf1SJerin Jacob 219ba11ebf1SJerin Jacob void 220ba11ebf1SJerin Jacob order_eventdev_destroy(struct evt_test *test, struct evt_options *opt) 221ba11ebf1SJerin Jacob { 222ba11ebf1SJerin Jacob RTE_SET_USED(test); 223ba11ebf1SJerin Jacob 224ba11ebf1SJerin Jacob rte_event_dev_stop(opt->dev_id); 225ba11ebf1SJerin Jacob rte_event_dev_close(opt->dev_id); 226ba11ebf1SJerin Jacob } 227ba11ebf1SJerin Jacob 228ba11ebf1SJerin Jacob void 229ba11ebf1SJerin Jacob order_opt_dump(struct evt_options *opt) 230ba11ebf1SJerin Jacob { 231ba11ebf1SJerin Jacob evt_dump_producer_lcores(opt); 232ba11ebf1SJerin Jacob evt_dump("nb_wrker_lcores", "%d", evt_nr_active_lcores(opt->wlcores)); 233ba11ebf1SJerin Jacob evt_dump_worker_lcores(opt); 234ba11ebf1SJerin Jacob evt_dump("nb_evdev_ports", "%d", order_nb_event_ports(opt)); 235ba11ebf1SJerin Jacob } 236ba11ebf1SJerin Jacob 2375710e751SJerin Jacob int 23833b7483dSJerin Jacob order_launch_lcores(struct evt_test *test, struct evt_options *opt, 23933b7483dSJerin Jacob int (*worker)(void *)) 24033b7483dSJerin Jacob { 24133b7483dSJerin Jacob int ret, lcore_id; 24233b7483dSJerin Jacob struct test_order *t = evt_test_priv(test); 24333b7483dSJerin Jacob 24433b7483dSJerin Jacob int wkr_idx = 0; 24533b7483dSJerin Jacob /* launch workers */ 24633b7483dSJerin Jacob RTE_LCORE_FOREACH_SLAVE(lcore_id) { 24733b7483dSJerin Jacob if (!(opt->wlcores[lcore_id])) 24833b7483dSJerin Jacob continue; 24933b7483dSJerin Jacob 25033b7483dSJerin Jacob ret = rte_eal_remote_launch(worker, &t->worker[wkr_idx], 25133b7483dSJerin Jacob lcore_id); 25233b7483dSJerin Jacob if (ret) { 25333b7483dSJerin Jacob evt_err("failed to launch worker %d", lcore_id); 25433b7483dSJerin Jacob return ret; 25533b7483dSJerin Jacob } 25633b7483dSJerin Jacob wkr_idx++; 25733b7483dSJerin Jacob } 25833b7483dSJerin Jacob 25933b7483dSJerin Jacob /* launch producer */ 26033b7483dSJerin Jacob int plcore = evt_get_first_active_lcore(opt->plcores); 26133b7483dSJerin Jacob 26233b7483dSJerin Jacob ret = rte_eal_remote_launch(order_producer, &t->prod, plcore); 26333b7483dSJerin Jacob if (ret) { 26433b7483dSJerin Jacob evt_err("failed to launch order_producer %d", plcore); 26533b7483dSJerin Jacob return ret; 26633b7483dSJerin Jacob } 26733b7483dSJerin Jacob 26833b7483dSJerin Jacob uint64_t cycles = rte_get_timer_cycles(); 26933b7483dSJerin Jacob int64_t old_remaining = -1; 27033b7483dSJerin Jacob 27133b7483dSJerin Jacob while (t->err == false) { 27233b7483dSJerin Jacob uint64_t new_cycles = rte_get_timer_cycles(); 27333b7483dSJerin Jacob int64_t remaining = rte_atomic64_read(&t->outstand_pkts); 27433b7483dSJerin Jacob 27533b7483dSJerin Jacob if (remaining <= 0) { 27633b7483dSJerin Jacob t->result = EVT_TEST_SUCCESS; 27733b7483dSJerin Jacob break; 27833b7483dSJerin Jacob } 27933b7483dSJerin Jacob 28033b7483dSJerin Jacob if (new_cycles - cycles > rte_get_timer_hz() * 1) { 28133b7483dSJerin Jacob printf(CLGRN"\r%"PRId64""CLNRM, remaining); 28233b7483dSJerin Jacob fflush(stdout); 28333b7483dSJerin Jacob if (old_remaining == remaining) { 28433b7483dSJerin Jacob rte_event_dev_dump(opt->dev_id, stdout); 28533b7483dSJerin Jacob evt_err("No schedules for seconds, deadlock"); 28633b7483dSJerin Jacob t->err = true; 28733b7483dSJerin Jacob rte_smp_wmb(); 28833b7483dSJerin Jacob break; 28933b7483dSJerin Jacob } 29033b7483dSJerin Jacob old_remaining = remaining; 29133b7483dSJerin Jacob cycles = new_cycles; 29233b7483dSJerin Jacob } 29333b7483dSJerin Jacob } 29433b7483dSJerin Jacob printf("\r"); 29533b7483dSJerin Jacob 29633b7483dSJerin Jacob return 0; 29733b7483dSJerin Jacob } 29833b7483dSJerin Jacob 29933b7483dSJerin Jacob int 3005710e751SJerin Jacob order_event_dev_port_setup(struct evt_test *test, struct evt_options *opt, 3015710e751SJerin Jacob uint8_t nb_workers, uint8_t nb_queues) 3025710e751SJerin Jacob { 3035710e751SJerin Jacob int ret; 3045710e751SJerin Jacob uint8_t port; 3055710e751SJerin Jacob struct test_order *t = evt_test_priv(test); 306*f77f8c9fSPavan Nikhilesh struct rte_event_dev_info dev_info; 307*f77f8c9fSPavan Nikhilesh 308*f77f8c9fSPavan Nikhilesh memset(&dev_info, 0, sizeof(struct rte_event_dev_info)); 309*f77f8c9fSPavan Nikhilesh ret = rte_event_dev_info_get(opt->dev_id, &dev_info); 310*f77f8c9fSPavan Nikhilesh if (ret) { 311*f77f8c9fSPavan Nikhilesh evt_err("failed to get eventdev info %d", opt->dev_id); 312*f77f8c9fSPavan Nikhilesh return ret; 313*f77f8c9fSPavan Nikhilesh } 314*f77f8c9fSPavan Nikhilesh 315*f77f8c9fSPavan Nikhilesh if (opt->wkr_deq_dep > dev_info.max_event_port_dequeue_depth) 316*f77f8c9fSPavan Nikhilesh opt->wkr_deq_dep = dev_info.max_event_port_dequeue_depth; 317ba11ebf1SJerin Jacob 3185710e751SJerin Jacob /* port configuration */ 319*f77f8c9fSPavan Nikhilesh const struct rte_event_port_conf p_conf = { 3205710e751SJerin Jacob .dequeue_depth = opt->wkr_deq_dep, 321*f77f8c9fSPavan Nikhilesh .enqueue_depth = dev_info.max_event_port_dequeue_depth, 322*f77f8c9fSPavan Nikhilesh .new_event_threshold = dev_info.max_num_events, 3235710e751SJerin Jacob }; 3245710e751SJerin Jacob 3255710e751SJerin Jacob /* setup one port per worker, linking to all queues */ 3265710e751SJerin Jacob for (port = 0; port < nb_workers; port++) { 3275710e751SJerin Jacob struct worker_data *w = &t->worker[port]; 3285710e751SJerin Jacob 3295710e751SJerin Jacob w->dev_id = opt->dev_id; 3305710e751SJerin Jacob w->port_id = port; 3315710e751SJerin Jacob w->t = t; 3325710e751SJerin Jacob 333*f77f8c9fSPavan Nikhilesh ret = rte_event_port_setup(opt->dev_id, port, &p_conf); 3345710e751SJerin Jacob if (ret) { 3355710e751SJerin Jacob evt_err("failed to setup port %d", port); 3365710e751SJerin Jacob return ret; 3375710e751SJerin Jacob } 3385710e751SJerin Jacob 3395710e751SJerin Jacob ret = rte_event_port_link(opt->dev_id, port, NULL, NULL, 0); 3405710e751SJerin Jacob if (ret != nb_queues) { 3415710e751SJerin Jacob evt_err("failed to link all queues to port %d", port); 3425710e751SJerin Jacob return -EINVAL; 3435710e751SJerin Jacob } 3445710e751SJerin Jacob } 3455710e751SJerin Jacob struct prod_data *p = &t->prod; 3465710e751SJerin Jacob 3475710e751SJerin Jacob p->dev_id = opt->dev_id; 3485710e751SJerin Jacob p->port_id = port; /* last port */ 3495710e751SJerin Jacob p->queue_id = 0; 3505710e751SJerin Jacob p->t = t; 3515710e751SJerin Jacob 352*f77f8c9fSPavan Nikhilesh ret = rte_event_port_setup(opt->dev_id, port, &p_conf); 3535710e751SJerin Jacob if (ret) { 3545710e751SJerin Jacob evt_err("failed to setup producer port %d", port); 3555710e751SJerin Jacob return ret; 3565710e751SJerin Jacob } 3575710e751SJerin Jacob 3585710e751SJerin Jacob return ret; 3595710e751SJerin Jacob } 360