doc: add runtime option examples to hns3 guide
[dpdk.git] / doc / guides / sample_app_ug / l3_forward_power_man.rst
1 ..  SPDX-License-Identifier: BSD-3-Clause
2     Copyright(c) 2010-2014 Intel Corporation.
3
4 L3 Forwarding with Power Management Sample Application
5 ======================================================
6
7 Introduction
8 ------------
9
10 The L3 Forwarding with Power Management application is an example of power-aware packet processing using the DPDK.
11 The application is based on existing L3 Forwarding sample application,
12 with the power management algorithms to control the P-states and
13 C-states of the Intel processor via a power management library.
14
15 Overview
16 --------
17
18 The application demonstrates the use of the Power libraries in the DPDK to implement packet forwarding.
19 The initialization and run-time paths are very similar to those of the :doc:`l3_forward`.
20 The main difference from the L3 Forwarding sample application is that this application introduces power-aware optimization algorithms
21 by leveraging the Power library to control P-state and C-state of processor based on packet load.
22
23 The DPDK includes poll-mode drivers to configure Intel NIC devices and their receive (Rx) and transmit (Tx) queues.
24 The design principle of this PMD is to access the Rx and Tx descriptors directly without any interrupts to quickly receive,
25 process and deliver packets in the user space.
26
27 In general, the DPDK executes an endless packet processing loop on dedicated IA cores that include the following steps:
28
29 *   Retrieve input packets through the PMD to poll Rx queue
30
31 *   Process each received packet or provide received packets to other processing cores through software queues
32
33 *   Send pending output packets to Tx queue through the PMD
34
35 In this way, the PMD achieves better performance than a traditional interrupt-mode driver,
36 at the cost of keeping cores active and running at the highest frequency,
37 hence consuming the maximum power all the time.
38 However, during the period of processing light network traffic,
39 which happens regularly in communication infrastructure systems due to well-known "tidal effect",
40 the PMD is still busy waiting for network packets, which wastes a lot of power.
41
42 Processor performance states (P-states) are the capability of an Intel processor
43 to switch between different supported operating frequencies and voltages.
44 If configured correctly, according to system workload, this feature provides power savings.
45 CPUFreq is the infrastructure provided by the Linux* kernel to control the processor performance state capability.
46 CPUFreq supports a user space governor that enables setting frequency via manipulating the virtual file device from a user space application.
47 The Power library in the DPDK provides a set of APIs for manipulating a virtual file device to allow user space application
48 to set the CPUFreq governor and set the frequency of specific cores.
49
50 This application includes a P-state power management algorithm to generate a frequency hint to be sent to CPUFreq.
51 The algorithm uses the number of received and available Rx packets on recent polls to make a heuristic decision to scale frequency up/down.
52 Specifically, some thresholds are checked to see whether a specific core running a DPDK polling thread needs to increase frequency
53 a step up based on the near to full trend of polled Rx queues.
54 Also, it decreases frequency a step if packet processed per loop is far less than the expected threshold
55 or the thread's sleeping time exceeds a threshold.
56
57 C-States are also known as sleep states.
58 They allow software to put an Intel core into a low power idle state from which it is possible to exit via an event, such as an interrupt.
59 However, there is a tradeoff between the power consumed in the idle state and the time required to wake up from the idle state (exit latency).
60 Therefore, as you go into deeper C-states, the power consumed is lower but the exit latency is increased. Each C-state has a target residency.
61 It is essential that when entering into a C-state, the core remains in this C-state for at least as long as the target residency in order
62 to fully realize the benefits of entering the C-state.
63 CPUIdle is the infrastructure provide by the Linux kernel to control the processor C-state capability.
64 Unlike CPUFreq, CPUIdle does not provide a mechanism that allows the application to change C-state.
65 It actually has its own heuristic algorithms in kernel space to select target C-state to enter by executing privileged instructions like HLT and MWAIT,
66 based on the speculative sleep duration of the core.
67 In this application, we introduce a heuristic algorithm that allows packet processing cores to sleep for a short period
68 if there is no Rx packet received on recent polls.
69 In this way, CPUIdle automatically forces the corresponding cores to enter deeper C-states
70 instead of always running to the C0 state waiting for packets.
71
72 .. note::
73
74     To fully demonstrate the power saving capability of using C-states,
75     it is recommended to enable deeper C3 and C6 states in the BIOS during system boot up.
76
77 Compiling the Application
78 -------------------------
79
80 To compile the sample application see :doc:`compiling`.
81
82 The application is located in the ``l3fwd-power`` sub-directory.
83
84 Running the Application
85 -----------------------
86
87 The application has a number of command line options:
88
89 .. code-block:: console
90
91     ./<build_dir>/examples/dpdk-l3fwd_power [EAL options] -- -p PORTMASK [-P]  --config(port,queue,lcore)[,(port,queue,lcore)] [--enable-jumbo [--max-pkt-len PKTLEN]] [--no-numa]
92
93 where,
94
95 *   -p PORTMASK: Hexadecimal bitmask of ports to configure
96
97 *   -P: Sets all ports to promiscuous mode so that packets are accepted regardless of the packet's Ethernet MAC destination address.
98     Without this option, only packets with the Ethernet MAC destination address set to the Ethernet address of the port are accepted.
99
100 *   --config (port,queue,lcore)[,(port,queue,lcore)]: determines which queues from which ports are mapped to which cores.
101
102 *   --enable-jumbo: optional, enables jumbo frames
103
104 *   --max-pkt-len: optional, maximum packet length in decimal (64-9600)
105
106 *   --no-numa: optional, disables numa awareness
107
108 *   --empty-poll: Traffic Aware power management. See below for details
109
110 *   --telemetry:  Telemetry mode.
111
112 *   --pmd-mgmt: PMD power management mode.
113
114 See :doc:`l3_forward` for details.
115 The L3fwd-power example reuses the L3fwd command line options.
116
117 Explanation
118 -----------
119
120 The following sections provide some explanation of the sample application code.
121 As mentioned in the overview section,
122 the initialization and run-time paths are identical to those of the L3 forwarding application.
123 The following sections describe aspects that are specific to the L3 Forwarding with Power Management sample application.
124
125 Power Library Initialization
126 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
127
128 The Power library is initialized in the main routine.
129 It changes the P-state governor to userspace for specific cores that are under control.
130 The Timer library is also initialized and several timers are created later on,
131 responsible for checking if it needs to scale down frequency at run time by checking CPU utilization statistics.
132
133 .. note::
134
135     Only the power management related initialization is shown.
136
137 .. code-block:: c
138
139     int main(int argc, char **argv)
140     {
141         struct lcore_conf *qconf;
142         int ret;
143         unsigned nb_ports;
144         uint16_t queueid, portid;
145         unsigned lcore_id;
146         uint64_t hz;
147         uint32_t n_tx_queue, nb_lcores;
148         uint8_t nb_rx_queue, queue, socketid;
149
150         // ...
151
152         /* init RTE timer library to be used to initialize per-core timers */
153
154         rte_timer_subsystem_init();
155
156         // ...
157
158
159         /* per-core initialization */
160
161         for (lcore_id = 0; lcore_id < RTE_MAX_LCORE; lcore_id++) {
162             if (rte_lcore_is_enabled(lcore_id) == 0)
163                 continue;
164
165             /* init power management library for a specified core */
166
167             ret = rte_power_init(lcore_id);
168             if (ret)
169                 rte_exit(EXIT_FAILURE, "Power management library "
170                     "initialization failed on core%d\n", lcore_id);
171
172             /* init timer structures for each enabled lcore */
173
174             rte_timer_init(&power_timers[lcore_id]);
175
176             hz = rte_get_hpet_hz();
177
178             rte_timer_reset(&power_timers[lcore_id], hz/TIMER_NUMBER_PER_SECOND, SINGLE, lcore_id, power_timer_cb, NULL);
179
180             // ...
181         }
182
183         // ...
184     }
185
186 Monitoring Loads of Rx Queues
187 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
188
189 In general, the polling nature of the DPDK prevents the OS power management subsystem from knowing
190 if the network load is actually heavy or light.
191 In this sample, sampling network load work is done by monitoring received and
192 available descriptors on NIC Rx queues in recent polls.
193 Based on the number of returned and available Rx descriptors,
194 this example implements algorithms to generate frequency scaling hints and speculative sleep duration,
195 and use them to control P-state and C-state of processors via the power management library.
196 Frequency (P-state) control and sleep state (C-state) control work individually for each logical core,
197 and the combination of them contributes to a power efficient packet processing solution when serving light network loads.
198
199 The rte_eth_rx_burst() function and the newly-added rte_eth_rx_queue_count() function are used in the endless packet processing loop
200 to return the number of received and available Rx descriptors.
201 And those numbers of specific queue are passed to P-state and C-state heuristic algorithms
202 to generate hints based on recent network load trends.
203
204 .. note::
205
206     Only power control related code is shown.
207
208 .. code-block:: c
209
210     static
211     __rte_noreturn int main_loop(__rte_unused void *dummy)
212     {
213         // ...
214
215         while (1) {
216         // ...
217
218         /**
219          * Read packet from RX queues
220          */
221
222         lcore_scaleup_hint = FREQ_CURRENT;
223         lcore_rx_idle_count = 0;
224
225         for (i = 0; i < qconf->n_rx_queue; ++i)
226         {
227             rx_queue = &(qconf->rx_queue_list[i]);
228             rx_queue->idle_hint = 0;
229             portid = rx_queue->port_id;
230             queueid = rx_queue->queue_id;
231
232             nb_rx = rte_eth_rx_burst(portid, queueid, pkts_burst, MAX_PKT_BURST);
233             stats[lcore_id].nb_rx_processed += nb_rx;
234
235             if (unlikely(nb_rx == 0)) {
236                 /**
237                  * no packet received from rx queue, try to
238                  * sleep for a while forcing CPU enter deeper
239                  * C states.
240                  */
241
242                 rx_queue->zero_rx_packet_count++;
243
244                 if (rx_queue->zero_rx_packet_count <= MIN_ZERO_POLL_COUNT)
245                     continue;
246
247                 rx_queue->idle_hint = power_idle_heuristic(rx_queue->zero_rx_packet_count);
248                 lcore_rx_idle_count++;
249             } else {
250                 rx_ring_length = rte_eth_rx_queue_count(portid, queueid);
251
252                 rx_queue->zero_rx_packet_count = 0;
253
254                 /**
255                  * do not scale up frequency immediately as
256                  * user to kernel space communication is costly
257                  * which might impact packet I/O for received
258                  * packets.
259                  */
260
261                 rx_queue->freq_up_hint = power_freq_scaleup_heuristic(lcore_id, rx_ring_length);
262             }
263
264             /* Prefetch and forward packets */
265
266             // ...
267         }
268
269         if (likely(lcore_rx_idle_count != qconf->n_rx_queue)) {
270             for (i = 1, lcore_scaleup_hint = qconf->rx_queue_list[0].freq_up_hint; i < qconf->n_rx_queue; ++i) {
271                 x_queue = &(qconf->rx_queue_list[i]);
272
273                 if (rx_queue->freq_up_hint > lcore_scaleup_hint)
274
275                     lcore_scaleup_hint = rx_queue->freq_up_hint;
276             }
277
278             if (lcore_scaleup_hint == FREQ_HIGHEST)
279
280                 rte_power_freq_max(lcore_id);
281
282             else if (lcore_scaleup_hint == FREQ_HIGHER)
283                 rte_power_freq_up(lcore_id);
284             } else {
285                 /**
286                  *  All Rx queues empty in recent consecutive polls,
287                  *  sleep in a conservative manner, meaning sleep as
288                  * less as possible.
289                  */
290
291                 for (i = 1, lcore_idle_hint = qconf->rx_queue_list[0].idle_hint; i < qconf->n_rx_queue; ++i) {
292                     rx_queue = &(qconf->rx_queue_list[i]);
293                     if (rx_queue->idle_hint < lcore_idle_hint)
294                         lcore_idle_hint = rx_queue->idle_hint;
295                 }
296
297                 if ( lcore_idle_hint < SLEEP_GEAR1_THRESHOLD)
298                     /**
299                      *   execute "pause" instruction to avoid context
300                      *   switch for short sleep.
301                      */
302                     rte_delay_us(lcore_idle_hint);
303                 else
304                     /* long sleep force ruining thread to suspend */
305                     usleep(lcore_idle_hint);
306
307                stats[lcore_id].sleep_time += lcore_idle_hint;
308             }
309         }
310     }
311
312 P-State Heuristic Algorithm
313 ~~~~~~~~~~~~~~~~~~~~~~~~~~~
314
315 The power_freq_scaleup_heuristic() function is responsible for generating a frequency hint for the specified logical core
316 according to available descriptor number returned from rte_eth_rx_queue_count().
317 On every poll for new packets, the length of available descriptor on an Rx queue is evaluated,
318 and the algorithm used for frequency hinting is as follows:
319
320 *   If the size of available descriptors exceeds 96, the maximum frequency is hinted.
321
322 *   If the size of available descriptors exceeds 64, a trend counter is incremented by 100.
323
324 *   If the length of the ring exceeds 32, the trend counter is incremented by 1.
325
326 *   When the trend counter reached 10000 the frequency hint is changed to the next higher frequency.
327
328 .. note::
329
330     The assumption is that the Rx queue size is 128 and the thresholds specified above
331     must be adjusted accordingly based on actual hardware Rx queue size,
332     which are configured via the rte_eth_rx_queue_setup() function.
333
334 In general, a thread needs to poll packets from multiple Rx queues.
335 Most likely, different queue have different load, so they would return different frequency hints.
336 The algorithm evaluates all the hints and then scales up frequency in an aggressive manner
337 by scaling up to highest frequency as long as one Rx queue requires.
338 In this way, we can minimize any negative performance impact.
339
340 On the other hand, frequency scaling down is controlled in the timer callback function.
341 Specifically, if the sleep times of a logical core indicate that it is sleeping more than 25% of the sampling period,
342 or if the average packet per iteration is less than expectation, the frequency is decreased by one step.
343
344 C-State Heuristic Algorithm
345 ~~~~~~~~~~~~~~~~~~~~~~~~~~~
346
347 Whenever recent rte_eth_rx_burst() polls return 5 consecutive zero packets,
348 an idle counter begins incrementing for each successive zero poll.
349 At the same time, the function power_idle_heuristic() is called to generate speculative sleep duration
350 in order to force logical to enter deeper sleeping C-state.
351 There is no way to control C- state directly, and the CPUIdle subsystem in OS is intelligent enough
352 to select C-state to enter based on actual sleep period time of giving logical core.
353 The algorithm has the following sleeping behavior depending on the idle counter:
354
355 *   If idle count less than 100, the counter value is used as a microsecond sleep value through rte_delay_us()
356     which execute pause instructions to avoid costly context switch but saving power at the same time.
357
358 *   If idle count is between 100 and 999, a fixed sleep interval of 100 μs is used.
359     A 100 μs sleep interval allows the core to enter the C1 state while keeping a fast response time in case new traffic arrives.
360
361 *   If idle count is greater than 1000, a fixed sleep value of 1 ms is used until the next timer expiration is used.
362     This allows the core to enter the C3/C6 states.
363
364 .. note::
365
366     The thresholds specified above need to be adjusted for different Intel processors and traffic profiles.
367
368 If a thread polls multiple Rx queues and different queue returns different sleep duration values,
369 the algorithm controls the sleep time in a conservative manner by sleeping for the least possible time
370 in order to avoid a potential performance impact.
371
372 Empty Poll Mode
373 -------------------------
374 Additionally, there is a traffic aware mode of operation called "Empty
375 Poll" where the number of empty polls can be monitored to keep track
376 of how busy the application is. Empty poll mode can be enabled by the
377 command line option --empty-poll.
378
379 See :doc:`Power Management<../prog_guide/power_man>` chapter in the DPDK Programmer's Guide for empty poll mode details.
380
381 .. code-block:: console
382
383     ./<build_dir>/examples/dpdk-l3fwd-power -l xxx -n 4 -a 0000:xx:00.0 -a 0000:xx:00.1 \
384         -- -p 0x3 -P --config="(0,0,xx),(1,0,xx)" --empty-poll="0,0,0" -l 14 -m 9 -h 1
385
386 Where,
387
388 --empty-poll: Enable the empty poll mode instead of original algorithm
389
390 --empty-poll="training_flag, med_threshold, high_threshold"
391
392 * ``training_flag`` : optional, enable/disable training mode. Default value is 0. If the training_flag is set as 1(true), then the application will start in training mode and print out the trained threshold values. If the training_flag is set as 0(false), the application will start in normal mode, and will use either the default thresholds or those supplied on the command line. The trained threshold values are specific to the user’s system, may give a better power profile when compared to the default threshold values.
393
394 * ``med_threshold`` : optional, sets the empty poll threshold of a modestly busy system state. If this is not supplied, the application will apply the default value of 350000.
395
396 * ``high_threshold`` : optional, sets the empty poll threshold of a busy system state. If this is not supplied, the application will apply the default value of 580000.
397
398 * -l : optional, set up the LOW power state frequency index
399
400 * -m : optional, set up the MED power state frequency index
401
402 * -h : optional, set up the HIGH power state frequency index
403
404 Empty Poll Mode Example Usage
405 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
406 To initially obtain the ideal thresholds for the system, the training
407 mode should be run first. This is achieved by running the l3fwd-power
408 app with the training flag set to “1”, and the other parameters set to
409 0.
410
411 .. code-block:: console
412
413         ./<build_dir>/examples/dpdk-l3fwd-power -l 1-3 -- -p 0x0f --config="(0,0,2),(0,1,3)" --empty-poll "1,0,0" –P
414
415 This will run the training algorithm for x seconds on each core (cores 2
416 and 3), and then print out the recommended threshold values for those
417 cores. The thresholds should be very similar for each core.
418
419 .. code-block:: console
420
421         POWER: Bring up the Timer
422         POWER: set the power freq to MED
423         POWER: Low threshold is 230277
424         POWER: MED threshold is 335071
425         POWER: HIGH threshold is 523769
426         POWER: Training is Complete for 2
427         POWER: set the power freq to MED
428         POWER: Low threshold is 236814
429         POWER: MED threshold is 344567
430         POWER: HIGH threshold is 538580
431         POWER: Training is Complete for 3
432
433 Once the values have been measured for a particular system, the app can
434 then be started without the training mode so traffic can start immediately.
435
436 .. code-block:: console
437
438         ./<build_dir>/examples/dpdk-l3fwd-power -l 1-3 -- -p 0x0f --config="(0,0,2),(0,1,3)" --empty-poll "0,340000,540000" –P
439
440 Telemetry Mode
441 --------------
442
443 The telemetry mode support for ``l3fwd-power`` is a standalone mode, in this mode
444 ``l3fwd-power`` does simple l3fwding along with calculating empty polls, full polls,
445 and busy percentage for each forwarding core. The aggregation of these
446 values of all cores is reported as application level telemetry to metric
447 library for every 500ms from the main core.
448
449 The busy percentage is calculated by recording the poll_count
450 and when the count reaches a defined value the total
451 cycles it took is measured and compared with minimum and maximum
452 reference cycles and accordingly busy rate is set  to either 0% or
453 50% or 100%.
454
455 .. code-block:: console
456
457         ./<build_dir>/examples/dpdk-l3fwd-power --telemetry -l 1-3 -- -p 0x0f --config="(0,0,2),(0,1,3)" --telemetry
458
459 The new stats ``empty_poll`` , ``full_poll`` and ``busy_percent`` can be viewed by running the script
460 ``/usertools/dpdk-telemetry-client.py`` and selecting the menu option ``Send for global Metrics``.
461
462 PMD power management Mode
463 -------------------------
464
465 The PMD power management  mode support for ``l3fwd-power`` is a standalone mode.
466 In this mode, ``l3fwd-power`` does simple l3fwding
467 along with enabling the power saving scheme on specific port/queue/lcore.
468 Main purpose for this mode is to demonstrate
469 how to use the PMD power management API.
470
471 .. code-block:: console
472
473         ./build/examples/dpdk-l3fwd-power -l 1-3 --  --pmd-mgmt -p 0x0f --config="(0,0,2),(0,1,3)"
474
475 PMD Power Management Mode
476 -------------------------
477
478 There is also a traffic-aware operating mode that,
479 instead of using explicit power management,
480 will use automatic PMD power management.
481 This mode is limited to one queue per core,
482 and has three available power management schemes:
483
484 ``monitor``
485   This will use ``rte_power_monitor()`` function to enter
486   a power-optimized state (subject to platform support).
487
488 ``pause``
489   This will use ``rte_power_pause()`` or ``rte_pause()``
490   to avoid busy looping when there is no traffic.
491
492 ``scale``
493   This will use frequency scaling routines
494   available in the ``librte_power`` library.
495
496 See :doc:`Power Management<../prog_guide/power_man>` chapter
497 in the DPDK Programmer's Guide for more details on PMD power management.
498
499 .. code-block:: console
500
501         ./<build_dir>/examples/dpdk-l3fwd-power -l 1-3 -- -p 0x0f --config="(0,0,2),(0,1,3)" --pmd-mgmt=scale