xref: /dpdk/lib/dispatcher/rte_dispatcher.c (revision c6552d9a8deffa448de2d5e2e726f50508c1efd2)
1ecca8a0bSMattias Rönnblom /* SPDX-License-Identifier: BSD-3-Clause
2ecca8a0bSMattias Rönnblom  * Copyright(c) 2023 Ericsson AB
3ecca8a0bSMattias Rönnblom  */
4ecca8a0bSMattias Rönnblom 
5ecca8a0bSMattias Rönnblom #include <stdbool.h>
6ecca8a0bSMattias Rönnblom #include <stdint.h>
7ecca8a0bSMattias Rönnblom 
8ecca8a0bSMattias Rönnblom #include <rte_branch_prediction.h>
9ecca8a0bSMattias Rönnblom #include <rte_common.h>
10ecca8a0bSMattias Rönnblom #include <rte_lcore.h>
11ecca8a0bSMattias Rönnblom #include <rte_random.h>
12ecca8a0bSMattias Rönnblom #include <rte_service_component.h>
13ecca8a0bSMattias Rönnblom 
14ecca8a0bSMattias Rönnblom #include "eventdev_pmd.h"
15ecca8a0bSMattias Rönnblom 
16ecca8a0bSMattias Rönnblom #include <rte_dispatcher.h>
17ecca8a0bSMattias Rönnblom 
18ecca8a0bSMattias Rönnblom #define EVD_MAX_PORTS_PER_LCORE 4
19ecca8a0bSMattias Rönnblom #define EVD_MAX_HANDLERS 32
20ecca8a0bSMattias Rönnblom #define EVD_MAX_FINALIZERS 16
21ecca8a0bSMattias Rönnblom #define EVD_AVG_PRIO_INTERVAL 2000
22ecca8a0bSMattias Rönnblom #define EVD_SERVICE_NAME "dispatcher"
23ecca8a0bSMattias Rönnblom 
24ecca8a0bSMattias Rönnblom struct rte_dispatcher_lcore_port {
25ecca8a0bSMattias Rönnblom 	uint8_t port_id;
26ecca8a0bSMattias Rönnblom 	uint16_t batch_size;
27ecca8a0bSMattias Rönnblom 	uint64_t timeout;
28ecca8a0bSMattias Rönnblom };
29ecca8a0bSMattias Rönnblom 
30ecca8a0bSMattias Rönnblom struct rte_dispatcher_handler {
31ecca8a0bSMattias Rönnblom 	int id;
32ecca8a0bSMattias Rönnblom 	rte_dispatcher_match_t match_fun;
33ecca8a0bSMattias Rönnblom 	void *match_data;
34ecca8a0bSMattias Rönnblom 	rte_dispatcher_process_t process_fun;
35ecca8a0bSMattias Rönnblom 	void *process_data;
36ecca8a0bSMattias Rönnblom };
37ecca8a0bSMattias Rönnblom 
38ecca8a0bSMattias Rönnblom struct rte_dispatcher_finalizer {
39ecca8a0bSMattias Rönnblom 	int id;
40ecca8a0bSMattias Rönnblom 	rte_dispatcher_finalize_t finalize_fun;
41ecca8a0bSMattias Rönnblom 	void *finalize_data;
42ecca8a0bSMattias Rönnblom };
43ecca8a0bSMattias Rönnblom 
44*c6552d9aSTyler Retzlaff struct __rte_cache_aligned rte_dispatcher_lcore {
45ecca8a0bSMattias Rönnblom 	uint8_t num_ports;
46ecca8a0bSMattias Rönnblom 	uint16_t num_handlers;
47ecca8a0bSMattias Rönnblom 	int32_t prio_count;
48ecca8a0bSMattias Rönnblom 	struct rte_dispatcher_lcore_port ports[EVD_MAX_PORTS_PER_LCORE];
49ecca8a0bSMattias Rönnblom 	struct rte_dispatcher_handler handlers[EVD_MAX_HANDLERS];
50ecca8a0bSMattias Rönnblom 	struct rte_dispatcher_stats stats;
51a7ba9d04SMattias Rönnblom 	RTE_CACHE_GUARD;
52*c6552d9aSTyler Retzlaff };
53ecca8a0bSMattias Rönnblom 
54ecca8a0bSMattias Rönnblom struct rte_dispatcher {
55ecca8a0bSMattias Rönnblom 	uint8_t event_dev_id;
56ecca8a0bSMattias Rönnblom 	int socket_id;
57ecca8a0bSMattias Rönnblom 	uint32_t service_id;
58ecca8a0bSMattias Rönnblom 	struct rte_dispatcher_lcore lcores[RTE_MAX_LCORE];
59ecca8a0bSMattias Rönnblom 	uint16_t num_finalizers;
60ecca8a0bSMattias Rönnblom 	struct rte_dispatcher_finalizer finalizers[EVD_MAX_FINALIZERS];
61ecca8a0bSMattias Rönnblom };
62ecca8a0bSMattias Rönnblom 
63ecca8a0bSMattias Rönnblom static int
evd_lookup_handler_idx(struct rte_dispatcher_lcore * lcore,const struct rte_event * event)64ecca8a0bSMattias Rönnblom evd_lookup_handler_idx(struct rte_dispatcher_lcore *lcore,
65ecca8a0bSMattias Rönnblom 	const struct rte_event *event)
66ecca8a0bSMattias Rönnblom {
67ecca8a0bSMattias Rönnblom 	uint16_t i;
68ecca8a0bSMattias Rönnblom 
69ecca8a0bSMattias Rönnblom 	for (i = 0; i < lcore->num_handlers; i++) {
70ecca8a0bSMattias Rönnblom 		struct rte_dispatcher_handler *handler =
71ecca8a0bSMattias Rönnblom 			&lcore->handlers[i];
72ecca8a0bSMattias Rönnblom 
73ecca8a0bSMattias Rönnblom 		if (handler->match_fun(event, handler->match_data))
74ecca8a0bSMattias Rönnblom 			return i;
75ecca8a0bSMattias Rönnblom 	}
76ecca8a0bSMattias Rönnblom 
77ecca8a0bSMattias Rönnblom 	return -1;
78ecca8a0bSMattias Rönnblom }
79ecca8a0bSMattias Rönnblom 
80ecca8a0bSMattias Rönnblom static void
evd_prioritize_handler(struct rte_dispatcher_lcore * lcore,int handler_idx)81ecca8a0bSMattias Rönnblom evd_prioritize_handler(struct rte_dispatcher_lcore *lcore,
82ecca8a0bSMattias Rönnblom 	int handler_idx)
83ecca8a0bSMattias Rönnblom {
84ecca8a0bSMattias Rönnblom 	struct rte_dispatcher_handler tmp;
85ecca8a0bSMattias Rönnblom 
86ecca8a0bSMattias Rönnblom 	if (handler_idx == 0)
87ecca8a0bSMattias Rönnblom 		return;
88ecca8a0bSMattias Rönnblom 
89ecca8a0bSMattias Rönnblom 	/* Let the lucky handler "bubble" up the list */
90ecca8a0bSMattias Rönnblom 
91ecca8a0bSMattias Rönnblom 	tmp = lcore->handlers[handler_idx - 1];
92ecca8a0bSMattias Rönnblom 	lcore->handlers[handler_idx - 1] = lcore->handlers[handler_idx];
93ecca8a0bSMattias Rönnblom 	lcore->handlers[handler_idx] = tmp;
94ecca8a0bSMattias Rönnblom }
95ecca8a0bSMattias Rönnblom 
96ecca8a0bSMattias Rönnblom static inline void
evd_consider_prioritize_handler(struct rte_dispatcher_lcore * lcore,int handler_idx,uint16_t handler_events)97ecca8a0bSMattias Rönnblom evd_consider_prioritize_handler(struct rte_dispatcher_lcore *lcore,
98ecca8a0bSMattias Rönnblom 	int handler_idx, uint16_t handler_events)
99ecca8a0bSMattias Rönnblom {
100ecca8a0bSMattias Rönnblom 	lcore->prio_count -= handler_events;
101ecca8a0bSMattias Rönnblom 
102ecca8a0bSMattias Rönnblom 	if (unlikely(lcore->prio_count <= 0)) {
103ecca8a0bSMattias Rönnblom 		evd_prioritize_handler(lcore, handler_idx);
104ecca8a0bSMattias Rönnblom 
105ecca8a0bSMattias Rönnblom 		/*
106ecca8a0bSMattias Rönnblom 		 * Randomize the interval in the unlikely case
107ecca8a0bSMattias Rönnblom 		 * the traffic follow some very strict pattern.
108ecca8a0bSMattias Rönnblom 		 */
109ecca8a0bSMattias Rönnblom 		lcore->prio_count =
110ecca8a0bSMattias Rönnblom 			rte_rand_max(EVD_AVG_PRIO_INTERVAL) +
111ecca8a0bSMattias Rönnblom 			EVD_AVG_PRIO_INTERVAL / 2;
112ecca8a0bSMattias Rönnblom 	}
113ecca8a0bSMattias Rönnblom }
114ecca8a0bSMattias Rönnblom 
115ecca8a0bSMattias Rönnblom static inline void
evd_dispatch_events(struct rte_dispatcher * dispatcher,struct rte_dispatcher_lcore * lcore,struct rte_dispatcher_lcore_port * port,struct rte_event * events,uint16_t num_events)116ecca8a0bSMattias Rönnblom evd_dispatch_events(struct rte_dispatcher *dispatcher,
117ecca8a0bSMattias Rönnblom 	struct rte_dispatcher_lcore *lcore,
118ecca8a0bSMattias Rönnblom 	struct rte_dispatcher_lcore_port *port,
119ecca8a0bSMattias Rönnblom 	struct rte_event *events, uint16_t num_events)
120ecca8a0bSMattias Rönnblom {
121ecca8a0bSMattias Rönnblom 	int i;
122ecca8a0bSMattias Rönnblom 	struct rte_event bursts[EVD_MAX_HANDLERS][num_events];
123ecca8a0bSMattias Rönnblom 	uint16_t burst_lens[EVD_MAX_HANDLERS] = { 0 };
124ecca8a0bSMattias Rönnblom 	uint16_t drop_count = 0;
125ecca8a0bSMattias Rönnblom 	uint16_t dispatch_count;
126ecca8a0bSMattias Rönnblom 	uint16_t dispatched = 0;
127ecca8a0bSMattias Rönnblom 
128ecca8a0bSMattias Rönnblom 	for (i = 0; i < num_events; i++) {
129ecca8a0bSMattias Rönnblom 		struct rte_event *event = &events[i];
130ecca8a0bSMattias Rönnblom 		int handler_idx;
131ecca8a0bSMattias Rönnblom 
132ecca8a0bSMattias Rönnblom 		handler_idx = evd_lookup_handler_idx(lcore, event);
133ecca8a0bSMattias Rönnblom 
134ecca8a0bSMattias Rönnblom 		if (unlikely(handler_idx < 0)) {
135ecca8a0bSMattias Rönnblom 			drop_count++;
136ecca8a0bSMattias Rönnblom 			continue;
137ecca8a0bSMattias Rönnblom 		}
138ecca8a0bSMattias Rönnblom 
139ecca8a0bSMattias Rönnblom 		bursts[handler_idx][burst_lens[handler_idx]] = *event;
140ecca8a0bSMattias Rönnblom 		burst_lens[handler_idx]++;
141ecca8a0bSMattias Rönnblom 	}
142ecca8a0bSMattias Rönnblom 
143ecca8a0bSMattias Rönnblom 	dispatch_count = num_events - drop_count;
144ecca8a0bSMattias Rönnblom 
145ecca8a0bSMattias Rönnblom 	for (i = 0; i < lcore->num_handlers &&
146ecca8a0bSMattias Rönnblom 		 dispatched < dispatch_count; i++) {
147ecca8a0bSMattias Rönnblom 		struct rte_dispatcher_handler *handler =
148ecca8a0bSMattias Rönnblom 			&lcore->handlers[i];
149ecca8a0bSMattias Rönnblom 		uint16_t len = burst_lens[i];
150ecca8a0bSMattias Rönnblom 
151ecca8a0bSMattias Rönnblom 		if (len == 0)
152ecca8a0bSMattias Rönnblom 			continue;
153ecca8a0bSMattias Rönnblom 
154ecca8a0bSMattias Rönnblom 		handler->process_fun(dispatcher->event_dev_id, port->port_id,
155ecca8a0bSMattias Rönnblom 				     bursts[i], len, handler->process_data);
156ecca8a0bSMattias Rönnblom 
157ecca8a0bSMattias Rönnblom 		dispatched += len;
158ecca8a0bSMattias Rönnblom 
159ecca8a0bSMattias Rönnblom 		/*
160ecca8a0bSMattias Rönnblom 		 * Safe, since any reshuffling will only involve
161ecca8a0bSMattias Rönnblom 		 * already-processed handlers.
162ecca8a0bSMattias Rönnblom 		 */
163ecca8a0bSMattias Rönnblom 		evd_consider_prioritize_handler(lcore, i, len);
164ecca8a0bSMattias Rönnblom 	}
165ecca8a0bSMattias Rönnblom 
166ecca8a0bSMattias Rönnblom 	lcore->stats.ev_batch_count++;
167ecca8a0bSMattias Rönnblom 	lcore->stats.ev_dispatch_count += dispatch_count;
168ecca8a0bSMattias Rönnblom 	lcore->stats.ev_drop_count += drop_count;
169ecca8a0bSMattias Rönnblom 
170ecca8a0bSMattias Rönnblom 	for (i = 0; i < dispatcher->num_finalizers; i++) {
171ecca8a0bSMattias Rönnblom 		struct rte_dispatcher_finalizer *finalizer =
172ecca8a0bSMattias Rönnblom 			&dispatcher->finalizers[i];
173ecca8a0bSMattias Rönnblom 
174ecca8a0bSMattias Rönnblom 		finalizer->finalize_fun(dispatcher->event_dev_id,
175ecca8a0bSMattias Rönnblom 					port->port_id,
176ecca8a0bSMattias Rönnblom 					finalizer->finalize_data);
177ecca8a0bSMattias Rönnblom 	}
178ecca8a0bSMattias Rönnblom }
179ecca8a0bSMattias Rönnblom 
180ecca8a0bSMattias Rönnblom static __rte_always_inline uint16_t
evd_port_dequeue(struct rte_dispatcher * dispatcher,struct rte_dispatcher_lcore * lcore,struct rte_dispatcher_lcore_port * port)181ecca8a0bSMattias Rönnblom evd_port_dequeue(struct rte_dispatcher *dispatcher,
182ecca8a0bSMattias Rönnblom 	struct rte_dispatcher_lcore *lcore,
183ecca8a0bSMattias Rönnblom 	struct rte_dispatcher_lcore_port *port)
184ecca8a0bSMattias Rönnblom {
185ecca8a0bSMattias Rönnblom 	uint16_t batch_size = port->batch_size;
186ecca8a0bSMattias Rönnblom 	struct rte_event events[batch_size];
187ecca8a0bSMattias Rönnblom 	uint16_t n;
188ecca8a0bSMattias Rönnblom 
189ecca8a0bSMattias Rönnblom 	n = rte_event_dequeue_burst(dispatcher->event_dev_id, port->port_id,
190ecca8a0bSMattias Rönnblom 				    events, batch_size, port->timeout);
191ecca8a0bSMattias Rönnblom 
192ecca8a0bSMattias Rönnblom 	if (likely(n > 0))
193ecca8a0bSMattias Rönnblom 		evd_dispatch_events(dispatcher, lcore, port, events, n);
194ecca8a0bSMattias Rönnblom 
195ecca8a0bSMattias Rönnblom 	lcore->stats.poll_count++;
196ecca8a0bSMattias Rönnblom 
197ecca8a0bSMattias Rönnblom 	return n;
198ecca8a0bSMattias Rönnblom }
199ecca8a0bSMattias Rönnblom 
200ecca8a0bSMattias Rönnblom static __rte_always_inline uint16_t
evd_lcore_process(struct rte_dispatcher * dispatcher,struct rte_dispatcher_lcore * lcore)201ecca8a0bSMattias Rönnblom evd_lcore_process(struct rte_dispatcher *dispatcher,
202ecca8a0bSMattias Rönnblom 	struct rte_dispatcher_lcore *lcore)
203ecca8a0bSMattias Rönnblom {
204ecca8a0bSMattias Rönnblom 	uint16_t i;
205ecca8a0bSMattias Rönnblom 	uint16_t event_count = 0;
206ecca8a0bSMattias Rönnblom 
207ecca8a0bSMattias Rönnblom 	for (i = 0; i < lcore->num_ports; i++) {
208ecca8a0bSMattias Rönnblom 		struct rte_dispatcher_lcore_port *port =
209ecca8a0bSMattias Rönnblom 			&lcore->ports[i];
210ecca8a0bSMattias Rönnblom 
211ecca8a0bSMattias Rönnblom 		event_count += evd_port_dequeue(dispatcher, lcore, port);
212ecca8a0bSMattias Rönnblom 	}
213ecca8a0bSMattias Rönnblom 
214ecca8a0bSMattias Rönnblom 	return event_count;
215ecca8a0bSMattias Rönnblom }
216ecca8a0bSMattias Rönnblom 
217ecca8a0bSMattias Rönnblom static int32_t
evd_process(void * userdata)218ecca8a0bSMattias Rönnblom evd_process(void *userdata)
219ecca8a0bSMattias Rönnblom {
220ecca8a0bSMattias Rönnblom 	struct rte_dispatcher *dispatcher = userdata;
221ecca8a0bSMattias Rönnblom 	unsigned int lcore_id = rte_lcore_id();
222ecca8a0bSMattias Rönnblom 	struct rte_dispatcher_lcore *lcore =
223ecca8a0bSMattias Rönnblom 		&dispatcher->lcores[lcore_id];
224ecca8a0bSMattias Rönnblom 	uint64_t event_count;
225ecca8a0bSMattias Rönnblom 
226ecca8a0bSMattias Rönnblom 	event_count = evd_lcore_process(dispatcher, lcore);
227ecca8a0bSMattias Rönnblom 
228ecca8a0bSMattias Rönnblom 	if (unlikely(event_count == 0))
229ecca8a0bSMattias Rönnblom 		return -EAGAIN;
230ecca8a0bSMattias Rönnblom 
231ecca8a0bSMattias Rönnblom 	return 0;
232ecca8a0bSMattias Rönnblom }
233ecca8a0bSMattias Rönnblom 
234ecca8a0bSMattias Rönnblom static int
evd_service_register(struct rte_dispatcher * dispatcher)235ecca8a0bSMattias Rönnblom evd_service_register(struct rte_dispatcher *dispatcher)
236ecca8a0bSMattias Rönnblom {
237ecca8a0bSMattias Rönnblom 	struct rte_service_spec service = {
238ecca8a0bSMattias Rönnblom 		.callback = evd_process,
239ecca8a0bSMattias Rönnblom 		.callback_userdata = dispatcher,
240ecca8a0bSMattias Rönnblom 		.capabilities = RTE_SERVICE_CAP_MT_SAFE,
241ecca8a0bSMattias Rönnblom 		.socket_id = dispatcher->socket_id
242ecca8a0bSMattias Rönnblom 	};
243ecca8a0bSMattias Rönnblom 	int rc;
244ecca8a0bSMattias Rönnblom 
245ecca8a0bSMattias Rönnblom 	snprintf(service.name, sizeof(service.name), EVD_SERVICE_NAME);
246ecca8a0bSMattias Rönnblom 
247ecca8a0bSMattias Rönnblom 	rc = rte_service_component_register(&service, &dispatcher->service_id);
248ecca8a0bSMattias Rönnblom 	if (rc != 0)
249ecca8a0bSMattias Rönnblom 		RTE_EDEV_LOG_ERR("Registration of dispatcher service "
250ae282b06SDavid Marchand 				 "%s failed with error code %d",
251ecca8a0bSMattias Rönnblom 				 service.name, rc);
252ecca8a0bSMattias Rönnblom 
253ecca8a0bSMattias Rönnblom 	return rc;
254ecca8a0bSMattias Rönnblom }
255ecca8a0bSMattias Rönnblom 
256ecca8a0bSMattias Rönnblom static int
evd_service_unregister(struct rte_dispatcher * dispatcher)257ecca8a0bSMattias Rönnblom evd_service_unregister(struct rte_dispatcher *dispatcher)
258ecca8a0bSMattias Rönnblom {
259ecca8a0bSMattias Rönnblom 	int rc;
260ecca8a0bSMattias Rönnblom 
261ecca8a0bSMattias Rönnblom 	rc = rte_service_component_unregister(dispatcher->service_id);
262ecca8a0bSMattias Rönnblom 	if (rc != 0)
263ecca8a0bSMattias Rönnblom 		RTE_EDEV_LOG_ERR("Unregistration of dispatcher service "
264ae282b06SDavid Marchand 				 "failed with error code %d", rc);
265ecca8a0bSMattias Rönnblom 
266ecca8a0bSMattias Rönnblom 	return rc;
267ecca8a0bSMattias Rönnblom }
268ecca8a0bSMattias Rönnblom 
269ecca8a0bSMattias Rönnblom struct rte_dispatcher *
rte_dispatcher_create(uint8_t event_dev_id)270ecca8a0bSMattias Rönnblom rte_dispatcher_create(uint8_t event_dev_id)
271ecca8a0bSMattias Rönnblom {
272ecca8a0bSMattias Rönnblom 	int socket_id;
273ecca8a0bSMattias Rönnblom 	struct rte_dispatcher *dispatcher;
274ecca8a0bSMattias Rönnblom 	int rc;
275ecca8a0bSMattias Rönnblom 
276ecca8a0bSMattias Rönnblom 	socket_id = rte_event_dev_socket_id(event_dev_id);
277ecca8a0bSMattias Rönnblom 
278ecca8a0bSMattias Rönnblom 	dispatcher =
279ecca8a0bSMattias Rönnblom 		rte_malloc_socket("dispatcher", sizeof(struct rte_dispatcher),
280ecca8a0bSMattias Rönnblom 				  RTE_CACHE_LINE_SIZE, socket_id);
281ecca8a0bSMattias Rönnblom 
282ecca8a0bSMattias Rönnblom 	if (dispatcher == NULL) {
283ae282b06SDavid Marchand 		RTE_EDEV_LOG_ERR("Unable to allocate memory for dispatcher");
284ecca8a0bSMattias Rönnblom 		rte_errno = ENOMEM;
285ecca8a0bSMattias Rönnblom 		return NULL;
286ecca8a0bSMattias Rönnblom 	}
287ecca8a0bSMattias Rönnblom 
288ecca8a0bSMattias Rönnblom 	*dispatcher = (struct rte_dispatcher) {
289ecca8a0bSMattias Rönnblom 		.event_dev_id = event_dev_id,
290ecca8a0bSMattias Rönnblom 		.socket_id = socket_id
291ecca8a0bSMattias Rönnblom 	};
292ecca8a0bSMattias Rönnblom 
293ecca8a0bSMattias Rönnblom 	rc = evd_service_register(dispatcher);
294ecca8a0bSMattias Rönnblom 	if (rc < 0) {
295ecca8a0bSMattias Rönnblom 		rte_free(dispatcher);
296ecca8a0bSMattias Rönnblom 		rte_errno = -rc;
297ecca8a0bSMattias Rönnblom 		return NULL;
298ecca8a0bSMattias Rönnblom 	}
299ecca8a0bSMattias Rönnblom 
300ecca8a0bSMattias Rönnblom 	return dispatcher;
301ecca8a0bSMattias Rönnblom }
302ecca8a0bSMattias Rönnblom 
303ecca8a0bSMattias Rönnblom int
rte_dispatcher_free(struct rte_dispatcher * dispatcher)304ecca8a0bSMattias Rönnblom rte_dispatcher_free(struct rte_dispatcher *dispatcher)
305ecca8a0bSMattias Rönnblom {
306ecca8a0bSMattias Rönnblom 	int rc;
307ecca8a0bSMattias Rönnblom 
308ecca8a0bSMattias Rönnblom 	if (dispatcher == NULL)
309ecca8a0bSMattias Rönnblom 		return 0;
310ecca8a0bSMattias Rönnblom 
311ecca8a0bSMattias Rönnblom 	rc = evd_service_unregister(dispatcher);
312ecca8a0bSMattias Rönnblom 	if (rc != 0)
313ecca8a0bSMattias Rönnblom 		return rc;
314ecca8a0bSMattias Rönnblom 
315ecca8a0bSMattias Rönnblom 	rte_free(dispatcher);
316ecca8a0bSMattias Rönnblom 
317ecca8a0bSMattias Rönnblom 	return 0;
318ecca8a0bSMattias Rönnblom }
319ecca8a0bSMattias Rönnblom 
320ecca8a0bSMattias Rönnblom uint32_t
rte_dispatcher_service_id_get(const struct rte_dispatcher * dispatcher)321ecca8a0bSMattias Rönnblom rte_dispatcher_service_id_get(const struct rte_dispatcher *dispatcher)
322ecca8a0bSMattias Rönnblom {
323ecca8a0bSMattias Rönnblom 	return dispatcher->service_id;
324ecca8a0bSMattias Rönnblom }
325ecca8a0bSMattias Rönnblom 
326ecca8a0bSMattias Rönnblom static int
lcore_port_index(struct rte_dispatcher_lcore * lcore,uint8_t event_port_id)327ecca8a0bSMattias Rönnblom lcore_port_index(struct rte_dispatcher_lcore *lcore,
328ecca8a0bSMattias Rönnblom 	uint8_t event_port_id)
329ecca8a0bSMattias Rönnblom {
330ecca8a0bSMattias Rönnblom 	uint16_t i;
331ecca8a0bSMattias Rönnblom 
332ecca8a0bSMattias Rönnblom 	for (i = 0; i < lcore->num_ports; i++) {
333ecca8a0bSMattias Rönnblom 		struct rte_dispatcher_lcore_port *port =
334ecca8a0bSMattias Rönnblom 			&lcore->ports[i];
335ecca8a0bSMattias Rönnblom 
336ecca8a0bSMattias Rönnblom 		if (port->port_id == event_port_id)
337ecca8a0bSMattias Rönnblom 			return i;
338ecca8a0bSMattias Rönnblom 	}
339ecca8a0bSMattias Rönnblom 
340ecca8a0bSMattias Rönnblom 	return -1;
341ecca8a0bSMattias Rönnblom }
342ecca8a0bSMattias Rönnblom 
343ecca8a0bSMattias Rönnblom int
rte_dispatcher_bind_port_to_lcore(struct rte_dispatcher * dispatcher,uint8_t event_port_id,uint16_t batch_size,uint64_t timeout,unsigned int lcore_id)344ecca8a0bSMattias Rönnblom rte_dispatcher_bind_port_to_lcore(struct rte_dispatcher *dispatcher,
345ecca8a0bSMattias Rönnblom 	uint8_t event_port_id, uint16_t batch_size, uint64_t timeout,
346ecca8a0bSMattias Rönnblom 	unsigned int lcore_id)
347ecca8a0bSMattias Rönnblom {
348ecca8a0bSMattias Rönnblom 	struct rte_dispatcher_lcore *lcore;
349ecca8a0bSMattias Rönnblom 	struct rte_dispatcher_lcore_port *port;
350ecca8a0bSMattias Rönnblom 
351ecca8a0bSMattias Rönnblom 	lcore =	&dispatcher->lcores[lcore_id];
352ecca8a0bSMattias Rönnblom 
353ecca8a0bSMattias Rönnblom 	if (lcore->num_ports == EVD_MAX_PORTS_PER_LCORE)
354ecca8a0bSMattias Rönnblom 		return -ENOMEM;
355ecca8a0bSMattias Rönnblom 
356ecca8a0bSMattias Rönnblom 	if (lcore_port_index(lcore, event_port_id) >= 0)
357ecca8a0bSMattias Rönnblom 		return -EEXIST;
358ecca8a0bSMattias Rönnblom 
359ecca8a0bSMattias Rönnblom 	port = &lcore->ports[lcore->num_ports];
360ecca8a0bSMattias Rönnblom 
361ecca8a0bSMattias Rönnblom 	*port = (struct rte_dispatcher_lcore_port) {
362ecca8a0bSMattias Rönnblom 		.port_id = event_port_id,
363ecca8a0bSMattias Rönnblom 		.batch_size = batch_size,
364ecca8a0bSMattias Rönnblom 		.timeout = timeout
365ecca8a0bSMattias Rönnblom 	};
366ecca8a0bSMattias Rönnblom 
367ecca8a0bSMattias Rönnblom 	lcore->num_ports++;
368ecca8a0bSMattias Rönnblom 
369ecca8a0bSMattias Rönnblom 	return 0;
370ecca8a0bSMattias Rönnblom }
371ecca8a0bSMattias Rönnblom 
372ecca8a0bSMattias Rönnblom int
rte_dispatcher_unbind_port_from_lcore(struct rte_dispatcher * dispatcher,uint8_t event_port_id,unsigned int lcore_id)373ecca8a0bSMattias Rönnblom rte_dispatcher_unbind_port_from_lcore(struct rte_dispatcher *dispatcher,
374ecca8a0bSMattias Rönnblom 	uint8_t event_port_id, unsigned int lcore_id)
375ecca8a0bSMattias Rönnblom {
376ecca8a0bSMattias Rönnblom 	struct rte_dispatcher_lcore *lcore;
377ecca8a0bSMattias Rönnblom 	int port_idx;
378ecca8a0bSMattias Rönnblom 	struct rte_dispatcher_lcore_port *port;
379ecca8a0bSMattias Rönnblom 	struct rte_dispatcher_lcore_port *last;
380ecca8a0bSMattias Rönnblom 
381ecca8a0bSMattias Rönnblom 	lcore =	&dispatcher->lcores[lcore_id];
382ecca8a0bSMattias Rönnblom 
383ecca8a0bSMattias Rönnblom 	port_idx = lcore_port_index(lcore, event_port_id);
384ecca8a0bSMattias Rönnblom 
385ecca8a0bSMattias Rönnblom 	if (port_idx < 0)
386ecca8a0bSMattias Rönnblom 		return -ENOENT;
387ecca8a0bSMattias Rönnblom 
388ecca8a0bSMattias Rönnblom 	port = &lcore->ports[port_idx];
389ecca8a0bSMattias Rönnblom 	last = &lcore->ports[lcore->num_ports - 1];
390ecca8a0bSMattias Rönnblom 
391ecca8a0bSMattias Rönnblom 	if (port != last)
392ecca8a0bSMattias Rönnblom 		*port = *last;
393ecca8a0bSMattias Rönnblom 
394ecca8a0bSMattias Rönnblom 	lcore->num_ports--;
395ecca8a0bSMattias Rönnblom 
396ecca8a0bSMattias Rönnblom 	return 0;
397ecca8a0bSMattias Rönnblom }
398ecca8a0bSMattias Rönnblom 
399ecca8a0bSMattias Rönnblom static struct rte_dispatcher_handler *
evd_lcore_get_handler_by_id(struct rte_dispatcher_lcore * lcore,int handler_id)400ecca8a0bSMattias Rönnblom evd_lcore_get_handler_by_id(struct rte_dispatcher_lcore *lcore, int handler_id)
401ecca8a0bSMattias Rönnblom {
402ecca8a0bSMattias Rönnblom 	uint16_t i;
403ecca8a0bSMattias Rönnblom 
404ecca8a0bSMattias Rönnblom 	for (i = 0; i < lcore->num_handlers; i++) {
405ecca8a0bSMattias Rönnblom 		struct rte_dispatcher_handler *handler =
406ecca8a0bSMattias Rönnblom 			&lcore->handlers[i];
407ecca8a0bSMattias Rönnblom 
408ecca8a0bSMattias Rönnblom 		if (handler->id == handler_id)
409ecca8a0bSMattias Rönnblom 			return handler;
410ecca8a0bSMattias Rönnblom 	}
411ecca8a0bSMattias Rönnblom 
412ecca8a0bSMattias Rönnblom 	return NULL;
413ecca8a0bSMattias Rönnblom }
414ecca8a0bSMattias Rönnblom 
415ecca8a0bSMattias Rönnblom static int
evd_alloc_handler_id(struct rte_dispatcher * dispatcher)416ecca8a0bSMattias Rönnblom evd_alloc_handler_id(struct rte_dispatcher *dispatcher)
417ecca8a0bSMattias Rönnblom {
418ecca8a0bSMattias Rönnblom 	int handler_id = 0;
419ecca8a0bSMattias Rönnblom 	struct rte_dispatcher_lcore *reference_lcore =
420ecca8a0bSMattias Rönnblom 		&dispatcher->lcores[0];
421ecca8a0bSMattias Rönnblom 
422ecca8a0bSMattias Rönnblom 	if (reference_lcore->num_handlers == EVD_MAX_HANDLERS)
423ecca8a0bSMattias Rönnblom 		return -1;
424ecca8a0bSMattias Rönnblom 
425ecca8a0bSMattias Rönnblom 	while (evd_lcore_get_handler_by_id(reference_lcore, handler_id) != NULL)
426ecca8a0bSMattias Rönnblom 		handler_id++;
427ecca8a0bSMattias Rönnblom 
428ecca8a0bSMattias Rönnblom 	return handler_id;
429ecca8a0bSMattias Rönnblom }
430ecca8a0bSMattias Rönnblom 
431ecca8a0bSMattias Rönnblom static void
evd_lcore_install_handler(struct rte_dispatcher_lcore * lcore,const struct rte_dispatcher_handler * handler)432ecca8a0bSMattias Rönnblom evd_lcore_install_handler(struct rte_dispatcher_lcore *lcore,
433ecca8a0bSMattias Rönnblom 	const struct rte_dispatcher_handler *handler)
434ecca8a0bSMattias Rönnblom {
435ecca8a0bSMattias Rönnblom 	int handler_idx = lcore->num_handlers;
436ecca8a0bSMattias Rönnblom 
437ecca8a0bSMattias Rönnblom 	lcore->handlers[handler_idx] = *handler;
438ecca8a0bSMattias Rönnblom 	lcore->num_handlers++;
439ecca8a0bSMattias Rönnblom }
440ecca8a0bSMattias Rönnblom 
441ecca8a0bSMattias Rönnblom static void
evd_install_handler(struct rte_dispatcher * dispatcher,const struct rte_dispatcher_handler * handler)442ecca8a0bSMattias Rönnblom evd_install_handler(struct rte_dispatcher *dispatcher,
443ecca8a0bSMattias Rönnblom 	const struct rte_dispatcher_handler *handler)
444ecca8a0bSMattias Rönnblom {
445ecca8a0bSMattias Rönnblom 	int i;
446ecca8a0bSMattias Rönnblom 
447ecca8a0bSMattias Rönnblom 	for (i = 0; i < RTE_MAX_LCORE; i++) {
448ecca8a0bSMattias Rönnblom 		struct rte_dispatcher_lcore *lcore =
449ecca8a0bSMattias Rönnblom 			&dispatcher->lcores[i];
450ecca8a0bSMattias Rönnblom 		evd_lcore_install_handler(lcore, handler);
451ecca8a0bSMattias Rönnblom 	}
452ecca8a0bSMattias Rönnblom }
453ecca8a0bSMattias Rönnblom 
454ecca8a0bSMattias Rönnblom int
rte_dispatcher_register(struct rte_dispatcher * dispatcher,rte_dispatcher_match_t match_fun,void * match_data,rte_dispatcher_process_t process_fun,void * process_data)455ecca8a0bSMattias Rönnblom rte_dispatcher_register(struct rte_dispatcher *dispatcher,
456ecca8a0bSMattias Rönnblom 	rte_dispatcher_match_t match_fun, void *match_data,
457ecca8a0bSMattias Rönnblom 	rte_dispatcher_process_t process_fun, void *process_data)
458ecca8a0bSMattias Rönnblom {
459ecca8a0bSMattias Rönnblom 	struct rte_dispatcher_handler handler = {
460ecca8a0bSMattias Rönnblom 		.match_fun = match_fun,
461ecca8a0bSMattias Rönnblom 		.match_data = match_data,
462ecca8a0bSMattias Rönnblom 		.process_fun = process_fun,
463ecca8a0bSMattias Rönnblom 		.process_data = process_data
464ecca8a0bSMattias Rönnblom 	};
465ecca8a0bSMattias Rönnblom 
466ecca8a0bSMattias Rönnblom 	handler.id = evd_alloc_handler_id(dispatcher);
467ecca8a0bSMattias Rönnblom 
468ecca8a0bSMattias Rönnblom 	if (handler.id < 0)
469ecca8a0bSMattias Rönnblom 		return -ENOMEM;
470ecca8a0bSMattias Rönnblom 
471ecca8a0bSMattias Rönnblom 	evd_install_handler(dispatcher, &handler);
472ecca8a0bSMattias Rönnblom 
473ecca8a0bSMattias Rönnblom 	return handler.id;
474ecca8a0bSMattias Rönnblom }
475ecca8a0bSMattias Rönnblom 
476ecca8a0bSMattias Rönnblom static int
evd_lcore_uninstall_handler(struct rte_dispatcher_lcore * lcore,int handler_id)477ecca8a0bSMattias Rönnblom evd_lcore_uninstall_handler(struct rte_dispatcher_lcore *lcore,
478ecca8a0bSMattias Rönnblom 	int handler_id)
479ecca8a0bSMattias Rönnblom {
480ecca8a0bSMattias Rönnblom 	struct rte_dispatcher_handler *unreg_handler;
481ecca8a0bSMattias Rönnblom 	int handler_idx;
482ecca8a0bSMattias Rönnblom 	uint16_t last_idx;
483ecca8a0bSMattias Rönnblom 
484ecca8a0bSMattias Rönnblom 	unreg_handler = evd_lcore_get_handler_by_id(lcore, handler_id);
485ecca8a0bSMattias Rönnblom 
486ecca8a0bSMattias Rönnblom 	if (unreg_handler == NULL) {
487ae282b06SDavid Marchand 		RTE_EDEV_LOG_ERR("Invalid handler id %d", handler_id);
488ecca8a0bSMattias Rönnblom 		return -EINVAL;
489ecca8a0bSMattias Rönnblom 	}
490ecca8a0bSMattias Rönnblom 
491ecca8a0bSMattias Rönnblom 	handler_idx = unreg_handler - &lcore->handlers[0];
492ecca8a0bSMattias Rönnblom 
493ecca8a0bSMattias Rönnblom 	last_idx = lcore->num_handlers - 1;
494ecca8a0bSMattias Rönnblom 
495ecca8a0bSMattias Rönnblom 	if (handler_idx != last_idx) {
496ecca8a0bSMattias Rönnblom 		/* move all handlers to maintain handler order */
497ecca8a0bSMattias Rönnblom 		int n = last_idx - handler_idx;
498ecca8a0bSMattias Rönnblom 		memmove(unreg_handler, unreg_handler + 1,
499ecca8a0bSMattias Rönnblom 			sizeof(struct rte_dispatcher_handler) * n);
500ecca8a0bSMattias Rönnblom 	}
501ecca8a0bSMattias Rönnblom 
502ecca8a0bSMattias Rönnblom 	lcore->num_handlers--;
503ecca8a0bSMattias Rönnblom 
504ecca8a0bSMattias Rönnblom 	return 0;
505ecca8a0bSMattias Rönnblom }
506ecca8a0bSMattias Rönnblom 
507ecca8a0bSMattias Rönnblom static int
evd_uninstall_handler(struct rte_dispatcher * dispatcher,int handler_id)508ecca8a0bSMattias Rönnblom evd_uninstall_handler(struct rte_dispatcher *dispatcher, int handler_id)
509ecca8a0bSMattias Rönnblom {
510ecca8a0bSMattias Rönnblom 	unsigned int lcore_id;
511ecca8a0bSMattias Rönnblom 
512ecca8a0bSMattias Rönnblom 	for (lcore_id = 0; lcore_id < RTE_MAX_LCORE; lcore_id++) {
513ecca8a0bSMattias Rönnblom 		struct rte_dispatcher_lcore *lcore =
514ecca8a0bSMattias Rönnblom 			&dispatcher->lcores[lcore_id];
515ecca8a0bSMattias Rönnblom 		int rc;
516ecca8a0bSMattias Rönnblom 
517ecca8a0bSMattias Rönnblom 		rc = evd_lcore_uninstall_handler(lcore, handler_id);
518ecca8a0bSMattias Rönnblom 		if (rc < 0)
519ecca8a0bSMattias Rönnblom 			return rc;
520ecca8a0bSMattias Rönnblom 	}
521ecca8a0bSMattias Rönnblom 
522ecca8a0bSMattias Rönnblom 	return 0;
523ecca8a0bSMattias Rönnblom }
524ecca8a0bSMattias Rönnblom 
525ecca8a0bSMattias Rönnblom int
rte_dispatcher_unregister(struct rte_dispatcher * dispatcher,int handler_id)526ecca8a0bSMattias Rönnblom rte_dispatcher_unregister(struct rte_dispatcher *dispatcher, int handler_id)
527ecca8a0bSMattias Rönnblom {
528ecca8a0bSMattias Rönnblom 	return evd_uninstall_handler(dispatcher, handler_id);
529ecca8a0bSMattias Rönnblom }
530ecca8a0bSMattias Rönnblom 
531ecca8a0bSMattias Rönnblom static struct rte_dispatcher_finalizer *
evd_get_finalizer_by_id(struct rte_dispatcher * dispatcher,int handler_id)532ecca8a0bSMattias Rönnblom evd_get_finalizer_by_id(struct rte_dispatcher *dispatcher,
533ecca8a0bSMattias Rönnblom 		       int handler_id)
534ecca8a0bSMattias Rönnblom {
535ecca8a0bSMattias Rönnblom 	int i;
536ecca8a0bSMattias Rönnblom 
537ecca8a0bSMattias Rönnblom 	for (i = 0; i < dispatcher->num_finalizers; i++) {
538ecca8a0bSMattias Rönnblom 		struct rte_dispatcher_finalizer *finalizer =
539ecca8a0bSMattias Rönnblom 			&dispatcher->finalizers[i];
540ecca8a0bSMattias Rönnblom 
541ecca8a0bSMattias Rönnblom 		if (finalizer->id == handler_id)
542ecca8a0bSMattias Rönnblom 			return finalizer;
543ecca8a0bSMattias Rönnblom 	}
544ecca8a0bSMattias Rönnblom 
545ecca8a0bSMattias Rönnblom 	return NULL;
546ecca8a0bSMattias Rönnblom }
547ecca8a0bSMattias Rönnblom 
548ecca8a0bSMattias Rönnblom static int
evd_alloc_finalizer_id(struct rte_dispatcher * dispatcher)549ecca8a0bSMattias Rönnblom evd_alloc_finalizer_id(struct rte_dispatcher *dispatcher)
550ecca8a0bSMattias Rönnblom {
551ecca8a0bSMattias Rönnblom 	int finalizer_id = 0;
552ecca8a0bSMattias Rönnblom 
553ecca8a0bSMattias Rönnblom 	while (evd_get_finalizer_by_id(dispatcher, finalizer_id) != NULL)
554ecca8a0bSMattias Rönnblom 		finalizer_id++;
555ecca8a0bSMattias Rönnblom 
556ecca8a0bSMattias Rönnblom 	return finalizer_id;
557ecca8a0bSMattias Rönnblom }
558ecca8a0bSMattias Rönnblom 
559ecca8a0bSMattias Rönnblom static struct rte_dispatcher_finalizer *
evd_alloc_finalizer(struct rte_dispatcher * dispatcher)560ecca8a0bSMattias Rönnblom evd_alloc_finalizer(struct rte_dispatcher *dispatcher)
561ecca8a0bSMattias Rönnblom {
562ecca8a0bSMattias Rönnblom 	int finalizer_idx;
563ecca8a0bSMattias Rönnblom 	struct rte_dispatcher_finalizer *finalizer;
564ecca8a0bSMattias Rönnblom 
565ecca8a0bSMattias Rönnblom 	if (dispatcher->num_finalizers == EVD_MAX_FINALIZERS)
566ecca8a0bSMattias Rönnblom 		return NULL;
567ecca8a0bSMattias Rönnblom 
568ecca8a0bSMattias Rönnblom 	finalizer_idx = dispatcher->num_finalizers;
569ecca8a0bSMattias Rönnblom 	finalizer = &dispatcher->finalizers[finalizer_idx];
570ecca8a0bSMattias Rönnblom 
571ecca8a0bSMattias Rönnblom 	finalizer->id = evd_alloc_finalizer_id(dispatcher);
572ecca8a0bSMattias Rönnblom 
573ecca8a0bSMattias Rönnblom 	dispatcher->num_finalizers++;
574ecca8a0bSMattias Rönnblom 
575ecca8a0bSMattias Rönnblom 	return finalizer;
576ecca8a0bSMattias Rönnblom }
577ecca8a0bSMattias Rönnblom 
578ecca8a0bSMattias Rönnblom int
rte_dispatcher_finalize_register(struct rte_dispatcher * dispatcher,rte_dispatcher_finalize_t finalize_fun,void * finalize_data)579ecca8a0bSMattias Rönnblom rte_dispatcher_finalize_register(struct rte_dispatcher *dispatcher,
580ecca8a0bSMattias Rönnblom 	rte_dispatcher_finalize_t finalize_fun, void *finalize_data)
581ecca8a0bSMattias Rönnblom {
582ecca8a0bSMattias Rönnblom 	struct rte_dispatcher_finalizer *finalizer;
583ecca8a0bSMattias Rönnblom 
584ecca8a0bSMattias Rönnblom 	finalizer = evd_alloc_finalizer(dispatcher);
585ecca8a0bSMattias Rönnblom 
586ecca8a0bSMattias Rönnblom 	if (finalizer == NULL)
587ecca8a0bSMattias Rönnblom 		return -ENOMEM;
588ecca8a0bSMattias Rönnblom 
589ecca8a0bSMattias Rönnblom 	finalizer->finalize_fun = finalize_fun;
590ecca8a0bSMattias Rönnblom 	finalizer->finalize_data = finalize_data;
591ecca8a0bSMattias Rönnblom 
592ecca8a0bSMattias Rönnblom 	return finalizer->id;
593ecca8a0bSMattias Rönnblom }
594ecca8a0bSMattias Rönnblom 
595ecca8a0bSMattias Rönnblom int
rte_dispatcher_finalize_unregister(struct rte_dispatcher * dispatcher,int finalizer_id)596ecca8a0bSMattias Rönnblom rte_dispatcher_finalize_unregister(struct rte_dispatcher *dispatcher,
597ecca8a0bSMattias Rönnblom 	int finalizer_id)
598ecca8a0bSMattias Rönnblom {
599ecca8a0bSMattias Rönnblom 	struct rte_dispatcher_finalizer *unreg_finalizer;
600ecca8a0bSMattias Rönnblom 	int finalizer_idx;
601ecca8a0bSMattias Rönnblom 	uint16_t last_idx;
602ecca8a0bSMattias Rönnblom 
603ecca8a0bSMattias Rönnblom 	unreg_finalizer = evd_get_finalizer_by_id(dispatcher, finalizer_id);
604ecca8a0bSMattias Rönnblom 
605ecca8a0bSMattias Rönnblom 	if (unreg_finalizer == NULL) {
606ae282b06SDavid Marchand 		RTE_EDEV_LOG_ERR("Invalid finalizer id %d", finalizer_id);
607ecca8a0bSMattias Rönnblom 		return -EINVAL;
608ecca8a0bSMattias Rönnblom 	}
609ecca8a0bSMattias Rönnblom 
610ecca8a0bSMattias Rönnblom 	finalizer_idx = unreg_finalizer - &dispatcher->finalizers[0];
611ecca8a0bSMattias Rönnblom 
612ecca8a0bSMattias Rönnblom 	last_idx = dispatcher->num_finalizers - 1;
613ecca8a0bSMattias Rönnblom 
614ecca8a0bSMattias Rönnblom 	if (finalizer_idx != last_idx) {
615ecca8a0bSMattias Rönnblom 		/* move all finalizers to maintain order */
616ecca8a0bSMattias Rönnblom 		int n = last_idx - finalizer_idx;
617ecca8a0bSMattias Rönnblom 		memmove(unreg_finalizer, unreg_finalizer + 1,
618ecca8a0bSMattias Rönnblom 			sizeof(struct rte_dispatcher_finalizer) * n);
619ecca8a0bSMattias Rönnblom 	}
620ecca8a0bSMattias Rönnblom 
621ecca8a0bSMattias Rönnblom 	dispatcher->num_finalizers--;
622ecca8a0bSMattias Rönnblom 
623ecca8a0bSMattias Rönnblom 	return 0;
624ecca8a0bSMattias Rönnblom }
625ecca8a0bSMattias Rönnblom 
626ecca8a0bSMattias Rönnblom static void
evd_set_service_runstate(struct rte_dispatcher * dispatcher,int state)627ecca8a0bSMattias Rönnblom evd_set_service_runstate(struct rte_dispatcher *dispatcher, int state)
628ecca8a0bSMattias Rönnblom {
629ecca8a0bSMattias Rönnblom 	int rc;
630ecca8a0bSMattias Rönnblom 
631ecca8a0bSMattias Rönnblom 	rc = rte_service_component_runstate_set(dispatcher->service_id,
632ecca8a0bSMattias Rönnblom 						state);
633ecca8a0bSMattias Rönnblom 	/*
634ecca8a0bSMattias Rönnblom 	 * The only cause of a runstate_set() failure is an invalid
635ecca8a0bSMattias Rönnblom 	 * service id, which in turns means the dispatcher instance's
636ecca8a0bSMattias Rönnblom 	 * state is invalid.
637ecca8a0bSMattias Rönnblom 	 */
638ecca8a0bSMattias Rönnblom 	if (rc != 0)
639ecca8a0bSMattias Rönnblom 		RTE_EDEV_LOG_ERR("Unexpected error %d occurred while setting "
640ae282b06SDavid Marchand 				 "service component run state to %d", rc,
641ecca8a0bSMattias Rönnblom 				 state);
642ecca8a0bSMattias Rönnblom 
643ecca8a0bSMattias Rönnblom 	RTE_VERIFY(rc == 0);
644ecca8a0bSMattias Rönnblom }
645ecca8a0bSMattias Rönnblom 
646ecca8a0bSMattias Rönnblom void
rte_dispatcher_start(struct rte_dispatcher * dispatcher)647ecca8a0bSMattias Rönnblom rte_dispatcher_start(struct rte_dispatcher *dispatcher)
648ecca8a0bSMattias Rönnblom {
649ecca8a0bSMattias Rönnblom 	evd_set_service_runstate(dispatcher, 1);
650ecca8a0bSMattias Rönnblom }
651ecca8a0bSMattias Rönnblom 
652ecca8a0bSMattias Rönnblom void
rte_dispatcher_stop(struct rte_dispatcher * dispatcher)653ecca8a0bSMattias Rönnblom rte_dispatcher_stop(struct rte_dispatcher *dispatcher)
654ecca8a0bSMattias Rönnblom {
655ecca8a0bSMattias Rönnblom 	evd_set_service_runstate(dispatcher, 0);
656ecca8a0bSMattias Rönnblom }
657ecca8a0bSMattias Rönnblom 
658ecca8a0bSMattias Rönnblom static void
evd_aggregate_stats(struct rte_dispatcher_stats * result,const struct rte_dispatcher_stats * part)659ecca8a0bSMattias Rönnblom evd_aggregate_stats(struct rte_dispatcher_stats *result,
660ecca8a0bSMattias Rönnblom 	const struct rte_dispatcher_stats *part)
661ecca8a0bSMattias Rönnblom {
662ecca8a0bSMattias Rönnblom 	result->poll_count += part->poll_count;
663ecca8a0bSMattias Rönnblom 	result->ev_batch_count += part->ev_batch_count;
664ecca8a0bSMattias Rönnblom 	result->ev_dispatch_count += part->ev_dispatch_count;
665ecca8a0bSMattias Rönnblom 	result->ev_drop_count += part->ev_drop_count;
666ecca8a0bSMattias Rönnblom }
667ecca8a0bSMattias Rönnblom 
668ecca8a0bSMattias Rönnblom void
rte_dispatcher_stats_get(const struct rte_dispatcher * dispatcher,struct rte_dispatcher_stats * stats)669ecca8a0bSMattias Rönnblom rte_dispatcher_stats_get(const struct rte_dispatcher *dispatcher,
670ecca8a0bSMattias Rönnblom 	struct rte_dispatcher_stats *stats)
671ecca8a0bSMattias Rönnblom {
672ecca8a0bSMattias Rönnblom 	unsigned int lcore_id;
673ecca8a0bSMattias Rönnblom 
674ecca8a0bSMattias Rönnblom 	*stats = (struct rte_dispatcher_stats) {};
675ecca8a0bSMattias Rönnblom 
676ecca8a0bSMattias Rönnblom 	for (lcore_id = 0; lcore_id < RTE_MAX_LCORE; lcore_id++) {
677ecca8a0bSMattias Rönnblom 		const struct rte_dispatcher_lcore *lcore =
678ecca8a0bSMattias Rönnblom 			&dispatcher->lcores[lcore_id];
679ecca8a0bSMattias Rönnblom 
680ecca8a0bSMattias Rönnblom 		evd_aggregate_stats(stats, &lcore->stats);
681ecca8a0bSMattias Rönnblom 	}
682ecca8a0bSMattias Rönnblom }
683ecca8a0bSMattias Rönnblom 
684ecca8a0bSMattias Rönnblom void
rte_dispatcher_stats_reset(struct rte_dispatcher * dispatcher)685ecca8a0bSMattias Rönnblom rte_dispatcher_stats_reset(struct rte_dispatcher *dispatcher)
686ecca8a0bSMattias Rönnblom {
687ecca8a0bSMattias Rönnblom 	unsigned int lcore_id;
688ecca8a0bSMattias Rönnblom 
689ecca8a0bSMattias Rönnblom 	for (lcore_id = 0; lcore_id < RTE_MAX_LCORE; lcore_id++) {
690ecca8a0bSMattias Rönnblom 		struct rte_dispatcher_lcore *lcore =
691ecca8a0bSMattias Rönnblom 			&dispatcher->lcores[lcore_id];
692ecca8a0bSMattias Rönnblom 
693ecca8a0bSMattias Rönnblom 		lcore->stats = (struct rte_dispatcher_stats) {};
694ecca8a0bSMattias Rönnblom 	}
695ecca8a0bSMattias Rönnblom }
696