summaryrefslogtreecommitdiffstats
path: root/src/udev
diff options
context:
space:
mode:
authorSusant Sahani <145210+ssahani@users.noreply.github.com>2018-05-08 13:03:41 +0200
committerZbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>2018-05-08 13:03:41 +0200
commit5f94520221bcf1aed783c6adf37f54174861989f (patch)
tree1a34f660e1045240f59b105939a70ca6f465185f /src/udev
parentMerge pull request #8898 from poettering/nspawn-mount-block (diff)
downloadsystemd-5f94520221bcf1aed783c6adf37f54174861989f.tar.xz
systemd-5f94520221bcf1aed783c6adf37f54174861989f.zip
link: Add support to configure channels of the specified network device (#8882)
closes #8856
Diffstat (limited to 'src/udev')
-rw-r--r--src/udev/net/ethtool-util.c102
-rw-r--r--src/udev/net/ethtool-util.h14
-rw-r--r--src/udev/net/link-config-gperf.gperf4
-rw-r--r--src/udev/net/link-config.c6
-rw-r--r--src/udev/net/link-config.h1
5 files changed, 127 insertions, 0 deletions
diff --git a/src/udev/net/ethtool-util.c b/src/udev/net/ethtool-util.c
index ccea64b573..37525ce841 100644
--- a/src/udev/net/ethtool-util.c
+++ b/src/udev/net/ethtool-util.c
@@ -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;
+}
diff --git a/src/udev/net/ethtool-util.h b/src/udev/net/ethtool-util.h
index 1db07dec53..da2a2458f0 100644
--- a/src/udev/net/ethtool-util.h
+++ b/src/udev/net/ethtool-util.h
@@ -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);
diff --git a/src/udev/net/link-config-gperf.gperf b/src/udev/net/link-config-gperf.gperf
index 8bfa998dac..dee305f325 100644
--- a/src/udev/net/link-config-gperf.gperf
+++ b/src/udev/net/link-config-gperf.gperf
@@ -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
diff --git a/src/udev/net/link-config.c b/src/udev/net/link-config.c
index c4fab4e63b..e33eae5421 100644
--- a/src/udev/net/link-config.c
+++ b/src/udev/net/link-config.c
@@ -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");
diff --git a/src/udev/net/link-config.h b/src/udev/net/link-config.h
index 9f41132810..bedb80ea43 100644
--- a/src/udev/net/link-config.h
+++ b/src/udev/net/link-config.h
@@ -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);
};