link: Add support to configure channels of the specified network device (#8882)

closes #8856
This commit is contained in:
Susant Sahani
2018-05-08 13:03:41 +02:00
committed by Zbigniew Jędrzejewski-Szmek
parent 6b1ca2a948
commit 5f94520221
6 changed files with 151 additions and 0 deletions
+24
View File
@@ -525,6 +525,30 @@
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>
+102
View 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;
}
+14
View 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);
+4
View 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
+6
View 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");
+1
View 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);
};