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 49*a4931d5bSThomas Monjalon const flow_id_t flow = (uintptr_t)m % nb_flows; 5033b7483dSJerin Jacob /* Maintain seq number per flow */ 5133b7483dSJerin Jacob m->seqn = producer_flow_seq[flow]++; 52*a4931d5bSThomas Monjalon order_flow_id_save(t, flow, m, &ev); 5333b7483dSJerin Jacob 5433b7483dSJerin Jacob while (rte_event_enqueue_burst(dev_id, port, &ev, 1) != 1) { 5533b7483dSJerin Jacob if (t->err) 5633b7483dSJerin Jacob break; 5733b7483dSJerin Jacob rte_pause(); 5833b7483dSJerin Jacob } 5933b7483dSJerin Jacob 6033b7483dSJerin Jacob count++; 6133b7483dSJerin Jacob } 6233b7483dSJerin Jacob return 0; 6333b7483dSJerin Jacob } 6433b7483dSJerin Jacob 65ba11ebf1SJerin Jacob int 66ba11ebf1SJerin Jacob order_opt_check(struct evt_options *opt) 67ba11ebf1SJerin Jacob { 68f77f8c9fSPavan Nikhilesh if (opt->prod_type != EVT_PROD_TYPE_SYNT) { 699fdc9986SPavan Nikhilesh evt_err("Invalid producer type '%s' valid producer '%s'", 709fdc9986SPavan Nikhilesh evt_prod_id_to_name(opt->prod_type), 719fdc9986SPavan Nikhilesh evt_prod_id_to_name(EVT_PROD_TYPE_SYNT)); 729fdc9986SPavan Nikhilesh return -1; 73f77f8c9fSPavan Nikhilesh } 74f77f8c9fSPavan Nikhilesh 75cb056611SStephen Hemminger /* 1 producer + N workers + main */ 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 */ 82cb056611SStephen Hemminger if (evt_lcores_has_overlap(opt->wlcores, rte_get_main_lcore())) { 83cb056611SStephen Hemminger evt_err("worker lcores overlaps with main 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 */ 118cb056611SStephen Hemminger if (plcore == (int)rte_get_main_lcore()) { 119cb056611SStephen Hemminger evt_err("producer lcore and main 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; 138*a4931d5bSThomas Monjalon struct test_order *t; 139*a4931d5bSThomas Monjalon static const struct rte_mbuf_dynfield flow_id_dynfield_desc = { 140*a4931d5bSThomas Monjalon .name = "test_event_dynfield_flow_id", 141*a4931d5bSThomas Monjalon .size = sizeof(flow_id_t), 142*a4931d5bSThomas Monjalon .align = __alignof__(flow_id_t), 143*a4931d5bSThomas Monjalon }; 144d1f59fb7SJerin Jacob 145d1f59fb7SJerin Jacob test_order = rte_zmalloc_socket(test->name, sizeof(struct test_order), 146d1f59fb7SJerin Jacob RTE_CACHE_LINE_SIZE, opt->socket_id); 147d1f59fb7SJerin Jacob if (test_order == NULL) { 148d1f59fb7SJerin Jacob evt_err("failed to allocate test_order memory"); 149d1f59fb7SJerin Jacob goto nomem; 150d1f59fb7SJerin Jacob } 151d1f59fb7SJerin Jacob test->test_priv = test_order; 152*a4931d5bSThomas Monjalon t = evt_test_priv(test); 153d1f59fb7SJerin Jacob 154*a4931d5bSThomas Monjalon t->flow_id_dynfield_offset = 155*a4931d5bSThomas Monjalon rte_mbuf_dynfield_register(&flow_id_dynfield_desc); 156*a4931d5bSThomas Monjalon if (t->flow_id_dynfield_offset < 0) { 157*a4931d5bSThomas Monjalon evt_err("failed to register mbuf field"); 158*a4931d5bSThomas Monjalon return -rte_errno; 159*a4931d5bSThomas Monjalon } 160d1f59fb7SJerin Jacob 161d1f59fb7SJerin Jacob t->producer_flow_seq = rte_zmalloc_socket("test_producer_flow_seq", 162d1f59fb7SJerin Jacob sizeof(*t->producer_flow_seq) * opt->nb_flows, 163d1f59fb7SJerin Jacob RTE_CACHE_LINE_SIZE, opt->socket_id); 164d1f59fb7SJerin Jacob 165d1f59fb7SJerin Jacob if (t->producer_flow_seq == NULL) { 166d1f59fb7SJerin Jacob evt_err("failed to allocate t->producer_flow_seq memory"); 167d1f59fb7SJerin Jacob goto prod_nomem; 168d1f59fb7SJerin Jacob } 169d1f59fb7SJerin Jacob 170d1f59fb7SJerin Jacob t->expected_flow_seq = rte_zmalloc_socket("test_expected_flow_seq", 171d1f59fb7SJerin Jacob sizeof(*t->expected_flow_seq) * opt->nb_flows, 172d1f59fb7SJerin Jacob RTE_CACHE_LINE_SIZE, opt->socket_id); 173d1f59fb7SJerin Jacob 174d1f59fb7SJerin Jacob if (t->expected_flow_seq == NULL) { 175d1f59fb7SJerin Jacob evt_err("failed to allocate t->expected_flow_seq memory"); 176d1f59fb7SJerin Jacob goto exp_nomem; 177d1f59fb7SJerin Jacob } 178d1f59fb7SJerin Jacob rte_atomic64_set(&t->outstand_pkts, opt->nb_pkts); 179d1f59fb7SJerin Jacob t->err = false; 180d1f59fb7SJerin Jacob t->nb_pkts = opt->nb_pkts; 181d1f59fb7SJerin Jacob t->nb_flows = opt->nb_flows; 182d1f59fb7SJerin Jacob t->result = EVT_TEST_FAILED; 183d1f59fb7SJerin Jacob t->opt = opt; 184d1f59fb7SJerin Jacob return 0; 185d1f59fb7SJerin Jacob 186d1f59fb7SJerin Jacob exp_nomem: 187d1f59fb7SJerin Jacob rte_free(t->producer_flow_seq); 188d1f59fb7SJerin Jacob prod_nomem: 189d1f59fb7SJerin Jacob rte_free(test->test_priv); 190d1f59fb7SJerin Jacob nomem: 191d1f59fb7SJerin Jacob return -ENOMEM; 192d1f59fb7SJerin Jacob } 193d1f59fb7SJerin Jacob 194d1f59fb7SJerin Jacob void 195d1f59fb7SJerin Jacob order_test_destroy(struct evt_test *test, struct evt_options *opt) 196d1f59fb7SJerin Jacob { 197d1f59fb7SJerin Jacob RTE_SET_USED(opt); 198d1f59fb7SJerin Jacob struct test_order *t = evt_test_priv(test); 199d1f59fb7SJerin Jacob 200d1f59fb7SJerin Jacob rte_free(t->expected_flow_seq); 201d1f59fb7SJerin Jacob rte_free(t->producer_flow_seq); 202d1f59fb7SJerin Jacob rte_free(test->test_priv); 203d1f59fb7SJerin Jacob } 204ba11ebf1SJerin Jacob 205ba11ebf1SJerin Jacob int 206ba11ebf1SJerin Jacob order_mempool_setup(struct evt_test *test, struct evt_options *opt) 207ba11ebf1SJerin Jacob { 208ba11ebf1SJerin Jacob struct test_order *t = evt_test_priv(test); 209ba11ebf1SJerin Jacob 210ba11ebf1SJerin Jacob t->pool = rte_pktmbuf_pool_create(test->name, opt->pool_sz, 211ba11ebf1SJerin Jacob 256 /* Cache */, 0, 212ba11ebf1SJerin Jacob 512, /* Use very small mbufs */ 213ba11ebf1SJerin Jacob opt->socket_id); 214ba11ebf1SJerin Jacob if (t->pool == NULL) { 215ba11ebf1SJerin Jacob evt_err("failed to create mempool"); 216ba11ebf1SJerin Jacob return -ENOMEM; 217ba11ebf1SJerin Jacob } 218ba11ebf1SJerin Jacob 219ba11ebf1SJerin Jacob return 0; 220ba11ebf1SJerin Jacob } 221ba11ebf1SJerin Jacob 222ba11ebf1SJerin Jacob void 223ba11ebf1SJerin Jacob order_mempool_destroy(struct evt_test *test, struct evt_options *opt) 224ba11ebf1SJerin Jacob { 225ba11ebf1SJerin Jacob RTE_SET_USED(opt); 226ba11ebf1SJerin Jacob struct test_order *t = evt_test_priv(test); 227ba11ebf1SJerin Jacob 228ba11ebf1SJerin Jacob rte_mempool_free(t->pool); 229ba11ebf1SJerin Jacob } 230ba11ebf1SJerin Jacob 231ba11ebf1SJerin Jacob void 232ba11ebf1SJerin Jacob order_eventdev_destroy(struct evt_test *test, struct evt_options *opt) 233ba11ebf1SJerin Jacob { 234ba11ebf1SJerin Jacob RTE_SET_USED(test); 235ba11ebf1SJerin Jacob 236ba11ebf1SJerin Jacob rte_event_dev_stop(opt->dev_id); 237ba11ebf1SJerin Jacob rte_event_dev_close(opt->dev_id); 238ba11ebf1SJerin Jacob } 239ba11ebf1SJerin Jacob 240ba11ebf1SJerin Jacob void 241ba11ebf1SJerin Jacob order_opt_dump(struct evt_options *opt) 242ba11ebf1SJerin Jacob { 243ba11ebf1SJerin Jacob evt_dump_producer_lcores(opt); 244ba11ebf1SJerin Jacob evt_dump("nb_wrker_lcores", "%d", evt_nr_active_lcores(opt->wlcores)); 245ba11ebf1SJerin Jacob evt_dump_worker_lcores(opt); 246ba11ebf1SJerin Jacob evt_dump("nb_evdev_ports", "%d", order_nb_event_ports(opt)); 247ba11ebf1SJerin Jacob } 248ba11ebf1SJerin Jacob 2495710e751SJerin Jacob int 25033b7483dSJerin Jacob order_launch_lcores(struct evt_test *test, struct evt_options *opt, 25133b7483dSJerin Jacob int (*worker)(void *)) 25233b7483dSJerin Jacob { 25333b7483dSJerin Jacob int ret, lcore_id; 25433b7483dSJerin Jacob struct test_order *t = evt_test_priv(test); 25533b7483dSJerin Jacob 25633b7483dSJerin Jacob int wkr_idx = 0; 25733b7483dSJerin Jacob /* launch workers */ 258cb056611SStephen Hemminger RTE_LCORE_FOREACH_WORKER(lcore_id) { 25933b7483dSJerin Jacob if (!(opt->wlcores[lcore_id])) 26033b7483dSJerin Jacob continue; 26133b7483dSJerin Jacob 26233b7483dSJerin Jacob ret = rte_eal_remote_launch(worker, &t->worker[wkr_idx], 26333b7483dSJerin Jacob lcore_id); 26433b7483dSJerin Jacob if (ret) { 26533b7483dSJerin Jacob evt_err("failed to launch worker %d", lcore_id); 26633b7483dSJerin Jacob return ret; 26733b7483dSJerin Jacob } 26833b7483dSJerin Jacob wkr_idx++; 26933b7483dSJerin Jacob } 27033b7483dSJerin Jacob 27133b7483dSJerin Jacob /* launch producer */ 27233b7483dSJerin Jacob int plcore = evt_get_first_active_lcore(opt->plcores); 27333b7483dSJerin Jacob 27433b7483dSJerin Jacob ret = rte_eal_remote_launch(order_producer, &t->prod, plcore); 27533b7483dSJerin Jacob if (ret) { 27633b7483dSJerin Jacob evt_err("failed to launch order_producer %d", plcore); 27733b7483dSJerin Jacob return ret; 27833b7483dSJerin Jacob } 27933b7483dSJerin Jacob 28033b7483dSJerin Jacob uint64_t cycles = rte_get_timer_cycles(); 28133b7483dSJerin Jacob int64_t old_remaining = -1; 28233b7483dSJerin Jacob 28333b7483dSJerin Jacob while (t->err == false) { 28433b7483dSJerin Jacob uint64_t new_cycles = rte_get_timer_cycles(); 28533b7483dSJerin Jacob int64_t remaining = rte_atomic64_read(&t->outstand_pkts); 28633b7483dSJerin Jacob 28733b7483dSJerin Jacob if (remaining <= 0) { 28833b7483dSJerin Jacob t->result = EVT_TEST_SUCCESS; 28933b7483dSJerin Jacob break; 29033b7483dSJerin Jacob } 29133b7483dSJerin Jacob 29233b7483dSJerin Jacob if (new_cycles - cycles > rte_get_timer_hz() * 1) { 29333b7483dSJerin Jacob printf(CLGRN"\r%"PRId64""CLNRM, remaining); 29433b7483dSJerin Jacob fflush(stdout); 29533b7483dSJerin Jacob if (old_remaining == remaining) { 29633b7483dSJerin Jacob rte_event_dev_dump(opt->dev_id, stdout); 29733b7483dSJerin Jacob evt_err("No schedules for seconds, deadlock"); 29833b7483dSJerin Jacob t->err = true; 29933b7483dSJerin Jacob rte_smp_wmb(); 30033b7483dSJerin Jacob break; 30133b7483dSJerin Jacob } 30233b7483dSJerin Jacob old_remaining = remaining; 30333b7483dSJerin Jacob cycles = new_cycles; 30433b7483dSJerin Jacob } 30533b7483dSJerin Jacob } 30633b7483dSJerin Jacob printf("\r"); 30733b7483dSJerin Jacob 30833b7483dSJerin Jacob return 0; 30933b7483dSJerin Jacob } 31033b7483dSJerin Jacob 31133b7483dSJerin Jacob int 3125710e751SJerin Jacob order_event_dev_port_setup(struct evt_test *test, struct evt_options *opt, 3135710e751SJerin Jacob uint8_t nb_workers, uint8_t nb_queues) 3145710e751SJerin Jacob { 3155710e751SJerin Jacob int ret; 3165710e751SJerin Jacob uint8_t port; 3175710e751SJerin Jacob struct test_order *t = evt_test_priv(test); 318f77f8c9fSPavan Nikhilesh struct rte_event_dev_info dev_info; 319f77f8c9fSPavan Nikhilesh 320f77f8c9fSPavan Nikhilesh memset(&dev_info, 0, sizeof(struct rte_event_dev_info)); 321f77f8c9fSPavan Nikhilesh ret = rte_event_dev_info_get(opt->dev_id, &dev_info); 322f77f8c9fSPavan Nikhilesh if (ret) { 323f77f8c9fSPavan Nikhilesh evt_err("failed to get eventdev info %d", opt->dev_id); 324f77f8c9fSPavan Nikhilesh return ret; 325f77f8c9fSPavan Nikhilesh } 326f77f8c9fSPavan Nikhilesh 327f77f8c9fSPavan Nikhilesh if (opt->wkr_deq_dep > dev_info.max_event_port_dequeue_depth) 328f77f8c9fSPavan Nikhilesh opt->wkr_deq_dep = dev_info.max_event_port_dequeue_depth; 329ba11ebf1SJerin Jacob 3305710e751SJerin Jacob /* port configuration */ 331f77f8c9fSPavan Nikhilesh const struct rte_event_port_conf p_conf = { 3325710e751SJerin Jacob .dequeue_depth = opt->wkr_deq_dep, 333f77f8c9fSPavan Nikhilesh .enqueue_depth = dev_info.max_event_port_dequeue_depth, 334f77f8c9fSPavan Nikhilesh .new_event_threshold = dev_info.max_num_events, 3355710e751SJerin Jacob }; 3365710e751SJerin Jacob 3375710e751SJerin Jacob /* setup one port per worker, linking to all queues */ 3385710e751SJerin Jacob for (port = 0; port < nb_workers; port++) { 3395710e751SJerin Jacob struct worker_data *w = &t->worker[port]; 3405710e751SJerin Jacob 3415710e751SJerin Jacob w->dev_id = opt->dev_id; 3425710e751SJerin Jacob w->port_id = port; 3435710e751SJerin Jacob w->t = t; 3445710e751SJerin Jacob 345f77f8c9fSPavan Nikhilesh ret = rte_event_port_setup(opt->dev_id, port, &p_conf); 3465710e751SJerin Jacob if (ret) { 3475710e751SJerin Jacob evt_err("failed to setup port %d", port); 3485710e751SJerin Jacob return ret; 3495710e751SJerin Jacob } 3505710e751SJerin Jacob 3515710e751SJerin Jacob ret = rte_event_port_link(opt->dev_id, port, NULL, NULL, 0); 3525710e751SJerin Jacob if (ret != nb_queues) { 3535710e751SJerin Jacob evt_err("failed to link all queues to port %d", port); 3545710e751SJerin Jacob return -EINVAL; 3555710e751SJerin Jacob } 3565710e751SJerin Jacob } 3575710e751SJerin Jacob struct prod_data *p = &t->prod; 3585710e751SJerin Jacob 3595710e751SJerin Jacob p->dev_id = opt->dev_id; 3605710e751SJerin Jacob p->port_id = port; /* last port */ 3615710e751SJerin Jacob p->queue_id = 0; 3625710e751SJerin Jacob p->t = t; 3635710e751SJerin Jacob 364f77f8c9fSPavan Nikhilesh ret = rte_event_port_setup(opt->dev_id, port, &p_conf); 3655710e751SJerin Jacob if (ret) { 3665710e751SJerin Jacob evt_err("failed to setup producer port %d", port); 3675710e751SJerin Jacob return ret; 3685710e751SJerin Jacob } 3695710e751SJerin Jacob 3705710e751SJerin Jacob return ret; 3715710e751SJerin Jacob } 372