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 182Arming Event Timers 183~~~~~~~~~~~~~~~~~~~ 184 185Once an event timer adapter has been started, an application can begin to 186manage event timers with it. 187 188The application should allocate ``struct rte_event_timer`` objects from a 189mempool or huge-page backed application buffers of required size. Upon 190successful allocation, the application should initialize the event timer, and 191then set any of the necessary event attributes described in the 192`Timer Expiry Event`_ section. In the following example, assume ``conn`` 193represents a TCP connection and that ``event_timer_pool`` is a mempool that 194was created previously: 195 196.. code-block:: c 197 198 rte_mempool_get(event_timer_pool, (void **)&conn->evtim); 199 if (conn->evtim == NULL) { ... } 200 201 /* Set up the event timer. */ 202 conn->evtim->ev.op = RTE_EVENT_OP_NEW; 203 conn->evtim->ev.queue_id = event_queue_id; 204 conn->evtim->ev.sched_type = RTE_SCHED_TYPE_ATOMIC; 205 conn->evtim->ev.priority = RTE_EVENT_DEV_PRIORITY_NORMAL; 206 conn->evtim->ev.event_type = RTE_EVENT_TYPE_TIMER; 207 conn->evtim->ev.event_ptr = conn; 208 conn->evtim->state = RTE_EVENT_TIMER_NOT_ARMED; 209 conn->evtim->timeout_ticks = 30; //3 sec Per RFC1122(TCP returns) 210 211Note that it is necessary to initialize the event timer state to 212RTE_EVENT_TIMER_NOT_ARMED. Also note that we have saved a pointer to the 213``conn`` object in the timer's event payload. This will allow us to locate 214the connection object again once we dequeue the timer expiry event from the 215event device later. As a convenience, the application may specify no value for 216ev.event_ptr, and the adapter will by default set it to point at the event 217timer itself. 218 219Now we can arm the event timer with ``rte_event_timer_arm_burst()``: 220 221.. code-block:: c 222 223 ret = rte_event_timer_arm_burst(adapter, &conn->evtim, 1); 224 if (ret != 1) { ... } 225 226Once an event timer expires, the application may free it or rearm it as 227necessary. If the application will rearm the timer, the state should be reset 228to RTE_EVENT_TIMER_NOT_ARMED by the application before rearming it. 229 230Multiple Event Timers with Same Expiry Value 231^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 232 233In the special case that there is a set of event timers that should all expire 234at the same time, the application may call 235``rte_event_timer_arm_tmo_tick_burst()``, which allows the implementation to 236optimize the operation if possible. 237 238Canceling Event Timers 239~~~~~~~~~~~~~~~~~~~~~~ 240 241An event timer that has been armed as described in `Arming Event Timers`_ can 242be canceled by calling ``rte_event_timer_cancel_burst()``: 243 244.. code-block:: c 245 246 /* Ack for the previous tcp data packet has been received; 247 * cancel the retransmission timer 248 */ 249 rte_event_timer_cancel_burst(adapter, &conn->timer, 1); 250 251Processing Timer Expiry Events 252------------------------------ 253 254Once an event timer has successfully enqueued a timer expiry event in the event 255device, the application will subsequently dequeue it from the event device. 256The application can use the event payload to retrieve a pointer to the object 257associated with the event timer. It can then re-arm the event timer or free the 258event timer object as desired: 259 260.. code-block:: c 261 262 void 263 event_processing_loop(...) 264 { 265 while (...) { 266 /* Receive events from the configured event port. */ 267 rte_event_dequeue_burst(event_dev_id, event_port, &ev, 1, 0); 268 ... 269 switch(ev.event_type) { 270 ... 271 case RTE_EVENT_TYPE_TIMER: 272 process_timer_event(ev); 273 ... 274 break; 275 } 276 } 277 } 278 279 uint8_t 280 process_timer_event(...) 281 { 282 /* A retransmission timeout for the connection has been received. */ 283 conn = ev.event_ptr; 284 /* Retransmit last packet (e.g. TCP segment). */ 285 ... 286 /* Re-arm timer using original values. */ 287 rte_event_timer_arm_burst(adapter_id, &conn->timer, 1); 288 } 289 290Summary 291------- 292 293The Event Timer Adapter library extends the DPDK event-based programming model 294by representing timer expirations as events in the system and allowing 295applications to use existing event processing loops to arm and cancel event 296timers or handle timer expiry events. 297