1 /* 2 * BSD LICENSE 3 * 4 * Copyright (C) Cavium, Inc 2017. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 10 * * Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * * Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in 14 * the documentation and/or other materials provided with the 15 * distribution. 16 * * Neither the name of Cavium, Inc nor the names of its 17 * contributors may be used to endorse or promote products derived 18 * from this software without specific prior written permission. 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 21 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 22 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 23 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 24 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 25 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 26 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 30 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 */ 32 33 #ifndef _TEST_ORDER_COMMON_ 34 #define _TEST_ORDER_COMMON_ 35 36 #include <stdio.h> 37 #include <stdbool.h> 38 39 #include <rte_cycles.h> 40 #include <rte_eventdev.h> 41 #include <rte_lcore.h> 42 #include <rte_malloc.h> 43 #include <rte_mbuf.h> 44 45 #include "evt_common.h" 46 #include "evt_options.h" 47 #include "evt_test.h" 48 49 #define BURST_SIZE 16 50 51 struct test_order; 52 53 struct worker_data { 54 uint8_t dev_id; 55 uint8_t port_id; 56 struct test_order *t; 57 }; 58 59 struct prod_data { 60 uint8_t dev_id; 61 uint8_t port_id; 62 uint8_t queue_id; 63 struct test_order *t; 64 }; 65 66 struct test_order { 67 /* Don't change the offset of "err". Signal handler use this memory 68 * to terminate all lcores work. 69 */ 70 int err; 71 /* 72 * The atomic_* is an expensive operation,Since it is a functional test, 73 * We are using the atomic_ operation to reduce the code complexity. 74 */ 75 rte_atomic64_t outstand_pkts; 76 enum evt_test_result result; 77 uint32_t nb_flows; 78 uint64_t nb_pkts; 79 struct rte_mempool *pool; 80 struct prod_data prod; 81 struct worker_data worker[EVT_MAX_PORTS]; 82 uint32_t *producer_flow_seq; 83 uint32_t *expected_flow_seq; 84 struct evt_options *opt; 85 } __rte_cache_aligned; 86 87 static inline int 88 order_nb_event_ports(struct evt_options *opt) 89 { 90 return evt_nr_active_lcores(opt->wlcores) + 1 /* producer */; 91 } 92 93 static inline __attribute__((always_inline)) void 94 order_process_stage_1(struct test_order *const t, 95 struct rte_event *const ev, const uint32_t nb_flows, 96 uint32_t *const expected_flow_seq, 97 rte_atomic64_t *const outstand_pkts) 98 { 99 const uint32_t flow = (uintptr_t)ev->mbuf % nb_flows; 100 /* compare the seqn against expected value */ 101 if (ev->mbuf->seqn != expected_flow_seq[flow]) { 102 evt_err("flow=%x seqn mismatch got=%x expected=%x", 103 flow, ev->mbuf->seqn, expected_flow_seq[flow]); 104 t->err = true; 105 rte_smp_wmb(); 106 } 107 /* 108 * Events from an atomic flow of an event queue can be scheduled only to 109 * a single port at a time. The port is guaranteed to have exclusive 110 * (atomic) access for given atomic flow.So we don't need to update 111 * expected_flow_seq in critical section. 112 */ 113 expected_flow_seq[flow]++; 114 rte_pktmbuf_free(ev->mbuf); 115 rte_atomic64_sub(outstand_pkts, 1); 116 } 117 118 static inline __attribute__((always_inline)) void 119 order_process_stage_invalid(struct test_order *const t, 120 struct rte_event *const ev) 121 { 122 evt_err("invalid queue %d", ev->queue_id); 123 t->err = true; 124 rte_smp_wmb(); 125 } 126 127 #define ORDER_WORKER_INIT\ 128 struct worker_data *w = arg;\ 129 struct test_order *t = w->t;\ 130 struct evt_options *opt = t->opt;\ 131 const uint8_t dev_id = w->dev_id;\ 132 const uint8_t port = w->port_id;\ 133 const uint32_t nb_flows = t->nb_flows;\ 134 uint32_t *expected_flow_seq = t->expected_flow_seq;\ 135 rte_atomic64_t *outstand_pkts = &t->outstand_pkts;\ 136 if (opt->verbose_level > 1)\ 137 printf("%s(): lcore %d dev_id %d port=%d\n",\ 138 __func__, rte_lcore_id(), dev_id, port) 139 140 int order_test_result(struct evt_test *test, struct evt_options *opt); 141 int order_opt_check(struct evt_options *opt); 142 int order_test_setup(struct evt_test *test, struct evt_options *opt); 143 int order_mempool_setup(struct evt_test *test, struct evt_options *opt); 144 int order_launch_lcores(struct evt_test *test, struct evt_options *opt, 145 int (*worker)(void *)); 146 int order_event_dev_port_setup(struct evt_test *test, struct evt_options *opt, 147 uint8_t nb_workers, uint8_t nb_queues); 148 void order_test_destroy(struct evt_test *test, struct evt_options *opt); 149 void order_opt_dump(struct evt_options *opt); 150 void order_mempool_destroy(struct evt_test *test, struct evt_options *opt); 151 void order_eventdev_destroy(struct evt_test *test, struct evt_options *opt); 152 153 #endif /* _TEST_ORDER_COMMON_ */ 154