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