#1 Backport recent network/udev changes
Merged 3 years ago by anitazha. Opened 3 years ago by daandemeyer.
centos-sig-hyperscale/ daandemeyer/systemd network-backports  into  fb-v249.4

file modified
+87 -36
@@ -702,62 +702,42 @@ 

          </listitem>

        </varlistentry>

        <varlistentry>

-         <term><varname>LargeReceiveOffload=</varname></term>

+         <term><varname>GenericReceiveOffloadHardware=</varname></term>

          <listitem>

-           <para>Takes a boolean. If set to true, Large Receive Offload (LRO) is enabled.

-           When unset, the kernel's default will be used.</para>

+           <para>Takes a boolean. If set to true, hardware accelerated Generic Receive Offload (GRO) is

+           enabled. When unset, the kernel's default will be used.</para>

          </listitem>

        </varlistentry>

        <varlistentry>

-         <term><varname>RxChannels=</varname></term>

+         <term><varname>LargeReceiveOffload=</varname></term>

          <listitem>

-           <para>Sets the number of receive channels (a number between 1 and 4294967295) .</para>

+           <para>Takes a boolean. If set to true, Large Receive Offload (LRO) is enabled.

+           When unset, the kernel's default will be used.</para>

          </listitem>

        </varlistentry>

        <varlistentry>

+         <term><varname>RxChannels=</varname></term>

          <term><varname>TxChannels=</varname></term>

-         <listitem>

-           <para>Sets the number of transmit channels (a number between 1 and 4294967295).</para>

-         </listitem>

-       </varlistentry>

-       <varlistentry>

          <term><varname>OtherChannels=</varname></term>

-         <listitem>

-           <para>Sets the number of other channels (a number between 1 and 4294967295).</para>

-         </listitem>

-       </varlistentry>

-       <varlistentry>

          <term><varname>CombinedChannels=</varname></term>

          <listitem>

-           <para>Sets the number of combined set channels (a number between 1 and 4294967295).</para>

+           <para>Specifies the number of receive, transmit, other, or combined channels, respectively.

+           Takes an unsigned integer in the range 1…4294967295 or <literal>max</literal>. If set to

+           <literal>max</literal>, the advertised maximum value of the hardware will be used. When

+           unset, the number will not be changed. Defaults to unset.</para>

          </listitem>

        </varlistentry>

        <varlistentry>

          <term><varname>RxBufferSize=</varname></term>

-         <listitem>

-           <para>Takes an integer. Specifies the maximum number of pending packets in the NIC receive buffer.

-           When unset, the kernel's default will be used.</para>

-         </listitem>

-       </varlistentry>

-       <varlistentry>

          <term><varname>RxMiniBufferSize=</varname></term>

-         <listitem>

-           <para>Takes an integer. Specifies the maximum number of pending packets in the NIC mini receive buffer.

-           When unset, the kernel's default will be used.</para>

-         </listitem>

-       </varlistentry>

-       <varlistentry>

          <term><varname>RxJumboBufferSize=</varname></term>

-         <listitem>

-           <para>Takes an integer. Specifies the maximum number of pending packets in the NIC jumbo receive buffer.

-           When unset, the kernel's default will be used.</para>

-         </listitem>

-       </varlistentry>

-       <varlistentry>

          <term><varname>TxBufferSize=</varname></term>

          <listitem>

-           <para>Takes an integer. Specifies the maximum number of pending packets in the NIC transmit buffer.

-           When unset, the kernel's default will be used.</para>

+           <para>Specifies the maximum number of pending packets in the NIC receive buffer, mini receive

+           buffer, jumbo receive buffer, or transmit buffer, respectively. Takes an unsigned integer in

+           the range 1…4294967295 or <literal>max</literal>. If set to <literal>max</literal>, the

+           advertised maximum value of the hardware will be used. When unset, the number will not be

+           changed. Defaults to unset.</para>

          </listitem>

        </varlistentry>

        <varlistentry>
@@ -800,6 +780,77 @@ 

            accept. An unsigned integer in the range 1…65535. Defaults to unset.</para>

          </listitem>

        </varlistentry>

+       <varlistentry>

+         <term><varname>UseAdaptiveRxCoalesce=</varname></term>

+         <term><varname>UseAdaptiveTxCoalesce=</varname></term>

+         <listitem>

+           <para>Boolean properties that, when set, enable/disable adaptive Rx/Tx coalescing if the hardware

+           supports it. When unset, the kernel's default will be used.</para>

+         </listitem>

+       </varlistentry>

+       <varlistentry>

+         <term><varname>RxCoalesceSec=</varname></term>

+         <term><varname>RxCoalesceIrqSec=</varname></term>

+         <term><varname>RxCoalesceLowSec=</varname></term>

+         <term><varname>RxCoalesceHighSec=</varname></term>

+         <term><varname>TxCoalesceSec=</varname></term>

+         <term><varname>TxCoalesceIrqSec=</varname></term>

+         <term><varname>TxCoalesceLowSec=</varname></term>

+         <term><varname>TxCoalesceHighSec=</varname></term>

+         <listitem>

+           <para>These properties configure the delay before Rx/Tx interrupts are generated after a packet is

+           sent/received. The <literal>Irq</literal> properties come into effect when the host is servicing an

+           IRQ. The <literal>Low</literal> and <literal>High</literal> properties come into effect when the

+           packet rate drops below the low packet rate threshold or exceeds the high packet rate threshold

+           respectively if adaptive Rx/Tx coalescing is enabled. When unset, the kernel's defaults will be

+           used.</para>

+         </listitem>

+       </varlistentry>

+         <varlistentry>

+         <term><varname>RxMaxCoalescedFrames=</varname></term>

+         <term><varname>RxMaxCoalescedIrqFrames=</varname></term>

+         <term><varname>RxMaxCoalescedLowFrames=</varname></term>

+         <term><varname>RxMaxCoalescedHighFrames=</varname></term>

+         <term><varname>TxMaxCoalescedFrames=</varname></term>

+         <term><varname>TxMaxCoalescedIrqFrames=</varname></term>

+         <term><varname>TxMaxCoalescedLowFrames=</varname></term>

+         <term><varname>TxMaxCoalescedHighFrames=</varname></term>

+         <listitem>

+           <para>These properties configure the maximum number of frames that are sent/received before a Rx/Tx

+           interrupt is generated. The <literal>Irq</literal> properties come into effect when the host is

+           servicing an IRQ. The <literal>Low</literal> and <literal>High</literal> properties come into

+           effect when the packet rate drops below the low packet rate threshold or exceeds the high packet

+           rate threshold respectively if adaptive Rx/Tx coalescing is enabled. When unset, the kernel's

+           defaults will be used.</para>

+         </listitem>

+       </varlistentry>

+       <varlistentry>

+         <term><varname>CoalescePacketRateLow=</varname></term>

+         <term><varname>CoalescePacketRateHigh=</varname></term>

+         <listitem>

+           <para>These properties configure the low and high packet rate (expressed in packets per second)

+           threshold respectively and are used to determine when the corresponding coalescing settings for low

+           and high packet rates come into effect if adaptive Rx/Tx coalescing is enabled. If unset, the

+           kernel's defaults will be used.</para>

+         </listitem>

+       </varlistentry>

+       <varlistentry>

+         <term><varname>CoalescePacketRateSampleIntervalSec=</varname></term>

+         <listitem>

+           <para>Configures how often to sample the packet rate used for adaptive Rx/Tx coalescing. This

+           property cannot be zero. This lowest time granularity supported by this property is seconds.

+           Partial seconds will be rounded up before being passed to the kernel. If unset, the kernel's

+           default will be used.</para>

+         </listitem>

+       </varlistentry>

+       <varlistentry>

+         <term><varname>StatisticsBlockCoalesceSec=</varname></term>

+         <listitem>

+           <para>How long to delay driver in-memory statistics block updates. If the driver does not have an

+           in-memory statistic block, this property is ignored. This property cannot be zero. If unset, the

+           kernel's default will be used.</para>

+         </listitem>

+       </varlistentry>

  

      </variablelist>

    </refsect1>

file modified
+265 -99
@@ -14,6 +14,7 @@ 

  #include "memory-util.h"

  #include "socket-util.h"

  #include "string-table.h"

+ #include "strv.h"

  #include "strxcpyx.h"

  

  static const char* const duplex_table[_DUP_MAX] = {
@@ -69,13 +70,14 @@ 

  DEFINE_CONFIG_PARSE_ENUM(config_parse_port, port, NetDevPort, "Failed to parse Port setting");

  

  static const char* const netdev_feature_table[_NET_DEV_FEAT_MAX] = {

-         [NET_DEV_FEAT_RX]   = "rx-checksum",

-         [NET_DEV_FEAT_TX]   = "tx-checksum-", /* The suffix "-" means any feature beginning with "tx-checksum-" */

-         [NET_DEV_FEAT_GSO]  = "tx-generic-segmentation",

-         [NET_DEV_FEAT_GRO]  = "rx-gro",

-         [NET_DEV_FEAT_LRO]  = "rx-lro",

-         [NET_DEV_FEAT_TSO]  = "tx-tcp-segmentation",

-         [NET_DEV_FEAT_TSO6] = "tx-tcp6-segmentation",

+         [NET_DEV_FEAT_RX]     = "rx-checksum",

+         [NET_DEV_FEAT_TX]     = "tx-checksum-", /* The suffix "-" means any feature beginning with "tx-checksum-" */

+         [NET_DEV_FEAT_GSO]    = "tx-generic-segmentation",

+         [NET_DEV_FEAT_GRO]    = "rx-gro",

+         [NET_DEV_FEAT_GRO_HW] = "rx-gro-hw",

+         [NET_DEV_FEAT_LRO]    = "rx-lro",

+         [NET_DEV_FEAT_TSO]    = "tx-tcp-segmentation",

+         [NET_DEV_FEAT_TSO6]   = "tx-tcp6-segmentation",

  };

  

  static const char* const ethtool_link_mode_bit_table[] = {
@@ -329,6 +331,17 @@ 

                  dest = _v;                             \

          } while(false)

  

+ #define UPDATE_WITH_MAX(dest, max, val, updated)       \

+         do {                                           \

+                 typeof(dest) _v = (val);               \

+                 typeof(dest) _max = (max);             \

+                 if (_v == 0 || _v > _max)              \

+                         _v = _max;                     \

+                 if (dest != _v)                        \

+                         updated = true;                \

+                 dest = _v;                             \

+         } while(false)

+ 

  int ethtool_set_wol(int *ethtool_fd, const char *ifname, uint32_t wolopts) {

          struct ethtool_wolinfo ecmd = {

                  .cmd = ETHTOOL_GWOL,
@@ -382,10 +395,10 @@ 

          assert(ifname);

          assert(ring);

  

-         if (!ring->rx_pending_set &&

-             !ring->rx_mini_pending_set &&

-             !ring->rx_jumbo_pending_set &&

-             !ring->tx_pending_set)

+         if (!ring->rx.set &&

+             !ring->rx_mini.set &&

+             !ring->rx_jumbo.set &&

+             !ring->tx.set)

                  return 0;

  

          r = ethtool_connect(ethtool_fd);
@@ -398,17 +411,17 @@ 

          if (r < 0)

                  return -errno;

  

-         if (ring->rx_pending_set)

-                 UPDATE(ecmd.rx_pending, ring->rx_pending, need_update);

+         if (ring->rx.set)

+                 UPDATE_WITH_MAX(ecmd.rx_pending, ecmd.rx_max_pending, ring->rx.value, need_update);

  

-         if (ring->rx_mini_pending_set)

-                 UPDATE(ecmd.rx_mini_pending, ring->rx_mini_pending, need_update);

+         if (ring->rx_mini.set)

+                 UPDATE_WITH_MAX(ecmd.rx_mini_pending, ecmd.rx_mini_max_pending, ring->rx_mini.value, need_update);

  

-         if (ring->rx_jumbo_pending_set)

-                 UPDATE(ecmd.rx_jumbo_pending, ring->rx_jumbo_pending, need_update);

+         if (ring->rx_jumbo.set)

+                 UPDATE_WITH_MAX(ecmd.rx_jumbo_pending, ecmd.rx_jumbo_max_pending, ring->rx_jumbo.value, need_update);

  

-         if (ring->tx_pending_set)

-                 UPDATE(ecmd.tx_pending, ring->tx_pending, need_update);

+         if (ring->tx.set)

+                 UPDATE_WITH_MAX(ecmd.tx_pending, ecmd.tx_max_pending, ring->tx.value, need_update);

  

          if (!need_update)

                  return 0;
@@ -824,10 +837,10 @@ 

          assert(ifname);

          assert(channels);

  

-         if (!channels->rx_count_set &&

-             !channels->tx_count_set &&

-             !channels->other_count_set &&

-             !channels->combined_count_set)

+         if (!channels->rx.set &&

+             !channels->tx.set &&

+             !channels->other.set &&

+             !channels->combined.set)

                  return 0;

  

          r = ethtool_connect(fd);
@@ -840,17 +853,17 @@ 

          if (r < 0)

                  return -errno;

  

-         if (channels->rx_count_set)

-                 UPDATE(ecmd.rx_count, channels->rx_count, need_update);

+         if (channels->rx.set)

+                 UPDATE_WITH_MAX(ecmd.rx_count, ecmd.max_rx, channels->rx.value, need_update);

  

-         if (channels->tx_count_set)

-                 UPDATE(ecmd.tx_count, channels->tx_count, need_update);

+         if (channels->tx.set)

+                 UPDATE_WITH_MAX(ecmd.tx_count, ecmd.max_tx, channels->tx.value, need_update);

  

-         if (channels->other_count_set)

-                 UPDATE(ecmd.other_count, channels->other_count, need_update);

+         if (channels->other.set)

+                 UPDATE_WITH_MAX(ecmd.other_count, ecmd.max_other, channels->other.value, need_update);

  

-         if (channels->combined_count_set)

-                 UPDATE(ecmd.combined_count, channels->combined_count, need_update);

+         if (channels->combined.set)

+                 UPDATE_WITH_MAX(ecmd.combined_count, ecmd.max_combined, channels->combined.value, need_update);

  

          if (!need_update)

                  return 0;
@@ -909,57 +922,6 @@ 

          return 0;

  }

  

- int config_parse_channel(

-                 const char *unit,

-                 const char *filename,

-                 unsigned line,

-                 const char *section,

-                 unsigned section_line,

-                 const char *lvalue,

-                 int ltype,

-                 const char *rvalue,

-                 void *data,

-                 void *userdata) {

- 

-         netdev_channels *channels = data;

-         uint32_t k;

-         int r;

- 

-         assert(filename);

-         assert(section);

-         assert(lvalue);

-         assert(rvalue);

-         assert(data);

- 

-         r = safe_atou32(rvalue, &k);

-         if (r < 0) {

-                 log_syntax(unit, LOG_WARNING, filename, line, r,

-                            "Failed to parse channel value for %s=, ignoring: %s", lvalue, rvalue);

-                 return 0;

-         }

-         if (k < 1) {

-                 log_syntax(unit, LOG_WARNING, filename, line, 0,

-                            "Invalid %s= value, ignoring: %s", lvalue, rvalue);

-                 return 0;

-         }

- 

-         if (streq(lvalue, "RxChannels")) {

-                 channels->rx_count = k;

-                 channels->rx_count_set = true;

-         } else if (streq(lvalue, "TxChannels")) {

-                 channels->tx_count = k;

-                 channels->tx_count_set = true;

-         } else if (streq(lvalue, "OtherChannels")) {

-                 channels->other_count = k;

-                 channels->other_count_set = true;

-         } else if (streq(lvalue, "CombinedChannels")) {

-                 channels->combined_count = k;

-                 channels->combined_count_set = true;

-         }

- 

-         return 0;

- }

- 

  int config_parse_advertise(

                  const char *unit,

                  const char *filename,
@@ -1015,7 +977,7 @@ 

          }

  }

  

- int config_parse_nic_buffer_size(

+ int config_parse_ring_buffer_or_channel(

                  const char *unit,

                  const char *filename,

                  unsigned line,
@@ -1027,7 +989,7 @@ 

                  void *data,

                  void *userdata) {

  

-         netdev_ring_param *ring = data;

+         u32_opt *dst = data;

          uint32_t k;

          int r;

  
@@ -1037,10 +999,22 @@ 

          assert(rvalue);

          assert(data);

  

+         if (isempty(rvalue)) {

+                 dst->value = 0;

+                 dst->set = false;

+                 return 0;

+         }

+ 

+         if (streq(rvalue, "max")) {

+                 dst->value = 0;

+                 dst->set = true;

+                 return 0;

+         }

+ 

          r = safe_atou32(rvalue, &k);

          if (r < 0) {

                  log_syntax(unit, LOG_WARNING, filename, line, r,

-                            "Failed to parse interface buffer value, ignoring: %s", rvalue);

+                            "Failed to parse %s=, ignoring: %s", lvalue, rvalue);

                  return 0;

          }

          if (k < 1) {
@@ -1049,20 +1023,8 @@ 

                  return 0;

          }

  

-         if (streq(lvalue, "RxBufferSize")) {

-                 ring->rx_pending = k;

-                 ring->rx_pending_set = true;

-         } else if (streq(lvalue, "RxMiniBufferSize")) {

-                 ring->rx_mini_pending = k;

-                 ring->rx_mini_pending_set = true;

-         } else if (streq(lvalue, "RxJumboBufferSize")) {

-                 ring->rx_jumbo_pending = k;

-                 ring->rx_jumbo_pending_set = true;

-         } else if (streq(lvalue, "TxBufferSize")) {

-                 ring->tx_pending = k;

-                 ring->tx_pending_set = true;

-         }

- 

+         dst->value = k;

+         dst->set = true;

          return 0;

  }

  
@@ -1131,3 +1093,207 @@ 

  

          return 0;

  }

+ 

+ int config_parse_coalesce_u32(

+                 const char *unit,

+                 const char *filename,

+                 unsigned line,

+                 const char *section,

+                 unsigned section_line,

+                 const char *lvalue,

+                 int ltype,

+                 const char *rvalue,

+                 void *data,

+                 void *userdata) {

+         u32_opt *dst = data;

+         uint32_t k;

+         int r;

+ 

+         if (isempty(rvalue)) {

+                 dst->value = 0;

+                 dst->set = false;

+                 return 0;

+         }

+ 

+         r = safe_atou32(rvalue, &k);

+         if (r < 0) {

+                 log_syntax(unit, LOG_WARNING, filename, line, r,

+                            "Failed to parse %s=, ignoring: %s", lvalue, rvalue);

+                 return 0;

+         }

+ 

+         dst->value = k;

+         dst->set = true;

+         return 0;

+ }

+ 

+ int config_parse_coalesce_sec(

+                 const char *unit,

+                 const char *filename,

+                 unsigned line,

+                 const char *section,

+                 unsigned section_line,

+                 const char *lvalue,

+                 int ltype,

+                 const char *rvalue,

+                 void *data,

+                 void *userdata) {

+         u32_opt *dst = data;

+         usec_t usec;

+         int r;

+ 

+         if (isempty(rvalue)) {

+                 dst->value = 0;

+                 dst->set = false;

+                 return 0;

+         }

+ 

+         r = parse_sec(rvalue, &usec);

+         if (r < 0) {

+                 log_syntax(unit, LOG_WARNING, filename, line, r,

+                            "Failed to parse coalesce setting value, ignoring: %s", rvalue);

+                 return 0;

+         }

+ 

+         if (usec > UINT32_MAX) {

+                 log_syntax(unit, LOG_WARNING, filename, line, 0,

+                            "Too large %s= value, ignoring: %s", lvalue, rvalue);

+                 return 0;

+         }

+ 

+         if (STR_IN_SET(lvalue, "StatisticsBlockCoalesceSec", "CoalescePacketRateSampleIntervalSec") && usec < 1) {

+                 log_syntax(unit, LOG_WARNING, filename, line, 0,

+                            "Invalid %s= value, ignoring: %s", lvalue, rvalue);

+                 return 0;

+         }

+ 

+         dst->value = (uint32_t) usec;

+         dst->set = true;

+ 

+         return 0;

+ }

+ 

+ int ethtool_set_nic_coalesce_settings(int *ethtool_fd, const char *ifname, const netdev_coalesce_param *coalesce) {

+         struct ethtool_coalesce ecmd = {

+                 .cmd = ETHTOOL_GCOALESCE,

+         };

+         struct ifreq ifr = {

+                 .ifr_data = (void*) &ecmd,

+         };

+         bool need_update = false;

+         int r;

+ 

+         assert(ethtool_fd);

+         assert(ifname);

+         assert(coalesce);

+ 

+         if (coalesce->use_adaptive_rx_coalesce < 0 &&

+             coalesce->use_adaptive_tx_coalesce < 0 &&

+             !coalesce->rx_coalesce_usecs.set &&

+             !coalesce->rx_max_coalesced_frames.set &&

+             !coalesce->rx_coalesce_usecs_irq.set &&

+             !coalesce->rx_max_coalesced_frames_irq.set &&

+             !coalesce->tx_coalesce_usecs.set &&

+             !coalesce->tx_max_coalesced_frames.set &&

+             !coalesce->tx_coalesce_usecs_irq.set &&

+             !coalesce->tx_max_coalesced_frames_irq.set &&

+             !coalesce->stats_block_coalesce_usecs.set &&

+             !coalesce->pkt_rate_low.set &&

+             !coalesce->rx_coalesce_usecs_low.set &&

+             !coalesce->rx_max_coalesced_frames_low.set &&

+             !coalesce->tx_coalesce_usecs_low.set &&

+             !coalesce->tx_max_coalesced_frames_low.set &&

+             !coalesce->pkt_rate_high.set &&

+             !coalesce->rx_coalesce_usecs_high.set &&

+             !coalesce->rx_max_coalesced_frames_high.set &&

+             !coalesce->tx_coalesce_usecs_high.set &&

+             !coalesce->tx_max_coalesced_frames_high.set &&

+             !coalesce->rate_sample_interval.set)

+                 return 0;

+ 

+         r = ethtool_connect(ethtool_fd);

+         if (r < 0)

+                 return r;

+ 

+         strscpy(ifr.ifr_name, IFNAMSIZ, ifname);

+ 

+         r = ioctl(*ethtool_fd, SIOCETHTOOL, &ifr);

+         if (r < 0)

+                 return -errno;

+ 

+         if (coalesce->use_adaptive_rx_coalesce >= 0)

+                 UPDATE(ecmd.use_adaptive_rx_coalesce, (uint32_t) coalesce->use_adaptive_rx_coalesce, need_update);

+ 

+         if (coalesce->use_adaptive_tx_coalesce >= 0)

+                 UPDATE(ecmd.use_adaptive_tx_coalesce, (uint32_t) coalesce->use_adaptive_tx_coalesce, need_update);

+ 

+         if (coalesce->rx_coalesce_usecs.set)

+                 UPDATE(ecmd.rx_coalesce_usecs, coalesce->rx_coalesce_usecs.value, need_update);

+ 

+         if (coalesce->rx_max_coalesced_frames.set)

+                 UPDATE(ecmd.rx_max_coalesced_frames, coalesce->rx_max_coalesced_frames.value, need_update);

+ 

+         if (coalesce->rx_coalesce_usecs_irq.set)

+                 UPDATE(ecmd.rx_coalesce_usecs_irq, coalesce->rx_coalesce_usecs_irq.value, need_update);

+ 

+         if (coalesce->rx_max_coalesced_frames_irq.set)

+                 UPDATE(ecmd.rx_max_coalesced_frames_irq, coalesce->rx_max_coalesced_frames_irq.value, need_update);

+ 

+         if (coalesce->tx_coalesce_usecs.set)

+                 UPDATE(ecmd.tx_coalesce_usecs, coalesce->tx_coalesce_usecs.value, need_update);

+ 

+         if (coalesce->tx_max_coalesced_frames.set)

+                 UPDATE(ecmd.tx_max_coalesced_frames, coalesce->tx_max_coalesced_frames.value, need_update);

+ 

+         if (coalesce->tx_coalesce_usecs_irq.set)

+                 UPDATE(ecmd.tx_coalesce_usecs_irq, coalesce->tx_coalesce_usecs_irq.value, need_update);

+ 

+         if (coalesce->tx_max_coalesced_frames_irq.set)

+                 UPDATE(ecmd.tx_max_coalesced_frames_irq, coalesce->tx_max_coalesced_frames_irq.value, need_update);

+ 

+         if (coalesce->stats_block_coalesce_usecs.set)

+                 UPDATE(ecmd.stats_block_coalesce_usecs, coalesce->stats_block_coalesce_usecs.value, need_update);

+ 

+         if (coalesce->pkt_rate_low.set)

+                 UPDATE(ecmd.pkt_rate_low, coalesce->pkt_rate_low.value, need_update);

+ 

+         if (coalesce->rx_coalesce_usecs_low.set)

+                 UPDATE(ecmd.rx_coalesce_usecs_low, coalesce->rx_coalesce_usecs_low.value, need_update);

+ 

+         if (coalesce->rx_max_coalesced_frames_low.set)

+                 UPDATE(ecmd.rx_max_coalesced_frames_low, coalesce->rx_max_coalesced_frames_low.value, need_update);

+ 

+         if (coalesce->tx_coalesce_usecs_low.set)

+                 UPDATE(ecmd.tx_coalesce_usecs_low, coalesce->tx_coalesce_usecs_low.value, need_update);

+ 

+         if (coalesce->tx_max_coalesced_frames_low.set)

+                 UPDATE(ecmd.tx_max_coalesced_frames_low, coalesce->tx_max_coalesced_frames_low.value, need_update);

+ 

+         if (coalesce->pkt_rate_high.set)

+                 UPDATE(ecmd.pkt_rate_high, coalesce->pkt_rate_high.value, need_update);

+ 

+         if (coalesce->rx_coalesce_usecs_high.set)

+                 UPDATE(ecmd.rx_coalesce_usecs_high, coalesce->rx_coalesce_usecs_high.value, need_update);

+ 

+         if (coalesce->rx_max_coalesced_frames_high.set)

+                 UPDATE(ecmd.rx_max_coalesced_frames_high, coalesce->rx_max_coalesced_frames_high.value, need_update);

+ 

+         if (coalesce->tx_coalesce_usecs_high.set)

+                 UPDATE(ecmd.tx_coalesce_usecs_high, coalesce->tx_coalesce_usecs_high.value, need_update);

+ 

+         if (coalesce->tx_max_coalesced_frames_high.set)

+                 UPDATE(ecmd.tx_max_coalesced_frames_high, coalesce->tx_max_coalesced_frames_high.value, need_update);

+ 

+         if (coalesce->rate_sample_interval.set)

+                 UPDATE(ecmd.rate_sample_interval, DIV_ROUND_UP(coalesce->rate_sample_interval.value, USEC_PER_SEC), need_update);

+ 

+         if (!need_update)

+                 return 0;

+ 

+         ecmd.cmd = ETHTOOL_SCOALESCE;

+         r = ioctl(*ethtool_fd, SIOCETHTOOL, &ifr);

+         if (r < 0)

+                 return -errno;

+ 

+         return 0;

+ }

file modified
+44 -20
@@ -23,6 +23,7 @@ 

          NET_DEV_FEAT_TX,

          NET_DEV_FEAT_GSO,

          NET_DEV_FEAT_GRO,

+         NET_DEV_FEAT_GRO_HW,

          NET_DEV_FEAT_LRO,

          NET_DEV_FEAT_TSO,

          NET_DEV_FEAT_TSO6,
@@ -57,30 +58,50 @@ 

          } link_modes;

  };

  

+ typedef struct u32_opt {

+         uint32_t value; /* a value of 0 indicates the hardware advertised maximum should be used.*/

+         bool set;

+ } u32_opt;

+ 

  typedef struct netdev_channels {

-         uint32_t rx_count;

-         uint32_t tx_count;

-         uint32_t other_count;

-         uint32_t combined_count;

- 

-         bool rx_count_set;

-         bool tx_count_set;

-         bool other_count_set;

-         bool combined_count_set;

+         u32_opt rx;

+         u32_opt tx;

+         u32_opt other;

+         u32_opt combined;

  } netdev_channels;

  

  typedef struct netdev_ring_param {

-         uint32_t rx_pending;

-         uint32_t rx_mini_pending;

-         uint32_t rx_jumbo_pending;

-         uint32_t tx_pending;

- 

-         bool rx_pending_set;

-         bool rx_mini_pending_set;

-         bool rx_jumbo_pending_set;

-         bool tx_pending_set;

+         u32_opt rx;

+         u32_opt rx_mini;

+         u32_opt rx_jumbo;

+         u32_opt tx;

  } netdev_ring_param;

  

+ typedef struct netdev_coalesce_param {

+         u32_opt rx_coalesce_usecs;

+         u32_opt rx_max_coalesced_frames;

+         u32_opt rx_coalesce_usecs_irq;

+         u32_opt rx_max_coalesced_frames_irq;

+         u32_opt tx_coalesce_usecs;

+         u32_opt tx_max_coalesced_frames;

+         u32_opt tx_coalesce_usecs_irq;

+         u32_opt tx_max_coalesced_frames_irq;

+         u32_opt stats_block_coalesce_usecs;

+         int use_adaptive_rx_coalesce;

+         int use_adaptive_tx_coalesce;

+         u32_opt pkt_rate_low;

+         u32_opt rx_coalesce_usecs_low;

+         u32_opt rx_max_coalesced_frames_low;

+         u32_opt tx_coalesce_usecs_low;

+         u32_opt tx_max_coalesced_frames_low;

+         u32_opt pkt_rate_high;

+         u32_opt rx_coalesce_usecs_high;

+         u32_opt rx_max_coalesced_frames_high;

+         u32_opt tx_coalesce_usecs_high;

+         u32_opt tx_max_coalesced_frames_high;

+         u32_opt rate_sample_interval;

+ } netdev_coalesce_param;

+ 

  int ethtool_get_driver(int *ethtool_fd, const char *ifname, char **ret);

  int ethtool_get_link_info(int *ethtool_fd, const char *ifname,

                            int *ret_autonegotiation, uint64_t *ret_speed,
@@ -94,6 +115,7 @@ 

                                uint64_t speed, Duplex duplex, NetDevPort port);

  int ethtool_set_channels(int *ethtool_fd, const char *ifname, const netdev_channels *channels);

  int ethtool_set_flow_control(int *fd, const char *ifname, int rx, int tx, int autoneg);

+ int ethtool_set_nic_coalesce_settings(int *ethtool_fd, const char *ifname, const netdev_coalesce_param *coalesce);

  

  const char *duplex_to_string(Duplex d) _const_;

  Duplex duplex_from_string(const char *d) _pure_;
@@ -109,6 +131,8 @@ 

  CONFIG_PARSER_PROTOTYPE(config_parse_duplex);

  CONFIG_PARSER_PROTOTYPE(config_parse_wol);

  CONFIG_PARSER_PROTOTYPE(config_parse_port);

- CONFIG_PARSER_PROTOTYPE(config_parse_channel);

  CONFIG_PARSER_PROTOTYPE(config_parse_advertise);

- CONFIG_PARSER_PROTOTYPE(config_parse_nic_buffer_size);

+ CONFIG_PARSER_PROTOTYPE(config_parse_ring_buffer_or_channel);

+ CONFIG_PARSER_PROTOTYPE(config_parse_coalesce_u32);

+ CONFIG_PARSER_PROTOTYPE(config_parse_coalesce_sec);

+ CONFIG_PARSER_PROTOTYPE(config_parse_nic_coalesce_setting);

@@ -21,54 +21,77 @@ 

  %struct-type

  %includes

  %%

- Match.MACAddress,                      config_parse_hwaddrs,                  0,                             offsetof(LinkConfig, match.mac)

- Match.PermanentMACAddress,             config_parse_hwaddrs,                  0,                             offsetof(LinkConfig, match.permanent_mac)

- Match.OriginalName,                    config_parse_match_ifnames,            0,                             offsetof(LinkConfig, match.ifname)

- Match.Path,                            config_parse_match_strv,               0,                             offsetof(LinkConfig, match.path)

- Match.Driver,                          config_parse_match_strv,               0,                             offsetof(LinkConfig, match.driver)

- Match.Type,                            config_parse_match_strv,               0,                             offsetof(LinkConfig, match.iftype)

- Match.Property,                        config_parse_match_property,           0,                             offsetof(LinkConfig, match.property)

- Match.Host,                            config_parse_net_condition,            CONDITION_HOST,                offsetof(LinkConfig, conditions)

- Match.Virtualization,                  config_parse_net_condition,            CONDITION_VIRTUALIZATION,      offsetof(LinkConfig, conditions)

- Match.KernelCommandLine,               config_parse_net_condition,            CONDITION_KERNEL_COMMAND_LINE, offsetof(LinkConfig, conditions)

- Match.KernelVersion,                   config_parse_net_condition,            CONDITION_KERNEL_VERSION,      offsetof(LinkConfig, conditions)

- Match.Architecture,                    config_parse_net_condition,            CONDITION_ARCHITECTURE,        offsetof(LinkConfig, conditions)

- Link.Description,                      config_parse_string,                   0,                             offsetof(LinkConfig, description)

- Link.MACAddressPolicy,                 config_parse_mac_address_policy,       0,                             offsetof(LinkConfig, mac_address_policy)

- Link.MACAddress,                       config_parse_hwaddr,                   0,                             offsetof(LinkConfig, mac)

- Link.NamePolicy,                       config_parse_name_policy,              0,                             offsetof(LinkConfig, name_policy)

- Link.Name,                             config_parse_ifname,                   0,                             offsetof(LinkConfig, name)

- Link.AlternativeName,                  config_parse_ifnames,                  IFNAME_VALID_ALTERNATIVE,      offsetof(LinkConfig, alternative_names)

- Link.AlternativeNamesPolicy,           config_parse_alternative_names_policy, 0,                             offsetof(LinkConfig, alternative_names_policy)

- Link.Alias,                            config_parse_ifalias,                  0,                             offsetof(LinkConfig, alias)

- Link.TransmitQueues,                   config_parse_rx_tx_queues,             0,                             offsetof(LinkConfig, txqueues)

- Link.ReceiveQueues,                    config_parse_rx_tx_queues,             0,                             offsetof(LinkConfig, rxqueues)

- Link.TransmitQueueLength,              config_parse_txqueuelen,               0,                             offsetof(LinkConfig, txqueuelen)

- Link.MTUBytes,                         config_parse_mtu,                      AF_UNSPEC,                     offsetof(LinkConfig, mtu)

- Link.BitsPerSecond,                    config_parse_si_uint64,                0,                             offsetof(LinkConfig, speed)

- Link.Duplex,                           config_parse_duplex,                   0,                             offsetof(LinkConfig, duplex)

- Link.AutoNegotiation,                  config_parse_tristate,                 0,                             offsetof(LinkConfig, autonegotiation)

- Link.WakeOnLan,                        config_parse_wol,                      0,                             offsetof(LinkConfig, wol)

- Link.Port,                             config_parse_port,                     0,                             offsetof(LinkConfig, port)

- Link.ReceiveChecksumOffload,           config_parse_tristate,                 0,                             offsetof(LinkConfig, features[NET_DEV_FEAT_RX])

- Link.TransmitChecksumOffload,          config_parse_tristate,                 0,                             offsetof(LinkConfig, features[NET_DEV_FEAT_TX])

- Link.GenericSegmentationOffload,       config_parse_tristate,                 0,                             offsetof(LinkConfig, features[NET_DEV_FEAT_GSO])

- Link.TCPSegmentationOffload,           config_parse_tristate,                 0,                             offsetof(LinkConfig, features[NET_DEV_FEAT_TSO])

- Link.TCP6SegmentationOffload,          config_parse_tristate,                 0,                             offsetof(LinkConfig, features[NET_DEV_FEAT_TSO6])

- Link.UDPSegmentationOffload,           config_parse_warn_compat,              DISABLED_LEGACY,               0

- Link.GenericReceiveOffload,            config_parse_tristate,                 0,                             offsetof(LinkConfig, features[NET_DEV_FEAT_GRO])

- Link.LargeReceiveOffload,              config_parse_tristate,                 0,                             offsetof(LinkConfig, features[NET_DEV_FEAT_LRO])

- Link.RxChannels,                       config_parse_channel,                  0,                             offsetof(LinkConfig, channels)

- Link.TxChannels,                       config_parse_channel,                  0,                             offsetof(LinkConfig, channels)

- Link.OtherChannels,                    config_parse_channel,                  0,                             offsetof(LinkConfig, channels)

- Link.CombinedChannels,                 config_parse_channel,                  0,                             offsetof(LinkConfig, channels)

- Link.Advertise,                        config_parse_advertise,                0,                             offsetof(LinkConfig, advertise)

- Link.RxBufferSize,                     config_parse_nic_buffer_size,          0,                             offsetof(LinkConfig, ring)

- Link.RxMiniBufferSize,                 config_parse_nic_buffer_size,          0,                             offsetof(LinkConfig, ring)

- Link.RxJumboBufferSize,                config_parse_nic_buffer_size,          0,                             offsetof(LinkConfig, ring)

- Link.TxBufferSize,                     config_parse_nic_buffer_size,          0,                             offsetof(LinkConfig, ring)

- Link.RxFlowControl,                    config_parse_tristate,                 0,                             offsetof(LinkConfig, rx_flow_control)

- Link.TxFlowControl,                    config_parse_tristate,                 0,                             offsetof(LinkConfig, tx_flow_control)

- Link.AutoNegotiationFlowControl,       config_parse_tristate,                 0,                             offsetof(LinkConfig, autoneg_flow_control)

- Link.GenericSegmentOffloadMaxBytes,    config_parse_iec_size,                 0,                             offsetof(LinkConfig, gso_max_size)

- Link.GenericSegmentOffloadMaxSegments, config_parse_uint32,                   0,                             offsetof(LinkConfig, gso_max_segments)

+ Match.MACAddress,                         config_parse_hwaddrs,                  0,                             offsetof(LinkConfig, match.mac)

+ Match.PermanentMACAddress,                config_parse_hwaddrs,                  0,                             offsetof(LinkConfig, match.permanent_mac)

+ Match.OriginalName,                       config_parse_match_ifnames,            0,                             offsetof(LinkConfig, match.ifname)

+ Match.Path,                               config_parse_match_strv,               0,                             offsetof(LinkConfig, match.path)

+ Match.Driver,                             config_parse_match_strv,               0,                             offsetof(LinkConfig, match.driver)

+ Match.Type,                               config_parse_match_strv,               0,                             offsetof(LinkConfig, match.iftype)

+ Match.Property,                           config_parse_match_property,           0,                             offsetof(LinkConfig, match.property)

+ Match.Host,                               config_parse_net_condition,            CONDITION_HOST,                offsetof(LinkConfig, conditions)

+ Match.Virtualization,                     config_parse_net_condition,            CONDITION_VIRTUALIZATION,      offsetof(LinkConfig, conditions)

+ Match.KernelCommandLine,                  config_parse_net_condition,            CONDITION_KERNEL_COMMAND_LINE, offsetof(LinkConfig, conditions)

+ Match.KernelVersion,                      config_parse_net_condition,            CONDITION_KERNEL_VERSION,      offsetof(LinkConfig, conditions)

+ Match.Architecture,                       config_parse_net_condition,            CONDITION_ARCHITECTURE,        offsetof(LinkConfig, conditions)

+ Link.Description,                         config_parse_string,                   0,                             offsetof(LinkConfig, description)

+ Link.MACAddressPolicy,                    config_parse_mac_address_policy,       0,                             offsetof(LinkConfig, mac_address_policy)

+ Link.MACAddress,                          config_parse_hwaddr,                   0,                             offsetof(LinkConfig, mac)

+ Link.NamePolicy,                          config_parse_name_policy,              0,                             offsetof(LinkConfig, name_policy)

+ Link.Name,                                config_parse_ifname,                   0,                             offsetof(LinkConfig, name)

+ Link.AlternativeName,                     config_parse_ifnames,                  IFNAME_VALID_ALTERNATIVE,      offsetof(LinkConfig, alternative_names)

+ Link.AlternativeNamesPolicy,              config_parse_alternative_names_policy, 0,                             offsetof(LinkConfig, alternative_names_policy)

+ Link.Alias,                               config_parse_ifalias,                  0,                             offsetof(LinkConfig, alias)

+ Link.TransmitQueues,                      config_parse_rx_tx_queues,             0,                             offsetof(LinkConfig, txqueues)

+ Link.ReceiveQueues,                       config_parse_rx_tx_queues,             0,                             offsetof(LinkConfig, rxqueues)

+ Link.TransmitQueueLength,                 config_parse_txqueuelen,               0,                             offsetof(LinkConfig, txqueuelen)

+ Link.MTUBytes,                            config_parse_mtu,                      AF_UNSPEC,                     offsetof(LinkConfig, mtu)

+ Link.BitsPerSecond,                       config_parse_si_uint64,                0,                             offsetof(LinkConfig, speed)

+ Link.Duplex,                              config_parse_duplex,                   0,                             offsetof(LinkConfig, duplex)

+ Link.AutoNegotiation,                     config_parse_tristate,                 0,                             offsetof(LinkConfig, autonegotiation)

+ Link.WakeOnLan,                           config_parse_wol,                      0,                             offsetof(LinkConfig, wol)

+ Link.Port,                                config_parse_port,                     0,                             offsetof(LinkConfig, port)

+ Link.ReceiveChecksumOffload,              config_parse_tristate,                 0,                             offsetof(LinkConfig, features[NET_DEV_FEAT_RX])

+ Link.TransmitChecksumOffload,             config_parse_tristate,                 0,                             offsetof(LinkConfig, features[NET_DEV_FEAT_TX])

+ Link.GenericSegmentationOffload,          config_parse_tristate,                 0,                             offsetof(LinkConfig, features[NET_DEV_FEAT_GSO])

+ Link.TCPSegmentationOffload,              config_parse_tristate,                 0,                             offsetof(LinkConfig, features[NET_DEV_FEAT_TSO])

+ Link.TCP6SegmentationOffload,             config_parse_tristate,                 0,                             offsetof(LinkConfig, features[NET_DEV_FEAT_TSO6])

+ Link.UDPSegmentationOffload,              config_parse_warn_compat,              DISABLED_LEGACY,               0

+ Link.GenericReceiveOffload,               config_parse_tristate,                 0,                             offsetof(LinkConfig, features[NET_DEV_FEAT_GRO])

+ Link.GenericReceiveOffloadHardware,       config_parse_tristate,                 0,                             offsetof(LinkConfig, features[NET_DEV_FEAT_GRO_HW])

+ Link.LargeReceiveOffload,                 config_parse_tristate,                 0,                             offsetof(LinkConfig, features[NET_DEV_FEAT_LRO])

+ Link.RxChannels,                          config_parse_ring_buffer_or_channel,   0,                             offsetof(LinkConfig, channels.rx)

+ Link.TxChannels,                          config_parse_ring_buffer_or_channel,   0,                             offsetof(LinkConfig, channels.tx)

+ Link.OtherChannels,                       config_parse_ring_buffer_or_channel,   0,                             offsetof(LinkConfig, channels.other)

+ Link.CombinedChannels,                    config_parse_ring_buffer_or_channel,   0,                             offsetof(LinkConfig, channels.combined)

+ Link.Advertise,                           config_parse_advertise,                0,                             offsetof(LinkConfig, advertise)

+ Link.RxBufferSize,                        config_parse_ring_buffer_or_channel,   0,                             offsetof(LinkConfig, ring.rx)

+ Link.RxMiniBufferSize,                    config_parse_ring_buffer_or_channel,   0,                             offsetof(LinkConfig, ring.rx_mini)

+ Link.RxJumboBufferSize,                   config_parse_ring_buffer_or_channel,   0,                             offsetof(LinkConfig, ring.rx_jumbo)

+ Link.TxBufferSize,                        config_parse_ring_buffer_or_channel,   0,                             offsetof(LinkConfig, ring.tx)

+ Link.RxFlowControl,                       config_parse_tristate,                 0,                             offsetof(LinkConfig, rx_flow_control)

+ Link.TxFlowControl,                       config_parse_tristate,                 0,                             offsetof(LinkConfig, tx_flow_control)

+ Link.AutoNegotiationFlowControl,          config_parse_tristate,                 0,                             offsetof(LinkConfig, autoneg_flow_control)

+ Link.GenericSegmentOffloadMaxBytes,       config_parse_iec_size,                 0,                             offsetof(LinkConfig, gso_max_size)

+ Link.GenericSegmentOffloadMaxSegments,    config_parse_uint32,                   0,                             offsetof(LinkConfig, gso_max_segments)

+ Link.RxCoalesceSec,                       config_parse_coalesce_sec,             0,                             offsetof(LinkConfig, coalesce.rx_coalesce_usecs)

+ Link.RxMaxCoalescedFrames,                config_parse_coalesce_u32,             0,                             offsetof(LinkConfig, coalesce.rx_max_coalesced_frames)

+ Link.RxCoalesceIrqSec,                    config_parse_coalesce_sec,             0,                             offsetof(LinkConfig, coalesce.rx_coalesce_usecs_irq)

+ Link.RxMaxCoalescedIrqFrames,             config_parse_coalesce_u32,             0,                             offsetof(LinkConfig, coalesce.rx_max_coalesced_frames_irq)

+ Link.TxCoalesceSec,                       config_parse_coalesce_sec,             0,                             offsetof(LinkConfig, coalesce.tx_coalesce_usecs)

+ Link.TxMaxCoalescedFrames,                config_parse_coalesce_u32,             0,                             offsetof(LinkConfig, coalesce.tx_max_coalesced_frames)

+ Link.TxCoalesceIrqSec,                    config_parse_coalesce_sec,             0,                             offsetof(LinkConfig, coalesce.tx_coalesce_usecs_irq)

+ Link.TxMaxCoalescedIrqFrames,             config_parse_coalesce_u32,             0,                             offsetof(LinkConfig, coalesce.tx_max_coalesced_frames_irq)

+ Link.StatisticsBlockCoalesceSec,          config_parse_coalesce_sec,             0,                             offsetof(LinkConfig, coalesce.stats_block_coalesce_usecs)

+ Link.UseAdaptiveRxCoalesce,               config_parse_tristate,                 0,                             offsetof(LinkConfig, coalesce.use_adaptive_rx_coalesce)

+ Link.UseAdaptiveTxCoalesce,               config_parse_tristate,                 0,                             offsetof(LinkConfig, coalesce.use_adaptive_tx_coalesce)

+ Link.CoalescePacketRateLow,               config_parse_coalesce_u32,             0,                             offsetof(LinkConfig, coalesce.pkt_rate_low)

+ Link.RxCoalesceLowSec,                    config_parse_coalesce_sec,             0,                             offsetof(LinkConfig, coalesce.rx_coalesce_usecs_low)

+ Link.RxMaxCoalescedLowFrames,             config_parse_coalesce_u32,             0,                             offsetof(LinkConfig, coalesce.rx_max_coalesced_frames_low)

+ Link.TxCoalesceLowSec,                    config_parse_coalesce_sec,             0,                             offsetof(LinkConfig, coalesce.tx_coalesce_usecs_low)

+ Link.TxMaxCoalescedLowFrames,             config_parse_coalesce_u32,             0,                             offsetof(LinkConfig, coalesce.tx_max_coalesced_frames_low)

+ Link.CoalescePacketRateHigh,              config_parse_coalesce_u32,             0,                             offsetof(LinkConfig, coalesce.pkt_rate_high)

+ Link.RxCoalesceHighSec,                   config_parse_coalesce_sec,             0,                             offsetof(LinkConfig, coalesce.rx_coalesce_usecs_high)

+ Link.RxMaxCoalescedHighFrames,            config_parse_coalesce_u32,             0,                             offsetof(LinkConfig, coalesce.rx_max_coalesced_frames_high)

+ Link.TxCoalesceHighSec,                   config_parse_coalesce_sec,             0,                             offsetof(LinkConfig, coalesce.tx_coalesce_usecs_high)

+ Link.TxMaxCoalescedHighFrames,            config_parse_coalesce_u32,             0,                             offsetof(LinkConfig, coalesce.tx_max_coalesced_frames_high)

+ Link.CoalescePacketRateSampleIntervalSec, config_parse_coalesce_sec,             0,                             offsetof(LinkConfig, coalesce.rate_sample_interval)

@@ -353,6 +353,10 @@ 

          if (r < 0)

                  log_device_warning_errno(device, r, "Could not set flow control, ignoring: %m");

  

+         r = ethtool_set_nic_coalesce_settings(ethtool_fd, name, &config->coalesce);

+         if (r < 0)

+                 log_device_warning_errno(device, r, "Could not set coalesce settings, ignoring: %m");

+ 

          return 0;

  }

  

@@ -64,6 +64,7 @@ 

          int rx_flow_control;

          int tx_flow_control;

          int autoneg_flow_control;

+         netdev_coalesce_param coalesce;

  

          LIST_FIELDS(LinkConfig, links);

  };

@@ -36,6 +36,7 @@ 

  TCP6SegmentationOffload=

  UDPSegmentationOffload=

  GenericReceiveOffload=

+ GenericReceiveOffloadHardware=

  LargeReceiveOffload=

  RxChannels=

  TxChannels=
@@ -51,3 +52,25 @@ 

  AutoNegotiationFlowControl=

  GenericSegmentOffloadMaxBytes=

  GenericSegmentOffloadMaxSegments=

+ RxCoalesceSec=

+ RxMaxCoalescedFrames=

+ RxCoalesceIrqSec=

+ RxMaxCoalescedIrqFrames=

+ TxCoalesceSec=

+ TxMaxCoalescedFrames=

+ TxCoalesceIrqSec=

+ TxMaxCoalescedIrqFrames=

+ StatisticsBlockCoalesceSec=

+ UseAdaptiveRxCoalesce=

+ UseAdaptiveTxCoalesce=

+ CoalescePacketRateLow=

+ RxCoalesceLowSec=

+ RxMaxCoalescedLowFrames=

+ TxCoalesceLowSec=

+ TxMaxCoalescedLowFrames=

+ CoalescePacketRateHigh=

+ RxCoalesceHighSec=

+ RxMaxCoalescedHighFrames=

+ TxCoalesceHighSec=

+ TxMaxCoalescedHighFrames=

+ CoalescePacketRateSampleIntervalSec=