diff options
author | Susant Sahani <145210+ssahani@users.noreply.github.com> | 2018-05-08 13:03:41 +0200 |
---|---|---|
committer | Zbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl> | 2018-05-08 13:03:41 +0200 |
commit | 5f94520221bcf1aed783c6adf37f54174861989f (patch) | |
tree | 1a34f660e1045240f59b105939a70ca6f465185f /src/udev | |
parent | Merge pull request #8898 from poettering/nspawn-mount-block (diff) | |
download | systemd-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.c | 102 | ||||
-rw-r--r-- | src/udev/net/ethtool-util.h | 14 | ||||
-rw-r--r-- | src/udev/net/link-config-gperf.gperf | 4 | ||||
-rw-r--r-- | src/udev/net/link-config.c | 6 | ||||
-rw-r--r-- | src/udev/net/link-config.h | 1 |
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); }; |