1 /*- 2 * BSD LICENSE 3 * 4 * Copyright(c) 2017 Intel Corporation. All rights reserved. 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 Intel Corporation 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 _RTE_DISTRIBUTOR_H_ 34 #define _RTE_DISTRIBUTOR_H_ 35 36 /** 37 * @file 38 * RTE distributor 39 * 40 * The distributor is a component which is designed to pass packets 41 * one-at-a-time to workers, with dynamic load balancing. 42 */ 43 44 #ifdef __cplusplus 45 extern "C" { 46 #endif 47 48 /* Type of distribution (burst/single) */ 49 enum rte_distributor_alg_type { 50 RTE_DIST_ALG_BURST = 0, 51 RTE_DIST_ALG_SINGLE, 52 RTE_DIST_NUM_ALG_TYPES 53 }; 54 55 struct rte_distributor; 56 struct rte_mbuf; 57 58 /** 59 * Function to create a new distributor instance 60 * 61 * Reserves the memory needed for the distributor operation and 62 * initializes the distributor to work with the configured number of workers. 63 * 64 * @param name 65 * The name to be given to the distributor instance. 66 * @param socket_id 67 * The NUMA node on which the memory is to be allocated 68 * @param num_workers 69 * The maximum number of workers that will request packets from this 70 * distributor 71 * @param alg_type 72 * Call the legacy API, or use the new burst API. legacy uses 32-bit 73 * flow ID, and works on a single packet at a time. Latest uses 15- 74 * bit flow ID and works on up to 8 packets at a time to workers. 75 * @return 76 * The newly created distributor instance 77 */ 78 struct rte_distributor * 79 rte_distributor_create(const char *name, unsigned int socket_id, 80 unsigned int num_workers, 81 unsigned int alg_type); 82 83 /* *** APIS to be called on the distributor lcore *** */ 84 /* 85 * The following APIs are the public APIs which are designed for use on a 86 * single lcore which acts as the distributor lcore for a given distributor 87 * instance. These functions cannot be called on multiple cores simultaneously 88 * without using locking to protect access to the internals of the distributor. 89 * 90 * NOTE: a given lcore cannot act as both a distributor lcore and a worker lcore 91 * for the same distributor instance, otherwise deadlock will result. 92 */ 93 94 /** 95 * Process a set of packets by distributing them among workers that request 96 * packets. The distributor will ensure that no two packets that have the 97 * same flow id, or tag, in the mbuf will be processed on different cores at 98 * the same time. 99 * 100 * The user is advocated to set tag for each mbuf before calling this function. 101 * If user doesn't set the tag, the tag value can be various values depending on 102 * driver implementation and configuration. 103 * 104 * This is not multi-thread safe and should only be called on a single lcore. 105 * 106 * @param d 107 * The distributor instance to be used 108 * @param mbufs 109 * The mbufs to be distributed 110 * @param num_mbufs 111 * The number of mbufs in the mbufs array 112 * @return 113 * The number of mbufs processed. 114 */ 115 int 116 rte_distributor_process(struct rte_distributor *d, 117 struct rte_mbuf **mbufs, unsigned int num_mbufs); 118 119 /** 120 * Get a set of mbufs that have been returned to the distributor by workers 121 * 122 * This should only be called on the same lcore as rte_distributor_process() 123 * 124 * @param d 125 * The distributor instance to be used 126 * @param mbufs 127 * The mbufs pointer array to be filled in 128 * @param max_mbufs 129 * The size of the mbufs array 130 * @return 131 * The number of mbufs returned in the mbufs array. 132 */ 133 int 134 rte_distributor_returned_pkts(struct rte_distributor *d, 135 struct rte_mbuf **mbufs, unsigned int max_mbufs); 136 137 /** 138 * Flush the distributor component, so that there are no in-flight or 139 * backlogged packets awaiting processing 140 * 141 * This should only be called on the same lcore as rte_distributor_process() 142 * 143 * @param d 144 * The distributor instance to be used 145 * @return 146 * The number of queued/in-flight packets that were completed by this call. 147 */ 148 int 149 rte_distributor_flush(struct rte_distributor *d); 150 151 /** 152 * Clears the array of returned packets used as the source for the 153 * rte_distributor_returned_pkts() API call. 154 * 155 * This should only be called on the same lcore as rte_distributor_process() 156 * 157 * @param d 158 * The distributor instance to be used 159 */ 160 void 161 rte_distributor_clear_returns(struct rte_distributor *d); 162 163 /* *** APIS to be called on the worker lcores *** */ 164 /* 165 * The following APIs are the public APIs which are designed for use on 166 * multiple lcores which act as workers for a distributor. Each lcore should use 167 * a unique worker id when requesting packets. 168 * 169 * NOTE: a given lcore cannot act as both a distributor lcore and a worker lcore 170 * for the same distributor instance, otherwise deadlock will result. 171 */ 172 173 /** 174 * API called by a worker to get new packets to process. Any previous packets 175 * given to the worker is assumed to have completed processing, and may be 176 * optionally returned to the distributor via the oldpkt parameter. 177 * 178 * @param d 179 * The distributor instance to be used 180 * @param worker_id 181 * The worker instance number to use - must be less that num_workers passed 182 * at distributor creation time. 183 * @param pkts 184 * The mbufs pointer array to be filled in (up to 8 packets) 185 * @param oldpkt 186 * The previous packet, if any, being processed by the worker 187 * @param retcount 188 * The number of packets being returned 189 * 190 * @return 191 * The number of packets in the pkts array 192 */ 193 int 194 rte_distributor_get_pkt(struct rte_distributor *d, 195 unsigned int worker_id, struct rte_mbuf **pkts, 196 struct rte_mbuf **oldpkt, unsigned int retcount); 197 198 /** 199 * API called by a worker to return a completed packet without requesting a 200 * new packet, for example, because a worker thread is shutting down 201 * 202 * @param d 203 * The distributor instance to be used 204 * @param worker_id 205 * The worker instance number to use - must be less that num_workers passed 206 * at distributor creation time. 207 * @param oldpkt 208 * The previous packets being processed by the worker 209 * @param num 210 * The number of packets in the oldpkt array 211 */ 212 int 213 rte_distributor_return_pkt(struct rte_distributor *d, 214 unsigned int worker_id, struct rte_mbuf **oldpkt, int num); 215 216 /** 217 * API called by a worker to request a new packet to process. 218 * Any previous packet given to the worker is assumed to have completed 219 * processing, and may be optionally returned to the distributor via 220 * the oldpkt parameter. 221 * Unlike rte_distributor_get_pkt_burst(), this function does not wait for a 222 * new packet to be provided by the distributor. 223 * 224 * NOTE: after calling this function, rte_distributor_poll_pkt_burst() should 225 * be used to poll for the packet requested. The rte_distributor_get_pkt_burst() 226 * API should *not* be used to try and retrieve the new packet. 227 * 228 * @param d 229 * The distributor instance to be used 230 * @param worker_id 231 * The worker instance number to use - must be less that num_workers passed 232 * at distributor creation time. 233 * @param oldpkt 234 * The returning packets, if any, processed by the worker 235 * @param count 236 * The number of returning packets 237 */ 238 void 239 rte_distributor_request_pkt(struct rte_distributor *d, 240 unsigned int worker_id, struct rte_mbuf **oldpkt, 241 unsigned int count); 242 243 /** 244 * API called by a worker to check for a new packet that was previously 245 * requested by a call to rte_distributor_request_pkt(). It does not wait 246 * for the new packet to be available, but returns NULL if the request has 247 * not yet been fulfilled by the distributor. 248 * 249 * @param d 250 * The distributor instance to be used 251 * @param worker_id 252 * The worker instance number to use - must be less that num_workers passed 253 * at distributor creation time. 254 * @param mbufs 255 * The array of mbufs being given to the worker 256 * 257 * @return 258 * The number of packets being given to the worker thread, zero if no 259 * packet is yet available. 260 */ 261 int 262 rte_distributor_poll_pkt(struct rte_distributor *d, 263 unsigned int worker_id, struct rte_mbuf **mbufs); 264 265 #ifdef __cplusplus 266 } 267 #endif 268 269 #endif 270