rte_dispatcher.h(3)
π rte_dispatcher.h π
okay bestie, welcome to rte_dispatcher.h(3) β yes it's a real manpage, yes it's from the Library Functions Manual, and yes we're gonna get through it together. grab a boba, bc this is part 1 of 2 and there's a LOT of slay ahead πΈ
β¨ NAME β¨
rte_dispatcher.h β like, the whole file, that's the name, that's it, no notes π
π¦ SYNOPSIS π¦
okay so first you gotta pull in the headers, no cap:
#include <stdbool.h>
#include <stdint.h>
#include <rte_compat.h>
#include <rte_eventdev.h>
π Data Structures
struct rte_dispatcher_statsβ yeah that's the one struct, she's lowkey the whole vibe
π§ Typedefs
typedef bool(* rte_dispatcher_match_t) (const struct rte_event *event, void *cb_data)typedef void(* rte_dispatcher_process_t) (uint8_t event_dev_id, uint8_t event_port_id, struct rte_event *events, uint16_t num, void *cb_data)typedef void(* rte_dispatcher_finalize_t) (uint8_t event_dev_id, uint8_t event_port_id, void *cb_data)
π Functions
__rte_experimental struct rte_dispatcher * rte_dispatcher_create (uint8_t event_dev_id)__rte_experimental int rte_dispatcher_free (struct rte_dispatcher *dispatcher)__rte_experimental uint32_t rte_dispatcher_service_id_get (const struct rte_dispatcher *dispatcher)__rte_experimental 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)__rte_experimental int rte_dispatcher_unbind_port_from_lcore (struct rte_dispatcher *dispatcher, uint8_t event_port_id, unsigned int lcore_id)__rte_experimental int rte_dispatcher_register (struct rte_dispatcher *dispatcher, rte_dispatcher_match_t match_fun, void *match_cb_data, rte_dispatcher_process_t process_fun, void *process_cb_data)__rte_experimental int rte_dispatcher_unregister (struct rte_dispatcher *dispatcher, int handler_id)__rte_experimental int rte_dispatcher_finalize_register (struct rte_dispatcher *dispatcher, rte_dispatcher_finalize_t finalize_fun, void *finalize_data)__rte_experimental int rte_dispatcher_finalize_unregister (struct rte_dispatcher *dispatcher, int reg_id)__rte_experimental void rte_dispatcher_start (struct rte_dispatcher *dispatcher)__rte_experimental void rte_dispatcher_stop (struct rte_dispatcher *dispatcher)__rte_experimental void rte_dispatcher_stats_get (const struct rte_dispatcher *dispatcher, struct rte_dispatcher_stats *stats)__rte_experimental void rte_dispatcher_stats_reset (struct rte_dispatcher *dispatcher)
πΈ Detailed Description πΈ
RTE Dispatcher
Warning β οΈ EXPERIMENTAL: All functions in this file may be changed or removed without prior notice. likeβ¦ she's not committed to you bestie, she's experimental, she can ghost ANY TIME π do NOT build your whole personality around her API, fr fr.
okay so the purpose of the dispatcher is to help decouple different parts of an application (e.g., modules), sharing the same underlying event device.
it's giving matchmaker energy π«Ά β like, multiple modules all wanna talk to the same event device, and the dispatcher is the bestie in the group chat who forwards everyone's messages so nobody has to text them directly. iconic.
Definition in file rte_dispatcher.h.
π Typedef Documentation π
typedef bool(* rte_dispatcher_match_t) (const struct rte_event *event, void *cb_data)
Function prototype for match callbacks. β¨
Match callbacks are used by an application to decide how the dispatcher distributes events to different parts of the application.
the way that this works is: your app gets to be the bouncer at the club door, deciding which events get let in and which get sent to which module. main character behavior honestly π
The application is not expected to process the event at the point of the match call. no no no, do NOT do the actual work here bestie. Such matters should be deferred to the process callback invocation. (she's like "okay i see you but deal with it in the process callback, not now")
The match callback may be used as an opportunity to prefetch data. lowkey a little pro move, highkey valid π
Parameters
- event β Pointer to event
- cb_data β The pointer supplied by the application in
rte_dispatcher_register().
Returns
Returns true in case this event should be delivered (via the process callback), and false otherwise. yes/yes or no/no, that's the vibe check π₯
Definition at line 56 of file rte_dispatcher.h.
typedef void(* rte_dispatcher_process_t) (uint8_t event_dev_id, uint8_t event_port_id, struct rte_event *events, uint16_t num, void *cb_data)
Function prototype for process callbacks. π
The process callbacks are used by the dispatcher to deliver events for processing. THIS is where the actual work happens, bestie β the events show up, you do the thing, no takebacks πΈ
Parameters
- event_dev_id β The originating event device id.
- event_port_id β The originating event port.
- events β Pointer to an array of events.
- num β The number of events in the events array.
- cb_data β The pointer supplied by the application in
rte_dispatcher_register().
Definition at line 81 of file rte_dispatcher.h.
typedef void(* rte_dispatcher_finalize_t) (uint8_t event_dev_id, uint8_t event_port_id, void *cb_data)
Function prototype for finalize callbacks. π¦
The finalize callbacks are used by the dispatcher to notify the application it has delivered all events from a particular batch dequeued from the event device. it's the "okay that's a wrap on this batch, you may now exhale" notification, essentially periodt π
Parameters
- event_dev_id β The originating event device id.
- event_port_id β The originating event port.
- cb_data β The pointer supplied by the application in
rte_dispatcher_finalize_register().
Definition at line 102 of file rte_dispatcher.h.
and that's part 1 bestie!! part 2 is loading, don't go anywhere π«Άβ¨
π«Ά rte_dispatcher_create() π«Ά
__rte_experimental struct rte_dispatcher *rte_dispatcher_create(uint8_t event_dev_id)
Bestie, this is the glow-up moment β it makes you a brand-new dispatcher with the id you picked. β¨
Params:
- event_dev_id β the identifier of the event device that this dispatcher is gonna dequeue events from. That's its whole personality.
Returns:
- a pointer to a fresh new dispatcher instance π
- or
NULLif it flops, and in that caserte_errnogets set so you know what went wrong.
π rte_dispatcher_free() π
__rte_experimental int rte_dispatcher_free(struct rte_dispatcher *dispatcher)
Say bye-bye, it's over, we're freeing the dispatcher. π
Params:
- dispatcher β the dispatcher instance.
Returns:
0: success, iconic<0: error code on failure π
β rte_dispatcher_service_id_get() β
__rte_experimental uint32_t rte_dispatcher_service_id_get(const struct rte_dispatcher *dispatcher)
Give me the service identifier for this dispatcher, quick.
Params:
- dispatcher β the dispatcher instance.
Returns: the dispatcher service's id. That's it, that's the whole thing. π
πΈ rte_dispatcher_bind_port_to_lcore() πΈ
__rte_experimental 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)
Okay so this one matches up an event device port with a specific lcore on the dispatcher you hand it β it's giving matchmaker energy. π
What it's actually doing: it configures the event port id that the dispatcher service is gonna use, if it runs on the lcore you specify.
Real talk about the rules here:
- Multiple event device ports can be bound to the same lcore. No jealousy, we're poly.
- But a particular port must not be bound to more than one lcore. That's a hard no. π
Also: if the dispatcher service gets mapped (via rte_service_map_lcore_set()) to an lcore that has zero ports bound to it, the service function is just gonna be a no-operation. It's literally not doing anything bestie, it's on standby.
This function may be called by any thread (including unregistered non-EAL threads) β but not while the dispatcher is running on the lcore specified by lcore_id. Do not do that.
Params:
- dispatcher β the dispatcher instance.
- event_port_id β the event device port identifier.
- batch_size β the batch size to use in
rte_event_dequeue_burst(), for the configured event device port and lcore. - timeout β the timeout parameter to use in
rte_event_dequeue_burst(), for the configured event device port and lcore. - lcore_id β the lcore by which this event port will be used.
Returns:
0: success β¨-ENOMEM: can't allocate enough resources, tragic-EEXISTS: this event port is already configured, girl we been knew-EINVAL: invalid arguments
π§ rte_dispatcher_unbind_port_from_lcore() π§
__rte_experimental int rte_dispatcher_unbind_port_from_lcore(struct rte_dispatcher *dispatcher, uint8_t event_port_id, unsigned int lcore_id)
The breakup function π₯ β it unbinds an event device port from a specific lcore.
This function may be called by any thread (including unregistered non-EAL threads), but not while the dispatcher is running on the lcore specified by lcore_id.
Params:
- dispatcher β the dispatcher instance.
- event_port_id β the event device port identifier.
- lcore_id β the lcore which was using this event port (aka the ex).
Returns:
0: success-ENOENT: this event port id was never bound to this lcore_id. Nothing to unbind, nothing to mourn.
π₯ rte_dispatcher_register() π₯
__rte_experimental int rte_dispatcher_register(struct rte_dispatcher *dispatcher, rte_dispatcher_match_t match_fun, void *match_cb_data, rte_dispatcher_process_t process_fun, void *process_cb_data)
Register an event handler, bestie. This is where you tell the dispatcher how to sort your events. π―
Here's the lore: the match callback function is what decides whether a particular event should be delivered, and the corresponding process callback function is what actually handles it.
Why two separate steps though? Because it lets the dispatcher deliver all the events as a batch, which means a particular kind of event gets processed back-to-back, and that improves cache locality. Cache-brained king behavior. π
The list of handler callback functions is shared among all lcores β but it will only be executed on lcores that have an eventdev port bound to them and that are running the dispatcher service.
An event is delivered to at most one handler. Events where no handler is found get dropped. π Nobody matched, so it's gone.
The application must not depend on the order in which the match functions are invoked. Fr fr, do not do it.
Ordering of events is not guaranteed to be maintained between different deliver callbacks. Example time, because this one is a whole situation: suppose you've got two callbacks registered that match different subsets of events arriving on an atomic queue. A batch of events [ev0, ev1, ev2] gets dequeued on a particular port, and all of them pertain to the same flow. The match callback for registration A returns true for ev0 and ev2, and the matching function for registration B returns true for ev1. In that scenario, the dispatcher may choose to deliver first [ev0, ev2] using A's deliver function, and then [ev1] to B β or vice versa. Either way. No promises. π
rte_dispatcher_register() may be called by any thread (including unregistered non-EAL threads), but not while the event dispatcher is running on any service lcore.
Params:
- dispatcher β the dispatcher instance.
- match_fun β the match callback function.
- match_cb_data β a pointer to some application-specific opaque data (or
NULL), which is supplied back to the application when match_fun is called. - process_fun β the process callback function.
- process_cb_data β a pointer to some application-specific opaque data (or
NULL), which is supplied back to the application when process_fun is called.
Returns:
>= 0: the identifier for this registration π-ENOMEM: unable to allocate sufficient resources
π¦ rte_dispatcher_unregister() π¦
__rte_experimental int rte_dispatcher_unregister(struct rte_dispatcher *dispatcher, int handler_id)
Unregister an event handler. We're taking it off the roster.
This function may be called by any thread (including unregistered non-EAL threads), but not while the dispatcher is running on any service lcore.
Params:
- dispatcher β the dispatcher instance.
- handler_id β the handler registration id returned by the original
rte_dispatcher_register()call. You gotta remember it, keep the receipt.
Returns:
0: success-EINVAL: the handler_id parameter was invalid, awk
π rte_dispatcher_finalize_register() π
__rte_experimental int rte_dispatcher_finalize_register(struct rte_dispatcher *dispatcher, rte_dispatcher_finalize_t finalize_fun, void *finalize_data)
Register a finalize callback function. β¨ Your app may optionally install one or more of these β zero, one, many, your call, no pressure.
All finalize callbacks are invoked by the dispatcher when a complete batch of events (retrieved using rte_event_dequeue_burst()) has been delivered to the application β or has been dropped. Either way, the batch is done, so the finalize runs.
Important: the finalize callback is not tied to any particular handler. She's independent. π
So what's the point? It gives the application an opportunity to do per-batch processing. One case where that's useful: if you're using an event output buffer and it's shared among several handlers. In that situation, you can make sure the output buffer gets flushed properly using a finalize callback. Knowledge drop. π§
rte_dispatcher_finalize_register() may be called by any thread (including unregistered non-EAL threads), but not while the dispatcher is running on any service lcore.
Params:
- dispatcher β the dispatcher instance.
- finalize_fun β the function called after completing the processing of a dequeue batch.
- finalize_data β a pointer to some application-specific opaque data (or
NULL), which is supplied back to the application when finalize_fun is called.
Returns:
>= 0: the identifier for this registration π«Ά-ENOMEM: unable to allocate sufficient resources
π rte_dispatcher_finalize_unregister() π
__rte_experimental int rte_dispatcher_finalize_unregister(struct rte_dispatcher *dispatcher, int reg_id)
Unregister a finalize callback. Closing that chapter. π₯
This function may be called by any thread (including unregistered non-EAL threads), but not while the dispatcher is running on any service lcore.
Params:
- dispatcher β the dispatcher instance.
- reg_id β the finalize registration id returned by the original
rte_dispatcher_finalize_register()call.
Returns:
0: success-EINVAL: the reg_id parameter was invalid
π rte_dispatcher_start() π (main character moment)
__rte_experimental void rte_dispatcher_start(struct rte_dispatcher *dispatcher)
Start a dispatcher instance β this is the "enabling the dispatcher service" step. She's awake now. π
Checklist before you do this, bestie:
- The underlying event device must have been started prior to calling
rte_dispatcher_start(). Non-negotiable. - For the dispatcher to actually do work (aka actually dispatch events), its service must have been mapped to one or more service lcores, and its service run state must be set to
'1'. A dispatcher's service is retrieved usingrte_dispatcher_service_id_get(). - Every service lcore the dispatcher is mapped to should have at least one event port configured. You do that by calling
rte_dispatcher_bind_port_to_lcore(), and you do it before starting the dispatcher.
Params:
- dispatcher β the dispatcher instance.
Returns nothing. It's void. It just goes. πββοΈ
π rte_dispatcher_stop() π
__rte_experimental void rte_dispatcher_stop(struct rte_dispatcher *dispatcher)
Stop a running dispatcher instance. Disables the dispatcher service. Nap time for the dispatcher. π΄
Params:
- dispatcher β the dispatcher instance.
π rte_dispatcher_stats_get() π
__rte_experimental void rte_dispatcher_stats_get(const struct rte_dispatcher *dispatcher, struct rte_dispatcher_stats *stats)
Retrieve statistics for a dispatcher instance β numbers, we love numbers. β¨
This function is MT safe and may be called by any thread (including unregistered non-EAL threads). Thread-safe queen. π
Params:
- dispatcher β the dispatcher instance.
- stats β a pointer to a structure to fill with statistics.
π
rte_dispatcher_stats_reset() π
__rte_experimental void rte_dispatcher_stats_reset(struct rte_dispatcher *dispatcher)
Reset statistics for a dispatcher instance. Fresh start, clean slate, zeroes everywhere. π
This function may be called by any thread (including unregistered non-EAL threads) β but heads up, it may not produce the correct result if the dispatcher is running on any service lcore. So maybe don't do that. π
Params:
- dispatcher β the dispatcher instance.
π AUTHOR π
Generated automatically by Doxygen for DPDK from the source code. Not me, not you, not a human β a robot did this. And honestly? It ate. π
That's the whole page, bestie β rte_dispatcher.h(3) from DPDK, Version 25.11.3. Go forth and dispatch responsibly, and remember: bind your ports before you start, don't unregister while it's running, and never trust event ordering between callbacks. π¦ mwah, bye! π«Άπβ¨
π¦ where this page comes from
- ubuntu resolute: dpdk-doc 25.11.3-0ubuntu0.26.04.1 Β· BSD-3-Clause
- ubuntu stonking: dpdk-doc 25.11.3-1 Β· BSD-3-Clause
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash on : a language model's rewrite of the original, under its terms