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