]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
link: Add support to configure channels of the specified network device (#8882)
authorSusant Sahani <145210+ssahani@users.noreply.github.com>
Tue, 8 May 2018 11:03:41 +0000 (16:33 +0530)
committerZbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>
Tue, 8 May 2018 11:03:41 +0000 (13:03 +0200)
closes #8856

man/systemd.link.xml
src/udev/net/ethtool-util.c
src/udev/net/ethtool-util.h
src/udev/net/link-config-gperf.gperf
src/udev/net/link-config.c
src/udev/net/link-config.h

index c7c920913b373aada3eb36064a1e08228d2749f3..6857248ef3225fc675e10e27f42c6494e7dd6f54 100644 (file)
           Defaults to "unset".</para>
         </listitem>
       </varlistentry>
+      <varlistentry>
+        <term><varname>RxChannels=</varname></term>
+        <listitem>
+          <para>Sets the number of receive channels (a number between 1 and 4294967295) .</para>
+        </listitem>
+      </varlistentry>
+      <varlistentry>
+        <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>
+        </listitem>
+      </varlistentry>
     </variablelist>
   </refsect1>
 
index ccea64b5735c56ff4ffa51fd906411a715ba8387..37525ce841b2406f76afa575b349241bc3e1cc52 100644 (file)
@@ -568,3 +568,105 @@ int ethtool_set_glinksettings(int *fd, const char *ifname, struct link_config *l
 
         return r;
 }
+
+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) {
+        link_config *config = 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_ERR, filename, line, r, "Failed to parse channel value, ignoring: %s", rvalue);
+                return 0;
+        }
+
+        if (k < 1) {
+                log_syntax(unit, LOG_ERR, filename, line, -EINVAL, "Invalid %s value, ignoring: %s", lvalue, rvalue);
+                return 0;
+        }
+
+        if (streq(lvalue, "RxChannels")) {
+                config->channels.rx_count = k;
+                config->channels.rx_count_set = true;
+        } else if (streq(lvalue, "TxChannels")) {
+                config->channels.tx_count = k;
+                config->channels.tx_count_set = true;
+        } else if (streq(lvalue, "OtherChannels")) {
+                config->channels.other_count = k;
+                config->channels.other_count_set = true;
+        } else if (streq(lvalue, "CombinedChannels")) {
+                config->channels.combined_count = k;
+                config->channels.combined_count_set = true;
+        }
+
+        return 0;
+}
+
+int ethtool_set_channels(int *fd, const char *ifname, netdev_channels *channels) {
+        struct ethtool_channels ecmd = {
+                .cmd = ETHTOOL_GCHANNELS
+        };
+        struct ifreq ifr = {
+                .ifr_data = (void*) &ecmd
+        };
+
+        bool need_update = false;
+        int r;
+
+        if (*fd < 0) {
+                r = ethtool_connect(fd);
+                if (r < 0)
+                        return log_warning_errno(r, "link_config: could not connect to ethtool: %m");
+        }
+
+        strscpy(ifr.ifr_name, IFNAMSIZ, ifname);
+
+        r = ioctl(*fd, SIOCETHTOOL, &ifr);
+        if (r < 0)
+                return -errno;
+
+        if (channels->rx_count_set && ecmd.rx_count != channels->rx_count) {
+                ecmd.rx_count = channels->rx_count;
+                need_update = true;
+        }
+
+        if (channels->tx_count_set && ecmd.tx_count != channels->tx_count) {
+                ecmd.tx_count = channels->tx_count;
+                need_update = true;
+        }
+
+        if (channels->other_count_set && ecmd.other_count != channels->other_count) {
+                ecmd.other_count = channels->other_count;
+                need_update = true;
+        }
+
+        if (channels->combined_count_set && ecmd.combined_count != channels->combined_count) {
+                ecmd.combined_count = channels->combined_count;
+                need_update = true;
+        }
+
+        if (need_update) {
+                ecmd.cmd = ETHTOOL_SCHANNELS;
+
+                r = ioctl(*fd, SIOCETHTOOL, &ifr);
+                if (r < 0)
+                        return -errno;
+        }
+
+        return 0;
+}
index 1db07dec53ae7350ff76e8bbf05efa4bbf302896..da2a2458f0ca6abce4d38c244aa5ab73e32f3c3d 100644 (file)
@@ -72,6 +72,18 @@ struct ethtool_link_usettings {
         } link_modes;
 };
 
+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;
+} netdev_channels;
+
 int ethtool_connect(int *ret);
 
 int ethtool_get_driver(int *fd, const char *ifname, char **ret);
@@ -79,6 +91,7 @@ int ethtool_set_speed(int *fd, const char *ifname, unsigned int speed, Duplex du
 int ethtool_set_wol(int *fd, const char *ifname, WakeOnLan wol);
 int ethtool_set_features(int *fd, const char *ifname, NetDevFeature *features);
 int ethtool_set_glinksettings(int *fd, const char *ifname, struct link_config *link);
+int ethtool_set_channels(int *fd, const char *ifname, netdev_channels *channels);
 
 const char *duplex_to_string(Duplex d) _const_;
 Duplex duplex_from_string(const char *d) _pure_;
@@ -92,3 +105,4 @@ NetDevPort port_from_string(const char *port) _pure_;
 int config_parse_duplex(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);
 int config_parse_wol(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);
 int config_parse_port(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);
+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);
index 8bfa998dacf6a70d0c0b08074886f7242b3aac9a..dee305f3250ddea2cda5310d6b932db325448123 100644 (file)
@@ -47,3 +47,7 @@ Link.TCP6SegmentationOffload,    config_parse_tristate,      0,
 Link.UDPSegmentationOffload,     config_parse_warn_compat,   DISABLED_LEGACY,               0
 Link.GenericReceiveOffload,      config_parse_tristate,      0,                             offsetof(link_config, features[NET_DEV_FEAT_GRO])
 Link.LargeReceiveOffload,        config_parse_tristate,      0,                             offsetof(link_config, features[NET_DEV_FEAT_LRO])
+Link.RxChannels,                 config_parse_channel,       0,                             0
+Link.TxChannels,                 config_parse_channel,       0,                             0
+Link.OtherChannels,              config_parse_channel,       0,                             0
+Link.CombinedChannels,           config_parse_channel,       0,                             0
index c4fab4e63b1f940d17e2951affc54ef8c443231f..e33eae542176dd4000e0b8dfe901428e7233368b 100644 (file)
@@ -393,6 +393,12 @@ int link_config_apply(link_config_ctx *ctx, link_config *config,
         if (r < 0)
                 log_warning_errno(r, "Could not set offload features of %s: %m", old_name);
 
+        if (config->channels.rx_count_set || config->channels.tx_count_set || config->channels.other_count_set || config->channels.combined_count_set) {
+                r = ethtool_set_channels(&ctx->ethtool_fd, old_name, &config->channels);
+                if (r < 0)
+                        log_warning_errno(r, "Could not set channels of %s: %m", old_name);
+        }
+
         ifindex = udev_device_get_ifindex(device);
         if (ifindex <= 0) {
                 log_warning("Could not find ifindex");
index 9f411328105573a851426e654642ef8d05c866a9..bedb80ea4392cd594cd40dc30908ef671921910b 100644 (file)
@@ -62,6 +62,7 @@ struct link_config {
         WakeOnLan wol;
         NetDevPort port;
         NetDevFeature features[_NET_DEV_FEAT_MAX];
+        netdev_channels channels;
 
         LIST_FIELDS(link_config, links);
 };