xref: /dpdk/doc/guides/prog_guide/eventdev/event_timer_adapter.rst (revision 41dd9a6bc2d9c6e20e139ad713cc9d172572dd43)
1..  SPDX-License-Identifier: BSD-3-Clause
2    Copyright(c) 2017 Intel Corporation. All rights reserved.
3
4Event Timer Adapter Library
5===========================
6
7The DPDK :doc:`Event Device library <eventdev>`
8introduces an event driven programming model which presents applications with
9an alternative to the polling model traditionally used in DPDK
10applications. Event devices can be coupled with arbitrary components to provide
11new event sources by using **event adapters**. The Event Timer Adapter is one
12such adapter; it bridges event devices and timer mechanisms.
13
14The Event Timer Adapter library extends the event driven model
15by introducing a :ref:`new type of event <timer_expiry_event>` that represents
16a timer expiration, and providing an API with which adapters can be created or
17destroyed, and :ref:`event timers <event_timer>` can be armed and canceled.
18
19The Event Timer Adapter library is designed to interface with hardware or
20software implementations of the timer mechanism; it will query an eventdev PMD
21to determine which implementation should be used.  The default software
22implementation manages timers using the DPDK :doc:`../timer_lib`.
23
24Examples of using the API are presented in the `API Overview`_ and
25`Processing Timer Expiry Events`_ sections.  Code samples are abstracted and
26are based on the example of handling a TCP retransmission.
27
28.. _event_timer:
29
30Event Timer struct
31------------------
32Event timers are timers that enqueue a timer expiration event to an event
33device upon timer expiration.
34
35The Event Timer Adapter API represents each event timer with a generic struct,
36which contains an event and user metadata.  The ``rte_event_timer`` struct is
37defined in ``rte_event_timer_adapter.h``.
38
39.. _timer_expiry_event:
40
41Timer Expiry Event
42~~~~~~~~~~~~~~~~~~
43
44The event contained by an event timer is enqueued in the event device when the
45timer expires, and the event device uses the attributes below when scheduling
46it:
47
48* ``event_queue_id`` - Application should set this to specify an event queue to
49  which the timer expiry event should be enqueued
50* ``event_priority`` - Application can set this to indicate the priority of the
51  timer expiry event in the event queue relative to other events
52* ``sched_type`` - Application can set this to specify the scheduling type of
53  the timer expiry event
54* ``flow_id`` - Application can set this to indicate which flow this timer
55  expiry event corresponds to
56* ``op`` - Will be set to ``RTE_EVENT_OP_NEW`` by the event timer adapter
57* ``event_type`` - Will be set to ``RTE_EVENT_TYPE_TIMER`` by the event timer
58  adapter
59
60Timeout Ticks
61~~~~~~~~~~~~~
62
63The number of ticks from now in which the timer will expire. The ticks value
64has a resolution (``timer_tick_ns``) that is specified in the event timer
65adapter configuration.
66
67State
68~~~~~
69
70Before arming an event timer, the application should initialize its state to
71RTE_EVENT_TIMER_NOT_ARMED. The event timer's state will be updated when a
72request to arm or cancel it takes effect.
73
74If the application wishes to rearm the timer after it has expired, it should
75reset the state back to RTE_EVENT_TIMER_NOT_ARMED before doing so.
76
77User Metadata
78~~~~~~~~~~~~~
79
80Memory to store user specific metadata.  The event timer adapter implementation
81will not modify this area.
82
83API Overview
84------------
85
86This section will introduce the reader to the event timer adapter API, showing
87how to create and configure an event timer adapter and use it to manage event
88timers.
89
90From a high level, the setup steps are:
91
92* rte_event_timer_adapter_create()
93* rte_event_timer_adapter_start()
94
95And to start and stop timers:
96
97* rte_event_timer_arm_burst()
98* rte_event_timer_cancel_burst()
99
100Create and Configure an Adapter Instance
101~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
102
103To create an event timer adapter instance, initialize an
104``rte_event_timer_adapter_conf`` struct with the desired values, and pass it
105to ``rte_event_timer_adapter_create()``.
106
107.. code-block:: c
108
109	#define NSECPERSEC 1E9
110	const struct rte_event_timer_adapter_conf adapter_config = {
111                .event_dev_id = event_dev_id,
112                .timer_adapter_id = 0,
113		.socket_id = rte_socket_id(),
114                .clk_src = RTE_EVENT_TIMER_ADAPTER_CPU_CLK,
115                .timer_tick_ns = NSECPERSEC / 10,
116                .max_tmo_ns = 180 * NSECPERSEC,
117                .nb_timers = 40000,
118                .flags = 0,
119	};
120
121	struct rte_event_timer_adapter *adapter;
122	adapter = rte_event_timer_adapter_create(&adapter_config);
123
124	if (adapter == NULL) { ... };
125
126Before creating an instance of a timer adapter, the application should create
127and configure an event device along with its event ports. Based on the event
128device capability, it might require creating an additional event port to be
129used by the timer adapter.  If required, the
130``rte_event_timer_adapter_create()`` function will use a default method to
131configure an event port;  it will examine the current event device
132configuration, determine the next available port identifier number, and create
133a new event port with a default port configuration.
134
135If the application desires to have finer control of event port allocation
136and setup, it can use the ``rte_event_timer_adapter_create_ext()`` function.
137This function is passed a callback function that will be invoked if the
138adapter needs to create an event port, giving the application the opportunity
139to control how it is done.
140
141Event device configuration for service based adapter
142^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
143
144When ``rte_event_timer_adapter_create()`` is used for creating
145adapter instance, ``rte_event_dev_config::nb_event_ports`` is
146automatically incremented, and the event device is reconfigured
147with additional event port during service initialization.
148This event device reconfigure logic also increments the
149``rte_event_dev_config::nb_single_link_event_port_queues``
150parameter if the adapter event port config is of type
151``RTE_EVENT_PORT_CFG_SINGLE_LINK``.
152
153Application no longer needs to account for the
154``rte_event_dev_config::nb_event_ports`` and
155``rte_event_dev_config::nb_single_link_event_port_queues``
156parameters required for timer adapter in event device configuration,
157when the adapter is created using the above-mentioned API.
158
159Adapter modes
160^^^^^^^^^^^^^
161An event timer adapter can be configured in either periodic or non-periodic mode
162to support timers of the respective type. A periodic timer expires at a fixed
163time interval repeatedly till it is cancelled. A non-periodic timer expires only
164once. The periodic capability flag, ``RTE_EVENT_TIMER_ADAPTER_CAP_PERIODIC``,
165can be set for implementations that support periodic mode if desired. To
166configure an adapter in periodic mode, ``flags`` of
167``rte_event_timer_adapter_conf`` is set to include the periodic flag
168``RTE_EVENT_TIMER_ADAPTER_F_PERIODIC``. Maximum timeout (``max_tmo_ns``) does
169not apply to periodic mode.
170
171Retrieve Event Timer Adapter Contextual Information
172~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
173The event timer adapter implementation may have constraints on tick resolution
174or maximum timer expiry timeout based on the given event timer adapter or
175system.  In this case, the implementation may adjust the tick resolution or
176maximum timeout to the best possible configuration.
177
178Upon successful event timer adapter creation, the application can get the
179configured resolution and max timeout with
180``rte_event_timer_adapter_get_info()``. This function will return an
181``rte_event_timer_adapter_info`` struct, which contains the following members:
182
183* ``min_resolution_ns`` - Minimum timer adapter tick resolution in ns.
184* ``max_tmo_ns`` - Maximum timer timeout(expiry) in ns.
185* ``adapter_conf`` - Configured event timer adapter attributes
186
187Configuring the Service Component
188~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
189
190If the adapter uses a service component, the application is required to map
191the service to a service core before starting the adapter:
192
193.. code-block:: c
194
195        uint32_t service_id;
196
197        if (rte_event_timer_adapter_service_id_get(adapter, &service_id) == 0)
198                rte_service_map_lcore_set(service_id, EVTIM_CORE_ID);
199
200An event timer adapter uses a service component if the event device PMD
201indicates that the adapter should use a software implementation.
202
203Starting the Adapter Instance
204~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
205
206The application should call ``rte_event_timer_adapter_start()`` to start
207running the event timer adapter. This function calls the start entry points
208defined by eventdev PMDs for hardware implementations or puts a service
209component into the running state in the software implementation.
210
211.. Note::
212
213         The eventdev to which the event_timer_adapter is connected needs to
214         be started before calling rte_event_timer_adapter_start().
215
216Arming Event Timers
217~~~~~~~~~~~~~~~~~~~
218
219Once an event timer adapter has been started, an application can begin to
220manage event timers with it.
221
222The application should allocate ``struct rte_event_timer`` objects from a
223mempool or huge-page backed application buffers of required size. Upon
224successful allocation, the application should initialize the event timer, and
225then set any of the necessary event attributes described in the
226`Timer Expiry Event`_ section. In the following example, assume ``conn``
227represents a TCP connection and that ``event_timer_pool`` is a mempool that
228was created previously:
229
230.. code-block:: c
231
232	rte_mempool_get(event_timer_pool, (void **)&conn->evtim);
233	if (conn->evtim == NULL) { ... }
234
235	/* Set up the event timer. */
236	conn->evtim->ev.op = RTE_EVENT_OP_NEW;
237	conn->evtim->ev.queue_id = event_queue_id;
238        conn->evtim->ev.sched_type = RTE_SCHED_TYPE_ATOMIC;
239        conn->evtim->ev.priority = RTE_EVENT_DEV_PRIORITY_NORMAL;
240        conn->evtim->ev.event_type = RTE_EVENT_TYPE_TIMER;
241	conn->evtim->ev.event_ptr = conn;
242	conn->evtim->state = RTE_EVENT_TIMER_NOT_ARMED;
243	conn->evtim->timeout_ticks = 30; //3 sec Per RFC1122(TCP returns)
244
245Note that it is necessary to initialize the event timer state to
246RTE_EVENT_TIMER_NOT_ARMED.  Also note that we have saved a pointer to the
247``conn`` object in the timer's event payload. This will allow us to locate
248the connection object again once we dequeue the timer expiry event from the
249event device later.
250
251Now we can arm the event timer with ``rte_event_timer_arm_burst()``:
252
253.. code-block:: c
254
255	ret = rte_event_timer_arm_burst(adapter, &conn->evtim, 1);
256	if (ret != 1) { ... }
257
258Once an event timer expires, the application may free it or rearm it as
259necessary.  If the application will rearm the timer, the state should be reset
260to RTE_EVENT_TIMER_NOT_ARMED by the application before rearming it. Timer expiry
261events will be generated once or periodically until the timer is cancelled based
262on adapter mode.
263
264Multiple Event Timers with Same Expiry Value
265^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
266
267In the special case that there is a set of event timers that should all expire
268at the same time, the application may call
269``rte_event_timer_arm_tmo_tick_burst()``, which allows the implementation to
270optimize the operation if possible.
271
272Canceling Event Timers
273~~~~~~~~~~~~~~~~~~~~~~
274
275An event timer that has been armed as described in `Arming Event Timers`_ can
276be canceled by calling ``rte_event_timer_cancel_burst()``:
277
278.. code-block:: c
279
280	/* Ack for the previous tcp data packet has been received;
281	 * cancel the retransmission timer
282         */
283	rte_event_timer_cancel_burst(adapter, &conn->timer, 1);
284
285Processing Timer Expiry Events
286------------------------------
287
288Once an event timer has successfully enqueued a timer expiry event in the event
289device, the application will subsequently dequeue it from the event device.
290The application can use the event payload to retrieve a pointer to the object
291associated with the event timer. It can then re-arm the event timer or free the
292event timer object as desired:
293
294.. code-block:: c
295
296	void
297	event_processing_loop(...)
298	{
299		while (...) {
300			/* Receive events from the configured event port. */
301			rte_event_dequeue_burst(event_dev_id, event_port, &ev, 1, 0);
302			...
303			switch(ev.event_type) {
304				...
305				case RTE_EVENT_TYPE_TIMER:
306					process_timer_event(ev);
307					...
308					break;
309			}
310		}
311	}
312
313	uint8_t
314	process_timer_event(...)
315	{
316		/* A retransmission timeout for the connection has been received. */
317		conn = ev.event_ptr;
318		/* Retransmit last packet (e.g. TCP segment). */
319		...
320		/* Re-arm timer using original values. */
321		rte_event_timer_arm_burst(adapter_id, &conn->timer, 1);
322	}
323
324Summary
325-------
326
327The Event Timer Adapter library extends the DPDK event-based programming model
328by representing timer expirations as events in the system and allowing
329applications to use existing event processing loops to arm and cancel event
330timers or handle timer expiry events.
331