162306a36Sopenharmony_ci====================================================== 262306a36Sopenharmony_ciNet DIM - Generic Network Dynamic Interrupt Moderation 362306a36Sopenharmony_ci====================================================== 462306a36Sopenharmony_ci 562306a36Sopenharmony_ci:Author: Tal Gilboa <talgi@mellanox.com> 662306a36Sopenharmony_ci 762306a36Sopenharmony_ci.. contents:: :depth: 2 862306a36Sopenharmony_ci 962306a36Sopenharmony_ciAssumptions 1062306a36Sopenharmony_ci=========== 1162306a36Sopenharmony_ci 1262306a36Sopenharmony_ciThis document assumes the reader has basic knowledge in network drivers 1362306a36Sopenharmony_ciand in general interrupt moderation. 1462306a36Sopenharmony_ci 1562306a36Sopenharmony_ci 1662306a36Sopenharmony_ciIntroduction 1762306a36Sopenharmony_ci============ 1862306a36Sopenharmony_ci 1962306a36Sopenharmony_ciDynamic Interrupt Moderation (DIM) (in networking) refers to changing the 2062306a36Sopenharmony_ciinterrupt moderation configuration of a channel in order to optimize packet 2162306a36Sopenharmony_ciprocessing. The mechanism includes an algorithm which decides if and how to 2262306a36Sopenharmony_cichange moderation parameters for a channel, usually by performing an analysis on 2362306a36Sopenharmony_ciruntime data sampled from the system. Net DIM is such a mechanism. In each 2462306a36Sopenharmony_ciiteration of the algorithm, it analyses a given sample of the data, compares it 2562306a36Sopenharmony_cito the previous sample and if required, it can decide to change some of the 2662306a36Sopenharmony_ciinterrupt moderation configuration fields. The data sample is composed of data 2762306a36Sopenharmony_cibandwidth, the number of packets and the number of events. The time between 2862306a36Sopenharmony_cisamples is also measured. Net DIM compares the current and the previous data and 2962306a36Sopenharmony_cireturns an adjusted interrupt moderation configuration object. In some cases, 3062306a36Sopenharmony_cithe algorithm might decide not to change anything. The configuration fields are 3162306a36Sopenharmony_cithe minimum duration (microseconds) allowed between events and the maximum 3262306a36Sopenharmony_cinumber of wanted packets per event. The Net DIM algorithm ascribes importance to 3362306a36Sopenharmony_ciincrease bandwidth over reducing interrupt rate. 3462306a36Sopenharmony_ci 3562306a36Sopenharmony_ci 3662306a36Sopenharmony_ciNet DIM Algorithm 3762306a36Sopenharmony_ci================= 3862306a36Sopenharmony_ci 3962306a36Sopenharmony_ciEach iteration of the Net DIM algorithm follows these steps: 4062306a36Sopenharmony_ci 4162306a36Sopenharmony_ci#. Calculates new data sample. 4262306a36Sopenharmony_ci#. Compares it to previous sample. 4362306a36Sopenharmony_ci#. Makes a decision - suggests interrupt moderation configuration fields. 4462306a36Sopenharmony_ci#. Applies a schedule work function, which applies suggested configuration. 4562306a36Sopenharmony_ci 4662306a36Sopenharmony_ciThe first two steps are straightforward, both the new and the previous data are 4762306a36Sopenharmony_cisupplied by the driver registered to Net DIM. The previous data is the new data 4862306a36Sopenharmony_cisupplied to the previous iteration. The comparison step checks the difference 4962306a36Sopenharmony_cibetween the new and previous data and decides on the result of the last step. 5062306a36Sopenharmony_ciA step would result as "better" if bandwidth increases and as "worse" if 5162306a36Sopenharmony_cibandwidth reduces. If there is no change in bandwidth, the packet rate is 5262306a36Sopenharmony_cicompared in a similar fashion - increase == "better" and decrease == "worse". 5362306a36Sopenharmony_ciIn case there is no change in the packet rate as well, the interrupt rate is 5462306a36Sopenharmony_cicompared. Here the algorithm tries to optimize for lower interrupt rate so an 5562306a36Sopenharmony_ciincrease in the interrupt rate is considered "worse" and a decrease is 5662306a36Sopenharmony_ciconsidered "better". Step #2 has an optimization for avoiding false results: it 5762306a36Sopenharmony_cionly considers a difference between samples as valid if it is greater than a 5862306a36Sopenharmony_cicertain percentage. Also, since Net DIM does not measure anything by itself, it 5962306a36Sopenharmony_ciassumes the data provided by the driver is valid. 6062306a36Sopenharmony_ci 6162306a36Sopenharmony_ciStep #3 decides on the suggested configuration based on the result from step #2 6262306a36Sopenharmony_ciand the internal state of the algorithm. The states reflect the "direction" of 6362306a36Sopenharmony_cithe algorithm: is it going left (reducing moderation), right (increasing 6462306a36Sopenharmony_cimoderation) or standing still. Another optimization is that if a decision 6562306a36Sopenharmony_cito stay still is made multiple times, the interval between iterations of the 6662306a36Sopenharmony_cialgorithm would increase in order to reduce calculation overhead. Also, after 6762306a36Sopenharmony_ci"parking" on one of the most left or most right decisions, the algorithm may 6862306a36Sopenharmony_cidecide to verify this decision by taking a step in the other direction. This is 6962306a36Sopenharmony_cidone in order to avoid getting stuck in a "deep sleep" scenario. Once a 7062306a36Sopenharmony_cidecision is made, an interrupt moderation configuration is selected from 7162306a36Sopenharmony_cithe predefined profiles. 7262306a36Sopenharmony_ci 7362306a36Sopenharmony_ciThe last step is to notify the registered driver that it should apply the 7462306a36Sopenharmony_cisuggested configuration. This is done by scheduling a work function, defined by 7562306a36Sopenharmony_cithe Net DIM API and provided by the registered driver. 7662306a36Sopenharmony_ci 7762306a36Sopenharmony_ciAs you can see, Net DIM itself does not actively interact with the system. It 7862306a36Sopenharmony_ciwould have trouble making the correct decisions if the wrong data is supplied to 7962306a36Sopenharmony_ciit and it would be useless if the work function would not apply the suggested 8062306a36Sopenharmony_ciconfiguration. This does, however, allow the registered driver some room for 8162306a36Sopenharmony_cimanoeuvre as it may provide partial data or ignore the algorithm suggestion 8262306a36Sopenharmony_ciunder some conditions. 8362306a36Sopenharmony_ci 8462306a36Sopenharmony_ci 8562306a36Sopenharmony_ciRegistering a Network Device to DIM 8662306a36Sopenharmony_ci=================================== 8762306a36Sopenharmony_ci 8862306a36Sopenharmony_ciNet DIM API exposes the main function net_dim(). 8962306a36Sopenharmony_ciThis function is the entry point to the Net 9062306a36Sopenharmony_ciDIM algorithm and has to be called every time the driver would like to check if 9162306a36Sopenharmony_ciit should change interrupt moderation parameters. The driver should provide two 9262306a36Sopenharmony_cidata structures: :c:type:`struct dim <dim>` and 9362306a36Sopenharmony_ci:c:type:`struct dim_sample <dim_sample>`. :c:type:`struct dim <dim>` 9462306a36Sopenharmony_cidescribes the state of DIM for a specific object (RX queue, TX queue, 9562306a36Sopenharmony_ciother queues, etc.). This includes the current selected profile, previous data 9662306a36Sopenharmony_cisamples, the callback function provided by the driver and more. 9762306a36Sopenharmony_ci:c:type:`struct dim_sample <dim_sample>` describes a data sample, 9862306a36Sopenharmony_ciwhich will be compared to the data sample stored in :c:type:`struct dim <dim>` 9962306a36Sopenharmony_ciin order to decide on the algorithm's next 10062306a36Sopenharmony_cistep. The sample should include bytes, packets and interrupts, measured by 10162306a36Sopenharmony_cithe driver. 10262306a36Sopenharmony_ci 10362306a36Sopenharmony_ciIn order to use Net DIM from a networking driver, the driver needs to call the 10462306a36Sopenharmony_cimain net_dim() function. The recommended method is to call net_dim() on each 10562306a36Sopenharmony_ciinterrupt. Since Net DIM has a built-in moderation and it might decide to skip 10662306a36Sopenharmony_ciiterations under certain conditions, there is no need to moderate the net_dim() 10762306a36Sopenharmony_cicalls as well. As mentioned above, the driver needs to provide an object of type 10862306a36Sopenharmony_ci:c:type:`struct dim <dim>` to the net_dim() function call. It is advised for 10962306a36Sopenharmony_cieach entity using Net DIM to hold a :c:type:`struct dim <dim>` as part of its 11062306a36Sopenharmony_cidata structure and use it as the main Net DIM API object. 11162306a36Sopenharmony_ciThe :c:type:`struct dim_sample <dim_sample>` should hold the latest 11262306a36Sopenharmony_cibytes, packets and interrupts count. No need to perform any calculations, just 11362306a36Sopenharmony_ciinclude the raw data. 11462306a36Sopenharmony_ci 11562306a36Sopenharmony_ciThe net_dim() call itself does not return anything. Instead Net DIM relies on 11662306a36Sopenharmony_cithe driver to provide a callback function, which is called when the algorithm 11762306a36Sopenharmony_cidecides to make a change in the interrupt moderation parameters. This callback 11862306a36Sopenharmony_ciwill be scheduled and run in a separate thread in order not to add overhead to 11962306a36Sopenharmony_cithe data flow. After the work is done, Net DIM algorithm needs to be set to 12062306a36Sopenharmony_cithe proper state in order to move to the next iteration. 12162306a36Sopenharmony_ci 12262306a36Sopenharmony_ci 12362306a36Sopenharmony_ciExample 12462306a36Sopenharmony_ci======= 12562306a36Sopenharmony_ci 12662306a36Sopenharmony_ciThe following code demonstrates how to register a driver to Net DIM. The actual 12762306a36Sopenharmony_ciusage is not complete but it should make the outline of the usage clear. 12862306a36Sopenharmony_ci 12962306a36Sopenharmony_ci.. code-block:: c 13062306a36Sopenharmony_ci 13162306a36Sopenharmony_ci #include <linux/dim.h> 13262306a36Sopenharmony_ci 13362306a36Sopenharmony_ci /* Callback for net DIM to schedule on a decision to change moderation */ 13462306a36Sopenharmony_ci void my_driver_do_dim_work(struct work_struct *work) 13562306a36Sopenharmony_ci { 13662306a36Sopenharmony_ci /* Get struct dim from struct work_struct */ 13762306a36Sopenharmony_ci struct dim *dim = container_of(work, struct dim, 13862306a36Sopenharmony_ci work); 13962306a36Sopenharmony_ci /* Do interrupt moderation related stuff */ 14062306a36Sopenharmony_ci ... 14162306a36Sopenharmony_ci 14262306a36Sopenharmony_ci /* Signal net DIM work is done and it should move to next iteration */ 14362306a36Sopenharmony_ci dim->state = DIM_START_MEASURE; 14462306a36Sopenharmony_ci } 14562306a36Sopenharmony_ci 14662306a36Sopenharmony_ci /* My driver's interrupt handler */ 14762306a36Sopenharmony_ci int my_driver_handle_interrupt(struct my_driver_entity *my_entity, ...) 14862306a36Sopenharmony_ci { 14962306a36Sopenharmony_ci ... 15062306a36Sopenharmony_ci /* A struct to hold current measured data */ 15162306a36Sopenharmony_ci struct dim_sample dim_sample; 15262306a36Sopenharmony_ci ... 15362306a36Sopenharmony_ci /* Initiate data sample struct with current data */ 15462306a36Sopenharmony_ci dim_update_sample(my_entity->events, 15562306a36Sopenharmony_ci my_entity->packets, 15662306a36Sopenharmony_ci my_entity->bytes, 15762306a36Sopenharmony_ci &dim_sample); 15862306a36Sopenharmony_ci /* Call net DIM */ 15962306a36Sopenharmony_ci net_dim(&my_entity->dim, dim_sample); 16062306a36Sopenharmony_ci ... 16162306a36Sopenharmony_ci } 16262306a36Sopenharmony_ci 16362306a36Sopenharmony_ci /* My entity's initialization function (my_entity was already allocated) */ 16462306a36Sopenharmony_ci int my_driver_init_my_entity(struct my_driver_entity *my_entity, ...) 16562306a36Sopenharmony_ci { 16662306a36Sopenharmony_ci ... 16762306a36Sopenharmony_ci /* Initiate struct work_struct with my driver's callback function */ 16862306a36Sopenharmony_ci INIT_WORK(&my_entity->dim.work, my_driver_do_dim_work); 16962306a36Sopenharmony_ci ... 17062306a36Sopenharmony_ci } 17162306a36Sopenharmony_ci 17262306a36Sopenharmony_ciDynamic Interrupt Moderation (DIM) library API 17362306a36Sopenharmony_ci============================================== 17462306a36Sopenharmony_ci 17562306a36Sopenharmony_ci.. kernel-doc:: include/linux/dim.h 17662306a36Sopenharmony_ci :internal: 177